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

Problems linking msvc intrinsics using clang on windows

本文关键字:内部函数 问题 msvc 链接 窗口 clang      更新时间:2023-10-16

我正在使用msvc交换一个大型代码库来获取Windows产品。 本产品使用大量的 msvc 编译器内部函数,如_InterlockedOr等。 如果我在Windows上使用clang构建一个小测试程序,它可以构建,链接和运行得很好,但是如果我从我们的产品构建一个使用内部函数的库,它就会作为一个缺失的符号出现。

我尝试使用 --verbose 选项编译测试代码和我们的产品,但无法发现两者之间的任何不同之处。调用它们的方式的唯一区别是大型产品是使用 fastbuild 构建的,这需要使用 -c 来防止编译器调用链接器。 Clang 显然添加了一些我自己手动调用链接器时缺少的库,所以任何人都可以让我知道它们可能是什么吗? (我已经在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: %llun", r);
}

但在通过快速构建调用时无法链接: 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/子系统:CONSOLE/OPT:NOICF/OPT:NOREF

IntrinsicsTest.obj : 错误 LNK2019:函数中引用___rdtsc未解析的外部符号 _wmain ...\IntrinsicsTest.debug.Win32.exe

致命错误 LNK1120:1 个未解析的外部

我已经解决了这个问题。 有几个促成因素都与快速构建、clang 和 msvc 的交互方式有关。

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

-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 版本内联声明了内联函数,因此如果使用此标头,则测试程序可以正常编译。Windows xmmintrin 将内部函数声明为 extern 函数,因此程序可以编译,但不链接 - msvc 构建从何处获取这些符号现在无关紧要。

但是,即使首先使用 clang 包含路径,当任何内容包含 <intrin.h> 时,它也会拉入 windows 标头。

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

c/除了 clang,我的机器上还安装了几个版本的 msvc。 Clang正在接受MSVC14,而fastbuild则试图让Clang使用MSVC 12。通过将 fastbuild 更改为使用 MSVC14,我终于能够克服内部函数的问题。

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

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

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

Mingw-W64显然确实支持_Interlocked???,通过<winnt.h>。 这个邮件列表帖子是一个补丁,它将实现从内联asm切换到GNU C __sync_fetch_and_???函数。 IDK,如果它与当前的 mingw 一起提供,或者如果有 mingw 版本的 clang。 但这就是你应该寻找的。 我敢肯定,您不是第一个想要使用其他编译器编译 MSVC 代码库的人。