外观
01.make和makefile
约 1243 字大约 4 分钟
make个人随笔记录
2022-06-18
第一部分 :make和makefile
1.1 make是一个应用程序
- 解析源程序之间的依赖关系
- 根据依赖关系自动维护编译工作
eg: 编译10000个源文件,第9999个,出错了,改好后重新编译,make自动跳过前9998个;
- 执行宿主操作系统中的各种命令
1.2 makefile是一个描述文件
- 定义一系列的规则来指定源文件编译的先后顺序
- 拥有特定的语法规则,支持函数定义和函数调用
- 能够直接集成操作系统中的各种命令
1.3 make和makefile之间的关系
- makefile中的描述用于指导make程序如何完成工作;
- make根据makefile中的规则执行命令,最后完成编译输出。

1.4 最简单的makefile示例

注意:目标后的命令需要用Tab键('\t')隔开!否则报错。
1.5 make程序的使用示例
make -f mf.txt hello
功能说明:以hello关键字作为目标查找mf.txt文件(-f 后),并执行hello处的命令。
1.6 make程序的简写实例
make hello
功能说明:以hello关键字作为目标查找makefile或Makefile文件,并执行hello处的命令。
make
功能说明:查找makefile或Makefile文件中最顶层目标。并执行最顶层目标的命令。
1.7 编程实验:makefile初探
hello :
echo "hello makefile"
test :
echo "test"
pwd
ls

1.8 小结
- make只是一个特殊功能的应用程序
- make用于根据指定的目标执行相应的命令
- makefile用于定义目标和实现目标所需的命令
- makefile有特定的语法规则,支持函数定义和调用
第二部分 :初识 makefile 的结构
2.1 makefile的意义
- makefile 用于定义源文件间的依赖关系
- makefile 说明如何编译各个源文件并生成可执行文件
依赖的定义:

- : 将目标与依赖隔开
- ; 将依赖与命令隔开,将命令写在下一行,无须加 ;
- 依赖规则里,依赖可以省略
- 目标、依赖、命令都可以有多条
2.2 makefile中的元素含义
targets
通常是需要生成的目标文件名
make所需执行的命令名称
prerequisities
当前目标所依赖的其它目标或文件
command
完成目标所需要执行的命令
2.3 规则中的注意事项
targets可以包含多个目标
使用空格对多个目标名进行分隔
prerequisites可以包含多个依赖
使用空格对多个依赖进行分隔
[ Tab ]键:‘\t'
每一个命令行必须以[ Tab ]字符开始
[ Tab ]字符告诉 make 此行是一个命令行
续行符︰\
可以将内容分开写到下一行,提高可读性
2.4 一个makefile的依赖示例
all : test
echo "make all"
test :
echo "make test"


2.5 依赖规则
当目标对应的文件不存在,执行对应命令
当依赖在时间上比目标更新(代表程序改动),执行对应命令
当依赖关系连续发生时,对比依赖链上的每一个目标,确保都存在
2.6 小技巧
makefile 中可以在命令前加上@符,作用为命令无回显。
2.7 编程实验:makefile的规则依赖
all : test
@echo "make all"
test :
@echo "make test"

2.8 第一个make的编译案例
hello.out : main. o func.o
gcc -o hello. out main.o func.o
main.o : main.c
gcc -o main.o -c main.c
func.o : func.c
gcc -o func.o -c func .c

2.9 小技巧
工程开发中可以将最终可执行文件名和all同时作为makefile 中第一条规则的目标。(会检查hello.out为最新,从而减少编译次数)
hello.out all : main.o func.o
gcc -o hello.out main.o func.o
2.10 编程实验:初探make 编译
① makefile
hello.out all : func.o main.o
gcc -o hello.out func.o main.o
func.o : func.c
gcc -o func.o -c func.c
·
main.o : main.c
gcc -o main.o -c main.c
② func.c文件
#include "stdio.h"
void foo()
{
printf("void foo() : hello makefile\n");
}
③ main.c
extern void foo();
int main()
{
foo();
return 0;
}

解释:hello.out all中的hello.out,若不加,即使all的依赖func.o main.o是最新的,也会执行gcc -o hello.out func.o main.o,添加hello.out 后,若依赖func.o main.o为最新的,则不会进行编译。

2.11 小结
- makefile 用于定义源文件间的依赖关系
- makefile 说明如何编译各个源文件并生成可执行文件
- makefile 中的目标之间存在连续依赖关系
- 依赖存在并且命令执行成功是目标完成的充要条件
