Generating Dokka Javadoc from CLI

Hello,

I was able to follow the [Discussion thread](https://discuss.kotlinlang.org/t/problems-running-dokka-cli-1-4-0-rc-jar-from-the-command-line/18855) to generate html output using Dokka 1.4.20 but I wasn’t able to figure out how to generate Javadoc output. Adding javadoc-plugin-1.4.20.jar to -pluginsClasspath doesn’t appear to do anything.

java -jar dokkalib/dokka-cli-1.4.20.jar \
            -outputDir javadoc_out \
            -moduleName cfg \
            -sourceSet "-src src" \
            -pluginsClasspath "dokkalib/dokka-analysis-1.4.20.jar;dokkalib/dokka-base-1.4.20.jar;dokkalib/kotlin-analysis-compiler-1.4.20.jar;dokkalib/kotlin-analysis-intellij-1.4.20.jar;dokkalib/kotlinx-coroutines-core-1.3.9.jardokkalib/kotlinx-html-jvm-0.7.2.jar;dokkalib/javadoc-plugin-1.4.20.jar"

Could anyone point how I am supposed to use the tool?

Thanks,
Daryl

With Gradle!

Is there a way to use it with the CLI? Otherwise I’d need a tutorial on how to use Gradle. I build my project with javac and kotlinc commands in a Makefile.

Gradle is a modern build tool that allows you to completely automatize any task, so basically, the hipster-but-more-complete grandson of Makefile :grin:. You can “pack” a series of interconnected tasks (such as building a Kotlin project with docs) in Plugins. JetBrains wrote a Plugin for the Kotlin compiler and one for Dokka. A task in Gradle is called, simply, Task, which is an action that does something, for example compiling your project.

In a nutshell, Gradle is just a bunch of APIs that allows you declare how you want your build to behave. Those APIs can be invokes using scripts in Groovy or Kotlin (of course I highly recommend Kotlin instead of Groovy for a big number of reasons).

“What is Gradle?” official page here!

It goes like this: you put a build.gradle.kts (mind the .kts extension, or it will be a Groovy script!) file in the root of your project and inside it you declare that you want to use the JB plugins for building Kotlin, configure them by following the documentation. The task that builds the project is called build and you can invoke it from command line by either:

  • gradle build: this works if you have Gradle installed in your system.
  • ./gradlew build (or .\gradlew build in Windows PowerShell, or gradlew build in Windows cmd): to use the Gradle wrapper.

Gradle installation official page here!

What is the Gradle wrapper?” you might ask. The wrapper is just a script that you put in your project that automatically installs Gradle in your system if you do not have it, so that if you need to build your project from another machine you won’t need to manually install Gradle.
Where do you get that magic script? IntelliJ IDEA can do it for you, otherwise you need to have Gradle installed manually and invoke the task gradle :wrapper (mind the two dots :).


If using IntelliJ IDEA, create a new project as shown here and copy the sources in the src/main/kotlin folder.

If not using an IDE different from IntelliJ IDEA (glhf :stuck_out_tongue:), I’d recommend to install Gradle in your system, run the command gradle :wrapper in the root of your project.

Assuming you are building a Kotlin/JVM only project, read the official JB page for Gradle.

There are many plugins available from JB, use the one you need (probably the JVM one if you target the JVM or, simply put, Java).

For the Dokka plugin, use the link of my previous answer. There is a JB official Dokka example project available here, also here’s the build.gradle.kts file of the example project.

I’ll briefly comment the script to let you understand:

import org.jetbrains.dokka.gradle.DokkaTask
import java.net.URL

// Here you declare the plugins you want to use. From were Gradle is gonna 
// get them is not far from magic. Take it for granted right now!
plugins {
    kotlin("jvm") version "1.4.0" // the official Kotlin/JVM plugin
    id("org.jetbrains.dokka") version "1.4.0" // the official Dokka plugin
}

// Those are from were you recover dependencies for your project, plugin excluded;
// remember, plugins are magic!
repositories {
    mavenCentral()
    jcenter()
    maven("https://dl.bintray.com/kotlin/kotlin-eap")
    maven("https://maven.pkg.jetbrains.space/kotlin/p/dokka/dev")
}

// The dependencies that will be added to your compilation classpath;
// Gradle will look for them in the upper declared repositories.
dependencies {
    implementation(kotlin("stdlib")) // adds the kotlin stdlib to the classpath
    testImplementation(kotlin("test-junit")) // adds kotlin test stuff to the testing classpath (yes, 
    //  there can be many classpaths in the build based on the task you invoke)
}

// `tasks` is a container of all tasks in your project created by plugins; the `withType`
// function recovers all tasks of class `org.jetbrains.dokka.gradle.DokkaTask` and configures 
// them all in the same way
tasks.withType<DokkaTask>().configureEach {
    // to understand what is happening here I recommend to read the official Dokka documentation
    dokkaSourceSets {
        named("main") {
            moduleDisplayName.set("Dokka Gradle Example")
            includes.from("Module.md")
            sourceLink {
                localDirectory.set(file("src/main/kotlin"))
                remoteUrl.set(URL("https://github.com/Kotlin/kotlin-examples/tree/master/" +
                        "gradle/dokka/dokka-gradle-example/src/main/kotlin"
                ))
                remoteLineSuffix.set("#L")
            }
        }
    }
}

Gradle is an amazing tool that goes way beyond Kotlin and Dokka. I believe it’s the swiss knife of the building tools and once you get to know it, you just cannot do without it anymore. The learning curve for Gradle is somewhat steep (thanks to Kotlin as scripting language is waaaaay less steep that in Groovy).

Also, I strongly suggest to use IntelliJ IDEA if you are not doing it already. You may create a new Kotlin project as explained here using IntelliJ IDEA; by doing so, IDEA will create for you the Gradle wrapper so that you do not need to install Gradle!


Well that’s most of what you need to understand Gradle and many Kotlin tools design choices. Take your time to read most of the stuff I linked you (I know it’s a lot of stuff but trust me it is very worth). If you need help write here! I may be not available but the community is really active!

Also happy new year! :partying_face: :partying_face: :partying_face:

1 Like

Thank you for the very thorough response. I really appreciate it!

1 Like

It took me much more time to understand how gradle works than how to use kotlin…

Gradle is built with technologies like Kotlin, if not Kotlin itself. Therefore it is inherently more complex then Kotlin, since Kotlin is a piece of it!

It took a while but I was able to use gradle to generate javadoc documentation for my kotlin source. This is probably not an optimal solution but it works. What I would up doing was taking build.gradle.kts and settings.gradle.kts from the Kotlin example project and commenting out the sourceLink section since I wasn’t building documentation from code hosted online:

// settings.gradle.kts

pluginManagement {
    repositories {
        gradlePluginPortal()
        jcenter()
        mavenCentral()
        maven("https://dl.bintray.com/kotlin/kotlin-eap")
        maven("https://maven.pkg.jetbrains.space/kotlin/p/dokka/dev")
    }
}

rootProject.name = "dokka-gradle-example"
// build.gradle.kts

import org.jetbrains.dokka.gradle.DokkaTask
import java.net.URL

plugins {
    kotlin("jvm") version "1.4.0"
    id("org.jetbrains.dokka") version ("1.4.0")
}

repositories {
    mavenCentral()
    jcenter()
    maven("https://dl.bintray.com/kotlin/kotlin-eap")
    maven("https://maven.pkg.jetbrains.space/kotlin/p/dokka/dev")
}

dependencies {
    implementation(kotlin("stdlib"))
    testImplementation(kotlin("test-junit"))
}

tasks.withType<DokkaTask>().configureEach {
    dokkaSourceSets {
        named("main") {
            moduleDisplayName.set("Dokka Gradle Example")
            includes.from("Module.md")
            // sourceLink {
            //     localDirectory.set(file("src/main/kotlin"))
            //     remoteUrl.set(URL("https://github.com/Kotlin/kotlin-examples/tree/master/" +
            //             "gradle/dokka/dokka-gradle-example/src/main/kotlin"
            //     ))
            //     remoteLineSuffix.set("#L")
            // }
        }
    }
}

I was then able to create a Dockerfile to containerize the build:

# dokka.dockerfile
FROM ubuntu:18.04

# base dependencies
RUN apt-get update \ 
    && apt-get install -y default-jdk-headless gradle \
    && rm -rf /var/lib/apt/lists/*

# gradle wrapper
COPY settings.gradle.kts /root/dokka/settings.gradle.kts
RUN cd /root/dokka \
    && gradle wrapper --gradle-version 6.5.1 \
    && ./gradlew

# dokka javadoc dependencies
COPY build.gradle.kts /root/dokka/build.gradle.kts
RUN cd /root/dokka \
    && ./gradlew dokkaJavadoc \
    && ./gradlew clean

and build with:

docker build -t dokka -f dokka.dockerfile .

From a directory containing my source in src/com… I was able to generate the javadoc:

docker run -it --rm \
    -v $(pwd)/src/com:/root/dokka/src/main/kotlin/com:ro \
    -v $(pwd)/javadoc:/root/dokka/build/dokka/javadoc \
    -w /root/dokka \
    dokka ./gradlew dokkaJavadoc