无法使用lld-link.exe(Windows)链接C运行时库(libcmt.lib)

4

我正在使用LLVM编写一种编程语言。我希望避免打包clang,只需使用LLVM工具(例如lld,lld-link)。我一直在尝试从我的简单IR代码(testinput.ll)中调用printf函数:

; ModuleID = 'Test2'
source_filename = "entry"

@str_0 = private unnamed_addr constant [13 x i8] c"Hello world!\00"

declare i32 @printf(i8*, ...)

define i32 @main() {
entry:
  %anonymous_10 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @str_0, i32 0, i32 0))
  ret i32 1234
}

无论我尝试什么方法,仍然会持续收到错误消息:

$ clang-cl -fuse-ld=lld-link testinput.ll "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\lib\spectre\x64\libcmt.lib"

注意:我随机选择了链接 "... spectre\x64\libcmt.lib ...",仅仅是在系统中搜索libcmt.lib
错误:
C:\Program Files\LLVM\bin\lld-link: warning: libcmt.lib(loadcfg.obj): undefined symbol: __enclave_config
error: link failed
clang-cl.exe: error: linker command failed with exit code 1 (use -v to see invocation)

我正在使用 Windows 10(x64)和 LLVM 5.0。有趣的是,使用 link.exe(Windows 的 VS 工具链链接器),一切都正常工作(这也是在我的情况下 Clang 使用的内容)。

我在这篇文章中读到:

......如我之前所写的那样,__enclave_config 是由链接器填充的变量,但你必须使用 VC 链接器,并且链接器足够新才能自动填充它。......

我认为问题在于 libcmt.liblld-link 链接器。我使用的 lld-link 版本(LLVM 5.0)与我正在使用的 libcmt.lib 不兼容,这是问题的原因吗?

编辑:我已经追踪到 Clang 在幕后执行的操作,并发现它使用了以下命令:

lld-link -out:a.exe -defaultlib:libcmt "-libpath:C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\VC\\Tools\\MSVC\\14.16.27023\\lib\\x64" "-libpath:C:\\Program Files (x86)\\Windows Kits\\10\\Lib\\10.0.17763.0\\ucrt\\x64" "-libpath:C:\\Program Files (x86)\\Windows Kits\\10\\Lib\\10.0.17763.0\\um\\x64" -nologo "test.obj"

显然它正在使用lld-link,并且正在工作。然而,奇怪的是,只有当输入目标文件使用clang编译为.LL(LLVM IR)时(可能使用选项-fuse-ld = lld -v?),它才能编译而没有错误。
奇怪之处在于,检查clang的输出.LL文件(test.ll)时,printf的完整源代码(在IR中)定义(以及它使用的一些其他* printf函数)存在于输出.LL文件中。
因此,某种方式将printf本身的定义获取到了输出的.LL,IR代码文件中。
据我所知,你不能只是$ llc libcmt.lib testinput.ll?那就是链接器的工作...(llc仅接受一个位置参数)
当我尝试使用相同的lld-link命令和参数与我的testinput.ll文件(未从clang输出)时,我得到的错误如下:
lld-link: error: <root>: undefined symbol: _mainCRTStartup
lld-link: error: undefined symbol: _printf
1个回答

8
原来,这比我预想的要简单得多。如果错误提示有点帮助的话,我或许就能避免所有的困惑了...
通过比较clang输出的LL文件,我发现了一个奇怪的行在开头:
target triple = "x86_64-pc-windows-msvc"

一旦我将它添加到我的 testinput.ll 文件中,使用 lld-link 一切都完美无缺。太好了!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接