iT邦幫忙

2026 iThome 鐵人賽

DAY 14
0
Software Development

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

D14:Conan Package ID 與 Revision 是什麼?

  • 分享至 

  • xImage
  •  

今天會解釋 Conan 幾個重要的名詞:Package ID、Package Revision、Recipe Revision。

看起來很嚇人嗎?其實不會啦,看下去就知道了。

我們都知道 C++ 套件管理是個特別麻煩的東西,尤其是處理二進位檔的時候,同一份 fmt/12.2.0 的原始碼,編譯出來一份給 Windows、一份給 macOS,Debug/Release 又各要一份,同平台上的每個編譯器版本又各一份 (gcc10/13、Xcode16/26、Visual Studio 2019/2022)。

Conan 要怎麼知道該拿哪一份二進位檔?

答案就是透過這些 Package ID、Revision 之類的東西來分辨的。

今天的目標:搞懂 Recipe Revision、Package ID、Package Revision 這三個東西各代表什麼,還有 Package ID是怎麼算出來的。

一、哪裡會出現這些 Package ID/ Revision 呀?

如果你之前跑過這個系列的範例,請再跑一次 conan install 指令:

conan install . --build=missing

看輸出的這一行:

fmt/12.2.0#b445244e6d0151a425e229248cd2bed8:8db65e2827b8126426a61b6cb7bf0c8a67f5915d#7c7bb68c3f6404d3a32a9e4682a011d9 - Cache

哇,除了套件版本號碼(fmt/12.2.0)以外,後面還有一個好長的隨機字串!

這是在我的 MacBook Air (Xcode26) 上跑出來的結果,你看到的字串可能會跟我的不一樣。

仔細看,這一串字可以拆成四段結構:

  • 第一段 fmt/12.2.0 是套件名稱和版本。
  • 第二段 #b445244e... 是 Recipe revision,也就是 recipe 的版本。
  • 第三段 :8db65e28... 是 Package ID,代表是哪一個二進位檔,這是今天的主角。
  • 第四段 #7c7bb68c... 是 Package revision,也就是這個二進位檔的版本。

這一串字才是完整的套件,接下來,我們一段一段看。

二、Recipe 與 Recipe Revision

Recipe 這個字的中文意思是「食譜」,因為準備套件的過程,很像照著食譜上的步驟,一步一步進行烹煮,最後完成一道料理,是很生動的比喻。

所以我們用 Recipe 來統稱 conanfile.py 以及一些打包套件的周邊輔助檔案。

Conan 官方幫 fmt 寫了一份食譜,裡面寫著 fmt 的原始碼去哪裡下載、要怎麼編譯、編完之後哪些檔案要打包起來。然後官方就用這份食譜實際去打包 fmt 產生二進位檔,然後我們才有 fmt 套件可以直接抓下來用。

這個 Recipe Revision 就是食譜版本,也就是那串長字串裡的第二段:

fmt/12.2.0#b445244e6d0151a425e229248cd2bed8

這個 Recipe Revision 是根據 conanfile.py 加上幾個周邊檔案內容計算出來的 hash 字串。

有時候 ConanCenter 會修改食譜,例如修正某個平台的編譯問題、改一下打包方式。

食譜的內容變了,但是 fmt 的原始碼都沒變,版本號也還是 12.2.0,此時就會多出一個 Recipe Revision。因為 recipe 一有改動,算出來的 hash 就不一樣。

來看看 fmt/10.2.1 在 ConanCenter 上一共改過五次食譜,套件重新打包了五次。

conan list "fmt/10.2.1#*" -r conancenter
conancenter
  fmt
    fmt/10.2.1
      revisions
        9199a7a0611866dea5c8849a77467b25 (2024-01-05 00:38:40 UTC)
        8d582aeebdf05b6f0abe2911b926c3f4 (2024-07-03 14:13:49 UTC)
        658771bb858b77f380be2ebb22c338e9 (2025-01-03 10:12:47 UTC)
        25441914a1da0c98628fb50c865639f8 (2026-05-07 09:24:38 UTC)
        15db2a3ea0646365bf05a6f50369ac59 (2026-08-03 10:56:10 UTC)

三、Package ID

接下來講字串中的第三段:Package ID。

