Как запустить программу через cmake

Некоторое время назад мы познакомились с Autotools. Несмотря на то, что Autotools до сих пор используется во многих известных проектах с открытым исходным кодом, инструмент этот трудно назвать особо удобным. Кроме того, нормально работает он только в *nix системах, а в каком-нибудь Windows пользоваться Autotools, скажем так, весьма непросто. В общем, Autotools — это легаси, и нормальные программисты в наше время пытаются использовать CMake или, например, SCons. В этой заметке мы познакомимся с CMake.

Говоря простыми словами, CMake — это такая штука, в которой вы описываете проект, а она вам генерирует Makefile’ы в *nix системах, проекты Visual Studio под Windows, файлы конкретных редакторов и IDE, например Sublime Text, Code::Blocks, Eclipse или KDevelop, и так далее. Несмотря на спорный в некоторых моментах синтаксис, в последнее время CMake становится стандартом де-факто в мире C/C++. В частности, CMake используется в LLVM, Qt, MariaDB, Blender, KiCad, GNU Radio и ряде других проектов. Кроме того, в CLion, IDE для C/C++ от компании JetBrains, по умолчанию также создаются проекты, основанные на CMake.

Основы CMake

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

cmake_minimum_required ( VERSION 3.1 )

# так пишутся комментарии

find_library ( PTHREAD_LIBRARY pthread )
find_library ( PCRE_LIBRARY pcre )

include_directories ( include )
set ( CMAKE_CXX_STANDARD 17 )
set ( CMAKE_CXX_STANDARD_REQUIRED on )
set ( CMAKE_CXX_FLAGS » $ -Wall -Wextra -Werror» )

add_executable ( main src/Main.cpp src/HttpServer.cpp )

Хочется надеяться, какая строчка здесь что означает, пояснять не нужно. Затем исходники складываются в каталог src, а заголовочные файлы — в каталог include. Для сборки проекта говорим:

mkdir build
cd build
cmake ..
make

Просто, не правда ли?

Помимо приведенного выше find_library в CMake есть ряд скриптов для подключения конкретных библиотек. В частности, подключение OpenGL осуществляется как-то так:

find_package ( OpenGL REQUIRED )

CMake можно указать конкретный тип Makefile’ов, которые вы хотите получить на выходе:

cmake -G «Unix Makefiles» ..
cmake -G «MinGW Makefiles» ..
# для просмотра списка всех доступных генераторов:
cmake -G

В частности, многие программисты для ускорения сборки проектов предпочитают использовать Ninja:

cmake -G Ninja ..
ninja -j1

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

cmake -DCMAKE_BUILD_TYPE=Release -G Ninja ..
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -G Ninja ..
cmake -DCMAKE_BUILD_TYPE=MinSizeRel -G Ninja ..
# Debug используется по умолчанию
cmake -DCMAKE_BUILD_TYPE=Debug -G Ninja ..

Вместо запуска напрямую make или ninja можно сказать что-то вроде:

cmake —build . —config Release —target main

CMake основы

Можно выбрать конкретный компилятор для сборки проекта

cmake -DCMAKE_C_COMPILER= ` which clang `
-DCMAKE_CXX_COMPILER= ` which clang++ ` -G Ninja ..

… а также указать дополнительные флаги компиляции:

cmake -DCMAKE_C_FLAGS= «-O0 -g» -DCMAKE_CXX_FLAGS= «-O0 -g» ..

cmake -DCMAKE_C_FLAGS= «-O0 -g -fprofile-arcs -ftest-coverage»
-DCMAKE_EXE_LINKER_FLAGS= «-lgcov» ..

В мире C/C++ нередко бывает, что сторонние библиотеки, использующие CMake, подключаются к проекту при помощи сабмодулей Git. Подключение таких библиотек к проекту осуществляется довольно просто:

cmake_minimum_required ( VERSION 2.8 )

include_directories ( deps/algorithms/include )
add_subdirectory ( deps/algorithms/src )

add_executable ( rbtree_example rbtree_example.c )
target_link_libraries ( rbtree_example CAlgorithms )

В свою очередь, у библиотеки файл src/CMakeList.txt должен быть примерно таким:

