Makefile学习笔记2

来源:互联网 发布:大数据人才需求趋势 编辑:程序博客网 时间:2024/05/09 02:09

Makefile学习笔记2

Makefile规则

makefile中终极目标只有一个,必须是第一个。其他规则的书写顺序在makefile中没有意义
多目标中,第一个将会被作为终极目标。

终极目标是执行make的唯一目的,其所在的规则作为第一个被执行的规则。而其他的规则时在完成重建“终极目标”的过程中被连带出来的。所以这些目标所在的规则在Makefile中的顺序无关紧要。

依赖的类型

两种依赖关系:
1. 常规依赖

只要这个依赖有更新,就会更新目标
2. order-only依赖
只在目标不存在的情况下,依赖才会被更新,否则这个以来的规则不会更新

书写方法

LIBS=libtest.afoo: foo.c | $(LIBS)    $(CC) $(CFLAGS) $< -o $(LIBS)

foo.c就是常规依赖,foo.c比foo新时,就会重新生成foo
libtest.a就是order-only依赖,更新时,foo不会重新生成。

文件名使用通配符

Makefile中表示文件名时可使用通配符。可使用的通配符有“*”,“?”和“[…]”。
可以用在两个地方:
1. 规则的目标和依赖中
2. 规则的命令中
除了这两种上下文,其他的场景不能直接使用通配符,要使用函数wildcard来处理

举例:

clean:    rm -f *.o

函数wildcard

objects=$(wildcard *.o)

目标搜寻

依赖文件的搜索路径
环境变量VPATH
关键字vpath

伪目标

强制目标(没有命令或依赖的规则)

强制目标被认为总是更新过的,把这个目标作为依赖时,依赖它的目标总是被更新
比如:

clean: force    rm -f *.oforce:;

因为force被认为总是更新过的,所以make会认为force比clean新,导致clean的命令总是被执行。

空目标文件

伪目标的一个变种。
空目标文件通常是一个空文件,它只用来记录被更新的时间
如:

print: foo.c bar.c    lpr -p $?    touch print

执行make print时,如果print不存在,print会被创建,其次,如果foo.c或bar.c比print新时,命令也会被执行,否则不执行命令。

Makefile的特殊目标

.PHONY:定义伪目标, 伪目标所在的规则定义的命令会被无条件执行
.SUFFIXES:特殊目标“SUFFIXES”的所有依赖指出了一系列在后缀规则中需要检查的后缀名。

.DEFAULT:这个规则定义的命令,被用在重建哪些没有具体规则的目标。
.PRECIOUS:目标“.PRECIOUS”的所有依赖文件在make过程中会被特殊处理:当命令在执行过程中被中断时,make不会删除它们。而且如果目标的依赖文件是中间过程文件,同样这些文件不会被删除。这一点目标“.PRECIOUS”和目标“.SECONDARY”实现的功能相同。
.INTERMEDIATE:目标“.INTERMEDIATE”的依赖文件在make时被作为中间过程文件对待。没有任何依赖文件的目标”.INTERMEDIATE”没有意义。
.SECONDARY:目标“.SECONDARY”的依赖文件被作为中间过程文件对待。但这些文件不会被自动删除。没有热河依赖文件的目标“.SECONDARY”的含义是:将所有的文件作为中间过程文件(不会自动删除任何文件)。
.DELETE_ON_ERROR:如果在Makefile中存在特殊目标“.DELETE_ON_ERROR”,make在执行过程中,如果规则的命令执行错误,将删除一杯修改的目标文件。
.IGNORE:如果给目标“.IGNORE”指定依赖文件,则忽略创建这个文件所执行命令的错误。给此目标指定命令时没有意义的。当此目标没有依赖文件时,将忽略所哟命令执行的错误。
.LOW_RESOLUTION_TIME:目标“.LOW_RESOLUTION_TIME”的依赖文件被make认为是低分辨率的时间戳文件。
.SILENT: 出现在目标“.SILENT”的依赖列表中的文件,make在创建这些文件时,不打印出重建此文件做执行的命令,没有依赖文件,表示不打印任何命令。
.EXPORT_ALL_VARIABLES:此目标应该作为一个简单的没有依赖的目标,它的功能含义是将之后所有的变量传递给子make进程。
.NOTPARALLEL:Makefile中,如果出现目标“.NOPARALLEL”,则所有命令按照串行方式执行,即使存在make -j参数。

多目标

一个规则中可以有多个目标,规则的命令对所有的目标有效。相当于多个规则,规则的命令对不同的目标执行效果不同,多目标意味所有的目标有相同的依赖。
通常有两种情况:
* 仅需要一个描述依赖关系的规则,不需要在规则中定义命令。例如:

kbd.o command.o files.o: command.h

多规则目标

Makefile中,一个文件可以作为多个规则的目标。

静态模式

规则存在多个目标,并且不同的目标可以根据目标的文件的名字自动构造出依赖文件。
静态模式的基本语法:

TARGETS ... : TARGET-PATTERN : PREREQ-PATTERNS ...    COMMANDS    ...

例如:

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

如果目标文件列表中,规则不同,可以使用filter函数进行分类,不同类别的目标,指定不同的规则命令。

静态模式和隐含规则

双冒号规则

一个目标可以出现在多个规则中。但是这些规则必须是同一类型的规则,要么都是普通规则, 要么都是双冒号规则。而不允许一个目标同时出现在两种不同类型的规则中。
双冒号规则和普通规则的区别:
1. 双冒号规则中,当依赖文件比目标更新时。规则将会被执行。对于一个没有依赖而只有命令行的双冒号规则,当引用此目标时,规则的命令将会被无条件执行。而普通规则,当规则的目标文件存在时,此规则的命令永远不会被执行(目标文件永远是最新的)。
2. 当同一个文件作为多个双冒号规则的目标时。这些不同的规则会被独立的处理,而不是像普通规则那样合并所有的依赖到一个目标文件。这就意味着对这些规则的处理就像多个不同的普通规则一样。就是说多个双冒号规则中的每一个的依赖文件被改变之后, make 只执行此规则定义的命令,而其它的以这个文件作为目标的双冒号规则将不会被执行。

自动产生依赖

%.d:%.c    $(CC) -M $(CPPFLAGS) $< > $@.$$$$; \    sed 's,\($*\).o[:]*,\1.o $@:,g' < $@.$$$$ > $@; \    rm -f $@.$$$$

使用时如:

sources = foo.c bar.cinclude $(sources:.c=.d)  #必须出现在终极目标之后
原创粉丝点击