Felipe Torrezan
b7d0f4611a
|
3 years ago | |
---|---|---|
examples | 3 years ago | |
.gitignore | 3 years ago | |
LICENSE | 3 years ago | |
README.md | 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:
- Update CMAKE_SYSTEM_PROCESSOR with one of the valid compiler's target
<arch>
:
430
,8051
,arm
,avr
,riscv
,rx
,rh850
,rl78
,stm8
orv850
.
- Update IAR_INSTALL_DIR to point to the toolchain's install location:
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
orv850
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.