cmake_minimum_required ( VERSION 2.8 )

add_library ( CAlgorithms STATIC
struct/ilist.c
struct/rbtree.c
struct/htable.c
common/utils.c
)

Вообще, add_subdirectory может принимать путь до любого каталога, в котором есть файл CMakeLists.txt. Это позволяет разбивать проект на подпроекты даже в рамках одного репозитория. Опять же, в случае с библиотеками это позволяет поместить тесты в отдельный подпроект, который не будет собираться при подключении библиотеки в сторонние проекты.

Например, в корне библиотеки CMakeList.txt может быть таким:

cmake_minimum_required ( VERSION 2.8 )

add_subdirectory ( src )
add_subdirectory ( test )

Непосредственно тесты добавляются в проект следующим образом:

cmake_minimum_required ( VERSION 2.8 )

set ( CMAKE_C_FLAGS » $ -O0 -g» )

add_executable ( test_htable test_htable.c )
target_link_libraries ( test_htable CAlgorithms )

add_executable ( test_rbtree test_rbtree.c )
target_link_libraries ( test_rbtree CAlgorithms )

add_test ( test_htable «./test_htable» )
add_test ( test_rbtree «./test_rbtree» )

Запуск тестов осуществляется простой командой:

make test
# или, с включением отладочного вывода:
make test ARGS = «-V»
# или, если используете Ninja:
ninja test

… выполненной в каталоге build. Если вас интересует тема написания модульных тестов на C++, она более подробно раскрыта в заметке Тестирование кода на C++ с помощью Google Test.

Если же вы используете какой-нибудь PyTest, просто допишите в CMakeList.txt что-то вроде:

find_package ( PythonInterp REQUIRED )

add_test ( NAME python_test
COMMAND py.test —capture=no $ /tests/run.py )

Вывод тестов пишется в файл Testing/Temporary/LastTest.log. Кстати, подробности о переменных окружения, доступных в CMake, таких, как CMAKE_SOURCE_DIR, можно найти здесь.

Помимо рассмотренных выше возможностей часто можно встретить поддержку сборки проектов с различными опциями. В частности, это используется в Assimp и LLDB. При сборке проекта опции выбираются так:

cmake -DLLDB_DISABLE_CURSES: BOOL =TRUE .
cmake -DASSIMP_BUILD_ASSIMP_TOOLS=OFF .

Опции обычно описывают в документации, но в крайнем случае их можно посмотреть и через curses-интерфейс:

В рамках одного поста, конечно, не представляется возможным рассмотреть все возможности CMake. Однако представленной выше информации вам должно вполне хватить в 90% случаев. Полноценные рабочие примеры использования CMake вы найдете, например, в этом, этом, а также в этом репозиториях на GitHub. Примеры использования опций и условных операторов можно найти в репозиториях уже упомянутых Assimp и LLDB. Ну и, конечно же, массу полезного вы найдете на официальном сайте CMake.

Читайте также:
Что такое партнерская программа в дзене

А пользуетесь ли вы CMake и если да, используете ли какие-то его возможности, о которых не было рассказано выше?

Вы можете прислать свой комментарий мне на почту, или воспользоваться комментариями в Telegram-группе.

Источник: eax.me

cmake(1)

CMake исполняемый интерфейс командной строки из buildsystem генератора кросс-платформенной CMake. В приведенном выше синопсисе перечислены различные действия, которые может выполнять инструмент, как описано в следующих разделах.

Чтобы создать программный проект с помощью CMake, создайте систему сборки проекта . При желании используйте cmake, чтобы создать проект , установить проект или просто запустить соответствующий инструмент сборки (например, make ) напрямую. cmake также можно использовать для просмотра справки .

Другие действия предназначены для использования разработчиками программного обеспечения, которые пишут скрипты на CMake language для поддержки своих сборок.

Для графических пользовательских интерфейсов, которые могут использоваться вместо cmake , смотрите ccmake и cmake-gui . Интерфейсы командной строки к средствам тестирования и упаковки CMake см. В ctest и cpack .

Для получения дополнительной информации о CMake в целом см. Также ссылки в конце этого руководства.

Введение в CMake Buildsystems

