一.概述
1.Make和MakeFile
- make 是个命令,是个可执行程序,用来解析Makefile 文件的命令
- 执行这个命令后,它会在当前目录下找makefile 文件,根据makefile内编写的规则,编译程序
- makefile 是个文件,这个文件中描述了咱们程序的编译规则
2.使用的好处
1、**简化命令输入:**简化编译程序的时候输入得命令,编译的时候只需要敲 make 命令就可以了
2、**减少重复编译:**可以节省编译时间,提高编译效率
- 其会在编译前去通过文件的修改时间,判断该文件是否经过修改,如果没有经过修改,会重复利用已编译的
.o
文件,从而避免重复编译,节省编译时间
二.makefile语法及执行
存在"依赖"的特性,当目前的目标中用到的依赖不存在时,它会去寻找生成依赖的目标,生成依赖,而后再执行目标
1.makefile文件
(1)语法规则
切记命名列表前面要使用Tab键进行分隔
- **目标:**通常用于指定要产生的文件名称
- **传输文件:**用来输入从而产生目标的文件
- **命令:**make执行的动作
- 一个规则可以含有多个命令,也可以没有
- 多个命令时,每个命令占一行
目标: 依赖文件列表
命令列表
(2)示例
下面的示例定义了多个目标,使用时默认执行第一个目标
main
,可以通过[targets]
指定
**目标:**main、clean
- main目标:将main.c和mian.h用gcc编译器进行编译
- clean目标:对编译好的文件进行删除
main:main.c main.h
gcc main.c -o main
clean:
rm main
2.make命令
(1)命令格式
参数;
-
[-f file]
:使用-f
可以指定默认搜寻名字之外的文件作为输入文件- make默认会在工作目录中找GNUmakefile、makefile、Makefile的文件作为makefile输入文件,
-
[targets]
:用来指定指定的目标- 如果没有指定,默认会在执行第一个后退出
- 可以指定一个或多个目标,使用空格分隔
命令;
make [-f file] [targets]
三.makefile变量
还有一个类似占位符的东西
1.自定义变量
(1)概述
① 命名规则
- makefile变量名可以以数字开头
- 变量是大小写敏感的
② 作用范围
- 变量一般都在makefile的头部定义
- 变量集合可在makefile的任何地方使用
(2)格式
定义变量
变量名=变量值
引用变量:
$(变量名) 或 ${变量名}
(3)示例
注:这里第一个目标使用的
.o
文件一开始是没有的,它会自动去下面找看有没有生成依赖的目标,有则会先执行生成依赖的目标生成依赖,再继续执行第一个目标
下面的例子中,使用自定义变量对MakeFile中的通用数据进行了替换
cc=gcc
obj=main.o printf.o
target=main
cflags=-Wall -g
$(target):$(obj)
$(cc) ${obj} -o $(target) $(cflags)
main.o:main.c main.h printf.h
$(cc) -c main.c -o main.o $(cflags)
printf.o:printf.c main.h
$(cc) -c printf.c -o printf.o $(cflags)
clean:
rm $(obj) $(target)
2.系统环境变量
(1)概述
即make
工具可以从操作系统中获取系统变量并将其设置成makefile的变量,在makefile中可直接读取或拷贝这些变量,无需指定,可直接使用
(2)例子
创建环境变量:
在Linux操作系统中,使用export
命令即可创建环境变量(只在当前Shell有效)
export name=HonestLiu
Makefile文件:
main:main.c main.h
gcc main.c -o main
clean:
rm main
echo $(name)
**运行:**可以看到,makefile中从未定义name
变量,但其成功从系统获取并打印了出来
root@iZbp1aupqg3cfppq5uigwdZ:~#make clean
rm main
echo $(name)
HonestLiu
3.预定义变量
(1)概述
makefile 中有许多预定义变量,这些变量具有特殊的含义,可在 makefile 中直接使用
(2)常见的预定义变量
-
$@
目标名- 可在命令列表中用这个替换目标名
-
$<
依赖文件列表中的第一个文件- 可以在命令列表中用这个替换第一个文件
-
$^
依赖文件列表中除去重复文件的部分- 可以在命令类别中,替换依赖文件的全部内容,当然是去除重复的之后的
-
AR
归档维护程序的程序名,默认值为 ar ARFLAGS 归档维护程序的选项 -
AS
汇编程序的名称,默认值为 as ASFLAGS 汇编程序的选项 -
CC
C 编译器的名称,默认值为 cc CFLAGS C 编译器的选项 -
CPP
C 预编译器的名称,默认值为$(CC) -E CPPFLAGS C 预编译的选项 -
CXX
C++编译器的名称,默认值为 g++ -
CXXFLAGS
C++编译器的选项
(3)示例
整体使得更加简洁
- 使用了
$^
替换了main
中列表中的编译目标源文件- 因为其和依赖列表内容一样,且这个还去除了重复内容
- 在生成
main
依赖文件的依赖的目标命令列表中,使用了$<
和$@
去代指依赖列表第一个文件和目标名
cc=gcc
obj=main.o printf.o
target=main
cflags=-Wall -g
$(target):$(obj)
$(cc) $^ -o $@ $(cflags)
main.o:main.c main.h printf.h
$(cc) -c $< -o $@ $(cflags)
printf.o:printf.c main.h
$(cc) -c $< -o $@ $(cflags)
clean:
rm $(obj) $(target)
4,占位符
暂时这里放着吧,赶着去学校时间不够