Conan - это менеджер зависимостей и пакетов для языков C и C++ с открытым исходным кодом. Работает на всех платформах Windows, Linux, OSX, FreeBSD, Solaris и т. д. и может использоваться для разработки для множества платформ, включая мобильные (iOS, Android). Он также интегрируется с многими системами управления сборкой, такими как CMake, Visual Studio (MSBuild), Makefile и т.д.
Conan построен в соответствии с архитектурой клиент-сервер. Это означает, что клиенты могут извлекать пакеты с различных серверов («удаленные серверы»), а также загружать пакеты на них.
Сервера просто хранят пакеты. Они не собирают и не создают пакеты. Пакеты создаются клиентом, и если двоичные файлы собираются из исходных кодов, эта компиляция также выполняется клиентским приложением. Схему взаимодействия клиента с Conan можно проиллюстрировать при помощи следующей схемы.
Клиент Conan - это консольное приложение командной строки, содержащее сложную логику для создания и использования пакетов. Клиент Conan имеет локальный кэш для хранения пакетов, поэтому он позволяет вам полностью создавать и тестировать пакеты в автономном режиме.
JFrog Artifactory Community Edition (CE) - рекомендуемый сервер Conan для размещения собственных пакетов в частном порядке под вашим контролем. Conan_server - это сервер, распространяемый вместе с клиентом Conan. Это реализация с открытым исходным кодом, которая обеспечивает базовую функциональность, но не имеет WebUI или других расширенных функций.
ConanCenter — это центральный публичный репозиторий, куда сообщество добавляет пакеты для популярных библиотек с открытым исходным кодом, таких как Boost, Zlib, OpenSSL, Poco и т. д.
Одной из самых мощных функций Conan является то, что он может создавать и управлять предварительно скомпилированными двоичными файлами для многих платформ и конфигураций. Используя предварительно скомпилированные двоичные файлы и избегая повторных сборок из исходного кода, он значительно экономит время разработчиков и серверов непрерывной интеграции. Установка пакетов с серверов заключается в скачивании только необходимых бинарных файлов для текущей платформы и конфигурации. Если совместимый бинарный файл недоступен то, пакет собирается из исходников на клиенте. Для работы Conan требуется Python 3.
Команда conan install загружает бинарный пакет, необходимый для вашей конфигурации (обнаруживается при первом запуске команды), вместе с другими. Она также создаст файл conanbuildinfo.cmake в текущем каталоге, в котором вы можете увидеть переменные CMake, и conaninfo.txt, в котором сохраняются настройки и дополнительная информация. При запуске команды conan install применяются настройки, указанные в командной строке или взятые из значений по умолчанию, задаваемых в файле <userhome>/.conan/profiles/default. Здесь userhome - домашний каталог пользователя. На моем компьютере этот файл имеет следующий вид:
То есть в настройках указывается тип ОС, архитектура ЦП, компилятор, его версия по умолчанию, тип сборки и т.д.
Извлеченные пакеты устанавливаются в локальный кэш пользователя (обычно .conan/data) и могут быть повторно использованы из этого расположения для других проектов. Это позволяет избавить от необходимости скачивать зависимости для каждого проекта как было показано в предыдущей статье и продолжать работу даже при отсутствии подключения к сети. На моем компьютере кэш представлен в виде множества директорий, находящихся в папке data:
b2 bzip2 fmt icu libpq mongo-c-driver openssl zlib
boost catch2 gtest libbacktrace libpqxx mongo-cxx-driver snappy zstd
Одна директория соответствует одному пакету. Для каждого пакета имеется возможность хранения нескольких его версий в одной директории. Например у меня в папке gtest установлены 2 версии GoogleTest. Они хранятся в папках, названия которых совпадает с номером версии 1.12.1 и 1.15.0. Список всех пакетов, хранящихся в локальном кэше, можно вывести командой conan search "*" .
Чтобы проверить все зависимости вашего текущего проекта, используйте команду conan info, указав ей местоположение папки conanfile.txt:
Также можно создать граф зависимостей проекта, используя форматы Dot или HTML при помощи команды: conan info .. --graph=file.html
Можно проверить локальный кэш с помощью команды conan search и удалить из него пакеты с помощью команды conan remove pack_name/version. Здесь pack_name - название пакета, выводимое командой conan search, version - его версия.
Загружать пакеты можно из командной строки. Например команда conan install poco/1.9.4@ загрузит пакет Poco и его зависимости (openssl/1.0.2t и zlib/1.2.11) в ваш локальный кэш и выведет информацию о папке, в которой они установлены.
Несмотря на то, что вы можете установить каждую из своих зависимостей по отдельности, рекомендуемый подход - создание файла conanfile.txt в корневой директории проекта и указание зависимостей в нем . conanfile.txt должен включать разделы requires и generators. Необходимые зависимости должны быть указаны в разделе [requires], например:
[requires]
mypackage/1.0.0@company/stable
Где mypackage - имя пакета, которое обычно совпадает с именем библиотеки. 1.0.0 - это версия, часто совпадает с именем библиотеки. Это может быть строка не обязательно состоящая из цифр. company - владелец пакета/библиотеки. По сути, это пространство имен, которое позволяет разным пользователям иметь собственные пакеты для одной и той же библиотеки с одинаковым именем. stable - это характеристика пакета. Характеристика предоставляет способ иметь разные варианты пакетов для одной и той же библиотеки и использовать их взаимозаменяемо. Обычно они обозначают зрелость пакета как произвольную строку, например «стабильный» или «тестируемый». Параметры «владелец» и «характеристика» являются необязательными и могут быть опущены, например:
[requires]
packagename/1.2.0
Генераторы - это специальные компоненты, которые предоставляют информацию о зависимостях, вычисленных Conan в формате, подходящем для системы сборки. Обычно они предоставляют пользователям Conan файл conanbuildinfo.XXX, который может быть включен в систему сборки. Сгенерированный файл содержит информацию о зависимостях в виде различных переменных, а иногда и вспомогательных функций.
Conan считывает генераторы из раздела generators в conanfile.txt и создает файлы для каждого генератора. Такие файлы обычно являются временными, создаются в папке сборки и не передаются в систему контроля версий. Файлы соответствуют конфигурации (Debug/Release, x86/x86_64 и т.д.), указанной при запуске conan install. Если конфигурация изменится, файлы также изменятся.
Некоторые настройки проекта можно указать во время установки зависимостей. Например, вызов conan install .. -s build_type=Debug позволяет задать отладочную сборку . Эти настройки обычно являются конфигурацией всего проекта. В настоящее время Conan доступен в двух версиях 1.X и 2.X. Сначала рассмотрим работу с версией 1.X. Для работы c Conan требуется установить на компьютере python 3.5 или более поздней версии.
Проверить факт установки и версию можно командой python --version. Установить Python в ОС Ubuntu можно командой sudo apt install python3. Установка Conan осуществляется при помощи пакетного менеджера pip. Если pip не установлен, то в консоли выполните команду: sudo apt install python3-pip . Далее установить Conan версии 1.X можно командой sudo pip install conan==1.* . Conan будет загружен и установлен. Для проверки результата установки выполните команду conan --version.
Возьмем проект калькулятора из предыдущей статьи и подключим к нему GoogleTest при помощи Conan. Для этого в корневой директории проекта создадим файл conanfile.txt и укажем в нем зависимость.
conanfile.txt
[requires]
gtest/1.15.0
[generators]
cmake
Генератор cmake создает файл с именем conanbuildinfo.cmake, который затем импортируется в test/CMakeLists.txt.
Дерево проекта имеет следующий вид:
test/CMakeLists.txt:
if(NOT (CMAKE_SYSTEM_NAME STREQUAL "Linux"))
message(FATAL_ERROR "This CMake file works on linux systems only! CMake will exit!" )
endif()
#Подключение сгенерированного скрипта conanbuildinfo.cmake, который создан Conan
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
#Выполнение макроса из conanbuildinfo.cmake, который настраивает СMake на работу с библиотеками, которые установил Conan
conan_basic_setup()
find_package(GTest REQUIRED)
if(GTest_FOUND)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
if(NOT Threads_FOUND)
message( FATAL_ERROR "pthread not found, CMake will exit!" )
endif()
else()
message(FATAL_ERROR "GTest not found, CMake will exit!" )
endif()
add_executable(unit_tests arithmetic_test.cpp logic_test.cpp)
target_link_libraries(unit_tests PRIVATE arithmetic logic gtest pthread)
Необходимо отметить, что библиотека, импортируемая в проект, в свою очередь может зависеть от других зависимостей или библиотек, в нашем случае от библиотеки pthreads, обеспечивающей поддержку много поточности в операционных системах, совместимых со стандартом posix. Насколько мне известно, Windows не обеспечивает поддержку pthreads "из коробки". Поэтому вначале CMakeLists.txt определяется тип ОС и если это не Linux, то работа завершается (параметр FATAL_ERROR в функции message). conan_basic_setup - вспомогательный макрос, который используетcя для установки всех переменных CMake в соответствии с переменными, созданными Conan. Как говорилось в предыдущей статье, find_package используется для поиска библиотеки (в данном случае GTest), которая предварительно должна быть установлена в системе при помощи Conan. Ключевое слово REQUIRED говорит о том что проект не может быть построен, если GTest отсутствует. Также find_package(PackageName) устанавливает переменную <PackageName>_FOUND (в данном случае GTest_FOUND) в значение true/false, сигнализируя о том, что пакет найден или нет. Если пакет не найден, выводим сообщение и завершаем работу. После успешного нахождения GTest ищем библиотеку pthreads вызовом find_package(Threads REQUIRED). При включении GoogleTest в проект при помощи FetchContent_Declare(смотри предыдущую статью) явно подключать pthreads было не нужно.
Далее в один из файлов с тестами (например в arithmetic_test.cpp) надо добавить функцию main, иначе CMake выведет ошибку об отсутствии функции main при линковке (чего также не надо было делать при использовании FetchContent_Declare). Файл arithmetic_test.cpp примет следующий вид:
#include <gtest/gtest.h>
#include "arithmetic.h"
TEST(ArithmeticTest, Sum) {
int a = 10;
int b = 20;
EXPECT_EQ(sum(a, b), 30);
}
TEST(ArithmeticTest, Sub) {
int a = 10;
int b = 20;
EXPECT_EQ(sub(a, b), -10);
}
TEST(ArithmeticTest, Mult) {
int a = 10;
int b = 20;
EXPECT_EQ(mult(a, b), 200);
}
int main(int argc, char** argv)
{
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
В функции main происходит инициализация библиотеки вызовом метода InitGoogleTest и запуск всех тестов при помощи вызова RUN_ALL_TESTS. Далее создадим в корневой директории проекта папку build, перейдем в нее и запустим процесс скачивания GoogleTest командой conan install .. После завершения установки введите команду cmake .. и далее уже знакомую команду cmake --build . После завершения сборки запустим программу для тестирования (из папки build/test/bin) и убедимся что все тесты проходят как и раньше.
Исходный код примера для версии 1.X можно посмотреть здесь.
Для установки Conan версии 2.x в Ubuntu нужно ввести команду sudo pip install conan. Будет установлена самая свежая версия. Наиболее заметным отличием от первой версии является необходимость указывать другие генераторы, а также необходимость удаления из CMakeLists.txt подключения сгенерированного скрипта conanbuildinfo.cmake и conan_basic_setup. Таким образом в CMakeLists.txt не должно быть никаких ссылок на Conan. Ссылку на файл conan_toolchain.cmake теперь необходимо задавать через командную строку. Но обо всем по порядку.
Для использования Conan версии 2.x нужно изменить conanfile.txt. Сделать это можно на основе информации о подключении библиотеки GTest, которую получим с сайта conan.io. После захода на сайта вносим название библиотеки в строку поиска и нажимаем клавишу Enter. Будет выведен результат поиска библиотеки, который называется рецептом.
Для рецепта доступно краткое описание, а также список ОС, для которых работает библиотека. Переходим к содержимому рецепта кликнув по его названию как по гиперссылке. Попадаем на вкладку Use it. Там размещена информация о том как подключать библиотеку, в частности содержимое файла conanfile.txt.
Его можно скопировать себе в проект, убрав последнюю секцию layout, так как если ее оставить возникают проблемы с путями (по крайней мере у меня). conanfile.txt
[requires]
gtest/1.15.0
[generators]
CMakeDeps
CMakeToolchain
Генератор CMakeDeps создает необходимые файлы для каждой зависимости, чтобы можно было использовать функцию для ее поиска find_package. CMakeToolchain создает файл цепочки инструментов, который можно использовать в командной строке для вызова СMake c ключом DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake. Этот генератор преобразует текущую конфигурацию пакета, настройки и опции в синтаксис цепочки инструментов CMake.
test/CMakeLists.txt:
if(NOT (CMAKE_SYSTEM_NAME STREQUAL "Linux"))
message(FATAL_ERROR "This CMake file works on linux systems only! CMake will exit!" )
endif()
find_package(GTest REQUIRED)
if(NOT GTest_FOUND)
message(FATAL_ERROR "GTest not found, CMake will exit!" )
endif()
add_executable(unit_tests arithmetic_test.cpp logic_test.cpp)
target_link_libraries(unit_tests PRIVATE arithmetic logic gtest::gtest)
Как видно из приведенного листинга упоминание о Conan отсутствуют. При этом в target _link_libraries появилась цель gtest::gtest. Ее название берется из примера подключения библиотеки GoogleTest, расположенного в разделе Targets рецепта использования библиотеки.
Для получения библиотеки нужно находясь в корневой директории ввести команду conan install . --output-folder=build --build=missing . Как и в случае версии 1.X если библиотека отсутствует на компьютере, она будет скачана из репозитория Conan и помещена в кэш. Если библиотека уже находится в кэше, то будет выведено сообщение о том что она уже установлена. В результате выполнения команды будет создана директория build, заданная параметром output-folder . Если в репозитории Conan нет двоичной версии GTest для Вашей системы, то она будет собрана непосредственно на клиенте (параметр build=missing).
Перейдем в директорию build и введем команду для указания файла настроек цепочки инструментов и типа сборки :
cmake .. -DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake -DCMAKE_BUILD_TYPE=Release
После этого завершим сборку командой cmake --build .
Исходный код примера для версии 2.X можно посмотреть здесь.
В следующей статье рассмотрим вопросы получения отчета о покрытии кода тестами.