Hopefully a quick question. I'm converting a kotli...
# dokka
s
Hopefully a quick question. I'm converting a kotlin multi-platform (KMP) library project to Dokka 2. I'm having trouble getting the HTML generated, and the doc at Dokka V 2.0 migration guide looks incorrect. It claims that this should be valid in the dokka block in build.gradle.kts:
dokkaPublications.html {
outputDirectory.set(rootDir.resolve("docs/api/0.x"))
includes.from(project.layout.projectDirectory.file("README.md"))
}
but when I try this the html clause is an unresolved reference (using Idea 2025.2 EAP). And using the snippet below the builds/dokka folder has only an empty javadoc subfolder, so nothing is being generated. Since this is KMP I know V 2.0.0 doesn't support the javadoc option. What do I need to add to get the HTML to generate? Here's my beginning dokka snippet:
Copy code
dokka {
    moduleName.set("Kotlin Multiplatform Common IO Library")
    dokkaSourceSets.commonMain {
        includes.from("$appleFrameworkName.md")
    }
}
Also, as a followup, I've struggled to find an example of how to tell maven publish to publish the HTML once generated. I'd also appreciate any info on that. Thanks in advance for any help...
Part of the first problem was a missing gradle.properties entry to enable v2. So now the above dokkaPublications.html snippet syncs fine. Manually running task dokkaGeneratePublicationHtml does try to generate HTML now. So my main question is now how to get the output of dokkaGeneratePublicationHtml used by maven-publish in a format that mavenCentral accepts.
Subsequent searches showed an AI response that basically suggested treating the html just like javadoc. In other words jar it up and include the HTML jar as an artifact in the publish. So I tried adding this block:
Copy code
val htmlJarTask = tasks.register<Jar>("htmlJar") {
     archiveClassifier.set("htmldoc")
     dependsOn(tasks.dokkaGeneratePublicationHtml)
}
and added
artifact(htmlJarTask)
to the publish. That caused a signing-related error on the html jar, so I'm still doing this wrong 🙂. The error for the android publish task looks like this:
Copy code
- Gradle detected a problem with the following location: '/mnt/Projects/KmpIO/KmpIO/build/libs/KmpIO-0.1.8-htmldoc.jar.asc'.
    
    Reason: Task ':KmpIO:publishAndroidDebugPublicationToMavenLocal' uses this output of task ':KmpIO:signAndroidReleasePublication' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed.
    
    Possible solutions:
      1. Declare task ':KmpIO:signAndroidReleasePublication' as an input of ':KmpIO:publishAndroidDebugPublicationToMavenLocal'.
      2. Declare an explicit dependency on ':KmpIO:signAndroidReleasePublication' from ':KmpIO:publishAndroidDebugPublicationToMavenLocal' using Task#dependsOn.
      3. Declare an explicit dependency on ':KmpIO:signAndroidReleasePublication' from ':KmpIO:publishAndroidDebugPublicationToMavenLocal' using Task#mustRunAfter.
Seems wrong to have to explicitly specify the dependencies above to get this to work, and then do that on all the different target platform tasks as well. Worse, the HTML jars now being generated only have a manifest file, so the generate is running with no errors but producing basically nothing. Still looking...
Fixed the empty jar problem - bad from clause in the task. I used the from clause below as I couldn't figure out how to get the output directory property value from the dokkaGeneratePublicationsHtml task:
Copy code
from(project.layout.buildDirectory.dir("dokka/html"))
To help with the android dependency issue, tried adding the html jar artifact to the androidTarget block:
Copy code
androidTarget {
        publishLibraryVariants("release", "debug")
        mavenPublication {
            artifactId = artifactId.replace(project.name, mavenArtifactId)
            artifact(htmlJarTask)
        }
    }
where mavenArtifactId is the project name. That results in a different error:
Copy code
Execution failed for task ':KmpIO:publishAndroidDebugPublicationToMavenLocal'.
> Failed to publish publication 'androidDebug' to repository 'mavenLocal'
   > Invalid publication 'androidDebug': multiple artifacts with the identical extension and classifier ('jar.asc', 'htmldoc').
