gradle icon indicating copy to clipboard operation
gradle copied to clipboard

Shouldn't JavaExec default to using the project's toolchain if any?

Open tbroyer opened this issue 5 years ago • 9 comments

Expected Behavior

When configuring a toolchain at project level (java { toolchain { … } }), all JavaExec tasks in that project default to using that toolchain.

Current Behavior

JavaExec tasks use the JVM the Gradle build has been launched with, irrespective of the project-level toolchain.

Context

I've started using toolchains rather than asking devs to use a specific JDK for the project (I used to throw when JavaVersion.current() was an unexpected value), and discovered that while JavaCompile, Javadoc and Test tasks use the configured toolchain, JavaExec tasks don't, so this needs to be configured explicitly:

tasks.withType<JavaExec>().configureEach {
    javaLauncher.set(javaToolchains.launcherFor(java.toolchain))
}

Fwiw, the application plugin configures its JavaExec task to use the project toolchain: https://github.com/gradle/gradle/blob/v6.8.3/subprojects/plugins/src/main/java/org/gradle/api/plugins/ApplicationPlugin.java#L167

tbroyer avatar Apr 12 '21 13:04 tbroyer

We need some infrastructure feature for doing that, see #14363.

ljacomet avatar Jun 08 '21 09:06 ljacomet

This issue has been automatically marked as stale because it has not had recent activity. Given the limited bandwidth of the team, it will be automatically closed if no further activity occurs. If you're interested in how we try to keep the backlog in a healthy state, please read our blog post on how we refine our backlog. If you feel this is something you could contribute, please have a look at our Contributor Guide. Thank you for your contribution.

stale[bot] avatar Jun 12 '22 10:06 stale[bot]

Should this be kept open or merged with #14363? (I'd vote for keeping it separate)

tbroyer avatar Jun 12 '22 11:06 tbroyer

When configuring a toolchain at project level (java { toolchain { … } }), all JavaExec tasks in that project [should] default to using that toolchain.

Just sharing that this is not my expectation at all. Toolchains allow you to configure the JDK to use for compiling the project, not for running Gradle. Running JavaExec tasks, though, to me is more related to running Gradle than to compiling my application. Thus I'd expect the JVM to be used that runs Gradle itself. Also, keep in mind that for running JavaExec tasks (usually) a JRE is sufficient, whereas for compiling a JDK is required.

So in the end, IMO the current behavior is a cleaner separation between the JVM / JRE to run Gradle, and a JVM / JDK to compile the project defined by Gradle.

sschuberth avatar Feb 28 '24 07:02 sschuberth

@sschuberth it just isn't that clear cut every time. For example we are using a plugin that generates code through the JavaExec task. This forces us to take extra care of the version we run gradle with.

simondivi avatar Feb 28 '24 10:02 simondivi

For example we are using a plugin that generates code through the JavaExec task. This forces us to take extra care of the version we run gradle with.

Which is fine, IMO. Whatever solution we had, it should probably be configurable to cover all needs, and have a sane default value. And that's how it currently is. It's configurable, and the default is to use the JVM that runs Gradle, which arguably is the value that covers most cases.

sschuberth avatar Feb 28 '24 10:02 sschuberth

I had to enhance JPA entity class files (EclipseLink) using a tool that the dependency provides. So I did

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
    }
}

compileJava {
  doLast {
    javaexec {
      // enhance class files produced by compileJava
    }
  }
}

in order to have the enhanced classes being change tracked by Gradle for the compile task. I think in such a case it is a valid assumption that the toolchain configuration is used by default.

Of course at the end it is question about the default behavior as it is already configurable.

which arguably is the value that covers most cases.

Is it? Definition of toolchains is relatively new compared to javaexec and before toolchain definition existed you had to take care about the JVM running Gradle. These days it is common practice to define a toolchain used to build a project/module to be independent of the JVM running Gradle. So I can definitely understand that it is surprising to see that the toolchain won't be applied to everything the build does by default. I mean take a look at the example above: Just reading it will give you a false understanding. It is not self-explanatory anymore. So maybe the current default is not optimal anymore.

jnehlmeier avatar Feb 28 '24 12:02 jnehlmeier

Running JavaExec tasks, though, to me is more related to running Gradle than to compiling my application. Thus I'd expect the JVM to be used that runs Gradle itself.

This feels like the old days when running something meant for either maven or gradle running with the JVM that run the build tool. But toolchains changes that model.

A counterexample to this point, is that if a toolchain is declared with JDK 21, but gradle is running JDK 17, then JavaExec should at least use the Java 21 version not the one from the build tool. And I would also expects it by default on distributions (could be early access builds, etc) where what is compiled needs it at runtime.

If a different tool needs a specific JDK then it should be explicitly declared.

Maybe the default boils down to what JavaExec runs, code from the sourcesets, or external code as part of the build lifecycle. In this later case I would understand the JDK is the one from Gradle by default, but for simplicity when there's a toolchain I would use the toolchain by default.

bric3 avatar Feb 29 '24 12:02 bric3

How can toolchain versions be configured separately per module or task? A java-library must be compiled against Java 8, but a plugin in the same module requires Java 11 (since checkstyle 10.0), because 9.3 uses com.google.guava:guava:31.0.1-jre with CVE-2023-2976. And another module requires Java 11 too (documentation with asciidoctor).

reneleonhardt avatar May 10 '24 15:05 reneleonhardt