一个简单的Makefile文件
现在有五个文件:main.c add.c add.h sub.c sub.h
main.c中的内容如下:
int main() { return 0; }
main.c假设是依赖于add.c和sub.c
于是Makefile的内容如下:
.PHONY:clean main:main.o add.o sub.o gcc -Wall -g main.o add.o sub.o -o main main.o:main.c gcc -Wall -g -c main.c -o main.o add.o:add.c add.h gcc -Wall -g -c add.c -o add.o sub.o:sub.c sub.h gcc -Wall -g -c sub.c -o sub.o clean: rm -f main main.o add.o sub.o
main行表示需要生成main目标文件,它的依赖文件是main.o add.o sub.o
main第二行表示需要执行的命令,
gcc的前面必须是一个tab,如果是在vim下编辑的,可能有配置过把tab换成空格
clean是一个伪目标,执行删除文件的操作,在命令行中:make clean即可执行该操作
.PHONY显示指定一个伪目标
Makefile自动化变量
$@:规则的目标文件名
$<:规则的第一个依赖文件名
$^:规则的所有依赖文件列表
所以Makefile文件还可以是这样:
.PHONY:clean OBJECTS=main.o add.o sub.o main:$(OBJECTS) gcc -Wall -g $^ -o $@ main.o:main.c gcc -Wall -g -c $< -o $@ add.o:add.c add.h gcc -Wall -g -c $< -o $@ sub.o:sub.c sub.h gcc -Wall -g -c $< -o $@ clean: rm -f main $(OBJECTS)
OBJECTS表示一个变量名为这main.o add.o sub.o三个文件
第一个gcc 中的$^表示所有依赖的文件列表,$@表示目标文件
以此类推。
Makefile生成多个可执行文件
现在有两个文件,分别是01test.c 02test.c
Makefile文件格式如下:
.PHONY:clean all BIN=01test 02test all:$(BIN) clean: rm -f $(BIN)
在命令行执行:make命令,就会生成相应的可执行文件
因为没有给出all的生成命令,而all依赖于$(BIN),编译器推导出$(BIN)的生成规则,生成目标文件
如果不想让编译器推导的话,可以按照下面方法:
.PHONY:clean all CC=gcc CFLAGS=-Wall -g BIN=01test 02test all:$(BIN) #%.o:%.c .c.o: $(CC) $(CFLAGS) -c $< -o $@ 01test:01test.o $(CC) $(CFLAGS) $^ -o $@ 02test:02test.o $(CC) $(CFLAGS) $^ -o $@ clean: rm -r $(BIN) *.o
这里使用了两个变量CC和CFLAGS代替了编译器和编译选项
这里可以使用使用模式规则(%.o:%.c)和后缀规则(.c.o:)将该目录下的.c文件生成相应的.o文件
之后如下希望添加新的文件的话,直接用同样的方法在后面添加就可以了。
Makefile完成二级目录的编译链接
.PHONY:clean CC=gcc CFLAGS=-Wall -g BIN=main #想要生成的目标文件 SUBDIR=$(shell ls -d */) #保存的是子文件夹列表 ROOTSRC=$(wildcard *.c) #匹配所有的.c文件 ROOTOBJ=$(ROOTSRC:%.c=%.o) #将.c文件替换成.o SUBSRC=$(shell find $(SUBDIR) -name '*.c') #将子文件的所有.c文件列出来 SUBOBJ=$(SUBSRC:%.c=%.o) #将子文件的所有.c文件替换成.o文件 $(BIN):$(ROOTOBJ) $(SUBOBJ) #$(CC) $(CFLAGS) -o $(BIN) $(ROOTOBJ) $(SUBOBJ) $(CC) $(CFLAGS) $^ -o $@ #这里不能将$(BIN)提前到-o之前,因为现在还没有$(BIN)文件 .c.o: $(CC) $(CFLAGS) -c $< -o $@ clean: rm -f $(BIN) $(ROOTOBJ) $(SUBOBJ)
在该目录下有.c文件,在其他子目录下也有相应的.c文件,
通过Makefile完成对二级目录的编译链接工作。
Makefile多级目录编译
SUBDIRS=test1 test2 .PHONY:default all clean $(SUBDIRS) default:all all clean: $(MAKE) $(SUBDIRS) TARGET=$@ #$(MAKE)等于MAKE,是一个内置变量,当输入make命令的时候,$@=all #扩展开=make test1 test2 all $(SUBDIRS): $(MAKE) -C $@ $(TARGET) #进入test1或者test2的时候,它的依赖就是上一行 #会执行如:make -C test1 all #make -C 表示:会进入test1文件夹,调用其中的Makefile文件 #相当于make all test1/Makefile
此Makefile文件在多级目录之上,通过这个多级目录调用子目录中的Makefile文件
其中一个子目录Makefile文件:
CC=gcc BIN=test1 OBJS=test1.o .PHONY:all clean print all:print $(BIN) print: @echo "---make all in $(PWD)---" $(BIN):$(OBJS) $(CC) $(OBJS) -o $@ %.o:%.c $(CC) -c $< clean: @echo "---make clean in $(PWD)---" rm -f $(BIN) $(OBJS)
通过调用子目录的Makefile文件,生成所需要的可执行文件,从而可以实现多级目录的make命令操作