如何在 Bazel 工作区中使用不同的引导类路径?

How to use different bootclasspaths in Bazel workspace?

我目前正在尝试构建一个 Bazel 0.11.1 工作区,其中包含使用不同 Java 语言级别的项目。实际应用程序使用 Java 7,但对于某些无法发布的代码,我想使用更新的 Java 版本来解决,以便能够使用新的语言功能。

我可以在一定程度上解决这个问题,方法是在 .bazelrc 中使用 --javacopt,设置 -source 1.7 -target 1.7 并使用 javacopts 属性覆盖项目级别的默认值,但是在使用更新的 Java 版本编译时,这不足以确保适当的 Java 7 兼容性。为此,我确实需要针对 Java 7 个类路径编译 Java 7 个项目。

使用自定义引导类路径的唯一方法似乎是通过 java_toolchain。有用。但是我找不到为不同的项目使用不同的引导类路径的方法,因为工具链影响所有项目并且与 javacopts 不同,不能在项目级别覆盖。

这是 Bazel 根本不可能(还?)的用例吗?还是有什么技巧可以让它发挥作用?

原来有一个方法:写一个执行编译的自定义规则。

java_common 模块为编译器提供接口。

library.bzl

def _impl(ctx):
    deps = []
    for dep in ctx.attr.deps:
        if java_common.provider in dep:
            deps.append(dep[java_common.provider])
    output_jar = ctx.new_file("lib{0}.jar".format(ctx.label.name))
    runtime = java_common.JavaRuntimeInfo
    compilation_provider = java_common.compile(
        ctx,
        source_jars = ctx.files.srcs_jars,
        source_files = ctx.files.srcs,
        output = output_jar,
        javac_opts = ctx.attr.javac_opts,
        deps = deps,
        strict_deps = ctx.attr.strict_deps,
        java_toolchain = ctx.attr.toolchain,
        host_javabase = ctx.attr._host_javabase,
        resources = ctx.files.resources,
        neverlink = ctx.attr.neverlink,
    )

    return struct(
        files = depset([output_jar]),
        providers = [compilation_provider],
    )

library = rule(
    implementation = _impl,
    attrs = {
        "srcs_jars": attr.label_list(allow_files=True),
        "srcs": attr.label_list(allow_files=True),
        "javac_opts": attr.string_list(default=[]),
        "deps": attr.label_list(),
        "strict_deps": attr.string(default="ERROR"),
        "toolchain": attr.label(default=Label("@bazel_tools//tools/jdk:toolchain")),
        "sourcepath": attr.label_list(),
        "resources": attr.label_list(),
        "neverlink": attr.bool(default=False),
        "_host_javabase": attr.label(default=Label("@local_jdk//:jdk")),
    },
    fragments = ["java"],
)

我现在可以使用这条规则来设置不同的编译工具链。

BUILD

load('//build/jdk:library.bzl', 'library')

library(
    name = "test",
    srcs = glob(["src/main/java/**/*.java"]),
#    data = glob(["src/main/resources/**"]),
    toolchain = "//build/jdk:jdk8",
    deps = ["..."],
)

不幸的是,我还没有 100% 达到目标。 java_common.compile 似乎没有 java_librarydata 属性的等价物,但大部分工具链问题已解决。