首页 > 解决方案 > 从 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++。我也不确定如何纠正这个问题,因为这似乎是一种较新的过程,而且还没有大量的文档。任何建议表示赞赏。

标签: c++cmakeclangcross-compilingwindows-subsystem-for-linux

解决方案


推荐阅读