Makefile学习总结

相信做过rom开发的,尤其做过机型适配的,一定知道makefile的重要性。
这里我开了个章节,专门针对makefile做入门学习,学习的内容就是陈皓老师的 跟我一起写makefile.个人感觉作为入门还是比较经典的,当然更详细的可以看看 《GNU make 学习手册》

Makefile入门(一):概述
Makefile入门(二):MakeFile介绍
Makefile入门(三):书写规则
Makefile入门(四):书写命令
Makefile入门(五):使用变量
Makefile入门(六):使用条件判断
Makefile入门(七):使用函数
Makefile入门(八):make运行
Makefile入门(九):隐含规则
Makefile入门(十):使用make更新函数库文件
Android.mk入门
理解 Android Build 系统

针对十一篇的内容做一个简单的提炼:

一、概述

1.什么是makefile?
一个工程中的源文件不计其数,并且按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个 Shell脚本一样,其中也可以执行操作系统的命令。

我们可以简单的把makefile认为是一份定义了源文件间依赖关系、如何编译各个源文件并生成可执行文件的说明书。makefile关系到了整个工程的编译规则,makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。

2.程序的编译和链接
首先要把源文件编译成中间代码文件,这个动作叫做编译(compile),
然后再把大量的中间代码文件合成执行文件,这个动作叫作链接(link)

make命令执行时,需要一个 makefile 文件,以告诉make命令如何去编译和链接程序。一个示例:我们的工程有8个c文件,和3个头文件,我们要写一个makefile来告诉make命令如何编译和链接这几个文件
编译链接规则:
1)如果这个工程没有编译过,那么我们的所有c文件都要编译并被链接。
2)如果这个工程的某几个c文件被修改,那么我们只编译被修改的c文件,并链接目标程序。
3)如果这个工程的头文件被改变了,那么我们需要编译引用了这几个头文件的c文件,并链接目标程序

二、makefile介绍

1.makefile规则
target ... : prerequisites ...
command
...
...
target可以是一个object file(目标文件),也可以是一个执行文件,还可以是一个标签(label)。对于标签这种特性,在后续的“伪目标”章节中会有叙述。
prerequisites就是,要生成那个target所需要的文件或是目标。
command也就是make需要执行的命令。(任意的shell命令)
另外command前使用tab

2.make是如何工作的

  1. make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
  2. 如果找到,它会找文件中的第一个目标文件(target),并把这个文件作为最终的目标文件。
  3. 如果目标文件不存在,或是目标文件所依赖的文件的修改时间要比目标文件新,那么,他就会执行后面所定义的命令来生成目标文件。
  4. 如果目标文件所依赖的文件也不存在,那么make会在当前文件中以此依赖的文件为目标寻找它的依赖性,如果找到则再根据那一个规则生成当前的依赖文件。(这有点像一个堆栈的过程)

这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,就不工作了。

3.makefile的工作方式:

  1. 读入所有的Makefile。
  2. 读入被include的其它Makefile。
  3. 初始化文件中的变量。
  4. 推导隐晦规则,并分析所有规则。
  5. 为所有的目标文件创建依赖关系链。
  6. 根据依赖关系,决定哪些目标要重新生成。
  7. 执行生成命令

三、书写规则与书写命令

一般来说,make会以UNIX的标准Shell,也就是/bin/sh来执行命令。
1.通配符
make支持三个通配符:“*”,“?”和“~”。这是和Unix的B-Shell是相同的。

2.伪目标
.PHONY: clean
clean:
rm *.o temp

