Pull to refresh

Тайные знания: библиотеки для С++

Reading time5 min
Views29K

Рун не должен резать
Тот, кто в них не смыслит.
В непонятных знаках
Всякий может сбиться.
(Сага об Эгиле)

Многие начинающие программисты, уже освоив синтаксис C++, обнаруживают, что нет простого способа как подключить библиотеку, так и собрать программу для другой ОС, или чего хуже, под другим компьютером с той же ОС.
Это проблема отчасти порождается спорной практикой в обучении, когда код учат писать и запускать средствами IDE, таких как Visual Studio, Code::Blocks, и других. Поначалу такой подход работает, но лишь до первой реальной задачи сделать что-то, что запустится не только на вашем компьютере. Тут-то новички и сталкиваются с отсутствием стандартной системы сборки и менеджера зависимостей. После осознания этой сложности, большинство студентов, как правило, переходят на другие языки, попутно тиражируя в индустрии миф о том, что C++ де не кроссплатформенный язык, а вот мой Python/Java/C# - да. Между тем нас окружает множество замечательных кроссплатформенных программ написанных на C++. Если вы обучаетесь C++ и хотите понять как создавать такое ПО, то эта статья для вас.

1. Минутка теории. Получение исполняемого файла всегда и везде, зачем это необходимо?

Если вы читаете эту статью, то наверное, отдалено уже понимаете, что преобразует код компилятор (а склеивает в один исполнямый файл линковщик), но на практике, скорее всего до сих пор не сталкивались с этим, запуская сборку в один исполняемый файл сразу из IDE. Возможно вы вообще не пробовали собрать программу в файл, запуская её красивой зелененькой кнопочкой Run.
Однако и сама IDE, в свою очередь, не собирает и не запускает ваш код, а лишь вызывает специальную программу, которая называется система сборки, или сборщик, который-то и отвечает за сборку проекта и взаимодействие с компилятором и линковщиком.

У Visual Studio, к примеру, сборщиком по умолчанию является MSBuild, а у CLion - CMake. Те дополнительные файлы, которые вы видите, создав новый проект через интерфейс IDE, и являются конфигурацией для системы сборки. Наша задача просто научиться взаимодействовать с ней напрямую. Для этого мы возьмем CMake, потому что в отличие от MSBuild, эта система сборки запускается на большинстве ОС.

Почему надо разобраться в конфигурации системы сборки? Разве мне недостаточно среды, спросите вы? Потому что ваша среда может запуститься не везде, а система сборки гораздо более переносима, с ней вы сможете автоматизировать сборку, использовать контейнеры Docker, сможете оставить в репозитории билд скрипт который соберет ваш код на любом компьютере - ну разве не круто?

2. Пишем конфигурацию сборки самостоятельно

Итак, пришло время выйти из уютного мира в IDE, и вступить на путь уже кроссплатформенной стрельбы себе в ногу. Прежде всего, убедитесь что ваш код использует только стандартные функции С++. Если он вызывает ОС-зависимые API, вроде #include <Windows.h>, то рассмотрите чем их можно заменить. После этого воспользуемся следующим шаблоном CMake и создадим новый файл CMakeLists.txt:

cmake_minimum_required(VERSION 3.18)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Подключаем менеджер зависимостей Conan
list(APPEND CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR})
list(APPEND CMAKE_PREFIX_PATH ${CMAKE_BINARY_DIR})
if (NOT EXISTS "${CMAKE_BINARY_DIR}/conan.cmake")
    message(STATUS "Downloading conan.cmake from https://github.com/conan-io/cmake-conan")
    file(DOWNLOAD "https://raw.githubusercontent.com/conan-io/cmake-conan/v0.16.1/conan.cmake"
            "${CMAKE_BINARY_DIR}/conan.cmake"
            EXPECTED_HASH SHA256=396e16d0f5eabdc6a14afddbcfff62a54a7ee75c6da23f32f7a31bc85db23484
            TLS_VERIFY ON)
endif ()
include(${CMAKE_BINARY_DIR}/conan.cmake)

