我发现他们在文档的前两章中定义语言的方法和方式特别有趣。所以我决定试一试,从“你好,世界!”开始。
顺便说一句,我是在Windows 7 x64上这么做的。
fn main() {
println!("Hello, world!");
}
发布cargo build并在目标\调试中查看结果,我发现结果的.exe为3MB。经过一番搜索(cargo命令行标志的文档很难找到…)我找到了——release选项并创建了发布版本。令我惊讶的是,.exe的大小只变小了一点:2.99MB而不是3MB。
我的期望是系统编程语言会产生一些紧凑的东西。
谁能详细解释一下Rust编译的目的是什么,它是如何从一个3行程序生成如此巨大的图像的?它是否编译到虚拟机?是否有我错过的strip命令(发布版本中的调试信息?)?还有什么能让我们理解的吗?
#![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 {}
}
下一个配置文件
[profile.release]
debug = false
strip = true
opt-level = 'z'
codegen-units = 1
lto = true
panic = 'abort'
用-r给出9 kb,而C
#include <stdio.h>
main() {
puts("Hello, World!");
}
GCC和-Os给出48 kb, TCC给出2 kb。令人印象深刻,不是吗?
#![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 {}
}
下一个配置文件
[profile.release]
debug = false
strip = true
opt-level = 'z'
codegen-units = 1
lto = true
panic = 'abort'
用-r给出9 kb,而C
#include <stdio.h>
main() {
puts("Hello, World!");
}
GCC和-Os给出48 kb, TCC给出2 kb。令人印象深刻,不是吗?
我没有任何Windows系统可以尝试,但在Linux上,一个静态编译的Rust hello世界实际上比等效的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)编译的,都有默认选项,gcc有-static, rustc有-C prefer-dynamic。
我有两个版本的C hello world,因为我认为使用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!");
}
另外,请记住,不同数量的调试信息或不同的优化级别也会产生不同的效果。但我认为,如果你看到了巨大的差异,那是因为静态链接和动态链接。