Система сборки описывает, как создавать исполняемые файлы и библиотеки проекта из исходного кода с помощью инструмента сборки для автоматизации процесса. Например, система сборки может быть Makefile для использования с инструментом make из командной строки или файлом проекта для интегрированной среды разработки (IDE). Чтобы избежать поддержки нескольких таких систем сборки, проект может указать свою систему сборки абстрактно, используя файлы, написанные на CMake language . Из этих файлов CMake генерирует предпочтительную систему сборки локально для каждого пользователя через серверную часть, называемую генератором .

Для создания системы сборки с CMake необходимо выбрать следующее:

Каталог верхнего уровня, содержащий исходные файлы, предоставленные проектом. Проект определяет свою систему сборки с использованием файлов, как описано в руководстве по cmake-language(7) , начиная с файла верхнего уровня с именем CMakeLists.txt . Эти файлы задают цели сборки и их зависимости, как описано в руководстве cmake-buildsystem(7) .

Каталог верхнего уровня, в котором должны храниться системные файлы сборки и выходные артефакты сборки (например, исполняемые файлы и библиотеки). CMake напишет файл CMakeCache.txt , чтобы идентифицировать каталог как дерево сборки и хранить постоянную информацию, такую ​​как параметры конфигурации системы сборки.

Чтобы сохранить исходное дерево исходных текстов, выполните сборку вне источника , используя отдельное выделенное дерево сборки. В истоке сборка , в котором дерево сборки находится в том же каталоге, что и исходного дерево , также поддерживается, но не рекомендуется.

Это выбирает тип системы сборки для генерации. См. Руководство по cmake-generators(7) для документации всех генераторов. Запустите cmake —help , чтобы увидеть список доступных локальных генераторов. При желании используйте опцию -G ниже, чтобы указать генератор, или просто примите выбор CMake по умолчанию для текущей платформы.

При использовании одного из генераторов инструментов сборки командной строки CMake ожидает, что среда, необходимая для цепочки инструментов компилятора, уже настроена в оболочке. При использовании одного из генераторов инструментов сборки IDE особой среды не требуется.

Сгенерировать систему сборки проектов

Запустите CMake с одной из следующих сигнатур команд,чтобы указать источник и построить деревья,а также сгенерировать систему сборки:

Использует текущий рабочий каталог в качестве дерева сборки, а — в качестве дерева исходного кода. Указанный путь может быть абсолютным или относительным к текущему рабочему каталогу. CMakeCache.txt дерево должно содержать файл CMakeLists.txt и не должно содержать файл CMakeCache.txt, поскольку последний идентифицирует существующее дерево сборки. Например:

$ mkdir build ; cd build $ cmake ../src

Использует в качестве дерева сборки и загружает путь к исходному дереву из его файла CMakeCache.txt , который, должно быть, уже был сгенерирован предыдущим запуском CMake. Указанный путь может быть абсолютным или относительным к текущему рабочему каталогу. Например:

$ cd build $ cmake .
cmake [] -S -B

Использует в качестве дерева сборки и в качестве дерева исходного кода. Указанные пути могут быть абсолютными или относительными к текущему рабочему каталогу. Исходное дерево должно содержать файл CMakeLists.txt . Дерево сборки будет создано автоматически, если оно еще не существует. Например:

$ cmake -S src -B build

Во всех случаях могут быть нулем или более из опций ниже.

Вышеупомянутые стили для указания исходного дерева и дерева построения могут быть смешанными. Пути, указанные с помощью -S или -B , всегда классифицируются как исходные или сборочные деревья соответственно. Пути, указанные с простыми аргументами, классифицируются на основе их содержимого и типов путей, заданных ранее. Если задан только один тип пути, для другого используется текущий рабочий каталог (cwd). Например:

Источник: runebook.dev

CMake и C++ — братья навек

Дружба навек

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

Многие ругают CMake, и часто заслуженно, но если разобраться, то не всё так плохо, а в последнее время очень даже неплохо, и направление развития вполне позитивное.

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

  1. Сборку;
  2. Автозапуск тестов;
  3. Замер покрытия кода;
  4. Установку;
  5. Автодокументирование;
  6. Генерацию онлайн-песочницы;
  7. Статический анализ.

