I am struggling to publish a Kotlin multiplatform project properly to maven (for now mavenLocal). I can add the dependency to another multiplatform project and use the code but I don't get any documentation and I am not sure if I am doing something wrong or if that is simply not possible at the moment.
From what I understand you cannot use the normal javadoc because it is bound to Java which does not make sense in a multiplatform environment. I read somewhere that in that case you should use the html version of dokka. I can see that I get a "javadoc.jar" with content to my mavenLocal but still in the IDE in an example project where I add my KMP library as a dependency, I don't see any documentation. Also, the code decompiling seems to be weird. I guess somehow the sources are also not properly resolved.
According to the documentation everything should automatically and perfectly work by simply adding the maven-publish and the dokka plugin. But it seems like this is not the case and actually nothing is working as I'd expect it :D
Does anyone know, how to properly set that up?
My gradle file looks like this:
plugins {
kotlin("multiplatform") version "1.6.21"
id("org.jetbrains.kotlinx.benchmark") version "0.4.2"
id("org.jetbrains.dokka") version "1.6.21"
`maven-publish`
signing
}
group = "io.github.quillraven.fleks"
version = "1.4-KMP-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_1_8
repositories {
mavenCentral()
}
kotlin {
targets {
jvm {
compilations {
all {
kotlinOptions {
jvmTarget = "1.8"
}
}
val main by getting { }
// custom benchmark compilation
val benchmarks by compilations.creating {
defaultSourceSet {
dependencies {
// Compile against the main compilation's compile classpath and outputs:
implementation(main.compileDependencyFiles + main.output.classesDirs)
}
}
}
}
withJava()
testRuns["test"].executionTask.configure {
useJUnitPlatform()
}
}
}
js(BOTH) {
browser { }
}
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"))
}
}
val jvmMain by getting
val jvmTest by getting
val jvmBenchmarks by getting {
dependsOn(commonMain)
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-benchmark-runtime:0.4.2")
implementation("com.badlogicgames.ashley:ashley:1.7.4")
implementation("net.onedaybeard.artemis:artemis-odb:2.3.0")
}
}
val jsMain by getting
val jsTest by getting
val nativeMain by getting
val nativeTest by getting
}
}
benchmark {
targets {
register("jvmBenchmarks")
}
}
val javadocJar by tasks.registering(Jar::class) {
archiveClassifier.set("javadoc")
from(tasks.dokkaHtml)
}
publishing {
repositories {
maven {
url = if (project.version.toString().endsWith("SNAPSHOT")) {
uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")
} else {
uri("https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/")
}
credentials {
username = System.getenv("OSSRH_USERNAME")
password = System.getenv("OSSRH_TOKEN")
}
}
}
publications {
val kotlinMultiplatform by getting(MavenPublication::class) {
version = project.version.toString()
groupId = project.group.toString()
artifactId = "Fleks"
artifact(javadocJar)
pom {
name.set("Fleks")
description.set("A lightweight entity component system written in Kotlin.")
url.set("https://github.com/Quillraven/Fleks")
scm {
connection.set("scm:git:git@github.com:quillraven/fleks.git")
developerConnection.set("scm:git:git@github.com:quillraven/fleks.git")
url.set("https://github.com/quillraven/fleks/")
}
licenses {
license {
name.set("MIT License")
url.set("https://opensource.org/licenses/MIT")
}
}
developers {
developer {
id.set("Quillraven")
name.set("Simon Klausner")
email.set("quillraven@gmail.com")
}
}
}
}
signing {
useInMemoryPgpKeys(System.getenv("SIGNING_KEY"), System.getenv("SIGNING_PASSWORD"))
sign(kotlinMultiplatform)
}
}
}
// only sign if version is not a SNAPSHOT release.
// this makes it easier to publish to mavenLocal and test the packed version.
tasks.withType<Sign>().configureEach {
onlyIf { !project.version.toString().endsWith("SNAPSHOT") }
}
When I run the publishToMavenLocal
gradle task then I get following directories in my .m2 folder:
When I then create an example project and add it as a dependency, then I don't see any quick documentation and also the decompiling is not working properly:
Here is my example gradle file that publishes a kotlin multiplatform project with sources and javadocs to a maven repository.
The project source is here: https://github.com/danbrough/misc_demos/tree/master/kotlin_multiplatform_dokka
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
import org.gradle.api.tasks.testing.logging.TestLogEvent
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
kotlin("multiplatform")
id("org.jetbrains.dokka")
id("com.android.library")
`maven-publish`
}
group = "dokka.test"
version = "0.0.1"
buildscript {
repositories {
mavenCentral()
gradlePluginPortal()
}
}
repositories {
mavenCentral()
google()
}
kotlin {
jvm()
android()
linuxX64()
macosX64()
sourceSets {
val commonTest by getting {
dependencies {
implementation(kotlin("test"))
}
}
}
val posixMain by sourceSets.creating {}
targets.withType<KotlinNativeTarget>() {
compilations["main"].defaultSourceSet.dependsOn(posixMain)
}
}
tasks.withType<AbstractTestTask>() {
testLogging {
events = setOf(
TestLogEvent.PASSED, TestLogEvent.SKIPPED, TestLogEvent.FAILED
)
exceptionFormat = TestExceptionFormat.FULL
showStandardStreams = true
showStackTraces = true
}
outputs.upToDateWhen {
false
}
}
tasks.withType(KotlinCompile::class) {
kotlinOptions {
jvmTarget = "11"
}
}
tasks.dokkaHtml.configure {
outputDirectory.set(buildDir.resolve("dokka"))
}
val javadocJar by tasks.registering(Jar::class) {
archiveClassifier.set("javadoc")
from(tasks.dokkaHtml)
}
publishing {
repositories {
maven(project.buildDir.resolve("m2").toURI()) {
name = "m2"
}
}
publications.forEach {
if (it !is MavenPublication) {
return@forEach
}
it.artifact(javadocJar)
}
}
android {
compileSdk = 33
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
namespace = project.group.toString()
defaultConfig {
minSdk = 23
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
signingConfigs.register("release") {
storeFile = File(System.getProperty("user.home"), ".android/keystore")
keyAlias = "keyAlias"
storePassword = System.getenv("KEYSTORE_PASSWORD") ?: ""
keyPassword = System.getenv("KEYSTORE_PASSWORD") ?: ""
}
lint {
abortOnError = false
}
buildTypes {
getByName("debug") {
//debuggable(true)
}
getByName("release") {
isMinifyEnabled = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
)
signingConfig = signingConfigs.getByName("release")
}
}
}