vcpkg新特性:交叉編譯下的主機依賴關係

如果你還不熟悉我們的C++包管理器vcpkg,那麼:歡迎閱讀本文。

今天的這篇文章,我們將覆蓋一些關於vcpkg的中高階主題,所以,你可能需要先從我們之前的博文中瞭解一下vcpkg的概念性知識,最好能親自動手做一些小實驗,以加深理解。

介紹

C++的最佳功能之一是,它為每臺特定的機器生成量身定製的專用程式碼,使你能夠最大程度地榨取機器的每一分效能,它使乾淨的抽象與特定於底層平臺的細節平穩地共存。

但是,很多開發人員也會為這一收益付出一定的代價:與最終目標平臺相比,你必須為開發人員計算機構建不同的二進位制檔案,目標平臺可能是一個移動手機平臺,一臺雲伺服器,甚至是一個嵌入式系統。

對於小型或中型工程來說,這可能並不是一個很大的問題。

你已經擁有一個編譯器,一個程式碼編輯器和一個構建系統,這足以用來開發大量令人難以置信的應用程式。但是,由於時間久遠,一些開發人員不僅需要編譯器,還需要更多的靈活性,可擴充套件性和強大功能;他們需要在構建時生成複雜的程式碼。

可能是在基於一個已知資料集合的雜湊值計算程式,也可能是嵌入式指令碼語言中的一堆外部功能介面模板。不管原因是什麼,除了最終的執行時目標之外,你還需要C++在開發環境中的靈活性。

下面,我們會介紹解決上述問題的vcpkg的新功能:Host Dependencies(主機依賴)。

並行編譯

如引言中所述,由於C++會一直持續進行編譯,因此你通常無法使用相同的編譯器和標誌同時用於目標平臺和開發平臺。如果你使用的是多目標平臺編譯器(例如Clang / LLVM),則至少需要使用不同的編譯標誌;如果你使用的是單目標編譯器(例如GCC或MSVC),則需要使用完全不同的編譯器。

如果幸運的話,構建系統會提供有關如何處理這種情況的文件。即使那樣,為了確保各個配置都正確得到配置,編譯過程也會變得非常複雜:你是否意外地將目標平臺的編譯標誌傳遞給開發平臺版本? 如果你需要執行程式碼生成器的庫該怎麼辦? 如果程式碼生成器為其他程式碼生成器生成程式碼又如何處理呢?這是一個棘手的問題集合,會對構建環境的各個方面都產生影響。

Triplets

在vcpkg中,我們將每個目標平臺空間標記為單獨的“triplet”。

舉個例子,使用動態CRT和MSVC的x64 Windows桌面系統,在構建靜態庫時的名稱可能為x64-windows-static-md。在該空間中構建的每個庫都與該空間中的其他庫連結,從而使所有內容保持超級一致。

我們在框架中包含許多預定義的triplet,但是你可以輕鬆地自己調整每個庫的編譯器標誌或調整設定(例如,你希望動態構建Qt,但是JSON解析器是靜態構建的)。

自然,你的開發環境也匹配這些空間中的某一個。 預設情況下,我們選擇適當的x64-windows,x64-linux或x64-osx,但可以在執行時透過多種方法對其進行完全配置。

主機依賴

儘管vcpkg具有與開發人員環境匹配的triplet,但是vcpkg的合適的語法表示對環境構建庫的依賴性。 我們已經採用了一些不那麼完善的方法,例如動態地嘗試從一組硬編碼的後備triplet中使用庫,但是,這些方法始終不是最好的。

這些變通辦法在清單模式下也不能正常工作,這是專門設計用來防止在此類“動態”訪問中發生的意外行為。 當然,這個修正方法是一種自然而直接地表達對為開發人員環境構建要求的方法。

現在可以正式引入主機依賴的特性了。

它的語法非常簡單,就是在依賴項的清單檔案中設定host為true,如下圖所示:

在執行期間,庫可以知道,它的所有依賴庫都已安裝到

CURRENT_HOST_INSTALLED_DIR指定的位置,並且它們可以透過HOST_TRIPLET(TARGET_TRIPLET的模擬)獲取當前配置的主機triplet。

對於內部嵌入了自己的程式碼生成器的專案,要求自己為主機構建是完全有效的:

然後,庫可以透過比較triplets來確定它是交叉編譯還是本地編譯:

總結

我們才剛剛開始將這種功能強大的新功能合併到現有功能中,例如Boost。Build。 對於面向新興開發平臺(例如iOS,安卓和Emscripten/WebAssembly)的vcpkg使用者而言,這是巨大的進步。

最後

Microsoft Visual C++團隊的部落格是我非常喜歡的部落格之一,裡面有很多關於Visual C++的知識和最新的開發進展。大浪淘沙,如果你對Visual C++這門古老的技術還是那麼感興趣,則可以經常去他們那(或者我這)逛逛。

本文來自:《vcpkg Host Dependencies for Cross-Compilation》

相關文章