从 LLVM 位码生成 Rust 可执行文件
Generating Rust executable from LLVM bitcode
如何生成用 Rust 编写并编译成 LLVM-IR 位码的应用程序的可执行文件?
如果我尝试用 rustc 编译 .bc 文件,它会告诉我 stream did not contain valid UTF-8
我似乎无法弄清楚 rustc 中是否有特定的选项。
基本上我想实现这个:
program.rs
-> program.bc
-> program
。
其中 program
是最终的可执行文件。我应该采取哪些步骤来实现这一目标?
从这个源代码开始:
fn main() {
println!("Hello, world!");
}
您可以创建 LLVM 中间表示 (IR) 或 bitcode (BC):
# IR in hello.ll
rustc hello.rs --emit=llvm-ir
# BC in hello.bc
rustc hello.rs --emit=llvm-bc
然后 LLVM 可以进一步处理这些文件以生成 assembly 或 object 文件:
# Assembly in hello.s
llc hello.bc
# Object in hello.o
llc hello.bc --filetype=obj
然后您需要link 文件来生成可执行文件。这需要 linking 到 Rust 标准库。该路径依赖于平台和版本:
cc -L/path/to/stage2/lib/rustlib/x86_64-apple-darwin/lib/ -lstd-f4a73f2c70e583e1 -o hello2 hello.o
然后您可以运行程序:
DYLD_LIBRARY_PATH=/path/to/stage2/lib/rustlib/x86_64-apple-darwin/lib/ ./hello2
这个答案有 macOS 特定的解决方案,但是一般概念 应该 可以扩展到 Linux 和 Windows。 Linux 的实现会略有不同,Windows 的实现可能会有很大不同。值得注意的是,我正在使用 DYLD_LIBRARY_PATH
,因为我动态 linked 到 Rust 标准库,它不在我通常的库搜索路径中。
请注意,LLVM IR 和 BC 文件没有最强的前向/后向兼容性保证。这意味着您需要使用与您正在使用的 rustc
版本兼容的 llc
版本。对于这个答案,我使用了由我的本地 Rust 开发构建生成的 llc
:
% rustc --version --verbose
rustc 1.53.0 (53cb7b09b 2021-06-17)
binary: rustc
commit-hash: 53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b
commit-date: 2021-06-17
host: x86_64-apple-darwin
release: 1.53.0
LLVM version: 12.0.1
% llc --version
LLVM (http://llvm.org/):
LLVM version 12.0.1-rust-dev
Optimized build.
Default target: x86_64-apple-darwin20.5.0
Host CPU: skylake
另请参阅:
- How stable is the LLVM assembly language?
这并不明显,因为 LLVM 文档非常晦涩,但是 clang 将同时编译 LLVM IR 文件 (".ll") 和位码文件 (".bc") ),以及 link 与您的系统库。
在 Linux 上使用 Rust 1.9:
clang -dynamic-linker /usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-d16b8f0e.so hello.ll -o hello
如何生成用 Rust 编写并编译成 LLVM-IR 位码的应用程序的可执行文件?
如果我尝试用 rustc 编译 .bc 文件,它会告诉我 stream did not contain valid UTF-8
我似乎无法弄清楚 rustc 中是否有特定的选项。
基本上我想实现这个:
program.rs
-> program.bc
-> program
。
其中 program
是最终的可执行文件。我应该采取哪些步骤来实现这一目标?
从这个源代码开始:
fn main() {
println!("Hello, world!");
}
您可以创建 LLVM 中间表示 (IR) 或 bitcode (BC):
# IR in hello.ll
rustc hello.rs --emit=llvm-ir
# BC in hello.bc
rustc hello.rs --emit=llvm-bc
然后 LLVM 可以进一步处理这些文件以生成 assembly 或 object 文件:
# Assembly in hello.s
llc hello.bc
# Object in hello.o
llc hello.bc --filetype=obj
然后您需要link 文件来生成可执行文件。这需要 linking 到 Rust 标准库。该路径依赖于平台和版本:
cc -L/path/to/stage2/lib/rustlib/x86_64-apple-darwin/lib/ -lstd-f4a73f2c70e583e1 -o hello2 hello.o
然后您可以运行程序:
DYLD_LIBRARY_PATH=/path/to/stage2/lib/rustlib/x86_64-apple-darwin/lib/ ./hello2
这个答案有 macOS 特定的解决方案,但是一般概念 应该 可以扩展到 Linux 和 Windows。 Linux 的实现会略有不同,Windows 的实现可能会有很大不同。值得注意的是,我正在使用 DYLD_LIBRARY_PATH
,因为我动态 linked 到 Rust 标准库,它不在我通常的库搜索路径中。
请注意,LLVM IR 和 BC 文件没有最强的前向/后向兼容性保证。这意味着您需要使用与您正在使用的 rustc
版本兼容的 llc
版本。对于这个答案,我使用了由我的本地 Rust 开发构建生成的 llc
:
% rustc --version --verbose
rustc 1.53.0 (53cb7b09b 2021-06-17)
binary: rustc
commit-hash: 53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b
commit-date: 2021-06-17
host: x86_64-apple-darwin
release: 1.53.0
LLVM version: 12.0.1
% llc --version
LLVM (http://llvm.org/):
LLVM version 12.0.1-rust-dev
Optimized build.
Default target: x86_64-apple-darwin20.5.0
Host CPU: skylake
另请参阅:
- How stable is the LLVM assembly language?
这并不明显,因为 LLVM 文档非常晦涩,但是 clang 将同时编译 LLVM IR 文件 (".ll") 和位码文件 (".bc") ),以及 link 与您的系统库。
在 Linux 上使用 Rust 1.9:
clang -dynamic-linker /usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-d16b8f0e.so hello.ll -o hello