Как собрать программу cmake

Содержание

CMake — это инструмент для определения и управления сборками кода, прежде всего для C ++.

Прелюбодеяние в ка�.

Please enable JavaScript

CMake — это кросс-платформенный инструмент; идея состоит в том, чтобы иметь единое определение того, как строится проект, — который переводится в конкретные определения построения для любой поддерживаемой платформы.

Это достигается путем сопряжения с различными платформами, специфичными для платформы; CMake — это промежуточный шаг, который генерирует ввод данных для разных конкретных платформ. В Linux CMake генерирует Makefiles; в Windows он может создавать проекты Visual Studio и т. д.

Поведение сборки определяется в файлах CMakeLists.txt — по одному в каждом каталоге исходного кода. Файл CMakeLists каждого каталога определяет, что должна делать система сборки в этом конкретном каталоге. Он также определяет, какие подкаталоги должны обрабатывать CMake.

Типичные действия включают:

  • Создайте библиотеку или исполняемый файл из некоторых исходных файлов в этом каталоге.
  • Добавьте путь к пути include-path, который используется во время сборки.
  • Определите переменные, которые будет использовать buildsystem в этом каталоге, и в его подкаталогах.
  • Создайте файл на основе конкретной конфигурации сборки.
  • Найдите библиотеку, которая находится где-то в исходном дереве.

Окончательные файлы CMakeLists могут быть очень четкими и понятными, поскольку каждый из них настолько ограничен по объему. Каждый из них обрабатывает столько же сборки, сколько присутствует в текущем каталоге.

Основы CMake

Для официальных ресурсов на CMake см. Документацию и учебник CMake.

Версии

Версия Дата выхода
3,9 2017-07-18
3,8 2017-04-10
3,7 2016-11-11
3,6 2016-07-07
3,5 2016-03-08
3,4 2015-11-12
3,3 2015-07-23
3,2 2015-03-10
3,1 2014-12-17
3.0 2014-06-10
2.8.12.1 2013-11-08
2.8.12 2013-10-11
2.8.11 2013-05-16
2.8.10.2 2012-11-27
2.8.10.1 2012-11-07
2.8.10 2012-10-31
2.8.9 2012-08-09
2.8.8 2012-04-18
2.8.7 2011-12-30
2.8.6 2011-12-30
2.8.5 2011-07-08
2.8.4 2011-02-16
2.8.3 2010-11-03
2.8.2 2010-06-28
2.8.1 2010-03-17
2,8 2009-11-13
2,6 2008-05-05

Установка CMake

Перейдите на страницу загрузки CMake и получите двоичный файл для вашей операционной системы, например Windows, Linux или Mac OS X. В Windows дважды щелкните двоичный файл для установки. В Linux запускается двоичный файл с терминала.

CMake основы

В Linux вы также можете установить пакеты из диспетчера пакетов дистрибутива. На Ubuntu 16.04 вы можете установить командную строку и графическое приложение с помощью:

sudo apt-get install cmake sudo apt-get install cmake-gui

В FreeBSD вы можете установить командную строку и графическое приложение на основе Qt с помощью:

pkg install cmake pkg install cmake-gui

В Mac OSX, если вы используете один из менеджеров пакетов, доступных для установки вашего программного обеспечения, наиболее заметным из которых является MacPorts ( MacPorts ) и Homebrew ( Homebrew ), вы также можете установить CMake через один из них. Например, в случае MacPorts, введите следующие

sudo port install cmake

установит CMake, в то время как в случае использования ящика Homebrew, который вы наберете

brew install cmake

После того, как вы установили CMake, вы можете легко проверить, выполнив следующие

cmake —version

Вы должны увидеть что-то похожее на следующее

cmake version 3.5.1 CMake suite maintained and supported by Kitware (kitware.com/cmake).

Переключение между типами сборки, например отладка и выпуск

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

По умолчанию CMake может обрабатывать следующие типы сборки:

  • Отладка : обычно классическая сборка отладки, включая отладочную информацию, отсутствие оптимизации и т. Д.
  • Выпуск : типичная версия сборки без отладочной информации и полной оптимизации.
  • RelWithDebInfo:: То же, что и Release , но с информацией об отладке.
  • MinSizeRel : специальная версия выпуска, оптимизированная для размера.

