当我们写程序过程中存在多个文件之间有复杂的包含关系时,若修改了其中一个源文件,就重新编译所有文件,一般是不必要的,并且当文件很多时,就显得非常笨拙。所有包含该文件的文件需要重新编译,而其它无关系的文件则不需要编译,但往往判断的这个过程会很令程序员头疼,并且一不小心就会出现某些需要重新编译的文件被遗漏的情况,这样就会使程序无法正常工作。
make就可以解决上述问题,它会在必要时编译所有受改动影响的源文件。
但是make自身是不能完成这项任务的,我们需要为其提供一个文件,告诉它如何去处理文件之间的关系,这个文件就是makefile文件。
就是在makefile文件中按照一定的格式把要生成的文件在编译时所需要的源文件以及编译规则写出来。这样,make会根据makefile文件按照规则在需要时重新编译所有受改动影响的源文件。可以同时存在多个不同的makefile文件分别管理项目的不同部分。makefile文件一般和其它源文件放在同一目录下。
make -f makefile文件名
-f 选项就是指定将哪个文件作为makefile文件。如果没有使用-f选项,标准版本make命令将首先在当前目录下找名字为makefile的文件,找不到会继续查找Makefile的文件。(特殊的GNU Make则会按照GNUmakefile、makefile、Makefile的顺序搜索)
makefile文件由一组依赖关系和规则构成。完整的makefile文件例子会在后面列出。
makefile中的每个依赖关系由 一个目标文件(一般为要创建的可执行文件)和一组该目标所依赖的源文件组成。
makefile文件依赖关系的写法()如下:
mypro: main.o myc1.o
main.o: main.c a.h b.h
myc1.o: myc1.c b.h
mypro1: mypro1.c
最开始是目标文件名称,然后一个冒号,后面是目标文件所依赖的源文件(冒号和后面的源文件之间以及不同源文件之间用空格或制表符间隔)
特别需要注意的是,虽然makefile文件中已经写入了多个目标文件,但是如果只是这样执行 make 则make命令只会创建makefile文件中的第一个目标,即mypro
若要一次性创建makefile中的所有文件,需要在makefile文件的第一个目标定义为all(我们称之为伪目标),即:
all: mypro mypro1
mypro: main.o myc1.o
main.o: main.c a.h b.h
myc1.o: myc1.c b.h
mypro1: mypro1.c
或者执行make命令时,加上all参数 : make all
makefile文件的规则:
规则就是指当make创建目标文件时的方式,比如在编译myc1.o文件时,如何进行编译(如可能需要指定头文件的目录等)。
在此应特别注意:makefile文件中的 空格 和 制表符 是有区别的。规则所在的行必须以 制表符 开头,不可以用空格。并且makefile文件中不能以空格结尾,可能会使make命令执行失败(这属于历史遗留问题)
另外,makefile文件中可以使用宏定义。
下面举例完整的makefile文件:
定义一个命名为Makefile123的makefile文件
#cat Makefile123
all: mypro
#This is a makefile
#the compiler
CC = gcc
#the path
INCLUDE = .
#where to install
INSTDIR = /usr/local/bin
install: mypro
@if [ -d $(INSTDIR) ]; \
then \
cp mypro $(INSTDIR) &&\
chmod a+x $(INSTDIR)/mypro &&\
chmod og-w $(INSTDIR)/mypro &&\
echo "Installed in $(INSTDIR)" ;\
else \
echo "Sorry, $(INSTDIR) does not exist" ; \
fi
mypro: main.o c1.o
gcc -o mypro main.o a.o
main.o: main.c m.h
$(CC) -I$(INCLUDE) -c main.c
c1.o: c1.c
$(CC) -c c1.c
clean:
-rm main.o c1.o
1、make中的特殊符号:
-
告诉make命令忽略所有错误
@ 告诉make执行某条命令前不要将该条命令显示在准输出上
# 是makefile中的注释符号
CC = gcc 以及 INCLUDE = . 和INSTDIR = /usr/local/bin 是makefile中自行建立的的宏定义,引用方式为$(CC)、$(INCLUDE)和$(INSTDIR)
2、注意all只指定了一个目标mypro,所以只执行 make -f Makefile123时,则默认只创建目标mypro
我们可以看到在Makefile123文件中存在两个目标clean 和 install。
install依赖于mypro ,执行make -f Makefile123 install时,make会自行判断创建文件的正确顺序
该文件中目标install的规则由一串shell脚本命令组成,此处注意,make命令在执行规则时会调用一个shell,并且每个规则都使用一个新的shell,所以在代码结尾加上反斜杠\,使得所有shell脚本命令在逻辑上处于一行。 &&符号保证保证前面的命令执行成功后面的才会继续执行。
clean目标后面没有依赖文件,则执行 make -f Makefile123 clean时,clean对应的规则总会执行,而不是像其他目标一样只有在依赖文件发生变化时执行规则。