Makefile笔记

objects := $(wildcard *.o)
all: $(objects)
$(objects): %.o: %.c
$(CC) -c $(CFLAGS) $< -o [email protected]

%.o : %.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o [email protected]

.PHONY : clean
clean :
rm $(objects) # 或-rm或@rm
—————————————————————-
[email protected]
表示规则中的目标文件集。

$%
仅当目标是函数库文件中,表示规则中的目标成员名。例如,如果一个目标是”foo.a(bar.o)”,那么,”$%”就是”bar.o”,”[email protected]”就是”foo.a”。如果目标不是函数库文件(Unix下是[.a],Windows下是[.lib]),那么,其值为空。

$<
依赖目标中的第一个目标名字。如果依赖目标是以模式(即”%”)定义的,那么”$<“将是符合模式的一系列的文件集。注意,其是一个一个取出来的。

$?
所有比目标新的依赖目标的集合。以空格分隔。

当你希望只对更新过的依赖文件进行操作时,”$?”在显式规则中很有用,例如,假设有一个函数库文件叫”lib”,其由其它几个object文件更新。那么把object文件打包的比较有效率的Makefile规则是:

lib : foo.o bar.o lose.o win.o
ar r lib $?

$^
所有的依赖目标的集合。以空格分隔。如果在依赖目标中有多个重复的,那个这个变量会去除重复的依赖目标,只保留一份。

$+
这个变量很像”$^”,也是所有依赖目标的集合。只是它不去除重复的依赖目标。
—————————————————————-
sources = foo.c bar.c
sinclude $(sources:.c=.d)
# 变量$(sources)所有[.c]的字串都替换成[.d]
%.d: %.c
@set -e; rm -f [email protected]; $(CC) -MM $(CPPFLAGS) $< > [email protected]$$$$; sed ‘s,\($*\)\.o[ :]*,\1.o [email protected] : ,g’ < [email protected]$$$$ > [email protected]; rm -f [email protected]$$$$
# main.o : main.c defs.h –> main.o main.d : main.c defs.h
—————————————————————-
make -n 或 –just-print
make -nw

The `-W’ flag provides two features:

* If you also use the `-n’ or `-q’ flag, you can see what `make’
would do if you were to modify some files.

