KSP on Kotlin Multiplatform fails on the kspJs with "Collection has more than one element." - kotlin

I'm experimenting with KSP (Kotlin Symbol Processing) to see what it's capable of and I'm trying to get it working on a Kotlin Multiplatform project.
When I only enable kspJvm, it works perfectly, as soon as I enable kspJs as well, it fails with "Collection has more than one element."
I've recreated the issue in this demo github project:
https://github.com/janvladimirmostert/observable-demo
In my processor, I have the following config:
build.gradle.kts:
val kspVersion: String by project
group = "io.jvaas"
plugins {
kotlin("multiplatform")
}
kotlin {
jvm {
compilations.all {
kotlinOptions.jvmTarget = "11"
}
}
sourceSets {
val commonMain by getting
val jvmMain by getting {
dependencies {
implementation("com.google.devtools.ksp:symbol-processing-api:$kspVersion")
}
}
}
}
gradle.properties:
kotlinVersion=1.6.0
kspVersion=1.6.0-1.0.1
src/commonMain/kotlin/io/jvaas/observe/Observable.kt
package io.jvaas.observe
annotation class Observable
src/jvmMain/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider
io.jvaas.observe.ObservableProcessorProvider
src/jvmMain/kotlin/io/jvaas/observe/ObservableProcessor.kt
class ObservableProcessor(
val codeGenerator: CodeGenerator,
val logger: KSPLogger,
) : SymbolProcessor {
...
}
class ObservableProcessorProvider : SymbolProcessorProvider {
override fun create(
environment: SymbolProcessorEnvironment
): SymbolProcessor {
return ObservableProcessor(environment.codeGenerator, environment.logger)
}
}
In my consumer I have the following:
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackOutput.Target.UMD
group = "com.od"
plugins {
application
id("com.google.devtools.ksp") version "1.6.0-1.0.1"
kotlin("plugin.serialization")
kotlin("multiplatform")
id("com.github.johnrengelman.shadow")
}
kotlin {
jvm {
compilations.all {
kotlinOptions.jvmTarget = "11"
}
}
js(IR) {
browser {
binaries.executable()
webpackTask {
output.libraryTarget = UMD
}
}
}
sourceSets {
val commonMain by getting {
dependencies {
val serializationVersion = "1.3.1"
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$serializationVersion")
implementation("io.jvaas:jvaas-observe")
}
}
val commonTest by getting
val jvmMain by getting {
dependencies {
}
}
val jvmTest by getting {
dependencies {
implementation(kotlin("test-junit"))
}
}
val jsMain by getting
val jsTest by getting {
dependencies {
implementation(kotlin("test-js"))
}
}
}
}
dependencies {
add("kspJvm", "io.jvaas:jvaas-observe")
// add("kspJs", "io.jvaas:jvaas-observe") // <--- fails if enabled
//ksp("io.jvaas:jvaas-observe")
}
application {
mainClassName = "com.od.demo.Main"
}
applications/od-server/src/commonMain/kotlin/com/od/demo/Blah.kt
package com.od.demo
import io.jvaas.observe.Observable
#Observable
class Blah {
var test1: String = ""
var test2: Int = 0
var test3: Array<String> = arrayOf()
}
This correctly gets processed when the kspJvm option is enabled and correctly outpus a file at
applications/od-server/build/generated/ksp/jvmMain/kotlin/com/od/demo/BlahO.kt
If I enable it for kspJs, it fails
add("kspJs", "io.jvaas:jvaas-observe")
Execution failed for task ':applications:od-server:compileProductionExecutableKotlinJs'.
> Failed to calculate the value of task ':applications:od-server:compileProductionExecutableKotlinJs' property 'entryModule$kotlin_gradle_plugin'.
> Collection has more than one element.
I've tried the usual gradle build --info / --debug / --scan but it's not clear where I can start looking to resolve this issue.
As mentioned above, I made a demo project to demonstrate the error:
https://github.com/janvladimirmostert/observable-demo
Any ideas on how to resolve that error?

Issue has been fixed in https://github.com/google/ksp/issues/744 but I'm not sure if it has been released yet.

