checkerframework-gradle-plugin
checkerframework-gradle-plugin copied to clipboard
Configuration checkerFrameworkAnnotatedJDK has missing dep org.checkerframework:jdk8:3.5.0 even when it is not required.
When using the plugin with checkerframework 3.4.x or later, the plugin still creates the (obsolete?) configuration checkerFrameworkAnnotatedJDK with the missing dependency org.checkerframework:jdk8:3.5.0. This causes some tools that process dependencies to fail, for example https://github.com/jk1/Gradle-License-Report.
Jenkins build with two gradle scans failing in the same way: https://ci-beam.apache.org/job/beam_PreCommit_Python2_PVR_Flink_Commit/5547/
Gradle scan of a quick repro: https://scans.gradle.com/s/nivpttv2sfiuu/dependencies?toggled=W1swXSxbMCw0XV0#configurationId=4&projectId=0
Specific steps to repro:
- Clone https://github.com/apache/beam/pull/12162
- modify
applyJavaNature(enableChecker:false, ...)toapplyJavaNature(enableChecker:true, ...)in any module. I chose the moduleexamples/kotlin/build.gradlefor the repro above. ./gradlew :examples:kotlin:dependencyReportwill show the configuration with the missing dependency.
I've dug around in the code enough that I feel OK making this change, if my understanding sounds right to you.
Actually I take this back. It seems that while this is based on the CF version, that version is pulled from the jar in some configurations which requires dependencies to already have been resolved. So I will leave this bug report in the hope that you have suggestions. In the meantime, the workaround is to exclude the configuration from those plugins that it breaks.
Sorry you ran into this.
I'd still like to create the checkerFrameworkAnnotatedJDK configuration, to support older versions of the CF that use it. Here are some other ideas for possible workarounds, within the plugin:
- remove the dependency from the configuration if the CF version is 3.4.x or higher, or
- use a different default version for the annotated JDK that actually exists (e.g. 3.3.0) even though it won't actually be used
I don't like the latter, because that dependency will still be cluttered the dependency graph. I'm not sure if the former is technically possible, because the CF version is calculated in an afterEvaluate block, which I think is too late to modify dependencies.
Yea, I tried "remove the dependency from the configuration if CF version is 3.4.x or higher" but I got tangled in the control flow between configureProject, applyToProject and the callback that sets missing dependency versions just as dependencies are being resolved.
I definitely would never argue to drop old version support.
If I were to guess one thing to drop, it might be reading the version from the jar file. That would result in a plugin that defaults to "the version of CF when the plugin was released" and allows users to set it to a new one. The version would always be known much earlier in the project lifecycle. Is it also to support jars that are provided directly? (hence the version is not really specified anywhere)
Our project has been bitten by the errorprone plugin silently upgrading us, and we have since pinned the version. We will be doing the same for CF, and we recommend everyone do the same so their builds are reproducible.
@kelloggm @kennknowles any progress on this one? I'm running into the same issue within openjdk:11 Docker image, plugin v0.5.5, CF v3.5.0 :/
I just worked around it in my project. We had a process that iterated over all configurations. I changed it to a specific list of configurations.
@kennknowles , can you please point out your workaround in Beam?
If I recall, I changed the configurations property of https://github.com/mdietrichstein/gradle-offline-dependencies-plugin
I am doing the same thing now with another plugin.
3.8.0 now. this is how I fixed it
configurations.all {
resolutionStrategy.dependencySubstitution {
substitute(module("org.checkerframework:jdk8:3.8.0"))
.using(module("org.checkerframework:jdk8:3.+"))
}
}
I'd still like to create the checkerFrameworkAnnotatedJDK configuration, to support older versions of the CF that use it. Here are some other ideas for possible workarounds, within the plugin:
so it's not actually used? aren't we supposed to have an annotated version of the jdk? or are we now supposed to do it all ourselves
aren't we supposed to have an annotated version of the jdk? or are we now supposed to do it all ourselves
The annotated JDK is no longer a separate artifact, but it's still present in the distribution. With CF versions 3.5.0 and higher, the checker.jar artifact automatically includes an annotated JDK.
ah, ok, the documentation for CF doesn't imply that. then my rule probably should have been exclude instead. seems like the plugin could already do that though. TBF, I don't care though, I've decided not to proceed with CF, it's trippled my build time, and that was only with ~5 classes. I can't imagine what it would do with 200k lines of code
-
Can you suggest how the CF documentation can be improved, so that others don't face the same problem you did? Thanks.
-
We agree that the slower build time is a negative! Sorry about that. If it triples your build time with 5 classes, it will triple your build time with 200k lines of code too. It is a modular (class-by-class) analysis. You could consider running it in CI if running it on every compile is too onerous.
You could consider running it in CI if running it on every compile is too onerous
for the 200k project CI is already like 20 minutes, and I consider 1+ minutes on 5 classes way too slow.
@xenoterracide yeah, I second the observation that CF increases the build time significantly... but still, the value added by the Framework is so significant in my assessment that it's worth its overhead.
Actually, in our project we only locally turn on:
- GuiEffect Checker where applicable (since it's an IntellijPlugin with a GUI)
- I18nFormatter Checker where applicable
- Nullness Checker
On CI we also turn on the other, rarely failing checkers: Aliasing (some modules), Index, Interning, Optional, Subtyping (some modules), see build.gradle for details.
There's around 240 non-test Java files in total (~13k LoC), compilation time on CI from scratch with all above checkers on is around 2:30-3:00. Having Gradle caching (locally) and CI caching, compilation time isn't usually that much of a problem. I wouldn't trade the benefits of CF for slightly better compilation times, ever ;)
(Non-)disclaimer: I am not associated with the CF team in any way.
I consider 1+ minutes on 5 classes way too slow.
Actually, you can share the specific Gradle configuration :thinking:
but still, the value added by the Framework is so significant in my assessment that it's worth its overhead.
for me I'm not so certain, not when I'm running error prone (with nullaway), checkstyle and spotbugs, each with very strict configs. I've turned on about 95% of checks, as errors.
- Can you suggest how the CF documentation can be improved, so that others don't face the same problem you did? Thanks.
@xenoterracide A ping on this, which seems to have fallen through the cracks.
I @ted you on https://github.com/typetools/checker-framework/issues/3991
You should worry less about compilation time in large projects. If a large project is recompiling everything, it is doing something wrong.
We use CF in http://github.com/apache/beam which has more than 1.1 million lines of Java. The effect of adding CF was not observable for CI runs, which are around 40 minutes including running all the unit tests. They were the same before CF.
But the raw compile time was 5x when CF was added (See https://groups.google.com/d/topic/checker-framework-discuss/qV6AWNtLAvY/discussion where I ask if this is normal. I guess it is normal). It turns out this does not really matter very much. Almost all the time, almost every target is either UP-TO-DATE or FROM-CACHE (using Gradle's terminology).
We do not disable checker for local builds because otherwise it is too easy to build code that is broken and you don't find out until a CI run.
We do not separate "checker" CI run from main build CI run because it could become too easy to ignore.
If you run clean a lot, or if you are using Maven, then you are just wasting a lot of CPU and it is not the fault of CF.
Thank you for the workaround, by the way!