编译的Rust可执行文件是否从依赖项中排除未使用的代码

Tho*_*att 14 dependencies rust rust-cargo

如果我使用带有一些crate依赖项的Cargo构建一个Rust应用程序,那么我的应用程序未使用的那些依赖项中的任何代码是否会从最终的可执行文件中删除?

Mat*_*son 11

它看起来像.我并排测试了lib和bin箱子:

// hellobin/src/main.rs

extern crate hellolib;

fn main() {
    hellolib::func1();
}
Run Code Online (Sandbox Code Playgroud)

对于lib:

// hellolib/src/main.rs

pub fn func1() {
    println!("Hello, world!");
}

pub fn func2() {
    println!("Hello, other world!");
}
Run Code Online (Sandbox Code Playgroud)

构建我的二进制文件,然后检查符号nm:

$ nm target/debug/helloworld | grep hello
0000000100001360 t __ZN10helloworld4main17h749f61fb726f0a10E
00000001000014b0 T __ZN8hellolib5func117hec0b5301559d46f6E
Run Code Online (Sandbox Code Playgroud)

只有used函数在最终二进制文件中有一个符号.

您可以编译,cargo rustc -- -C link-dead-code但您会看到两个符号都存在,包括未使用的符号:

$ nm target/debug/helloworld | grep hello
0000000100001270 t __ZN10helloworld4main17h3104b73b00fdd798E
00000001000013d0 T __ZN8hellolib5func117hec0b5301559d46f6E
0000000100001420 T __ZN8hellolib5func217hc9d0886874057b84E
Run Code Online (Sandbox Code Playgroud)

我相信(但我不确定)它是链接器删除死代码,所以它可能仍然被编译,然后在链接期间被删除.


Mar*_*ein 7

TL; DR:是的,所有未使用的功能都将被排除在外。

实际上,这是LLVM的工作,它将至少跟踪每个未使用的功能。任何未使用的代码(如未在整个应用程序中使用的功能的代码路径中的代码)都可能需要激活LTO(链接时间优化),才能将板条箱转换为一个编译单元,并为LLVM争取机会。