Related

IntelliJ Show an Error on kotlinx.serialization, but compiling works

I have a problem where IntelliJ tells me that the #Serializable annotation cannot be accessed as it's internal to kotlin.io etc. The kotlinx.serialization package also shows as an unresolved reference.
Apparently, this has something to do with using Kotlin 1.7.x as when I downgrade to Kotlin 1.6.10 the issue no longer presents itself. However, Gradle compiles and runs the application without issue even on 1.7.10. Therefore, this seems like ultimately an issue with IntelliJ and/or one of my settings.
This is a Kotlin Multiplatform project. I've tried many things to fix this:
Reloading Gradle Project
Refreshing Gradle Dependencies
Completely refreshing all project indexes via the new Repair IDE tool
Deleting .idea and .gradle folders
Adjusting the project structure versions
Generally messing around with versions and settings
My build.gradle.kts:
plugins {
application
kotlin("multiplatform") version Versions.kotlin
kotlin("plugin.serialization") version Versions.kotlin
}
group = "com.example"
version = "4.0"
repositories {
mavenCentral()
}
kotlin {
jvm {
compilations.all {
kotlinOptions.jvmTarget = "17"
}
withJava()
testRuns["test"].executionTask.configure {
useJUnitPlatform()
}
}
js {
binaries.executable()
browser {
commonWebpackConfig {
cssSupport.enabled = true
}
webpackTask {
outputFileName = "app.js"
}
}
}
sourceSets {
val commonMain by getting {
dependencies {
implementation("io.ktor:ktor-client-core:${Versions.ktor}")
implementation("io.ktor:ktor-client-websockets:${Versions.ktor}")
implementation("io.ktor:ktor-serialization-kotlinx-json:${Versions.ktor}")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:${Versions.serialization}")
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val jvmMain by getting {
dependencies {
implementation("io.ktor:ktor-server-core:${Versions.ktor}")
implementation("io.ktor:ktor-server-auth:${Versions.ktor}")
implementation("io.ktor:ktor-serialization:${Versions.ktor}")
implementation("io.ktor:ktor-server-html-builder:${Versions.ktor}")
implementation("io.ktor:ktor-client-cio:${Versions.ktor}")
implementation("io.ktor:ktor-server-cio:${Versions.ktor}")
implementation("io.ktor:ktor-server-websockets:${Versions.ktor}")
}
}
val jvmTest by getting
val jsMain by getting {
dependencies {
implementation("io.ktor:ktor-client-js:${Versions.ktor}")
implementation("io.ktor:ktor-client-json:${Versions.ktor}")
implementation("io.ktor:ktor-client-auth:${Versions.ktor}")
implementation("io.ktor:ktor-client-websockets:${Versions.ktor}")
implementation("io.ktor:ktor-client-serialization:${Versions.ktor}")
implementation("org.jetbrains.kotlin-wrappers:kotlin-react:${Versions.react}")
implementation("org.jetbrains.kotlin-wrappers:kotlin-react-dom:${Versions.react}")
}
}
val jsTest by getting
}
}
application {
mainClass.set("com.example.app.ServerKt")
}
tasks.named<Copy>("jvmProcessResources") {
val jsBrowserDistribution = tasks.named("jsBrowserDistribution")
from(jsBrowserDistribution)
}
tasks.named<JavaExec>("run") {
dependsOn(tasks.named<Jar>("jvmJar"))
classpath(tasks.named<Jar>("jvmJar"))
}
object Versions {
const val ktor = "2.0.3"
const val kotlin = "1.7.10"
const val coroutines = "1.6.3"
const val serialization = "1.3.3"
const val react = "18.2.0-pre.358-compat"
}
The class that is having issues is:
import kotlinx.serialization.Serializable
#Serializable
data class Customer(val id: Int, val firstName: String, val lastName: String)
I appreciate any help I can get

Publish kotlin multiplatform library to Maven Central (InvalidMavenPublicationException multiple artifacts with the identical ...)

As Jcenter will be shutdown soon I’m trying to migrate my libs to Maven Central. I have searched a lot to find any working script but with no luck. There is official docs, but it is like a joke, there just told to put maven-publish plugin to the gradle script and voila that’s it.
Currently I'm getting error:
Caused by: org.gradle.api.publish.maven.InvalidMavenPublicationException: Invalid publication 'js': multiple artifacts with the identical extension and classifier ('jar', 'sources').
My script looks like this:
plugins {
id("kotlin-multiplatform")
id("org.jetbrains.dokka") version "1.4.0-rc"
`maven-publish`
signing
}
kotlin {
sourceSets {
jvm()
js() {
nodejs()
browser()
}
linuxX64()
linuxArm64()
mingwX64()
macosX64()
iosArm64()
iosX64()
val commonMain by getting {
dependencies {
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val jsMain by getting {
dependencies {
}
}
val jsTest by getting {
dependencies {
implementation(kotlin("test-js"))
}
}
val jvmMain by getting {
dependencies {
}
}
val jvmTest by getting {
dependencies {
implementation(kotlin("test"))
implementation(kotlin("test-junit"))
}
}
val nativeMain by creating {
dependsOn(commonMain)
dependencies {
}
}
val linuxX64Main by getting {
dependsOn(nativeMain)
}
val linuxArm64Main by getting {
dependsOn(nativeMain)
}
val mingwX64Main by getting {
dependsOn(nativeMain)
}
val macosX64Main by getting {
dependsOn(nativeMain)
}
val iosArm64Main by getting {
dependsOn(nativeMain)
}
val iosX64Main by getting {
dependsOn(nativeMain)
}
}
}
tasks {
create<Jar>("javadocJar") {
dependsOn(dokkaJavadoc)
archiveClassifier.set("javadoc")
from(dokkaJavadoc.get().outputDirectory)
}
dokkaJavadoc {
println("Dokka !")
dokkaSourceSets {
create("commonMain") {
displayName = "common"
platform = "common"
}
}
}
}
// Publishing
val fis = FileInputStream("local.properties")
val properties = Properties().apply {
load(fis)
}
val ossUser = properties.getProperty("oss.user")
val ossPassword = properties.getProperty("oss.password")
extra["signing.keyId"] = properties.getProperty("signing.keyId")
extra["signing.password"] = properties.getProperty("signing.password")
extra["signing.secretKeyRingFile"] = properties.getProperty("signing.secretKeyRingFile")
val libraryVersion: String by project
val publishedGroupId: String by project
val artifactName: String by project
val libraryName: String by project
val libraryDescription: String by project
val siteUrl: String by project
val gitUrl: String by project
val licenseName: String by project
val licenseUrl: String by project
val developerOrg: String by project
val developerName: String by project
val developerEmail: String by project
val developerId: String by project
project.group = publishedGroupId
project.version = libraryVersion
signing {
sign(publishing.publications)
}
publishing {
publications.withType(MavenPublication::class) {
groupId = publishedGroupId
artifactId = artifactName
version = libraryVersion
artifact(tasks["javadocJar"])
artifact(tasks["sourcesJar"])
pom {
name.set(libraryName)
description.set(libraryDescription)
url.set(siteUrl)
licenses {
license {
name.set(licenseName)
url.set(licenseUrl)
}
}
developers {
developer {
id.set(developerId)
name.set(developerName)
email.set(developerEmail)
}
}
organization {
name.set(developerOrg)
}
scm {
connection.set(gitUrl)
developerConnection.set(gitUrl)
url.set(siteUrl)
}
}
}
repositories {
maven("https://oss.sonatype.org/service/local/staging/deploy/maven2/") {
name = "sonatype"
credentials {
username = ossUser
password = ossPassword
}
}
}
}
I also find this reddit topic with no solution, this article that doesn't work, and lot of others. There are tons of materials how to publish to bintray, but they are irrelevant now
It seems the issue was in this line artifact(tasks["sourcesJar"]) as this task already included.
Here I want to put my working script for uploading kotlin multiplatform library to Maven Central.
First of all we need to register Sonatype account, validate our domain, etc, here is a fresh article with detailed steps.
Then your project script build.gradle.kts may look like this:
import java.io.FileInputStream
import java.util.Properties
import org.gradle.api.publish.PublishingExtension
plugins {
id("kotlin-multiplatform")
id("org.jetbrains.dokka") version "1.4.0-rc"
id("io.codearte.nexus-staging") version "0.22.0"
`maven-publish`
signing
}
enum class OS {
LINUX, WINDOWS, MAC
}
fun getHostOsName(): OS =
System.getProperty("os.name").let { osName ->
when {
osName == "Linux" -> OS.LINUX
osName.startsWith("Windows") -> OS.WINDOWS
osName.startsWith("Mac") -> OS.MAC
else -> throw GradleException("Unknown OS: $osName")
}
}
kotlin {
sourceSets {
jvm()
js() {
browser()
nodejs()
}
when (getHostOsName()) {
OS.LINUX -> {
linuxX64()
linuxArm64()
}
OS.WINDOWS -> {
mingwX64()
}
OS.MAC -> {
macosX64()
iosArm64()
iosX64()
}
}
val commonMain by getting {
dependencies {
implementation(kotlin("stdlib-common"))
implementation(Libs.olekdia.common)
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val jvmMain by getting {
dependencies {
}
}
val jvmTest by getting {
dependencies {
implementation(kotlin("test"))
implementation(kotlin("test-junit"))
}
}
val jsMain by getting {
dependencies {
}
}
val nativeMain by creating {
dependsOn(commonMain)
}
when (getHostOsName()) {
OS.LINUX -> {
val linuxX64Main by getting {
dependsOn(nativeMain)
}
val linuxArm64Main by getting {
dependsOn(nativeMain)
}
}
OS.WINDOWS -> {
val mingwX64Main by getting {
dependsOn(nativeMain)
}
}
OS.MAC -> {
val macosX64Main by getting {
dependsOn(nativeMain)
}
val iosArm64Main by getting {
dependsOn(nativeMain)
}
val iosX64Main by getting {
dependsOn(nativeMain)
}
}
}
}
}
tasks {
create<Jar>("javadocJar") {
dependsOn(dokkaJavadoc)
archiveClassifier.set("javadoc")
from(dokkaJavadoc.get().outputDirectory)
}
dokkaJavadoc {
dokkaSourceSets {
create("commonMain") {
displayName = "common"
platform = "common"
}
}
}
}
//--------------------------------------------------------------------------------------------------
// Publishing
//--------------------------------------------------------------------------------------------------
val fis = FileInputStream("local.properties")
val properties = Properties().apply {
load(fis)
}
val ossUser = properties.getProperty("oss.user")
val ossPassword = properties.getProperty("oss.password")
extra["signing.keyId"] = properties.getProperty("signing.keyId")
extra["signing.password"] = properties.getProperty("signing.password")
extra["signing.secretKeyRingFile"] = properties.getProperty("signing.secretKeyRingFile")
val libraryVersion: String by project
val publishedGroupId: String by project
val artifactName: String by project
val libraryName: String by project
val libraryDescription: String by project
val siteUrl: String by project
val gitUrl: String by project
val licenseName: String by project
val licenseUrl: String by project
val developerOrg: String by project
val developerName: String by project
val developerEmail: String by project
val developerId: String by project
project.group = publishedGroupId
project.version = libraryVersion
signing {
sign(publishing.publications)
}
afterEvaluate {
configure<PublishingExtension> {
publications.all {
val mavenPublication = this as? MavenPublication
mavenPublication?.artifactId =
"${project.name}${"-$name".takeUnless { "kotlinMultiplatform" in name }.orEmpty()}"
}
}
}
publishing {
publications.withType(MavenPublication::class) {
groupId = publishedGroupId
artifactId = artifactName
version = libraryVersion
artifact(tasks["javadocJar"])
pom {
name.set(libraryName)
description.set(libraryDescription)
url.set(siteUrl)
licenses {
license {
name.set(licenseName)
url.set(licenseUrl)
}
}
developers {
developer {
id.set(developerId)
name.set(developerName)
email.set(developerEmail)
}
}
organization {
name.set(developerOrg)
}
scm {
connection.set(gitUrl)
developerConnection.set(gitUrl)
url.set(siteUrl)
}
}
}
repositories {
maven("https://oss.sonatype.org/service/local/staging/deploy/maven2/") {
name = "sonatype"
credentials {
username = ossUser
password = ossPassword
}
}
}
}
nexusStaging {
username = ossUser
password = ossPassword
packageGroup = publishedGroupId
}
Provide needed library details in gradle.properties:
libraryVersion = 0.1.1
libraryName = Your library name
libraryDescription = Your library description
publishedGroupId = com.yourdomain
artifactName = your-cool-librayr
siteUrl = https://gitlab.com/yourlibrayr
gitUrl = https://gitlab.com/yourlibrayr.git
developerId = ...
developerOrg = ...
developerName = Your Name
developerEmail = yourmail#mail.com
licenseName = The Apache Software License, Version 2.0
licenseUrl = http://www.apache.org/licenses/LICENSE-2.0.txt
allLicenses = ["Apache-2.0"]
kotlin.mpp.enableGranularSourceSetsMetadata = true
gnsp.disableApplyOnlyOnRootProjectEnforcement = true
Here gnsp.disableApplyOnlyOnRootProjectEnforcement = true property needed for declaring nexusStaging in subprojects.
And finally put your credits to local.properties:
oss.user=your_user_name
oss.password=your_pass
signing.keyId=last_8_numbers_of_key
signing.password=your_pass
signing.secretKeyRingFile=/path/to/keystorage.gpg
Now for publishing open terminal in project directory:
./gradlew build
./gradlew publish
./gradlew closeAndReleaseRepository
You could skip last command, and close and release staging packages from Nexus repository manager. That nexus-staging plugin is only needed to do it from command line.
I have tried to move publishing part of script to separate file, and include it with apply(from = "publish.gradle.kts"), but it didn't work, as it loses context in separate file
I use older version of dokka library (1.4.0-rc), as newer version could not generate javadocs for all platforms. And this javadocs is required by repository for publishing. As authors mentioned we could generate empty javadoc.jar file for that purpose.

How can I publish a javadoc.jar file with my Kotlin multiplatform project?

I am trying to publish my Kotlin multiplatform library to Maven Central via Sonatype. This repository requires me to include a javadoc.jar file with my artifacts. Unfortunately, the IntelliJ IDEA project wizard and the Kotlin multiplatform docs do not help me do that. When running the Gradle task dokkaJavadoc (for the official Kotlin documentation tool Dokka), I get the error "Dokka Javadoc plugin currently does not support generating documentation for multiplatform project."
I actually do not need genuine JavaDocs for publishing - an empty javadoc.jar or one with other docs generated by Dokka would suffice. Since I have been a longtime Maven user and these are my first steps with Gradle, I have no idea how to do that.
build.gradle.kts:
plugins {
kotlin("multiplatform") version "1.4.31"
id("org.jlleitschuh.gradle.ktlint") version "10.0.0"
id("io.gitlab.arturbosch.detekt") version "1.15.0"
id("org.jetbrains.dokka") version "1.4.20"
id("maven-publish")
signing
}
group = "com.marcoeckstein"
version = "0.0.3-SNAPSHOT"
publishing {
publications {
create<MavenPublication>("maven") {
pom {
val projectGitUrl = "https://github.com/marco-eckstein/kotlin-lib"
name.set(rootProject.name)
description.set(
"A general-purpose multiplatform library. " +
"Implemented in Kotlin, usable also from Java, JavaScript and more."
)
url.set(projectGitUrl)
inceptionYear.set("2021")
licenses {
license {
name.set("MIT")
url.set("https://opensource.org/licenses/MIT")
}
}
developers {
developer {
id.set("marcoeckstein.com")
name.set("Marco Eckstein")
email.set("marco.eckstein#gmx.de")
url.set("https://www.marcoeckstein.com")
}
}
issueManagement {
system.set("GitHub")
url.set("$projectGitUrl/issues")
}
scm {
connection.set("scm:git:$projectGitUrl")
developerConnection.set("scm:git:$projectGitUrl")
url.set(projectGitUrl)
}
}
}
}
repositories {
maven {
name = "sonatypeStaging"
url = uri("https://oss.sonatype.org/service/local/staging/deploy/maven2")
credentials(PasswordCredentials::class)
}
}
}
signing {
useGpgCmd()
sign(publishing.publications["maven"])
}
repositories {
mavenCentral()
jcenter()
}
kotlin {
targets.all {
compilations.all {
kotlinOptions {
allWarningsAsErrors = true
}
}
}
jvm {
compilations.all {
kotlinOptions.jvmTarget = "11"
}
testRuns["test"].executionTask.configure {
useJUnitPlatform()
}
}
js(BOTH) {
browser {
testTask {
useKarma {
useChromeHeadless()
webpackConfig.cssSupport.enabled = true
}
}
}
}
val hostOs = System.getProperty("os.name")
val isMingwX64 = hostOs.startsWith("Windows")
val nativeTarget = when {
hostOs == "Mac OS X" -> macosX64("native")
hostOs == "Linux" -> linuxX64("native")
isMingwX64 -> mingwX64("native")
else -> throw GradleException("Host OS is not supported in Kotlin/Native.")
}
sourceSets {
val commonMain by getting
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
implementation("io.kotest:kotest-assertions-core:4.4.1")
}
}
val jvmMain by getting
val jvmTest by getting {
dependencies {
implementation(kotlin("test-junit5"))
implementation("org.junit.jupiter:junit-jupiter-api:5.6.0")
runtimeOnly("org.junit.jupiter:junit-jupiter-engine:5.6.0")
}
}
val jsMain by getting
val jsTest by getting {
dependencies {
implementation(kotlin("test-js"))
}
}
val nativeMain by getting
val nativeTest by getting
}
}
configure<org.jlleitschuh.gradle.ktlint.KtlintExtension> {
enableExperimentalRules.set(true)
verbose.set(true)
// ktlint.disabled_rules:
// filename:
// Caught more precisely (with desired exceptions) with detekt.
// import-ordering:
// ktlint's order is not supported (yet) by IntelliJ.
// See:
// - https://github.com/pinterest/ktlint/issues/527
// - https://youtrack.jetbrains.com/issue/KT-10974
// no-wildcard-imports:
// Not desired. We want them for Java statics and Enum members.
// experimental:annotation:
// Not desired.
// experimental:multiline-if-else:
// Not desired.
disabledRules.set(
setOf(
"filename",
"import-ordering",
"no-wildcard-imports",
"experimental:annotation",
"experimental:multiline-if-else"
)
)
additionalEditorconfigFile.set(file("$projectDir/.editorconfig"))
}
detekt {
input = files("$projectDir/src/")
config = files("$projectDir/detekt-config.yml")
buildUponDefaultConfig = true
}
tasks {
withType<io.gitlab.arturbosch.detekt.Detekt> {
// Target version of the generated JVM bytecode. It is used for type resolution.
jvmTarget = "11"
}
}
Also posted at Kotlin Discussions.
This answer is a cross-post from Kotlin Discussions. Credit goes to Lamba92_v2 of the JetBrains Team, who linked his solution in his project kotlingram.
I noticed I had another issue related to publishing: Signatures and POM information where not applied to all modules. But given Lamba92_v2's code I could resolve all publishing-related issues:
plugins {
kotlin("multiplatform") version "1.4.31"
id("org.jlleitschuh.gradle.ktlint") version "10.0.0"
id("io.gitlab.arturbosch.detekt") version "1.15.0"
id("org.jetbrains.dokka") version "1.4.20"
id("maven-publish")
signing
}
group = "com.marcoeckstein"
version = "0.0.3"
val dokkaHtml by tasks.getting(org.jetbrains.dokka.gradle.DokkaTask::class)
val javadocJar: TaskProvider<Jar> by tasks.registering(Jar::class) {
dependsOn(dokkaHtml)
archiveClassifier.set("javadoc")
from(dokkaHtml.outputDirectory)
}
publishing {
publications.withType<MavenPublication> {
artifact(javadocJar)
pom {
val projectGitUrl = "https://github.com/marco-eckstein/kotlin-lib"
name.set(rootProject.name)
description.set(
"A general-purpose multiplatform library. " +
"Implemented in Kotlin, usable also from Java, JavaScript and more."
)
url.set(projectGitUrl)
inceptionYear.set("2021")
licenses {
license {
name.set("MIT")
url.set("https://opensource.org/licenses/MIT")
}
}
developers {
developer {
id.set("marcoeckstein.com")
name.set("Marco Eckstein")
email.set("marco.eckstein#gmx.de")
url.set("https://www.marcoeckstein.com")
}
}
issueManagement {
system.set("GitHub")
url.set("$projectGitUrl/issues")
}
scm {
connection.set("scm:git:$projectGitUrl")
developerConnection.set("scm:git:$projectGitUrl")
url.set(projectGitUrl)
}
}
the<SigningExtension>().sign(this)
}
repositories {
maven {
name = "sonatypeStaging"
url = uri("https://oss.sonatype.org/service/local/staging/deploy/maven2")
credentials(PasswordCredentials::class)
}
}
}
signing {
useGpgCmd()
}
repositories {
mavenCentral()
jcenter()
}
kotlin {
targets.all {
compilations.all {
kotlinOptions {
allWarningsAsErrors = true
}
}
}
jvm {
compilations.all {
kotlinOptions.jvmTarget = "11"
}
testRuns["test"].executionTask.configure {
useJUnitPlatform()
}
}
js(BOTH) {
browser {
testTask {
useKarma {
useChromeHeadless()
webpackConfig.cssSupport.enabled = true
}
}
}
}
val hostOs = System.getProperty("os.name")
val isMingwX64 = hostOs.startsWith("Windows")
val nativeTarget = when {
hostOs == "Mac OS X" -> macosX64("native")
hostOs == "Linux" -> linuxX64("native")
isMingwX64 -> mingwX64("native")
else -> throw GradleException("Host OS is not supported in Kotlin/Native.")
}
sourceSets {
val commonMain by getting
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
implementation("io.kotest:kotest-assertions-core:4.4.1")
}
}
val jvmMain by getting
val jvmTest by getting {
dependencies {
implementation(kotlin("test-junit5"))
implementation("org.junit.jupiter:junit-jupiter-api:5.6.0")
runtimeOnly("org.junit.jupiter:junit-jupiter-engine:5.6.0")
}
}
val jsMain by getting
val jsTest by getting {
dependencies {
implementation(kotlin("test-js"))
}
}
val nativeMain by getting
val nativeTest by getting
}
}
configure<org.jlleitschuh.gradle.ktlint.KtlintExtension> {
enableExperimentalRules.set(true)
verbose.set(true)
// ktlint.disabled_rules:
// filename:
// Caught more precisely (with desired exceptions) with detekt.
// import-ordering:
// ktlint's order is not supported (yet) by IntelliJ.
// See:
// - https://github.com/pinterest/ktlint/issues/527
// - https://youtrack.jetbrains.com/issue/KT-10974
// no-wildcard-imports:
// Not desired. We want them for Java statics and Enum members.
// experimental:annotation:
// Not desired.
// experimental:multiline-if-else:
// Not desired.
disabledRules.set(
setOf(
"filename",
"import-ordering",
"no-wildcard-imports",
"experimental:annotation",
"experimental:multiline-if-else"
)
)
additionalEditorconfigFile.set(file("$projectDir/.editorconfig"))
}
detekt {
input = files("$projectDir/src/")
config = files("$projectDir/detekt-config.yml")
buildUponDefaultConfig = true
}
tasks {
withType<io.gitlab.arturbosch.detekt.Detekt> {
// Target version of the generated JVM bytecode. It is used for type resolution.
jvmTarget = "11"
}
}

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() )
}