4
votes

I'm trying to develop a Kotlin AnnotationProcessor library, and I can't figure why I get this error:

Error:Execution failed for task ':app:javaPreCompileDebug'.
> 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.
    - compiler.jar (project :compiler)
  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.

I know that as mentionned I could use includeCompileClasspath = true and I tried it and it works fine. But as mentionned, it's deprecated, soon removed, and it is expected to be used for libraries you don't use according to android doc.

So I'm looking for a cleaner solution.

App module

Hello.kt

@HelloGenerated
class Hello(){
    override fun showLog() {
        Log.i(Hello::class.simpleName, "${Gahfy_Hello().getName()}")
    }
}

Build.gradle

dependencies{ kapt project(":compiler") compileOnly project(":compiler") implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" }

Compiler module

HelloGenerated.kt

@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.SOURCE)
annotation class HelloGenerated

I also tried without Target and Retention and have same issue

HelloGenerator.kt

@SupportedAnnotationTypes("net.gahfy.HelloGenerated")
class HelloGeneratedInjectorProcessor: AbstractProcessor() {

    override fun getSupportedAnnotationTypes(): MutableSet<String> {
        return mutableSetOf(HelloGenerated::class.java.name)
    }

    override fun getSupportedSourceVersion(): SourceVersion {
        return SourceVersion.latest()
    }

    override fun process(annotations: MutableSet<out TypeElement>, roundEnv: RoundEnvironment): Boolean {
        val annotation = annotations.firstOrNull { it.toString() == "net.gahfy.HelloGenerated" } ?: return false
        for (element in roundEnv.getElementsAnnotatedWith(annotation)) {
            val className = element.simpleName.toString()
            val `package` = processingEnv.elementUtils.getPackageOf(element).toString()
            generateClass(className, `package`)
        }
        return true
    }

    private fun generateClass(className: String, `package`: String) {
        val kotlinGeneratedPath = (processingEnv.options["kapt.kotlin.generated"] as String).replace("kaptKotlin", "kapt")
        val kaptKotlinGenerated = File(kotlinGeneratedPath)
        val source = "package $`package`\n\nclass Lachazette_$className(){fun getName():String{return \"World\"}}"
        val relativePath = `package`.replace('.', File.separatorChar)

        val folder = File(kaptKotlinGenerated, relativePath).apply { if(!exists()){mkdirs()} }
        File(folder, "Lachazette_$className.kt").writeText(source)
    }

    companion object {
        const val KAPT_KOTLIN_GENERATED_OPTION_NAME = "kapt.kotlin.generated"
    }
}

build.gradle

apply plugin: 'java-library'
apply plugin: 'kotlin'

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
}

sourceCompatibility = "1.7"
targetCompatibility = "1.7"

resources/META-INF/services/javax.annotation.processing.Processor

net.gahfy.HelloGenerator

I'm now looking for a cleaner solution than just includeCompileClasspath = true.

Some information:

  • kapt works well, I'm using it with Dagger and BindingAdapter without any problem
  • My annotation processor is well processed when building, and the message in the log is the good one when I set includeCompileClasspath = true

Thank you very much

1

1 Answers

1
votes

Not sure if this is 100% related to your problem but I had the same error after moving auto-value to kapt. I solved it by declaring the auto-value dependency as both kapt and annotationProcessor.

So in your case:

dependencies{
    kapt project(":compiler")
    annotationProcessor project(":compiler")
    compileOnly project(":compiler")
    implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
}