首页 文章

为什么Rust可执行文件如此庞大?

提问于
浏览
94

刚刚找到Rust并阅读了文档的前两章,我发现他们定义语言的方法和方式特别有趣 . 所以我决定让我的手指湿透,开始使用Hello world ...

我是在Windows 7 x64上完成的,顺便说一句 .

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

发出 cargo build 并在 targets\debug 中查看结果我发现 .exe 为3MB . 经过一番搜索(很难找到货物命令行标志的文档......)我找到了 --release 选项并创建了发布版本 . 令我惊讶的是,.exe大小只变小了一小部分:2.99MB而不是3MB .

因此,承认我是Rust及其生态系统的新手,我的期望是系统编程语言会产生紧凑的东西 .

任何人都可以详细说明Rust正在编译的内容,如何通过3个线程程序生成如此巨大的图像?它是否正在编译为虚拟机?我错过了一个strip命令(在发布版本中调试信息吗?)?还有什么可能让我们了解正在发生的事情?

4 回答

  • 20

    Rust使用静态链接来编译程序,这意味着即使是最简单的 Hello world! 程序所需的所有库也将被编译到您的可执行文件中 . 这还包括Rust运行时 .

    要强制Rust动态链接程序,请使用命令行参数 -C prefer-dynamic ;这将导致更小的文件大小 but 还将要求Rust库(包括其运行时)在运行时可用于您的程序 . 这实际上意味着如果计算机没有它们,您将需要提供它们,占用的空间比原始静态链接程序占用的空间多 .

    为了便于携带,我建议您按照自己的方式静态链接Rust库和运行时,如果您要将程序分发给其他人 .

  • 41

    我没有任何Windows系统可以尝试,但在Linux上,静态编译的Rust hello world实际上比同等C小 . 如果你看到大小的巨大差异,可能是因为你链接了Rust可执行文件静态地和C一动态 .

    使用动态链接时,您还需要考虑所有动态库的大小,而不仅仅是可执行文件 .

    因此,如果你想比较苹果和苹果,你需要确保两者都是动态的或两者都是静态的 . 不同的编译器将具有不同的默认值,因此您不能仅依靠编译器默认值来生成相同的结果 .

    如果您有兴趣,这是我的结果:

    -rw-r--r-- 1 aij aij     63 Apr  5 14:26 printf.c
    -rwxr-xr-x 1 aij aij   6696 Apr  5 14:27 printf.dyn
    -rwxr-xr-x 1 aij aij 829344 Apr  5 14:27 printf.static
    -rw-r--r-- 1 aij aij     59 Apr  5 14:26 puts.c
    -rwxr-xr-x 1 aij aij   6696 Apr  5 14:27 puts.dyn
    -rwxr-xr-x 1 aij aij 829344 Apr  5 14:27 puts.static
    -rwxr-xr-x 1 aij aij   8712 Apr  5 14:28 rust.dyn
    -rw-r--r-- 1 aij aij     46 Apr  5 14:09 rust.rs
    -rwxr-xr-x 1 aij aij 661496 Apr  5 14:28 rust.static
    

    这些是用gcc(Debian 4.9.2-10)4.9.2和rustc 1.0.0-nightly(d17d6e7f1 2015-04-02)(建于2015-04-03)编译的,两者都有默认选项,而 -static 用于gcc和 -C prefer-dynamic 为rustc .

    我有两个版本的C hello世界,因为我认为使用 puts() 可能会链接更少的编译单元 .

    如果您想尝试在Windows上重现它,以下是我使用的来源:

    printf.c:

    #include <stdio.h>
    int main() {
      printf("Hello, world!\n");
    }
    

    puts.c:

    #include <stdio.h>
    int main() {
      puts("Hello, world!");
    }
    

    rust.rs

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

    另外,请记住,不同数量的调试信息或不同的优化级别也会产生影响 . 但我希望如果你看到一个巨大的差异,那是由于静态与动态链接 .

  • 87

    使用Cargo进行编译时,您可以使用动态链接:

    cargo rustc --release -- -C prefer-dynamic
    

    这将大大减小二进制文件的大小,因为它现在是动态链接的 .

    至少在Linux上,您还可以使用 strip 命令去除符号的二进制:

    strip target/release/<binary>
    

    这大约会使大多数二进制文件的大小减半 .

  • -3

    这是一个功能,而不是一个bug!

    您可以指定程序中使用的库版本(在project's associated Cargo.toml file中)(甚至是隐式版本)以确保库版本兼容性 . 另一方面,这需要将特定库静态链接到可执行文件,从而生成大的运行时映像 .

    嘿,这不是1978年了 - 很多人的电脑里面有超过2 MB的RAM :-)

相关问题