一.概述

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,占位符

暂时这里放着吧,赶着去学校时间不够

image-20240221114841280

最后修改:2024 年 03 月 11 日
如果觉得我的文章对你有用,请随意赞赏