Open ichaus-we opened 3 years ago
JavaToolChain had been deprecated for quite some time and went when Gradle 7.x released.
Please, compare: https://github.com/gradle/gradle/tree/v6.9.1/subprojects/platform-jvm/src/main/java/org/gradle/jvm/toolchain (JavaToolChain.java is present) https://github.com/gradle/gradle/tree/v7.0.0/subprojects/platform-jvm/src/main/java/org/gradle/jvm/toolchain (no JavaToolChain.java)
Looks like it's time to convert the plugin from 'software model' API to the contemporary one.
Unfortunately, Gradle does not yet offer a good replacement for the removed (half baked) API: https://github.com/gradle/gradle/issues/15942
Gradle's API changes certainly don't make it easy, but one can still create Java compilation tasks that use ECJ. Here's how I define a JavaCompileUsingEcj
task in a large project that I co-maintain, and here's how I put that task to work creating one JavaCompileUsingEcj
task instance for each Java source set. Note that I am not replacing the standard tasks, such as compileJava
and compileTestJava
. Rather, I am adding tasks that recompile the same sources using ECJ. For this project, we want to use the standard compiler for building distributable artifacts, but we also compile using ECJ for extra static linting/checking.
Thanks for sharing the solution @liblit. I think you do not necessarily need this:
// Advise Gradle that this task will not be using the Java compilation API associated with the
// standard Java toolchain. Instead, we will use an external compiler command, configured below.
javaCompiler.set(project.provider { null })
If I am not mistaken, Gradle will ignore the toolchain configuration if you explicitly set an executable the fork options (which you do). So I think you do not necessarily need to extend the JavaCompile
task, but can register another instance of it and do all the configuration there. That would be a bit "cleaner" (if it works).
The solution was not suitable for the project I need this for, as everything needed to be done with ECJ since some code only compiles with ECJ (certain generics stuff). The project is quite large so forking a new compiler process for each subproject had quite a performance impact.
What we ended up doing now is copying the implementation on JavaCompile and replacing the implementation of the Compiler interface in createCompiler() with one that delegates to the ECJ compiler. This is similar to the pre Gradle 7 solution, using more internal API. I think it is quite fragile as it may break down as soon as internals around the JavaCompile task change. Right now it works with all Gradle 7.x releases so far.
Since we have a new task, we needed to register it separately - similar to @liblit's solution. We then deactivated the standard compile tasks completely.
@jjohannes wrote:
Thanks for sharing the solution @liblit. I think you do not necessarily need this:
// Advise Gradle that this task will not be using the Java compilation API associated with the // standard Java toolchain. Instead, we will use an external compiler command, configured below. javaCompiler.set(project.provider { null })
If I am not mistaken, Gradle will ignore the toolchain configuration if you explicitly set an executable the fork options (which you do).
You're right, so I have removed this unnecessary step. Thanks!
Hi, we had to go from Gradle 6.7 to 7.1.1 because of JAVA 16 support. The problem is, that de.set.ecj fails to load.
Gradle error message:
build.gradle
Full Gradle output: