開始用 vcpkg 之後,你可能一直有個問題:
vcpkg.json 裡只有套件名字,沒有版本號碼,所以我們導入的函式庫到底是哪一個版本?是 fmt 10, 11 還是 12?到底要怎麼確認呢?
要回答這個問題,我們就要先知道什麼是 baseline 。
這個東西是 vcpkg 版本控制的基礎。

進入專案目錄,打開 vcpkg-configuration.json 這個檔案:
{
"default-registry": {
"kind": "git",
"baseline": "dc1232a6e05dcc49703091e83743e3b4df9b9b7c",
"repository": "https://github.com/microsoft/vcpkg"
}
}
有一個JSON欄位叫做 baseline。這個很長一串字是 microsoft/vcpkg 這個 repo 的一個 commit hash。
紀錄 commit hash 幹啥用呢?
原來啊,整個 vcpkg 的套件版本都是透過 git 來管理的。透過這個 baseline 我們就可以查到套件的版本號碼。
請打開 vcpkg repo 切換到剛剛 baseline 指定的 commit dc1232a6。
接著查看 versions/baseline.json 這個檔案,裡頭記錄了所有套件的版本。
我在 baseline.json 裡面全文搜尋關鍵字 fmt 和 nlohmann-json,找到以下內容:
"fmt": {
"baseline": "12.2.0",
"port-version": 1
},
....
"nlohmann-json": {
"baseline": "3.12.0",
"port-version": 2
},
....
看到版本號碼了!
所以原來這幾天的範例中,我們編譯的是 fmt 12.2.0 以及 nlohmann-json 3.12.0 呀~~
這就是 baseline。
baseline 是 vcpkg 倉庫的一個歷史版本(commit),這個歷史版本裡面指定了全部套件的版本號碼,是「vcpkg 官方在某一天驗證過、能一起用的版本清單」。
給你挑一個 vcpkg 歷史版本(commit),然後 vcpkg 就幫你決定了整組套件版本。
除了套件版本以外,還有一個 port-version 是vcpkg 打包腳本的版本。有時候 vcpkg 修正了打包方式(例如改了 patch、修了某個平台的編譯問題),但是 fmt 原始碼還是 12.2.0 沒變,就把 port-version 加一。寫成文字的時候用 # 接在版本號碼後面:12.2.0#1。
排序規則:12.2.0 < 12.2.0#1 < 12.2.1。
假設有一天 fmt 推出了新版,而我們想要升級 fmt 套件,該怎麼做呢?
官方推薦的正統作法,就是更新 baseline,換成 vcpkg repo 最新的 commit。
這件事不用自己去查 commit hash,只要打指令:
vcpkg x-update-baseline
它就會把 vcpkg-configuration.json 裡的 baseline 改成最新的那個。更新後重新編譯專案時,vcpkg 會把有變動的套件重新編譯一次。
這是官方建議的升級方式:不要一個一個套件升,整批一起升。 因為 baseline 裡的版本組合是 vcpkg 的 CI 一起測過的。
但是一旦更新了 baseline,通常不會只動到一個套件的版本,而是整個專案的所有套件版本都有可能變了,此時除了 fmt 搞不好 nlohmann-json 的版本也換了,這個就有點討厭。
在大型商業專案中,通常升級第三方套件版本都要非常小心,大家都不想因為套件而引入意外的問題。
有時候我們真的只想升級一個套件就好,不想動整個 baseline,因為一次改一堆函式庫真的風險有點大。這時候怎麼辦?
有一個辦法,就是在 vcpkg.json 裡寫 version>=:
{
"dependencies": [
{
"name": "fmt",
"version>=": "12.2.0"
},
"nlohmann-json"
]
}
我們把 dependency 下面的 "fmt" 轉成 JSON物件。然後用 version>= 指定版本。這個版本號碼必須比 baseline 裡的 fmt 新。vcpkg 會挑「滿足該條件的最低版本」,所以通常用的就是你寫的那一版,不會自動跳到最新版。
另外,version>= 一定要搭配 baseline,沒有 baseline 的話 vcpkg 會直接報錯。
請注意:version>= 的版本只能升級,不能往回降版本。
意思是你只能選比 baseline 更新的版本。寫一個比 baseline 舊的版本等於沒寫,因為 version>= 只是下限,baseline 的版本本來就已經滿足它,所以還是用 baseline 的版本。
真的要降版,只能用 overrides:
{
"dependencies": [
"fmt",
"nlohmann-json"
],
"overrides": [
{ "name": "fmt", "version": "11.2.0" }
]
}
overrides 會跳過上面的選版規則,直接用你寫的版本,不管 baseline 或其他套件怎麼要求。
overrides 指定的版本號碼,必須要曾經記錄在案。 vcpkg repo 的 versions/f-/fmt.json 這個檔案就條列了過去收錄過的版本清單。不在清單上的版本號碼,寫進 overrides 會直接報錯。
vcpkg x-update-baseline。version>= 只能往上拉,想降版要用 overrides。