make使用总结(2)-Makefile介绍

make使用总结(2)-Makefile介绍

之前已经提到了,make使用Makefile文件来描述工程中文件的组织关系以及gcc编译时的依赖关系。因此我们需要为工程项目编写一个或多个Makefile文件。下面就介绍Makefile相关的语法。

Makefile主要由显式规则隐晦规则变量定义指示命令注释五个部分组成。下面将一一介绍。

注释

makefile使用#作为注释符号。

显式规则与隐式规则

规则是make的核心。make规则的格式如下:

[目标] : [依赖]
[tab键] [shell命令]

规则告诉我们两件事:目标何时过期以及如何在目标过期时更新它们。目标通常是要生成的文件名,如最终的可执行文件或者中间文件。依赖用于指明目标何时过期,它可以是多个文件,当依赖中的某些文件发生变化时,则表明目标过期。而shell命令则用于重新生成已经过期的目标。如下面的例子。目标为main,依赖为test1.c test2.c.当test1.c或test2.c发生变化时,则make会使用gcc -o main test1.c test2.c来重新生成main.

main : test1.c test2.c
	gcc -o main test1.c test2.c

make通过比较目标文件最后修改的时间与依赖文件最后修改的时间来判定目标是否过期。当依赖修改的时间新于目标的时间时,则表明目标过期。

为了简化规则的编写。make使用%来表示规则的通配符。如下面的%.o:%.c可以匹配test.o:test.c.

%.o:%.c
	gcc -o -c -o $@ $<

为了方便编写Makefile,make定义了一些默认的规则,我们称之为隐式规则。如下面的规则,make在生成main时,首先需要获取test1.o 和test2.o,但test1.o和test2.o是中间文件。也需要生成,但用户并没有定义如生成test1.o和test2.o的规则。这是make就会使用默认的规则来查找test1.c文件来生成test1.o.

main : test1.o test2.o
	gcc -o main test1.o test2.o

我们在Makefile文件中编写的规则都叫显式规则。为了避免麻烦,建议尽量时用显示规则来表明要用到的规则。

伪目标

上面提到目标一般为要生成的文件名,但也可以是要执行的动作名。为了防止文件名与动作名重复造成的冲突。系统使用了伪目标(.PHONY)来标识动作目标.如下面的例程,目标名clean使用.PHONY:clean显式的标记成动作名。

.PHONY: clean

clean:
	rm -f *.o *.d

shell命令

当要重新生成目标时,make会调用shell去执行每一条指令。但需要注意的是,即便在同一个目标下,每一条指令都是相互独立的。也就是说make会分别调用shell去执行每一条指令,而非使用一个shell进程按顺序将所有指令都执行一遍。有些状况下,用户希望能够使用cd命令来控制命令执行时所在的路径,比如cd到某个目录下,编译其中的源代码,此时必须在一行中写入多条指令。并用;隔开。

静态模式

有时候使用静态模式规则模式的规则,可以简化规则的编写。尤其规则存在多个目标,并且不同的目标可以根据目标文件的名字来自动构造出依赖文件。使用多目标可以使makefile文件变得简洁。语法如下:

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

targets:定义了一系列的目标文件,可以有通配符。是目标的一个集合。
target-parrtern:是指明了targets的模式,也就是目标集模式。
prereq-parrterns:是目标的依赖模式。

使用例程如下:

objects = foo.o bar.o
$(objects): %.o: %.c
    $(CC) -c $(CFLAGS) $< -o $@

等价于
foo.o : foo.c
    $(CC) -c $(CFLAGS) foo.c -o foo.o
bar.o : bar.c
    $(CC) -c $(CFLAGS) bar.c -o bar.o

运行make,生成目标

在默认的方式下,我们只要在工程的根目录下输入make命令。make会在当前目录下寻找名叫Makefile的文件。然后读取文件内容,对立即赋值的变量等进行展开,最后make会寻找文件中的第一个规则目标作为最终目标。但下面的目标无法作为最终目标

  1. 伪目标无法作为最终目标。如.PHONY
  2. 模式目标无法被认定为终极目标。如%:
  3. include指定文件中的目标可以作为终极目标
    找到最终目标后,它会根据此目标的规则,进行依赖分析,当依赖不存在或过时时,进一步递归的进行依赖的生成,直到最终目标的生成。

当我们多次执行make时,会涉及到目标的重建规则,规则如下:

  1. 目标文件不存在
  2. 依赖项的时间比目标文件要晚
  3. 目标为伪目标

其他

当我们用到库时,可以在依赖列表中使用-lNAME链接共享库和静态库.依赖列表中的-lNMAE将被解析为名为libNAME.so或 libNAME.a文件。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

theboynoName

感谢鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值