CMake Details

Overview

CMake is used to build your application together with the mJackets API. A CMake build is done in two stages. The first stage is called configuration. During configuration, the CMakeLists.txt build scripts are executed. After configuration is finished, CMake has an internal model of the mJackets API build, and can generate build scripts that are native to the host platform.

CMake supports generating scripts for several build systems, but only Make has tested to work with mJackets. After configuration, you begin the build stage by executing the generated build scripts. These build scripts can recompile the application without involving CMake following most code changes. However, after certain changes, the configuration step must be executed again before building. The build scripts can detect some of these situations and reconfigure automatically, but there are cases when this must be done manually.

mJackets uses CMake’s concept of a ‘target’ to organize the build. A target can be an executable, a library, or a generated file. For application developers, the library target is the most important to understand. All source code that goes into a mJackets build does so by being included in a library target, even application code.

Library targets have source code, that is added through CMakeLists.txt build scripts like this:

target_sources(app PRIVATE src/main.c)

In the above CMakeLists.txt, an existing library target named app is configured to include the source file src/main.c. The PRIVATE keyword indicates that we are modifying the internals of how the library is being built. Using the keyword PUBLIC would modify how other libraries that link with app are built. In this case, using PUBLIC would cause libraries that link with app to also include the source file src/main.c, behavior that we surely do not want. The PUBLIC keyword could however be useful when modifying the include paths of a target library.

Application CMakeLists.txt

Every application must have a CMakeLists.txt file. This file is the entry point, or top level, of the build system. The final <your_project>.elf image contains the application and API libraries.

This section describes some of what you can do in your top-level CMakeLists.txt. file. Make sure to follow these steps in order.

#. Add the model of your STM32 chip by setting the CHIP variable. This will allow CMake to configure your project for your specific chip by including the appropriate drivers, and generate the approriate linker script and startup files.

set(CHIP STM32F405RG)

Refer to supported chips for a complete list of supported chips.

The mJackets build system determines a value for CHIP by checking the following, in order (when a BOARD value is found, CMake stops looking further down the list):

  • Any previously used value as determined by the CMake cache takes highest precedence. This ensures you don’t try to run a build with a different CHIP value than you set during the build configuration step.

  • Any value given on the CMake command line (directly or indirectly via cmake build) using -DCHIP=YOUR_CHIP will be checked for and used next.

  • If an environment variable CHIP is set, its value will then be used.

  • Finally, if you set CHIP in your application CMakeLists.txt as described in this step, this value will be used.

  1. If using the template project structure, you will need to let CMake know that you want to configure the mJackets API and BSP CMake projects. To do this, add the below lines to your application CMakeLists.txt :

    add_subdirectory(mjackets-api)
    add_subdirectory(bsp)
    
  2. Now add any application source files to the project sources, and then create a target executable:

    set(PROJECT_SOURCES
            main.cpp
    )
    
    add_executable(${CMAKE_PROJECT_NAME} ${PROJECT_SOURCES})
    
  3. You then need to link all of the dependant libraries to your application. This can be done by linking to the API library using the target_link_libraries directive, which in turn includes all of the needed libraries.

target_link_libraries(${CMAKE_PROJECT_NAME} PUBLIC API)
  1. Finally, you can create an output binary using the STM32_ADD_HEX_BIN_TARGETS function:

STM32_ADD_HEX_BIN_TARGETS(${CMAKE_PROJECT_NAME})

Below is a simple example CMakeList.txt:

cmake_minimum_required(VERSION 3.14.7)

project(my_app LANGUAGES C CXX)

set(CHIP STM32F405RG)

add_subdirectory(mjackets-api)
add_subdirectory(bsp)

set(PROJECT_SOURCES
   main.cpp
)

add_executable(${CMAKE_PROJECT_NAME} ${PROJECT_SOURCES})

target_link_libraries(${CMAKE_PROJECT_NAME} PUBLIC API)

STM32_ADD_HEX_BIN_TARGETS(${CMAKE_PROJECT_NAME})

CMakeCache.txt

CMake uses a CMakeCache.txt file as persistent key/value string storage used to cache values between runs, including compile and build options and paths to library dependencies. This cache file is created when CMake is run in an empty build folder.

For more details about the CMakeCache.txt file see the official CMake documentation Running CMake .