Как обрабатываются конфигурации, зависит от используемого генератора.

Некоторые генераторы (например, Visual Studio) поддерживают несколько конфигураций. CMake будет генерировать все конфигурации сразу, и вы можете выбрать из IDE или использовать —config CONFIG (с cmake —build ), какую конфигурацию вы хотите построить. Для этих генераторов CMake будет стараться изо всех сил генерировать структуру каталогов сборки, чтобы файлы из разных конфигураций не наступали друг на друга.

Генераторы, которые поддерживают только одну конфигурацию (например, Unix Make-файлы), работают по-разному. Здесь CMAKE_BUILD_TYPE активная конфигурация определяется значением переменной CMake CMAKE_BUILD_TYPE .

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

cmake -DCMAKE_BUILD_TYPE=Debug path/to/source cmake -DCMAKE_BUILD_TYPE=Release path/to/source

Сценарий CMake должен избегать установки самого CMAKE_BUILD_TYPE , так как обычно это отвечает за ответственность пользователей.

Для генераторов с одним коннектором для переключения конфигурации требуется перезапуск CMake. Последующая сборка, скорее всего, перезапишет объектные файлы, созданные более ранней конфигурацией.

Простой проект «Hello World»

Учитывая исходный файл C ++ main.cpp определяющий функцию main() , сопровождающий файл CMakeLists.txt (со следующим содержимым) будет инструктировать CMake для генерации соответствующих инструкций сборки для текущей системы и компилятора C ++ по умолчанию.

#include int main()

CMakeLists.txt

cmake_minimum_required(VERSION 2.4) project(hello_world) add_executable(app main.cpp)

  1. cmake_minimum_required(VERSION 2.4) устанавливает минимальную версию CMake, необходимую для оценки текущего скрипта.
  2. project(hello_world) запускает новый проект CMake. Это вызовет много внутренней логики CMake, особенно при обнаружении компилятора C и C ++ по умолчанию.
  3. С помощью add_executable(app main.cpp) создается целевое app для сборки, которое будет вызывать сконфигурированный компилятор с некоторыми стандартными флагами для текущего параметра для компиляции исполняемого app из данного исходного файла main.cpp .

Командная строка (In-Source-Build, не рекомендуется)

> cmake . . > cmake —build .

cmake . обнаруживает компилятор, оценивает CMakeLists.txt в данном . и генерирует среду сборки в текущем рабочем каталоге.

cmake —build . команда является абстракцией для необходимого вызова build / make.

Командная строка (рекомендуется использовать Out-of-Source)

Чтобы ваш исходный код был чистым от каких-либо артефактов сборки, вы должны делать сборки «вне источника».

> mkdir build > cd build > cmake .. > cmake —build .

Или CMake также может абстрагировать основные команды оболочки платформы из примера выше:

> cmake -E make_directory build > cmake -E chdir build cmake .. > cmake —build build

«Hello World» с несколькими исходными файлами

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

Ниже приведен простой пример: все файлы предполагаются помещенными в каталог PROJECT_SOURCE_DIR .

main.cpp

#include «foo.h» int main()

foo.h

void foo();

foo.cpp

#include #include «foo.h» void foo()

CMakeLists.txt

cmake_minimum_required(VERSION 2.4) project(hello_world) include_directories($) add_executable(app main.cpp foo.cpp) # be sure there’s exactly one main() function in the source files

Полное руководство по CMake. Часть вторая: Система сборки

Полное руководство по CMake. Часть вторая: Система сборки

2018-12-04 в 18:46, admin , рубрики: C, c++, cmake, автоматизация рутины, для начинающих, компиляция, руководство для новичков, руководство для разработчика, руководство для чайников, системы сборки

Полное руководство по CMake. Часть вторая: Система сборки - 1

Введение

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

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

Запуск CMake

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

Принцип работы

Система сборки CMake представляет из себя оболочку над другими платформенно зависимыми утилитами (например, Ninja или Make). Таким образом, в самом процессе сборки, как бы парадоксально это ни звучало, она непосредственного участия не принимает.

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

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

Проверка версии CMake

Команда cmake_minimum_required проверяет запущенную версию CMake: если она меньше указанного минимума, то CMake завершает свою работу фатальной ошибкой. Пример, демонстрирующий типичное использование данной команды в начале любого CMake-файла:

