您的位置:首页 > 其它

读书笔记之:GNU make中文手册

2007-05-28 19:55 288 查看
lyjinger读书笔记之:GNU make中文手册

原书信息:
名称:GNU make中文手册
版本:ver-3.8
作者:
译者:徐海兵

读书笔记:
make默认查找的文件名顺序为:“GNUmakefile”、“makefile”、“Makefile”

每一个命令行必须以[Tab]字符开始,[Tab]字符告诉make此行是一个命令行。make按照命令完成相应的动作。这也是书写Makefile中容易产生,而且比较隐蔽的错误
书写时,可以将一个较长行使用反斜线(/)来分解为多行,这样可以使我们的Makefile书写清晰、容易阅读理解。但需要注意:反斜线之后不能有空格(这也是大家最容易犯的错误,错误比较隐蔽)

make程序会把出现在第一条规则之后的所有以[Tab]字符开始的行都作为命令行来处理
Makefile中把那些没有任何依赖只有执行动作的目标称为“伪目标”(phony targets)

在Makefile中一个规则的目标如果不是“终极目标”所依赖的(或者“终极目标”的依赖文件所依赖的),那么这个规则将不会被执行
在实际工作中大家都比较认同的方法是,使用一个变量“objects”、“OBJECTS”、“objs”、“OBJS”、“obj”或者“OBJ”来作为所有的.o文件的列表的替代

对一个目标文件是“N.o”,倚赖文件是“N.c”的规则,完全可以省略其规则的命令行
显式规则、隐含规则、变量定义、指示符和注释

“include”指示符告诉make暂停读取当前的Makefile,而转去读取“include”指定的一个或者多个文件,完成以后再继续当前Makefile的读取

TARGETS : NORMAL-PREREQUISITES | ORDER-ONLY-PREREQUISITES
“~/bin”代表“/home/username/bin/”(当前用户宿主目录下的bin目录)
“~john/bin”就是代表用户john的宿主目录下的bin目录

自动化变量“$?”表示依赖文件列表中被改变过的所有文件
自动化变量“$<”代表规则的第一个依赖,“$@”代表规则的目标

变量定义中使用的通配符不会被通配处理,“objects = *.o”表示变量“objects”的值是字符串“*.o”
当需要变量“objects”代表所有.o文件列表示,需要使用函数“wildcard”(objects = $(wildcar *.o))

$(wildcard PATTERN...) 在Makefile中,它被展开为已经存在的、使用空格分开的、匹配此模式的所有文件列表

通过变量“VPATH”可以指定依赖文件的搜索路径
VPATH = src:../headers 为所有规则的依赖指定了两个搜索目录,“src”和“../headers”
另一个设置文件搜索路径的方法是使用make的“vpath”关键字(全小写的)
vpath %.h ../headers 其含义是:Makefile中出现的.h文件;如果不能在当前目录下找到,则到目录“../headers”下寻找

.PHONY: clean
clean:
rm *.o temp

.PHONY: cleanall cleanobj cleandiff
cleanall : cleanobj cleandiff
rm program
cleanobj :
rm *.o
cleandiff :
rm *.diff

make存在一个内嵌隐含变量“RM”,它被定义为:“RM = rm –f”

Makefile的特殊目标:
.PHONY:
目标“.PHONY”的所有的依赖被作为伪目标。伪目标时这样一个目标:当使用make命令行指定此目标时,这个目标所在规则定义的命令、无论目标文件是否存在都会被无条件执行
.SUFFIXES:
特殊目标“SUFFIXES”的所有依赖指出了一系列在后缀规则中需要检查的后缀名(就是当前make需要处理的后缀)
.DEFAULT
一个文件作为某个规则的依赖,但却不是另外一个规则的目标时。Make程序无法找到重建此文件的规则,此种情况时就执行“.DEFAULT”所指定的命令
.PRECIOUS
目标“.PRECIOUS”的所有依赖文件在make过程中会被特殊处理:当命令在执行过程中被中断时,make不会删除它们。而且如果目标的依赖文件是中间过程文件,同样这些文件不会被删除。
另外,目标“.PRECIOUS”的依赖文件也可以是一个模式,例如“%.o”。这样可以保留有规则创建的中间过程文件。
.INTERMEDIATE
目标“.INTERMEDIATE”的依赖文件在make时被作为中间过程文件对待。没有任何依赖文件的目标“.INTERMEDIATE”没有意义。
.SECONDARY
.DELETE_ON_ERROR
.IGNORE
.LOW_RESOLUTION_TIME
.SILENT
.EXPORT_ALL_VARIABLES
.NOTPARALLEL

