Skip to content

Conversation

@CRogers
Copy link
Contributor

@CRogers CRogers commented Nov 7, 2025

Before this PR

Currently when compiling Java code, if we want to target Java major version XX bytecode in class files, we'll use an XX Java compiler. We do not use the --release flag (which would allow us to target a lower source/bytecode/jdk api from a higher versioned Java compiler) because it's is verboten to use --release with --add-exports, which happens a lot around our codebases.

Error Prone 2.43.0 has made JDK 21 the minimum required JDK that Error Prone is run in. The recommendation is to use --release so a higher version JDK can safely output java classes at a lower language level. However, we can't do this due to the aforementioned issue with --add-exports. Similarly, we're stuck on Java 17 libraries for now, so can't just upgrade everything to Java 21. This makes us stuck, unable to upgrade Error Prone.

Luckily, in a previous PR I have removed the --release/--add-exports restriction (it also has more details about the errorprone issue). There is nothing stopping us using a higher compiler and targeting a lower version using --release.

After this PR

==COMMIT_MSG==
baseline-java-versions: Introduce a required javaCompiler property to javaVersions which will determine which JDK is used to run the Java compiler. --release is now used to target lower Java language versions/class file bytecode than the compiler.
==COMMIT_MSG==

I've expanded the tests quite a lot.

Possible downsides?

  • The groovy and scala codepaths in this plugins were/are also entirely untested. I've mostly left them be.
  • Needs some more manual testing.
  • We will need to excavate out the compiler property as part of baseline upgrades.

@changelog-app
Copy link

changelog-app bot commented Nov 7, 2025

Generate changelog in changelog/@unreleased

Type (Select exactly one)

  • Feature (Adding new functionality)
  • Improvement (Improving existing functionality)
  • Fix (Fixing an issue with existing functionality)
  • Break (Creating a new major version by breaking public APIs)
  • Deprecation (Removing functionality in a non-breaking way)
  • Migration (Automatically moving data/functionality to a new system)

Description

baseline-java-versions: Introduce a required javaCompiler property to javaVersions which will determine which JDK is used to run the Java compiler. --release is now used to target lower Java language versions/class file bytecode than the compiler.

Check the box to generate changelog(s)

  • Generate changelog entry


@Override
public final void setLibraryTarget(int _value) {
throw throwCannotSetFromSubproject();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hilariously this is throwing the result of a method that always throws.

@CRogers CRogers changed the title baseline-java-versions: compiler property to compile code with a certain JDK version baseline-java-versions: compiler property to compile Java code with a certain JDK version Nov 7, 2025
README.md Outdated
The configurable fields of the `javaVersions` extension are:
* `libraryTarget`: (required) The Java version used for compilation of libraries that are published.
* `distributionTarget`: (optional) The Java version used for compilation of code used within distributions, but not published externally. Defaults to the `libraryTarget` version.
* `compiler`: (required) The version of the Java compiler used.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I wonder if this should be javaCompiler to make clear this version is not being used for groovy/scala compilation

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

README.md Outdated
The configurable fields of the `javaVersions` extension are:
* `libraryTarget`: (required) The Java version used for compilation of libraries that are published.
* `distributionTarget`: (optional) The Java version used for compilation of code used within distributions, but not published externally. Defaults to the `libraryTarget` version.
* `compiler`: (required) The version of the Java compiler used.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have made this required because if it is not, everything remains unset and Gradle defaults to using the daemon JDK version, which seems not ideal. But it does mean it always needs to be set, even if your project only has groovy/scala and no java.

}

// In Gradle <8, we need to set sourceCompatibility to opt out of '-release', allowing opens/exports to be used.
// https://github.com/gradle/gradle/issues/18824#issuecomment-1026909824
Copy link
Contributor Author

@CRogers CRogers Nov 7, 2025

Choose a reason for hiding this comment

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

Pretty sure this is irrelevant after #3324. But really need some tests (currently the new tests do not even test against Gradle 7). I'm not even sure groovy/scala have --add-exports at compilation time.

Comment on lines 156 to 159
groovyCompileTask
.getOptions()
.getCompilerArgumentProviders()
.add(new EnablePreviewArgumentProvider(target));
Copy link
Contributor Author

@CRogers CRogers Nov 8, 2025

Choose a reason for hiding this comment

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

Unsure if this actually does anything for Groovy compile. Same for Scala. Needs more testing. Might need it to be able to compile against preview APIs (maybe use Java preview source features when compiling with Java files with Groovy?)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I guess not really relevant for this PR.

@CRogers CRogers changed the title baseline-java-versions: compiler property to compile Java code with a certain JDK version baseline-java-versions: javaCompiler property to compile Java code with a certain JDK version Nov 8, 2025
apply plugin: 'com.palantir.baseline-java-versions'
javaVersions {
javaCompiler = 25
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We'll need to excavate this (javaCompiler = 21) out.

proj.getPluginManager().apply(BaselineReproducibility.class);
proj.getPluginManager().apply(BaselineClassUniquenessPlugin.class);
proj.getPluginManager().apply(BaselineExactDependencies.class);
proj.getPluginManager().apply(BaselineReleaseCompatibility.class);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This would set --release on Java <9, but we always set --release now so it's no longer needed.

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.

2 participants