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
Make incremental compile efficient in the presence of Annotation Processors #1320
Comments
Great news ! Instead of instrumenting the compiler, it would be possible also to apply the same discovery mechanism for annotation processors as APT and ask all processors which annotations they process, and find all files containing these annotations. It could also be interesting to let the javac maintainers know about this work when it's done as it should lead to an enhancement of the APT APIs / JSR. They could also probably help to instrument the compiler if that's the way to go. |
Yes, this is what "instrumenting the compiler" means. |
I thought it was about hacking it via reflection or something like that.
Thanks for the precision.
We would actually be glad to participate if there is some space for
collaborative work.
For instance, I am thinking of a case we have in one of our annotation processors where the annotation classes can be passed as parameters to the annotation processor.
|
The link to "introduced in Gradle 3.4" does not work? |
@dongshengbc Fixed it. Sorry I had linked to the release candidate before. |
@eriwen , we are really very motivated to get this solved. Can we help in anyway ? |
@stephanenicolas Thanks for volunteering. I think there are 4 potential ways to help:
@oehme leads the team that would be responsible for addressing this. Anything technically they (Groupon team) can take on here? |
I will come back to you on this. If you could have a more detailed list of areas with which we can help, that would be great. |
@oehme @eriwen is there a way we can get more directly in touch with you and work together on this. We are switching to gradle 4 and the new android plugin and this issue is really our last bottle neck to get decent build times. If you wanna write an email to me, my personal email address is pretty easy to find on the web.. |
Any progress? I agree with/can just quote @stephanenicolas from the old issue tracker:
I wonder why this is not having a much higher priority because I think this is an issue for many (many) developer - or am I forgetting something? |
We are working together with the Google and Groupon teams, but the work is still at an early stage. We plan to have a first milestone for simple processors like AutoValue and Butterknife late October.
There are only so many things we can tackle at once. I understand that this is probably the biggest issue for you. But I hope you understand that there are other big issues for other users. |
If anyone interested in how to achieve full gradle power (e.g. incremental builds) with annotation processors, see my workaround solution here https://stackoverflow.com/questions/47289457/how-to-configure-gradles-incremental-build-with-annotation-processor/47392788#47392788 |
@jaredsburrows see #3434 for the current status. Dagger 2 will be complicated though, because even if just one class changed, it would still need to do some heavy analysis to make sure all injection points are still valid. |
I've broken this epic down into a few initial stories. You can take a look at the design spec to get a better idea of what use cases we plan to support and what is out of scope (for now). |
A good solution. Only one question:
Why not fail the compilation until incremental is switched off here as well? |
For backwards compatibility reasons (many users set incremental=true globally and rely on Gradle to figure out whether it can actually be incremental or not). Also we want to remove the incremental flag altogether in the mid term, making incremental the default and only mode. We'll likely add incremental compile insights to build scans by that time, so they can warn you about this more prominently than the info log can. |
The approach sounds reasonable and well thought out. I would agree with @fab1an to fail fast instead of silent full recompile, that would be more consistent. In addition, it would be handy if the build composer would have an option to provide the processor type information in the build file, if none is provided by the processor author, e.g. in the configurations section. |
I thought about this too, but I'm not sure in how many cases it would work, since the processor also needs to use the originatingElements API correctly. |
In the most simplest case, a processor (like Lombok) only modifies the one class defined by the corresponding java, and might generate additional inner classes, which can easily be associated by the |
APT does not allow processors to change classes in-place. Lombok is operating outside the APT specification and uses internal APIs. I would not consider it a "simple case". There is also no way to generated inner classes. You might use a dollar sign as a separator, but that won't be considered an inner class by the compiler (and it won't have access to the internals of the outer class). For any generated file we will require originating elements to be provided, otherwise processing will fail. That's why I think the number of processors that use this API correctly and don't have an opt-in declaration will likely be small. |
I totally agree, therefore I'm looking for a way to "approximate" a solution better than a full recompile for processors which do not know about the Gradle API, yet. Such an approximation would be the association of dollar-classes with their "main" class. |
Most processors don't use a dollar sign (some use underscores, some just use camel case) and I really don't want to put such assumptions in, as correctness is the most important concern for Gradle. Let's first see if convincing processor authors to opt in is a problem at all. If it isn't then we've saved a bunch of time. If it is, we can start thinking about alternatives. |
@filiphr Your understanding of isolating/aggregating is correct. The working of the incremental compiler is explained in its own chapter right above the one about incremental processing, so I didn't repeat it there. In short, any change to any dependency of a class will trigger its recompilation/reprocessing. @Alexander-- is right about resource generation - We don't support it at the moment and Gradle will throw an error if it is attempted. However, I think we can make an easy improvement here: Instead of failing, we could do a full rebuild if a resource is generated. You said it is rarely used, so most users would benefit from incremental processing in that case. There is also no deeper reason for forbidding resource generation, it's just another thing to implement. If your processor uses the |
Thanks for clearing it up @oehme. To be honest I read only the part about the annotation processor (didn't read the previous chapter). You don't have to repeat, if you just reference the part that it is explained it would be much easier for annotation processor writers 😄. Yes in our case I would say that it is used in max 1% of the cases. As it requires multiple conditions to be fulfilled and requires actions from the user. So out of the box it can never happen. It's an opt in feature. So if you can do the improvement and not error out it would be great. Yes we use the I just saw that we are not passing the originating elements to the |
Is it possible to force gradle to avoid a full rebuild even when annotation processors are present, even if they don't/haven''t implemented this? For example, in a CI pipeline, I don't want to rebuild modules that have such annotation processors in every stage, but I'm seeing that behavior. |
@wrotte I'm afraid I don't understand your question. This is only about incremental compilation. It doesn't affect up-to-date checking or caching. Can you elaborate on your setup a bit more? |
@oehme Sorry for the late reply; I've been trying to distill a succinct test case and I think I've found that the latest Android plugin solves the issue I'm seeing. If I can reproduce I'll file a new issue. |
Good news everyone, the upcoming Gradle 4.8 will contain several big improvements to incremental annotation processing:
|
I've compiled a list of popular processors and their current state of adoption. Please express your support by giving 👍 on the issue trackers of the ones you care about. Also feel free to suggest others that we should get in touch with. |
Is there any way how to get to know which plugin causing not using incremental compilation? I see just this when I run build with --info
|
That's not coming from us, but probably from the Android plugin. @ducrohet can you comment on this? It would be great if the incremental compile decision was completely left to Gradle. Is there any adverse condition we are not detecting? |
For some reason our plugin output this when you apply the retrolambda plugin but I'm not sure why. This was done a while back (2 years) and may not be required anymore. I'll investigate. |
It looks like previously this disabled inc java on both android-apt and retrolambda. Probably a remnant of a time when the java compile task didn't automatically disable inc compilation if annotation processor was one. |
I'm definitely not using retrolamba or android-apt plugin. I can't guarantee that it was not used in any library used by me, but it should not affect it, right? |
yes, sorry, this is triggered with a few more cases than just retrolambda. This still seems a bit strange to me. I'll review this. |
Thanks, so data binding is the reason. Somebody on Google I/O told this year, that one of the news in new building tools is incremental support. So would be great if also java compilation will be part of this, especially now when Gradle is able to do it also with annotation processors. |
I created an issue for "Incremental Java compilation disabled in variant ... as you are using an incompatible plugin" here https://issuetracker.google.com/issues/110061530 to not spam here about the issue which is not related to Gradle itself. |
I'm closing this issue since the work on the Gradle side is done and lots of annotation processors can now be incremental. Please have a look at the list of processors we know about and their adoption status. Any kind of support from your side will help. You could
I'll be happy to help too, just mention me in a conversation if clarification is needed. |
@oehme what kotlin incremental annotation processing ? Do you know if it is also supported ? |
They're currently working on making KAPT compatible. |
Is there any link to their effort ? I actually never had any contact with people from Jetbrain.. |
I haven't found a public issue, feel free to create one on Youtrack. |
Migrated from GRADLE-3259 which had 19 votes
Compile avoidance was introduced in Gradle 3.4 (<= Users please read this). One can improve performance somewhat by separate annotation processors from the compile classpath.
Expected Behavior
Incremental Java compilation should avoid full rebuild when annotation processors are present.
Current Behavior
Currently we fall back to a full recompile when annotation processors are used. The reason for this is that we don't know which source files they need as an input. The APT API allows processor to access other source files then the one containing the annotation being processed.
Context
We could instrument the compiler to find out which files the annotation processors are actually reading and use this information to run them incrementally as well.
In cases where an annotation processor is taking the whole source tree as an input, we could warn the user (e.g. in build scans) that this is causing slower builds. Many developers might not even be aware of the trade-off between "saving time writing code" and "saving time running the build" they have to make.
Design Spec
Since this is a bigger feature, you can download the design spec as a PDF.
The text was updated successfully, but these errors were encountered: