Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Java toolchain is not respected #148

Open
swarren12 opened this issue Oct 24, 2023 · 2 comments
Open

Java toolchain is not respected #148

swarren12 opened this issue Oct 24, 2023 · 2 comments
Labels
P2 We'll consider to work on this in future. (Assignee optional)

Comments

@swarren12
Copy link

swarren12 commented Oct 24, 2023

It seems that --java_language_version and related flags are not respected by rules_java.

Expected behaviour: setting the following flags in .bazelrc should build using a Java 17 JDK:

build --java_language_version=17
build --tool_java_language_version=17
build --java_runtime_version=remotejdk_17
build --tool_java_runtime_version=remotejdk_17

Actual behaviour: the build happens with a Java 21 JDK.

Steps to reproduce: see https://github.com/swarren12/example-rules_java.

Specifically: include rules_java by way of bzlmod:

bazel_dep(name = "rules_java", version = "7.0.6", dev_dependency = True)

Create a java_library with sources using Java 17 preview features:

java_library(
    name = "example",
    srcs = glob(["src/main/java/**/*.java"]),
)

Set the properties above in .bazelrc. Attempt to build the code using bazel build //:example.

The build will fail due to:

src/main/java/com/example/Main.java:10: error: patterns in switch statements are not supported in -source 17

Adding the build --javacopt="--enable-preview" property to .bazelrc and re-building causes the following error:

ERROR: BUILD.bazel:4:13: Building libexample.jar (1 source file) failed: (Exit 1): java failed: error executing command (from target //:example) external/rules_java~7.0.6~toolchains~remotejdk21_linux/bin/java '--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED' '--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED' ... (remaining 19 arguments skipped)
error: invalid source release 17 with --enable-preview

We can see that the build is actually happening on remotejdk21_linux rather than remotejdk17_linux as would be expected.

Why this is important: trying to convert a Gradle project to Bazel and prove correctness. The Gradle project builds on JDK 17 using --enable-preview. If we attempt to set --enable-preview on here, the compiler complains that --enable-preview can only be used with "release 21". Without setting --enable-preview, preview features cannot be used and so the project cannot be migrated "like-for-like" without first being upgraded to Java 21.

Running the build with --toolchain_resolution_debug='@bazel_tools//tools/jdk:runtime_toolchain_type shows the following:

INFO: Build option --toolchain_resolution_debug has changed, discarding analysis cache.
...
INFO: ToolchainResolution:   Type @bazel_tools//tools/jdk:runtime_toolchain_type: target platform @local_config_platform//:host: execution @local_config_platform//:host: Selected toolchain @rules_java~7.0.6~toolchains~remotejdk17_linux//:jdk
...
INFO: ToolchainResolution:     Type @bazel_tools//tools/jdk:runtime_toolchain_type: target platform @local_config_platform//:host: execution platform @local_config_platform//:host: Skipping toolchain @remotejdk17_linux//:jdk; execution platform already has selected toolchain
...
INFO: ToolchainResolution: Target platform @local_config_platform//:host: Selected execution platform @local_config_platform//:host, type @bazel_tools//tools/jdk:runtime_toolchain_type -> toolchain @rules_java~7.0.6~toolchains~remotejdk17_linux//:jdk
...
INFO: ToolchainResolution:   Type @bazel_tools//tools/jdk:runtime_toolchain_type: target platform @local_config_platform//:host: execution @local_config_platform//:host: Selected toolchain @rules_java~7.0.6~toolchains~remotejdk17_linux//:jdk
...
INFO: ToolchainResolution:     Type @bazel_tools//tools/jdk:runtime_toolchain_type: target platform @local_config_platform//:host: execution platform @local_config_platform//:host: Skipping toolchain @remotejdk17_linux//:jdk; execution platform already has selected toolchain
...
INFO: ToolchainResolution: Target platform @local_config_platform//:host: Selected execution platform @local_config_platform//:host, type @bazel_tools//tools/jdk:runtime_toolchain_type -> toolchain @rules_java~7.0.6~toolchains~remotejdk17_linux//:jdk
...
INFO: ToolchainResolution:   Type @bazel_tools//tools/jdk:runtime_toolchain_type: target platform @local_config_platform//:host: execution @local_config_platform//:host: Selected toolchain @rules_java~7.0.6~toolchains~remotejdk21_linux//:jdk
...
INFO: ToolchainResolution: Target platform @local_config_platform//:host: Selected execution platform @local_config_platform//:host, type @bazel_tools//tools/jdk:runtime_toolchain_type -> toolchain @rules_java~7.0.6~toolchains~remotejdk21_linux//:jdk
INFO: Analyzed target //:example (0 packages loaded, 1113 targets configured).
INFO: Found 1 target...

It seems from this that remotejdk17_linux is selected, but then remotejdk21_linux is picked in preference to it. I cannot see any obvious way of excluding remotejdk21_linux from the selection process?

Seems like a similar issue to #95. The solution here was to explicitly define JDKs, but that doesn't feel like the right solution?

@swarren12
Copy link
Author

swarren12 commented Oct 25, 2023

To summarise some points from fmeum's reply on the Bazel issue and my follow-up comment:

It just so happens that Bazel 6 uses a JDK 17 and Bazel 7 uses a JDK 21 for the Java toolchains registered by default. These toolchains use a transition on --java_runtime_version to resolve a matching JDK, which is why you see this additional resolution in the debugger.

It seems this also applies to the versions of rules_java: 6.3.2 uses Java 17 by default, whilst 7.0.4 uses Java 21.

We can use this to resolve the immediate issue by downgrading to 6.3.2 until the migration is complete. However, it is still unclear to me if (or how) we would force version 7.0.6 to use the Java 17 toolchain, rather than the Java 21 toolchain.

@EdbertChan
Copy link

EdbertChan commented Oct 26, 2023

Thought I would leave my comment here for the record:
bazelbuild/bazel#19934 (comment)

I believe the real fix is to add

[
    default_java_toolchain(
        name = "toolchain_java%d" % release,
        configuration = DEFAULT_TOOLCHAIN_CONFIGURATION,
        source_version = "%s" % release,
        target_version = "%s" % release,
+     java_runtime = "@bazel_tools//tools/jdk:toolchain_jdk%d" %release,
    )
    for release in RELEASES
]

And supply the toolchain_jdk for versions 8,9,10,11 (or at least a corresponding @bazel_tools//tools/jdk:remote_jdk{8,9,10}).

This will not work out of the box without it because otherwise you will get

java_runtime attribute of java_toolchain rule @rules_java//toolchains:toolchain_java11: '@bazel_tools//tools/jdk:toolchain_java11' does not have mandatory providers: 'JavaRuntimeInfo'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
P2 We'll consider to work on this in future. (Assignee optional)
Projects
None yet
Development

No branches or pull requests

3 participants