https://kotlinlang.org logo
#multiplatform
Title
# multiplatform
i

Ido Flax

11/07/2023, 4:14 PM
I’m having trouble getting project dependencies to be included in a native binary lib. Basically, i have a multiplatform library project that has a shared module that different libraries in the project use as a project dependency. When i publish the library and then add it as a dependency in another multiplatform project, the shared module is available for jvm but not for native. I tried to configure the library binary as both shared or static but still no go. Attached is a minimal reproduction More info in the thread->
library: dependency project:
Copy code
plugins {
    kotlin("multiplatform")
}

group = "me.example"
version = "0.0.1"

repositories {
    mavenCentral()
}

kotlin {
    jvm {
        jvmToolchain(17)
    }
    linuxX64("native"){
        binaries {
            sharedLib() { }
        }
    }
}
library project:
Copy code
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import groovy.util.NodeList
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension

plugins {
    kotlin("multiplatform")
    `maven-publish`
    id("com.github.johnrengelman.shadow") version "8.1.1" apply false
}

group = "me.example"
version = "0.0.1"

repositories {
    mavenCentral()
}


kotlin {
    jvm {
        jvmToolchain(17)
    }
    linuxX64("native") {
        binaries {
            staticLib {}
        }
    }

    sourceSets {
        val commonMain by getting {
            dependencies {
                implementation(project(":producer"))
            }
        }
    }
}

val mainCompilation = with(the<KotlinMultiplatformExtension>()) {
    targets.getByName("jvm").compilations.getByName("main")
}
val sourceJar = tasks.register("sourceJar", org.gradle.api.tasks.bundling.Jar::class) {
    from(mainCompilation.allKotlinSourceSets.map { kotlinSourceSet -> kotlinSourceSet.kotlin })
    archiveClassifier.set("sources")
}
val shadowJvmJar = tasks.register("shadowJvmJar", ShadowJar::class) {
    archiveBaseName = "${project.name}-jvm"
    from(mainCompilation.output)
    archiveClassifier.set("")
    dependsOn(tasks.named("jvmJar"))
    configurations = listOf(
        project.configurations["jvmCompileClasspath"],
        project.configurations["jvmRuntimeClasspath"],
    )
    mustRunAfter(tasks.named("generateMetadataFileForJvmPublication"))
}
with(the<PublishingExtension>()) {
    publications {
        create("shadowJvm", MavenPublication::class) {
            artifact(shadowJvmJar.map { it.archiveFile })
            artifact(sourceJar)
            artifactId = "${project.name}-jvm"
            pom.withXml {
                (asNode().get("dependencies") as NodeList).clear()
            }
        }
    }
}
tasks.withType(AbstractPublishToMaven::class) {
    if (publication?.name?.contains("jvm", ignoreCase = true) == true
        && publication?.name?.contains("shadow", ignoreCase = true) != true
    ) {
        enabled = false
    }
}
project using the library:
Copy code
plugins {
    kotlin("multiplatform") version "1.9.20"
    application
}

group = "you.example"
version = "0.0.1"

kotlin {
    jvm() {
        jvmToolchain(17)
    }
    linuxX64("native") {
        binaries {
            executable {
                entryPoint = "main"
            }
        }
    }

    sourceSets {
        commonMain {
            dependencies {
                implementation("me.example:consumer:0.0.1")
            }
        }
        jvmTest {
            dependencies {
                implementation(kotlin("test"))
            }
        }
    }
}

tasks.withType<Test>() {
    useJUnitPlatform()
}
maven local:
Copy code
.
├── consumer
│   ├── 0.0.1
│   │   ├── consumer-0.0.1-kotlin-tooling-metadata.json
│   │   ├── consumer-0.0.1-sources.jar
│   │   ├── consumer-0.0.1.jar
│   │   ├── consumer-0.0.1.module
│   │   └── consumer-0.0.1.pom
│   └── maven-metadata-local.xml
├── consumer-jvm
│   ├── 0.0.1
│   │   ├── consumer-jvm-0.0.1-sources.jar
│   │   ├── consumer-jvm-0.0.1.jar
│   │   └── consumer-jvm-0.0.1.pom
│   └── maven-metadata-local.xml
└── consumer-native
    ├── 0.0.1
    │   ├── consumer-native-0.0.1-sources.jar
    │   ├── consumer-native-0.0.1.klib
    │   ├── consumer-native-0.0.1.module
    │   └── consumer-native-0.0.1.pom
    └── maven-metadata-local.xml