So still looking. I don't know why gradle thinks at least in the android case why there are multiple htmlJar artifacts. It sure would be nice if there was some explicit doc on publishing to maven and mavenlocal when using Dokka v2 and the HTML output. If there is I've been unable to find it with searches....
If I comment out the signing block then mavenLocal publishes work. But I'm afraid that likely means until the dependency crossover issue is resolved, maven publish (which requires signing) won't work. As part of trying to diagnose this, I tried adding this to the androidTarget:
Copy code
if (name == "androidRelease")
                artifact(htmlJarTask)
so that would only include the jar artifact on release builds. To avoid duplication I also added this to the publishing block:
Copy code
if (name != "androidDebug" && name != "androidRelease") {
            artifact(htmlJarTask)
        }
So now the jar is only included in androidRelease and non-android builds. That fixed the duplicate extension and classifier issue but surprisingly resulted in this:
Copy code
A problem was found with the configuration of task ':KmpIO:signJvmPublication' (type 'Sign').
  - Gradle detected a problem with the following location: '/mnt/Projects/KmpIO/KmpIO/build/libs/KmpIO-0.1.8-htmldoc.jar.asc'.
    
    Reason: Task ':KmpIO:publishAndroidReleasePublicationToMavenLocal' uses this output of task ':KmpIO:signJvmPublication' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed.
So now there's a dependency crossover between the signJvmPublication task and the androidRelease task?? This feels like a bug. If anyone has gotten this to work I'd love to hear about it. I have to go back to Dokka V1 where publishes of javadoc with signing work until this gets figured out.
o
Hey! Maybe you can create a reproducer on GitHub? It's a bit hard to understand where the issue is coming from because of how Gradle works Or maybe you can share the diff between Dokka Gradle Plugin V1 and V2 configuration? In theory, there should be minimal difference between V1 and V2 regarding jar generation based on Dokka output
s
Thanks! It is a github repo already so I could push up my changes pretty easy. I posted a question about this on the gradle discussion forum to see what the signing plugin folks say. No one has responded there yet so if I don't here anything by tomorrow, I'll push my changes up and post here again. Thanks for your response, this is a weird one and I'll be very interested to see what the resolution is 🙂 FYI I removed the artifact from Android altogether to see if this is some androidTarget issue. Then I still get a crossover error between the JVM and LinuxX64 targets. so the issue is not android-specific. If I push up, the pushed stuff will have the HTML jar artifact only in the publishing block, not also in the androidTarget block. I want to see it work on the regular targets before I add it back to androidTarget.
If anyone is still interested in looking at this, I've updated this repo: https://github.com/skolson/KmpIO Re-create the error by running publishToMavenLocal. The targets that get called out in the error change depending on what host the build is on. So far I've used Linux and MacOS. Linux often errors on the KMP and JVM targets. MacOS errors usually on the IOS and IOSSimulator targets. Android is not currently publishing the HTML jar so it doesn't get crossed up. But adding the HTML jar as an artifact to the androidTarget block will then often cause one of the android targets to be part of the first errors.
Running on Linux gets this error stack:
Copy code
> Task :KmpIO:signKotlinMultiplatformPublication FAILED
> Task :KmpIO:signLinuxArm64Publication FAILED
> Task :KmpIO:signLinuxX64Publication FAILED

[Incubating] Problems report is available at: file:///mnt/Projects/KmpIO/build/reports/problems/problems-report.html

FAILURE: Build completed with 3 failures.

1: Task failed with an exception.
-----------
* What went wrong:
A problem was found with the configuration of task ':KmpIO:signKotlinMultiplatformPublication' (type 'Sign').
  - Gradle detected a problem with the following location: '/mnt/Projects/KmpIO/KmpIO/build/libs/KmpIO-0.1.8-htmldoc.jar.asc'.
    
    Reason: Task ':KmpIO:publishJvmPublicationToMavenLocal' uses this output of task ':KmpIO:signKotlinMultiplatformPublication' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed.
    
    Possible solutions:
      1. Declare task ':KmpIO:signKotlinMultiplatformPublication' as an input of ':KmpIO:publishJvmPublicationToMavenLocal'.
      2. Declare an explicit dependency on ':KmpIO:signKotlinMultiplatformPublication' from ':KmpIO:publishJvmPublicationToMavenLocal' using Task#dependsOn.
      3. Declare an explicit dependency on ':KmpIO:signKotlinMultiplatformPublication' from ':KmpIO:publishJvmPublicationToMavenLocal' using Task#mustRunAfter.
    
    For more information, please refer to <https://docs.gradle.org/8.14.2/userguide/validation_problems.html#implicit_dependency> in the Gradle documentation.

