Какие есть проблемы у систем сборки языка C++? | OTUS
⚡ Подписка на курсы OTUS!
Интенсивная прокачка навыков для IT-специалистов!
Подробнее

Курсы

Программирование
Алгоритмы и структуры данных Team Lead Архитектура и шаблоны проектирования Разработчик IoT C# Developer. Professional PostgreSQL Разработчик на Spring Framework
-5%
Flutter Mobile Developer NoSQL iOS Developer. Basic
-10%
C++ Developer. Basic C++ Developer. Professional Android Developer. Professional Microservice Architecture Unity Game Developer. Professional Базы данных Node.js Developer React.js Developer Специализация Java-разработчик
-25%
Web-разработчик на Python Framework Laravel Cloud Solution Architecture Vue.js разработчик Интенсив «Оптимизация в Java» Супер - интенсив по паттернам проектирования Супер - интенсив по Kubernetes Супер-интенсив "Tarantool" PHP Developer. Basic
Инфраструктура
Мониторинг и логирование: Zabbix, Prometheus, ELK Administrator Linux. Professional Дизайн сетей ЦОД Разработчик IoT PostgreSQL Экспресс-курс "Версионирование и командная работа с помощью Git"
-30%
Microservice Architecture Highload Architect Специализация Administrator Linux
-25%
Network engineer Cloud Solution Architecture Внедрение и работа в DevSecOps Супер-практикум по работе с протоколом BGP Супер - интенсив по паттернам проектирования Супер - интенсив по Kubernetes Супер-интенсив «СУБД в высоконагруженных системах» Супер-интенсив "Tarantool" Network engineer. Basic
Корпоративные курсы
Безопасность веб-приложений IT-Recruiter Дизайн сетей ЦОД Компьютерное зрение Разработчик IoT Вебинар CERTIPORT Machine Learning. Professional
-6%
NoSQL Пентест. Практика тестирования на проникновение Java QA Engineer. Базовый курс Руководитель поддержки пользователей в IT
-8%
SRE практики и инструменты Cloud Solution Architecture Внедрение и работа в DevSecOps Супер-практикум по работе с протоколом BGP Infrastructure as a code Супер-практикум по использованию и настройке GIT Промышленный ML на больших данных Экспресс-курс «CI/CD или Непрерывная поставка с Docker и Kubernetes» BPMN: Моделирование бизнес-процессов Основы Windows Server
Специализации Курсы в разработке Подготовительные курсы Подписка
+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 комментариев
Для комментирования необходимо авторизоваться