Программирование ARM cmake FAQ Wed, October 22 2025  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.


cmake FAQ Печать
Добавил(а) microsin   

Описание решения различных вопросов, возникающих в проектах, где используется CMake.

В CMake с переменными окружения можно работать напрямую в CMakeLists.txt — читать, устанавливать и проверять их наличие. Вот основные способы и важные нюансы.

[Чтение и проверка переменных окружения]

Для чтения переменных окружения в CMake используется синтаксис `$ENV{VAR_NAME}`.

# Вывести значение переменной HOME
message(STATUS "Home directory: $ENV{HOME}")

Чтобы проверить, определена ли переменная, используйте команду `if(DEFINED ENV{...})`:

# Проверка существования переменной
if(DEFINED ENV{MY_VARIABLE})
message(STATUS "MY_VARIABLE is set to: $ENV{MY_VARIABLE}")
else()
message(WARNING "MY_VARIABLE is not set.")
endif()

Альтернативный способ — проверить, не является ли значение переменной пустой строкой:

if(NOT "$ENV{MY_VARIABLE}" STREQUAL "")

    message(STATUS "MY_VARIABLE has a value: $ENV{MY_VARIABLE}")
endif()

[Установка и удаление переменных]

Установить переменную окружения на время выполнения CMake можно с помощью `set(ENV{...})`:

# Установить переменную
set(ENV{MY_VARIABLE} "my_value")

Удалить переменную можно с помощью `unset()`:

# Удалить переменную
unset(ENV{MY_VARIABLE})

Важно: установленные таким способом переменные действуют только в процессе CMake и не влияют на систему или вызывающую оболочку.

[Практическое применение: условная логика и значения по умолчанию]

Переменные окружения удобно использовать для условной логики в сборке. Например, можно установить значение по умолчанию, если переменная не определена:

# Установить значение по умолчанию, если переменная окружения не задана
if(NOT DEFINED ENV{BUILD_TYPE})
set(BUILD_TYPE "Release")
else()
set(BUILD_TYPE "$ENV{BUILD_TYPE}")
endif()

message(STATUS "Build type: ${BUILD_TYPE}")

Или управлять флагами компиляции:

# Включить отладочный режим на основе переменной окружения
if(DEFINED ENV{ENABLE_DEBUG} AND "$ENV{ENABLE_DEBUG}" STREQUAL "1")
add_compile_definitions(-DDEBUG)
message(STATUS "Debug mode enabled")
endif()

[Важные ограничения и предупреждения]

1. Область видимости: переменные, установленные через `set(ENV{...})`, видны только в текущем процессе CMake (на этапе конфигурации) и не передаются в целевые программы (исполняемые файлы) при их запуске.

2. Этап сборки (Build Time): переменные, установленные во время конфигурации (вызова `cmake`), **не передаются автоматически** командам сборки (например, внутри `add_custom_command()`). Для этого нужно использовать аргументы команды или другие методы.

3. Отсутствие отслеживания изменений: CMake не отслеживает изменения переменных окружения. Если вы измените переменную в оболочке и повторно запустите сборку (`cmake --build`), CMake не переконфигурируется автоматически. Чтобы изменения вступили в силу, необходимо повторно запустить конфигурацию (`cmake`).

В CMake есть несколько способов вывести значения переменных. Вот основные методы:

[Основной способ - команда message()]

# Вывод обычного сообщения
message("Простое сообщение")

# Вывод статуса (префикс --)
message(STATUS "Информационное сообщение")

# Вывод предупреждения (желтый цвет в большинстве терминалов)
message(WARNING "Предупреждение")

# Вывод ошибки (красный цвет, прерывает конфигурацию)
message(FATAL_ERROR "Критическая ошибка")

[Вывод значений переменных]

# Установим тестовые переменные
set(MY_VARIABLE "Hello World")
set(MY_LIST "item1" "item2" "item3")

# Вывод простой переменной
message(STATUS "MY_VARIABLE = ${MY_VARIABLE}")

# Вывод переменной окружения
message(STATUS "HOME directory = $ENV{HOME}")

# Вывод встроенных переменных CMake
message(STATUS "CMAKE_VERSION = ${CMAKE_VERSION}")
message(STATUS "CMAKE_SOURCE_DIR = ${CMAKE_SOURCE_DIR}")
message(STATUS "CMAKE_BINARY_DIR = ${CMAKE_BINARY_DIR}")
message(STATUS "CMAKE_CURRENT_SOURCE_DIR = ${CMAKE_CURRENT_SOURCE_DIR}")

[Вывод списков]

# Создаем список
set(MY_LIST "apple" "banana" "cherry")