# Подключаем репозиторий зависимостей https://conan.io
conan_add_remote(NAME conan-center INDEX 1 URL https://center.conan.io VERIFY_SSL True)

# Скачиваем нужные нам зависимости, например:
conan_cmake_configure(REQUIRES catch2/2.13.6 spdlog/1.8.5 threadpool/20140926 simdjson/0.9.6 icu/69.1 GENERATORS cmake_find_package)
conan_cmake_autodetect(settings)
conan_cmake_install(PATH_OR_REFERENCE . BUILD missing REMOTE conan-center SETTINGS ${settings})

# Делаем зависимости видимыми для CMake
find_package(Catch2) # фреймворк тестирования
find_package(ICU) # работа с юникодом
find_package(spdlog) # логирование
find_package(simdjson) # парсинг json с помощью simd
find_package(ThreadPool) # ThreadPoolExecutor

# Подключаем файлы с основным кодом
file(GLOB proj_sources src/*.cpp)
add_executable(app ${proj_sources})

# Линкуем зависимости для основного кода (имена для линковки можно вытащить из описания зависимостей)
target_link_libraries(app PRIVATE ThreadPool::ThreadPool spdlog::spdlog simdjson::simdjson ICU::io ICU::i18n ICU::uc ICU::data)

# Подключаем файлы с кодом тестов
list(FILTER proj_sources EXCLUDE REGEX ".*/Main.cpp$")
file(GLOB test_sources test/*.cpp)
add_executable(test ${proj_sources} ${test_sources})

# Линкуем зависимости для тестов
target_link_libraries(test PRIVATE Catch2::Catch2 ThreadPool::ThreadPool spdlog::spdlog simdjson::simdjson ICU::io ICU::i18n ICU::uc ICU::data)

В этом шаблоне задаётся практически все, что нужно вам для сборки:

  1. Устанавливается стандарт C++20

  2. Подключается репозиторий библиотек Conan

  3. Задается соглашение, что файлы с кодом (.cpp, .h) будут лежать в папке src.

  4. Задается соглашение, что файлы с кодом для тестов будут лежать в паке test.

  5. Задаётся соглашение, что точки входа (int main) будут лежать в файлах Main.cpp

Убедитесь что ваш код хранится по этим соглашениям.
В скрипте также сразу подключается для примера несколько библиотек, по аналогии, следуя комментариям, вы можете добавить нужные вам.
Искать их можно тут: conan.io.

3. Как теперь собрать наше приложение в файл?

Мы отказались от кнопочек IDE в пользу более могущественного скрипта. Теперь нам понадобится платформа GCC или LLVM (возможно они уже есть на вашем компьютере), установленная система сборки CMake и менеджер зависимостей Conan. Их легко установить при помощи пакетного менеджера вашей ОС, или вручную, с официальных сайтов.

Откройте терминал в папке, где лежит CMakeLists.txt. Сначала нужно подготовить make-файлы. Воспринимайте это как предварительное действие:

cmake -DCMAKE_BUILD_TYPE=Release -G "Unix Makefiles" -B bin

После этого можно собрать само приложение и тесты:

cmake --build bin --target all

Приложение будет расположено в директории bin в файле под именем app.
Тесты могут быть запущены при помощи отдельного файла test в той же директории.

Вот и всё! Не так уж сложно, правда? Теперь вы можете распространять свое ПО на разные ОС, легко собирать его и подключать библиотеки. Если вы попробовали и что-то не работает, или есть какие-то вопросы, то их можно задать в комментариях под этой статьёй, постараюсь ответить.

После того как вы разберетесь как это делать, можно пользоваться моим project-wizard'ом для создания кроссплатформенных C++ утилит и библиотек в один клик: github.com/demidko
Однако сперва рекомендую попробовать воспроизвести результат самостоятельно, для лучшего понимания, что именно вы делаете, ведь в процессе приходят осознание и навык.

Tags:
Hubs:
Total votes 11: ↑6 and ↓5+1
Comments34

Articles