- Знакомство с CMake. Часть 1. Установка, CMakeLists.txt, сборка.
- Введение.
- Установка в Linux.
- Установка в Windows.
- Cmake windows cmakelists txt
- Структура CMakeLists.txt
- Автогенерация проекта для Visual Studio (Windows)
- Зависимости между библиотеками и приложениями
- Выбор стандарта и диалекта C++
- Функции в CMake
- Добавление исходников к цели с target_sources
- Интерфейс к утилитам командной строки
- Функция find_package
- Записки программиста
- Основы сборки проектов на С/C++ при помощи CMake
- Дневник программиста
- вторник, 10 апреля 2012 г.
- Пример заготовки CMakeList.txt для простого проекта
- Введение в CMake
- CMakeLists.txt для простого проекта
Знакомство с CMake. Часть 1. Установка, CMakeLists.txt, сборка.
Введение.
Многие, кто начинал создавать собственные программы, пользовался какой-либо системой сборки. В общем, система сборки – это набор инструментов, облегчающий работу с компилятором. Это включает в себя компиляцию, линковку, установку, а также сбор исходных файлов для передачи их компилятору и слежение за зависимостями. Также современные системы сборки облегчают работу с библиотеками, позволяют создавать переносимые проекты и выполняют ещё массу других вкусностей. Эта статья посвящена популярной системе сборки CMake и расскажет, как правильно её установить и настроить, а также будет рассмотрен простой пример её использования. Она рассчитана на тех, что хоть немного знаком с понятиями make, Makefile, компиляция, линковка.
Установка в Linux.
Для популярных дистрибутивов Linux типа Debian, Gentoo, Fedora и т.д. CMake давно лежит в официальных репозиториях. Нам нужно всего лишь установить пакет cmake с помощью менеджера пакетов. Как правило, он устанавливается в системные директории, и необходимости править переменные окружения нету. Можете проверить её работоспособность, выполнив
Если же в репозитории нет такого пакета, то можно его собрать вручную. Скачиваем Unix/Linux Source, например, cmake-3.5.0-rc3.tar.gz, распаковываем и собираем:
Если нет необходимости устанавливать в системную /usr директорию, можно в аргументе —prefix прописать нужный корень установки. По умолчанию, без явного указания —prefix, установка будет произведена в /usr/local. -j используется для ускорения сборки, например, на 4-х ядерном процессоре можно указать -j4, и сборка будет вестись параллельно в 4 потока.
Установка в Windows.
Для Windows на сайте CMake лежит установочный файл msi. Рекомендую при установке отметить галочку добавления пути в переменные окружения PATH для всех пользователей. Тогда, после перелогинивания, CMake будет доступен из любого места. Проверить можно, открыв cmd и выполнив тот же
Cmake windows cmakelists txt
На первом шаге проект нужно сконфигурировать, то есть создать финальный скрипт сборки, запустив cmake в будущем каталоге сборки.
На втором шаге нужно запустить финальный скрипт. Не вызывайте make ! Утилита cmake сделает это сама:
Структура CMakeLists.txt
В начале главного файла CMakeLists.txt ставят метаинформацию о минимальной версии CMake и названии проекта:
Затем следует список инструкций, служащих для вычисления различных переменных, создания целей сборки, подключения проектов из подкаталогов и так далее. Например, подключить дополнительный CMakeLists.txt из подкаталога можно так:
Целью может стать исполняемый файл, собираемый из исходного кода
Целью также может быть библиотека, статическая или динамическая.
Автогенерация проекта для Visual Studio (Windows)
Если используется Visual C++, то путь немного другой: на шаге конфигурирования создаётся проект для Visual Studio, который затем можно собрать из IDE либо так же из командной строки.
Созданный проект Visual Studio нельзя изменять и использовать постоянно, потому что при генерации проекта используются абсолютные пути и другие неприемлемые для постоянной работы вещи.
Если проект был сконфигурирован успешно, то в каталоге ../myapp-build появятся автоматически сгенерированный BUILD_ALL.sln и проекты для Visual Studio. Их можно открыть к IDE, либо собрать из командной строки с помощью cmake. Названия опций говорят сами за себя:
Зависимости между библиотеками и приложениями
Не используйте директивы include_directories , add_definitions , add_compile_options ! Они меняют глобальные настройки для всех целей, это создаёт проблемы при масштабировании.
- Используйте target_link_libraries для добавления статических и динамических библиотек, от которых зависит цель
- Используйте target_include_directories вместо include_directories для добавления путей поиска заголовков, от которых зависит цель
- Используйте target_compile_definitions вместо add_definitions для добавления макросов, с которыми собирается цель
- Используйте target_compile_options для добавления специфичных флагов компилятора, с которыми собирается цель
Вы можете выбирать область видимости настройки:
- PUBLIC делает настройку видимой для текущей цели и для всех зависящих от неё целей
- PRIVATE делает настройку видимой только для текущей цели
- INTERFACE делает настройку видимой только для всех зависящих от неё целей
Пример использования областей видимости:
Схема зависимостей условного проекта:
Выбор стандарта и диалекта C++
Для настройки стандарта и флагов языка C++ не добавляйте флаги напрямую!
В CMake версии 3.8+ вы можете прямо потребовать включить нужный стандарт:
В CMake версии до 3.7 включительно можно использовать set_target_properties (если не работает, то у вас слишком старый CMake):
Для разработчиков библиотек есть более тонкий контроль над возможностями языка:
Функции в CMake
CMake позволяет объявлять функции командами function(name) / endfunction() и макросы командами macro(name) / endmacro() . Предпочитайте функции, а не макросы, т.к. у функций есть своя область видимости переменных, а у макросов — нет.
Добавление исходников к цели с target_sources
Лучше добавлять специфичные исходники с помощью target_sources, а не с помощью дополнительных переменных.
Интерфейс к утилитам командной строки
Функция find_package
Функция find_package принимает имя библиотеки как аргумент и обращается к CMake, чтобы найти скрипт для настройки переменных данной библиотеки. В итоге при сборке либо возникает ошибка из-за того что пакет не найден, либо добавляются переменные, хранящие пути поиска заголовков, имена библиотек для компоновщика и другие параметры.
Пример подключения Boost, вызывающего встроенный в CMake скрипт FindBoost:
Пример подключения библиотеки Bullet с помощью встроенного скрипта FindBullet и компоновки с приложением my_app:
Записки программиста
Основы сборки проектов на С/C++ при помощи 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 в простейшем случае выглядит следующим образом. В корне репозитория создается файл 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 » $
add_executable ( main src/Main.cpp src/HttpServer.cpp )
Хочется надеяться, какая строчка здесь что означает, пояснять не нужно. Затем исходники складываются в каталог src, а заголовочные файлы — в каталог include. Для сборки проекта говорим:
Просто, не правда ли?
Помимо приведенного выше find_library в CMake есть ряд скриптов для подключения конкретных библиотек. В частности, подключение OpenGL осуществляется как-то так:
find_package ( OpenGL REQUIRED )
CMake можно указать конкретный тип Makefile’ов, которые вы хотите получить на выходе:
В частности, многие программисты для ускорения сборки проектов предпочитают использовать Ninja:
Выбор между отладочной и релизной сборкой осуществляется так:
Вместо запуска напрямую make или ninja можно сказать что-то вроде:
Можно выбрать конкретный компилятор для сборки проекта
… а также указать дополнительные флаги компиляции:
В мире 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 » $
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» )
Запуск тестов осуществляется простой командой:
… выполненной в каталоге build. Если вас интересует тема написания модульных тестов на C++, она более подробно раскрыта в заметке Тестирование кода на C++ с помощью Google Test.
Если же вы используете какой-нибудь PyTest, просто допишите в CMakeList.txt что-то вроде:
find_package ( PythonInterp REQUIRED )
add_test ( NAME python_test
COMMAND py.test —capture=no $
Вывод тестов пишется в файл Testing/Temporary/LastTest.log. Кстати, подробности о переменных окружения, доступных в CMake, таких, как CMAKE_SOURCE_DIR, можно найти здесь.
Помимо рассмотренных выше возможностей часто можно встретить поддержку сборки проектов с различными опциями. В частности, это используется в Assimp и LLDB. При сборке проекта опции выбираются так:
Опции обычно описывают в документации, но в крайнем случае их можно посмотреть и через curses-интерфейс:
В рамках одного поста, конечно, не представляется возможным рассмотреть все возможности CMake. Однако представленной выше информации вам должно вполне хватить в 90% случаев. Полноценные рабочие примеры использования CMake вы найдете, например, в этом, этом, а также в этом репозиториях на GitHub. Примеры использования опций и условных операторов можно найти в репозиториях уже упомянутых Assimp и LLDB. Ну и, конечно же, массу полезного вы найдете на официальном сайте CMake.
А пользуетесь ли вы CMake и если да, используете ли какие-то его возможности, о которых не было рассказано выше?
Дневник программиста
вторник, 10 апреля 2012 г.
Пример заготовки CMakeList.txt для простого проекта
Введение в CMake
Утилита cmake является кроссплатформенной утилитой с открытым исходным кодом (open source), используемой для создания традиционных сценариев сборки проектов для следующих платформ.
- Unix/Linux -> Makefile (для утилиты GNU make)
- Windows -> VS Projects/Workspaces
- Apple -> Xcode
Процесс сборки проекта, при использовании cmake, состоит из следующих этапов.
- Создание файла конфигурации CMakeLists.txt в котором через систему команд, свойств и переменных описываются исходные файлы проекта, цель сборки и все сопутствующие сборке детали.
- Выполнение утилиты cmake. При это будет произведена обработка файла конфигурации CMakeLists.txt в процессе которой будет сгенерирован файл традиционного для данной операционной системы сценария сборки. Например, Makefile.
- Выполнение традиционных сценариев сборки. Например, утилитой make.
Используя специальные генераторы можно привязать систему CMake к определенным системам сборки, таким как Qt, Borland C++ Builder, MS Visual C++ и пр. Это свойство системы, само по себе интересно, но привязка кроссплатформенной сборки к какому-то конкретному продукту, выглядит, в общем случае, неразумно. Не считая, разумеется, вариант с поддержкой Qt SDK. Здесь особый разговор, так как сборка остается кроссплатформенной, но составляет альтернативу собственной системе сборки для Qt, qmake, которая не лишена некоторых недостатков.
Я вспоминаю о CMake всегда, когда не делаю проект в Qt. Вот почему.
- Проект не привязывается к какой-то среде разработке и его можно писать хоть в vim. Для небольших проектов это исключительно удобно. Для тех, кто относится к vim с предубеждением путь представят себе вместо vim любой другой редактор плоского кода с подсветкой синтаксиса, который им кажется удобным. Сейчас таких много под любой платформой.
- Проект удобно передавать в виде исходников для сборки у заказчика или какого-то иного лица потребляющего этот код. Удобно в контексте его простой компиляции. Не придется ставить среду разработки. Потребуется только наличие CMake, а это уже может быть много проще. Особенно с этим нет проблем в Linux.
- Сборка проекта по Makefile, который был сгенерирован системой CMake достаточно зрелищная. Во-первых, выполняется в цвете, а, во-вторых, с отображением процента исполнения.
Из написанного выше не следует, что CMake удобен только для небольших проектов. Просто большие проекты это дело особого обсуждения. Часто тут решение принимает не один человек и, в некоторых случаях, это решение определяется самой постановкой задачи. Зачем, например, городить огород, если задача заказана в MS Visual Studio и будет использована только там. В случае, если CMake допустим для проекта, то это позволит получить удобства описанные в списке выше.
Изучение системы CMake особая тема по которой через Google можно найти много статей и специальной документации. Цель данной статьи — дать простую заготовку конфигурационного файла системы CMake. Создавая в консоли новый проект надо будет просто скопировать эту заготовку и внести в нее изменения характерные для вашего проекта.
CMakeLists.txt для простого проекта
Итак, мы начали простой проект. Создали каталог my-project и создали в нем подкаталог src для размещения источников кода нашего проекта. Напишем заготовку в файл src/main.cpp и теперь настроим CMake для сборки по этому проекту. Потом мы будем добавлять в сборку новые файлы и, возможно, библиотеки. Отразим все эти возможности в нашей заготовке.
Конфигурационный файл для системы CMake должен называться CMakeLists.txt. Расположим его в каталоге my-project и получим следующую систему файлов.
Представим шаблон файла CMakeLists.txt для простого проекта.
Рассмотрим значение представленных в файле команд.
cmake_minimum_required — выставляет требование по минимальной версии CMake, требуемой для обработки даного файла конфигурации.
) — задает имя проекта. Необходимо учитывать, что дополнительной функцией данной команды является установка переменных
_SOURCE_DIR в значение имени каталога проекта.
set — задает значение переменной для дальнейшего использования. Здесь создаем переменную SRC_DIR по значению подставленному из предопределенной переменной PROJECT_SOURCE_DIR и подстроки «/src». Чтобы получить значение переменной, её идентификатор надо поместить в фигурные скобки и предварить знаком доллара — $<. >.
include_directories — добавить указанный в скобках каталог к списку каталогов поиска заголовочных файлов. В одной команде можно указать несколько каталогов заголовочных файлов, разделив их пробелом.
link_directories — добавить указанный в скобках каталог к списку каталогов поиска библиотек для линковки. В одной команде можно указать несколько каталогов библиотек, разделив их пробелом.
list с первым аргументом APPEND выполняет добавление к списку, указанному вторым аргументом, элемента заданного третьим аргументом. В нашем случае, к списку под именем SRC добавлено имя файла main.cpp с путем, указанным значением переменной SRC_DIR.
add_executable — для сборки исполняемого файла представленного первым аргументом добавляет компиляционные листы, которые будут образованы по списку файлов источников, заданных вторым аргументом — значением списка SRC.