You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
Felipe Torrezan b7d0f4611a
Initial commit
3 years ago
examples Initial commit 3 years ago
.gitignore Initial commit 3 years ago
LICENSE Initial commit 3 years ago
README.md Initial commit 3 years ago

README.md

Tutorial
Building and testing with the IAR Systems tools in CMake

If you end up with a question or suggestion specifically related to this tutorial, you might be interested in verifying if it was already discussed in earlier issues. If you could not find what you are looking for, feel free to create a new issue.

It is possible to receive notifications about updates to this tutorial directly in your GitHub inbox by starting to watch this repository.

Introduction

CMake is a cross-platform, open-source build system generator. CMake is maintained and supported by Kitware. It is developed in collaboration with a productive community of contributors.

For full documentation visit the CMake Documentation Page.

The core ideas in this tutorial, inspired by the Technical Note 190701, serve as a mini-guide on how CMake can be used alongside the IAR C/C++ Compiler to cross-compile embedded software applications.

This tutorial assumes that the reader is familiar with the usage of the IAR Systems tools,as well as with the Kitware tools, from their respective command-line interfaces.

Required tools

The required tools are similar either if Windows or Linux is being used:

Tool Windows Linux
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.22 or later v3.22 or later
Build engine Ninja Ninja

⚠️ In order to conveniently execute cmake and ninja from anywhere in your system, without specifying their respective full paths, make sure their locations are in the PATH variable of your operating system.

Configuring the toolchain file

When cross-compiling applications with CMake, an appropriate <toolchain-file>.cmake must be specified. This file contains the toolchain's location for its compiler and assembler.

This section provides a simple example of a generic toolchain file for CMake that can be used along with the IAR C/C++ Compiler.

On the examples/iar-toolchain.cmake file, perform the following changes to match your system:

430, 8051, arm, avr, riscv, rx, rh850, rl78, stm8 or v850.

Windows example:

"C:/Program\ Files/IAR\ Systems/Embedded\ Workbench\ 9.0"

Linux example:

"/opt/iarsystems/bxarm"

Note If the path contains blank spaces, it might be necessary to escape them using backslashes \ .

  • When using the IAR Assembler for 430, 8051, avr or v850 architecture, update CMAKE_ASM_COMPILER to:

"a${CMAKE_SYSTEM_PROCESSOR}"

Examples

In this section you will find examples on how CMakeLists.txt files can be created to build executable targets as well as library targets.

The examples work with all the architectures supported in CMake.

CMake 3 has been described as the beginning of the "Modern CMake" age. Since then, it has been advised to avoid variables in favor of targets and properties. The commands add_compile_options(), include_directories(), link_directories(), link_libraries(), that were at the core of CMake 2, should now be replaced by target-specific commands.

The CMakeLists.txt in the examples use expressions that look like this $<...>. Those are the so-called generator expressions (or genex, for short) and they allow us to express our intentions in many powerful ways.

⚠️ In order to get the all the examples, you can clone this repository or, if you want to get only the files from a single example, click on its respective link in the examples' titles and get it bundled in a zip archive.

Example 1 - Mixing C and Assembly

The mix-c-asm 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.
  • Windows-only: How to execute the target using the IAR C-SPY Debugger Simulator via CTest.

Each <arch> has its own CMakeLists.txt. The file is located in the respective <arch> folder and has further comments. Below you will find the direct links to each of them:

430 8051 arm avr riscv rx rh850 rl78 stm8 v850

Instructions for building and testing these projects are provided below.

Example 2 - Creating and using libraries

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

It also shows:

  • How to use set_target_properties() to propagate configuration details across the target options.
  • How to set target_linker_options() to create a map file of the executable.
  • How to use add_custom_target() for executing ielftool and generate an .ihex|.srec|.bin output.
  • Windows-only: How to execute the target using the IAR C-SPY Debugger Simulator via CTest.

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.

For each architecture, the project uses 3 CMakeLists.txt. These files have further comments.

  • The CMakeLists.txt in the top-level directory:
430 8051 arm avr riscv rx rh850 rl78 stm8 v850
  • The lib/CMakeLists.txt for the library target:
430 8051 arm avr riscv rx rh850 rl78 stm8 v850
  • The app/CMakeLists.txt for the executable target:
430 8051 arm avr riscv rx rh850 rl78 stm8 v850

Instructions for building and testing these projects are provided below.

Building Projects

Generate a Project Buildsystem

The general syntax to generate the input files for a native build system is:

cmake -G <generator> -B <build-dir> --toolchain <file>
Option Explanation
-B Explicitly specify a build directory.
-G Specify a generator name.
--toolchain Specify the toolchain file [CMAKE_TOOLCHAIN_FILE]

