Руководство CMake. Шаг 1. Базовая отправная точка

Добавлено 7 января 2023 в 23:23

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

Руководство CMake. Шаг 1. Базовая отправная точка

Каждое упражнение на этом этапе начинается с некоторой исходной информации. Затем предоставляется цель и список полезных ресурсов. Каждый файл в разделе «Редактируемые файлы» находится в каталоге Step1 и содержит один или несколько комментариев TODO. Каждое TODO представляет собой одну или две строки кода, которые нужно изменить или добавить. TODO предназначены для выполнения в порядке нумерации, сначала выполните TODO 1, затем TODO 2 и т. д. В разделе «С чего начать» вы найдете несколько полезных советов и руководство по выполнению упражнения. Затем в разделе «Сборка и запуск» будет пошагово показано, как создать и протестировать упражнение. Наконец, в конце каждого упражнения обсуждается предполагаемое решение.

Также обратите внимание, что каждый шаг в руководстве основан на следующем. Так, например, исходный код для Шага 2 является полным решением для Шага 1.

Упражнение 1. Создание базового проекта

Самый простой проект CMake – это исполняемый файл, созданный из одного файла исходного кода. Для таких простых проектов достаточно файла CMakeLists.txt с тремя командами.

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

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

Чтобы начать проект, мы используем команду project() для установки имени проекта. Этот вызов требуется для каждого проекта и должен вызываться вскоре после cmake_minimum_required(). Как мы увидим позже, эту команду также можно использовать для указания другой информации на уровне проекта, такой как язык или номер версии.

Наконец, команда add_executable() указывает CMake создать исполняемый файл, используя указанные файлы исходного кода.

Цель

Узнать, как создать простой проект CMake.

Полезные ресурсы

Редактируемые файлы

  • CMakeLists.txt

С чего начать

Исходный код tutorial.cxx находится в каталоге Help/guide/tutorial/Step1 и может использоваться для вычисления квадратного корня числа. Этот файл на данном шаге редактировать не нужно.

В том же каталоге находится файл CMakeLists.txt, который вы должны заполнить. Начните с TODO 1 и проработайте до TODO 3.

Сборка и запуск

Как только TODO 1 – TODO 3 будут выполнены, мы будем готовы собрать и запустить наш проект! Сначала запустите исполняемый файл cmake или cmake-gui, чтобы сконфигурировать проект, а затем соберите его с помощью выбранного инструмента сборки.

Например, из командной строки мы можем перейти в каталог Help/guide/tutorial дерева исходного кода CMake и создать каталог сборки:

mkdir Step1_build

Затем перейдите в этот каталог сборки и запустите cmake, чтобы настроить проект и создать файлы нативной системы сборки:

cd Step1_build
cmake ../Step1

Затем вызовите эту систему сборки, чтобы скомпилировать/слинковать проект:

cmake --build .

Наконец, попробуйте использовать только что собранный Tutorial с этими командами:

Tutorial 4294967296
Tutorial 10
Tutorial

Решение

Как упоминалось выше, всё, что нам нужно для запуска, – это трехстрочный файл CMakeLists.txt. Первая строка – используем cmake_minimum_required() для установки версии CMake следующим образом:

TODO 1

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)

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

TODO 2

CMakeLists.txt

project(Tutorial)

Последней командой для вызова базового проекта является add_executable(). Мы вызываем его так:

TODO 3

CMakeLists.txt

add_executable(Tutorial tutorial.cxx)

Упражнение 2. Определение стандарта C++

В CMake есть специальные переменные, которые либо создаются за кулисами, либо имеют значение для CMake, если они установлены кодом проекта. Многие из этих переменных начинаются с CMAKE_. Согласно соглашению об именовании избегайте этого префикса при создании переменных для ваших проектов. Две из этих специальных устанавливаемых пользователем переменных – CMAKE_CXX_STANDARD и CMAKE_CXX_STANDARD_REQUIRED. Их можно использовать вместе, чтобы указать стандарт C++, необходимый для сборки проекта.

Цель

Добавить функцию, которая требует C++11.

Полезные ресурсы

Редактируемы файлы

  • CMakeLists.txt
  • tutorial.cxx

С чего начать

Продолжаем редактировать файлы в каталоге Step1. Начните с TODO 4 и завершите TODO 6.

Во-первых, отредактируйте tutorial.cxx, добавив функцию, для которой требуется C++11. Затем обновите CMakeLists.txt, чтобы он требовал C++11.

Сборка и запуск

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

cd Step1_build
cmake --build .

