简体   繁体   English

如何在Bazel工作空间中使用不同的bootclasspath?

[英]How to use different bootclasspaths in Bazel workspace?

I'm currently trying to build a Bazel 0.11.1 workspace with projects that use different Java language levels. 我目前正在尝试使用使用不同Java语言级别的项目构建Bazel 0.11.1工作区。 The actual application uses Java 7, but for some code that won't ship, I want to settle with a more recent Java version to be able to use the new language features. 实际的应用程序使用Java 7,但是对于某些无法交付的代码,我希望使用较新的Java版本才能使用新的语言功能。

I can solve this to some extent by using --javacopt in .bazelrc , setting -source 1.7 -target 1.7 and override the defaults on a project level with the javacopts attribute, but this is not enough to ensure proper Java 7 compatibility when compiling with a more recent Java version. 我可以通过在.bazelrc使用--javacopt ,设置-source 1.7 -target 1.7并在项目级别使用javacopts属性覆盖默认值来在某种程度上解决此问题,但这不足以确保在使用最新的Java版本。 For this I really need to compile Java 7 projects against a Java 7 classpath as well. 为此,我确实还需要针对Java 7类路径编译Java 7项目。

The only way to use a custom bootclasspath seems to be via java_toolchain . 使用自定义java_toolchain的唯一方法似乎是通过java_toolchain It works. 有用。 But I could not found a way to use different bootclasspaths for different projects, because the toolchain affects all projects and unlike with javacopts cannot be overridden at the project level. 但是我找不到用于不同项目的不同javacopts方法,因为该工具链会影响所有项目,并且与javacopts不同,该工具链无法在项目级别覆盖。

Is this a usecase that is simply not (yet?) possible with Bazel? 这是Bazel无法(还可以)使用的用例吗? Or is there some trickery to make it work? 还是有一些使它起作用的技巧?

It turns out there is a way: write a custom rule that performs compilation. 事实证明,有一种方法:编写执行编译的自定义规则。

The java_common module provides an interface to the compiler. 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"],
)

This rule I can now use to set a different toolchain for compilation. 我现在可以使用此规则来设置不同的工具链进行编译。

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 = ["..."],
)

Unfortunately I'm not 100% there yet. 不幸的是,我还不是100%。 java_common.compile does not seem to have an equivalent for the data attribute of java_library , but for the most part the toolchain problem is solved. java_common.compile似乎与java_librarydata属性没有等效项,但是在大多数情况下,工具链问题已解决。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM