clang - 无法使用 lld-link.exe (Windows) 链接 C 运行时库 (libcmt.lib)
问题描述
我正在使用 LLVM 编写一种语言。我想避免打包 clang 并简单地使用 LLVM 工具(例如 lld、lld-link)。我一直在尝试printf
从我的简单 IR 代码 ( 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)
我正在使用带有 LLVM 5.0 的 Windows 10 (x64)。有趣的是,使用link.exe
(Windows 的 VS 工具的链接器)一切正常(在我的例子中,这就是 clang 在后台使用的)。
我读过这篇文章:
...正如我之前写的,__enclave_config 是一个由链接器填充的变量,但是您必须使用 VC 链接器,以及一个足够新的链接器,以便能够自动填充它。...
我相信这里的问题是libcmt.lib
和lld-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,并且它正在工作。-fuse-ld=lld -v
然而,奇怪的是,只有使用 clang(也许使用选项?)将输入目标文件编译为 .LL (LLVM IR) 时,它才能正确编译。
奇怪的是,在检查来自 clang ( test.ll
) 的输出 .LL 文件时,存在 printf (以及它使用的一些其他 *printf 函数)的完整源代码(在 IR 中)定义(在输出 .LL 中)文件)。
因此,它以某种方式printf
在输出 .LL、IR 代码文件中获取了自身的定义。
据我所知,你不能只是$ llc libcmt.lib testinput.ll
?那将是链接器的工作......(llc 只接受一个位置参数)
一旦我对我的文件(不是从 clang 输出)尝试相同的 lld-link 命令和参数,我 testinput.ll
得到的错误如下:
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
. 欢呼!
推荐阅读
- aws-lambda - 如何防止 Aws Step Function 在调用 Lambda 时插入父键“Input”?
- c# - 范围服务在(非 Web)主机上下文中的含义
- powershell - 如何以安全的方式提供 api 密钥?
- php - Laravel POST 请求中收到的原始 PDF
- python - 使用 Keras.NET 进行数组整形
- android - 底部导航上的 Nativescript 设置 selectedIndex 在 Android 上不起作用
- python - 我的 pygame 屏幕的左上角没有正确更新,但其他一切正常
- python - Python正则表达式匹配序列中的许多标记
- redirect - wp_redirect() 函数导致 WooCommerce Checkout 上的无限加载/微调器
- android - 每当用户在颤动中更改操作系统主题时如何获得通知?