Кто и так разбирается в плюсах и си-мейке может просто скачать шаблон проекта и начать им пользоваться.

Проект изнутри

Структура проекта

. ├── CMakeLists.txt ├── README.en.md ├── README.md ├── doc │ ├── CMakeLists.txt │ └── Doxyfile.in ├── include │ └── mylib │ └── myfeature.hpp ├── online │ ├── CMakeLists.txt │ ├── mylib-example.cpp │ └── wandbox.py └── test ├── CMakeLists.txt ├── mylib │ └── myfeature.cpp └── test_main.cpp

Главным образом речь пойдёт о том, как организовать CMake-скрипты, поэтому они будут разобраны подробно. Остальные файлы каждый желающий может посмотреть непосредственно на странице проекта-шаблона.

Читайте также:
Игровая программа чтобы радость людям дарить надо добрым и вежливым быть

Главный CMake-файл (./CMakeLists.txt)

Информация о проекте

В первую очередь нужно затребовать нужную версию системы CMake. CMake развивается, меняются сигнатуры команд, поведение в разных условиях. Чтобы CMake сразу понимал, чего мы от него хотим, нужно сразу зафиксировать наши к нему требования.

cmake_minimum_required(VERSION 3.13)

Затем обозначим наш проект, его название, версию, используемые языки и прочее (см. команду project ).

В данном случае указываем язык CXX (а это значит C++), чтобы CMake не напрягался и не искал компилятор языка C (по умолчанию в CMake включены два языка: C и C++).

project(Mylib VERSION 1.0 LANGUAGES CXX)

Здесь же можно сразу проверить, включён ли наш проект в другой проект в качестве подпроекта. Это сильно поможет в дальнейшем.

get_directory_property(IS_SUBPROJECT PARENT_DIRECTORY)

Опции проекта

Предусмотрим две опции.

Первая опция — MYLIB_TESTING — для выключения модульных тестов. Это может понадобиться, если мы уверены, что с тестами всё в порядке, а мы хотим, например, только установить или запакетировать наш проект. Или наш проект включён в качестве подпроекта — в этом случае пользователю нашего проекта не интересно запускать наши тесты. Вы же не тестируете зависимости, которыми пользуетесь?

option(MYLIB_TESTING «Включить модульное тестирование» ON)

Кроме того, мы сделаем отдельную опцию MYLIB_COVERAGE для замеров покрытия кода тестами, но она потребует дополнительных инструментов, поэтому включать её нужно будет явно.

option(MYLIB_COVERAGE «Включить измерение покрытия кода тестами» OFF)

Опции компиляции

Разумеется, мы крутые программисты-плюсовики, поэтому хотим от компилятора максимального уровня диагностик времени компиляции. Ни одна мышь не проскочит.

add_compile_options( -Werror -Wall -Wextra -Wpedantic -Wcast-align -Wcast-qual -Wconversion -Wctor-dtor-privacy -Wenum-compare -Wfloat-equal -Wnon-virtual-dtor -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wsign-conversion -Wsign-promo )

Расширения тоже отключим, чтобы полностью соответствовать стандарту языка C++. По умолчанию в CMake они включены.

if(NOT CMAKE_CXX_EXTENSIONS) set(CMAKE_CXX_EXTENSIONS OFF) endif()

Основная цель

Наша библиотека состоит только из заголовочных файлов, а значит, мы не располагаем каким-либо выхлопом в виде статических или динамических библиотек. С другой стороны, чтобы использовать нашу библиотеку снаружи, её нужно установить, нужно, чтобы её можно было обнаружить в системе и подключить к своему проекту, и при этом вместе с ней были привязаны эти самые заголовки, а также, возможно, какие-то дополнительные свойства.

Для этой цели создаём интерфейсную библиотеку.

add_library(mylib INTERFACE)

Привязываем заголовки к нашей интерфейсной библиотеке.

Современное, модное, молодёжное использование CMake подразумевает, что заголовки, свойства и т.п. передаются через одну единственную цель. Таким образом, достаточно сказать target_link_libraries(target PRIVATE dependency) , и все заголовки, которые ассоциированы с целью dependency , будут доступны для исходников, принадлежащих цели target . И не требуется никаких [target_]include_directories . Это будет продемонстрировано ниже при разборе CMake-скрипта для модульных тестов.