静态模式
TARGETS ...: TARGET-PATTERN: PREREQ-PATTERNS ...
COMMANDS
从目标模式(TAGET-PATTERN)的目标名字中抽取一部分字符串(称为“茎”)。使用“茎”替代依赖模式(PREREQ-PATTERNS)中的相应部分来产生对应目标的依赖文件
files = foo.elc bar.o lose.o
$(filter %.o,$(files)): %.o: %.c
$(CC) -c $(CFLAGS) $< -o $@
$(filter %.elc,$(files)): %.elc: %.el
emacs -f batch-byte-compile $<

变量赋值:
递归展开式变量 = 在引用的地方是严格的文本替换
直接展开式变量 := 以变量被定义后就是一个实际需要的文本串,其中不再包含任何变量的引用
条件赋值 ?= 只有此变量在之前没有赋值的情况下才会对这个变量进行赋值
追加变量值 +=

make的函数:
调用方式:$(FUNCTION ARGUMENTS)
文本处理函数
$(subst FROM,TO,TEXT)
字符串替换函数—subst:把字串“TEXT”中的“FROM”字符替换为“TO”。
$(subst ee,EE,feet on the street)

$(patsubst PATTERN,REPLACEMENT,TEXT)
模式替换函数—patsubst:搜索“TEXT”中以空格分开的单词,将符合模式“PATTERN”替换为“REPLACEMENT”。
$(patsubst %.c,%.o,x.c bar.c)
$(VAR:PATTERN=REPLACEMENT)相当于:
$(patsubst PATTERN,REPLACEMENT,$(VAR))
$(VAR:SUFFIX=REPLACEMENT) 等于:$(patsubst %SUFFIX,%REPLACEMENT,$(VAR))

$(strip STRINT)
去空格函数—strip:去掉字串(若干单词,使用若干空字符分割)“STRINT”开头和结尾的空字符,并将其中多个连续空字符合并为一个空字符。
STR = a b c
LOSTR = $(strip $(STR))

$(findstring FIND,IN)
查找字符串函数—findstring:搜索字串“IN”,查找“FIND”字串。
$(findstring a,a b c)

$(filter PATTERN…,TEXT)
过滤函数—filter:过滤掉字串“TEXT”中所有不符合模式“PATTERN”的单词,保留所有符合此模式的单词。
sources := foo.c bar.c baz.s ugh.h
foo: $(sources)
cc $(filter %.c %.s,$(sources)) -o foo

$(filter-out PATTERN...,TEXT)
反过滤函数—filter-out:过滤掉字串“TEXT”中所有符合模式“PATTERN”的单词,保留所有不符合此模式的单词。
objects=main1.o foo.o main2.o bar.o
mains=main1.o main2.o
$(filter-out $(mains),$(objects))

$(sort LIST)
排序函数—sort:给字串“LIST”中的单词以首字母为准进行排序(升序),并取掉重复的单词。
$(sort foo bar lose foo)

$(word N,TEXT)
取单词函数—word:取字串“TEXT”中第“N”个单词(“N”的值从1开始)。
$(word 2, foo bar baz)

$(wordlist S,E,TEXT)
取字串函数—wordlist:从字串“TEXT”中取出从“S”开始到“E”的单词串。
$(wordlist 2, 3, foo bar baz)

$(words TEXT)
统计单词数目函数—words:计算字串“TEXT”中单词的数目。
$(words, foo bar)

$(firstword NAMES…)
取首单词函数—firstword:取字串“NAMES…”中的第一个单词。
$(firstword foo bar)

