從這篇開始換 vcpkg 上場囉。vcpkg 是微軟開發的一套 C++ 套件管理器。
今天我們的目標非常簡單,就是建立第一個 vcpkg + CMake 的專案,把這條路打工:

我的測試環境如下
安裝步驟微軟的官方教學就寫得很清楚,參考連結:
https://learn.microsoft.com/zh-tw/vcpkg/get_started/get-started
這裡我也很快的講一遍:vcpkg 安裝法是直接 clone 它的 GitHub repo,再跑 bootstrap 腳本
git clone https://github.com/microsoft/vcpkg.git
cd vcpkg
.\bootstrap-vcpkg.bat
如果是 macOS/Linux 就改跑 ./bootstrap-vcpkg.sh
bootstrap 腳本會下載一個編譯好的 vcpkg 執行檔,放在 repo 根目錄。
macOS 要先裝好 Xcode Command Line Tools,不然 bootstrap 會失敗。
接著設定兩個環境變數
VCPKG_ROOT : 指向你剛剛 clone 下來的 github repo 位置。VCPKG_ROOT 加入 PATH 環境變數。用命令列確認一下可以呼叫 vcpkg:
vcpkg --version
有看到版本號碼印出來就是安裝成功囉。
我們一樣從最基本的迷你 CMake 專案開始,目錄結構如下:
hello-vcpkg/
├── CMakeLists.txt
└── src/
└── main.cpp
接著,請到專案根目錄執行以下命令:
vcpkg new --application
執行後,目錄下會多出兩個檔案:vcpkg.json 以及 vcpkg-configuration.json
hello-vcpkg/
├── vcpkg.json
├── vcpkg-configuration.json
├── CMakeLists.txt
└── src/
└── main.cpp
vcpkg.json 這個檔案就是 vcpkg 的入口。
這種把套件清單寫在專案裡的用法,叫做 Manifest Mode(清單模式)。
vcpkg 還有另一種比較舊的 Classic Mode(傳統模式)。如果你在網路上找教學,看到
vcpkg install fmt這種 install 後面直接接套件名稱的寫法,就是舊式的 Classic Mode。這個系列只會介紹新式的 Manifest Mode。
下一步,就是為專案導入 fmt 以及 nlohmann JSON 這兩個套件,請輸入以下命令:
vcpkg add port fmt nlohmann-json
指令跑完後,我們去查看 vcpkg.json 的內容,會發現多出了兩個字串值:
{
"dependencies": [
"fmt",
"nlohmann-json"
]
}
這樣就是設定好了。有兩個小地方注意:
nlohmann-json。查詢套件名稱 https://vcpkg.io/en/packages
fmt,不用寫套件的版本號碼。不用寫版本號碼?那版本是怎麼決定的呢?
原來啊,vcpkg 會幫你選好版本號碼,所有 vcpkg 套件的版本是整批一起鎖住的,如果要一個一個指定每個套件的版本,需要特別的設定,這些留待以後再解釋。
這是 CMakeLists.txt
cmake_minimum_required(VERSION 3.23)
project(hello_vcpkg CXX)
find_package(fmt CONFIG REQUIRED)
find_package(nlohmann_json CONFIG REQUIRED)
add_executable(hello src/main.cpp)
target_compile_features(hello PRIVATE cxx_std_17)
target_link_libraries(hello PRIVATE
fmt::fmt nlohmann_json::nlohmann_json)
這是一個看起來再平凡不過的 CMake 專案入口。
用 find_package() 先尋找外部函式庫,然後用 target_link_libraries() 來連結函式庫。
注意 find_package 裡面用的名字是 nlohmann_json(底線)。但是 vcpkg 套件名稱是 nlohmann-json (連字號),竟然有這樣微妙的差別!
所以要小心 vcpkg 給套件取名字,不一定會完全跟函式庫作者決定的 CMake package 名稱相同。
接著這是 main.cpp
#include <fmt/base.h>
#include <nlohmann/json.hpp>
int main()
{
nlohmann::json j = {
{"name", "vcpkg"},
{"language", "C++"},
{"stars", 9000}
};
fmt::print("Hello, {}!\n", j["name"].get<std::string>());
fmt::print("{}\n", j.dump(2));
return 0;
}
寫好之後,我們就要來看這個平凡無奇的 CMake 專案,到底是怎麼透過 vcpkg 導入套件的。
接著我們要來編譯專案囉!
vcpkg 跟 CMake 接軌的方式,是透過 toolchain file,檔案位置在:$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake。
我們要用 -DCMAKE_TOOLCHAIN_FILE 把這個檔案傳遞給 CMake。
請執行以下指令,路徑記得用引號括起來。
Windows(PowerShell)
cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE="$env:VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake"
macOS / Linux
cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE="$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" -DCMAKE_BUILD_TYPE=Release
此時的 CMake configure 輸出會多印出一大段 vcpkg 的訊息:
-- Running vcpkg install
Detecting compiler hash for triplet x64-windows...
The following packages will be built and installed:
fmt:x64-windows@12.x.x
* nlohmann-json:x64-windows@3.12.0
* vcpkg-cmake:x64-windows@...
* vcpkg-cmake-config:x64-windows@...
...
-- Running vcpkg install - done
第一次 CMake configure 會跑特別久。是在做什麼呢?
原來是在你的電腦上,從原始碼編譯每個套件。
編譯好之後 vcpkg 會把結果快取起來(binary caching),所以不用擔心,下次同樣的套件就不需重新編譯了。
套件會被裝在 build/vcpkg_installed/ 底下,每個專案各自一份。
下一步,就來編譯專案本體啦!
Windows(Visual Studio)
cmake --build build --config Release
build\Release\hello.exe
macOS / Debian(single-config generator)
cmake --build build
./build/hello
執行結果:
Hello, vcpkg!
{
"language": "C++",
"name": "vcpkg",
"stars": 9000
}
如果你用 Windows,打開執行檔目錄,你會發現旁邊多出一個 fmt.dll,這是 vcpkg 建置專案完畢之後自動幫你複製過去的。
恭喜你,打通了第一個 vcpkg 專案!
使用 vcpkg 的流程,說穿了只需要三步:
vcpkg new --application:初始化 vcpkg.jsonvcpkg add port:宣告要用哪些套件cmake -DCMAKE_TOOLCHAIN_FILE=...:指定 Toolchain file 後,照平常的方式編譯就好了。應該不算難吧。