Какие есть проблемы у систем сборки языка C++? | OTUS
🔥 Начинаем BLACK FRIDAY!
Максимальная скидка -25% на всё. Успейте начать обучение по самой выгодной цене.
Выбрать курс

Курсы

Программирование
iOS Developer. Basic
-25%
Python Developer. Professional
-25%
Разработчик на Spring Framework
-25%
Golang Developer. Professional
-25%
Python Developer. Basic
-25%
iOS Developer. Professional
-25%
Highload Architect
-25%
JavaScript Developer. Basic
-25%
Kotlin Backend Developer
-25%
JavaScript Developer. Professional
-25%
Android Developer. Basic
-25%
Unity Game Developer. Basic
-25%
Разработчик C#
-25%
Программист С Web-разработчик на Python Алгоритмы и структуры данных Framework Laravel PostgreSQL Reverse-Engineering. Professional CI/CD Vue.js разработчик VOIP инженер Программист 1С Flutter Mobile Developer Супер - интенсив по Kubernetes Symfony Framework Advanced Fullstack JavaScript developer Супер-интенсив "Azure для разработчиков"
Инфраструктура
Мониторинг и логирование: Zabbix, Prometheus, ELK
-25%
DevOps практики и инструменты
-25%
Архитектор сетей
-25%
Инфраструктурная платформа на основе Kubernetes
-25%
Супер-интенсив «ELK»
-16%
Супер-интенсив «IaC Ansible»
-16%
Супер-интенсив "SQL для анализа данных"
-16%
Базы данных Сетевой инженер AWS для разработчиков Cloud Solution Architecture Разработчик голосовых ассистентов и чат-ботов Внедрение и работа в DevSecOps Администратор Linux. Виртуализация и кластеризация Нереляционные базы данных Супер-практикум по использованию и настройке GIT IoT-разработчик Супер-интенсив «СУБД в высоконагруженных системах»
Специализации Курсы в разработке Подготовительные курсы
+7 499 938-92-02

Какие есть проблемы у систем сборки языка C++?

С___Deep_23-5020-25b88f.08_Site.png

Проблема только одна – отсутствие каких бы то ни было стандартных систем сборки. Но нас спасут нестандартные! В данном случае великий и ужасный CMake, в котором есть две переменные с не совсем очевидными отличиями.

– CMAKE_SOURCE_DIR – путь к директории исходников (директория, в которой расположен корневой файл CMakeLists.txt, с которого началась обработка);

– CMAKE_CURRENT_SOURCE_DIR – путь к текущей директории исходников (директория, в которой расположен CMakeLists.txt, который обрабатывается в данный момент).

Какую переменную лучше использовать для относительных путей в иерархии проекта?

Предположим, мы написали ещё один велосипед (но на этот раз превзошли всех предшественников в «велосипедостроении») и реализовали свой модуль суммирования переменных типа int. Структура проекта примерно такая:

|   CMakeLists.txt
|
+---SuperProject
|       CMakeLists.txt
|       Summator.cpp
|       Summator.h
|
\---Tests
        CMakeLists.txt
        Summator_test.cpp

Если вы, как и подобает нормальному человеку, не сразу воспринимаете вывод команды tree. Поясню: в корне проекта находится файл CMakeLists.txt и две директории – SuperProject (реализация нашего велосипеда) и Tests (так сказать, юнит-тесты). Думаю, теперь стало понятно, что где лежит.

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

add_subdirectory(SuperProject)
add_subdirectory(Tests)

С файлом CMakeLists.txt из директории SuperProject тоже всё просто:

project(SuperProject)
add_library(SuperProjectLib SHARED Summator.cpp)

И, наконец, самый смак: директория Tests и её файл CMakeLists.txt:

set(SOURCES
    ${CMAKE_SOURCE_DIR}/SuperProject/Summator.cpp
    Summator_test.cpp)
include_directories(${CMAKE_SOURCE_DIR})
add_executable(Summator_test ${SOURCES} ${HEADERS})

Заметили?

Мы используем CMAKE_SOURCE_DIR, чтобы собирать исходники проекта вместе с тестами. Обычно так делается для тестирования внутренних модулей продукта (иначе можно было бы просто прилинковать уже собранную библиотеку SuperProject.so(dll)).

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

Один из возможных вариантов использования – добавить наш репозиторий в свой в качестве git submodule и где-то в своём корневом CMakeLists.txt добавить команду:

add_subdirectory(SuperProjectPackage)

Иерархия проекта нашего благодарного пользователя будет выглядеть примерно так:

\---OtherProject
    |   CMakeLists.txt
    |
    +---sources
    \---SuperProjectPackage
        |   CMakeLists.txt
        |
        +---SuperProject
        |       CMakeLists.txt
        |       Summator.cpp
        |       Summator.h
        |
        \---Tests
                CMakeLists.txt
                Summator_test.cpp

Когда дело дойдёт до сборки проекта SuperProjectPackage, а если конкретнее, то до сборки тестов в директории Tests, куда будет указывать переменная CMAKE_SOURCE_DIR ?

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

В итоге на этапе CMake возникнет ошибка при выполнении вот этой строчки:

${CMAKE_SOURCE_DIR}/SuperProject/Summator.cpp

Что вполне законно, ибо корневая директория проекта теперь не содержит директорию SuperProject.

Что же делать?

Если вы читали эту заметку с начала, вероятно, вы можете заподозрить, что помочь нам призвана переменная CMAKE_CURRENT_SOURCE_DIR. И данный вывод совершенно верен!

Переменная CMAKE_CURRENT_SOURCE_DIR всегда указывает на директорию с текущим файлом CMakeFiles.txt, который в настоящий момент подвергается обработке. Использование этой переменной вместо CMAKE_SOURCE_DIR убережёт пользователей ваших супер-модулей от нервных расстройств, а вам даст дополнительный повод для гордости.

Ведь что может сравниться с ощущением того, что результаты твоей работы не пылятся на жёстком диске, а приносят пользу человечеству?

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

Правильное решение

В файле Tests/CMakeLists.txt следовало написать:

project(Tests)

set(SOURCES
    ${CMAKE_CURRENT_SOURCE_DIR}/../SuperProject/Summator.cpp
    Summator_test.cpp)

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../.)

add_executable(Summator_test ${SOURCES} ${HEADERS})

Есть вопрос? Напишите в комментариях!

Не пропустите новые полезные статьи!

Спасибо за подписку!

Мы отправили вам письмо для подтверждения вашего email.
С уважением, OTUS!

Автор
0 комментариев
Для комментирования необходимо авторизоваться
🎁 Максимальная скидка!
Черная пятница уже в OTUS! Скидка -25% на всё!