Также стоит обратить внимание на т.н. выражения-генераторы: $ <. >.

Данная команда ассоциирует нужные нам заголовки с нашей интерфейсной библиотекой, причём, в случае, если наша библиотека будет подключена к какой-либо цели в рамках одной иерархии CMake, то с ней будут ассоциированы заголовки из директории $/include , а если наша библиотека установлена в систему и подключена в другой проект с помощью команды find_package , то с ней будут ассоциированы заголовки из директории include относительно директории установки.

target_include_directories(mylib INTERFACE $/include> $ )

Установим стандарт языка. Разумеется, самый последний. При этом не просто включаем стандарт, но и распространяем его на тех, кто будет использовать нашу библиотеку. Это достигается за счёт того, что установленное свойство имеет категорию INTERFACE (см. команду target_compile_features).

target_compile_features(mylib INTERFACE cxx_std_17)

Заводим псевдоним для нашей библиотеки. Причём для красоты он будет в специальном «пространстве имён». Это будет полезно, когда в нашей библиотеке появятся разные модули, и мы заходим подключать их независимо друг от друга. Как в Бусте, например.

add_library(Mylib::mylib ALIAS mylib)

Установка

Установка наших заголовков в систему. Тут всё просто. Говорим, что папка со всеми заголовками должна попасть в директорию include относительно места установки.

install(DIRECTORY include/mylib DESTINATION include)

Далее сообщаем системе сборки о том, что мы хотим иметь возможность в сторонних проектах звать команду find_package(Mylib) и получать цель Mylib::mylib .

install(TARGETS mylib EXPORT MylibConfig) install(EXPORT MylibConfig NAMESPACE Mylib:: DESTINATION share/Mylib/cmake)

Следующее заклинание нужно понимать так. Когда в стороннем проекте мы вызовем команду find_package(Mylib 1.2.3 REQUIRED) , и при этом реальная версия установленной библиотеки окажется несовместимой с версией 1.2.3 , CMake автоматически сгенерирует ошибку. То есть не нужно будет следить за версиями вручную.

include(CMakePackageConfigHelpers) write_basic_package_version_file(«$/MylibConfigVersion.cmake» VERSION $ COMPATIBILITY AnyNewerVersion ) install(FILES «$/MylibConfigVersion.cmake» DESTINATION share/Mylib/cmake)

Тесты

Если тесты выключены явно с помощью соответствующей опции или наш проект является подпроектом, то есть подключён в другой CMake-проект с помощью команды add_subdirectory , мы не переходим дальше по иерархии, и скрипт, в котором описаны команды для генерации и запуска тестов, просто не запускается.

if(NOT MYLIB_TESTING) message(STATUS «Тестирование проекта Mylib выключено») elseif(IS_SUBPROJECT) message(STATUS «Mylib не тестируется в режиме подмодуля») else() add_subdirectory(test) endif()

Документация

Документация также не будет генерироваться в случае подпроекта.

if(NOT IS_SUBPROJECT) add_subdirectory(doc) endif()

Онлайн-песочница

Аналогично, онлайн-песочницы у подпроекта тоже не будет.

if(NOT IS_SUBPROJECT) add_subdirectory(online) endif()

Скрипт для тестов (test/CMakeLists.txt)

Тестирование

Первым делом находим пакет с нужным тестовым фреймворком (замените на свой любимый).

find_package(doctest 2.3.3 REQUIRED)

Создаём наш исполняемый файл с тестами. Обычно непосредственно в исполняемый бинарник я добавляю только файл, в котором будет функция main .

add_executable(mylib-unit-tests test_main.cpp)

А файлы, в которых описаны сами тесты, добавляю позже. Но так делать не обязательно.

target_sources(mylib-unit-tests PRIVATE mylib/myfeature.cpp)

Подключаем зависимости. Обратите внимание, что к нашему бинарнику мы привязали только нужные нам CMake-цели, и не вызывали команду target_include_directories . Заголовки из тестового фреймворка и из нашей Mylib::mylib , а также параметры сборки (в нашем случае это стандарт языка C++) пролезли вместе с этими целями.