In this example we will use the Ninja generator. Once the toolchain file is modified, inside each example's architecture subdirectory, use the following command to generate the build scripts in the _builds sub-directory:

cmake -G "Ninja Multi-Config" -B_builds --toolchain ../../iar-toolchain.cmake

The expected output is similar to:

-- The C compiler identification is IAR <ARCH> <VERSION>
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/<install-path>/<arch>/bin/icc<arch>.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: C:/<...>/cmake-tutorial/examples/<example>/<arch>/_builds

Build the project

The general syntax to build a project through CMake is:

cmake --build <build-dir> --config <cfg> [extra-options]
Option Explanation
--build Build a CMake-generated project binary tree.
--config For multi-configuration tools, choose <cfg>.
--parallel [<jobs>] Build in parallel using the given number of <jobs>.
--clean-first Build target 'clean' first, then build.
(To clean only, use --target clean.)
--verbose Enable verbose output - if supported - including the build commands to be executed.

Once the build tree is configured, inside each example's architecture subdirectory, use the following command line to build the project:

cmake --build _builds --config <Debug|Release>

Convert the output

Optionally, there is an additional target named ielftool for the using-libs examples.

The ielftool target executes the IAR ELF Tool in order to convert the default ELF output to the selected format. The output format parameter can be set to the preferred format in the target's FORMAT property which accepts formats such as Intel-extended, Motorola S-record or binary.

Inside each architecture's project example directory, the following command can be used to create the additional output:

cmake --build _builds --config <Debug|Release> --target=ielftool

⚠️ The ielftool target is not available for architectures using the UBROF format, created by the IAR XLINK Linker.

Testing Projects

CTest is an extension of CMake that can help when performing automated tests.

The enable_testing() command in the CMakeLists.txt file enables CTest. Once CTest is enabled, the add_test() command can be used with executable targets.

In its conception, a test in CTest allows desktop software developers to execute the target directly on the host computer, evaluating its exit code.

Although, in cross-compiling scenarios, it is not possible to execute embedded software for the target architecture directly from the host computer. So we need a slightly different concept in order to execute embedded software from CTest.

The situation narrows down to the following question: what about if we can execute from a simulator, or perhaps, directly from the target itself?

Here is where the IAR C-SPY Debugger comes into play. One possibility for us is to create custom macros in the CMakeLists.txt of the executable targets. In the examples, the custom macro named add_test_cspy() illustrates such a concept. The custom macro will create the command line to execute the target with CSpyBat.exe.

The syntax for the add_test_cspy() in the examples is simple:

add_test_cspy(TESTNAME EXPECTED_VALUE)
Parameter Explanation
TESTNAME A name for the test.
EXPECTED_VALUE Output anything outputted by the test program if the test should fail.

The general syntax to test one of the example projects using CTest is:

ctest --test-dir _builds --build-config Debug --output-on-failure --timeout 10
Option Explanation
--test-dir Specify the directory in which to look for tests.
--output-on-failure Output anything outputted by the test program if the test should fail.
--timeout <seconds> Set the default test timeout.

⚠️ When testing, make sure to use targets built with debug information.

How it works?

In the CMakeLists.txt for the executable targets, the add_test_cspy() macro composes the command-line which will invoke IAR C-SPY Debugger. The flags --macro=<file>.mac and --macro-param="variable=value" are appended to the command-line. These flags forward the test parameters to the example's C-SPY Macro file (test.mac), which will monitor the function's result and then print out a __message with PASS or FAIL. Whenever CTest detects a message containing PASS, it will consider the test successful. This feature shows how powerful and flexible a C-SPY Macro can be. The general syntax in the C-SPY macro system resembles parts of the C Language itself. One of the favorable aspects of using such macros like this, is that they do not impose code overhead to the target executable itself.

Example 1 - expected output:

Internal ctest changing into directory: C:/<...>/cmake-tutorial/examples/mix-c-asm/<arch>/_builds
Test project C:/<...>/cmake-tutorial/examples/mix-c-asm/</arch>/_builds
   Start 1: test_mynum
1/1 Test #1: test_mynum .......................   Passed    0.19 sec

100% tests passed, 0 tests failed out of 1

Total Test time (real) =   0.20 sec

Example 2 - expected output:

Internal ctest changing into directory: C:/<...>/cmake-tutorial/examples/using-libs/<arch>/_builds
Test project C:/<...>/cmake-tutorial/examples/using-libs/<arch>/_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

⚠️ The IAR C-SPY Debugger is only available on Windows.

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.

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 Systems' 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.