consumer-native-0.0.1.module:
Copy code
{
  "formatVersion": "1.1",
  "component": {
    "url": "../../consumer/0.0.1/consumer-0.0.1.module",
    "group": "me.example",
    "module": "consumer",
    "version": "0.0.1",
    "attributes": {
      "org.gradle.status": "release"
    }
  },
  "createdBy": {
    "gradle": {
      "version": "8.4"
    }
  },
  "variants": [
    {
      "name": "nativeApiElements-published",
      "attributes": {
        "artifactType": "org.jetbrains.kotlin.klib",
        "org.gradle.category": "library",
        "org.gradle.usage": "kotlin-api",
        "org.jetbrains.kotlin.native.target": "linux_x64",
        "org.jetbrains.kotlin.platform.type": "native"
      },
      "dependencies": [
        {
          "group": "org.jetbrains.kotlin",
          "module": "kotlin-stdlib",
          "version": {
            "requires": "1.9.20"
          }
        },
        {
          "group": "me.example",
          "module": "producer",
          "version": {
            "requires": "0.0.1"
          }
        }
      ],
      "files": [
        {
          "name": "consumer.klib",
          "url": "consumer-native-0.0.1.klib",
          "size": 4996,
          "sha512": "1fc221db7e53b44fa118e0a26e0612b92fed9e1bee908feed165ee7cb4d44dc1dfd858fd8795551980e9b0af1d6336d1c5548e7738b8b7b8d1a28cecaac90e94",
          "sha256": "c8e3f1fe0598f3fd3be8e56b6f268a7264308449975e7c7f31f03b326361cfe8",
          "sha1": "0601bcf215be95ba55e1294eb8e4a93fae4f1a25",
          "md5": "9172349de0900ccbb0485fa7e4580f90"
        }
      ]
    },
    {
      "name": "nativeSourcesElements-published",
      "attributes": {
        "org.gradle.category": "documentation",
        "org.gradle.dependency.bundling": "external",
        "org.gradle.docstype": "sources",
        "org.gradle.usage": "kotlin-runtime",
        "org.jetbrains.kotlin.native.target": "linux_x64",
        "org.jetbrains.kotlin.platform.type": "native"
      },
      "files": [
        {
          "name": "consumer-native-0.0.1-sources.jar",
          "url": "consumer-native-0.0.1-sources.jar",
          "size": 805,
          "sha512": "713515a6b84860d7f3e3f6c8e703f27f5099ba56aa19ce1ad435d5801b7e9d65c7d6d0c7a021bd62a93cce6c5e7171557b153dc3bd63f616cc40a89f9d59e858",
          "sha256": "6b45cc8c6c29b53dbcc2b6e908ae60b5e204a6e775fee478fa290f0f6e851d22",
          "sha1": "a9a7c10ac113dd19d5313c5b1a3b5a9108f026f7",
          "md5": "a7bf47e049fc32b84586adf2796427e8"
        }
      ]
    }
  ]
}
@dsavvinov FYI^^ please help K
PS the error happens when running
runReleaseExecutableNative
:
Copy code
Execution failed for task ':compileKotlinNative'.
> Could not resolve all files for configuration ':nativeCompileKlibraries'.
   > Could not find me.example:producer:0.0.1.
     Searched in the following locations:
       - file:/Users/myself/.m2/repository/me/example/producer/0.0.1/producer-0.0.1.pom
       - <https://repo.maven.apache.org/maven2/me/example/producer/0.0.1/producer-0.0.1.pom>
     Required by:
         project : > me.example:consumer:0.0.1 > me.example:consumer-native:0.0.1
Publishing the producer causes the error to go away, but the point is to have a native lib with the dependencies included, like the shadowJar Also notice the custom shadowJvmJar, since shadow plugin doesn’t work out of the box with multiplatform
d

dsavvinov

11/08/2023, 2:14 PM
The
shadowJar
plugin doesn’t support K/N klibs (or any Kotlin klibs, for that matter) I’m not aware plugins that provide similar functionality for K/N at the moment
i

Ido Flax

11/08/2023, 2:16 PM
Yes i didn’t expect the shadow plugin to do it. i just wanted to know if there’s a way to include the project dependencies in a shared/static lib
3 Views