make通过makefile文件来完成并自动维护编译工作,makefile描述了整个工程的编译、连接规则。
Makefile基本规则:
TARGET…: DEPENDENCIES …
COMAND
TARGET(目标): 程序产生的文件,如可执行文件和目标文件;目标也可以指要执行的动作,如clean,也称为伪目标,可以有多个目标或者一个目标,一般只有一个目标。
DEPENDENCIES(依赖):用来产生目标的输入文件列表,一般一个目标依赖多个文件,。
COMMAND(命令):是make要执行的动作(命令是shell命令或者是可以在shell下执行的程序),注意,每个命令行前面必须有一个TAB字符!
如果DEPENDENCIES中有一个或者多个文件更新的话,COMMAND就要执行,这是Makefile最核心的内容
//创建测试文件
touch main.c add.c add.h sub.c sub.h
//一个简单的例子
//Makefile
main:main.o sub.o add.o #main是目标文件(TARGET),是要生成的文件,main.o sub.o add.o
#是依赖文件(DEPENDENCIES),如果make发现依赖文件列表中的依赖不存在,就会先执行后面的命令,来生成相应的依赖文件.
gcc -Wall main.o sub.o add.o -o main#这一句是COMMAND,用来生成TARGET
sub.o:sub.c sub.h
gcc -Wall -c sub.c -o sub.o
add.o:add.c add.h
gcc -Wall -c add.c -o add.o
main.o:main.c add.h sub.h
gcc -Wall -c main.c -o main.o
clean:
rm -f *.o main
是一条基本的规则和命令
随后直接执行make,就可以
执行make clean:
简单的Makefile就可以完成了
伪目标: 上面的Makefile文件中 clean是一个伪目标,最好在Makefile文件前面加上 .PHONY: clean
.PHONY:clean
main:main.o sub.o add.o
gcc -Wall main.o sub.o add.o -o main
sub.o:sub.c sub.h
gcc -Wall -c sub.c -o sub.o
add.o:add.c add.h
gcc -Wall -c add.c -o add.o
main.o:main.c add.h sub.h
gcc -Wall -c main.c -o main.o
clean:
rm -f *.o main
为什么我们需要加上.PHONY:clean 显式指定clean是一个伪目标呢?
1)我们不显式指定伪目标,并在当前文件夹下创建一个clean文件,并且执行make clean
目录下的文件:
Makefile文件:
.PHONY:clean 已经注释:
执行make clean可看到一下结果
这是因为文件夹中有一个clean文件,make认为clean没有修改过,所以出错,加上.PHONY:clean之后,这个问题就可以解决
现在Makefile基本上可以工作了,但是可以发现,Makefile文件中有好几处是重复的,我们是否可以将重复的部分定义成一个变量呢?答案是可以的!
Makefile自动化变量:
$@:规则的目标文件名,比如说,以上的Makefile文件中
这是一条规则,main.o是这条规则的目标文件名,他可以用 $@来表示,即可以表示成:
这样在命令中,main.o 就被$@代替了
$<:规则的第一个依赖文件名,即依赖文件列中中第一个依赖文件,如:
上面一条命令中,依赖文件列表时 main.c add.h sub.h,那么main.c就是依赖文件列表中第一个文件
$< 可以表示main.c。这样命令可以被表示成:
$^表示所有的依赖文件:
现在来定义一个变量:
.PHONY:clean
OBJECT=main.o sub.o add.o
main:$(OBJECT)
gcc -Wall main.o sub.o add.o -o main
sub.o:sub.c sub.h
gcc -Wall -c sub.c -o sub.o
add.o:add.c add.h
gcc -Wall -c add.c -o add.o
main.o:main.c add.h sub.h
gcc -Wall -c main.c -o main.o
clean:
rm -f *.o main
上面的Makefile文件中,我们定义了一个变量OBJECT, OBJECT代表了 main.o sub.o add.o这个文件列表
在$()表示引用变量 $(OBJECT) 应用了定义的文件列表,$^表示目标文件列表,这时候我们可以用他来替换main.o sub.o add.o,所以替换之后为:
.PHONY:clean
OBJECT=main.o sub.o add.o
main:$(OBJECT)
gcc -Wall $^ -o main
sub.o:sub.c sub.h
gcc -Wall -c sub.c -o sub.o
add.o:add.c add.h
gcc -Wall -c add.c -o add.o
main.o:main.c add.h sub.h
gcc -Wall -c main.c -o main.o
clean:
rm -f *.o main
最后,我们用$@ $^ $< 替换Makefile文件中各部分,替换之后为
.PHONY:clean
OBJECT=main.o sub.o add.o
main:$(OBJECT)
gcc -Wall $^ -o $@
sub.o:sub.c sub.h
gcc -Wall -c $< -o $@
add.o:add.c add.h
gcc -Wall -c $< -o $@
main.o:main.c add.h sub.h
gcc -Wall -c $< -o $@
clean:
rm -f $(OBJECT) main
这样替换就完成了,相比于开始的,就显得更加专业一些了