* Try:
> Declare task ':KmpIO:signKotlinMultiplatformPublication' as an input of ':KmpIO:publishJvmPublicationToMavenLocal'
> Declare an explicit dependency on ':KmpIO:signKotlinMultiplatformPublication' from ':KmpIO:publishJvmPublicationToMavenLocal' using Task#dependsOn
> Declare an explicit dependency on ':KmpIO:signKotlinMultiplatformPublication' from ':KmpIO:publishJvmPublicationToMavenLocal' using Task#mustRunAfter
> Run with --scan to get full insights.
==============================================================================

2: Task failed with an exception.
-----------
* What went wrong:
A problem was found with the configuration of task ':KmpIO:signLinuxArm64Publication' (type 'Sign').
  - Gradle detected a problem with the following location: '/mnt/Projects/KmpIO/KmpIO/build/libs/KmpIO-0.1.8-htmldoc.jar.asc'.
    
    Reason: Task ':KmpIO:publishJvmPublicationToMavenLocal' uses this output of task ':KmpIO:signLinuxArm64Publication' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed.
    
    Possible solutions:
      1. Declare task ':KmpIO:signLinuxArm64Publication' as an input of ':KmpIO:publishJvmPublicationToMavenLocal'.
      2. Declare an explicit dependency on ':KmpIO:signLinuxArm64Publication' from ':KmpIO:publishJvmPublicationToMavenLocal' using Task#dependsOn.
      3. Declare an explicit dependency on ':KmpIO:signLinuxArm64Publication' from ':KmpIO:publishJvmPublicationToMavenLocal' using Task#mustRunAfter.
    
    For more information, please refer to <https://docs.gradle.org/8.14.2/userguide/validation_problems.html#implicit_dependency> in the Gradle documentation.

* Try:
> Declare task ':KmpIO:signLinuxArm64Publication' as an input of ':KmpIO:publishJvmPublicationToMavenLocal'
> Declare an explicit dependency on ':KmpIO:signLinuxArm64Publication' from ':KmpIO:publishJvmPublicationToMavenLocal' using Task#dependsOn
> Declare an explicit dependency on ':KmpIO:signLinuxArm64Publication' from ':KmpIO:publishJvmPublicationToMavenLocal' using Task#mustRunAfter
> Run with --scan to get full insights.
==============================================================================

3: Task failed with an exception.
-----------
* What went wrong:
A problem was found with the configuration of task ':KmpIO:signLinuxX64Publication' (type 'Sign').
  - Gradle detected a problem with the following location: '/mnt/Projects/KmpIO/KmpIO/build/libs/KmpIO-0.1.8-htmldoc.jar.asc'.
    
    Reason: Task ':KmpIO:publishJvmPublicationToMavenLocal' uses this output of task ':KmpIO:signLinuxX64Publication' without declaring an explicit or implicit dependency. This can lead to incorrect results being produced, depending on what order the tasks are executed.
    
    Possible solutions:
      1. Declare task ':KmpIO:signLinuxX64Publication' as an input of ':KmpIO:publishJvmPublicationToMavenLocal'.
      2. Declare an explicit dependency on ':KmpIO:signLinuxX64Publication' from ':KmpIO:publishJvmPublicationToMavenLocal' using Task#dependsOn.
      3. Declare an explicit dependency on ':KmpIO:signLinuxX64Publication' from ':KmpIO:publishJvmPublicationToMavenLocal' using Task#mustRunAfter.
    
    For more information, please refer to <https://docs.gradle.org/8.14.2/userguide/validation_problems.html#implicit_dependency> in the Gradle documentation.

