Skip to content

CMake Cookbook

Jamie Smith edited this page Mar 21, 2021 · 4 revisions

Here's how to do a couple of common tasks in your program's CMake buildfiles:

Adding an Executable

To add a new executable which can be flashed onto an Mbed processor, you'll need to use the add_mbed_executable() function. This works just like CMake's add_executable(), except that it runs some Mbed-specific code as well (creating the .bin file, printing the memory map, etc.). It will also automatically take care of linking mbed-os to your executable.

Here's an example:

set(FOO_SOURCES foo.cpp main.cpp)
add_mbed_executable(foo ${FOO_SOURCES})

Adding a Library

Code libraries can be created using the standard CMake method. Make sure to create only static libraries, shared libraries aren't supported for bare-metal targets like Mbeds.

If the code being built needs access to Mbed OS, you will need to link the mbed-os library using target_link_libraries(). Note that since these are static libraries no actual link step is performed, this just pulls in the needed flags and includes from mbed-os.

set(LIBBAR_SOURCES bar.cpp)

add_library(bar STATIC ${LIBBAR_SOURCES})
target_link_libraries(bar mbed-os)

If your library contains headers that other code needs to access, then you should apply these as target includes. This way, other libraries that link to this library will have them applied automatically:

set(LIBBAR_HEADER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include)
target_include_directories(bar PUBLIC ${LIBBAR_HEADER_DIR})

Adding Compile Flags

You can add extra compiler flags most easily using add_compile_options(). This will apply the flags to targets created in the current directory and all subdirectories.

add_compile_options(-Wextra -pedantic)

You can also add flags to an individual target (and optionally all other things that link to it):

target_compile_options(foo PRIVATE -funsigned-char)

Note that Mbed and CMake provide good defaults for most compilation options (including warnings and optimization) out of the box. Check the config file cmake/MBedOSConfig.cmake for more info.

Also, be aware that the mbed-cmake toolchain file initializes the CMAKE_C_FLAGS and CMAKE_CXX_FLAGS variables with the essential flags for your processor the first time you run CMake. You should not attempt to modify these variables on the command line or in your buildscript. It's very easy to do it incorrectly and accidentally wipe out all of the important flags! Use the methods above to set compile flags instead.

Changing the Project Name

The CMake project name is used in a couple places, such as the window title displayed in some IDEs. You will probably want to change that from the default of mbed-cmake. To do this, find this line in the top-level CMakeLists.txt:

project(mbed-cmake LANGUAGES C CXX ASM)

You can then change the first argument to whatever you want to name the project. You can also add VERSION and DESCRIPTION arguments per the documentation, but there are really only useful if you need access to these in other places in your code (such as configuring the version number into your project).

As for changing the banner text, that's up to you :)

Importing an MBed Library

MBed has a huge variety of libraries available to developers, and MBed's regular build system makes adding these libraries easy (if a bit unpredictable). Adding these to mbed-cmake is a bit more manual, but is still straightforward. Plus, by storing the library in the project, it's a lot easier to make your own changes and bugfixes! First, download the library and extract it to a folder somewhere in your project. Then, create a CMakeLists.txt in this folder and write a buildfile for the library. Finally, add that directory to the build by calling add_subdirectory() from a higher level buildfile.

The buildfiles for these libraries are usually quite simple. Here's an example of one we wrote for Maxim's MAX31856 driver:

set(MAX31856_SOURCES
        MAX31856.h
        MAX31856.cpp)

add_library(max31856 STATIC ${MAX31856_SOURCES})
target_include_directories(max31856 PUBLIC .)
target_link_libraries(max31856 mbed-os)