make和Makefile
make命令可以自动判断一个大型软件项目中哪些代码文件需要重新编译,并且重新编译他们。我们经常见到C语言软件项目使用make,但make并不受编程语言的限制,只要编译器可以在shell中运行即可。Makefile文件用来告诉make做什么,怎么去编译和链接一个程序。
Makefile的规则
目标文件 ... : 依赖文件 ...
命令
...
...
默认情况下,必须要在命令前使用tab而不是空格。make通过执行命令,由依赖文件生成目标文件。目标文件也可以没有依赖文件,而只是一个操作。
一个简单的Makefile
edit : main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
cc -o edit main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
main.o : main.c defs.h
cc -c main.c
kbd.o : kbd.c defs.h command.h
cc -c kbd.c
command.o : command.c defs.h command.h
cc -c command.c
display.o : display.c defs.h buffer.h
cc -c display.c
insert.o : insert.c defs.h buffer.h
cc -c insert.c
search.o : search.c defs.h buffer.h
cc -c search.c
files.o : files.c defs.h buffer.h command.h
cc -c files.c
utils.o : utils.c defs.h
cc -c utils.c
clean :
rm edit main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
该Makefile定义了生成edit可执行程序的规则。它一共依赖8个C文件和三个头文件。反斜杠\可以用来进行换行。通过执行make和make clean可以生成和清理可执行程序edit和中间目标文件。
make如何执行Makefile
make执行Makefile的过程很好理解。默认情况下,make读取当前目录下的Makefile文件,并处理第一个目标文件的生成。但在执行定义的命令之前,必须先处理依赖文件的生成。如此执行下去。
在执行完make之后,如果有任何依赖文件进行了更新,即依赖文件比目标文件还要新,再次进行make的时候将会重新编译该文件,以及所有依赖它的目标文件。
使用变量简化Makefile
objects = main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
edit : $(objects)
cc -o edit $(objects)
main.o : main.c defs.h
cc -c main.c
kbd.o : kbd.c defs.h command.h
cc -c kbd.c
command.o : command.c defs.h command.h
cc -c command.c
display.o : display.c defs.h buffer.h
cc -c display.c
insert.o : insert.c defs.h buffer.h
cc -c insert.c
search.o : search.c defs.h buffer.h
cc -c search.c
files.o : files.c defs.h buffer.h command.h
cc -c files.c
utils.o : utils.c defs.h
cc -c utils.c
clean :
rm edit $(objects)
通常会为所有的中间目标文件定义一个变量,方便引用。
使用隐晦规则简化Makefile
Makefile存在一些隐晦的规则,如.o文件通过cc -c命令对相应的.c文件进行编译而生成。因此该Makefile可以进一步简化。
objects = main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
edit : $(objects)
cc -o edit $(objects)
main.o : defs.h
kbd.o : defs.h command.h
command.o : defs.h command.h
display.o : defs.h buffer.h
insert.o : defs.h buffer.h
search.o : defs.h buffer.h
files.o : defs.h buffer.h command.h
utils.o : defs.h
.PHONY : clean
clean :
rm edit $(objects)
关于clean
通常clean操作可以写成如下形式,对可执行程序和中间目标文件进行清理。
clean:
rm edit $(objects)
但是更为合适的写法应该是,
.PHONY : clean
clean :
-rm edit $(objects)
.PHONY声明clean是一个操作,伪目标文件,从而与clean文件区别起来。-rm使得Makefile可以在rm命令出错之后可以继续执行。
参考
https://www.gnu.org/software/make/manual/