use a kotlin multiplatform lib in another kotlin multiplatfor lib - kotlin

I have create a multiplatform kotlin librarie (L1)using intellij in gradle, who build in JS and JVM.
I want to reuse this lib in another multiplatform kotlin lib L2
How can I do it?
I have issue with importing the "common" part of L1 in the common target of L2, (the eror are a lot of Unresolved reference), basicaly the common target of L2 cannot find the implementation contained in L1.
I have only this issue with the common target, the js and jvm work fine.
the gradle of L1, the lib to be reused
kotlin {
jvm {
compilations.all {
kotlinOptions.jvmTarget = "1.8"
}
testRuns["test"].executionTask.configure {
useJUnit()
}
}
js(LEGACY) {
browser {
testTask {
useKarma {
useChromeHeadless()
webpackConfig.cssSupport.enabled = true
}
}
}
}
sourceSets {
val commonMain by getting
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val jvmMain by getting
val jvmTest by getting {
dependencies {
implementation(kotlin("test-junit"))
}
}
val jsMain by getting
val jsTest by getting {
dependencies {
implementation(kotlin("test-js"))
}
}
}
}
the gradle of L2,the lib who reuse L1:
sourceSets {
val commonMain by getting {
dependencies {
implementation("groupId:L1:1.0-SNAPSHOT")
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val jvmMain by getting {
dependencies {
implementation("groupId:L1-jvm:1.0-SNAPSHOT")
}
}
val jvmTest by getting {
dependencies {
implementation(kotlin("test-junit"))
}
}
val jsMain by getting {
dependencies {
implementation("groupId:L1-js:1.0-SNAPSHOT")
}
}
val jsTest by getting {
dependencies {
implementation(kotlin("test-js"))
}
}
}
}

Related

Kotlin Multiplatform. Cannot access class SqlDriver.Schema. Check your module classpath for missing or conflicting dependencies

I am trying to build a KMP library targeting iOS, Android, JS(Browser), Mac, Windows and Linux. For now I am only using Ktor and SQLDelight as a dependency. But getting the following issue in nativeMain's actual implementation while creating driver for SQLDelight
While the same code doesn't give any issue for iOS main which is also using the same NativeSqliteDriver (I need them separately since Ktor client for iOS and desktop platforms are separate).
Following is my build.gradle.kts
plugins {
kotlin("multiplatform") version "1.5.31"
id("maven-publish")
id("com.android.library")
kotlin("plugin.serialization") version "1.5.31"
id("com.squareup.sqldelight") version "1.5.3"
}
group = "me.group"
version = "1.0-SNAPSHOT"
val xcFrameworkName = "AddressLib"
repositories {
google()
mavenCentral()
}
kotlin {
jvm {
compilations.all {
kotlinOptions.jvmTarget = "1.8"
}
testRuns["test"].executionTask.configure {
useJUnit()
}
}
js(LEGACY) {
browser {
commonWebpackConfig {
cssSupport.enabled = true
}
}
}
val xcFramework = XCFramework(xcFrameworkName)
val hostOs = System.getProperty("os.name")
val isMingwX64 = hostOs.startsWith("Windows")
when {
hostOs == "Mac OS X" -> macosX64("native") {
binaries.framework(xcFrameworkName) {
xcFramework.add(this)
}
}
hostOs == "Linux" -> linuxX64("native")
isMingwX64 -> mingwX64("native")
else -> throw GradleException("Host OS is not supported in Kotlin/Native.")
}
android()
ios {
binaries.framework(xcFrameworkName) {
xcFramework.add(this)
}
}
val coroutinesVersion = "1.5.2-native-mt"
val serializationVersion = "1.3.1"
val ktorVersion = "1.6.5"
val sqlDelightVersion = "1.5.3"
val napierVersion = "2.2.0"
val koinVersion = "3.1.4"
sourceSets {
val commonMain by getting {
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesVersion")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:$serializationVersion")
implementation("io.ktor:ktor-client-core:$ktorVersion")
implementation("io.ktor:ktor-client-serialization:$ktorVersion")
implementation("io.ktor:ktor-client-logging:$ktorVersion")
implementation("com.squareup.sqldelight:runtime:$sqlDelightVersion")
implementation("io.insert-koin:koin-core:$koinVersion")
implementation("io.github.aakira:napier:$napierVersion")
}
}
val commonTest by getting
val jvmMain by getting {
dependencies {
implementation("io.ktor:ktor-client-java:$ktorVersion")
implementation("com.squareup.sqldelight:sqlite-driver:$sqlDelightVersion")
}
}
val jvmTest by getting
val jsMain by getting {
dependencies {
implementation("io.ktor:ktor-client-js:$ktorVersion")
implementation("com.squareup.sqldelight:sqljs-driver:$sqlDelightVersion")
}
}
val jsTest by getting
val nativeMain by getting {
dependencies {
implementation("io.ktor:ktor-client-curl:$ktorVersion")
implementation("com.squareup.sqldelight:native-driver:$sqlDelightVersion")
}
}
val nativeTest by getting
val androidMain by getting {
dependencies {
implementation("io.ktor:ktor-client-android:$ktorVersion")
implementation("com.squareup.sqldelight:android-driver:$sqlDelightVersion")
}
}
val androidTest by getting {
dependencies {
implementation(kotlin("test-junit"))
implementation("junit:junit:4.13.2")
}
}
val iosMain by getting {
dependencies {
implementation("io.ktor:ktor-client-ios:$ktorVersion")
implementation("com.squareup.sqldelight:native-driver:$sqlDelightVersion")
}
}
val iosTest by getting
}
sqldelight {
database("AddressDatabase") {
packageName = "com.library.address.database"
}
}
}
android {
compileSdkVersion(31)
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
defaultConfig {
minSdkVersion(24)
targetSdkVersion(31)
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}
publishing {
repositories {
maven {
credentials {
username = "<username>"
password = "<pwd>"
}
url = URI("https://mymavenrepo.com")
}
}
}
So it seems the issue was somewhat due to same dependency being added to the build gradle twice and it's corresponding code being added twice as well. To solve the same I had to make a separate source set like the following
val sqlDriverNativeMain by creating {
dependsOn(commonMain)
dependencies {
implementation("com.squareup.sqldelight:native-driver:$sqlDelightVersion")
}
}
val iosMain by getting {
dependsOn(sqlDriverNativeMain)
dependencies {
implementation("io.ktor:ktor-client-ios:$ktorVersion")
}
}
val nativeMain by getting {
dependsOn(sqlDriverNativeMain)
dependencies {
implementation("io.ktor:ktor-client-curl:$ktorVersion")
}
}
and after that move the driver creation code inside the sourceSet directory named sqlDriverNativeMain. This resolved the issue.

Imports not resolving in generated GraphQL queries with Apollo3

I've noticed that when I generate class files from GraphQL queries, the imports for Apollo3 aren't resolving. See the screenshot below.
I'm using the Apollo3 GraphQL library in a Kotlin Multiplatform project. The Apollo Get Started With Multiplatform docs are pretty confusing and I may have my project configured incorrectly.
I can download the schema, and generate the files without a problem.
./build.gradle.kts
buildscript {
repositories {
gradlePluginPortal()
google()
mavenCentral()
}
dependencies {
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.21")
classpath("com.android.tools.build:gradle:7.0.0")
}
}
allprojects {
repositories {
google()
mavenCentral()
}
}
tasks.register("clean", Delete::class) {
delete(rootProject.buildDir)
}
./shared/build.gradle.kts
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
plugins {
kotlin("multiplatform")
id("com.android.library")
id("com.apollographql.apollo3").version("3.0.0-alpha03")
}
kotlin {
android()
val iosTarget: (String, KotlinNativeTarget.() -> Unit) -> KotlinNativeTarget =
if (System.getenv("SDK_NAME")?.startsWith("iphoneos") == true)
::iosArm64
else
::iosX64
iosTarget("ios") {
binaries {
framework {
baseName = "shared"
}
}
}
sourceSets {
val commonMain by getting {
dependencies {
implementation("com.apollographql.apollo:apollo-runtime-kotlin:2.5.7")
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val androidMain by getting
val androidTest by getting {
dependencies {
implementation(kotlin("test-junit"))
implementation("junit:junit:4.13.2")
}
}
val iosMain by getting
val iosTest by getting
}
}
android {
compileSdkVersion(30)
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
defaultConfig {
minSdkVersion(23)
targetSdkVersion(30)
}
}
I was having the same issue. In my case, it was fixed by making sure the runtime dep is using the same version as the apollo plugin applied (3.0.0-alpha03).
So try changing the content in ./shared/build.gradle.kts file, replacing this line
implementation("com.apollographql.apollo:apollo-runtime-kotlin:2.5.7")
with
implementation("com.apollographql.apollo:apollo-runtime-kotlin:3.0.0-alpha03")

How to share kotlin multiplatform targets between submodules?

After an eternity I managed to setup a kotlin multi-platform and multi-module project. As there is almost no proper guide or documentation, I have just one more issue I couldn't solve.
Can I share kotlin multiplatform targets between the submodules?
Right now every submodule has a build.gradle.kts containing:
kotlin {
jvm {
compilations.all {
kotlinOptions.jvmTarget = "15"
}
}
js(IR) {
nodejs()
browser {
testTask {
useKarma {
useChromeHeadless()
webpackConfig.cssSupport.enabled = true
}
}
}
}
}
Obviously, I want all modules to compile to the same platforms using the same versions and it would be nice to not copy this snippet for every module.
Not to mention that the test dependencies are identical as well.
sourceSets {
val commonTest by getting {
dependencies {
implementation("io.kotest:kotest-framework-api:$kotestVersion")
implementation("io.kotest:kotest-assertions-core:$kotestVersion")
implementation("io.kotest:kotest-property:$kotestVersion")
}
}
val jvmTest by getting {
dependsOn(commonTest)
dependencies {
implementation("io.kotest:kotest-runner-junit5:$kotestVersion")
}
}
val jsTest by getting {
dependsOn(commonTest)
dependencies {
implementation("io.kotest:kotest-framework-engine:$kotestVersion")
}
}
}

Getting kotlinx serialization working in multiplatform project

I'm taking Kotlin seriazliation for a test drive in a multiplatform project in Kotlin 1.4-M2, following the tutorial on github, but i'm not getting the serialization bit to compile.
This is my build.gradle.kts
plugins {
val kotlinVersion = "1.4-M2"
kotlin("multiplatform") version kotlinVersion
kotlin("plugin.serialization") version kotlinVersion
}
repositories {
mavenCentral()
maven {
url = uri("https://dl.bintray.com/kotlin/kotlin-eap")
}
maven {
url = uri("https://kotlin.bintray.com/kotlinx")
}
jcenter()
gradlePluginPortal()
}
kotlin {
jvm {
compilations.all {
kotlinOptions.jvmTarget = "11"
}
}
js(IR) {
moduleName = "hotel"
browser {
dceTask {
keep(
...
)
}
binaries.executable()
}
}
sourceSets {
// val serializationVersion = "0.20.0-1.4-M2"
val serializationVersion = "0.20.0"
val commonMain by getting {
dependencies {
implementation(kotlin("stdlib-common"))
implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$serializationVersion")
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val jvmMain by getting {
dependencies {
implementation(kotlin("stdlib-jdk8"))
implementation(kotlin("reflect"))
implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime:$serializationVersion")
}
}
val jvmTest by getting {
dependencies {
implementation(kotlin("test-junit"))
}
}
val jsMain by getting {
dependencies {
implementation(kotlin("stdlib-js"))
implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime-js:$serializationVersion")
}
}
val jsTest by getting {
dependencies {
implementation(kotlin("test-js"))
}
}
all {
languageSettings.enableLanguageFeature("InlineClasses")
}
}
}
I've tried it on a simple data class
#Serializable
data class Test(
val blah: Int = 0
)
import kotlinx.serialization.json.Json <<<--- Unresolved reference: kotlinx
import kotlinx.serialization.json.JsonConfiguration <<<--- Unresolved reference: kotlinx
import kotlin.js.ExperimentalJsExport
import kotlin.js.JsExport
...
fun main() {
val json = Json(JsonConfiguration.Default)
val jstring = json.toJson(Test.serializer(), Test(blah = 3))
println(jstring.toString())
}
It's complaining about Unresolved reference: kotlinx
Is there something specific one needs to do to make kotlinx imports work or should i be using different versions of the serializer libraries?
I got some help on Slack, thanks Sergey!
https://kotlinlang.org/eap/ shows the versions compatible with the EAP
or Milestone releases. You should use the serialization runtime
version 0.20.0-1.4-M2. Note that with this version, you need to add a
single dependency on kotlinx-serialization-runtime in the commonMain
source set, not separate dependencies on
kotlinx-serialization-runtime-common and the platform parts. See the
Specifying dependencies only once section here:
https://blog.jetbrains.com/kotlin/2020/06/kotlin-1-4-m2-released
So in short, my plugin should be matching my Kotlin version
plugins {
val kotlinVersion = "1.4-M2"
kotlin("multiplatform") version kotlinVersion
kotlin("plugin.serialization") version kotlinVersion
}
then under sourceSets, i should be using a single dependency instead of one per platform
sourceSets {
val serializationVersion = "0.20.0-1.4-M2"
val commonMain by getting {
dependencies {
implementation(kotlin("stdlib-common"))
implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime:$serializationVersion")
}
}
JVM and JS Main should not have any serialization plugin, so those lines should be removed
val jvmMain by getting {
dependencies {
implementation(kotlin("stdlib-jdk8"))
implementation(kotlin("reflect"))
// implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime:$serializationVersion") <<-- remove this
val jsMain by getting {
dependencies {
implementation(kotlin("stdlib-js"))
// implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime-js:$serializationVersion") <<-- remove this
}
}

Intellij autocomplete failing on multiplatform library dependencies

I've created a multiplatform library that I consume in a different multiplatform project. After including the dependency I am able to use the libraries in commonMain without issue and all targets build without errors. However, intellij autocomplete does not know about my new types. I have invalidated caches and restarted the application many times, but it just cannot find this type. Anybody encountered this?
just in case, here is my build.gradle.kts:
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpack
buildscript {
repositories {
jcenter()
}
}
plugins {
kotlin("multiplatform") version "1.3.61"
}
repositories {
jcenter()
maven( "https://dl.bintray.com/kotlin/ktor" )
mavenCentral()
mavenLocal()
}
val ktor_version = "1.1.3"
val logback_version = "1.2.3"
kotlin {
js {
browser { }
}
jvm {
compilations.named("main") {
tasks.getByName<Copy>(processResourcesTaskName) {
dependsOn("jsBrowserWebpack")
tasks.named<KotlinWebpack>("jsBrowserWebpack") {
from(entry.name, destinationDirectory)
}
}
}
}
sourceSets {
val commonMain by getting {
dependencies {
implementation(kotlin("stdlib-common"))
api("github.fatalcatharsis:constraint:1.0-SNAPSHOT")
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val jvmMain by getting {
dependencies {
implementation( kotlin("stdlib-jdk8"))
implementation( "io.ktor:ktor-server-netty:$ktor_version")
implementation( "io.ktor:ktor-html-builder:$ktor_version")
implementation( "ch.qos.logback:logback-classic:$logback_version")
}
}
val jvmTest by getting {
dependencies {
implementation(kotlin("test"))
implementation(kotlin("test-testng"))
}
}
val jsMain by getting {
dependencies {
implementation( kotlin("stdlib-js"))
}
}
val jsTest by getting {
dependencies {
implementation( kotlin("test-js"))
}
}
}
}
tasks.register<JavaExec>("run") {
dependsOn("jvmJar")
group = "application"
main = "sample.SampleJvmKt"
val t = tasks.named<Jar>("jvmJar")
classpath(configurations.named("jvmRuntimeClasspath"), t.get() )
}