c++ - 从 WSL Ubuntu 交叉编译到 Win32 时出错
问题描述
我正在编写很多跨平台 C++,并试图在平台之间统一构建过程(目前主要针对 Windows 和 Mac,未来可能会移动。)除了我们正常的 CI 构建之外,我们是从源代码作为超大型 C++ 项目构建的一部分,因此具有相当复杂的工具链。
现在,我的代码在 Windows 上使用 CMake 生成 Visual Studio 项目,然后使用 clang-cl 编译干净。同样,我们是使用 CMake 生成一个 ninja 项目,然后 clang 进行编译。
我们是一家 Windows 商店,我想利用 WSL 来设置交叉编译,这应该允许我们使用同一个 ninja 项目来针对两个支持的平台并在将来进行修改。
我能够从我的 wsl 托管 bash 终端使用 clang 成功编译一个简单的 hello world exe 程序。为了做到这一点,我必须为 clang 提供大量选项,并将大量 Win10 SDK 库移动到我的构建环境中,以供 clang 构建和链接。
以下是我运行成功生成 helloworld.exe 的两个命令: 编译:
clang -target i686-pc-win32 -fms-compatibility-version=19 -fms-extensions -fdelayed-template-parsing -fexceptions -mthread-model posix -fno-threadsafe-statics -Wno-msvc-not-found -DWIN32 -D_WIN32 -D_MT -D_DLL -Xclang -disable-llvm-verifier -Xclang '--dependent-lib=msvcrt' -Xclang '--dependent-lib=ucrt' -Xclang '--dependent-lib=oldnames' -Xclang '--dependent-lib=vcruntime' -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE -U__GNUC__ -U__gnu_linux__ -U__GNUC_MINOR__ -U__GNUC_PATCHLEVEL__ -U__GNUC_STDC_INLINE__ -I/mnt/d/source/windeps/LLVM/include -I/mnt/d/source/windeps/MSVC/14.22.27905/include -I/mnt/d/source/windeps/ucrt -I/mnt/d/source/windeps/shared -I/mnt/d/source/windeps/winrt -c hello.cc -o hello.o
链接:
clang -fuse-ld=lld-link.exe -target i686-pc-win32 -Wl,-machine:x86 -fmsc-version=1923 -o hello.exe hello.o -L/mnt/d/source/windeps/MSVC/14.22.27905/lib/x86/msvcrt.lib -nostdlib -lmsvcrt -Wno-msvc-not-found
自然地,我试图通过我的 CMake 工具链来表达第一个命令:
add_compile_options(
-W
-Wall
-std=c++17
-stdlib=libc++
-fcoroutines-ts
-fms-extensions
-fdelayed-template-parsing
-fexceptions
-fdeclspec
-mthread-model posix
-fno-threadsafe-statics
-Wno-msvc-not-found
-DWIN32
-D_WIN32
-D_MT
-D_DLL
-Xclang
-disable-llvm-verifier
# These are commented out currently, but I have linked them to the proper CMakeList
# -Xclang '--dependent-lib=msvcrt'
# -Xclang '--dependent-lib=ucrt'
# -Xclang '--dependent-lib=oldnames'
# -Xclang '--dependent-lib=vcruntime'
-D_CRT_SECURE_NO_WARNINGS
-D_CRT_NONSTDC_NO_DEPRECATE
-U__GNUC__
-U__gnu_linux__
-U__GNUC_MINOR__
-U__GNUC_PATCHLEVEL__
-U__GNUC_STDC_INLINE__
-I/mnt/d/source/windeps/LLVM/include
-I/mnt/d/source/windeps/MSVC/14.22.27905/include
-I/mnt/d/source/windeps/um
-I/mnt/d/source/windeps/ucrt
-I/mnt/d/source/windeps/shared
-I/mnt/d/source/windeps/winrt
)
当我们的文件之一 (event_logger.cpp) 执行时,这会从 ucrt 库中引发错误#include <array>
。
In file included from src/client/services/src/event_logger.cpp:10:
In file included from /mnt/d/source/windeps/MSVC/14.22.27905/include/array:6:
In file included from /mnt/d/source/windeps/MSVC/14.22.27905/include/algorithm:6:
In file included from /mnt/d/source/windeps/MSVC/14.22.27905/include/xmemory:8:
In file included from /mnt/d/source/windeps/MSVC/14.22.27905/include/limits:8:
In file included from /mnt/d/source/windeps/MSVC/14.22.27905/include/cwchar:8:
In file included from /mnt/d/source/windeps/MSVC/14.22.27905/include/cstdio:8:
In file included from /mnt/d/source/windeps/ucrt/stdio.h:13:
/mnt/d/source/windeps/ucrt/corecrt_wstdio.h:581:9: error: use of undeclared identifier '__crt_va_end'
__crt_va_end(_ArgList);
^
/mnt/d/source/windeps/ucrt/corecrt_wstdio.h:597:9: error: use of undeclared identifier '__crt_va_start_a'
__crt_va_start(_ArgList, _Locale);
^
/mnt/d/source/windeps/MSVC/14.22.27905/include/vadefs.h:156:99: note: expanded from macro '__crt_va_start'
#define __crt_va_start(ap, x) ((void)(__vcrt_assert_va_start_is_not_reference<decltype(x)>(), __crt_va_start_a(ap, x)))
由于这种行为,我怀疑我们可能没有使用-stdlib
标志所指示的 libc++。我也不确定如何纠正这个问题,因为这似乎是一种较新的过程,而且还没有大量的文档。任何建议表示赞赏。
解决方案
推荐阅读
- javascript - 如何在新页面中保留展开的下拉菜单?
- java - 在 Java 中使用匿名类进行模拟
- jenkins - 如何获得 Jenkins 目前的工作,以便更新它的编号?
- javascript - 在 React Native 中根据命名约定导入 typescript 文件
- javascript - 多个事件监听器
- javascript - AWS S3 通过预签名 URL 上传返回 400 错误请求
- vb.net - 为什么 vb.nets '=' 运算符以这种方式评估不同的类型?
- tensorflow - 如何协调 TFP 与 PyMC3 MCMC 结果?
- android - 应用程序在模拟器上运行良好,但应用程序无法通过 apk 包安装在移动设备上
- javascript - Javascript不适用于asp.net MVC中多选下拉列表的onchange事件