Linux 如何减小生成的二进制文件的大小?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6771905/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to decrease the size of generated binaries?
提问by felix021
I know that there is an option "-Os" to "Optimize for size", but it has little affect, or even increase the size on some occasion :(
我知道有一个选项“-Os”来“优化大小”,但它几乎没有影响,甚至在某些情况下会增加大小:(
strip (or "-s" option) removes debug symbol table, which works fine; but it can only decrease only a small propotion of the size.
strip(或“-s”选项)删除调试符号表,它工作正常;但它只能减少一小部分尺寸。
Is there any other way to go furthur?
有没有其他方法可以走得更远?
采纳答案by Damon
Apart from the obvious (-Os -s
), aligning functions to the smallest possible value that will not crash (I don't know ARM alignment requirements) might squeeze out a few bytes per function.-Os
shouldalready disable aligning functions, but this might still default to a value like 4 or 8. If aligning e.g. to 1 is possible with ARM, that might save some bytes.
除了明显的 ( -Os -s
) 之外,将函数对齐到不会崩溃的最小可能值(我不知道 ARM 对齐要求)可能会为每个函数挤出几个字节。-Os
应该已经禁用对齐功能,但这可能仍然默认为 4 或 8 之类的值。如果使用 ARM 可以将例如对齐到 1,这可能会节省一些字节。
-ffast-math
(or the less abrasive -fno-math-errno
) will not set errno and avoid some checks, which reduces code size. If, like most people, you don't read errno anyway, that's an option.
-ffast-math
(或较少磨损-fno-math-errno
)不会设置 errno 并避免一些检查,从而减少代码大小。如果像大多数人一样,无论如何你都不读 errno,那是一个选择。
Properly using __restrict
(or restrict
) and const
removes redundant loads, making code both faster and smaller (and more correct). Properly marking pure functions as such eleminates function calls.
正确使用__restrict
(or restrict
) 并const
删除冗余负载,使代码更快更小(更正确)。像这样正确标记纯函数会消除函数调用。
Enabling LTO may help, and if that is not available, compiling all source files into a binary in one go (gcc foo.c bar.c baz.c -o program
instead of compiling foo.c
, bar.c
, and baz.c
to object files first and then linking) will have a similar effect. It makes everything visible to the optimizer at one time, possibly allowing it to work better.
启用LTO可能会有帮助,如果不可用,编译所有的源文件转换成二进制一气呵成(gcc foo.c bar.c baz.c -o program
而非编译foo.c
,bar.c
以及baz.c
对目标文件,然后再连接)将有类似的效果。它一次使优化器可以看到所有内容,从而可能使其更好地工作。
-fdelete-null-pointer-checks
may be an option (note that this is normally enabled with any "O", but noton embedded targets).
-fdelete-null-pointer-checks
可能是一个选项(请注意,这通常通过任何“O”启用,但不适用于嵌入式目标)。
Putting static globals (you hopefully don't have that many, but still) into a struct can eleminate a lot of overheadinitializing them. I learned that when writing my first OpenGL loader. Having all the function pointers in a struct and initializing the struct with = {}
generates one call to memset
, whereas initializing the pointers the "normal way" generates a hundred kilobytes of code just to set each one to zero individually.
将静态全局变量(您希望没有那么多,但仍然如此)放入结构中可以消除初始化它们的大量开销。我在编写我的第一个 OpenGL 加载程序时了解到这一点。将所有函数指针放在一个结构中并用 初始化该结构会= {}
生成一个对 的调用memset
,而以“正常方式”初始化指针会生成一百千字节的代码,只是为了将每个单独设置为零。
Avoid non-trivial-constructor static localvariables like the devil (POD types are no problem). Gcc will initialize non-trivial-constructor static locals threadsafe unless you compile with -fno-threadsafe-statics
, which links in a lotof extra code (even if you don't use threads at all).
避免像魔鬼一样的非平凡构造函数静态局部变量(POD 类型没有问题)。Gcc 将初始化非平凡构造函数静态局部线程安全,除非您使用 进行编译-fno-threadsafe-statics
,它会链接许多额外的代码(即使您根本不使用线程)。
Using something like libowfat instead of the normal crt can greatlyreduce your binary size.
使用 libowfat 之类的东西代替普通的 crt 可以大大减少二进制文件的大小。
回答by felix021
Assuming that another tool is also allowed ;-)
假设还允许使用另一个工具;-)
Then consider UPX: the Ultimate Packer for Binarieswhich uses runtime decompression.
然后考虑UPX:使用运行时解压缩的二进制文件的终极打包程序。
Happy coding.
快乐编码。
回答by Chris Eberle
If you want to squeeze every last drop of space out of your binaries, you'll probably have to learn assembly. For a very interesting (and entertaining) intro, see this link:
如果您想从二进制文件中挤出最后一滴空间,您可能必须学习汇编。有关非常有趣(和有趣)的介绍,请参阅此链接:
A Whirlwind Tutorial on Creating Really Teensy ELF Executables for Linux
回答by Sebastian Mach
You can also use-nostartfiles
and/or -nodefaultlibs
or the combo of both -nostdlib
. In case you don't want a standard start file, you must write your own _start function then. See also this thread (archived)on oompf:
您还可以使用-nostartfiles
和/或-nodefaultlibs
两者的组合-nostdlib
。如果您不想要标准的启动文件,那么您必须编写自己的 _start 函数。另请参阅oompf 上的此线程(已存档):
(quoting Perrin)
(引用佩林)
# man syscalls
# cat phat.cc
extern "C" void _start() {
asm("int ##代码##x80" :: "a"(1), "b"(42));
}
# g++ -fno-exceptions -Os -c phat.cc
# objdump -d phat.o
phat.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <_start>:
0: 53 push %rbx
1: b8 01 00 00 00 mov ##代码##x1,%eax
6: bb 2a 00 00 00 mov ##代码##x2a,%ebx
b: cd 80 int ##代码##x80
d: 5b pop %rbx
e: c3 retq
# ld -nostdlib -nostartfiles phat.o -o phat
# sstrip phat
# ls -l phat
-rwxr-xr-x 1 tbp src 294 2007-04-11 22:47 phat
# ./phat; echo $?
42
Summary: Above snippet yielded a binary of 294 bytes, each byte 8 bits.
总结:上面的代码片段产生了一个294 字节的二进制文件,每个字节 8 位。
回答by mripard
It also depends on the architecture you are using.
它还取决于您使用的架构。
On arm, you have the Thumb instruction set that is here to reduce the generated code size.
在 arm 上,您可以使用 Thumb 指令集来减少生成的代码大小。
You can also avoid dynamic linking and prefer static linking for libs only used by your program or very few programs on your system. This will not decrease the size of your generated binary per se, but overall, you will use less space on your system for this program.
您还可以避免动态链接,而更喜欢静态链接仅由您的程序或系统上的少数程序使用的库。这不会减少生成的二进制文件本身的大小,但总的来说,您将在系统上为该程序使用更少的空间。
回答by mripard
When using strip(1), you'll want to make sure you use all the relevant options. For some reason, --strip-all
doesn't always strip everything. Removing unnecessary sections may be helpful.
使用条带(1) 时,您需要确保使用所有相关选项。出于某种原因,--strip-all
并不总是剥离一切。删除不必要的部分可能会有所帮助。
Ultimately, though, the best way to reduce the size of the binary is to remove code and static data from the program. Make it do less, or select programming constructs that result in fewer instructions. For example, you might build data structures at runtime, or load them from a file, on-demand, rather than have a statically initialized array.
不过,最终减小二进制文件大小的最佳方法是从程序中删除代码和静态数据。让它做得更少,或者选择导致更少指令的编程结构。例如,您可以在运行时构建数据结构,或者按需从文件加载它们,而不是使用静态初始化的数组。
回答by fwhacking
You can try playing with -fdata-sections
, -ffunction-sections
and -Wl,--gc-sections
, but this is not safe, so be sure to understand how they work before using them.
您可以尝试使用-fdata-sections
,-ffunction-sections
和-Wl,--gc-sections
,但这并不安全,因此在使用它们之前一定要了解它们的工作原理。