接下来我们先回顾一下基础的makefile编写方法



首先我创建了这样几个文件

​fun1.c fun2.c fun3.c fun4.c main.c​

fun1.c:
#include "stdio.h"
void fun1(void)
{

printf("i am fun1\n");
}

其他的·fun文件都是类似的

看一下main.c

#include "stdio.h"
void fun1(void);
void fun2(void);
void fun3(void);
void fun4(void);

void main(void)
{
fun1();
fun2();
fun3();
fun4();

}

首先我们用最简单的方法编写makefile

main: main.o fun1.o fun2.o fun3.o fun4.o
gcc main.o fun1.o fun2.o fun3.o fun4.o -o main
main.o: main.c
gcc -c main.c -o main.o
fun1.o: fun1.c
gcc -c fun1.c -o fun1.o
fun2.o: fun2.c
gcc -c fun2.c -o fun2.o
fun3.o: fun3.c
gcc -c fun3.c -o fun3.o
fun4.o: fun4.c
gcc -c fun4.c -o fun4.o
clean:
rm *.o -rf

如何做一些改变的?

Makefile 特殊变量
$@
目标文件
$^
所有的依赖文件集合
$<
依赖文件第一个
%表示着依赖文件一次一次的展开

%.c 所有的.c

%.o 所有的.o

main: main.o fun1.o fun2.o fun3.o fun4.o
gcc $^ -o $@ # $^就是main.o fun1.o....$@就是main
main.o: main.c
gcc -c $< -o $@
fun1.o: fun1.c
gcc -c $< -o $@
fun2.o: fun2.c
gcc -c $< -o $@
fun3.o: fun3.c
gcc -c $< -o $@
fun4.o: fun4.c
gcc -c $< -o $@
clean:
rm *.o -rf

这样写是不是看起来还是有点复杂?能不能再简化一下呢?

如果我要添加.c文件呢?如何做到不改代码就可以直接添加呢?

我们接着看一下:

OBJ := main                 # 类似宏定义
CFILE := $(wildcard ./*.c) # ./意思是当前路径 *.c 下的所有.c文件.当前路径下的所有.c文件返回给CFILE
OFILE := $(patsubst %.c,%.o,$(CFILE)) #将CFILE里面的.c文件转换成.o文件输出
$(OBJ) : $(OFILE) # main : fun1.o fun2.o fun3.o
gcc $^ -o $@
%.o : %.c # fun1.o : fun1.c fun2.c fun3.c
gcc -c $< -o $@
echo:
@echo "name" = $(name)
@echo "CFILE" = $(CFILE)
@echo "OFILE" = $(OFILE)


clean:
rm *.o -rf

接上面,我们开始尝试,不在同一目录下的makefile我再当前目录下创建了一个INCLUDE目录,然后在里面放上几个头文件。

OBJ := main                 # 类似宏定义
CFILE := $(wildcard ./*.c) # ./意思是当前路径 *.c 下的所有.c文件.当前路径下的所有.c文件返回给CFILE
OFILE := $(patsubst %.c,%.o,$(CFILE)) #将CFILE里面的.c文件转换成.o文件输出
$(OBJ) : $(OFILE) # main : fun1.o fun2.o fun3.o
gcc $^ -o $@
%.o : %.c # fun1.o : fun1.c fun2.c fun3.c
gcc -c -I ./INCLUDE $< -o $@ #当前头文件路径当前目录下的INCLUDE目录下面
echo:
@echo "name" = $(name)
@echo "CFILE" = $(CFILE)
@echo "OFILE" = $(OFILE)


clean:
rm *.o -rf

接上面,我把除了mian.c以外的.c文件放到当前目录下面的API文件里面,main.c放到USER文件里面,这样该怎么写呢

OBJ := main                 # 类似宏定义
CDIR := ./API\
./USER
CFILE := $(foreach tmp,$(CDIR),$(wildcard $(tmp)/*.c)) # 将CDIR中的参数依次取出来放到tmp中,再传给$(wildcard ./*.c)
OFILE := $(patsubst %.c,%.o,$(CFILE)) #将CFILE里面的.c文件转换成.o文件输出
$(OBJ) : $(OFILE) # main : fun1.o fun2.o fun3.o
gcc $^ -o $@
%.o : %.c # fun1.o : fun1.c fun2.c fun3.c
gcc -c -I ./INCLUDE $< -o $@ #当前头文件路径当前目录下的INCLUDE目录下面
echo:
@echo "name" = $(name)
@echo "CFILE" = $(CFILE)
@echo "OFILE" = $(OFILE)


# CFILE := $(wildcard ./*.c) # ./意思是当前路径 *.c 下的所有.c文件.当前路径下的所有.c文件返回给CFILE
# wildcard ,只能查找一个目录下的文件
# foreach <var>,<list>,<text> 作用:把参数list中的参数逐一取出来拿到中,再传给text

还有一部分makefile编译文件定向输出的,下次再更。

欢迎评论区或者私信交流。如有错误,感谢指正。