From d94d414d18dcdfc288fa353cda0e513f432d29b7 Mon Sep 17 00:00:00 2001 From: geekard Date: Sun, 30 Dec 2012 17:47:01 +0800 Subject: [PATCH] updated --- Zim/.zim/index.db | Bin 231424 -> 231424 bytes Zim/.zim/state.conf | 4 +- Zim/.zim/state.conf.zim-new~ | 129 - Zim/Utils/autoconf---automake.txt | 243 -- Zim/Utils/autoconf---automake/1.jpg | Bin 6616 -> 0 bytes Zim/Utils/autoconf---automake/2.gif | Bin 8009 -> 0 bytes Zim/Utils/autoconf---automake/3.gif | Bin 3876 -> 0 bytes Zim/Utils/autoconf---automake/4.gif | Bin 4743 -> 0 bytes Zim/Utils/autoconf---automake/5.gif | Bin 4686 -> 0 bytes Zim/Utils/autoconf---automake/6.gif | Bin 2443 -> 0 bytes Zim/Utils/autoconf---automake/代码.txt | 38 - Zim/Utils/gcc&g++.txt | 7 - Zim/Utils/gcc&g++/C++编译初步.txt | 219 -- Zim/Utils/gcc&g++/C编译初步.txt | 220 -- .../Installing---GCC--Configuration.txt | 659 ----- Zim/Utils/make.txt | 2437 ----------------- Zim/Utils/工具链/autoconf---automake.txt | 68 +- .../autoconf---automake/Autoconf学习笔记.txt | 84 +- .../autoconf---automake/Autotools上手指南.txt | 4 +- .../autoconf---automake/autoconf软件包.txt | 29 - Zim/Utils/工具链/autoconf---automake/实例.txt | 271 ++ .../autoconf---automake/实例/autoreconf.txt | 53 + .../autoconf---automake/实例/demo.c.txt | 67 + .../工具链/autoconf---automake/实例/foo.c.txt | 14 + 24 files changed, 472 insertions(+), 4074 deletions(-) delete mode 100644 Zim/.zim/state.conf.zim-new~ delete mode 100644 Zim/Utils/autoconf---automake.txt delete mode 100644 Zim/Utils/autoconf---automake/1.jpg delete mode 100644 Zim/Utils/autoconf---automake/2.gif delete mode 100644 Zim/Utils/autoconf---automake/3.gif delete mode 100644 Zim/Utils/autoconf---automake/4.gif delete mode 100644 Zim/Utils/autoconf---automake/5.gif delete mode 100644 Zim/Utils/autoconf---automake/6.gif delete mode 100644 Zim/Utils/autoconf---automake/代码.txt delete mode 100644 Zim/Utils/gcc&g++.txt delete mode 100644 Zim/Utils/gcc&g++/C++编译初步.txt delete mode 100644 Zim/Utils/gcc&g++/C编译初步.txt delete mode 100644 Zim/Utils/gcc&g++/Installing---GCC--Configuration.txt delete mode 100644 Zim/Utils/make.txt delete mode 100644 Zim/Utils/工具链/autoconf---automake/autoconf软件包.txt create mode 100644 Zim/Utils/工具链/autoconf---automake/实例.txt create mode 100644 Zim/Utils/工具链/autoconf---automake/实例/autoreconf.txt create mode 100644 Zim/Utils/工具链/autoconf---automake/实例/demo.c.txt create mode 100644 Zim/Utils/工具链/autoconf---automake/实例/foo.c.txt diff --git a/Zim/.zim/index.db b/Zim/.zim/index.db index a42c5af38912a46f014e1be7bf12f19e73c3de75..a7abf6225bdfdf8155b2b388e961222a37ea756e 100644 GIT binary patch delta 716 zcmX|8T}YE*6h7xY`>?z8;ar=hvDEHLbM5)HKUq93Qyg4YW?H^o8c=Jx!8I z&*%|VQ;6=;ExJrzI!6w*+>}RYsRBo06e_BYoY#fP?dam8pi?$jml(R_a?=gE8L+F~ zih+7OAq#!?#1R^&X_}>ZTBh%O(7HO%$J@|DdFcMHtsETHn54#xI-*pMBpu%P(>C0z z{jNd1Q^)L3rwIMnq_pF%z~>p zgO{)fR$v%9d1_~DP$}nI+_*1bH-PydL*!9CG&Q&S$~+mST*-(jQHh_z@uXUW$~h|@ zIo3E|9H`}>yaZ_F<-oVep5<=;=V3(l5s}w1dH4BON+5z(MTlUR(zl3p%HIf@dt=foc|_$)ct2~d%FLPhA(gOAj1;RwrutwLZjIBYKox3)yM2dA0Bfjt>vmo@Q3oimg1ZO`egb^fUP!RO4NjDuhhvzvj@ADj<{+PQz=8hTe z#SJ0Er_C;oSMBG;ji>En#n91iimFKvN12jv&)#3nYBt2EQ zC{JhTq(dF;i#L?Y)g>AxA)hQ!P_AXDR?cRq(he+BrpDGC{0;xlM7>@=S;2J1uSEQ! zQ(#I()r(ftVJ9!~G!JsOG-4b`?A3SKoiWyUyAgE=Z}rhbjiFF^iSG4MLAG+!9vtER zcfLZA0%pWIE?^I@^Fxv15Iv@_%Jqs&b>n9C=%8Zz>~Ih2=y*1$>7QzO_=e9Vs#};y zk$ll{{#;*YUvK2|%k;{N$<的方法来覆盖。 -其它的预定义目录还包括:bindir = $(prefix)/bin, libdir = $(prefix)/lib, **datadir** = $(prefix)/share, **sysconfdir** = $(prefix)/etc等等。 - -2) 定义一个新的安装路径 - -比如test, 可定义testdir = $(prefix)/test, 然后test_DATA =test1 test2,则test1,test2会作为数据文件安装到$(prefix)/test目录下。 -我们首先需要在工程顶层目录下(即project/)创建一个Makefile.am来指明包含的子目录: - -__SUBDIRS__=src/lib src/ModuleA/apple/shell src/ModuleA/apple/core -**CURRENTPATH**=$(shell /bin/pwd) -**INCLUDES=**-I$(CURRENTPATH)/src/include -I$(CURRENTPATH)/src/ModuleA/apple/include -**export **INCLUDES - - -由于每个源文件都会用到相同的头文件,所以我们在最顶层的Makefile.am中包含了编译源文件时所用到的头文件,并导出,见蓝色部分代码。 - -我们将lib目录下的swap.c文件编译成libswap.a文件,被apple/shell/apple.c文件调用,那么lib目录下的Makefile.am如下所示: - -**noinst**_LIBRARIES=__libswap.a__ -libswap_a_SOURCES=swap.c -INCLUDES=-I**$(top_srcdir)**/src/includ - - -细心的读者可能就会问:怎么表1中给出的是bin_LIBRARIES,而这里是noinst_LIBRARIES?这是因为如果只想编译,而不想安装到系统中,就用noinst_LIBRARIES代替bin_LIBRARIES,对于可执行文件就用noinst_PROGRAMS代替bin_PROGRAMS。对于安装的情况,库将会安装到$(prefix)/lib目录下,可执行文件将会安装到${prefix}/bin。如果想安装该库,则Makefile.am示例如下: - -bin_LIBRARIES=libswap.a -libswap_a_SOURCES=swap.c -INCLUDES=-I$(top_srcdir)/src/include -**swapincludedir=**$(includedir)/swap #自定义的一个变量 -**swapinclude_HEADERS**=$(top_srcdir)/src/include/**swap.h** - - -最后两行的意思是将swap.h安装到${prefix}/include /swap目录下。 - -接下来,对于**可执行文件类型**的情况,我们将讨论如何写Makefile.am?对于编译apple/core目录下的文件,我们写成的Makefile.am如下所示: - -noinst_PROGRAMS=test -test_SOURCES=test.c -test_**LDADD**=$(top_srcdir)/src/ModuleA/apple/shell/**apple.o** $(top_srcdir)/src/lib/libswap.a -test_**LDFLAGS**=-D_GNU_SOURCE -DEFS+=-D_GNU_SOURCE -#__LIBS__=-lpthread - - -由于我们的test.c文件在**链接时**,需要apple.o和libswap.a文件,所以我们需要在test_LDADD中包含这两个文件。对于Linux下的信号量/读写锁文件进行编译,需要在编译选项中指明-D_GNU_SOURCE。所以在test_LDFLAGS中指明。而test_LDFLAGS只是链接时的选项,**编译时同样需要指明该选项**,所以需要__DEFS来指明编译选项__,由于DEFS**已经有初始值**,所以这里用+=的形式指明。从这里可以看出,Makefile.am中的语法与Makefile的语法一致,也可以采用条件表达式。如果你的程序还包含其他的库,除了用AC_CHECK_LIB宏来指明外,还可以用LIBS来指明。 - -如果你只想编译某一个文件,那么Makefile.am如何写呢?这个文件也很简单,写法跟可执行文件的差不多,如下例所示: - -noinst_PROGRAMS=apple -apple_SOURCES=apple.c -DEFS+=-D_GNU_SOURCE - - -我们这里只是欺骗automake,假装要生成apple文件,让它为我们**生成依赖关系和执行命令**。所以当你运行完automake命令后,然后修改apple/shell/下的**Makefile.in**文件,直接将LINK语句删除,即: - -……. -clean-noinstPROGRAMS: - -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) -apple$(EXEEXT): $(apple_OBJECTS) $(apple_DEPENDENCIES) - @rm -f apple$(EXEEXT) -#$(LINK) $(apple_LDFLAGS) $(apple_OBJECTS) $(apple_LDADD) $(LIBS) -……. - - -通过上述处理,就可以达到我们的目的。从图1中不难看出为什么要修改Makefile.in的原因,而不是修改其他的文件。 diff --git a/Zim/Utils/autoconf---automake/1.jpg b/Zim/Utils/autoconf---automake/1.jpg deleted file mode 100644 index 1f929e014eb4bbc7ae81c1dc8107f12e7d215029..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6616 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 diff --git a/Zim/Utils/autoconf---automake/2.gif b/Zim/Utils/autoconf---automake/2.gif deleted file mode 100644 index ed1093fcf976dc19d8761b6fd5be820c837476d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8009 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 diff --git a/Zim/Utils/autoconf---automake/3.gif b/Zim/Utils/autoconf---automake/3.gif deleted file mode 100644 index 7fdd39b94facedd038f5791cba85b1947242b920..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3876 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 Vt=D_a*Px8We+}4yJ$D5F06Rc;i5dU^ diff --git a/Zim/Utils/autoconf---automake/5.gif b/Zim/Utils/autoconf---automake/5.gif deleted file mode 100644 index 429e05b7c82e92600dd42f76e341c86adc43752a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4686 zcmV-U60z+^Nk%w1VG9D?0FeLy00030|Nq(9*#H0lA^8LZ6afDKEC2ui01E=$00092 zjE||y?GK}zwAzca-n{z{hT=$;=82~2%C_zc$MQ_q_KoNIP6GZ93<`(DqVb4KDwoWr z^9hYgr_`$Tip^@b&;>vM4vWX+viXcotJmzd`wfq)zw)~Mj?e4&{J#G$2H*uqSZH_% zNQbz{*y#8O*(a!=7-@Nl`Bs_9+3EQS8aNnAT6(x?nyR|Wnl_n$+A2F+7E61Jo4fdm zV5|E}>I*zfTs${w?B-jP%qHB-`Ycc>4IRpRP+go9_T>|3?HZnIOWi##i*2CYtQhM~ z$8Ic-&goqXK3(6c9zZ{Q4@|&mNcQD3sLCC_G5-)c>euksz<3UoRV?)l9>b0Q7cn9; zNKxQ9fkZk+?3l=0H!WyYKfit&^!NM!?||Qb0uI>2 zas(b|0d&|X2*D)0sPiBNygBGYHbz_!;RElLw;+Q28R%h%8mb2ii5gb;3WO#00>p~z zRQTeElpv9fi!S1~orCL$7(;&+3IgMgLIN4&izyPpVh}^}SRjZyI;o^Tz4+5&jZ{XN zqKzHGLgSQACW&H|EK14c5nt-aqzgV;Nv4-=!q^|0U$#l+k!gy+pqEFsm}LVC^2z3& zLd;3$lV~1#;hAp+S}2>2zB%ZfDXe+smX?wahYW6mmStu@M-M6*Nu80NbAx@xMn z=z3eKxbbouC%oIf`)>y7HX5O*=0f{0k^`suu)YCiJ1vD~mKa_U35TF7#J>hSuEE^; z`>_NIcg%07(puZDyvWkIalP(Z9KpgTr>sH9kJ_py$G~bz^3FVqTQZ~c&U^F0Fw=Ue zl>WiahhnjrVI|+x$+>_Jm&lI7{f;f1Z1*)``pL>*w+D zHY1#&{){is%C7F`sc^3gD&nICy65Gx+Rm`(8|bS0d7k$U{0_Va|K0DzAOB&|$eU;U z^3Jy~{PWZ`FMaj7_HF(2*>5jH^xX46{rBQ4jQ#lFn~(nWr6#Prno8 zr;kJU`0tOj-u&C3zyAqPSOFZM`V5FbmEA9aYGR-RwX?tns-S=p{GRtJcmfJyFnbr= zV3U-mvw*oyW(q8wky00_3XJf6915KUBj~{oCQW&lV^!|PCZ<{iZbLOpl-fdhCWZh>QpwIBGa_=Iyi2zZls#n z+}KqqFQP7TO%vZ9Y1lA-kqeOHQ;@Ol<}M0tQEHKTRv8Z`tzSiLWOiy74?CAdOZF{m zt`wmV_lL$+)e>HR{2~ciB`7a$Y>}1QS0!!8$>&`%bYVMI-UOISE;=l2IwaD)9GSY2 zx$u_0jFu812P`DX@|LvJqRF25zi1AzmMLuJBo!5`nsw=q^lVW7lIgrq<$W!vupvx&|AZHmj5;{%)ZU00YG6_k$SWaz}3e{#Y=>|${4O64s zV6n<2E|DG68Lqp5&a#9$L~E9uQ&px?Le}ge6Kc z(WkF#DkYm$)U^?msGLLR3xg_D8D_PKFx+aoyjoGLg7vFo9bgB`+B395v#V;w02td^ zM7F|Jg>yZlTc z1T9-V$YK^{n+=|3JBv@y9__Q8Ri_y}TD0F;?r%%{W?ljL%Kj{|4@mH^bQ2 zh-;vZl`@CJtxtS2XSHnkv7?zq+aSR;&45x3qkzM%(z-b{4F{9FT4EcBSVqy;+ULPH zjOW=_cv@vHE?>H=mNl>SMm1toiOPMXiLX^jL=KI)H+EcrV+MQt>*}3Q{pHik~?(RI_X+_J{bID$4l*^YahKp>B-$VV=qk~{X~DEE)b8O!pP>*wW( zjk(NM%vZwdeCIsxxzB(9?mmBW{N}o&`C)BN^w9}Dvj_Q zhPGbt5$P^>4_q+Q!p2_1J4$Le7ufZhPcXF2d*0L**X(#7DKiQD+lO}!@Q+8L9g}Oc zj^}xOhOd621MPSJ2*-Ap(MJ~#dHi;M#(yOQWs2l%ck^uLWPhsTUqU7}6jx}A6M3Tt zM1WRGbLVzXR(~sFd9)Q$x5ItMwt0jkcC+I{-Sua}lwE_AREQLAWW#(a5@s}&Y3x^E z)VE2eW=&LPZ#f8gvd3ry!*(&4fyZQ32_s0#cT7S?XuYHz&h~ugcWWTlPzfeZCAes6 zQ#nk8H$|9(@AqyP2!x!6HTZRQ&=+J@lrjKUPo-BiO&DV;lvK6Wc|q7@kh6N@hkm%0 zT5E@RU&B{AG=$j}eb+~9N@jrA7e*Ggd=Us}d?fey3_@uGCr$L_guA19VJK24Xp0B8X?!$^yw**2 zxNPG^ZLKwogXel#S64mtRHibCXqX^0qHUV^W5hQjv-UGq#fG7%IZwy|5Ljs^5@n^x zb+31jlOlL5z>aR!XHu4s`BQ%|(2#HijS-n071>r7iIMZ+bt~7ANcfR37n1*?k!r<} zB}pD5S#v7ceIeL#De01;#*#-jlelt{XeE<3sRKD#Ry)a)`BRfn7nFD6lVfFk#i)sD z7=UU22$UT1Uimj(+(>WNNQT6SgC}BoAq12UbTNu!VW>inmljLJI8d2bQ0*V{+4oLP&KU2Yq9dXfJq$HI;V~_JkU9Zx!e`7pR5sCtt~^fc$nahk2a& zrf-?jgc~@T?dWy}rh4PMG#XsgGqWv_G8HzVGviE(H4K(Ial&%9hfM9z^QCxRGQ=&ZyflI z6SaNl22bh8eEi0R4mgcdC=uCQ8Cg_Hw`e%QJS#?^u zjIE=OW(Fov<)&&>kZzTkeo0eF!kU0MmAF`nZ3(5Kmx-YnZ-JMP6dGNC>Q#&X8LE#p zk!9MO`B{`{BC1>Esj1o{WV(^A$|I|qRjn$k4RoraWvjQ!kg$r9yy_veDpb1)tO}W{ zphc|3nnAv*lgdhR%=(kgIv~OtL&++w&jGDSIb-tqn`r52A|#m)YMKrhquI)sVX31S zrdd5oM1 zXY$EO*1CwtT3W56cm@cYIisG_32PTSOy;Mp602LS38BGBSGxv}S2>_B+LYxAvKY6m zlm|<1S*Ju=XK@Nlb;JCQo0TBbCh z_lcn$JDxiWs;EkcRrrgZr;EO~rgx-v<2r%#+Ok8(w9GiQ2?DS}Bc(&SFIM@T_NuhL zDYB#3w(ppa?v`wL8;a`qw(AG6I9ac(nseVqsBR02AgCr@xucs_llyh3i*u?AlC0}sg$s1EOS`peySH1r zpI?#!HmQJ9Tr5waklkx?8X-3zy1Sh@2^#vllyN z2cq{0mBAM=HVd!K=%3k}JkG1D)XSyJIe*^cv$>|QbLgKe7=<|hYqBUfjUc+UaVb33 zmo}HTnU)u?dwROjd#`%huCnNOapISCxtES9j^tXPwg<2g`oA&?jzQZ!Otw0!1csKV zxcAkXhdRNM>75Z&qO&NwWfyD^N|pVJzsur?y2qpis+8`*!D8B9K-lJFTZ^(*!;`AM=PR0~=ruc>hCVF8zBFPQyPFHBvorLb#95E~ z)?bB0n~wv7viPT!8pb%RXQ!BjZX|JbWl?kZMHzO0(&;nWOMeQ?Wn;=`G3+oY=!`OK z!AC`keJrrc8dQLZT1}d+1#G~1i#lbTmtM?z@MedE_qT!n++s7Vec32e0*tn2ONYDa zzJ7P0{P(^h9BAq?qYG${;3|*AsiCSjVwCvJIl;9%E=6g>b$Sx z61Nn{slFV-m3U$L^U9%Y&Xp;I&scFGIwae>gFpq0Z)BEI%gwIDxbG~0o64Wa7HMet zwO@>HhnGjzvY)t$zQ{Vl`*_6hShuoLzwyh0h>55I_Ne=I(G1#bRg1wQ-M3VXpXm#| zm3*}{UDI8syrh}aI=#^o+tcGwx)nspK`qReYt+#nD7~4R)Wx&HxC_-$E!9&^)xXiy QSB=$Kt<_tNE(HJpJEEXTHNk%w1VG06p0FeLy00030|Nq(9*#H0lA^8LZ6afDKEC2ui015(d00092 zjE||y?GK}zwAzca-n{z{hT=$;=82~2%C_zc#}Gi*_KoNI&iDQg3<`(DqVb4KDwoWr z^9hX_6##+tip^@b+^+Wv4vWX+viS_IqSx%U`wfrF=kz)jK(*`l{Jvf77brMLSZFwh zmjHOk*yvcc_$WC^S!sEfcd5DA7s>ev8Y=pgh~PPjn!0tW+UoimSbD$;TdPTHo2$E< zmT7xqMO%f_C9K0MfQvk;oP4+JDr?Xz3aAEr<+=EioxF`q4b92=9W1UY9S{y`?QGti zB@7>*eGPsd?M@HBjxU+sZ(KcR<(_HNH>_TdT>HRurx_}A;+UA;D=_Da$QVFu*b1!>lVAqf66R1Hb7}VfecoNp@9)*$YF;bLU`eaBFeDgh$f!sAb=>Ys6vS> zz6j%eD#l3T2QJP)gE}{uq5}gxPO}4#IS4sq1wG8d1CTq;f@F~DG>Jo#I@$nYjStMY zz>QXJ8R3yrG7081VurcolOdXd=9xZPAWNHT=0|3lW9n#Tol1sTrw>~$$Y+*0%1Pp! zcTHr(qAIMmW+Dsbj?&Uf?w-bqN$Q>IK6$FHoBjzblHa1cX|oo zyON8jp3e6AtCOrIJ1D!m-l(a)2_KrSum08=?w1lTI;_PBJIv;)?iPG%#0=J3ZNBC5 zI&G^aml$!T>;{`-tixW*rK9pznr^)(GioWyI&aMJq#pZ;GLf^A{HV81#(DCx1Uq`P z%1qB3FP$Re+_RPE9*gzGKm#dtu&~-3^sR6%$aA0Irj0by+p38%Kn#1^r_+iWtTWGP zTY7cPb<+o~+j+xTGO0gPT(;R)ZW}O_vLdTu+eM!X>C1}$F#Po2+=lJ*%bqq~_1+F| z4LR0~*&+_Pb!u-t+4)ZmqGaQqsFD zyzN$PHORihzPP?h<1TKelZX52(h^(Dd&K}AtbNy~Tb?uSqLz((`9sHGJoR7S>izKG z58CegFt6M6nSJ*Uy?%XBUZgCy1Z?Qun|Jnrnd+gdVX#;J^rGP=Xv3 zQTsZ`q78y@gcbTA2~8xz6RJ=_CS0M1Qs}}M2B?KH#1IT?h(j4sFozVnArF7(0=da& zh(s)+5s!$(Br0)-mNXZiCYzKpfI75Z^s ziNY7{tX03! zYbMkLrcGk$l9y;i7)!~Q%*%nZkob#JydVZjjH-@g84I8sL%7P31=XWQV_w!GrAkbq zOMx?GmMEv0I)Gv;sr6J_=9DT=U3t@R!OUsfxC+WQHVdX6vn8}R$yFhy({q+%+}jY@ zr9FmHX(X+fIT3c!g>i1BL=9x%zBf2d1y*u{%_==F#ZP=1w5#8$s`fq?Rd&YHrjZpa zRB08r@+6X&W(6Hb`_?{Y3eKccvuk0)y2a5UwyZ-X8#8BGJg>SHZj*gnTZsx-O#%+H z;p=Ed-4|1=VpgKJWh?6{yVHwicDaWCw{ zbprRQq(xrnc(gp7;u5`7n`pokme`*Hb+#^w)LRv&IqEhtfV_&UG@F~(Xf-W&hg9j^ zz^l9AJ~yXhYuPgaOy0}tkc2D!5q~vyNttR(boVr@AFb6~mZJAgBF3+x_-DMm!4_Hx z7Mn9u>s0^9cfOLWF$Uf^H&-FFfwHu*kMAnpADc?ZM26>#i~M3FD>=VQw$G89{6n!q z8G}<^vXrabfhS{GhF9Kl7`;s7E`vGAW45uF%gj(T+wsh5Zf%>*$mTaoSI%dQGo5jJ zXE541&x35}NB6s8#i}xwY4)H0ocGMXv&uJ{T~;jOauYc&S!( zF@qr;&~b??z8Mtm-_+6>lT0wEaLm-K{#b zu9Q?BAJLraJF`02MDuCf{#e{Rg|}1fCH2Edi|N!R8lK-|bf~dg+m|l-XVtXeYSGru zCMTQDuhU!fWc^Kl@|LdxR3uyfy1q?vw94x~^g$ihy3&FB&o#yOu?NjHPDgsUZ|--) zeaSLW+f~w1J6uSQ+G22fS6^Fpc&ee>Y~y-vNZqwx{PUOxE%fJ+9{Z;t#SG z)n~y+$<2BbJK7QbH7p-otYnxYdsVN7FU!Au>vH9+!(DS7P8t63#csQ$Q~#pS%k1*1 zbL{G4&brp^#r14|or__|_1MX-?X#y_?J6vL$Jt&*wK8$;bg#SJ?~eDp#|Q3w@4Mgs J9>W3v06QB~?a%-K diff --git a/Zim/Utils/autoconf---automake/代码.txt b/Zim/Utils/autoconf---automake/代码.txt deleted file mode 100644 index 30f95e3..0000000 --- a/Zim/Utils/autoconf---automake/代码.txt +++ /dev/null @@ -1,38 +0,0 @@ -Content-Type: text/x-zim-wiki -Wiki-Format: zim 0.4 -Creation-Date: 2011-12-22T22:26:12+08:00 - -====== 代码 ====== -Created Thursday 22 December 2011 - -=== Autoconf === - - -Autoconf (2.59): -ftp://ftp.gnu.org/gnu/autoconf/ - -===== Autoconf的内容 ===== - -Autoconf 能生成用于自动配置源代码的 shell 脚本(**configure**),该脚本可以生成makefile文件。 - -安装下列程序: autoconf, autoheader, autom4te, autoreconf, autoscan, autoupdate 和 ifnames - -===== 简短说明 ===== - -autoconf是一个产生可以自动配置源代码包,生成shell脚本的工具,以适应各种类UNIX系统的需要。autoconf 产生的配置脚本在运行时独立于autoconf ,因此使用这些脚本的用户不需要安装autoconf。 - -autoheader能够产生供configure脚本使用的C #define语句模板文件。 - -autom4te对文件执行 GNU M4。 - -autoreconf,如果有多个autoconf产生的配置文件,autoreconf可以保存一些工作,它通过重复运行autoconf(以及在合适的地方运行autoheader)以重新产生autoconf配置脚本和配置头模板,这些文件保存在以当前目录为根的目录树中。 - -autoscan程序可以用来为软件包创建configure.in文件。autoscan在以命令行参数中指定的目录为根(如果未给定参数,则以当前目录为根)的目录树中检查源文件。它为通常的轻便问题搜索源文件,并且为那个包创建一个configure.scan文件,这个文件就是configure.in的前身。 - -autoupdate程序将一个调用autoconf 宏的旧名称的configure.in文件中的宏更新为新的名称。 - -ifnames当为一个软件包写configure.in 时,ifnames可以提供一些帮助。它打印包中那些在C预处理器中已经使用了的表示符。如果一个包已经设置成具有某些可移植属性,这个程序能够帮助指出它的配置应该如何检查。它可以用来填补由autoscan产生的configure.in中的隔阂。 - -Autoconf 安装依赖关系 - -Autoconf 依赖于: Bash, Coreutils, Diffutils, Grep, M4, Make, Perl, Sed. diff --git a/Zim/Utils/gcc&g++.txt b/Zim/Utils/gcc&g++.txt deleted file mode 100644 index effc0cb..0000000 --- a/Zim/Utils/gcc&g++.txt +++ /dev/null @@ -1,7 +0,0 @@ -Content-Type: text/x-zim-wiki -Wiki-Format: zim 0.4 -Creation-Date: 2011-11-11T17:37:05+08:00 - -====== gcc&g++ ====== -Created Friday 11 November 2011 - diff --git a/Zim/Utils/gcc&g++/C++编译初步.txt b/Zim/Utils/gcc&g++/C++编译初步.txt deleted file mode 100644 index 9d82c06..0000000 --- a/Zim/Utils/gcc&g++/C++编译初步.txt +++ /dev/null @@ -1,219 +0,0 @@ -Content-Type: text/x-zim-wiki -Wiki-Format: zim 0.4 -Creation-Date: 2011-11-11T17:37:12+08:00 - -====== C++编译初步 ====== -Created Friday 11 November 2011 - -===== C++ 编程中相关文件后缀 ===== -.a 静态库 (archive) - -.C -.c -.cc -.cp -.cpp -.cxx -.c++ C++源代码(需要编译预处理) - -.h C或者C++源代码头文件 -.ii C++源代码(不需编译预处理) -.o 对象文件 -.s 汇编语言代码 -.so 动态库 - 标准C++系统头文件 - -===== 单个源文件生成可执行程序 ===== - -下面是一个保存在文件 helloworld.cpp 中一个简单的 C++ 程序的代码: - -/* helloworld.cpp */ -#include -int main(int argc,char *argv[]) -{ - std::cout << "hello, world" << std::endl; - return(0); -} - -程序使用定义在头文件 iostream 中的 cout,向标准输出写入一个简单的字符串。该代码可用以下命令编译为可执行文件: - -$ g++ helloworld.cpp - -编译器 g++ 通过检查命令行中指定的文件的后缀名可识别其为 C++ 源代码文件。编译器默认的动作:编译源代码文件生成对象文件(object file),__链接__对象文件和 libstdc++ 库中的函数得到可执行程序。然后删除对象文件。由于命令行中未指定可执行程序的文件名,编译器采用默认的** a.out**。程序可以这样来运行: - -$ ./a.out -hello, world - -更普遍的做法是通过 -o 选项指定可执行程序的文件名。下面的命令将产生名为 helloworld 的可执行文件: - -$ g++ helloworld.cpp -o helloworld - -在命令行中输入程序名可使之运行: - -$ ./helloworld -hello, world - -程序 g++ 是将 gcc 默认语言设为 C++ 的一个特殊的版本,链接时它自动使用** C++ 标准库**而不用 C 标准库。通过遵循源码的命名规范并指定对应库的名字,用 gcc 来编译链接 C++ 程序是可行的,如下例所示: - -$ gcc helloworld.cpp __-lstdc++__ -o helloworld - -选项 -l (ell) 通过添加前缀 lib 和后缀 .a 将跟随它的名字变换为库的名字 libstdc++.a。而后它在标准库路径中查找该库。gcc 的编译过程和输出文件与 g++ 是完全相同的。 - -在大多数系统中,GCC 安装时会安装一名为 c++ 的程序。如果被安装,它和 g++ 是等同,如下例所示,用法也一致: - -$ c++ helloworld.cpp -o helloworld - -===== 多个源文件生成可执行程序 ===== - -如果多于一个的源码文件在 g++ 命令中指定,它们都将被编译并被链接成一个__单一__的可执行文件。下面是一个名为 speak.h 的头文件;它包含一个仅含有一个函数的类的定义: - -/* speak.h */ -#include -class Speak -{ - public: - void sayHello(const char *); -}; - -下面列出的是文件 speak.cpp 的内容:包含 sayHello() 函数的函数体: - -/* speak.cpp */ -#include "speak.h" -void Speak::sayHello(const char *str) -{ - std::cout << "Hello " << str << "\n"; -} - -文件 hellospeak.cpp 内是一个使用 Speak 类的程序: - -/* hellospeak.cpp */ -#include "speak.h" -int main(int argc,char *argv[]) -{ - Speak speak; - speak.sayHello("world"); - return(0); -} - -下面这条命令将上述两个源码文件编译链接成一个单一的可执行程序: - -$ g++ hellospeak.cpp speak.cpp -o hellospeak - -PS:这里说一下为什么在命令中没有提到“speak.h“该文件(原因是:在“speak.cpp“中包含有”#include"speak.h"“这句代码,它的意思是搜索系统头文件目录之前将先在当前目录中搜索文件“speak.h“。而”speak.h“正在该目录中,不用再在命令中指定了)。 - -===== 源文件生成对象文件 ===== - -选项 -c 用来告诉编译器__编译__源代码但不要执行链接,输出结果为__对象文件__。文件默认名与源码文件名相同,只是将其后缀变为 .o。例如,下面的命令将编译源码文件 hellospeak.cpp 并生成对象文件 hellospeak.o: - -$ g++ -c hellospeak.cpp - -命令 g++ 也能识别 .o 文件并将其作为输入文件传递给链接器。下列命令将编译源码文件为对象文件并将其链接成单一的可执行程序: - -$ g++ -c hellospeak.cpp -$ g++ -c speak.cpp -$ g++ hellospeak.o speak.o -o hellospeak - -选项 -o 不仅仅能用来命名可执行文件。它也用来命名编译器输出的其他文件。例如:除了中间的对象文件有不同的名字外,下列命令生将生成和上面完全相同的可执行文件: - -$ g++ -c hellospeak.cpp -o hspk1.o -$ g++ -c speak.cpp -o hspk2.o -$ g++ hspk1.o hspk2.o -o hellospeak - -===== 编译预处理 ===== - -选项 __-E__ 使 g++ 将源代码用**编译预处理器**处理后不再执行其他动作。下面的命令预处理源码文件 helloworld.cpp 并将结果显示在__标准输出__中: - -$ g++ -E helloworld.cpp - -本文前面所列出的 helloworld.cpp 的源代码,仅仅有六行,而且该程序除了显示一行文字外什么都不做,但是,预处理后的版本将超过 **1200 **行。这主要是因为头文件 iostream 被包含进来,而且它又包含了其他的头文件,除此之外,还有若干个处理输入和输出的类的定义。 - -预处理过的文件的 GCC 后缀为__ .ii__,它可以通过 -o 选项来生成,例如: - -$ gcc -E helloworld.cpp -o helloworld.ii - -===== 生成汇编代码 ===== - -选项 __-S __指示编译器将程序编译成**汇编语言**,输出汇编语言代码而後结束。下面的命令将由 C++ 源码文件生成汇编语言文件 helloworld.s: - -$ g++ -S helloworld.cpp - -生成的汇编语言依赖于编译器的目标平台。 - -===== 创建静态库 ===== - -静态库是编译器生成的一系列**对象文件的集合**。链接一个程序时用库中的对象文件还是目录中的对象文件都是一样的。库中的成员包括普通函数,类定义,类的对象实例、全局变量、静态变量等等。静态库的另一个名字叫__归档文件__(archive),管理这种归档文件的工具叫 ar 。 - -在下面的例子中,我们先创建两个对象模块,然后用其生成静态库。 - -头文件 say.h 包含函数 sayHello() 的原型和类 Say 的定义: - -/* say.h */ -#include -void sayhello(void); -class Say { - private: - char *string; - public: - Say(char *str) - { - string = str; - } - void sayThis(const char *str) - { - std::cout << str << " from a static library\n"; - } - void sayString(void); -}; - -下面是文件 say.cpp 是我们要加入到静态库中的两个对象文件之一的源码。它包含 Say 类中 sayString() 函数的定义体;类 Say 的一个**实例** librarysay 的声明也包含在内: - -/* say.cpp */ -#include "say.h" -void Say::sayString() -{ - std::cout << string << "\n"; -} - -Say __librarysay__("Library instance of Say"); - -源码文件 sayhello.cpp 是我们要加入到静态库中的第二个对象文件的源码。它包含函数 sayhello() 的定义: - -/* sayhello.cpp */ -#include "say.h" -void sayhello() -{ - std::cout << "hello from a static library\n"; -} - -下面的命令序列将源码文件编译成对象文件,命令 ar 将其存进库中: - -$ g++ -c sayhello.cpp -$ g++ -c say.cpp -$ **ar -r libsay.a sayhello.o say.o** - -程序 ar 配合参数 -r 创建一个新库 libsay.a 并将命令行中列出的对象文件插入。采用这种方法,如果库不存在的话,参数 -r 将创建一个新的库,而如果库存在的话,将用新的模块**替换**原来的模块。 -下面是主程序 saymain.cpp,它调用库 libsay.a 中的代码: - -/* saymain.cpp */ -#include "say.h" -int main(int argc,char *argv[]) -{ - __ extern__ Say librarysay; - Say localsay = Say("Local instance of Say"); - sayhello(); - librarysay.sayThis("howdy"); - librarysay.sayString(); - localsay.sayString(); - return(0); -} - -该程序可以下面的命令来编译和链接: - -$ g++ saymain.cpp **libsay.a** -o saymain - -程序运行时,产生以下输出: - -hello from a static library -howdy from a static library -Library instance of Say -Local instance of Say diff --git a/Zim/Utils/gcc&g++/C编译初步.txt b/Zim/Utils/gcc&g++/C编译初步.txt deleted file mode 100644 index b77394a..0000000 --- a/Zim/Utils/gcc&g++/C编译初步.txt +++ /dev/null @@ -1,220 +0,0 @@ -Content-Type: text/x-zim-wiki -Wiki-Format: zim 0.4 -Creation-Date: 2011-11-11T18:00:47+08:00 - -====== C编译初步 ====== -Created Friday 11 November 2011 -http://wiki.ubuntu.org.cn/Compiling_C - -===== C 编程中相关文件后缀 ===== -.a 静态库 (archive) -.c C源代码(需要编译预处理) -.h C源代码头文件 -__.i __ C源代码(不需编译预处理) -.o 对象文件 -.s 汇编语言代码 -.so 动态库 - -===== 单个源文件生成可执行程序 ===== - -下面是一个简单的“hello, ubuntu”程序的源代码: - -/* helloubuntu.c */ -#include -int main(int argc,char *argv[]) -{ - printf("hello, ubuntu\n"); - - return 0; -} - -最简单直接的编译该代码为可执行程序的方法是,将该代码保存为文件 helloubuntu.c,并执行以下命令: - -$ gcc** -Wall **helloubuntu.c - - -编译器通过检查命令行中指定的文件的后缀名可识别其为 C 源代码文件。GCC 默认的动作:编译源代码文件生成对象文件(object file),链接对象文件得到可执行程序,删除对象文件。由于命令行中未指定可执行程序的文件名,编译器采用默认的 a.out。在命令行中输入程序名可使其执行并显示结果: - -$ ./a.out -hello, ubuntu - -选项 -o 用来指定所生成的可执行程序的文件名。下面的命令生成名为 helloubuntu 的可执行程序: - -$ gcc -Wall helloubuntu.c -o helloubuntu - -在命令行中输入程序名将使其执行,如下: - -$ ./helloubuntu -hello, ubuntu - -注意如果有用到math.h库等非gcc默认调用的标准C库,请使用__ -lm__参数 - -===== 源文件生成对象文件 ===== - -选项 -c 指示 GCC 编译源代码文件,但将对象文件保留在磁盘中并跳过链接对象文件生成可执行文件这一步。在这种情况下,默认的输出文件的文件名同源代码文件名一致,只不过後缀换为 .o 。例如:下面的命令将生成名为 helloubuntu.o 的对象文件: - -$ gcc -c -Wall helloubuntu.c - -选项 -o 可用来指定生成的对象文件的文件名。以下命令将产生名为kubuntu.o的对象文件: - -$ gcc -c -Wall helloubuntu.c -o kubuntu.o - -当构建对象库或者生成一系列对象文件以备稍後链接用时,一条命令即可从多个源码文件生成对应的对象文件。下面的命令将__分别生成__对象文件ubuntu.o, kubuntu.o 与 xubuntu.o: - -$ gcc -c -Wall ubuntu.c kubuntu.c xubuntu.c - -===== 多个源文件生成可执行程序 ===== -即使多个源码文件被编译,GCC编译器也会__自动进行链接__操作。例如:下面的代码保存在名为 hellomain.c 的文件中并调用一个名为 sayhello()的函数: - -/* hellomain.c */ -void sayhello(void); -int main(int argc,char *argv[]) -{ - sayhello(); - return 0; -} - -以下代码保存在名为 sayhello.c 的文件中并定义了 sayhello() 函数: - -/* sayhello.c */ -#include -void sayhello() -{ - printf("hello, ubuntu\n");/*这里有个小错误,是中文输入法造成的引号使gcc报错*/ -} - -下面的命令将两个文件分别编译为对象文件且将其链接为可执行程序 hello,并__自动删除__对象文件: - -$ gcc -Wall hellomain.c sayhello.c -o hello - -===== 编译预处理 ===== - -选项 **-E **指示编译器只进行编译预处理。下面的命令将预处理源码文件 helloubuntu.c 并将结果在**标准输出**中列出: - -$ gcc -E helloubuntu.c - -选项 -o 用来将预处理过的代码**重定向**到一个文件。像本文一开始给出的後缀列表所给出的,不需经过预处理的C源码文件保存为後缀为 __.i__的文件中,这种文件可以这样来获得: - -$ gcc -E helloubuntu.c -o helloubuntu.i - -===== 生成汇编代码 ===== - -选项 **-S **指示编译器生成汇编语言代码然後结束。下面的命令将由 C 源码文件 helloubuntu.c 生成汇编语言文件 helloubuntu.s: - -$ gcc -S helloubuntu.c - -汇编语言的形式依赖于编译器的目标平台。如果多个源码文件被编译,每个文件将分别产生对应的汇编代码模块。 - -===== 创建静态库 ===== - -静态库是编译器生成的普通的 .o 文件的集合。链接一个程序时用库中的对象文件还是目录中的对象文件都是一样的。静态库的另一个名字叫归档文件(archive),管理这种归档文件的工具叫 ar 。 - -要构建一个库,首先要编译出库中需要的**对象模块**。例如,下面的两个源码文件为 hellofirst.c 和 hellosecond.c: - -/* hellofirst.c */ -#include -void hellofirst() -{ - printf(“The first hello\n”); -} - -/* hellosecond.c */ -#include -void hellosecond() -{ - printf(“The second hello\n”); -} - -这两个源码文件可以用以下命令编译成对象文件: - -$ gcc -c -Wall hellofirst.c hellosecond.c - -程序 ar 配合参数 -r 可以创建一个新库并将对象文件插入。如果库不存在的话,参数 -r 将创建一个新的,并将对象模块添加(如有必要,通过替换)到归档文件中。下面的命令将创建一个包含本例中两个对象模块的名为 libhello.a 的静态库: - -$ ar -r libhello.a hellofirst.o hellosecond.o - -现在库已经构建完成可以使用了。下面的程序 twohellos.c 将调用该库中的这两个函数: - -/* twohellos.c */ -void hellofirst(void); -void hellosecond(void); -int main(int argc,char *argv[]) -{ - hellofirst(); - hellosecond(); - return 0; -} - -程序 twohellos 可以通过在命令行中指定库用一条命令来编译和链接,命令如下: - -$ gcc -Wall twohellos.c **libhello.a** -o twohellos - -静态库的__命名惯例__是名字以三个字母 lib 开头并以後缀 .a 结束。所有的系统库都采用这种命名惯例,并且它允许通过__ -l(ell)__ 选项来简写命令行中的库名。下面的命令与先前命令的区别仅在于 gcc 期望的找寻该库的位置不同: - -$ gcc -Wall twohellos.c -lhello -o twohellos - -指定完整的路径名可使编译器在给定的目录中寻找库。库名可以指定为绝对路径(比如 /usr/worklibs/libhello.a)或者相对与当前目录的路径(比如 ./lib/libhello.a)。选项 -l 不能具有指定路径的能力,但是它要求编译器在__系统库目录__下找寻该库。 - -===== 创建共享库 ===== - -共享库是编译器以一种特殊的方式生成的对象文件的集合。对象文件模块中所有地址(变量引用或函数调用)都是__相对__而不是绝对的,这使得共享模块可以在程序的**运行过程中**被动态地调用和执行。 -要构建一个共享库,首先要编译出库中需要的对象模块。例如:下面是文件名为 shellofirst.c 和 shellosecond.c 的两个源码文件: - -/* shellofirst.c */ -#include -void shellofirst() -{ - printf(“The first hello from a shared library\n”); -} -/* shellosecond.c */ -#include -void shellosecond() -{ - printf(“The second hello from a shared library\n”); -} - -要将以上两个源码文件编译成对象文件,可以用下面的命令: - -$ gcc -c -Wall __-fpic __shellofirst.c shellosecond.c #这只是编译出共享库中的模块对象文件 - -选项 -c 告诉编译器只生成 .o 的对象文件。选项 -fpic 使生成的对象模块采用**浮动的(可重定位的)地址**。缩微词 pic 代表“__位置无关代码__”(position independent code)。 - -下面的 gcc 命令将对象文件构建成一个名为 hello.so 的共享库: - -$ gcc -Wall __-shared__ shellofirst.o shellosecond.o -o hello.__so __ - -选项 -o 用来为输出文件命名,而文件後缀名 .so 告诉编译器将对象文件链接成一个共享库。通常情况下,链接器定位并使用 main() 函数作为程序的__入口__,但是本例中输出模块中没有这种入口点(同时也没有指定-c参数),为抑制错误选项 -shared 是必须的。 - -编译器能将後缀为 .c 的文件识别为 C 语言源代码文件,并知道如何将其编译成为对象文件。基于这一点,先前的两条命令我们可以合并为一条;下面的命令直接将模块编译并存储为共享库: - -$ gcc -Wall __-fpic -shared__ shellofirst.c shellosecond.c -o hello.so - -下面的程序,存储在文件 stwohellos.c 内,是调用共享库中两个函数的主程序: - -/* stwohellos.c */ -void shellofirst(void); -void shellosecond(void); -int main(int argc,char *argv[]) -{ - shellofirst(); - shellosecond(); - return 0; -} - -该程序可以用下面的命令编译并链接共享库: - -$ gcc -Wall stwohellos.c **hello.so** -o stwohellos - -程序 stwohello 已经完成,但要运行它必须让其能定位到共享库 hello.so,因为库中的函数要在程序运行时被加载。需要注意的是,当前工作目录可能不在__共享库的查找路径__中,因此需要使用如下的命令行设定环境变量__LD_LIBRARY_PATH__: - - $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./ - -===== 超越命名惯例 ===== - -如果环境要求你使用 .c 以外的後缀名来命名你的 C 源码文件,你可以通过 -x 选项来指定其对应的语言以忽略我们的命名规范。例如,下面的命令将从文件 helloworrld.jxj 编译 C 语言源代码并生成可执行文件 helloubuntu: - -$ gcc -xc helloubuntu.jxj -o helloubuntu - -通常,在没有 -x 选项的情况下,任何具有未知後缀名的源码文件名都被认为是__连接器可以识别__的选项,并在不做任何更改的情况下传递给链接器。选项 -x 对其後的所有未知後缀的文件都起作用。例如,下面的命令使 gcc 将 align.zzz 和 types.xxx 都作为 C 源码文件来处理: - -$ gcc -c -xc align.zzz types.xxx diff --git a/Zim/Utils/gcc&g++/Installing---GCC--Configuration.txt b/Zim/Utils/gcc&g++/Installing---GCC--Configuration.txt deleted file mode 100644 index 7d18654..0000000 --- a/Zim/Utils/gcc&g++/Installing---GCC--Configuration.txt +++ /dev/null @@ -1,659 +0,0 @@ -Content-Type: text/x-zim-wiki -Wiki-Format: zim 0.4 -Creation-Date: 2011-12-20T10:35:59+08:00 - -====== Installing---GCC--Configuration ====== -Created Tuesday 20 December 2011 -http://gcc.gnu.org/install/configure.html - -Like most GNU software, GCC must be **configured before it can be built**. This document describes the recommended configuration procedure for both native and cross targets.这里的native是原生目标,也就是说编译后生成的二进制文件运行的主机环境和编译的主机一样;cross是交叉编译目标,编译后生成的二进制文件的运行环境和编译主机不一样,如编译主机是i686-gun-linux环境,而目标文件的运行环境是powerpc-gun-linux。配置时,如果--build == --host则是native target, 否则是cross target。 - -We use** srcdir** to refer to the toplevel source directory for GCC; we use **objdir** to refer to the toplevel build/object directory. - -If you obtained the sources via SVN, srcdir must refer to the top gcc directory, the one where the MAINTAINERS file can be found, and not its gcc subdirectory, otherwise the build will fail. - -If either srcdir or objdir is located on an automounted NFS file system, the shell's built-in** pwd** command will return temporary pathnames. Using these can lead to various sorts of build problems. To avoid this issue, set the PWDCMD environment variable to an automounter-aware pwd command, e.g., pawd or `amq -w', during the configuration and build phases. - -First, we highly recommend that GCC be __built into a separate directory__ from the sources which does not reside within the source tree. This is how we generally build GCC; building where srcdir == objdir should still work, but doesn't get extensive testing; building where objdir is a// subdirectory// of srcdir is unsupported. - -If you have previously built GCC in the same directory for a **different target** machine, do `__make distclean__' to delete all files that might be invalid. One of the files this deletes is //Makefile//; if `make distclean' complains that Makefile does not exist or issues a message like “don't know how to make distclean” it probably means that the directory is already suitably clean. However, with the recommended method of building in a separate objdir, you should** simply use a different objdir** for each target. - -Second, when configuring a native system, either **cc or gcc** must be in your path or you must set **CC** in your environment before running configure. Otherwise the configuration scripts may fail. -如果是cross target,则一定要指定环境变量CC为能产生--host主机环境二进制代码的compiler,例如在编译运行于powerpc-gun-linux上的glibc时,CC=/path/to/powerpc-gnu-linux-gcc。 - -To configure GCC: - - % mkdir objdir - % cd objdir - % srcdir/configure [options] [target] - -===== Distributor options ===== - -If you will be **distributing binary versions** of GCC, with modifications to the source code, you should use the options described in this section to make clear that your version contains modifications. - -**--with-pkgversion=version** - Specify a string that identifies your package. You may wish to include a build number or build date. This version string will be included in the output of// gcc --version//. This** suffix** does not replace the default version string, only the `GCC' part. - - The default value is `GCC'. -**--with-bugurl=url** - Specify the URL that users should visit if they wish to report a bug. You are of course welcome to forward bugs reported to you to the FSF, if you determine that they are not bugs in your modifications. - - The default value refers to the FSF's GCC bug tracker. - -===== Target specification ===== - - GCC has code to correctly determine the correct value for target for nearly all **native** systems. Therefore, we highly recommend you __do not provide a configure target when configuring a native compiler__. - target must be specified as **--target=target** when configuring a __cross compiler__; examples of valid targets would be m68k-elf, sh-elf, etc. - Specifying just target instead of --target=target implies that the host defaults to target. - -===== Options specification ===== - -Use options to override several //configure time// options for GCC. A list of supported options follows; `configure --help' may list other options, but those not listed below may not work and should not normally be used. - -Note that each --enable option has a corresponding --disable option and that each --with option has a corresponding --without option. - -__--prefix__**=dirname** - Specify the__ toplevel installation__// directory.// This is the recommended way to install the tools into a directory other than the default. The toplevel installation directory defaults to **/usr/local**. - - We highly recommend against dirname being the same or a subdirectory of objdir or vice versa. If specifying a directory beneath a user's home directory tree, some shells will not expand dirname correctly if it contains the `~' metacharacter; use $HOME instead. - - The following standard **autoconf** options are supported. Normally you should **not need** to use these options. - - --__exec-prefix__=dirname - Specify the__ toplevel installation directory__ for** architecture-dependent** files. The default is **prefix**. - --bindir=dirname - Specify the installation directory for the **executables** called by users (such as gcc and g++). The default is **exec-prefix/bin**. - --libdir=dirname - Specify the installation directory for **object code libraries and internal data files **of GCC. The default is **exec-prefix/lib**. - --libexecdir=dirname - Specify the installation directory for **internal executables** of GCC. The default is **exec-prefix/libexec**. - --with-slibdir=dirname - Specify the installation directory for the **shared libgcc library**. The default is libdir. - --__datarootdir__=dirname - Specify the root of the directory tree for** read-only architecture-independent data files** referenced by GCC. The default is **prefix/share**. - --infodir=dirname - Specify the installation directory for documentation in info format. The default is datarootdir/info. - --datadir=dirname - Specify the installation directory for **some architecture-independent data files** referenced by GCC. The default is datarootdir. - --docdir=dirname - Specify the installation directory for documentation files (other than Info) for GCC. The default is **datarootdir/doc**. - --htmldir=dirname - Specify the installation directory for HTML documentation files. The default is docdir. - --pdfdir=dirname - Specify the installation directory for PDF documentation files. The default is docdir. - --mandir=dirname - Specify the installation directory for manual pages. The default is datarootdir/man. (Note that the manual pages are only extracts from the full GCC manuals, which are provided in //Texinfo //format. The manpages are derived by an automatic conversion process from parts of the full manual.) - **--with-gxx-include-dir=dirname** - Specify the installation directory for** G++ header** files. The default depends on other configuration options, and differs between cross and native configurations. - **--with-specs=specs** - Specify additional command line driver SPECS. This can be useful if you need to turn on a non-standard feature by default without modifying the compiler's source code, for instance --with-specs=%{!fcommon:%{!fno-common:-fno-common}}. See “Spec Files” in the main manual - -1.// toplevel installation directory : 程序文件的顶级安装目录,各个程序一般会在其下建立以//**程序名命名的单独目录。** -2.Installation directories: - --prefix=PREFIX install **architecture-independent** files in PREFIX [/usr/local] - --exec-prefix=EPREFIX install **architecture-dependent** files in EPREFIX [PREFIX] ---prefix指定程序被安装到的顶级目录,如果只有该选项而没有指定其它安装目录选项(如下所示),一般编译后的程序的所有文件都会放在--prefix下的目录结构中。 -3.Fine tuning of the installation directories: - --bindir=DIR **user **executables [EPREFIX/bin] #普通、管理员用户可执行的程序文件。 - --sbindir=DIR **system admin** executables [EPREFIX/sbin] #管理员可执行的程序文件 - --libdir=DIR object code libraries [EPREFIX/lib] #程序输出的库文件,库中存放的二进制对象文件可以供其它程序使用。 - --libexecdir=DIR __program__ executables [EPREFIX/libexec] #供__程序(本程序或其它)调用__的可执行文件(用户一般__不会直接__调用它们) -以上四个选项控制与体系结构相关的二进制文件的存放位置,不同类型的二进制文件是用于不同目的的。 - --sysconfdir=DIR ** read-only** single-machine data [__PREFIX/etc__] - --localstatedir=DIR **modifiable** single-machine data [PREFIX/var] -以上两个目录是程序执行时**读取配置文件,保存运行数据文件**的地方。 - --includedir=DIR C header files [PREFIX/include] -~~ --oldincludedir=DIR C header files for non-gcc [/usr/include]~~ - --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] - --datadir=DIR read-only architecture-independent data [DATAROOTDIR] - --infodir=DIR info documentation [DATAROOTDIR/info] - --localedir=DIR locale-dependent data [DATAROOTDIR/locale] - --mandir=DIR man documentation [DATAROOTDIR/man] - --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] - --htmldir=DIR html documentation [DOCDIR] - --dvidir=DIR dvi documentation [DOCDIR] - --pdfdir=DIR pdf documentation [DOCDIR] - --psdir=DIR ps documentation [DOCDIR] -以上选项是程序的体系结构无关的数据文件,程序不依赖它们运行。 -一般情况下,以上所有选项的值都被__硬编码__到生成的可执行二进制文件中,所以程序在运行时可以到相关目录找到所需的文件。如果想增强程序的可移动性(位置无关性),如将程序的安装目录移动到另一个位置后,程序还能够正常运行(如读取配置文件,存放临时数据)的话,相关选项需要使用__相对路径__。 - - - -**--program-prefix=prefix** - GCC supports some transformations of the names of its programs when installing them. This option prepends prefix to the names of programs to install in **bindir** (see above). For example, specifying //--program-prefix=//__foo-__ would result in `gcc' being installed as /usr/local/bin/foo-gcc. -**--program-suffix=suffix** - Appends suffix to the names of programs to install in bindir (see above). For example, specifying// --program-suffix=-3.1// would result in `gcc' being installed as [[/usr/local/bin/gcc-3.1.]] -注意,无论是前缀还是后缀,最好载字符串后加一个**短横线**,另外如果字符串中没有空格,可以不加引号。 -**--program-transform-name=pattern** - Applies the `sed' script pattern to be applied to the names of programs to install in bindir (see above). pattern has to consist of one or more basic// `sed' editing commands//, separated by semicolons. For example, if you want the `gcc' program name to be transformed to the installed program /usr/local/bin/myowngcc and the `g++' program name to be transformed to /usr/local/bin/gspecial++ without changing other program names, you could use the pattern **--program-transform-name='s/^gcc$/myowngcc/; s/^g++$/gspecial++/'** to achieve this effect. - All three options can be //combined and used together//, resulting in more complex conversion patterns. As a basic rule, prefix (and suffix) are prepended (appended) __before__ further transformations can happen with a special transformation script pattern. - As currently implemented, this option __only takes effect for native builds(生成的程序的运行环境和当前一致)__; cross compiler binaries' names are not transformed even when a transformation is explicitly asked for by one of these options. - For native builds, some of the installed programs are __also installed with the target alias in front of their name__, as in `i686-pc-linux-gnu-gcc'. All of the above transformations happen __before__ the target alias is prepended to the name—so, specifying --program-prefix=foo- and program-suffix=-3.1, the resulting binary would be installed as /usr/local/bin///i686-pc-linux-gnu-foo-gcc-3.1//. -以上三个选项只适合native target(build), 对于cross build(target)无效,这是由于 - - - -**--with-local-prefix=dirname** - Specify the installation directory for //local include files//. The default is /usr/local. Specify this option if you want the compiler to search directory **dirname/include** for locally installed header files instead of /usr/local/include. - - You should specify --with-local-prefix__ only if__ your site has a different convention (not /usr/local) for where to put //site-specific files//. - - The default value for__ --with-local-prefix is /usr/local regardless of the value of --prefix__. Specifying --prefix has no effect on which directory GCC searches for local header files. (指的是本机的gcc在编译这个gcc源代码时,回到local-prefix指定的目录下的include目录下寻找header文件。)This may seem counterintuitive, but actually it is logical. - - The purpose of --prefix is to specify **where to install GCC**. The local header files in /usr/local/include—if you put any in that directory—are **not part of GCC(即将编译安装的GCC)**. They are part of other programs—perhaps many others. (GCC installs **its own header files** in another directory which is based on the --prefix value.) - - Both the local-prefix include directory and the GCC-prefix include directory are part of __GCC's “system include” directories__. Although these two directories are not fixed, they need to be searched in the proper order for the correct processing of the include_next directive. The local-prefix include directory is searched before the GCC-prefix include directory. Another characteristic of system include directories is that pedantic warnings are turned off for headers in these directories. - - Some autoconf macros add **-I directory **options to the compiler command line, to ensure that directories containing installed packages' headers are searched. When directory is one of GCC's system include directories, GCC will** ignore** the option so that system directories continue to be processed in the correct order. This may result in a search order different from what was specified but the directory will still be searched. - - GCC automatically searches for ordinary libraries using __GCC_EXEC_PREFIX__. Thus, when the same installation prefix is used for both GCC and packages, GCC will automatically search for both headers and libraries. This provides a configuration that is easy to use. GCC behaves in a manner similar to that when it is installed as a system compiler in /usr. - - Sites that need to install **multiple versions** of GCC may not want to use the above simple configuration. It is possible to use the --program-prefix, --program-suffix and --program-transform-name options to install multiple versions into a single directory, but it may be simpler to use different prefixes and the --with-local-prefix option to specify the location of the site-specific files// for each version//. It will then be necessary for users to specify explicitly the location of local site libraries (e.g., with LIBRARY_PATH). - - The same value can be used for both --with-local-prefix and --prefix provided it is not /usr. This can be used to avoid the default search of /usr/local/include. - - __ Do not specify /usr as the --with-local-prefix!__ The directory you use for --with-local-prefix must not contain any of the **system's** standard header files. If it did contain them, certain programs would be miscompiled (including GNU Emacs, on certain targets), because this would override and nullify the header file corrections made by the __fixincludes script__. - - Indications are that people who use this option use it based on **mistaken ideas** of what it is for. People use it as if it specified where to install part of GCC. Perhaps they make this assumption because installing GCC creates the directory. -**--with-native-system-header-dir=dirname** - Specifies that dirname is the directory that contains native system header files, **rather than /usr/include**. This option is most useful if you are creating a compiler that should be __isolated__ from the system as much as possible. It is most commonly used with the **--with-sysroot **option and will cause GCC to search dirname inside the system root specified by that option. -**--enable-shared[=package[,...]]** - Build shared versions of libraries, if shared libraries are supported on the target platform. Unlike GCC 2.95.x and earlier, shared libraries are__ enabled by default__ on all platforms that support shared libraries. - - If a list of packages is given as an argument, build shared libraries **only for** the listed packages. For other packages, only static libraries will be built. Package names currently recognized in the **GCC tree **are `libgcc' (also known as `gcc'), `libstdc++' (not `libstdc++-v3'), `libffi', `zlib', `boehm-gc', `ada', `libada', `libjava', `libgo', and `libobjc'. Note `libiberty' does not support shared libraries at all. - - Use **--disable-shared** to build only static libraries. Note that --disable-shared does not accept a list of package names as argument, only --enable-shared does. -**--with-gnu-as** - Specify that the compiler should assume that the assembler it finds is the GNU assembler. However, this does not modify the rules to find an assembler and will result in confusion if the assembler found is not actually the GNU assembler. (Confusion may also result if the compiler finds the GNU assembler but has not been configured with --with-gnu-as.) If you have **more than one assembler** installed on your system, you may want to use this option in connection with **--with-as=pathname** or **--with-build-time-tools=pathname**. - - The following systems are the only ones where it makes a difference whether you use the GNU assembler. On any other system, --with-gnu-as has** no effect**. - - `hppa1.0-any-any' - `hppa1.1-any-any' - `sparc-sun-solaris2.any' - `sparc64-any-solaris2.any' - - -**--with-as=pathname** - Specify that the compiler(主机编译后**生成**的编译器) should use the assembler pointed to by pathname, rather than the one found by the standard rules to find an assembler, which are: - -* Unless GCC is being built with a cross compiler, check the **libexec/gcc/target/version** directory. libexec defaults to exec-prefix/libexec; exec-prefix defaults to prefix, which defaults to /usr/local unless overridden by the --prefix=pathname switch described above. target is the __target system triple__, such as `sparc-sun-solaris2.7', and version denotes the GCC version, such as 3.0. -* If the target system is the same that you are building on, check operating system specific directories (e.g. /usr/ccs/bin on Sun Solaris 2). -* Check in the PATH for a tool whose name is **prefixed by the target system triple**. -* Check in the PATH for a tool whose name is **not prefixed** by the target system triple, if the host and target system triple are the same (in other words, we use a host tool if it can be used for the target as well). - - You may want to use --with-as if no assembler is installed in the directories listed above, or if you have multiple assemblers installed and want to choose one that is not found by the above rules. -**--with-gnu-ld** - Same as --with-gnu-as but for the linker. -**--with-ld=pathname** - Same as --with-as but for the linker. --**-with-stabs** - Specify that stabs debugging information should be used instead of whatever format the host normally uses. Normally GCC uses the same debug format as the host system. - - On MIPS based systems and on Alphas, you must specify whether you want GCC to create the normal ECOFF debugging format, or to use BSD-style stabs passed through the ECOFF symbol table. The normal ECOFF debug format cannot fully handle languages other than C. BSD stabs format can handle other languages, but it only works with the GNU debugger GDB. - - Normally, GCC uses the ECOFF debugging format by default; if you prefer BSD stabs, specify --with-stabs when you configure GCC. - - No matter which default you choose when you configure GCC, the user can use the -gcoff and -gstabs+ options to specify explicitly the debug format for a particular compilation. - - --with-stabs is meaningful on the ISC system on the 386, also, if --with-gas is used. It selects use of stabs debugging information embedded in COFF output. This kind of debugging information supports C++ well; ordinary COFF debugging information does not. - - --with-stabs is also meaningful on 386 systems running SVR4. It selects use of stabs debugging information embedded in ELF output. The C++ compiler currently (2.6.0) does not support the DWARF debugging information normally used on 386 SVR4 platforms; stabs provide a workable alternative. This requires gas and gdb, as the normal SVR4 tools can not generate or interpret stabs. ---with-tls=dialect - Specify the default TLS dialect, for systems were there is a choice. For ARM targets, possible values for dialect are gnu or gnu2, which select between the original GNU dialect and the GNU TLS descriptor-based dialect. -**--disable-multilib** - Specify that **multiple target libraries** to support different target variants, calling conventions, etc. __should not__ be built. The default is to build a predefined set of them. - - Some targets provide finer-grained control over which multilibs are built (e.g., --disable-softfloat): - - arm-*-* - fpu, 26bit, underscore, interwork, biendian, nofmult. - m68*-*-* - softfloat, m68881, m68000, m68020. - mips*-*-* - single-float, biendian, softfloat. - powerpc*-*-*, rs6000*-*-* - aix64, pthread, softfloat, powercpu, powerpccpu, powerpcos, biendian, sysv, aix. - - -**--with-multilib-list=list** -**--without-multilib-list** - Specify what multilibs to build. Currently only implemented for sh*-*-* and x86-64-*-linux*. - - sh*-*-* - list is a comma separated **list of CPU** names. These must be of the form sh* or m* (in which case they match the compiler option for that processor). The list should not contain any endian options - these are handled by --with-endian. - - If list is empty, then there will be no multilibs for extra processors. The multilib for the secondary endian remains enabled. - - As a special case, if an entry in the list starts with a ! (exclamation point), then it is added to the list of excluded multilibs. Entries of this sort should be compatible with `MULTILIB_EXCLUDES' (once the leading ! has been stripped). - - If --with-multilib-list is not given, then a default set of multilibs is selected based on the value of --target. This is usually the complete set of libraries, but some targets imply a more specialized subset. - - Example 1: to configure a compiler for SH4A only, but supporting both endians, with little endian being the default: - - --with-cpu=sh4a --with-endian=little,big --with-multilib-list= - - - Example 2: to configure a compiler for both SH4A and SH4AL-DSP, but with only little endian SH4AL: - - --with-cpu=sh4a --with-endian=little,big \ - --with-multilib-list=sh4al,!mb/m4al - - - - x86-64-*-linux* - list is a comma separated list of m32, m64 and mx32 to enable 32-bit, 64-bit and x32 run-time libraries, respectively. If list is empty, then there will be no multilibs and only the default run-time library will be enabled. - - If --with-multilib-list is not given, then only 32-bit and 64-bit run-time libraries will be enabled. - - -**--with-endian=endians** - Specify what endians to use. Currently only implemented for sh*-*-*. - - endians may be one of the following: - - big - Use big endian exclusively. - little - Use little endian exclusively. - big,little - Use big endian by default. Provide a multilib for little endian. - little,big - Use little endian by default. Provide a multilib for big endian. - - -**--enable-threads** - Specify that the target supports threads. This affects the Objective-C compiler and runtime library, and **exception handling** for other languages like C++ and Java. On some systems, this is the default. - - In general, the best (and, in many cases, the only known) threading model available will be configured for use. Beware that on some systems, GCC has not been taught what threading models are generally available for the system. In this case, --enable-threads is an alias for __--enable-threads=single__. -**--disable-threads** - Specify that threading support should be disabled for the system. This is an alias for --enable-threads=single. -**--enable-threads=lib** - Specify that lib is the thread support library. This affects the Objective-C compiler and runtime library, and exception handling for other languages like C++ and Java. The possibilities for lib are: - - aix - AIX thread support. - dce - DCE thread support. - lynx - LynxOS thread support. - mipssde - MIPS SDE thread support. - no - This is an alias for `single'. - posix - Generic POSIX/Unix98 thread support. - rtems - RTEMS thread support. - single - **Disable** thread support, should work for all platforms. - tpf - TPF thread support. - vxworks - VxWorks thread support. - win32 - Microsoft Win32 API thread support. - - -**--enable-tls** - Specify that the target supports__ TLS (Thread Local Storage)__. Usually configure can correctly determine if TLS is supported. In cases where it guesses incorrectly, TLS can be explicitly enabled or disabled with --enable-tls or --disable-tls. This can happen if the assembler supports TLS but the C library does not, or if the assumptions made by the configure test are incorrect. -**--disable-tls** - Specify that the target does not support TLS. This is an alias for --enable-tls=no. ---with-cpu=cpu ---with-cpu-32=cpu ---with-cpu-64=cpu - Specify which cpu variant the compiler should generate code for by default. cpu will be used as the default value of the -mcpu= switch. This option is only supported on some targets, including ARM, i386, M68k, PowerPC, and SPARC. The --with-cpu-32 and --with-cpu-64 options specify separate default CPUs for 32-bit and 64-bit modes; these options are only supported for i386, x86-64 and PowerPC. ---with-schedule=cpu ---with-arch=cpu ---with-arch-32=cpu ---with-arch-64=cpu ---with-tune=cpu ---with-tune-32=cpu ---with-tune-64=cpu ---with-abi=abi ---with-fpu=type ---with-float=type - These configure options provide default values for the -mschedule=, -march=, -mtune=, -mabi=, and -mfpu= options and for -mhard-float or -msoft-float. As with --with-cpu, which switches will be accepted and acceptable values of the arguments depend on the target. ---with-mode=mode - Specify if the compiler should default to -marm or -mthumb. This option is only supported on ARM targets. ---with-stack-offset=num - This option sets the default for the -mstack-offset=num option, and will thus generally also control the setting of this option for libraries. This option is only supported on Epiphany targets. ---with-fpmath=isa - This options sets -mfpmath=sse by default and specifies the default ISA for floating-point arithmetics. You can select either `sse' which enables -msse2 or `avx' which enables -mavx by default. This option is only supported on i386 and x86-64 targets. ---with-divide=type - Specify how the compiler should generate code for checking for division by zero. This option is only supported on the MIPS target. The possibilities for type are: - - traps - Division by zero checks use conditional traps (this is the default on systems that support conditional traps). - breaks - Division by zero checks use the break instruction. - - ---with-llsc - On MIPS targets, make -mllsc the default when no -mno-lsc option is passed. This is the default for Linux-based targets, as the kernel will emulate them if the ISA does not provide them. ---without-llsc - On MIPS targets, make -mno-llsc the default when no -mllsc option is passed. ---with-synci - On MIPS targets, make -msynci the default when no -mno-synci option is passed. ---without-synci - On MIPS targets, make -mno-synci the default when no -msynci option is passed. This is the default. ---with-mips-plt - On MIPS targets, make use of copy relocations and PLTs. These features are extensions to the traditional SVR4-based MIPS ABIs and require support from GNU binutils and the runtime C library. ---enable-__cxa_atexit - Define if you want to use __cxa_atexit, rather than atexit, to register C++ destructors for local statics and global objects. This is essential for fully standards-compliant handling of destructors, but requires __cxa_atexit in libc. This option is currently only available on systems with GNU libc. When enabled, this will cause -fuse-cxa-atexit to be passed by default. ---enable-gnu-indirect-function - Define if you want to enable the ifunc attribute. This option is currently only available on systems with GNU libc on certain targets. ---enable-target-optspace - Specify that target libraries should be optimized for code space instead of code speed. This is the default for the m32r platform. ---with-cpp-install-dir=dirname - Specify that the user visible cpp program should be installed in prefix/dirname/cpp, in addition to bindir. ---enable-comdat - Enable COMDAT group support. This is primarily used to override the automatically detected value. ---enable-initfini-array - Force the use of sections .init_array and .fini_array (instead of .init and .fini) for constructors and destructors. Option --disable-initfini-array has the opposite effect. If neither option is specified, the configure script will try to guess whether the .init_array and .fini_array sections are supported and, if they are, use them. -**--enable-build-with-cxx** - Build GCC using a C++ compiler rather than a C compiler. This is an __experimental option__ which may become the default in a later release. ---enable-build-poststage1-with-cxx - When __bootstrapping__, build stages 2 and 3 of GCC using a C++ compiler rather than a C compiler. Stage 1 is still built with a C compiler. This is **enabled by default** and may be disabled using --disable-build-poststage1-with-cxx. ---enable-maintainer-mode - The build rules that regenerate the Autoconf and Automake output files as well as the GCC master message catalog gcc.pot are normally disabled. This is because it can only be rebuilt if the complete source tree is present. If you have changed the sources and want to rebuild the catalog, configuring with --enable-maintainer-mode will enable this. Note that you need a recent version of the gettext tools to do so. -**--disable-bootstrap** - For a native build, the default configuration is to __perform a 3-stage bootstrap of the compiler__ when `make' is invoked, __testing that GCC can compile itself correctly__. If you want to disable this process, you can configure with --disable-bootstrap. ---enable-bootstrap - In special cases, you may want to perform a 3-stage build even if the target and host triplets are different. This is possible when the host can run code compiled for the target (e.g. host is i686-linux, target is i486-linux). Starting from GCC 4.2, to do this you have to configure explicitly with --enable-bootstrap. -**--enable-generated-files-in-srcdir** - Neither the .c and .h files that are generated from Bison and flex nor the info manuals and man pages that are built from the .texi files are present in the SVN development tree. When building GCC from that development tree, or from one of our snapshots, those generated files are placed in your build directory, which allows for the source to be in a readonly directory. - - If you configure with --enable-generated-files-in-srcdir then those generated files will go into the source directory. This is mainly intended for generating release or prerelease tarballs of the GCC sources, since it is not a requirement that the users of source releases to have flex, Bison, or makeinfo. ---enable-version-specific-runtime-libs - Specify that runtime libraries should be installed in the compiler specific subdirectory (libdir/gcc) rather than the usual places. In addition, `libstdc++''s include files will be installed into libdir unless you overruled it by using --with-gxx-include-dir=dirname. Using this option is particularly useful if you intend to use several versions of GCC in parallel. This is currently supported by `libgfortran', `libjava', `libmudflap', `libstdc++', and `libobjc'. -__--enable-languages=lang1,lang2,...__ - Specify that only a particular subset of compilers and their runtime libraries should be built. For a list of valid values for langN you can issue the following command in the gcc directory of your GCC source tree: - - grep language= */config-lang.in - - - Currently, you can use any of the following: all, ada, c, c++, fortran, go, java, objc, obj-c++. Building the Ada compiler has special requirements, see below. If you do not pass this flag, or specify the option all, then all default languages available in the gcc sub-tree will be configured. Ada, Go and Objective-C++ are not default languages; the rest are. ---enable-stage1-languages=lang1,lang2,... - Specify that a particular subset of compilers and their runtime libraries should be built with the system C compiler during stage 1 of the bootstrap process, rather than only in later stages with the bootstrapped C compiler. The list of valid values is the same as for --enable-languages, and the option all will select all of the languages enabled by --enable-languages. This option is primarily useful for GCC development; for instance, when a development version of the compiler cannot bootstrap due to compiler bugs, or when one is debugging front ends other than the C front end. When this option is used, one can then build the target libraries for the specified languages with the stage-1 compiler by using make stage1-bubble all-target, or run the testsuite on the stage-1 compiler for the specified languages using make stage1-start check-gcc. -**--disable-libada** - Specify that the__ run-time libraries__ and tools used by GNAT should not be built. This can be useful for debugging, or for compatibility with previous Ada build procedures, when it was required to explicitly do a `make -C gcc gnatlib_and_tools'. ---disable-libssp - Specify that the run-time libraries for __stack smashing protection__ should not be built. ---disable-libquadmath - Specify that the GCC __quad-precision math library__ should not be built. On some systems, the library is required to be linkable when building the Fortran front end, unless --disable-libquadmath-support is used. ---disable-libquadmath-support - Specify that the Fortran front end and libgfortran do not add support for libquadmath on systems supporting it. ---disable-libgomp - Specify that the run-time libraries used by GOMP should not be built. ---with-dwarf2 - Specify that the compiler should use DWARF 2 debugging information as the default. -**--enable-targets=all** ---enable-targets=target_list - Some GCC targets, e.g. powerpc64-linux, build __bi-arch__ compilers. These are compilers that are able to generate either 64-bit or 32-bit code. Typically, the corresponding 32-bit target, e.g. powerpc-linux for powerpc64-linux, only generates 32-bit code. This option enables the 32-bit target to be a bi-arch compiler, which is useful when you want a bi-arch compiler that defaults to 32-bit, and you are building a bi-arch or multi-arch binutils in a combined tree. On mips-linux, this will build a tri-arch compiler (ABI o32/n32/64), defaulted to o32. Currently, this option only affects **sparc-linux, powerpc-linux, x86-linux, mips-linux and s390-linux**. ---enable-secureplt - This option enables -msecure-plt by default for powerpc-linux. See “RS/6000 and PowerPC Options” in the main manual ---enable-cld - This option enables -mcld by default for 32-bit x86 targets. See “i386 and x86-64 Options” in the main manual ---enable-win32-registry ---enable-win32-registry=key ---disable-win32-registry - The --enable-win32-registry option enables Microsoft Windows-hosted GCC to look up installations paths in the registry using the following key: - - HKEY_LOCAL_MACHINE\SOFTWARE\Free Software Foundation\key - - - key defaults to GCC version number, and can be overridden by the --enable-win32-registry=key option. Vendors and distributors who use custom installers are encouraged to provide a different key, perhaps one comprised of vendor name and GCC version number, to avoid conflict with existing installations. This feature is enabled by default, and can be disabled by --disable-win32-registry option. This option has no effect on the other hosts. ---nfp - Specify that the machine does not have a floating point unit. This option only applies to `m68k-sun-sunosn'. On any other system, --nfp has no effect. ---enable-werror ---disable-werror ---enable-werror=yes ---enable-werror=no - When you specify this option, it controls whether certain files in the compiler are built with -Werror in bootstrap stage2 and later. If you don't specify it, -Werror is turned on for the main development trunk. However it defaults to off for release branches and final releases. The specific files which get -Werror are controlled by the Makefiles. -**--enable-checking** ---enable-checking=list - When you specify this option, the compiler is built to perform internal consistency checks of the requested complexity. This does not change the generated code, but adds error checking within the compiler. This will slow down the compiler and may only work properly if you are building the compiler with GCC. This is `yes' by default when building from SVN or snapshots, but `release' for releases. The default for building the stage1 compiler is `yes'. More control over the checks may be had by specifying list. The categories of checks available are `yes' (most common checks `assert,misc,tree,gc,rtlflag,runtime'), `no' (no checks at all), `all' (all but `valgrind'), `release' (cheapest checks `assert,runtime') or `none' (same as `no'). Individual checks can be enabled with these flags `assert', `df', `fold', `gc', `gcac' `misc', `rtl', `rtlflag', `runtime', `tree', and `valgrind'. - - The `valgrind' check requires the external valgrind simulator, available from http://valgrind.org/. The `df', `rtl', `gcac' and `valgrind' checks are very expensive. To disable all checking, `--disable-checking' or `--enable-checking=none' must be explicitly requested. Disabling assertions will make the compiler and runtime slightly faster but increase the risk of undetected internal errors causing wrong code to be generated. ---disable-stage1-checking ---enable-stage1-checking ---enable-stage1-checking=list - If no --enable-checking option is specified the stage1 compiler will be built with `yes' checking enabled, otherwise the stage1 checking flags are the same as specified by --enable-checking. To build the stage1 compiler with different checking options use --enable-stage1-checking. The list of checking options is the same as for --enable-checking. If your system is too slow or too small to bootstrap a released compiler with checking for stage1 enabled, you can use `--disable-stage1-checking' to disable checking for the stage1 compiler. ---enable-coverage ---enable-coverage=level - With this option, the compiler is built to collect self coverage information, every time it is run. This is for internal development purposes, and only works when the compiler is being built with gcc. The level argument controls whether the compiler is built optimized or not, values are `opt' and `noopt'. For coverage analysis you want to disable optimization, for performance analysis you want to enable optimization. When coverage is enabled, the default level is without optimization. ---enable-gather-detailed-mem-stats - When this option is specified more detailed information on memory allocation is gathered. This information is printed when using -fmem-report. ---with-gc ---with-gc=choice - With this option you can specify the **garbage collector** implementation used during the compilation process. choice can be one of `page' and `zone', where `page' is the default. ---enable-nls ---disable-nls - The --enable-nls option enables__ Native Language Support (NLS)__, which lets GCC output diagnostics in languages other than American English. Native Language Support is enabled by default if not doing a canadian cross build. The --disable-nls option disables NLS. ---with-included-gettext - If NLS is enabled, the --with-included-gettext option causes the build procedure to prefer its copy of GNU gettext. ---with-catgets - If NLS is enabled, and if the host lacks gettext but has the inferior catgets interface, the GCC build procedure normally ignores catgets and instead uses GCC's copy of the GNU gettext library. The --with-catgets option causes the build procedure to use the host's catgets in this situation. ---with-libiconv-prefix=dir - Search for libiconv header files in dir/include and libiconv library files in dir/lib. ---enable-obsolete - Enable configuration for an obsoleted system. If you attempt to configure GCC for a system (build, host, or target) which has been obsoleted, and you do not specify this flag, configure will halt with an error message. - - All support for systems which have been obsoleted in one release of GCC is removed entirely in the next major release, unless someone steps forward to maintain the port. ---enable-decimal-float ---enable-decimal-float=yes ---enable-decimal-float=no ---enable-decimal-float=bid ---enable-decimal-float=dpd ---disable-decimal-float - Enable (or disable) support for the C decimal floating point extension that is in the IEEE 754-2008 standard. This is enabled by default only on PowerPC, i386, and x86_64 GNU/Linux systems. Other systems may also support it, but require the user to specifically enable it. You can optionally control which decimal floating point format is used (either `bid' or `dpd'). The `bid' (binary integer decimal) format is default on i386 and x86_64 systems, and the `dpd' (densely packed decimal) format is default on PowerPC systems. ---enable-fixed-point ---disable-fixed-point - Enable (or disable) support for C fixed-point arithmetic. This option is enabled by default for some targets (such as MIPS) which have hardware-support for fixed-point operations. On other targets, you may enable this option manually. ---with-long-double-128 - Specify if long double type should be 128-bit by default on selected GNU/Linux architectures. If using --without-long-double-128, long double will be by default 64-bit, the same as double type. When neither of these configure options are used, the default will be 128-bit long double when built against GNU C Library 2.4 and later, 64-bit long double otherwise. ---with-gmp=pathname ---with-gmp-include=pathname ---with-gmp-lib=pathname ---with-mpfr=pathname ---with-mpfr-include=pathname ---with-mpfr-lib=pathname ---with-mpc=pathname ---with-mpc-include=pathname ---with-mpc-lib=pathname - If you do not have GMP (the GNU Multiple Precision library), the MPFR library and/or the MPC library installed in a __standard location__ and you want to build GCC, you can explicitly specify the directory where they are installed (`--with-gmp=gmpinstalldir', `--with-mpfr=mpfrinstalldir', `--with-mpc=mpcinstalldir'). The --with-gmp=gmpinstalldir option is shorthand for --with-gmp-lib=gmpinstalldir/lib and --with-gmp-include=gmpinstalldir/include. Likewise the --with-mpfr=mpfrinstalldir option is shorthand for --with-mpfr-lib=mpfrinstalldir/lib and --with-mpfr-include=mpfrinstalldir/include, also the --with-mpc=mpcinstalldir option is shorthand for --with-mpc-lib=mpcinstalldir/lib and --with-mpc-include=mpcinstalldir/include. If these shorthand assumptions are not correct, you can use the explicit include and lib options directly. You might also need to ensure the shared libraries can be found by the dynamic linker when building and using GCC, for example by setting the runtime shared library path variable (LD_LIBRARY_PATH on GNU/Linux and Solaris systems). - - These flags are applicable to the host platform only. When building a cross compiler, they will not be used to configure target libraries. ---with-ppl=pathname ---with-ppl-include=pathname ---with-ppl-lib=pathname ---with-cloog=pathname ---with-cloog-include=pathname ---with-cloog-lib=pathname - If you do not have PPL (the Parma Polyhedra Library) and the CLooG libraries installed in a standard location and you want to build GCC, you can explicitly specify the directory where they are installed (`--with-ppl=pplinstalldir', `--with-cloog=clooginstalldir'). The --with-ppl=pplinstalldir option is shorthand for --with-ppl-lib=pplinstalldir/lib and --with-ppl-include=pplinstalldir/include. Likewise the --with-cloog=clooginstalldir option is shorthand for --with-cloog-lib=clooginstalldir/lib and --with-cloog-include=clooginstalldir/include. If these shorthand assumptions are not correct, you can use the explicit include and lib options directly. - - These flags are applicable to the host platform only. When building a cross compiler, they will not be used to configure target libraries. -**--with-host-libstdcxx=linker-args** - If you are linking with a static copy of PPL, you can use this option to specify how the linker should find the standard C++ library used internally by PPL. Typical values of linker-args might be `-lstdc++' or `-Wl,-Bstatic,-lstdc++,-Bdynamic -lm'. If you are linking with a shared copy of PPL, you probably do not need this option; shared library dependencies will cause the linker to search for the standard C++ library automatically. ---with-stage1-ldflags=flags - This option may be used to set linker flags to be used when linking stage 1 of GCC. These are also used when linking GCC if configured with --disable-bootstrap. By default no special flags are used. ---with-stage1-libs=libs - This option may be used to set libraries to be used when linking stage 1 of GCC. These are also used when linking GCC if configured with --disable-bootstrap. The default is the argument to --with-host-libstdcxx, if specified. ---with-boot-ldflags=flags - This option may be used to set linker flags to be used when linking stage 2 and later when bootstrapping GCC. If neither –with-boot-libs nor –with-host-libstdcxx is set to a value, then the default is `-static-libstdc++ -static-libgcc'. ---with-boot-libs=libs - This option may be used to set libraries to be used when linking stage 2 and later when bootstrapping GCC. The default is the argument to --with-host-libstdcxx, if specified. ---with-debug-prefix-map=map - Convert source directory names using -fdebug-prefix-map when building runtime libraries. `map' is a space-separated list of maps of the form `old=new'. ---enable-linker-build-id - Tells GCC to pass --build-id option to the linker for all final links (links performed without the -r or --relocatable option), if the linker supports it. If you specify --enable-linker-build-id, but your linker does not support --build-id option, a warning is issued and the --enable-linker-build-id option is ignored. The default is off. ---with-linker-hash-style=choice - Tells GCC to pass --hash-style=choice option to the linker for all final links. choice can be one of `sysv', `gnu', and `both' where `sysv' is the default. ---enable-gnu-unique-object ---disable-gnu-unique-object - Tells GCC to use the gnu_unique_object relocation for C++ template static data members and inline function local statics. Enabled by default for a native toolchain with an assembler that accepts it and GLIBC 2.11 or above, otherwise disabled. ---enable-lto ---disable-lto - Enable support for__ link-time optimization (LTO)__. This is enabled by default, and may be disabled using --disable-lto. ---with-plugin-ld=pathname - Enable an alternate linker to be used at link-time optimization (LTO) link time when -fuse-linker-plugin is enabled. This linker should have plugin support such as gold starting with version 2.20 or GNU ld starting with version 2.21. See -fuse-linker-plugin for details. - -===== Cross-Compiler-Specific Options ===== - -The following options only apply to building cross compilers. - -**--with-sysroot** -**--with-sysroot=dir(生成的编译器,会把dir当作其运行的根目录,只会在其中搜索编译程序时需要的头文件、库文件,但是编译器自生运行所需的库文件、头文件不受这限制)** - Tells GCC to consider dir as the root of a tree that contains (a subset of) the** root filesystem of the target operating system**.__ Target system__ headers, libraries and run-time object files will__ be searched in there__. More specifically, this acts as if __--sysroot=dir__ was added to the default options of the built compiler(用编译好的编译器编译源文件时指定--sysroot=dir选项). The specified directory is __not copied__ into the install tree, unlike the options --with-headers and --with-libs that this option obsoletes. The default value, in case --with-sysroot is not given an argument, is ${gcc_tooldir}/sys-root. If the specified directory is a__ subdirectory of ${exec_prefix}, then it will be found relative to the GCC binaries if the installation tree is moved__. - - This option affects the system root for the compiler used to build **target libraries** (which runs on the build system) and the compiler **newly **installed with make install; it does **not affect** the compiler which is used to build GCC itself.(这个选项只会对生成的编译器有影响,不会影响正在编译编译器代码的主机编译器) - - If you specify the --with-native-system-header-dir=dirname option then the compiler(编译后生成的编译器) will search that directory within dirname **for native system headers**__ rather than__ the default /usr/include.(生成的编译器只会在dir中搜索头文件) - -**--with-build-sysroot** -**--with-build-sysroot=dir(当--prefix和实际安装的位置不一致时,可以使用这个选项)** - Tells GCC to consider dir as the system root (see --with-sysroot) while building target libraries, instead of the directory specified with --with-sysroot. This option is only useful __when you are already using --with-sysroot__. You can use --with-build-sysroot when you are configuring with --prefix set to a directory that is __different__ from the one in which you are installing GCC and your target libraries. - - This option affects the system root for the compiler used to build target libraries (which runs on the build system); it does not affect the compiler which is used to build GCC itself. - - If you specify the --with-native-system-header-dir=dirname option then the compiler will search that directory within dirname for native system headers rather than the default /usr/include. -**--with-headers** -**--with-headers=dir(供编译编译器的主机编译器使用,然后复制到生成的编译器的安装目录中)** - Deprecated in favor of --with-sysroot. Specifies that __target headers__ are available when building a cross compiler. The dir argument specifies a directory which has the **target include files**. These include files will be __copied__ into the gcc install directory. This option with the dir argument is required when building a cross compiler, if **prefix/target/sys-include** doesn't pre-exist. If prefix/target/sys-include does pre-exist, the dir argument may be omitted. fixincludes will be run on these files to make them compatible with GCC. -**--without-headers** - Tells GCC** not use any target headers from a libc** when building a cross compiler. When crossing to GNU/Linux, you need the headers so GCC can build the **exception handling** for libgcc. -**--with-libs** -**--with-libs="dir1 dir2 ... dirN"** - Deprecated in favor of --with-sysroot. Specifies a list of directories which contain the __target runtime libraries__. These libraries will be **copied** into the gcc install directory. If the directory list is omitted, this option has no effect. -**--with-newlib** - Specifies that `newlib' is being used as the target C library. This causes __eprintf to be omitted from libgcc.a on the assumption that it will be provided by `newlib'. -**--with-build-time-tools=dir** - Specifies where to find the set of __target tools__ (assembler, linker, etc.) that will be used while building GCC itself. This option can be useful if the directory layouts are different between the system you are building GCC on, and the system where you will deploy it. - - For example, on an `ia64-hp-hpux' system, you may have the GNU assembler and linker in /usr/bin, and the native tools in a different path, and build a toolchain that expects to find the native tools in /usr/bin. - - When you use this option, you should ensure that dir includes **ar, as, ld, nm, ranlib and strip **if necessary, and possibly objdump. Otherwise, GCC may use an inconsistent set of tools. - -===== Java-Specific Options ===== - -The following option applies to the build of the Java front end. - ---disable-libgcj - Specify that the run-time libraries used by GCJ should not be built. This is useful in case you intend to use GCJ with some other run-time, or you're going to install it separately, or it just happens not to build on your particular machine. In general, if the Java front end is enabled, the GCJ libraries will be enabled too, unless they're known to not work on the target platform. If GCJ is enabled but `libgcj' isn't built, you may need to port it; in this case, before modifying the top-level configure.in so that `libgcj' is enabled by default on this platform, you may use --enable-libgcj to override the default. - -The following options apply to building `libgcj'. -General Options - ---enable-java-maintainer-mode - By default the `libjava' build will not attempt to compile the .java source files to .class. Instead, it will use the .class files from the source tree. If you use this option you must have executables named ecj1 and gjavah in your path for use by the build. You must use this option if you intend to modify any .java files in libjava. ---with-java-home=dirname - This `libjava' option overrides the default value of the `java.home' system property. It is also used to set `sun.boot.class.path' to dirname/lib/rt.jar. By default `java.home' is set to prefix and `sun.boot.class.path' to datadir/java/libgcj-version.jar. ---with-ecj-jar=filename - This option can be used to specify the location of an external jar file containing the Eclipse Java compiler. A specially modified version of this compiler is used by gcj to parse .java source files. If this option is given, the `libjava' build will create and install an ecj1 executable which uses this jar file at runtime. - - If this option is not given, but an ecj.jar file is found in the topmost source tree at configure time, then the `libgcj' build will create and install ecj1, and will also install the discovered ecj.jar into a suitable place in the install tree. - - If ecj1 is not installed, then the user will have to supply one on his path in order for gcj to properly parse .java source files. A suitable jar is available from ftp://sourceware.org/pub/java/. ---disable-getenv-properties - Don't set system properties from GCJ_PROPERTIES. ---enable-hash-synchronization - Use a global hash table for monitor locks. Ordinarily, `libgcj''s `configure' script automatically makes the correct choice for this option for your platform. Only use this if you know you need the library to be configured differently. ---enable-interpreter - Enable the Java interpreter. The interpreter is automatically enabled by default on all platforms that support it. This option is really only useful if you want to disable the interpreter (using --disable-interpreter). ---disable-java-net - Disable java.net. This disables the native part of java.net only, using non-functional stubs for native method implementations. ---disable-jvmpi - Disable JVMPI support. ---disable-libgcj-bc - Disable BC ABI compilation of certain parts of libgcj. By default, some portions of libgcj are compiled with -findirect-dispatch and -fno-indirect-classes, allowing them to be overridden at run-time. - - If --disable-libgcj-bc is specified, libgcj is built without these options. This allows the compile-time linker to resolve dependencies when statically linking to libgcj. However it makes it impossible to override the affected portions of libgcj at run-time. ---enable-reduced-reflection - Build most of libgcj with -freduced-reflection. This reduces the size of libgcj at the expense of not being able to do accurate reflection on the classes it contains. This option is safe if you know that code using libgcj will never use reflection on the standard runtime classes in libgcj (including using serialization, RMI or CORBA). ---with-ecos - Enable runtime eCos target support. ---without-libffi - Don't use `libffi'. This will disable the interpreter and JNI support as well, as these require `libffi' to work. ---enable-libgcj-debug - Enable runtime debugging code. ---enable-libgcj-multifile - If specified, causes all .java source files to be compiled into .class files in one invocation of `gcj'. This can speed up build time, but is more resource-intensive. If this option is unspecified or disabled, `gcj' is invoked once for each .java file to compile into a .class file. ---with-libiconv-prefix=DIR - Search for libiconv in DIR/include and DIR/lib. ---enable-sjlj-exceptions - Force use of the setjmp/longjmp-based scheme for exceptions. `configure' ordinarily picks the correct value based on the platform. Only use this option if you are sure you need a different setting. ---with-system-zlib - Use installed `zlib' rather than that included with GCC. ---with-win32-nlsapi=ansi, unicows or unicode - Indicates how MinGW `libgcj' translates between UNICODE characters and the Win32 API. ---enable-java-home - If enabled, this creates a JPackage compatible SDK environment during install. Note that if –enable-java-home is used, –with-arch-directory=ARCH must also be specified. ---with-arch-directory=ARCH - Specifies the name to use for the jre/lib/ARCH directory in the SDK environment created when –enable-java-home is passed. Typical names for this directory include i386, amd64, ia64, etc. ---with-os-directory=DIR - Specifies the OS directory for the SDK include directory. This is set to auto detect, and is typically 'linux'. ---with-origin-name=NAME - Specifies the JPackage origin name. This defaults to the 'gcj' in java-1.5.0-gcj. ---with-arch-suffix=SUFFIX - Specifies the suffix for the sdk directory. Defaults to the empty string. Examples include '.x86_64' in 'java-1.5.0-gcj-1.5.0.0.x86_64'. ---with-jvm-root-dir=DIR - Specifies where to install the SDK. Default is $(prefix)/lib/jvm. ---with-jvm-jar-dir=DIR - Specifies where to install jars. Default is $(prefix)/lib/jvm-exports. ---with-python-dir=DIR - Specifies where to install the Python modules used for aot-compile. DIR should not include the prefix used in installation. For example, if the Python modules are to be installed in /usr/lib/python2.5/site-packages, then –with-python-dir=/lib/python2.5/site-packages should be passed. If this is not specified, then the Python modules are installed in $(prefix)/share/python. ---enable-aot-compile-rpm - Adds aot-compile-rpm to the list of installed scripts. ---enable-browser-plugin - Build the gcjwebplugin web browser plugin. ---enable-static-libjava - Build static libraries in libjava. The default is to only build shared libraries. - - ansi - Use the single-byte char and the Win32 A functions natively, translating to and from UNICODE when using these functions. If unspecified, this is the default. - unicows - Use the WCHAR and Win32 W functions natively. Adds -lunicows to libgcj.spec to link with `libunicows'. unicows.dll needs to be deployed on Microsoft Windows 9X machines running built executables. libunicows.a, an open-source import library around Microsoft's unicows.dll, is obtained from http://libunicows.sourceforge.net/, which also gives details on getting unicows.dll from Microsoft. - unicode - Use the WCHAR and Win32 W functions natively. Does not add -lunicows to libgcj.spec. The built executables will only run on Microsoft Windows NT and above. - -===== AWT-Specific Options ===== - ---with-x - Use the X Window System. ---enable-java-awt=PEER(S) - Specifies the AWT peer library or libraries to build alongside `libgcj'. If this option is unspecified or disabled, AWT will be non-functional. Current valid values are gtk and xlib. Multiple libraries should be separated by a comma (i.e. --enable-java-awt=gtk,xlib). ---enable-gtk-cairo - Build the cairo Graphics2D implementation on GTK. ---enable-java-gc=TYPE - Choose garbage collector. Defaults to boehm if unspecified. ---disable-gtktest - Do not try to compile and run a test GTK+ program. ---disable-glibtest - Do not try to compile and run a test GLIB program. ---with-libart-prefix=PFX - Prefix where libart is installed (optional). ---with-libart-exec-prefix=PFX - Exec prefix where libart is installed (optional). ---disable-libarttest - Do not try to compile and run a test libart program. - -===== Overriding configure test results ===== - -Sometimes, it might be necessary to override the result of some configure test, for example in order to ease porting to a new system or work around a bug in a test. The toplevel configure script provides three variables for this: - -build_configargs - The contents of this variable is passed to all build configure scripts. -host_configargs - The contents of this variable is passed to all host configure scripts. -target_configargs - The contents of this variable is passed to all target configure scripts. - -In order to avoid shell and make quoting issues for complex overrides, you can pass a setting for CONFIG_SITE and set variables in the site file. - -Return to the GCC Installation page -For questions related to the use of GCC, please consult these web pages and the GCC manuals. If that fails, the gcc-help@gcc.gnu.org mailing list might help. Comments on these web pages and the development of GCC are welcome on our developer list at gcc@gcc.gnu.org. All of our lists have public archives. - -Copyright (C) Free Software Foundation, Inc. Verbatim copying and distribution of this entire article is permitted in any medium, provided this notice is preserved. - -These pages are maintained by the GCC team. Last modified 2011-11-23. diff --git a/Zim/Utils/make.txt b/Zim/Utils/make.txt deleted file mode 100644 index 25bd1ee..0000000 --- a/Zim/Utils/make.txt +++ /dev/null @@ -1,2437 +0,0 @@ -Content-Type: text/x-zim-wiki -Wiki-Format: zim 0.4 -Creation-Date: 2011-11-20T11:24:38+08:00 - -====== make ====== -Created Sunday 20 November 2011 -http://blog.csdn.net/haoel/article/details/2886 -跟我一起写 Makefile -陈皓 - -概述 -—— - -什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional的程序员,makefile还是要懂。这就好像现在有这么多的HTML的编辑器,但如果你想成为一个专业人士,你还是要了解HTML的标识的含义。特别在Unix下的软件编译,你就不能不自己写makefile了,会不会写makefile,从一个侧面说明了一个人是否具备完成__大型工程__的能力。 - -因为,makefile关系到了整个工程的编译规则。一个工程中的源文件不计数,其按**类型、功能、模块**分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个**Shell脚本**一样,其中也可以执行操作系统的命令。 - -makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。make是一个命令工具,是一个**解释**makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。 - -现在讲述如何写makefile的文章比较少,这是我想写这篇文章的原因。当然,不同产商的make各不相同,也有不同的语法,但其本质都是在“__文件依赖性__”上做文章,这里,我仅对GNU的make进行讲述,我的环境是RedHat Linux 8.0,make的版本是3.80。必竟,这个make是应用最为广泛的,也是用得最多的。而且其还是最遵循于IEEE 1003.2-1992 标准的(POSIX.2)。 - -在这篇文档中,将以C/C++的源码作为我们基础,所以必然涉及一些关于C/C++的编译的知识,相关于这方面的内容,还请各位查看相关的编译器的文档。这里所默认的编译器是UNIX下的GCC和CC。 - - -关于程序的编译和链接 -—————————— - -在此,我想多说关于程序编译的一些规范和方法,一般来说,无论是C、C++、还是pas,首先要把源文件编译成__中间代码__文件,在Windows下也就是 .obj 文件,UNIX下是 .o 文件,即 Object File,这个动作叫做__编译__(compile)。然后再把大量的Object File合成执行文件,这个动作叫作__链接__(link)。 - -编译时,编译器需要的是语法的正确,函数与变量的声明的正确。对于后者,通常是你需要告诉编译器头文件的所在位置(头文件中应该只是声明,而定义应该放在C/C++文件中),只要所有的__语法__正确,编译器就可以编译出中间目标文件。一般来说,每个源文件都应该对应于一个中间目标文件(O文件或是OBJ文件)。 - -链接时,主要是__链接函数和全局变量__,所以,我们可以使用这些中间目标文件(O文件或是OBJ文件)来链接我们的应用程序。链接器并不管函数所在的源文件,只管函数的中间目标文件(Object File),在大多数时候,由于源文件太多,编译生成的**中间目标文件太多**,而在链接时需要明显地指出中间目标文件名,这对于编译很不方便,所以,我们要给中间目标文件打个包,在Windows下这种包叫“库文件”(Library File),也就是 .lib 文件,在UNIX下,是Archive File,也就是__ .a 文件__。 - -总结一下,源文件首先会生成中间目标文件,再由中间目标文件生成执行文件。在编译时,编译器只检测程序语法,和函数、变量是否被声明。如果函数未被声明,编译器会给出一个警告,但可以生成Object File。而在链接程序时,链接器会在所有的Object File中找寻函数的__实现__,如果找不到,那到就会报链接错误码(Linker Error),在VC下,这种错误一般是:Link 2001错误,意思说是说,链接器未能找到函数的实现。你需要指定函数的Object File. - -好,言归正传,GNU的make有许多的内容,闲言少叙,还是让我们开始吧。 - - -Makefile 介绍 -——————— - -make命令执行时,需要一个 __Makefile__ 文件,以告诉make命令需要怎么样的去编译和链接程序。 - -首先,我们用一个示例来说明Makefile的书写规则。以便给大家一个感兴认识。这个示例来源于GNU的make使用手册,在这个示例中,我们的工程有8个C文件,和3个头文件,我们要写一个Makefile来告诉make命令如何编译和链接这几个文件。我们的规则是: - 1)如果这个工程没有编译过,那么我们的所有C文件都要编译并被链接。 - 2)如果这个工程的某几个C文件被修改,那么我们只编译被修改的C文件,并链接目标程序。 - 3)如果这个工程的头文件被改变了,那么我们需要编译引用了这几个头文件的C文件,并链接目标程序。 - -只要我们的Makefile写得够好,所有的这一切,我们只用一个make命令就可以完成,make命令会自动智能地根据当前的文件修改的情况来确定哪些文件需要重编译,从而自己编译所需要的文件和链接目标程序。 - - -一、Makefile的规则 - -在讲述这个Makefile之前,还是让我们先来粗略地看一看Makefile的规则。 - - target ... : prerequisites ... - command - ... - ... - - target也就是一个目标文件,可以是Object File,也可以是执行文件。还可以是一个**标签**(Label),对于标签这种特性,在后续的“伪目标”章节中会有叙述。 - - prerequisites就是,要生成那个target所需要的文件或是目标。 - - command也就是make需要执行的命令。(任意的Shell命令) - -这是一个__文件的依赖关系__,也就是说,target这一个或多个的目标文件依赖于prerequisites中的文件,其生成规则定义在command中。说白一点就是说,prerequisites中如果有一个以上的文件比target文件要新的话,command所定义的命令就会被执行。这就是Makefile的规则。也就是Makefile中最核心的内容。 - -说到底,Makefile的东西就是这样一点,好像我的这篇文档也该结束了。呵呵。还不尽然,这是Makefile的主线和核心,但要写好一个Makefile还不够,我会以后面一点一点地结合我的工作经验给你慢慢到来。内容还多着呢。:) - - -二、一个示例 - -正如前面所说的,如果一个工程有3个头文件,和8个C文件,我们为了完成前面所述的那三个规则,我们的Makefile应该是下面的这个样子的。 - - edit : main.o kbd.o command.o display.o \ - insert.o search.o files.o utils.o - cc -o edit main.o kbd.o command.o display.o \ - insert.o search.o files.o utils.o - - main.o : main.c defs.h - cc -c main.c - kbd.o : kbd.c defs.h command.h - cc -c kbd.c - command.o : command.c defs.h command.h - cc -c command.c - display.o : display.c defs.h buffer.h - cc -c display.c - insert.o : insert.c defs.h buffer.h - cc -c insert.c - search.o : search.c defs.h buffer.h - cc -c search.c - files.o : files.c defs.h buffer.h command.h - cc -c files.c - utils.o : utils.c defs.h - cc -c utils.c - clean : - rm edit main.o kbd.o command.o display.o \ - insert.o search.o files.o utils.o - -反斜杠(\)是换行符的意思。这样比较便于Makefile的易读。我们可以把这个内容保存在文件为“Makefile”或“makefile”的文件中,然后在该目录下直接输入命令“make”就可以生成执行文件edit。如果要删除执行文件和所有的中间目标文件,那么,只要简单地执行一下“make clean”就可以了。 - -在这个makefile中,目标文件(target)包含:执行文件edit和中间目标文件(*.o),依赖文件(prerequisites)就是冒号后面的那些 .c 文件和 .h文件。每一个 .o 文件都有一组依赖文件,而这些 .o 文件又是执行文件 edit 的依赖文件。依__赖关系的实质__上就是说明了目标文件是由哪些文件生成的,换言之,__目标文件是哪些文件更新的__。 - -在定义好依赖关系后,后续的那一行定义了如何生成目标文件的操作系统命令,一定要__以一个Tab键作为开头__。记住,make并不管命令是怎么工作的,他只管执行所定义的命令。make会比较targets文件和prerequisites文件的修改日期,如果prerequisites文件的日期要比targets文件的日期要新,或者target不存在的话,那么,make就会执行后续定义的命令。 - -这里要说明一点的是,clean不是一个文件,它只不过是一个动作名字,有点像C语言中的lable一样,其冒号后什么也没有,那么,make就不会自动去找文件的依赖性,也就__不会自动执行__其后所定义的命令。要执行其后的命令,就要在make命令后明显得指出这个lable的名字。这样的方法非常有用,我们可以在一个makefile中定义不用的编译或是和编译无关的命令,比如程序的打包,程序的备份,等等。 - - -三、make是如何工作的 - -在默认的方式下,也就是我们只输入make命令。那么, - - 1、make会在当前目录下找名字叫“Makefile”或“makefile”的文件。 - 2、如果找到,它会找文件中的__第一个__目标文件(target),在上面的例子中,他会找到“edit”这个文件,并把这个文件作为__最终__的目标文件。 - 3、如果edit文件不存在,或是edit所依赖的后面的 .o 文件的文件修改时间要比edit这个文件新,那么,他就会执行后面所定义的命令来生成edit这个文件。 - 4、如果edit所依赖的.o文件也存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件。(这有点像一个堆栈的过程) - 5、当然,你的C文件和H文件是存在的啦,于是make会生成 .o 文件,然后再用 .o 文件生命make的终极任务,也就是执行文件edit了。 - -这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会__直接退出__,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。make__只管文件的依赖性__,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦。 - -通过上述分析,我们知道,像clean这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不过,我们可以显示要make执行。即命令——“make clean”,以此来清除所有的目标文件,以便重编译。 - -于是在我们编程中,如果这个工程已被编译过了,当我们修改了其中一个源文件,比如file.c,那么根据我们的依赖性,我们的目标file.o会被重编译(也就是在这个依性关系后面所定义的命令),于是file.o的文件也是最新的啦,于是file.o的文件修改时间要比edit要新,所以edit也会被重新链接了(详见edit目标文件后定义的命令)。 - -而如果我们改变了“command.h”,那么,kdb.o、command.o和files.o都会被重编译,并且,edit会被重链接。 - - -四、makefile中使用变量 - -在上面的例子中,先让我们看看edit的规则: - - edit : main.o kbd.o command.o display.o \ - insert.o search.o files.o utils.o - cc -o edit main.o kbd.o command.o display.o \ - insert.o search.o files.o utils.o - -我们可以看到[.o]文件的字符串被重复了两次,如果我们的工程需要加入一个新的[.o]文件,那么我们需要在两个地方加(应该是三个地方,还有一个地方在clean中)。当然,我们的makefile并不复杂,所以在两个地方加也不累,但如果makefile变得复杂,那么我们就有可能会忘掉一个需要加入的地方,而导致编译失败。所以,为了makefile的易维护,在makefile中我们可以使用__变量__。makefile的变量也就是一个字符串,理解成C语言中的宏可能会更好。 - -比如,我们声明一个变量,叫objects, OBJECTS, objs, OBJS, obj, 或是 OBJ,反正不管什么啦,只要能够表示obj文件就行了。我们在makefile一开始就这样定义: - - objects = main.o kbd.o command.o display.o \ - insert.o search.o files.o utils.o - -于是,我们就可以很方便地在我们的makefile中以“__$(objects)__”的方式来使用这个变量了,于是我们的改良版makefile就变成下面这个样子: - - objects = main.o kbd.o command.o display.o \ - insert.o search.o files.o utils.o - - edit : $(objects) - cc -o edit $(objects) - main.o : main.c defs.h - cc -c main.c - kbd.o : kbd.c defs.h command.h - cc -c kbd.c - command.o : command.c defs.h command.h - cc -c command.c - display.o : display.c defs.h buffer.h - cc -c display.c - insert.o : insert.c defs.h buffer.h - cc -c insert.c - search.o : search.c defs.h buffer.h - cc -c search.c - files.o : files.c defs.h buffer.h command.h - cc -c files.c - utils.o : utils.c defs.h - cc -c utils.c - clean : - rm edit $(objects) - - -于是如果有新的 .o 文件加入,我们只需简单地修改一下 objects 变量就可以了。 - -关于变量更多的话题,我会在后续给你一一道来。 - - -五、让make自动推导 - -GNU的make很强大,它可以自动推导文件以及文件依赖关系后面的__命令__,于是我们就没必要去在每一个[.o]文件后都写上类似的命令,因为,我们的make会自动识别,并自己__推导命令__。 - -只要make看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中,如果make找到一个whatever.o,那么whatever.c,就会是whatever.o的依赖文件。并且 cc -c whatever.c 也会被推导出来,于是,我们的makefile再也不用写得这么复杂。我们的是新的makefile又出炉了。 - - - objects = main.o kbd.o command.o display.o \ - insert.o search.o files.o utils.o - - edit : $(objects) - cc -o edit $(objects) - - main.o : defs.h //只有头文件,.o对应的源文件可以省略,而且编译命令也可以省略。 - kbd.o : defs.h command.h - command.o : defs.h command.h - display.o : defs.h buffer.h - insert.o : defs.h buffer.h - search.o : defs.h buffer.h - files.o : defs.h buffer.h command.h - utils.o : defs.h - - .PHONY : clean - clean : - rm edit $(objects) - -这种方法,也就是make的“隐晦规则”。上面文件内容中,“.PHONY”表示,clean是个__伪目标文件__。 - -关于更为详细的“隐晦规则”和“伪目标文件”,我会在后续给你一一道来。 - - -六、另类风格的makefile - -即然我们的make可以自动推导命令,那么我看到那堆[.o]和[.h]的依赖就有点不爽,那么多的重复的[.h],能不能把其__收拢起来__,好吧,没有问题,这个对于make来说很容易,谁叫它提供了自动推导命令和文件的功能呢?来看看最新风格的makefile吧。 - - objects = main.o kbd.o command.o display.o \ - insert.o search.o files.o utils.o - - edit : $(objects) - cc -o edit $(objects) - - $(objects) : defs.h - kbd.o command.o files.o : command.h - display.o insert.o search.o files.o : buffer.h - - .PHONY : clean - clean : - rm edit $(objects) - -这种风格,让我们的makefile变得很简单,但我们的文件依赖关系就显得有点凌乱了。鱼和熊掌不可兼得。还看你的喜好了。我是不喜欢这种风格的,一是文件的依赖关系看不清楚,二是如果文件一多,要加入几个新的.o文件,那就理不清楚了。 - - -七、清空目标文件的规则 - -每个Makefile中都应该写一个清空目标文件(.o和执行文件)的规则,这不仅便于重编译,也很利于保持文件的清洁。这是一个“修养”(呵呵,还记得我的《编程修养》吗)。一般的风格都是: - - clean: - rm edit $(objects) - -更为稳健的做法是: - - .PHONY : clean - clean : - __-rm __edit $(objects) - -前面说过,.PHONY意思表示clean是一个“伪目标”,。而在rm命令前面加了一个小减号的意思就是,也许某些文件出现问题,但不要管,继续做后面的事。当然,clean的规则不要放在文件的开头,不然,这就会变成make的默认目标,相信谁也不愿意这样。不成文的规矩是——“clean从来都是放在文件的最后”。 - - -上面就是一个makefile的概貌,也是makefile的基础,下面还有很多makefile的相关细节,准备好了吗?准备好了就来。 - - -一、Makefile里有什么? - -Makefile里主要包含了五个东西:显式规则、隐晦规则、变量定义、文件指示和注释。 - -1、显式规则。显式规则说明了,如何生成一个或多的的目标文件。这是由Makefile的书写者明显指出,要生成的文件,文件的依赖文件,生成的命令。 - -2、隐晦规则。由于我们的make有自动推导的功能,所以隐晦的规则可以让我们比较粗糙地简略地书写Makefile,这是由make所支持的。 - -3、变量的定义。在Makefile中我们要定义一系列的变量,变量一般都是字符串,这个有点你C语言中的宏,当Makefile被执行时,其中的变量都会被扩展到相应的引用位置上。 - -4、文件指示。其包括了三个部分,一个是在一个Makefile中引用另一个Makefile,就像C语言中的include一样;另一个是指根据某些情况指定Makefile中的有效部分,就像C语言中的预编译#if一样;还有就是定义一个多行的命令。有关这一部分的内容,我会在后续的部分中讲述。 - -5、注释。Makefile中只有行注释,和UNIX的Shell脚本一样,其注释是用“#”字符,这个就像C/C++中的“//”一样。如果你要在你的Makefile中使用“#”字符,可以用反斜框进行转义,如:“\#”。 - -最后,还值得一提的是,在Makefile中的命令,__必须要以[Tab]键开始__。 - - -二、Makefile的文件名 - -默认的情况下,make命令会在当前目录下按顺序找寻文件名为“GNUmakefile”、“makefile”、“Makefile”的文件,找到了解释这个文件。在这三个文件名中,最好使用“__Makefile__”这个文件名,因为,这个文件名第一个字符为大写,这样有一种显目的感觉。最好不要用“GNUmakefile”,这个文件是GNU的make识别的。有另外一些make只对全小写的“makefile”文件名敏感,但是基本上来说,大多数的make都支持“makefile”和“Makefile”这两种默认文件名。 - -当然,你可以使用别的文件名来书写Makefile,比如:“Make.Linux”,“Make.Solaris”,“Make.AIX”等,如果要指定特定的Makefile,你可以使用make的“-f”和“--file”参数,如:make -f Make.Linux或make --file Make.AIX。 - - -三、引用其它的Makefile - -在Makefile使用include关键字可以把别的Makefile包含进来,这很像C语言的#include,被包含的文件会原模原样的放在当前文件的包含位置。include的语法是: - - include ; - - filename可以是当前操作系统__Shell的文件模式__(可以保含路径和通配符) - -在include前面可以有一些空字符,但是绝不能是[Tab]键开始。include和;可以用一个或多个空格隔开。举个例子,你有这样几个Makefile:a.mk、b.mk、c.mk,还有一个文件叫foo.make,以及一个变量$(bar),其包含了e.mk和f.mk,那么,下面的语句: - - include foo.make *.mk $(bar) - - 等价于: - - include foo.make a.mk b.mk c.mk e.mk f.mk - -make命令开始时,会把找寻include所指出的其它Makefile,并把其内容安置在当前的位置。就好像C/C++的#include指令一样。如果文件都没有指定绝对路径或是相对路径的话,make会在**当前目录**下首先寻找,如果当前目录下没有找到,那么,make还会在下面的几个目录下找: - - 1、如果make执行时,有“-I”或“--include-dir”参数,那么make就会在这个参数所指定的目录下去寻找。 - 2、如果目录;/include(一般是:/usr/local/bin或/usr/include)存在的话,make也会去找。 - -如果有文件没有找到的话,make会生成一条警告信息,但不会马上出现致命错误。它会继续载入其它的文件,一旦完成makefile的读取,make会再重试这些没有找到,或是不能读取的文件,如果还是不行,make才会出现一条致命信息。如果你想让make不理那些无法读取的文件,而继续执行,你可以在include前加一个减号“-”。如: - - __-include __; - 其表示,无论include过程中出现什么错误,都不要报错继续执行。和其它版本make兼容的相关命令是sinclude,其作用和这一个是一样的。 - - -四、环境变量 MAKEFILES - -如果你的当前环境中定义了环境变量MAKEFILES,那么,make会把这个变量中的值做一个__类似于include的动作__。这个变量中的值是其它的Makefile,用**空格分隔**。只是,它和include不同的是,从这个环境变中引入的Makefile的“目标”不会起作用,如果环境变量中定义的文件发现错误,make也会不理。 - -但是在这里我还是建议__不要使用__这个环境变量,因为只要这个变量一被定义,那么当你使用make时,所有的Makefile都会受到它的影响,这绝不是你想看到的。在这里提这个事,只是为了告诉大家,也许有时候你的Makefile出现了怪事,那么你可以看看当前环境中有没有定义这个变量。 - - -五、make的工作方式 - -GNU的make工作时的执行步骤入下:(想来其它的make也是类似) - - 1、读入所有的Makefile。 - 2、读入被include的其它Makefile。 - 3、初始化文件中的变量。 - 4、推导隐晦规则,并分析所有规则。 - 5、为所有的目标文件创建依赖__关系链__。 - 6、根据依赖关系,决定哪些目标要重新生成。 - 7、执行生成命令。 - -1-5步为第一个阶段,6-7为第二个阶段。第一个阶段中,如果定义的变量被使用了,那么,make会把其展开在使用的位置。但make并不会完全马上展开,make使用的是**拖延战术**,如果变量出现在依赖关系的规则中,那么仅当这条依赖被决定要使用了,变量才会在其内部展开。 - -当然,这个工作方式你不一定要清楚,但是知道这个方式你也会对make更为熟悉。有了这个基础,后续部分也就容易看懂了。 - - -书写规则 -———— - -规则包含两个部分,__一个是依赖关系,一个是生成目标的方法__。 - -在Makefile中,规则的__顺序__是很重要的,因为,Makefile中只应该有__一个__最终目标,其它的目标都是被这个目标所连带出来的,所以一定要让make知道你的最终目标是什么。一般来说,定义在Makefile中的目标可能会有很多,但是第一条规则中的目标将被确立为最终的目标。如果第一条规则中的目标有很多个,那么,第一个目标会成为最终的目标。make所完成的也就是这个目标。 - -好了,还是让我们来看一看如何书写规则。 - - -一、规则举例 - - foo.o : foo.c defs.h # foo模块 - cc -c -g foo.c - -看到这个例子,各位应该不是很陌生了,前面也已说过,foo.o是我们的目标,foo.c和defs.h是目标所依赖的源文件,而只有一个命令“cc -c -g foo.c”(以Tab键开头)。这个规则告诉我们两件事: - - 1、文件的依赖关系,foo.o依赖于foo.c和defs.h的文件,如果foo.c和defs.h的文件日期要比foo.o文件日期要新,或是foo.o不存在,那么依赖关系发生。 - 2、如何生成(或更新)foo.o文件。也就是那个cc命令,其说明了,如何生成foo.o这个文件。(当然foo.c文件include了defs.h文件) - - -二、规则的语法 - - targets : prerequisites - command - ... - - 或是这样: - - targets : prerequisites __;__ command - command - ... - -targets是文件名,以**空格分开**,可以使用**通配符**。一般来说,我们的目标基本上是一个文件,但也有可能是多个文件。 - -command是命令行,如果其不与“target:prerequisites”在一行,那么,必须以[Tab键]开头,如果和prerequisites在一行,那么可以用分号做为分隔。(见上) - -prerequisites也就是目标所依赖的文件(或依赖目标)。如果其中的某个文件要比目标文件要新,那么,目标就被认为是“过时的”,被认为是需要重生成的。这个在前面已经讲过了。 - -如果命令太长,你可以使用__反斜框__(‘\’)作为换行符。make对一行上有多少个字符没有限制。规则告诉make两件事,文件的依赖关系和如何成成目标文件。 - -一般来说,make会以UNIX的标准Shell,也就是/bin/sh来执行命令。 - - -三、在规则中使用通配符 - -如果我们想定义一系列比较类似的文件,我们很自然地就想起使用通配符。make支持三种通配符:__“*”,“?”和“[...]”__。这是和Unix的B-Shell是相同的。 - -波浪号(__“~”__)字符在文件名中也有比较特殊的用途。如果是“~/test”,这就表示当前用户的$HOME目录下的test目录。而“~hchen/test”则表示用户hchen的宿主目录下的test目录。(这些都是Unix下的小知识了,make也支持)而在Windows或是MS-DOS下,用户没有宿主目录,那么波浪号所指的目录则根据环境变量“HOME”而定。 - -通配符代替了你一系列的文件,如“*.c”表示所以后缀为c的文件。一个需要我们注意的是,如果我们的文件名中有通配符,如:“*”,那么可以用转义字符“\”,如“\*”来表示真实的“*”字符,而不是任意长度的字符串。 - -好吧,还是先来看几个例子吧: - - clean: - rm -f *.o - - 上面这个例子我不不多说了,这是操作系统Shell所支持的通配符。这是在命令中的通配符。 - - print: *.c - lpr -p $? - touch print - - 上面这个例子说明了通配符也可以在我们的规则中,目标print依赖于所有的[.c]文件。其中的“$?”是一个自动化变量,我会在后面给你讲述。 - - objects = *.o - - 上面这个例子,表示了,**通符同样可以用在变量中**。__并不是说[*.o]会展开__,不!objects的值就是“*.o”。Makefile中的变量其实就是C/C++中的宏。如果你要让通配符在变量中展开,也就是让objects的值是所有[.o]的文件名的集合,那么,你可以这样: - - objects := __$(wildcard *.o)__ - -这种用法由关键字“wildcard”指出,关于Makefile的关键字,我们将在后面讨论。 - - -四、文件搜寻 - -在一些大的工程中,有大量的源文件,我们通常的做法是把这许多的源文件分类,并存放在__不同的目录中__。所以,当make需要去找寻文件的依赖关系时,你可以在文件前加上路径,但最好的方法是把一个路径告诉make,让make在自动去找。 - -Makefile文件中的__特殊变量“VPATH”__就是完成这个功能的,如果没有指明这个变量,make只会在当前的目录中去找寻依赖文件和目标文件。如果定义了这个变量,那么,make就会在当__当前目录找不到的情况下__,到所指定的目录中去找寻文件了。 - - VPATH = src:../headers - -上面的的定义指定两个目录,“src”和“../headers”,make会按照这个顺序进行搜索。目录由“__冒号__”分隔。(当然,当前目录永远是最高优先搜索的地方) - -另一个设置文件搜索路径的方法是使用__make的“vpath”关键字__(注意,它是全小写的),这不是变量,这是一个make的关键字,这和上面提到的那个VPATH变量很类似,但是它更为灵活。它可以指定不同的文件在不同的搜索目录中。这是一个很灵活的功能。它的使用方法有三种: - - 1、vpath ; ; - - 为符合模式;的文件指定搜索目录;。 - - 2、vpath ; - - 清除符合模式;的文件的搜索目录。 - - 3、vpath - - 清除所有已被设置好了的文件搜索目录。 - -vapth使用方法中的;需要__包含“%”字符__。“%”的意思是匹配零或若干字符,例如,“%.h”表示所有以“.h”结尾的文件。;指定了要搜索的文件集,而;则指定了;的文件集的搜索的目录。例如: - - vpath %.h ../headers - -该语句表示,要求make在“../headers”目录下搜索所有以“.h”结尾的文件。(如果某文件在当前目录没有找到的话) - -我们可以连续地使用vpath语句,以指定不同搜索策略。如果连续的vpath语句中出现了相同的;,或是被重复了的;,那么,make会按照vpath语句的__先后顺序__来执行搜索。如: - - vpath %.c foo - vpath %.c blish - vpath %.c bar - -其表示“.c”结尾的文件,先在“foo”目录,然后是“blish”,最后是“bar”目录。 - - vpath %.c foo:bar - vpath % blish - -而上面的语句则表示“.c”结尾的文件,先在“foo”目录,然后是“bar”目录,最后才是“blish”目录。 - - -五、伪目标 - -最早先的一个例子中,我们提到过一个“clean”的目标,这是一个“伪目标”, - - clean: - rm *.o temp - -正像我们前面例子中的“clean”一样,即然我们生成了许多文件编译文件,我们也应该提供一个清除它们的“目标”以备完整地重编译而用。 (以“make clean”来使用该目标) - -因为,我们并不生成“clean”这个文件。“伪目标”并不是一个文件,只是__一个标签__,由于“伪目标”不是文件,所以make无法生成它的依赖关系和决定它是否要执行。我们只有通过显示地指明这个“目标”才能让其生效。当然,“伪目标”的取名不能和文件名重名,不然其就失去了“伪目标”的意义了。 - -当然,为了避免和文件重名的这种情况,我们可以使用一个特殊的标记“.PHONY”来显示地指明一个目标是“伪目标”,向make说明,__不管是否有这个文件,这个目标就是“伪目标”__。而且只能在命令行上. - - .PHONY : clean - -只要有这个声明,不管是否有“clean”文件,要运行“clean”这个目标,只有“make clean”这样。于是整个过程可以这样写: - - .PHONY: clean - clean: - rm *.o temp - -伪目标一般没有依赖的文件。但是,我们也可以为伪目标指定所依赖的文件。伪目标同样可以作为“默认目标”,只要将其放在第一个。一个示例就是,如果你的Makefile需要一口气生成若干个可执行文件,但你只想简单地敲一个make完事,并且,所有的目标文件都写在一个Makefile中,那么你可以使用“伪目标”这个特性: - - all : prog1 prog2 prog3 - .PHONY : all - - prog1 : prog1.o utils.o - cc -o prog1 prog1.o utils.o - - prog2 : prog2.o - cc -o prog2 prog2.o - - prog3 : prog3.o sort.o utils.o - cc -o prog3 prog3.o sort.o utils.o - -我们知道,Makefile中的第一个目标会被作为其默认目标。我们声明了一个“all”的伪目标,其依赖于其它三个目标。由于__伪目标的特性是,总是被执行的__,所以其依赖的那三个目标就总是不如“all”这个目标新。所以,其它三个目标的规则总是会被决议。也就达到了我们一口气生成多个目标的目的。“.PHONY : all”声明了“all”这个目标为“伪目标”。 - -随便提一句,从上面的例子我们可以看出,目标也可以成为依赖。所以,伪目标同样也可成为依赖。看下面的例子: - - .PHONY: cleanall cleanobj cleandiff - - cleanall : cleanobj cleandiff - rm program - - cleanobj : - rm *.o - - cleandiff : - rm *.diff - -“make cleanall”将清除所有要被清除的文件。“cleanobj”和“cleandiff”这两个伪目标有点像“子程序”的意思。我们可以输入“make cleanall”和“make cleanobj”和“make cleandiff”命令来达到清除不同种类文件的目的。 - - -六、多目标 - -Makefile的规则中的目标可以不止一个,其支持多目标,有可能我们的多个目标同时依赖于一个文件,并且其生成的命令大体类似。于是我们就能把其合并起来。当然,多个目标的生成规则的执行命令是同一个,这可能会可我们带来麻烦,不过好在我们的可以使用一个自动化变量“$@”(关于自动化变量,将在后面讲述),这个变量表示着目前规则中__所有的目标的集合__,这样说可能很抽象,还是看一个例子吧。 - - bigoutput littleoutput : text.g - generate text.g -$(subst output,,$@) >; $@ - - 上述规则等价于: - - bigoutput : text.g - generate text.g -big >; bigoutput - littleoutput : text.g - generate text.g -little >; littleoutput - - 其中,-$(subst output,,$@)中的“$”表示执行一个Makefile的函数,函数名为subst,后面的为参数。关于函数,将在后面讲述。这里的这个函数是截取字符串的意思,“$@”表示目标的集合,就像一个数组,__“$@”依次取出目标,并执于命令__。 - - -七、静态模式 - -静态模式可以更加容易地定义多目标的规则,可以让我们的规则变得更加的有弹性和灵活。我们还是先来看一下语法: - - ;: ;: ; - ; - ... - - - targets定义了一系列的目标文件,可以有通配符。是目标的一个集合。 - target-parrtern是__指明了targets的模式__,也就是的目标集模式。 - prereq-parrterns是目标的依赖模式,它对target-parrtern形成的模式再进行一次依赖目标的定义。 - -这样描述这三个东西,可能还是没有说清楚,还是举个例子来说明一下吧。如果我们的;定义成“%.o”,意思是我们的;集合中__都是以__“.o”结尾的,而如果我们的;定义成“%.c”,意思是对;所形成的目标集进行二次定义,其计算方法是,取;模式中的“%”(也就是去掉了[.o]这个结尾),并为其加上[.c]这个结尾,形成的新集合。 - -所以,我们的“目标模式”或是“依赖模式”中都应该有“%”这个字符,如果你的文件名中有“%”那么你可以使用反斜杠“\”进行转义,来标明真实的“%”字符。 - -看一个例子: - - objects = foo.o bar.o - - all: $(objects) - - $(objects): %.o: %.c - $(CC) -c $(CFLAGS) $< -o $@ - - -上面的例子中,指明了我们的目标从$object中获取,“%.o”表明要__所有以__“.o”结尾的目标,也就是“foo.o bar.o”,也就是变量$object集合的模式,而依赖模式“%.c”则取模式“%.o”的“%”,也就是“foo bar”,并为其加下“.c”的后缀,于是,我们的依赖目标就是“foo.c bar.c”。而命令中的“$<”和“$@”则是自动化变量,__“$<”表示所有的依赖目标集__(也就是“foo.c bar.c”),__“$@”表示目标集__(也就是“foo.o bar.o”)。于是,上面的规则展开后等价于下面的规则: - - foo.o : foo.c - $(CC) -c $(CFLAGS) foo.c -o foo.o - bar.o : bar.c - $(CC) -c $(CFLAGS) bar.c -o bar.o - -试想,如果我们的“%.o”有几百个,那种我们只要用这种很简单的“静态模式规则”就可以写完一堆规则,实在是太有效率了。“静态模式规则”的用法很灵活,如果用得好,那会一个很强大的功能。再看一个例子: - - - files = foo.elc bar.o lose.o - - $(filter %.o,$(files)): %.o: %.c - $(CC) -c $(CFLAGS) $< -o $@ - $(filter %.elc,$(files)): %.elc: %.el - emacs -f batch-byte-compile $< - - -$(filter %.o,$(files))表示调用Makefile的filter函数,过滤“$filter”集,只要其中模式为“%.o”的内容。其的它内容,我就不用多说了吧。这个例字展示了Makefile中更大的弹性。 - - -八、自动生成依赖性 - -在Makefile中,我们的依赖关系可能会需要包含一系列的__头文件__,比如,如果我们的main.c中有一句“#include "defs.h"”,那么我们的依赖关系应该是: - - main.o : main.c defs.h - -但是,如果是一个比较大型的工程,你必需清楚哪些C文件包含了哪些头文件,并且,你在加入或删除头文件时,也需要小心地修改Makefile,这是一个很没有维护性的工作。为了避免这种繁重而又容易出错的事情,我们可以使用C/C++编译的一个功能。大多数的C/C++编译器都支持一个__“-M”__的选项,即自动找寻源文件中包含的头文件,并生成一个依赖关系。例如,如果我们执行下面的命令: - - cc -M main.c - -其输出是: - - main.o : main.c defs.h - -于是由编译器自动生成的依赖关系,这样一来,你就不必再手动书写若干文件的依赖关系,而由编译器自动生成了。需要提醒一句的是,如果你使用GNU的C/C++编译器,你得用__“-MM”__参数,不然,“-M”参数会把一些标准库的头文件也包含进来。 - - gcc -M main.c的输出是: - - main.o: main.c defs.h /usr/include/stdio.h /usr/include/features.h \ - /usr/include/sys/cdefs.h /usr/include/gnu/stubs.h \ - /usr/lib/gcc-lib/i486-suse-linux/2.95.3/include/stddef.h \ - /usr/include/bits/types.h /usr/include/bits/pthreadtypes.h \ - /usr/include/bits/sched.h /usr/include/libio.h \ - /usr/include/_G_config.h /usr/include/wchar.h \ - /usr/include/bits/wchar.h /usr/include/gconv.h \ - /usr/lib/gcc-lib/i486-suse-linux/2.95.3/include/stdarg.h \ - /usr/include/bits/stdio_lim.h - - - gcc -MM main.c的输出则是: - - main.o: main.c defs.h - -那么,编译器的这个功能如何与我们的Makefile联系在一起呢。因为这样一来,我们的Makefile也要根据这些源文件重新生成,让Makefile自已依赖于源文件?这个功能并不现实,不过我们可以有其它手段来迂回地实现这一功能。GNU组织建议把编译器为每一个源文件的自动生成的依赖关系放到一个文件中,__为每一个“name.c”的文件都生成一个“name.d”的Makefile文件__,[.d]文件中就存放对应[.c]文件的依赖关系。 - -于是,我们可以写出[.c]文件和[.d]文件的依赖关系,并__让make自动更新或自成[.d]文件__,并把其包含在我们的主Makefile中,这样,我们就可以__自动化地生成每个文件的依赖关系__了。 - -这里,我们给出了一个模式规则来产生[.d]文件: - - %.d: %.c - @set -e; rm -f $@; \ - $(CC) -M $(CPPFLAGS) $< >; $@.$$$$; \ - sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ >; $@; \ - rm -f $@.$$$$ - - -这个规则的意思是,所有的[.d]文件依赖于[.c]文件,“rm -f $@”的意思是删除所有的目标,也就是[.d]文件,第二行的意思是,为每个依赖文件“$<”,也就是[.c]文件生成依赖文件,“$@”表示模式“%.d”文件,如果有一个C文件是name.c,那么“%”就是“name”,“$$$$”意为一个随机编号,第二行生成的文件有可能是“name.d.12345”,第三行使用sed命令做了一个替换,关于sed命令的用法请参看相关的使用文档。第四行就是删除临时文件。 - -总而言之,这个模式要做的事就是在__编译器生成的依赖关系中加入[.d]文件的依赖__,即把依赖关系: - - main.o : main.c defs.h #由 $(CC) -M $(CPPFLAGS) $< >; $@.$$$$; 命令生成 - -转成: - - main.o main.d : main.c defs.h - -于是,我们的[.d]文件也会自动更新了,并会自动生成了,当然,你还可以在这个[.d]文件中加入的不只是依赖关系,包括生成的命令也可一并加入,让每个[.d]文件都包含一个完赖的规则。一旦我们完成这个工作,接下来,我们就要__把这些自动生成的规则放进我们的主Makefile中__。我们可以使用Makefile的“include”命令,来引入别的Makefile文件(前面讲过),例如: - - sources = foo.c bar.c - - include $(sources:.c=.d) - -上述语句中的“$(sources:.c=.d)”中的“.c=.d”的意思是做一个替换,把变量$(sources)所有[.c]的字串都替换成[.d],关于这个“替换”的内容,在后面我会有更为详细的讲述。当然,你得注意次序,因为include是按次来载入文件,最先载入的[.d]文件中的目标会成为默认目标。 - - - -书写命令 -———— - -每条规则中的命令和操作系统Shell的命令行是一致的。make会一按顺序一条一条的执行命令,每条命令的开头必须以[Tab]键开头,除非,命令是紧跟在依赖规则后面的分号后的。在命令行之间中的空格或是空行会被忽略,但是如果该空格或空行是以Tab键开头的,那么make会认为其是一个空命令。 - -我们在UNIX下可能会使用不同的Shell,但是__make的命令默认是被“/bin/sh”__——UNIX的标准Shell解释执行的。除非你特别指定一个其它的Shell。Makefile中,“#”是注释符,很像C/C++中的“//”,其后的本行字符都被注释。 - -一、显示命令 - -通常,make会把其要执行的__命令行__在命令执行前输出到屏幕上。当我们用“@”字符在命令行前,那么,这个__命令行本身将不被make显示__出来,最具代表性的例子是,我们用这个功能来像屏幕显示一些信息。如: - - @echo 正在编译XXX模块...... - -当make执行时,会输出“正在编译XXX模块......”字串,但__不会输出命令__,如果没有“@”,那么,make将输出: - - echo 正在编译XXX模块...... - 正在编译XXX模块...... - -如果make执行时,带入make参数__“-n”或“--just-print”__,那么其只是显示命令,但不会执行命令,这个功能很有利于我们调试我们的Makefile,看看我们书写的命令是执行起来是什么样子的或是什么顺序的。 - -而make参数__“-s”或“--slient”__则是全面禁止命令的显示。 - - -二、命令执行, make会为每一个命令行调用一个__新的shell__来执行。 - -当依赖目标新于目标时,也就是当规则的目标需要被更新时,make会一条一条的执行其后的命令。需要注意的是,如果你要让上一条命令的结果应用在下一条命令时,你应该使用__分号__分隔这两条命令。比如你的第一条命令是cd命令,你希望第二条命令得在cd之后的基础上运行,那么你就不能把这两条命令写在两行上,而应该把这两条命令写在一行上,用分号分隔。如: - - 示例一: - exec: - cd /home/hchen - pwd - - 示例二: - exec: - cd /home/hchen; pwd - -当我们执行“make exec”时,第一个例子中的cd没有作用,pwd会打印出当前的Makefile目录,而第二个例子中,cd就起作用了,pwd会打印出“/home/hchen”。 - -make一般是使用环境变量SHELL中所定义的系统Shell来执行命令,默认情况下使用UNIX的标准Shell——/bin/sh来执行命令。但在MS-DOS下有点特殊,因为MS-DOS下没有SHELL环境变量,当然你也可以指定。如果你指定了UNIX风格的目录形式,首先,make会在SHELL所指定的路径中找寻命令解释器,如果找不到,其会在当前盘符中的当前目录中寻找,如果再找不到,其会在PATH环境变量中所定义的所有路径中寻找。MS-DOS中,如果你定义的命令解释器没有找到,其会给你的命令解释器加上诸如“.exe”、“.com”、“.bat”、“.sh”等后缀。 - - - -三、命令出错 - -每当命令运行完后,make会检测每个命令的返回码,如果命令返回成功,那么make会执行下一条命令,当规则中所有的命令成功返回后,这个规则就算是成功完成了。如果一个规则中的某个命令出错了(命令退出码非零),那么make就会终止执行当前规则,这将有可能终止所有规则的执行。 - -有些时候,命令的出错并不表示就是错误的。例如mkdir命令,我们一定需要建立一个目录,如果目录不存在,那么mkdir就成功执行,万事大吉,如果目录存在,那么就出错了。我们之所以使用mkdir的意思就是一定要有这样的一个目录,于是我们就不希望mkdir出错而终止规则的运行。 - -为了做到这一点,__忽略命令的出错__,我们可以在Makefile的命令行前加一个减号“-”(在Tab键之后),标记为__不管命令出不出错都认为是成功的__。如: - - clean: - -rm -f *.o - -还有一个全局的办法是,给make加上“-i”或是“--ignore-errors”参数,那么,Makefile中所有命令都会忽略错误。而如果一个规则是以“.IGNORE”作为目标的,那么这个规则中的所有命令将会忽略错误。这些是不同级别的防止命令出错的方法,你可以根据你的不同喜欢设置。 - -还有一个要提一下的make的参数的是“-k”或是“--keep-going”,这个参数的意思是,如果某规则中的命令出错了,那么就终目该规则的执行,但继续执行其它规则。 - - -四、嵌套执行make - -在一些大的工程中,我们会把我们__不同模块或是不同功能__的源文件放在不同的目录中,我们可以在每个目录中都书写一个该目录的Makefile,这有利于让我们的Makefile变得更加地简洁,而不至于把所有的东西全部写在一个Makefile中,这样会很难维护我们的Makefile,这个技术对于我们模块编译和分段编译有着非常大的好处。 - -例如,我们有一个子目录叫subdir,这个目录下有个Makefile文件,来指明了这个目录下文件的编译规则。那么我们总控的Makefile可以这样书写: - - subsystem: - cd subdir && $(MAKE) - -其等价于: - - subsystem: - $(MAKE) __-C __subdir - -定义$(MAKE)宏变量的意思是,也许我们的make需要一些参数,所以定义成一个变量比较利于维护。这两个例子的意思都是先进入“subdir”目录,然后执行make命令。 - -我们把这个Makefile叫做“__总控Makefile__”,**总控Makefile的变量可以传递到下级的Makefile中**(如果你显明的声明),但是不会覆盖下层的Makefile中所定义的变量,除非指定了“-e”参数。 - -如果你要传递变量到下级Makefile中,那么你可以使用这样的声明: - - __ export __; - -如果你不想让某些变量传递到下级Makefile中,那么你可以这样声明: - - __ unexport__ ; - -如: - - 示例一: - - export variable = value - - 其等价于: - - variable = value - export variable - - 其等价于: - - export **variable := value** - - 其等价于: - - variable := value - export variable - - 示例二: - - export **variable += value** - - 其等价于: - - variable += value - export variable - -如果你要传递所有的变量,那么,只要__一个export__就行了。后面什么也不用跟,表示传递所有的变量。 - -需要注意的是,有两个变量,一个是__SHELL__,一个是__MAKEFLAGS__,这两个变量不管你是否export,其__总是__要传递到下层Makefile中,特别是MAKEFILES变量,其中包含了make的参数信息,如果我们执行“总控Makefile”时有make参数或是在上层Makefile中定义了这个变量,那么MAKEFILES变量将会是这些参数,并会传递到下层Makefile中,这是一个系统级的环境变量。 - -但是make命令中的有几个参数并不往下传递,它们是“-C”,“-f”,“-h”“-o”和“-W”(有关Makefile参数的细节将在后面说明),如果你不想往下层传递参数,那么,你可以这样来: - - subsystem: - cd subdir && $(MAKE) MAKEFLAGS= - -如果你定义了环境变量MAKEFLAGS,那么你得确信其中的选项是大家都会用到的,如果其中有“-t”,“-n”,和“-q”参数,那么将会有让你意想不到的结果,或许会让你异常地恐慌。 - -还有一个在“嵌套执行”中比较有用的参数,__“-w”或是“--print-directory”__会在make的过程中输出一些信息,让你看到目前的工作目录。比如,如果我们的下级make目录是“/home/hchen/gnu/make”,如果我们使用“make -w”来执行,那么当进入该目录时,我们会看到: - - make: Entering directory `/home/hchen/gnu/make'. - -而在完成下层make后离开目录时,我们会看到: - - make: Leaving directory `/home/hchen/gnu/make' - -当你使用“-C”参数来指定make下层Makefile时,“-w”会被自动打开的。如果参数中有“-s”(“--slient”)或是“--no-print-directory”,那么,“-w”总是失效的。 - - - -五、定义命令包 - -如果Makefile中出现一些__相同命令序列__,那么我们可以为这些相同的命令序列定义一个变量。定义这种命令序列的语法以“define”开始,以“endef”结束,如: - - define run-yacc - yacc $(firstword $^) - mv y.tab.c $@ - endef - -这里,“run-yacc”是这个命令包的名字,其不要和Makefile中的变量重名。在“define”和“endef”中的两行就是命令序列。这个命令包中的第一个命令是运行Yacc程序,因为Yacc程序总是生成“y.tab.c”的文件,所以第二行的命令就是把这个文件改改名字。还是把这个命令包放到一个示例中来看看吧。 - - foo.c : foo.y - $(run-yacc) - -我们可以看见,要使用这个命令包,我们就好像使用变量一样。在这个命令包的使用中,命令包“run-yacc”中的“$^”就是“foo.y”,“$@”就是“foo.c”(有关这种以“$”开头的特殊变量,我们会在后面介绍),make在执行命令包时,命令包中的每个命令会被依次独立执行。 - - -使用变量 -———— - -在Makefile中的定义的变量,就像是C/C++语言中的宏一样,他代表了一个文本字串,在Makefile中执行的时候其会自动原模原样地展开在所使用的地方。其与C/C++所不同的是,你可以在Makefile中__改变其值__。在Makefile中,变量可以使用在“目标”,“依赖目标”,“命令”或是Makefile的其它部分中。 - -变量的命名字可以包含字符、数字,下划线(可以是数字开头),但不应该含有“:”、“#”、“=”或是空字符(空格、回车等)。变量是大小写敏感的,“foo”、“Foo”和“FOO”是三个不同的变量名。__传统的Makefile的变量名是全大写的命名方式__,但我推荐使用大小写搭配的变量名,如:MakeFlags。这样可以避免和系统的变量冲突,而发生意外的事情。 - -有一些变量是很奇怪字串,如“$<”、“$@”等,这些是自动化变量,我会在后面介绍。 - -一、变量的基础 - -变量在声明时需要给予初值,而在使用时,需要给在变量名前加上“$”符号,但最好用小括号“()”或是大括号“{}”把变量给包括起来。如果你要使用真实的“$”字符,那么你需要用__“$$”__来表示。 - -变量可以使用在许多地方,如规则中的“目标”、“依赖”、“命令”以及新的变量中。先看一个例子: - - objects = program.o foo.o utils.o - program : $(objects) - cc -o program $(objects) - - $(objects) : defs.h - -变量会在使用它的地方__精确地展开__,就像C/C++中的宏一样,例如: - - foo = c - prog.o : prog.$(foo) - $(foo)$(foo) -$(foo) prog.$(foo) - -展开后得到: - - prog.o : prog.c - cc -c prog.c - -当然,千万不要在你的Makefile中这样干,这里只是举个例子来表明Makefile中的变量在使用处展开的真实样子。可见其就是一个__“替代”__的原理。 - -另外,给变量加上括号完全是为了更加__安全地使用__这个变量,在上面的例子中,如果你不想给变量加上括号,那也可以,但我还是强烈建议你给变量加上括号。 - - -二、变量中的变量 - -在定义变量的值时,我们可以使用其它变量来构造变量的值,在Makefile中有两种方式来在用变量定义变量的值。 - -先看第一种方式,也就是简单的使用“=”号,在“=”左侧是变量,右侧是变量的值,右侧变量的值可以定义在__文件的任何一处__,也就是说,右侧中的变量不一定非要是已定义好的值,其也可以使用__后面__定义的值。如: - - foo = $(bar) - bar = $(ugh) - ugh = Huh? - - all: - echo $(foo) - -我们执行“make all”将会打出变量$(foo)的值是“Huh?”( $(foo)的值是$(bar),$(bar)的值是$(ugh),$(ugh)的值是“Huh?”)可见,变量是可以使用后面的变量来定义的。 - -这个功能有好的地方,也有不好的地方,好的地方是,我们可以把变量的真实值推到后面来定义,如: - - CFLAGS = $(include_dirs) -O - include_dirs = -Ifoo -Ibar - -当“CFLAGS”在命令中被展开时,会是“-Ifoo -Ibar -O”。但这种形式也有不好的地方,那就是递归定义,如: - - CFLAGS = $(CFLAGS) -O - - 或: - - A = $(B) - B = $(A) - -这会让make陷入无限的变量展开过程中去,当然,我们的make是有能力检测这样的定义,并会报错。还有就是如果在变量中使用函数,那么,这种方式会让我们的make运行时非常慢,更糟糕的是,他会使用得两个make的函数“wildcard”和“shell”发生不可预知的错误。因为你不会知道这两个函数会被调用多少次。 - -为了避免上面的这种方法,我们可以使用make中的另一种用变量来定义变量的方法。这种方法使用的是“:=”操作符,如: - - x := foo - y := $(x) bar - x := later - -其等价于: - - y := foo bar - x := later - -值得一提的是,这种方法,__前面的变量不能使用后面的变量__,只能使用前面__已定义__好了的变量。如果是这样: - - y := $(x) bar - x := foo - -那么,y的值是“bar”,而不是“foo bar”。 - -上面都是一些比较简单的变量使用了,让我们来看一个复杂的例子,其中包括了make的函数、条件表达式和一个系统变量“MAKELEVEL”的使用: - - ifeq (0,${MAKELEVEL}) - cur-dir := $(shell pwd) - whoami := $(shell whoami) - host-type := $(shell arch) - MAKE := ${MAKE} host-type=${host-type} whoami=${whoami} - endif - -关于条件表达式和函数,我们在后面再说,对于__系统变量“MAKELEVEL”__,其意思是,如果我们的make有一个嵌套执行的动作(参见前面的“嵌套使用make”),那么,这个变量会记录了我们的当前Makefile的__调用层数__。 - -下面再介绍两个定义变量时我们需要知道的,请先看一个例子,如果我们要定义一个变量,其__值是一个空格__,那么我们可以这样来: - - nullstring := - space := $(nullstring) # end of the line - -nullstring是一个Empty变量,其中什么也没有,而我们的space的值是一个空格。因为在操作符的右边是很难描述一个空格的,这里采用的技术很管用,先用一个Empty变量来标明变量的值开始了,而后面采用“#”注释符来表示变量定义的终止,这样,我们可以定义出其值是一个空格的变量。请注意这里关于“#”的使用,注释符“#”的这种特性值得我们注意,如果我们这样定义一个变量: - - dir := /foo/bar # directory to put the frobs in - -dir这个变量的值是“/foo/bar”,后面还**跟了4个空格**,如果我们这样使用这样变量来指定别的目录——“$(dir)/file”那么就完蛋了。 - -还有一个比较有用的操作符是“?=”,先看示例: - - FOO ?= bar - -其含义是,如果FOO没有被定义过,那么变量FOO的值就是“bar”,如果FOO先前被定义过,那么这条语将什么也不做,其等价于: - - ifeq ($(origin FOO), undefined) - FOO = bar - endif - - -三、变量高级用法 - -这里介绍两种变量的高级使用方法,第一种是__变量值的替换__。 - -我们可以替换变量中的共有的部分,其格式是“$(var:a=b)”或是“${var:a=b}”,其意思是,__把变量“var”中所有以“a”字串“结尾”的“a”替换成“b”字串__。这里的“结尾”意思是“空格”或是“结束符”。 - -还是看一个示例吧: - - foo := a.o b.o c.o - bar := $(foo:.o=.c) - -这个示例中,我们先定义了一个“$(foo)”变量,而第二行的意思是把“$(foo)”中所有以“.o”字串“结尾”全部替换成“.c”,所以我们的“$(bar)”的值就是“a.c b.c c.c”。 - -另外一种变量替换的技术是以“__静态模式__”(参见前面章节)定义的,如: - - foo := a.o b.o c.o - bar := $(foo:%.o=%.c) - -这依赖于被替换字串中的有相同的模式,模式中必须包含一个“%”字符,这个例子同样让$(bar)变量的值为“a.c b.c c.c”。 - -第二种高级用法是——“把变量的值再当成变量”。先看一个例子: - - x = y - y = z - a := $($(x)) - -在这个例子中,$(x)的值是“y”,所以$($(x))就是$(y),于是$(a)的值就是“z”。(注意,是“x=y”,而不是“x=$(y)”) - -我们还可以使用更多的层次: - - x = y - y = z - z = u - a := $($($(x))) - -这里的$(a)的值是“u”,相关的推导留给读者自己去做吧。 - -让我们再复杂一点,使用上“在变量定义中使用变量”的第一个方式,来看一个例子: - - x = $(y) - y = z - z = Hello - a := $($(x)) - -这里的$($(x))被替换成了$($(y)),因为$(y)值是“z”,所以,最终结果是:a:=$(z),也就是“Hello”。 - -再复杂一点,我们再加上函数: - - x = variable1 - variable2 := Hello - y = $(subst 1,2,$(x)) - z = y - a := $($($(z))) - -这个例子中,“$($($(z)))”扩展为“$($(y))”,而其再次被扩展为“$($(subst 1,2,$(x)))”。$(x)的值是“variable1”,subst函数把“variable1”中的所有“1”字串替换成“2”字串,于是,“variable1”变成“variable2”,再取其值,所以,最终,$(a)的值就是$(variable2)的值——“Hello”。(喔,好不容易) - -在这种方式中,或要可以使用多个变量来组成一个变量的名字,然后再取其值: - - first_second = Hello - a = first - b = second - all = $($a_$b) - -这里的“$a_$b”组成了“first_second”,于是,$(all)的值就是“Hello”。 - -再来看看结合第一种技术的例子: - - a_objects := a.o b.o c.o - 1_objects := 1.o 2.o 3.o - - sources := $($(a1)_objects:.o=.c) - -这个例子中,如果$(a1)的值是“a”的话,那么,$(sources)的值就是“a.c b.c c.c”;如果$(a1)的值是“1”,那么$(sources)的值是“1.c 2.c 3.c”。 - -再来看一个这种技术和“函数”与“条件语句”一同使用的例子: - - ifdef do_sort - func := sort - else - func := strip - endif - - bar := a d b g q c - - foo := $($(func) $(bar)) - -这个示例中,如果定义了“do_sort”,那么:foo := $(sort a d b g q c),于是$(foo)的值就是“a b c d g q”,而如果没有定义“do_sort”,那么:foo := $(sort a d b g q c),调用的就是strip函数。 - -当然,“把变量的值再当成变量”这种技术,同样可以用在操作符的左边: - - dir = foo - $(dir)_sources := $(wildcard $(dir)/*.c) - define $(dir)_print - lpr $($(dir)_sources) - endef - -这个例子中定义了三个变量:“dir”,“foo_sources”和“foo_print”。 - - -四、追加变量值 - -我们可以使用__“+=”__操作符给变量追加值,如: - - objects = main.o foo.o bar.o utils.o - objects += another.o - -于是,我们的$(objects)值变成:“main.o foo.o bar.o utils.o another.o”(another.o被追加进去了) - -使用“+=”操作符,可以模拟为下面的这种例子: - - objects = main.o foo.o bar.o utils.o - objects := $(objects) another.o - -所不同的是,用“+=”更为简洁。 - -如果变量之前没有定义过,那么,“+=”会自动变成“=”,如果前面有变量定义,那么“+=”会继承于前次操作的赋值符。如果前一次的是“:=”,那么“+=”会以“:=”作为其赋值符,如: - - variable := value - variable += more - -等价于: - - variable := value - variable := $(variable) more - -但如果是这种情况: - - variable = value - variable += more - -由于前次的赋值符是“=”,所以“+=”也会以“=”来做为赋值,那么岂不会发生变量的递补归定义,这是很不好的,所以make会自动为我们解决这个问题,我们不必担心这个问题。 - - -五、override 指示符 - -如果有变量是通常__make的命令行参数设置的,那么Makefile中对这个变量的赋值会被忽略__。如果你想在Makefile中设置这类参数的值,那么,你可以使用“override”指示符。其语法是: - - override ; = ; - - override ; := ; - -当然,你还可以追加: - - override ; += ; - -对于多行的变量定义,我们用define指示符,在define指示符前,也同样可以使用ovveride指示符,如: - - override define foo - bar - endef - - - -六、多行变量 - -还有一种设置变量值的方法是使用define关键字。使用define关键字设置变量的值可以有换行,这有利于定义__一系列的命令__(前面我们讲过“命令包”的技术就是利用这个关键字)。 - -define指示符后面跟的是变量的名字,而重起一行定义变量的值,定义是以endef关键字结束。其工作方式和“=”操作符一样。变量的值可以包含函数、命令、文字,或是其它变量。因为__命令需要以[Tab]键开头__,所以如果你用define定义的命令变量中没有以[Tab]键开头,那么make就不会把其认为是命令。 - -下面的这个示例展示了define的用法: - - define two-lines - echo foo - echo $(bar) - endef - - -七、环境变量 - -make运行时的系统环境变量可以在make开始运行时被载入到Makefile文件中,但是如果Makefile中已定义了这个变量,或是这个变量由make命令行带入,那么系统的__环境变量的值将被覆盖__。(如果make指定了“-e”参数,那么,系统环境变量将覆盖Makefile中定义的变量) - -因此,如果我们在环境变量中设置了“CFLAGS”环境变量,那么我们就可以在所有的Makefile中使用这个变量了。这对于我们使用统一的编译参数有比较大的好处。如果Makefile中定义了CFLAGS,那么则会使用Makefile中的这个变量,如果没有定义则使用系统环境变量的值,一个共性和个性的统一,很像“全局变量”和“局部变量”的特性。 - -当make嵌套调用时(参见前面的“嵌套调用”章节),上层Makefile中定义的变量会__以系统环境变量的方式__传递到下层的Makefile中。当然,默认情况下,__只有通过命令行设置的变量会被传递__。而定义在文件中的变量,如果要向下层Makefile传递,则需要使用__exprot__关键字来声明。(参见前面章节) - -当然,我并不推荐把许多的变量都定义在系统环境中,这样,在我们执行不用的Makefile时,拥有的是同一套系统变量,这可能会带来更多的麻烦。 - - -八、目标变量 - -前面我们所讲的在__Makefile中定义的变量都是“全局变量”__,在整个文件,我们都可以访问这些变量。当然,“自动化变量”除外,如“$<”等这种类量的自动化变量就属于“规则型变量”,这种变量的值依赖于规则的目标和依赖目标的定义。 - -当然,我样同样可以为某个目标设置局部变量,这种变量被称为“Target-specific Variable”,它可以和“全局变量”同名,因为它的作用范围只在这条规则以及连带规则中,所以其值也只在作用范围内有效。而不会影响规则链以外的全局变量的值。 - -其语法是: - - ; : ; - - ; : overide ; - -;可以是前面讲过的各种赋值表达式,如“=”、“:=”、“+=”或是“?=”。第二个语法是针对于make__命令行__带入的变量,或是系统环境变量。 - -这个特性非常的有用,当我们设置了这样一个变量,这个变量会作用到由这个目标所引发的所有的规则中去。如: - - prog : CFLAGS = -g - prog : prog.o foo.o bar.o - $(CC) $(CFLAGS) prog.o foo.o bar.o - - prog.o : prog.c - $(CC) $(CFLAGS) prog.c - - foo.o : foo.c - $(CC) $(CFLAGS) foo.c - - bar.o : bar.c - $(CC) $(CFLAGS) bar.c - -在这个示例中,不管全局的$(CFLAGS)的值是什么,在prog目标,以及其__所引发的所有规则中__(prog.o foo.o bar.o的规则),$(CFLAGS)的值都是“-g” - - -九、模式变量 - -在GNU的make中,还支持模式变量(Pattern-specific Variable),通过上面的目标变量中,我们知道,变量可以定义在某个目标上。模式变量的好处就是,我们可以给定一种“模式”,可以把__变量定义在符合这种模式的所有目标__上。 - -我们知道,make的“模式”一般是至少含有一个“%”的,所以,我们可以以如下方式给所有以[.o]结尾的目标定义目标变量: - - %.o : CFLAGS = -O - -同样,模式变量的语法和“目标变量”一样: - - ; : ; - - ; : override ; - -override同样是针对于系统环境传入的变量,或是make命令行指定的变量。 - - - -使用条件判断 -—————— - -使用条件判断,可以让make根据运行时的不同情况选择不同的执行分支。条件表达式可以是比较变量的值,或是比较变量和常量的值。 - -一、示例 - -下面的例子,判断$(CC)变量是否“gcc”,如果是的话,则使用GNU函数编译目标。 - - libs_for_gcc = -lgnu - normal_libs = - - foo: $(objects) - ifeq ($(CC),gcc) - $(CC) -o foo $(objects) $(libs_for_gcc) - else - $(CC) -o foo $(objects) $(normal_libs) - endif - -可见,在上面示例的这个规则中,目标“foo”可以根据变量“$(CC)”值来选取不同的函数库来编译程序。 - -我们可以从上面的示例中看到三个关键字:__ifeq、else和endif__。ifeq的意思表示条件语句的开始,并指定一个条件表达式,表达式包含两个参数,以逗号分隔,表达式以圆括号括起。else表示条件表达式为假的情况。endif表示一个条件语句的结束,任何一个条件表达式都应该以endif结束。 - -当我们的变量$(CC)值是“gcc”时,目标foo的规则是: - - foo: $(objects) - $(CC) -o foo $(objects) $(libs_for_gcc) - -而当我们的变量$(CC)值不是“gcc”时(比如“cc”),目标foo的规则是: - - foo: $(objects) - $(CC) -o foo $(objects) $(normal_libs) - -当然,我们还可以把上面的那个例子写得更简洁一些: - - libs_for_gcc = -lgnu - normal_libs = - - ifeq ($(CC),gcc) - libs=$(libs_for_gcc) - else - libs=$(normal_libs) - endif - - foo: $(objects) - $(CC) -o foo $(objects) $(libs) - - -二、语法 - -条件表达式的语法为: - - ; - ; - endif - -以及: - - ; - ; - else - ; - endif - -其中;表示条件关键字,如“ifeq”。这个关键字有四个。 - -第一个是我们前面所见过的“ifeq” - - ifeq (;, ;) - ifeq ';' ';' - ifeq ";" ";" - ifeq ";" ';' - ifeq ';' ";" - -比较参数“arg1”和“arg2”的值是否相同。当然,参数中我们还可以使用make的函数。如: - - ifeq ($(strip $(foo)),) - ; - endif - -这个示例中使用了“strip”函数,如果这个函数的返回值是空(Empty),那么;就生效。 - -第二个条件关键字是“ifneq”。语法是: - - ifneq (;, ;) - ifneq ';' ';' - ifneq ";" ";" - ifneq ";" ';' - ifneq ';' ";" - -其比较参数“arg1”和“arg2”的值是否相同,如果不同,则为真。和“ifeq”类似。 - -第三个条件关键字是“ifdef”。语法是: - - ifdef ; - -如果变量;的值非空,那到表达式为真。否则,表达式为假。当然,;同样可以是一个函数的返回值。注意,ifdef只是测试一个变量是否有值,其并不会把变量扩展到当前位置。还是来看两个例子: - - 示例一: - bar = - foo = $(bar) - ifdef foo - frobozz = yes - else - frobozz = no - endif - - 示例二: - foo = - ifdef foo - frobozz = yes - else - frobozz = no - endif - -第一个例子中,“$(frobozz)”值是“yes”,第二个则是“no”。 - -第四个条件关键字是“ifndef”。其语法是: - - ifndef ; - -这个我就不多说了,和“ifdef”是相反的意思。 - -**在;这一行上,多余的空格是被允许的**,**但是不能以[Tab]键做为开始**(不然就被认为是命令)。而注释符“#”同样也是安全的。“else”和“endif”也一样,只要不是以[Tab]键开始就行了。 - -特别注意的是,make是在读取Makefile时就计算条件表达式的值,并根据条件表达式的值来选择语句,所以,你最好不要把自动化变量(如“$@”等)放入条件表达式中,因为**自动化变量是在运行时才有的**。 - -而且,为了避免混乱,make不允许把整个条件语句分成两部分放在不同的文件中。 - - - -使用函数 -———— - -在Makefile中可以使用函数来处理变量,从而让我们的命令或是规则更为的灵活和具有智能。make所支持的函数也不算很多,不过已经足够我们的操作了。函数调用后,**函数的返回值可以当做变量来使用**。 - - -一、函数的调用语法 - -函数调用,很像变量的使用,也是以“$”来标识的,其语法如下: - - $(; ;) - -或是 - - ${; ;} - -这里,;就是函数名,make支持的函数不多。;是函数的参数,**参数间以逗号“,”分隔**,而函数名和参数之间**以“空格”分隔**。函数调用以“$”开头,以圆括号或花括号把函数名和参数括起。感觉很像一个变量,是不是?函数中的参数可以使用变量,为了风格的统一,函数和变量的括号最好一样,如使用“$(subst a,b,$(x))”这样的形式,而不是“$(subst a,b,${x})”的形式。因为统一会更清楚,也会减少一些不必要的麻烦。 - -还是来看一个示例: - - comma:= , - empty:= - space:= $(empty) $(empty) - foo:= a b c - bar:= $(subst $(space),$(comma),$(foo)) - -在这个示例中,$(comma)的值是一个逗号。$(space)使用了$(empty)定义了一个空格,$(foo)的值是“a b c”,$(bar)的定义用,调用了函数“subst”,这是一个替换函数,这个函数有三个参数,第一个参数是被替换字串,第二个参数是替换字串,第三个参数是替换操作作用的字串。这个函数也就是把$(foo)中的空格替换成逗号,所以$(bar)的值是“a,b,c”。 - - -二、字符串处理函数 - -$(subst ;,;,;) - - 名称:字符串替换函数——subst。 - 功能:把字串;中的;字符串替换成;。 - 返回:函数返回被替换过后的字符串。 - - 示例: - - $(subst ee,EE,feet on the street), - - 把“feet on the street”中的“ee”替换成“EE”,返回结果是“fEEt on the strEEt”。 - - -$(patsubst ;,;,;) - - 名称:模式字符串替换函数——patsubst。 - 功能:查找;中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式;,如果匹配的话,则以;替换。这里,;可以包括通配符“%”,表示任意长度的字串。如果;中也包含“%”,那么,;中的这个“%”将是;中的那个“%”所代表的字串。(可以用“\”来转义,以“\%”来表示真实含义的“%”字符) - 返回:函数返回被替换过后的字符串。 - - 示例: - - $(patsubst %.c,%.o,x.c.c bar.c) - - 把字串“x.c.c bar.c”符合模式[%.c]的单词替换成[%.o],返回结果是“x.c.o bar.o” - - 备注: - - 这和我们前面“变量章节”说过的相关知识有点相似。如: - - “$(var:;=;)” - 相当于 - “$(patsubst ;,;,$(var))”, - - 而“$(var: ;=;)” - 则相当于 - “$(patsubst %;,%;,$(var))”。 - - 例如有:objects = foo.o bar.o baz.o, - 那么,“$(objects:.o=.c)”和“$(patsubst %.o,%.c,$(objects))”是一样的。 - -$(strip ;) - - 名称:去空格函数——strip。 - 功能:去掉;字串中开头和结尾的空字符。 - 返回:返回被去掉空格的字符串值。 - 示例: - - $(strip a b c ) - - 把字串“a b c ”去到开头和结尾的空格,结果是“a b c”。 - -$(findstring ;,;) - - 名称:查找字符串函数——findstring。 - 功能:在字串;中查找;字串。 - 返回:如果找到,那么返回;,否则返回空字符串。 - 示例: - - $(findstring a,a b c) - $(findstring a,b c) - - 第一个函数返回“a”字符串,第二个返回“”字符串(空字符串) - -$(filter ;,;) - - 名称:过滤函数——filter。 - 功能:以;模式过滤;字符串中的单词,保留符合模式;的单词。可以有多个模式。 - 返回:返回符合模式;的字串。 - 示例: - - sources := foo.c bar.c baz.s ugh.h - foo: $(sources) - cc $(filter %.c %.s,$(sources)) -o foo - - $(filter %.c %.s,$(sources))返回的值是“foo.c bar.c baz.s”。 - -$(filter-out ;,;) - - 名称:反过滤函数——filter-out。 - 功能:以;模式过滤;字符串中的单词,去除符合模式;的单词。可以有多个模式。 - 返回:返回不符合模式;的字串。 - 示例: - - objects=main1.o foo.o main2.o bar.o - mains=main1.o main2.o - - $(filter-out $(mains),$(objects)) 返回值是“foo.o bar.o”。 - -$(sort ;) - - 名称:排序函数——sort。 - 功能:给字符串;中的单词排序(升序)。 - 返回:返回排序后的字符串。 - 示例:$(sort foo bar lose)返回“bar foo lose” 。 - 备注:sort函数会去掉;中相同的单词。 - -$(word ;,;) - - 名称:取单词函数——word。 - 功能:取字符串;中第;个单词。(从一开始) - 返回:返回字符串;中第;个单词。如果;比;中的单词数要大,那么返回空字符串。 - 示例:$(word 2, foo bar baz)返回值是“bar”。 - -$(wordlist ;,;,;) - - 名称:取单词串函数——wordlist。 - 功能:从字符串;中取从;开始到;的单词串。;和;是一个数字。 - 返回:返回字符串;中从;到;的单词字串。如果;比;中的单词数要大,那么返回空字符串。如果;大于;的单词数,那么返回从;开始,到;结束的单词串。 - 示例: $(wordlist 2, 3, foo bar baz)返回值是“bar baz”。 - -$(words ;) - - 名称:单词个数统计函数——words。 - 功能:统计;中字符串中的单词个数。 - 返回:返回;中的单词数。 - 示例:$(words, foo bar baz)返回值是“3”。 - 备注:如果我们要取;中最后的一个单词,我们可以这样:$(word $(words ;),;)。 - -$(firstword ;) - - 名称:首单词函数——firstword。 - 功能:取字符串;中的第一个单词。 - 返回:返回字符串;的第一个单词。 - 示例:$(firstword foo bar)返回值是“foo”。 - 备注:这个函数可以用word函数来实现:$(word 1,;)。 - -以上,是所有的字符串操作函数,如果搭配混合使用,可以完成比较复杂的功能。这里,举一个现实中应用的例子。我们知道,make使用“VPATH”变量来指定“依赖文件”的搜索路径。于是,我们可以利用这个搜索路径来指定编译器对头文件的搜索路径参数CFLAGS,如: - - override CFLAGS += $(patsubst %,-I%,$(subst :, ,$(VPATH))) - - 如果我们的“$(VPATH)”值是“src:../headers”,那么“$(patsubst %,-I%,$(subst :, ,$(VPATH)))”将返回“-Isrc -I../headers”,这正是cc或gcc搜索头文件路径的参数。 - - -三、文件名操作函数 - -下面我们要介绍的函数主要是处理文件名的。每个函数的参数字符串都会被当做一个或是一系列的文件名来对待。 - -$(dir ;) - - 名称:取目录函数——dir。 - 功能:从文件名序列;中取出目录部分。目录部分是指最后一个反斜杠(“/”)之前的部分。如果没有反斜杠,那么返回“./”。 - 返回:返回文件名序列;的目录部分。 - 示例: $(dir src/foo.c hacks)返回值是“src/ ./”。 - -$(notdir ;) - - 名称:取文件函数——notdir。 - 功能:从文件名序列;中取出非目录部分。非目录部分是指最后一个反斜杠(“/”)之后的部分。 - 返回:返回文件名序列;的非目录部分。 - 示例: $(notdir src/foo.c hacks)返回值是“foo.c hacks”。 - -$(suffix ;) - - 名称:取后缀函数——suffix。 - 功能:从文件名序列;中取出各个文件名的后缀。 - 返回:返回文件名序列;的后缀序列,如果文件没有后缀,则返回空字串。 - 示例:$(suffix src/foo.c src-1.0/bar.c hacks)返回值是“.c .c”。 - -$(basename ;) - - 名称:取前缀函数——basename。 - 功能:从文件名序列;中取出各个文件名的前缀部分。 - 返回:返回文件名序列;的前缀序列,如果文件没有前缀,则返回空字串。 - 示例:$(basename src/foo.c src-1.0/bar.c hacks)返回值是“src/foo src-1.0/bar hacks”。 - -$(addsuffix ;,;) - - 名称:加后缀函数——addsuffix。 - 功能:把后缀;加到;中的每个单词后面。 - 返回:返回加过后缀的文件名序列。 - 示例:$(addsuffix .c,foo bar)返回值是“foo.c bar.c”。 - -$(addprefix ;,;) - - 名称:加前缀函数——addprefix。 - 功能:把前缀;加到;中的每个单词后面。 - 返回:返回加过前缀的文件名序列。 - 示例:$(addprefix src/,foo bar)返回值是“src/foo src/bar”。 - -$(join ;,;) - - 名称:连接函数——join。 - 功能:把;中的单词对应地加到;的单词后面。如果;的单词个数要比;的多,那么,;中的多出来的单词将保持原样。如果;的单词个数要比;多,那么,;多出来的单词将被复制到;中。 - 返回:返回连接过后的字符串。 - 示例:$(join aaa bbb , 111 222 333)返回值是“aaa111 bbb222 333”。 - - gunguymadman 回复于:2004-09-16 12:24:08 - -四、foreach 函数 - - -foreach函数和别的函数非常的不一样。因为这个函数是用来做循环用的,Makefile中的foreach函数几乎是仿照于Unix标准Shell(/bin/sh)中的for语句,或是C-Shell(/bin/csh)中的foreach语句而构建的。它的语法是: - - - $(foreach ;,;,;) - - - -这个函数的意思是,把参数;中的单词逐一取出放到参数;所指定的变量中,然后再执行;所包含的表达式。每一次;会返回一个字符串,循环过程中,;的所返回的每个字符串会以空格分隔,最后当整个循环结束时,;所返回的每个字符串所组成的整个字符串(以空格分隔)将会是foreach函数的返回值。 - - - -所以,;最好是一个变量名,;可以是一个表达式,而;中一般会使用;这个参数来依次枚举;中的单词。举个例子: - - - - names := a b c d - - files := $(foreach n,$(names),$(n).o) - - - -上面的例子中,$(name)中的单词会被挨个取出,并存到变量“n”中,“$(n).o”每次根据“$(n)”计算出一个值,这些值以空格分隔,最后作为foreach函数的返回,所以,$(files)的值是“a.o b.o c.o d.o”。 - - - -注意,foreach中的;参数是一个临时的局部变量,foreach函数执行完后,参数;的变量将不在作用,其作用域只在foreach函数当中。 - - - - - -五、if 函数 - - -if函数很像GNU的make所支持的条件语句——ifeq(参见前面所述的章节),if函数的语法是: - - - - $(if ;,;) - - - -或是 - - - - $(if ;,;,;) - - - -可见,if函数可以包含“else”部分,或是不含。即if函数的参数可以是两个,也可以是三个。;参数是if的表达式,如果其返回的为非空字符串,那么这个表达式就相当于返回真,于是,;会被计算,否则;会被计算。 - - - -而if函数的返回值是,如果;为真(非空字符串),那个;会是整个函数的返回值,如果;为假(空字符串),那么;会是整个函数的返回值,此时如果;没有被定义,那么,整个函数返回空字串。 - - - -所以,;和;只会有一个被计算。 - - - - - -六、call函数 - - -call函数是唯一一个可以用来创建新的参数化的函数。你可以写一个非常复杂的表达式,这个表达式中,你可以定义许多参数,然后你可以用call函数来向这个表达式传递参数。其语法是: - - - - $(call ;,;,;,;...) - - - -当make执行这个函数时,;参数中的变量,如$(1),$(2),$(3)等,会被参数;,;,;依次取代。而;的返回值就是call函数的返回值。例如: - - reverse = $(1) $(2) - - foo = $(call reverse,a,b) - - - -那么,foo的值就是“a b”。当然,参数的次序是可以自定义的,不一定是顺序的,如: - - - - reverse = $(2) $(1) - - foo = $(call reverse,a,b) - - - -此时的foo的值就是“b a”。 - - - - - -七、origin函数 -origin函数不像其它的函数,他并不操作变量的值,他只是告诉你你的这个变量是哪里来的?其语法是: - - - $(origin ;) - - - -注意,;是变量的名字,不应该是引用。所以你最好不要在;中使用“$”字符。Origin函数会以其返回值来告诉你这个变量的“出生情况”,下面,是origin函数的返回值: - - - -“undefined” - - 如果;从来没有定义过,origin函数返回这个值“undefined”。 - - - -“default” - - 如果;是一个默认的定义,比如“CC”这个变量,这种变量我们将在后面讲述。 - - - -“environment” - - 如果;是一个环境变量,并且当Makefile被执行时,“-e”参数没有被打开。 - - - -“file” - - 如果;这个变量被定义在Makefile中。 - - - -“command line” - - 如果;这个变量是被命令行定义的。 - - - -“override” - - 如果;是被override指示符重新定义的。 - - - -“automatic” - - 如果;是一个命令运行中的自动化变量。关于自动化变量将在后面讲述。 - - - -这些信息对于我们编写Makefile是非常有用的,例如,假设我们有一个Makefile其包了一个定义文件Make.def,在Make.def中定义了一个变量“bletch”,而我们的环境中也有一个环境变量“bletch”,此时,我们想判断一下,如果变量来源于环境,那么我们就把之重定义了,如果来源于Make.def或是命令行等非环境的,那么我们就不重新定义它。于是,在我们的Makefile中,我们可以这样写: - - - - ifdef bletch - - ifeq "$(origin bletch)" "environment" - - bletch = barf, gag, etc. - - endif - - endif - - - -当然,你也许会说,使用override关键字不就可以重新定义环境中的变量了吗?为什么需要使用这样的步骤?是的,我们用override是可以达到这样的效果,可是override过于粗暴,它同时会把从命令行定义的变量也覆盖了,而我们只想重新定义环境传来的,而不想重新定义命令行传来的。 - - - - - -八、shell函数 - -shell函数也不像其它的函数。顾名思义,它的参数应该就是操作系统Shell的命令。它和反引号“`”是相同的功能。这就是说,shell函数把执行操作系统命令后的输出作为函数返回。于是,我们可以用操作系统命令以及字符串处理命令awk,sed等等命令来生成一个变量,如: - - - - contents := $(shell cat foo) - - - - files := $(shell echo *.c) - - - -注意,这个函数会新生成一个Shell程序来执行命令,所以你要注意其运行性能,如果你的Makefile中有一些比较复杂的规则,并大量使用了这个函数,那么对于你的系统性能是有害的。特别是Makefile的隐晦的规则可能会让你的shell函数执行的次数比你想像的多得多。 - - - - - -九、控制make的函数 - - -make提供了一些函数来控制make的运行。通常,你需要检测一些运行Makefile时的运行时信息,并且根据这些信息来决定,你是让make继续执行,还是停止。 - - -$(error ;) - - - - 产生一个致命的错误,;是错误信息。注意,error函数不会在一被使用就会产生错误信息,所以如果你把其定义在某个变量中,并在后续的脚本中使用这个变量,那么也是可以的。例如: - - - - 示例一: - - ifdef ERROR_001 - - $(error error is $(ERROR_001)) - - endif - - - - 示例二: - - ERR = $(error found an error!) - - .PHONY: err - - err: ; $(ERR) - - - - 示例一会在变量ERROR_001定义了后执行时产生error调用,而示例二则在目录err被执行时才发生error调用。 - - - -$(warning ;) - - - - 这个函数很像error函数,只是它并不会让make退出,只是输出一段警告信息,而make继续执行。 - - -make 的运行 -—————— - -一般来说,最简单的就是直接在命令行下输入make命令,make命令会找当前目录的makefile来执行,一切都是自动的。但也有时你也许只想让make重编译某些文件,而不是整个工程,而又有的时候你有几套编译规则,你想在不同的时候使用不同的编译规则,等等。本章节就是讲述如何使用make命令的。 - -一、make的退出码 - -make命令执行后有三个退出码: - - 0 —— 表示成功执行。 - 1 —— 如果make运行时出现任何错误,其返回1。 - 2 —— 如果你使用了make的“-q”选项,并且make使得一些目标不需要更新,那么返回2。 - -Make的相关参数我们会在后续章节中讲述。 - - -二、指定Makefile - -前面我们说过,GNU make找寻默认的Makefile的规则是在当前目录下依次找三个文件——“GNUmakefile”、“makefile”和“Makefile”。其按顺序找这三个文件,一旦找到,就开始读取这个文件并执行。 - -当前,我们也可以给make命令指定一个特殊名字的Makefile。要达到这个功能,我们要使用make的“-f”或是“--file”参数(“--makefile”参数也行)。例如,我们有个makefile的名字是“hchen.mk”,那么,我们可以这样来让make来执行这个文件: - - make –f hchen.mk - -如果在make的命令行是,你不只一次地使用了“-f”参数,那么,所有指定的makefile将会被连在一起传递给make执行。 - - -三、指定目标 - -一般来说,make的最终目标是makefile中的第一个目标,而其它目标一般是由这个目标连带出来的。这是make的默认行为。当然,一般来说,你的makefile中的第一个目标是由许多个目标组成,你可以指示make,让其完成你所指定的目标。要达到这一目的很简单,需在make命令后直接跟目标的名字就可以完成(如前面提到的“make clean”形式) - -任何在makefile中的目标都可以被指定成终极目标,但是除了以“-”打头,或是包含了“=”的目标,因为有这些字符的目标,会被解析成命令行参数或是变量。甚至没有被我们明确写出来的目标也可以成为make的终极目标,也就是说,只要make可以找到其隐含规则推导规则,那么这个隐含目标同样可以被指定成终极目标。 - -有一个make的环境变量叫“MAKECMDGOALS”,这个变量中会存放你所指定的终极目标的列表,如果在命令行上,你没有指定目标,那么,这个变量是空值。这个变量可以让你使用在一些比较特殊的情形下。比如下面的例子: - - sources = foo.c bar.c - ifneq ( $(MAKECMDGOALS),clean) - include $(sources:.c=.d) - endif - -基于上面的这个例子,只要我们输入的命令不是“make clean”,那么makefile会自动包含“foo.d”和“bar.d”这两个makefile。 - -使用指定终极目标的方法可以很方便地让我们编译我们的程序,例如下面这个例子: - - .PHONY: all - all: prog1 prog2 prog3 prog4 - -从这个例子中,我们可以看到,这个makefile中有四个需要编译的程序——“prog1”, “prog2”, “prog3”和 “prog4”,我们可以使用“make all”命令来编译所有的目标(如果把all置成第一个目标,那么只需执行“make”),我们也可以使用“make prog2”来单独编译目标“prog2”。 - -即然make可以指定所有makefile中的目标,那么也包括“伪目标”,于是我们可以根据这种性质来让我们的makefile根据指定的不同的目标来完成不同的事。在Unix世界中,软件发布时,特别是GNU这种开源软件的发布时,其makefile都包含了编译、安装、打包等功能。我们可以参照这种规则来书写我们的makefile中的目标。 - - “all” - 这个伪目标是所有目标的目标,其功能一般是编译所有的目标。 - “clean” - 这个伪目标功能是删除所有被make创建的文件。 - “install” - 这个伪目标功能是安装已编译好的程序,其实就是把目标执行文件拷贝到指定的目标中去。 - “print” - 这个伪目标的功能是例出改变过的源文件。 - “tar” - 这个伪目标功能是把源程序打包备份。也就是一个tar文件。 - “dist” - 这个伪目标功能是创建一个压缩文件,一般是把tar文件压成Z文件。或是gz文件。 - “TAGS” - 这个伪目标功能是更新所有的目标,以备完整地重编译使用。 - “check”和“test” - 这两个伪目标一般用来测试makefile的流程。 - -当然一个项目的makefile中也不一定要书写这样的目标,这些东西都是GNU的东西,但是我想,GNU搞出这些东西一定有其可取之处(等你的UNIX下的程序文件一多时你就会发现这些功能很有用了),这里只不过是说明了,如果你要书写这种功能,最好使用这种名字命名你的目标,这样规范一些,规范的好处就是——不用解释,大家都明白。而且如果你的makefile中有这些功能,一是很实用,二是可以显得你的makefile很专业(不是那种初学者的作品)。 - - -四、检查规则 - -有时候,我们不想让我们的makefile中的规则执行起来,我们只想检查一下我们的命令,或是执行的序列。于是我们可以使用make命令的下述参数: - - “-n” - “--just-print” - “--dry-run” - “--recon” - 不执行参数,这些参数只是打印命令,不管目标是否更新,把规则和连带规则下的命令打印出来,但不执行,这些参数对于我们调试makefile很有用处。 - - “-t” - “--touch” - 这个参数的意思就是把目标文件的时间更新,但不更改目标文件。也就是说,make假装编译目标,但不是真正的编译目标,只是把目标变成已编译过的状态。 - - “-q” - “--question” - 这个参数的行为是找目标的意思,也就是说,如果目标存在,那么其什么也不会输出,当然也不会执行编译,如果目标不存在,其会打印出一条出错信息。 - - “-W ;” - “--what-if=;” - “--assume-new=;” - “--new-file=;” - 这个参数需要指定一个文件。一般是是源文件(或依赖文件),Make会根据规则推导来运行依赖于这个文件的命令,一般来说,可以和“-n”参数一同使用,来查看这个依赖文件所发生的规则命令。 - -另外一个很有意思的用法是结合“-p”和“-v”来输出makefile被执行时的信息(这个将在后面讲述)。 - - -五、make的参数 - -下面列举了所有GNU make 3.80版的参数定义。其它版本和产商的make大同小异,不过其它产商的make的具体参数还是请参考各自的产品文档。 - -“-b” -“-m” -这两个参数的作用是忽略和其它版本make的兼容性。 - -“-B” -“--always-make” -认为所有的目标都需要更新(重编译)。 - -“-C