* Try:
> Declare task ':KmpIO:signLinuxX64Publication' as an input of ':KmpIO:publishJvmPublicationToMavenLocal'
> Declare an explicit dependency on ':KmpIO:signLinuxX64Publication' from ':KmpIO:publishJvmPublicationToMavenLocal' using Task#dependsOn
> Declare an explicit dependency on ':KmpIO:signLinuxX64Publication' from ':KmpIO:publishJvmPublicationToMavenLocal' using Task#mustRunAfter
> Run with --scan to get full insights.
==============================================================================

BUILD FAILED in 1m 41s
I'm still unsure how to proceed with this. I thought the maven publish plugin should properly handle the HTML jar as an artifact and publish it to all the targets, as well as a KMP one for the common 'target'. Looking in build/libs (the default output location for the Jar task) I only see
KmpIO-0.1.8-htmldoc.jar
and
KmpIO-0.1.8-androidhtmldoc.jar
. None of the other target HTML jars are created, but maybe that's because the error happens first. Interestingly there are signing files for each of these jars, so signing did that much. Anyway, any thoughts on how to diagnose what's happening here are welcome!
I just now added this block to gradle to dig into this more:
Copy code
afterEvaluate {
    tasks.getByName("publishJvmPublicationToMavenLocal") {
        this.inputs.files.forEach {
            println("publishJvm input: ${it.path} ${it.name}")
        }
    }
    tasks.getByName("signKotlinMultiplatformPublication") {
        this.outputs.files.forEach {
            println("signKMP output: ${it.path} ${it.name}")
        }
    }
}
Results of sync:
Copy code
htmlJarTask.configure output: /mnt/Projects/KmpIO/KmpIO/build/libs
publishJvm input: /mnt/Projects/KmpIO/KmpIO/build/libs/KmpIO-0.1.8-htmldoc.jar KmpIO-0.1.8-htmldoc.jar
publishJvm input: /mnt/Projects/KmpIO/KmpIO/build/publications/jvm/pom-default.xml pom-default.xml

==> publishJvm input: /mnt/Projects/KmpIO/KmpIO/build/libs/KmpIO-0.1.8-htmldoc.jar.asc KmpIO-0.1.8-htmldoc.jar.asc

publishJvm input: /mnt/Projects/KmpIO/KmpIO/build/publications/jvm/pom-default.xml.asc pom-default.xml.asc
signKMP output: /mnt/Projects/KmpIO/KmpIO/build/kotlinToolingMetadata/kotlin-tooling-metadata.json.asc kotlin-tooling-metadata.json.asc
signKMP output: /mnt/Projects/KmpIO/KmpIO/build/libs/KmpIO-0.1.8-htmldoc.jar.asc KmpIO-0.1.8-htmldoc.jar.asc
signKMP output: /mnt/Projects/KmpIO/KmpIO/build/publications/kotlinMultiplatform/module.json.asc module.json.asc
signKMP output: /mnt/Projects/KmpIO/KmpIO/build/publications/kotlinMultiplatform/pom-default.xml.asc pom-default.xml.asc
The signing outputs look correct for the KMP task. But the publish JVM task has the signing file from the KMP task as input. I highlighted that line. Why would publish do that? Lol I think I'm stuck.
o
Okay, now I probably see the issue Gradle doesn't like it if multiple tasks use the same output without declaring it. In this case, that's because of the
signing
plugin, which messes this up, you receive such errors. I do have a workaround for a similar situation in one of my personal projects That's needed because we have one jar file which is signed multiple times, as the same file is included in multiple publications Also, I wanted to point out that publication to Maven Central via the default Gradle
maven-publish
plugin will stop working on June 30 because of the sunset of OSSRH by Sonatype. In light of this, you might want to migrate to https://github.com/vanniktech/gradle-maven-publish-plugin, which, in addition to support for the new Maven Central publication workflow, better handles the case with attaching Dokka or javadoc jars there.
s
Thanks so much, this will get me going...
The vanniktech plugin fixed me up. I'm having a little trouble getting it to use my central.sonatype.org credential, but I'll get that figured out. Thanks again for your help!!
kodee loving 1