Aceki / cmake-study

Заметки о системе сборки CMake.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

CMAKE STUDY

Генераторы:

Генераторами называются компоненты инструмента CMake, отвечающие за создание проектов для конечных систем построения. Для каждой поддерживаемой системы (make, Microsoft Visual Studio определенной версии и т.д.) существует свой генератор. Выбор конкретного генератора задаётся в командной строке CMake при помощи ключа "-G".

$ cmake -G "Visual Studio 14 2015" ..\project_src

Полный список имён поддерживаемых генератором для данной версии можно узнать при помощи команды:

$ cmake --help

Ключ "-A" позволяет указать целевую платформу (ARM, x64, и т.д.)


Входные файлы:

Входными файлами для программы CMake являются файлы CMakeLists.txt, лежащие в корне каталога проекта (с файлами исходных кодов). Путь к каталогу проекта предаётся инструменту CMake в качестве последнего аргумента командной строки. Крупные проекты могут также содержать подкаталоги с проектами нижнего уровня, каждый из которых будет иметь в корне свой файл CMakeLists.txt Кроме файлов CMakeLists.txt также могут использоваться файлы с расширением ".cmake". Эти файлы могут подключаться из программы на языке CMake при помощи директивы include(...), вызываться при исполнении команды find_package(...) (модули поиска или конфигурационные файлы) или передаваться инструменту CMake для исполнения при помощи ключа "-P"


Комментарии:

# - Однострочный комментарий.
#[[ ]] - Блочный комментарий.

Команды общего назначения:

Команда cmake_minimum_required(...) определяет минимальную версию инструмента CMake, при помощи которого можно обрабатывать текущий входной файл проекта. Аргумент {версия} может содержать до 4 чисел, разделенных точками. Команду cmake_minimum_required(...) рекомендуется указывать самой первой в файле CMakeLists.txt верхнего уровня.

cmake_minimum_required(VERSION {версия} [FATAL_ERROR])

Команда project(...) устанавливает имя для иерархии проектов. Например, для генераторов Microsoft Visual Studio это имя определяет имя создаваемого решения.

project({имя_проекта} [VERSION {версия}] [LANGUAGES {язык1} ... {языкN}])
  • После аргумента VERSION можно указать версию проекта - строку, содержащую до 4 чисел, разделенных точками. Установка версии проекта доступна в CMake начиная с версии 3.0.
  • После необязательного аргумента LANGUAGES указываются языки программирования, для которых обеспечивается поддержка в проекте.

Команда include(...) загружает из внешнего файла и исполняет заданный модуль CMake. Модуль может задаваться при помощи пути к файлу, либо только именем модуля (без пути и расширения). В последнем случае файл с именем {модуль}.cmake ищется в каталогах, список которых задан переменной CMAKE_MODULE_PATH (по умолчанию пустая), и затем в каталоге стандартных модулей, поставляемых вместе с CMake.

include({файл} | {модуль} [OPTIONAL] [RESULT_VARIABLE {имя_переменной}])

Команда message(...) предназначена для вывода сообщения различными утилитами, интерпретирующими входной файл.

message([{режим}] {строка1} ... {строка2})
{режим} = STATUS | WARNING | AUTHOR_WARNING | SEND_ERROR | FATAL_ERROR | DEPRECATION

Команды генерации целей:

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

add_executable({логическое_имя_цели} [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL] {исходный_модуль1} ... {исходный_модульN})

Изменить имя можно при помощи установки свойства OUTPUT_NAME цели.

set_property(TARGET {имя_цели} PROPERTY OUTPUT_NAME {имя_выходного_файла})

CMAKE_RUNTIME_OUTPUT_DIRECTORY содержит имя подкатолога построения. Использование аргумента WIN32 приведёт к отключению консоли при построении на платформе Windows. Для остальных платформ этот аргумент игнорируется. Передача аргумента EXCLUDE_FROM_ALL приведет к тому, что генерируемая цель будет исключена из цели "all".

Первая форма команды add_library(...) аналогична команде add_executable(...), но создаёт цель для построения библиотеки.

