我們開始用 vcpkg 之後,一直有個問題:
vcpkg.json 裡只寫 fmt,沒寫版本號碼,那我們專案用的到底是哪個版本?是 fmt 10, 11 還是 12?要去哪裡看?畢竟不同版本之間的 API 可是有點差異的。
要回答這個問題,我們就要先知道 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,切換到 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": 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。
有一天 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 的版本也換了。
這個狀況有點討厭。
大型商業專案中,第三方套件版本升級要非常小心,以避免引入不必要的問題。
有時候我們真的只想升級某一個套件就好。你就是需要某個套件新一點的版本,但不想動整個 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:
{
"dependencies": [
"fmt",
"nlohmann-json"
],
"overrides": [
{ "name": "fmt", "version": "11.2.0" }
]
}
overrides 會跳過上面的選版規則,直接用你寫的版本,不管 baseline 或其他套件的怎麼說。
overrides 指定的版本號碼,必須要有記錄在案。 vcpkg repo 的 versions/f-/fmt.json 這個檔案就條列了過去收錄過的版本清單。不在這份清單上的版本,寫進 overrides 會直接報錯。vcpkg 只能用它收錄過的版本,不能指定任意 git tag。
vcpkg x-update-baseline。version>= 只能往上拉,想降版要用 overrides。