Makefile 书写

Makefile 是定义管理工程编译依赖,在 Linux 系统编译 c/c++ 得到良好的使用
其定义指定哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作
因为 Makefile 就像一个 Shell 脚本一样,其中也可以执行操作系统的命令

Makefile 带来的好处就是——“自动化编译”,一旦写好,只需要一个 make 命令,整个工程完全自动编译,极大的提高了软件开发的效率。

规则

1
2
3
4
target ... : prerequisites ...
command
...
...

举个栗子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
demo: max.o min.o sum.o avg.o
gcc -o demo max.o min.o sum.o avg.o
max.o: max.c
gcc -c max.c calc.h
min.o: min.c
gcc -c min.c calc.h
sum.o: sum.c
gcc -c sum.c calc.h
avg.o: avg.c
gcc -c avg.c calc.h

.PHONY : clean
clean:
rm demo max.o min.o sum.o avg.o

在命令行执行 make 编译生成 demo 运行文件,执行 make clean 清除编译生成文件

在默认的方式下,也就是我们只输入 make 命令,他的执行流程是:

  1. make 会在当前目录下找名字叫 Makefilemakefile 的文件。
  2. 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到 demo 这个文件,并把这个文件作为最终的目标文件。
  3. 如果 demo 文件不存在,或是 demo 所依赖的后面的 .o 文件的文件修改时间要比 demo 文件新,
    他就会执行后面所定义的命令来生成 demo这个文件。
  4. 如果 demo 所依赖的 .o 文件也不存在,那么 make 会在当前文件中找目标为 .o 文件的依赖性,再根据那一个规则生成 .o 文件
  5. 你的 C 文件和 H 文件是存在的啦,make 会生成 .o 文件,然后再用 .o 文件生成 make 的终极任务,也就是执行文件 demo

使用变量

在上面的例子中,我们在三个地方用到了 max.o min.o sum.o avg.o 这些文件,重复多次,我们维护比较复杂,这是就会用到变量的概念
定义: 变量名:值 obj = max.o min.o sum.o avg.o
使用: $(变量名) $(obj)

优化上面栗子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
obj = max.o min.o sum.o avg.o
demo: $(obj)
gcc -o demo $(obj)
max.o: max.c
gcc -c max.c calc.h
min.o: min.c
gcc -c min.c calc.h
sum.o: sum.c
gcc -c sum.c calc.h
avg.o: avg.c
gcc -c avg.c calc.h

.PHONY : clean
clean:
rm demo $(obj)

这样编译管理,有信息的 .o 文件需要编译的话,只需要修改 obj 变量即可

自动推导

GNU 的 make 很强大,它可以自动推导文件以及文件依赖关系后面的命令,于是我们就没必要去在每一个[.o]文件后都写上类似的命令
因为,我们的 make 会自动识别,并自己推导命令。
只要 make 看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中,如果 make 找到一个 min.o
那么 min.c,就是默认依赖文件。并且 gcc -c min.c 也会被推导出来,
于是,我们的 makefile 再也不用写得这么复杂

优化上面栗子:

1
2
3
4
5
6
7
8
9
10
11
obj = max.o min.o sum.o avg.o
demo: $(obj)
gcc -o demo $(obj)
max.o: calc.h
min.o: calc.h
sum.o: calc.h
avg.o: calc.h

.PHONY : clean
clean:
rm demo $(obj)

利用推导功能,还有例外一种写法

1
2
3
4
5
6
7
8
obj = max.o min.o sum.o avg.o
demo: $(obj)
gcc -o demo $(obj)
max.o min.o sum.o avg.o: calc.h

.PHONY : clean
clean:
rm demo $(obj)

这种风格,让我们的makefile变得很简单,但我们的文件依赖关系就显得有点凌乱了,显示不出依赖的层次关系

清空编译文件

1
2
clean:
rm demo max.o min.o sum.o avg.o: calc.h

这样便于重新编译

引入文件

1
include filename

补充make的工作方式:

  1. 读入所有的 Makefile。
  2. 读入被 include 的其它 Makefile。
  3. 初始化文件中的变量。
  4. 推导隐晦规则,并分析所有规则。
  5. 为所有的目标文件创建依赖关系链。
  6. 根据依赖关系,决定哪些目标要重新生成。
  7. 执行生成命令

©版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 & 作者信息

End

坚持原创技术分享,您的支持将鼓励我继续创作!
Flyertutor WeChat Pay

WeChat Pay

Flyertutor Alipay

Alipay