Hi guys, I already have several modules that have ...
# multiplatform
o
Hi guys, I already have several modules that have no reference to android/ios. So really pure Kotlin modules, business logic etc. The idea is the following three following repo's: • core • android implementations • ios implementations So I don't want to use the expect, actual mechanism, but just the interface/implementation mechanism. How do I set something like this up?
k
you could do 3 separate repos, or 3 modules in the same repo
o
Yes, 3 repos is what I want. Which multiplatform module project setup do I need to chose in intellij idea for the Core repo? Core repo consists of multiple modules. In the android/ios default setup I get android/ios folders created what I not want. I want the core repo to be pure, not having any mention of any platform.
@Kris Wong
Do I need to choose Multiplatform Library?
k
that sounds closest to what you want
r
Even if all your code is common, the core module still needs to declare what platforms it builds for. So those templates will generate source folders for the platforms but you can delete the ones you don't have any code in. But you'll still have them declared in gradle.
o
Allright thanks. I have two more questions: Question 1: Right now my Core modules have the `
Copy code
apply plugin: 'java-library'
apply plugin: 'kotlin'
in there build.gradle. Will this be replaced now with
Copy code
plugins {
    id 'org.jetbrains.kotlin.multiplatform' version '1.3.61'
}
? Question 2:
The generated gradles are in default groovy I see (build.gradle). Is it recommended to switch to the newer kotlin dsl gradle files? (build.gradle.kts) ?
r
yes on 1. For 2, opinions vary. Long-term I think kts is the way to go and I use it for my own projects, but IDE support can be inconsistent. There should be a checkbox on the templates though to generate kts scripts if you want.
o
I didn't see a checkbox for generating kts scripts. Im using intellij idea 2019.3.3
r
Oh. It's in the gradle kotlin templates but not the kotlin ones
There's also samples online you can look at, eg https://github.com/touchlab/KaMPKit
k
Kotlin DSL is much easier to work with
o
Thanks guys, you've been helpful. Assuming we have this 3 repo setup, how is building meant? Am I supposed to open the core repo in intellij idea and open the android repo in Android studio? How is building and running done.
Should I publish the Core to maven and make the android repo just use it as a external dependency? How would the flow of that go, debuggin etc.
k
that's up to you. either include it as an inline subproject, or publish it to Maven. it depends on your work flows and how you want to run module releases
o
If you go down the publish to Maven path, does that mean that, for example I am trying to fix a bug in Core, and in order to test if it works on Android, I have to first publish it to maven with a new release 1.0.x+1? Which makes the release track polluted for just some trial and error
Or am I missing somethign
k
that's correct
it's also not too complicated to define a flag in a local properties file that will allow each developer to switch between inline project, and artifact repo (default)
o
So that makes the publishing to Maven thing really not an option, since trial and error developing isn't possible with that. Publishing Core to maven is only meant for teams were the core repo and android repo are really separate islands I guess.
k
but for iOS, ultimately you need a framework file. and if have multiple MPPs, you'll need one umbrella framework
i'd say that's correct
it's really to everyone's benefit if you have a unit test for every use case in your MPP
o
I understand
I should to delete all of those sourceSets except commonMain and commonTest, right?
I see that every module has is own build.gradle with mpp and sourceset definitions. What is the use of the root build.gradle (yellow one)?
k
you can try, but it may not build the target if you delete it's source set
it's for project level configuration
o
My source was this:
Russell Wolf
Even if all your code is common, the core module still needs to declare what platforms it builds for. So those templates will generate source folders for the platforms but you can delete the ones you don't have any code in. But you'll still have them declared in gradle.
Previously in the thread
k
give it a try
o
So should I put all those sourcesets into the single root build.gradle file, making the seperate module gradle's redundant?
k
no
you should only put things in the root that apply to every module
o
The similarity between all modules is that they only have commonMain and commonTest sourcesets. The difference ofcourse is that each module will have different dependencies.
So with this situation, I guess the root build.gradle doesn't have anything to add that it can apply for every module, making the root build.gradle redundant/useless? Is it better for me to delete the root build.gradle?
k
i suspect you will apply the KMP plugin at that level
i actually haven't tried a multi-module setup for KMP
o
What about the target declaration
Can I just declare this (everything in the red square) once in the root build.gradle, and not mention it again in the individual module build.gradle's ?
k
i doubt it, you'll have to experiment i think
o
Ok
Can I just put this code in every module build.gradle, and delete the root build.gradle completely?
r
You can omit the root level gradle file if you want. I usually have a small one with common repositories and some other simple config declared in an
allprojects{}
block I don't think you can share target definitions there but try it if you're curious. One way you can share some of that logic is using
buildSrc
. For example I have a bunch of helper logic here in Multiplatform Settings so I can just call
standardConfiguration()
at the module level. https://github.com/russhwolf/multiplatform-settings/blob/master/buildSrc/src/main/kotlin/BuildHelpers.kt
o
Thanks, gradle was always a black box, magic place for me
But now I learn slowly how it actually works
How do I specify plugins for every module in the root gradle?
This doesn't work
Gives me a build error
r
Yeah you can't do everything from there. Plugins block has to be at the top.
o
But then it says
Plugin [id: 'com.android.library'] was not found in any of the following sources:
Taken from the KampKit github sample @Kris Wong, I assume this is necessary for every module even tho it has no android code?
Is it even required for my domain code module to specify the above?
r
You need an
android
block with at least a
compileSdkVersion
for any module with one of the Android plugins applied. If you use
jvm
for the Android side you don't need it
k
if you are not using Android SDK APIs, then you don't need the android plugin
change your target to JVM
otherwise, you will need android config block, AndroidManifest.xml, etc...
o
Ah ok I get it, because jvm() target also works seamlessly on Android side ofcourse, right?
k
correct
o
Hey @Kris Wong, you were saying that there two options to use a mpp repo with a standalone android repo. The Publish to maven way and the other way. How should my Android repo reference the mpp repo this other way?
k
will there be frequent or infrequent changes in the KMP module?
o
Hmm, not sure yet. What would the difference be in setup?
k
well, if it were frequent, then I would add it as a subproject
otherwise I'd drop the artifact in libs
o
Frequent changes in the KMP module, as in constantly trial and error debugging?
How do I add the kmp project as a subproject?
And an artifact is something like a generated .jar of the project but then in kotlin mpp form?
k
it would work the same as any other subproject in gradle
o
But if I add it as a subproject to my android project, won't the files be duplicated? Or is there a way I can make my android project add the mpp project as a subproject, without affecting the on-disk structure?
k
i would use git submodules
o
Hmm, is it hard to use?
Also, why would the link the artifact of the mpp to android not work for frequent changes?
k
i don't understand your question
o
You were suggesting me to drop the artifact in the libs folder, when the mpp has infrequent changes. Why shouldn't this be applied when it has frequently changes?
k
you really want to be manually copying artifacts around on every change, and not know which version of the artifact is actually in your libs folder?
o
I get it
So we are talking about the artifacts in the.idea/artifacts/ folder right?
@Kris Wong I set up the git submodules in the android repo. It looks something like this now:
Copy code
android-repo/
    build.gradle
    settings.gradle.kts
    (..android-modules)
    core (git submodule) /
        (..mpp-modules)
        build.gradle
        settings.gradle.kts
How should my android modules build.gradles reference the mpp modules as a dependency?
k
include
it in settings.gradle, and add it as a
project
dependency in whatever project consumes it
o
Thanks for the quick response Kris, you're really helpful. Given a module_a in the core folder, does that mean the android-repo settings.gradle.kts should look like the following?:
Copy code
include(..other, ":module_a")
k
yes. you just need to tell it where to find each project, since they are not in the source root
o
@Kris Wong Ok, this is how my settings.gradle.kts looks now. It works I think. The only issue I get now is the following build error:
Caused by: org.gradle.plugin.management.internal.InvalidPluginRequestException: Plugin request for plugin already on the classpath must not include a version
k
you have multiple projects that are using the same gradle plugin. you need to resolve it in the settings file, and remove the version from the build file
o
Ok, just for clarification, If I change this:
Copy code
plugins {
    kotlin("multiplatform") version "1.3.70"
}
to this:
Copy code
plugins {
    kotlin("multiplatform")
}
will that make gradle automatically use the latest version of the kotlin multiplatform plugin?
k
no
o
Which version would be used then?
k
try it and find out
o
I did, now getting the following error:
Plugin [id: 'org.jetbrains.kotlin.multiplatform'] was not found in any of the following sources:
. Looks like omitting the plugin version number isn't an option?
k
are you resolving it in the settings file?
o
No I didn't, because frankly I don't know how to. I found this: Do you mean something like this?:
k
yes
o
Ok, interesting, thanks
Is there any reason why the KaMPKit github doesn't have this?
k
i am going to assume app is including the version
o
o
I see
Whats the difference between useModule and classpath?
k
the project is using
buildSrc
, which is a nice concept, but adds slight complication
o
I get it
So I should just stick to the settings.gradle.kts example earlier in the conversation right
I managed to make it work by resolving it in the root build.gradle.kts. Thanks for the help Kris!
🍻 1