* Without the `-n’ or `-q’ flag, when `make’ is actually executing
commands, the `-W’ flag can direct `make’ to act as if some files
had been modified, without actually modifying the files.

使用”-C”参数来指定make下层Makefile时,”-w”会被自动打开的

make -t 或 –touch
make -q 或 –question
make -s 或 –silent
make -C <dir> 或 –directory=<dir> 指定读取makefile的目录
make -i 或 –ignore-errors
make -k 或 –keep-going 及 .IGNORE目标
—————————————————————-
exec:
cd /home/hchen
pwd

exec:
cd /home/hchen; pwd
—————————————————————-
IMMEDIATE = DEFERRED
IMMEDIATE ?= DEFERRED
# 如果没定义
IMMEDIATE := IMMEDIATE
# 只能使用已定义好的变量
IMMEDIATE += DEFERRED or IMMEDIATE

For the append operator, `+=’, the right-hand side is considered
immediate if the variable was previously set as a simple variable
(`:=’), and deferred otherwise.

define IMMEDIATE
DEFERRED
endef
—————————————————————
ifeq (0,${MAKELEVEL})
cur-dir := $(shell pwd)
whoami := $(shell whoami)
host-type := $(shell arch)
MAKE := ${MAKE} host-type=${host-type} whoami=${whoami}
endif
—————————————————————
nullstring :=
space := $(nullstring) # end of the line
—————————————————————
libs_for_gcc = -lgnu
normal_libs =

ifeq ($(CC),gcc)
libs=$(libs_for_gcc)
else
libs=$(normal_libs)
endif

foo: $(objects)
$(CC) -o foo $(objects) $(libs)
—————————————————————
comma:= ,
empty:=
space:= $(empty) $(empty)
foo:= a b c
bar:= $(subst $(space),$(comma),$(foo))
# 把$(foo)中的空格替换成逗号,所以$(bar)的值是”a,b,c”
—————————————————————
$(subst <from>,<to>,<text>)
$(patsubst <pattern>,<replacement>,<text>)
$(patsubst %.c,%.o,x.c.c bar.c)
$(strip <string>)
去掉<string>字串中开头和结尾的空字符
$(strip a b c )从”a b c “得到”a b c”
—————————————————————
$(dir <names…>)

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

$(notdir <names…>)

名称:取文件函数–notdir。
功能:从文件名序列<names>中取出非目录部分。非目录部分是指最后一个反斜杠(”/”)之后的部分。
返回:返回文件名序列<names>的非目录部分。
示例: $(notdir src/foo.c hacks)返回值是”foo.c hacks”。

$(suffix <names…>)

名称:取后缀函数–suffix。
功能:从文件名序列<names>中取出各个文件名的后缀。
返回:返回文件名序列<names>的后缀序列,如果文件没有后缀,则返回空字串。
示例:$(suffix src/foo.c src-1.0/bar.c hacks)返回值是”.c .c”。

$(basename <names…>)

名称:取前缀函数–basename。
功能:从文件名序列<names>中取出各个文件名的前缀部分。
返回:返回文件名序列<names>的前缀序列,如果文件没有前缀,则返回空字串。
示例:$(basename src/foo.c src-1.0/bar.c hacks)返回值是”src/foo src-1.0/bar hacks”。

$(addsuffix <suffix>,<names…>)

名称:加后缀函数–addsuffix。
功能:把后缀<suffix>加到<names>中的每个单词后面。
返回:返回加过后缀的文件名序列。
示例:$(addsuffix .c,foo bar)返回值是”foo.c bar.c”。

$(addprefix <prefix>,<names…>)

名称:加前缀函数–addprefix。
功能:把前缀<prefix>加到<names>中的每个单词后面。
返回:返回加过前缀的文件名序列。
示例:$(addprefix src/,foo bar)返回值是”src/foo src/bar”。

$(join <list1>,<list2>)

名称:连接函数–join。
功能:把<list2>中的单词对应地加到<list1>的单词后面。如果<list1>的单词个数要比<list2>的多,那么,<list1>中的多出来的单词将保持原样。如果<list2>的单词个数要比<list1>多,那么,<list2>多出来的单词将被复制到<list2>中。
返回:返回连接过后的字符串。
示例:$(join aaa bbb , 111 222 333)返回值是”aaa111 bbb222 333″。
—————————————————————
$(foreach <var>,<list>,<text>)
names := a b c d
files := $(foreach n,$(names),$(n).o)
# $(files)的值是”a.o b.o c.o d.o”。
—————————————————————
reverse = $(2) $(1)

foo = $(call reverse,a,b)
—————————————————————
sources = foo.c bar.c
ifneq ( $(MAKECMDGOALS),clean)
include $(sources:.c=.d)
endif
只要我们输入的命令不是”make clean”,那么makefile会自动包含”foo.d”和”bar.d”这两个makefile。
—————————————————————
There are two reasons to use a phony target: to avoid a
conflict with a file of the same name, and to improve performance.

.PHONY: all
all: prog1 prog2 prog3 prog4

—————————————————————

“-b”
“-m”
这两个参数的作用是忽略和其它版本make的兼容性。

“-B”
“–always-make”
认为所有的目标都需要更新(重编译)。

“-C <dir>;”
“–directory=<dir>;”
指定读取makefile的目录。如果有多个”-C”参数,make的解释是后面的路径以前面的作为相对路径,并以最后的目录作为被指定目录。如:”make -C ~hchen/test -C prog”等价于”make -C ~hchen/test/prog”。

“-debug[=<options>;]”
输出make的调试信息。它有几种不同的级别可供选择,如果没有参数,那就是输出最简单的调试信息。下面是<options>;的取值:
a — 也就是all,输出所有的调试信息。(会非常的多)
b — 也就是basic,只输出简单的调试信息。即输出不需要重编译的目标。
v — 也就是verbose,在b选项的级别之上。输出的信息包括哪个makefile被解析,不需要被重编译的依赖文件(或是依赖目标)等。
i — 也就是implicit,输出所以的隐含规则。
j — 也就是jobs,输出执行规则中命令的详细信息,如命令的PID、返回码等。
m — 也就是makefile,输出make读取makefile,更新makefile,执行makefile的信息。

“-d”
相当于”–debug=a”。

“-e”
“–environment-overrides”
指明环境变量的值覆盖makefile中定义的变量的值。

“-t”
“–touch”
相当于UNIX的touch命令,只是把目标的修改日期变成最新的,也就是阻止生成目标的命令运行

“-W <file>;”
“–what-if=<file>;”
“–new-file=<file>;”
“–assume-file=<file>;”
假定目标<file>;需要更新,如果和”-n”选项使用,那么这个参数会输出该目标更新时的运行动作。如果没有”-n”那么就像运行UNIX的”touch”命令一样,使得<file>;的修改时间为当前时间。
—————————————————————
http://www.chinaunix.net/jh/23/408225.html 及 make manual摘录


相关文章

Speak Your Mind

If you want a pic to show with your comment, go get a gravatar!