# Задать третью минимальную версию CMake: cmake_minimum_required(VERSION 3.0)

Оформление проекта

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

# Задать характеристики проекта «MyProject»: project(MyProject VERSION 1.2.3.4 LANGUAGES C CXX)

Стоит отметить, что если ключевое слово LANGUAGES опущено, то по умолчанию задаются языки C CXX . Вы также можете отключить указание любых языков путём написания ключевого слова NONE в качестве списка языков или просто оставить пустой список.

Запуск скриптовых файлов

Команда include заменяет строку своего вызова кодом заданного файла, действуя аналогично препроцессорной команде include языков C/C++. Этот пример запускает скриптовый файл MyCMakeScript.cmake описанной командой:

message(«‘TEST_VARIABLE’ is equal to [$]») # Запустить скрипт `MyCMakeScript.cmake` на выполнение: include(MyCMakeScript.cmake) message(«‘TEST_VARIABLE’ is equal to [$]»)

В данном примере, первое сообщение уведомит том, что переменная TEST_VARIABLE ещё не определена, однако если скрипт MyCMakeScript.cmake определит данную переменную, то второе сообщение уже будет информировать о новом значении тестовой переменной. Таким образом, скриптовый файл, включаемый командой include , не создаёт собственной области видимости, о чём метко упомянули в комментариях к предыдущей статье.

Компиляция исполняемых файлов

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

# Скомпилировать исполняемый файл «MyExecutable» из # исходников «ObjectHandler.c», «TimeManager.c» и «MessageGenerator.c»: add_executable(MyExecutable ObjectHandler.c TimeManager.c MessageGenerator.c)

Компиляция библиотек

Команда add_library компилирует библиотеку с указанным видом и именем из исходников. Важно отметить, что окончательное имя библиотеки зависит от целевой платформы (например, lib.a или .lib ). Типичный пример вызова данной команды:

# Скомпилировать статическую библиотеку «MyLibrary» из # исходников «ObjectHandler.c», «TimeManager.c» и «MessageConsumer.c»: add_library(MyLibrary STATIC ObjectHandler.c TimeManager.c MessageConsumer.c)

  • Статические библиотеки задаются ключевым словом STATIC вторым аргументом и представляют из себя архивы объектных файлов, связываемых с исполняемыми файлами и другими библиотеками во время компиляции.
  • Динамические библиотеки задаются ключевым словом SHARED вторым аргументом и представляют из себя двоичные библиотеки, загружаемые операционной системой во время выполнения программы.
  • Модульные библиотеки задаются ключевым словом MODULE вторым аргументом и представляют из себя двоичные библиотеки, загружаемые посредством техник выполнения самим исполняемым файлом.
  • Объектные библиотеки задаются ключевым словом OBJECT вторым аргументом и представляют из себя набор объектных файлов, связываемых с исполняемыми файлами и другими библиотеками во время компиляции.

Добавление исходников к цели

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

Первым аргументом команда target_sources принимает название цели, ранее указанной с помощью команд add_library или add_executable , а последующие аргументы являются списком добавляемых исходных файлов.

Повторяющиеся вызовы команды target_sources добавляют исходные файлы к цели в том порядке, в каком они были вызваны, поэтому нижние два блока кода являются функционально эквивалентными:

# Задать исполняемый файл «MyExecutable» из исходников # «ObjectPrinter.c» и «SystemEvaluator.c»: add_executable(MyExecutable ObjectPrinter.c SystemEvaluator.c) # Добавить к цели «MyExecutable» исходник «MessageConsumer.c»: target_sources(MyExecutable MessageConsumer.c) # Добавить к цели «MyExecutable» исходник «ResultHandler.c»: target_sources(MyExecutable ResultHandler.c)
# Задать исполняемый файл «MyExecutable» из исходников # «ObjectPrinter.c», «SystemEvaluator.c», «MessageConsumer.c» и «ResultHandler.c»: add_executable(MyExecutable ObjectPrinter.c SystemEvaluator.c MessageConsumer.c ResultHandler.c)

Генерируемые файлы

