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_ATU_MANAGE`: Enable/disable ATU management support. This option
120  should be enabled only if the MSCP has permissions to configure the ATU.
121
122- `SCP_ENABLE_ATU_DELEGATE`: Enable/disable ATU delegation support. This option
123  should be enabled when the ATU is not managed directly by the firmware.
124
125- `SCP_ENABLE_FWK_EVENT_WATERMARK_TRACING`: Enable/disable tracing for event
126  queues.
127
128- `SCP_ENABLE_MARKED_LIST`: Enable/disable calculations of list max size.
129
130- `SCP_ENABLE_FAST_CHANNELS`: Enable/disable Fast Channels support. This
131  option should be enabled/disabled by the use of a platform specific setting
132  like `SCP_ENABLE_SCMI_PERF_FAST_CHANNELS`.
133
134- `SCP_TARGET_EXCLUDE_SCMI_PERF_PROTOCOL_OPS`: Allow conditional inclusion of
135  SCMI Performance commands operations. This allows platforms to include only
136  the core Perf and FastChannels without the commands ops (for ACPI-based
137  systems).
138
139It can also be used to provide some platform specific settings.
140e.g. For ARM Juno platform. See below
141
142- `SCP_ENABLE_SCMI_PERF_FAST_CHANNELS`: Enable/disable Juno SCMI-perf
143  Fast channels.
144
145- `SCP_ENABLE_DEBUG_UNIT`: Enable/disable Juno debug unit.
146
147- `SCP_ENABLE_STATISTICS`: Enable/disable Juno statistics.
148
149## Modifying build options
150There are a number of ways to configure a specific option.
151
152- Using cmake command line option
153
154> ```sh
155> cmake -B /tmp/build  -DSCP_FIRMWARE_SOURCE_DIR:PATH=juno/scp_ramfw\
156> -DSCP_ENABLE_DEBUG_UNIT=TRUE
157> ```
158> It will configure cmake to build firmware for Juno platform `scp_ramfw`
159> firmware. with debug unit enabled
160> where:
161> - `/tmp/build`:  is the directory where the build will be generated.
162> - `juno/scp_romfw`: is the firmware to build for the platform.
163>
164> ```sh
165> $ cmake --build /tmp/build    # will build the configured cmake
166> ```
167
168- Using ccmake or cmake-gui
169
170> ```sh
171> $ ccmake -B /tmp/build  -DSCP_FIRMWARE_SOURCE_DIR:PATH=juno/scp_ramfw
172> ```
173> It will configure cmake to build firmware for Juno platform scp_ramfw
174> firmware with debug unit enabled
175> where:
176> * `/tmp/build`:  is the directory where the build will be generated.
177> * `juno/scp_romfw`: is the firmware to build for the platform.
178>
179> It opens a curses based UI. If `/tmp/build` is not present i.e. if this
180> is the first time the configuration is generated, select `'c'` (Configure)
181> and then modify the options as desired. After selecting the options
182> select `'c'` (Configure) and `'g'`(Generate) to generate the build system.
183>
184> ```sh
185> $ cmake --build /tmp/build    # will build the configured cmake
186> ```
187>
188> Build options can subsequently tuned using below command
189> ```sh
190> $ ccmake /tmp/build
191> ```
192
193- Using default value set for a specific option in `Firmware.cmake`.
194>
195> Every SCP firmware specific option(e.g. `SCP_ENABLE_XXX`) has a corresponding
196> `_INIT` variable in respective `Firmware.cmake` and can be modified before
197> build generation
198>
199> e.g.
200> For Arm Juno platform `scp_ramfw/Firmware.cmake` following value can be edited
201> manually before build configuration is generated.
202>
203> ```cmake
204> set(SCP_ENABLE_DEBUG_UNIT_INIT FALSE)
205> ```
206>
207> **NOTE** In this method, if value needs to be re-modified then old build
208> folder must be manually deleted. Subsequent re-run without deleting old
209> configuration will not update the earlier configured value, See CACHE
210> variables in CMake documentation.
211
212**NOTE**: Enabling/disabling option may result in inclusion or exclusion of
213a particular module in the firmware.
214e.g. See module/resource_perms/Module.cmake and note following
215```cmake
216if(SCP_ENABLE_RESOURCE_PERMISSIONS)
217   list(APPEND SCP_MODULES "resource-perms")
218endif()
219```
220The above code will include `resource-perms` module in the firmware only if
221`SCP_ENABLE_RESOURCE_PERMISSIONS` is enabled. This also means, define
222`BUILD_HAS_MOD_RESOURCE_PERMS` will available only if this option is enabled.
223
224# Development Environments {#development-environments}
225
226Along with core CMake build system, also provided is a option to generate
227a build environment, please see details below.
228
229## Vagrant (recommended) {#vagrant}
230
231> **NOTE**: If you're unfamiliar with Vagrant, we recommend you read the brief
232> introduction found [here][Vagrant].
233
234Vagrant is an open-source software product for building and maintaining portable
235virtual software development environments. The `SCP-firmware `project offers a
236Vagrant configuration based on the [Docker] provider, and so you will need to
237have them both installed:
238
239- Install [Docker](https://docs.docker.com/get-docker)
240- Install [Vagrant](https://www.vagrantup.com/downloads)
241
242> **NOTE**: Vagrant and Docker are generally both available through system
243> package managers:
244>
245> - Ubuntu and other Debian-based Linux distributions:
246>   https://docs.docker.com/engine/install/ubuntu/
247>
248> ```sh
249> $ sudo apt install vagrant
250> ```
251>
252
253When using Vagrant, there are no additional prerequisites for the host system,
254as all build and quality assurance tools are packaged with the container.
255
256[Docker]: https://www.docker.com/why-docker
257[Vagrant]: https://www.vagrantup.com/intro
258
259### Interactive Development {#interactive-vagrant-development}
260
261You can bring up an interactive development environment by simply running the
262following:
263
264```sh
265$ vagrant up
266Bringing machine 'default' up with 'docker' provider...
267==> default: Machine already provisioned. Run `vagrant provision` or use the
268`--provision`
269==> default: flag to force provisioning. Provisioners marked to run always will
270still run.
271```
272
273> **NOTE**: The Docker container image will be built the first time you run
274> this, which can take a while. Be patient - it won't happen again unless you
275> modify the Dockerfile.
276
277The project working directory will be mounted within the container as
278`/scp-firmware`.
279
280You can then connect to the embedded SSH server as the non-root user `user`
281with:
282
283```sh
284$ vagrant ssh
285```
286
287You will have access to `sudo` from within the container, and Vagrant will
288persist any changes to the container even if you halt it. If you need to rebuild
289the container for any reason, like if you have made changes to the Dockerfile,
290you can rebuild the development environment with:
291
292```sh
293$ vagrant reload
294```
295
296Do note, however, that reloading the development environment will rebuild it
297from scratch.
298
299### Running Commands {#running-vagrant-commands}
300
301If you simply wish to invoke a command from within the container, you may also
302use Vagrant's [`docker-run`] command, e.g.:
303
304```sh
305$ vagrant docker-run -- pwd
306==> default: Image is already built from the Dockerfile. `vagrant reload` to
307rebuild.
308==> default: Creating the container...
309    default:   Name: git_default_1601546529_1601546529
310    default:  Image: b7c4cbfc3534
311    default:    Cmd: pwd
312    default: Volume: /tmp/tmp.cGFeybHqFb:/vagrant
313    default:
314    default: Container is starting. Output will stream in below...
315    default:
316    default: /vagrant
317```
318
319[`docker-run`]: https://www.vagrantup.com/docs/providers/docker/commands#docker-run
320
321## Visual Studio Code Development Containers {#vscode-containers}
322
323If you use Visual Studio Code, you may also work directly within a
324pre-configured development container. See the [official tutorial] if you are
325unfamiliar with the process of developing within containers.
326
327[official tutorial]: https://code.visualstudio.com/docs/remote/containers-tutorial
328
329## Docker {#docker}
330
331> **NOTE**: Using Docker in SCP build might show some errors.
332
333The SCP-firmware project includes a [`Dockerfile`] which can be used to set up
334an environment containing all of the necessary prerequisites required to build
335and test a firmware.
336
337This Dockerfile has four variants:
338
339- `ci`: A continuous integration variant, which provides the tooling required
340  for automating builds and quality assurance processes.
341- `jenkins`: A Jenkins-specific continuous integration variant, which includes
342  additional steps required to use it from Jenkins.
343- `dev`: A development variant, which includes additional tools for developers
344  accessing the container directly.
345- `vagrant`: A Vagrant variant, which includes an SSH server and a workspace
346  more familiar to Vagrant users.
347
348We *highly* recommend using [Vagrant](#vagrant) to manage your development
349environment, but in case you must do so directly through Docker, you can build
350the development container with the following:
351
352```sh
353$ docker build -t scp-firmware --target=dev -f docker/Dockerfile .
354```
355
356You can then begin an interactive login shell with:
357
358```sh
359$ docker run -v $(pwd):/scp-firmware -v ~/.gitconfig:/home/user/.gitconfig \
360    -e TERM -e ARMLMD_LICENSE_FILE -it scp-firmware /bin/bash
361```
362
363Alternatively, you can run commands directly from within the container with:
364
365```sh
366$ docker run -v $(pwd):/scp-firmware -v ~/.gitconfig:/home/user/.gitconfig \
367      -e TERM -e ARMLMD_LICENSE_FILE -it scp-firmware pwd
368
369```
370
371[`Dockerfile`]: ./docker/Dockerfile
372
373## Arm Compiler 6 support for Docker
374
375To use Arm compiler 6 in the container it will be necessary to mount the
376directory into `/opt/arm-compiler-6`.
377
378# Getting Started {#getting-started}
379
380## Prerequisites {#prerequisites}
381
382In order to build, validate and test the full suite of in-tree firmware targets,
383you will need the following (adjust for your desired platform):
384
385- [cmake-format 0.6.13](https://pypi.org/project/cmake-format/0.6.13/#files)
386- [CMake 3.18.3](https://github.com/Kitware/CMake/releases/tag/v3.18.3)
387- [Python 3.8.2](https://www.python.org/downloads/release/python-382)
388
389## Basics {#basics}
390
391The SCP-firmware project uses CMake, a build system generator for C-like
392languages, to configure and generate its build system. This section is
393dedicated to getting you familiarized with the basics of our CMake build system
394configuration.
395
396For basic usage instructions on CMake, see [Running CMake].
397
398[Running CMake]: https://cmake.org/runningcmake
399
400## Configuration
401
402### Firmware
403
404> **NOTE:** Unlike in previous generations of the build system, there is no
405> "product" concept, and you select the firmware directly. While this prevents
406> you from building all the firmware images of a product at once, it allows you
407> to configure firmware images individually.
408
409In order to begin with building a firmware, you will need to first provide to
410the build system a path to the firmware you wish to build. This is done through
411the `SCP_FIRMWARE_SOURCE_DIR` cache variable, and represents a directory
412containing a `Firmware.cmake` file, which the build system will load to
413configure the firmware target. If you're using `cmake` on the command line, this
414should look like the following:
415
416```sh
417$ cmake "${SCP_SOURCE_DIR}" -B "${SCP_BUILD_DIR}" \
418  -DSCP_FIRMWARE_SOURCE_DIR:PATH="${SCP_PRODUCT}/${SCP_FIRMWARE}"
419  ...
420```
421
422`SCP_FIRMWARE_SOURCE_DIR` may also be a path relative to the root project
423directory.
424
425### Variables
426
427> **NOTE:** If you are using a GUI-based tool, how you configure these variables
428> may differ from how this section describes. For instance, `cmake-gui` and
429> `cmake` both present the options you may configure by default, and you do not
430> need to do anything else. If you are using an IDE, you may need to modify
431> the generated `CMakeCache.txt` file, or your IDE may offer an integrated way
432> to modify these variables.
433
434The various configuration variables can be listed on the command line with:
435
436```sh
437$ cmake "${SCP_SOURCE_DIR}" -LAH
438```
439
440This will give you a list of the options available to you as well as a helpful
441description and their type.
442
443You can override the default values for any of the settings you see with the
444`-D` CMake option:
445
446```sh
447$ cmake "${SCP_SOURCE_DIR}" -B "${SCP_BUILD_DIR}" \
448  -D${VARIABLE_NAME}:${VARIABLE_TYPE}="${VARIABLE_VALUE}"
449  ...
450```
451
452> **NOTE:** If you do not see a variable that you expect to see, it is likely
453> because the firmware has forcibly overridden it.
454
455### Toolchain
456
457If you wish to adjust the toolchain used to build the firmware, you may provide
458the `SCP_TOOLCHAIN` cache variable. Toolchain support is on a per-firmware
459basis, and the toolchains supported by the firmware are given by
460`Toolchain-${SCP_TOOLCHAIN}.cmake` files found in the firmware.
461
462When `SCP_TOOLCHAIN` is set as `Clang` `SCP_LLVM_SYSROOT_CC` must be defined.
463
464For example, a firmware supporting both GCC and Arm Compiler 6 may offer a `GNU`
465toolchain and an `ArmClang` toolchain (`Toolchain-GNU.cmake` and
466`Toolchain-ArmClang.cmake`). In this situation, for GCC you might use:
467
468```sh
469$ cmake "${SCP_SOURCE_DIR}" -B "${SCP_BUILD_DIR}" \
470  -DSCP_TOOLCHAIN:STRING="GNU"
471  ...
472```
473
474Or for Arm Compiler 6:
475
476```sh
477$ cmake "${SCP_SOURCE_DIR}" -B "${SCP_BUILD_DIR}" \
478  -DSCP_TOOLCHAIN:STRING="ArmClang"
479  ...
480```
481
482Alternatively, if you wish to use a [custom toolchain file], you may provide
483[`CMAKE_TOOLCHAIN_FILE`]:
484
485```sh
486$ cmake "${SCP_SOURCE_DIR}" -B "${SCP_BUILD_DIR}" \
487  -DCMAKE_TOOLCHAIN_FILE:FILEPATH="${SCP_TOOLCHAIN_FILE}"
488  ...
489```
490
491[custom toolchain file]: https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html
492[`CMAKE_TOOLCHAIN_FILE`]: https://cmake.org/cmake/help/latest/variable/CMAKE_TOOLCHAIN_FILE.html
493
494> **NOTE:** An out-of-tree firmware may be configured per these instructions by
495> providing a firmware directory outside of the project source directory.
496
497## Quality Assurance {#qa}
498
499The SCP-firmware project has adopted a number of quality assurance tools in
500order to programmatically measure and increase code quality, and most of these
501tools can be invoked directly through the build system for convenience with the
502following:
503
504```sh
505$ cmake --build <build directory> --target <target>
506```
507
508Or, alternatively, directly through the generated build system. For instance,
509if you configured the project with the *Unix Makefiles* generator:
510
511```sh
512$ make -C <build directory> <target>
513```
514
515The following validation targets are supported:
516
517- `check`: Runs all linting and formatting checks
518  - `lint`: Runs all linting checks
519    - `lint-cmake`: Runs CMake linting checks
520    - `lint-python`: Runs Python linting checks
521  - `check-cmake`: Runs CMake formatting checks
522- `format`: Formats all code
523  - `format-cmake`: Formats all CMake code
524