Общая информация
CMake - это единственная и неповторимая система сборки, которую мы используем. CMake позволяет собрать C++ проект в исполняемый файл, статическую или динамическую библиотеку на разных платформах, компиляторах и операционных системах.
Каждый этап сборки с помощью CMake состоит из трёх шагов:
- Конфигурация: на этом этапе задаются переменные окружения, компиляторы, конфигурация сборки, шаблоны и прочее. Выполняет роль описание того, как будет собираться проект, но сам процесс компиляции и линковки происходит не здесь.
- Сборка: на этом этапе происходит компиляция и линковка всех целей CMake (targets) в соответствии с конфигурацией из предыдущего этапа.
- Установка: готовые бинарные файлы, заголовки и файлы конфигурации собираются в пакет и устанавливаются в указанную директорию (префиксный путь). Это опциональный этап, но хорошим тоном является описывать шаг установки в своих CMake-файлах.
Конфигурация
Для конфигурации проекта необходимо вызвать команду cmake со следующими аргументами:
-S- папка, в которой лежит корневой CMakeLists.txt вашего проекта-B- папка, в которой вы хотите произвести сборку-G [Ninja|...]- генератор (подробнее про генераторы здесь). Мы используемNinjaв качестве основного генератора.-DCMAKE_BUILD_TYPE=[Release|Debug|MinSizeRel|RelWithDebugInfo]- шаблон сборки. Для релизных проектов всегда выбирайтеRelease, для разработки -Debug.-DBUILD_SHARED_LIBS=[ON|OFF]- выбор между статической/динамической версией сборки (только для библиотек). Для сборки динамической библиотеки используйтеON, в противном случае -OFF-DCMAKE_C_COMPILER=$PATH- выбор компилятора для языкаC. По умолчанию для генератораNinjaна ОС Linux этоgcc, на ОС Windows -mingw-w64-x86_64-gcc(если установлен) илиcl.exe(MSVC). Не указывайте этот аргумент в большинстве случаев.-DCMAKE_CXX_COMPILER=$PATH- аналогично предыдущему, выбор компилятора для языкаC++. По умолчанию для генератораNinjaна ОС Linux этоg++, на ОС Windows -mingw-w64-x86_64-g++илиcl.exe.--presetи-DCMAKE_TOOLCHAIN_PATH- подробнее об этом в статье про Conan. (здесь появится ссылка, когда я ее напишу!).
Примеры конфигурации проекта, лежащего в текущей рабочей директории:
Простая отладочная конфигурация
cmake -S . -B target/debug -G NinjaКонфигурация динамической библиотеки
cmake -S . -B target/release -G Ninja\
-DCMAKE_BUILD_TYPE="Release"\
-DBUILD_SHARED_LIBS=ONКонфигурация релизной динамической библиотеки с помощью Clang
cmake -S . -B target/release-clang -G Ninja\
-DCMAKE_BUILD_TYPE="Release"\
-DBUILD_SHARED_LIBS=ON\
-DCMAKE_C_COMPILER="/usr/bin/clang"\
-DCMAKE_CXX_COMPLILER="/usr/bin/clang++"Конфигурация для кросс-компиляции под Windows из ОС Linux
x86_64-w64-mingw32-cmake -S . -B target/release -G Ninja\
-DCMAKE_BUILD_TYPE="Release"\
-DBUILD_SHARED_LIBS=ONПримечание
Обратите внимание, что для кросс-компиляции под Windows на этапе конфигурации используется команда
x86_64-w64-mingw32-cmakeвместоcmake. Это необходимо для корректного выбора компилятора и настройки среды MinGW, Данная команда применяется только к этапу конфигурации. Дальнейшая сборка и установка будет выполняться обычной командойcmake.
Сборка
На этапе сборки проекта исходный код компилируется и линкуется в бинарные файлы.
Сборка любого проекта должна осуществляться командой cmake --build.
Замечание
Распостраненной плохой практикой является методика сборки проекта, где сначала производится конфигурация с помощью CMake, а затем прямой вызов генератора в директорию сборки (напр.
ninjaилиmake). Собирая проект таким образом, вы теряете возможность задавать аргументы сборки CMake и возможность быстро изменить генератор.
Аргументы сборки
--target <TARGET>- явно указывает, какая цель будет собрана (в случае если целей сборки в проекте несколько). По умолчанию собираются все цели.--config <Release/Debug/MinSizeRel/ReleaseWithDebugInfo>- конфигурация сборки (аналогично опции-DCMAKE_BUILD_TYPE=<TYPE>на этапе конфигурации.--clean-first- производит очистку кеша предыдущей сборки перед новой.--parallel- выполняет сборку на всех доступных ядрах устройства.-- <...>- прямая передача нативных аргументов в вызываемый генератор.
Примеры
Производит сборку уже сконфигурированного проекта:
cmake --build target --parallelПроизводит сборку уже сконфигурированного проекта в режиме Release:
cmake --build target --config "Release" --parallelПроизводит сборку только одной цели с именем binary-file:
cmake --build target --target "binary-file" --parallelЭкспорт
Любой хороший проект должен иметь секцию установки (install), также именуемую секцией экспорта.
Экспорт файлов выполняется после этапов конфигурации и сборки. В ходе экспорта публичные заголовочные файлы, собранные библиотеки, исполняемые файлы и прочие файлы на выбор разработчика помещаются в префиксный путь, т. е. папку, имеющую следующую структуру:
.
├── include
├── bin
├── lib/
│ └── cmake/
│ └── <libname>
└── share
Проект, который был экспортирован, можно подключать в другие проекты с помощью удобного инструмента поиска пакетов CMake - команды find_package(). Также такой проект легко использовать в связке с пакетными менеджерами - Conan, vcpkg и другими.
Экспорт проектных файлов производится с помощью команды cmake --install.
Аргументы экспорта
--prefix "<PATH>"- целевая папка, в которую будет экспортирован проект. По умолчанию зависит от системы и равна:C:\Program Files (x86)на ОС Windows;/usr/localили/usrна ОС Linux.
При установке в системные директории команду cmake --install необходимо запускать от имени администратора ОС (т.е. sudo cmake --install на ОС Linux).
Примеры
Установка в подпапку export существующей папки target:
cmake --install target --prefix "target/export"Установка в системные директории:
sudo cmake --install target # на ОС Linux
cmake --install target # на ОС Windows, требует запуска консоли от им. адм.Пример сборки проекта
Простая сборка и установка в локальную подпапку:
cmake -S . -B target -DCMAKE_BUILD_TYPE="Release"
cmake --build target --config "Release" --parallel
cmake --install target --prefix "target/export"Сборка проекта в режиме Debug:
cmake -S . -B target
cmake --build target --parallelСборка проекта с передачей особого префиксного пути, затем установка в этот же путь:
cmake -S . -B target -DCMAKE_BUILD_TYPE="Release" -DCMAKE_PREFIX_PATH="/usr/local/cmakelibs"
cmake --build target --config "Release" --parallel
sudo cmake --install target --prefix "/usr/local/cmakelibs"