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

时间:2019-05-16 03:15:52

标签: clang llvm msvcrt crt lld

我正在使用LLVM编写语言。我想避免打包cl​​ang并仅使用LLVM工具(例如lld,lld-link)。我一直在尝试从我的简单IR代码(printf)调用testinput.ll函数:

; 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"

注意:我只是通过在系统上搜索libcmt.lib来随机选择链接“ ... spectre \ x64 \ 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所使用的)。

我已经读过this article

  

...如我之前所写,__enclave_config是链接器填充的变量,但是您必须使用VC链接器,并且必须使用足够新的链接器才能自动填充它。... < / p>

我相信这里的问题是libcmt.liblld-link链接程序。 lld-link版本(LLVM 5.0)是否与我使用的libcmt.lib不兼容,是问题所在吗?

编辑:我设法跟踪了c声在后台的作用,并使用以下命令找到了它:

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(也许使用-fuse-ld=lld -v选项?)将输入目标文件编译为.LL(LLVM IR),它只会编译没有错误。

这很奇怪,是在检查从clang(test.ll)输出的.LL文件时,printf(及其使用的其他一些* printf函数)的完整,源代码(在IR中)定义存在(在输出.LL文件中)。

因此,它以某种方式在输出的.LL,IR代码文件中获取了printf本身的定义。

据我所知,您不能只是$ llc libcmt.lib testinput.ll吗?那将是链接器的工作...(llc仅接受一个位置参数)

使用 testinput.ll文件(不是从clang输出)尝试相同的lld-link命令和参数时出现的错误如下:

lld-link: error: <root>: undefined symbol: _mainCRTStartup
lld-link: error: undefined symbol: _printf

1 个答案:

答案 0 :(得分:3)

结果证明,它比我预期的简单得多。也许这些错误至少对您有所帮助,我本可以避免所有这些混乱...

我已经通过比较clang的输出LL文件找出了答案,并在开始时发现了一条奇怪的行:

target triple = "x86_64-pc-windows-msvc"

一旦将其添加到我的testinput.ll文件中,一切就可以在lld-link上正常工作。哇!