vcpkg і CMake: toolchain-файл, manifest vcpkg.json, IDE
vcpkg і CMake: toolchain-файл, manifest vcpkg.json, IDE
🎯 Мета лекції
- Підключити vcpkg до CMake через toolchain-файл і знати, чому він має стояти перед
project(). - Описати залежності проєкту у файлі
vcpkg.json(manifest-режим). - Зібрати проєкт із кількома бібліотеками за один виклик CMake.
- Налаштувати vcpkg у VS Code, Visual Studio та CLion.
🔑 Ключові терміни
- Toolchain-файл (
vcpkg.cmake): скрипт CMake, який підключає vcpkg до конфігурації проєкту. - Маніфест (
vcpkg.json): файл у корені проєкту з переліком залежностей. CONFIG-режимfind_package: пошук за файлом<пакет>Config.cmake, який постачає сам пакет.vcpkg_installed: папка всерединіbuild/, у яку manifest-режим ставить залежності проєкту.
Лекція про основи vcpkg завершилась двома режимами роботи. Тепер ці режими підключаються до CMake: спершу з'ясовується, як CMake взагалі дізнається про vcpkg, а потім розглядається повний сценарій manifest-режиму.
Як CMake дізнається про vcpkg
CMake сам про vcpkg нічого не знає. Зв'язок створює toolchain-файл vcpkg.cmake, який лежить усередині каталогу vcpkg:
$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake
Файл виконується на самому початку конфігурації. Він налаштовує пошук пакетів так, щоб find_package(fmt CONFIG REQUIRED) знаходив бібліотеки, встановлені через vcpkg, а в manifest-режимі ще й сам запускає vcpkg install для залежностей проєкту. Перед викликом find_package у вашому CMakeLists.txt нічого змінювати не потрібно.

