编写 bazelrc 配置文件

Bazel 接受许多选项。有些选项经常变化(例如 --subcommands),而另一些选项在多个 build 中保持不变(例如 --package_path)。为避免为每个 build(和其他命令)指定这些未更改的选项,您可以在名为 .bazelrc 的配置文件中指定选项。

.bazelrc 文件位于何处?

Bazel 会按照以下显示的顺序在以下位置查找可选配置文件。系统会按此顺序解读选项,因此,如果发生冲突,后续文件中的选项可以替换之前文件中的值。所有用于控制加载哪些文件的选项都是启动选项,这意味着它们必须出现在 bazel 之后和命令(buildtest 等)之前。

  1. 系统 RC 文件,除非存在 --nosystem_rc

    路径:

    • 在 Linux/macOS/Unix 上:/etc/bazel.bazelrc
    • 在 Windows 上:%ProgramData%\bazel.bazelrc

    如果此文件不存在,则不会出现错误。

    如果需要其他系统指定的位置,您必须构建自定义 Bazel 二进制文件,并替换 BAZEL_SYSTEM_BAZELRC_PATH 值(位于 //src/main/cpp:option_processor中)。 系统指定的位置可能包含环境变量引用,例如 Unix 上的 ${VAR_NAME} 或 Windows 上的 %VAR_NAME%

  2. 工作区 RC 文件,除非存在 --noworkspace_rc

    路径:工作区目录中的 .bazelrc(位于主 MODULE.bazel 文件旁边)。

    如果此文件不存在,则不会出现错误。

  3. 主目录 RC 文件,除非存在 --nohome_rc

    路径:

    • 在 Linux/macOS/Unix 上:$HOME/.bazelrc
    • 在 Windows 上:如果存在,则为 %USERPROFILE%\.bazelrc,否则为 %HOME%/.bazelrc

    如果此文件不存在,则不会出现错误。

  4. 用户指定的 RC 文件,如果使用 --bazelrc=file 指定

    此标志是可选的,但也可以多次指定。

    /dev/null 表示所有后续 --bazelrc 都将被忽略,这 对于停用对用户 RC 文件的搜索非常有用,例如在发布 build 中。

    例如:

    --bazelrc=x.rc --bazelrc=y.rc --bazelrc=/dev/null --bazelrc=z.rc
    
    • 系统会读取 x.rcy.rc
    • 由于之前的 /dev/null,系统会忽略 z.rc

除了此可选配置文件之外,Bazel 还会查找全局 RC 文件。如需了解详情,请参阅全局 bazelrc 部分

.bazelrc 语法和语义

与所有 UNIX“rc”文件一样,.bazelrc 文件是一个基于行的语法的文本文件。系统会忽略空行和以 # 开头的行(注释)。每行都包含一系列字词,这些字词会按照与 Bourne shell 相同的规则进行分词。

导入

importtry-importtry-import-if-bazel-version 开头的行是特殊的:使用这些行加载其他“rc”文件。如需指定相对于工作区根目录的路径,请写入 import %workspace%/path/to/bazelrc

各种 import 语句之间的区别如下:

  • import - 如果 imported 的文件缺失(或无法 读取),Bazel 将失败
  • try-import - 系统将尝试导入文件,但与 import不同的是,如果文件缺失(或无法读取),Bazel 不会失败。
  • try-import-if-bazel-version - 与 try-import 类似,但在尝试执行导入之前,系统会检查当前 Bazel 版本的其他条件。如需了解语法,请参阅下文。

如果项目需要在多个 Bazel 版本下运行,或者在从一个 Bazel 版本过渡到另一个 Bazel 版本期间运行,则有条件的 Bazel 版本导入可能很有用。由于每个版本中可能会弃用、移除或引入不同的标志,因此不同的 Bazel 版本可能需要不同的标志。如需查看您拥有的 Bazel 版本,请运行 bazel --version。系统支持以下条件检查,并且需要有效的语义版本:

# Strictly greater than: used for post-release targeting
try-import-if-bazel-version >7.0.0 %workspace%/configs/post_v7.rc

# Greater than or equal to: commonly used for feature introduction
try-import-if-bazel-version >=6.0.0 %workspace%/configs/features.rc

# Strictly less than: used for deprecated flags removed in newer versions
try-import-if-bazel-version <7.0.0 %workspace%/configs/legacy.rc

# Less than or equal to: caps configuration to a specific version
try-import-if-bazel-version <=5.4.0 %workspace%/configs/v5_fixes.rc

# Exact match: hotfix for a specific broken release
try-import-if-bazel-version ==6.3.2 %workspace%/configs/hotfix_6.3.2.rc

# Not equal to: excludes broken version from standard config
try-import-if-bazel-version !=7.0.1 %workspace%/configs/standard.rc

额外的波浪号运算符可提供补丁程序、次要版本和主要版本更改的范围:

# Equivalent to >=1.2.3 <1.3.0
try-import-if-bazel-version ~1.2.3 %workspace%/configs/1.2.3_flags.rc

# Equivalent to >=1.2.0 <1.3.0 (Same as 1.2.x)
try-import-if-bazel-version ~1.2 %workspace%/configs/1.2_flags.rc

# Equivalent to >=1.0.0 <2.0.0 (Same as 1.x)
try-import-if-bazel-version ~1 %workspace%/configs/v1_flags.rc

导入优先级:

  • 导入文件中的选项优先于在 import 语句之前指定的选项。
  • 在 import 语句之后指定的选项优先于导入文件中的选项。
  • 稍后导入的文件中的选项优先于之前导入的文件。

选项默认值

bazelrc 的大多数行都定义了默认选项值。每行的第一个字词指定了何时应用这些默认值:

  • startup:启动选项,位于命令之前,并在 bazel help startup_options 中进行了说明。
  • common:应应用于所有支持它们的 Bazel 命令的选项。如果某个命令不支持以这种方式指定的选项,只要该选项对某些其他 Bazel 命令有效,系统就会忽略该选项。 请注意,这仅适用于选项名称:如果当前命令接受具有指定名称的选项,但不接受指定的值,则该命令将失败。
  • always:适用于所有 Bazel 命令的选项。如果某个命令不支持以这种方式指定的选项,则该命令将失败。
  • command:Bazel 命令,例如 buildquery,选项适用于这些命令 。这些选项也适用于从指定命令继承的所有命令。(例如,test 继承自 build。)

这些行中的每一行都可以使用多次,并且第一个字词后面的实参会合并,就像它们出现在同一行中一样。(CVS 的用户会发现此语法与 .cvsrc 的语法类似,CVS 是另一个具有“瑞士军刀”命令行界面的工具。)例如,以下行:

build --test_tmpdir=/tmp/foo --verbose_failures
build --test_tmpdir=/tmp/bar

会合并为:

build --test_tmpdir=/tmp/foo --verbose_failures --test_tmpdir=/tmp/bar

因此,有效的标志是 --verbose_failures--test_tmpdir=/tmp/bar

选项优先级:

  • 命令行中的选项始终优先于 RC 文件中的选项。 例如,如果 RC 文件显示 build -c opt,但命令行 flag 为 -c dbg,则命令行 flag 优先。
  • 在 RC 文件中,优先级由具体性决定:针对更具体命令的行优先于针对不太具体命令的行。

    具体性由继承定义。某些命令从其他命令继承选项,这使得继承命令比基本命令更具体。例如,test 继承自 build 命令,因此所有 bazel build 标志对 bazel test 都有效,并且所有 build 行也适用于 bazel test,除非同一选项存在 test 行。如果 RC 文件显示:

    test -c dbg --test_env=PATH
    build -c opt --verbose_failures

    那么 bazel build //foo 将使用 -c opt --verbose_failures,而 bazel test //foo 将使用 --verbose_failures -c dbg --test_env=PATH

    继承(具体性)图如下所示:

    • 每个命令都继承自 common
    • 以下命令继承自 build(并且比 build 更具体):testruncleanmobile-installinfoprint_actionconfigcqueryaquery
    • coveragefetchvendor 继承自 test
  • 如果两行指定了同一命令的选项,并且具体性相同,则系统会按照它们在文件中出现的顺序进行解析。

  • 由于此优先级规则与文件顺序不匹配,因此,如果您遵循 RC 文件中的优先级顺序,将有助于提高可读性:从顶部的 common 选项开始,以文件底部的最具体命令结束。这样,读取选项的顺序与应用选项的顺序相同,这更加直观。

RC 文件行的实参可能包含不是选项的实参,例如 build 目标的名称等。与同一文件中指定的选项一样,这些实参的优先级低于命令行中的同级实参,并且始终会添加到非选项实参的显式列表之前。

--config

除了设置选项默认值之外,RC 文件还可用于对选项进行分组,并为常见分组提供简写。为此,请向命令添加 :name 后缀。默认情况下,系统会忽略这些选项,但如果命令行或 .bazelrc 文件中存在 --config=name 选项,系统会以递归方式(即使在另一个配置定义中)包含这些选项。系统只会针对适用的命令展开 command:name 指定的选项,并按照上述优先级顺序进行展开。

--config=foo 会“就地”展开为 RC 文件中定义的选项,以便为配置指定的选项具有与 --config=foo 选项 相同的优先级。

此语法不适用于使用 startup 设置 启动选项。在 .bazelrc 中设置 startup:config-name --some_startup_option 将被忽略。

--enable_platform_specific_config

可以使用 --enable_platform_specific_config 自动启用 .bazelrc 中的平台特定配置。例如,如果主机操作系统是 Linux 并且 运行了 build 命令,则系统会自动启用 build:linux 配置。支持的操作系统标识符包括 linuxmacoswindowsfreebsdopenbsd。启用此标志等同于在 Linux 上使用 --config=linux,在 Windows 上使用 --config=windows,依此类推。

请参阅 --enable_platform_specific_config

示例

以下是一个示例 ~/.bazelrc 文件:

# Bob's Bazel option defaults

startup --host_jvm_args=-XX:-UseParallelGC
import /home/bobs_project/bazelrc
build --show_timestamps --keep_going --jobs 600
build --color=yes
query --keep_going

# Definition of --config=memcheck
build:memcheck --strip=never --test_timeout=3600

控制 Bazel 行为的其他文件

.bazelignore

您可以指定工作区中要 Bazel 忽略的目录,例如使用其他 build 系统的相关项目。在工作区的根目录中放置一个名为 .bazelignore 的文件,并添加要 Bazel 忽略的目录,每行一个。条目相对于工作区根目录。

全局 bazelrc 文件

Bazel 会按以下顺序读取可选 bazelrc 文件:

  1. 系统 RC 文件,位于 etc/bazel.bazelrc
  2. 工作区 RC 文件,位于 $workspace/tools/bazel.rc
  3. 主目录 RC 文件,位于 $HOME/.bazelrc

此处列出的每个 bazelrc 文件都有一个对应的标志,可用于停用它们(例如 --nosystem_rc--noworkspace_rc--nohome_rc)。您还可以传递 --ignore_all_rc_files 启动选项,使 Bazel 忽略所有 bazelrc。