makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令。对于我的理解而言,makefile是将gcc编译的一些命令集中写在一个文件中,一个make就可以全部执行这些命令,也可以先编译再链接,对于一个大型项目来说,通常有上百个需要处理的代码文件,而每次修改后的编译过程往往会消耗我们的大量的时间。而makefile中可以实现只编译已修改的文件,再进行链接(不太耗时),从而节省大量时间。
makefile三要素:目标,依赖,命令
例子:实现四则运算并分开编译
app:main.o add.o sub.o mul.o 生成终极目标app(必须写在第一行) 依赖main.o等 当子目标执行完成后 最后执行此,执行过程:先查找依赖,如果依赖不存在则向下查找有没有生成依赖的。
gcc main.o add.o sub.o mul.o -o app 要有一个tab
main.o:main.c 子目标
gcc -c main.c
add.o:add.c
gcc -c add.c
sub.o:sub.c
gcc -c sub.c
mul.o:mul.c
gcc -c mul.c
如果只修改的add.c 只编译add.c。实现原理:通过比较app和add.c的时间,在修改之前app的时间应在add.c之后,修改后app的时间在add.c之前。
进一步修改:使用变量
obj=main.o add.o sub.o mul.o
target=app 可以使用vi命令进行替换 3,4s/app/$(target) 将3 4行的app替换为$(target)
$(target):$(obj) $(obj) 取obj中的值
gcc $(obj) -o $(target)
%.o:%.c 匹配公式,在向下查找main.o时将%t替换为main
gcc -c $< -o $@ makefile中的自动变量,$<:规则中的第一个依赖
$@:规则中的目标
$`:规则中的所有依赖
只能在规则的命令中使用
如gcc main.o add.o sub.o mul.o -o app可写为gcc $` -o $@
makefile中自己维护的变量:普遍为大写
CC=cc=gcc CPPFLAGS=-I
进一步修改:使用函数,所有函数都有返回值
src=$(wildcard ./*.c) 使用wildcard函数查找目录下的相应文件,参数跟在函数后面。使用$提取返回值
ojb=$(patsubst ./%.c, ./%.o,$(src)) 匹配替换,把所有的.c替换为.o,.c是src里面的
如下:
target=app
src=$(wildcard ./*.c)
ojb=$(patsubst ./%.c, ./%.o,$(src))
CC=gcc
CPPFLAGS=-I
$(target):$(obj)
$(CC) $(obj) -o $(target)
%.o:%.c
$(CC) -c $< -o $@
进一步修改:增加额外的操作
clean: 用于清除一些中间临时文件
rm $(obj) $(target) 删除所有的.o和目标文件
直接make是生成终极目标app,想要执行clean则需要写 make clean
clean:
rm $(obj) $(target) -f 强制执行,不管能不能删除
如果执行目录下有一个clean文件,则会提示clean已是最新的。因为clean是一个目标文件,单实际上并未生成,所以目录下的文件总是最新的。
解决方法:如果是伪目标(如clean等,未生成的目标),则需要进行申明
.PHONY:clean
clean:
rm $(obj) $(target) -f
如果在执行过程中出现错误,默认处理方法为退出不执行后续命令。若想继续执行后续命令,则加-
clean:
-mkdir /aa 在根目录下创建目录,普通用户无权限,报错!但会继续执行rm命令
rm $(obj) $(target) -f