Apollo Release Build 简介(需要修改)

来源:intro_to_apollo_release_build

背景

基于 CyberRT 的 Apollo 在相当长的时间内一直没有二进制发布版本。用户需要先在 Apollo 开发容器内自行完成对整个项目的编译构建才能运行 Apollo 中的模块和工具。这 种部署上的不足,在若干情形下对用户相当不便。SVL 模拟器的开发者发现,将 Apollo 中 Docker 镜像、Docker 卷及 Bazel 缓存和构建查出加起来,足有 40 多 GB!

Release Build 的实现原理

这种部署上的不足的根本原因,在于 Bazel 缺少其他构建系统通常具备的开箱即用的「安 装」支持,如make install.

为解决这一问题,我们借鉴了Drake 项目 中的「安装」实现,,利用 Starlark 语言,实现了 适用于 Apollo 的 Bazel「安装」扩 展,支持 Apollo 中二进制程序、共享库、资源文件(配置、数据、DAG 文件等)以及文档 的安装。

单独完备的二进制程序的安装是简单的。然而,CyberRT 框架的核心概念即为将每个模块( 如感知、预测、规划)作为组件,以共享库的形式(libX_component.so)动态加载。在 目前的 Bazel 构建下,mainboard二进制程序和libX_component.so链接了成千上百各 其他共享库对象。如,对规划模块运行如下ldd命令:

ldd bazel-bin/modules/planning/libplanning_component.so

会输出如下消息:

	linux-vdso.so.1 (0x00007ffc8a77c000)
	libmodules_Splanning_Slibplanning_Ucomponent_Ulib.so => /apollo/bazel-bin/modules/planning/../../_solib_local/libmodules_Splanning_Slibplanning_Ucomponent_Ulib.so (0x00007fe8a7f9f000)
	libmodules_Splanning_Slibnavi_Uplanning.so => /apollo/bazel-bin/modules/planning/../../_solib_local/libmodules_Splanning_Slibnavi_Uplanning.so (0x00007fe8a7d81000)
	libmodules_Splanning_Slibon_Ulane_Uplanning.so => /apollo/bazel-bin/modules/planning/../../_solib_local/libmodules_Splanning_Slibon_Ulane_Uplanning.so (0x00007fe8a7b53000)
	libmodules_Splanning_Slibplanning_Ubase.so => /apollo/bazel-bin/modules/planning/../../_solib_local/libmodules_Splanning_Slibplanning_Ubase.so (0x00007fe8a7945000)
	libmodules_Splanning_Scommon_Ssmoothers_Slibsmoother.so => /apollo/bazel-bin/modules/planning/../../_solib_local/libmodules_Splanning_Scommon_Ssmoothers_Slibsmoother.so (0x00007fe8a7739000)
	libmodules_Splanning_Splanner_Slibplanner_Udispatcher.so => /apollo/bazel-bin/modules/planning/../../_solib_local/libmodules_Splanning_Splanner_Slibplanner_Udispatcher.so (0x00007fe8a752e000)
    ...

如何实现对libplanning_component.so 及其链接的所有共享库(后缀为”.so”)文件的「 安装」,成为实现install规则中最难的部分。

幸好有patchelf。利用 Bazel 中runfiles_data的概念来确定出链接的所有共享库文件 ,再利用patchelf --force-rpath --set-rpath 来修改其 RPATH 设置。

欲要更深入了解,请参考: tools/install/install.bzl

如何执行 Release Build 构建

可运行如下命令以生成二进制发布构建产物:

./apollo.sh release -c

其中,-c为可选参数,用于清理先前构建的残留。产物位于/apollo/output目录。

上述命令略等价于如下 Bazel 命令:

bazel run --config=opt --config=gpu //:install \
        -- --pre_clean /apollo/output

可输入./apollo.sh release -h 查看apollo.sh release子命令的更多用法。

通过二进制发布构建产物运行 Apollo

在二进制发布产物根目录下,运行如下命令以启动 Apollo Runtime Docker 镜像:

bash docker/scripts/runtime_start.sh

国内用户可使用-g cn选项来加速 Docker 镜像的拉取。

bash docker/scripts/runtime_start.sh -g cn

运行如下命令以进入 Apollo Runtime Docker 环境:

bash docker/scripts/runtime_into.sh

启动 Dreaview:

./scripts/bootstrap.sh

如何将install规则应用到任一自定义模块

欲实现自定义模块的安装,可参考 Apollo 代码中其他模块的示例,还是以规划模块为例 :

这是最上层的BUILD 文件的一部分:

install(
    name = "install",
    deps = [
        "//cyber:install",
        # ...
        "//modules/planning:install",
        # ...
    ],
)

这是规划模块自身的 BUILD 文件 modules/planning/BUILD:

filegroup(
    name = "planning_conf",
    srcs = glob([
        "conf/**",
    ]),
)

filegroup(
    name = "runtime_data",
    srcs = glob([
        "dag/*.dag",
        "launch/*.launch",
    ]) + [":planning_conf"],
)

install(
    name = "install",
    data = [
        ":runtime_data",
    ],
    targets = [
        ":libplanning_component.so",
    ],
    deps = [
        "//cyber:install",
    ],
)

install规则的参数列表

install规则定义在 tools/install/install.bzl:

install = rule(
    attrs = {
        "deps": attr.label_list(providers = [InstallInfo]),
        "data": attr.label_list(allow_files = True),
        "data_dest": attr.string(default = "@PACKAGE@"),
        "data_strip_prefix": attr.string_list(),
        "targets": attr.label_list(),
        "library_dest": attr.string(default = "@PACKAGE@"),
        "library_strip_prefix": attr.string_list(),
        "mangled_library_dest": attr.string(default = "lib"),
        "mangled_library_strip_prefix": attr.string_list(),
        "runtime_dest": attr.string(default = "bin"),
        "runtime_strip_prefix": attr.string_list(),
        "rename": attr.string_dict(),
        "install_script_template": attr.label(
            allow_files = True,
            executable = True,
            cfg = "target",
            default = Label("//tools/install:install.py.in"),
        ),
    },
    executable = True,
    implementation = _install_impl,
)

其具体参数列举如下

参数

含义

deps

本规则依赖的其它安装规则

data

待安装的资源文件(平台无关)列表

data_dest

资源文件目标安装地址

data_strip_prefix

需去掉的资源文件路径前缀列表

targets

待安装目标

runtime_dest

可执行目标的目标安装地址,默认为 bin 目录

runtime_strip_prefix

需去掉可执行目标路径的前缀

rename

安装时的文件重命名

局限性

当前的 Release Build 实现

  • 只支持 C++,不支持 Python。

  • 只支持 x86_64 架构,Aarch64 支持尚待完善。