天天看點

随心所欲地對vcpkg依賴進行版本控制

特别鳴謝

感謝Victor Romero對本文内容的貢獻。

今天,我們高興地宣布vcpkg的一項新特性:包版本控制。開發者等待這項新特性已經很久了,今天它終于來了。這項特性可以實作軟體包特定依賴版本的安裝,同時控制現有已安裝的版本。為了使用這項新特性,你需要在你的倉庫裡建立一個vcpkg.json的清單檔案,用來聲明各個程式包的依賴關系。請注意,在指令行模式下安裝的程式庫還暫未支援版本控制(例如,使用vcpkg install library_name)。版本控制特性是完全可選的,也就是說,你可以選擇不指定程式庫的版本,這樣的話,vcpkg将會替你從基線目錄中選擇最為合适的相容版本。

目前,這項特性還是實驗性質的,那大家就試試看呗,體驗體驗也好。

關于新特性:程式包版本控制

在過去的一年,我們一直緻力于實作開發者希望的新特性,以使vcpkg可以廣泛地使用在各種工作場景。清單(manifests)和二進制檔案緩存(binary caching)就是其中的2項新特性,我們已經在之前的文章中有專門介紹過它們,從那時開始,開發者就已經在他們的項目中用上它們了。

今天,我們再次官宣一項群衆呼聲高的新特性:程式包版本控制。有了這一新特性,開發者就可以做如下的事情:

> 在依賴項上聲明最小版本限制。

> 當機指定版本的依賴項。

> 通過使用基線友善地更新所有已聲明的依賴項。

> 擷取獨立于目前vcpkg的ports系統資料庫狀态的可重制建構版本。

讓我們開始吧

首先,你需要在環境變量中打開”versions”特性标志。有如下幾種方法:

> 如果是在Windows 10中,可以通過設定VCPKG_FEATURE_FLAGS環境變量,如下圖所示:

随心所欲地對vcpkg依賴進行版本控制

> 通過在指令行(例如,PowerShell)中設定VCPKG_FEATURE_FLAGS變量:

$env:VCPKG_FEATURE_FLAGS=”versions” vcpkg install

> 通過在指令行(例如,PowerShell)中向vcpkg傳入新特性标志:

vcpkg –feature-flags=”versions” install

在下面的例子中,我們将會使用到Visual Studio Code來建立一個簡單的CMake工程,它會自動讀取vcpkg的清單檔案并安裝其需要的依賴包。在Visual Studio中,你也可以這樣做。如果需要了解有關如何在Visual Studio中使用vcpkg和清單的更多資訊,請檢視我們之前的一篇講解vcpkg的介紹性文章。

第一個例子:簡單的版本控制

如下圖所示,通過在vcpkg.json中編寫如下語句以建立一個檔案夾:

随心所欲地對vcpkg依賴進行版本控制

當你使用清單檔案的時候,vcpkg有一個新的版本聲明的屬性可用。在之前的版本中,你隻能使用屬性”version-string”為你的項目聲明版本。現在,版本控制的方法變了,vcpkg可以感覺到新的版本控制結構,如下圖所示:

随心所欲地對vcpkg依賴進行版本控制

首先,被選中的版本結構可以影響vcpkg的程式包查找的順序規則。

其次,我們使用屬性”version>=”來聲明最小版本限制。請注意,我們還使用不帶特定版本限制的聲明添加了一項對zlib的依賴。

最後,我們聲明了”builtin-baseline”,它的值是vcpkg倉庫的一項代碼送出的SHA哈希值。

在上面的例子中,vcpkg将會查找”

b60f003ccf5fe8613d029f49f835c8929a66eb61″對應的送出版本,然後會找到最新的fmt版本以及當時的zlib版本,如下:

> fmt 7.1.3

> zlib 1.2.11#9 (這裡的#9字尾表明這個是程式庫的第9個建構版本)

上面列出來的程式包集合被定義在工程依賴的基線版本中。當需要解決程式包版本沖突的時候,基線版本添加了最小版本限制資訊。

下面是一個簡單的源檔案,它示範了如何測試依賴項是否安裝:

随心所欲地對vcpkg依賴進行版本控制

為了在一個CMake工程中使用vcpkg清單檔案,需要在CMakeLists.txt檔案中添加find_package和target_link_libraries這兩個函數來定位所有的依賴項。不管是否使用像vcpkg那樣的程式包管理器,都可以使用這兩個函數,這樣就可以在工程的建構中包含所需要的依賴項。

随心所欲地對vcpkg依賴進行版本控制