Местоположение выходных файлов, сгенерированных командами add_executable и add_library , определяется только на стадии генерации, однако данное правило можно изменить несколькими переменными, определяющими конечное местоположение двоичных файлов:

  • Переменные RUNTIME_OUTPUT_DIRECTORY и RUNTIME_OUTPUT_NAME определяют местоположение целей выполнения.
  • Переменные LIBRARY_OUTPUT_DIRECTORY и LIBRARY_OUTPUT_NAME определяют местоположение библиотек.
  • Переменные ARCHIVE_OUTPUT_DIRECTORY и ARCHIVE_OUTPUT_NAME определяют местоположение архивов.

Исполняемые файлы всегда рассматриваются целями выполнения, статические библиотеки — архивными целями, а модульные библиотеки — библиотечными целями. Для «не-DLL» платформ динамические библиотеки рассматриваются библиотечными целями, а для «DLL-платформ» — целями выполнения. Для объектных библиотек таких переменных не предусмотрено, поскольку такой вид библиотек генерируется в недрах каталога CMakeFiles .

Важно подметить, что «DLL-платформами» считаются все платформы, основанные на Windows, в том числе и Cygwin.

Компановка с библиотеками

Команда target_link_libraries компанует библиотеку или исполняемый файл с другими предоставляемыми библиотеками. Первым аргументом данная команда принимает название цели, сгенерированной с помощью команд add_executable или add_library , а последующие аргументы представляют собой названия целей библиотек или полные пути к библиотекам. Пример:

# Скомпановать исполняемый файл «MyExecutable» с # библиотеками «JsonParser», «SocketFactory» и «BrowserInvoker»: target_link_libraries(MyExecutable JsonParser SocketFactory BrowserInvoker)

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

Добавление подпроектов

Команда add_subdirectory побуждает CMake к незамедлительной обработке указанного файла подпроекта. Пример ниже демонстрирует применение описанного механизма:

# Добавить каталог «subLibrary» в сборку основного проекта, # а генерируемые файлы расположить в каталоге «subLibrary/build»: add_subdirectory(subLibrary subLibrary/build)

В данном примере первым аргументом команды add_subdirectory выступает подпроект subLibrary , а второй аргумент необязателен и информирует CMake о папке, предназначенной для генерируемых файлов включаемого подпроекта (например, CMakeCache.txt и cmake_install.cmake ).

Стоит отметить, что все переменные из родительской области видимости унаследуются добавленным каталогом, а все переменные, определённые и переопределённые в данном каталоге, будут видимы лишь ему (если ключевое слово PARENT_SCOPE не было определено аргументом команды set ). Данную особенность упомянули в комментариях к предыдущей статье.

Поиск пакетов

Команда find_package находит и загружает настройки внешнего проекта. В большинстве случаев она применяется для последующей линковки внешних библиотек, таких как Boost и GSL. Данный пример вызывает описанную команду для поиска библиотеки GSL и последующей линковки:

# Загрузить настройки пакета библиотеки «GSL»: find_package(GSL 2.5 REQUIRED) # Уведомить компилятор о каталоге заголовков «GSL»: include_directories($) # Скомпановать исполняемый файл с библиотекой «GSL»: target_link_libraries(MyExecutable GSL::gsl)

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

Далее вызывается команда include_directories , информирующая компилятора о расположении заголовочных файлов библиотеки GSL. Обратите внимание на то, что используется переменная GSL_INCLUDE_DIRS , хранящая местоположение описанных мною заголовков (это пример импортированных настроек пакета).

В конечном итоге, исполняемый файл MyExecutable линкуется с библиотекой GSL командой target_link_libraries с помощью переменной GSL::gsl , инкапсулирующей расположение самой GSL.

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

Вам, вероятно, захочеться проверить результат поиска пакета, если Вы указали опцию QUIET . Это можно сделать путём проверки переменной _FOUND , автоматически определяемой после завершения команды find_package . Например, в случае успешного импортирования настроек GSL в Ваш проект, переменная GSL_FOUND обратится в истину.

В общем случае, команда find_package имеет две разновидности запуска: модульную и конфигурационную. Пример выше применял модульную форму. Это означает, что во время вызова команды CMake ищет скриптовый файл вида Find.cmake в директории CMAKE_MODULE_PATH , а затем запускает его и импортирует все необходимые настройки (в данном случае CMake запустила стандартный файл FindGSL.cmake ).

