如何构建 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 包含标头兼容。
COFF/PE 文件格式。
LLD
注意:不使用 compiler-rt。此功能由 MS VCRT 提供。
先决条件¶
MS SDK 作为 MS Visual Studio 的一部分安装。
Clang,支持 windows-itanium 三元组。
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”覆盖三元组。链接器可以使用“-fuse-ld=lld”指定。
在 Itanium C++ ABI 中,对象的第一个成员是指向其类的虚函数表的指针。虚函数表通常与关键函数一起发出到目标文件中,并且必须为标记为 dllimport 的类导入。指针必须是全局唯一的。不幸的是,COFF/PE 文件格式没有提供一种机制将来自另一个 DLL 的运行时地址存储到此指针中(尽管运行时地址已修补到 IAT 中)。因此,编译器必须发出一些代码,这些代码在 IAT 修补之后但在任何可能使用虚函数表指针的代码之前运行,并将虚函数表指针设置为来自 IAT 的地址。对于从 typeinfo 对象到 __cxxabiv1::__class_type_info 的虚函数表的引用的特殊情况,编译器没有可用的声明,因此无法完成此操作。为了允许程序链接,我们目前依赖 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=<安装 路径>
库和标头的安装位置。
构建 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=<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 路径>/include
-DLIBCXX_CXX_ABI_LIBRARY_PATH=<libcxxabi build 路径>/lib
使用先前构建的静态 libc++abi 库。
-DLIBCXX_NO_VCRUNTIME=ON
删除对 VC 运行时的任何依赖项 - 我们需要 libc++abi 来提供 C++ 运行时。
-DCMAKE_C_FLAGS=<已安装的 unwind.lib 路径>
由于我们是静态链接到 libc++abi,因此我们需要链接到 unwind 导入库以解析来自 libc++abi 对象的 unwind 引用。
-DCMAKE_C_FLAGS+=' -UCLOCK_REALTIME'
防止包含 MS 不提供的 sys/time。
注释:¶
此处提供了一个示例构建配方:https://reviews.llvm.org/D88124