Способи підключити toolchain
Спосіб 1: параметр командного рядка (рекомендовано)
# Windows
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake
cmake --build build
# Linux / macOS
cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake
cmake --build build
Це найбільш явний і надійний спосіб. Шлях до vcpkg зберігається поза CMakeLists.txt, тому проєкт можна збирати й на комп'ютері, де vcpkg лежить в іншій папці.
-DCMAKE_TOOLCHAIN_FILE=... потрібно вказувати при першій конфігурації папки build. Додати його до вже налаштованої папки не вдасться: CMake проігнорує зміну. Видаліть build/ або виконайте cmake -S . -B build --fresh.Спосіб 2: змінна середовища
CMake починаючи з версії 3.21 бере значення параметра зі змінної середовища CMAKE_TOOLCHAIN_FILE, якщо в командному рядку його не вказано:
# Додайте в ~/.bashrc або ~/.zshrc
export VCPKG_ROOT=$HOME/vcpkg
export CMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake
[Environment]::SetEnvironmentVariable("VCPKG_ROOT", "C:\vcpkg", "User")
[Environment]::SetEnvironmentVariable("CMAKE_TOOLCHAIN_FILE", "C:\vcpkg\scripts\buildsystems\vcpkg.cmake", "User")
Після цього достатньо cmake -B build: toolchain підхоплюється автоматично. Недолік такого підходу: усі CMake-проєкти на комп'ютері починають використовувати vcpkg, навіть ті, яким він не потрібен. Користувачеві на іншому комп'ютері теж доведеться задати змінну.
Спосіб 3: встановити змінну в CMakeLists.txt (до project)
Якщо хочеться, щоб проєкт сам знаходив vcpkg, змінну можна встановити у файлі. Критично важливий порядок: toolchain-файл читається під час виконання project(), тому змінна має бути встановлена раніше.
cmake_minimum_required(VERSION 3.15)
# Toolchain потрібно задати ДО project()
if(DEFINED ENV{VCPKG_ROOT} AND NOT DEFINED CMAKE_TOOLCHAIN_FILE)
set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
CACHE STRING "")
endif()
project(MyProject)
set(CMAKE_CXX_STANDARD 17)
find_package(fmt CONFIG REQUIRED)
add_executable(MyApp main.cpp)
target_link_libraries(MyApp PRIVATE fmt::fmt)
cmake_minimum_required(VERSION 3.15)
project(MyProject)
# Занадто пізно: toolchain уже не підхопиться
if(DEFINED ENV{VCPKG_ROOT} AND NOT DEFINED CMAKE_TOOLCHAIN_FILE)
set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
CACHE STRING "")
endif()
set(CMAKE_CXX_STANDARD 17)
find_package(fmt CONFIG REQUIRED)
add_executable(MyApp main.cpp)
target_link_libraries(MyApp PRIVATE fmt::fmt)
Різницю підтверджує реальний запуск обох варіантів (змінна CMAKE_TOOLCHAIN_FILE середовища прибрана, а vcpkg.json однаковий):
У першому випадку vcpkg навіть не запускався: CMake не знав про нього, і find_package не знайшов нічого. У другому vcpkg встановив залежності з vcpkg.json і find_package пройшов.
Спосіб 4: пресети CMake
У командній роботі найзручніше записати toolchain у CMakePresets.json:
{
"version": 6,
"configurePresets": [
{
"name": "default",
"binaryDir": "${sourceDir}/build",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
}
},
{
"name": "release",
"inherits": "default",
"binaryDir": "${sourceDir}/build-release",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
}
],
"buildPresets": [
{ "name": "default", "configurePreset": "default" },
{ "name": "release", "configurePreset": "release" }
]
}
Вираз $env{VCPKG_ROOT} береться зі змінної середовища кожного розробника, тому файл однаковий для всієї команди і не містить особистих шляхів. Використання: cmake --preset default && cmake --build --preset default.
Manifest-режим
У manifest-режимі залежності проєкту описані у файлі vcpkg.json, який лежить поруч із кореневим CMakeLists.txt. Виконувати vcpkg install <пакет> вручну не потрібно: toolchain сам запускає установку під час конфігурації.
Мінімальний vcpkg.json
{
"name": "my-application",
"version": "1.0.0",
"dependencies": [
"fmt",
"nlohmann-json",
"spdlog"
]
}
Поля файлу:
| Поле | Призначення |
|---|---|
name | Ім'я проєкту: малі літери, цифри та дефіси |
version | Версія проєкту (також є version-semver, version-date, version-string) |
dependencies | Список залежностей: рядки-назви або об'єкти з додатковими параметрами |
builtin-baseline | Хеш коміту каталогу vcpkg, який фіксує версії (детально в лекції про версії) |
builtin-baseline приймає хеш коміту з 40 символів, а не дату. Запис на кшталт "builtin-baseline": "2024-01-01" не є правильним. Правильне значення vcpkg підставляє сам: vcpkg x-update-baseline --add-initial-baseline.Правильне значення зручно отримати так:
vcpkg x-update-baseline --add-initial-baseline
Команда vcpkg add port <ім'я> додає залежність, не вимагаючи редагувати JSON вручну.
Повний приклад: застосунок із чотирма бібліотеками
Проєкт використовує cxxopts для аргументів командного рядка, spdlog для логування, fmt для форматованого виводу та nlohmann-json для JSON.
Що відбувається під час конфігурації
Одна команда робить усе: бачить vcpkg.json, збирає бібліотеки та підготовляє find_package.
cmake -B build -DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake
cmake --build build
Вміст списку показує: vcpkg взяв зі vcpkg.json чотири пакети, а ще два службових (позначені *) додав сам. Зверніть увагу на Restored 0 package(s): бінарного кешу ще не було, і всі пакети збиралися з джерел. Повторна конфігурація на цьому ж комп'ютері відновить їх із кешу за мілісекунди.
Після конфігурації залежності лежать усередині папки збірки:
| Шлях | Вміст |
|---|---|
build/vcpkg_installed/arm64-osx/include/ | Заголовки бібліотек (fmt/, spdlog/, nlohmann/, cxxopts.hpp) |
build/vcpkg_installed/arm64-osx/lib/ | Бібліотеки .a / .lib |
build/vcpkg_installed/arm64-osx/share/ | CMake Config-файли і файли usage кожного пакета |
Тобто залежності проєкту ізольовані від решти системи: видалення build/ прибирає і їх. Зібрані пакети при цьому зберігаються в бінарному кеші, тому повторна збірка не буде довгою.
Запуск
Допомога, яку згенерував cxxopts:
Як дізнатися, що писати у find_package
Назва порту й назва CMake-пакета не завжди збігаються. Наприклад, порт називається nlohmann-json, а в find_package пишуть nlohmann_json. Після встановлення vcpkg друкує підказку (як було видно у лекції про основи), а також зберігає її у файлі share/<порт>/usage.
| Порт vcpkg | find_package | Ціль для target_link_libraries |
|---|---|---|
fmt | find_package(fmt CONFIG REQUIRED) | fmt::fmt |
spdlog | find_package(spdlog CONFIG REQUIRED) | spdlog::spdlog |
nlohmann-json | find_package(nlohmann_json CONFIG REQUIRED) | nlohmann_json::nlohmann_json |
cxxopts | find_package(cxxopts CONFIG REQUIRED) | cxxopts::cxxopts |
gtest | find_package(GTest CONFIG REQUIRED) | GTest::gtest, GTest::gtest_main |
catch2 | find_package(Catch2 CONFIG REQUIRED) | Catch2::Catch2, Catch2::Catch2WithMain |
cpp-httplib | find_package(httplib CONFIG REQUIRED) | httplib::httplib |
eigen3 | find_package(Eigen3 CONFIG REQUIRED) | Eigen3::Eigen |
boost-* | find_package(Boost CONFIG REQUIRED COMPONENTS ...) | Boost::<компонент> |
sqlite3 | find_package(unofficial-sqlite3 CONFIG REQUIRED) | unofficial::sqlite3::sqlite3 |
curl | find_package(CURL REQUIRED) | CURL::libcurl |
openssl | find_package(OpenSSL REQUIRED) | OpenSSL::SSL, OpenSSL::Crypto |
zlib | find_package(ZLIB REQUIRED) | ZLIB::ZLIB |
yaml-cpp | find_package(yaml-cpp CONFIG REQUIRED) | yaml-cpp::yaml-cpp |
sdl2 | find_package(SDL2 CONFIG REQUIRED) | SDL2::SDL2 |
curl, openssl, zlib) використовують вбудовані модулі CMake, і для них CONFIG не вказують. Пакети з префіксом unofficial- додані спільнотою vcpkg: їхні цілі не збігаються з тими, які надає автор бібліотеки. Точні імена завжди підказує usage або повідомлення після встановлення.Змінні vcpkg для CMake
Toolchain vcpkg.cmake реагує на ряд змінних. Їх задають через -D або у пресеті:
| Змінна | Призначення |
|---|---|
VCPKG_TARGET_TRIPLET | Triplet, для якого встановлювати пакети |
VCPKG_MANIFEST_MODE | ON (за замовчуванням, якщо є vcpkg.json) або OFF |
VCPKG_MANIFEST_DIR | Папка з vcpkg.json, якщо він не в корені проєкту |
VCPKG_INSTALL_OPTIONS | Додаткові параметри команди vcpkg install |
VCPKG_MANIFEST_FEATURES | Необов'язкові групи залежностей, описані в vcpkg.json |
Приклад: збірка зі статичними бібліотеками на Windows та докладним виводом:
cmake -B build -S . ^
-DCMAKE_TOOLCHAIN_FILE=C:/vcpkg/scripts/buildsystems/vcpkg.cmake ^
-DVCPKG_TARGET_TRIPLET=x64-windows-static
Налаштування IDE
VS Code
Розширення «CMake Tools» використовує пресети або налаштування конфігурації. Найпростіший варіант:
{
"cmake.configureSettings": {
"CMAKE_TOOLCHAIN_FILE": "${env:VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
}
}
Файл зберігається як .vscode/settings.json. Запис ${env:VCPKG_ROOT} береться із змінної середовища, тому не залежить від ОС і особистих шляхів. Якщо в проєкті вже є CMakePresets.json, CMake Tools використовує його, і додатково нічого налаштовувати не потрібно.
Visual Studio
Visual Studio 2022 розпізнає vcpkg у двох варіантах:
- Для CMake-проєктів (відкриття папки з
CMakeLists.txt): достатньоCMakePresets.jsonзCMAKE_TOOLCHAIN_FILE, як у способі 4. Крім того, у складі Visual Studio поставляється власна копія vcpkg, і якщо в корені проєкту єvcpkg.json, середовище може саме встановлювати залежності. - Для проєктів MSBuild (
.sln/.vcxproj): виконайтеvcpkg integrate install. Після цього пакети vcpkg доступні в усіх таких проєктах, а в manifest-режимі залежності беруться зvcpkg.json.
CLion
У CLion відкрийте Settings → Build, Execution, Deployment → CMake і додайте в поле «CMake options»:
-DCMAKE_TOOLCHAIN_FILE=/шлях/до/vcpkg/scripts/buildsystems/vcpkg.cmake
Також у Settings → Build, Execution, Deployment → Vcpkg можна додати каталог vcpkg, після чого CLion сам підставляє toolchain у налаштування CMake.
Типові помилки
cmake -L -N build | grep TOOLCHAIN), він заданий після project(), або параметр додано до вже існуючої папки build. Видаліть build/ і повторіть конфігурацію з -DCMAKE_TOOLCHAIN_FILE=... у першому ж виклику.vcpkg.json перезапустіть конфігурацію: cmake -B build. Сучасні IDE роблять це автоматично при збереженні файлу, у терміналі потрібно виконати команду самостійно.vcpkg.json, toolchain працює в manifest-режимі й ігнорує пакети, встановлені через vcpkg install <пакет> у спільну папку. Для експериментів із класичним режимом є змінна VCPKG_MANIFEST_MODE=OFF.CONFIG CMake спершу шукає модуль Findfmt.cmake, якого в стандартному CMake немає, а потім переходить до Config-режиму. Результат залежить від версії CMake та налаштувань політик. З CONFIG пошук відразу йде правильним шляхом, тож запис однозначніший.Практичне завдання
Напишіть утиліту todo, яка зберігає список справ у JSON-файлі:
- Створіть проєкт із
vcpkg.json(залежностіnlohmann-json,cxxopts,fmt) таCMakeLists.txt. - Додайте
builtin-baselineкомандоюvcpkg x-update-baseline --add-initial-baseline. - Реалізуйте команди
--add "текст"і--list. Дані зберігайте уtodo.json. - Зберіть проєкт з пресетом, у якому toolchain заданий через
$env{VCPKG_ROOT}. - Видаліть
build/і зберіть знову. Що змінилось у часі першої та повторної конфігурації?
- Читання файлу:
json::parse(std::ifstream("todo.json")), запис:std::ofstream("todo.json") << data.dump(2);. - Для списку використовуйте масив:
data["items"].push_back(text);. - Друга конфігурація має бути значно швидшою: пакети відновляться з бінарного кешу (
Restored N package(s)).
Резюме
🔌 Toolchain
vcpkg.cmake підключає vcpkg до CMake. Задається через -DCMAKE_TOOLCHAIN_FILE, змінну середовища або пресет, і завжди до project().📄 Manifest
vcpkg.json у корені проєкту описує залежності. CMake сам запускає vcpkg install, а результат лежить у build/vcpkg_installed.🧩 find_package
find_package(<пакет> CONFIG REQUIRED) та цілі виду fmt::fmt. Точні імена показує повідомлення після встановлення.💻 IDE
cmake.configureSettings. Visual Studio: пресети або integrate install. CLion: CMake options.version>=, overrides), features, vcpkg-configuration.json з реєстрами, власні порти, бінарний кеш та діагностику збоїв.vcpkg: встановлення, основні команди та triplets
Що таке vcpkg, встановлення на Windows, Linux і macOS, змінна VCPKG_ROOT, команди search, install, list, remove, upgrade, export, класичний і manifest режими, triplets та їхні реальні властивості.
vcpkg для досвідчених: версії, features, реєстри, власні порти, кеш і діагностика
Фіксація версій через builtin-baseline, version>= та overrides, необов'язкові features, vcpkg-configuration.json із реєстрами та overlay-портами, створення власного порту, бінарний кеш, використання у CI і розв'язання типових проблем.