lukyer
lukyer

Reputation: 7993

How to configure Gradle's incremental build with annotation processor

I want to use QueryDSL annotation processor as a part of my build process. How can I get rid of unnecessary annotation processor compile&run everytime i change any class? I want QueryDSL to generate Q-* classes only if some related classes are changed.

This always running annotation processor has negative impact on our build process time and it looks like incremental building is not working if annotation processor has to run.

Thank you.

Upvotes: 3

Views: 3830

Answers (3)

Rule
Rule

Reputation: 630

The issue seems to have been solved! https://issuetracker.google.com/issues/37079915

Upvotes: -1

lukyer
lukyer

Reputation: 7993

Gradle cannot know which files annotation processors use as their input so it has to trigger full recompilation every time something in watched directory changes (src).

However you can easily tell Gradle which files should only trigger annotation processing. Change to other files will not trigger use of annotation processors and gradle can use all its power (e.g. incremental builds).

I also added "force" task buildWithAP calling annotation processors regardless of hint (heuristic) function result.

My solution:

ext.isTask = { name -> return project.gradle.startParameter.taskNames.contains(name) }

/**
 * Heuristic function allowing to build process guess if annotation processor run is necessary
 * Annotation processors will not be called during build task if this function returns FALSE
 */
ext.isApInvalidated = { -> return hasAnyFileRelatedToApChanged() }

dependencies {
  if (isTask("buildWithAP") || isApInvalidated()) {
    println "Going to run annotation processors ..."
    apt "com.querydsl:querydsl-apt:$queryDslVersion:jpa"
  ...
  } else {
    // just add generated classes to the classpath
    // must be in else branch or multiple AP calls will collide!
  sourceSets.main.java.srcDirs += projectDir.absolutePath + "/build/generated/apt"
  } 

}

task buildWithAP (dependsOn: build) {}

You can use any annotation processor you want, for example your own, not just QueryDSL.

Hope my point is clear.

Upvotes: 4

TmTron
TmTron

Reputation: 19411

AFAIK this is currently not possible: see this blog post - section "Incremental compile with annotation processors":

...with annotation processors, Gradle does not know which files they are going to generate. Neither does it know where and based on what conditions. Therefore Grade disables the Java incremental compiler if annotation processors are in use

Related issue for Gradle: Make incremental compile efficient in the presence of Annotation Processors #1320

The Blog post also mentions a possible Workaround:

It is however possible to limit the impact of this to the set of classes that really use annotation processors. In short, you can declare a different source set, with a different compile task, that will use the annotation processor, and leave the other compile tasks without any kind of annotation processing

However, this seems to be quite some work, so I haven't used this yet.

Upvotes: 2

Related Questions