Bazel构建

简介

Bazel是一个类似于Make,Maven和Gradle的开源构建和测试工具。Bazel支持多种语言混编的项目并且可以根据不同的平台输出不同的构建结果。

优势:

  • 加快构建和测试速度:Bazel只重建必要的东西,借助缓存,优化依赖关系分析和并行执行,可以获得快速的和增量的构建。
  • 支持多种语言:支持Java, C++, Android, iOS, Go和各种其他语言,可以运行在Windows,macOS和Linux上。
  • 可扩展:可以扩展Bazel以支持您选择的语言

基本概念

工作区

一个工作空间是你的文件系统,它包含了源文件、符号链接以及输出目录。每个工作空间都有一个名为WORKSPACE的文本文件,该文件可能为空,或者包含对外部依赖引用

包被定义为包含文件的目录

目标

包是一个容器。包的元素称为 目标,大多数目标有两种类型,即文件规则

文件进一步分为两种。 源文件生成的文件

第二种目标是规则

如何使用bazel

  1. 下载并安装Bazel。
  2. 设置项目工作区,这是Bazel查找构建输入和BUILD文件以及存储构建输出的目录。
  3. 写一个BUILD文件,告诉Bazel要构建什么以及如何构建它。BUILD使用类似抽象的Python语言来编写,指定Bazel将构建的一组输入及其依赖项
  4. 在命令行运行bazel,bazel将输出放在工作区内

Bazel如何运作

运行构建或测试时,Bazel执行以下操作:

  1. 加载BUILD与目标相关的文件。
  2. 分析输入及其依赖关系,应用指定的构建规则。并生产action
  3. 对输入执行构建操作,直到生成最终构建输出。

由于所有以前的构建工作都是缓存的,因此Bazel可以识别并重用缓存,只重建或重新测试更改的内容

什么是action图

action图表示各个构建输入和他们之间的关系,以及Bazel将执行的构建操作。基于这张图Bazel可以跟踪文件内容的更改

安装

通过Homebrew安装Bazel包,如下所示:

brew install bazel

可以了,好了!您可以通过运行以下命令确认Bazel已成功安装:

bazel version

安装后,您可以使用以下命令升级到较新版本的Bazel:

brew upgrade bazel

常用命令

 $bazel help
                           
  用法:bazel <command> <options> ...

  可用命令:
    analyze-profile      分析构建配置文件数据。
    aquery              对分析后的操作图执行查询。
    build                构建指定的目标。

    canonicalize-flags   Canonicalize Bazel flags。
    clean                删除输出文件,并可选择停止服务器。

    cquery               执行分析后依赖图查询。

    dump                 转储Bazel服务器进程的内部状态。

    help                 打印命令或索引的帮助。
    info                 显示有关bazel服务器的运行时信息。

    fetch                获取目标的所有外部依赖项。
    mobile-install       在移动设备上安装应用程序。

    query                执行依赖关系图查询。

    run                  运行指定的目标。
    shutdown             停止Bazel服务器。
    test                 构建并运行指定的测试目标。
    version              打印Bazel的版本信息。

  获得更多帮助:
    bazel help <command>
                     打印<command>的帮助和选项。
    bazel帮助startup_options
                     JVM托管Bazel的选项。
    bazel帮助目标语法
                     解释指定目标的语法。
    bazel帮助信息键
                     显示info命令使用的键列表。

构建Java项目

