|
在网上,有好多绿色软件,不仅功能强大,而且软件本身的体积非常小。有的通常
4 H$ a7 z4 H* n1 ` |只在几十K左右。那他们是怎么做到把软件做的怎么小的呢?现在我手把手的告诉
% ]& r0 Z2 z: h2 f, u0 f$ t你如何通过修改程序的编译选项来瘦身你的执行文件
! X/ }9 c% C4 F& L; B先看一个最典型的程序:
/ I3 e5 _6 A5 T w; P#include<stdio.h>
) F. a' m& X6 p" H& r! \. nint main()
8 f" F: _/ b6 T{
; Y- r) f2 [, p0 g: c% d printf("Hello,World");
8 p. |0 E% B& M0 D6 L- | return 0;
, v4 n$ y* C0 @}6 l2 I8 n l3 E+ @+ r% z
! h% @% L" G" O* F8 X- t- H上面的程序之所以被称之为典型,是因为他有如下的内容:6 V& I4 ?0 W" D7 _/ E
1、系统函数调用:printf
2 |! B$ L" S/ G2、有静态数据段8 d! o+ A& u* |
2 K( d- ~' C# J( O5 N好,现在把此文件放到VisualStudio6.0中进行编译,看看文件有多大。
' I' N* d6 j- B' ]5 u8 Z1、用VisualStudio6.0打开HelloWorld.cpp文件,直接按F7。然后点击OK,生成3 x6 E* ?0 g0 D' H! a Y% w, [& z
Project文件,然后进行编译。编译完成了以后,看看Debug目录下的执行文件的大- ^% ~( d- o+ n" M3 M$ \8 x
小,为172,096Bytes。) L$ e U5 _; Z! T. E
5 O3 c% E9 P7 a4 H2、刚才编译的Debug文件,现在修改成Release文件看看。选择Win32 Release,再 q6 h( t0 I! \* M! i6 {
编译。察看执行文件大小,现在成了40,960Bytes。看来Debug版本的要比Release
) n+ j8 }9 n: _: F9 v# q的小。$ m0 \* f/ R+ E- }, x' b/ m
8 S* y, b X+ m1 Q3、检查代码优化:发现执行文件的优化是Maximize Speed。那么修改成Minimize
6 w: ^; k2 S! i$ W- e" b+ QSize看看。重新编译,得到执行文件的大小为:40,960Bytes。看来大小没什么变
. Q, B/ H: o0 a& _化。其实这是由于我们的代码本身太小的缘故,导致即使变化了也看不出来。
6 ?2 A4 O; w" l- |6 h- }& L3 N
7 R: A6 W P3 J1 A4 j& t8 s4、想想我们程序的main函数是由CRT类库进行引导的。在我们现在的设定当中,由
( E0 [+ L3 }1 i于采取的是系统缺省的编译连接方式(缺省为编译为Single Thread,Static; Y6 A2 L+ m3 v+ r6 }
Library),所以,在我们的执行文件当中,包含了CRT的二进制代码。好,修改编, Y- C3 X. v" [. j3 [
译选项:C/C++ => Category:Code Generation => Use run-time
5 q8 t+ v$ N5 }/ v* tlibrary:MutiThreaded Dll。编译看看:执行文件大小变成了16,384Bytes。: H" D% s+ z5 K5 r* d
1 s, d6 q; s3 E. w
5、刚才的设定确实不错,一下子把执行文件大小减小到了16K。现在用UltraEdit
! Z+ B& m7 V4 D; h看看执行文件都是些什么内容。结果大吃一惊:基本上都是0。看来这个有减小的- K2 ^/ O. ?2 E. [: o$ `" c
必要了。都知道,执行文件都有自己的代码段,数据段等等,每个段的大小也是采" {7 {+ T# b# m! T) o# s0 D/ W u
用编译器缺省设定的。好,我们来修改一下段的大小看看:, F3 q1 R- j7 x; A& M; Q% a
5.1 连接选项中有一个是/opt:nowin98,意思是将段的大小设定成为Win2000适应
+ M2 o: R6 z* T的。编译看看:哇塞,变成了2,560byte。看来这个选项确实把文件变小了N多。2 Q- G; r. d' x) e
5.2 在查察连接选项中还有没有什么特别的。发现/align:xx还可以将段大小缩
4 F# w$ F* |3 g( E( c小。通过UltraEdit察看刚才/opt:nowin98编译出来的文件,发现每个段的大小都4 { Q- H( x4 y# e
是4K的整数倍。看来/align:xx还有减小的趋势。试一把再说:添加连接选项:
! i4 K& q9 \$ l4 }4 |5 X8 Q( y/align:16(这个大小已经是能够设定的最小的了)。看看结果:1,408Bytes。厉6 s3 p- ]" _5 g- B5 y
害,现在代码更小了。
) S/ M2 ~3 E6 U1 ~7 C6 n. }; i6 e5.3 现在回想起来,执行文件大小有数据段,执行代码段等等,如果把这些段都合, Z$ h, L8 X) Y$ a) i& O
并起来,是不是就会把段之间的冗余有减小了呢?再试试看:添加选项:6 C# H/ e1 H# h3 n2 [ K
/merge:.data=.text /merge:.rdata=.text。再看看文件大小:1,328bytes。真的$ B! i7 t3 p# Q+ B" S3 O
很不错了。, I9 K/ Q4 A3 U- i! h+ v) c
( V% ^9 R. g T, {4 L: u5 y
6、刚才的设定确实不错,似乎达到了我们想要的极限了。但是回头想一下,如果
: d2 R% L0 l/ ^' m: P没有CRT库的话,会不会更小了?实际上确实这样。添加连接选项: /entry:
1 o R/ u# @3 Z: l& u' z) w Ymain,把入口地址直接指向我们的main函数看看。得到592Bytes。 u6 W' S ^6 s" w! ]6 {" m' s
2 C& @( V% d+ n9 c' S2 C0 q6 l最终我们得到我们最后的大小592Bytes了。我想这也许是我们通过编译器能够编译! I; J: P$ ?% m. W0 R- M* J% m
出来的最小的代码了。
- T% _3 m2 Y5 E7 ?! F( l1 X6 S% b3 m- U% o
2 v; |5 X/ w, V' v结论:) L( L6 m, u+ y- O" h4 T
通过上述的步骤,我们了解了如何修改那些编译连接选项来达到执行文件瘦身的目
) O; h/ C8 }5 ]# b F" s的。但是,通常来讲,在我们的Release文件当中,并不需要如此小的执行文件。
+ k% D" ~1 j; [8 c如果想达到瘦身的目的,修改为library:MutiThreaded Dll和添加/opt:nowin98已
2 f6 k# | e- m X( B经是很好的选择了。其他别的选项在编译的时候或多或少的有警告出现,而且,带% n, l+ ?4 @3 z9 q; P* j0 S$ g
有那些编译选项编出来的执行文件也不一定在各个平台上能够适用。: {" J6 n& t+ A. D( u5 q0 Y
$ h0 \ Y% {+ D8 M2 f/ p另外:如果你的执行文件即使通过了这些设定还是比较大的话,也可以通过一些
$ G+ l9 |6 j; q. m5 _EXE文件压缩工具来进行压缩。比如UPX等等。在此不再细说了。4 P9 l1 l; E* F0 b! e; {9 L' w, Y9 m3 ^# U
, K, I* h, V( Y& s# r; f
以上部分的不足之处,还请多多指正。 |
|