如何构建 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 的一部分安装。
支持 windows-itanium 三元组的 Clang。
支持 -autoimport 开关的 COFF LLD。
已知问题:¶
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 中,对象的第一个成员是指向其类 vtable 的指针。vtable 通常与关键函数一起输出到目标文件中,并且必须为标记为 dllimport 的类导入。指针必须全局唯一。不幸的是,COFF/PE 文件格式没有提供将来自另一个 DLL 的运行时地址存储到此指针中的机制(尽管运行时地址已修补到 IAT 中)。因此,编译器必须发出一些代码,这些代码在 IAT 修补后但在任何可能使用 vtable 指针之前运行,并将 vtable 指针设置为来自 IAT 的地址。对于从 typeinto 对象到 __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 中的库的一种方法是“独立”构建它们。独立构建不涉及 LLVM 树的其余部分。步骤如下
cd build-dir
cmake -DLLVM_PATH=<llvm 检出路径,例如 /llvm-project/> -DCMAKE_INSTALL_PREFIX=<安装路径> <其他选项> <项目路径,例如 /llvm-project/libcxxabi>
<make 程序,例如 ninja>
<make 程序> install
有关独立构建的更多信息,请参阅各个库的构建文档。下一节讨论使用独立构建构建和安装库所需的相关选项和修改。这假设我们正在将 libunwind 和 ibc++ 构建为 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源代码路径>/include
-DLIBCXX_CXX_ABI_LIBRARY_PATH=<libcxxabi构建路径>/lib
使用之前构建的静态 libc++abi 库。
-DLIBCXX_NO_VCRUNTIME=ON
删除对 VC 运行时的任何依赖关系 - 我们需要 libc++abi 来提供 C++ 运行时。
-DCMAKE_C_FLAGS=<已安装unwind.lib路径>
由于我们正在静态链接 libcxxabi,因此我们需要链接 unwind 导入库以解析来自 libcxxabi 对象的 unwind 引用。
-DCMAKE_C_FLAGS+=' -UCLOCK_REALTIME'
防止包含 MS 未提供的 sys/time。
注释:¶
示例构建配方在此处提供:https://reviews.llvm.org/D88124