Bazel:java_library 通过 javacopts 进行的字符编码不起作用?

Bazel: java_library character encoding via javacopts not working?

我有一个外部源存储库,它显然存储了一些使用 ISO-8859-1 字符编码的源文件。当通过 Bazel 调用时,我无法让 javac 从默认的 UTF-8 更改为 ISO-8859-1。

我正在通过 Bazel 获取外部存储库,并且可以确定所获取文件的字符集:

> cd bazel-PROJECT/external/third-party/src
> file -i LibraryCode.java 
LibraryCode.java: text/x-c; charset=iso-8859-1

通过 Bazel 的 java_library 构建外部源,或尝试直接从命令行通过 javac 编译外部存储库源文件失败(预期):

error: unmappable character for encoding UTF8

尝试使用 javac 的 -encoding 参数解决了从命令行针对 Bazel 获取的外部存储库文件使用时的编译问题:

> javac -encoding iso-8859-1 LibraryCode.java

但是,我无法通过 Bazel 成功将 -encoding 选项传递给 javac。

到目前为止我已经尝试过:

  1. 在 java_library 规则中设置 javacopts
  2. 从 Bazel 的命令行设置 --javacopt
  3. 使用编码 ISO-8859-1 声明 java_toolchain 规则,并在 Bazel 的命令行中将其与 --java_toolchain 一起使用。

None 这些尝试解决了字符集不匹配和编译器错误。

1) repository_rule build_file: thirdparty.BUILD

java_library(
  name = "thirdparty",
  srcs = glob(["src/**/*.java"]),
  javacopts = ["-encoding iso-8859-1"],
  visibility = ["//visibility:public"]
)

2) Bazel 命令行:

> bazel build --javacopt="-encoding iso-8859-1" target 

3) 使用编码设置定义 Java 工具链目标:

java_toolchain(
  name = "toolchain",
  bootclasspath = ["@bazel_tools//tools/jdk:bootclasspath"],
  encoding = "iso-8859-1",
  extclasspath = ["@bazel_tools//tools/jdk:extdir"],
  forcibly_disable_header_compilation = 0,
  genclass = ["@bazel_tools//tools/jdk:GenClass_deploy.jar"],
  header_compiler = ["@bazel_tools//tools/jdk:turbine_deploy.jar"],
  ijar = ["@bazel_tools//tools/jdk:ijar"],
  javabuilder = ["@bazel_tools//tools/jdk:JavaBuilder_deploy.jar"],
  javac = ["@bazel_tools//third_party/java/jdk/langtools:javac_jar"],
  javac_supports_workers = 1,
  jvm_opts = [
    "-XX:+TieredCompilation",
    "-XX:TieredStopAtLevel=1",
  ],
  misc = [
    "-XDskipDuplicateBridges=true",
  ],
  singlejar = ["@bazel_tools//tools/jdk:SingleJar_deploy.jar"],
  source_version = "8",
  target_version = "8",

  visibility = ["//visibility:public"]
)

全部以错误结束:编码 UTF8 的不可映射字符。

我在通过 Bazel 设置 javac 编码时犯了什么错误?

我可以尝试通过 iconv 转换外部存储库源文件来解决这个问题,但我更愿意按预期通过 javac 的编码设置来解决它。

跟进

未被识别的 java_toolchain 编码似乎是一个错误。我在我的本地 Bazel 副本上对此进行了初步修复——java_toolchain 更改字符集的方法(上面的选项 #3)似乎有效。

跟踪此问题并在以下位置提出修复建议:#2926

不幸的是,没有从命令行/基于目标的好方法来做到这一点。你必须写一个 java_toolchain and point to it. Deriving the one from bazel 会导致:

java_toolchain(
    name = "toolchain",
    bootclasspath = ["@bazel_tools//tools/jdk:bootclasspath"],
    encoding = "iso-8859-1",
    extclasspath = ["@bazel_tools//tools/jdk:extclasspath"],
    forcibly_disable_header_compilation = 0,
    genclass = ["@bazel_tools//tools/jdk:genclass"],
    header_compiler = ["@bazel_tools//tools/jdk:turbine"],
    ijar = ["@bazel_tools//tools/jdk:ijar"],
    javabuilder = ["@bazel_tools//tools/jdk:javabuilder"],
    javac = ["@bazel_tools//third_party/java/jdk/langtools:javac_jar"],
    javac_supports_workers = 1,
    jvm_opts = [
        "-XX:+TieredCompilation",
        "-XX:TieredStopAtLevel=1",
    ],
    misc = [
        "-XDskipDuplicateBridges=true",
    ],
    singlejar = ["@bazel_tools//tools/jdk:SingleJar_deploy.jar"],
    source_version = "8",
    target_version = "8",
)

(出于性能原因,您可能希望将 singlejar 目标更改为 C++ 二进制文件:@bazel_tools//tools/jdk:singlejar IIRC)

然后您可以使用 --java_toolchain=//my:toolchain 指向该工具链(参见 java_toolchain flag