makefile入门
1.学习makefile
make---->自动确定工程的那部分源程序文件需要重新编译,编译多个源文件;
用法:make [options] [target] ...
-f filename -C -e -k -s -S
makefile----自动化编译
- 实例1:
all:main.c foo.c foo1.c foo2.c //all生成二进制的目标文件,后面为其依赖的文件,如果main.c foo.c foo1.c...中任何一个文件的修改日期比all文件日期新,或者all不存在,那么依赖关系发生;
gcc main.c foo1.c foo2.c foo.c -o all #生成目标all(可执行文件)的方法或命令;
- 实例2:
如果工程中某几个C文件被修改,只需编译被修改的C文件;
如果头文件被改变,则需要引用几个头文件的C文件,并连接目标程序;
all:作为最终执行目标;
all:main.o kbd.o util.o
gcc -o all main.o kbd.o utils.o
main.o:main.c defs.h
gcc -c main.c
kbd.o:kbd.c def.h
gcc -c kbd.c
.....
clean: #clean伪目标
rm all main.o kbd.o.....utils.o
#clean作用删除make中生成过程文件
- 语法规则:
target : prerequistes #all为目标文件名,prerequistes为依赖的文件,command命令行(bash命令)
command
或者是
targets:prerequisites; command #command如果与prerequisites在一行,可以用分号分隔;
command #command支持正则表达式;
2.通配符
- 通配符也可以在目标文件中使用
print:*.c #生成的目标文件为print,其依赖所有的*.c文件
lpr -p $? #$?是一个自动化变量,表示所有比目标新的依赖文件的集合
touch print
- 通配符也可以使用在变量中: objects=.o #不会展开,其变量值就是.o
如果让其展开即所有的.o文件名的集合,需这样写: objects:=$(wildcard *.o) #其中wildcard是makefile的关键字;
3.伪目标
伪目标并不是一个文件,而只是一个标签;为防止与文件名重名的这种情况,可以是使用一个特殊标记".PHONY"来显示的指明一个目标是伪目标,向make说明不管有没有这个文件,这个目标都是伪目标;
执行时 make clean;
.PHONY:clean
clean:
rm all main.o kbd.o....
伪目标也可以作为默认目标,只要将它放在第一个;一口气生成多个目标;伪目标总会被执行的;
all:prog1 prog2 #makefile中的第一个目标会被作为其默认目标;
.PHONY:all
prog1: prog1.o utils.o
cc -o prog1 util.s
prog2: prog2.o
cc -o prog2 prog2.o #all总会比其三个目标新,在进行make重新编译时,其他三个目标规则就会宗被决议
4.多目标
多个目标同时依赖于同一个文件;
使用一个自动化变量“$@”,意味着目前规则中所有的目标的集合;
bigoutput littleoutput: text.g
generate text.g -$(subst output,,$@)>;$@
#等价于:
bigoutput:text.g
generate text.g -big>;bigoutput
littleoutput:text.g
generate text.g -litter >;bigoutput
#其中-$(subst output,,$@)中的$表示指向一个makefile的函数,函数名为subst,后面为参数,subst函数时截取字符串的以上,$@表示目标的集合; $@依次取出目标,并指向命令;
5.makefile特征:
make会按照顺序一条一条的执行命令,所有命令以tab开头,除非紧跟依赖规则后面;
----->如果要让上一条的命令结果应用在下一条命令,需要使用分号分割这两条命令
exec:
- cd /home
pwd #输出makefile所在目录,即./
exec:
cd /home;pwd #输出/home
- 每当命令执行完毕后,make会自动检测它们的返回码;
命令前加"-",标记为不管命令是否出错都认为是成功的。
6.变量
在使用变量时应加入"$“符号,最后使用()或{}把遍历包括起来;如果使用真实的”$“字符,那么需要”$$"来表示;
objects=program.o foo.o utils.o
program:$(objects)
cc -o program $(objects)
$(objects):defs.h #这个变量又依赖defs.h文件;
?= 若未初始化,则赋值; 若初始化,则不会赋值;
FOO?=bar
等价于:
ifeq ($(origin FOO),undefined) #ifeq判断语句
FOO=bar
endif
7.makefile常用的字符串函数调用
- $(<function arguments) 函数中参数可以使用变量,函数和变量的括号最好一样;
- 字符串替换:
$(subst ee,EE,feet on the street)
模式替换函数patsubst、查找字符串函数findstring、过滤函数filter
sources:=foo.c bar.c baz.s ugh.h
source:$(sources)
cc $(filter %.c %.s,$(sources)) -o foo #其中%.c %.s为模式过滤 输出foo.c bar.c baz.s
反过滤函数filter-out、排序函数sort(遇见相同函数则删除)、取单词函数ward 、 取单词串函数wordlist
单词个数统计函数words、首单词函数firstword
8.文件名操作函数
取目录函数dir(取出最后一个反斜杠前)、取文件名函数notdir、取后准名函数suffix、取前缀函数basename、
加后缀函数addsuffix、加前缀函数addprefix、
$(addsuffix .c, foo bar hello)
- 循环函数:foreach函数$(foreach (var),(list),(text)),有点向C中的for循环;
names:=a b c d
files:=$(foreach n,$(names),$(n).o) #$(files)的值为a.o b.o c.o d.o
- 条件判断语句:ifeq、ifneq、ifdef(是否为空)、ifndef
- 条件判断函数:$(if ,,);
9.隐式规则
make预先约定好的规则;make的隐士规则功能会自动推导这两个目标的依赖目标和生成命令
foo:foo.o bar.o
cc -o foo.o bar.o $(CFLAGS) $(LDFLAGS) #隐士规则基本上使用了一些预先设置的变量;可以改变这些值;
#完全没必要写成:
foo.o:foo.c
cc -c foo.c $(CFLAGS)
bar.o:bar.c
cc -c bar.c $(CFLAGS)
使用"-R"或"–no-builtin-variable"参数来取消所定义的变量对隐士规则的作用;
- makefile的隐士规则中常用的变量:
一种是和命令相关的"CC",
AR、AS、CC、CXX、CO、CPP、TEX、RM等等
一种是和参数相关的,“CFLAGS”;
10.模式规则
- 最少在规则的目标中要包含"%“符号;
“%.c” 表示以.c结尾的文件名
“s.%.c” 表示以s.开头,以.c结尾的文件名
如果目标中模式的”%“决定了依赖目标中”%"的样子
%.o:%.c;<command....> 指出了从所有的.c文件生成相应的.o文件的规则;
- makefile自动化变量21个:
字母"D"表示Directory ; "F"表示File; $(<)要比$<好;
$@、$%、$<、$?、$^、$+=、$-=;