文件名处理函数
$(dir NAMES…)
取目录函数—dir:从文件名序列“NAMES…”中取出各个文件名的目录部分。
$(dir src/foo.c hacks)

$(notdir NAMES…)
取文件名函数——notdir:从文件名序列“NAMES…”中取出非目录部分。
$(notdir src/foo.c hacks)

$(suffix NAMES…)
取后缀函数—suffix:从文件名序列“NAMES…”中取出各个文件名的后缀。
$(suffix src/foo.c src-1.0/bar.c hacks)

$(basename NAMES…)
取前缀函数—basename:从文件名序列“NAMES…”中取出各个文件名的前缀部分(点号之后的部分)。
$(basename src/foo.c src-1.0/bar.c /home/jack/.font.cache-1 hacks)

$(addsuffix SUFFIX,NAMES…)
加后缀函数—addsuffix:为“NAMES…”中的每一个文件名添加后缀“SUFFIX”
$(addsuffix .c,foo bar)

$(addprefix PREFIX,NAMES…)
加前缀函数—addprefix:为“NAMES…”中的每一个文件名添加前缀“PREFIX”
$(addprefix src/,foo bar)

$(join LIST1,LIST2)
单词连接函数——join:将字串“LIST1”和字串“LIST2”各单词进行对应连接。就是将“LIST2”中的第一个单词追加“LIST1”第一个单词字后合并为一个单词;将“LIST2”中的第二个单词追加到“LIST1”的第一个单词之后并合并为一个单词,……依次列推。
$(join a b c , .c .o)

$(wildcard PATTERN)
获取匹配模式文件名函数—wildcard:列出当前目录下所有符合模式“PATTERN”格式的文件名。
$(wildcard *.c)

foreach 函数
$(foreach VAR,LIST,TEXT)
dirs := a b c d
files := $(foreach dir,$(dirs),$(wildcard $(dir)/*))
等价于:
files := $(wildcard a/* b/* c/* d/*)

if 函数
$(if CONDITION,THEN-PART[,ELSE-PART])
SUBDIR += $(if $(SRC_DIR) $(SRC_DIR),/home/src)
函数的结果是:如果“SRC_DIR”变量值不为空,则将变量“SRC_DIR”指定的目录作为一个子目录;否则将目录“/home/src”作为一个子目录。

call函数
$(call VARIABLE,PARAM,PARAM,...)
reverse = $(2) $(1)
foo = $(call reverse,a,b) 变量“foo”的值为“ba”
pathsearch = $(firstword $(wildcard $(addsuffix /$(1),$(subst :, ,$(PATH)))))
LS := $(call pathsearch,ls) 变量“LS”的结果为“/bin/sh”

value函数
eval函数
origin函数

shell函数

自动化变量:
$@ 表示规则的目标文件名
$% 当规则的目标文件是一个静态库文件时,代表静态库的一个成员名
$< 规则的第一个依赖文件名
$? 所有比目标文件更新的依赖文件列表,空格分割
$^ 规则的所有依赖文件列表,使用空格分隔
$+ 类似“$^”,但是它保留了依赖文件中重复出现的文件。主要用在程序链接时库的交叉引用场合
$* 在模式规则和静态模式规则中,代表“茎”
$(@D) 表示目标文件的目录部分(不包括斜杠)
$(@F) 目标文件的完整文件名中除目录以外的部分(实际文件名)
$(*D)
$(*F) 分别代表目标“茎”中的目录部分和文件名部分
$(%D)
$(%F) 当以如“archive(member)”形式静态库为目标时,分别表示库文件成员“member”名中的目录部分和文件名部分。它仅对这种形式的规则目标有效
$(<D)
$(<F) 分别表示规则中第一个依赖文件的目录部分和文件名部分
$(^D)
$(^F) 分别表示所有依赖文件的目录部分和文件部分(不存在同一文件)
$(+D)
$(+F) 分别表示所有依赖文件的目录部分和文件部分(可存在重复文件)
$(?D)
$(?F) 分别表示被更新的依赖文件的目录部分和文件名部分
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: