《跟我一起学Makefile》笔记

来源:互联网 发布:北京80越野车数据 编辑:程序博客网 时间:2024/05/17 22:16

1}makefile介绍

1、makefile是什么?

.o 目标文件,一个大型工程,编译生成的目标文件太多,链接时需要指出中间目标 文件名,会很不方便,所以我们要把目标文件打个包生成.a 库文件,相当于.lib

.o目标文件,再经链接,生成可执行文件。

Makefile文件就是告诉make命令怎么去编译和链接程序。

反斜杠(\)  换行符。

2makefile里有什么?

 主要包含5个东西:显式规则、隐晦规则、变量定义、文件指示和注释。

3、Makefile的文件名

 一般就是Makefile,当然也可以用别的文件名,如Make.linux,make.inc;

指定特定的Makefile,可使用make -f --file参数,如make -f Make.linux

4、引用其它的Makefile

 比如我有几个Makefilea.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,并把其内容安放到当前位置。

5make的工作方式

 make工作时的执行步骤如下:

1、读入所有的Makefile

2、读入被include的其它Makefile

3、初始化文件中的变量

4、推导隐晦规则,并分析所有规则

5、为所有的目标文件创建依赖关系链

6、根据依赖关系,决定哪些目标要重新生成

7、执行生成命令


2}规则

1)通配符

make支持3个通配符:*,?,[...]

另外,~的用法,~/test表示$HOME目录下的test目录。

~hchen/test表示hchen用户宿主目录下的test目录。

*表示所有的同类文件,若有打出*,可以用转义字符”\”,如“\*”表示真正的*.

linuxtouch命令不常用,一般在使用make的时候可能会用到,用来修改文件时间戳,或者新建一个不存在的文件

2)文件搜寻

make首先会在当前目录下找文件,找不到会再到指定目录下去找。

指定目录用VPATH,它有3种方法:

1、vpath <pattern> <directories>
为符合模式<pattern>的文件指定搜索目录<directories>。
2、vpath <pattern>
清除符合模式<pattern>的文件的搜索目录。
3、vpath
清除所有已被设置好了的文件搜索目录。
vapth使用方法中的<pattern>需要包含“%”字符。

3)多目标

bigoutput littleoutput : text.ggenerate text.g -$(subst output,,$@) > $@上述规则等价于:bigoutput : text.ggenerate text.g -big > bigoutputlittleoutput : text.ggenerate text.g -little > littleoutput

其中,-$(subst output,,$@)中的“$”表示执行一个Makefile的函数,函数名为subst,后
面的为参数。关于函数,将在后面讲述。这里的这个函数是截取字符串的意思,“$@”
表示目标的集合,就像一个数组,“$@”依次取出目标,并执于命令。


3}静态模式

1

静态模式可以更加容易地定义多目标的规则。语法:

<targets ...>: <target-pattern>: <prereq-patterns ...><commands>...

targets定义了一系列的目标文件,可以有通配符。是目标的一个集合。

target-parrtern是指明了targets的模式,也就是的目标集模式。

prereq-parrterns是目标的依赖模式,它对target-parrtern形成的模式再进行一次依赖目

标的定义。

如果我们的 <target-parrtern>定义成“%.o”,意思是我们的<target>集合中都是以“.o”结尾的,而如果我们的<prereq-parrterns>定义成“%.c”,意思是对<target-parrtern>所形成的目标集进

行二次定义,其计算方法是,取<target-parrtern>模式中的“%”,并为其加上[.c]这个结尾,形成的新集合。

看一个例子:

objects = foo.o bar.oall: $(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.obar.o : bar.c$(CC) -c $(CFLAGS) bar.c -o bar.o

2)自动生成依赖

如何一个目标依赖很多头文件,那将是一个很麻烦的事情。怎么来管理这些头文件呢?

 加入“-M”的选项,即自动找寻源文件中包含的头文件,并生成一个依赖关系。

如果你使用GNU的C/C++编译器,你得用“-MM”参数,不然,“-M”参数会把一些标准库的头文件也包含进来。

我们给出了一个模式规则来产生[.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命令的用法请参看相关的使用文档。第四行就是删除临时文件。


4}书写命令

1)隐显

命令前加@就不会把命令行显示出来。

2)命令执行

 如果你要让上一条命令的结果应用在下一条命令时,你应该使用分号分隔这两条命令,并写在同一行上:

exec:cd /home/hchen; pwd 

3)嵌套执行make

 为了方便明了,我们会在每一个目录下写一个Makefile,那么总控Makefile可以这样写:

subsystem:cd subdir && $(MAKE)其等价于:subsystem:$(MAKE) -C subdir

定义$(MAKE)宏变量的意思是,也许我们的make需要一些参数,所以定义成一个变

量比较利于维护。这两个例子的意思都是先进入“subdir”目录,然后执行make命令。

 如果你要传递变量到下级Makefile中,那么你可以使用这样的声明:

export <variable ...>

如果你不想让某些变量传递到下级Makefile中,那么你可以这样声明:

unexport <variable ...>如:示例一:export variable = value等价于:export variable := value

如果你要传递所有的变量,那么,只要一个export就行了。后面什么也不用跟,表示传

递所有的变量。

 

还有一个在“嵌套执行”中比较有用的参数,“-w”会在make的过程中输出一些信息,让你看到目前的工作目录。比如,如果我们的下级make目录是“/home/hchen/gnu/make”,如果我们使用“make -w”来执行,那么当进入该目录时,我们会看到:

make: Entering directory `/home/hchen/gnu/make'.

而在完成下层make后离开目录时,我们会看到:

make: Leaving directory `/home/hchen/gnu/make'

 

 

4)定义命令包

如果Makefile中出现一些相同命令序列,那么我们可以为这些相同的命令序列定义一

个变量。定义这种命令序列的语法以“define”开始,以“endef”结束,如:

define run-yaccyacc $(firstword $^)mv y.tab.c $@endef

“run-yacc”是这个命令包的名字,其不要和Makefile中的变量重名。在“define”

和“endef”中的两行就是命令序列。这个命令包中的第一个命令是运行Yacc程序,因为

Yacc程序总是生成“y.tab.c”的文件,所以第二行的命令就是把这个文件改改名字。











0 0
原创粉丝点击