Установка проекта

Команда install генерирует установочные правила для Вашего проекта. Данная команда способна работать с целями, файлами, папками и многим другим. Сперва рассмотрим установку целей.

Для установки целей необходимо первым аргументом описанной функции передать ключевое слово TARGETS , за которым должен следовать список устанавливаемых целей, а затем ключевое слово DESTINATION с расположением каталога, в который установятся указанные цели. Данный пример демонстрирует типичную установку целей:

# Установить цели «TimePrinter» и «DataScanner» в директорию «bin»: install(TARGETS TimePrinter DataScanner DESTINATION bin)

Процесс описания установки файлов аналогичен, за тем исключением, что вместо ключевого слова TARGETS следует указать FILES . Пример, демонстрирующий установку файлов:

# Установить файлы «DataCache.txt» и «MessageLog.txt» в директорию «~/»: install(FILES DataCache.txt MessageLog.txt DESTINATION ~/)

Процесс описания установки папок также аналогичен, за тем исключением, что вместо ключевого слова FILES следует указать DIRECTORY . Важно подметить, что при установке будет копироваться всё содержимое папки, а не только её название. Пример установки папок выглядит следующим образом:

# Установить каталоги «MessageCollection» и «CoreFiles» в директорию «~/»: install(DIRECTORY MessageCollection CoreFiles DESTINATION ~/)

После завершения обработки CMake всех Ваших файлов Вы можете выполнить установку всех описанных объектов командой sudo make install (если CMake генерирует Makefile ), или же выполнить данное действие интегрированной средой разработки, поддерживающей CMake.

Наглядный пример проекта

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

+ MyProject — CMakeLists.txt — Defines.h — StartProgram.c + core — CMakeLists.txt — Core.h — ProcessInvoker.c — SystemManager.c

Главный файл сборки CMakeLists.txt описывает компиляцию всей программы: сперва происходит вызов команды add_executable , компилирующей исполняемый файл, затем вызывается команда add_subdirectory , побуждающая обработку подпроекта, и наконец, исполняемый файл линкуется с собранной библиотекой:

# Задать минимальную версию CMake: cmake_minimum_required(VERSION 3.0) # Указать характеристики проекта: project(MyProgram VERSION 1.0.0 LANGUAGES C) # Добавить в сборку исполняемый файл «MyProgram»: add_executable(MyProgram StartProgram.c) # Требовать обработку файла «core/CMakeFiles.txt»: add_subdirectory(core) # Скомпановать исполняемый файл «MyProgram» со # скомпилированной статической библиотекой «MyProgramCore»: target_link_libraries(MyProgram MyProgramCore) # Установить исполняемый файл «MyProgram» в директорию «bin»: install(TARGETS MyProgram DESTINATION bin)

Файл core/CMakeLists.txt вызывается главным файлом сборки и компилирует статическую библиотеку MyProgramCore , предназначенную для линковки с исполняемым файлом:

# Задать минимальную версию CMake: cmake_minimum_required(VERSION 3.0) # Указать характеристики проекта: project(MyProgramCore VERSION 1.0.0 LANGUAGES C) # Добавить в сборку статическую библиотеку «MyProgramCore»: add_library(MyProgramCore STATIC ProcessInvoker.c SystemManager.c)

После череды команд cmake . make sudo make install работа системы сборки CMake завершается успешно. Первая команда побуждает обработку файла CMakeLists.txt в корневом каталоге проекта, вторая команда окончательно компилирует необходимые двоичные файлы, а третья команда устанавливает скомпанованный исполняемый файл MyProgram в систему.

Заключение

Теперь Вы способны писать свои и понимать чужие CMake-файлы, а подробно прочитать про остальные механизмы Вы можете на официальном сайте.

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

Источник: www.pvsm.ru

Введение

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

Запуск CMake

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

Принцип работы

Система сборки CMake представляет из себя оболочку над другими платформенно зависимыми утилитами (например, Ninja или Make). Таким образом, в самом процессе сборки, как бы парадоксально это ни звучало, она непосредственного участия не принимает.

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

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

Проверка версии CMake

