CMake Basics
Every CMake-based application requires root CMakeLists.txt
file in the root directory, that describes the project and provides input information for build system generation.
Essential things described in CMakeLists.txt
file:
- Toolchain and compiler information
- Project name
- Source files to build with compiler, C, C++ or Assembly files
- List of include paths for compiler to find functions, defines, ... (
-I
) - MCU sepecific compiler flags
- Linker script path
- Compilation defines, or sometimes called preprocessor defines (
-D
)
Prepare CMakeList.txt file
This is the main CMake setup file.
-
Make new file in project root:
CMakeList.txt
-
Modify
project name
,linker file
, andMCU sepecific setting
. -
If you are using this project folder structure, you may run the bash script
.\getIncludeList.sh
and.\getSourceList.sh
to auto scan/Application
folder for generating CMake source list. -
Otherwise, you will have to modify
/camke/IncludeList.cmake
and/cmake/IncludeList.cmake
.
CMakeList.txt
# Define needed CMake verion
cmake_minimum_required(VERSION 3.22)
# Setup cmake module path and compiler settings
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
# Print current build type to console
message("Build type: " ${CMAKE_BUILD_TYPE})
# Setup C and C++ version
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Define current path for shorter reference below
set(PROJ_PATH ${CMAKE_CURRENT_SOURCE_DIR})
# Define .cmake module for toolchain compile flags that does holds true for all ARM projects
# This path is defined in the list() function above
set(CMAKE_TOOLCHAIN_FILE gcc-arm-none-eabi)
# Project Name --- MUST EDIT ---
project(L432KC-Template)
# Part of project name but made seperate for ease of editing project name
enable_language(C CXX ASM)
# Linker File --- MUST EDIT ---
set(linker_script_SRC ${PROJ_PATH}/Core/STM32L432KCUX_FLASH.ld)
# The use project name for binary file name
set(EXECUTABLE ${CMAKE_PROJECT_NAME})
# MCU Sepecific Setting --- MUST EDIT ---
# Make multiple for various STM32 core
# This path is defined in the list() function above
include(STM32L432xx_HAL_PARA)
# .cmake module generated by using .\getIncludeList.sh and .\getSourceList.sh
# Those two file contains all the project source file list and include list
# This path is defined in the list() function above
include(SourceList)
include(IncludeList)
# Executable files
add_executable(${EXECUTABLE} ${source_list})
# Include paths
target_include_directories(${EXECUTABLE} PRIVATE ${include_list})
# Project symbols
target_compile_definitions(${EXECUTABLE} PRIVATE ${compiler_define})
# Compiler options
target_compile_options(${EXECUTABLE} PRIVATE
${CPU_PARAMETERS}
-Wall
-Wpedantic
-Wno-unused-parameter
)
# Linker options
target_link_options(${EXECUTABLE} PRIVATE
-T${linker_script_SRC}
${CPU_PARAMETERS}
-Wl,-Map=${CMAKE_PROJECT_NAME}.map
--specs=nosys.specs
#-u _printf_float # STDIO float formatting support
-Wl,--start-group
-lc
-lm
-lstdc++
-lsupc++
-Wl,--end-group
-Wl,--print-memory-usage
)
# Execute post-build to print size
add_custom_command(TARGET ${EXECUTABLE} POST_BUILD
COMMAND ${CMAKE_SIZE} $<TARGET_FILE:${EXECUTABLE}>
)
# Convert output to hex and binary
add_custom_command(TARGET ${EXECUTABLE} POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -O ihex $<TARGET_FILE:${EXECUTABLE}> ${EXECUTABLE}.hex
)
# Convert to bin file -> add conditional check?
add_custom_command(TARGET ${EXECUTABLE} POST_BUILD
COMMAND ${CMAKE_OBJCOPY} -O binary $<TARGET_FILE:${EXECUTABLE}> ${EXECUTABLE}.bin
)