C++ 在編譯原始碼的時候,有很多互不相容的設定,這就是所謂的 settings/options,詳細的內容可以回去看 D08 Conan Profile。

而把這些 settings/options 揉起來計算出一個 hash,這就是 Package ID。

只要用同樣的 settings/options 來編譯套件,就會計算出一模一樣的 Package ID。相對的,只要換了編譯器,或者改動任何一項 settings/options,就會計算出不同的 Package ID。

所以 Package ID 就是對應到一組編譯設定、選項和依賴。

來查看看 ConanCenter 上面的 fmt/12.2.0 有幾個 Package ID:

conan list "fmt/12.2.0:*" -r conancenter

這張圖就是我執行上面指令的結果,數一數裡面應該一共有 11 個 Package。從截圖裡可以看到最上頭的兩個 Package ID,都是 MSVC 編譯器,一個是 x86_64 架構,另一個是 armv8 架構。

Package List

Header only 的套件比較特別。
像是 nlohmann_json 的 package ID 只有一個 da39a3ee5e6b4b0d3255bfef95601890afd80709
這是因為 nlohmann_json 是 header-only,套件裡只有標頭檔,沒有預編譯 lib,所以不需要區分編譯器、Debug、Release 等等設定。所有的平台跟編譯器都拿到同一份 Package。
da39a3ee... 其實就是「空字串」的 SHA-1。什麼都沒放進去算,算出來就是這個值。

四、Package Revision

最後一段是 Package Revision。

Package ID 告訴你二進位檔是用哪一個編譯器組態編譯出來的(例如 Release、msvc 194、靜態庫)。

Package Revision 則是拿打包好的最終產出二進位檔案內容算出 hash。

所以一直到走到第四步 Package Revision 為止,我們才終於拿到了一包二進位檔。

看到這裡你可能會有個疑問:既然食譜(Recipe)沒變、編譯設定(Package ID)也都一樣,為什麼產出的二進位檔還需要版本號?

原來啊,就算原始碼和參數都一樣,換一台機器、編譯器更新一下,編出來的二進位檔還是可能有一點點不同。

Conan 不會偷偷蓋掉舊的那包,它會再給新的那包一個新的 Package Revision,就像是這次編譯結果的「指紋」,所以每一包都找得回來。

那我們平常開發需要管它嗎?通常是不用啦!

在日常開發中,Conan 預設自動幫你挑最新的那包 Package Revision。

五、跟著 conan install 走一遍

回頭看 conan install 指令的輸出,從頭到尾仔細看,你會發現 Conan 其實分兩個階段做事。

第一階段先處理食譜(Recipe Revision):


======== Computing dependency graph ========
...
Requirements
    fmt/12.2.0#b445244e6d0151a425e229248cd2bed8 - Cache
    nlohmann_json/3.12.0#2d634ab0ec8d9f56353e5ccef6d6612c - Cache

這裡每一個套件都只有 Recipe Revision,後面兩段都沒有,因為這時候 Conan 還在計算套件的相依關係。

第二階段 Conan 開始找二進位檔,套件名後面才多了 Package ID & Package Revision:


======== Computing necessary packages ========
Requirements
    fmt/12.2.0#b445244e6d0151a425e229248cd2bed8:8db65e2827b8126426a61b6cb7bf0c8a67f5915d#7c7bb68c3f6404d3a32a9e4682a011d9 - Cache
    nlohmann_json/3.12.0#2d634ab0ec8d9f56353e5ccef6d6612c:da39a3ee5e6b4b0d3255bfef95601890afd80709#2ea4b814fc9da53f7cdf5b7d68052688 - Cache

小結

  1. Conan 套件的完整名稱分四段:套件名/版本、Recipe Revision、Package ID、Package Revision。
  2. Recipe Revision 是食譜內容的 hash,食譜一改就換新的。
  3. Package ID 是編譯設定、選項和依賴算出來的 hash,同一份食譜可以有很多個 Package ID。
  4. Package Revision 是二進位檔內容的 hash,平常開發不用管它,Conan 會自動挑最新的。

上一篇
D13:Conan 版本範圍
下一篇
D15:自己打包第一個 Conan 套件
系列文
C++ 套件管理器求生指南 Conan vs Vcpkg 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言