target_link_libraries(mylib-unit-tests PRIVATE Mylib::mylib doctest::doctest )

Читайте также:
Что выявляет служебная программа проверка диска

Наконец, создаём фиктивную цель, «сборка» которой эквивалентна запуску тестов, и добавляем эту цель в сборку по умолчанию (за это отвечает атрибут ALL ). Это значит, что сборка по умолчанию инициирует запуск тестов, то есть мы никогда не забудем их запустить.

add_custom_target(check ALL COMMAND mylib-unit-tests)

Покрытие

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

find_program(GCOVR_EXECUTABLE gcovr) if(MYLIB_COVERAGE AND GCOVR_EXECUTABLE) message(STATUS «Измерение покрытия кода тестами включено») target_compile_options(mylib-unit-tests PRIVATE —coverage) target_link_libraries(mylib-unit-tests PRIVATE gcov) add_custom_target(coverage COMMAND $ —root=$/include/ —object-directory=$ DEPENDS check ) elseif(MYLIB_COVERAGE AND NOT GCOVR_EXECUTABLE) set(MYLIB_COVERAGE OFF) message(WARNING «Для замеров покрытия кода тестами требуется программа gcovr») endif()

Скрипт для документации (doc/CMakeLists.txt)

find_package(Doxygen)

Дальше проверяем, установлена ли пользователем переменная с языком. Если да, то не трогаем, если нет, то берём русский. Затем конфигурируем файлы системы Doxygen. Все нужные переменные, в том числе и язык попадают туда в процессе конфигурации (см. команду configure_file ).

После чего создаём цель doc , которая будет запускать генерирование документации. Поскольку генерирование документации — не самая большая необходимость в процессе разработки, то по умолчанию цель включена не будет, её придётся запускать явно.

if (Doxygen_FOUND) if (NOT MYLIB_DOXYGEN_LANGUAGE) set(MYLIB_DOXYGEN_LANGUAGE Russian) endif() message(STATUS «Doxygen documentation will be generated in $») configure_file(Doxyfile.in Doxyfile) add_custom_target(doc COMMAND $ $/Doxyfile) endif ()

Скрипт для онлайн-песочницы (online/CMakeLists.txt)

Тут находим третий Питон и создаём цель wandbox , которая генерирует запрос, соответствующий API сервиса Wandbox, и отсылает его. В ответ приходит ссылка на готовую песочницу.

Проект снаружи

Теперь рассмотрим, как этим всем пользоваться.

Сборка

Сборка данного проекта, как и любого другого проекта на системе сборки CMake, состоит из двух этапов:

Генерация

cmake -S путь/к/исходникам -B путь/к/сборочной/директории [опции . ]

Если команда выше не сработала из-за старой версии CMake, попробуйте опустить -S :

cmake путь/к/исходникам -B путь/к/сборочной/директории [опции . ]

Подробнее про опции.

Сборка проекта

cmake —build путь/к/сборочной/директории [—target target]

Подробнее про сборочные цели.

Опции

MYLIB_COVERAGE

cmake -S . -B . -DMYLIB_COVERAGE=ON [прочие опции . ]

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

MYLIB_TESTING

cmake -S . -B . -DMYLIB_TESTING=OFF [прочие опции . ]

Предоставляет возможность выключить сборку модульных тестов и цель check . Как следствие, выключается замер покрытия кода тестами (см. MYLIB_COVERAGE ).

Также тестирование автоматически отключается в случае, если проект подключается в другой проект качестве подпроекта с помощью команды add_subdirectory .

MYLIB_DOXYGEN_LANGUAGE

cmake -S . -B . -DMYLIB_DOXYGEN_LANGUAGE=English [прочие опции . ]

Переключает язык документации, которую генерирует цель doc на заданный. Список доступных языков см. на сайте системы Doxygen.

По умолчанию включён русский.

Сборочные цели

По умолчанию

cmake —build path/to/build/directory cmake —build path/to/build/directory —target all

Если цель не указана (что эквивалентно цели all ), собирает всё, что можно, а также вызывает цель check .

mylib-unit-tests

cmake —build path/to/build/directory —target mylib-unit-tests

