CMake Build System: Difference between revisions

From Miosix Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
 
(One intermediate revision by the same user not shown)
Line 1: Line 1:
Miosix 3 introduces a new build system, based on [https://cmake.org CMake]. The CMake build system has the same capabilities of the old Miosix Makefiles, and in addition it allows better composability of Miosix with other external projects.
Miosix 3 introduces a new build system, based on [https://cmake.org CMake]. The CMake build system has the same capabilities of the old Miosix Makefiles, and in addition it allows better composability of Miosix with other external projects.


== How to build Miosix with CMake ==
== Creating a kernelspace project with CMake ==
 
If you are following the instructions from the [[Main Page#Getting started|Getting started]] guides, <code>init_project_out_of_git_tree.pl</code> script should have already created a CMakeLists.txt file for you. For a simple Miosix project without processes or external libraries, the script will look like this (after the copyright notice):
 
<source>
cmake_minimum_required(VERSION 3.21)
 
# Set the path to the Miosix kernel
set(MIOSIX_KPATH ${CMAKE_SOURCE_DIR}/../../miosix)
# Configure CMake toolchain and build type.
# This must to be done before the project() command
set(CMAKE_TOOLCHAIN_FILE ${MIOSIX_KPATH}/cmake/Toolchains/gcc.cmake)
set(CMAKE_BUILD_TYPE "Release")
 
project(Main C CXX ASM)
 
# Select the board (mandatory). See the options in miosix/arch/CMakeLists.txt
set(MIOSIX_BOARD stm32...)
# User config path and linker script selection are optional
# set(MIOSIX_USER_CONFIG_PATH ${CMAKE_SOURCE_DIR}/config)
# set(MIOSIX_LINKER_SCRIPT unikernel.ld)
 
# Include the Miosix kernel's project
add_subdirectory(${MIOSIX_KPATH} miosix EXCLUDE_FROM_ALL)
 
# Define a kernel level program
add_executable(main main.cpp)
# target_include_directories(main PRIVATE here_your_includes)
# target_compile_options(main PRIVATE here_your_compile_options)
# target_link_directories(main PRIVATE here_your_link_directories)
# target_link_libraries(main PRIVATE here_your_libraries)
 
# Link the main target with Miosix. When specifying PROGRAM_DEFAULT, the
# `program' target will be available to flash it (type `make program' to use it)
miosix_link_target(main PROGRAM_DEFAULT)
</source>
 
=== Initial configuration of CMake ===
 
The first line of the CMakeLists.txt sets the required version of CMake to 3.21. This enables features required by the Miosix CMake scripts; the version number cannot be lowered.
 
After this line, the script sets a few initial configuration variables that only take effect if set before the <code>project()</code> command is called.
 
==== Setting the path to the kernel and the toolchain file ====
 
The first thing the script does is to set a <code>MIOSIX_KPATH</code> variable to the absolute path of the Miosix kernel's directory. We recommend that this path (and all other paths in a CMake project) should remain absolute, for extra robustness of your scripts.
{{Note|The variable <code>MIOSIX_KPATH</code> is not used by the Miosix kernel's CMake scripts, it is only a helper variable used by the default application script.}}
 
Then, the script sets <code>CMAKE_TOOLCHAIN_FILE</code> to the path of one of the toolchain scripts in Miosix's directory. This is ''required'' to force CMake to use an embedded toolchain. At the moment only the default <code>gcc.cmake</code> toolchain file is supported.
 
==== Setting the build type ====
 
The script sets the <code>CMAKE_BUILD_TYPE</code> to the default build type, <code>Release</code>. Change this line to set a different build type, or remove the line to allow setting the build type from the command line.
{{Tip|The [https://cmake.org/cmake/help/v3.21/variable/CMAKE_BUILD_TYPE.html available build types] in CMake (which also apply to Miosix) are <code>Debug</code>, <code>Release</code> and <code>RelWithDebInfo</code> and <code>MinSizeRel</code>. Miosix does not add custom build types.}}
{{Warning|Variables in CMake are not all created equal. All variables assigned with <code>set()</code> outside of a function are '''local''' to the current directory scope and its children (a new directory scope is created by <code>add_subdirectory</code>). Global configuration options are instead called "cache" variables, and they are set using the <code>CACHE</code> option of the <code>set()</code> command.
 
Miosix declares a minimum CMake version of 3.21 in order to allow overriding "cache" variables with standard (non-CACHE) <code>set()</code> commands. We find this to be a significant simplification of the semantics of cache variables: it removes a lot of surprising behaviour for beginners, and makes CMake files more coincise. However, a cache variable overridden like this cannot be set from the command line anymore.
 
This is why the line which sets <code>CMAKE_BUILD_TYPE</code> must be removed to allow setting the build type from the command line.
 
See the [https://cmake.org/cmake/help/v3.21/manual/cmake-language.7.html#cmake-language-variables CMake documentation] for more information about this topic.}}
 
=== Creating the Miosix binary ===
 
The rest of the script imports the Miosix kernel as a subdirectory, and then create an executable that links with the Miosix kernel: your application. There are a few Miosix-specific variables and functions that are used to help with this task.
 
==== Setting the board ====
 
The target board for the application is chosen by setting the <code>MIOSIX_BOARD</code> variable to the name of the board. The board names are the same ones previously used for the Makefile-based build system, and some of the supported boards are documented here on the Wiki on the [[Board list]] page.
 
The [[Board list]] on the Wiki is not complete. There are several ways to see the ''full'' list of supported boards:
* Look at the contents of the <code>miosix/arch/boards</code> directory in the kernel's source tree. Each directory corresponds to a board, and the directory name is the same as the board name.
* Open the <code>miosix/arch/CMakeLists.txt</code> file. At the beginning of the file, the <code>MIOSIX_BOARDS</code> variable is set to the list of all supported boards.
* In your project's build directory, run <code>cmake .. -DMIOSIX_PRINT_BOARD_LIST=ON</code>.
 
The list of all supported boards is also printed if the board selected does not exist.
 
==== Setting the linker script ====
 
By default, the build system selects a linker script for compiling Miosix as a unikernel, with no provision for userspace applications. To select a different linker script, set the <code>MIOSIX_LINKER_SCRIPT</code> variable to the name of the script desired.
 
There are a few standard linker scripts available (not all of them are available for all boards):
* <code>unikernel.ld</code> Baseline unikernel configuration. Default, available for all boards.<br>.text/.rodata in Flash, .data/.bss/heap in internal RAM.
* <code>processes.ld</code> Baseline fluid kernel configuration.<br>.text/.rodata in Flash, .data/.bss/heap/process pool in internal RAM.
* <code>unikernel-xram-heap.ld</code> Unikernel configuration using external RAM only for the heap.<br>.text/.rodata in Flash, .data/.bss in internal RAM, heap in external RAM.
* <code>processes-xram.ld</code> Fluid kernel configuration using external RAM only for the process pool.<br>.text/.rodata in Flash, .data/.bss/heap in internal RAM, process pool in external RAM.
* <code>unikernel-xram.ld</code> Unikernel configuration using external RAM.<br>.text/.rodata in Flash, .data/.bss/heap in external RAM. Internal RAM is used for a statically allocated IRQ stack (also used at boot before external RAM is enabled).
* <code>processes-kernel-xram.ld</code> Fluid kernel configuration using external RAM exclusively.<br>.text/.rodata in Flash, .data/.bss/heap/process pool in external RAM. Internal RAM is used for a statically allocated IRQ stack (also used at boot before external RAM is enabled).
* <code>unikernel-all-in-xram.ld</code> Unikernel configuration for loading Miosix entirely into external RAM with a bootloader.<br>All sections and the heap in external RAM.
Some boards have additional linker scripts reserving parts of RAM for special purposes (i.e. Safeguard Memory, SGM).
 
The list of linker scripts available for a board can be obtained by passing <code>-DMIOSIX_PRINT_LINKER_SCRIPT_LIST=ON</code> to a CMake invocation.
 
If a linker script requires specific defines to be set for it to work, these defines are enabled automatically. For instance, the <code>processes.ld</code> linker script will automatically define <code>WITH_PROCESSES</code> in Miosix.
 
==== Selecting a Miosix configuration directory ====
 
If you desire to use a custom Miosix config directory with different kernel settings than the default, you shall set the <code>MIOSIX_USER_CONFIG_PATH</code> variable to the path of the Miosix config directory desired. A default config directory is created automatically by the <code>init_project_out_of_git_tree.pl</code> script, but you can create one manually simply by copying the <code>miosix/config</code> directory in the Miosix source tree.
 
==== Importing the Miosix kernel into the project ====
 
Once all Miosix configuration variables are set, you can include Miosix by calling the <code>add_subdirectory()</code> command passing the path to the <code>miosix</code> kernel directory.
{{Warning|You need to add the <code>miosix</code> subdirectory, which is one of the top-level directories in the <code>miosix-kernel</code> repository, not <code>miosix-kernel</code> itself.}}
{{Note|The default template CMakeLists.txt also passes two additional arguments to <code>add_subdirectory()</code>:
* The second argument (<code>miosix</code>) is necessary in case the Miosix kernel directory is not actually a subdirectory of your project, in order for CMake to properly create its internal directory structure in the build directory.
* The third argument (<code>EXCLUDE_FROM_ALL</code>) removes Miosix from being a default compilation target, which is necessary as Miosix is effectively a library, not a target in and of itself.
See also the [https://cmake.org/cmake/help/v3.21/command/add_subdirectory.html CMake documentation].}}
 
Adding the <code>miosix</code> subdirectory makes available the Miosix-defined helper functions, and a <code>miosix</code> static library target to link in your executable binary (i.e. the Flash or RAM image).
 
==== Creating the target binary ====
 
Once the <code>miosix</code> subdirectory has been imported, you can create a Miosix binary by adding an executable target with <code>add_executable()</code> linked with Miosix using the function <code>miosix_link_target()</code>.
 
<source>
add_executable(main main.cpp ...)
miosix_link_target(main PROGRAM_DEFAULT)
</source>
 
While you could use the standard CMake command <code>target_link_libraries()</code> to link with Miosix, using <code>miosix_link_target()</code> performs the following additional modifications to the executable target:
* Tells the linker to generate the map file
* Registers custom targets to create the hex and bin files. The targets are called <code>${TARGET}_bin</code> and <code>${TARGET}_hex</code> (so, for the example above, <code>main_bin</code> and <code>main_hex</code>)
* Registers a custom target to flash the program to the board <code>${TARGET}_program</code>.
 
If <code>PROGRAM_DEFAULT</code> is also passed to the function, as in the example, it also defines the <code>program</code> target as an alias for <code>${TARGET}_program</code>.
By default, the size of the target .elf file is also printed at the end of the linking process, unless the <code>NO_SIZE</code> argument is also specified.
 
As a result of this, in our example, the CMake binary directory will contain the files:
* <code>main.elf</code>: the main ELF format memory image
* <code>main.map</code>: the map file produced by the linker
* <code>main.bin</code>: a flat binary image obtained from main.elf, to be loaded at a base address decided by the board configuration
* <code>main.hex</code>: a Intel HEX file image obtained from main.elf (useful if the memory areas to be programmed consist of more than one contiguous span).
Note that at the present time the name of the <code>map</code>, <code>bin</code> and <code>hex</code> files cannot be customized.
 
== Creating a userspace binary with CMake ==
 
Adding one or more userspace process binaries to your Miosix CMake project involves adding the targets for the processes, and then creating a target for building the [[RomFs]] image.
 
First of all, remember to change the configuration of the Miosix kernel to enable userspace processes:
* Set the linker script to <code>processes.ld</code> or to another linker script that supports processes
* Enable the configuration options <code>WITH_FILESYSTEM</code> and <code>WITH_PROCESSES</code>.
 
A process target can be created using the <code>miosix_add_process()</code> function, which works in a similar way to <code>add_executable()</code>:
 
<source>
miosix_add_process(
  <target>
  <source1> <source2> ...
  [RAM_SIZE ram-size]
  [STACK_SIZE stack-size]
  [NO_STRIP_SECTHEADER]
)
</source>
* <code><target></code> is the name of the process target to be created
* <code><source1> <source2> ...</code> is a list of source files to be compiled and linked in the executable
* The <code>RAM_SIZE</code> and <code>STACK_SIZE</code> arguments allow to specify the size of the RAM and stack partitions (in bytes) that will be reserved for the process at runtime from the process pool. The defaults are 16384 and 2048 respectively.
* If <code>NO_STRIP_SECTHEADER</code> is specified, the section headers are not stripped from the ELF file. These headers are not necessary in a valid executable (only the segment headers are required) so this flag is only useful for debugging purposes.
 
The <code>miosix_add_process()</code> performs automatically all the necessary configuration of the executable target, adding mandatory libraries and also enabling linker garbage collection and symbol stripping automatically.
 
==== Creating a RomFs ====
 
Finally, to create the RomFs image, the Miosix build system provides the <code> miosix_add_romfs_image()</code> function:
 
<source>
miosix_add_romfs_image(
  [PROGRAM_DEFAULT]
  IMAGE_NAME <name>
  KERNEL <kernel>
  DIR_NAME <dir_name>
  PROCESSES <process1> <process2> ...
)
</source>
* <code><name></code> is the name of the image target (the resulting file will be named <code><name>.bin</code>).
* <code><kernel></code> is the name of the target linked to the Miosix kernel with <code>miosix_link_target()</code> whose binary should appear in the image leading the RomFs part.
* <code><dir_name></code> is the name of a directory that will be created to collect all the contents of the image. Typically <code>bin</code> is a good name.
* <code><process1> <process2> ...</code> are the process targets to include in the image.
 
Like for <code>miosix_link_target()</code>, a target <code><name>_program</code> is implicitly created for flashing the RomFs image. To make the <code>program</code> target flash the RomFs image, add the <code>PROGRAM_DEFAULT</code> argument to the function call. In that case, remove <code>PROGRAM_DEFAULT</code> (if present) from existing calls to <code>miosix_link_target()</code> to prevent redefinition of the <code>program</code> target.
 
== How to build a Miosix application with CMake ==


Building Miosix with CMake follows the standard workflow that you expect from any other CMake project.
Building Miosix with CMake follows the standard workflow that you expect from any other CMake project.
Line 15: Line 195:
These commands assume your CMake configuration uses Unix Makefiles as the default generator.
These commands assume your CMake configuration uses Unix Makefiles as the default generator.


== Creating a kernelspace project with CMake ==
== Configuration options reference ==


== Creating a userspace binary with CMake ==
As a reference, in the following we list the options provided by the Miosix CMake build system, settable via the command line or through your application's CMakeLists.txt.
 
== Configuration options ==
 
The Miosix CMake build system provides the following options, that can be set via the command line or by your application's CMakeLists.txt.


{| class="wikitable"
{| class="wikitable"
Line 32: Line 208:
|-
|-
| MIOSIX_LINKER_SCRIPT || The linker script to use when linking executables with Miosix using <code>miosix_link_target()</code>. The linker script choice also influences compiler options by adding/removing defines that are required for Miosix to work with that linker script.
| MIOSIX_LINKER_SCRIPT || The linker script to use when linking executables with Miosix using <code>miosix_link_target()</code>. The linker script choice also influences compiler options by adding/removing defines that are required for Miosix to work with that linker script.
The standard linker script choices are:
The standard linker script choices are listed in the [[#Setting the linker script]] section.
* <code>unikernel.ld</code> Baseline unikernel configuration. Available for all boards.<br>.text/.rodata in Flash, .data/.bss/heap in internal RAM.
* <code>processes.ld</code> Baseline fluid kernel configuration.<br>.text/.rodata in Flash, .data/.bss/heap/process pool in internal RAM.
* <code>unikernel-xram-heap.ld</code> Unikernel configuration using external RAM only for the heap.<br>.text/.rodata in Flash, .data/.bss in internal RAM, heap in external RAM.
* <code>processes-xram.ld</code> Fluid kernel configuration using external RAM only for the process pool.<br>.text/.rodata in Flash, .data/.bss/heap in internal RAM, process pool in external RAM.
* <code>unikernel-xram.ld</code> Unikernel configuration using external RAM.<br>.text/.rodata in Flash, .data/.bss/heap in external RAM. Internal RAM is used for a statically allocated IRQ stack (also used at boot before external RAM is enabled).
* <code>processes-kernel-xram.ld</code> Fluid kernel configuration using external RAM exclusively.<br>.text/.rodata in Flash, .data/.bss/heap/process pool in external RAM. Internal RAM is used for a statically allocated IRQ stack (also used at boot before external RAM is enabled).
* <code>unikernel-all-in-xram.ld</code> Unikernel configuration for loading Miosix entirely into external RAM with a bootloader.<br>All sections and the heap in external RAM.
Some boards have additional linker scripts reserving parts of RAM for special purposes (i.e. Safeguard Memory, SGM).
|-
|-
| MIOSIX_USER_CONFIG_PATH || Path to the config directory of your application. The default is <code>${CMAKE_SOURCE_DIR}/config</code>. If this directory does not exist, the defaults will be picked up (as the default config is in the search path).
| MIOSIX_USER_CONFIG_PATH || Path to the config directory of your application. The default is <code>${CMAKE_SOURCE_DIR}/config</code>. If this directory does not exist, the defaults will be picked up (as the default config is in the search path).
Line 52: Line 220:
| MIOSIX_ENABLE_LINKER_GC || Enables linker garbage collection (<code>-ffunction-sections -fdata-sections</code>). Default is ON (which is recommended for optimal code size).
| MIOSIX_ENABLE_LINKER_GC || Enables linker garbage collection (<code>-ffunction-sections -fdata-sections</code>). Default is ON (which is recommended for optimal code size).
|-
|-
|}
== Chip-defined internal variables ==
Each directory specific to a chip includes a CMakeLists.txt that defines a set of variables that describes that chip. This is the list of variables that these scripts need to define.
{| class="wikitable"
|-
! Variable !! Explanation
|-
| MIOSIX_CPU_INC || Path of the directory with Miosix include files for the CPU in this chip. The source files associated with the correct CPU are included in the MIOSIX_CHIP_SRC variable.
|-
| MIOSIX_MULTILIB_PATH || Path of the GCC multilibs for this CPU. Use by clang/LLVM support, to be removed in the future.
|-
| MIOSIX_CPU_FLAGS || Compiler flags selecting the CPU. Passed to the C and C++ compilers, and to the assembler and the C++ compiler while linking too.
|-
| MIOSIX_CHIP_{C&nbsp;&#124;&nbsp;CXX}_FLAGS || Additional flags for the chip. Usually includes a <code>-D_CHIP_{CHIP_NAME}</code> option to make Miosix aware of the chip choice.
|-
| MIOSIX_CHIP_SRC || List of chip and CPU specific files to be compiled with the Miosix kernel.
|}
|}

Latest revision as of 20:19, 17 September 2026

Miosix 3 introduces a new build system, based on CMake. The CMake build system has the same capabilities of the old Miosix Makefiles, and in addition it allows better composability of Miosix with other external projects.

Creating a kernelspace project with CMake

If you are following the instructions from the Getting started guides, init_project_out_of_git_tree.pl script should have already created a CMakeLists.txt file for you. For a simple Miosix project without processes or external libraries, the script will look like this (after the copyright notice):

cmake_minimum_required(VERSION 3.21)

# Set the path to the Miosix kernel
set(MIOSIX_KPATH ${CMAKE_SOURCE_DIR}/../../miosix)
# Configure CMake toolchain and build type.
# This must to be done before the project() command
set(CMAKE_TOOLCHAIN_FILE ${MIOSIX_KPATH}/cmake/Toolchains/gcc.cmake)
set(CMAKE_BUILD_TYPE "Release")

project(Main C CXX ASM)

# Select the board (mandatory). See the options in miosix/arch/CMakeLists.txt
set(MIOSIX_BOARD stm32...)
# User config path and linker script selection are optional
# set(MIOSIX_USER_CONFIG_PATH ${CMAKE_SOURCE_DIR}/config)
# set(MIOSIX_LINKER_SCRIPT unikernel.ld)

# Include the Miosix kernel's project
add_subdirectory(${MIOSIX_KPATH} miosix EXCLUDE_FROM_ALL)

# Define a kernel level program
add_executable(main main.cpp)
# target_include_directories(main PRIVATE here_your_includes)
# target_compile_options(main PRIVATE here_your_compile_options)
# target_link_directories(main PRIVATE here_your_link_directories)
# target_link_libraries(main PRIVATE here_your_libraries)

# Link the main target with Miosix. When specifying PROGRAM_DEFAULT, the
# `program' target will be available to flash it (type `make program' to use it)
miosix_link_target(main PROGRAM_DEFAULT)

Initial configuration of CMake

The first line of the CMakeLists.txt sets the required version of CMake to 3.21. This enables features required by the Miosix CMake scripts; the version number cannot be lowered.

After this line, the script sets a few initial configuration variables that only take effect if set before the project() command is called.

Setting the path to the kernel and the toolchain file

The first thing the script does is to set a MIOSIX_KPATH variable to the absolute path of the Miosix kernel's directory. We recommend that this path (and all other paths in a CMake project) should remain absolute, for extra robustness of your scripts.

Note The variable MIOSIX_KPATH is not used by the Miosix kernel's CMake scripts, it is only a helper variable used by the default application script.

Then, the script sets CMAKE_TOOLCHAIN_FILE to the path of one of the toolchain scripts in Miosix's directory. This is required to force CMake to use an embedded toolchain. At the moment only the default gcc.cmake toolchain file is supported.

Setting the build type

The script sets the CMAKE_BUILD_TYPE to the default build type, Release. Change this line to set a different build type, or remove the line to allow setting the build type from the command line.

Tip The available build types in CMake (which also apply to Miosix) are Debug, Release and RelWithDebInfo and MinSizeRel. Miosix does not add custom build types.
Warning Variables in CMake are not all created equal. All variables assigned with set() outside of a function are local to the current directory scope and its children (a new directory scope is created by add_subdirectory). Global configuration options are instead called "cache" variables, and they are set using the CACHE option of the set() command.

Miosix declares a minimum CMake version of 3.21 in order to allow overriding "cache" variables with standard (non-CACHE) set() commands. We find this to be a significant simplification of the semantics of cache variables: it removes a lot of surprising behaviour for beginners, and makes CMake files more coincise. However, a cache variable overridden like this cannot be set from the command line anymore.

This is why the line which sets CMAKE_BUILD_TYPE must be removed to allow setting the build type from the command line.

See the CMake documentation for more information about this topic.

Creating the Miosix binary

The rest of the script imports the Miosix kernel as a subdirectory, and then create an executable that links with the Miosix kernel: your application. There are a few Miosix-specific variables and functions that are used to help with this task.

Setting the board

The target board for the application is chosen by setting the MIOSIX_BOARD variable to the name of the board. The board names are the same ones previously used for the Makefile-based build system, and some of the supported boards are documented here on the Wiki on the Board list page.

The Board list on the Wiki is not complete. There are several ways to see the full list of supported boards:

  • Look at the contents of the miosix/arch/boards directory in the kernel's source tree. Each directory corresponds to a board, and the directory name is the same as the board name.
  • Open the miosix/arch/CMakeLists.txt file. At the beginning of the file, the MIOSIX_BOARDS variable is set to the list of all supported boards.
  • In your project's build directory, run cmake .. -DMIOSIX_PRINT_BOARD_LIST=ON.

The list of all supported boards is also printed if the board selected does not exist.

Setting the linker script

By default, the build system selects a linker script for compiling Miosix as a unikernel, with no provision for userspace applications. To select a different linker script, set the MIOSIX_LINKER_SCRIPT variable to the name of the script desired.

There are a few standard linker scripts available (not all of them are available for all boards):

  • unikernel.ld Baseline unikernel configuration. Default, available for all boards.
    .text/.rodata in Flash, .data/.bss/heap in internal RAM.
  • processes.ld Baseline fluid kernel configuration.
    .text/.rodata in Flash, .data/.bss/heap/process pool in internal RAM.
  • unikernel-xram-heap.ld Unikernel configuration using external RAM only for the heap.
    .text/.rodata in Flash, .data/.bss in internal RAM, heap in external RAM.
  • processes-xram.ld Fluid kernel configuration using external RAM only for the process pool.
    .text/.rodata in Flash, .data/.bss/heap in internal RAM, process pool in external RAM.
  • unikernel-xram.ld Unikernel configuration using external RAM.
    .text/.rodata in Flash, .data/.bss/heap in external RAM. Internal RAM is used for a statically allocated IRQ stack (also used at boot before external RAM is enabled).
  • processes-kernel-xram.ld Fluid kernel configuration using external RAM exclusively.
    .text/.rodata in Flash, .data/.bss/heap/process pool in external RAM. Internal RAM is used for a statically allocated IRQ stack (also used at boot before external RAM is enabled).
  • unikernel-all-in-xram.ld Unikernel configuration for loading Miosix entirely into external RAM with a bootloader.
    All sections and the heap in external RAM.

Some boards have additional linker scripts reserving parts of RAM for special purposes (i.e. Safeguard Memory, SGM).

The list of linker scripts available for a board can be obtained by passing -DMIOSIX_PRINT_LINKER_SCRIPT_LIST=ON to a CMake invocation.

If a linker script requires specific defines to be set for it to work, these defines are enabled automatically. For instance, the processes.ld linker script will automatically define WITH_PROCESSES in Miosix.

Selecting a Miosix configuration directory

If you desire to use a custom Miosix config directory with different kernel settings than the default, you shall set the MIOSIX_USER_CONFIG_PATH variable to the path of the Miosix config directory desired. A default config directory is created automatically by the init_project_out_of_git_tree.pl script, but you can create one manually simply by copying the miosix/config directory in the Miosix source tree.

Importing the Miosix kernel into the project

Once all Miosix configuration variables are set, you can include Miosix by calling the add_subdirectory() command passing the path to the miosix kernel directory.

Warning You need to add the miosix subdirectory, which is one of the top-level directories in the miosix-kernel repository, not miosix-kernel itself.
Note The default template CMakeLists.txt also passes two additional arguments to add_subdirectory():
  • The second argument (miosix) is necessary in case the Miosix kernel directory is not actually a subdirectory of your project, in order for CMake to properly create its internal directory structure in the build directory.
  • The third argument (EXCLUDE_FROM_ALL) removes Miosix from being a default compilation target, which is necessary as Miosix is effectively a library, not a target in and of itself.
See also the CMake documentation.

Adding the miosix subdirectory makes available the Miosix-defined helper functions, and a miosix static library target to link in your executable binary (i.e. the Flash or RAM image).

Creating the target binary

Once the miosix subdirectory has been imported, you can create a Miosix binary by adding an executable target with add_executable() linked with Miosix using the function miosix_link_target().

add_executable(main main.cpp ...)
miosix_link_target(main PROGRAM_DEFAULT)

While you could use the standard CMake command target_link_libraries() to link with Miosix, using miosix_link_target() performs the following additional modifications to the executable target:

  • Tells the linker to generate the map file
  • Registers custom targets to create the hex and bin files. The targets are called ${TARGET}_bin and ${TARGET}_hex (so, for the example above, main_bin and main_hex)
  • Registers a custom target to flash the program to the board ${TARGET}_program.

If PROGRAM_DEFAULT is also passed to the function, as in the example, it also defines the program target as an alias for ${TARGET}_program. By default, the size of the target .elf file is also printed at the end of the linking process, unless the NO_SIZE argument is also specified.

As a result of this, in our example, the CMake binary directory will contain the files:

  • main.elf: the main ELF format memory image
  • main.map: the map file produced by the linker
  • main.bin: a flat binary image obtained from main.elf, to be loaded at a base address decided by the board configuration
  • main.hex: a Intel HEX file image obtained from main.elf (useful if the memory areas to be programmed consist of more than one contiguous span).

Note that at the present time the name of the map, bin and hex files cannot be customized.

Creating a userspace binary with CMake

Adding one or more userspace process binaries to your Miosix CMake project involves adding the targets for the processes, and then creating a target for building the RomFs image.

First of all, remember to change the configuration of the Miosix kernel to enable userspace processes:

  • Set the linker script to processes.ld or to another linker script that supports processes
  • Enable the configuration options WITH_FILESYSTEM and WITH_PROCESSES.

A process target can be created using the miosix_add_process() function, which works in a similar way to add_executable():

miosix_add_process(
  <target> 
  <source1> <source2> ...
  [RAM_SIZE ram-size]
  [STACK_SIZE stack-size]
  [NO_STRIP_SECTHEADER]
)
  • <target> is the name of the process target to be created
  • <source1> <source2> ... is a list of source files to be compiled and linked in the executable
  • The RAM_SIZE and STACK_SIZE arguments allow to specify the size of the RAM and stack partitions (in bytes) that will be reserved for the process at runtime from the process pool. The defaults are 16384 and 2048 respectively.
  • If NO_STRIP_SECTHEADER is specified, the section headers are not stripped from the ELF file. These headers are not necessary in a valid executable (only the segment headers are required) so this flag is only useful for debugging purposes.

The miosix_add_process() performs automatically all the necessary configuration of the executable target, adding mandatory libraries and also enabling linker garbage collection and symbol stripping automatically.

Creating a RomFs

Finally, to create the RomFs image, the Miosix build system provides the miosix_add_romfs_image() function:

miosix_add_romfs_image(
  [PROGRAM_DEFAULT]
  IMAGE_NAME <name>
  KERNEL <kernel>
  DIR_NAME <dir_name>
  PROCESSES <process1> <process2> ...
)
  • <name> is the name of the image target (the resulting file will be named <name>.bin).
  • <kernel> is the name of the target linked to the Miosix kernel with miosix_link_target() whose binary should appear in the image leading the RomFs part.
  • <dir_name> is the name of a directory that will be created to collect all the contents of the image. Typically bin is a good name.
  • <process1> <process2> ... are the process targets to include in the image.

Like for miosix_link_target(), a target <name>_program is implicitly created for flashing the RomFs image. To make the program target flash the RomFs image, add the PROGRAM_DEFAULT argument to the function call. In that case, remove PROGRAM_DEFAULT (if present) from existing calls to miosix_link_target() to prevent redefinition of the program target.

How to build a Miosix application with CMake

Building Miosix with CMake follows the standard workflow that you expect from any other CMake project. Change directory to the root of the Miosix application you want to build and execute the following commands:

mkdir build
cd build
cmake ..
make

These commands assume your CMake configuration uses Unix Makefiles as the default generator.

Configuration options reference

As a reference, in the following we list the options provided by the Miosix CMake build system, settable via the command line or through your application's CMakeLists.txt.

Variable Explanation
MIOSIX_BOARD Name of the board Miosix should be configured for. This variable has no default and must be set from the command line or from the application's CMake scripts.
MIOSIX_BOARD_VARIANT Name of a board variant. A few boards define variants when there are jumpers, or different component fitting options, that are minor and do not warrant the definition of a different board. Default is the empty string, which is appropriate for most boards.
MIOSIX_LINKER_SCRIPT The linker script to use when linking executables with Miosix using miosix_link_target(). The linker script choice also influences compiler options by adding/removing defines that are required for Miosix to work with that linker script.

The standard linker script choices are listed in the #Setting the linker script section.

MIOSIX_USER_CONFIG_PATH Path to the config directory of your application. The default is ${CMAKE_SOURCE_DIR}/config. If this directory does not exist, the defaults will be picked up (as the default config is in the search path).
MIOSIX_USER_BOARD_SETTINGS_PATH Path to the config directory of the selected board. The default is ${MIOSIX_USER_CONFIG_PATH}/board/${MIOSIX_BOARD}. If this directory does not exist, the defaults will be picked up (as the default config is in the search path).
MIOSIX_ASM_FLAGS
MIOSIX_C_FLAGS
MIOSIX_CXX_FLAGS
MIOSIX_EXE_LINKER_FLAGS
Additional configuration flags that are passed to the compiler but are not necessary to build the kernel. You can customize these flags to change the warning level of compilers or linkers. Their use is not recommended.
MIOSIX_DISABLE_EXCEPTIONS When set to ON, exceptions are disabled. Reduces code size. Default is OFF. Always use this flag instead of adding -fno-exceptions to C(XX)FLAGS, as it enables extra flags required by Miosix.
MIOSIX_ENABLE_LINKER_GC Enables linker garbage collection (-ffunction-sections -fdata-sections). Default is ON (which is recommended for optimal code size).