Команда cmake_minimum_required проверяет запущенную версию CMake: если она меньше указанного минимума, то CMake завершает свою работу фатальной ошибкой. Пример, демонстрирующий типичное использование данной команды в начале любого CMake-файла:

# Задать третью минимальную версию CMake: cmake_minimum_required(VERSION 3.0)

Оформление проекта

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

# Задать характеристики проекта «MyProject»: project(MyProject VERSION 1.2.3.4 LANGUAGES C CXX)

Стоит отметить, что если ключевое слово LANGUAGES опущено, то по умолчанию задаются языки C CXX . Вы также можете отключить указание любых языков путём написания ключевого слова NONE в качестве списка языков или просто оставить пустой список.

Запуск скриптовых файлов

Команда include заменяет строку своего вызова кодом заданного файла, действуя аналогично препроцессорной команде include языков C/C++. Этот пример запускает скриптовый файл MyCMakeScript.cmake описанной командой:

message(«‘TEST_VARIABLE’ is equal to [$]») # Запустить скрипт `MyCMakeScript.cmake` на выполнение: include(MyCMakeScript.cmake) message(«‘TEST_VARIABLE’ is equal to [$]»)

В данном примере, первое сообщение уведомит том, что переменная TEST_VARIABLE ещё не определена, однако если скрипт MyCMakeScript.cmake определит данную переменную, то второе сообщение уже будет информировать о новом значении тестовой переменной. Таким образом, скриптовый файл, включаемый командой include , не создаёт собственной области видимости, о чём метко упомянули в комментариях к предыдущей статье.

Компиляция исполняемых файлов

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

# Скомпилировать исполняемый файл «MyExecutable» из # исходников «ObjectHandler.c», «TimeManager.c» и «MessageGenerator.c»: add_executable(MyExecutable ObjectHandler.c TimeManager.c MessageGenerator.c)

Компиляция библиотек

Команда add_library компилирует библиотеку с указанным видом и именем из исходников. Важно отметить, что окончательное имя библиотеки зависит от целевой платформы (например, lib.a или .lib ). Типичный пример вызова данной команды:

# Скомпилировать статическую библиотеку «MyLibrary» из # исходников «ObjectHandler.c», «TimeManager.c» и «MessageConsumer.c»: add_library(MyLibrary STATIC ObjectHandler.c TimeManager.c MessageConsumer.c)

  • Статические библиотеки задаются ключевым словом STATIC вторым аргументом и представляют из себя архивы объектных файлов, связываемых с исполняемыми файлами и другими библиотеками во время компиляции.
  • Динамические библиотеки задаются ключевым словом SHARED вторым аргументом и представляют из себя двоичные библиотеки, загружаемые операционной системой во время выполнения программы.
  • Модульные библиотеки задаются ключевым словом MODULE вторым аргументом и представляют из себя двоичные библиотеки, загружаемые посредством техник выполнения самим исполняемым файлом.
  • Объектные библиотеки задаются ключевым словом OBJECT вторым аргументом и представляют из себя набор объектных файлов, связываемых с исполняемыми файлами и другими библиотеками во время компиляции.

Добавление исходников к цели

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

Читайте также:
Как подключить программу спасибо

Первым аргументом команда target_sources принимает название цели, ранее указанной с помощью команд add_library или add_executable , а последующие аргументы являются списком добавляемых исходных файлов.

Повторяющиеся вызовы команды target_sources добавляют исходные файлы к цели в том порядке, в каком они были вызваны, поэтому нижние два блока кода являются функционально эквивалентными:

# Задать исполняемый файл «MyExecutable» из исходников # «ObjectPrinter.c» и «SystemEvaluator.c»: add_executable(MyExecutable ObjectPrinter.c SystemEvaluator.c) # Добавить к цели «MyExecutable» исходник «MessageConsumer.c»: target_sources(MyExecutable MessageConsumer.c) # Добавить к цели «MyExecutable» исходник «ResultHandler.c»: target_sources(MyExecutable ResultHandler.c)
# Задать исполняемый файл «MyExecutable» из исходников # «ObjectPrinter.c», «SystemEvaluator.c», «MessageConsumer.c» и «ResultHandler.c»: add_executable(MyExecutable ObjectPrinter.c SystemEvaluator.c MessageConsumer.c ResultHandler.c)