# Вывод всего списка
message(STATUS "MY_LIST = ${MY_LIST}")

# Вывод элементов списка по одному
foreach(item IN LISTS MY_LIST)
message(STATUS " - ${item}")
endforeach()

[Практические примеры для отладки]

Отладка компиляторов:

message(STATUS "=== CMake Configuration ===")
message(STATUS "C compiler: ${CMAKE_C_COMPILER}")
message(STATUS "C++ compiler: ${CMAKE_CXX_COMPILER}")
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")

Отладка путей:

message(STATUS "=== Paths ===")
message(STATUS "Source dir: ${CMAKE_SOURCE_DIR}")
message(STATUS "Binary dir: ${CMAKE_BINARY_DIR}")
message(STATUS "Current source dir: ${CMAKE_CURRENT_SOURCE_DIR}")
message(STATUS "Current binary dir: ${CMAKE_CURRENT_BINARY_DIR}")

Отладка найденных пакетов:

find_package(Python3 COMPONENTS Interpreter)
if(Python3_FOUND)
message(STATUS "Python3 found: ${Python3_EXECUTABLE}")
message(STATUS "Python3 version: ${Python3_VERSION}")
else()
message(WARNING "Python3 not found")
endif()

[Форматированный вывод]

# Вывод с разделителями
message(STATUS "")
message(STATUS "=== Build Summary ===")
message(STATUS "Project: ${PROJECT_NAME}")
message(STATUS "Version: ${PROJECT_VERSION}")
message(STATUS "System: ${CMAKE_SYSTEM_NAME}")
message(STATUS "Processor: ${CMAKE_SYSTEM_PROCESSOR}")
message(STATUS "")

[Важные моменты]

1. Типы сообщений:

   - `STATUS` - для информации (видно при `cmake -S . -B build`)
   - `WARNING` - для предупреждений
   - `FATAL_ERROR` - останавливает конфигурацию

2. Время вывода - сообщения выводятся во время конфигурации CMake, а не во время сборки.

3. Для отладки условий:

if(SOME_CONDITION)
message(STATUS "Condition is TRUE")
else()
message(STATUS "Condition is FALSE")
endif()

Эти методы помогут вам эффективно отлаживать CMake скрипты и понимать, какие значения принимают переменные в процессе конфигурации.

Эта строка в CMakeLists.txt ищет и проверяет наличие системы контроля версий Git в системе.

Синтаксис:

find_package(Git)

Что это делает:

1. Поиск исполняемого файла Git - ищет программу `git` в системных путях (PATH).

2. Устанавливает переменные - после выполнения создаются несколько CMake переменных:

   - `Git_FOUND` - булева переменная, указывающая найден ли Git
   - `GIT_EXECUTABLE` - полный путь к исполняемому файлу git
   - `GIT_VERSION_STRING` - версия установленного Git

3. Проверяет доступность - позволяет скрипту узнать, доступна ли команда git.

Типичное использование:

# Ищем Git
find_package(Git)

# Проверяем, найден ли Git
if(Git_FOUND)
message(STATUS "Git found: ${GIT_EXECUTABLE}")
message(STATUS "Git version: ${GIT_VERSION_STRING}")
else()
message(WARNING "Git not found - some features may be unavailable")
endif()

Зачем это нужно в CMake проектах:

1. Автоматическое управление версиями:

if(Git_FOUND)
# Получить текущий хэш коммита
execute_process(
COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD
OUTPUT_VARIABLE GIT_COMMIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
)

# Установить в препроцессорные определения
add_compile_definitions(GIT_COMMIT_HASH="${GIT_COMMIT_HASH}")
endif()

2. Включение информации о версии в приложение:

if(Git_FOUND)
# Получить тег версии
execute_process(
COMMAND ${GIT_EXECUTABLE} describe --tags
OUTPUT_VARIABLE GIT_VERSION_TAG
OUTPUT_STRIP_TRAILING_WHITESPACE
)
endif()

3. Проверка наличия зависимостей:

find_package(Git REQUIRED)  # Остановить сборку если Git не найден

Варианты использования:

- `find_package(Git)` - просто проверить наличие
- `find_package(Git REQUIRED)` - обязательное требование, ошибка если не найден
- `find_package(Git QUIET)` - тихий режим без вывода сообщений

Эта команда особенно полезна для проектов, которые хотят автоматически включать информацию о версии из Git или выполнять Git-операции во время сборки.

Переменная CMAKE_TOOLCHAIN_FILE в CMake служит для указания файла инструментария (toolchain), который определяет настройки для кросс-компиляции или специфичной платформы.

