Makefile编写
1. make规则
使用make命令构建的规则,都写在makefile文件中或Makefile,或用命令行参数指定为其他文件名
$ make -f rules.txt //make -file=rules.txt
2. 如何编写Makefile文件
Makefile文件由一系列规则构成,每条规则的形成如下:
<target>:<prerequisites>
[tab]<commands>
1、<prerequisites>前置条件和<commands>命令两者必须至少存在一个。
2、<target>目标可以是文件名或某个操作的名字(称伪目标)。
例如:
clean:
rm *.o
为了避免当前目录下已存在clean文件,可以明确声明clean是伪目标:
.PHONY:clean
rm *.o temp
3、如果Make命令运行时没有指定目标,默认会执行Makefile文件的第一个目标。
$make
4、前置条件<prerequisites>通常是一组文件名,之间用空格分隔
result.txt:source.txt
cp source.txt result.txt
source.txt:
echo "this is the source" >source.txt
$make result.txt //会先构建source.txt,再构建result.txt
5、如果需要生成多个文件,往往采用下面的写法:
source:file1 file2 file3 //source 为一个伪目标,只有三个前置条件
$makee source //一次性生成file1,file2,file3三个文件
6、命令<commands>
1)每行命令前必须有一个tab键,如果想用其他键,可以用内置变量
.RECIPEPREFIX声明:
.RECIPEPREFIX = >
all:
>echo Hello,world
2)每行命令在一个单独的shell中执行。这些shell之间没有继承关系
var-lost:
export foo=bar
echo "foo=[$$foo]"
3. Makefile文件的语法
1、回声(echoing)
正常情况下,make会打印每条命令,然后再执行,这叫回声(echoing)
在命令的前面加上@,就可以关闭回声。
注:由于在构建过程中,需要了解当前在执行哪条命令,所以通常只在注释和纯显示的echo命令前面加上@
如:
test:
@#这是测试
@echo"hello,world"
2、通配符(wildcard)
Makefile的通配符与Bash一致,主要有*,?,...
3、模式匹配,匹配符%
比如,当前目录下有file1.c和file2.c两个源码文件,需要将它们编译为对应的对象:
%.o:%.c
4、变量和赋值符
1)调用自定义变量,变量放在$()之中
txt=HelloWorld
test:
@echo $(txt)
2)调用shell变量,需在$符号前再加上一个$符号
test:
@echo $$HOME
3)为了解决扩展方式的问题,提供了四个赋值运算符(=、:=、?=、+=)
VARIABLE=value #在执行时扩展,允许递归扩展
VARIABLE:=value #在定义时扩展
VARIABLE?=value #只有在该变量为空时才设置值
VARIABLE+=value #将值追加到变量的尾端
5、内置变量(Implicit Variables)
make命令提供一系列内置变量,如,$(CC)指向当前使用的编译器,$(MAKE)指向当前使用的Make工具
output:
$(CC) -o output input.c
6、自动变量(Automatic Variables)
Make命令还提供一些自动变量,它们的值与当前规则有关
1)$@ 指代当前目标,就是Make命令当前构建的那个目标
a.txt b.txt:
touch $@
2)$< 指代第一个前置条件
a.txt b.txt:
cp $< $@
3)$? 指代比目标更新的所有前置条件
4)$^ 指代所有前置条件
5)$* 指代匹配符%匹配的部分
6)$(@D)和$(@F)分别指向$@的目录名和文件名
7)$(<D)和$(<F)分别指向$<的目录名和文件名
dest/%.txt:src/%.txt
@[-d dest]||mkdir dest
cp $< $@
上面的代码将src目录下的txt文件,拷贝到dest目录下,首先判断dest目录是否存在,如果不存在就新建,然后,$<指代前置文件(src/%.txt),%@指代目标文件(dest/%.txt)
7、判断和循环
1)判断
ifeq($(CC),gcc)
libs=$(libs_for_gcc)
else
libs=$(normal_libs)
endif
2)循环
LIST=one two three
all:
for i in $(LIST); do \
echo $$i: \
done
8、函数
格式如下:
$(function arguments)
1)shell函数:用来执行shell命令
srcfiles:=$(shell echo src/{00..99}.txt)
2)wildcard函数:用来在Makefile中,替换Bash的通配符
srcfiles:=$(wildcard src/*.txt)
3)subst函数:用来文本替换
例1 $(subst ee,EE,feet on the street)
上面例子将字符串"feet on the street" 替换成 "fEEt on the strEEt"
例2
comma:=,
empty:=
space:=$(empty) $(empty) #space变量用两个空变量作为标识符,当中是一个空格
foo:=a b c
bar:=$(subst $(space),$(comma),$(foo) #bar is now 'a,b,c'
4)pastsubst函数:用于模式匹配的替换
格式: $(pastsubst pattern,replacement,text)
例如: $(pastsubst %.c,%.o,X.c.c bar.c) //将文件名"X.c.c bar.c"替换为"X.c.o bar.o"
5)替换后缀名
例如: min:$(OUTPUT:.js=.min.js)
将变量OUTPUT中的后缀名.js全部替换成.min.js