目录
[1.采用 Makefile 的好处](#1.采用 Makefile 的好处)
[2.make 主要解决两个题:](#2.make 主要解决两个题:)
[二、makefile 语法及其执行](#二、makefile 语法及其执行)
[1.makefile 语法规则](#1.makefile 语法规则)
一、Makefile介绍
什么是make
make 是个命令,是个可执行程序
什么是 makefile?makefile 是个文件,这个文件中描述了程序的编译规则
执行 make 命令的时候,make 命令会在当前目录下找 makefile 文件, 根据 makefile 文件里的规则,编译 的程序
1.采用 Makefile 的好处
1、简化编译程序的时候输入得命令,编译的时候只需要敲 make 命令就可以了
2、可以节省编译时间,提高编译效率
2.make 主要解决两个题:
1.大量代码的关系维护
大项目中源代码比较多,手工维护、编译时间长而且编译命令复杂,难以记忆及维护
把代码维护命令及编译命令写在 makefile 文件中,然后再用 make 工具解析此文件自动执行相应命令,可实现代码的合理编译
2.减少重复编译时间
在改动其中一个文件的时候,能判断哪些文件被修改过,可以只对该文件进行重新编译,然后重新链接所有的目标文件,节省编译时间
二、makefile 语法及其执行
1.makefile 语法规则
目标:依赖文件列表
<Tab>命令列表
1、目标:通常是要产生的文件名称,目标可以是可执行文件或其它 obj 文件,也可是一个动作的名称
2、依赖文件:是用来输入从而产生目标的文件,一个目标通常有几个依赖文件(可以没有)
3、命令:make 执行的动作,一个规则可以含几个命令(可以有) 有多个命令时,每个命令占一行
例子:
bash
mycalc: main.o add.o sub.o mul.o div.o
gcc main.o add.o sub.o mul.o div.o -o mycalc
main.o: main.c
gcc -c main.c -o main.o
add.o: add.c
gcc -c add.c -o add.o
sub.o: sub.c
gcc -c sub.c -o sub.o
div.o: div.c
gcc -c div.c -o div.o
mul.o: mul.c
gcc -c mul.c -o mul.o
clean:
rm *.o
rm mycalc
第一行执行命令时,找不到文件的话会往下面找生成该文件的命令
clean的使用,使用命令 make clean可以清除带.o的文件和mycalc程序
注意:如果makefile的名字不是默认名称(这里使用makefile1做例子)
则需要用 make -f makefile1 clean来执行
-f 可以指定以上名字以外的文件作为 makefile 输入文件
2.Make是如何工作的?
在默认的方式下,也就是我们只输入make命令。那么:
1、make会在当前目录下找名字叫"Makefile"或"makefile"的文件。
2、如果找到,它会找文件中的第一个目标文件(target),在下面的例子中,他会找到"mycalc"这个文件,并把这个文件作为最终的目标文件。
3、如果mycalc文件不存在,或是mycalc所依赖的后面的 .o 文件的文件修改时间要比mycalc这个文件新,那么,他就会执行后面所定义的命令来生成mycalc这个文件。
4、如果mycalc所依赖的.o文件也不存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件。(这有点像一个堆栈的过程)
5、当然,你的C文件和H文件是存在的,于是make会生成 .o 文件,然后再用 .o 文件生成make的终极任务,也就是执行文件mycalc了。
这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦。
通过上述分析,我们知道,像clean这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不过,我们可以显示要make执行。即命令------"make clean",以此来清除所有的目标文件,以便重编译。
于是在我们编程中,如果这个工程已被编译过了,当我们修改了其中一个源文件,比如add.c,那么根据我们的依赖性,我们的目标add.o会被重编译(也就是在这个依性关系后面所定义的命令),于是file.o的文件也是最新的啦,于是add.o的文件修改时间要比mycalc要新,所以 mycalc也会被重新链接了(详见mycalc目标文件后定义的命令)。
三、makefile变量
makefile 变量类似于 C 语言中的宏,当 makefile 被 make 工具解析时,其中的变量会被展开。
1.自定义变量:
定义变量:
变量名=变量值引用变量:
(变量名)或{变量名}
2.预定义变量:

makefile中有许多预定义变量,这些变量具有特殊的含义,可在 makefile 中直接使用。
$@ 目标名
$< 依赖文件列表中的第一个文件
$^ 依赖文件列表中除去重复文件的部分
SRC =依赖
TARGET =目标AR 归档维护程序的程序名,默认值为 ar ARFLAGS 归档维护程序的选项
AS 汇编程序的名称,默认值为 as ASFLAGS 汇编程序的选项
CC C 编译器的名称,默认值为 cc CFLAGS C 编译器的选项
CPP C 预编译器的名称,默认值为$(CC) -E CPPFLAGS C 预编译的选项
CXX C++编译器的名称,默认值为 g++
CXXFLAGS C++编译器的选项
例如:将上面的代码替换成自定义变量与预定义变量
bash
CC=gcc
SRC = main.o add.o sub.o mul.o div.o
TARGET =mycalc
CFLAGS= -g
$(TARGET):$(SRC)
$(CC) $^ -o $(TARGET) $(CFLAGS)
main.o: main.c
$(CC) -c $< -o $@
add.o: add.c
$(CC) -c $< -o $@
sub.o: sub.c
$(CC) -c $< -o $@
div.o: div.c
$(CC) -c $< -o $@
mul.o: mul.c
$(CC) -c $< -o $@
clean:
rm *.o
rm mycalc