“伪目标”并不是一个文件,只是一个标签,由于“伪目标”不是文件,所以make无法生成它的依赖关系和决定它是否要执行。我们只有通过显示地指明这个“目标”才能让其生效。为了避免和文件重名的这种情况,我们可以使用一个特殊的标记“.PHONY”来显示地指明一个目标是“伪目标”,向make说明,不管是否有这个文件,这个目标就是“伪目标”。伪目标一般没有依赖的文件。但是,我们也可以为伪目标指定所依赖的文件。伪目标同样可以作为“默认目标”,只要将其放在第一个。一个示例就是,如果你的 Makefile需要一口气生成若干个可执行文件,但你只想简单地敲一个make完事,并且,所有的目标文件都写在一个Makefile中,那么你可以使 用“伪目标”这个特性。

3.显示命令
当我们用“@”字符在命令行前,那么,这个命令将不被make显示出来,最具代表性的例子是,我们用这个功能来像屏幕显示一些信息。如:
@echo 正在编译XXX模块......
当make执行时,会输出“正在编译XXX模块......”字串,但不会输出命令,如果没有“@”,那么,make将输出:
echo 正在编译XXX模块......
正在编译XXX模块......

4.命令执行
当依赖目标新于目标时,也就是当规则的目标需要被更新时,make会一条一条的执行其后的命令。需要注意的是,如果你要让上一条命令的结果应用在下一条命令时,你应该使用分号分隔这两条命令
例如:
exec:
cd /home/hchen; pwd
会先执行cd 再执行pwd

四. 使用变量

1.变量的定义与使用
举例:
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文件字符串被重复了两次,可以使用变量来定义:
objects = main.o kbd.o command.o display.o \

            insert.o search.o files.o utils.o

使用变量:$(objects)

2.变量的赋值方式

= 是最基本的赋值
:= 是覆盖之前的值
?= 是如果没有被赋值过就赋予等号后面的值
+= 是添加等号后面的值

"=":递归赋值,即赋值后并不马上生效,等到使用时才真正的赋值,此时通过递归找出当前的值,所有在使用是很有可并不是开始赋的值,所有使用时有应
":=":直接赋值,这就是我们常规的那种赋值方式,一赋值马上有效。在没赋值是为空字符。前面的变量不能使用后面的变量,只能使用前面已定义好的变量
"?=":仅仅在变量还没赋值的情况下才有效,所有一般用在第一次赋值。
"+=": 在变量后加上字符

五、条件判断

条件表达式的语法为:
<conditional-directive>
<text-if-true>
endif
以及:
<conditional-directive>
<text-if-true>
else
<text-if-false>
endif
关键字分为两对:每一对都是相反的意思,所以挑一个讲就行
ifeq 、ifneq
ifdef 、ifndef

1.ifeq <variable-name>比较参数的值是否相等

ifeq (<arg1>, <arg2>)
ifeq '<arg1>' '<arg2>'
ifeq "<arg1>" "<arg2>"
ifeq "<arg1>" '<arg2>'
ifeq '<arg1>' "<arg2>"

比较参数“arg1”和“arg2”的值是否相同。当然,参数中我们还可以使用make的函数。如:
ifeq ((strip(foo)),)
<text-if-empty>
endif
2.ifdef <variable-name> 如果变量<variable-name>的值非空,那到表达式为真。否则,表达式为假
示例一:
bar =
foo = $(bar)
ifdef foo
frobozz = yes
else
frobozz = no
endif
示例二:
foo =
ifdef foo
frobozz = yes
else
frobozz = no
endif

六、使用函数

函数调用,很像变量的使用,也是以“”来标识的,其语法如下:(<function> <arguments>)
或是
{ } 这里,就是函数名,make支持的函数不多。为函数的参数,参数间以逗号“,”分隔,而函数名和参数之间以“空格”分隔。函数调用以“公式输入有误(subst a,b,公式输入有误(subst a,b,{x})”的形式。因为统一会更清楚,也会减少一些不必要的麻烦。

具体函数可以看函数篇,不在此总结了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,254评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,875评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,682评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,896评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,015评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,152评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,208评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,962评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,388评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,700评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,867评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,551评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,186评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,901评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,689评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,757评论 2 351

推荐阅读更多精彩内容