1# CMake Introduction
2
3The SCP-Firmware project currently uses the CMake build system.
4Please follow the instructions below to build the SCP firmware
5using CMake.
6
7## Prerequisites
8
9Please follow the prerequisites from [user_guide.md](user_guide.md)
10
11## Building
12Make sure you have updated submodule in the repo
13```sh
14$ git submodule update --init
15```
16
17Unlike the existing build system, CMake only allows the building of
18one firmware target at a time e.g
19
20```sh
21cmake -B /tmp/build  -DSCP_FIRMWARE_SOURCE_DIR:PATH=juno/scp_romfw
22```
23
24This will configure cmake to build firmware for Juno platform scp_romfw firmware.
25where
26- `/tmp/build`: is the directory where the build will be generated.
27- `juno/scp_romfw`: is the firmware to build for the platform.
28
29```sh
30cmake --build /tmp/build    # will build the configured cmake
31```
32
33In some case like running SCP-firmware with OP-TEE, the firmware is a
34static library that is then linked to a larger binary. Instead of providing all
35the static libraries that have been built by cmake and which can change with the
36configuration of your product, you can gather all of them in a single one.
37
38> ```sh
39> cmake --build /tmp/build --target ${SCP_FIRMWARE_TARGET}-all
40> will build the configured cmake and append all static librairies in
41> lib${SCP_FIRMWARE_TARGET}-all.a
42> ```
43
44For ease of building the product, the make wrapper can be used with the below
45command to build all firmwares for a product
46
47```sh
48$ make -f Makefile.cmake PRODUCT=juno
49```
50
51By default all the binaries will be located at `./build/<platform>` directory.
52e.g. in above case it will be under `./build/juno directory`.
53
54The above command accepts a number of options. Execute the command below to get
55the available options.
56
57```sh
58$ make -f Makefile.cmake help
59```
60
61## Build and execute framework and module unit tests
62See below to build and execute tests
63
64```sh
65$ make -f Makefile.cmake test
66```
67
68Alternatively, execute just framework or module tests
69
70```sh
71$ make -f Makefile.cmake fwk_test
72```
73
74```sh
75$ make -f Makefile.cmake mod_test
76```
77
78See unit_test/user_guide.md for more information on configuring
79module tests.
80
81> **LIMITATIONS** \
82> ArmClang toolchain is supported but not all platforms are working.
83
84> **NOTE**: Read below documentation for advanced use of development environment
85> and CMake build options.
86
87## Build configuration options
88CMake provides a feature to configure certain setting to generate required
89build. SCP firmware uses this feature to configure various build options
90for a firmware target(e.g. `scp_ramfw` or `scp_romfw`). At present the following
91few common options can be configured.
92
93- `SCP_ENABLE_NOTIFICATIONS`: Enable/disable notifications within SCP firmware.
94
95- `SCP_ENABLE_SCMI_NOTIFICATIONS`: Enable/disable SCMI notifications.
96
97- `SCP_ENABLE_RESOURCE_PERMISSIONS`: Enable/disable resource permissions
98  settings.
99
100- `SCP_ENABLE_PLUGIN_HANDLER`: Enable the Performance Plugin handler extension.
101
102- `SCP_TARGET_EXCLUDE_BASE_PROTOCOL`: Exclude Base Protocol functionality from
103  the SCMI Module.
104
105- `SCP_ENABLE_SUB_SYSTEM_MODE`: Enable the execution as a sub-system.
106
107- `SCP_ENABLE_SCMI_SENSOR_EVENTS`: Enable/disable SCMI sensor events.
108
109- `SCP_ENABLE_SCMI_SENSOR_V2`: Enable/disable SCMI sensor V2 protocol support.
110
111- `SCP_ENABLE_SENSOR_TIMESTAMP`: Enable/disable sensor timestamp support.
112
113- `SCP_ENABLE_SENSOR_MULTI_AXIS`: Enable/disable sensor multi axis support.
114
115- `SCP_ENABLE_SCMI_RESET`: Enable/disable SCMI reset.
116
117- `SCP_ENABLE_CLOCK_TREE_MGMT`: Enable/disable clock tree management support.
118
119- `SCP_ENABLE_FAST_CHANNELS`: Enable/disable Fast Channels support. This
120  option should be enabled/disabled by the use of a platform specific setting
121  like `SCP_ENABLE_SCMI_PERF_FAST_CHANNELS`.
122
123It can also be used to provide some platform specific settings.
124e.g. For ARM Juno platform. See below
125
126- `SCP_ENABLE_SCMI_PERF_FAST_CHANNELS`: Enable/disable Juno SCMI-perf
127  Fast channels.
128
129- `SCP_ENABLE_DEBUG_UNIT`: Enable/disable Juno debug unit.
130
131- `SCP_ENABLE_STATISTICS`: Enable/disable Juno statistics.
132
133## Modifying build options
134There are a number of ways to configure a specific option.
135
136- Using cmake command line option
137
138> ```sh
139> cmake -B /tmp/build  -DSCP_FIRMWARE_SOURCE_DIR:PATH=juno/scp_ramfw\
140> -DSCP_ENABLE_DEBUG_UNIT=TRUE
141> ```
142> It will configure cmake to build firmware for Juno platform `scp_ramfw`
143> firmware. with debug unit enabled
144> where:
145> - `/tmp/build`:  is the directory where the build will be generated.
146> - `juno/scp_romfw`: is the firmware to build for the platform.
147>
148> ```sh
149> $ cmake --build /tmp/build    # will build the configured cmake
150> ```
151
152- Using ccmake or cmake-gui
153
154> ```sh
155> $ ccmake -B /tmp/build  -DSCP_FIRMWARE_SOURCE_DIR:PATH=juno/scp_ramfw
156> ```
157> It will configure cmake to build firmware for Juno platform scp_ramfw
158> firmware with debug unit enabled
159> where:
160> * `/tmp/build`:  is the directory where the build will be generated.
161> * `juno/scp_romfw`: is the firmware to build for the platform.
162>
163> It opens a curses based UI. If `/tmp/build` is not present i.e. if this
164> is the first time the configuration is generated, select `'c'` (Configure)
165> and then modify the options as desired. After selecting the options
166> select `'c'` (Configure) and `'g'`(Generate) to generate the build system.
167>
168> ```sh
169> $ cmake --build /tmp/build    # will build the configured cmake
170> ```
171>
172> Build options can subsequently tuned using below command
173> ```sh
174> $ ccmake /tmp/build
175> ```
176
177- Using default value set for a specific option in `Firmware.cmake`.
178>
179> Every SCP firmware specific option(e.g. `SCP_ENABLE_XXX`) has a corresponding
180> `_INIT` variable in respective `Firmware.cmake` and can be modified before
181> build generation
182>
183> e.g.
184> For Arm Juno platform `scp_ramfw/Firmware.cmake` following value can be edited
185> manually before build configuration is generated.
186>
187> ```cmake
188> set(SCP_ENABLE_DEBUG_UNIT_INIT FALSE)
189> ```
190>
191> **NOTE** In this method, if value needs to be re-modified then old build
192> folder must be manually deleted. Subsequent re-run without deleting old
193> configuration will not update the earlier configured value, See CACHE
194> variables in CMake documentation.
195
196**NOTE**: Enabling/disabling option may result in inclusion or exclusion of
197a particular module in the firmware.
198e.g. See module/resource_perms/Module.cmake and note following
199```cmake
200if(SCP_ENABLE_RESOURCE_PERMISSIONS)
201   list(APPEND SCP_MODULES "resource-perms")
202endif()
203```
204The above code will include `resource-perms` module in the firmware only if
205`SCP_ENABLE_RESOURCE_PERMISSIONS` is enabled. This also means, define
206`BUILD_HAS_MOD_RESOURCE_PERMS` will available only if this option is enabled.
207
208# Development Environments {#development-environments}
209
210Along with core CMake build system, also provided is a option to generate
211a build environment, please see details below.
212
213## Vagrant (recommended) {#vagrant}
214
215> **NOTE**: If you're unfamiliar with Vagrant, we recommend you read the brief
216> introduction found [here][Vagrant].
217
218Vagrant is an open-source software product for building and maintaining portable
219virtual software development environments. The `SCP-firmware `project offers a
220Vagrant configuration based on the [Docker] provider, and so you will need to
221have them both installed:
222
223- Install [Docker](https://docs.docker.com/get-docker)
224- Install [Vagrant](https://www.vagrantup.com/downloads)
225
226> **NOTE**: Vagrant and Docker are generally both available through system
227> package managers:
228>
229> - Ubuntu and other Debian-based Linux distributions:
230>   https://docs.docker.com/engine/install/ubuntu/
231>
232> ```sh
233> $ sudo apt install vagrant
234> ```
235>
236
237When using Vagrant, there are no additional prerequisites for the host system,
238as all build and quality assurance tools are packaged with the container.
239
240[Docker]: https://www.docker.com/why-docker
241[Vagrant]: https://www.vagrantup.com/intro
242
243### Interactive Development {#interactive-vagrant-development}
244
245You can bring up an interactive development environment by simply running the
246following:
247
248```sh
249$ vagrant up
250Bringing machine 'default' up with 'docker' provider...
251==> default: Machine already provisioned. Run `vagrant provision` or use the
252`--provision`
253==> default: flag to force provisioning. Provisioners marked to run always will
254still run.
255```
256
257> **NOTE**: The Docker container image will be built the first time you run
258> this, which can take a while. Be patient - it won't happen again unless you
259> modify the Dockerfile.
260
261The project working directory will be mounted within the container as
262`/scp-firmware`.
263
264You can then connect to the embedded SSH server as the non-root user `user`
265with:
266
267```sh
268$ vagrant ssh
269```
270
271You will have access to `sudo` from within the container, and Vagrant will
272persist any changes to the container even if you halt it. If you need to rebuild
273the container for any reason, like if you have made changes to the Dockerfile,
274you can rebuild the development environment with:
275
276```sh
277$ vagrant reload
278```
279
280Do note, however, that reloading the development environment will rebuild it
281from scratch.
282
283### Running Commands {#running-vagrant-commands}
284
285If you simply wish to invoke a command from within the container, you may also
286use Vagrant's [`docker-run`] command, e.g.:
287
288```sh
289$ vagrant docker-run -- pwd
290==> default: Image is already built from the Dockerfile. `vagrant reload` to
291rebuild.
292==> default: Creating the container...
293    default:   Name: git_default_1601546529_1601546529
294    default:  Image: b7c4cbfc3534
295    default:    Cmd: pwd
296    default: Volume: /tmp/tmp.cGFeybHqFb:/vagrant
297    default:
298    default: Container is starting. Output will stream in below...
299    default:
300    default: /vagrant
301```
302
303[`docker-run`]: https://www.vagrantup.com/docs/providers/docker/commands#docker-run
304
305## Visual Studio Code Development Containers {#vscode-containers}
306
307If you use Visual Studio Code, you may also work directly within a
308pre-configured development container. See the [official tutorial] if you are
309unfamiliar with the process of developing within containers.
310
311[official tutorial]: https://code.visualstudio.com/docs/remote/containers-tutorial
312
313## Docker {#docker}
314
315> **NOTE**: Using Docker in SCP build might show some errors.
316
317The SCP-firmware project includes a [`Dockerfile`] which can be used to set up
318an environment containing all of the necessary prerequisites required to build
319and test a firmware.
320
321This Dockerfile has four variants:
322
323- `ci`: A continuous integration variant, which provides the tooling required
324  for automating builds and quality assurance processes.
325- `jenkins`: A Jenkins-specific continuous integration variant, which includes
326  additional steps required to use it from Jenkins.
327- `dev`: A development variant, which includes additional tools for developers
328  accessing the container directly.
329- `vagrant`: A Vagrant variant, which includes an SSH server and a workspace
330  more familiar to Vagrant users.
331
332We *highly* recommend using [Vagrant](#vagrant) to manage your development
333environment, but in case you must do so directly through Docker, you can build
334the development container with the following:
335
336```sh
337$ docker build -t scp-firmware --target=dev "./docker"
338```
339
340You can then begin an interactive login shell with:
341
342```sh
343$ docker run -v $(pwd):/scp-firmware -v ~/.gitconfig:/home/user/.gitconfig \
344    -e TERM -e ARMLMD_LICENSE_FILE -it scp-firmware /bin/bash
345```
346
347Alternatively, you can run commands directly from within the container with:
348
349```sh
350$ docker run -v $(pwd):/scp-firmware -v ~/.gitconfig:/home/user/.gitconfig \
351      -e TERM -e ARMLMD_LICENSE_FILE -it scp-firmware pwd
352
353```
354
355[`Dockerfile`]: ./docker/Dockerfile
356
357## Arm Compiler 6 support for Docker
358
359To use Arm compiler 6 in the container it will be necessary to mount the
360directory into `/opt/arm-compiler-6`.
361
362# Getting Started {#getting-started}
363
364## Prerequisites {#prerequisites}
365
366In order to build, validate and test the full suite of in-tree firmware targets,
367you will need the following (adjust for your desired platform):
368
369- [cmake-format 0.6.13](https://pypi.org/project/cmake-format/0.6.13/#files)
370- [CMake 3.18.3](https://github.com/Kitware/CMake/releases/tag/v3.18.3)
371- [Markdownlint 0.11.0](https://rubygems.org/gems/mdl/versions/0.11.0)
372- [Python 3.8.2](https://www.python.org/downloads/release/python-382)
373- [yamllint 1.25.0](https://pypi.org/project/yamllint/1.25.0/#files)
374
375## Basics {#basics}
376
377The SCP-firmware project uses CMake, a build system generator for C-like
378languages, to configure and generate its build system. This section is
379dedicated to getting you familiarized with the basics of our CMake build system
380configuration.
381
382For basic usage instructions on CMake, see [Running CMake].
383
384[Running CMake]: https://cmake.org/runningcmake
385
386## Configuration
387
388### Firmware
389
390> **NOTE:** Unlike in previous generations of the build system, there is no
391> "product" concept, and you select the firmware directly. While this prevents
392> you from building all the firmware images of a product at once, it allows you
393> to configure firmware images individually.
394
395In order to begin with building a firmware, you will need to first provide to
396the build system a path to the firmware you wish to build. This is done through
397the `SCP_FIRMWARE_SOURCE_DIR` cache variable, and represents a directory
398containing a `Firmware.cmake` file, which the build system will load to
399configure the firmware target. If you're using `cmake` on the command line, this
400should look like the following:
401
402```sh
403$ cmake "${SCP_SOURCE_DIR}" -B "${SCP_BUILD_DIR}" \
404  -DSCP_FIRMWARE_SOURCE_DIR:PATH="${SCP_PRODUCT}/${SCP_FIRMWARE}"
405  ...
406```
407
408`SCP_FIRMWARE_SOURCE_DIR` may also be a path relative to the root project
409directory.
410
411### Variables
412
413> **NOTE:** If you are using a GUI-based tool, how you configure these variables
414> may differ from how this section describes. For instance, `cmake-gui` and
415> `cmake` both present the options you may configure by default, and you do not
416> need to do anything else. If you are using an IDE, you may need to modify
417> the generated `CMakeCache.txt` file, or your IDE may offer an integrated way
418> to modify these variables.
419
420The various configuration variables can be listed on the command line with:
421
422```sh
423$ cmake "${SCP_SOURCE_DIR}" -LAH
424```
425
426This will give you a list of the options available to you as well as a helpful
427description and their type.
428
429You can override the default values for any of the settings you see with the
430`-D` CMake option:
431
432```sh
433$ cmake "${SCP_SOURCE_DIR}" -B "${SCP_BUILD_DIR}" \
434  -D${VARIABLE_NAME}:${VARIABLE_TYPE}="${VARIABLE_VALUE}"
435  ...
436```
437
438> **NOTE:** If you do not see a variable that you expect to see, it is likely
439> because the firmware has forcibly overridden it.
440
441### Toolchain
442
443If you wish to adjust the toolchain used to build the firmware, you may provide
444the `SCP_TOOLCHAIN` cache variable. Toolchain support is on a per-firmware
445basis, and the toolchains supported by the firmware are given by
446`Toolchain-${SCP_TOOLCHAIN}.cmake` files found in the firmware.
447
448When `SCP_TOOLCHAIN` is set as `Clang` `SCP_LLVM_SYSROOT_CC` must be defined.
449
450For example, a firmware supporting both GCC and Arm Compiler 6 may offer a `GNU`
451toolchain and an `ArmClang` toolchain (`Toolchain-GNU.cmake` and
452`Toolchain-ArmClang.cmake`). In this situation, for GCC you might use:
453
454```sh
455$ cmake "${SCP_SOURCE_DIR}" -B "${SCP_BUILD_DIR}" \
456  -DSCP_TOOLCHAIN:STRING="GNU"
457  ...
458```
459
460Or for Arm Compiler 6:
461
462```sh
463$ cmake "${SCP_SOURCE_DIR}" -B "${SCP_BUILD_DIR}" \
464  -DSCP_TOOLCHAIN:STRING="ArmClang"
465  ...
466```
467
468Alternatively, if you wish to use a [custom toolchain file], you may provide
469[`CMAKE_TOOLCHAIN_FILE`]:
470
471```sh
472$ cmake "${SCP_SOURCE_DIR}" -B "${SCP_BUILD_DIR}" \
473  -DCMAKE_TOOLCHAIN_FILE:FILEPATH="${SCP_TOOLCHAIN_FILE}"
474  ...
475```
476
477[custom toolchain file]: https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html
478[`CMAKE_TOOLCHAIN_FILE`]: https://cmake.org/cmake/help/latest/variable/CMAKE_TOOLCHAIN_FILE.html
479
480> **NOTE:** An out-of-tree firmware may be configured per these instructions by
481> providing a firmware directory outside of the project source directory.
482
483## Quality Assurance {#qa}
484
485The SCP-firmware project has adopted a number of quality assurance tools in
486order to programmatically measure and increase code quality, and most of these
487tools can be invoked directly through the build system for convenience with the
488following:
489
490```sh
491$ cmake --build <build directory> --target <target>
492```
493
494Or, alternatively, directly through the generated build system. For instance,
495if you configured the project with the *Unix Makefiles* generator:
496
497```sh
498$ make -C <build directory> <target>
499```
500
501The following validation targets are supported:
502
503- `check`: Runs all linting and formatting checks
504  - `lint`: Runs all linting checks
505    - `lint-cmake`: Runs CMake linting checks
506    - `lint-python`: Runs Python linting checks
507    - `lint-markdown`: Runs Markdown linting checks
508    - `lint-yaml`: Runs YAML linting checks
509  - `check-cmake`: Runs CMake formatting checks
510  - `check-yaml`: Runs YAML formatting checks
511  - `check-c`: Runs C formatting checks
512- `format`: Formats all code
513  - `format-cmake`: Formats all CMake code
514  - `format-yaml`: Formats all YAML code
515  - `format-c`: Formats all C code
516