Генерируемые файлы

Местоположение выходных файлов, сгенерированных командами add_executable и add_library , определяется только на стадии генерации, однако данное правило можно изменить несколькими переменными, определяющими конечное местоположение двоичных файлов:

  • Переменные RUNTIME_OUTPUT_DIRECTORY и RUNTIME_OUTPUT_NAME определяют местоположение целей выполнения.
  • Переменные LIBRARY_OUTPUT_DIRECTORY и LIBRARY_OUTPUT_NAME определяют местоположение библиотек.
  • Переменные ARCHIVE_OUTPUT_DIRECTORY и ARCHIVE_OUTPUT_NAME определяют местоположение архивов.

Исполняемые файлы всегда рассматриваются целями выполнения, статические библиотеки — архивными целями, а модульные библиотеки — библиотечными целями. Для «не-DLL» платформ динамические библиотеки рассматриваются библиотечными целями, а для «DLL-платформ» — целями выполнения. Для объектных библиотек таких переменных не предусмотрено, поскольку такой вид библиотек генерируется в недрах каталога CMakeFiles .

Важно подметить, что «DLL-платформами» считаются все платформы, основанные на Windows, в том числе и Cygwin.

Компановка с библиотеками

Команда target_link_libraries компанует библиотеку или исполняемый файл с другими предоставляемыми библиотеками. Первым аргументом данная команда принимает название цели, сгенерированной с помощью команд add_executable или add_library , а последующие аргументы представляют собой названия целей библиотек или полные пути к библиотекам. Пример:

# Скомпановать исполняемый файл «MyExecutable» с # библиотеками «JsonParser», «SocketFactory» и «BrowserInvoker»: target_link_libraries(MyExecutable JsonParser SocketFactory BrowserInvoker)

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

Добавление подпроектов

Команда add_subdirectory побуждает CMake к незамедлительной обработке указанного файла подпроекта. Пример ниже демонстрирует применение описанного механизма:

# Добавить каталог «subLibrary» в сборку основного проекта, # а генерируемые файлы расположить в каталоге «subLibrary/build»: add_subdirectory(subLibrary subLibrary/build)

В данном примере первым аргументом команды add_subdirectory выступает подпроект subLibrary , а второй аргумент необязателен и информирует CMake о папке, предназначенной для генерируемых файлов включаемого подпроекта (например, CMakeCache.txt и cmake_install.cmake ).

Стоит отметить, что все переменные из родительской области видимости унаследуются добавленным каталогом, а все переменные, определённые и переопределённые в данном каталоге, будут видимы лишь ему (если ключевое слово PARENT_SCOPE не было определено аргументом команды set ). Данную особенность упомянули в комментариях к предыдущей статье.

Поиск пакетов

Команда find_package находит и загружает настройки внешнего проекта. В большинстве случаев она применяется для последующей линковки внешних библиотек, таких как Boost и GSL. Данный пример вызывает описанную команду для поиска библиотеки GSL и последующей линковки:

# Загрузить настройки пакета библиотеки «GSL»: find_package(GSL 2.5 REQUIRED) # Уведомить компилятор о каталоге заголовков «GSL»: include_directories($) # Скомпановать исполняемый файл с библиотекой «GSL»: target_link_libraries(MyExecutable GSL::gsl)

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

Далее вызывается команда include_directories , информирующая компилятора о расположении заголовочных файлов библиотеки GSL. Обратите внимание на то, что используется переменная GSL_INCLUDE_DIRS , хранящая местоположение описанных мною заголовков (это пример импортированных настроек пакета).

В конечном итоге, исполняемый файл MyExecutable линкуется с библиотекой GSL командой target_link_libraries с помощью переменной GSL::gsl , инкапсулирующей расположение самой GSL.

Вам, вероятно, захочеться проверить результат поиска пакета, если Вы указали опцию QUIET . Это можно сделать путём проверки переменной _FOUND , автоматически определяемой после завершения команды find_package . Например, в случае успешного импортирования настроек GSL в Ваш проект, переменная GSL_FOUND обратится в истину.

