Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gradle 5.0: Planned behaviour of ignoring jars with annotation processors not okay. #5056

Closed
rzwitserloot opened this issue Apr 16, 2018 · 10 comments
Labels

Comments

@rzwitserloot
Copy link

Problem

If you have a jar that contains an annotation processor on the compile classpath, and you build with option --warning-mode=all build, you get:

Putting annotation processors on the compile classpath has been deprecated and is scheduled to be removed in Gradle 5.0. Please add them to the processor path instead. If these processors were unintentionally leaked on the compile classpath, use the -proc:none compiler option to ignore them.

This makes no sense. Why is this a problem, exactly? Javac uses the compilation classpath to look up classes required by whatever you're asking it to compile. The existence of classes on the classpath that you don't, in fact, need or use, is no problem. We do it all the time; If you include guava and elect NOT to use the 'Files' class, should gradle whine about it? Clearly, no.

Perhaps there's some confusion here: Including an annotation processor in a jar that ends up being 'exported' as a dep is somewhat hairy and not a choice you should make lightly, but, as far as I can tell, this warning/error (in 5.0) occurs regardless.

Or, the confusion stems from compilation cp vs. runtime cp: Shipping (or shading, or however you ship your end product) a jar carrying annotation processor code in the final product is definitely odd and a warning when gradle is tasked to do it, is warranted. However, the above warning/error is explicitly about COMPILE path. That's definitely not the time to start worrying about needless things being on the classpath. That time comes later.

Expected Behavior

It should simply not do that. Move it to step where gradle ships runtime cps or shades them into a fat jar.

Context

This warns/errors when using lombok. Main contributor of project lombok here: As far as we can tell this is a misunderstanding by team gradle; we've been asked to split up our jar to 'solve' this problem, but if we do that, we get 50 different bug reports because, well, that'd break a lot of other things; as such we are disinclined to fix this problem. I'm sure 'gradle and lombok are broken and cannot work together' wasn't the intent of this warning. If there's anything we can do to solve this is a nicer way, we can make some changes if that would help for you to solve this issue. I have a few ideas:

  • Hardcode lombok as being no problem here.

  • Have a mechanism whereby a jar can mark itself as being designed to work like this, perhaps by including some file in the META-INF dir of the jar.

Steps to Reproduce

Put in your gradle file:

dependencies {
	compileOnly 'org.projectlombok:lombok:1.16.20'
}

put any java code in your source dir (just public class Test {} ought to do it).

and then run (tried with gradle 4.6):

gradle --warning-mode=all build

@marcphilipp
Copy link
Contributor

The reason that putting annotation processors on the compile classpath is deprecated is to support incremental annotation processing:
https://docs.gradle.org/4.7-rc-2/userguide/java_plugin.html#sec:incremental_annotation_processing

From the 4.6 Release Notes:

Putting processors on the compile classpath or using an explicit -processorpath compiler argument has been deprecated and will be removed in Gradle 5.0. Annotation processors should be added to the annotationProcessor configuration instead.

If Lombok does not want to split its JAR file into api/processor that's fine, but users will then have to add its single JAR to both the compileOnly and the annotationProcessor configuration.

@rzwitserloot
Copy link
Author

We'll update our documentation for gradle to take this into account.

@oehme
Copy link
Contributor

oehme commented Apr 16, 2018

Annotation processors belong on the processor path, not the compile classpath. Note that this is not related to incremental annotation processing, but about compile avoidance. It's about proper separation of concerns. On the compile classpath only the ABI should matter, while on the processor path every implementation detail matters for the correct compilation result. That's why we will ignore them on the compile classpath in the future.

@rzwitserloot
Copy link
Author

@oehme this is overzealous. Take gradle. Do you require gradle to split into two packages; one with only interfaces, and one with implementations? They'd have to start with even making a bunch of interfaces first. What about a project that has two related but technically separate concepts in it; such that it is imaginable a project will only use one of the two features (though most projects use both): Should gradle detect this and error?

There's an ocean between 'this would be an ideal API design for the library' and 'gradle will enforce this at, effectively, gunpoint'.

As long as putting lombok on both the compileOnly path and the annotationProcessor path works out fine (and without any warnings), all is well.

@oehme
Copy link
Contributor

oehme commented Apr 16, 2018

It's not about having things on the compile classpath that you may not use. That's fine. It's about the fact the annotation processors change the behavior of the compiler itself and thus need to be treated very differently from normal classes.

When Gradle snapshots the compile classpath, it will only look at the API of a class, thus avoiding recompilation if the API didn't change. On the processor path that optimization can't be done, since obviously the result of processing depends on its implementation.

So if a user puts a processor on the compile classpath, we have to shut that optimization off, making their incremental builds slower. That's why we are deprecating this and will ignore processors on the compile classpath in the future. I don't know why the JDK team decided to allow this in the first place (probably because Maven couldn't fit the processorPath into its anemic model), but it's definitely not a good idea.

As long as putting lombok on both the compileOnly path and the annotationProcessor path works out fine (and without any warnings), all is well.

It will.

@rzwitserloot
Copy link
Author

Sounds good. One last thing:

Right now if a jar-with-processor is on the compileOnly path, you get the warning.

Let's say it's on the compileOnly path and the annotationProcessor path. Do you still get this warning?

@oehme
Copy link
Contributor

oehme commented Apr 17, 2018

The warning will disappear as soon as you start using annotationProcessor.

The reason is backwards compatiblity. Putting processors on the compile classpath worked before, so we need to keep it working till 5.0. Gradle will currently fall back to the compile classpath if the annotationProcessor configuration is empty. As soon as you use it, processors on the compile classpath are ignored.

@sasconsul
Copy link

sasconsul commented Apr 23, 2018

Folks, I am late to the party and a gradle novice.

I it not clear from the error message how to fix the problem.

The following does not resolve the problem:

compileJava {
    sourceCompatibility = 1.8
    targetCompatibility = 1.8
    options.compilerArgs += ["-proc:none"]
}

Any pointers?

The annotation process in question is from org.apache.logging.log4j.core.config.plugins.processor.PluginProcessor

Also here is my gradle version information:

$ ./gradlew -version

------------------------------------------------------------
Gradle 4.7
------------------------------------------------------------

Build time:   2018-04-18 09:09:12 UTC
Revision:     b9a962bf70638332300e7f810689cb2febbd4a6c

Groovy:       2.4.12
Ant:          Apache Ant(TM) version 1.9.9 compiled on February 2 2017
JVM:          1.8.0_162 (Oracle Corporation 25.162-b12)
OS:           Mac OS X 10.13.4 x86_64

Thank-You
Stuart

@oehme
Copy link
Contributor

oehme commented Apr 23, 2018

@sasconsul I can't tell for sure without least the full message or ideally a build scan or sample project. My suspicion is that the message is coming from test compilation, but you only deactivated processing for the main compile task.

@sasconsul
Copy link

@oehme you are right the problem is in the compiletestJava task -- I did not notice when reading the message:

> Task :compileTestJava UP-TO-DATE
The following annotation processors were detected on the compile classpath: 'org.apache.logging.log4j.core.config.plugins.processor.PluginProcessor'. Detecting annotation processors on the compile classpath is deprecated and Gradle 5.0 will ignore them. Please add them to the annotation processor path instead. If you did not intend to use annotation processors, you can use the '-proc:none' compiler argument to ignore them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants