dokka icon indicating copy to clipboard operation
dokka copied to clipboard

AGP 7.1 ships with unshaded Dokka 1.4 and causes dependency compatibility issues

Open IgnatBeresnev opened this issue 3 years ago • 7 comments

Background

Starting from 7.1, com.android.tools.build:gradle, known as Android Gradle Plugin (AGP), ships with unshaded Dokka 1.4. Initially it was introduced as a feature so that AGP users could build and publish documentation without having to apply Dokka themselves.

./gradlew buildEnvironment output for an android project:

classpath
+--- com.android.tools.build:gradle:7.1.2
|    +--- ...
|    +--- org.jetbrains.dokka:dokka-core:1.4.32
|    +--- ...
+--- ...

The problem

You might suddenly encounter this if you updated AGP from 7.0.X to 7.1.X or if you updated Dokka from any version.

Compatibility problems begin happening if AGP is applied on the root project level, and Dokka is applied for a single or a subset of modules/subprojects.

What happens then is on the root project level you have Dokka 1.4, and for the subproject you have Dokka 1.6.21 -- gradle doesn't resolve this as overriding the dependency for some reason. Because the rootproject class loader is the parent of the subproject class loader, the classes on it win. So you inevitably end up with multiple variants of the same classes from different versions of Dokka, and it all starts falling apart. The ordering in which they will be loaded is nondeterministic.

This leads to various problems:

  1. You may start seeing the old, outdated UI from 1.4, it's because HtmlRenderer and other classes are picked up from Dokka 1.4 instead of 1.6.21
  2. java.lang.NoSuchMethodError errors, this is because classes loaded from 1.6.21 start referencing new methods which do not exist in classes loaded from 1.4. Which methods -- completely random and depends on the classpath of your project.
  3. Error while evaluating property 'unsuppressedSourceSets' -- same reason as above, but for fields.
  4. Unable to load class 'org.jetbrains.dokka.model.AncestryNode' - pretty much the same reason, it tries to load classes which do not exist in 1.4.
  5. ...

Proper solution

Since this problem is caused primarily by AGP, there's an upstream issue for it, the fix for now is planned for 7.3: https://issuetracker.google.com/issues/229979216

Workaround / Temporary solution

The problem is caused because on the root project level you have Dokka 1.4, and you have Dokka 1.6.21 on the subproject level, and they mix.

So the workaround is to specify Dokka version in the root gradle.build.kts (optionally with apply false if you don't want documentation generation for all modules):

// ${PROJECT_ROOT}/build.gradle.kts
plugins {
    id("org.jetbrains.dokka") version "1.6.21" apply false
}

And then apply Dokka plugin in the subproject/module that you want to generate documentation for (you can skip it if you enable dokka for all subprojects/modules):

// ${PROJECT_ROOT}/libs/mycoolidea/build.gradle.kts
plugins {
    id("org.jetbrains.dokka")
}

Then Dokka 1.4 which is shipped with AGP is overriden:


classpath
+--- com.android.tools.build:gradle:7.1.3
|    +--- ...
|    +--- org.jetbrains.dokka:dokka-core:1.4.32 -> 1.6.21
|    +--- ...
+--- ...

This issue will be updated once there's anything to share.

IgnatBeresnev avatar Apr 26 '22 18:04 IgnatBeresnev

Is dokka 1.6.21 also ABI incompatible with the 1.4.* releases? Even if I force dokka to be 1.6.21 for the buildenvironment:

buildscript {
  dependencies {
    classpath("org.jetbrains.dokka:dokka-gradle-plugin") {
      version {
        strictly "1.6.21"
      }
    }
  }
}

I get NoSuchMethod errors, but invoked from AGP:

Caused by: java.lang.NoSuchMethodError: 'void org.jetbrains.dokka.DokkaSourceSetImpl.<init>(java.lang.String, org.jetbrains.dokka.DokkaSourceSetID, java.util.List, java.util.Set, java.util.Set, java.util.Set, java.util.Set, boolean, boolean, boolean, boolean, int, java.util.Set, java.util.List, java.util.Set, java.lang.String, java.lang.String, boolean, boolean, java.util.Set, org.jetbrains.dokka.Platform, int, kotlin.jvm.internal.DefaultConstructorMarker)'
        at com.android.build.gradle.tasks.JavaDocGenerationTask.buildDokkaSourceSetImpl(JavaDocGenerationTask.kt:147)

So it looks like AGP is trying to call a constructor signature that no longer exists in 1.6.21

I have confirmed dokka 1.6.21 is being used via ./gradlew buildEnvironment

AlecKazakova avatar May 06 '22 00:05 AlecKazakova

@AlecStrong thank you for the stacktrace, I think that was the missing piece for NoSuchMethod errors. Looks like that, yeah.

Is this AGP task executed automatically or do you call it yourself somehow? i.e does it occur when you do ./gradlew build or when you do ./gradlew javadoc?

I think there's two choices:

  1. Use dokka shipped with AGP (1.4 for now, but it will be updated to a more recent release on AGP's side) through tasks provided by AGP. That means removing explicit Dokka dependency and configuration
  2. Override Dokka in the buildscripts and exclude JavaDocGenerationTask from the build pipeline (if at all possible, maybe via dependsOn.remove("task") or something), build it via Dokka's ./gradlew dokkaHtml command

Haven't dug into it too deep, unfortunately, so if you manage to resolve it - please share some info :) I'll try to investigate when I have some free time

IgnatBeresnev avatar May 06 '22 11:05 IgnatBeresnev

yea its ./gradlew build. Right now I'm doing option 1, I just let AGP's dokka override, but #2 is a good idea, I'll give that a shot

AlecKazakova avatar May 06 '22 12:05 AlecKazakova

Note

Even if you specified newer Dokka version (like 1.6.21) in your root build.gradle.kts and you can see that it overrides the version shipped with AGP in ./gradlew buildEnvironment output (org.jetbrains.dokka:dokka-core:1.4.32 -> 1.6.21), dokka tasks might still fail.

For some reason, Dokka 1.4.32 is picked up from AGP by buildSrc/build.gradle.kts instead of the newer version that you specified in the root build script.

You can explicitly depend on the newer dokka-core (artifact used by AGP), for instance via putting it into the dependencies block. It should solve the problem.

Originally found in https://github.com/Kotlin/dokka/issues/2452#issuecomment-1121283678, see for more context

IgnatBeresnev avatar May 09 '22 16:05 IgnatBeresnev

I'm getting the NoSuchMethodError even though I am explicitly depending on dokka-core 1.6.21 (in both my root project and my included build) when I run gradle publishToMavenLocal.

You can see this here - https://github.com/eygraber/android-date-time-input/pull/133

eygraber avatar May 09 '22 20:05 eygraber

I solved it just by adding classpath("org.jetbrains.dokka:dokka-core:1.6.21") in the same place as classpath("com.android.tools.build:gradle:7.1.2") is

tprochazka avatar Jun 01 '22 13:06 tprochazka

JFYI: This issue will be resolved in AGP 7.3

IgnatBeresnev avatar Jun 01 '22 15:06 IgnatBeresnev

Android Gradle Plugin 7.3.0 was released in September, it includes the fix for this problem: old Dokka 1.4 is not on classpath anymore, at least not at the time of using Dokka's tasks. It has been confirmed to work.

The recommended solution is to update AGP to 7.3, but if you're unable to do that just yet, there are some workarounds posted above for 7.1 and 7.2.

Closing the issue as resolved as there's nothing else to be done.

IgnatBeresnev avatar Nov 17 '22 00:11 IgnatBeresnev