vcpkg 的 binary cache 簡單介紹

| | 0 Comments| 10:39|
Categories:

vcpkg 的第三方套件在使用上基本上都是下載原始碼來在自己的環境建置,這對一般小型專案問題應該不算太大。

但是如果套件很多、或是要使用大型套件,而且又需要在多台相同配置的電腦使用的時候,每個環境都還需要重新建置一次、其實就很浪費時間了。像是 CI/CD 環境,如果每個 pipeline 都得把 vcpkg 的套件重建一次,對於有用到大型的第三方函式庫的人來說,可能會很想哭吧。

所以 vcpkg 也有提供「binary cache」的機制(官方文件)、針對建置好的結果作快取、讓之後有必要的時候可以不需要重新建置、直接拿來用。

預設的本機 Binary Cache

vcpkg 預設會使用本機的檔案系統來做 binary cache,他的資料夾會是:

  • Windows
    1. %VCPKG_DEFAULT_BINARY_CACHE%
    2. %LOCALAPPDATA%\vcpkg\archives
    3. %APPDATA%\vcpkg\archives
  • 非 Windows
    1. $VCPKG_DEFAULT_BINARY_CACHE
    2. $XDG_CACHE_HOME/vcpkg/archives
    3. $HOME/.cache/vcpkg/archives

這邊他會按照上面的順序、選擇第一個可以用的路徑。

在 Heresy 的 Windows 上,預設似乎是沒有 %VCPKG_DEFAULT_BINARY_CACHE% 這個路徑,所以是使用 %LOCALAPPDATA%\vcpkg\archives(實際上是 C:\Users\Heresy\AppData\Local\vcpkg\archives)作為 binary cache。

也因此,如果是在不同的專案使用同一個 vcpkg 套件的話,在可以的狀況下,他會去使用之前建置好的版本、而不會在每個專案都重新建置。

修改 Binary cache 的儲存路徑

使用本機資料夾作為 binary cache 對個人開發者來說問題應該不大,但是在跨電腦、或是要跑 CI/CD 的時候,其實算是不太夠用的。也因此,vcpkg 也可以透過環境變數、來定義要使用什麼方式來管理 binary cache。

這邊基本上是要靠 VCPKG_BINARY_SOURCES 這個環境變數來做設定。

以 PowerShell 來說,設定方法是:

$env:VCPKG_BINARY_SOURCES="clear;files,D:\vcpkg\binary-cache,readwrite"

這邊的參數可以有多個設定組成,透過「;」來做區隔,而這邊的例子可以拆成兩部分。

第一個部分是「clear」、代表是要先清除之前關於 binary cache 的設定、包含前面提到的預設路徑。

第二部分則是「files,D:\vcpkg\binary-cache,readwrite」,中間是用「,」做區隔、實際上是三個部分:

  • files:代表是要用檔案系統來儲存 binary cache
  • D:\vcpkg\binary-cache:要使用的路徑、要先建立好資料夾
  • readwrite:權限,這邊代表可以讀取也可以寫入,也就是說除了可以從這邊拿之前建置好的套件,遇到新建置的套件也可以放進去。

這邊也可以同時指定多組設定,做為不同的 binary cache 來源/目的;例如:

$env:VCPKG_BINARY_SOURCES="clear;
files,\\NAS\shared_vcpkg_binary,read;
files,D:\vcpkg\binary-cache,readwrite"

這樣的話,vcpkg 就會先去檢查 \\NAS\shared_vcpkg_binary 這個網芳的路徑,然後試著從這邊拿預先建置好的套件來用。

但是這邊因為是設定成「read」,所以是代表就算有新建置的套件,也不會放把建置好的套件放來這邊讓別人共用;這樣設定應該是限制只有特定的人可以提供共用的快取了。

比較特別的是也可以設定成「write」、代表只能把新建置好的套件放進去、但是不能拿已經建置好的來用。

停用 Binary Cache

而如果完全不想要使用 binary cache 的話,其實也可以設定環境變數:

$env:VCPKG_BINARY_SOURCES="clear"

這樣就完全不會使用 binary cache 了。

但是要注意的,是這樣會大幅提高重新建置同樣的套件的可能性,很有可能會浪費許多時間和計算資源。

其他的 binary cache 管理方式

既然他有一個「files」的設定代表檔案系統,所以當然也有其他形式的儲存方式了。以官方文件有介紹的部分,包括了 nuget 和 GitHub Packages。

由於 Heresy 這邊的需求應該會是搭配 GitLab 使用,所以實際上是可以透過 nuget 來使用 GitLab 的 package registry(官方文件)。

不過這邊要使用的話,在認證的部分由於牽扯到 nuget 本身的設計、瑣碎的問題還滿雜的,所以這邊就先不詳細講了。

而比較奇怪的,是在這邊的測試,在使用 GitLab 的 package registry 作為多系統的 binary cache 的情況下,就算不同的系統都是用同一份 Docker 映像檔來執行同一個專案的建置,不知道為什麼還是會出現不使用已經建置好的 binary cache、而是各自重新建置的狀況,感覺沒有達到當初設定 binary cache 的目的?

設定機制的限制

在實務上,個人覺得 vcpkg 設計用環境變數來指定 binary cache 有一個問題,是這樣的架構基本上會是以整個系統都用同樣的 binary cache 為概念來做的。

像是如果是打算把 binary cache 放在 GitLab 的 package registry、讓多電腦可以共用的時候,感覺上會變得很難針對個別專案做快取來源的控制。比如說想要讓專案 A 和 專案 B 對應到個別的 GitLab 專案的 package registry 的話,基本上要做到個別控制就相當麻煩了…

Binary Cache 的管理

如果是使用檔案系統來存放 vcpkg 的 binary cache,那碰到的問題可能會是難以管理了。

在進到 binary cache 的資料夾之後,會看到第一層目錄都是兩個字員組成的資料夾,裡面都是一堆以檔名應該是 hash 過的結果的 zip 檔案,基本上不解壓縮都看不出來是什麼東西。

所以實際上要自己來管理這邊的東西,基本上應該是很難進行的吧…

而如果是使用 GitLab 的 package registry 的話,雖然說 GitLab 有提供網頁介面,所以會相對好很多;但是實際上由於 vcpkg 建置出來的套件在版本編號的部分,除了本來的版本編號後、都還會加上建置環境的 hash,所以也有很大的機會會出現同一個套件的同一個版本會有好幾個建置結果的狀況。基本上,要管理還是有點麻煩。


另外,實務上在使用的時候,個人覺得一個很大的問題,是 vcpkg 對開發環境的偵測感覺還滿敏感的,只要有一些小變動,hash 的結果就會不一樣、需要重建。

像是目前 Visual Studio 應該是每個月都會更新一次小版本,這個時候其實第三方套件並沒有重建的必要,但是如果是使用 Visual Studio 的話,就會自動開始重建了…

技術上應該是可以透過一些 triplet 的變數來做控制(官方文件),像是透過設定「VCPKG_DISABLE_COMPILER_TRACKING」應該是可以關閉編譯器版本的追蹤、進而降低重建的頻率;不過基本上這邊應該就是要自己定義一個 triplet 出來,而 Heresy 這邊還沒試過這個參數,就不知道會不會有什麼副作用了…

Leave a Reply

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *