Этот пример демонстрирует генерацию исходного кода во время сборки проекта с помощью Python скрипта. Показывает, как интегрировать внешние инструменты и скрипты в процесс сборки CMake.
- add_custom_target - создание пользовательских целей сборки
- add_custom_command - выполнение произвольных команд при сборке
- add_dependencies - управление зависимостями между целями
- find_package(Python) - поиск интерпретатора Python
- Генерация графа зависимостей проекта (Graphviz)
# Python 3 должен быть установлен
python3 --version
# Опционально: для визуализации графа зависимостей
sudo apt-get install graphviz # Ubuntu/Debian
brew install graphviz # macOS04_generate_code_from_python/
├── CMakeLists.txt # Конфигурация сборки
├── main.cpp # Программа, использующая сгенерированный код
├── generate_array.py # Python скрипт для генерации
├── data.json # Входные данные (массив чисел)
├── array.h # Сгенерированный заголовочный файл (создается при сборке)
└── README.md # Этот файл
- Python скрипт
generate_array.pyчитаетdata.json - Преобразует JSON массив в C++ код:
int arr[] = {1, 2, 4, 5, ...}; - Сохраняет результат в
array.h main.cppвключает сгенерированныйarray.h- Программа компилируется с использованием сгенерированных данных
mkdir build
cd build
cmake ..
make
# Запуск программы
./GenerateArray
# Просмотр сгенерированного файла
cat array.hfind_package(Python COMPONENTS Interpreter REQUIRED)Ищет интерпретатор Python в системе. Создает IMPORTED target Python::Interpreter, который можно использовать в командах.
Компоненты:
Interpreter- интерпретатор PythonDevelopment- заголовочные файлы и библиотеки для разработки расширенийNumPy- поддержка NumPy (опционально)
add_custom_target(
RunGenerator
BYPRODUCTS array.h
COMMAND Python::Interpreter ${PROJECT_SOURCE_DIR}/generate_array.py ...
DEPENDS generate_array.py data.json
COMMENT "Generating array from json"
)Параметры:
RunGenerator- имя целиBYPRODUCTS- файлы, которые будут созданы (для Ninja generator)COMMAND- команда для выполненияDEPENDS- зависимости; если эти файлы изменятся, цель будет пересобранаCOMMENT- сообщение при выполнении
Важно: add_custom_target всегда выполняется при сборке (если есть зависимости от этой цели).
| Аспект | add_custom_command | add_custom_target |
|---|---|---|
| Когда выполняется | Только если выходной файл устарел | Всегда (если есть зависимости) |
| Выходные файлы | Требуются (OUTPUT) | Опциональны (BYPRODUCTS) |
| Имя в make | Нет | Да (можно вызвать make RunGenerator) |
add_dependencies(GenerateArray RunGenerator)Устанавливает зависимость между целями. Гарантирует, что RunGenerator будет выполнен до сборки GenerateArray.
Без этого: компиляция может начаться до завершения генерации, что приведет к ошибке.
target_include_directories(GenerateArray PRIVATE ${CMAKE_BINARY_DIR})Добавляем директорию сборки в пути поиска, потому что array.h генерируется именно там.
В main.cpp:
#include "array.h" // Сгенерированный файл из CMAKE_BINARY_DIRadd_custom_target(graphviz ALL
"${CMAKE_COMMAND}" "--graphviz=foo" .
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}")Создает файл foo.dot с графом зависимостей проекта.
Визуализация:
cd build
dot -Tpng foo.dot -o graph.png
# или
dot -Tpng file.dot -o file.pngПараметры:
ALL- выполнять при каждой сборке--graphviz=foo- имя выходного файлаWORKING_DIRECTORY- где выполнять команду
Преобразование JSON/YAML конфигурации в C++ константы:
# config.json → config.h
const char* API_URL = "https://api.example.com";
const int MAX_RETRIES = 3;Генерация C++ классов из JSON Schema, Protocol Buffers, или других схем данных.
Встраивание файлов (изображений, шейдеров) в исполняемый файл:
# Convert image.png → image_data.h
const unsigned char image_data[] = {0x89, 0x50, 0x4E, ...};Создание lookup tables, таблиц CRC, и других предвычисленных данных.
- Откройте
data.jsonи измените массив:
[100, 200, 300]- Пересоберите проект:
cd build
make- CMake обнаружит изменение
data.jsonи автоматически перегенерируетarray.h
# Добавьте VERBATIM для точного выполнения команды
COMMAND Python::Interpreter ${PROJECT_SOURCE_DIR}/generate_array.py
VERBATIMУбедитесь, что:
- Добавлена зависимость:
add_dependencies(GenerateArray RunGenerator) - Директория сборки в include paths:
target_include_directories(...)
make VERBOSE=1| Аспект | 03_include_other_libraries | 04_generate_code_from_python |
|---|---|---|
| Внешние инструменты | Только библиотеки | Python скрипты |
| Генерация кода | Нет | Да |
| add_custom_target | Не используется | Используется |
| Зависимости целей | Неявные | Явные (add_dependencies) |
Изучите примеры в 05_supplementary для специальных возможностей CMake:
- Версионирование проекта
- Опциональные библиотеки
- configure_file для шаблонов
Затем переходите к 07-find-module для создания собственных Find-модулей.