make 知识小记

于 2012年03月19日 发布在 linux应用 跳到评论

/*写完来吐槽下,,make的语法够多够复杂的。。。*/

make 可以简化编译过程,如果有一个近百个源文件的项目,如果有个文件更改后工程需要重新编译,那么一直用gcc -c a.c这些个命令敲来敲去会屎人的。运行make时候,他会寻找指定目录下(默认是 .)的Makefile文件并且分析依赖关系进行必要的编译。

Makefile文件的基本格式很简单:

目标文件: 依赖文件1 依赖文件2 依赖文件3 。。。。

[tab]编译命令

他的意思是目标文件是依赖于冒号后面几个文件的,如果这些依赖文件有更新的,那么其目标文件也需要更新。

Makefile中可能有很多以上条目,他们共同组成了一个有向无回路图(DAG图),这样可以传递依赖。make命令会把Makefile文件的第一个目标文件作为默认目标,当执行make命令时,make会考察这个目标文件的依赖关系,进行编译。也可以指定,比如这个Makefile:

main: a.o b.o

[tab]gcc -o main a.o b.o

a.o : a.c c.h

[tab]gcc -c a.c -o a.o

b.o: b.c c.h

[tab]gcc -c b.c -o b.o

#[tab]的意思是这里用tab字符代替,不能有其他的什么字符

在命令行里执行make,分析关系并生成main,如果是make a.o那么他只会编译到 a.o 。

当然我们还可以设定伪目标,比如:

clean:

[tab]rm a.o b.o

这样执行make clean的时候就把.o文件清除了,这里不会生成什么文件,只进行一些操作,更清楚的做法是在前面加上以下语句:

 .PHONY : clean install dest [其他伪目标]

下面来说下变量,Makefile里的变量按惯例是大写,包括数字字母下划线。当我们需要一个变量的值的时候,通常用${NAME} 或者$(NAME)。他有好几种变量定义的方法。

首先是常规法,就是A=content,等号两边可以有空格,和shell不一样。

其次是递归法,比如A=$(B),B=$(C),C=haha,那么当寻找A的定义的时候就会去找B,然后再找C,变量展开的时候就是当他被引用的时候,这种方法效率比较低,因为如果他引用了函数,那么每次展开都要调用函数,而且可能会出现无限递归(A=$(B),B=$(A),)。

然后是直接展开法。这个很容易理解,就像是c语言是按照顺序执行的,当变量定义的时候这个变量就已经展开了(如果他引用了变量A,引用的是他定义时候A的值),当被引用的时候就直接用他代表的字符串替代。但是他用的不是等号 是 := ,比如 A:=hello,A:=$(B)。

还有嵌套定义: A=B,B=haha,V=$($(A))类似于这种的V的值是haha

最后是替换引用定义,他会替换后缀,有个例子很好 foo := a.o b.o c.o ,bar := $(foo:.o=.c),我们可以知道bar的值就是 a.c b.c c.c。

 

变量还有分类:

1.预定义变量,当使用隐式规则的时候他会派上用场,常用的有以下几个:

CC   c编译器的名称(默认gcc?)

CPP    c预编译器名称(默认$(CC) -E)

CXX c++编译器的名称(默认g++)

CFLAGS c编译器选项,无默认值

CXXFLAGS c++编译器选项,无默认值

2.自动变量,常用有以下:

$@:表示当前规则中的完整目标文件名

$*:不包含扩展名的目标文件名

$<:当前规则中第一个依赖文件名

$^:当前规则所有文件列表

$%:当目标为库文件时,表示库文件名

3.环境变量,Makefile对环境变量是可见的,可以引用.

 

Makefile中还有函数,也可以执行shell命令..懒..不细说了..

 

Makefile还有个常用的东东就是隐式规则,make会自己推导.比如说

c:a.o b.o

[tab]gcc -o c a.o b.o

这时我们可以省略下面的命令,直接用第一行就行。make自动分析生成a,此时预定义变量就有用了,CC,CFLAGS等也派上了用场。

由于把握不了隐式规则的底线和能力,我还是觉得隐式规则应用的不要太多太复杂影响阅读为好。。

make的工作过程大概是一下几步

1.读取Makefile,根据make的选项查找Makefile

2.初始化Makefile,将Makefile中的变量进行替换,如果Makefile中包含其他文件,则加载他

3.解释规则,对其中的执行规则进行解析,推导隐藏规则,为目标建立关系链

4.分析变更,根据依赖关系和时间戳,判断有木有变化。

5.执行。

参考资料:

1.跟我一起写Makefile:http://www.chinaunix.net/jh/23/408225.html

2.《linux常用工具入门到精通》 ,page 231

3.《鸟哥的linux私房菜》,第二版,Page 397

 

 

 

 

留下评论!

:wink: :twisted: :roll: :oops: :mrgreen: :lol: :idea: :evil: :cry: :arrow: :?: :-| :-x :-o :-P :-D :-? :) :( :!: 8-O 8)