iT邦幫忙

2026 iThome 鐵人賽

DAY 12
0
Software Development

C++ 套件管理器求生指南 Conan vs Vcpkg系列 第 12 篇

D12:vcpkg 的版本控制與 baseline 概念

  • 分享至 

  • xImage
  •  

開始用 vcpkg 之後,你可能一直有個問題:

vcpkg.json 裡只有套件名字,沒有版本號碼,所以我們導入的函式庫到底是哪一個版本?是 fmt 10, 11 還是 12?到底要怎麼確認呢?

要回答這個問題,我們就要先知道什麼是 baseline 。

這個東西是 vcpkg 版本控制的基礎。

一、什麼是 Baseline?

進入專案目錄,打開 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。

二、升級套件版本:換一個 baseline

假設有一天 fmt 推出了新版,而我們想要升級 fmt 套件,該怎麼做呢?

官方推薦的正統作法,就是更新 baseline,換成 vcpkg repo 最新的 commit。

這件事不用自己去查 commit hash,只要打指令:

vcpkg x-update-baseline

它就會把 vcpkg-configuration.json 裡的 baseline 改成最新的那個。更新後重新編譯專案時,vcpkg 會把有變動的套件重新編譯一次。

這是官方建議的升級方式:不要一個一個套件升,整批一起升。 因為 baseline 裡的版本組合是 vcpkg 的 CI 一起測過的。

但是一旦更新了 baseline,通常不會只動到一個套件的版本,而是整個專案的所有套件版本都有可能變了,此時除了 fmt 搞不好 nlohmann-json 的版本也換了,這個就有點討厭。

三、version>=:要求最低版本

在大型商業專案中,通常升級第三方套件版本都要非常小心,大家都不想因為套件而引入意外的問題。

有時候我們真的只想升級一個套件就好,不想動整個 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:直接指定版本

真的要降版,只能用 overrides:

{
  "dependencies": [
    "fmt",
    "nlohmann-json"
  ],
  "overrides": [
    { "name": "fmt", "version": "11.2.0" }
  ]
}

overrides 會跳過上面的選版規則,直接用你寫的版本,不管 baseline 或其他套件怎麼要求。

overrides 指定的版本號碼,必須要曾經記錄在案。 vcpkg repo 的 versions/f-/fmt.json 這個檔案就條列了過去收錄過的版本清單。不在清單上的版本號碼,寫進 overrides 會直接報錯。

小結

  • baseline 是 vcpkg repo 的一個 commit,決定所有套件的預設版本。
  • 想升套件版本最好的方式是換 baseline,指令是 vcpkg x-update-baseline。
  • version>= 只能往上拉,想降版要用 overrides。

上一篇
D11:vcpkg 的 triplet 是什麼碗糕?
下一篇
D13:Conan 版本範圍
系列文
C++ 套件管理器求生指南 Conan vs Vcpkg 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言