在 windows 上使用 clang 链接 msvc 内部函数时出现问题

Problems linking msvc intrinsics using clang on windows

我正在将大型代码库从使用 msvc 转换为 windows 产品。该产品使用了大量的 msvc 编译器内部函数,例如 _InterlockedOr 等。如果我在 windows 上使用 clang 构建一个小测试程序,它会构建 links 并运行得很好,但是如果我构建一个我们产品中使用内在函数的库显示为缺少符号。

我已经尝试使用 --verbose 选项编译测试代码和我们的产品,但无法发现两者之间有任何不同。它们调用方式的唯一区别是大型产品是使用 fastbuild 构建的,这需要使用 -c 来防止编译器也调用 linker。当我自己手动调用 linker 时,Clang 显然添加了一些缺少的库,所以任何人都可以让我知道它们可能是什么吗? (我已经 link 在 crt 库(libcmt、msvcrt)中学习,所以不是那样。

我已经开始在汇编中编写自己的内部函数库,这很有趣,但不是必需的。有人吗?

根据要求,使用 clang 编译以下代码在直接使用时有效,即 clang IntrinsicsTest.cpp生成一个 exe。

IntrinsicsTest.cpp
#include "stdio.h"
#include "intrin.h"

int _tmain(int argc, _TCHAR* argv[])
{
    unsigned long long r = __rdtsc();
    printf("Intrinsic: %llu\n", r);
}

但通过 fastbuild 调用时 link 失败: FBuild.exe -showcmds -clean IntrinsicsTest_debug_x86

clang.exe "\IntrinsicsTest.cpp" -D_WINDOWS -c -m32 -mfpmath=sse -D_UNICODE -DUNICODE -fno-rtti -fexceptions -E ...\IntrinsicsTest.debug.Win32.lib

lib.exe /NOLOGO /OUT:"...\IntrinsicsTest.debug.Win32.lib" "...\IntrinsicsTest.obj" ...\IntrinsicsTest.debug.Win32.exe

link.exe /NOLOGO /INCREMENTAL:NO /OUT:"...\IntrinsicsTest.debug.Win32.exe" "...\IntrinsicsTest.obj" -defaultlib:libcmt.lib -INCREMENTAL -MANIFEST /MACHINE:X86 /SUBSYSTEM:CONSOLE /OPT:NOICF /OPT:NOREF

IntrinsicsTest.obj : error LNK2019: unresolved external symbol ___rdtsc referenced in function _wmain ...\IntrinsicsTest.debug.Win32.exe

fatal error LNK1120: 1 unresolved externals

内在函数不应该是函数调用,它们应该内联到一条或几条指令。或者在某些情况下,没有指令(例如编译器内存屏障,如 c++ 的 std::atomic_signal_fence)。

MSVC 和 GNU C 是 C 的不同版本。clang 实现 GNU C,而 AFAIK 不支持 MSVC 内在函数。

当 GNU C __builtin_something 等同于 MSVC 内在函数时,通过包装函数使用它。

mingw-w64 显然通过 <winnt.h> 支持 _Interlocked???This mailing list post 是一个补丁,将实现从内联汇编切换到 GNU C __sync_fetch_and_??? 函数。 IDK 是否随当前的 mingw 一起提供,或者是否有 clang 的 mingw 版本。但这就是你应该寻找的。我确定您不是第一个想要使用不同编译器编译 MSVC 代码库的人。

我已经解决了这个问题。有几个因素都与 fastbuild、clang 和 msvc 的交互方式有关。

a/ 使用 Windows 上的 Clang,无需指定 "system" 包含。 在我们的项目中,包含路径为:

-I"C:/Program Files/LLVM/lib/clang/3.8.0/include" 
-I"C:/Program Files (x86)/Microsoft Visual Studio 12.0/VC/include/" 
-I"C:/Program Files (x86)/Microsoft Visual Studio 12.0/VC/atlmfc/include" 
-I"C:/Program Files (x86)/Windows Kits/8.1/include/um" 
-I"C:/Program Files (x86)/Windows Kits/8.1/include/shared"
-I"C:/Program Files (x86)/Windows Kits/8.1/include/winrt"

xmmintrin 的 clang 版本声明内联函数,因此如果使用此 header,则测试程序可以正常编译。 Windows xmmintrin 将内在函数声明为外部函数,因此程序编译,但不编译 link - msvc 构建从中获取这些符号的位置现在无关紧要。

然而,即使首先使用 clang 包含路径,当 <intrin.h> 被任何东西包含时,它也会引入 windows header。

b/ Fastbuild 允许您为构建环境设置环境变量。我们的脚本包含使用 msvc 路径定义的 INCLUDE 和 PATH。删除这些有帮助。

c/ 除了 clang,我的机器上还安装了多个版本的 msvc。 Clang 开始使用 MSVC14,而 fastbuild 试图让 clang 使用 MSVC 12。通过将 fastbuild 更改为使用 MSVC14,我终于能够解决内部问题。