
Простая система сборки с использованием CMake
Прежде чем начать, позвольте мне сказать, что это второй шаг из серии Проект с нуля, которую я подготовил на своем YouTube-канале (/c/cppdev), и вы можете найти пошаговое видео здесь и также в текстовом формате на моем сайте (thecppdev.com) в этой статье.
Опять же, это в основном основано на дистрибутиве Linux Ubuntu, поскольку я считаю его более подходящим для разработки на C++ (и программирования в целом).
Теперь, когда мы разобрались с этим, давайте начнем.
CMake. Я уверен, что если вам до сих пор приходилось работать на C++, вы уже хотя бы раз слышали о CMake. Когда вы создаете какой-либо проект, вам понадобится система сборки, чтобы вы не всегда использовали огромные инструкции с использованием компилятора.
Просто чтобы добавить немного понимания, компилятор — это инструмент, который на самом деле «компилирует» ваш проект, то есть он генерирует двоичный файл или библиотеку, начиная с вашего исходного кода. CMake — это просто инструмент сборки, который будет использовать компилятор для создания двоичного файла/библиотеки или выполнения других шагов, необходимых для сборки вашего проекта.
Обычно, если вы используете IDE, вам не нужно создавать собственную систему сборки, так как IDE позаботится об этом, но, на мой взгляд, полезно знать, как выполняются шаги в фоновом режиме, поэтому у вас есть лучше понять обо всей среде разработки.
Следует отметить, что CMake на самом деле является кроссплатформенным. Итак, если он настроен правильно, его можно использовать для сборки вашего проекта как в среде Linux, так и в среде Windows.
Итак, чтобы создать собственную систему сборки с помощью CMake, нам нужно выполнить несколько шагов.
1. CMake, Make и установка инструментов компилятора
В этом руководстве мы собираемся использовать g++ в качестве компилятора, который является инструментом, предоставляемым коллекцией компиляторов GNU. Нам нужно установить как утилиту CMake, так и утилиту g++.
Помимо этого, нам также понадобится утилита Make, потому что CMake фактически использует Make в бэкенде.
Процесс будет следующим: CMake сгенерирует всю конфигурацию, необходимую для файлов Make. Затем мы будем использовать Make, чтобы фактически скомпилировать наш проект на основе сгенерированной конфигурации.
Мы собираемся сделать это в простой строке (в Linux Ubuntu): sudo apt-get install cmake make g++
После этого у нас есть все инструменты, необходимые для сборки нашего проекта с использованием CMake и g++. Просто так.
2. Обзор и структура конфигурации CMake
Чтобы настроить CMake для нашего проекта, нам нужен файл с именем CMakeLists.txt. Когда мы запускаем двоичный файл CMake для пути, в котором существует файл CMakeLists.txt, будут выполняться инструкции из этого файла.
В нашем случае, если у нас есть проект со следующей структурой каталогов:
У нас будет следующая структура CMakeLists.txt:
Итак, мы собираемся создать CMakeLists.txt для каждого каталога, содержащего любой исходный код (файлы .cpp), который должен привести к двоичному файлу/библиотеке. В нашем случае содержимое каталога src приведет к основному двоичному файлу (например, двоичному файлу проекта), а содержимое тестового каталога приведет к тестовому двоичному файлу (например, двоичному файлу проекта-теста).
Также нам нужно иметь «глобальный» CMakeLists.txt в основном каталоге нашего проекта. Этот глобальный файл конфигурации CMakeLists.txt будет использоваться каждый раз, когда мы пытаемся собрать проект с помощью CMake. Отсюда мы будем включать (или нет) подкаталоги для src и test, которые, в свою очередь, будут выполнять все инструкции из CMakeLists.txt в этих каталогах.
Если мы включим подкаталог src в глобальный CMakeLists.txt, то кроме всех инструкций из глобального CMakeLists.txt будут выполняться все инструкции из каталога src/CMakeLists.txt.
Поскольку у нас есть фактическая структура файлов CMake, нам нужно только добавить к ним некоторое содержимое/инструкции, поэтому наша система сборки знает, как собрать наш проект, когда мы используем утилиту CMake.
3.Содержимое конфигурационного файла CMake (реализация)
Что касается содержимого файлов CMakeLists.txt, я просто добавлю его сюда и буду комментировать каждую строку знаком «#». Я думаю, это должно дать хорошее понимание того, что происходит.
cpp-учебник/CMakeLists.txt
# минимальная версия утилиты cmake — обычно та, в которой был создан этот файл
cmake_minimum_required(VERSION 3.20)
# установить имя проекта
set(PROJECT_NAME «CPP Tutorial»)
# установите PROJECT_ID, который будет целевым именем, заменив каждый
# небуквенно-цифровой символ в PROJECT_NAME на строку подчеркивания
(MAKE_C_IDENTIFIER «${PROJECT_NAME}» PROJECT_ID)
# т. е. CPP Tutorial -› CPP_Учебник
# измените PROJECT_ID на строку нижнего регистра
(TOLOWER ${PROJECT_ID} PROJECT_ID)
# т.е. CPP_Tutorial -> cpp_tutorial
# установить проект для CMake
project(${PROJECT_NAME})
# включить CMakeLists.txt в src
# это запустит все в этом файле
add_subdirectory(src)
# добавить опцию для сборки тестов
option(BUILD_TESTS «Сборка тестов также для ${PROJECT_NAME}» ВЫКЛ)
# если нужно собрать тесты
# добавить подкаталог (с CMakeLists.txt) для тестов
if(BUILD_TESTS)
add_subdirectory(test)
endif()
cpp-tutorial/src/CMakeLists.txt
# установить переменную, содержащую список
# исходных файлов, которые будут собраны для наших целей
set(${PROJECT_ID}_SOURCES
Board.cpp
Game.cpp
main.cpp
)
# цель PROJECT_ID должна быть исполняемым файлом
add_executable(${PROJECT_ID})
# установить исходные файлы для встраивания в исполняемый файл
target_sources(${PROJECT_ID}
PRIVATE
${${PROJECT_ID}_SOURCES}
)
# предоставить закрытые пути включения для нашего исполняемого файла
target_include_directories(${PROJECT_ID}
PRIVATE
../include
)
# установить стандарт C++ 20
target_compile_features(${PROJECT_ID}
PRIVATE
cxx_std_20
)
# очистить переменную ${PROJECT_ID}_SOURCES
# чтобы не загрязнять все подряд
unset(${PROJECT_ID}_SOURCES)
Теперь, когда мы закончили с глобальным CMakeLists.txt и src/CMakeLists.txt, давайте посмотрим на CMakeLists.txt для тестового двоичного файла (в тестовом каталоге).
Мы просто создадим еще один исполняемый файл, только с исходным кодом в тестовом каталоге.
cpp-учебник/тест/CMakeLists.txt
# установить переменную, содержащую список
# исходных файлов, которые будут собраны для наших целей
set(${PROJECT_ID}_TEST_SOURCES
BoardTest.cpp
GameTest.cpp
main.cpp
)
# целевой объект ${PROJECT_ID}-test должен быть исполняемым файлом
add_executable(${PROJECT_ID}-test
${SRC_TEST_FILES}
)
# устанавливаем исходные файлы для встраивания в исполняемый файл
target_sources(${PROJECT_ID}-test
PRIVATE
${${PROJECT_ID}_TEST_SOURCES}
)
# предоставить закрытые пути включения для нашего исполняемого файла
target_include_directories(${PROJECT_ID}-test
PRIVATE
../include
)
# установить стандарт C++ 20
target_compile_features(${PROJECT_ID}-test
PRIVATE
cxx_std_20
)
Теперь все настроено для нашей простой системы сборки, и мы можем просто использовать ее для сборки нашего проекта.
4. Фактическая компиляция и сборка (с помощью CMake и Make)
Чтобы скомпилировать и собрать наш проект, нам нужны утилиты CMake и Make.
Мы также хотим создать другой каталог, в котором будут создаваться файлы сборки, чтобы не перегружать наш проект.
Прежде всего, нам нужно создать новый каталог с именем build, и внутри этого каталога мы можем сначала вызвать CMake, а затем Make, и все будет сгенерировано там.
Если мы хотим собрать только исходный код, мы не собираемся предоставлять параметр «BUILD_TESTS» для CMake. Это сделает так, что для него будет принято значение по умолчанию — в нашем случае OFF. Любой параметр CMake можно указать с помощью синтаксиса "-D‹option=value›". В нашем случае, если мы хотим построить тестовые примеры, синтаксис будет "-DBUILD_TESTS=ON".
После создания файлов CMake мы просто собираемся использовать "make" для сборки всего.
Сборка без тестов — после создания каталога build — с помощью команды mkdir:
Сборка с тестовыми примерами (также генерируется тестовый двоичный файл) — все еще в каталоге build:
У нас есть как основной исполняемый файл cpp_tutorial (двоичный), так и тестовый исполняемый файл cpp_tutorial-test (двоичный).
Все это также можно сделать, объединив все в одну команду:
mkdir build && cd build && cmake .. -DBUILD_TESTS=ON && make
Исходный код
Исходный код этой статьи, а также все остальное из Проекта с нуля вы можете найти на моем github.
Кроме того, возможно, вы захотите также проверить небольшой пример CMake в другой моей статье здесь.
Это все люди
Вот и все для этой простой системы сборки CMake. Как я уже указывал ранее, лучшее в использовании CMake для вашего проекта — это то, что он кроссплатформенный. Вы можете настроить файлы CMake так, чтобы их можно было создавать как для сред Linux, так и для Windows.
Надеюсь, вы узнали что-то новое из этого. Не забудьте также заглянуть на мой YouTube канал, возможно, вы найдете более подробную информацию, которая может вас заинтересовать.