My current understanding of annotation processor is that it refers to code that pre-parses a file looking for certain annotations, generating or changing other code based on that. It happens before the regular compilation phase of your project.
In gradle we typically use apt, kpt - and I've seen sometimes the use of annotationProcessor
- to indicate that some dependency will be needed at "annotation processing time".
If the understand above is right, how does compileOnly
differs from apt, kpt, etc?
As you've said, there are couple of annotation processing solutions in Gradle:
annotationProcessor
facilities for Androidapt
for pure Java and Groovykapt
for Kotlinand so on. You can even implement one yourself! All of them use separate configuration
for annotation processing.
Some of them, indeed, used to use compile
classpath for processing. But this is not semantically corrent, it is not a "Gradle way". You should not mix your compile time only dependencies with the artifacts, required for you app to run. One simple scenario I can think of is creating fat JARs: most probably you do not want to pack and ship the processors you've used because it makes no sense! There may be other scenarios as well.
What you can do, thanks to Gradle's flexibility, is create another classpath (configuration
) and use it only for annotation processing and then just forget about them. It is kind of semantics: you're telling Gradle (and other developers) that these dependencies are not required for you application to run. And this is the place where compileOnly
differs from apt
: compileOnly
dependencies are mandatory for you code to operate, but they are meant to be provided by the environment. Will it be your application server, or plugin host system, or even you'll add them to the classpath manually - they will just exist on you runtime so you should not pack them with your distributable. But they are required to for your code to run. Some examples of compileOnly
dependencies are Servlet API (your classes obviously extend and use them, but it will be provided by the server) or, if you're writing a Jenkins plugin, Jenkins core APIs (your plugin will be installed in a Jenkins where that core already exists). JDK itself is kind of compileOnly
too. Annotation processors, on the contrary, are not meant to be used at runtime at all. They won't exist on classpath and they are not needed to run your app: they already generated some code that was compiled later.
Other implication of "mixing" configuration is performance. Just let me quote Android's documentation:
In previous versions of the plugin, dependencies on the compile classpath were automatically added to the processor classpath. That is, you could add an annotation processor to the compile classpath and it would work as expected. However, this causes a significant impact to performance by adding a large number of unnecessary dependencies to the processor.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With