百度Apollo源码学习之Bazel编译介绍

image.png

什么是Bazel

Bazel是一个类似于Make的编译工具,是Google为其内部软件开发的特点量身定制的工具,如今Google使用它来构建内部大多数的软件。(怪不得看起来很像Android.bp语法 O(∩_∩)O)

Google认为直接用Makefile构建软件速度太慢,结果不可靠,所以构建了一个新的工具叫做Bazel,Bazel的规则层级更高。


image.png

开始使用

Bazel的编译是基于工作区(workspace)的概念。

workspace

workspace存放了所有源代码和Bazel编译输出文件的目录,也就是整个项目的根目录。

workspace需要包含的必要文件:

  • WORKSPACE文件,用于指定当前文件夹就是一个Bazel的工作区。所以WORKSPACE文件总是存在于项目的根目录下。

  • BUILD文件,用于告诉Bazel怎么构建项目的不同部分。(如果工作区中的一个目录包含BUILD文件,那么它就是一个package)

要指定一个目录为Bazel的工作区,就只要在该目录下创建一个空的WORKSPACE文件即可。

但是在百度Apollo源码我们只能看到一个WORKSPACE.in文件:
.
├── apollo_docker.sh
├── apollo.doxygen
├── apollo.sh
├── BUILD
├── CONTRIBUTING.md
├── CPPLINT.cfg
├── cyber
├── docker
├── docs
├── LICENSE
├── MANIFESTO.md
├── modules
├── README.md
├── readthedocs.yml
├── RELEASE.md
├── scripts
├── third_party
├── tools
├── ubuntu_18.04_env
└── WORKSPACE.in

根据官网的描述:

一个工作区是在文件系统包含的源文件要构建的软件,以及符号链接到包含生成输出目录的目录。每个工作空间目录都有一个名为的文本文件WORKSPACE,该文件可以为空,或者可以包含 对构建输出所需的外部依赖项的引用。

包含名为的文件 WORKSPACE的目录被视为工作空间的根。因此,Bazel会忽略工作空间中的任何目录树,这些工作树植根于包含WORKSPACE文件的子目录(因为它们形成另一个工作空间)。

Bazel还支持将WORKSPACE.bazelfile作为文件的别名WORKSPACE。如果两个文件都存在,WORKSPACE.bazel将具有优先权。

可以看出bazel并不支持名为WORKSPACE.in的文件.

继续搜索源码,在文件apollo.sh中:

image.png

这里sed的作用:

sed 可依照脚本的指令来处理、编辑文本文件。
Sed 主要用来自动编辑一个或多个文件、简化对文件的反复操作、编写转换程序等。

文件中大部分描述的就是编译过程中所需要的外部依赖.

具体语法可以参考官网.

BUILD文件

BUILD文件中包含了多个不同类型的bazel指令。

其中最重要的是编译规则(build rule),它告诉bazel怎么编译目标输出,是一个执行文件还是一个库。

BUILD文件中每一个编译规则被称为target,指向了一堆源文件和相关的依赖,一个target也可以指向其他target。
例子:

cc_binary(
    name = "hello-world",
    srcs = ["hello-world.c"],
)

其中的cc_binary,name,srcs都是相关的target.这些语法和Android.bp的语法很像,就不在多说.

看一下Apollo源码中的写法:(以location为例)

load("//tools:cpplint.bzl", "cpplint")

package(default_visibility = ["//visibility:public"])

filegroup(
    name = "localization_testdata",
    srcs = glob(["testdata/*"]),
)

cpplint()

这里声明加载tools:cpplint.bzl文件的cpplint函数:

def cpplint(data=None, extra_srcs=None):
  """For every rule in the BUILD file so far, adds a test rule that runs
  cpplint over the C++ sources listed in that rule.  Thus, BUILD file authors
  should call this function at the *end* of every C++-related BUILD file.
  By default, only the CPPLINT.cfg from the project root and the current
  directory are used.  Additional configs can be passed in as data labels.
  Sources that are not discoverable through the "sources so far" heuristic can
  be passed in as extra_srcs=[].
  """
  # Iterate over all rules.
  for rule in native.existing_rules().values():
    # Extract the list of C++ source code labels and convert to filenames.
    candidate_labels = (
      _extract_labels(rule.get("srcs", ())) +
      _extract_labels(rule.get("hdrs", ()))
    )
    source_labels = [
      label for label in candidate_labels
      if _is_source_label(label)
    ]
    source_filenames = ["$(location %s)" % x for x in source_labels]

    # Run the cpplint checker as a unit test.
    if len(source_filenames) > 0:
      _add_linter_rules(source_labels, source_filenames, rule["name"], data)

  # Lint all of the extra_srcs separately in a single rule.
  if extra_srcs:
    source_labels = extra_srcs
    source_filenames = ["$(location %s)" % x for x in source_labels]
    _add_linter_rules(source_labels, source_filenames,
                      "extra_srcs_cpplint", data)

