在 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,我终于能够解决内部问题。
我正在将大型代码库从使用 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,我终于能够解决内部问题。