Alexandre Brown

    Alexandre Brown

    9 months ago
    How can we create sub modules like we can easily do on JVM (not multiplatform) projects? For instance, in the photo the module is recognized as a directory even though I have the include in my
    settings.gradle.kts
    Thanks
    Big Chungus

    Big Chungus

    9 months ago
    Because it overlaps with the path of another module sources. Move it to be a sibling of src and it will work
    Alexandre Brown

    Alexandre Brown

    9 months ago
    Thanks @Big Chungus, so I guess it's not possible to have nested sub modules like it's possible for normal jvm projects?
    Big Chungus

    Big Chungus

    9 months ago
    It is, it just can't be in the sources of another module
    Alexandre Brown

    Alexandre Brown

    9 months ago
    But the top level module is the KMP library (project name), So we can have MyLib which has src then inside it we have commonMain. You are saying we cannot have another nested module inside commonMain?
    Big Chungus

    Big Chungus

    9 months ago
    I.e. this is fine /rootProject /src /moduleA /moduleB /src /src /src This is not /rootProject /src /commonMain /kotlin /resources /moduleB
    Alexandre Brown

    Alexandre Brown

    9 months ago
    What if we want module B inside module A ? Is this possible in any ways?
    Big Chungus

    Big Chungus

    9 months ago
    See my first example. ModuleB path is /moduleA/moduleB
    Alexandre Brown

    Alexandre Brown

    9 months ago
    Ok trying this example right now
    Big Chungus

    Big Chungus

    9 months ago
    So it's inside moduleA. It would break only if you place in /moduleA/src/commonMain/moduleB since commonMain is a source dir of moduleA
    Here's an example of nested modular mpp project https://github.com/mpetuska/klip
    Alexandre Brown

    Alexandre Brown

    9 months ago
    @Big Chungus Thanks a lot I got the hang of it now! I'd send you a coffee if I could!
    Big Chungus

    Big Chungus

    9 months ago
    Virtual coffee is fine. Always glad to help 😀
    Although I'd rename your commonMain module to something else as that's standard sourceSet name for mpp projects
    Remember module != sourceSet
    Alexandre Brown

    Alexandre Brown

    9 months ago
    My initial thought was that everything included in this commonMain will not be jvm specific. How should I name it? It was named commonMain initially
    Big Chungus

    Big Chungus

    9 months ago
    Here's a reminder of gradle hierarchy Build -> Project -> sourceSet -> sourceRoot
    It wasn't. sourceSet of a module was 😉
    Name it shared, common or something like that
    Alexandre Brown

    Alexandre Brown

    9 months ago
    Is there a way to un-module it?
    Big Chungus

    Big Chungus

    9 months ago
    Is your repo open source?
    I could raise a pr sorting this out
    Alexandre Brown

    Alexandre Brown

    9 months ago
    I plan on having a "core" module inside "commonMain". Do I just created this project, no code yet.
    The idea is to have none-jvm specific implementations and code inside commonMain. commonMain -----core -----project-name-A -----project-name-B
    Big Chungus

    Big Chungus

    9 months ago
    Then have it named simply common
    Alexandre Brown

    Alexandre Brown

    9 months ago
    Ok and I guess it must be a module even though other sourceSet are not modules?
    Big Chungus

    Big Chungus

    9 months ago
    Otherwise you'll get it confused with sourceSet. e.g. commonMain/core/src/commonMain/kotlin/main.kt
    Alexandre Brown

    Alexandre Brown

    9 months ago
    Big Chungus

    Big Chungus

    9 months ago
    All sourceSets are not modules. They're parts of a module
    Alexandre Brown

    Alexandre Brown

    9 months ago
    I see what you mean
    It used to be sourceSet but now it isn't anymore and the sourceSet will be in the project module and in core. Got it (correct me if im wrong)
    Big Chungus

    Big Chungus

    9 months ago
    Have a look at this module (especially src subfolder structure) and then check how it's declared in settings.kts https://github.com/mpetuska/kon/tree/master/lib%2Fkon-core
    Alexandre Brown

    Alexandre Brown

    9 months ago
    Got it , I will create 2 modules then, one "common" where all its sub modules will have only a commonMain sourceSet and another module where each sub modules will have the sourceSet for js, native etc (but not common). would that be ok standard wise?
    Big Chungus

    Big Chungus

    9 months ago
    That's not even possible 😀
    You cannot have a mpp module without src/commonMain
    Ok, let's try this - can you explain to me what modules you plan to have and their intended use ases?
    Alexandre Brown

    Alexandre Brown

    9 months ago
    Sure
    Big Chungus

    Big Chungus

    9 months ago
    I can then send you a file tree
    Alexandre Brown

    Alexandre Brown

    9 months ago
    Give me a minute, I'm making a folder structure
    Here is what I want to achieve (I only created a minimal number of modules, but in reality each project will have like 5-6 project specific modules (one for each layers of the architecture), I did this to keep it simple for the explanation)
    My goal is to have a Core module that can be used by the library and the jvm server module. Then inside the library I would like to have a project-based structure where I put project specific and library specific code. Context: The library will be used for offline users while the server will be a ktor server. Some of the code between the library and the server will be the same (this should be in core) but since the library and the server is 2 different application, I will put application business logic for the server inside the server module, application business rules for the library will be inside the library
    My initial idea was to have this, but then I was not sure how we can make sure that core/ will work with the library and not use any jvm specific api.
    I kept the image simple and didnt duplicate project-B in server but in theory there will always be project-B in both library and server.
    Big Chungus

    Big Chungus

    9 months ago
    Ok, here's the file tree up to kotlin sources for each module (modules with
    commonMain
    are MPP, with just
    main
    are JVM. each module also has gradle path to place in setting.kts listed)
    core/ # not a module
        entities/ # JVM module :core:entities
            src/
                main/kotlin
                test/kotlin
            build.gradle.kts
    library/ #not a module
        project-A/ # MPP module :library:project-A
            build.gradle.kts
            src/
                commonMain/kotlin
                commonTest/kotlin
                jvmMain/kotlin
                jvmTest/kotlin
                jsMain/kotlin
                jsTest/kotlin
                linuxX64/kotlin
                linuxX64Test/kotlin
            library-specific-controllers/ # MPP module :library:project-A:library-specific-controllers
                build.gradle.kts
                src/
                    commonMain/kotlin
                    commonTest/kotlin
                    jvmMain/kotlin
                    jvmTest/kotlin
                    jsMain/kotlin
                    jsTest/kotlin
                    linuxX64/kotlin
                    linuxX64Test/kotlin
            library-specific-usecases/ # MPP module :library:project-A:library-specific-usecases
                build.gradle.kts
                src/
                    commonMain/kotlin
                    commonTest/kotlin
                    jvmMain/kotlin
                    jvmTest/kotlin
                    jsMain/kotlin
                    jsTest/kotlin
                    linuxX64/kotlin
                    linuxX64Test/kotlin
        project-B/ # MPP module :library:project-B
            build.gradle.kts
            src/
                commonMain/kotlin
                commonTest/kotlin
                jvmMain/kotlin
                jvmTest/kotlin
                jsMain/kotlin
                jsTest/kotlin
                linuxX64/kotlin
                linuxX64Test/kotlin
            library-specific-controllers/ # MPP module :library:project-B:library-specific-controllers
                build.gradle.kts
                src/
                    commonMain/kotlin
                    commonTest/kotlin
                    jvmMain/kotlin
                    jvmTest/kotlin
                    jsMain/kotlin
                    jsTest/kotlin
                    linuxX64/kotlin
                    linuxX64Test/kotlin
            library-specific-usecases/ # MPP module :library:project-B:library-specific-usecases
                build.gradle.kts
                src/
                    commonMain/kotlin
                    commonTest/kotlin
                    jvmMain/kotlin
                    jvmTest/kotlin
                    jsMain/kotlin
                    jsTest/kotlin
                    linuxX64/kotlin
                    linuxX64Test/kotlin
    server/ # not a module
        project-A/ # JVM module :server:project-A
            server-specific-usecases/ # JVM module :server:project-A:server-specific-usecases
                src/
                    main/kotlin
                    test/kotlin
                build.gradle.kts
            src/
                main/kotlin
                test/kotlin
            build.gradle.kts
    build.gradle.kts
    settings.gradle.kts
    note how modules are never in other module's
    src
    directory. Also the distinction between multiple sourceSets (even for JVM-only projects). I hope it now makes sense why the sourceSets are even needed.
    To simplify, it might help to think of a module as a lego block. You cannot place another lego block inside a lego block, but uou can place them either side-by-side or on top of each other. Here's the bare minimum for such "lego block" that a module owns:
    entities/ # JVM module :core:entities
        src/
            main/kotlin
            test/kotlin
        build.gradle.kts
    Or rather this to better fit my side-by-side analogy
    src/
        main/kotlin
        test/kotlin
    build.gradle.kts
    Alexandre Brown

    Alexandre Brown

    9 months ago
    Looks great, I have 2 questiosn. 1 : If
    :core:entities
    is a jvm module then will I be able to use it inside
    library:project-B:library-specific-usecases
    for instance (because that's the goal of core, to be used by the lib and the server) 2 : Can I delete the sourceSet
    jvmMain/kotlin
    jvmTest/kotlin
    jsMain/kotlin
    jsTest/kotlin
    linuxX64/kotlin
    linuxX64Test/kotlin
    inside
    library:project-B:library-specific-usecases
    since my use cases will be pure kotlin ?
    Hmmmm actually it might be unsafe to do so, because what if my use case uses something very basic but that is jvm specific like a UUID, then I'd be in trouble. I guess it is safer to have the sourceSet. Beset case everything will be in commonMain but at least I wont be trapped. Is this correct?
    Btw your lego block analogy is super clear
    Big Chungus

    Big Chungus

    9 months ago
    sourceSets are not required if you have no sources for them. ie. if you are able to write all your code in commonMain only, you can remove the others. Their use case is to build on top of commonMain (which does not have access to platform specific APIs) and be aable to access platform specific apis for that target
    As for core, I just gave you a random shuffle of MPP vs JVM-only modules. You can change that by just switching kotlin gradle plugin from
    kotlin("jvm")
    to
    kotlin("multiplatform")
    in module's build.gradle.kts
    Note that JVM module can depend on MPP module, but MPP module can only depend on JVM module for its jvmMain sourceSet
    Also, sourceSet paths are implied by gradle.. You creating folders for them or not having them changes nothing 😄
    Alexandre Brown

    Alexandre Brown

    9 months ago
    Ok so I will be forced to have core an MPP module (with a jvm and a native sourceSet). Dumb question : Is it possible to have a MPP module but not publish the library externally? Since core is only used internally, would that be ok? So only referencing the MPP module from the library it via
    :core:entities
    for instance like we can for jvm modules for instance.
    Big Chungus

    Big Chungus

    9 months ago
    Sure, just add it as dependency to other MPP or JVM module. Here's how you add it to another MPP module
    kotlin {
        sourceSets {
            named("commonMain") {
                dependencies {
                    implementation(project(":core:entities"))
                }
            }
        }
    }
    And for JVM it's even simpler
    dependencies {
        implementation(project(":core:entities"))
    }
    Alexandre Brown

    Alexandre Brown

    9 months ago
    Perfect, then I think I'm all set! Thank you so much again you don't realize how this helps me !
    Big Chungus

    Big Chungus

    9 months ago
    I do. I started just as clueless when I first got into MPP 😄 It's a steep learning curve!
    What helped me most actually is browsing through the setups of other OSS MPP projects.
    Alexandre Brown

    Alexandre Brown

    9 months ago
    That is awesome, I will bookmark these for sure as the one you sent earlier already helped a lot