Bazel编译看来也不是那么简单的.....

我们看一下根目录的BUILD文件:

package(
    default_visibility = ["//visibility:public"],
)

exports_files([
    "CPPLINT.cfg",
])

其中导入了一个cfg文件:

# Stop searching for additional config files.
set noparent

# Disable a warning about C++ features that were not in the original
# C++11 specification (and so might not be well-supported).
filter=-build/c++11

# Disable header_guard warning
# Consider using #pragma once instead
filter=-build/header_guard

cfg文件中设置了一些编译器的使用.

我们再看一下Bazel自己的配置文件.bazelrc

# load bazelrc from the legacy location
# as recommended in https://github.com/bazelbuild/bazel/issues/6319
import %workspace%/tools/bazel.rc

导入tools/bazel.rc文件,这个文件的内容如下:

# bazelrc file
# https://docs.bazel.build/versions/master/user-manual.html

# bazel >= 0.18 looks for %workspace%/.bazelrc (which redirects here)
# Older bazel versions look for %workspace%/tools/bazel.rc (this file)
# See https://github.com/bazelbuild/bazel/issues/6319

# +------------------------------------------------------------+
# | Startup Options                                            |
# +------------------------------------------------------------+
startup --batch_cpu_scheduling

startup --host_jvm_args=-XX:-UseParallelGC

startup --output_user_root=/apollo/.cache/bazel
# +------------------------------------------------------------+
# | Test Configurations                                        |
# +------------------------------------------------------------+

# By default prints output only from failed tests.
test --test_output=errors

# Work around the sandbox issue.
test --spawn_strategy=standalone

# Specify protobuf cc toolchain
test --proto_toolchain_for_cc="@com_google_protobuf//:cc_toolchain"

# +------------------------------------------------------------+
# | CPP Lint Tests & Unit Tests                                |
# +------------------------------------------------------------+
# By default, cpplint tests are run as part of `bazel test` alongside all of
# the other compilation and test targets.  This is a convenience shortcut to
# only do the cpplint testing and nothing else.
# Do bazel test --config=cpplint <target> to enable this configuration.
# To enable the lint test, the BUILD *must* load the cpplint.bzl by having
# 'load("//tools:cpplint.bzl", "cpplint")' at the beginning and 'cpplint()'
# at the end.
test:cpplint --test_tag_filters=cpplint
test:cpplint --build_tests_only

# Regular unit tests.
test:unit_test --test_tag_filters=-cpplint

# Coverage tests
test:coverage --test_tag_filters=-cpplint
test:coverage --copt=--coverage
test:coverage --cxxopt=--coverage
test:coverage --cxxopt=-fprofile-arcs
test:coverage --cxxopt=-ftest-coverage
test:coverage --linkopt=-coverage
test:coverage --linkopt=-lgcov
test:coverage --linkopt=-lgcc
test:coverage --linkopt=-lc

# +------------------------------------------------------------+
# | Build Configurations                                       |
# +------------------------------------------------------------+
# Do not show warnings from external dependencies.
build --output_filter="^//"

build --show_timestamps

# Work around the sandbox issue.
build --spawn_strategy=standalone

# Specify protobuf cc toolchain
build --proto_toolchain_for_cc="@com_google_protobuf//:cc_toolchain"

# build with profiling
build:cpu_prof --linkopt=-lprofiler

build --copt="-Werror=sign-compare"
build --copt="-Werror=return-type"
build --copt="-Werror=reorder"
build --copt="-Werror=unused-variable"
build --copt="-Werror=unused-but-set-variable"
build --copt="-Werror=switch"

# Strict check on type conversion.
# absl/strings/str_cat.h breaks the rule.
# build --per_file_copt=^modules/.*\.cc,-modules/tools/visualizer/.*\.cc,^cyber/.*\.cc@-Werror=conversion


# Enable C++14
build --cxxopt="-std=c++1y"
# Enable colorful output of GCC
# build --cxxopt="-fdiagnostics-color=always"

# +------------------------------------------------------------+
# | Python Configurations                                      |
# +------------------------------------------------------------+
run --python_path=/usr/bin/python3

也是配置各种编译环境,写的还是蛮复杂的.

参考

官网
Bazel简介:编译一个C++工程

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350