【问题标题】:Problems linking msvc intrinsics using clang on windows在 Windows 上使用 clang 链接 msvc 内部函数的问题
【发布时间】:2016-07-05 07:44:41
【问题描述】:

我正在将大型代码库从使用 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: %llu\n", r);
}

通过 fastbuild 调用时却无法链接: 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:错误 LNK2019:函数中引用了未解析的外部符号 ___rdtsc _wmain ...\IntrinsicsTest.debug.Win32.exe

致命错误 LNK1120:1 个未解决的外部问题

【问题讨论】:

  • 内在函数通常是编译器扩展,并且是非标准的,因此它们依赖于编译器。
  • 你在用clang-cl吗? mingw-w64 铿锵? MS 铿锵声/C2?
  • "Clang --version" 给我:clang version 3.8.0 (branches/release_38) Target: x86_64-pc-windows-msvc Thread model: posix InstalledDir: C:\Program Files\LLVM\bin
  • 你能修复编译器输出中的格式吗?我不确定这是否只是一个命令。并尝试使用clang++,这样调用未声明的函数实际上是错误的。
  • 这是由 fastbuild 分别调用的 3 个命令。希望编辑使这一点更清楚。我很确定如果不花费大量精力更改构建工具,我就无法使用 clang++,因为我们拥有 c 和 c++(以及程序集)的混合代码库。 clang 似乎很好地应对了两者之间的交换,而 clang++ 似乎从来没有编译为 c。

标签: c++ visual-c++ build clang intrinsics


【解决方案1】:

我已经解决了这个问题。有几个因素都与 fastbuild、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/ Fastbuild 允许您为构建环境设置环境变量。我们的脚本包含使用 msvc 路径定义的 INCLUDE 和 PATH。删除这些有帮助。

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

【讨论】:

  • 啊,这在某种程度上解释了为什么只有原型的标头可能存在于应该是内在函数的事物中。原型可能有助于 IDE 和其他东西,但可能 MSVC 编译器本身已经为它们提供了内部内置定义,就像 gcc/clang 预定义了 __builtin_XYZ 一样。
【解决方案2】:

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

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

当存在相当于 MSVC 内部函数的 GNU C __builtin_something 时,通过包装函数使用它。

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

【讨论】:

  • Windows 上的 Clang 提供了它自己的 <Intrin.h> 以及许多 MSVC 的内在函数。有些只是直接实现,有些映射到 LLVM 支持的内在函数(包括 _Interlocked??? 系列),有些只是声明(不确定这些定义是否在某个库中)。
  • 感谢您的回复,但这有点忽略了我的问题的要点。 Windows 上的 Clang 可以很好地编译 msvc 内在函数,因为它们包含在其 intrin.h 中。但是,如果我手动链接它们,它们会作为缺失符号出现。 @melak47 我也假设该定义在某个库中,但我找不到该库的名称。
  • @Teknogrebo:您对哪些内在函数有疑问?就像我在第一段中所说的那样,大多数应该在编译时内联,所以链接器不是图片的一部分。如果存在链接时问题,则意味着您没有为它们获得正确的内联/内置定义。也许用一个在独立可执行文件中构建良好但不是作为库的函数的最小示例来编辑您的问题?这似乎就是你的意思。
  • @PeterCordes 我很感激他们应该被内联。但在我的情况下,从经验上看,它们不是。当我构建我们的产品时,有一长串缺失的符号,其中 __mm_add_ps、__mm_store_ss、__cpuid、_InterlockedOr 和 _BitScanForward 只是其中的一小部分。至于最小的例子,代码是无关紧要的,因为它是被破坏的过程,但我已经相应地修改了问题。
  • @PeterCordes 我正在尝试构建的实际代码库使用 _mm_add_ps 并且找不到 __mm* 函数。我没有禁用任何与隐式声明有关的警告,也没有生成任何警告。我添加到问题中的最小代码示例当然没有给出任何警告,并且表现出我试图深入了解的行为。
猜你喜欢
  • 2021-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-12
  • 2011-05-08
  • 1970-01-01
相关资源
最近更新 更多