Kotlin 1.3-M2: new multiplatform projects model


#126

@Egorand, yes, there is a plan. Please follow the issue to get the updates.


#127

Thanks! We were able to use Dokka with the old version of MPP by just applying it to the JVM module, however I find that it’s completely unusable with the new MPP - simply apply-ing the plugin fails the build.


#128

As a result of setting up all target platform in a single Gradle file I’m getting collision of android and frontend plugins:
Cannot add task ‘:app:bundle’ as a task with that name already exists.
Is there any quick fix ?


#130

Sorry for the late reply.
Unfortunately, there is no quick workaround yet. Do you use kotlin-frontend-plugin? If so, you may submit a request to the tracker, for the task name update for kotlin-frontend-plugin


#131

Hello! For what I understood, the idea with this new mpp plugin is that as all multiplatform code as common (“expected” code) and platform (“actual” code) should sit under the same module in IntelliJ. Is that correct?

All examples show complete apps inside the same mpp module, but I would really like to keep the apps separated.

Do you have an example where an mpp project is built and through dependencies (maven, or npm, or cocoapods) the right output is used per app?

The best would be that each app would really use its own plugin (frontend-plugin for js, android-gradle-plugin for an android app, etc.) so we’ll have real world examples on how to integrate.

What do you think?


#132

— platform-agnostic and platform-specific parts of the same multiplatform module (expected declarations and the corresponding actual side in other words) should be placed into the same Gradle module. However, when we’re talking about the import of a Gradle based project into IntelliJ, a separate IDE module is created for each source set of the multiplatform module, like commonMain, commonTest and so on.

— I guess here you mean compilations configuration. Please have a look at the documentation to get more information on the subject. As said in previous answers above kotlin-mpp-example might be used for the reference of what you are asking for. Also, here is an example of an app for iOS & Android.


#133

Hello :slight_smile:
Is there a guide or some example on how to sign and setup the artifact for mavenCentral in a multiplatform project using Kotlin version 1.3.20 and Kotlin DSL?
Following the new guide I was able to avoid artifacts duplications when multi-step-publishing (even tho there is an error in the guide, OperatingSystem.current().isLinux is the correct way to check the OS). Now i just need to sign all of them and configure the publishing extension lambda. The project is this one: https://github.com/lamba92/kotlin-extlib
Here’s the Gradle build file: https://github.com/lamba92/kotlin-extlib/blob/master/build.gradle.kts

I guess this is a step in the right direction:

publishing {
    repositories {
        maven(url = "https://oss.sonatype.org/service/local/staging/deploy/maven2")
            .credentials {
                val sonatypeUsername: String by properties("local.properties")
                val sonatypePassword: String by properties("local.properties")
                username = sonatypeUsername
                password = sonatypePassword
            }
    }
}

signin {
    ???
}
...
fun properties(file: File) 
    = Properties().apply{ load(file.inputStream()) }
fun properties(fileSrc: String) 
    = properties(file(fileSrc))

#134

Thank you for your answer, I think I am starting to understand! :smile:
I set up my project to have three targets:

kotlin {
  targets {
    android()
    jvm('backend')
    js('node') {
      tasks.getByName(compilations.main.compileKotlinTaskName).kotlinOptions {
        moduleKind = 'commonjs'
      }
    }
  }
}

I have set up the source sets to have common code (expect) and the platform specific (actual) for each platform (with their dependency to the right stdlib), deploy them locally and use them in other Gradle projects. Cool!

Now, I’d like to “insert” a source set “commonClients” between common and the clients (android, node) source sets so I can write client network specific code with ktor-client libs. I added the following:

commonClientsMain {
  dependsOn commonMain
  dependencies {
    implementation kotlin('stdlib')
    implementation "io.ktor:ktor-client-core:$ktor_version"
  }
}

commonClientsTest {
  dependsOn commonTest
  dependencies {
    implementation kotlin('test-common')
    implementation kotlin('test-annotations-common')
  }
}

Adding dependsOn commonClientsMain in nodeMain was easy and I could see it being picked up as dependency in the Gradle Tool Window:

nodeMain {
  dependsOn commonClientsMain
  dependencies {
        implementation kotlin('stdlib-js')
        implementation "io.ktor:ktor-client-js:$ktor_version"
  }
}

