如何在Bazel 0.11.1工作区配置不同bootclasspaths适配多Java版本?
我来帮你搞定这个Bazel 0.11.1多Java版本的问题——我之前也在老版本Bazel上折腾过类似场景,分享几个能彻底解决兼容性的办法:
1. 用
java_toolchain规则彻底隔离版本 单纯改javacopt只能调整编译参数,没法隔离JDK本身和核心类库,用java_toolchain能从根源上区分不同版本的Java环境:
- 先在根目录的
BUILD文件里定义Java7的工具链,作为全局默认:java_toolchain( name = "java7_toolchain", source_version = "7", target_version = "7", javacopts = ["-source", "1.7", "-target", "1.7"], # 如果你需要指定本地JDK路径,加上这行: # jdk_path = "/path/to/your/java7/jdk" ) - 再定义一个新版本(比如Java11)的工具链,给内部非发布代码用:
java_toolchain( name = "java11_toolchain", source_version = "11", target_version = "11", javacopts = ["-source", "11", "-target", "11"], jdk_path = "/path/to/your/java11/jdk" ) - 在
.bazelrc里全局设置默认使用Java7工具链:build --java_toolchain=//:java7_toolchain - 对于需要用新版本的目标,直接在
BUILD文件里覆盖工具链:java_library( name = "internal_utils", srcs = glob(["src/main/java/com/yourcompany/internal/**/*.java"]), java_toolchain = "//:java11_toolchain", )
2. 强制对外代码的Java7兼容性
你之前的方法可能漏掉了依赖的字节码和API兼容性——哪怕自己代码用Java7编译,如果依赖了高版本Java编译的库,运行时还是会报错。可以这么补全:
- 给所有对外发布的目标添加
-bootclasspath参数,强制编译器使用Java7的核心类库,避免不小心调用高版本API:java_binary( name = "release_app", srcs = glob(["src/main/java/com/yourcompany/app/**/*.java"]), javacopts = ["-source", "1.7", "-target", "1.7", "-bootclasspath", "/path/to/java7/jre/lib/rt.jar"], ) - 编译发布版本时开启全量lint检查,让编译器提示你有没有用Java7以上的API:
bazel build --javacopt="-Xlint:all" //path/to/release:target
3. 用条件编译切换版本(可选)
如果需要通过编译开关快速切换发布/内部版本的Java配置,可以结合select和编译标记:
- 在
.bazelrc里添加编译配置:build --define=is_release=false build:release --define=is_release=true - 在
BUILD文件里用select动态选择参数和工具链:java_library( name = "my_lib", srcs = glob(["src/main/java/com/yourcompany/lib/**/*.java"]), javacopts = select({ ":is_release": ["-source", "1.7", "-target", "1.7", "-bootclasspath", "/path/to/java7/jre/lib/rt.jar"], "//conditions:default": ["-source", "11", "-target", "11"], }), java_toolchain = select({ ":is_release": "//:java7_toolchain", "//conditions:default": "//:java11_toolchain", }), ) - 编译发布版本时只需加
--config=release:bazel build --config=release //...
注意:Bazel 0.11.1是比较老的版本,java_toolchain的部分语法可能和新版本略有差异,如果遇到配置问题,可以仔细核对对应版本的内置规则文档。
内容的提问来源于stack exchange,提问作者Marco
相关产品推荐
相关产品推荐

