makefile-老王笔记

文件编译过程

源文件首先经过compile,生成.o文件(linux下),object file, 再把大量object file经过link合成执行文件。

compile,告诉编译器位置,只要语法正确就会生成目标文件,一个源文件对应一个目标文件(.o)

编译器需要的是语法的正确,函数与变量的声明的正确。对于后者,通常是你需要告诉编译器头文件的所在位置(头文件中应该只是声明,而定义应该放在C/C++文件中),只要所有的语法正确,编译器就可以编译出中间目标文件。一般来说,每个源文件都应该对应于一个中间目标文件(O文件或是OBJ文件)。

link, 链接函数和全局变量

链接器并不管函数所在的源文件,只管函数的中间目标文件(Object File),在大多数时候,由于源文件太多,编译生成的中间目标文件太多,而在链接时需要明显地指出中间目标文件名,这对于编译很不方便,所以,我们要给中间目标文件打个包,在Windows下这种包叫“库文件”(Library File),也就是 .lib 文件,在UNIX下,是Archive File,也就是 .a 文件。
Link 2001错误,意思说是说,链接器未能找到函数的实现。你需要指定函数的Object File.

makefile rules

/换行符,命令太长时候用
target ... : prerequisites ...
command(必须tab开头)
...
...

prerequisites就是,要生成那个target所需要的文件或是目标。
command也就是make需要执行的命令。(任意的Shell命令)
这是一个文件的依赖关系,也就是说,target这一个或多个的目标文件依赖于prerequisites中的文件,其生成规则定义在command中。
说白一点就是说,prerequisites中如果有一个以上的文件比target文件要新的话,command所定义的命令就会被执行。
这就是Makefile的规则。也就是Makefile中最核心的内容。

举个例子:

makefile

make看到.o文件就会自动把.c文件加在依赖关系中,所以不用写了, cc -c whatever.c 也会被推导出来,只写依赖的头文件(.h)就可以了
所以新的makefile

new_makefile

“.PHONY”表示,clean是个伪目标文件。写clean是个好习惯

引用makefile

在Makefile使用include关键字可以把别的Makefile包含进来,这很像C语言的#include,被包含的文件会原模原样的放在当前文件的包含位置。include的语法是:include <filename>
在include前面可以有一些空字符,但是绝不能是[Tab]键开始。include和<filename>可以用一个或多个空格隔开。
举个例子:
你有这样几个Makefile:a.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

指定makefile:

GNU make 找寻默认的 Makefile 的规则是在当前目录下依次找三个文件—— “GNUmakefile”、“makefile”和“Makefile”。其按顺序找这三个文件,一旦找到,就开始读取这个 文件并执行
而使用 make 的 -f 或是 --file 参数(--makefile 参数也行),可以给 make 命令指定一个特殊名字的 Makefile,例如,我们有个 makefile 的名字是“hchen.mk”, 那么,我们可以这样来让 make 来执行这个文件:make -f hchen.mk

指定终极目标

.phone:all
all:prog1 prog2 prog3 prog4
也算是伪目标(clean什么的也是伪目标,可以make clean 显式执行)
这个makefile中有四个需要编译的程序——“prog1”,“prog2”, “prog3”和“prog4”,我们可以使用“make all”命令来编译所有的目标(如果把all置成第一个目标,那么只需执行“make”),我们也可以使用“make prog2”来单独编译目标“prog2”

GNU的make工作时的执行步骤

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

1-5步为第一个阶段,6-7为第二个阶段。第一个阶段中,如果定义的变量被使用了,那么,make会把其展开在使用的位置。但make并不会完全马上展开,make使用的是拖延战术,如果变量出现在依赖关系的规则中,那么仅当这条依赖被决定要使用了,变量才会在其内部展开。

VPATH

大量源文件分类,存放在不同的目录中。当make需要去找寻文件的依赖关系时,可以在文件前加上路径,但最好的方法是把一个路径告诉make,让make在自动去找。
Makefile文件中的特殊变量“VPATH”就是完成这个功能的,如果没有指明这个变量,make只会在当前的目录中去找寻依赖文件和目标文件。如果定义了这个变量,那么,make就会在当当前目录找不到的情况下,到所指定的目录中去找寻文件了。
VPATH = src:../headers
上面的的定义指定两个目录,“src”和“../headers”,make会按照这个顺序进行搜索。目录由“冒号”分隔。(当然,当前目录永远是最高优先搜索的地方)

另一个设置文件搜索路径的方法是使用make的“vpath”关键字(注意,它是全小写的),这不是变量,这是一个make的关键字,有三种使用方法:

  1. vpath <pattern> <directories>
    为符合模式<pattern>的文件指定搜索目录<directories>。
    例如:vpath %.h ../headers该语句表示,要求make在“../headers”目录下搜索所有以“.h”结尾的文件。(如果某文件在当前目录没有找到的话)
  2. vpath <pattern>
    清除符合模式<pattern>的文件的搜索目录。
  3. vpath
    清除所有已被设置好了的文件搜索目录。

vapth使用方法中的<pattern>需要包含“%”字符。“%”的意思是匹配零或若干字符,例如,“%.h”表示所有以“.h”结尾的文件。<pattern>指定了要搜索的文件集,而<directories>则指定了<pattern>的文件集的搜索的目录。如果连续的vpath语句中出现了相同的<pattern>,或是被重复了的<pattern>,那么,make会按照vpath语句的先后顺序来执行搜索

多目标

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

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

