Как настроить инкрементную сборку Gradle с процессором аннотации
Я хочу использовать процессор аннотаций QueryDSL как часть моего процесса сборки. Как я могу избавиться от ненужных аннотаций процессора компиляции и запуска каждый раз, когда я изменяю любой класс? Я хочу, чтобы QueryDSL генерировал классы Q-*, только если некоторые связанные классы изменены.
Этот постоянно работающий процессор аннотаций отрицательно влияет на время нашего процесса сборки, и похоже, что добавочное построение не работает, если процессор аннотаций должен работать.
Спасибо.
2 ответа
Gradle не может знать, какие файлы процессоры аннотаций используют в качестве входных данных, поэтому он должен запускать полную перекомпиляцию каждый раз, когда что-то в наблюдаемых каталогах изменяется (src).
Однако вы можете легко указать Gradle, какие файлы должны запускать только обработку аннотаций. Изменение в другие файлы не приведет к использованию процессоров аннотаций, и Gradle может использовать всю свою мощь (например, инкрементные сборки).
Я также добавил "принудительную" задачу buildWithAP, вызывающую процессоры аннотаций независимо от результата подсказки (эвристической) функции.
Мое решение:
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) {}
Вы можете использовать любой процессор аннотаций, например, свой собственный, а не только QueryDSL.
Надеюсь, моя точка зрения ясна.
AFAIK это в настоящее время невозможно: см. Этот пост в блоге - раздел "Инкрементная компиляция с обработчиками аннотаций":
... с процессорами аннотации Gradle не знает, какие файлы они собираются сгенерировать. Он также не знает, где и на каких условиях. Поэтому Grade отключает инкрементный компилятор Java, если используются процессоры аннотаций
Связанная проблема для Gradle: сделать инкрементную компиляцию эффективной в присутствии процессоров аннотации #1320
В блоге также упоминается возможный обходной путь:
Однако возможно ограничить влияние этого на набор классов, которые действительно используют процессоры аннотаций. Короче говоря, вы можете объявить другой исходный набор с другой задачей компиляции, который будет использовать процессор аннотаций, и оставить другие задачи компиляции без какой-либо обработки аннотаций.
Тем не менее, это, кажется, довольно трудоемкая работа, поэтому я еще не использовал это.
Кажется, проблема решена! https://issuetracker.google.com/issues/37079915