首页 > 解决方案 > 手动链接到 LLVM 中的 Windows 库

问题描述

我正在编写自己的编程语言,并希望通过编译为 LLVM IR 将其编译为本机二进制文件,然后让 LLVM 工具链的其余部分接管。最终,我将针对多个平台,但现在我只关注 Windows。

对于初学者,我编译的是空程序,这意味着通常我的工具链已设置并正在工作,并且我从中获得了一个无操作可执行文件。下一个合乎逻辑的步骤是执行“Hello World”,但是在查看了简单调用它的 C 程序的 clang 的 LLVM IR 输出之后,puts("Hello World!")看起来更简单的第一步是简单地_exit();. 在查看该 C 程序的 clang 输出时,看起来相关行是 to do call void @_exit(i32 0). 我把它提炼成我认为是调用exit的最低限度的程序:

define i64* @main() {
    %1 = alloca i32, align 4
    store i32 0, i32* %1, align 4
    call void @_exit(i32 0)
    unreachable
}
declare dso_local void @_exit(i32)

当尝试直接运行等效的 C 程序时,当然它在我clang直接使用时可以工作,但是创建 LLVM IR 后的步骤对我来说是不透明的,我相信我使用了错误的链接器选项或其他东西,因为我得到了lld-link: error: undefined symbol: _exit在 lld-link 步骤期间。(实际上,当我尝试手动链接 的输出时也会发生这种情况clang -S --emit-llvm,因此我没有理由相信我的 IR 是问题所在)。我用于 lld-link 的当前调用是lld-link /out:"exit.exe" /entry:main exit.obj. 我尝试过添加各种风格的/defaultlib开关,包括手动链接到 libcmt 两个 libucrt,我认为在查看符号后包含 _exitdumpbin,但这似乎没有帮助。查看 clang 程序的 IR 输出,似乎没有对 <stdlib.h> 的任何特别引用,所以我猜在 IR 生成阶段之后信息会丢失,所以我不认为我错过了我的 IR 中的任何内容。

这似乎是一个一般的 Windows 链接器问题,而不是与 LLVM 有任何关系,因为如果我这样做,link /out:exit.exe /entry:main exit.obj我会得到基本相同的错误。

无论如何,在链接期间显然有一些我不明白的步骤,围绕如何找到给定外部调用所在的实际库,所以如果有人能指出我如何解决这个问题的正确方向给定 C 运行时调用,那就太好了。特别是在这种情况下,我想我需要找到包含 _exit 函数的库。谢谢!

标签: windowslinkerllvm

解决方案


Turns out the libcmt has been replaced. The replacement is ucrt, and so doing /defaultlib:ucrt seems to fix the problem!


推荐阅读