搭配 Visual Studio 使用 vcpkg

| | 0 Comments| 10:51|
Categories:

前一篇大概介紹了 vcpkg 這個由微軟推出的 C++ 套件管理工具,這一篇則是來比較詳細地記錄一下在 Windows 上以 Visual Studio 做為開發工作、搭配 vcpkg 來使用,之後也讓專案可以在 Linux 上透過 Makefile + g++ 可以建置的狀況。

這邊的使用情境會是「Manifest 模式」、以專案為導向的設定。

在個人來看,使用 vcpkg 來管理第三方函式庫的好處,大致上是:

  • 在 Visual Studio / Linux 兩個開發環境都可以有同樣的第三方函式庫管理機制
  • 專案中不需要另外設定 header、lib 等路徑資訊
  • 在正確設定完成後,Visual Studio 會自動建置第三方函式庫、不需要另外的操作
  • vcpkg.json 這個設定檔案隨著專案原始碼一起發布,可以讓其他人更明確地知道專案需要那些第三方函式庫,也可以更方便地安裝。


安裝、前期設定

在使用 Visual Studio 時要使用 vcpkg 的話,其實在安裝的時候,就有相關的選項可以勾選、讓它隨著 Visual Studio 安裝了。而在目前的 Visual Studio 2022Visual Studio 2026,安裝時如果選擇了「使用 C++ 的桌面開發」這個工作負載的話,預設似乎是會勾選起來的。

不過以 Heresy 之前的經驗、Visual Studio 的隨附版本和官方 GitHub 上的有一點差異、功能也有點不同,而且之後如果要更新 vcpkg 的版本也必須要等 Visual Studio 更新才行;所以個人會覺得還是按照官方說明(連結)、透過 GitHub 來安裝會比較合適。

如果是新的系統、不想要另外裝 Git 的話,在安裝 Visual Studio 的時候也可以勾選 Git for Windows 來安裝。

而之後如果想要把 vcpkg 安裝在 C:\ 底下的話,則可以開啟一個 cmd、使用下面的指令完成安裝與設定:

git clone https://github.com/microsoft/vcpkg.git c:\vcpkg
cd c:\vcpkg && .\bootstrap-vcpkg.bat

setx VCPKG_ROOT C:\vcpkg
setx PATH "%VCPKG_ROOT%;%PATH%"

.\vcpkg.exe integrate install

這樣的話,就會把 vcpkg 的 repo 複製到 c:\vcpkg、然後在這邊安裝 vcpkg 了。

同時,這邊也會透過 setx 來設定使用者環境變數 VCPKG_ROOTPATH,之後只要重新開啟命令提示字元,應該就可以在任何地方執行 vcpkg 了。

不過可能要注意的是,之後執行 vcpkg 的時候,可能會在這個資料夾中下載大量的檔案、並且進行建置,所以如果系統磁碟比較小、或者擔心系統 SSD 的寫入量的話,可能放到別的位置會比較好。


針對專案設定 vcpkg

都設定好了之後,如果想把自己的既有專案改成使用 vcpkg 來管理第三方套件該怎麼做呢?這邊以 https://gitlab.com/kheresy/vcpkg-example/-/tree/no-vcpkg 這個專案來作例子。

這個專案是一個使用 libarchive 來讀取壓縮檔案的範例(官網),目前的 Visual Studio 專案和 CI/CD 腳本都會因為沒有 Boost 而編譯失敗。

如果要使用 vcpkg 來做套件管理的話,那可以開啟一個命令提示字元、在切換到專案資料夾後、透過下面的指令來完成:

vcpkg new --application
vcpkg add port libarchive

第一行會建立出 vcpkg.jsonvcpkg-configuration.json 兩個檔案作為 vcpkg 的基礎設定。


其中,vcpkg-configuration.json 是用來設定使用哪個 registry、以哪個時間點作為套件的基準用的。內容大致上會如下:

{
   "default-registry": {
     "kind": "git",
     "baseline": "62efe42f53b1886a20cbeb22ee9a27736d20f149",
     "repository": https://github.com/microsoft/vcpkg
   },
   "registries": [
     {
       "kind": "artifact",
       "location": https://github.com/microsoft/vcpkg-ce-catalog/archive/refs/heads/main.zip,
       "name": "microsoft"
     }
   ] }