add_library({логическое_имя_цели} [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] {исходный_модуль1} ... {исходный_модульN})
add_library({логическое_имя_цели} {тип_библиотеки = SHARED | STATIC | MODULE | UNKNOWN} IMPORTED)

Тип библиотеки можно задать при помощи необязательного аргумента:

  • STATIC: статическая;
  • SHARED: динамическая (разделяемая);
  • MODULE: разделяемая, предназначенная исключительно для загрузки при помощи функций API (POSIX dlopen() и т.п.). Такой тип библиотеки используется для реализации загружаемых модулей (plugins).

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

Имя свойства Тип библиотеки
CMAKE_ARCHIVE_OUTPUT_DIRECTORY статические(+импорта)
CMAKE_RUNTIME_OUTPUT_DIRECTORY DLL
CMAKE_LIBRARY_OUTPUT_DIRECTORY модули, разделяемые

Размещение библиотек в разных ОС стр. 85

Вторая форма команды add_library(...) предназначена для добавления к проекту внешней заранее собранной библиотеки (как правило, сторонней). Как и для предыдущей формы команды, создаётся цель с заданным логическим именем, которая по умолчанию имеет область видимости текущего каталога построения и ниже и которую можно использовать, как и остальные цели библиотек, для связывания с другими целями проекта при помощи команды target_link_libraries(...). Однако в этом случае не создаётся никаких правил построения библиотеки.

Чтобы указать местоположение файла библиотеки для создаваемой цели, необходимо записать его в свойство цели IMPORTED_LOCATION, а также в свойства IMPORTED_LOCATION_DEBUG и т.д. для каждой используемой конфигурации. Для получения пути к исполняемому файлу библиотеки можно использовать команду find_library(...).

Команда add_subdirectory(...) добавляет к построению подпроект, расположенный заданном подкаталоге. В нём должен находиться файл CMakeLists.txt с описанием подпроекта.

add_subdirectory({подкаталог_проекта} [{подкаталог_построения}] [EXCLUDE_FROM_ALL])

Имеет смысл указывать относительный путь к каталогу.

  • При помощи необязательного аргумента {подкаталог_построения} можно указать подкаталог для выходных и промежуточных файлов проекта.

Команды настроек целей

Команда include_directories(...) добавляет указанные каталоги к списку каталогов в которых компилятор должен искать заголовочные файлы, подключаемые директивами #include. Эти каталоги добавляются к соответствующему свойству всех целей, определенных в текущем файле CMakeLists.txt. Относительные пути интерпретируются по отношению к текущему каталогу исходных файлов проекта.

include_directories([AFTER | BEFORE] [SYSTEM] {каталог1} ... {каталогN})
  • При помощи необязательного аргумента BEFORE или AFTER можно сообщить команде, что заданные в ней каталоги должны добавляться в начало или конец списка каталогов для поиска
  • При помощи аргумента SYSTEM можно сообщить, что указанные каталоги являются системными (относящимися к компилятору).

Результат исполнения команды target_include_directories(...) аналогичен вызову команды include_directories(...), основные же отличия состоят в следующем:

  • В аргументе команды указывается имя цели к которой она относится. Команда влияет на соответствующие свойства этой цели, в то время как команда include_directories(...)_ влияет на свойство каталога проекта (т.е. действует на все цели, определяемые в текущем подпроекте).
  • Есть возможность указать, будут ли использованы указанные в аргументах команды каталоги для компиляции самой цели или для зависимых от неё целей.
target_include_directories({имя_цели} [SYSTEM] [BEFORE] INTERFACE | PUBLIC | PRIVATE [{каталог1,1} ... {каталог1,M}]
[
	INTERFACE | PUBLIC | PRIVATE [{каталог2,1} ... {каталог2, n})
...
])

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

  • PRIVATE: каталоги будут использованы для поиска заголовочных файлов при компиляции файлов текущей цели (аналогично команде include_directories(...)).
  • INTERFACE: каталоги будут использованы при компиляции файлов зависимых целей от текущей.
  • PUBLIC: каталоги будут использованы при компиляции файлов как текущей цели, так и зависимых от неё целей (как будто они описаны одновременно как PRIVATE и INTERFACE) Таким образом, команда позволяет упростить подключение библиотек к исполяемым файлам.

