Bit*_*ler 128 rust rust-cargo
刚刚找到Rust并阅读了文档的前两章,我发现他们定义语言的方法和方式特别有趣.所以我决定让我的手指湿润,开始使用Hello world ...
我在Windows 7 x64上这样做了,顺便说一下.
fn main() {
println!("Hello, world!");
}
Run Code Online (Sandbox Code Playgroud)
发行cargo build并查看结果targets\debug我发现所得.exe的存在3MB.经过一些搜索(很难找到货物命令行标志的文档......)我找到了--release选项并创建了发布版本.令我惊讶的是,.exe大小只变小了一小部分:2.99MB而不是3MB.
因此,承认我是Rust及其生态系统的新手,我的期望是系统编程语言会产生紧凑的东西.
任何人都可以详细说明Rust正在编译的内容,如何通过3个线程程序生成如此巨大的图像?它是否正在编译为虚拟机?我错过了一个strip命令(在发布版本中调试信息吗?)?还有什么可能让我们了解正在发生的事情?
ASt*_*her 114
Rust使用静态链接来编译程序,这意味着即使是最简单的Hello world!程序所需的所有库也将被编译到您的可执行文件中.这还包括Rust运行时.
要强制Rust动态链接程序,请使用命令行参数-C prefer-dynamic; 这将导致文件小得多,但也需要Rust库(包括其运行时)在运行时可用于您的程序.这基本上意味着你将需要为他们提供如果计算机没有他们,占用了更多的比你原来的静态链接程序占用空间.
为了便于携带,我建议你以你曾经做过的方式静态链接Rust库和运行时,如果你要将程序分发给其他人.
aij*_*aij 54
我没有任何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-dynamicfor rustc.
我有两个版本的C hello世界,因为我认为使用puts()可能会链接更少的编译单元.
如果你想尝试在Windows上复制它,这里是我使用的来源:
printf.c:
#include <stdio.h>
int main() {
printf("Hello, world!\n");
}
Run Code Online (Sandbox Code Playgroud)
puts.c:
#include <stdio.h>
int main() {
puts("Hello, world!");
}
Run Code Online (Sandbox Code Playgroud)
rust.rs
fn main() {
println!("Hello, world!");
}
Run Code Online (Sandbox Code Playgroud)
此外,请记住,不同数量的调试信息或不同的优化级别也会产生影响.但我希望如果你看到一个巨大的差异,那是由于静态与动态链接.
小智 24
使用Cargo进行编译时,您可以使用动态链接:
cargo rustc --release -- -C prefer-dynamic
Run Code Online (Sandbox Code Playgroud)
这将大大减小二进制文件的大小,因为它现在是动态链接的.
至少在Linux上,您还可以使用以下strip命令去除符号的二进制:
strip target/release/<binary>
Run Code Online (Sandbox Code Playgroud)
这大约会使大多数二进制文件的大小减半.
pho*_*nix 13
有关减少Rust二进制文件大小的所有方法的概述,请参见min-sized-rust存储库。
当前减少二进制文件大小的高级步骤是:
jemalloc默认情况下不包括)Cargo.toml[profile.release]
opt-level = 'z' # Optimize for size.
lto = true # Enable Link Time Optimization
codegen-units = 1 # Reduce number of codegen units to increase optimizations.
panic = 'abort' # Abort on panic
Run Code Online (Sandbox Code Playgroud)
cargo build --releasestrip在生成的二进制文件上运行。使用nightlyRust 可以完成更多工作,但是min-sized-rust由于使用了不稳定的功能,信息会随着时间的推移而变化,因此我会保留这些信息。
您也可以使用#![no_std]删除Rust的libstd。有关min-sized-rust详细信息,请参见。
#![no_main]
#![no_std]
#[link(name = "msvcrt", kind = "dylib")]
extern {
fn puts(ptr: *const u8); // i8 or u8 doesn't matter in this case
}
#[no_mangle]
unsafe extern fn main() {
puts("Hello, World!\0".as_ptr());
}
#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! {
loop {}
}
Run Code Online (Sandbox Code Playgroud)
与下一个配置文件
[profile.release]
debug = false
strip = true
opt-level = 'z'
codegen-units = 1
lto = true
panic = 'abort'
Run Code Online (Sandbox Code Playgroud)
给出 9 kb -r,而 C
#include <stdio.h>
main() {
puts("Hello, World!");
}
Run Code Online (Sandbox Code Playgroud)
使用 GCC 给出 48 kb,-Os使用 TCC 给出 2 kb。非常令人印象深刻,不是吗?