在前面搭配 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.json 的 dependencies 裡面,其實可以透過「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 來覆寫,這點也是個人覺得很詭異的…
這篇大概就先這樣了。
