bazelbuild / bazel

a fast, scalable, multi-language and extensible build system
https://bazel.build
Apache License 2.0
22.76k stars 3.99k forks source link

com.sun.tools not visible with non-default language levels #21983

Closed bdleitner closed 3 months ago

bdleitner commented 3 months ago

Description of the bug:

Transcribing from stackoverflow since I didn't get any hits there and I think this might constitute a bug:

TL:DR;

Expected behavior: regardless of --java_language_version and --tool_java_language_version flags, com.sun.tools.javac.* classes should be importable. Observed behavior: Specifying these flags for any non-default value causes a compile time error due to lack of visibility for these packages.

Minimal Example

OS: Windows 10 Bazel: 7.1.1

Long Version.

I'm migrating to bzlmod with a local registry and wanted to write a custom bugchecker for errorprone. This meant adding the check_api portion to my registry's errorprone module. Errorprone code uses the var keyword and also com.sun.tools.javac.*.

With no java language level specified, the default is 8, and so the use of the var keyword causes the build to fail. But specifying any other language level causes the com.sun.tools.javac.* dependency to stop being visible and leads to the error:

error: package com.sun.tools.javac.code is not visible
import com.sun.tools.javac.code.Symbol.ClassSymbol;
                          ^
  (package com.sun.tools.javac.code is declared in module jdk.compiler, which does not export it to the unnamed module)

this occurs even though bazel reports that the expanded command is:

external\rules_java~~toolchains~remotejdk21_win\bin\java.exe \
    --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)

and I would expect these --add-exports flags to be precisely what would be needed to solve the problem.

The minimal example illustrates this without the use of the registry.

Which category does this issue belong to?

Java Rules

What's the simplest, easiest way to reproduce this bug? Please provide a minimal example if possible.

  1. import a class from com.sun.tools.javac.code into a java class that is included in a java_library target's sources.
  2. try to bazel build --java_language_version=11 --tool_java_language_version=11 the target.

Which operating system are you running Bazel on?

Windows 10

What is the output of bazel info release?

7.1.1

If bazel info release returns development version or (@non-git), tell us how you built Bazel.

No response

What's the output of git remote get-url origin; git rev-parse HEAD ?

No response

Is this a regression? If yes, please try to identify the Bazel commit where the bug was introduced.

No response

Have you found anything relevant by searching the web?

I tried Googling the error, which led to information about the --add-exports flag, which only furthered my confusion as those flags seem to already be included.

After being unable to cobble together a solution and being able to reproduce with a minimal example, I tried posting to stackoverflow. No answers there yet.

Any other information, logs, or outputs that you want to share?

No response

fmeum commented 3 months ago

The --add-exports you are seeing are passed to the JVM running the Java compiler, not as arguments to the compiler itself. Similarly, your .bazelrc entries using --jvmopt pass them to the JVMs running your targets.

Instead, could you try adding them with --javacopt or the javacopts attribute on a target?

bdleitner commented 3 months ago

I tried this, and I updated the minimal example readme with the results. The short version:

with either the --javacopt in bazelrc or javacopts on the BUILD target I get the same behavior as before with one small change. Without the language level flags I get errors for var as expected, and with the flags I get:

warning: [options] --add-opens has no effect at compile time
java\com\bdl\demo\tools\DemoComSunToolsIssue.java:3: error: package com.sun.tools.javac.code is not visible
import com.sun.tools.javac.code.Symbol.ClassSymbol;
                          ^
  (package com.sun.tools.javac.code is declared in module jdk.compiler, which does not export it to the unnamed module)
java\com\bdl\demo\tools\DemoComSunToolsIssue.java:10: error: cannot find symbol
    System.out.printf("%s:%s\n", foo, ClassSymbol.class.getCanonicalName()); // with the flags, this is an error.
                                      ^
  symbol:   class ClassSymbol
  location: class DemoComSunToolsIssue
Target //java/com/bdl/demo/tools:tools failed to build

Which is the same error as before, but the warning: [options] --add-opens has no effect at compile time is new, and it would seem to indicate that the very flags we're trying to use are not having an effect.

bdleitner commented 3 months ago

Side note: I'm also a Googler, so if there's anything I can do to help out internally, let me know. My LDAP is bdleitner.

fmeum commented 3 months ago

The warning is right, you want --add-exports at compile time. With these changes (some of them required because I'm not running this on Windows), I get the build to pass:

diff --git a/.bazelrc b/.bazelrc
index 687c629..e91f58e 100644
--- a/.bazelrc
+++ b/.bazelrc
@@ -1,3 +1,3 @@
-startup --output_user_root="D:/_bazel_out"
-common  --enable_bzlmod=true --registry="file:///c:/projects/bazel/bzlmod/registry" --registry="https://bcr.bazel.build" --lockfile_mode=off
+common  --enable_bzlmod=true  --lockfile_mode=off
 test --test_output=errors
+common --java_language_version=17
diff --git a/java/com/bdl/demo/tools/BUILD b/java/com/bdl/demo/tools/BUILD
index d0ef013..a32c68d 100644
--- a/java/com/bdl/demo/tools/BUILD
+++ b/java/com/bdl/demo/tools/BUILD
@@ -1,6 +1,7 @@
 java_library(
     name = "tools",
     srcs = glob(["*.java"]),
+    javacopts = ["--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED"],
     visibility = ["//visibility:public"],
     deps = [],
 )

Side note: I'm also a Googler, so if there's anything I can do to help out internally, let me know. My LDAP is bdleitner.

I am not though ;-)

bdleitner commented 3 months ago

Interesting... the difference between add-opens and add-exports did the trick. I originally got the list of flags from a bazel query command I found to list the jvm flags on the java toolchain and copied them over. But now knowing that those are to the jvm running the compiler and not the compiler itself, I understand the mismatch. This got it working and it unblocks me for my weekend project. Thanks!