如果你使用的是Visual Studio Code,則下面的配置示範了如何将一個CMake工程指向一個vcpkg CMake工具鍊檔案。對于使用vcpkg的任何CMake工程,這個檔案必須被設定。另外,其他的內建開發環境或者編輯器可能有不同的方式來配置CMake工具鍊檔案。

接下來,使用Visual Studio Code中的”CMake: Configure”指令,就可以生成CMake緩存了,如下圖所示:

随心所欲地對vcpkg依賴進行版本控制

上圖是當使用CMake指令行建立CMake緩存時的資訊輸出。在Visual Studio Code中,如果安裝了CMake Tools工具擴充,則可以通過執行”CMake: Configure”指令生成緩存。

如果你注意到路徑中的”

/buildtrees/versioning/versions//”,你就可以明白新的版本控制特性已經正在工作起來了。vcpkg會檢查倉庫中的程式包的版本。

最後,我們執行我們的測試程式,會有如下的輸出:

fmt version is 70103

zlib version is 1.2.11

第二個例子:固定舊版本

因為基線版本确定了所有程式包的基礎版本資訊,以及當程式包低于基線版本時需要做的一些顯式限制檢查,是以,我們需要另外一種機制來對版本進行降級以通過基線檢查。

vcpkg提供的新的機制是:override。

當我們在一個程式包上聲明一個override時,vcpkg将會忽略所有其他的版本限制和在清單裡直接聲明的版本或者依賴的版本。簡單說來,就是重寫會強制vcpkg使用準确聲明的版本。

首先,請修改你的清單檔案,在fmt上添加一個override并強制vcpkg使用6.0.0這一版本,如下圖所示:

随心所欲地對vcpkg依賴進行版本控制

接下來,請删除你的工程建構檔案夾,并生成CMake緩存并重新執行一次建構:

随心所欲地對vcpkg依賴進行版本控制

最後,還是執行我們的測試程式,我們會觀察到如下的輸出:

fmt version is 60000

zlib version is 1.2.11

vcpkg中的版本控制是如何工作的?

下圖我們描述了四個程式包的版本釋出時間表:FMT, zlib, Boost and Azure Core C++庫。

随心所欲地對vcpkg依賴進行版本控制

vcpkg内部的版本系統包含如下幾個部分:

基線

為了使用版本控制,你需要将基線設定到一個特定的vcpkg送出版本。通過選擇一個基線,你可以選擇版本釋出時間表中的一個版本快照。通過設定基線,可以為所有的依賴項設定一個最小的版本。

在上圖中,我們有FMT的7.1.0版本,zlib的v1.2.11修訂版v9版本,Boost的1.74.0版本以及2020年9月釋出的Azure Core C++庫。

使用基線的一個好處在于:同時期的版本非常可能就是能互相相容的。主vcpkg系統資料庫會建構它包含的所有同時期的程式庫,以確定整個程式庫目錄的整體相容性。

限制條件

與為所有軟體包設定最低版本的基準相反,限制使你可以逐個軟體包指定最低版本。

限制條件僅允許你更新版本,而不是基線版本。 如上所述,基線為所有軟體包設定了最低版本限制,是以,如果你嘗試添加一個低于基線的限制,則該限制将被更新。

關于限制的一個重要注意事項是,它們在基線和替代項不存在的情況下是可傳遞的。圖中的依賴項可以表達自己的限制,版本解析算法将考慮它們。

但是,如果你确實需要将版本設定為低于基準,該怎麼辦? 如何在不降低基準的情況下做到這一點? 對于這些情況,可以使用替代。

Overrides

Overrides會強制vcpkg使用特定版本,同時忽略所有其他限制(顯式或傳遞性)。 這使使用者可以解決某些特定情況,例如:

> 降級版本低于基準。

> 在傳遞依賴項上強制更新/降級版本。

> 解決不同軟體包之間的版本沖突。

在該圖所示的場景中,給出了我們對基線,限制和替代的全部了解。 我們可以看到,使用所有四個軟體包的項目的版本解析将導緻:

FMT:版本7.1.2,通過限制指定。

zlib:端口修訂版2的版本1.2.11(通過覆寫指定)。

Boost:版本1.74,由基線預設設定。

azure-core-cpp:版本2020-09-01(基線預設設定)。

版本和自定義ports

最後要讨論的是覆寫ports如何與版本控制解析的互動。

答案是:它們根本不會做任何互動。更詳細地講,當你為一個port提供覆寫時,vcpkg将始終使用覆寫ports,而無需關心其中包含的版本。

原因有兩個:

(1)與覆寫ports的現有行為一緻(完全掩蓋了現有ports)

(2)覆寫ports沒有(也不希望提供)足夠的資訊來支援vcpkg的版本控制特征。

總結

最後

繼續閱讀