vcpkg 套件的功能與版本設定(manifest 模式)

| | 0 Comments| 09:53|
Categories:

在前面搭配 Visual Studio 使用時,有大概介紹過要怎麼透過 vcpkg 的指令,來加入要使用的函式庫了。當時在加入 libarchive 後、也自動加入了大量相關聯的函式庫、導致整個前置建置時間拉得很久;而如果再確定用不到某些功能的時候,其實這樣的狀況是可以透過設定來避免的,這篇就來講一下,要怎麼針對要使用的套件做進一步的控制。


修改 manifest 的套件

因為在 manifest 模式下,針對套件的列舉、設定,都是存在 vcpkg.json 這個檔案裡面,所以除了透過 vcpkg 這個指令來做操作外,其實最直接的方法,就是手動編輯 vcpkg.json 這個檔案的內容了~

而在編輯後要讓他產生效用,基本上就是重新執行「vcpkg install」就可以了。

這時候,vcpkg 會去檢查有哪些要新安裝、有哪些要移除、哪些要重編譯,之後都會自己解決。

而如果想要確認他會做那些事的話,也可以加上「--dry-run」、透過「vcpkg install --dry-run」這個指令、讓他先列出來會進行的操作。

不過這邊個人覺得比較奇怪的,是似乎沒有指令可以移除之前已經加入的套件?所以如果要移除一個套件,好像就只能透過手動編輯 vcpkg.json 這個檔案來操作了?


確認 vcpkg 套件的「功能」

執行「vcpkg search libarchive」這個指令的時候,應該會看到類似下面的內容:

libarchive           3.8.1  Library for reading and writing streaming archives
libarchive[bzip2]           BZip2 support
libarchive[crypto]          Support for cryptographic features
libarchive[lz4]             Lz4 support
libarchive[lzma]            Lzma support
libarchive[lzo]             Lzo support
libarchive[xar]             Xar support
libarchive[zstd]            Zstd support

這邊第一行的「libarchive」有 3.8.1 這個版本編號、代表他本身是一個套件。

而下面以「libarcgive[bzip2]」為首、在名稱最後有中括號、後面沒有版本的項目,則代表是 libarchive 的各項「功能」(features);這些功能是一個套件裡面可以個別選擇是否要安裝的東西,像是這邊的 libarchive 就可以根據自己的需求,選擇是否要支援 BZip2、Lz4 等等格式。

vcpkg 會針對一個套件設定預設安裝的功能,如果要知道哪些是預設功能的話,可以透過下面的指令來確認(官方文件):

vcpkg depend-info libarchive

這邊會得到類似下面的結果:

vcpkg-cmake:
vcpkg-cmake-config:
libiconv:
zlib: vcpkg-cmake
vcpkg-cmake-get-vars: vcpkg-cmake
bzip2[tool]: vcpkg-cmake
liblzma: vcpkg-cmake, vcpkg-cmake-config
libxml2[zlib, iconv]: libiconv, vcpkg-cmake, vcpkg-cmake-config, zlib
lz4: vcpkg-cmake, vcpkg-cmake-config
openssl: vcpkg-cmake, vcpkg-cmake-config, vcpkg-cmake-get-vars
zstd: vcpkg-cmake, vcpkg-cmake-config
libarchive[xar, lz4, lzma, crypto, zstd, bzip2]: bzip2, liblzma, libxml2, lz4, openssl, vcpkg-cmake, zlib, zstd

這邊就是他預設會安裝的套件、以及相依性關係;如果相依性關係想要更好看的話,可以加上「--format=tree」、用樹狀結構來顯示。

最底下的

libarchive[xar, lz4, lzma, crypto, zstd, bzip2]

就代表他預設會啟用 xar、lz4、lzma、crypto、zstd、bzip2 這六項功能;也就是說唯一沒有預設安裝的功能、只有 lzo。


調整要安裝的功能

如果要調整要安裝的功能的話,該怎麼做呢?在執行「vcpkg add port」的時候,是可以指定要使用的功能的,基本上就是在後面用中括號來標註。

如果只需要核心功能、不需要任何附加功能的話,可以透過「core」來設定:

vcpkg add port libarchive[core]

如果是這樣加入的話,vcpkg.json 的內容會變成是:

{
   "dependencies": [
     {
       "name": "libarchive",
       "default-features": false
     }
   ]
}

但是要注意的是:如果之前已經有將 libarchive 加入 manifest 裡的話,那再次執行的時候,應該是會用附加的形式來擴增既有的設定、並不會覆蓋掉本來的設定

所以如果連續執行:

vcpkg add port libarchive
vcpkg add port libarchive[core]

