Makefile学习笔记

本文详细介绍了Makefile的工作原理和编写技巧,包括依赖关系树、目标文件的生成规则、自动变量的使用、隐晦规则、预定义变量和编译选项等。通过实例解析了如何构建、优化Makefile,如使用变量减少重复、自动推导依赖关系、创建子目录等,旨在帮助开发者更好地理解和运用Makefile。
摘要由CSDN通过智能技术生成

主要参考文档:《跟我一起写makefile》这里有一篇《谈谈职业规划——CSDN对陈皓的采访》,被采访的大牛就是这个文档的作者,他的CSDN专栏。本文的示例工程及Makefile 在这里

一、关于Makefile的一些Tips

1. 整个Makefile是按照“依赖关系树”来执行的,Makefile中的所有依赖根据各种规则定义出来,Makefile识别这些规则,并建立一个树状的依赖关系数据结构,并根据该数据结构的指导,有序地进行各项操作,从“依赖关系树”的各个叶子节点汇集到根节点,即Makefile的最终target,Build出target。这里的“依赖关系”实际上就是用了说明“目标文件是由哪些文件生成的”。当“依赖关系树”中的某个节点发生了改变,那么再次执行make时,从该节点往上到根节点,所有直接或间接依赖于该节点的中间节点和根节点都会被重新执行。

2. 在定义好依赖关系后,后续的那一行定义了如何生成目标文件的操作系统命令,一定要以一个Tab键作为开头。记住,make并不管命令是怎么工作的,他只管执行所定义的命令。make会比较targets文件和prerequisites文件的修改日期,如果prerequisites文件的日期要比targets文件的日期要新,或者target不存在的话,那么,make就会执行后续定义的命令。

3. Makefile中,一个标签的“:”后面(同一行)如果没有其他内容,则该标签只是一个动作的名字,有点像C语言中的lable,make就不会自动去找什么依赖性,而是去执行该标签的下一行所定义的命令(以一个Tab开头)。

4. make命令通常以在Makefile文件中找到的第一个标签作为其build的目标。而对于其他标签,如果根据依赖关系,能遍历到,则该标签对应的内容就会被执行,否则不会被执行。对于这种默认不会被执行到的标签,也可以显式地让它被执行。方法就是,在make命令后面显式地加上该标签。

5. 对于下面的四行,第三行和第四行中都有$(objects),看上去貌似重复定义了,但实际上二者有着不同的含义。第三行实际上是定义了“依赖关系树”中的edit节点和它的所有子节点之间的依赖关系数据结构,$(objects)在这里充当依赖树中的edit节点的子节点。而第四行定义了“为了生成edit节点,需要做什么动作”,$(objects)在这里为make提供了生成edit所需要的参数。即,第三行和“创建树状数据结构”相关,第四行定义的是“生成某个节点的具体参数”。

objects = main.o kbd.o command.o display.o \
    insert.o search.o files.o utils.o
edit : $(objects)
    cc -o edit $(objects)

6. Makefile 文件一般都以 Makefile 或 makefile 作为文件名,这两个文件名任何make 命令都能识别。如果以其他文件名命名Makefile文件,比如 Make.Linux,可以这样让make命令加载它:make -f Make.Linux

7. 在 Makefile 中,规则的顺序是很重要的,因为,Makefile 中只应该有一个最终目标,其它的目标都是被这个目标所连带出来的,所以一定要让 make 知道你的最终目标是什么。一般来说,定义在 Makefile 中的目标可能会有很多,但是第一条规则中的目标将被确立为最终的目标。 如果第一条规则中的目标有很多个, 那么, 第一个目标会成为最终的目标。make所完成的也就是这个目标。

8. 在 Makefile 中的命令, 必须要以[Tab]键开始。

9. Makefile 规则包含两个部分,一个是依赖关系,一个是生成目标的方法

10. 标签的下一行可以不是命令,比如:

kbd.o : defs.h command.h

其实,它包含隐含的生成目标的方法的命令:

    cc -c kbd.c

再比如:

objects = main.o kbd.o command.o display.o \
    insert.o search.o files.o utils.o
all : edit
edit : $(objects)
    cc -o edit $(objects)

这里的 all : edit 一行后面就没有定义什么命令,但它会间接调用 cc -o edit $(objects)

11. 关于通配符

对于 objects = *.o 这样的变量定义,并不是说[*.o]会展开,事实上,objects的值就是“*.o”。Makefile中的变量其实就是C/C++中的宏。如果你要让通配符在变量中展开,也就是让objects的值是所有[.o]的文件名的集合,那么,你可以这样:objects := $(wildcard *.o),其中 wildcard 是Makefile 的关键字。可以尝试用这种方法在Makefile中打印出各种Makefile 自动变量的值。

Makefile 中的"%"的意思是匹配零或若干字符,例如,“%.h”表示所有以“.h”结尾的文件。

12. 带问号的变量赋值

CC ?= gcc

的意思是,如果CC没有被赋过值,则 CC=gcc,否则不做任何操作,即CC取先前已赋的值。

13. Makefile.in中的 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值