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