Skip to content

Use Gradle toolchain to specify the jdk to use#558

Merged
cpovirk merged 1 commit into
jspecify:mainfrom
ben-manes:ben/toolchain
Jul 15, 2024
Merged

Use Gradle toolchain to specify the jdk to use#558
cpovirk merged 1 commit into
jspecify:mainfrom
ben-manes:ben/toolchain

Conversation

@ben-manes

Copy link
Copy Markdown
Contributor

"I'd be happy for someone to make that happen" -- @cpovirk

This resolves #428 (comment) by specifying java toolchains for the Gradle build daemon and the project. Previously the build daemon, the compiler, and runtime execution all inherited the system JDK, e.g. via JAVA_HOME. The daemon's is specified at Java 21 (gradle-daemon-jvm.properties) and the compile/execution by the project's language toolchain version. The latter defaults to Java 11 and may be overridden by the env variable JAVA_VERSION, which is used in the github actions. The toolchains are automatically downloaded if absent using the resolver plugin.

Comment thread build.gradle
repositories { mavenCentral() }

def javaVersion = JavaLanguageVersion.of(System.env.JAVA_VERSION ?: 11)
java.toolchain.languageVersion = javaVersion

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we do this within java?

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

  if (toolchain.languageVersion.canCompileOrRun(15)) { ...

From Gradle docs.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this project uses script plugins, I preferred doing this before they were applied to avoid any future ordering issues if they eagerly resolved their configuration to a fixed state. In reality this doesn't matter as your scripts do not appear to rely on any of this state in a problematic way. You are certainly welcome to move it for stylistic formatting purposes.

Long term, I'd recommend using precompiled script plugins to avoid quirky surprises that can arise from embedding scriptlets compared to true plugins (e.g. java-library.caffeine.gradle.kts).

@tbroyer

tbroyer commented Jul 14, 2024

Copy link
Copy Markdown

Fwiw, I tend to agree with https://jakewharton.com/gradle-toolchains-are-rarely-a-good-idea/
Toolchains are essential for cross-version compatibility testing, but for building (including compiling, as we've had --release for years now) I'd avoid using them; i.e. configure Test task with a specific JavaLauncher depending on the build matrix, but keep invoking Gradle itself with the same JDK every time.

with:
distribution: temurin
java-version: 17
java-version: ${{ env.JAVA_VERSION }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actions/setup-java can install several versions at once, so this could be used to install both 17 and 21 (or 22), setting up the latter as the default version, and this would remove the need for:

  • the gradle-daemon-jvm.properties toolchainVersion
  • the foojay plugin

@cpovirk

cpovirk commented Jul 15, 2024

Copy link
Copy Markdown
Collaborator

Thank you! If would lean toward the suggestion from @tbroyer of using (assuming that I have this right):

  • the newest JDK that we can for Gradle at the moment (probably 21 unless the recent Gradle upgrade unlocked 22)
  • the newest JDK that we can for the compilation (where 22 might well work now) with --release [edit: -source -target] as necessary

Then the toolchains would cover just the testing step (where we already have a test configured to run under Java 8).

But I also think that OSGi is more important than the build hygiene, so I don't want to miss out on that while we optimize things here. So I think we could merge this and then #428 as-is, but I won't press any buttons yet in case the tweaks are easy enough that you might choose to just do them. (No pressure. It's not like I'm going to volunteer... :))

@ben-manes

ben-manes commented Jul 15, 2024

Copy link
Copy Markdown
Contributor Author

Gradle supports jdk 22, and can compile/run against EA builds using org.gradle.java.installations.fromEnv (Caffeine uses jdk 24). The issue with EA builds is that tools that directly interact with byte code may not work, e.g. test discovery and code coverage.

The only potential flaw with the --release approach is when jdk8 is unsupported since it results in a deprecation warning so releasing on an older compatible jdk will become necessary (if it even still matters by then). Otherwise using the release flag is simple and safe. I wanted to make the most minimal changes and be least opinionated, and this suggestion further diverges from your existing build and CI process, so I would prefer that be done in a separate pull request by others.

I don't agree with the other rational in that article, e.g. Compact String are a runtime feature and specifying the build's jdk improves the new contributors experience (as they would otherwise only see the class file version mismatch error). But all of that is moot, what matters is that any change fit within the maintainers' workflow and obviously it did not fit Jake's. What best fits the team here is most important.

@cpovirk

cpovirk commented Jul 15, 2024

Copy link
Copy Markdown
Collaborator

Thanks. There's more that I'd want to dig into to understand the situation with toolchains fully, so let's roll with this for now.

@cpovirk cpovirk merged commit f0af7de into jspecify:main Jul 15, 2024
@cpovirk

cpovirk commented Jul 15, 2024

Copy link
Copy Markdown
Collaborator

It looks like this causes Gradle to need a local JDK 21 that it's able to autodetect. That's not a significant different from my perspective because my default JDK is a JDK 22, which Gradle doesn't like, so I have been needing to set JAVA_HOME already.

Here's a run with no JAVA_HOME on a machine without an autodetectable JDK 21:

$ ./gradlew clean assemble
...
* What went wrong:
Cannot find a Java installation on your machine (Linux 6.6.15-2rodete2-amd64 amd64) matching the Daemon JVM defined requirements: Compatible with Java 21 (from gradle/gradle-daemon-jvm.properties).
...

So I'll now run JAVA_HOME=$HOME/jdk-21.0.2 ./gradlew clean assemble. (Of course, that's theoretically better than using 17, which is what I'd been doing recently.)

@ben-manes

Copy link
Copy Markdown
Contributor Author

oh, you can change to that version in the properties file as Gradle is compatible with 22. All it needs is for the daemon to run on jdk17 or above for the bnd plugin.

@ben-manes

Copy link
Copy Markdown
Contributor Author

It looks like this causes Gradle to need a local JDK 21 that it's able to autodetect.

fyi the latest Gradle release will now auto-provision the daemon so you don't need any workarounds.

You can run ./gradlew updateDaemonJvm to regenerate and it will produce

#This file is generated by updateDaemonJvm
toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/e2d97f28068cf05b0467aa8e97b19f69/redirect
toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/a41f952f4496c2309be30fd168c6c117/redirect
toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/e2d97f28068cf05b0467aa8e97b19f69/redirect
toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/a41f952f4496c2309be30fd168c6c117/redirect
toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/e7806cd9471741d622398825f14d2da6/redirect
toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/0402cc5012ae8124ea0ad01bd29342ef/redirect
toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/e2d97f28068cf05b0467aa8e97b19f69/redirect
toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/a41f952f4496c2309be30fd168c6c117/redirect
toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/86ea5d26c5757681ffe78d87258b45ec/redirect
toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/ea8232621e1368089cec8b12816df5e3/redirect
toolchainVersion=21

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants