当前位置:   article > 正文

Makefile学习笔记2_makefile notparallel

makefile notparallel

#Makefile学习笔记2

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

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

###依赖的类型
两种依赖关系

  1. 常规依赖

    只要这个依赖有更新,就会更新目标

  2. order-only依赖

    只在目标不存在的情况下,依赖才会被更新,否则这个以来的规则不会更新

书写方法

LIBS=libtest.a
foo: foo.c | $(LIBS)
	$(CC) $(CFLAGS) $< -o $(LIBS)
  • 1
  • 2
  • 3

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

###文件名使用通配符
Makefile中表示文件名时可使用通配符。可使用的通配符有“*”,“?”和“[…]”。
可以用在两个地方:

  1. 规则的目标和依赖中
  2. 规则的命令中
    除了这两种上下文,其他的场景不能直接使用通配符,要使用函数wildcard来处理

举例:

clean:
	rm -f *.o
  • 1
  • 2

####函数wildcard
objects=$(wildcard *.o)

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

###伪目标

###强制目标(没有命令或依赖的规则)
强制目标被认为总是更新过的,把这个目标作为依赖时,依赖它的目标总是被更新
比如:

clean: force
	rm -f *.o

force:;
  • 1
  • 2
  • 3
  • 4

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

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

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

  • 1
  • 2
  • 3
  • 4

执行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
  • 1

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

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

TARGETS ... : TARGET-PATTERN : PREREQ-PATTERNS ...
	COMMANDS
	...
  • 1
  • 2
  • 3

例如:

objects:=foo.o bar.o

all: $(objects)

$(objects): %.o : %.c
	$(CC) -c $(CFLAGS) $< -o $@
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

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

###静态模式和隐含规则

###双冒号规则
一个目标可以出现在多个规则中。但是这些规则必须是同一类型的规则,要么都是普通规则, 要么都是双冒号规则。而不允许一个目标同时出现在两种不同类型的规则中。
双冒号规则和普通规则的区别:

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

###自动产生依赖

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

使用时如:

sources = foo.c bar.c
include $(sources:.c=.d)  #必须出现在终极目标之后
  • 1
  • 2
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/98973
推荐阅读
相关标签
  

闽ICP备14008679号