所有的Bazel构建都是基于一个 工作区(workspace) 概念,它是文件系统中一个保存了全部源代码的目录,同时还将包含一些构建后的输出目录的符号链接(例如:bazel-binbazel-out 等输出目录)。工作区目录可以随意放在哪里,但是工作区的根目录必须包含一个名为 WORKSPACE 的工作区配置文件。工作区配置文件可以是一个空文件,也可以包含引用外部构建输出所需的 依赖关系

  1. 创建BUILD文件

    $ cd ~/demo
    $ mkdir -p src/main/java/com/test
    $ cat > src/main/java/com/test/Main.java <<EOF
    package com.test;
    public class Main {
        public static void main(String args[]) {
            Test.sayHi();
        }
    }
    EOF
    $ cat > src/main/java/com/test/Test.java <<EOF
    package com.test;
    
    public class Test {
        public static void sayHi() {
            System.out.println("Hello World!");
        }
    }
    EOF
    

    Bazel通过工作区中所有名为 BUILD 的文件来解析需要构建的项目信息,因此,我们需要先在 ~/gitroot/my-project 目录创建一个 BUILD 构建文件。下面是BUILD构建文件的内容:

    # ~/demo/BUILD
    java_binary(
        name = "test",
        srcs = glob(["**/*.java"]),
        main_class = "com.test.Main",
    )
    

    BUILD文件采用类似Python的语法。虽然不能包含任意的Python语法,但是BUILD文件中的每个构建规则看起来都象是一个Python函数调用,而且你也可以用 "#" 开头来添加单行注释。

    java_binary 是一个构建规则。其中 name 对应一个构建目标的标识符,可用用它来向Bazel指定构建哪个项目。srcs 对应一个源文件列表,Bazel需要将这些源文件编译为二进制文件。其中 glob(["**/*.java"]) 表示递归包含每个子目录中以每个 .java 为后缀名的文件。com.test.Main 指定包含main方法的类。

  2. 执行构建命令

    $ bazel build //:test
    INFO: Analysed target //:test (0 packages loaded).
    INFO: Found 1 target...
    Target //:test up-to-date:
      bazel-bin/test.jar
      bazel-bin/test
    INFO: Elapsed time: 0.458s, Critical Path: 0.01s
    INFO: 0 processes.
    INFO: Build completed successfully, 1 total action
    $ bazel-bin/test
    Hello World!
    
    

Bazel和Android

构建Android应用程序

  1. 设置ANDROID_HOME变量

    将其设置为Android SDK的位置,默认为$HOME/Android/Sdk/

    例如:

    export ANDROID_HOME=$HOME/Android/Sdk/
    

    为方便起见,请将以上语句添加到您的~/.bashrc文件中。

  2. 获取示例项目

    需要从GitHub获取示例项目。有两个分支:source-onlymastersource-only分支只包含对项目的源文件。master分支包含源文件和完成的Bazel WORKSPACEBUILD文件。

    获取source-only 分支中的文件:

    cd ~/Desktop
    git clone -b source-only https://github.com/bazelbuild/examples
    
  3. 设置工作区

    一个工作空间是包含一个或多个软件项目中的源文件,以及一个目录WORKSPACE文件,BUILD是Bazel用来构建软件的说明文件。工作空间还可以包含指向输出目录的符号链接。

    Bazel本身对您在工作区中组织源文件的方式没有任何要求。

  4. 创建一个WORKSPACE文件

    每个工作空间必须具有一个名为WORKSPACE位于顶级工作空间目录中的文本文件。此文件可能为空,也可能包含对构建软件所需的外部依赖项引用。

  5. 更新WORKSPACE文件

    Bazel需要运行Android SDK 构建工具 并使用SDK库来构建应用程序。这意味着您需要向WORKSPACE文件中添加一些信息,以便Bazel知道在哪里找到它们。为其他平台构建时,不需要执行此步骤。Bazel会自动从您环境中的设置中检测Java,C ++和Objective-C编译器的位置。

    将以下行添加到您的WORKSPACE文件中:

    android_sdk_repository(
        name = "androidsdk"
    )
    

    这将使用ANDROID_HOME环境变量引用的Android SDK ,并自动检测安装在该位置的最高API级别和最新版本的构建工具。

    或者,你可以明确地指定了Android SDK的位置,API级别,以及构建工具的版本通过包括使用 pathapi_levelbuild_tools_version属性。您可以指定这些属性的任何子集:

    android_sdk_repository(
        name = "androidsdk",
        path = "~/Android/sdk",
        api_level = 25,
        build_tools_version = "26.0.1"
    )
    

    如果使用ndk还需要通过在WORKSPACE 文件中添加以下规则告诉Bazel在哪里找到它:

    android_ndk_repository(
        name = "androidndk"
    )
    
  6. 创建一个BUILD文件

    一个BUILD文件是描述一组输入输出之间的关系的文本文件,

    添加android_library规则

    一个BUILD文件包含Bazel的几种不同类型的指令。最重要的类型是构建规则,它告诉Bazel如何从一组源文件或其他依赖项构建最终软件输出。

    Bazel提供了两种生成规则,android_library并且android_binary,首先使用 android_library规则告诉Bazel如何从应用程序源代码和资源文件构建 Android库模块。然后,您将使用android_binary规则告诉它如何构建Android应用程序包。

    将以下内容添加到您的BUILD文件中:

    android_library(
      name = "activities",
      srcs = glob(["src/main/java/com/google/bazel/example/android/activities/*.java"]),
      custom_package = "com.google.bazel.example.android.activities",
      manifest = "src/main/java/com/google/bazel/example/android/activities/AndroidManifest.xml",
      resource_files = glob(["src/main/java/com/google/bazel/example/android/activities/res/**"]),
    )
    

    android_library构建规则包含一组属性,这些属性指定Bazel从源文件构建库模块所需的信息。另请注意,规则的名称是activities。您将使用此名称作为规则的依赖项被android_binary引用。

    添加android_binary规则

    android_binary规则.apk为您的应用构建Android应用程序包(文件)。

    将以下内容添加到构建文件中:

    android_binary(
        name = "android",
        custom_package = "com.google.bazel.example.android",
        manifest = "src/main/java/com/google/bazel/example/android/AndroidManifest.xml",
        resource_files = glob(["src/main/java/com/google/bazel/example/android/res/**"]),
        deps = [":activities"],
    )
    

    此处,该deps属性引用activities您添加到上述BUILD文件的规则的输出。这意味着,当Bazel构建此规则的输出时,它首先检查activities库规则的输出是否已构建并且是最新的。如果没有,它会构建它,然后使用该输出来构建应用程序包文件。

  7. 构建应用程序

    输入以下内容来构建示例应用程序:

    bazel build //android:android
    

    build子命令指示巴泽勒构建跟踪目标。目标被指定为BUILD文件内部的构建规则的名称,以及相对于工作区目录的程序包路径。请注意,有时可以省略包路径或目标名称,具体取决于命令行中的当前工作目录和目标名称。

    Bazel现在启动并构建示例应用程序。在构建过程中,其输出将显示类似于以下内容:

    INFO: Found 1 target...
    Target //android:android up-to-date:
      bazel-bin/android/android_deploy.jar
      bazel-bin/android/android_unsigned.apk
      bazel-bin/android/android.apk
    INFO: Elapsed time: 7.237s, Critical Path: 5.81s
    
  8. 运行该应用程序

    bazel mobile-install 命令从命令行将应用程序部署到连接的Android设备或模拟器 。此命令使用Android Debug Bridge(adb)与设备通信。您必须将设备设置为在部署之前adb按照Android Debug Bridge中的说明 使用。您还可以选择在Android Studio中包含的Android模拟器上安装该应用。在执行以下命令之前,请确保模拟器正在运行。

    输入以下内容:

    bazel mobile-install //android:android
    

