Skip to content

Toolchain and Presets

Both the toolchain file and the preset file are per-project artifacts that arrive from CubeMX. They are not shared, though in practice every project carries the same content.

Two usable presets, both inheriting a hidden default:

{
"name": "default", "hidden": true,
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/${presetName}",
"toolchainFile": "${sourceDir}/cmake/gcc-arm-none-eabi.cmake",
"cacheVariables": { "CMAKE_EXPORT_COMPILE_COMMANDS": "ON" }
}
PresetCMAKE_BUILD_TYPEOptimizationUse it for
DebugDebug-O0 -g3anything you intend to step through
ReleaseRelWithDebInfo-Os -g0flight builds

Build output always lands at:

<project>/build/<preset>/<target>.elf e.g. src/bmc/build/Debug/bmc.elf

cmake/gcc-arm-none-eabi.cmake is what every preset points at. The parts worth knowing:

SettingValue
SystemCMAKE_SYSTEM_NAME Generic, processor arm
Compilersarm-none-eabi-gcc, -g++, -objcopy, -size
CPU flags-mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard
C++ flagsC flags plus -fno-rtti -fno-exceptions -fno-threadsafe-statics
Linker-T ${CMAKE_SOURCE_DIR}/STM32G431XX_FLASH.ld, --specs=nano.specs, --gc-sections
Try-compileSTATIC_LIBRARY (a freestanding target cannot link a test executable)

Two consequences worth remembering:

  • The compiler is resolved from PATH. The toolchain names the tools bare, so whichever arm-none-eabi-gcc comes first wins. /etc/profile.d/mrover-esw.sh puts CubeCLT ahead of the standalone fallback; ./scripts/doctor.sh warns when that ordering has gone stale.
  • The linker script path is fixed relative to the project root. Every project must keep its STM32G431XX_FLASH.ld at its own top level.

Every project also ships a toolchain file for ST’s LLVM distribution. No preset references it and build.sh has no way to select it, so it is inert. Using it means invoking CMake by hand with -DCMAKE_TOOLCHAIN_FILE=.