這代表 vcpkg 會從「https://github.com/microsoft/vcpkg」的「62efe42f53b1886a20cbeb22ee9a27736d20f149」這個 commit 來尋找套件;除非有再回來修改這個檔案,否則就算官方有更新,使用的套件也會維持在這個時間點的版本。

而下面的 artifact 的 registry 則應該是用來定義相關的工具用的。


之後、第二行指令則就是加入要使用的套件,這邊就是「libarchive」(不確定名稱的話可以透過 vcpkg search 來找)。

而這時候,用來記錄需要的套件的 vcpkg.json 內容會如下:

{
   "dependencies": [
     "libarchive"
   ] }

這邊由於只有明確設定需要「libarchive」,所以算是相當簡單。

之後如果有其他需要的套件,也可以透過同樣的方法來加入;如果要一次加入多個套件,也可以用「vcpkg add port zlib libpng」這樣的指令。或者,也可以直接編輯這個 JSON 檔來進行。

理論上這樣就完成 vcpkg 相依性的設定、可以離開命令提示字元、回到 Visual Studio 的圖形介面了。

由於這邊之後會由 Visual Studio 來控制 vcpkg 的套件安裝,所以這邊不需要手動執行「vcpkg install」的指令。


針對專案設定 vcpkg

如果要讓 Visual Studio 的 C++ 專案使用 vcpkg 來做為第三方套件的管理工具的話,需要在 Visual Studio 中打開專案的屬性視窗、找到左邊的「vcpkg」、然後將右邊的「Use Vcpkg」和「Use Vcpkg Manifest」改成「是」。

image host

要注意的是,「vcpkg」這個分類是要執行過「vcpkg.exe integrate install」才會有的,所以如果沒看到的話可能就要確認一下是不是之前設定的時候漏了這一步了。

這樣設定後,由於 Visual Studio 預設會自己把 vcpkg 的相關資料設定好、所以本來像是 include、library 路徑、要連結的 lib 檔案這些本來應該要設定的東西這邊都可以不用自己去設定;所以如果本來已經有針對第三方函式庫設定這些資訊的話,可能要評估看看那些需要拿掉會比較好。


在 Visual Studio 建置

都設定完成後,建置專案的時候 Visual Studio 就會去檢查 vcpkg.json、如果他發現沒有安裝需要的套件的時候,就會在開始建置專案時、先透過 vcpkg 來安裝第三方套件了~

這邊大概會看到下面這樣的紀錄:

image host

而如果是第一次建置的時候,雖然這邊只設定說需要「libarchive」,但是由於他本身還需要建置時需要的工具、以及其他的函示庫,所以實際上這邊的安裝過程應該會花一段時間;但是最後應該是可以正確完成安裝、並將專案建置出來的。

此外,如果是在 CI/CD 或是其他沒有圖形介面的環境下,也可以透過 msbuild 這個指令來進行專案/方案的建置,他同樣會去自動安裝 vcpkg 設定的套件。不過考慮到第三方函式庫的建置時間可能滿長的,這邊可能就會需要使用他的 binary cache 的機制來加速會比較合適了。


透過 Visual Studio 安裝的檔案

vcpkg 安裝的檔案則會在「vcpkg_installed」這個資料夾下。以 x64 環境來說,實際上要使用的檔案會被放在「vcpkg_installed\x64-windows\x64-windows」(這邊比 vcpkg 預設的設定多了一層,但是 Visual Studio 就是這樣搞的…)。

而裡面的資料結構則和前一篇講的一樣,主要就是:

  • include:所有 header
  • lib:release 版的 lib 檔案
  • bin:release 版的 dll 檔案
  • debug:debug 的 lib 和 dll

如果有額外的檔案的話,他也可能會產生額外的資料夾。

另外,這個例子是沒有,不過如果系統判斷程式需要透過 vcpkg 安裝的 DLL 檔案的話,他預設也會把需要的 DLL 自動佈署到編譯出來的執行檔的資料夾,所以其實會要自己進到 vcpkg 安裝的資料夾的機會應該不大。


這邊比較討厭的,是因為 Visual Studio 在安裝 vcpkg 的套件的時候有強制修改安裝路徑、多了一層資料夾,所以後續在透過 vcpkg 指令操作的時候,有可能會不能直接使用;例如這邊就沒辦法直接透過 vcpkg list 來看出來自己安裝了那些套件。

