为什么要使用Makefile工具?. W3 G. |- H c8 O* d
当源码文件比较多的时候,不适合直接gcc命令来编译,这时候需要一个自动化编译工具来编译。Make 一般说是GNU Make 是一个软件,用于将源码文件编译器为可执行的二进制文件,make工具主要用于完整自动化编译,make编译的时候需要Makefile文件提供编译文件。5 s/ h: A) z! A( D' C
1、引入Makefile- + ]3 E6 G. J; ]% G
- a.c------>***.s------>***.o% ~9 D) f E0 v0 k, c- I' ^
- b.c------>xxx.s------>xxx.o
5 m) |2 d" k8 L: z - xxx.o + ***.o ------>test
复制代码
! W6 i+ i; V, \0 [9 y( c缺点:修改任一个文件所有.c都要重新编译,文件更多时可想而知,时间耗不起!0 f b8 ~7 Q @* L* c6 R
改进:应该分别编译,最后再链接
1 F, e& D6 H; R" X/ d- 0 ], p! n; x5 O% {7 e: O) \
- gcc -c a.c
2 s% X/ {2 {" g% C7 Q8 o" W - gcc -c b.c* m8 ]' b5 G3 g( s0 d! `8 T- w1 m
- gcc a.o b.o –o test
复制代码
6 c. l9 r( j( Z( |+ w- y为此需要一个这样的工具:
2 F5 H2 J( B. Z3 E8 T7 d' a01.如果工程没有编译过,那么工程中的所有.c文件都要被编译并且链接成可执行程序。7 i4 d1 e; P* R' ~" G+ q* g
02.如果工程中只有个别C 文件被修改了,那么只编译这些被修改的C文件即可。
1 f* a' x2 `' }* {7 D8 D03.如果工程的头文件被修改了,那么我们需要编译所有引用这个头文件的C文件,并且链接成可执行文件。8 P6 l& ?" h% e5 r' G4 K! g
2、makefile 的基本规则: 当依赖比目标新执行命令0 d3 r; T: p# [) c; M* Z
目标文件:依赖文件
* @: p4 S( { o! M! m5 ETAB键 命令
& t6 v6 D( N8 `* e根据Makefile的基本规则,我们针对上面的gcc编译过程来写一个Makefile文件,如下所示:
# v2 R) |: o1 b# ?) R' L1 f
- K/ a1 L( t6 u- test:a.o b.o" v# D' C5 K9 s' V7 V
- gcc –o test a.o b.o
m7 o" i" Z& K - a.o: a.c8 c3 s5 ?9 y) j( s6 O B- K
- gcc -c a.c
2 h% D/ l- K. n, o; g5 O. \ - b.o: b.c% y8 w- Z2 a) X: K
- gcc -c b.c) X7 D' R" u7 B7 |+ r. D
- clean:2 j4 a: B. [( ^* c4 T8 b
- rm *.o
$ z& j7 ?' y9 [1 U9 C" \& R- C - rm test
复制代码 : P: H. C& T. f% t
这样我们使用 make 命令就可以完成对 a.c b.c的编译和链接,直接生成test执行文件。
! i0 h; I/ F1 I d- i3、Makefile 的变量
: V2 [- K; s4 N8 yMakefile 也可以添加变量,但Makefile跟C语言不一样,没有类似于 int char …等很多的类型,只有字符串类型,比如可以定义一个 object = a.o b.o 引用变量使用$(objdect)即可。
+ {( {6 N9 J# |# X. [: h, o+ |这样就可以将上面的Makefile尽心简化,不需要输入两次的 a.o b.o, 具体如下:
6 D# U8 F. x9 h; h# m
1 z7 q& k9 Y3 s: w' e% d( a( k' j- objdect = a.o b.o
% N& Q6 \- j8 f* v5 y' ?) j - test:$(object)- @) \8 G. C! m. G4 t
- gcc –o test $(object)
6 Q# F, e Y5 m$ f - a.o: a.c# c) u. i4 N3 [
- gcc -c a.c/ w `1 z; o: u! A& ]3 r
- b.o: b.c4 m+ R. c+ s6 Q2 O, |/ _& G; G
- gcc -c b.c: P& C/ Q3 W( n* E4 w
- clean:. W" F o5 r1 R S( M
- rm *.o
4 }* e* l& [% `2 ~) K - rm test
复制代码 ~/ R$ I8 \. N: R* o& m
4、Makefile的通配符%和自动化变量9 o6 E/ d3 H6 j e8 C) w
对于上面的Makefile如果有很多.c文件,那我们就需要写很多依赖规则,可以使用通配符来对其简化,%.c 表示所有的.c文件,%.o表示所有的.o文件,当然我们就可以把上面的!( |1 u; a' _: W( B
b.o 依赖于 b.c和a.o依赖于a.c 等写成 %.o 依赖%.c的形式。对于命令则需要引入另一个叫做自动化变量了,如何通过一行命令来从不同的依赖文件中生成对应的目标?自动化变量就是用来实现这个功能的。在自动化变量中常用的是$@、$<、$^7 S z" y; |9 e- Z; I: s
$@ : 规则中目标集合( j9 k( `( p. Y
$< :依赖文件集合中的第一个文件7 k3 s& K2 j0 Z/ E/ f1 _- W
$^ :所有依赖文件的集合7 R+ h1 r. T: R4 U" i" ?
这样我们又可以对MakeFile进行简化啦……….,如下所示:. c( H6 B( [: p) k: V# n K
* x( V- E$ D' ~) V- objdect = a.o b.o
+ w3 g; I0 \1 Z; W3 K - test:$(object)0 {5 v2 L! P5 H, T9 A' L8 T1 @
- gcc –o test $(object)
: e: w: T6 u2 M7 } - %.o: %.c
: a8 G9 l9 o% i$ F' C3 G! s - gcc -c [ DISCUZ_CODE_0 ]lt;
' I% m: r/ H$ ~8 V2 [ - clean:
: v; Q! v( n5 _- A- a* O1 f - rm *.o5 s! l- {2 R8 O
- rm test
复制代码 ; L5 a7 p- e+ ?9 @% A4 X* B
5、Makefile伪目标
0 m; }7 O) b# R我们总是使用make clean来执行删除任务,单当我们在当前目录添加一个名为clean的文件,那么make clean还能奏效吗?如下:
3 C' }/ s4 o" ?* B4 }1 @& U
- |4 e3 J% t" \( ^% |解决办法:使用伪目标,将clean定义为假想目标即可。( \/ S1 ^! z/ ^0 T; G( ^% R' i
- 5 N& L, X' K/ A. h$ h6 E( E+ z0 L
- objdect = a.o b.o5 j/ R( w4 O) K0 h, N
- test:$(object)8 F: Y, I" K1 ^) k2 ~6 L
- gcc –o test $(object)
+ j% z! J, R) z8 w: D - %.o: %.c
V. F; o) l6 I/ O0 ]" s! l - gcc -c [ DISCUZ_CODE_0 ]lt;
2 \ f2 F, L1 `! _+ l - clean:5 a8 }, }& H' p" Z1 \
- rm *.o test- v `/ ~- w G8 t9 d
- .PHONY:clean
复制代码 - A- h( Z! y; p# s# K
6、Makefile条件判断Makefile同样支持条件判断,语法有两种如下:
0 p% G7 q) D; i% C4 k4 X% q<条件关键字>
9 F' Z% u1 j! P. M! f <条件为真时执行的语句>
$ L. i* L" s5 G: x, S: H& uendif
3 r y, j I% p$ h <条件关键字>! u1 q7 y8 C' r% X( r$ Q$ {" `
<条件为真时执行的语句>
6 ~ n9 h1 |$ r- B' K* `! Jelse
x) j; @6 E+ P1 ~, t) M <条件为假时执行的语句>
- `. V$ V; P ] i: S1 Oendif - N: G7 s0 _- R U, h7 U6 u% n
条件关键字:ifeq、ifneq、ifdef、ifndef,四个条件关键字分为两对:ifeq和ifneq用于是否相等;ifdef和ifndef 用于判断是否定义。
7 v# y( I+ [/ q! ^, i7 [1 N3 r( \! u5 W" P0 z" I
|