Makefile笔记

1.引用其它的Makefile

1) 语法:include xxx xxx  

2) 在执行make时,会默认在当前文件目录下查找,如有"-I"或"--include-dir"参数,那么make就会在参数所指定的目录中去寻找。

3) 如果文件没找的话,会生成一条警告信息,当不会马上生成致命错误。它会继续载入其它文件,一旦完成makefile的读取,makefile会再次寻找没有找到的文件,如果还是不行,make才会出现致命错误。如果想让make不理那些无法读取的文件而继续执行,可以在include前加一个“-”。

2.环境变量

1) MAKEFILES 

如果当前环境中定义了环境变量,那么make会把这个变量的值作为一个类似于“include”的操作。这个环境中的值是其他makefile,用空格隔开。只是,它和include不同的是,从这个环境变量中引入的“目标”不会起作用,如果环境变量中定义的文件错误,make也不会理会。

2)MAKECMDGOALS

此变量记录了命令行参数指定的终极目标列表,没有通过参数指定终极目标时此变量为空。注意:此变量仅用在特殊的场合,在Makefile在不要对他进行重新定义。

sources = foo.c bar.c
ifneq ($(MAKECMDGOALS),clean)
include $(sources:.c=.d)
endif 

3)MAKEFILE_LIST

make程序在读取多个makefile文件时,包括由环境变量“MAKEFILES”指定,命令行指定,当前工作下默认的以及使用指示符“include”指定包含的,在对这些文件进行解析之前make读取的文件名会被自动一次追加到变量“MAKEFILE_LIST”定义域中。

name1:=$(word $(words $(MAKEFILE_LIST)), $(MAKEFILE_LIST))

include inc.mk

name2:=$(word $(words $(MAKEFILE_LIST)), $(MAKEFILE_LIST))

all:
    @echo name1 = $(name1)
    @echo name2 = $(name2)

执行结果:

name1 = Makefile
name2 = inc.mk

 

3文件名使用通配符

Maekfile 中表示文件名时可使用通配符。可使用的通配符有:“ *”、“ ?”和“ […]”。 

1)  可以用在规则的目标、依赖中, make 在读取 Makefile 时会自动对其进行匹配处理。

2)  可出现在规则的命令中,通配符的通配处理是在 shell 在执行此命令时完成的 。

3)  除这两种情况之外的其它上下文中,不能直接使用通配符。而是需要通过函数“wildcard)来实现。

4 函数使用

1) foreach     $(foreach <var>;,<list>;,<text>;) 

这个函数的意思是,把参数<list>;中的单词逐一取出放到参数<var>;所指定的变量中,然后再执行<text>;所包含的表达式。每一次<text>;会返回一个字符串,循环过程中,<text>;的所返回的每个字符串会以空格分隔,最后当整个循环结束时,<text>;所返回的每个字符串所组成的整个字符串(以空格分隔)将会是foreach函数的返回值。
View Code

2)wildcard     $(wildcard *.c) 

展开为已经存在的、使用空格分开的、匹配此模式的所有文件列表。如果不存在任何符合此模式的文件,函数会忽略模式字符并返回空。

3)patsubst     $(patsubst <pattern>,<replacement>,<text> ) 

功能:查找<text>中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式<pattern>,如果匹配的话,则以<replacement>替换。这里,<pattern>可以包括通配符“%”,表示任意长度的字串。如果<replacement>中也包含“%”,那么,<replacement>中的这个“%”将是<pattern>中的那个“%”所代表的字串。(可以用“\”来转义,以“\%”来表示真实含义的“%”字符)
返回:函数返回被替换过后的字符串。
示例:

$(patsubst %.c,%.o,x.c.c bar.c)

把字串“x.c.c bar.c”符合模式[%.c]的单词替换成[%.o],返回结果是“x.c.o bar.o”
View Code

4)addprefix     $(addprefix fixstring,string1 string2 ...)   

fixstring表示任意要添加的固定前缀,在逗号的后面可以是一个或多个要添加前缀的子字符串,多个子字符串之间用空格隔开

5)filter     $(filter PATTERN…,TEXT)  ]     过滤函数filter

函数功能:过滤掉字串“TEXT”中所有不符合模式“PATTERN”的单词,保留所
有符合此模式的单词。可以使用多个模式。模式中一般需要包含模式字
符“%”。存在多个模式时,模式表达式之间使用空格分割。 
返回值:空格分割的“TEXT”字串中所有符合模式“PATTERN”的字串。 
函数说明:“filter”函数可以用来去除一个变量中的某些字符串,我们下边的例子中
就是用到了此函数。 
示例: 
sources := foo.c bar.c baz.s ugh.h 
foo: $(sources) 
cc $(filter %.c %.s,$(sources)) -o foo 
使用“$(filter %.c %.s,$(sources))”的返回值给 cc 来编译生成目标“foo”,函数返回
值为“foo.c bar.c baz.s”
View Code

6) 替换引用 $(VAR:A=B)

对于一个已经定义的变量,可以使用“替换引用”将其值中的后缀字符(串)使用指定的字符(字符串)替换。格式为“$(VAR:A=B)”(或者“${VAR:A=B}”),意思是,替换变量“VAR”中所有“A”字符结尾的字为“B”结尾的字。“结尾”的含义是空格之前(变量值多个字之间使用空格分开)。而对于变量其它部分的“A”字符不进行替换。例如:
foo := a.o b.o c.o
bar := $(foo:.o=.c)
执行后会将“ a.o b.o c.o”全部替换为“ a.c b.c c.c”
View Code

