规则
target ... : prerequisites ...
command
edit : main.o kbd.o command.o display.o
insert.o : search.o files.o utils.o
cc -o main.o kbd.o comand.o display.o
insert.o search.o files.o utils.o
clean :
rm edit main.o kbd.o command.o display,o
insert.o search.o files.o utils.o
工作方式
- 在目录中中找Makefile或makefile文件
- 找第一个目标文件,并作为最终目标
- 如果依赖文件不存在或所依赖的文件比较新,会执行后面所定义的命令
- 执行终极文件
变量和隐藏规则
objects
.PHONY : clean
clean :
-rm edit $(objects)
.PHONY意思表示clean是一个"伪目标",在rm命令前加一个小减号的意思是,也许某些文件出现问题,但不要管,继续作后面的事。
默认clean从来都是放在文件的最后
必须以[Tab]键开始
文件名
默认为Makefile,其他文件名如Make.Solars,Make.AIX需要添加-f指定
引用其他Makefile
在Makefile使用include关键字可以把别的Makefile包含进来,被包含的文件会放在当前文件的包含位置
include filename可以是当前操作系统的Shell文件模式(可以包含路径和通配符)在include前面可以
有一些空字符,但是绝不能是[Tab]键开始
规则
- 如果make执行时,有"-I"或"--include-dir"参数,那么make就会在这个参数的指定目录下去寻找
- 如果目录/include(一般是:/usr/local/bin或/usr/include)存在的法,make也会去寻找
环境变量 MAKEFILES
如果当前环境中定义了环境变量MAKEFILESS,那么make会把这个变量中的值做一个类似于include的动作。
不建议使用这个环境变量,因为一旦这个变量定义,使用make时,所有的Makefile都会受它的影响。
make的工作方式
- 读入所有的Makefile
- 读入被include的其他Makefie
- 初始化文件中的变量
- 推导隐晦式规则,并分析所有的规则
- 为所有的目标文件创建依赖关系链
- 根据依赖关系,决定哪些目标要重新生成。
- 执行生成命令
规则通配符
make支持三种通配符:"*","?"和[...],和Unix的B-Shell是相同的
文件搜索
VPATH = src:.../headers
上面的定义是指定两个目录,"src"和".../headers",make会按照这个顺序进行搜索。目录由"冒号"分割(当前目录永远是最高优先搜索的地方)
另一个设置文件搜索路径的方法是使用make的"vpath"关键字和VPATH变量很类似,但是更灵活。
- vpath 为符合模式的文件指定搜索目录
- vpath 清除符合模式的文件搜索目录
pattern需要包含"%"字符。"%"的意思是匹配零或若干字符
例如:"%.h"表示所有以".h"结尾的文件,指定了要搜索的文件集指定了文件集的搜索目录
伪目标
为了避免和文件重名的这种情况,可以使用一个特殊的标记".PHONY"来显示指明一个目标是伪目标
多目标
bigoutput litteoutput:text.g
generate text.g -(subst output,,@) > $@
等价于:
bigoutput : text.g
generate text.g -big > bigoutput
littleoutput : text.g
generate text.g -little > littleoutput
其中,-(subst output,,@)中的""表示执行一个Makefile函数,函数名为subst "@"表示目标的集合,就像一个数组,"$@"依次取出目标,并执行命令
静态模式
静态模式可以更加容易的定义目标的规则,可以让我们的规则变得更加有弹性和灵活
<targets ...>::<prereq-pattern ...>
...
targets定义了一系列的目标文件,可以有通配符。是目标的一个集合.
target-pattern是指明了targets的模式,也就是目标模式。
prereq-patterns是目标的依赖模式,它对target-pattern形成的模式再进行一次依赖目标的定义
objects = foo.o bar.o
all : $(objects)
(objects) : %.o : %.c (CC) -c (CFLAGS) < -o $@
在这个例子中,指明了目标从object中获取,"\%.o"表明要所有以"\%.o"结尾的目标,命令中的"<"表示所有的依赖目标集,"$@"表示目标集。
等价于
foo.o : foo.c
(CC) -c (CFLAGS) foo.c -o foo.o
bar.o : bar.c
(CC) -c (CFLAGS) bar.c -o bar.o
files = foo.elc bar.o lose.o
(filter %.o,(files)):%.o:%.c
(CC) -c (CFLAGS) < -o @
(filter %.o,(files))表示调用Makefile的filter函数,过滤"$filter“集中”%.o“的内容
自动生存依赖
大多数C/C++编译器都支持一个"-M"选项,即自动找源文件中包含的头文件,并生存一个依赖关系
cc -M main.c
其输出是:
main.o : main.c main.h
%.d: %.c
@set -e; rm -f @;\
(CC) -M (CPPFLAGS) < > @.$$$$; \
sed 's,\().o[:],\1.0 @:,g' <@.> $@; \
rm -rf $@.