1# CHRE Framework Build System
2
3[TOC]
4
5The CHRE build system is based on Make, and uses a set of Makefiles that allow
6building the CHRE framework for a variety of hardware and software architectures
7and variants (e.g. different combinations of CPU and OS/underlying system). It
8is also flexible to different build toolchains (though LLVM/Clang or GCC are
9recommended), by abstracting out key operations to a few Make or environment
10variables. While the CHRE framework source code may be integrated into another
11build system, it can be beneficial to leverage the existing build system to
12reduce maintenance burden when the CHRE framework is updated. Additionally, it
13should be possible to build nanoapps from the CHRE build system (to have
14commonality across devices), and the CHRE framework build shares configuration
15with the nanoapp build.
16
17By default, the output of the build is linked into both a static archive
18`libchre.a` and a shared library `libchre.so`, though generally only one of the
19two is used, depending on the target device details.
20
21## Design
22
23The CHRE build system was originally designed around the philosophy that a
24vanilla invocation of `make` or `make all` should build any given nanoapp for
25all targets. This allows for efficient use of the job scheduler in the Make
26build system for multi-threaded builds and also promotes a level of separation
27of concerns between targets (this is not enforced by any Make language
28construct, merely convention). In practice, the CHRE build system is rarely used
29to build multiple targets with one invocation of Make. However, the design goal
30is carried forward for the variant support and separation of concerns between
31targets.
32
33All variant-specific compiler and linker flags are held under variables that
34only apply to their specific target. This encourages developers to avoid leaking
35build details between targets. This is important because not all compiler or
36linker flags are compatible with all toolchains. For example: if a target uses a
37compiler that does not support `-Wdouble-promotion`, but this were to be
38enforced for all builds, then by definition this target would not compatible
39with the CHRE build. The goal is for the CHRE build to be as flexible as
40possible.
41
42### Build Template
43
44The CHRE build system is implemented using template meta-programming techniques.
45A build template is used to create Make rules for tasks that are common to all
46targets. This includes compiling C/C++/assembly sources, linking, nanoapp header
47generation, etc. The rationale behind this approach is to reduce boilerplate
48when adding support for a new build target.
49
50The build template is located at `build/build_template.mk`, and is documented
51with all the variables used to generate build targets, like `TARGET_CFLAGS`.
52
53## Build Targets (Variants)
54
55Compiling the framework for different devices is done by specifying the build
56target when invoking `make`. Conventionally, build targets consist of three
57parts: (software) vendor, architecture and variant and follow the
58`<vendor>_<arch>_<variant>` pattern. A “vendor” is typically the company that
59created the CHRE implementation, which may bring with it some details related to
60nanoapp compatibility, for example the Nanoapp Support Library from the same
61vendor may be required. The “arch” field refers to the Instruction Set
62Architecture (ISA) and related compiler configuration to create a binary for the
63target processor. The “variant” is primarily related to the underlying platform
64software that the CHRE framework builds on top of, such as the combination of
65operating system and other software needed to select the appropriate combination
66of code in the `platform/` folder, but can also define other attributes of the
67build, such as the target memory region for the binary. If a vendor,
68architecture, or variant consist of multiple words or components, then they
69should be separated by a hyphen and not an underscore.
70
71For example, if we assume that a fictional company named Aperture developed its
72own CHRE framework implementation, targeting a CPU family called Potato, and a
73collection of platform software called GladOS/Cake, then a suitable build target
74name would be `aperture_potato_glados-cake`.
75
76The build target may optionally have `_debug` appended, which is a common suffix
77which enables `-g` and any additional target-specific debug flags.
78
79### Creating a New Build Target
80
81#### Architecture Support
82
83The architecture-specific portion of the build deals with mainly the build
84toolchain, and its associated flags.
85
86It is easiest to check if the architecture is currently listed in `build/arch`,
87and if it is, _Hooray! You're (almost) done_. It is still worthwhile to quickly
88read through to know how the build is layered.
89
90CHRE expects the build toolchain to be exported via Makefile variables,
91specifically the compiler (`TARGET_CC`), archiver (`TARGET_AR`), and the linker
92(`TARGET_LD`). Architecture specific compiler and linker flags are passed in via
93the `TARGET_CFLAGS` and `TARGET_LDFLAGS` respectively. Additional
94architecture-specific configuration is possible - refer to existing files under
95`build/arch` and `build/build_template.mk` for details.
96
97#### Build Target Makefile
98
99Makefiles for each build target can be found at
100`build/variant/<target_name>.mk`. These files are included at the end of the
101top-level Makefile, and has the responsibility of collecting arguments for the
102build template and invoking it to instantiate build rules. This involves doing
103steps including (not an exhaustive listing):
104
105* Setting the target name and platform ID
106
107* Configuring (if needed) and including the apporpriate `build/arch/*.mk` file
108
109* Collecting sources and flags specific to the platform into
110  `TARGET_VARIANT_SRCS` and `TARGET_CFLAGS`
111
112* Including `build/build_template.mk` to instantiate the build targets - this
113  must be the last step, as the make targets cannot be modified once generated
114
115Refer to existing files under `build/variant` for examples.
116
117## Device Variants
118
119While the build target is primarily concerned with configuring the CHRE build
120for a particular chipset, the same chipset can appear in multiple device
121models/SKUs, potentially with different peripheral hardware, targeted levels of
122feature support, etc. Additionally, a device/chip vendor may wish to provide
123additional build customization outside of the Makefiles contained in the
124system/chre project. The build system supports configuration at this level via
125the device variant makefile, typically named `variant.mk`, which is injected
126into the build by setting the `CHRE_VARIANT_MK_INCLUDES` environment variable
127when invoking the top-level Makefile. Refer to the file
128`variant/android/variant.mk` for an example.
129
130## Platform Sources
131
132The file at `platform/platform.mk` lists sources and flags needed to compile the
133CHRE framework for each supported platform. These must be added to Make
134variables prefixed with the platform name (for example, `SIM_SRCS` for platform
135sources used with the simulator build target), and not `COMMON_SRCS` or other
136common variables, to avoid affecting other build targets.
137
138## Build Artifacts
139
140At the end of a successful build, the following are generated in the `out`
141directory:
142
143* `<build_target>/libchre.so` and `libchre.a`: the resulting CHRE framework
144  binary, built as a dynamic/static library
145
146* `<build_target>_objs/`: Directory with object files and other intermediates
147
148* Depending on the build target, additional intermediates (e.g. `nanopb_gen` for
149  files generated for use with NanoPB)
150