But for Android, adding dependsOn commonClientsMain in the android sourceSet returns the following error:

Could not find method dependsOn() for arguments [source set commonClientsMain] on target android (androidJvm) of type org.jetbrains.kotlin.gradle.plugin.mpp.KotlinAndroidTarget.

After printing the sourcesets in the Gradle Script, I realised I’ve got a few more source sets automatically set up for the android target:

[android, androidAndroidTest, androidAndroidTestDebug, androidDebug, androidMain, androidRelease, androidTest, androidTestDebug, androidTestRelease]

So I tried to add it to androidMain, as a best guess:

androidMain {
  dependsOn commonClientsMain
}

It seemed to work (no scripts errors) but I still don’t see commonClientsMain as dependency of “android” in the Gradle Tool Window. So my first question, what am I doing wrong here?

Second question, I’ve got an expect fun String.emailValid() in commonMain and I’ve implemented it differently in each platform specific source sets. Now that I added commonClientsMain in the hierarchy, I am forced to implement it there by the IDE. Is that the expected behavior? How could I not have to implement this function in commonClientMain but still have to implement it down the hierarchy in the platform specific source sets?

Thank you in advance! :sweat_smile:


#135

I actually found the issue for the first question. First, I mistakenly put android { publish… } in the kotlin {} extension so it looked like there as an extra source set. Secondly, the following lines work in Gradle:

androidMain {
  dependsOn commonClientsMain
}

Building the android library (target android()) will compile and build, but IntelliJ doesn’t realize the android library has that code as well so it’s like it ignores this extra source set. Is that a known bug?

For the second question I am still looking for an answer :blush:


#136

Hi. Thank you for pointing out the mistake. However, that’s not an error, I believe.

In the sample, it’s suggested to pass the build argument manually, as it written in the comment for the configuration you meant:

// Given that -PisLinux=true command line argument is passed when running on Linux

Indeed, one may also identify the platfrom automatically, but it might be inconvenient for development to make some publications strictly included or excluded based only on the platform. Also please note that org.gradle.internal.os.OperatingSystem class is marked as internal API.

There is no such example for Kotlin Gradle DSL yet. However, you may take a look at AtomicFu publishing configuration to get the idea. Also, there is an example of publishing configuration to publish a multiplatform library to Bintray.

Do you miss a way to express something particularly in Kotlin DSL or rather a general knowledge of how to configure the publication?


#137

— have you tried to perform Gradle refresh? Did it help? There is a bug about importing MPP with Android targets among others.

– no, that’s not expected, but there is a known issue about that. We are working on tooling improvements here, there is a key request on that holding all the known problems with multilevel MPP.


#138

I thought it was invoked automatically when ran under Linux! By the way it seems to do the trick anyway

Actually both. I found few (very synthetic) guides that shows how to publish on Maven Central but always in Groovy and always giving granted how .pom works.


#139

— have you tried to perform Gradle refresh? Did it help? There is a bug about importing MPP with Android targets among others.

Yes I did, but it doesn’t help. The issue I’ve got is not that I depend on an MPP project with an Android target but inside an MPP project with an Android library target I set up a custom source set and this custom source set is not recognized by IntelliJ as a dependency, but it is recognized by Gradle as I am able to build the target after adding the code and import manually (and that code is shown full of errors in IntelliJ).

– no, that’s not expected, but there is a known issue about that. We are working on tooling improvements here, there is a key request on that holding all the known problems with multilevel MPP.

Awesome, good to know. Count me as waiting for this impatiently :smile:


#140

My colleague has created this sample by properly applying this tutorial to the multiplatform story (with Kotlin DSL). He didn’t try to actually publish it to Maven Central, but I believe the example will help to get the idea. Also, the example doesn’t contain registration of the package at Maven Central yet, but the first part of the tutorial (linked at the beginning of the referenced one) describes how to do that. In addition, the tutorial itself is a good checklist of what you need to set up.


#141

Thank you, now the situation is clear! So that’s the same problem with IDE support of the multilevel multiplatform projects which I’ve referenced above. We are working on its improvement, thank you for sharing your use case :slight_smile:


#142

Hello. We have decided to close this old topic to prevent it from growing indefinitely. Please ask your MPP-related questions on the public Slack in the multiplatform channel or create a new forum topic. Thanks!


closed #143