学习了一下Makefile,结果让我很惊叹!!太智能了!!以下就是介绍:
就拿一个例子来介绍:
有一个小项目,有七个文件组成,4个.c文件,3个.h文件
afile.c bfile.c bfile.h cfile.c cfile.h dfile.c dfile.h
第一个Makefile的写法:
//==========================================================//
all : afile # afile 是可执行文件是最后要生成的文件
afile : afile.o bfile.o cfile.o dfile.o # 将 afile.o bfile.o cfile.o dfile.o 链接生成可执行文件 afile
gcc afile.o bfile.o cfile.o dfile.o -o afile # 执行规则
afile.o : afile.c bfile.h cfile.h dfile.h # 将 afile.c bfile.h cfile.h dfile.h 编译生成目标文件 afile.o
gcc -c afile.c -o afile.o # 执行规则
bfile.o : bfile.c # 将 bfile.c 编译生成目标文件 bfile.o
gcc -c bfile.c -o bfile.o # 执行规则
cfile.o : cfile.c # 将 cfile.c 编译生成目标文件 cfile.o
gcc -c cfile.c -o cfile.o # 执行规则
dfile.o : dfile.c # 将 dfile.c 编译生成目标文件 dfile.o
gcc -c dfile.c -o dfile.o # 执行规则
clean:
rm -fr *.o afile #删除中间文件跟可执行文件
//==========================================================//
第二个Makefile的写法:
对于上面的Makefile,写法虽然工整,但是非常死板,如果有很多的.c文件加入的话显得很不灵活,
所以第二中写法对第一种写法进行了简化。
//==========================================================//
CC = gcc
OBJECTS = afile.o bfile.o cfile.o dfile.o
all : afile # afile 是可执行文件是最后要生成的文件
afile : $(OBJECTS) # 将 afile.o bfile.o cfile.o dfile.o 链接生成可执行文件 afile
gcc $(OBJECTS) -o afile # 执行规则
afile.o : afile.c bfile.h cfile.h dfile.h # 将 afile.c bfile.h cfile.h dfile.h 编译生成目标文件 afile.o
gcc -c afile.c -o afile.o # 执行规则
bfile.o : bfile.c # 将 bfile.c 编译生成目标文件 bfile.o
gcc -c bfile.c -o bfile.o # 执行规则
cfile.o : cfile.c # 将 cfile.c 编译生成目标文件 cfile.o
gcc -c cfile.c -o cfile.o # 执行规则
dfile.o : dfile.c # 将 dfile.c 编译生成目标文件 dfile.o
gcc -c dfile.c -o dfile.o # 执行规则
clean:
rm -fr $(OBJECTS) afile #删除中间文件跟可执行文件
//==========================================================//
这样当有其它的.c文件加入的时候,需要改动的地方就少点了。
第三个Makefile的写法:
对于上面的Makefile,虽然较第一种有所简化,但是还是有很多的不灵活
所以第三中写法对第二种写法又进行了简化。
简化的参考是:
make可以自动推导文件以及文件依赖关系后面的命令,于是我们就没必要去在每一个[.o]文件后都
写上类似的命令,因为,我们的make会自动识别,并自己推导命令。只要make看到一个[.o]文件,它就
会自动的把[.c]文件加在依赖关系中,如果make找到一个whatever.o,那么whatever.c,就会是whatever.o
的依赖文件。并且 cc -c whatever.c 也会被推导出来。
//==========================================================//
CC = gcc
OBJECTS = afile.o bfile.o cfile.o dfile.o
all : afile # afile 是可执行文件是最后要生成的文件
afile : $(OBJECTS) # 将 afile.o bfile.o cfile.o dfile.o 链接生成可执行文件 afile
afile.o : afile.c bfile.h cfile.h dfile.h # 将 afile.c bfile.h cfile.h dfile.h 编译生成目标文件 afile.o
bfile.o : bfile.c # 将 bfile.c 编译生成目标文件 bfile.o
cfile.o : cfile.c # 将 cfile.c 编译生成目标文件 cfile.o
dfile.o : dfile.c # 将 dfile.c 编译生成目标文件 dfile.o
.PHONY : clean # 说明clean 是伪指令
clean:
rm -fr $(OBJECTS) afile #删除中间文件跟可执行文件
//==========================================================//
这样,就得到了较二更为简化的Makefile。
第四个Makefile的写法:
如果想让Makefile更简单,就来学习下第四种
//==========================================================//
CC = gcc
OBJECTS = afile.o bfile.o cfile.o dfile.o
all : afile
afile : $(OBJECTS)
$(OBJECTS) : bfile.h cfile.h dfile.h
.PHONY : clean # 说明clean 是伪指令
clean:
rm -fr $(OBJECTS) afile #删除中间文件跟可执行文件
//==========================================================/
对于第四种的简化解释就是:make 工具是一个非常智能的Makefile解释器,他检测到afile : $(OBJECTS)的时候
就会去查找依赖的文件,从而走到$(OBJECTS) : bfile.h cfile.h dfile.h,然后就会在当前路径下查找生成$(OBJECTS)
的所有文件,然后依次编译。
就拿一个例子来介绍:
有一个小项目,有七个文件组成,4个.c文件,3个.h文件
afile.c bfile.c bfile.h cfile.c cfile.h dfile.c dfile.h
第一个Makefile的写法:
//==========================================================//
all : afile # afile 是可执行文件是最后要生成的文件
afile : afile.o bfile.o cfile.o dfile.o # 将 afile.o bfile.o cfile.o dfile.o 链接生成可执行文件 afile
gcc afile.o bfile.o cfile.o dfile.o -o afile # 执行规则
afile.o : afile.c bfile.h cfile.h dfile.h # 将 afile.c bfile.h cfile.h dfile.h 编译生成目标文件 afile.o
gcc -c afile.c -o afile.o # 执行规则
bfile.o : bfile.c # 将 bfile.c 编译生成目标文件 bfile.o
gcc -c bfile.c -o bfile.o # 执行规则
cfile.o : cfile.c # 将 cfile.c 编译生成目标文件 cfile.o
gcc -c cfile.c -o cfile.o # 执行规则
dfile.o : dfile.c # 将 dfile.c 编译生成目标文件 dfile.o
gcc -c dfile.c -o dfile.o # 执行规则
clean:
rm -fr *.o afile #删除中间文件跟可执行文件
//==========================================================//
第二个Makefile的写法:
对于上面的Makefile,写法虽然工整,但是非常死板,如果有很多的.c文件加入的话显得很不灵活,
所以第二中写法对第一种写法进行了简化。
//==========================================================//
CC = gcc
OBJECTS = afile.o bfile.o cfile.o dfile.o
all : afile # afile 是可执行文件是最后要生成的文件
afile : $(OBJECTS) # 将 afile.o bfile.o cfile.o dfile.o 链接生成可执行文件 afile
gcc $(OBJECTS) -o afile # 执行规则
afile.o : afile.c bfile.h cfile.h dfile.h # 将 afile.c bfile.h cfile.h dfile.h 编译生成目标文件 afile.o
gcc -c afile.c -o afile.o # 执行规则
bfile.o : bfile.c # 将 bfile.c 编译生成目标文件 bfile.o
gcc -c bfile.c -o bfile.o # 执行规则
cfile.o : cfile.c # 将 cfile.c 编译生成目标文件 cfile.o
gcc -c cfile.c -o cfile.o # 执行规则
dfile.o : dfile.c # 将 dfile.c 编译生成目标文件 dfile.o
gcc -c dfile.c -o dfile.o # 执行规则
clean:
rm -fr $(OBJECTS) afile #删除中间文件跟可执行文件
//==========================================================//
这样当有其它的.c文件加入的时候,需要改动的地方就少点了。
第三个Makefile的写法:
对于上面的Makefile,虽然较第一种有所简化,但是还是有很多的不灵活
所以第三中写法对第二种写法又进行了简化。
简化的参考是:
make可以自动推导文件以及文件依赖关系后面的命令,于是我们就没必要去在每一个[.o]文件后都
写上类似的命令,因为,我们的make会自动识别,并自己推导命令。只要make看到一个[.o]文件,它就
会自动的把[.c]文件加在依赖关系中,如果make找到一个whatever.o,那么whatever.c,就会是whatever.o
的依赖文件。并且 cc -c whatever.c 也会被推导出来。
//==========================================================//
CC = gcc
OBJECTS = afile.o bfile.o cfile.o dfile.o
all : afile # afile 是可执行文件是最后要生成的文件
afile : $(OBJECTS) # 将 afile.o bfile.o cfile.o dfile.o 链接生成可执行文件 afile
afile.o : afile.c bfile.h cfile.h dfile.h # 将 afile.c bfile.h cfile.h dfile.h 编译生成目标文件 afile.o
bfile.o : bfile.c # 将 bfile.c 编译生成目标文件 bfile.o
cfile.o : cfile.c # 将 cfile.c 编译生成目标文件 cfile.o
dfile.o : dfile.c # 将 dfile.c 编译生成目标文件 dfile.o
.PHONY : clean # 说明clean 是伪指令
clean:
rm -fr $(OBJECTS) afile #删除中间文件跟可执行文件
//==========================================================//
这样,就得到了较二更为简化的Makefile。
第四个Makefile的写法:
如果想让Makefile更简单,就来学习下第四种
//==========================================================//
CC = gcc
OBJECTS = afile.o bfile.o cfile.o dfile.o
all : afile
afile : $(OBJECTS)
$(OBJECTS) : bfile.h cfile.h dfile.h
.PHONY : clean # 说明clean 是伪指令
clean:
rm -fr $(OBJECTS) afile #删除中间文件跟可执行文件
//==========================================================/
对于第四种的简化解释就是:make 工具是一个非常智能的Makefile解释器,他检测到afile : $(OBJECTS)的时候
就会去查找依赖的文件,从而走到$(OBJECTS) : bfile.h cfile.h dfile.h,然后就会在当前路径下查找生成$(OBJECTS)
的所有文件,然后依次编译。