bazel 构建问题 - com.sun.tools.javac 或 var 关键字导致失败

问题描述 投票:0回答:1

TL:博士;

使用默认的 java 语言版本,

var
关键字会导致错误,但指定版本 11 会导致对
com.sun.tools.javac.*
的引用,从而导致错误。

参见最小示例

长版

事物的版本:

  • 操作系统:Windows 10
  • Bazel:7.1.1(通过 Bazelisk 1.19.0)

背景:我最近迁移到

bzlmod
并了解了使用本地注册表的基础知识。我想尝试自定义
errorprone BugChecker
,这意味着扩展我的注册表的
errorprone
模块,除了注释之外还包含
check_api
目录树。

在与其他依赖项进行斗争之后,我能够找到该模块所需的 Maven 添加,但遇到了最后一个问题,我不知道如何解决:

该目录下的代码引用了

com.sun.tools.javac.*
,也使用了
var
关键字。如果我没有在
.bazelrc
中指定 java 语言版本,则
var
关键字会导致错误:

warning: as of release 10, 'var' is a restricted type name \
  and cannot be used for type declarations or as the element type of an array

一开始我觉得很困惑,因为我认为默认语言级别现在是 11,但是我错了。所以这是预料之中的。

但是当我通过将

build --java_language_version=11 --tool_java_language_version=11
添加到我的
bazelrc
来指定更高的语言级别时,
com.sun.tools.javac
引用会导致错误:

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)

特别令人困惑的是,当发生这种情况时,bazel 指示完整的命令是:

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)

那些

--add-exports
标志似乎正是解决此问题所需的标志。

我能够在一个不依赖于注册表的小型最小示例中重现这一点。

我不太了解 java 工具链设置或如何自定义它(或者如果需要的话在哪里进行自定义)。理想情况下,如果有必要,这将是我可以集中完成的事情。我有许多不同的工作区,如果我不必在每个工作区中单独重新配置工具链,那就更好了。

另一个潜在的担忧是,最终一些项目将基于 Android(我还没有任何 Android 可以与 bzlmod 注册表一起使用,但如果我无法破解它,下次会遇到不同的问题),因此对阻止这种情况发生的工具链并不理想。

由于任何自定义的易错检查只能由 bazel 本身通过其易错集成的一部分来运行,也许我只需要一个工具链来专门用于这些检查(及其测试)?不过,理想情况下,如果可以在没有工具链定制的情况下完成,那就更好了。

旁白

与具体问题无关,但可能有助于提高我的理解:

为了看看会发生什么,我尝试将语言级别设置得更高(17),然后我得到:

ERROR: D:/_bazel_out/sfuxpclr/external/rules_jvm_external~~maven~javax_maven/BUILD:26:11: Stamping the manifest of @@rules_jvm_external~~maven~javax_maven//:javax_annotation_javax_annotation_api failed: (Exit 1): AddJarManifestEntry.exe failed: error executing StampJarManifest command (from targ
et @@rules_jvm_external~~maven~javax_maven//:javax_annotation_javax_annotation_api) bazel-out\x64_windows-opt-exec-ST-13d3ddad9198\bin\external\rules_jvm_external~\private\tools\java\com\github\bazelbuild\rules_jvm_external\jar\AddJarManifestEntry.exe --source ... (remaining 5 arguments skipped)
Error: LinkageError occurred while loading main class com.github.bazelbuild.rules_jvm_external.jar.AddJarManifestEntry                                                                                                                                                                    
        java.lang.UnsupportedClassVersionError: com/github/bazelbuild/rules_jvm_external/jar/AddJarManifestEntry has been compiled by a more recent version of the Java Runtime (class file version 61.0), this version of the Java Runtime only recognizes class file versions up to 55.0

起初我以为这可能是由于包含了在较早版本下编译的 maven jar 文件导致的,然后无法链接。但是错误消息似乎是倒退的,因为“此版本的 java 运行时”将是较旧的版本,它(大概)抱怨我在指定的 v17 运行时下编译的代码。但如果我指定了

(tool_)java_language_version=17
,那么“这个”较旧的运行时来自哪里?试图使用它做什么?

java bazel
1个回答
0
投票

感谢 bazel 项目的 Fabian 对此提供的帮助。

事实证明,该问题源于对

add-exports
add-opens
标志如何工作的误解。

  1. 列表中提供混淆的标志被传递给运行编译器的 JVM,而不是编译器。
  2. 当我尝试手动添加标志作为 JVM 标志时,这不起作用,因为它们需要是
    javacopts
    标志。
  3. 此外,对于编译来说,
    add-exports
    add-opens
    之间的区别变得很重要,因为
    add-opens
    在编译时被忽略,因此我从查询中复制以从工具链获取列表的标志不正确,因为该列表中的
    add-opens
    标志需要更改为
    add-exports

将标志添加为

--javacopt
文件中的
bazelrc
标志或
javacopts
目标上的
java_library
,构建能够成功。

© www.soinside.com 2019 - 2024. All rights reserved.