Skip to content

Commit

Permalink
Docs: Introduction to Apollo Release Build added
Browse files Browse the repository at this point in the history
  • Loading branch information
storypku committed Mar 23, 2021
1 parent 4b01eee commit dc8dd7d
Show file tree
Hide file tree
Showing 2 changed files with 211 additions and 0 deletions.
2 changes: 2 additions & 0 deletions docs/technical_tutorial/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ Refer these documents as a guide to all other relevant documents for the version
- [Apollo 2.5](apollo_2.5_technical_tutorial.md)
- [Navigation Mode in Apollo 2.5 中文版](navigation_mode_tutorial_cn.md)
- [Apollo Best Coding Practice](apollo_best_coding_practice.md)
- [Introduction to Apollo Release Build](intro_to_apollo_release_build.md)

209 changes: 209 additions & 0 deletions docs/technical_tutorial/intro_to_apollo_release_build.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
# Introduction to Apollo Release Build

## Background

For quite some time, binary distribution was unavailable for CyberRT-based
Apollo. Users have to build the whole project themselves inside Apollo Dev
container before they can run various modules and tools. This incapability of
deployment causes trouble in certain situations. For example, people from
Lgsvl-Simulator find that the total size of all Docker images, volumes and Bazel
caches and build artifacts sums up to 40+ GB, which was rather inconvenient for
their use case.

## Principle of Release Build Implementation

The root cause of this incapability was Bazel's lack of out-of-box installation
support similar to those provided in other build systems (e.g., `make install`).

To resolve this issue, we borrowed ideas from the
[Drake](https://github.com/RobotLocomotion/drake) project, and implemented the
`install` extension in the Starlark language, which can be used to install
binaries, shared libraries, resource files (config, data, launch files, dags,
etc) and documents for the Apollo project.

Installation for standalone binaries was rather straightforward. As you may
already know, the core concept of the CyberRT framework was to load each module
(e.g, Perception, Prediction, Planning, etc) dynamically as a component in the
form of `libX_component.so`. Both the `mainboard` binary program and
`libX_component.so` links thousands of other shared libraries themselves. For
example, running `ldd` on the Planning module with the following command

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

will show the following output:

```text
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)
...
```

How to _install_ `libplanning_component.so` with all the shared objects (i.e.,
"\*.so" files) it links becomes the hardest issue to solve to implement the
`install` rule.

`patchelf` comes to rescue. All the shared objects can be retrieved from
`runfiles_data`, while `patchelf --force-rpath --set-rpath` can be used to
change RPATH settings.

Refer to [tools/install/install.bzl](../../tools/install/install.bzl) for a
thorough understanding.

## How to Run Release Build for Apollo

To generate binary outputs for Apollo, simply run:

```bash
./apollo.sh release -c
```

where `-c` is an optional argument used for pre-cleaning. The output was located
at `/apollo/output` inside Apollo Dev container.

The command above is roughly equivalent to the following:

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

Please type `./apollo.sh release -h` for more usage of `apollo.sh release`.

## How to Run Apollo with Release Build Output

In order to run Apollo Runtime Docker with release build output, type the
following command from the root of release build output directory outside Apollo
Dev Docker:

```bash
bash docker/scripts/runtime_start.sh
```

For users in China, use `-g cn` to speed up pulling of Docker images/volumes.

```bash
bash docker/scripts/runtime_start.sh -g cn
```

Log into Apollo Runtime Docker by running:

```bash
bash docker/scripts/runtime_into.sh
```

Start Dreamview by running:

```bash
./scripts/bootstrap.sh
```

from inside Apollo Runtime container.

## How to Use `install` Rule to Install a Custom Module

To _install_ a custom module, you can follow examples for installing other
modules from the Apollo repository.

Take the Planning module as an example.

This is part of the topmost [BUILD](../../BUILD) file:

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

This is a snippet from [modules/planning/BUILD](../../modules/planning/BUILD):

```python
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",
],
)
```

## Arguments of the `install` Bazel Rule

From [tools/install/install.bzl](../../tools/install/install.bzl):

```python
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,
)
```

The detailed attributes of the `install` rule was listed below:

| Argument | Notes |
| -------------------- | ---------------------------------------------------------------------------------------- |
| deps | List of other install rules that this rule should include. |
| data | List of (platform-independent) resource files to install |
| data_dest | Destination for resource files (default = "@PACKAGE@") |
| data_strip_prefix | List of prefixes to remove from resource paths |
| targets | List of targets to install |
| runtime_dest | Destination for executable targets (default = "bin") |
| runtime_strip_prefix | List of prefixes to remove from executable paths |
| rename | Mapping of install paths to alternate file names, used to rename files upon installation |

## Limitations of Current Release Build Implementation

- C++ support only. Installation for Python was not ready.
- x86_64 support only. ARM64 support was not ready at the moment.

0 comments on commit dc8dd7d

Please sign in to comment.