Android规则

描述了可用于使用Bazel构建和测试Android应用程序的规则

android_binary
属性 描述
name 规则的唯一名称
deps 要链接到二进制目标的其他库的列表。允许库类型是:android_libraryjava_library.so
srcs 源文件列表
aapt_version aapt版本。aapt_version = "aapt":使用aapt默认值;aapt_version = "aapt2":使用aapt2。这是新的资源打包系统,可提供改进的增量资源处理,更小的apks等。
assets 要打包的资产列表
custom_package 包名
debug_key apk签名文件
dex_shards dex的分片数。这使得dex的速度更快,但代价是应用安装和启动时间。二进制文件越大,应使用的分片越多。25是开始试验的好价值。
dexopts 生成classes.dex时dx工具的附加命令行标志
main_dex_list 这些类文件定义的类放在主classes.dex中
manifest Android清单文件的名称AndroidManifest.xml
multidex 是否将代码拆分为多个dex文件
proguard_specs 用作Proguard规范的文件
shrink_resources 是否执行资源缩减。二进制文件未使用的资源将从APK中删除。
aar_import
属性 描述
name 此规则的唯一名称。
aar aar文件

例子:

    aar_import(
        name =“google-vr-sdk”,
        aar =“gvr-android-sdk / libraries / sdk-common-1.10.0.aar”,
    )

    android_binary(
        name =“app”,
        manifest =“AndroidManifest.xml”,
        srcs = glob([“**。java”]),
        deps = [“:google-vr-sdk”],
    )
android_library

主要规则同android_binary

android_ndk_repository

