Rust 在 Windows 上 Release 编译彻底去除调试符号信息
本文介绍如何让 Rust 在以 Windows 为目标平台的 Release 编译的基础上,通过配置链接参数进一步彻底去除多余的调试符号信息,针对的工具链包括 GNU 和 MSVC。
去除额外的符号信息能减小最终生成程序的体积。如果是在 Windows 上使用 GNU 工具链,那么这一点会很明显。
一个 Rust 的 Hello World 程序,在 Windows 下,使用 GNU 工具链,即便是 Release 编译,最后生成的程序体积也有 3 MB 多。其中调试符号信息占了大部分体积;如果去除,程序体积可以下降至 600+ KB。好在如果使用的是 MSVC 工具链编译,调试符号会另存于 .pdb
文件,程序本体没有这样的体积问题。
在 Linux 下,如果编译时带上了符号信息,编译完还可以用 strip
工具解决这个问题,但是 Windows 下呢?
去除符号信息可以减小 Rust 程序体积,但本文不打算探讨减小 Rust 程序体积的各种技巧,本文只打算纯粹地介绍在 Windows 目标平台上编译 Rust 程序时如何去除额外的调试符号信息。
读者如果想进一步研究如何减小 Rust 生成程序的体积,可以参考网上已有的讲解得很具体和专业的精彩文章。在这里笔者也列举一些供读者参考:
优化 Rust 程序编译体积.[https://www.aloxaf.com/2018/09/reduce_rust_size/]
Minimizing Rust Binary Size.[https://github.com/johnthagen/min-sized-rust]
那么言归正传,本文主要关注如何在 Windows 上去除额外的符号信息。
在 Release 模式下编译 Rust 程序,虽然自己编写的这部分程序不会生成符号信息,但是链接的 Rust 标准库会带上调试信息。如果想去除这些信息,需要指定一些链接参数。指定链接参数的方式很多,本文为了方便,以 .cargo/config
为例。
在项目文件夹下创建文件 .cargo/config
(.cargo 文件夹可能不存在,需要自行创建)
如果是 pc-windows-gnu 工具链,欲链接时去除调试符号信息,则在 .cargo/config
中写入:(以 x86_64
为例)
[target.x86_64-pc-windows-gnu]
rustflags = [
"-C", "link-arg=-s",
]
这样链接时会将 -s
选项传给 GCC:
-s: Remove all symbol table and relocation information from the executable.
(https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html)
此后通过 Cargo build --release
编译,生成的程序就不带调试符号信息了,但是请留意本文最后的注意事项。
如果使用 pc-windows-msvc 工具链,那其实还好,因为符号文件(.pdb)和程序是分开的,大可不理会。但是即便这样也还是不满意,想要它彻底不产生也是可以的,在 .cargo/config
中写入:(以 x86_64
为例)
[target.x86_64-pc-windows-msvc]
rustflags = [
"-C", "link-arg=/DEBUG:NONE",
]
这样链接时会让 MSVC 的链接器带上 /DEBUG:NONE
选项。(参考:https://users.rust-lang.org/t/compile-in-release-mode-without-debugging-symbols/19764)
同样,此后通过 Cargo build --release
编译,生成的程序就不带调试符号信息了。
⚠注意⚠
.cargo/config
中指定的 rustflags
会对所有 Profile (如 Release、Debug)都生效。所以如果此后需要保留调试信息,请注意记得将以上修改注释掉,以免带来困扰,否则就算是 Debug 模式也没有调试信息,因为其直接向链接器传递了参数。现阶段 Cargo 还不支持针对特定的 Profile 设置 rustflags,所以比较狼狈,不过这个特性已经在讨论中了。当然,如果读者是行家,想必有自己的想法和技巧,能用其他方式指定这些参数,从而使其自动在正确时候生效。
评论
支持一年大佬 :)
发表评论