无法使用 lld-link.exe (Windows) link C 运行时库 (libcmt.lib)
Unable to link C runtime library (libcmt.lib) using lld-link.exe (Windows)
我正在使用 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![=14=]"
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 Studio17\Community\VC\Tools\MSVC.16.27023\lib\spectre\x64\libcmt.lib"
注意:我通过简单地在系统上搜索 libcmt.lib
随机选择了 link “... 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 工具' linker)一切正常(在我的案例中,这就是 clang 在幕后使用的)。
我读过 this article:
... As I wrote earlier, __enclave_config is a variable that is filled in by the linker, but you have to use the VC linker, and a linker new enough to be able to automatically fill it in. ...
我认为这里的问题是 libcmt.lib
和 lld-link
linker。 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(可能使用 -fuse-ld=lld -v
选项?)将输入目标文件编译为 .LL(LLVM IR),它只会编译而不会出错。
奇怪的是,在检查来自 clang (test.ll
) 的输出 .LL 文件时,printf 的完整源代码(在 IR 中)定义(以及 printf 使用的其他一些 *printf 函数)它)存在(在输出 .LL 文件中)。
因此,它以某种方式在输出 .LL、IR 代码文件中获取 printf
本身的定义。
据我所知,你不能只是 $ llc libcmt.lib testinput.ll
?那是linker的工作...(llc只接受一个位置参数)
我在使用 my testinput.ll
文件尝试相同的 lld-link 命令和参数时遇到的错误(不是从 clang 输出的) 如下:
lld-link: error: <root>: undefined symbol: _mainCRTStartup
lld-link: error: undefined symbol: _printf
事实证明,它比我预期的要简单得多。也许如果错误至少有点帮助,我本可以避免所有这些混乱...
我通过比较 clang 的输出 LL 文件弄明白了,并注意到开头有一行奇怪的内容:
target triple = "x86_64-pc-windows-msvc"
将它添加到我的 testinput.ll
文件后,lld-link
一切都完美无缺。万岁!
我正在使用 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![=14=]"
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 Studio17\Community\VC\Tools\MSVC.16.27023\lib\spectre\x64\libcmt.lib"
注意:我通过简单地在系统上搜索 libcmt.lib
随机选择了 link “... 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 工具' linker)一切正常(在我的案例中,这就是 clang 在幕后使用的)。
我读过 this article:
... As I wrote earlier, __enclave_config is a variable that is filled in by the linker, but you have to use the VC linker, and a linker new enough to be able to automatically fill it in. ...
我认为这里的问题是 libcmt.lib
和 lld-link
linker。 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(可能使用 -fuse-ld=lld -v
选项?)将输入目标文件编译为 .LL(LLVM IR),它只会编译而不会出错。
奇怪的是,在检查来自 clang (test.ll
) 的输出 .LL 文件时,printf 的完整源代码(在 IR 中)定义(以及 printf 使用的其他一些 *printf 函数)它)存在(在输出 .LL 文件中)。
因此,它以某种方式在输出 .LL、IR 代码文件中获取 printf
本身的定义。
据我所知,你不能只是 $ llc libcmt.lib testinput.ll
?那是linker的工作...(llc只接受一个位置参数)
我在使用 my testinput.ll
文件尝试相同的 lld-link 命令和参数时遇到的错误(不是从 clang 输出的) 如下:
lld-link: error: <root>: undefined symbol: _mainCRTStartup
lld-link: error: undefined symbol: _printf
事实证明,它比我预期的要简单得多。也许如果错误至少有点帮助,我本可以避免所有这些混乱...
我通过比较 clang 的输出 LL 文件弄明白了,并注意到开头有一行奇怪的内容:
target triple = "x86_64-pc-windows-msvc"
将它添加到我的 testinput.ll
文件后,lld-link
一切都完美无缺。万岁!