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