一、前言
在linux下一般使用Makefile来完成编译,而Makefile相当于脚本,它可以调用gcc、clang等编译器。但是Makefile有一套它自己的规则,而且与bash不太一样,以下介绍该规则。
二、伪目标
现在有以下main.c
#include "stdio.h"
void main() {
printf("hello makefile\r\n");
}
对其编写的Makefile如下
all:
gcc -o hello main.c
clean:
rm -rf *.o hello
结果如下
使用make all命令可以编译出可执行文件hello,使用make clean可以把hello删除。
伪目标可以调用一行bash命令。
三、目标和依赖
现在将Makefile改一下。
main.o:main.c
gcc -c main.c
all:
gcc main.o -o hello
clean:
rm -rf *.o hello
其中main.o:main.c,main.o就是目标文件,也就是需要用main.c编译出来的。而main.c就是依赖文件,也就是被编译的源码。
此时,使用make、make all命令同样可以编译出可执行文件hello。
四、变量
想要复用Makefile里面的代码,就不能直接写死文件名等,那就需要用到变量。再修改Makefile。
TAR = hello
DEP = main.c
OBJ = main.o
CC := gcc
$(OBJ):$(DEP)
$(CC) -c $(DEP)
all:
$(CC) $(OBJ) -o $(TAR)
clean:
rm -rf $(OBJ) $(TAR)
TAR = hello,就把hello命名为变量TAR,后面使用该变量时,需要写成$(TAR)。
然后用变量对下面的命名进行替换,那么如果要换个工程,也是简单修改就能使用了。
五、通配符
TAR = hello
OBJ = main.o
CC := gcc
$(TAR):$(OBJ)
$(CC) $(OBJ) -o $(TAR)
*.o:*.c
$(CC) -c *.c -o *.o
clean:
rm -rf $(OBJ) $(TAR)
可以使用通配符*,来匹配所有.o或者.c文件。
TAR = hello
OBJ = main.o
CC := gcc
$(TAR):$(OBJ)
$(CC) $(OBJ) -o $(TAR)
$@:$^
$(CC) -c $^ -o $@
clean:
rm -rf $(OBJ) $(TAR)
也可以写成$@代表所有的目标文件,相当于*.o,而$^则代表所有的依赖文件,相当于*.c。
六、多文件编译
现在有main.c
#include "disp.h"
void main() {
printf("hello makefile\r\n");
disp();
}
disp.h
#include "stdio.h"
void disp();
disp.c
#include "disp.h"
void disp() {
printf("disp()\r\n");
}
Makefile
TAR = hello
OBJ = main.o disp.o
CC := gcc
$(TAR):$(OBJ)
$(CC) $(OBJ) -o $(TAR)
$@:$^
$(CC) -c $^ -o $@
clean:
rm -rf $(OBJ) $(TAR)
结果如下