Linux下Makefile的automake生成全攻略
" V* J; X6 v3 h. @2 S
2006-06-01
+ ^8 g1 q& m% O0 g/ J
* F5 G/ F7 H3 ?8 R5 t! r' F+ T* Y
, J) N7 S% [& a# O; [9 V
, ~4 m9 d1 b' w) A 文/余涛
6 J4 n4 C# l; }# P # K3 ^) y* e# g( ^ T
作为Linux下的
程序开发人员,大家一定都遇到过Makefile,用make命令来编译自己写的程序确实是很方便。一般情况下,大家都是手工写一个简单Makefile,如果要想写出一个符合
自由软件惯例的Makefile就不那么容易了。
' ]! \, O/ |0 \; M: p; x
$ ^7 p3 d' u) w5 P* _
在本文中,将给大家介绍如何使用autoconf和automake两个工具来帮助我们自动地生成符合自由软件惯例的Makefile,这样就可以象常见的GNU程序一样,只要使用“./configure”,“make”,“makeinstal”就可以把程序安装到Linux
系统中去了。这将特别适合想做开放
源代码软件的程序开发人员,又或如果你只是自己写些小的Toy程序,那么这个文章对你也会有很大的帮助。
1 `8 l( c* p+ Z; o* E
) a3 d' |( P. ~9 J8 X8 ~
一、Makefile介绍
2 ^. i* P! I }& c8 M; c
/ H# z$ f7 R2 ` Makefile是用于自动编译和链接的,一个工程有很多文件组成,每一个文件的改变都会导致工程的重新链接,但是不是所有的文件都需要重新编译,Makefile中纪录有文件的
信息,在make时会决定在链接的时候需要重新编译哪些文件。
' l. D) s; B/ W u
R# }8 e0 T- s
Makefile的宗旨就是:让编译器知道要编译一个文件需要依赖其他的哪些文件。当那些依赖文件有了改变,编译器会自动的发现最终的生成文件已经过时,而重新编译相应的模块。
5 d: H, r+ ^' t7 c; V' S1 [$ o; S# j. ~- L. p5 J, x% S) |6 a
Makefile的基本
结构不是很复杂,但当一个程序开发人员开始写Makefile时,经常会怀疑自己写的是否符合惯例,而且自己写的Makefile经常和自己的开发
环境相关联,当系统环境变量或路径发生了变化后,Makefile可能还要跟着修改。这样就造成了手工书写Makefile的诸多问题,automake恰好能很好地帮助我们解决这些问题。
; S ~7 o/ T; N8 z3 Y4 N+ T( X
+ x4 S, j* }* s0 x# X 使用automake,程序开发人员只需要写一些简单的含有预定义宏的文件,由autoconf根据一个宏文件生成configure,由automake根据另一个宏文件生成Makefile.in,再使用configure依据Makefile.in来生成一个符合惯例的Makefile。下面我们将详细介绍Makefile的automake生成方法。
5 r/ E( A# I+ j) w7 q! K
+ y( j! {" R( k' ~# x' v. d" c# d+ R 二、使用的环境
+ \# c& H, I$ Y, G5 i& R
- l/ B' `" I' f& m; i 本文所提到的程序是基于Linux发行版本:FedoraCorerelease1,它包含了我们要用到的autoconf,automake。
, S. H$ Q- i z- Z6 ]# k5 j
( ?. a" x4 Y, t3 O 三、从helloworld入手
3 K, ~* V# @* ^& Y3 x* _
9 F/ g) c- ?0 O, |* o 我们从大家最常使用的例子程序helloworld开始。
0 ~9 J+ e7 C6 F7 r+ ]* r
U7 B% ]. _1 W! a
下面的过程如果简单地说来就是:
2 d* w& d* u( ]! t1 \1 Q
8 J. ]+ Z) W5 k |# N) [ 新建三个文件:
* {9 x7 q+ U+ s& }1 Z6 M* c, R
9 U2 G0 Q2 b) `
helloworld.c
4 B: Y1 B+ c: e# c) O' Z: d configure.in
* z- y: n4 G9 X7 q, T Makefile.am
9 K$ v) C& A: b# E, L$ ~9 S
/ N2 H* `4 v" y& w+ \4 e
然后执行:
6 Q* Z0 c ^$ ~% w1 a, {3 x, f+ u1 q. j! D2 n+ m3 B' ~
aclocal;autoconf;automake--add-missing;./configure;make;./helloworld
/ X: g& a4 A( ^: Y. M+ n8 V5 z% n h9 w( x* y
就可以看到Makefile被产生出来,而且可以将helloworld.c编译通过。
; p* _0 u2 p8 [* }3 l9 g
, {4 X! |1 u( ^% c9 F# r 很简单吧,几条命令就可以做出一个符合惯例的Makefile,感觉如何呀。
$ L7 P+ b0 t4 G1 c( A) D7 A6 e6 t; d2 R3 ~+ M) y( ]- o
现在开始介绍详细的过程:
8 r n9 A+ \1 F
8 Q+ i- R4 _$ H0 k 1、建目录
$ C7 @6 h6 X! M) l/ P
" k h0 g) O# V
在你的工作目录下建一个helloworld目录,我们用它来存放helloworld程序及相关文件,如在/home/my/build下:
! I: k( L* q' b. _8 Z
$ j- L; G; p4 M8 ?- M& y4 U1 K% I/ u
$mkdirhelloword
V, t5 T7 u l8 k0 d
$cdhelloworld
# J, d+ Y; \# k! V5 A+ z
: ]$ n% H3 f( q6 K" u 2、helloworld.c
+ H% h/ @/ t( Q, E$ ]: X+ r
8 e" g, K( q! T/ n 然后用你自己最喜欢的
编辑器写一个hellowrold.c文件,如命令:vihelloworld.c。使用下面的代码作为helloworld.c的内容。
, o! X& O: s3 f7 y1 U& g2 p+ \# I
8 y- G+ `& _# a4 {
intmain(intargc,char**argv)
% E% n& S; P m1 e
{
( g/ j) I8 O) C Y; {9 `. E0 dprintf("Hello,LinuxWorld!\n");
' m, y5 M1 m. l, M& x9 Lreturn0;
/ g z# {8 H5 M2 e2 ^4 V}
4 I6 Q) Q2 L4 W7 y6 E8 Y
9 B2 N: Y' Y: T' `& ~9 Y Q 完成后保存退出。
: r0 E& [4 P. @! M9 p
' i* d, i* b9 C0 X& w
现在在helloworld目录下就应该有一个你自己写的helloworld.c了。
9 M$ q6 O. K1 `$ ], b% {. c3 r- |: K9 a
3、生成configure
& f+ F) l; i0 F1 l& a. a8 h9 f) \
4 \* J1 u" b- y: h) s3 y6 C
我们使用autoscan命令来帮助我们根据目录下的源代码生成一个configure.in的模板文件。
$ O! s! B5 K5 V$ D8 s6 t* _3 w2 H* S' c
命令:
& H" s, M( j0 w3 E3 l
6 a6 S2 i$ F! k. H& m B$autoscan
6 C, W: Y. S0 |' L& e4 k) t8 n3 O" Z% T$ls
" m; w7 S6 ?6 t1 i2 T8 C8 ^configure.scanhelloworld.c
/ Y- @, |& `7 g8 ^
: w) m% X) ^" ^$ H/ R 执行后在hellowrold目录下会生成一个文件:configure.scan,我们可以拿它作为configure.in的蓝本。
$ {6 N: y) Q V
/ B/ F# d8 `/ Q$ ? 现在将configure.scan改名为configure.in,并且编辑它,按下面的内容修改,去掉无关的语句:
, B3 z; T1 x; e1 k7 F
8 y7 M0 ~6 ^/ m7 m+ v
============================configure.in内容开始=========================================
! c! U/ U" q4 b; `) E+ X#-*-Autoconf-*-
+ G! k! e- D7 W# a$ K#Processthisfilewithautoconftoproduceaconfigurescript.
* G3 {0 g; X" j5 v& E2 W% U9 G+ D
( v" s! N9 R s4 H3 J- b+ B8 R, Z
AC_INIT(helloworld.c)
4 F; t; s4 w! V5 f. PAM_INIT_AUTOMAKE(helloworld,1.0)
! P+ E6 n+ J4 h; @
8 U j u- w* \& w
#Checksforprograms.
$ m0 o# L& a6 e2 fAC_PROG_CC
! t( W+ o0 R. i) }. c) |; S- B/ T
#Checksforlibraries.
: J0 E3 d9 t. d7 O& n, c9 S2 C
; w9 L6 z1 c5 u. I/ Y' V- Q4 k, S! g N
#Checksforheaderfiles.
0 ~5 u" L6 X! C; D$ {+ b% C& v% B E
/ Q- D0 W5 O; t9 q* h% _#Checksfor
typedefs,structures,andcompilercharacteristics.
) H3 ^6 N9 L: u8 N
# u, W& w& _% ?9 N#Checksforlibraryfunctions.
! ?% q0 H) i! P7 i0 l
AC_OUTPUT(Makefile)
# G6 J+ y' N) v! x0 z1 Q============================configure.in内容结束=========================================
$ v6 k- v b+ e" D. ~; Z
# y1 Z4 I) m- o% Q$ S! x 然后执行命令aclocal和autoconf,分别会产生aclocal.m4及configure两个文件:
; Q1 b* R+ }! `- B" M( N+ m5 f5 n s! [2 J+ D# u( T/ p. g
$aclocal
`' n8 r+ G5 H1 @$ls
# r9 m8 r' s4 _: B+ V. oaclocal.m4configure.inhelloworld.c
4 `+ s- C: G; g `, _$autoconf
: J4 m9 I1 _ k! O9 @; k
$ls
o. q8 O5 ?# e2 U `( c
aclocal.m4autom4te.cacheconfigureconfigure.inhelloworld.c
. o4 `+ U, b! M
& U1 W$ _" l P0 x$ M# s2 S7 }
* X- s Q3 B/ A- R4 s6 R 大家可以看到configure.in内容是一些宏定义,这些宏经autoconf处理后会变成检查系统特性、环境变量、软件必须的参数的
shell脚本。
9 a6 A. O" l0 R+ U3 U+ k2 B! S
* E6 ?/ Z+ s* ~0 Q
autoconf是用来生成自动配置软件源代码脚本(configure)的工具。configure脚本能独立于autoconf运行,且在运行的过程中,不需要用户的干预。
" w: P' k$ w3 N# q" i/ `
4 R P' X% i3 G2 D3 Y 要生成configure文件,你必须告诉autoconf如何找到你所用的宏。方式是使用aclocal程序来生成你的aclocal.m4。
. K0 J. k* N6 e ^; _8 C
; M0 d& f a$ O# H' I aclocal根据configure.in文件的内容,自动生成aclocal.m4文件。aclocal是一个perl脚本程序,它的定义是:“aclocal-createaclocal.m4byscanningconfigure.ac”。
1 Q' `, j1 k" V% l
+ J$ e8 v$ p, s C( H autoconf从configure.in这个列举编译软件时所需要各种参数的模板文件中创建configure。
p9 {: L e: m, I" u
# P9 a1 z/ a% r0 d. v! ] autoconf需要GNUm4宏
处理器来处理aclocal.m4,生成configure脚本。
: t3 m5 t0 _* t' g* ?
& ?" y0 h$ ^: ~. q S m4是一个宏处理器。将输入拷贝到输出,同时将宏展开。宏可以是内嵌的,也可以是用户定义的。除了可以展开宏,m4还有一些内建的函数,用来引用文件,执行命令,整数运算,文本操作,循环等。m4既可以作为编译器的前端,也可以单独作为一个宏处理器。
! v! d1 c8 @; G7 E: Z2 p( T: x) ^) u6 Y" b: _8 E: a
4、新建Makefile.am
* \( d$ v" [- V& g" | W* n
3 p4 [- Q$ I. O" o: X3 p( f
新建Makefile.am文件,命令:
( W. N' G( E/ |4 }: a9 v
+ L" V8 J* h: G m" h
" p0 l" y) {% U# e. Y4 b5 c. ?/ U
$viMakefile.am
4 E6 z0 D% K5 P4 C& a% h2 a* _% e
4 _& m) ~; Y: b2 J$ O% B- l" x, N& P$ ?+ B0 _5 W
内容如下:
4 e# H' ?+ C% }) r l# x
, O7 Q3 x5 P* `+ o- i! `
0 [0 o5 C _6 l( ]8 a0 z+ C+ \+ xAUTOMAKE_OPTIONS=foreign
2 X) _5 L8 L- h5 ~* B, Wbin_PROGRAMS=helloworld
& C' s6 ?, S5 B
helloworld_SOURCES=helloworld.c
- U& \7 L. S4 Z- U' I* Q6 g$ S' U5 W
2 h, J* {% z' I, n: C
automake会根据你写的Makefile.am来自动生成Makefile.in。
. N& {0 F) j, C( m1 x1 | {) f3 U
Makefile.am中定义的宏和目标,会指导automake生成指定的代码。例如,宏bin_PROGRAMS将导致编译和连接的目标被生成。
+ o6 x. F6 U9 x k- n
" ^/ G6 q" \$ `5 }/ i7 U# o
5、运行automake
) ]0 ]. b1 u. ]: I, m" W
1 K, Z/ C i) Q* S$ i 命令:
" [; G k: \& ?8 b5 Z+ P$ j+ }
q$ ~5 F& G, o% {8 I+ W! z* O* G5 U/ S" J' ~: }2 G
$automake--add-missing
8 y, v# u( i" p
configure.in:installing`./install-sh'
- k( K9 M% P; I- B" N9 K ]$ o
configure.in:installing`./mkinstalldirs'
0 {( |+ ?4 @! ]& q9 z4 L6 L
configure.in:installing`./missing'
' N6 x) C% W Y( u* s$ u( I9 `Makefile.am:installing`./depcomp'
* I% ]1 p$ B. u$ ~! _4 T: l
, A- U3 `0 c0 j# G) s0 ]
! O* b) K! v5 B' _
automake会根据Makefile.am文件产生一些文件,包含最重要的Makefile.in。
1 [- x' P) q2 K7 ^+ X9 S, s
* t5 ]3 E, @4 N/ c& Z 6、执行configure生成Makefile
" d! X0 W' A2 ?; {. G: I9 b; J; j$ P& |. r5 m; j2 A
3 Y; J% Q5 Z" W s" c5 H) X
$./configure
, h9 x% [( _! S# o5 I* c
checkingforaBSD-compatibleinstall.../usr/bin/install-c
9 [% J `& |$ y' acheckingwhetherbuildenvironmentissane...yes
6 Q1 T$ F8 w2 a) r! v5 Ycheckingforgawk...gawk
4 A! l- K6 q3 M, {7 t& O( @
checkingwhethermakesets$(MAKE)...yes
9 \7 U5 `" l5 G2 g3 u9 i& K% ~0 m
checkingforgcc...gcc
) S% Z4 t1 s% V7 |( kcheckingforCcompilerdefaultoutput...a.out
. I4 F" O: i% p8 ]8 ~# [checkingwhethertheCcompilerworks...yes
* i. H0 G$ S! `+ i0 W- Q
checkingwhetherwearecrosscompiling...no
: d, X6 n- D3 I$ P% t$ ucheckingforsuffixofexecutables...
, c4 z4 Y l3 W4 L* o- K, j: e9 O
checkingforsuffixof
objectfiles...o
! Q3 ^7 \- \% l/ |& ?checkingwhetherweareusingtheGNUCcompiler...yes
4 G% b/ p1 W9 {
checkingwhethergccaccepts-g...yes
* d: I2 J& G+ @. k& ^checkingforgccoptiontoacceptANSIC...noneneeded
( X# }0 i( I% L( Y' y; g
checkingforstyleofincludeusedbymake...GNU
- [, J& y \( m) n- W/ t# f& o$ W/ O# Echeckingdependencystyleofgcc...gcc3
7 L/ s* V( `& q
configure:creating./config.status
* F% p, G6 E" v& O* yconfig.status:creatingMakefile
. ~9 S* P1 p1 ^) b$ H1 E$ z2 ^config.status:executingdepfilescommands
+ G/ _. M/ |" ?0 Z$ls-lMakefile
$ G9 Q$ ^ U& F3 E-rw-rw-r--1yutaoyutao15035Oct1510:40Makefile
- H1 W a3 v- M1 O
8 b) f9 \) H X1 m; Y' F+ r7 f' ^+ Z- Z1 V. t% z
你可以看到,此时Makefile已经产生出来了。
# ] @6 z6 c2 { X0 L
8 x# N& N0 U o7、使用Makefile编译代码
( w9 D. |* T }' m- ?/ A
; J( A+ E! K6 q" ]8 c. f4 B% u
3 g8 i. P! b1 C! R* B3 r5 T
5 J: v) ^; n' o* j# n9 f5 l$make
* ~; R, _! L- z5 difgcc-DPACKAGE_NAME=""-DPACKAGE_TA
RNAME=""-DPACKAGE_VERSION=""-
: I% p3 N/ X+ S9 S' B% B$ h
+ F9 z( p& `: X5 b2 U( p x% ?DPACKAGE_STRING=""-DPACKAGE_BUGREPORT=""-DPACKAGE="helloworld"-DVERSION="1.0"
+ n& y3 b% Z: \1 Y% G5 \
& y4 h. a I8 @6 v' m8 {8 v
-I.-I.-g-O2-MThelloworld.o-MD-MP-MF".deps/helloworld.Tpo"\
6 e5 X& y8 ]9 e/ K, l) m2 I$ A
-c-ohelloworld.o`test-f'helloworld.c'││echo'./'`helloworld.c;\
! g5 L7 g* U( V) Vthenmv-f".deps/helloworld.Tpo"".deps/helloworld.Po";\
/ h6 i: I; I5 J* Felserm-f".deps/helloworld.Tpo";exit1;\
1 I, n/ F$ S* {% \3 S3 rfi
# \) U, v8 }9 G* W7 Q$ Sgcc-g-O2-ohelloworldhelloworld.o
: F+ P. J! o0 S! D$ p) L' Q x
. l) |6 P, T$ P5 c& p1 z, u2 d
' i3 E t) i' e 运行helloworld
7 Y0 S U' h8 j% {6 q7 a
; M# f$ D3 v2 y* u7 V3 @. A, j5 _: x
; k7 p; Q( h5 k1 D" W4 z
$./helloworld
^& M# d) e$ u# j* P
Hello,LinuxWorld!
8 f6 t& N- W3 s1 R6 m' k& i8 X% i$ A+ g
9 J2 V: ^2 _" ^: S1 p0 w 这样helloworld就编译出来了,你如果按上面的步骤来做的话,应该也会很容易地编译出正确的helloworld文件。你还可以试着使用一些其他的make命令,如makeclean,makeinstall,makedist,看看它们会给你什么样的效果。感觉如何?自己也能写出这么专业的Makefile,老板一定会对你刮目相看。
0 `$ _2 r& h" O9 l) k) Z
2 A& ^0 c7 w0 h! N e; j
四、深入浅出
( s1 U. |0 x5 b5 }: @
0 e1 [+ r: P7 x, |$ {4 O6 |5 D. S
针对上面提到的各个命令,我们再做些详细的介绍。
4 z/ x K( S# R, T" S7 V, x) S, V ^; |, D1 M
1、autoscan
0 i, n1 K7 Z! H2 N8 X2 u
" ?1 T/ u) b( y autoscan是用来扫描源代码目录生成configure.scan文件的。autoscan可以用目录名做为参数,但如果你不使用参数的话,那么autoscan将认为使用的是当前目录。autoscan将扫描你所指定目录中的源文件,并创建configure.scan文件。
2 I- S7 K; G/ b2 S: L
2 Z8 |+ Y0 _( P( E4 M0 s 2、configure.scan
m* G% Z6 I4 b1 S- H- Q
8 X: u$ I2 H7 o/ k9 s/ K) a configure.scan包含了系统配置的基本选项,里面都是一些宏定义。我们需要将它改名为configure.in
! E1 {& Q" O; o1 l5 Y O9 V+ @( l6 P( _* v" x
3、aclocal
, ]2 r' ~9 O+ X1 _" ]# X" x' ^7 E, g8 N$ p+ M8 R& ^; P
aclocal是一个perl脚本程序。aclocal根据configure.in文件的内容,自动生成aclocal.m4文件。aclocal的定义是:“aclocal-createaclocal.m4byscanningconfigure.ac”。
# m, S& R3 s K9 j+ t, P) O5 E
0 C2 S, x* L5 Z+ d3 ]7 G# t
4、autoconf
/ l& H" G* T: G. m3 L
0 h7 N4 S/ F$ q# [1 J3 t8 j autoconf是用来产生configure文件的。configure是一个脚本,它能设置源程序来适应各种不同的
操作系统平台,并且根据不同的系统来产生合适的Makefile,从而可以使你的源代码能在不同的操作系统平台上被编译出来。
0 J9 h# E7 L% I
+ ]- x! v) b) u3 t. H9 ^6 \4 A' d u( s
configure.in文件的内容是一些宏,这些宏经过autoconf处理后会变成检查系统特性、环境变量、软件必须的参数的shell脚本。configure.in文件中的宏的顺序并没有规定,但是你必须在所有宏的最前面和最后面分别加上AC_INIT宏和AC_OUTPUT宏。
7 e8 a m7 I1 ?2 g
! U; ~) i/ S4 E! B6 H 在configure.ini中:
; i5 M- h( S8 o; u {! s; X9 P
% F- N1 U9 W. D' L5 x #号表示注释,这个宏后面的内容将被忽略。
, t# ^3 v Q9 j1 w+ |: d6 `
2 |' u: X9 }5 N! ^1 z$ M5 D6 K AC_INIT(FILE)
$ O; D# ^& F. |0 |% B
9 J( c) {3 L: g 这个宏用来检查源代码所在的路径。
% O* ?* A, J8 n O+ x/ H
0 n0 ~7 }/ y VAM_INIT_AUTOMAKE(PACKAGE,VERSION)
$ p4 a0 F7 `8 P: _$ N8 O7 E6 q+ ]
+ {% [4 g8 V: C' c: ^7 t0 l
这个宏是必须的,它
描述了我们将要生成的软件包的名字及其版本号:PACKAGE是软件包的名字,VERSION是版本号。当你使用makedist命令时,它会给你生成一个
类似helloworld-1.0.tar.gz的软件发行包,其中就有对应的软件包的名字和版本号。
+ F9 ?$ Y! B" J$ f$ J5 k4 ^- \" R; M" L" c7 h
AC_PROG_CC
b* b4 p" X+ f2 g" r- h& a( R% M& N1 G4 i- c# b. \* J
这个宏将检查系统所用的C编译器。
& M/ R2 p! E( q5 f% i' u! F* M8 X$ z2 _4 T+ r! S
AC_OUTPUT(FILE)
7 m) q& O) R z; k" Q+ _
5 ^8 R/ ?; x: q8 Q7 H
这个宏是我们要输出的Makefile的名字。
; F6 I: n9 ^3 q- b; t- C: O
* G/ K$ A8 |% ?) {
我们在使用automake时,实际上还需要用到其他的一些宏,但我们可以用aclocal来帮我们自动产生。执行aclocal后我们会得到aclocal.m4文件。
5 X: w9 r! w# b$ e+ b4 Q
4 K; N+ ^& s6 |3 g
产生了configure.in和aclocal.m4两个宏文件后,我们就可以使用autoconf来产生configure文件了。
0 e9 t g- Z& y) n C% F) z; ?& `/ Q; S$ F+ `3 e
5、Makefile.am
2 `2 u! n$ {% V7 M9 z5 q5 ]* \6 l6 {; c, I" r3 ~
Makefile.am是用来生成Makefile.in的,需要你手工书写。Makefile.am中定义了一些内容:
5 k4 i7 `6 ?- q8 {, q4 h; U0 a
* `% e( r+ @8 T& B+ Z6 I% ?4 KAUTOMAKE_OPTIONS
* {* Q& y' P' U/ P( x X4 f9 T, P/ u: w' E; u4 U/ f$ |
这个是automake的选项。在执行automake时,它会检查目录下是否存在
标准GNU软件包中应具备的各种文件,例如AUTHORS、ChangeLog、NEWS等文件。我们将其设置成foreign时,automake会改用一般软件包的标准来检查。
/ l2 e5 H1 @: e
: a+ Q0 O. j `" G8 A/ M1 Y6 D
bin_PROGRAMS
% u% y8 b( o4 l2 u0 e. ~. G
8 F6 y5 Z) C, K) l5 T0 c9 h7 T 这个是指定我们所要产生的可执行文件的文件名。如果你要产生多个可执行文件,那么在各个名字间用空格隔开。
* r- ]( [4 W5 c5 j2 ?1 g P
& i2 E& Q7 ^; g Y! W2 Z2 i$ Ehelloworld_SOURCES
! D( N% F: h ]- J
# K1 v" q; b: c4 p" A5 e 这个是指定产生“helloworld”时所需要的源代码。如果它用到了多个源文件,那么请使用空格符号将它们隔开。比如需要helloworld.h,helloworld.c那么请写成helloworld_SOURCES=helloworld.hhelloworld.c。
* k8 x) e& J, x+ m/ \, ?: D6 |$ D3 ^5 h2 `# h d7 w! r7 l
如果你在bin_PROGRAMS定义了多个可执行文件,则对应每个可执行文件都要定义相对的filename_SOURCES。
: `; e6 ^& s& L2 C, b+ _, o% i8 ?# {6 m/ x3 z6 z5 W
6、automake
@) v- a! i9 m- G4 i
$ x8 s1 C: B3 S) V3 r) _7 y 我们使用automake--add-missing来产生Makefile.in。
% G/ J1 V1 V" l' e
$ G' C6 b& A5 y q+ I 选项--add-missing的定义是“addmissingstandardfilestopackage”,它会让automake加入一个标准的软件包所必须的一些文件。
; l a, M; t5 X# a. H$ V9 ?. B
/ x! v8 X6 H" f2 L& n 我们用automake产生出来的Makefile.in文件是符合GNUMakefile惯例的,接下来我们只要执行configure这个shell脚本就可以产生合适的Makefile文件了。
% O% w0 R% ~. Q
8 ` w: P0 X3 P2 B# j6 \* ^ 7、Makefile
" P: t4 y, _1 s/ H0 n
w- |7 y' j2 ~, j0 ~( g 在符合GNUMakefiel惯例的Makefile中,包含了一些基本的预先定义的操作:
- {% m: J9 i9 b$ L+ O
6 y5 ]1 W% I) L! }' Cmake
* a9 F% M" J; B2 Q' L
6 X& O, D/ p$ g3 m! U0 c
根据Makefile编译源代码,连接,生成目标文件,可执行文件。
; m) F9 l6 r3 Z4 }8 i+ v: H1 ^" L( Y+ O. b" u s
makeclean
) \1 h) [2 m' y, E$ [' v4 V: J6 [
: d1 |3 P- E6 j 清除上次的make命令所产生的object文件(后缀为“.o”的文件)及可执行文件。
. `* o% N3 _+ S+ S
1 }/ d- b$ j5 @makeinstall
% d+ |! w6 P2 {# ]* a( s2 J
! H2 W/ y2 v2 b, s6 q 将编译成功的可执行文件安装到系统目录中,一般为/usr/local/bin目录。
+ U3 t& h" Z! T5 }# t& P, S
4 Z2 ]+ [" I) H; {
makedist
# P9 k( U8 u% ] C0 t% @7 S
/ G$ |1 [# k1 T0 |/ C, E; S 产生发布软件包文件(即distributionpackage)。这个命令将会将可执行文件及相关文件打包成一个tar.gz压缩的文件用来作为发布软件的软件包。
9 r7 q2 m% H: k4 p/ l. K3 W1 [
, a6 s I0 S! m: R9 `! O5 H 它会在当前目录下生成一个名字类似“PACKAGE-VERSION.tar.gz”的文件。PACKAGE和VERSION,是我们在configure.in中定义的AM_INIT_AUTOMAKE(PACKAGE,VERSION)。
6 O- E3 I+ D- |9 i$ i+ ~7 P* s) H' o1 E
makedistcheck
1 ~* ~/ ]; ?5 s2 C8 g4 | c, I) {4 {( Z2 J
生成发布软件包并对其进行
测试检查,以确定发布包的正确性。这个操作将自动把压缩包文件解开,然后执行configure命令,并且执行make,来确认编译不出现错误,最后提示你软件包已经准备好,可以发布了。
0 g1 U. K% K# Y# r( p$ M$ X* M6 P/ \# N' m
===============================================
2 p( f. c# i& S4 F" N' E$ y! ^
helloworld-1.0.tar.gzisreadyfordistribution
# q2 s; H* a' L, s: C9 {===============================================
% `1 B* M. `! S* m+ X9 A4 K
makedistclean
+ _+ w* J2 i: M5 e- ?- f9 K
* p% s8 I) P' Y( e, u5 b6 o 类似makeclean,但同时也将configure生成的文件全部删除掉,包括Makefile。
! N# x' x0 z. ]- s0 u
2 V4 N/ a8 `; E) T$ m5 o& {. E
五、结束语
: d* D" S* _4 X2 N w. u4 ^
( ]4 ~! B q, W 通过上面的介绍,你应该可以很容易地生成一个你自己的符合GNU惯例的Makefile文件及对应的项目文件。
* C1 P% Q K; s4 c+ r2 @
# v5 I/ y) I2 o* ~& P/ h 如果你想写出更复杂的且符合惯例的Makefile,你可以参考一些开放代码的项目中的configure.in和Makefile.am文件,比如:嵌入式
数据库sqlite,单元测试cppunit。