Основное назначение: CMAKE_TOOLCHAIN_FILE позволяет настроить CMake для сборки под целевую платформу, отличную от хостовой системы, где выполняется компиляция.

Как используется:

# При вызове cmake
$ cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=/path/to/toolchain.cmake

Или в коде:

set(CMAKE_TOOLCHAIN_FILE "/path/to/toolchain.cmake")

[Что обычно содержится в toolchain файле]

Базовые настройки компилятора:

# Компиляторы
set(CMAKE_C_COMPILER /path/to/arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER /path/to/arm-linux-gnueabihf-g++)

# Системный процессор
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)

# Пути поиска библиотек для целевой системы
set(CMAKE_FIND_ROOT_PATH /path/to/sysroot)

Флаги компиляции:

# Флаги компилятора
set(CMAKE_C_FLAGS "-march=armv8-a -mfpu=neon")
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}")

# Флаги линковки
set(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed")

[Практические примеры использования]

1. Встраиваемые системы (Embedded)

# Для STM32 (ARM Cortex-M)
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_C_COMPILER arm-none-eabi-gcc)
set(CMAKE_CXX_COMPILER arm-none-eabi-g++)
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

2. Кросс-компиляция для другой ОС

# Компиляция для Windows из Linux
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc)
set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++)

3. Для LuckFox Pico

# toolchain-luckfox.cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)

set(CMAKE_C_COMPILER ${SDK_PATH}/toolchain/bin/arm-rockchip830-linux-uclibcgnueabihf-gcc)
set(CMAKE_CXX_COMPILER ${SDK_PATH}/toolchain/bin/arm-rockchip830-linux-uclibcgnueabihf-g++)

# Пути поиска библиотек целевой системы
set(CMAKE_FIND_ROOT_PATH ${SDK_PATH}/sysroot)

[Ключевые переменные в toolchain файле]

- `CMAKE_SYSTEM_NAME` - целевая ОС (Linux, Windows, Generic)
- `CMAKE_SYSTEM_PROCESSOR` - архитектура процессора (arm, x86_64, aarch64)
- `CMAKE_C_COMPILER`, `CMAKE_CXX_COMPILER` - пути к компиляторам
- `CMAKE_FIND_ROOT_PATH` - корневой путь для поиска библиотек целевой системы
- `CMAKE_SYSROOT`** - системный корень для заголовков и библиотек

[Преимущества использования]

1. Изоляция настроек - все специфичные настройки в одном файле
2. Повторное использование - один toolchain файл для нескольких проектов
3. Чистота CMakeLists.txt - не загромождается платформо-специфичным кодом
4. Упрощение командной строки - не нужно передавать множество `-D` параметров

[Пример полного toolchain файла]

# toolchain-arm-linux.cmake
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)

# Компиляторы
set(CMAKE_C_COMPILER /opt/toolchain/bin/arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER /opt/toolchain/bin/arm-linux-gnueabihf-g++)

# Sysroot
set(CMAKE_SYSROOT /opt/sysroot/arm-linux-gnueabihf)

# Правила поиска библиотек
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

Таким образом, CMAKE_TOOLCHAIN_FILE - это фундаментальный механизм CMake для работы с кросс-компиляцией и специфичными платформами, что особенно актуально для встраиваемых систем типа LuckFox Pico.

Переменная @D в файлах *.mk пакетов Buildroot нужна для ссылки на каталог сборки пакета. Например, для LuckFox Buildroot это каталог buildroot-2023.02.6/output/build/имя_пакета.

@D обычно используется в хуках файла *.mk пакета для ручной модификации файлов перед их компиляцией. Например, следующий хук файла v4l2rtspserver.mk удалит использование библиотеки libv4l2cpp в пакете v4l2rtspserver:

define V4L2RTSPSERVER_REMOVE_LIBV4L2CPP
$(SED) 's/git submodule update --init//' $(@D)/CMakeLists.txt
$(SED) 's/add_subdirectory(libv4l2cpp EXCLUDE_FROM_ALL)//' $(@D)/CMakeLists.txt
$(info =[2]=====================================================)
$(info @D: $(@D))
$(info =========================================================)
endef

V4L2RTSPSERVER_POST_PATCH_HOOKS += V4L2RTSPSERVER_REMOVE_LIBV4L2CPP

После добавления этого хука в файл v4l2rtspserver.mk необходимо выполнить заново конфигурирование пакета командами:

$ make v4l2rtspserver-dirclean
$ make v4l2rtspserver

[Ссылки]

1. Step 1: A Basic Starting Point site:cmake.org.
2. Writing CMakeLists Files site:cmake.org.

 

Добавить комментарий


Защитный код
Обновить

Top of Page