115. Менеджеры сборки для прошивки: PlatformIO, west (Zephyr), CMake-пресеты
Alire у Ada и Cargo у Rust делают одно и то же: ставят компилятор, тянут
зависимости нужных версий и собирают проект одной командой. У C для
микроконтроллеров такого единого инструмента нет, и роль берут на себя
PlatformIO, west у Zephyr или CMake с файлом тулчейна и пресетами. Раздел
собирает одну и ту же прошивку — CRC-32 и мигание из разделов 113 и 114 —
через PlatformIO и через CMake-пресеты, для BluePill и STM32F4 Discovery,
в образе stm-pio:1, и показывает, где у каждого закреплены версии.
Ada и Alire — раздел 113, Rust и Cargo — раздел 114, CI/CD — раздел 110.
Как это называется в документации
Оригинал Перевод environment ( [env:…])окружение PlatformIO: плата, платформа, флаги platform, framework набор для семейства камней, библиотека поверх регистров package, tool пакет PlatformIO: тулчейн, фреймворк, инструмент manifest, west.ymlсписок репозиториев и их версий у Zephyr workspace рабочее дерево west со всеми проектами toolchain file файл тулчейна CMake: чем собирать для чужой машины presets ( CMakePresets.json)готовые наборы настроек CMake generator (Ninja) чем CMake исполняет сборку cross-compilation сборка на одной машине для другой pinning закрепление версии
115.1 PlatformIO: одна прошивка — две платы
Проект PlatformIO — файл platformio.ini и каталог src. Каждое окружение —
своя плата; платформа, фреймворк и флаги общие:
[env]
platform = ststm32@20.0.0 ; версия закреплена: иначе завтра приедет другая
framework = cmsis
build_flags = -Wall -Wextra -Os
[env:bluepill]
board = bluepill_f103c8
[env:disco407]
board = disco_f407vg
pio run сам поставил платформу ststm32 20.0.0, тулчейн
toolchain-gccarmnoneeabi 1.70201.0 — это GCC 7.2.1, — CMSIS для F1 4.3.5
и для F4 2.6.11 со стартовыми файлами. Отчёт pio run называет для BluePill
388 байт флеш-памяти и 28 байт ОЗУ, для Discovery — 396 и 28. Но во флеш-память
он засчитывает только .text, .rodata и .data, а таблицу векторов
(.isr_vector, 268 и 392 байта) и восемь байт .init_array и .fini_array
не считает: целиком образ — 664 и 796 байт. Камень код узнаёт по макросу,
который задаёт плата:
#if defined(STM32F103xB)
115.2 Версии: что закреплять
Незакреплённая платформа PlatformIO завтра приедет новой — с другим
компилятором и другим размером образа. Поэтому версию пишут прямо
в platform = ststm32@20.0.0. Тулчейн по умолчанию у этой платформы — GCC
7.2.1, давно не новый: другой компилятор задают отдельным пакетом
в platform_packages. У Alire то же делает строка gnat_arm_elf = "=16.1.0",
у Cargo версии крейтов закрепляет Cargo.lock, а сам компилятор — файл
rust-toolchain.toml с версией и целями: rustup ставит их сам при первой
сборке.
115.3 west и Zephyr
Zephyr — ОС для микроконтроллеров, и её проекты собирает west. Файл
west.yml перечисляет репозитории — само ядро, модули HAL, библиотеки —
и ревизию каждого; west update приводит рабочее дерево к ним, а
west build -b <плата> собирает CMake-проект с описанием платы из дерева
устройств. Рабочее дерево Zephyr занимает гигабайты, поэтому здесь его
не собирают; устроено оно так же, как всё в этом разделе: версии —
в манифесте, сборка — одной командой.
115.4 CMake: файл тулчейна и пресеты
Без менеджера та же прошивка собирается CMake. Файл тулчейна говорит, что собираем не для этой машины и чем:
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) # пробная сборка без компоновки: у голого камня нет libc-заглушек
file(GLOB _pio_gcc "$ENV{HOME}/.platformio/packages/toolchain-gccarmnoneeabi*/bin")
find_program(CMAKE_C_COMPILER arm-none-eabi-gcc HINTS ${_pio_gcc} REQUIRED)
set(CMAKE_ASM_COMPILER ${CMAKE_C_COMPILER})
Главная строка — CMAKE_C_COMPILER: без неё CMake возьмёт компилятор этой
машины — тот, что собирает программы для компьютера. Здесь
arm-none-eabi-gcc ищут сначала в пакете PlatformIO, потом в PATH. Ключи
ядра — -mcpu=cortex-m3 -mthumb для F103 и
-mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 для F407 —
задаёт CMakeLists.txt по переменной MCU, а её передают пресеты.
Пресеты сводят длинные командные строки к имени:
{ "name": "f103", "inherits": "base", "cacheVariables": { "MCU": "f103" } },
{ "name": "f407", "inherits": "base", "cacheVariables": { "MCU": "f407" } }
cmake --preset f103 и cmake --build --preset f103 собрали прошивку
тем же GCC 7.2.1 из пакета PlatformIO, со своим стартовым кодом из
раздела 113: 232 байта для F103 и 252 для F407. Это весь образ, с таблицей
векторов, и сравнивать его надо с образом PlatformIO — 664 и 796 байт.
Разница — таблица векторов камня в стартовом файле CMSIS (268 и 392 байта
против наших четырёх слов) и его более длинный стартовый код: один
__libc_init_array — 72 байта. В опыте CMake 4.4.3, PlatformIO 6.2.0.
115.5 Что выбрать
| Ставит тулчейн | Версии закреплены в | Одна команда | |
|---|---|---|---|
| PlatformIO | да | platformio.ini |
pio run |
| west (Zephyr) | нет, SDK отдельно | west.yml |
west build |
| CMake-пресеты | нет | образ или SDK | cmake --build --preset |
| Alire (Ada) | да | alire.toml |
alr build |
| Cargo (Rust) | через rustup по rust-toolchain.toml |
Cargo.lock и rust-toolchain.toml |
cargo build |
Для CI (раздел 110) удобнее всего то, что собирается в контейнере одной командой и с закреплёнными версиями, — любой из пяти, если версии действительно закреплены.
115.6 Грабли
Вчера собиралось, сегодня нет. Платформа PlatformIO не закреплена
и обновилась. Писать ststm32@20.0.0.
Компилятор оказался старым. Тулчейн по умолчанию у ststm32 20.0.0 — GCC 7.2.1.
CMake падает на проверке компилятора. Пробная сборка пытается
скомпоновать программу для голого камня; CMAKE_TRY_COMPILE_TARGET_TYPE
= STATIC_LIBRARY.
Скрипт компоновки не находит common.ld. INCLUDE ищет в путях -L.
Сборка на ноутбуке и в CI даёт разные образы. Тулчейн не из образа и не закреплён.
115.7 Итоги
- PlatformIO сам ставит платформу, тулчейн и CMSIS; одна прошивка —
окружение на каждую плату. Отчёт
pio runне считает таблицу векторов: 388 и 396 байт в отчёте, 664 и 796 — весь образ. - Версию платформы закрепляют: ststm32 20.0.0 тянет GCC 7.2.1.
- west у Zephyr — манифест репозиториев и сборка одной командой.
- CMake — файл тулчейна и пресеты: 232 и 252 байта со своим стартовым кодом.
- Во всех пяти инструментах главное одно: версии в файле, сборка одной командой.
Дальше: раздел 115а «CMake-проект прошивки: от .ioc до VS Code» — проект CubeMX для CMake.