配置Bazel使用Android NDK。目前支持NDK版本10到16。

还需要配置android_sdk_repository到您的WORKSPACE文件中

例子

android_ndk_repository(
    name =“androidndk”,
)

上面的示例将从您的Android NDK中找到$ANDROID_NDK_HOME并检测它支持的最高API级别。

android_ndk_repository(
    name =“androidndk”,
    path =“./android-ndk-r12b”,
    api_level = 24,
)

上面的示例将使用位于工作区内的 ./android-ndk-r12b

#BUILD
cc_library(
    name =“jni”,
    srcs = [“jni.cc”],
    deps = [“@androidndk //:cpufeatures”],
)
android_sdk_repository

配置Bazel使用本地Android SDK来支持构建Android目标。

为Bazel设置Android SDK的最低要求是

android_sdk_repository

WORKSPACE

文件中添加名为“androidsdk” 的规则,并将

$ANDROID_HOME

环境变量设置为Android SDK的路径。默认情况下,Bazel将使用安装在Android SDK中的最高Android API级别和构建工具版本。

android_sdk_repository(
    name =“androidsdk”,
)

为了确保重现建立的pathapi_level并且 build_tools_version属性可以设置为特定值。如果Android SDK没有安装指定的API级别或构建工具版本,则构建将失败。

android_sdk_repository(
    name =“androidsdk”,
    path =“./ sdk”,
    api_level = 19,
    build_tools_version =“25.0.0”,
)

Mobile-install

用于构建.apk的传统Android工具链需要许多单片,顺序步骤,所有这些都必须完成才能构建Android应用程序。在大型项目中,等待五分钟建立单线改变并不罕见。

bazel mobile-install 通过结合使用更改修剪,工作分片和Android内部的巧妙操作,可以更快地为Android进行迭代开发,所有这些都不会更改任何应用程序的代码。

传统应用安装的问题

我们发现了构建Android应用程序的以下瓶颈:

  • 默认情况下,“dx”在构建中,并不知道如何重用以前构建的工作:它会再次重新dex每个方法,即使只更改了一个方法。
  • 将数据上传到设备。adb不使用USB 2.0连接的全部带宽,较大的应用程序可能需要花费大量时间上传。整个应用程序上传,即使只有小部分发生了变化,例如资源或单个方法,因此这是一个主要的瓶颈。

bazel mobile-install做出以下改进:

  • Sharded dexing。在构建应用程序的Java代码之后,Bazel将类文件分片为大致相等大小的部分,并dx在它们上单独调用。dx在自上次构建后未更改的分片上未调用。
  • 增量文件传输。Android资源,.dex文件和本机库将从主.apk中删除,并存储在单独的移动安装目录下。这使得可以独立更新代码和Android资源,而无需重新安装整个应用程序。因此,传输文件所花费的时间更少,只有已更改的.dex文件才会在设备上重新编译。
  • 从.apk外部加载应用程序的部分内容。一个小的存根应用程序放入.apk中,从设备上的移动安装目录加载Android资源,Java代码和本机代码,然后将控制权转移到实际的应用程序

Sharded dexing

Sharded dexing相当简单:一旦构建了.jar文件, 工具 会将它们分割成大小相等的单独.jar文件,然后调用 dx自上一次构建以来更改的文件。确定dex的哪些分片不是特定于Android的逻辑:它只使用Bazel的一般更改修剪算法。

第一个版本的分片算法只是按字母顺序排序.class文件,然后将列表切割成相等大小的部分,但事实证明这是次优的:如果添加或删除了一个类(甚至是嵌套的或匿名的),它会导致所有类按字母顺序移动一个,从而导致再次删除这些分片。因此,我们决定不分割单个类,而是使用Java包。当然,如果添加或删除新包,这仍然会导致许多分片变形,但这比添加或删除单个类要少得多。

分片数由BUILD文件控制(使用 android_binary.dex_shards属性)。在一个理想的世界中,Bazel会自动确定有多少分片是最好的,但Bazel目前必须知道在执行任何分片之前的动作集(即在构建期间要执行的命令),因此它无法确定最佳分片数,因为它不知道应用程序中最终会有多少Java类。一般来说,分片越多,构建和安装就越快,但app启动速度变慢,因为动态链接器必须做更多的工作。通常在10到50个碎片之间。

增量文件传输

构建应用程序后,下一步是安装它,最好尽可能少。安装包括以下步骤:

  1. 安装.apk(即adb install
  2. 将.dex文件,Android资源和本机库上载到移动安装目录

第一步没有太多增量:应用程序是否已安装。Bazel目前依赖于用户来指示它是否应该通过--incremental命令行选项执行此步骤,因为它无法在所有情况下确定是否有必要。

在第二步中,将构建中的应用程序文件与设备上清单文件进行比较,该文件列出设备上的应用程序文件及其校验和。将任何新文件上载到设备,更新任何已更改的文件,并从设备中删除已删除的所有文件。如果清单不存在,则假定需要上载每个文件。

请注意,可以通过更改设备上的文件来欺骗增量安装算法,但不能清除清单中的校验和。我们可以通过计算设备上文件的校验和来防范这种情况,但这被认为不值得增加安装时间。

性能

通常,bazel mobile-install只需稍加更改即可构建和安装大型应用程序,速度提高4倍到10倍。我们为一些Google产品计算了以下数字:

[图片上传失败...(image-62a112-1539661819363)]

AndroidStudio集成

NDK

要为Android构建C ++,只需将cc_library依赖项添加到您的 android_binaryandroid_library规则中。

给定Android应用程序的以下BUILD文件:

# In <project>/app/src/main/BUILD.bazel

cc_library(
    name = "jni_lib",
    srcs = ["cpp/native-lib.cpp"],
)

android_library(
    name = "lib",
    srcs = ["java/com/example/android/bazel/MainActivity.java"],
    resource_files = glob(["res/**/*"]),
    custom_package = "com.example.android.bazel",
    manifest = "LibraryManifest.xml",
    deps = [":jni_lib"],
)

android_binary(
    name = "app",
    deps = [":lib"],
    manifest = "AndroidManifest.xml",
)

此BUILD文件生成以下目标图:

image

如何工作

Bazel 在构建目标时经历了三个步骤

  1. 加载阶段,Bazel会解析BUILD正在构建的目标BUILD文件以及文件传递依赖的所有文件。
  2. 分析阶段,Bazel构建了构建指定目标所需的操作图。
  3. 执行阶段,Bazel运行这些操作。

在分析过程中,Bazel为每个正在构建的目标及其传递依赖性运行规则。每个规则都会生成并记录它依赖的所有操作。

Android资源

Android库构建过程与普通Java构建过程的不同之处是Android 资源。资源是任何不是代码的东西 - 字符串,图像,布局等等

Bazel生成R.java文件(以及相关 文件R.classR.txt文件)以包含对可用资源的引用。这些R文件包含开发人员可用于引用其资源的整数资源ID。在应用程序中,每个资源ID都指向一个唯一资源。

aaptaapt2处理资源

image

Bazel支持使用原始Android资源处理器aapt或新版本处理资源aapt2。这两种方法基本相似,但有一些重要的区别。

Bazel经历了三个步骤来构建资源。

首先,Bazel序列化定义资源的文件。在aapt 管道中,解析操作将有关资源的信息序列化为 symbols.bin文件。在aapt2管道中,动作调用aapt2 编译命令,该命令将信息序列化为 aapt2使用的格式。

接下来,序列化资源与从依赖项继承的类似序列化资源合并。识别具有相同名称的资源之间的冲突,并且如果可能,在此合并期间解决。values资源文件的内容通常是显式合并的。对于其他文件,如果来自目标或其依赖项的资源具有相同的名称和限定符,则会比较文件的内容,如果它们不同,则会生成警告,并选择使用最后提供的资源。

最后,Bazel检查目标的资源是否合理并将其打包。在aapt中调用 aapt package命令,在aapt2中调用aapt2link命令。任何格式错误的资源或对不可用资源的引用都会导致失败,如果未遇到任何故障,生成 R.java文件和资源APK。

Android库

image

一个 android_library 规则是一个非常简单的规则,建立并组织一个Android库在另一个Android的目标使用。在分析阶段,基本上生成了三组操作:

首先,Bazel处理库的资源, 如上所述

接下来是库的实际编译。这主要是使用常规的Bazel Java编译路径。最大的区别是R.class资源处理中生成的 文件也包含在编译路径中(但不会被使用者继承,因为需要为每个目标重新生成R文件)。

最后,Bazel对编译的代码做了一些额外的工作:

  1. 编译后的.class替换只有java8才支持的属性。

  2. 处理后的 .class文件转换.dex

  3. hjar使用.java源文件生成一个 jar文件。方法体和私有字段将被删除,依赖时将依赖于此库.jar文件。由于这些jar只包含库的接口,因此当私有字段或方法实现发生更改时,不需要重新编译依赖库(只有在库的接口更改时才需要重新编译它们),这样可以加快构建速度。

Android二进制文件

image

对于二进制文件,三个主要的资源处理操作(解析,合并和验证)都合并为一个大型操作。在库中,Java编译可以在验证仍在进行时启动,但在二进制文件中,由于我们需要验证的最终资源ID,因此我们无法利用类似的并行化。由于创建更多操作总是会带来很小的成本,并且没有可用的并行化来弥补它,因此单个资源处理操作实际上更有效。

在二进制文件中,Java代码被编译,删除和dexed,就像在库中一样。但是,之后,.dex二进制.dex文件与依赖项中的文件合并在一起。

Bazel还将来自依赖项的已编译CC++本机代码链接到.so

合并的.dex文件,.so文件和资源APK都组合在一起构建一个初始的二进制APK,然后进行 zipaligned以生成一个未签名的APK。最后,使用二进制文件的调试密钥对未签名的APK进行签名,以生成签名的APK。

合并的.dex文件与资源APK组合以构建初始二进制APK,然后将其 压缩以生成未签名的APK。最后,使用二进制文件的调试密钥对未签名的APK进行签名,以生成签名的APK。

ProGuarded Android二进制文件

image

Bazel支持 针对目标运行ProGuardandroid_binary优化它们并减小其尺寸

ProGuarding使用一个deploy.jar文件,一个.jar包含所有二进制Java字节码的文件,由二进制文件的desugared(但不是dexed).class文件以及二进制文件的传递运行时.jar文件创建。(此 deploy.jar文件是所有android_binary目标的输出,但在没有ProGuarding的构建中它不起重要作用。)

基于一系列Proguard规范(来自二进制及其传递依赖性)的信息,ProGuard进行了多次传递deploy.jar,以优化代码,删除未使用的方法和字段,并缩短和混淆方法和字段的名称剩下的。除了生成的proguarded .jar文件之外,ProGuard还会输出从旧名称到新名称的方法和字段的映射。

外部依赖

Bazel项目

想使用bazel项目,您可以使用 local_repositorygit_repositoryhttp_archive 从本地文件系统中,一个Git仓库或下载。

例如,假设您正在处理一个项目,my-project/并且您希望依赖同事的项目coworkers-project。这两个项目都使用Bazel,因此您可以将同事的项目添加为外部依赖项,然后使用您的同事从您自己的BUILD文件中定义的任何目标。您可以将以下内容添加到my_project/WORKSPACE

local_repository(
    name = "coworkers_project",
    path = "/path/to/coworkers-project",
)

如果您的同事有目标//foo:bar,您的项目可以将其称为 @coworkers_project//foo:bar

非Bazel项目

前缀new_(例如 new_local_repositorynew_git_repositorynew_http_archive )允许您创建不使用Bazel的目标。

例如,假设您正在处理一个项目my-project/,并且您希望依赖于您的同事的项目,coworkers-project/。您的同事的项目用于make构建,但您希望依赖于它生成的.so文件之一。为此,请将以下内容添加到my_project/WORKSPACE

new_local_repository(
    name = "coworkers_project",
    path = "/path/to/coworkers-project",
    build_file = "coworker.BUILD",
)

build_file 指定要覆盖现有项目的BUILD文件,例如:

cc_library(
    name = "some-lib",
    srcs = glob(["**"]),
    visibility = ["//visibility:public"],
)

然后,您可以依赖@coworkers_project//:some-lib项目的BUILD文件。

外部包装

使用规则maven_jar (以及可选的规则maven_server)从Maven存储库下载jar并使其可用作Java依赖项。

maven_jar(name,artifact,repository,server,sha1,sha1_src)

从Maven下载jar并使其可用作Java依赖项。请注意,maven_jar名称用作存储库名称,因此受限于管理工作空间名称的规则:它不能包含破折号和点(有关确切规范,请参阅 有关工作空间名称的文档)。按照惯例,maven_jar名称应该与工件名称匹配,用下划线替换非法字符并且不使用版本。例如,artifact = "org.apache.commons:commons-lang3:3.4"应该具有 的规则name = "org_apache_commons_commons_lang3"

例子

假设当前的repostory包含一个需要依赖Guava的java_library目标。使用Maven,这个依赖项将在pom.xml文件中定义为:

<依赖性>
    <的groupId> com.google.guava </的groupId>
    <artifactId的>番石榴</ artifactId的>
    <版本> 18.0 </版本>
</依赖性>

使用Bazel,将以下行添加到WORKSPACE文件中:

maven_jar(
    name =“com_google_guava_guava”,
    artifact =“com.google.guava:guava:18.0”,
    sha1 =“cce0823396aa693798f8882e64213b1772032b09”,
    sha1_src =“ad97fe8faaf01a3d3faacecd58e8fa6e78a973ca”,
)

目标可以指定@com_google_guava_guava//jar依赖于此jar的依赖项。

参数

属性
name Name; required此规则的唯一名称。
artifact String; optional使用Maven坐标描述Maven工件 。这些描述的形式为<groupId>:<artifactId>:<version>,请参阅下面的文档以获取示例。
repository String; optional用于从中获取jar的Maven存储库的URL。这个或者server可以指定。默认为Maven Central(“central.maven.org”)。
server String; optional用于此工件的maven_server。这个或者repository可以指定。
sha1 String; optional所需jar的SHA-1哈希。如果下载的jar与此哈希不匹配,则Bazel将出错。由于远程文件可以更改,因此省略SHA-1是一种安全风险。最多省略此字段将使您的构建非密封。可以选择使开发更容易,但应在发货前进行设置。
sha1_src String; optional所需jar源文件的SHA-1哈希。

maven_server

maven_server(name,settings_file,url)

如何访问Maven存储库。

这是来自pom.xml文件的<repository>定义和settings.xml文件中的<server>定义的组合。

运用 maven_server

maven_jar规则可以maven_server在其 server字段中指定a的名称。例如,假设我们有以下WORKSPACE文件:

maven_jar(
    name =“junit”,
    artifact =“junit:junit-dep:4.10”,
    server =“my_server”,
)

maven_server(
    name =“my_server”,
    url =“http://intranet.mycorp.net”
)

这指定应使用〜/ .m2 / settings.xml中的身份验证信息(具体地说,具有id的服务器的设置)从http://intranet.mycorp.net下载junit my_server

指定默认服务器

如果maven_server使用name“默认” 创建一个,它将用于任何maven_jar未指定servernor的 repository。如果没有maven_server命名默认值,则默认将从Maven Central获取而不启用身份验证。

参数

属性
name Name; required此规则的唯一名称。
settings_file String; optionalsettings.xml文件的路径。用于测试。如果未指定,则默认使用 $M2_HOME/conf/settings.xml全局设置和 $HOME/.m2/settings.xml用户设置。
url String; optional用于访问服务器的URL。例如,Maven Central(默认情况下,不需要定义)将被指定为url = "http://central.maven.org/maven2/"
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容

  • 春日游,杏花吹满头,美好的春天里适合做各种美好的事,比如读一本温暖的书,一本关于爱情的小说,让自己治愈一下。 刚读...
    竞走的蜗牛阅读 589评论 0 1
  • 其实,写这篇文的想法在我心中已经萦绕很久了,只是最近突如其来的一些事情让自己变得好忙。也算是为了逃避这种情绪而找的...
    宁夏思溢阅读 725评论 0 0
  • 现在住在小区里,绿化都是大同小异,说起树,想起来的还是小时候老家院子里的树。 老家的院子很小,有一颗很大的臭椿树,...
    肉肉2017阅读 456评论 0 0
  • 敬爱的老师 智慧的教授亲爱的家人们 我是来自鑫山力机械的王齐港 携手前行共创辉煌,每天进步一点点距离成功变不远。 ...
    正在加载中_bfa6阅读 176评论 0 1
  • 我们有个群,都是全职妈妈或soho妈妈,成员包括前牙医,英语超八级的前外贸专业人才,搞艺术的,搞财务的,搞生意的,...
    张小妮在简书阅读 375评论 6 2