7) eval     

函数功能: 函数“ eval”是一个比较特殊的函数。使用它可以在Makefile中构造一个可变的规则结构关系(依赖关系链),其中可以使用其它变量和函数。
函数“ eval”对它的参数进行展开,展开的结果作为Makefile的一部分,make可以对展开内容进行语法解析。展开的结果可以包含一个新变量、目标、隐含规则或者是明确规则等。也就是说此函数的功能主要是:根据其参数的关系、结构,对它们进行替换展开。
返回值: 函数“ eval”的返回值时空,也可以说没有返回值。
函数说明:“ eval”函数执行时会对它的参数进行两次展开。第一次展开过程
发是由函数本身完成的,第二次是函数展开后的结果被作为Makefile内容时由make解析时展开的。明确这一过程对于使用“ eval”函数非常重要。理解了函数“ eval”二次展开的过程后。实际使用时,如果在函数的展开结果中存在引用(格式为: $(x)),那么在函数的参数中应该使用“ $$”来代替“ $”。因为这一点,所以通常它的参数中会使用函数“ value” 来取一个变量的文本值。
我们看一个例子。例子看起来似乎非常复杂,因为它综合了其它的一些概念和函数。不过我们可以考虑两点:其一,通常实际一个模板的定义可能比例子中的更为复杂;其二,我们可以实现一个复杂通用的模板,在所Makefile中包含它,亦可作到一劳永逸。相信这一点可能是大多数程序员所推崇的。

# sample Makefile
PROGRAMS = server client
server_OBJS = server.o server_priv.o server_access.o
server_LIBS = priv protocol
client_OBJS = client.o client_api.o client_mem.o
client_LIBS = protocol
# Everything after this is generic
.PHONY: all
all: $(PROGRAMS)
define PROGRAM_template
$(1): $$($(1)_OBJ) $$($(1)_LIBS:%=-l%)
ALL_OBJS += $$($(1)_OBJS)
endef
$(foreach prog,$(PROGRAMS),$(eval $(call PROGRAM_template,$(prog))))
$(PROGRAMS):
$(LINK.o) $^ $(LDLIBS) -o $@
clean:
rm -f $(ALL_OBJS) $(PROGRAMS)

来看一下这个例子:它实现的功能是完成“ PROGRAMS”的编译链接。例子中
“ $(LINK.o)”为“ $(CC) $(LDFLAGS)”,意思是对所有的.o文件和指定的库文件进行链接。
“ $(foreach prog,$(PROGRAM),$(eval $(call PROGRAM_template,$(prog))))”展开为:
server : $(server_OBJS) –l$(server_LIBS)
client : $(client_OBJS) –l$(client_LIBS)
View Code

8) notdir     $(notdir $(path)) 表示把path目录去掉路径名,只留当前文件名

9)basename     $(basename NAMES…)  取前缀函数

函数功能:从文件名序列“ NAMES…”中取出各个文件名的前缀部分(点号之后的部分)。前缀部分指的是文件名中最后一个点号之前的部分。
返回值:空格分割的文件名序列“ NAMES…”中各个文件的前缀序列。如果文件没有前缀,则返回空字串。
函数说明:如果“ NAMES…”中包含没有后缀的文件名,此文件名不改变。如果一个文件名中存在多个点号,则返回值为此文件名的最后一个点号之前的文件名部分。
View Code

10) sort 排序函数

函数名称:排序函数— sort。
函数功能:给字串“ LIST”中的单词以首字母为准进行排序(升序),并取掉重复的单词。
返回值:空格分割的没有重复单词的字串。
函数说明:两个功能,排序和去字串中的重复单词。可以单独使用其中一个功能。
View Code

11) subset     $(subst FROM,TO,TEXT)

函数名称:字符串替换函数— subst。
函数功能:把字串“ TEXT”中的“ FROM”字符替换为“ TO”。
返回值:替换后的新字符串。
View Code

 12) dir 取目录函数     $(dir <names...>)

功能:从文件名序列<names>中取出目录部分。目录部分是指最后一个反斜杠(“/”) 
之前的部分。如果没有反斜杠,那么返回“./”。 
返回:返回文件名序列<names>的目录部分。 
示例:$(dirsrc/foo.chacks)返回值是“src/./”。
View Code

 

5.make文件命名

默认的情况下,make会在工作目录下按照文件名顺序寻找makefile文件读取并执行,查找的文件名顺序为:“GUNmakefile”,“makefile”,“Makefile”(推荐使用Makefile)。

当目录下makefile命名不是以上三者之一时,可以通过“-f NAME”或者“--f=NAME”来指定makefile文件。

通过命令指定目标使用make的隐含规则:当前目录存在源文件“foo.c”,我们可以使用“make foo.o”自动生成“foo.o”。我们可以看到其命令行为为:"cc -c -o foo.o foo.c"。

 

6.“order only”依赖

有时,需要定义一个规则,在更新目标时只需要根据目标依赖中的部分文件来决定目标是否要更新。因此引入“order only”依赖,此依赖不影响目标文件的更新。

TARGETS:常规依赖 | “order only”依赖

 

其他:

1)makefile文件的重建

2)重载另一个makefile

3)目录搜寻

 

posted @ 2016-10-01 21:31  ZYVV  阅读(339)  评论(0)    收藏  举报