Skip to content

A short tutorial on how to build and test embedded software using the IAR C/C++ Compiler alongside CMake.

License

Notifications You must be signed in to change notification settings

panicking/cmake-tutorial

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

27 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Tutorial
Building and testing with the IAR tools in CMake

CMake is an open-source, cross-platform family of tools maintained and supported by Kitware. CMake is used to control the software compilation process through simple configuration files to generate native build scripts for a chosen build system (e.g. ninja, make, etc.). For full documentation visit the CMake Documentation Page.

This tutorial serves as a mini-guide on the ways CMake can be used alongside the IAR C/C++ Compilers to cross-compile embedded software applications for the supported target architectures. The core ideas presented were inspired by the Technical Note 190701.

Pre-requisites

This tutorial assumes that:

  • The reader is familiar with the usage of the IAR tools, as well as with the Kitware tools, from their respective command-line interfaces.

  • This repository is cloned to the development computer (alternatively it can be downloaded as a zip archive via the Code button).

  • The required tools are already installed in the system, according to the table below:

Tool Windows-based systems Linux-based systems
IAR C/C++ Compiler for... Arm, RISC-V, RL78, RX, RH850,
8051, AVR, MSP430, STM8 or V850
Arm, RISC-V, RL78, RX or RH850
CMake v3.23 or later v3.23 or later
Build engine Ninja Ninja

💡 On Linux-based systems, cmake and ninja are normally found on the default search path so that both can be executed directly from anywhere in the system. Although, on Windows-based systems, this is not always the case. It is recommended that their respective locations are on the search path, defined by the PATH environment variable. The same recommendation applies for when using cmake.exe with other generators such as "Unix Makefiles" that relies on make.exe as build system. Under such a scenario, if the make.exe program cannot be found, CMake will fail immediately during the toolchain configuration step with a corresponding error message (e.g. "CMAKE_MAKE_PROGRAM not found").

Building Projects

To build a project developed with the IAR Compiler using CMake we need at least

  • A toolchain file
  • A CMakeLists.txt file
  • The source code

Configuring the toolchain file

By default, CMake uses what it assumes to be the host platform's default compiler. When the application targets an embedded platform (known as cross-compiling), a toolchain file <toolchain-file>.cmake can be used to indicate the desired toolchain's location for its compiler and assembler. This section provides a simple generic template for the IAR C/C++ Compilers.

In the examples/iar-toolchain.cmake file:

  • Set TOOLKIT variable to the compiler's target architecture.
# Action: Set the `TOOLKIT` variable
# Examples: arm, riscv, rh850, rl78, rx, stm8, 430, 8051, avr or v850
# Alternative: override the default TOOLKIT_DIR (/path/to/installation/<arch>)
set(TOOLKIT arm)

💡 The default toolchain file will search for an available compiler in the default installation paths. Alternatively, the TOOLKIT variable can be used to set a specific installation directory (e.g., C:/IAR_Systems/EWARM/N.nn).

A minimal project

A CMake project is defined by one or more CMakeLists.txt file(s). Let's understand how a simple hello-world project can be configured for the Arm target architecture.

  • Change to the hello-world project:
cd /path/to/cmake-tutorial/examples/arm/hello-world
  • Verify the contents of the CMakeLists.txt file:

https://github.com/IARSystems/cmake-tutorial/blob/985f597765bd1186867b4157af3d1afde6531943/examples/arm/hello-world/CMakeLists.txt#L1-L16

💡 Adjust the target compile/link options for architectures other than arm.

  • Verify the contents of the main.c source file:

https://github.com/IARSystems/cmake-tutorial/blob/985f597765bd1186867b4157af3d1afde6531943/examples/arm/hello-world/main.c#L1-L9

Configuring the build system generator

Once we have our minimal project with a suitable toolchain file, we invoke CMake to configure our build environment for when cross-compiling, choosing which build system generator and which toolchain file should be used for the project.

In this example we will take advantage of the "Ninja Multi-Config" generator option. This option can be used to generate build configurations for "Debug" and "Release" purposes. The general recommendation when using CMake is to perform an "out-of-source" build, which means creating a subdirectory for the output files.

  • Use the following command to generate the scripts for the build system inside the _builds subdirectory:
cmake -B_builds -G "Ninja Multi-Config" --toolchain /path/to/iar-toolchain.cmake

💡 Use cmake --help for more information.

Expected output example (click to unfold):
-- The C compiler identification is IAR ARM N.nn
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /path/to/toolkit_dir/bin/iccarm.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /path/to/cmake-tutorial/examples/arm/hello-world/_builds

⚠️ If for some mistake the configuration step fails (e.g. wrong option, wrong selection, etc.), it might be necessary to remove the _builds subdirectory before trying again. This helps CMake to avoid potential cache misses interfering during a new attempt.

Building the project

  • Once the _builds tree is configured, use CMake with the --build flag to build the project:
cmake --build _builds

💡 Use cmake --help for more information.

Expected output example (click to unfold):
[2/2] Linking C executable Debug\hello-world.elf

