5

I am currently trying to write an annotation processor for Android in Kotlin. The project structure is as follows:

/annotation
  /src/main/kotlin/<package>
    Annotation.kt
    AnnotationProcessor.kt
/sample

project/build.gradle

buildscript {
  dependencies {
    classpath 'com.android.tools.build:gradle:3.1.1'
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.31"
  }
}

annotation/build.gradle

apply plugin: 'kotlin'

sourceCompatibility = 1.7
targetCompatibility = 1.7

dependencies {
  implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlinVersion"
}

sample/build.gradle

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'

android {
  ...
  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_7
    targetCompatibility JavaVersion.VERSION_1_7
  }

dependencies {
  implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlinVersion"
  implementation project(':annotation')
  kapt project(':annotation')
}

Annotation.kt

@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.SOURCE)
annotation class Annotation(val comment: String = "")

AnnotationProcessor.kt

class AnnotationProcessor : AbstractProcessor() {
  override fun process(annotations: MutableSet<out TypeElement>?, roundEnvironment: RoundEnvironment?): Boolean = true
}

With kapt the build breaks on sample:javaPreCompileDebug with the following message:

org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':sample:javaPreCompileDebug'
Caused by: java.lang.RuntimeException: Annotation processors must be explicitly declared now.  The following dependencies on the compile classpath are found to contain annotation processor.  Please add them to the annotationProcessor configuration.
- annotation.jar (project :annotation)
Alternatively, set android.defaultConfig.javaCompileOptions.annotationProcessorOptions.includeCompileClasspath = true to continue with previous behavior.  Note that this option is deprecated and will be removed in the future.
See https://developer.android.com/r/tools/annotation-processor-error-message.html for more details.

When I replace kapt with annotationProcessor, the build breaks on sample:transformClassesWithInstantRunForDebug with the following message:

Caused by: java.io.IOException: Failed to find byte code for javax/annotation/processing/AbstractProcessor
at com.android.build.gradle.internal.incremental.AsmUtils.lambda$static$0(AsmUtils.java:89)
at com.android.build.gradle.internal.incremental.AsmUtils.loadClass(AsmUtils.java:307)
at com.android.build.gradle.internal.incremental.AsmUtils.readClassAndInterfaces(AsmUtils.java:165)
at com.android.build.gradle.internal.incremental.AsmUtils.loadClass(AsmUtils.java:278)
at com.android.build.gradle.internal.incremental.IncrementalVisitor.instrumentClass(IncrementalVisitor.java:342)
at com.android.build.gradle.internal.transforms.InstantRunTransform.transformToClasses2Format(InstantRunTransform.java:406)
at com.android.build.gradle.internal.transforms.InstantRunTransform.lambda$doTransform$3(InstantRunTransform.java:268)
at com.android.build.gradle.internal.transforms.InstantRunTransform.lambda$null$4(InstantRunTransform.java:297)
at java.util.concurrent.ForkJoinTask$AdaptedCallable.exec(ForkJoinTask.java:1424)
... 4 more

When I disable Instant Run, everything works fine.

My question is now, where did I went wrong with my configuration? I followed sample project like this and the only big difference I see is that the annotation module is split into two (a runtime and a compiler). The error messages though indicates problems with either Kotlin or Instant Run.

1 Answers1

1

You have to split your "annotation" Project into two Parts.

Example:

implementation project(':annotation-lib') // here you put Annotation.kt
kapt project(':annotation-compiler') // AnnotationProcessor.kt

don't forget to add the processor to your META-INF inside the annotation-compiler project see What is the default annotation processors discovery process?

Rüdiger
  • 1,674
  • 1
  • 20
  • 28
  • That was it! Splitting the annotation module into two separate modules (one for the annotations and one for the processor) fixed the problems with Instant Run and made other workarounds like 'includeCompileClasspath' obsolete. Thank you very much and have a nice day! – Philipp Fahlteich Apr 12 '18 at 08:35
  • 1
    Why can't `kapt project` be the same project as the root project, not a separate one? – Vitaly Apr 22 '18 at 00:49