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