如何在Bazel构建中通过java_toolchain配置使用Eclipse编译器ECJ
问题根源
Bazel 中 java_toolchain 的 javabuilder 字段指向的是 Bazel 自研的编译封装程序,而非直接指向 Java 编译器本体。这个封装程序负责解析 Bazel 传入的 --output、--native_header_output 等自定义参数,再转换成对应编译器(javac/ECJ)可识别的参数格式。你直接将 javabuilder 替换为 ecj.jar,ECJ 自然无法识别 Bazel 的私有参数。
正确配置方案
1. 先在 WORKSPACE 中声明 ECJ 依赖
http_jar( name = "ecj", url = "ECJ 3.27.0 版本的jar下载地址", sha256 = "替换为对应jar包的真实sha256哈希值", )
2. 修改 java_toolchain 配置
不需要替换 javabuilder,保持使用默认的 Bazel JavaBuilder,通过 JVM 参数告诉 JavaBuilder 使用 ECJ 作为后端编译器即可,修改后的完整配置如下:
java_toolchain( name = "my-ecj-toolchain", # 恢复javabuilder为Bazel默认的封装程序,不要直接指向ecj.jar javabuilder = ["@bazel_tools//tools/jdk:javabuilder"], source_version = "8", target_version = "8", javac_supports_workers = False, javac_supports_multiplex_workers = False, bootclasspath = ["@bazel_tools//tools/jdk:platformclasspath"], # 注意:此处-XD开头的是javac专属参数,后续需要替换为ECJ支持的对应参数 misc = ["-XDskipDuplicateBridges=true", "-XDcompilePolicy=simple", "-g", "-parameters"], jvm_opts = [ # 指定使用ECJ作为后端编译器 "-Dcom.google.devtools.build.buildjar.javac.compiler=ecj", # 传入ECJ jar包的路径 "-Dcom.google.devtools.build.buildjar.javac.ecjjar=$(location @ecj//:jar)", ], # 加入ECJ依赖到工具链中 tools = ["@bazel_tools//tools/jdk:javac_jar", "@bazel_tools//tools/jdk:java_compiler_jar", "@bazel_tools//tools/jdk:jdk_compiler_jar", "@ecj//:jar"], singlejar = ["@bazel_tools//tools/jdk:singlejar"], forcibly_disable_header_compilation = True, genclass = ["@bazel_tools//tools/jdk:genclass"], ijar = ["@bazel_tools//tools/jdk:ijar"], header_compiler = ["@bazel_tools//tools/jdk:turbine_direct"], header_compiler_direct = ["@bazel_tools//tools/jdk:turbine_direct"], jacocorunner = "@bazel_tools//tools/jdk:JacocoCoverageFilegroup", )
额外注意事项
- 你之前关闭 Worker 支持、禁用头编译的配置是正确的,保留即可:ECJ 不兼容 Bazel 的持久化 Worker 协议,且 Turbine 头编译器不支持 ECJ 语法。
misc中的-XD开头参数是 javac 专属参数,ECJ 不识别,需要查阅 ECJ 官方文档替换为对应功能的参数,否则会触发新的参数错误。- 构建时需要指定使用你的自定义工具链,添加构建参数
--java_toolchain=//你的配置文件所在路径:my-ecj-toolchain,也可以直接在.bazelrc中全局配置该参数。
内容的提问来源于stack exchange,提问作者hagello
相关产品推荐
相关产品推荐

