如何在 Vcpkg 使用特並版本LIB

Vcpkg 作為微軟在Windows平台上的函示庫管理方案。當然Vcpkg也能運行於Linux與Mac平台上。只是這兩個平台上原本就有unix系統上與生俱來的庫管理系統,我想多數開發者都不太會使用vcpkg作為自己的庫管理工具。

在Windows上,一直缺乏統一的Library Manager。所以幾乎都是採用Case by Case的方式運作。此外,Windows也沒有統一的編譯環境。或者說與unix的方式有著本質上的不同,你無法用一套makefile來完成所有工作。總之,一切運作起來總是顯得格格不入。Vcpkg就是這麼一個為了解決此問題而提出的重要工具。

致命缺點:不具備版本管理

然而,嚴格來說,Vcpkg並不是一個完善的解決方案。至少我不這麼認為。他有著一個非常致命的缺點-他不具備版本管理的功能。這個缺點非常非常的嚴重。

我舉個我最近遇上的問題為例:我想所有開發OpenGL或是科學計算的人都會用上GLMGLFW3這兩個函示庫。在Vcpkg你只要簡單的使用:

.\vcpkg install glm glfw3
.\vcpkg integrate install

這樣你就能輕輕鬆鬆在你的 Visual Studio 專案中,直接使用這兩個函數庫,並且連Header、Includes、Libs 都不需要任何設定就能使用。而且 Visual Studio還會很聰明的依據依賴關係幫你把必要的DLLs都替你準備好。就在一切看來是那麼美好的情況下,他潛藏的一個巨大難題與缺點是,假設你有不同的專案需要使用不同版本的函示庫時,抱歉,Vcpkg並不具備多重版本管理的功能。這時候你無法用 "一套" Vcpkg滿足你所有的需求。

Vcpkg 一個基於GIT版本控制的方案

為了找到解法,我們就要先理解Vcpkg的運作方式。Vcpkg的是一套基於GIT的庫管理工具。他的思維比較像是微軟替你管理了一套雲端的庫版本套件,他在乎的不是你要的是哪個函示庫的哪個版本。而是微軟自顧自的一直演進這些版本,他只在乎他們能不能工作正常,而不是你自己能不能工作正常。所以一旦git pull 那你可能就把一堆庫的版本不知不覺的更新成別的版本。這樣一來你的專案可能再也無法正常工作。

正因為如此,隨意的更新套件就會帶來許多的衝突與困擾。維持一套特定可用的Vcpkg就是一個必須的工作。

解決方案1: 採用多個Vcpkg

既然更新Vcpkg可能會帶來潛在問題,那個我們所幸維持一個特定的版本給特定的專案使用,這樣也能減少因為版本衝突產生問題。而且這樣也不會帶來額外的工作,頂多是多浪費了磁碟空間。

既然Vcpkg是基於GIT。所以我們可以藉由觀察GIT Log來理解哪個Vcpkg是最適合我的。以下舉 OpenSSL 為例:

Vcpkg checkout Tag

我的專案需要使用 OpenSSL 1.0.2s 這個版本。但是Vcpkg 的 Head版本已經支持了OpenSSL 1.1.1,所以我不能使用master上head版本。最簡單的是直接拿特定Tag來使用。因為通常Tag的版本多為穩定版本。如此一來,我在我專案中,有了一個專屬的Vcpkg。

他看起來就像這樣:

MyProject\
+- vcpkg

安裝OpenSSL:

.\vcpkg install openssl openssl:x64-windows

因為我們這是一個特定版本的Vcpkg,所以我不能在上面使用Vcpkg的預設整合方案,我們僅可以採用手動或是nuget的方式。因為我很懶,我推薦使用nuget的方式。雖然在多數的C/C++專案中,我們很少使用nuget來管理packages。但是實際上在C++中也非常好用。

Vcpkg 產生 nuget project:這個步驟,我們讓Vcpkg產生nuget安裝路徑。

.\vcpkg integrate project

開啟 Package Manager Console:
Visual Studio -> Menu-> Other Windows

Package Manager Console

安裝剛剛Vcpkg產生的 nupkg 安裝路徑:

Install-Package vcpkg.C.vcpkg -Source "path\vcpkg\scripts\buildsystems"

安裝好之後,你的 Visual Studio 就能正常引用與編譯這些庫了。非常方便。而且不需要任何手動設定。

值得注意的,你只能同時使用一個 Vcpkg 產生的 nupkg。多個安裝的 Vcpkg 只有一個是有效的。當然,你安裝的 nupkg 的優先權將高於 root Vcpkg的整合式安裝,你不用擔心其他的 Vcpkg。 換句話說,別的 Vcpkg integrate install 並不會影響你的專案。這點非常重要。

解決方案2: 採用獨立nupkg安裝包

你或許會注意到如果每個專案都採用完整的Vcpkg,那將是非常耗非空間的。舉例來說,一個C++ Boost 就可能高達 10GB的空間。但是你可能僅僅需要數個小的工具程式,卻得付出高昂的空間,這點實在很不經濟實惠。

基於此,我們可以把解決方案1中安裝的Vcpkg打包成獨立安裝包。如此一來,我們只需要在專案引用這個安裝包,就可以避免重新下載、編譯整個Vcpkg。

打包nupkg安裝包:

.\vcpkg export boost boost:x64-windows zlib --nuget

這樣一來我們就有了一個名為:vcpkg-export-20200417–005338.nupkg。而且你只需要約250MB空間。接下來,我們僅需要發行這個安裝包給所有需要這些庫的專案,就能輕鬆解決函示庫安裝問題。

舉例來說,我們check out一個新專案。接下來我們重複剛剛安裝nuget的方式,安裝我們的nupkg。

Install-Package vcpkg-export-20200417-005338 -Source "path of nupkg"

注意的這種方式安裝包,一樣不能支持多個 Vcpkg 安裝包。並且也會受root Vcpkg integrate 影響。編譯前,請記得先把 root Vcpkg 的整合式安裝給移除。 root .\vcpkg integrate remove

結論:

Vcpkg 無疑是個強大又好用的函示庫管理工具。但是不具備版本管理功能讓我們產生了許多工作上的困擾。我所以採用這種多個 Vcpkg方式,其實也只能解決一部分多重版本的問題,更複雜的版本交雜則必須採用曠日廢時的手動調整,這樣一來是不是划算就很難說了。另外,Vcpkg完整的支持CMake功能,這點也是十分重要。因為Windows環境沒有預設的函示庫安裝路徑,在Windows上,使用多個CMake,而需要 find_package,幾乎無法正確找到對應的package。利用 CMake toolchain 設定為 Vcpkg 就成了一個超方便的解決方案。

--

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Allen Kuo (kwyshell)

Allen Kuo (kwyshell)

More from Medium

Animal Emotions

Project 1: Non-branded Object Webpage

Lonely Hears Space Voyager: Mak