从 Maven 迁移到 Bazel

报告问题 查看来源 每晚 · 7.2。 · 7.1敬上 · 7.0 · 6.5 条 · 6.4

本页面介绍了如何从 Maven 迁移到 Bazel,包括 前提条件和安装步骤它介绍了 并提供了使用 Guava 项目。

从任何构建工具迁移到 Bazel 时,最好同时进行 同时运行的多个工具,直到您完全迁移开发团队, CI 系统以及任何其他相关系统。您可以在 Cloud Build 和 Container Registry 中 相同的代码库

准备工作

  • 安装 Bazel(如果尚未安装)。
  • 如果您刚开始接触 Bazel,请学习本教程 Bazel 简介:构建 Java 准备工作 迁移。本教程介绍了 Bazel 的概念、结构和标签 语法。

Maven 与 Bazel 之间的区别

  • Maven 使用顶级 pom.xml 文件。Bazel 支持多个构建 每个 BUILD 文件有多个目标,从而允许构建 比 Maven 更具增量性。
  • Maven 负责部署过程的步骤。Bazel 的用途 无法自动执行部署。
  • Bazel 使您能够表达语言之间的依赖关系。
  • 向项目添加新部分时,您可能需要使用 Bazel BUILD 文件。最佳实践是在每个新的 Java 软件包中添加一个 BUILD 文件。

从 Maven 迁移到 Bazel

以下步骤说明了如何将项目迁移到 Bazel:

  1. 创建 WORKSPACE 文件
  2. 创建一个 build 文件
  3. 创建更多 BUILD 文件
  4. 使用 Bazel 构建

以下示例来自于迁移 Guava 项目(从 Maven 迁移到 Bazel)。 使用的 Guava 项目的版本为 v31.1。使用 Guava 的示例并未介绍 但迁移过程中会显示 是为迁移手动添加或添加的

$ git clone https://github.com/google/guava.git && cd guava
$ git checkout v31.1

1. 创建 WORKSPACE 文件

在项目的根目录下创建一个名为 WORKSPACE 的文件。如果您的项目 无外部依赖项,则工作区文件可以为空。

如果您的项目依赖的文件或软件包不在上述任何一项之列, 项目的目录中,请在工作区中指定这些外部依赖项 文件。如需自动列出工作区文件的外部依赖项,请执行以下操作: 请使用 rules_jvm_external。有关使用此规则集的说明,请参阅 自述文件

Guava 项目示例:外部依赖项

你可以列出 Guava 项目,其中包含 rules_jvm_external 规则集。

将以下代码段添加到 WORKSPACE 文件中:

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

RULES_JVM_EXTERNAL_TAG = "4.3"
RULES_JVM_EXTERNAL_SHA = "6274687f6fc5783b589f56a2f1ed60de3ce1f99bc4e8f9edef3de43bdf7c6e74"

http_archive(
    name = "rules_jvm_external",
    sha256 = RULES_JVM_EXTERNAL_SHA,
    strip_prefix = "rules_jvm_external-%s" % RULES_JVM_EXTERNAL_TAG,
    url = "https://github.com/bazelbuild/rules_jvm_external/archive/%s.zip" % RULES_JVM_EXTERNAL_TAG,
)

load("@rules_jvm_external//:defs.bzl", "maven_install")

maven_install(
    artifacts = [
        "com.google.code.findbugs:jsr305:3.0.2",
        "com.google.errorprone:error_prone_annotations:2.11.0",
        "com.google.j2objc:j2objc-annotations:1.3",
        "org.codehaus.mojo:animal-sniffer-annotations:1.20",
        "org.checkerframework:checker-qual:3.12.0",
    ],
    repositories = [
        "https://repo1.maven.org/maven2",
    ],
)

2. 创建一个 BUILD 文件

现在,您已经定义了工作区和外部依赖项(如果 适用)列出,您需要创建 BUILD 文件来描述您的项目 。与具有一个 pom.xml 文件的 Maven 不同,Bazel 可以使用多个 BUILD 文件,用于构建项目。这些文件会指定多个构建目标 可让 Bazel 生成增量构建

