|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
7 L$ F% Y" u1 P: H2 ?: m' \9 W只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉3 M; i0 j4 [& k9 X: \' m7 [1 s
你如何通过修改程序的编译选项来瘦身你的执行文件
. L* D0 v# Y2 i; I8 ^$ L先看一个最典型的程序: % B1 [% G/ U, X
#include<stdio.h>$ ^% P% @4 F7 `# Q, r0 ~, T
int main()0 O1 N& @/ ~. Z: ~+ _0 Q/ ~
{2 h; Y+ Q% n( T) ?: E1 ?4 R' N
printf("Hello,World");! w# ^# T- }4 _4 } N( j
return 0;
* S3 f1 {% F3 E5 r" c; S4 \# r}
D! T/ A/ \3 }
) C, l( g3 p- j( U8 Q上面的程序之所以被称之为典型,是因为他有如下的内容:
/ F) z9 i6 J! Z B Q& L8 c. F1、系统函数调用:printf4 C6 o$ R( N( t9 G* _$ S
2、有静态数据段6 v- C- p* F8 ^1 {3 i2 w7 n
( B7 Q5 _1 K g" k v/ \7 N
好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
( c$ E4 X) j8 O3 C. h+ U/ U1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成
" p) V& Q9 e3 T' [% }Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大; z8 K4 p9 J- ~! O) H+ u- p, {* L
小,为172,096Bytes。
: @; ?) W" }4 U) [/ t' ?* k& S3 `7 s, z
2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再
( |5 B# Z5 ~$ e, d, p1 Q3 H$ A编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release+ ^0 N- L# F+ O- @
的小。
" w/ |1 c+ |1 r) p. ?0 V) P0 X- S4 W& i* \! [/ v
3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
- \8 n8 x9 N! K9 @; YSize看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变5 z. w4 |9 R" w) }
化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。1 u& } [: Z8 t- F( W Z
/ \2 h2 S: t: o* L
4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
8 S* l/ d0 N8 M) _* k! j于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static
9 k: ` S; i! u; Q, FLibrary),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编& q8 s2 X0 r5 b0 v6 F( m! \
译选项:C/C++ => Category:Code Generation => Use run-time
- m. A2 N. N' F& ylibrary:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。
/ C( L7 d1 r' k. @6 o
& c. f4 s4 B$ e: q; }5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
8 T3 k7 R3 H. c2 \4 r看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的
$ |" @4 l, `4 `+ v0 a4 E必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采2 v/ p! I% W4 ?8 w; b
用编译器缺省设定的。好,我们来修改一下段的大小看看:
& {$ G0 }4 Y- [3 A3 _- f8 t Z5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应
* N- a4 O3 X. x2 D5 C% q+ P& W的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。$ n ^+ E; _2 `' a. I$ n
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
3 S! t2 `( ]3 s" S小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都
% `1 h. x2 F# x" ]! _% l! e是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:9 K1 `) ^8 @6 I: E# }) R( T" N6 U
/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉* r; V, O6 ~5 g8 w( z# Z7 d% c6 d
害,现在代码更小了。7 z) f* H- X! ^2 @/ S: i" p5 N
5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合
: F/ }, i9 Y6 O; N并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:0 i$ H; O, y* `- h# |: c
/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的+ k& q* ]0 X( E
很不错了。* C; k* L( I( V9 [+ N
: [ d5 L7 l8 G7 q' v1 O8 i+ X6 f5 \6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果5 [- M3 b' b/ g/ X( D0 i
没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
4 d, l: ]7 |0 w& ^, \, X' Y7 j" H5 Omain,把入口地址直接指向我们的main函数看看。得到592Bytes。" e, H: O' ~2 x
3 `5 N# D: _: T9 l1 F- u1 ?最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译
3 {) V: c$ {* z" r' \6 t! r4 c3 V: Y/ e! Z出来的最小的代码了。
9 u7 S: ?" U8 @5 R5 x$ a3 y& K
$ v7 |0 w/ P P( I& M8 L# z' X结论:! e4 c) j* m7 U7 o. j
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目+ V+ g, ^1 G& l/ M7 t
的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。
" o, j. |8 E" |- d0 [如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已( n% S" v% c3 R% F, [8 V0 ^
经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带- H' U o! g, p4 ]' ?
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。3 x$ A# V( U w" `+ \) }# g
- ]6 M& h9 S" J9 ~$ t0 d另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些( t( b) w2 K& L0 p
EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。
/ W# \3 b* K1 s) D! ?: ^5 T' @* m' i. ^# r8 |8 L8 ]7 G' T* }
以上部分的不足之处,还请多多指正。 |
|