Компилирует модульные тесты. Включено по умолчанию.

check

cmake —build путь/к/сборочной/директории —target check

Запускает собранные (собирает, если ещё не) модульные тесты. Включено по умолчанию.

См. также mylib-unit-tests .

coverage

cmake —build путь/к/сборочной/директории —target coverage

Анализирует запущенные (запускает, если ещё не) модульные тесты на предмет покрытия кода тестами при помощи программы gcovr.

Выхлоп покрытия будет выглядеть примерно так:

—————————————————————————— GCC Code Coverage Report Directory: /path/to/cmakecpptemplate/include/ —————————————————————————— File Lines Exec Cover Missing —————————————————————————— mylib/myfeature.hpp 2 2 100% —————————————————————————— TOTAL 2 2 100% ——————————————————————————

Цель доступна только при включённой опции MYLIB_COVERAGE .

doc

cmake —build путь/к/сборочной/директории —target doc

Запускает генерацию документации к коду при помощи системы Doxygen.

wandbox

cmake —build путь/к/сборочной/директории —target wandbox

Ответ от сервиса выглядит примерно так:

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

Примеры

Сборка проекта в отладочном режиме с замером покрытия

cmake -S путь/к/исходникам -B путь/к/сборочной/директории -DCMAKE_BUILD_TYPE=Debug -DMYLIB_COVERAGE=ON cmake —build путь/к/сборочной/директории —target coverage —parallel 16

Установка проекта без предварительной сборки и тестирования

cmake -S путь/к/исходникам -B путь/к/сборочной/директории -DMYLIB_TESTING=OFF -DCMAKE_INSTALL_PREFIX=путь/к/установойной/директории cmake —build путь/к/сборочной/директории —target install

Сборка в выпускном режиме заданным компилятором

cmake -S путь/к/исходникам -B путь/к/сборочной/директории -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=g++-8 -DCMAKE_PREFIX_PATH=путь/к/директории/куда/установлены/зависимости cmake —build путь/к/сборочной/директории —parallel 4

Генерирование документации на английском

cmake -S путь/к/исходникам -B путь/к/сборочной/директории -DCMAKE_BUILD_TYPE=Release -DMYLIB_DOXYGEN_LANGUAGE=English cmake —build путь/к/сборочной/директории —target doc

Инструменты

  1. CMake 3.13
    На самом деле версия CMake 3.13 требуется только для запуска некоторых консольных команд, описанных в данной справке. С точки зрения синтаксиса CMake-скриптов достаточно версии 3.8, если генерацию вызывать другими способами.
  2. Библиотека тестирования doctest
    Тестирование можно отключать (см. опцию MYLIB_TESTING ).
  3. Doxygen
    Для переключения языка, на котором будет сгенерирована документация, предусмотрена опция MYLIB_DOXYGEN_LANGUAGE .
  4. Интерпретатор ЯП Python 3
    Для автоматической генерации онлайн-песочницы.

Статический анализ

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

Cppcheck

В CMake встроена поддержка инструмента для статического анализа Cppcheck.

Для этого нужно воспользоваться опцией CMAKE_CXX_CPPCHECK :

cmake -S путь/к/исходникам -B путь/к/сборочной/директории -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_CPPCHECK=»cppcheck;—enable=all;-Iпуть/к/исходникам/include»

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

Clang

При помощи чудесного инструмента scan-build тоже можно запускать статический анализ в два счёта:

scan-build cmake -S путь/к/исходникам -B путь/к/сборочной/директории -DCMAKE_BUILD_TYPE=Debug scan-build cmake —build путь/к/сборочной/директории

Здесь, в отличие от случая с Cppcheck, требуется каждый раз запускать сборку через scan-build .

Послесловие

CMake — очень мощная и гибкая система, позволяющая реализовывать функциональность на любой вкус и цвет. И, хотя, синтаксис порой оставляет желать лучшего, всё же не так страшен чёрт, как его малюют. Пользуйтесь системой сборки CMake на благо общества и с пользой для здоровья.

→ Скачать шаблон проекта

Источник: temofeev.ru

Рейтинг
( Пока оценок нет )
Загрузка ...
EFT-Soft.ru