В общем случае, команда find_package имеет две разновидности запуска: модульную и конфигурационную. Пример выше применял модульную форму. Это означает, что во время вызова команды CMake ищет скриптовый файл вида Find.cmake в директории CMAKE_MODULE_PATH , а затем запускает его и импортирует все необходимые настройки (в данном случае CMake запустила стандартный файл FindGSL.cmake ).

Установка проекта

Команда install генерирует установочные правила для Вашего проекта. Данная команда способна работать с целями, файлами, папками и многим другим. Сперва рассмотрим установку целей.

Для установки целей необходимо первым аргументом описанной функции передать ключевое слово TARGETS , за которым должен следовать список устанавливаемых целей, а затем ключевое слово DESTINATION с расположением каталога, в который установятся указанные цели. Данный пример демонстрирует типичную установку целей:

# Установить цели «TimePrinter» и «DataScanner» в директорию «bin»: install(TARGETS TimePrinter DataScanner DESTINATION bin)

Процесс описания установки файлов аналогичен, за тем исключением, что вместо ключевого слова TARGETS следует указать FILES . Пример, демонстрирующий установку файлов:

# Установить файлы «DataCache.txt» и «MessageLog.txt» в директорию «~/»: install(FILES DataCache.txt MessageLog.txt DESTINATION ~/)

Процесс описания установки папок также аналогичен, за тем исключением, что вместо ключевого слова FILES следует указать DIRECTORY . Важно подметить, что при установке будет копироваться всё содержимое папки, а не только её название. Пример установки папок выглядит следующим образом:

# Установить каталоги «MessageCollection» и «CoreFiles» в директорию «~/»: install(DIRECTORY MessageCollection CoreFiles DESTINATION ~/)

После завершения обработки CMake всех Ваших файлов Вы можете выполнить установку всех описанных объектов командой sudo make install (если CMake генерирует Makefile ), или же выполнить данное действие интегрированной средой разработки, поддерживающей CMake.

Наглядный пример проекта

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

+ MyProject — CMakeLists.txt — Defines.h — StartProgram.c + core — CMakeLists.txt — Core.h — ProcessInvoker.c — SystemManager.c

Главный файл сборки CMakeLists.txt описывает компиляцию всей программы: сперва происходит вызов команды add_executable , компилирующей исполняемый файл, затем вызывается команда add_subdirectory , побуждающая обработку подпроекта, и наконец, исполняемый файл линкуется с собранной библиотекой:

# Задать минимальную версию CMake: cmake_minimum_required(VERSION 3.0) # Указать характеристики проекта: project(MyProgram VERSION 1.0.0 LANGUAGES C) # Добавить в сборку исполняемый файл «MyProgram»: add_executable(MyProgram StartProgram.c) # Требовать обработку файла «core/CMakeFiles.txt»: add_subdirectory(core) # Скомпановать исполняемый файл «MyProgram» со # скомпилированной статической библиотекой «MyProgramCore»: target_link_libraries(MyProgram MyProgramCore) # Установить исполняемый файл «MyProgram» в директорию «bin»: install(TARGETS MyProgram DESTINATION bin)

Файл core/CMakeLists.txt вызывается главным файлом сборки и компилирует статическую библиотеку MyProgramCore , предназначенную для линковки с исполняемым файлом:

# Задать минимальную версию CMake: cmake_minimum_required(VERSION 3.0) # Указать характеристики проекта: project(MyProgramCore VERSION 1.0.0 LANGUAGES C) # Добавить в сборку статическую библиотеку «MyProgramCore»: add_library(MyProgramCore STATIC ProcessInvoker.c SystemManager.c)

После череды команд cmake . make sudo make install работа системы сборки CMake завершается успешно. Первая команда побуждает обработку файла CMakeLists.txt в корневом каталоге проекта, вторая команда окончательно компилирует необходимые двоичные файлы, а третья команда устанавливает скомпанованный исполняемый файл MyProgram в систему.

Заключение

Теперь Вы способны писать свои и понимать чужие CMake-файлы, а подробно прочитать про остальные механизмы Вы можете на официальном сайте.

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

  • туториал
  • системы сборки
  • компиляция
  • для начинающих
  • автоматизация рутины
  • руководство для разработчика
  • руководство для новичков
  • руководство для чайников
  • cmake
  • c
  • c++
  • 26 марта 2018 в 16:24
    Квантовые вычисления и язык Q# для начинающих

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

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