這樣第二行基本上會是無效的,最後還是會包含 libarchive 的所有預設功能。

所以,如果需要針對已經加入 vcpkg.json 的套件做功能的調整,比較簡單的方法,應該會是先把本來 libarchive 的項目完全移除、然後再重新執行 vcpkg add port


如果要加入複數的功能的話,基本上只要在中括號裡、透過逗號區隔不同的功能就可以了。

假設這邊只需要 libarchive 的 bzip2 功能的話,可以寫成:

vcpkg add port libarchive[core,bzip2]

這樣 vcpkg.json 會變成:

{
   "dependencies": [
     {
       "name": "libarchive",
       "default-features": false,
       "features": [
         "bzip2"
       ]
     }
   ]
}

如果是這樣下去安裝的話,那之後透過 vcpkg list 來確認安裝的套件的話,結果會是類似下面的狀況:

bzip2:x64-windows               1.0.8#6      bzip2 is a freely available, patent free, high-q...
bzip2[tool]:x64-windows                      Builds bzip2 executable
libarchive:x64-windows          3.8.1        Library for reading and writing streaming archives
libarchive[bzip2]:x64-windows                BZip2 support
vcpkg-cmake:x64-windows         2024-04-23
zlib:x64-windows                1.3.1        A compression library

和之前的狀況比,算是簡化相當多了~

這邊修改過的版本,可以參考這個分支


更新套件版本

vcpkg 在 manifest 模式下,能使用的套件資訊基本上都是依據「vcpkg-configuration.json」中的 registry 的設定而定,在沒有修改這邊的設定的情況下,就算有新版本、也不會抓到、當然也就不能用。

如果是要快速地更新 baseline 的話,vcpkg 有提供一個實驗性質的命令、可以取得、並設定最新的 baseline:

vcpkg x-update-baseline

執行後他會去把「vcpkg-configuration.json」的內容更新到最新版本,方便使用者更新套件的版本。

之後再執行一次 vcpkg install、vcpkg 就會視需要更新安裝的套件了。


使用特定版本的套件

那如果不是要使用最新版、而是要使用特定版本呢?感覺在 vcpkg 要做到這點其實有點麻煩…

首先,沒理解錯的話,某個套件可以用的版本,應該是目前的 baseline 以前的所有版本(會不會因為過時而無法安裝是另一回事)。

但是目前 vcpkg 應該是沒有提供直接的指令可以查詢可以安裝的版本,所以要查詢變成得用 git 的指令才有辦法透過修改紀錄來確認(參考),其實還滿討厭的。

這邊比較簡單的方法,搞不好是直接去 GitHub 的網頁看歷史版本紀錄?
libarchive 來說,要看的檔案會是「versions/l-/libarchive.json」這個檔案(連結)、點右上方的「History」就可以看到他有那些歷史版本了(連結)。


在知道有那些版本後,要怎麼安裝指定的版本呢?vcpkg 的指令似乎也沒有對應的方法可以直接指定版本、需要手動修改 vcpkg.json 才行

如果是要使用特定版本的話,應該是需要額外加入「overrides」來設定(官方文件)。比如說要指定使用 libarchive 3.7.8 的話,可以寫成:

{
   "dependencies": [
     "libarchive"
   ],
   "overrides": [
     {
       "name": "libarchive",
       "version": "3.7.8"
     }
   ]
}

另外、在 vcpkg.jsondependencies 裡面,其實可以透過「version>=」來指定某個套件至少要在特定版本以上(官方文件)。

例如這邊是要確認 libarchive 的版本大於 3.7.2 的話,那可以手動把它改成:

{
   "dependencies": [
     {
       "name": "libarchive",
       "version>=": "3.7.2"
     }
   ]
}

這樣就可以了。而如果目前的 baseline 沒有符合的版本的話,就會出現錯誤、並列出所有可以安裝的版本。

比較有趣的,是這邊的比對似乎不是以版本編號的數字邏輯來比對,而是去比對完整的版本字串、然後透過 git 的修改紀錄來建立版本的新舊關係;所以,這邊設定的版本一定要在 vcpkg 裡面有紀錄才行。

比如說 libarchive 在 vcpkg 中並沒有 3.8.0 版,所以如果把上面的 3.7.2 改成 3.8.0 的話,儘管已經有比較新的 3.8.1 了、他還是會沒辦法找到可以用的版本。


不過,在 dependencies 裡面能針對套件做版本設定的、似乎也只有「version>=」、並沒有辦法限制在特定的版本?如果真的要指定特定版本的話,看來還是只能靠 overrides 來覆寫,這點也是個人覺得很詭異的…


這篇大概就先這樣了。

Leave a Reply

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