要解決這樣的問題,是要和 Visual Studio 一樣、手動加上安裝路徑的設定;以這邊的例子來說,可以加上「--x-install-root=.\vcpkg_installed\x64-windows\」來指定 Visual Studio 設定的路徑。

所以如果要想知道 vcpkg 到底裝了那些套件的話,需要使用下面的指令:

vcpkg list --x-install-root=.\vcpkg_installed\x64-windows\

以這邊來說,列出來的結果可能會如下:

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
libarchive[crypto]:x64-windows                                        Support for cryptographic features
libarchive[lz4]:x64-windows                                           Lz4 support
libarchive[lzma]:x64-windows                                          Lzma support
libarchive[xar]:x64-windows                                           Xar support
libarchive[zstd]:x64-windows                                          Zstd support
liblzma:x64-windows                               5.8.1               Compression library with an API similar to that ...
lz4:x64-windows                                   1.10.0              Lossless compression algorithm, providing compre...
openssl:x64-windows                               3.5.2               OpenSSL is an open source project that provides ...
vcpkg-cmake-config:x64-windows                    2024-05-23
vcpkg-cmake-get-vars:x64-windows                  2025-05-29
vcpkg-cmake:x64-windows                           2024-04-23
zlib:x64-windows                                  1.3.1               A compression library
zstd:x64-windows                                  1.5.7               Zstandard - Fast real-time compression algorithm

可以看到,除了指定的「libarchive」外,還裝了不少像是 zlib 這種壓縮相關的函式庫,這是因為他會自己去安裝所有需要的函示庫的關係,算是正常操作。

這樣的好處,是只要簡單的設定,vcpkg 就會把必要的相依性處理好,不用自己一個一個建置、一個一個設定。


簡單的 CI/CD 示意

這樣修改完的專案,則是放在 vcpkg 這個分支(連結)。理論上這邊的 Windows 版 CI 也有寫好,其腳本是:

windows:
     stage: build
     before_script:
     - git clone https://github.com/microsoft/vcpkg.git c:\vcpkg2
     - Push-Location c:\vcpkg2
     - .\bootstrap-vcpkg.bat
     - .\vcpkg.exe integrate install
     - Pop-Location
     script:
     - cmd /c '"C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvars64.bat" && msbuild .'
     tags:
     - saas-windows-medium-amd64

這邊實際上建置的指令是「script」下的那行。由於 GitLab 提供的 Windows share runner(官方文件)雖然有安裝 Visual Studio Build Tools,但是預設的 shell 並沒有去載入 Visual Studio 必要的環境變數,所以這邊才會需要特別去執行 vcvars64.bat、然後再執行 msbuild . 來進行建置。

另外,由於 runner 上也沒有安裝 vcpkg,所以這邊是在 before_script 裡面、把 vcpkg 安裝、設定好。

技術上,這樣的腳本是可以正確執行的,但是實際上,這樣的做法算是很浪費時間的。以這個簡單的專案來說,如果使用 GitLab 提供的 shared runner 建置會超過一個小時、在預設的工作時間限制內根本跑不完(參考)。

當然啦,GitLab 提供的 Windows Runner 初始化很慢也花了不少時間,但是每次都要重新 clone vcpkg、然後所有套件都要重新編譯,其實還是很浪費時間的;尤其是 libarchive 預設會使用的 OpenSSL、在 Windows 上建置的速度其實相當地慢…

所以比較好的做法,應該還是要在 Runner 的環境中預先安裝好 vcpkg、然後再搭配 binary cache 來避免沒意義的重新建置會更有效率;不過這部分就等之後有時間再寫了。

以 Heresy 這邊自己的環境來說,最後是用 docker-windows 形式的 runner 搭配自己的 Docker image 來建置(參考),script 的部分就只需要很簡單的 msbuild . 就夠了~


在 Windows 上搭配 Visual Studio 的基本使用大概就是這樣了。下一篇應該會來講一下同一個專案在 Linux 環境下、使用 g++ 搭配 Makefile 的使用狀況。


本系列文章目錄:

  • 簡介
  • 搭配 Visual Studio 使用 vcpkg
  • 在 Makefile 與 g++ 環境使用 vcpkg
  • vcpkg 套件的功能與版本設定(manifest 模式)
  • 自行擴展 vcpkg 的套件:以 zlib-ng 取代 zlib

Leave a Reply

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