In the minimal example we had an initial overview of what is needed to bootstrap a CMake project for a simple executable. Targets created from actual embedded software projects will typically require preprocessor symbols, compiler flags, linker flags and extended options. Additional project examples for the target architectures supported in CMake are provided as reference in the "Examples" section of this tutorial.

Examples

Now that you know how to configure and build embedded projects developed with the IAR tools using CMake, you can start to explore how projects can be configured in greater detail using the previously acquired knowledge.

In this section you will find descriptions for the provided examples. Each architecture (<arch>) subdirectory contains multiple examples.

Optionally, each example's CMakeLists.txt for executable targets comes with a line include(/path/to/iar-cspy-<arch>.cmake) in the end as an example that illustrates how to use CTest to invoke the IAR C-SPY Command-line Utility (cspybat.exe) to perform automated tests using macros.

Example 1 - Mixing C and Assembly

The examples/<arch>/mix-c-asm example project demonstrates the basic concepts on how to build a single executable target (mixLanguages) using C and Assembly sources.

It also shows:

  • How to use target_compile_definitions() to set preprocessor symbols that can be used in the target's sources.

Example 2 - Creating and using libraries

The examples/<arch>/using-libs example project demonstrates some advanced features and how to build one executable target (myProgram) linked against a static library target (myMath) using C sources.

The top-level directory contains a CMakeLists.txt file that will add the lib and the app subdirectories, each one containing its own CMakeLists.txt.

The myMath library target is located in the lib subdirectory. The library contains functions which take two integer parameters to perform basic arithmetic over them, returning another integer as result.

The myProgram executable target is located in the app subdirectory. The program performs arithmetic operations using the myMath's library functions.

It also shows:

  • How to use set_target_properties() to propagate configuration details across the target options.
  • How to set target_link_options() to create a map file of the executable.
  • How to use add_custom_command() for generating .bin/.hex/.srec outputs using ielftool.

Testing the examples

CTest is an extension of CMake that can help when performing automated tests. In its conception, a test in CTest allows desktop software developers to execute the target directly on the host computer, evaluating its exit code.

When cross-compiling, it is not possible to execute the target executable directly from the host computer. However it is possible to execute the target with the IAR C-SPY Debugger using, for example, a custom function that wraps the needed parameters (e.g. iar_cspy_add_test()). A module named iar-cspy-<arch>.cmake was included in the CMakeLists.txt files for executable targets and illustrates such a concept.

⚠️ This section requires the IAR C-SPY Command Line Utility (cspybat.exe), which is available with the IAR Embedded Workbench products.

  • Test the desired project example (*built with debug information) by executing:
ctest --test-dir _builds --build-config Debug --output-on-failure --timeout 10

💡 Use ctest --help for more information.

Expected output - Example 1 (click to unfold):
Internal ctest changing into directory: C:/path/to/cmake-tutorial/examples/<arch>/mix-c-asm/_builds
Test project C:/path/to/cmake-tutorial/examples/<arch>/mix-c-asm/_builds
   Start 1: test_mynum
1/1 Test #1: test_mynum .......................   Passed    0.20 sec

100% tests passed, 0 tests failed out of 1

Total Test time (real) =   0.25 sec
Expected output - Example 2 (click to unfold):
Internal ctest changing into directory: C:/path/to/cmake-tutorial/examples/<arch>/using-libs/_builds
Test project C:/path/to/cmake-tutorial/examples/<arch>/using-libs/_builds
   Start 1: test_add
1/3 Test #1: test_add .........................   Passed    0.44 sec
   Start 2: test_sub
2/3 Test #2: test_sub .........................***Failed  Required regular expression not found. Regex=[PASS]  0.44 sec
-- app debug output begin --
40 + 2 = 42
-- C-SPY TEST:test_sub. Expected: 38 Result: FAIL
40 - 2 = 39
40 * 2 = 80
-- app debug output end --

   Start 3: test_mul
3/3 Test #3: test_mul .........................   Passed    0.44 sec

67% tests passed, 1 tests failed out of 3

Total Test time (real) =   1.34 sec

The following tests FAILED:
         2 - test_sub (Failed)
Errors while running CTest

Debugging

When executable targets are built with debug information, they can be debugged with the IAR C-SPY Debugger, directly from the IAR Embedded Workbench IDE.

The Debugging an Externally Built Executable file Technical Note has the instructions for setting up a debug-only project.

Issues

Found an issue or have a suggestion related to the cmake-tutorial tutorial? Feel free to use the public issue tracker.

  • Do not forget to take a look at earlier issues.
  • If creating a new issue, please describe it in detail.

Conclusion

This tutorial provided information on how to start building embedded software projects and, also, on how to perform automated tests when using the IAR tools with CMake. Once the core ideas presented here are mastered, the possibilities are only limited by the developer's mind. Such a setup might be useful depending on each organization's needs and can be used as a starting point for particular customizations.

About

A short tutorial on how to build and test embedded software using the IAR C/C++ Compiler alongside CMake.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Shell 50.0%
  • CMake 39.6%
  • Assembly 5.9%
  • C 3.8%
  • C++ 0.7%