Теперь мы можем попробовать использовать только что собранное приложение Tutorial с теми же командами, что и раньше:

Tutorial 4294967296
Tutorial 10
Tutorial

Решение

Начнем с добавления в наш проект функций C++11, заменив atof на std::stod в tutorial.cxx. Это выглядит следующим образом:

TODO 4

tutorial.cxx

  const double inputValue = std::stod(argv[1]);

Чтобы выполнить TODO 5, просто удалите #include <cstdlib>.

Нам нужно будет явно указать в коде CMake, что он должен использовать правильные флаги. Один из способов включить поддержку определенного стандарта C++ в CMake – использовать переменную CMAKE_CXX_STANDARD. Для этого руководства установите для переменной CMAKE_CXX_STANDARD в файле CMakeLists.txt значение 11, а для CMAKE_CXX_STANDARD_REQUIRED – значение True. Объявления CMAKE_CXX_STANDARD обязательно добавьте перед вызовом add_executable().

TODO 6

CMakeLists.txt

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

Упражнение 3. Добавление номера версии и сконфигурированного заголовочного файла

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

Один из способов добиться этого – использовать сконфигурированный заголовочный файл. Мы создаем входной файл с одной или несколькими переменными для замены. Эти переменные имеют специальный синтаксис, похожий на @VAR@. Затем мы используем команду configure_file(), чтобы скопировать входной файл в заданный выходной файл и заменить эти переменные текущим значением VAR в файле CMakelists.txt.

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

Цель

Определить и сообщить номер версии проекта.

Полезные ресурсы

Редактируемые файлы

  • CMakeLists.txt
  • tutorial.cxx

С чего начать

Продолжаем редактировать файлы из Step1. Начните с TODO 7 и завершите TODO 12. В этом упражнении мы начнем с добавления номера версии проекта в CMakeLists.txt. В том же файле используйте configure_file(), чтобы скопировать заданный входной файл в выходной файл и заменить некоторые значения переменных в содержимом входного файла.

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

Наконец, обновите tutorial.cxx, чтобы распечатать номер его версии.

Сборка и запуск

Давайте снова соберем наш проект. Как и раньше, мы уже создали каталог сборки и запустили CMake, поэтому можем перейти к этапу сборки:

cd Step1_build
cmake --build .

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

Решение

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

Сначала мы модифицируем файл CMakeLists.txt, чтобы использовать команду project() для установки имени проекта и номера версии. Когда вызывается команда project(), CMake за кулисами определяет Tutorial_VERSION_MAJOR и Tutorial_VERSION_MINOR.

TODO 7

CMakeLists.txt

project(Tutorial VERSION 1.0)

Затем мы используем configure_file() для копирования входного файла с заменой переменных, указанных CMake:

TODO 8

CMakeLists.txt

configure_file(TutorialConfig.h.in TutorialConfig.h)

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

Примечание. В этом руководстве мы будем ссылаться на сборку проекта и каталог бинарных файлов проекта как синонимы. Они одинаковы и не означают ссылку на каталог bin/.

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

TODO 9

CMakeLists.txt

target_include_directories(Tutorial PUBLIC
                           "${PROJECT_BINARY_DIR}"
                           )

TutorialConfig.h.in – это входной заголовочный файл, который необходимо сконфигурировать. Когда configure_file() вызывается из нашего CMakeLists.txt, значения для @Tutorial_VERSION_MAJOR@ и @Tutorial_VERSION_MINOR@ будут заменены в TutorialConfig.h соответствующими номерами версий из проекта.

TODO 10

TutorialConfig.h.in

// сконфигурированные параметры и настройки для Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@

Затем нам нужно изменить tutorial.cxx, включив в него сконфигурированный заголовочный файл TutorialConfig.h.

TODO 11

tutorial.cxx

#include "TutorialConfig.h"

Наконец, мы распечатываем имя исполняемого файла и номер версии, обновляя tutorial.cxx следующим образом:

TODO 12

tutorial.cxx

  if (argc < 2) {
    // сообщить версию
    std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
              << Tutorial_VERSION_MINOR << std::endl;
    std::cout << "Usage: " << argv[0] << " number" << std::endl;
    return 1;
  }

Теги

C++ / CppCMakeАвтоматизация сборкиПрограммированиеСистема сборки

На сайте работает сервис комментирования DISQUS, который позволяет вам оставлять комментарии на множестве сайтов, имея лишь один аккаунт на Disqus.com.

В случае комментирования в качестве гостя (без регистрации на disqus.com) для публикации комментария требуется время на премодерацию.