Команда add_definitions(...) добавляет заданные определения символов препроцессора к свойствам текущего каталога и подчиненных (подключаемых при помощи команды add_subdirectory(...)). Определения символов должны быть в формате "-D{имя_символа}" или "/D{имя_символа}". Система CMake автоматически преобразует такие определния к аргументам командной строки, поддерживаемым используемым компилятором.

add_definitions({определение1} ... {определениеN})

# Пример

add_definitions(-DDEBUG -DEXTRA_TESTS)

При использовании в построении компилятора gcc ему будут переданы аргументы "-DDEBUG -DEXTRA_TESTS", а при использовании Microsoft Visual C++ - "/DDEBUG /DEXTRA_TESTS". После этого в компилируемых файлах препроцессором будут положительно обрабатываться директивы вида:

#ifdef EXTRA_TESTS
	do_extra_tests();
#endif

Команда add_compile_options(...) позволяет передавать аргументы компилятору в неизменном виде.

add_compile_options({аргумент1} ... {аргументN})

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

  • Для определения символов препроцессора с пустыми значениями предназначена команда add_definitions(...).
  • Для передачи компилятору дополнительных путей поиска заголовочных файлов предназначена команда include_directories(...), которая оказывает влияние на свойства текущего каталога построения, а также команда _target_include_directories(...), которая определяет свойства отдельной цели.
  • Для передачи компоновщику дополнительных библиотек используется команда target_link_libraries(...).
  • Для передачи компилятору аргументов, делающих доступными возможности новых стандартов C и C++ используется команда target_compile_features(...).
  • Для передачи компоновщику дополнительных путей поиска библиотек используется команда link_directories(...). Впрочем, в реальных ситуациях эта команда почти никогда не нужна, так как при добавлении библиотек от других целей или найденных при помощи команд find_library(...) и т.д. компоновщику будет передан путь к библиотеке.

Команда target_compile_definitions(...) аналогична команде add_definitions(...), однако позволяет добавлять определения символов препроцессора через командную вызовов компилятора не только для указанной цели, но и автоматические для всех целей, зависимых от данной, аналогично команде target_include_directories(...).

# CMake version >= 2.8.11
target_compile_definitions({имя_цели} 
	INTERFACE | PUBLIC | PRIVATE [{определение1,1} ... {определение1,M}]
	[INTERFACE | PUBLIC | PRIVATE [{определение2,1} ... {определение2,N}]
	...
])

Команда target_compile_options(...) аналогична команде add_compile_options(...), однако позволяет передавать аргументы компилятору не только для указанной цели, но и автоматически для всех целей, зависимых от данной, аналогично команде target_include_directories(...).

# CMake version >= 2.8.11
target_compile_options({имя_цели} [BEFORE] 
	INTERFACE | PUBLIC | PRIVATE [{аргумент1,1} ... {аргумент1,M}])
	[INTERFACE | PUBLIC | PRIVATE [{аргумент2,1} ... {аргумент2,N}]
	...
])
  • При помощи необязательного аргумента BEFORE можно добавлять аргументы компилятора в начало их списка вместо конца (по умолчанию).

&&&

# CMake version >= 3.1.0
target_compile_features({имя цели} INTERFACE | PUBLIC | PRIVATE {возможность1} ... {возможностьN})

Команда target_link_libraries(...) предназначена для определения подключаемых библиотек к заданной цели или произвольных аргументов командной строки, передаваемых комоновщику.

target_link_libraries({имя_цели} [{строка1} ... {строкаN}]
[
	[debug | optimized | general] {строка}
	...
])

target_link_libraries({имя_цели} INTERFACE | PUBLIC | PRIVATE {строка1} ... {строкаM}
[
	INTERFACE | PUBLIC | PRIVATE {строка1} ... {строкаN}
	...
])

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

About

Заметки о системе сборки CMake.


Languages

Language:CMake 95.8%Language:C++ 2.3%Language:Shell 1.9%