
Здравствуйте, дорогие читатели Хабра! Я давно хотел поделиться своими знаниями о работе с реестрами под ключ, так как нигде нет четкой и последовательной информации по этой теме. Сегодня мы разберем, как управлять зависимостями через реестры vcpkg и как кэшировать их на сервере. Статья рассчитана на пользователя, который имел опыт работы с vcpkg или conan
Ссылки на документацию
Содержание
-
Создание реестра
-
Создание своих пакетов Qt5/Boost
-
Сборка standalone окружения
-
Организация кэширования бинарей на сервере nuget
-
Сборка тестового проекта, с использованием vcpkg + nuget (кеширование)
Создание реестра
Создаем новый удаленный Git-репозиторий (подойдет любой, к которому у вас есть доступ). В статье я буду использовать свой репозиторий (ссылка)
Для первоначальной настройки потребуется файл baseline.json в папке versions.
versions/baseline.json
{ "default": { } }
Коммитим. Пушим. Пустой реестр создан. Для удобства работы можно взять скрипты для автоматизации из папки scripts.
Создание своих пакетов
Рекомендации по созданию port-файлов можно найти в официальной документации. В данной статье не предполагается подробное освещение этого вопроса.
В процессе работы мне потребуется использовать библиотеку Boost версии 1.87. В настоящее время в реестре доступна версия 1.88, однако её переопределение в vcpkg является для меня неудобным. Кроме того, я намерен использовать сборку qt5-base из исходников на зеркале Яндекса. Для достижения этой цели необходимо будет выполнить следующие действия:
-
Произвести форк файла port qt5-base.
-
Создать собственный файл port для библиотеки Boost.
Port qt5-base
За основе я взял актуальный port qt5-base. Копируем из vcpkg/ports в наш репозитори port/qt5-base
Структура репозитория
├───ports
│ ├───boost
│ └───qt5-base
│ ├───cmake
│ └───patches
├───scripts
├───share
└───versions
Редактируем источник скачивания (файл registry/ports/qt5-base/cmake/qt_download_submodule.cmake
set(FULL_VERSION "${QT_MAJOR_MINOR_VER}.${QT_PATCH_VER}") set(ARCHIVE_NAME "${NAME}-everywhere-opensource-src-${FULL_VERSION}.tar.xz") set(URLS "https://mirror.yandex.ru/mirrors/qt.io/${QT_MAJOR_MINOR_VER}/${FULL_VERSION}/submodules/${ARCHIVE_NAME}" )
Порядок действий для обновления информации о пакете:
-
Коммитим файлы в папке ports
-
Форматируем порт-фалы (scripts/format-ports.py)
cd scripts py format-ports.py
-
Коммитим изменения, если есть.
-
Обновляем актуальную информацию о версиях и снова коммитим изменения
cd scripts py update-versions.py
пример вывода
После выполнения данных шагов у вас появятся автоматически сгенерированые папки и файлы в versions (не нужно их редактировать руками!)
Пример файла versions/q-/qt5-base.json
{ "versions": [ { "git-tree": "e04eef6f4c169b57fd43a68a1a3d2bd9ef6d6ec2", "version": "5.15.16", "port-version": 4 } ] }
Этот файл содержит все версии и привязки к конкретным коммитам вашего port-файла.
Port boost
Все основные шаги по добавлению и обновлению описаны при добавлении qt5-base и заострять большое внимание на них не будем.
Расскажу кратко. Мой portfile будет
-
Собирать все библиотеки в рамках 1 порт-файла
-
Нужной мне версии
-
Представлены 2 фичи — принудительно static, принудительно shared
мой portfile.cmake
string(REPLACE "." "-" ARCHIVE_VERSION ${VERSION}) set(BOOST_ARVHICE_FILENAME boost-${ARCHIVE_VERSION}.zip) vcpkg_download_distfile( ARCHIVE_ZIP URLS https://github.com/boostorg/boost/releases/download/boost-${VERSION}/boost-${VERSION}-cmake.7z FILENAME ${BOOST_ARVHICE_FILENAME} SHA512 994356c84f4b96e263087eff40e53298791e7d72c6d24dd2cc3988c32edaa880180d39401504befe5c1b197ebead77c855452c608c6560a42f50f5a3016e0add ) vcpkg_extract_source_archive( SOURCE_PATH ARCHIVE "${ARCHIVE_ZIP}" ) string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "dynamic" BUILD_SHARED) string(COMPARE EQUAL "${VCPKG_CRT_LINKAGE}" "static" BUILD_STATIC_CRT) if(BUILD_SHARED) set(OPTION_BUILD_SHARED_LIBS ON) else() set(OPTION_BUILD_SHARED_LIBS OFF) endif() if(BUILD_STATIC_CRT) set(BOOST_RUNTIME_LINK static) else() set(BOOST_RUNTIME_LINK shared) endif() if("force-static" IN_LIST FEATURES) set(OPTION_BUILD_SHARED_LIBS OFF) #rewrite options vcpkg_check_linkage(ONLY_STATIC_LIBRARY) endif() if("force-shared" IN_LIST FEATURES) set(OPTION_BUILD_SHARED_LIBS ON) #rewrite options vcpkg_check_linkage(ONLY_DYNAMIC_LIBRARY) endif() set(BOOST_EXCLUDE_COMPONENTS test log wave stacktrace python) list(JOIN BOOST_EXCLUDE_COMPONENTS "\\;" BOOST_EXCLUDE_LIBRARIES) message(STATUS "Replace BoostConfig with fixed search lib_DIR") configure_file(${CMAKE_CURRENT_LIST_DIR}/BoostConfig.cmake.in ${SOURCE_PATH}/tools/cmake/config/BoostConfig.cmake USE_SOURCE_PERMISSIONS @ONLY) # disable check LINUX_VERSION_CODE in ASTRA if(UNIX) file(COPY_FILE ${CMAKE_CURRENT_LIST_DIR}/config.hpp ${SOURCE_PATH}/libs/asio/include/boost/asio/detail/config.hpp) endif() message(STATUS "Building boost with BUILD_SHARED_LIBS=${OPTION_BUILD_SHARED_LIBS}, CRT=${BOOST_RUNTIME_LINK} EXCLUDE:${BOOST_EXCLUDE_COMPONENTS}") vcpkg_cmake_configure( SOURCE_PATH ${SOURCE_PATH} WINDOWS_USE_MSBUILD OPTIONS -DBUILD_SHARED_LIBS=${OPTION_BUILD_SHARED_LIBS} -DBOOST_RUNTIME_LINK=${BOOST_RUNTIME_LINK} -DBOOST_EXCLUDE_LIBRARIES=${BOOST_EXCLUDE_LIBRARIES} -DBOOST_ENABLE_PYTHON=OFF -DBUILD_TESTING=OFF ) vcpkg_cmake_install() vcpkg_cmake_config_fixup(PACKAGE_NAME boost CONFIG_PATH lib/cmake/Boost-${VERSION} DO_NOT_DELETE_PARENT_CONFIG_PATH) #main config vcpkg_copy_pdbs() # Fixup configs for debug and release function(_fixup_boost_config_for_dir_ target_dir) message(STATUS "Fixup boost configs for dir: ${target_dir}") file(GLOB CONFIG_LIST LIST_DIRECTORIES true ${target_dir}/boost_*) foreach(dir ${CONFIG_LIST}) IF(IS_DIRECTORY ${dir}) string(REPLACE "${target_dir}/" "" dir_name "${dir}") #string(REPLACE "-1.83.0" "" PKG_CONFIG_NAME ${dir_name}) string(REPLACE "-${VERSION}" "" PKG_CONFIG_NAME ${dir_name}) message(STATUS "try fixup: ${dir_name} - ${PKG_CONFIG_NAME}") vcpkg_cmake_config_fixup(PACKAGE_NAME ${PKG_CONFIG_NAME} CONFIG_PATH lib/cmake/${dir_name} DO_NOT_DELETE_PARENT_CONFIG_PATH) ELSE() CONTINUE() ENDIF() endforeach() unset(CONFIG_LIST) endfunction() _fixup_boost_config_for_dir_(${CURRENT_PACKAGES_DIR}/debug/lib/cmake) _fixup_boost_config_for_dir_(${CURRENT_PACKAGES_DIR}/lib/cmake) file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include") file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/lib/cmake") file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/lib/cmake") file(INSTALL "${SOURCE_PATH}/LICENSE_1_0.txt" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" RENAME copyright)
Все изменения можно посмотреть в репозитории
Повторяем все действия по обновлению версий / коммитов, как в qt5-base
Сборка standalone окружения
С 2024 года vcpkg научился делать standalone окружения. Окружение может быть экспортировано полностью самостоятельным, отвязанным от основного репозитория vcpkg.
Для создания окружения нам будет необходимо подготовить два файла:
-
vcpkg.json — файл манифеста зависимостей
-
vcpkg-configuration.json — файл описания реестров, откуда что брать.
Для упрощения работы был написан вспомогательный скрипт make-vcpkg-configuration.py. Данный скрипт проходит по текущему реестру и собирает все версии, формируя эталонный конфигурации с привязкой к комиту и репозиторию.
пример подготовки файлов
cd scripts py make-vcpkg-configuration.py
Будут сформированы два файла
vcpkg.json
{ "dependencies": [], "overrides": [ { "name": "boost", "version": "1.87.0#2" }, { "name": "qt5-base", "version": "5.15.16#4" } ] }
vcpkg-configuration.json
{ "default-registry": { "kind": "git", "repository": "https://github.com/microsoft/vcpkg.git", "baseline": "3425f537d2f01c761d2d2cff59a7577eb4f568c0" }, "registries": [ { "kind": "git", "repository": "https://github.com/SaulBerrenson/registry.git", "reference": "main", "packages": [ "boost", "qt5-base" ], "baseline": "f3b8c64ae49a1dfd4cd845767e7d14f6f03bd09d" } ] }
Эти файлы можно заполнить руками, но скриптом проще и это универсальное решение.
Заполняем реестр теми пакетами, которые хотим видеть в будущем окружении
пример заполнения (vcpkg.json)
{ "dependencies": [ { "name": "boost", "features": ["force-static"] } ], "overrides": [ { "name": "boost", "version": "1.87.0#2" }, { "name": "qt5-base", "version": "5.15.16#4" } ] }
Выбираем удобую папку для сборки окружения и переносим туда:
-
vcpkg.json
-
vcpkg-configuration.json
-
vcpkg_manager.py (вспомогательный скрипт для удобства сборки окружений)
py vcpkg_manager.py --cache local --triplet x64-windows --steps install export PS C:\projects\article\build\env\v142_x64> Get-ChildItem -Recurse -Depth 1 | Select-Object @{Name="Level";Expression={($_.FullName.Split('\').Count - (Get-Location).Path.Split('\').Count)}}, Name, FullName | Format-Table Level Name FullName ----- ---- -------- 1 installed C:\projects\article\build\env\v142_x64\installed 1 scripts C:\projects\article\build\env\v142_x64\scripts 1 .vcpkg-root C:\projects\article\build\env\v142_x64\.vcpkg-root 1 vcpkg.exe C:\projects\article\build\env\v142_x64\vcpkg.exe 2 vcpkg C:\projects\article\build\env\v142_x64\installed\vcpkg 2 x64-windows C:\projects\article\build\env\v142_x64\installed\x64-windows 2 buildsystems C:\projects\article\build\env\v142_x64\scripts\buildsystems 2 cmake C:\projects\article\build\env\v142_x64\scripts\cmake
После выполнения мы получаем полностью отвязанное окружение от vcpkg. Для его использования необходимо передавать toolchainFile не из репозитория vcpkg, а из сформированной папки — тогда он не будет учитывать только это окружение.
Организация кэширования бинарей на сервере nuget
Сборка изолированных окружение заманчива, но иногда, особенно, в целях автоматизации CI\CD и т.д. — есть желание прокешировать пакеты аналогично conan.
Подготовка
Выбрать можно любой nuget-сервер, я выбираю бесплатный и простой open-source проект Baget. Разворачивать все будем в докере. Я заранее подготовил уже готовую конфигурацию на базе docker (ссылка). Авторизации никакой не будет — организация доступа не цель статьи.
docker-compose.yml
version: ‘3.8’
services:
baget:
image: loicsharma/baget
container_name: baget
ports:
— «5555:80»
volumes:
— ./baget-data:/var/baget
environment:
— ApiKey__IsRequired=false
— Storage__Type=FileSystem
— Storage__Path=/var/baget/packages
— Database__Type=PostgreSql
— Database__ConnectionString=Host=postgres;Port=5432;Database=baget;Username=baget;Password=baget_password
— Search__Type=Database
networks:
— baget-network
depends_on:
— postgres
postgres:
image: postgres:15-alpine
container_name: postgres
environment:
— POSTGRES_USER=baget
— POSTGRES_PASSWORD=baget_password
— POSTGRES_DB=baget
ports:
— «5432:5432»
volumes:
— postgres-data:/var/lib/postgresql/data
networks:
— baget-network
volumes:
postgres-data:
networks:
baget-network:
driver: bridge
docker-compose up -d
Важно: baget в стоке не умеет работать в postgresql с длинными наименованиями, который генерирует vcpkg. Фиксим это просто (сменой типов в ряде колонок)
docker exec -it postgres psql -U baget -d baget -c "ALTER TABLE \"Packages\" ALTER COLUMN \"Version\" TYPE TEXT; ALTER TABLE \"Packages\" ALTER COLUMN \"Id\" TYPE TEXT; ALTER TABLE \"Packages\" ALTER COLUMN \"OriginalVersion\" TYPE TEXT; ALTER TABLE \"PackageTypes\" ALTER COLUMN \"Version\" TYPE TEXT; ALTER TABLE \"Packages\" ALTER COLUMN \"Description\" TYPE TEXT;"
Сервер поднят — осталось наполнить пакетами.
Для организации кеширования можно воспользоваться vcpkg_manager.py
py vcpkg_manager.py --cache remote --triplet x64-windows --steps install export --nuget-url http://home-pc:5555/v3/index.json # Указываем сервер куда заливать --nuget-url http://home-pc:5555/v3/index.json
Т.к. я уже выполнял, у меня они прокэшировались на сервере и были восстановлены от туда. Кэширование завершено.
Сборка тестового проекта, с использованием vcpkg + nuget (кеширование)
Итак, на сервере у нас уже имеются нужные нам пакеты. Для конфигурирования проекта cmake на понадобится использовать режим манифеста и наши файлы vcpkg.json и vcpkg-configuration.json, которые мы использовали для сборки зависимостей.
Примерная структура проекта
Примерная структура проекта cmake
Level Name ----- ---- 1 CMakeLists.txt 1 CMakePresets.json 1 main.cpp 1 vcpkg-configuration.json 1 vcpkg.json
Для успешного конфигурирования нам понадобится:
-
toolchainFile — путь до vcpkg.cmake в основном репозитории (где у вас установлен vcpkg)
-
vcpkg.json
-
vcpkg-configuration.json
-
Переменная окружения VCPKG_BINARY_SOURCES с описанием источника пакетов:
"VCPKG_BINARY_SOURCES": "clear;nuget,http://home-pc:5555/v3/index.json,readwrite;nugettimeout,600"
Для удобства я использовал cmake presets
"configurePresets": [ { "name": "windows-base", "hidden": true, "generator": "Ninja", "binaryDir": "${sourceDir}/out/build/${presetName}", "installDir": "${sourceDir}/out/install/${presetName}", "toolchainFile": "c:\\buildtools\\vcpkg\\scripts\\buildsystems\\vcpkg.cmake", "environment": { "VCPKG_BINARY_SOURCES": "clear;nuget,http://home-pc:5555/v3/index.json,readwrite;nugettimeout,600" }, "cacheVariables": { "CMAKE_C_COMPILER": "cl.exe", "CMAKE_CXX_COMPILER": "cl.exe", "VCPKG_TARGET_TRIPLET": "x64-windows" }, "condition": { "type": "equals", "lhs": "${hostSystemName}", "rhs": "Windows" } }
Пример вывода конфигурирования проекта
Итак, мы сегодня научились:
-
делать простейший реестр пакетов
-
собирать окружение standalone
-
собирать и кэшировать окружение на удаленном сервере, подобно conan
Спасибо за внимание!
ссылка на оригинал статьи https://habr.com/ru/articles/916620/
Добавить комментарий