iT邦幫忙

2026 iThome 鐵人賽

DAY 12
0
Software Development

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

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

  • 分享至 

  • xImage
  •  

我們開始用 vcpkg 之後,一直有個問題:

vcpkg.json 裡只寫 fmt,沒寫版本號碼,那我們專案用的到底是哪個版本?是 fmt 10, 11 還是 12?要去哪裡看?畢竟不同版本之間的 API 可是有點差異的。

要回答這個問題,我們就要先知道 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,切換到 dc1232a6 這個 commit。

然後查看 repo 裡的檔案 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 倉庫的一個歷史版本,這個歷史版本裡面有全部套件的清單加上版本號。這組版本號是「vcpkg 官方在某一天驗證過、能一起用的版本清單」。你挑中一個歷史版本,vcpkg 就幫你決定了整組套件的版本號碼。

port-version 是什麼

上面的 "port-version": 1 不是 fmt 的版本,是 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。把 baseline 換成 vcpkg repo 最新的 commit。

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

vcpkg x-update-baseline

它會去 GitHub 查 microsoft/vcpkg 最新的 commit,把 vcpkg-configuration.json 裡的 baseline 改成最新的那個。然後重新 configure,vcpkg 就會把有變動的套件重新編一次。

這是官方建議的升級方式:不要一個一個套件升,整批一起升。

因為 baseline 裡的版本組合是 vcpkg 的 CI 一起測過的。

但是一旦更新了 baseline,通常不會只動到 fmt 的版本,而是整個專案的所有套件版本都有可能都變了,畢竟 baseline 裡面搞不好 nlohmann-json 的版本也換了。

version>=:要求最低版本

這個狀況有點討厭。

大型商業專案中,第三方套件版本升級要非常小心,以避免引入不必要的問題。

有時候我們真的只想升級某一個套件就好。你就是需要某個套件新一點的版本,但不想動整個 baseline。這時候怎麼辦?

就是在 vcpkg.json 裡寫 version>=:

{
  "dependencies": [
    {
      "name": "fmt",
      "version>=": "12.2.0"
    },
    "nlohmann-json"
  ]
}

我們把 dependency 下面的 "fmt" 字串變成JSON物件了,可以單獨指定版本。如果這個版本比 baseline 裡的 fmt 新,vcpkg 就改用這個版本。

請注意:version>= 的版本只能升級,不能往回降版本。

意思是你只能選比 baseline 更新的版本。寫一個比 baseline 舊的版本,vcpkg 會直接忽略,還是用 baseline 的版本。

overrides:直接指定版本

真的要降版,只能用 overrides:

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

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

overrides 指定的版本號碼,必須要有記錄在案。 vcpkg repo 的 versions/f-/fmt.json 這個檔案就條列了過去收錄過的版本清單。不在這份清單上的版本,寫進 overrides 會直接報錯。vcpkg 只能用它收錄過的版本,不能指定任意 git tag。

小結

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

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

尚未有邦友留言

立即登入留言