Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 | # Build system The OP-TEE build system is based on GNU make. It consists of a main `Makefile` in the root of the project together with `sub.mk` files in all source directories. In addition, some supporting files are used to recursively process all `sub.mk` files and generate the build rules. Name | Description :-----------------|:----------- `core/core.mk` | Included from `Makefile` to build the TEE Core `ta/ta.mk` | Included from `Makefile` to create the TA devkit `mk/compile.mk` | Create rules to make objects from source files `mk/lib.mk` | Create rules to make a libraries (.a) `mk/subdir.mk` | Process `sub.mk` files recursively `mk/config.mk` | Global configuration variable `core/arch/$(ARCH)/$(ARCH).mk` | Arch-specific compiler flags `core/arch/$(ARCH)/plat-$(PLATFORM)/conf.mk` | Platform-specific compiler flags and configuration variables `core/arch/$(ARCH)/plat-$(PLATFORM)/link.mk` | Make recipes to link the TEE Core `ta/arch/arm/link.mk` | Make recipes to link Trusted Applications `ta/mk/ta_dev_kit.mk` | Main Makefile to be included when building Trusted Applications `mk/checkconf.mk` | Utility functions to manipulate configuration variables and generate a C header file `sub.mk` | List source files and define compiler flags `make` is always invoked from the top-level directory; there is no recursive invocation of make itself. ## Choosing the build target The target architecture, platform and build directory may be selected by setting environment or make variables (**VAR=value make** or **make VAR=value**). ### ARCH (CPU architecture) **$(ARCH)** is the CPU architecture to be built. Currently, the only supported value is **arm** for 32-bit or 64-bit Armv7-A or Armv8-A. Please note that contrary to the Linux kernel, **$(ARCH)** should **not** be set to **arm64** for 64-bit builds. The **ARCH** variable does not need to be set explicitly before building either, because the proper instruction set is selected from the **$(PLATFORM)** value. For platforms that support both 32-bit and 64-bit builds, **CFG_ARM64_core=y** should be set to select 64-bit and not set (or set to **n**) to select 32-bit. Architecture-specific source code belongs to sub-directories that follow the `arch/$(ARCH)` pattern, such as: `core/arch/arm`, `lib/libmpa/arch/arm`, `lib/libutee/arch/arm` and so on. ### PLATFORM / PLATFORM_FLAVOR (hardware platform) A *platform* is a family of closely related hardware configurations. A platform *flavor* is a variant of such configurations. When used together they define the target hardware on which OP-TEE will be run. For instance **PLATFORM=stm PLATFORM_FLAVOR=b2260** will build for the ST Microelectronics 96boards/cannes2 board, while **PLATFORM=vexpress PLATFORM_FLAVOR=qemu_virt** will generate code for a para-virtualized ARM Versatile Express board running on QEMU. For convenience, the flavor may be appended to the platform name with a dash, so **make PLATFORM=stm-b2260** is a shortcut for **make PLATFORM=stm PLATFORM_FLAVOR=b2260**. Note that in both cases the value of **$(PLATFORM)** is **stm** in the makefiles. Platform-specific source code belongs to `core/arch/$(ARCH)/plat-$(PLATFORM)`, for instance: `core/arch/arm/plat-vexpress` or `core/arch/arm/plat-stm`. ### O (output directory) All output files go into a platform-specific build directory, which is by default `out/$(ARCH)-plat-$(PLATFORM)`. The output directory has basically the same structure as the source tree. For instance, assuming **ARCH=arm PLATFORM=stm**, `core/kernel/panic.c` will compile into `out/arm-plat-stm/core/kernel/panic.o`. However, some libraries are compiled several times: once or twice for user mode, and once for kernel mode. This is because they may be used by the TEE Core as well as by the Trusted Applications. As a result, the `lib` source directory gives two or three build directories: `ta_arm{32,64}-lib` and `core-lib`. The output directory also has an `export-ta_arm{32,64}` directory, which contains: - All the files needed to build Trusted Applications. - In `lib/`: **libutee.a** (the GlobalPlatform Internal API), **libutils.a** (which implements a part of the standard C library), and **libmpa.a** (which implements multiple precision arithmetic and is required by libutee.a). - In `include/`: header files for the above libraries - In `mk/`: **ta_dev_kit.mk**, which is a Make include file with suitable rules to build a TA, and its dependencies - `scripts/sign.py`: a Python script used by ta_dev_kit.mk to sign TAs. - In `src`: **user_ta_header.c**: source file to add a suitable header to the Trusted Application (as expected by the loader code in the TEE Core) - Some files needed to build host applications (using the Client API), under `export-ta_arm{32,64}/host_include`. Finally, the build directory contains the auto-generated configuration file for the TEE Core: `$(O)/include/generated/conf.h` (see below). ### CROSS_COMPILE* (cross-compiler selection) **$(CROSS_COMPILE)** is the prefix used to invoke the (32-bit) cross-compiler toolchain. The default value is **arm-linux-gnueabihf-**. This is the variable you want to change in case you want to use [ccache](https://ccache.samba.org/) to speed you recompilations: ```shell $ make CROSS_COMPILE="ccache arm-linux-gnueabihf-" ``` If the build includes a mix of 32-bit and 64-bit code, for instance if you set `CFG_ARM64_core=y` to build a 64-bit secure kernel, then two different toolchains are used, that are controlled by **$(CROSS_COMPILE32)** and **$(CROSS_COMPILE64)**. The default value of **$(CROSS_COMPILE32)** is the value of CROSS_COMPILE, which defaults to **arm-linux-gnueabihf-** as mentioned above. The default value of **$(CROSS_COMPILE64)** is **aarch64-linux-gnu-**. Examples: ```shell # FOr this example, select HiKey which supports both 32- and 64-bit builds $ export PLATFORM=hikey # 1. Build everything 32-bit $ make # 2. Same as (1.) but override the toolchain $ make CROSS_COMPILE="ccache arm-linux-gnueabihf-" # 3. Same as (2.) $ make CROSS_COMPILE32="ccache arm-linux-gnueabihf-" # 4. Select 64-bit secure 'core' (and therefore both 32- and 64-bit # Trusted Application libraries) $ make CFG_ARM64_core=y # 5. Same as (4.) but override the toolchains $ make CFG_ARM64_core=y \ CROSS_COMPILE32="ccache arm-linux-gnueabihf-" \ CROSS_COMPILE64="ccache aarch64-linux-gnu-" ``` ## Platform-specific configuration and flags The following variables are defined in `core/arch/$(ARCH)/$(ARCH).mk`: - **$(core-platform-aflags)**, **$(core-platform-cflags)** and **$(core-platform-cppflags)** are added to the assembler / C compiler / preprocessor flags for all source files compiled for TEE Core including the kernel versions of **libmpa.a** and **libutils.a**. - **$(ta_arm{32,64}-platform-aflags)**, **$(ta_arm{32,64}-platform-cflags)** and **$(ta_arm{32,64}-platform-cppflags)** are added to the assembler / C compiler / preprocessor flags when building the user-mode libraries (**libutee.a**, **libutils.a**, **libmpa.a**) or Trusted Applications. The following variables are defined in `core/arch/$(ARCH)/plat-$(PLATFORM)/conf.mk`: - If **$(arm{32,64}-platform-cflags)**, **$(arm{32,64}-platform-aflags)** and **$(arm{32,64}-platform-cppflags)** are defined their content will be added to **$(\*-platform-\*flags)** when they are are initialized in `core/arch/$(ARCH)/$(ARCH).mk` as described above. - **$(core-platform-subdirs)** is the list of the subdirectories that are added to the TEE Core. ## Platform-specific link recipes for the TEE Core The file `core/arch/$(ARCH)/plat-$(PLATFORM)/link.mk` contains the rules to link the TEE Core and perform any related tasks, such as running **objdump** to produce a dump file. **link.mk** adds files to the **all:** target. ## Source files Each directory that contains source files has a file called `sub.mk`. This makefile defines the source files that should be included in the build, as well as any subdirectories that should be processed, too. For example: ```Makefile # core/arch/arm/sm/sub.mk srcs-y += sm_asm.S srcs-y += sm.c ``` ```Makefile # core/sub.mk subdirs-y += kernel subdirs-y += mm subdirs-y += tee subdirs-y += drivers ``` The `-y` suffix is meant to facilitate conditional compilation. See *Configuration* below. `srcs-y` and `subdirs-y` are often not used together in the same `sub.mk`, because source files are usually alone in leaf directories. But this is not a hard rule. In addition to source files, `sub.mk` may define compiler flags, include directories and/or configuration variables as explained below. ## Compiler flags Default compiler flags are defined in `mk/compile.mk`. Note that platform-specific flags must not appear in this file which is common to all platforms. To add flags for a given source file, you may use the following variables in `sub.mk`: * `cflags-<filename>-y` for C files (*.c) * `aflags-<filename>-y` for assembler files (*.S) * `cppflags-<filename>-y` for both C and assembler For instance: ```Makefile # core/lib/libtomcrypt/src/pk/dh/sub.mk srcs-y += dh.c cflags-dh.c-y := -Wno-unused-variable ``` Compiler flags may also be removed, as follows: ```Makefile # lib/libutils/isoc/newlib/sub.mk srcs-y += memmove.c cflags-remove-memmove.c-y += -Wcast-align ``` Some variables apply to libraries only (that is, when using `mk/lib.mk`) and affect all the source files that belong to the library: `cppflags-lib-y` and `cflags-lib-y`. ## Include directories Include directories may be added to `global-incdirs-y`, in which case they will be accessible from all the source files and will be copied to `export-ta_arm{32,64}/include` and `export-ta_arm{32,64}/host_include`. When `sub.mk` is used to build a library, `incdirs-lib-y` may receive additional directories that will be used for that library only. ## Configuration variables Some features may be enabled, disabled or otherwise controlled at compile time through makefile variables. Default values are normally provided in makefiles with the `?=` operator so that their value may be easily overridden by environment variables. For instance: ```Makefile PLATFORM ?= stm PLATFORM_FLAVOR ?= default ``` Some global configuration variables are defined in `mk/config.mk`, but others may be defined in `sub.mk` when then pertain to a specific library for instance. Variables with the `CFG_` prefix are treated in a special way: their value is automatically reflected in the generated header file `$(out-dir)/include/generated/conf.h`, after all the included makefiles have been processed. `conf.h` is automatically included by the preprocessor when a source file is built. Depending on their value, variables may be considered either boolean or non-boolean, which affects how they are translated into `conf.h`. ### Boolean configuration variables When a configuration variable controls the presence or absence of a feature, **y** means *enabled*, while **n**, an empty value or an undefined variable means *disabled*. For instance, the following commands are equivalent and would disable feature *CFG_CRYPTO_GCM*: ```Shell $ make CFG_CRYPTO_GCM=n ``` ```Shell $ make CFG_CRYPTO_GCM= ``` ```Shell $ CFG_CRYPTO_GCM=n make ``` ```Shell $ export CFG_CRYPTO_GCM=n $ make ``` Configuration variables may then be used directly in `sub.mk` to trigger conditional compilation: ```Makefile # core/lib/libtomcrypt/src/encauth/sub.mk subdirs-$(CFG_CRYPTO_CCM) += ccm subdirs-$(CFG_CRYPTO_GCM) += gcm ``` When a configuration variable is *enabled* (**y**), `<generated/conf.h>` contains a macro with the same name as the variable and the value **1**. If it is *disabled*, however, no macro definition is output. This allows the C code to use constructs like: ```C /* core/lib/libtomcrypt/src/tee_ltc_provider.c */ /* ... */ #if defined(CFG_CRYPTO_GCM) struct tee_gcm_state { gcm_state ctx; /* the gcm state as defined by LTC */ size_t tag_len; /* tag length */ }; #endif ``` ### Non-boolean configuration variables Configuration variables that are not recognized as booleans are simply output unchanged into `<generated/conf.h>`. For instance: ```Makefile $ make CFG_TEE_CORE_LOG_LEVEL=4 ``` ```C /* out/arm-plat-vexpress/include/generated/conf.h */ #define CFG_TEE_CORE_LOG_LEVEL 4 /* '4' */ ``` ### Configuration dependencies Some combinations of configuration variables may not be valid. This should be dealt with by custom checks in makefiles. `mk/checkconf.h` provides functions to help detect and deal with such situations. |