CMake і vcpkg

vcpkg і CMake: toolchain-файл, manifest vcpkg.json, IDE

Як підключити vcpkg до CMake-проєкту: toolchain-файл і порядок його підключення, змінні середовища, пресети, manifest-режим з vcpkg.json, повний приклад з fmt, spdlog, nlohmann-json і cxxopts, налаштування VS Code, Visual Studio та CLion.

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

Після цього достатньо 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_TOOLCHAIN_FILE середовища прибрана, а vcpkg.json однаковий):

два варіанти порядку
неправильно (після project)
CMake Error at CMakeLists.txt:11 (find_package):
Could not find a package configuration file provided by "fmt" with any of
fmtConfig.cmake
fmt-config.cmake
правильно (до project)
-- Running vcpkg install
fmt:arm64-osx@10.2.1
Installing 3/3 fmt:arm64-osx@10.2.1...

У першому випадку 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.

Виберіть один спосіб для проєкту. Для навчальних проєктів достатньо способу 1. Для командного проєкту краще пресети, бо їх підтримують Visual Studio, CLion і VS Code.

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 x-update-baseline --add-initial-baseline
$ vcpkg add port fmt
Succeeded in adding ports to vcpkg.json file.
$ vcpkg x-update-baseline --add-initial-baseline
updated registry 'https://github.com/microsoft/vcpkg': baseline '' -> '1d611efb49276c65d69fb6d010c2aaaf039322b0'

Команда 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
cmake -B build (перший запуск, фрагмент)
$ cmake -B build -DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake
-- Running vcpkg install
Detecting compiler hash for triplet arm64-osx...
Compiler found: /usr/bin/c++
The following packages will be built and installed:
cxxopts:arm64-osx@3.3.1#1
fmt:arm64-osx@12.1.0
nlohmann-json:arm64-osx@3.12.0#1
spdlog:arm64-osx@1.16.0
* vcpkg-cmake:arm64-osx@2024-04-23
* vcpkg-cmake-config:arm64-osx@2024-05-23
Additional packages (*) will be modified to complete this operation.
Restored 0 package(s) from /Users/student/.cache/vcpkg/archives in 30.2 us.
Installing 1/6 vcpkg-cmake-config:arm64-osx@2024-05-23...
...
-- Configuring done (12.0s)
-- Generating done (0.0s)

Вміст списку показує: 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/ прибирає і їх. Зібрані пакети при цьому зберігаються в бінарному кеші, тому повторна збірка не буде довгою.

Запуск

./build/AwesomeApp --name Іван --verbose
$ ./build/AwesomeApp --name "Іван" --verbose
[2026-11-07 08:58:39.316] [info] Application started
[2026-11-07 08:58:39.317] [debug] Verbose mode is ON
Hello, Іван!
fmt library version: 12.1.0
Configuration:
{
"features": [
"logging",
"json",
"colors"
],
"user": "Іван",
"verbose": true,
"version": "1.0.0"
}
User from JSON: Іван
Features count: 3
[2026-11-07 08:58:39.317] [info] Application finished successfully

Допомога, яку згенерував cxxopts:

./build/AwesomeApp --help
$ ./build/AwesomeApp --help
Демонстрація популярних C++ бібліотек
Usage:
AwesomeApp [OPTION...]
-n, --name arg Your name (default: World)
-v, --verbose Verbose output
-h, --help Print help

Як дізнатися, що писати у find_package

Назва порту й назва CMake-пакета не завжди збігаються. Наприклад, порт називається nlohmann-json, а в find_package пишуть nlohmann_json. Після встановлення vcpkg друкує підказку (як було видно у лекції про основи), а також зберігає її у файлі share/<порт>/usage.

Порт vcpkgfind_packageЦіль для target_link_libraries
fmtfind_package(fmt CONFIG REQUIRED)fmt::fmt
spdlogfind_package(spdlog CONFIG REQUIRED)spdlog::spdlog
nlohmann-jsonfind_package(nlohmann_json CONFIG REQUIRED)nlohmann_json::nlohmann_json
cxxoptsfind_package(cxxopts CONFIG REQUIRED)cxxopts::cxxopts
gtestfind_package(GTest CONFIG REQUIRED)GTest::gtest, GTest::gtest_main
catch2find_package(Catch2 CONFIG REQUIRED)Catch2::Catch2, Catch2::Catch2WithMain
cpp-httplibfind_package(httplib CONFIG REQUIRED)httplib::httplib
eigen3find_package(Eigen3 CONFIG REQUIRED)Eigen3::Eigen
boost-*find_package(Boost CONFIG REQUIRED COMPONENTS ...)Boost::<компонент>
sqlite3find_package(unofficial-sqlite3 CONFIG REQUIRED)unofficial::sqlite3::sqlite3
curlfind_package(CURL REQUIRED)CURL::libcurl
opensslfind_package(OpenSSL REQUIRED)OpenSSL::SSL, OpenSSL::Crypto
zlibfind_package(ZLIB REQUIRED)ZLIB::ZLIB
yaml-cppfind_package(yaml-cpp CONFIG REQUIRED)yaml-cpp::yaml-cpp
sdl2find_package(SDL2 CONFIG REQUIRED)SDL2::SDL2
Деякі пакети (curl, openssl, zlib) використовують вбудовані модулі CMake, і для них CONFIG не вказують. Пакети з префіксом unofficial- додані спільнотою vcpkg: їхні цілі не збігаються з тими, які надає автор бібліотеки. Точні імена завжди підказує usage або повідомлення після встановлення.

Змінні vcpkg для CMake

Toolchain vcpkg.cmake реагує на ряд змінних. Їх задають через -D або у пресеті:

ЗміннаПризначення
VCPKG_TARGET_TRIPLETTriplet, для якого встановлювати пакети
VCPKG_MANIFEST_MODEON (за замовчуванням, якщо є 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.

Типові помилки

Практичне завдання

Резюме

🔌 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

VS Code: cmake.configureSettings. Visual Studio: пресети або integrate install. CLion: CMake options.
Далі розглянемо просунуті можливості vcpkg: фіксацію версій (baseline, version>=, overrides), features, vcpkg-configuration.json з реєстрами, власні порти, бінарний кеш та діагностику збоїв.
Copyright © 2026