;” -“--directory=;” -指定读取makefile的目录。如果有多个“-C”参数,make的解释是后面的路径以前面的作为相对路径,并以最后的目录作为被指定目录。如:“make –C ~hchen/test –C prog”等价于“make –C ~hchen/test/prog”。 - -“—debug[=;]” -输出make的调试信息。它有几种不同的级别可供选择,如果没有参数,那就是输出最简单的调试信息。下面是;的取值: - a —— 也就是all,输出所有的调试信息。(会非常的多) - b —— 也就是basic,只输出简单的调试信息。即输出不需要重编译的目标。 - v —— 也就是verbose,在b选项的级别之上。输出的信息包括哪个makefile被解析,不需要被重编译的依赖文件(或是依赖目标)等。 - i —— 也就是implicit,输出所以的隐含规则。 - j —— 也就是jobs,输出执行规则中命令的详细信息,如命令的PID、返回码等。 - m —— 也就是makefile,输出make读取makefile,更新makefile,执行makefile的信息。 - -“-d” -相当于“--debug=a”。 - -“-e” -“--environment-overrides” -指明环境变量的值覆盖makefile中定义的变量的值。 - -“-f=;” -“--file=;” -“--makefile=;” -指定需要执行的makefile。 - -“-h” -“--help” -显示帮助信息。 - -“-i” -“--ignore-errors” -在执行时忽略所有的错误。 - -“-I ;” -“--include-dir=;” -指定一个被包含makefile的搜索目标。可以使用多个“-I”参数来指定多个目录。 - -“-j [;]” -“--jobs[=;]” -指同时运行命令的个数。如果没有这个参数,make运行命令时能运行多少就运行多少。如果有一个以上的“-j”参数,那么仅最后一个“-j”才是有效的。(注意这个参数在MS-DOS中是无用的) - -“-k” -“--keep-going” -出错也不停止运行。如果生成一个目标失败了,那么依赖于其上的目标就不会被执行了。 - -“-l ;” -“--load-average[=;]” -指定make运行命令的负载。 - -“-n” -“--just-print” -“--dry-run” -“--recon” -仅输出执行过程中的命令序列,但并不执行。 - -“-o ;” -“--old-file=;” -“--assume-old=;” -不重新生成的指定的;,即使这个目标的依赖文件新于它。 - -“-p” -“--print-data-base” -输出makefile中的所有数据,包括所有的规则和变量。这个参数会让一个简单的makefile都会输出一堆信息。如果你只是想输出信息而不想执行makefile,你可以使用“make -qp”命令。如果你想查看执行makefile前的预设变量和规则,你可以使用“make –p –f /dev/null”。这个参数输出的信息会包含着你的makefile文件的文件名和行号,所以,用这个参数来调试你的makefile会是很有用的,特别是当你的环境变量很复杂的时候。 - -“-q” -“--question” -不运行命令,也不输出。仅仅是检查所指定的目标是否需要更新。如果是0则说明要更新,如果是2则说明有错误发生。 - -“-r” -“--no-builtin-rules” -禁止make使用任何隐含规则。 - -“-R” -“--no-builtin-variabes” -禁止make使用任何作用于变量上的隐含规则。 - -“-s” -“--silent” -“--quiet” -在命令运行时不输出命令的输出。 - -“-S” -“--no-keep-going” -“--stop” -取消“-k”选项的作用。因为有些时候,make的选项是从环境变量“MAKEFLAGS”中继承下来的。所以你可以在命令行中使用这个参数来让环境变量中的“-k”选项失效。 - -“-t” -“--touch” -相当于UNIX的touch命令,只是把目标的修改日期变成最新的,也就是阻止生成目标的命令运行。 - -“-v” -“--version” -输出make程序的版本、版权等关于make的信息。 - -“-w” -“--print-directory” -输出运行makefile之前和之后的信息。这个参数对于跟踪嵌套式调用make时很有用。 - -“--no-print-directory” -禁止“-w”选项。 - -“-W ;” -“--what-if=;” -“--new-file=;” -“--assume-file=;” -假定目标;需要更新,如果和“-n”选项使用,那么这个参数会输出该目标更新时的运行动作。如果没有“-n”那么就像运行UNIX的“touch”命令一样,使得;的修改时间为当前时间。 - -“--warn-undefined-variables” -只要make发现有未定义的变量,那么就输出警告信息。 - - -隐含规则 -———— - -在我们使用Makefile时,有一些我们会经常使用,而且使用频率非常高的东西,比如,我们编译C/C++的源程序为中间目标文件(Unix下是[.o]文件,Windows下是[.obj]文件)。本章讲述的就是一些在Makefile中的“隐含的”,早先约定了的,不需要我们再写出来的规则。 - -“隐含规则”也就是一种惯例,make会按照这种“惯例”心照不喧地来运行,那怕我们的Makefile中没有书写这样的规则。例如,把[.c]文件编译成[.o]文件这一规则,你根本就不用写出来,make会自动推导出这种规则,并生成我们需要的[.o]文件。 - -“隐含规则”会使用一些我们__系统变量__,我们可以改变这些系统变量的值来定制隐含规则的运行时的参数。如系统变量“CFLAGS”可以控制编译时的编译器参数。 - -我们还可以通过“模式规则”的方式写下自己的隐含规则。用“后缀规则”来定义隐含规则会有许多的限制。使用“模式规则”会更回得智能和清楚,但“后缀规则”可以用来保证我们Makefile的兼容性。 -我们了解了__“隐含规则”__,可以让其为我们更好的服务,也会让我们知道一些“约定俗成”了的东西,而不至于使得我们在运行Makefile时出现一些我们觉得莫名其妙的东西。当然,任何事物都是矛盾的,水能载舟,亦可覆舟,所以,有时候“隐含规则”也会给我们造成不小的麻烦。只有了解了它,我们才能更好地使用它。 - - -一、使用隐含规则 - -如果要使用隐含规则生成你需要的目标,你所需要做的就是不要写出这个目标的规则。那么,make会试图去自动推导产生这个目标的规则和命令,如果make可以自动推导生成这个目标的规则和命令,那么这个行为就是隐含规则的自动推导。当然,隐含规则是make事先约定好的一些东西。例如,我们有下面的一个Makefile: - - foo : foo.o bar.o - cc –o foo foo.o bar.o $(CFLAGS) $(LDFLAGS) - -我们可以注意到,这个Makefile中并没有写下如何生成foo.o和bar.o这两目标的规则和命令。因为make的“隐含规则”功能会自动为我们自动去推导这两个目标的依赖目标和生成命令。 - -make会在自己的“隐含规则”库中寻找可以用的规则,如果找到,那么就会使用。如果找不到,那么就会报错。在上面的那个例子中,make调用的隐含规则是,把[.o]的目标的依赖文件置成[.c],并使用C的编译命令__“cc –c $(CFLAGS) __[.c]”来生成[.o]的目标。也就是说,我们完全没有必要写下下面的两条规则: - - foo.o : foo.c - cc –c foo.c $(CFLAGS) - bar.o : bar.c - cc –c bar.c $(CFLAGS) - -因为,这已经是“约定”好了的事了,make和我们约定好了用C编译器“cc”生成[.o]文件的规则,这就是隐含规则。 - -当然,如果我们为[.o]文件书写了自己的规则,那么make就不会自动推导并调用隐含规则,它会按照我们写好的规则忠实地执行。 - -还有,在make的“隐含规则库”中,每一条隐含规则都在库中有其__顺序__,越靠前的则是越被经常使用的,所以,这会导致我们有些时候即使我们显示地指定了目标依赖,make也不会管。如下面这条规则(没有命令): - - foo.o : foo.p - -依赖文件“foo.p”(Pascal程序的源文件)有可能变得没有意义。如果目录下存在了“foo.c”文件,那么我们的隐含规则一样会生效,并会通过“foo.c”调用C的编译器生成foo.o文件。因为,在隐含规则中,Pascal的规则出现在C的规则之后,所以,make找到可以生成foo.o的C的规则就不再寻找下一条规则了。如果你确实不希望任何隐含规则推导,那么,你就不要只写出“依赖规则”,而不写命令。 - - -二、隐含规则一览 - -这里我们将讲述所有预先设置(也就是make内建)的隐含规则,如果我们不明确地写下规则,那么,make就会在这些规则中寻找所需要规则和命令。当然,我们也可以使用make的参数“-r”或“--no-builtin-rules”选项来取消所有的预设置的隐含规则。 - - -当然,即使是我们指定了“-r”参数,某些隐含规则还是会生效,因为有许多的隐含规则都是使用了“**后缀规则**”来定义的,所以,只要隐含规则中有“后缀列表”(也就一系统定义在目标.SUFFIXES的**依赖目标**),那么隐含规则就会生效。默认的后缀列表是:.out, .a, .ln, .o, .c, .cc, .C, .p, .f, .F, .r, .y, .l, .s, .S, .mod, .sym, .def, .h, .info, .dvi, .tex, .texinfo, .texi, .txinfo, .w, .ch .web, .sh, .elc, .el。具体的细节,我们会在后面讲述。 - -还是先来看一看常用的隐含规则吧。 - -1、编译C程序的隐含规则。 -“;.o”的目标的依赖目标会自动推导为“;.c”,并且其生成命令是“$(CC) –c $(CPPFLAGS) $(CFLAGS)” - -2、编译C++程序的隐含规则。 -“;.o”的目标的依赖目标会自动推导为“;.cc”或是“;.C”,并且其生成命令是“$(CXX) –c $(CPPFLAGS) $(CFLAGS)”。(建议使用“.cc”作为C++源文件的后缀,而不是“.C”) - -3、编译Pascal程序的隐含规则。 -“;.o”的目标的依赖目标会自动推导为“;.p”,并且其生成命令是“$(PC) –c $(PFLAGS)”。 - -4、编译Fortran/Ratfor程序的隐含规则。 -“;.o”的目标的依赖目标会自动推导为“;.r”或“;.F”或“;.f”,并且其生成命令是: - “.f” “$(FC) –c $(FFLAGS)” - “.F” “$(FC) –c $(FFLAGS) $(CPPFLAGS)” - “.f” “$(FC) –c $(FFLAGS) $(RFLAGS)” - -5、预处理Fortran/Ratfor程序的隐含规则。 -“;.f”的目标的依赖目标会自动推导为“;.r”或“;.F”。这个规则只是转换Ratfor或有预处理的Fortran程序到一个标准的Fortran程序。其使用的命令是: - “.F” “$(FC) –F $(CPPFLAGS) $(FFLAGS)” - “.r” “$(FC) –F $(FFLAGS) $(RFLAGS)” - -6、编译Modula-2程序的隐含规则。 -“;.sym”的目标的依赖目标会自动推导为“;.def”,并且其生成命令是:“$(M2C) $(M2FLAGS) $(DEFFLAGS)”。“;” 的目标的依赖目标会自动推导为“;.mod”,并且其生成命令是:“$(M2C) $(M2FLAGS) $(MODFLAGS)”。 - -7、汇编和汇编预处理的隐含规则。 -“;.o” 的目标的依赖目标会自动推导为“;.s”,默认使用编译品“as”,并且其生成命令是:“$(AS) $(ASFLAGS)”。“;.s” 的目标的依赖目标会自动推导为“;.S”,默认使用C预编译器“cpp”,并且其生成命令是:“$(AS) $(ASFLAGS)”。 - -8、链接Object文件的隐含规则。 -“;”目标依赖于“;.o”,通过运行C的编译器来运行链接程序生成(一般是“ld”),其生成命令是:“$(CC) $(LDFLAGS) ;.o $(LOADLIBES) $(LDLIBS)”。这个规则对于只有一个源文件的工程有效,同时也对多个Object文件(由不同的源文件生成)的也有效。例如如下规则: - - x : y.o z.o - -并且“x.c”、“y.c”和“z.c”都存在时,隐含规则将执行如下命令: - - cc -c x.c -o x.o - cc -c y.c -o y.o - cc -c z.c -o z.o - cc x.o y.o z.o -o x - rm -f x.o - rm -f y.o - rm -f z.o - -如果没有一个源文件(如上例中的x.c)和你的目标名字(如上例中的x)相关联,那么,你最好写出自己的生成规则,不然,隐含规则会报错的。 - -9、Yacc C程序时的隐含规则。 -“;.c”的依赖文件被自动推导为“n.y”(Yacc生成的文件),其生成命令是:“$(YACC) $(YFALGS)”。(“Yacc”是一个语法分析器,关于其细节请查看相关资料) - -10、Lex C程序时的隐含规则。 -“;.c”的依赖文件被自动推导为“n.l”(Lex生成的文件),其生成命令是:“$(LEX) $(LFALGS)”。(关于“Lex”的细节请查看相关资料) - -11、Lex Ratfor程序时的隐含规则。 -“;.r”的依赖文件被自动推导为“n.l”(Lex生成的文件),其生成命令是:“$(LEX) $(LFALGS)”。 - -12、从C程序、Yacc文件或Lex文件创建Lint库的隐含规则。 -“;.ln” (lint生成的文件)的依赖文件被自动推导为“n.c”,其生成命令是:“$(LINT) $(LINTFALGS) $(CPPFLAGS) -i”。对于“;.y”和“;.l”也是同样的规则。 - - -三、隐含规则使用的变量 - -在隐含规则中的命令中,基本上都是使用了一些预先设置的变量。你可以在你的__makefile中__改变这些变量的值,或是在__make的命令行__中传入这些值,或是在你的__环境变量__中设置这些值,无论怎么样,只要设置了这些特定的变量,那么其就会对隐含规则起作用。当然,你也可以利用make的“-R”或“--no–builtin-variables”参数来取消你所定义的变量对隐含规则的作用。 - -例如,第一条隐含规则——编译C程序的隐含规则的命令是“$(CC) –c $(CFLAGS) $(CPPFLAGS)”。Make默认的编译命令是“cc”,如果你把变量“$(CC)”重定义成“gcc”,把变量“$(CFLAGS)”重定义成“-g”,那么,隐含规则中的命令全部会以“gcc –c -g $(CPPFLAGS)”的样子来执行了。 - -我们可以把隐含规则中使用的变量分成两种:一种是命令相关的,如“CC”;一种是参数相的关,如“CFLAGS”。下面是所有隐含规则中会用到的变量: - -1、关于命令的变量。 - -AR - 函数库打包程序。默认命令是“ar”。 -AS - 汇编语言编译程序。默认命令是“as”。 -CC - C语言编译程序。默认命令是“cc”。 -CXX - C++语言编译程序。默认命令是“g++”。 -CO - 从 RCS文件中扩展文件程序。默认命令是“co”。 -CPP - C程序的预处理器(输出是标准输出设备)。默认命令是“$(CC) –E”。 -FC - Fortran 和 Ratfor 的编译器和预处理程序。默认命令是“f77”。 -GET - 从SCCS文件中扩展文件的程序。默认命令是“get”。 -LEX - Lex方法分析器程序(针对于C或Ratfor)。默认命令是“lex”。 -PC - Pascal语言编译程序。默认命令是“pc”。 -YACC - Yacc文法分析器(针对于C程序)。默认命令是“yacc”。 -YACCR - Yacc文法分析器(针对于Ratfor程序)。默认命令是“yacc –r”。 -MAKEINFO - 转换Texinfo源文件(.texi)到Info文件程序。默认命令是“makeinfo”。 -TEX - 从TeX源文件创建TeX DVI文件的程序。默认命令是“tex”。 -TEXI2DVI - 从Texinfo源文件创建军TeX DVI 文件的程序。默认命令是“texi2dvi”。 -WEAVE - 转换Web到TeX的程序。默认命令是“weave”。 -CWEAVE - 转换C Web 到 TeX的程序。默认命令是“cweave”。 -TANGLE - 转换Web到Pascal语言的程序。默认命令是“tangle”。 -CTANGLE - 转换C Web 到 C。默认命令是“ctangle”。 -RM - 删除文件命令。默认命令是“rm –f”。 - -2、关于命令参数的变量 - -下面的这些变量都是相关上面的命令的参数。如果没有指明其默认值,那么其默认值都是空。 - -ARFLAGS - 函数库打包程序AR命令的参数。默认值是“rv”。 -ASFLAGS - 汇编语言编译器参数。(当明显地调用“.s”或“.S”文件时)。 -CFLAGS - C语言编译器参数。 -CXXFLAGS - C++语言编译器参数。 -COFLAGS - RCS命令参数。 -CPPFLAGS - C预处理器参数。( C 和 Fortran 编译器也会用到)。 -FFLAGS - Fortran语言编译器参数。 -GFLAGS - SCCS “get”程序参数。 -LDFLAGS - 链接器参数。(如:“ld”) -LFLAGS - Lex文法分析器参数。 -PFLAGS - Pascal语言编译器参数。 -RFLAGS - Ratfor 程序的Fortran 编译器参数。 -YFLAGS - Yacc文法分析器参数。 - - -四、隐含规则链 - -有些时候,一个目标可能被一系列的隐含规则所作用。例如,一个[.o]的文件生成,可能会是先被Yacc的[.y]文件先成[.c],然后再被C的编译器生成。我们把这一系列的隐含规则叫做“__隐含规则链__”。 - -在上面的例子中,如果文件[.c]存在,那么就直接调用C的编译器的隐含规则,如果没有[.c]文件,但有一个[.y]文件,那么Yacc的隐含规则会被调用,生成[.c]文件,然后,再调用C编译的隐含规则最终由[.c]生成[.o]文件,达到目标。 - -我们把这种[.c]的文件(或是目标),叫做__中间目标__。不管怎么样,make会努力自动推导生成目标的一切方法,不管中间目标有多少,其都会执着地把所有的隐含规则和你书写的规则全部合起来分析,努力达到目标,所以,有些时候,可能会让你觉得奇怪,怎么我的目标会这样生成?怎么我的makefile发疯了? - -在默认情况下,对于中间目标,它和一般的目标有两个地方所不同:第一个不同是除非中间的目标不存在,才会引发中间规则。第二个不同的是,只要目标成功产生,那么,产生最终目标过程中,所产生的中间目标文件会被以“rm -f”删除。 - -通常,一个被makefile指定成目标或是依赖目标的文件不能被当作中介。然而,你可以明显地说明一个文件或是目标是中介目标,你可以使用伪目标“.INTERMEDIATE”来强制声明。(如:.INTERMEDIATE : mid ) - -你也可以阻止make自动删除中间目标,要做到这一点,你可以使用伪目标“.SECONDARY”来强制声明(如:.SECONDARY : sec)。你还可以把你的目标,以模式的方式来指定(如:%.o)成伪目标“.PRECIOUS”的依赖目标,以保存被隐含规则所生成的中间文件。 - -在“隐含规则链”中,禁止同一个目标出现两次或两次以上,这样一来,就可防止在make自动推导时出现无限递归的情况。 - -Make会优化一些特殊的隐含规则,而不生成中间文件。如,从文件“foo.c”生成目标程序“foo”,按道理,make会编译生成中间文件“foo.o”,然后链接成“foo”,但在实际情况下,这一动作可以被一条“cc”的命令完成(cc –o foo foo.c),于是优化过的规则就不会生成中间文件。 - - - -五、定义模式规则 - -你可以__使用模式规则来定义一个隐含规则__。一个模式规则就好像一个一般的规则,只是在规则中,目标的定义需要有"%"字符。 -"%"的意思是表示**一个或多个**任意字符。在依赖目标中同样可以使用"%",只是**依赖目标中的"%"的取值,取决于其目标**。 - -有一点需要注意的是,"%"的展开发生在变量和函数的展开之后,变量和函数的展开发生在make载入Makefile时,而模式规则中的"%"则发生在运行时。 - - -1、模式规则介绍 - -模式规则中,至少在规则的目标定义中要包含"%",否则,就是一般的规则。目标中的"%"定义表示对文件名的匹配,"%"表示长度任意的**非空字符串**。例如:"%.c"表示以".c"结尾的文件名(文件名的长度至少为3),而"s.%.c"则表示以"s."开头,".c"结尾的文件名(文件名的长度至少为5)。 - -如果"%"定义在目标中,那么,目标中的"%"的值决定了依赖目标中的"%"的值,也就是说,目**标中的模式的"%"决定了依赖目标中"%"的样子**。例如有一个模式规则如下: - - %.o : %.c ; ; - -其含义是,指出了怎么从所有的[.c]文件生成相应的[.o]文件的规则。如果要生成的目标是"a.o b.o",那么"%c"就是"a.c b.c"。 - -一旦依赖目标中的"%"模式被确定,那么,make会被要求去匹配当前目录下所有的文件名,一旦找到,make就会规则下的命令,所以,在模式规则中,目标可能会是多个的,如果有模式匹配出多个目标,make就会产生所有的模式目标,此时,make关心的是依赖的文件名和生成目标的命令这两件事。 - - -2、模式规则示例 - -下面这个例子表示了,把所有的[.c]文件都编译成[.o]文件. - - %.o : %.c - $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ - -其中,"__$@"表示所有的目标的挨个值,"$<"表示了所有依赖目标的挨个值__。这些奇怪的变量我们叫"自动化变量",后面会详细讲述。 - -下面的这个例子中有两个目标是模式的: - - %.tab.c %.tab.h: %.y - bison -d $< - -这条规则告诉make把所有的[.y]文件都以"bison -d ;.y"执行,然后生成";.tab.c"和";.tab.h"文件。(其中,";"表示一个任意字符串)。如果我们的执行程序"foo"依赖于文件"parse.tab.o"和"scan.o",并且文件"scan.o"依赖于文件"parse.tab.h",如果"parse.y"文件被更新了,那么根据上述的规则,"bison -d parse.y"就会被执行一次,于是,"parse.tab.o"和"scan.o"的依赖文件就齐了。(假设,"parse.tab.o"由"parse.tab.c"生成,和"scan.o"由"scan.c"生成,而"foo"由"parse.tab.o"和"scan.o"链接生成,而且foo和其[.o]文件的依赖关系也写好,那么,所有的目标都会得到满足) - - -3、自动化变量 - -在上述的模式规则中,目标和依赖文件都是一系例的文件,那么我们如何书写一个命令来完成从不同的依赖文件生成相应的目标?因为在每一次的对模式规则的解析时,都会是不同的目标和依赖文件。 - -__自动化变量__就是完成这个功能的。在前面,我们已经对自动化变量有所提涉,相信你看到这里已对它有一个感性认识了。所谓自动化变量,就是这种变量会把模式中所定义的一系列的文件自动地挨个取出,直至所有的符合模式的文件都取完了。这种自动化变量只应出现在规则的命令中。 - -下面是所有的自动化变量及其说明: - -$@ - 表示规则中的__目标文件集__。在模式规则中,如果有多个目标,那么,"$@"就是匹配于目标中模式定义的集合。 - -$% - 仅当目标是函数库文件中,表示规则中的__目标成员名__。例如,如果一个目标是__"foo.a(bar.o)"__,那么,"$%"就是"bar.o","$@"就是"foo.a"。如果目标不是函数库文件(Unix下是[.a],Windows下是[.lib]),那么,其值为空。 - -$< - __ 依赖目标__中的第一个目标名字。如果依赖目标是以模式(即"%")定义的,那么"$<"将是符合模式的一系列的文件集。注意,其是一个一个取出来的。 - -$? - 所有**比目标新**的依赖目标的集合。以空格分隔。 - -$^ - 所有的__依赖目标的集合__。以空格分隔。如果在依赖目标中有多个重复的,那个这个变量会去除重复的依赖目标,只保留一份。 - -$+ - 这个变量很像"$^",也是所有依赖目标的集合。只是它不去除重复的依赖目标。 - -$* - 这个变量表示目标模式中"%"及其之前的部分。如果目标是"dir/a.foo.b",并且目标的模式是"a.%.b",那么,"$*"的值就是"dir/a.foo"。这个变量对于构造有关联的文件名是比较有较。如果目标中没有模式的定义,那么"$*"也就不能被推导出,但是,如果目标文件的后缀是make所识别的,那么"$*"就是除了后缀的那一部分。例如:如果目标是"foo.c",因为".c"是make所能识别的后缀名,所以,"$*"的值就是"foo"。这个特性是GNU make的,很有可能不兼容于其它版本的make,所以,你应该尽量避免使用"$*",除非是在隐含规则或是静态模式中。如果目标中的后缀是make所不能识别的,那么"$*"就是空值。 - -当你希望只对更新过的依赖文件进行操作时,"$?"在显式规则中很有用,例如,假设有一个函数库文件叫"lib",其由其它几个object文件更新。那么把object文件打包的比较有效率的Makefile规则是: - - lib : foo.o bar.o lose.o win.o - ar r lib $? - -在上述所列出来的自动量变量中。四个变量($@、$<、$%、$*)在扩展时只会有一个文件,而另三个的值是一个文件列表。这七个自动化变量还可以取得文件的目录名或是在当前目录下的符合模式的文件名,只需要搭配上"D"或"F"字样。这是GNU make中老版本的特性,在新版本中,我们使用函数"dir"或"notdir"就可以做到了。"D"的含义就是Directory,就是目录,"F"的含义就是File,就是文件。 - -下面是对于上面的七个变量分别加上"D"或是"F"的含义: - -$(@D) - 表示"$@"的目录部分(不以斜杠作为结尾),如果"$@"值是"dir/foo.o",那么"$(@D)"就是"dir",而如果"$@"中没有包含斜杠的话,其值就是"."(当前目录)。 - -$(@F) - 表示"$@"的文件部分,如果"$@"值是"dir/foo.o",那么"$(@F)"就是"foo.o","$(@F)"相当于函数"$(notdir $@)"。 - -"$(*D)" -"$(*F)" - 和上面所述的同理,也是取文件的目录部分和文件部分。对于上面的那个例子,"$(*D)"返回"dir",而"$(*F)"返回"foo" - -"$(%D)" -"$(%F)" - 分别表示了函数包文件成员的目录部分和文件部分。这对于形同"archive(member)"形式的目标中的"member"中包含了不同的目录很有用。 - -"$(的方法来覆盖。 其它的预定义目录还包括:bindir = $(prefix)/bin, libdir = $(prefix)/lib, **datadir** = $(prefix)/share, **sysconfdir** = $(prefix)/etc等等。 2) 定义一个新的安装路径 - 比如test, 可定义testdir = $(prefix)/test, 然后test_DATA =test1 test2,则test1,test2会作为数据文件安装到$(prefix)/test目录下。 我们首先需要在工程//顶层目录//下(即project/)创建一个Makefile.am来指明包含的子目录: -__SUBDIRS__=src/lib src/ModuleA/apple/shell src/ModuleA/apple/core +__SUBDIRS__=src/lib src/ModuleA/apple/shell src/ModuleA/apple/core **CURRENTPATH**=$(shell /bin/pwd) #makefile.am采用的是makefile语法 **INCLUDES=**-I$(CURRENTPATH)/src/include -I$(CURRENTPATH)/src/ModuleA/apple/include **export **INCLUDES -SUBDIRS指出了子目录中包含makefile.am。 - -由于每个源文件都会用到相同的头文件,所以我们在最顶层的Makefile.am中包含了编译源文件时所用到的头文件,并导出,见蓝色部分代码。 +SUBDIRS指出了子目录中包含makefile.am。由于每个源文件都会用到相同的头文件,所以我们在最顶层的Makefile.am中包含了编译源文件时所用到的头文件,并导出. 我们将lib目录下的swap.c文件编译成libswap.a文件,被apple/shell/apple.c文件调用,那么lib目录下的Makefile.am如下所示: - **noinst**_LIBRARIES=__libswap.a__ libswap_a_SOURCES=swap.c INCLUDES=__-I$(top_srcdir)__/src/includ - 细心的读者可能就会问:怎么表1中给出的是bin_LIBRARIES,而这里是noinst_LIBRARIES?这是因为如果只想编译,而不想安装到系统中,就用noinst_LIBRARIES代替bin_LIBRARIES,对于可执行文件就用noinst_PROGRAMS代替bin_PROGRAMS。对于安装的情况,库将会安装到$(prefix)/lib目录下,可执行文件将会安装到${prefix}/bin。如果想安装该库,则Makefile.am示例如下: bin_LIBRARIES=libswap.a @@ -218,7 +211,7 @@ INCLUDES=-I$(top_srcdir)/src/include 最后两行的意思是将swap.h安装到${prefix}/include /swap目录下。 -接下来,对于**可执行文件类型**的情况,我们将讨论如何写Makefile.am?对于编译apple/core目录下的文件,我们写成的Makefile.am如下所示: +接下来,对于**可执行文件类型**的情况,我们将讨论如何写Makefile.am。对于编译apple/core目录下的文件,我们写成的Makefile.am如下所示: noinst_PROGRAMS=test test_SOURCES=test.c @@ -229,7 +222,7 @@ DEFS+=-D_GNU_SOURCE DEFS变量继承自autoconf,其内容会传给编译器,作为编译标志。 -由于我们的test.c文件在**链接时**,需要apple.o和libswap.a文件,所以我们需要在test_LDADD中包含这两个文件。对于Linux下的信号量/读写锁文件进行编译,需要在编译选项中指明-D_GNU_SOURCE,所以在test_LDFLAGS中指明。而test_LDFLAGS只是链接时的选项,**编译时同样需要指明该选项**,所以需要__DEFS来指明编译选项__,由于DEFS**已经有初始值**,所以这里用+=的形式指明。从这里可以看出,Makefile.am中的语法与Makefile的语法一致,也可以采用条件表达式。如果你的程序还包含其他的库,除了用AC_CHECK_LIB宏来指明外,还可以用LIBS来指明。 +由于我们的test.c文件在**链接时**,需要apple.o和libswap.a文件,所以我们需要在test_LDADD中包含这两个文件。对于Linux下的信号量/读写锁文件进行编译,需要在编译选项中指明-D_GNU_SOURCE,所以在test_LDFLAGS中指明。而test_LDFLAGS只是链接时的选项,**编译时同样需要指明该选项**,所以需要__DEFS来指明编译选项__,由于DEFS**已经有初始值**,所以这里用__+=__的形式指明。从这里可以看出,Makefile.am中的语法与Makefile的语法一致,也可以采用条件表达式。如果你的程序还包含其他的库,除了用AC_CHECK_LIB宏来指明外,还可以用LIBS来指明。 如果你只想编译某一个文件,那么Makefile.am如何写呢?这个文件也很简单,写法跟可执行文件的差不多,如下例所示: @@ -237,7 +230,6 @@ noinst_PROGRAMS=apple apple_SOURCES=apple.c DEFS+=-D_GNU_SOURCE - 我们这里只是欺骗automake,假装要生成apple文件,让它为我们**生成依赖关系和执行命令**。所以当你运行完automake命令后,然后修改apple/shell/下的**Makefile.in**文件,直接将LINK语句删除,即: ……. @@ -245,8 +237,6 @@ clean-noinstPROGRAMS: -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) apple$(EXEEXT): $(apple_OBJECTS) $(apple_DEPENDENCIES) @rm -f apple$(EXEEXT) -#$(LINK) $(apple_LDFLAGS) $(apple_OBJECTS) $(apple_LDADD) $(LIBS) -……. - +#$(LINK) $(apple_LDFLAGS) $(apple_OBJECTS) $(apple_LDADD) __$(LIBS)__ 通过上述处理,就可以达到我们的目的。从图1中不难看出为什么要修改Makefile.in的原因,而不是修改其他的文件。 diff --git a/Zim/Utils/工具链/autoconf---automake/Autoconf学习笔记.txt b/Zim/Utils/工具链/autoconf---automake/Autoconf学习笔记.txt index fc80e98..1c4db4f 100644 --- a/Zim/Utils/工具链/autoconf---automake/Autoconf学习笔记.txt +++ b/Zim/Utils/工具链/autoconf---automake/Autoconf学习笔记.txt @@ -7,35 +7,33 @@ Created Thursday 14 June 2012 http://lyanry.itpub.net/ **Autoconf是什么?** - 一 位物理学家、一位工程师和一位计算机科学家,三个人在讨论上帝是个什么样的人。物理学家说:“它老人家肯定是物理学家,因为在创世之初,上帝制造了光;你 们是知道的,麦克斯韦方程,电磁波的波粒二相性,相对论……“。工程师不干了:“它老人家肯定是一位工程师,因为在创造光之前,它把混沌分成了陆地和水; 开展了一项浩大的工程来处理泥浆,并从液体中分离出固体……“这时,只听得计算机科学家大吼:“呔!你所谓的‘混沌’是从哪里来的呢,呀?” 实际上,如果你从事__跨平台软件开发__工作,你就会发现不同系统之间存在众多微妙或巨大的差异,这使得程序顺利地通过编译困难重重,因为不同的系统仅接受适合自身的程序代码。而要向不同的系统提供相应的程序代码,是很难实现的事情,因此__POSIX出现__了,它好像一个理想中的系统,__程序员们为该系统编程__,然后使用 一个工具伪装为履行POSIX标准的用户机器,这样就能保证最终的源代码可以在不同平台(符合POSIX标准的)上编译。这个工具就是Autoconf (即本文开头那个计算机科学家所谓的‘混沌’)。 Autoconf 的任务就是帮助软件开发人员研究用户所用的系统,分析其是否符合POSIX标准,并提供相应解决方法。显然,要检测用户的机器,就需要运行一个检查器。因 为这个检查器的任务是去发现系统缺陷的,所以它必须具备绝对的跨平台运行能力。Bourne shell是最合适的一种语言,可以__用它来写configure作为检查器__。不过,Bourne shell不具备函数编程功能,用它来写较为复杂的检查器,就像用汇编语言编程一样困难。这样,类似于高级语言及其编译器被发明出来取代汇编语言那样, David J.MacKenzie发明了Autoconf语言及autoconf程序来替代普通的用Bourne shell写的检查器程序了。 -**Autoconf初步(1)** +**autoconf软件包安装的工具** + autoconf, autoheader, autom4te, autoreconf, autoscan, autoupdate 和 ifnames -__Autoconf 仅仅是一个基于M4开发的库,提供了一套宏语言,用于检测库、程序等是否存在__。因为M4过于低等且Autoconf目的在于生成Bourne shell脚本,因此其高于M4。将Autoconf代码扩展为Bourne shell脚本很简单,可以使用“autom4te --language=autoconf“,也可以直接使用”autoconf“命令。autom4te和autoconf来自于[[../autoconf软件包.txt|autoconf软件包]]。 +**Autoconf初步(1)** +__Autoconf 仅仅是一个基于M4开发的库,提供了一套宏语言,用于检测库、程序等是否存在__。因为M4过于低等且Autoconf目的在于生成Bourne shell脚本,因此其高于M4。 + +将Autoconf代码扩展为Bourne shell脚本很简单,可以使用“autom4te --language=autoconf“,也可以直接使用”autoconf“命令。autom4te和autoconf来自于autoconf软件包。 所有Autoconf脚本都要由__AC_INIT宏__开始: - //AC_INIT宏// - AC_INIT(package, version, [bug-report-address]) AC_INIT的参数列表中,package为预编译的软件包名,version表示其版本号。bug-report-address是可选参数,它通常是一个Email地址,用于用户向该Email地址发送bug报告。 下面是一份最简单的Autoconf脚本: - //auditor.ac// - AC_INIT(Auditor, 1.0) 下面使用autoconf工具,将auditor.ac脚本转换为Bourne shell脚本: //Autoconf脚本的转换与使用// - $ autom4te //-l autoconf -o auditor a//uditor.ac #或autoconf -o auditor auditor.ac $ ./auditor #在shell中执行生成的auditor脚本 $ ./auditor --version @@ -48,14 +46,13 @@ AC_INIT的参数列表中,package为预编译的软件包名,version表示 许多软件是用C语言开发的,因此需要C编译器;__AC_PROG_CC宏__可以检测系统中是否存在C编译器。下面将auditor.ac修改为: -//[code4]auditor.ac// - +//auditor.ac// AC_INIT(Auditor, 1.0) AC_PROG_CC 将修改后的auditor.ac转换为Boune shell脚本后并执行,如下: -//[code5]auditor.ac// +//auditor.ac// $autoconf -o auditor auditor.ac $ ./auditor @@ -69,47 +66,40 @@ AC_INIT的参数列表中,package为预编译的软件包名,version表示 checking whether gcc accepts -g... yes checking for gcc option to accept ANSI C... none needed -如何对AC_PROG_CC的运行结果加以利用呢?在Autoconf的工作流程中,AC_PROG_CC总是在Autoconf基于一些模板文件生成新文件之前运行。譬如,一旦对你的系统完成了全面检查,__Autoconf会根据对系统的检查结果将所有的'Makefile.in’模板转化为 ‘Makefile‘文件__。这个过程叫做软件包的‘configuring‘,传统的做法是由Autoconf根据‘configure.ac‘生成 configure脚本来实现的。 +如何对AC_PROG_CC的运行结果加以利用呢? +autoconf将用M4语言编写的config.ac文件展开为一shell脚本,默认名称为__configure__。configure是一个标准的bash脚本,不依赖于autoconf和M4。执行configure脚本时,它会执行系统特性检查,该检查内容和结果会记录在__config.log__文件中。configure脚本最后会生成config.status脚本,接着执行它。config.status脚本将configure检查到的系统特性写入到一些环境变量中,然后读取各makefile.am模板文件(由config.ac中的AC_CONFIG_FILES宏指定),替换其中的变量值,最终生成各个makefile。 **Autoconf初步(2)** - 将auditor脚本变为系统编译环境配置脚本仅需要两个宏调用: -//[code1]AC_CONFIG_FILES宏// - +//AC_CONFIG_FILES宏// AC_CONFIG_FILES(file……, [command]) -在AC_CONFIG_FILES宏中列出需要生成(替换)的文件是一个推荐的做法,AC_OUTPUT不需要参数,只用于指示生成config.status脚本,该脚本__实际负责__替换文件 -中的变量引用。 +在AC_CONFIG_FILES宏中的file部分用于指定需要生成的文件及其路径名(如/tmp/src/demo/Makefile),同时该目录中需要有一个同名的且后缀名为.in的模板文件如/tmp/src/demo/Makefile.in, 而该Makefile.in文件是由automake工具根据Makefile.am文件生成的。 -‘file’ 参数指要创建的文件,该文件复制于一份输入文件(默认为‘file.in’),并替换掉输出变量值。‘file’就是一份输出文件,称之为__系统编译环境配置文件__更准确一些。譬如,若‘FOO’是一个输出变量,而它的值为‘Bar’,那么在文件‘file.in’中出现的所有‘__@FOO@’__,在输出文件中都 会被替换为‘Bar’。 +Makefile.am文件和autoconf.ac文件一样都是由程序员自己书写的,编写autoconf.ac文件使用的是预定义的用于系统特性检查M4宏;而编写Makefile.am文件时使用的是类似于makefile语法,但是相对高级。AC_OUTPUT不需要参数,只用于指示生成config.status脚本,该脚本__实际负责__替换模板文件中的变量引用。譬如,若‘FOO’是一个输出变量,而它的值为‘Bar’,那么在文件‘file.in’中出现的所有‘__@FOO@’__,在输出文件中都 会被替换为‘Bar’。 可选参数‘command’表示如果有必要,一旦文件创建完毕,也可以运行一些shell命令的。 -//[code2]AC_OUTPUT// - +//AC_OUTPUT// AC_OUTPUT 这个宏用于完成所有输出(创建系统编译环境配置文件,输出头文件等等)。 下面对这两个宏的应用作简单演示: -//[code3]输入文件which-cc.in// - +//输入模板文件which-cc.in// #! @SHELL@ echo "cc is @CC@" -//[code4]Autoconf configure// +//Autoconf configure// AC_INIT(Sample, 1.0) AC_PROG_CC - AC_CONFIG_FILE([which-cc],[chmod +x which-cc]) + AC_CONFIG_FILE([**which-cc**],[chmod +x which-cc]) AC_OUTPUT configure脚本生成及其运行结果如下: - -//[code5]configure脚本生成及其运行结果// - $ autoconf $ ls autom4te.cache configure __configure.ac__ configure.ac~ __which-cc.in__ @@ -123,7 +113,7 @@ configure脚本生成及其运行结果如下: checking whether we are using the GNU C compiler... yes checking whether gcc accepts -g... yes checking for gcc option to accept ANSI C... none needed - configure: creating //./config.status// + configure: creating **./config.status** __config.status:__ creating which-cc $ cat which-cc #! /bin/sh @@ -132,30 +122,28 @@ configure脚本生成及其运行结果如下: 可能你会纳闷configure脚本运行时生成了一个config.status文件,这是个什么东东呢?事实上,__configure仅仅是一个检查器:它本身不执行任何配置行为,它所创建的config.status会进行配置工作。__ **Autoconf初步(3)** +对configure.ac脚本的处理,输出的不仅仅有系统编译环境配置文件(即makefile),__也可以向C程序提供检查结果,表现为输出一个头文件__,其所提供的信息通常是简单的__编译预处理宏定义列表__。 -对configure.ac脚本的处理,输出的不仅仅有系统编译环境配置文件,__也可以向C程序提供检查结果,表现为输出一个头文件__,其所提供的信息通常是简单的__编译预处理宏定义列表__。 - -[code1]**AC_CONFIG_HEADERS** - +**AC_CONFIG_HEADERS** AC_CONFIG_HEADERS(file……, [command]) -和配置脚本文件的输出一样,输出的头文件也要从一份模板文件中复制内容,__这份模板文件中定义了CPP输出符号__。对于输出的头文件,比较传统的命名是 config.h,其模板文件名模认为config.h.in。对于一些操作系统,可能模板文件名中两个句点的文件命名方式不被支持,可以采用 config.hin或config_h.in来代替,然后在AC_CONFIG_HEADERS标明config.h与该模板文件的依赖关系即可,如: AC_CONFIG_HEADERS(config.h:config.hin)。 +和配置脚本文件的输出一样,输出的头文件也要从一份模板文件中复制内容,__这份模板文件中定义了将向CPP输出的符号__。对于输出的头文件,比较传统的命名是 **config.h**,其模板文件名模认为__config.h.in__。对于一些操作系统,可能模板文件名中两个句点的文件命名方式不被支持,可以采用 config.hin或config_h.in来代替,然后在AC_CONFIG_HEADERS标明config.h与该模板文件的依赖关系即可,如: AC_CONFIG_HEADERS(config.h:config.hin)。 AC_CONFIG_HEADERS中的命令行参数表示如果有必要,可以调用一些shell命令。 -通常在‘configure.ac’中对软件包的名称和版本作出声明,虽然如此,还需要为__软件包的命令行选项__‘--help‘提供有关软件包名称及版本号确切的应答,__主程序__就必须知道当前软件包的名称及其版本号(编程时是不知道的,因为这个是可配置的变量),这个可以由配置脚本生成config.h文件来实现: +通常在‘configure.ac’中对软件包的名称和版本作出声明,虽然如此,还需要为__软件包中的主程序命令行选项__‘--help‘提供有关软件包名称及版本号确切的应答,__主程序代码__就必须知道当前软件包的名称及其版本号,但是__在编写主程序代码__时是不知道的,因为这个是可配置的变量。为了解决这个问题,开发者可以提供一个header.h.in__模板文件__,其中包含了多个类似于 + #undef PACKAGE_BUGREPORT +的编译预处理命令,然后在主程序中include这个**与模板文件对应的头文件如header.h**。在编译配置代码的时候,由配置脚本(configure->config.status)负责根据收集到的系统和用户信息,修改header.h.in文件中的相应定义,最后生成主程序中引用的header.h文件。 为生成这样的头文件,对上回书中的configure.ac文件再度修改,如下: - -[code2]configure.ac +configure.ac AC_INIT(Audit, 1.1, lyanry@gmail.com) - AC_CONFIG_HEADERS(config.h) + __AC_CONFIG_HEADERS(config.h)__ AC_OUTPUT 下面是__config.h文件的模板config.h.in__: - -[code3]config.h.in +config.h.in /*定义bug报告发送地址*/ #undef PACKAGE_BUGREPORT @@ -168,14 +156,16 @@ AC_CONFIG_HEADERS中的命令行参数表示如果有必要,可以调用一些 /*定义软件包版本号*/ #undef PACKAGE_VERSION +模板文件中的符号定义为#undef,这是因为当配置脚本没有检查到相应的符号配置值时不会修改相应的预处理定义。 + 下面对configure.ac进行处理,生成configure脚本,//运行configure脚本即可生成config.h文件(前提是config.h.in中的变量名称必须是autoconf可识别的)//: - [code4]生从configure及其运行结果 + 从configure及其运行结果: [lyanry@lyanry sample]$ autoconf [lyanry@lyanry sample]$ ./configure configure: creating ./config.status - config.status: creating config.h + config.status: creating **config.h** [lyanry@lyanry sample]$ cat config.h /* config.h. Generated by configure. */ /*定义bug报告发送地址*/ @@ -190,13 +180,9 @@ AC_CONFIG_HEADERS中的命令行参数表示如果有必要,可以调用一些 #define PACKAGE_VERSION "1.0" **Autoconf初步(4)** +上 一节,编译环境配置头文件模板config.h.in文件是手动编辑的,实际上它__可以很容易地由‘configure.ac’文件导出__,这通过检索__所有__已定义的预处理符号,并在其前冠以‘#undef’,然后再自动粘贴相应的标准注释,最后输出‘config.h.in’。用于完成这一过程的工具是 __autoheader__。configure.ac中定义的一些宏用于检查系统环境,它会将检查到的结果(库是否存在,版本号,软件路径及名称)写入到一些__特定的变量__中,这些变量可以被makefile.in引用,也可以__被源代码作为条件编译的参数__使用(常见的做法是将所有的这些变量以宏定义的形式写入到config.h文件中,然后__源程序include该头文件即可__)。 -上 一节,编译环境配置头文件模板config.h.in文件是手动编辑的,实际上它__可以很容易地由‘configure.ac’文件导出__,这通过检索所有已定义的预处理符号,并在其前冠以‘#undef’,然后再自动粘贴相应的标准注释,最后输出‘config.h.in’。用于完成这一过程的工具是 __autoheader__。configure.ac中定义的一些宏用于检查系统环境,它会将检查到的结果(库是否存在,版本号,软件路径及名称)写入到一些__特定的变量__中,这些变量可以被makefile.in引用,也可以被源代码作为条件编译的参数使用(常见的做法是将所有的这些变量以宏定义的形式写入到config.h文件中,然后__源程序include该头文件即可__)。 - - - -[code1]autoheader用法 - +autoheader用法 $ rm config.h.in $ autoheader $ cat config.h.in @@ -217,9 +203,9 @@ AC_CONFIG_HEADERS中的命令行参数表示如果有必要,可以调用一些 /* Define to the version of this package. */ #undef PACKAGE_VERSION -本文虽然在讲述Autoconf的初步应用,但依然需要运行两个程序,它们必须按次序运行?(并非如此)。我要在什么时机运行它们?(事实上,每次 'configure.ac'或其依赖文件发生更改之时都要运行这两个程序)。还有没有其他程序也像这样?(当然,automake, libtoolize,gettextize,aclocal……都这般运行)它们的运行次序是否也任意?(是的,本质上皆如此)。实际上,本文与其是讲Autoconf的初步使用,不如说是讲述autoreconf的初步使用:后者囊括了Autoconf中的各类工具,知道在什么情况下运行相应程序。我鼓励你__忘掉autoconf、automake等工具,仅使用autoreconf即可__,如下: +本文虽然在讲述Autoconf的初步应用,但依然需要运行两个程序,它们必须按次序运行?(并非如此)。我要在什么时机运行它们?(事实上,每次 'configure.ac'或其依赖文件发生更改之时都要运行这两个程序)。还有没有其他程序也像这样?(当然,automake, libtoolize,gettextize,aclocal……都这般运行)它们的运行次序是否也任意?(是的,本质上皆如此)。实际上,本文与其是讲Autoconf的初步使用,不如说是讲述autoreconf的初步使用:后者囊括了Autoconf中的各类工具,知道在什么情况下运行相应程序。我鼓励你__忘掉autoconf、automake等工具,仅使用autoreconf即可__,如下:[[实例:autoreconf]] -[code2]autoreconf用法 +autoreconf用法 [lyanry@lyanry sample]$ ls configure.ac diff --git a/Zim/Utils/工具链/autoconf---automake/Autotools上手指南.txt b/Zim/Utils/工具链/autoconf---automake/Autotools上手指南.txt index 8dfe776..1844774 100644 --- a/Zim/Utils/工具链/autoconf---automake/Autotools上手指南.txt +++ b/Zim/Utils/工具链/autoconf---automake/Autotools上手指南.txt @@ -8,9 +8,7 @@ http://blog.dccmx.com/2011/01/autotools-1/ ccmx 于 2011年 一月 7日 发表 | 最后修改于 2011年 一月 10日 -要想弄懂Autotools并使用它,必须先要了解一下M4这个怪物。 - -那么何为M4呢,M4的名称取自Macro(M后面跟4个字母…)。它和C预处理器里的宏是一个概念(其实,M4和C预处理器都K&R操刀设计的!!),用来处理文本替换。也就是说,M4是bash里的预处理器。 +要想弄懂Autotools并使用它,必须先要了解一下M4这个怪物。那么何为M4呢,M4的名称取自Macro(M后面跟4个字母…)。它和C预处理器里的宏是一个概念(其实,M4和C预处理器都K&R操刀设计的!!),用来处理文本替换。也就是说,M4是bash里的预处理器。 取自维基的例子: divert(-1) diff --git a/Zim/Utils/工具链/autoconf---automake/autoconf软件包.txt b/Zim/Utils/工具链/autoconf---automake/autoconf软件包.txt deleted file mode 100644 index d322aae..0000000 --- a/Zim/Utils/工具链/autoconf---automake/autoconf软件包.txt +++ /dev/null @@ -1,29 +0,0 @@ -Content-Type: text/x-zim-wiki -Wiki-Format: zim 0.4 -Creation-Date: 2011-12-22T22:26:12+08:00 - -====== autoconf软件包 ====== -Created Thursday 22 December 2011 - -===== Autoconf的内容 ===== -Autoconf 能生成用于自动配置源代码的 shell 脚本(**configure**),该脚本可以生成makefile文件。 - -安装下列程序: autoconf, autoheader, autom4te, autoreconf, autoscan, autoupdate 和 ifnames - -===== 简短说明 ===== -autoconf是一个产生可以自动配置源代码包,生成shell脚本的工具,以适应各种类UNIX系统的需要。autoconf 产生的配置脚本在运行时独立于autoconf ,因此使用这些脚本的用户不需要安装autoconf。 - -autoheader能够产生供configure脚本使用的C #define语句模板文件。 - -autom4te对文件执行 GNU M4。 - -autoreconf,如果有多个autoconf产生的配置文件,autoreconf可以保存一些工作,它通过重复运行autoconf(以及在合适的地方运行autoheader)以重新产生autoconf配置脚本和配置头模板,这些文件保存在以当前目录为根的目录树中。 - -autoscan程序可以用来为软件包创建configure.in文件。autoscan在以命令行参数中指定的目录为根(如果未给定参数,则以当前目录为根)的目录树中检查源文件。它为通常的轻便问题搜索源文件,并且为那个包创建一个configure.scan文件,这个文件就是configure.in的前身。 - -autoupdate程序将一个调用autoconf 宏的旧名称的configure.in文件中的宏更新为新的名称。 - -ifnames当为一个软件包写configure.in 时,ifnames可以提供一些帮助。它打印包中那些在C预处理器中已经使用了的表示符。如果一个包已经设置成具有某些可移植属性,这个程序能够帮助指出它的配置应该如何检查。它可以用来填补由autoscan产生的configure.in中的隔阂。 - -===== Autoconf 安装依赖关系 ===== -Autoconf 依赖于: Bash, Coreutils, Diffutils, Grep, M4, Make, Perl, Sed. diff --git a/Zim/Utils/工具链/autoconf---automake/实例.txt b/Zim/Utils/工具链/autoconf---automake/实例.txt new file mode 100644 index 0000000..ba99f78 --- /dev/null +++ b/Zim/Utils/工具链/autoconf---automake/实例.txt @@ -0,0 +1,271 @@ +Content-Type: text/x-zim-wiki +Wiki-Format: zim 0.4 +Creation-Date: 2012-12-30T16:56:06+08:00 + +====== 实例 ====== +Created Sunday 30 December 2012 + +[geekard@geekard demo]$ ls #两文件的代码见附件 +demo.c foo.c +[geekard@geekard demo]$ __aclocal__** //aclocal为configure.ac中使用的M4宏提供定义** +aclocal: error: 'configure.ac' is required +[geekard@geekard demo]$ __autoscan__ +[geekard@geekard demo]$ ls +autoscan.log __configure.scan__ demo.c foo.c +[geekard@geekard demo]$ mv configure.scan __configure.ac__ +[geekard@geekard demo]$ vim configure.ac **//修改configur.ac文件** +[geekard@geekard demo]$ cat configure.ac +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ([2.69]) +AC_INIT([demo], [0.1], [geekard@qq.com]) +AC_CONFIG_SRCDIR([.]) +AM_INIT_AUTOMAKE(demo,0.1) +AC_CONFIG_HEADERS([config.h]) + +# Checks for programs. +AC_PROG_CC + +# Checks for libraries. + +# Checks for header files. +AC_CHECK_HEADERS([stdlib.h]) + +# Checks for typedefs, structures, and compiler characteristics. + +# Checks for library functions. +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT +[geekard@geekard demo]$ __autoheader__ **//在执行该命令前需要先编写configure.ac文件** +[geekard@geekard demo]$ ls +autoscan.log __config.h.in__ configure.ac demo.c foo.c +[geekard@geekard demo]$ cat config.h.in +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Version number of package */ +#undef VERSION +[geekard@geekard demo]$ cat __Makefile.am__ +bin_PROGRAMS = demo //生成的可执行程序名称 +demo_SOURCES = demo.c foo.c //可执行程序依赖的源文件 +[geekard@geekard demo]$ __aclocal //在执行automake和autoconf前需要先执行aclocal,该命令为configure.ac文件中使用的M4宏提供定义。__ +[geekard@geekard demo]$ ls +__aclocal.m4 autom4te.cache__ autoscan.log configure.ac demo.c foo.c Makefile.am +[geekard@geekard demo]$ __automake //在执行automake前必须定义configure.ac和Makefile.am文件__ +configure.ac:7: warning: AM_INIT_AUTOMAKE: two- and three-arguments forms are deprecated. For more info, see: +configure.ac:7: http://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_INIT_AUTOMAKE-invocation +configure.ac:7: error: required file './install-sh' not found +configure.ac:7: 'automake --add-missing' can install 'install-sh' +configure.ac:7: error: required file './missing' not found +configure.ac:7: 'automake --add-missing' can install 'missing' +Makefile.am: error: required file './INSTALL' not found +Makefile.am: 'automake --add-missing' can install 'INSTALL' +Makefile.am: error: required file './NEWS' not found +Makefile.am: error: required file './README' not found +Makefile.am: error: required file './AUTHORS' not found +Makefile.am: error: required file './ChangeLog' not found +Makefile.am: error: required file './COPYING' not found +Makefile.am: 'automake --add-missing' can install 'COPYING' +Makefile.am: error: required file './depcomp' not found +Makefile.am: 'automake --add-missing' can install 'depcomp' +[geekard@geekard demo]$ __automake --add-missing__ +configure.ac:7: warning: AM_INIT_AUTOMAKE: two- and three-arguments forms are deprecated. For more info, see: +configure.ac:7: http://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_INIT_AUTOMAKE-invocation +configure.ac:7: installing './install-sh' +configure.ac:7: installing './missing' +Makefile.am: installing './INSTALL' +Makefile.am: error: required file './NEWS' not found +Makefile.am: error: required file './README' not found +Makefile.am: error: required file './AUTHORS' not found +Makefile.am: error: required file './ChangeLog' not found +Makefile.am: installing './COPYING' using GNU General Public License v3 file +Makefile.am: Consider adding the COPYING file to the version control system +Makefile.am: for your code, to avoid questions about which license your project uses +Makefile.am: installing './depcomp' +[geekard@geekard demo]$ __touch NEWS README AUTHORS ChangeLog__ +[geekard@geekard demo]$ **automake** +configure.ac:7: warning: AM_INIT_AUTOMAKE: two- and three-arguments forms are deprecated. For more info, see: +configure.ac:7: http://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_INIT_AUTOMAKE-invocation +[geekard@geekard demo]$ ls +aclocal.m4 autom4te.cache ChangeLog config.h.in COPYING depcomp INSTALL Makefile.am missing README +AUTHORS autoscan.log ChangLog configure.ac demo.c foo.c install-sh __Makefile.in__ NEWS +[geekard@geekard demo]$ __autoconf__ //**最后一步执行autoconf命令,如果先于automake执行则会提示** + **configure.ac:7: error: possibly undefined macro: AM_INIT_AUTOMAKE** + ** If this token and others are legitimate, please use m4_pattern_allow.** + ** See the Autoconf documentation.** +[geekard@geekard demo]$ ls +aclocal.m4 autom4te.cache ChangeLog config.h.in configure.ac demo.c foo.c install-sh Makefile.in NEWS +AUTHORS autoscan.log ChangLog __configure__ COPYING depcomp INSTALL Makefile.am missing README +[geekard@geekard demo]$ **./configure** +checking for a BSD-compatible install... /usr/bin/install -c +checking whether build environment is sane... yes +checking for a thread-safe mkdir -p... /usr/bin/mkdir -p +checking for gawk... gawk +checking whether make sets $(MAKE)... yes +checking for gcc... gcc +checking whether the C compiler works... yes +checking for C compiler default output file name... a.out +checking for suffix of executables... +checking whether we are cross compiling... no +checking for suffix of object files... o +checking whether we are using the GNU C compiler... yes +checking whether gcc accepts -g... yes +checking for gcc option to accept ISO C89... none needed +checking for style of include used by make... GNU +checking dependency style of gcc... gcc3 +checking how to run the C preprocessor... gcc -E +checking for grep that handles long lines and -e... /usr/bin/grep +checking for egrep... /usr/bin/grep -E +checking for ANSI C header files... yes +checking for sys/types.h... yes +checking for sys/stat.h... yes +checking for stdlib.h... yes +checking for string.h... yes +checking for memory.h... yes +checking for strings.h... yes +checking for inttypes.h... yes +checking for stdint.h... yes +checking for unistd.h... yes +checking for stdlib.h... (cached) yes +checking that generated files are newer than configure... done +configure: creating __./config.status__ +**config.status:** creating __Makefile__ +config.status: creating __config.h__ +config.status: executing __depfiles__ commands +[geekard@geekard demo]$ **make** +CDPATH="${ZSH_VERSION+.}:" && cd . && /bin/sh /home/geekard/Code/elf/demo/missing --run aclocal-1.12 + cd . && /bin/sh /home/geekard/Code/elf/demo/missing --run automake-1.12 --gnu +configure.ac:7: warning: AM_INIT_AUTOMAKE: two- and three-arguments forms are deprecated. For more info, see: +configure.ac:7: http://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_INIT_AUTOMAKE-invocation +CDPATH="${ZSH_VERSION+.}:" && cd . && /bin/sh /home/geekard/Code/elf/demo/missing --run autoconf +**/bin/sh ./config.status --recheck** +running CONFIG_SHELL=/bin/sh /bin/sh ./configure --no-create --no-recursion +checking for a BSD-compatible install... /usr/bin/install -c +checking whether build environment is sane... yes +checking for a thread-safe mkdir -p... /usr/bin/mkdir -p +checking for gawk... gawk +checking whether make sets $(MAKE)... yes +checking for gcc... gcc +checking whether the C compiler works... yes +checking for C compiler default output file name... a.out +checking for suffix of executables... +checking whether we are cross compiling... no +checking for suffix of object files... o +checking whether we are using the GNU C compiler... yes +checking whether gcc accepts -g... yes +checking for gcc option to accept ISO C89... none needed +checking for style of include used by make... GNU +checking dependency style of gcc... gcc3 +checking how to run the C preprocessor... gcc -E +checking for grep that handles long lines and -e... /usr/bin/grep +checking for egrep... /usr/bin/grep -E +checking for ANSI C header files... yes +checking for sys/types.h... yes +checking for sys/stat.h... yes +checking for stdlib.h... yes +checking for string.h... yes +checking for memory.h... yes +checking for strings.h... yes +checking for inttypes.h... yes +checking for stdint.h... yes +checking for unistd.h... yes +checking for stdlib.h... (cached) yes +checking that generated files are newer than configure... done +configure: creating ./config.status + /bin/sh ./config.status +config.status: creating Makefile +config.status: creating config.h +config.status: config.h is unchanged +config.status: executing depfiles commands +(CDPATH="${ZSH_VERSION+.}:" && cd . && /bin/sh /home/geekard/Code/elf/demo/missing --run autoheader) +rm -f stamp-h1 +touch config.h.in +cd . && /bin/sh ./config.status config.h +config.status: creating config.h +config.status: config.h is unchanged +**make all-am** +make[1]: Entering directory `/home/geekard/Code/elf/demo' +gcc -DHAVE_CONFIG_H -I. -g -O2 -MT demo.o __-MD -MP -MF .deps/demo.Tpo__ -c -o demo.o demo.c +demo.c: In function ‘greeting’: +demo.c:24:3: warning: initialization from incompatible pointer type [enabled by default] +demo.c:24:3: warning: (near initialization for ‘pp’) [enabled by default] +demo.c:24:3: warning: excess elements in scalar initializer [enabled by default] +demo.c:24:3: warning: (near initialization for ‘pp’) [enabled by default] +demo.c:24:3: warning: excess elements in scalar initializer [enabled by default] +demo.c:24:3: warning: (near initialization for ‘pp’) [enabled by default] +demo.c:24:3: warning: excess elements in scalar initializer [enabled by default] +demo.c:24:3: warning: (near initialization for ‘pp’) [enabled by default] +mv -f .deps/demo.Tpo .deps/demo.Po +gcc -DHAVE_CONFIG_H -I. -g -O2 **-MT foo.o -MD -MP -MF .deps/foo.Tpo** -c -o foo.o foo.c +mv -f .deps/foo.Tpo .deps/foo.Po +gcc -g -O2 -o demo demo.o foo.o +make[1]: Leaving directory `/home/geekard/Code/elf/demo' + +**#上面的-MD -MP -MF ./deps/demo.Tpo定义了demo程序的依赖文件。** +[geekard@geekard demo]$ ls +aclocal.m4 autoscan.log config.h config.status COPYING demo.o foo.o Makefile missing stamp-h1 +AUTHORS ChangeLog config.h.in configure __demo__ depcomp INSTALL Makefile.am NEWS +autom4te.cache ChangLog config.log configure.ac demo.c foo.c install-sh Makefile.in README +[geekard@geekard demo]$ ./demo +In main: + The globalVarStatic is:3 +In greeting: + Hello, geekard: + Yourt age is:23. + Yourt friends are: + Tom + John + Pi +Goodbye from greeting. +[geekard@geekard demo]$ diff --git a/Zim/Utils/工具链/autoconf---automake/实例/autoreconf.txt b/Zim/Utils/工具链/autoconf---automake/实例/autoreconf.txt new file mode 100644 index 0000000..135812e --- /dev/null +++ b/Zim/Utils/工具链/autoconf---automake/实例/autoreconf.txt @@ -0,0 +1,53 @@ +Content-Type: text/x-zim-wiki +Wiki-Format: zim 0.4 +Creation-Date: 2012-12-30T17:40:36+08:00 + +====== autoreconf ====== +Created Sunday 30 December 2012 +利用autoreconf工具,会自动生成相关的文件。 + +[geekard@geekard demo]$ ls +**configure.ac demo.c foo.c Makefile.am** + +[geekard@geekard demo]$ **autoreconf** +configure.ac:7: warning: AM_INIT_AUTOMAKE: two- and three-arguments forms are deprecated. For more info, see: +configure.ac:7: http://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_INIT_AUTOMAKE-invocation +configure.ac:7: error: required file './install-sh' not found +configure.ac:7: 'automake --add-missing' can install 'install-sh' +configure.ac:7: error: required file './missing' not found +configure.ac:7: 'automake --add-missing' can install 'missing' +Makefile.am: error: required file './INSTALL' not found +Makefile.am: 'automake --add-missing' can install 'INSTALL' +Makefile.am: error: required file './NEWS' not found +Makefile.am: error: required file './README' not found +Makefile.am: error: required file './AUTHORS' not found +Makefile.am: error: required file './ChangeLog' not found +Makefile.am: error: required file './COPYING' not found +Makefile.am: 'automake --add-missing' can install 'COPYING' +Makefile.am: error: required file './depcomp' not found +Makefile.am: 'automake --add-missing' can install 'depcomp' +autoreconf: **automake** failed with exit status: 1 +**[geekard@geekard demo]$ ls //可见自动调用了aclocal命令** +aclocal.m4 autom4te.cache config.h.in configure configure.ac demo.c foo.c Makefile.am +[geekard@geekard demo]$ __automake --add-missing__ +configure.ac:7: warning: AM_INIT_AUTOMAKE: two- and three-arguments forms are deprecated. For more info, see: +configure.ac:7: http://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_INIT_AUTOMAKE-invocation +configure.ac:7: installing './install-sh' +configure.ac:7: installing './missing' +Makefile.am: installing './INSTALL' +Makefile.am: error: required file './NEWS' not found +Makefile.am: error: required file './README' not found +Makefile.am: error: required file './AUTHORS' not found +Makefile.am: error: required file './ChangeLog' not found +Makefile.am: installing './COPYING' using GNU General Public License v3 file +Makefile.am: Consider adding the COPYING file to the version control system +Makefile.am: for your code, to avoid questions about which license your project uses +Makefile.am: installing './depcomp' +[geekard@geekard demo]$ __touch NEWS README AUTHORS ChangeLog__ +[geekard@geekard demo]$ __autoreconf__ +configure.ac:7: warning: AM_INIT_AUTOMAKE: two- and three-arguments forms are deprecated. For more info, see: +configure.ac:7: http://www.gnu.org/software/automake/manual/automake.html#Modernize-AM_INIT_AUTOMAKE-invocation +[geekard@geekard demo]$ ls **//可见自动调用了automake和autoconf** +aclocal.m4 autom4te.cache config.h.in configure.ac demo.c foo.c install-sh Makefile.in NEWS +AUTHORS ChangeLog __configure__ COPYING depcomp INSTALL Makefile.am missing README +[geekard@geekard demo]$ diff --git a/Zim/Utils/工具链/autoconf---automake/实例/demo.c.txt b/Zim/Utils/工具链/autoconf---automake/实例/demo.c.txt new file mode 100644 index 0000000..705360d --- /dev/null +++ b/Zim/Utils/工具链/autoconf---automake/实例/demo.c.txt @@ -0,0 +1,67 @@ +Content-Type: text/x-zim-wiki +Wiki-Format: zim 0.4 +Creation-Date: 2012-12-30T17:09:44+08:00 + +====== demo.c ====== +Created Sunday 30 December 2012 + +#include +#include + +//已初始化全局变量,保存在.data section中。 +int globalVar = 1; +//未初始化全局变量,当生成可重定位obj文件时,位于COMMON section中。 +int globalVarUninit; + +//对于static类型的变量和函数的引用,使用GOTOFF类型重定位。 +static int globalVarStatic = 3; + +extern int externVar; +//对于外部函数的调用,使用PLT形式重定位。 +extern int add(int, int); + +void greeting(char *name, int age, char** friends) +{ + + int a = 23; + char *nm = "zhangjun"; + //ap为数组名称,本身不占用内存单元 + char *ap[] = {"Tom", "John", "Pi", NULL}; + //pp为指针变量,指向一块保存有三个字符指针的内存单元(位于greeting的栈中) + char **pp = {"Tom", "John", "Pi", NULL}; + + if (name == NULL) + name = nm; + if (age == 0) + age = a; + if (friends == NULL) + friends = pp; + + printf("In greeting:\n"); + printf("\tHello, %s:\n", name); + printf("\tYourt age is:%d.\n", age); + printf("\tYourt friends are:\n"); + while (*friends != NULL) { + printf("\t\t%s\n", *friends); + friends += 1; + } + + printf("Goodbye from greeting.\n"); +} + +int main(int argc, char *argv[]) +{ + int autoVar = globalVar; + static int staticVar = 2; + int i = externVar; + + char *name = "geekard"; + int age = 23; + //friends为数组名称. + char *friends[] = {"Tom", "John", "Pi", NULL}; + + printf("In main:\n"); + printf("\tThe globalVarStatic is:%d\n",globalVarStatic); + greeting(name, age, friends); + add(2, 3); +} diff --git a/Zim/Utils/工具链/autoconf---automake/实例/foo.c.txt b/Zim/Utils/工具链/autoconf---automake/实例/foo.c.txt new file mode 100644 index 0000000..a34d065 --- /dev/null +++ b/Zim/Utils/工具链/autoconf---automake/实例/foo.c.txt @@ -0,0 +1,14 @@ +Content-Type: text/x-zim-wiki +Wiki-Format: zim 0.4 +Creation-Date: 2012-12-30T17:09:48+08:00 + +====== foo.c ====== +Created Sunday 30 December 2012 + +int externVar = 1; +int static staticVarStatic = 2; + +int add(int a, int b) +{ + return a + b; +}