刚找到Rust并阅读了文档的前两章后,我发现他们定义语言的方法和方式特别有趣。所以我决定弄湿我的手指,并开始使用Hello world ...
我是在Windows 7 x64,btw上执行的。
1 2 3
| fn main() {
println!("Hello, world!");
} |
发出cargo build并查看targets\debug中的结果,我发现生成的.exe为3MB。经过一些搜索(很难找到货运命令行标志的文档...),我找到了--release选项并创建了发布版本。令我惊讶的是,.exe的大小仅变小了一点:2.99MB而不是3MB。
因此,承认我是Rust及其生态系统的新手,我期望系统编程语言会产生紧凑的东西。
谁能详细说明Rust编译的内容,如何通过3线性程序生成如此大的图像?它可以编译到虚拟机吗?我是否错过了一个剥离命令(在发行版内部调试信息?)?还有什么可能让您了解正在发生的事情吗?
-
我认为3Mb不仅包含Hello World,还包含该平台所需的所有环境。使用Qt可以看到相同的结果。这并不意味着如果编写6行程序,大小将变为6 Mb。它将保持在3Mb,之后将非常缓慢地增长。
-
@AndreiNikolaenko我知道这一点。但这暗示它们要么不像C那样处理库,要么仅向图像添加所需的内容,要么正在发生其他情况。
-
@ user2225104参见我的回答,RUST以与C相同(或相似)的方式处理库,但是默认情况下C不会将静态库编译到您的程序中(至少在C ++上)。
-
密切相关:使用Rust构建的DLL在运行时是否需要libgcc.dll?
-
MinGW的strip.exe工具似乎可以在生成生锈的EXE上运行。但是我听说rustc是基于llvm构建的,不确定是否存在任何兼容问题。
-
不喜欢mingw,cygwin等。如果我在Windows上编程,那么我在Windows上编程而不是在穷人身上替代Linux。如果rust声称是一种系统编程语言,那么他们应该可以轻松支持各种平台。
-
@BitTickler您想尝试使用参数-C link-args = -s来减小大小(您说过" strip command",我试过了,它可以工作)。和参数-C link-args = -static-libgcc将删除对x86-32平台的libgcc_xxxx.dll的依赖性。我也不喜欢太多的DLL依赖。 C / C ++具有相对较简单的运行时,因此即使对于静态链接,生成的exe大小也不是很大。对于文件大小,MSVC似乎做得很好。 (mingw-g ++也为静态链接生成了兆字节的exe)
-
我发现-C opt-level = 3 -C lto有助于显着减小静态库的大小。
-
有关使Rust应用程序的二进制大小最小化的所有所有不同技术的概述,请参见min-sized-rust。
-
现在过时了吗?使用rustc版本1.35.0并且没有cli选项,我得到的文件大小为137kb。它是现在自动自动链接动态编译还是在此期间发生了其他事情?
Rust使用静态链接来编译其程序,这意味着即使最简单的Hello world!程序所需的所有库也将被编译为可执行文件。这也包括Rust运行时。
要强制Rust动态链接程序,请使用命令行参数-C prefer-dynamic;这将导致文件大小更小,但同时要求Rust库(包括其运行时)在运行时可用于您的程序。
从本质上讲,这意味着如果计算机没有它们,则需要提供它们,与原始静态链接程序所占用的空间相比,它们会占用更多的空间。
为了可移植性,如果您要将程序分发给其他人,我建议您以您一直使用的方式静态链接Rust库和运行时。
-
-C prefer-dynamic似乎不适用于我。错字?
-
编译为rustc -C prefer-dynamic .rs。
-
还有货物?
-
@ user2225104不确定货物,但是根据GitHub上的此错误报告,不幸的是这还不可能。
-
但是,一旦系统上有两个以上的rust可执行文件,动态链接将开始为您节省空间。
-
我认为静态链接无法解释巨大的HELLO-WORLD。它不应该仅链接到实际使用的库部分,而HELLO-WORLD实际上不使用任何内容吗?
-
BitTickler cargo rustc [--debug or --release] -- -C prefer-dynamic
-
没有Rust编译器就可以安装Rust运行时库吗?喜欢在没有GCC的情况下安装glibc吗?
-
@FranklinYu目前尚不可能-可能不会很快出现。主要限制是锈释放与二进制文件不兼容,并且锈没有稳定的ABI。使用动态链接,您需要同时对所有库和二进制文件进行同步更新。并在每6周发布一个新的编译器时执行此操作。
-
@daboross非常感谢。我一直在跟踪这个相关的RFC。真可惜,因为Rust还针对系统编程。
-
是的-我希望在2-5年内对语言优化和二进制格式充满信心,并且将存在稳定的ABI。希望是我所能做的一切:/。
-
@daboross:我希望ABI不会稳定下来。不稳定的ABI是实现优化(例如"细分"优化,更改结构布局等)所必需的。
-
@MattheiM如果我们不能完全稳定的话,我们总是可以编写一个带有清晰规范的ABI版本。我想那将至少有90%的收益。
-
Rusts可执行文件比Golangs可执行文件大吗?
我没有任何Windows系统可以尝试,但是在Linux上,静态编译的Rust hello世界实际上小于等效的C。如果您看到大小上的巨大差异,则可能是因为您链接了Rust可执行文件静态和C动态。
使用动态链接时,您还需要考虑所有动态库的大小,而不仅仅是可执行文件。
因此,如果您想将一个苹果与另一个苹果进行比较,则需要确保两者都是动态的,或者两者都是静态的。不同的编译器将具有不同的默认值,因此您不能仅仅依靠编译器的默认值来产生相同的结果。
如果您有兴趣,这是我的结果:
1 2 3 4 5 6 7 8 9
| -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:
1 2 3 4 5
| #include <stdio.h>
int main() {
printf("Hello, world!
");
} |
puts.c:
1 2 3 4
| #include <stdio.h>
int main() {
puts("Hello, world!");
} |
rust.rs
1 2 3
| fn main() {
println!("Hello, world!");
} |
另外,请记住,不同数量的调试信息或不同的优化级别也会有所不同。但是我希望,如果您看到巨大的差异,那是由于静态链接与动态链接所致。
-
gcc非常聪明,可以精确地执行printf->放置替换本身,这就是为什么结果相同的原因。
-
从2018年开始,如果您想进行公平的比较,请记住要``剥离''这些可执行文件,因为您好,我系统上的Rust可执行文件高达5.3MB,但是在删除所有调试符号后,降至不到10%这样。
使用Cargo进行编译时,可以使用动态链接:
1
| cargo rustc --release -- -C prefer-dynamic |
由于它现在是动态链接的,因此将大大减少二进制文件的大小。
至少在Linux上,您还可以使用strip命令剥离符号的二进制文件:
1
| strip target/release/<binary> |
这将使大多数二进制文件的大小大约减半。
-
某些统计信息,您好世界的默认发行版本(linux x86_64)。 3.5 M,首选动力8904 B,剥去6392 B.
有关减少Rust二进制文件大小的所有方法的概述,请参见min-sized-rust存储库。
当前减少二进制文件大小的高级步骤是:
使用Rust 1.32.0或更高版本(默认情况下不包含jemalloc)
将以下内容添加到Cargo.toml
1 2 3 4 5
| [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 |
使用cargo build --release在发布模式下构建
在生成的二进制文件上运行strip。
使用nightly Rust可以完成更多工作,但是由于使用了不稳定的功能,信息会随着时间而变化,因此我会将其保留在min-sized-rust中。
您也可以使用#![no_std]删除Rust的libstd。有关详细信息,请参见min-sized-rust。
这是功能,不是错误!
您可以指定程序中使用的库版本(在项目的关联Cargo.toml文件中)(甚至是隐式版本),以确保库版本兼容。另一方面,这要求将特定库静态链接到可执行文件,从而生成较大的运行时映像。
嘿,现在不再是1978年-许多人的计算机中的RAM超过2 MB :-)
-
指定库的版本需要将特定的库静态链接—不,不是。动态链接库的确切版本时,存在大量代码。