分阶段添加 BUILD 文件。首先添加一个 BUILD 文件 进入项目根目录,然后通过 Bazel 进行初始构建。 然后,您可以通过添加更多更精细的 BUILD 文件来优化 build 目标。

  1. WORKSPACE 文件所在的目录中,创建一个文本文件并 请将其命名为 BUILD

  2. 在此 BUILD 文件中,使用适当的规则创建一个目标, 构建项目。请参考以下提示:

    • 使用适当的规则:

      • 要使用单个 Maven 模块构建项目,请使用 java_library 规则,如下所示:

        java_library(
            name = "everything",
            srcs = glob(["src/main/java/**/*.java"]),
            resources = glob(["src/main/resources/**"]),
            deps = ["//:all-external-targets"],
        )
        
      • 要构建包含多个 Maven 模块的项目,请使用 java_library 规则,如下所示:

        java_library(
            name = "everything",
            srcs = glob([
                "Module1/src/main/java/**/*.java",
                "Module2/src/main/java/**/*.java",
                ...
            ]),
            resources = glob([
                "Module1/src/main/resources/**",
                "Module2/src/main/resources/**",
                ...
            ]),
            deps = ["//:all-external-targets"],
        )
        
      • 如需构建二进制文件,请使用 java_binary 规则:

        java_binary(
            name = "everything",
            srcs = glob(["src/main/java/**/*.java"]),
            resources = glob(["src/main/resources/**"]),
            deps = ["//:all-external-targets"],
            main_class = "com.example.Main"
        )
        
    • 指定属性:

      • name:为目标指定一个含义明确的名称。在上面的示例中, 那么这个目标就是“一切”
      • srcs:使用 globbing 列出项目中的所有 .java 文件。
      • resources:使用 globbing 列出项目中的所有资源。
      • deps:您需要确定 项目需求。例如,如果您生成了一个外部清单 使用 generate_workspace 工具指定依赖项,则依赖项 是java_library generated_java_libraries 宏。
    • 请参阅 此顶级 BUILD 文件的以下示例: Guava 项目的迁移过程。

  3. 现在,项目的根目录下有了 BUILD 文件,请构建 确保其有效在命令行上,从 工作区目录中,请使用 bazel build //:everything 构建 项目。

    项目现已使用 Bazel 成功构建。您需要 添加更多 BUILD 文件,以允许对项目进行增量构建。

Guava 项目示例:从一个 BUILD 文件开始

将 Guava 项目迁移到 Bazel 时,最初会使用一个 BUILD 文件 来构建整个项目下面是这个初始 BUILD 的内容 文件:

java_library(
    name = "everything",
    srcs = glob([
        "guava/src/**/*.java",
        "futures/failureaccess/src/**/*.java",
    ]),
    deps = [
        "@maven//:com_google_code_findbugs_jsr305",
        "@maven//:com_google_errorprone_error_prone_annotations",
        "@maven//:com_google_j2objc_j2objc_annotations",
        "@maven//:org_checkerframework_checker_qual",
        "@maven//:org_codehaus_mojo_animal_sniffer_annotations",
    ],
)

3. 创建更多 BUILD 文件(可选)

正如您在完成第一次请求后看到的那样,Bazel 只需要一个 BUILD file build。您仍应考虑将 build 拆分为多个较小的区块,方法是 添加更多具有精细目标的 BUILD 文件。

包含多个目标的多个 BUILD 文件会使 build 增大 支持:

  • 增加了项目的增量构建,
  • 可增加构建的并行执行
  • 为未来用户提供更好的 build 可维护性,以及
  • 可以控制软件包之间目标的可见性, 例如包含实现详情泄露到 公共 API。

有关添加更多 BUILD 文件的提示:

  • 首先,将 BUILD 文件添加到每个 Java 软件包。起始内容 依赖项最少的 Java 软件包,逐步扩展 依赖项最多的软件包
  • 在添加 BUILD 文件并指定目标时,将这些新目标添加到 依赖于它们的目标的 deps 个部分。请注意,glob() 函数不会跨越软件包边界,因此 的软件包使与 glob() 匹配的文件变小。
  • 每次将 BUILD 文件添加到 main 目录时,请确保将 将 BUILD 文件复制到相应的 test 目录。
  • 请注意适当限制软件包之间的可见性。
  • 为了简化对 BUILD 文件设置中的错误进行问题排查,请确保 项目将在您添加每个 build 时继续使用 Bazel 进行构建 文件。运行 bazel build //... 以确保所有目标仍会构建。

4. 使用 Bazel 构建

您一直在使用 Bazel 进行构建,同时添加了 BUILD 文件以验证设置 。

获得所需的 BUILD 文件后,您可以使用 Bazel 生成所有 build