make的参数(老王笔记):

-b, -m 这两个参数的作用是忽略和其它版本 make 的兼容性。 -B, --always-make 认为所有的目标都需要更新(重编译)。
-C <dir>, --directory=<dir> 指定读取 makefile 的目录。如果有多个“-C”参数,make 的解释是 后面的路径以前面的作为相对路径,并以最后的目录作为被指定目录。如:“make -C ~hchen/test -C prog”等价于“make -C ~hchen/test/prog”。

-debug[=<options>] 输出 make 的调试信息。如果没有参数,那就是 输出最简单的调试信息。下面是 <options> 的取值:
• a: 也就是 all,输出所有的调试信息。(会非常的多)
• b: 也就是 basic,只输出简单的调试信息。即输出不需要重编译的目标。
• v: 也就是 verbose,在 b 选项的级别之上。输出的信息包括哪个 makefile 被解析,不需 要被重编译的依赖文件(或是依赖目标)等
• i: 也就是 implicit,输出所以的隐含规则。
• j: 也就是 jobs,输出执行规则中命令的详细信息,如命令的 PID、返回码等。
• m: 也就是 makefile,输出 make 读取 makefile,更新 makefile,执行 makefile 的信 息。
-d 相当于“--debug=a”。
-e, --environment-overrides 指明环境变量的值覆盖 makefile 中定义的变量的值。
-f=<file>, --file=<file>, --makefile=<file> 指定需要执行的 makefile。
-h, --help 显示帮助信息。
-i , --ignore-errors 在执行时忽略所有的错误。
-I <dir>, --include-dir=<dir> 指定一个被包含 makefile 的搜索目标。可以使用多个“-I”参数 来指定多个目录。
-j [<jobsnum>], --jobs[=<jobsnum>] 指同时运行命令的个数。如果没有这个参数,make 运行命令 时能运行多少就运行多少。如果有一个以上的“-j”参数,那么仅最后一个“-j”才是有效的。(注 意这个参数在 MS-DOS 中是无用的)
-k, --keep-going 出错也不停止运行。如果生成一个目标失败了,那么依赖于其上的目标就不会被执 行了。
-l <load>, --load-average[=<load>], -max-load[=<load>] 指定 make 运行命令的负载。
-n, --just-print, --dry-run, --recon 仅输出执行过程中的命令序列,但并不执行。
-o <file>, --old-file=<file>, --assume-old=<file> 不重新生成的指定的 <file>,即使这个目 标的依赖文件新于它。
-p, --print-data-base 输出 makefile 中的所有数据,包括所有的规则和变量。这个参数会让一个 简单的 makefile 都会输出一堆信息。如果你只是想输出信息而不想执行 makefile,你可以使用 “make -qp”命令。如果你想查看执行 makefile 前的预设变量和规则,你可以使用“make –p – f /dev/null”。这个参数输出的信息会包含着你的 makefile 文件的文件名和行号,所以,用这
个参数来调试你的 makefile 会是很有用的,特别是当你的环境变量很复杂的时候。-q, --question 不运行命令,也不输出。仅仅是检查所指定的目标是否需要更新。如果是 0 则说明要
更新,如果是 2 则说明有错误发生。-r, --no-builtin-rules 禁止 make 使用任何隐含规则。-R, --no-builtin-variabes 禁止 make 使用任何作用于变量上的隐含规则。 -s, --silent, --quiet 在命令运行时不输出命令的输出。
-S, --no-keep-going, --stop 取消“-k”选项的作用。因为有些时候,make 的选项是从环境变量 “MAKEFLAGS”中继承下来的。所以你可以在命令行中使用这个参数来让环境变量中的“-k”选项
失效。
-t, --touch 相当于 UNIX 的 touch 命令,只是把目标的修改日期变成最新的,也就是阻止生成目标 的命令运行。

-v, --version 输出 make 程序的版本、版权等关于 make 的信息。
-w, --print-directory 输出运行 makefile 之前和之后的信息。这个参数对于跟踪嵌套式调用 make
时很有用。
--no-print-directory 禁止“-w”选项。
-W <file>, --what-if=<file>, --new-file=<file>, --assume-file=<file> 假定目标 <file>; 需要更新,如果和“-n”选项使用,那么这个参数会输出该目标更新时的运行动作。如果没有“-n” 那么就像运行 UNIX 的“touch”命令一样,使得 <file>; 的修改时间为当前时间。
--warn-undefined-variables 只要 make 发现有未定义的变量,那么就输出警告信息。

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

推荐阅读更多精彩内容

  • 来自陈浩的一片老文,但绝对营养。 示例工程:3 个头文件*.h,和 8 个 C 文件*.c。 初 编译过程,源文件...
    周筱鲁阅读 4,668评论 0 17
  • 本文章介绍了makefile跟kconfig文件,包括编译过程与makefile编码规则。 编译过程:我们在进行l...
    超低空阅读 17,402评论 0 5
  • makefile关系到整个工程的编译规则,一个工程中的源文件不计其数,按其类型、功能、模块分别放在若干的目录当中,...
    Joe_HUST阅读 1,870评论 0 3
  • 喜欢看漫画,后来随便画画,不过是画个人的上半身,描描头发,没有四肢,什么技巧色彩一窍不通。大学毕业后已经七...
    洋芋公主阅读 975评论 2 1
  • 文/雁南飞 一端上来,被像盆一样大的碗把我吓得不轻快。
    雁南飞fly阅读 474评论 21 33