如何建置 Windows Itanium 應用程式。¶
簡介¶
本文檔包含描述如何建立 Windows Itanium 工具鏈的資訊。
Windows Itanium 允許您在 MS VS CRT 之上部署 Itanium C++ ABI 應用程式。此環境可以直接使用 Windows SDK 標頭,並且不需要額外的標頭或額外的執行階段機制(例如 mingw 使用的機制)。
Windows Itanium 堆疊
使用 Itanium C++ abi。
libc++。
libc++-abi。
libunwind。
MS VS CRT。
與 MS Windows SDK include 標頭相容。
COFF/PE 檔案格式。
LLD
注意:未使用 compiler-rt。此功能由 MS VCRT 提供。
先決條件¶
MS SDK 作為 MS Visual Studio 的一部分安裝。
Clang 支援 windows-itanium triple。
COFF LLD 支援 -autoimport 開關。
已知問題:¶
SJLJ 例外,「-fsjlj-exceptions」是目前唯一支援的模型。
link.exe(MS 連結器)不適用,因為它不支援自動匯入,而自動匯入目前是正確連結所必需的。但是,如果消除了該限制,則使用 link.exe 沒有其他已知問題。
目前,Windows Itanium 缺少可用的 Windows 編譯器驅動程式。一個合理的解決方案是使用 windows-msvc 預設目標建置 clang,然後使用例如「-Xclang -triple -Xclang x86_64-unknown-windows-itanium」覆蓋 triple。連結器可以使用「-fuse-ld=lld」指定。
在 Itanium C++ ABI 中,物件的第一個成員是指向其類別的 vtable 的指標。vtable 通常與金鑰函數一起發射到物件檔案中,並且對於標記為 dllimport 的類別必須匯入。指標必須是全域唯一的。不幸的是,COFF/PE 檔案格式沒有提供將來自另一個 DLL 的執行階段位址儲存到此指標中的機制(儘管執行階段位址已修補到 IAT 中)。因此,編譯器必須發射一些程式碼,這些程式碼在 IAT 修補之後但在任何可能使用 vtable 指標的程式碼之前執行,並將 vtable 指標設定為來自 IAT 的位址。對於從 typeinfo 物件到 __cxxabiv1::__class_type_info 的 vtable 參考的特殊情況,編譯器沒有可用的宣告,因此無法完成此操作。為了允許程式連結,我們目前依賴 LLD 中的 -auto-import 開關來自動匯入對 __cxxabiv1::__class_type_info 指標的參考(請參閱:https://reviews.llvm.org/D43184 以取得相關討論)。這允許連結;但是,實際使用這些欄位的程式碼將無法運作,因為它們不會在執行階段修復。請參閱 _pei386_runtime_relocator,它處理用於 mingw 的自動匯入方案的執行階段組件,以及 https://reviews.llvm.org/D43184 和 https://reviews.llvm.org/D89518 中的註解以取得更多資訊。
組裝工具鏈:¶
程序如下
# 建置支援 Windows Itanium 的 LLVM 工具鏈。 # 使用步驟 1 中的工具鏈。建置 libc++、libc++abi 和 libunwind。
也可以從 Linux 進行交叉編譯。
若要建置步驟 2 中的程式庫,請參閱 libc++ 文件。
下一節討論建置和安裝程式庫所需的重要選項和修改。這假設我們正在將 libunwind 和 libc++ 建置為 DLL,並將 libc++abi 靜態連結到 libc++ 中。其他建置配置也是可能的,但此處不討論。
常見的 CMake 配置選項:¶
-D_LIBCPP_ABI_FORCE_ITANIUM'
告知 libc++ 標頭正在使用 Itanium C++ ABI。
-DCMAKE_C_FLAGS="-lmsvcrt -llegacy_stdio_definitions -D_NO_CRT_STDIO_INLINE"
提供 CRT 定義,包括已從 MS VS CRT 中移除的 stdio 定義。我們不希望 stdio 函數內聯宣告,因為當從 legacy_stdio_definitions.ib 中提取相同的符號時,它們會導致多重定義錯誤。
-DCMAKE_INSTALL_PREFIX=<install path>
程式庫和標頭的安裝位置。
建置 libunwind:¶
-DLIBUNWIND_ENABLE_SHARED=ON
-DLIBUNWIND_ENABLE_STATIC=OFF
libunwind 可以建置為 DLL。它不依賴其他專案。
-DLIBUNWIND_USE_COMPILER_RT=OFF
我們使用 MS 執行階段。
需要編輯 CMake 檔案以防止它們將 GNU 特定程式庫新增到連結行。
建置 libc++abi:¶
-DLIBCXXABI_ENABLE_SHARED=OFF
-DLIBCXXABI_ENABLE_STATIC=ON
-DLIBCXX_ENABLE_SHARED=ON'
-DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON
為了打破 libc++abi 和 libc++ 之間的符號依賴關係,我們將 libc++abi 建置為靜態程式庫,然後將其靜態連結到 libc++ DLL 中。這需要設定 CMake 檔案以確保可見性巨集(擴展為 dllexport/import)被擴展,因為在稍後建立最終的 libc++ DLL 時將需要它們,請參閱:https://reviews.llvm.org/D90021。
-DLIBCXXABI_LIBCXX_INCLUDES=<path to libcxx>/include
libc++ 標頭的尋找位置
建置 libc++:¶
-DLIBCXX_ENABLE_SHARED=ON
-DLIBCXX_ENABLE_STATIC=OFF
我們將 libc++ 建置為 DLL,並將 libc++abi 靜態連結到其中。
-DLIBCXX_INSTALL_HEADERS=ON
安裝標頭。
-DLIBCXX_USE_COMPILER_RT=OFF
我們使用 MS 執行階段。
-DLIBCXX_HAS_WIN32_THREAD_API=ON
Windows Itanium 不提供 WIN32 之上的 POSIX 類別層。
-DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON
-DLIBCXX_CXX_ABI=libcxxabi
-DLIBCXX_CXX_ABI_INCLUDE_PATHS=<libcxxabi src path>/include
-DLIBCXX_CXX_ABI_LIBRARY_PATH=<libcxxabi build path>/lib
使用先前建置的靜態 libc++abi 程式庫。
-DLIBCXX_NO_VCRUNTIME=ON
移除對 VC 執行階段的任何依賴 - 我們需要 libc++abi 來提供 C++ 執行階段。
-DCMAKE_C_FLAGS=<path to installed unwind.lib>
由於我們是靜態連結到 libc++abi,因此我們需要連結到 unwind 匯入程式庫,以解析來自 libc++abi 物件的 unwind 參考。
-DCMAKE_C_FLAGS+=' -UCLOCK_REALTIME'
防止包含 MS 未提供的 sys/time。
注意事項:¶
此處提供了一個範例建置配方:https://reviews.llvm.org/D88124