做一个论坛网站需要多少钱国内最好用的免费建站平台
自动变量和通配符
* 通配符
* 和 % 在Make 中都被称为通配符,但他们的含义完全不同。 * 会在你的文件系统中搜索匹配的文件名。可以在目标,先决条件或 wildcard 函数中使用。
print:$(wildcard *.c)ls -la $?
wildcard 作用:在 Makefile 规则中,通配符会被自动展开。但在变量的定义和引用时,通配符将是小。这种情况如果需要通配符有效,就需要使用函数 wildcard,它的用法是 $(wildcard PATTERN)。
$? 表示比目标还要新的依赖文件列表
要注意的是:* 不可以在变量中使用,就如上面所说的的 wildcard 规则所说
第二个是:当* 不匹任何文件时,它将维持原样(除非在 wildcard 函数中运行)
thing_wrong := *.o #错误一:在变量中不展开
thing_right := $(wildcard *.o)all :one two three four#失败,因为$(thing_wrong)是字符串 ".o"
one:$(thing_wrong)
#如果没有与此模式匹配的文件,则保持为 *.o
two:*.o
#如你所料!在这种情况下,它什么也不做
three:$(thing_right)
#与规则three相同
four:$(wildcard *.o)
%通配符
用来匹配任意一个字符
- 在“匹配”模式下使用时,匹配字符串中的一个或多个字符。这种匹配被称为词干。
- 在“替换”模式下使用时,它会获取匹配的词干,并替换字符串中的词干。
- % 最常用于规则定义和某些特定函数中。
自动变量
hey:one two
//输出“hey”,因为这是目标名称
echo $@
//输出比目标更新的所有先决条件
echo $?
//输出所有先决条件
echo $^touch hey
one :touch one
two :touch two
clean:rm -f hey one two
其它规则
隐式规则
Make 偏爱 c 编译。而每次它出现这种偏爱的时候,事情就变得混乱。也许 Make 中 最令人困惑的部分是Make 的魔术/自动规则 (magic/automatic rules)。Make 会调用这些“隐含的”规则。
- 编译 c 程序:从 n.c 自动生成 n.o,命令形式为 $(CC) -c $(CPPFLAGS) $(CFLAGS)
- 编译 C++ 程序:n.o 由 n.cc 或 n.cpp 自动生成,命令形式为 $(CXX) -c $(CPPFLAGS) $(CXXFLAGS)
- 链接单个目标文件:自动从 n.o 构造 n,通过运行命令 $(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)
隐式规则使用的重要变量包括:
- CC :编译 C 程序的程序;默认为 cc
- CXX:编译 C++ 程序的程序; 默认为 g++
- CFLAGS : 要提供给 C 编译器的额外标志
- CXXFLAGS : 给 C++ 编译器的额外标志
- CPPFFLAGS :要提供给 C 预处理器的额外标志
- LDFLAGS: 当编译器英国调用链接器时,会给他们额外的标志
构建一个 C 程序,而无需明确地告诉制造如何进行编译
CC = gcc #隐式规则标志
CFLAGS = -g #隐式规则的标志。打开调试信息#隐式规则 #1:blah是通过 C 链接器隐式规则构建的
#隐式规则 #2:blah.o 是通过 C 编译隐式规则构建的,因为 blah.c 存在blah:blah.oblah.c:echo "int main() {return 0;}" > blah.c
clean:rm -f blah
静态模式规则
静态模式规则是在 Makefile 中减少编写量的另一种方式,但我会说更有用,并且“魔术”技巧更少。它们的语法如下:
targets...:target-pattern:prereq-patterns...commands
本质是给定的 target 与 target-pattern 匹配(通过 % 通配符)。任何匹配的东西都被称为词干。然后将词干替换为 “prereq-pattern”,以生成目标的prereq。
一个典型的用例是将 .c 文件编译成 .o 文件。这里是手动方式:
object = foo.o bar.o all.o
all:$(object)#这些文件通过上面隐式规则进行编译
foo.o:foo.c
bar.o:bar.c
all.o:all.call.c :echo "int main() {return 0;}"> all.c
%.c:touch $@
clean:rm -f *.c *.o all
这是使用静态模式规则的更高效的方式:
object= foo.o bar.o all.o
all:$(object)#这些文件通过隐式规则进行编译
#语法-targets...:target-pattern: prereq-patterns...
#在第一个目标 foo.o 的情况下,目标模式与 foo.o 匹配,并将 “词干” 设置为 “foo”
#然后用该词干替换 prereq 模式中的 “%”
$(object):%.o:%.c
all.c:echo "int main(){return 0;}">all.c
%.c:touch $@
clean:rm -f *.c *.o all
静态模式规则和过滤器
filter 过滤器函数可以在静态模式规则中使用,以匹配正确的文件
obj_files= bar.o lose.o
src_file= bar.c lose.c
all:$(obj_files)
$(filter %.o, $(obj_files)):%.o:%.c
%.c :touch $@
clean:rm -f $(src_files)
模式规则
模式规则经常被使用,但非常令人困惑,你可以从两个方面看待他们:
- 定义自己的隐含规则的方法
- 静态模式规则的更简单形式
#定义将每个 .c 文件编译为 .o 文件的模式规则
%.o %.c$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@
模式规则在目标中包含 % 。此 % 匹配任何非空字符串,其他字符匹配自己。模式规则先决条件中的 % 代表与目标中 % 匹配的同一词干
#定义一个在先决条件中没有模式的模式规则
#这只会在需要时创建空的 .c 文件
%.c:touch $@
双冒号规则
很少使用双冒号规则,但用它允许为同一目标定义多个规则。如果这些规则是单冒号,则会打印一条警告1,并且只运行这里的第二条命令
all:blahblah::echo "hello"blah::echo "hello agagin"
命令和执行
命令回显/静默
在命令之前添加 @ 以阻止其打印
还可以运行带有 -s 的 make 命令,等同于在每行前面添加一个 @
all:@echo "this make line will not be printed"echo "But this will"
命令执行
每个命令都在一个新的 shell 中运行(或者至少效果是这样的)
all:cd..#上面的 cd 不会影响该行,因为每个命令都有效的在新的 shell 中运行echo 'pwd'# 此 cd 命令会影响下一个命令,因为它们在同一行上cd..;echo 'pwd'#同上cd..;\echo 'pwd'
默认 Shell
默认 Shell 是 ‘/bin/sh’。你可以通过更改变量 SHELL 来更改此设置:
SHELL=/bin/bash
cool:echo "Hello from bash"
-k、-i、-错误处理
-k 表示终止出错命令,继续执行下面的命令
在命令前添加 - 以抑制错误:表示命令不管怎么样都必须执行命令
-i 表示忽略全部错误,强制执行每一条命令
中断或者杀死Make
备注:如果你对 make 按下 ctrl+c, 它将删除它刚刚创建的教新的目标
Make的递归使用
要递归调用 makefile,请使用特殊的 $(MAKE) 而不是 make,因为这样它才能为你传递 make 标志,并且本身不会受到它们的影响。
new_contents= "hello:\n\ttouch inside_file"
all:make -p subdirprintf $(new_contents)|sed -s 's/^//'>subdir/makefilecd subdir&&$(MAKE)
clean:rm -rf subdir
make的参数
可以有多个目标来make,例如 make clean run test,运行 clean,然后 run,然后 test