Makefile编译实战

makefile 原理

Makefile 其实只是一个指示 make 程序(有时称之为 make 命令)如何为我们工作的命令文件,我们说 Makefile 其实是在说 make,这一点要有很清晰的认识。而对于我们的项目来说,Makefile 是指linux下软件项目的编译环境。
Makefile 概念
一个是目标(target),另一个就是依赖(dependency)。目标就是指要干什么,或说运行 make 后生成什么,而依赖是告诉 make 如何去做以实现目标。在 Makefile 中,目标和依赖是通过规则(rule)来表达的。 驾驭 Makefile,最为重要的是要学会采用目标和依赖关系来思考所需解决的问题。

目标: 目标放在‘:’的前面,其名字可以是由字母和下划线‘_’组成; 一个 Makefile 中可以定义多个目标。第一个目标是默认目标,这“第一个”目标也称之为默认目标(和是不是al没有关系)。

命令: 要使 make 不打印出命令,命令前加了一个‘@’。 这一符号告诉 make,在运行时不要将这一行命令显示出来;

依赖:依赖目标在 Makefile 中又被称之为先决条件。出现这种目标依赖关系时,make工具会按从左到右的先后顺序先构建规则中所依赖的每一个目标(目标和‘:’ 后的第一个元素)。
Makefile 三要素
图1

工作原理

在这里插入图片描述

规则

什么是规则

一个规则是由目标(targets)、先决条件(prerequisites)以及命令(commands)所组成的;

目标和先决条件之间表达的就是依赖关系(dependency),这种依赖关系指明在构建目标之前,必须保证先决条件先满足(或构建)。而先决条件可以是其它的目标,当先决条件是目标时,其必须先被构建出来。还有就是一个规则中目标可以有多个,当存在多个目标,且这一规则是 Makefile 中的第一个规则时,如果我们运行 make 命令不带任何目标,那么规则中的第一个目标将被视为是缺省目标

代码的执行顺序和先决条件的先后顺序有关,先决条件在左边的限制性。

规则作用

规则的功能就是指明 make 什么时候以及如何来为我们重新创建目标,

规则table 占位

每行的明亮 前面必须只有 TAB(即你键盘上的 TAB键),且至少有一个 TAB,而不能用空格代替;

伪目标

在现实中也难免存在所定义的目标与所存在的文件是同名的,采用 Makefile如何处理这种情况呢?Makefile 中的假目标(phony target)可以解决这个问题.
采用.PHONY 关键字声明一个目标后,make 并不会将其当作一个文件来处理,而只是当作一个概念上的目标。对于假目标,我们可以想像的是由于并不与文件关联,所以每一次 make 这个假目标时,其所在的规则中的命令都会被执行。

假目标可以采用.PHONY: 关键字来定义,需要注意的是其必须是大写字母。

变量

变量引用

对于变量的引用,则需要采用$(变量名)或者${变量名}这种模式。

常用变量

CC:   保存编译器名
RM:    用于删除文件的命令是什么
EXE:  存放可执行文件名。
OBJS:  放置所有的目标文件名。

自动变量

  • $@用于表示一个规则中的目标。当我们的一个规则中有多个目标时, $@ 所指的是其中任何造成命令被运行的目标。
  • $^则表示的是规则中的所有先择条件
  • $<表示的是规则中的第一个先决条件

特殊变量

变量MAKE 变量,它表示的是make 命令名是什么。当我们需要在 Makefile 中调用另一个 Makefile 时需要用到这个变量,采用这种方式,有利于写一个容易移植的 Makefile。

.PHONY: all
all:
@echo "MAKE = $(MAKE)"

$make
MAKE = make

变量MAKECMDGOALS,它表示的是当前用户所输入的 make 目标是什么
MAKECMDGOALS 指的是用户输入的目标,当我们只运行 make 命令时,虽然根据 Makefile 的语法,第一个目标将成为缺省目标,即 all 目标,但 MAKECMDGOALS 仍然是空,而不是 all,这一点我们需要注意。

变量的类别

  1. 只用一个**“=”**符号定义的变量,我们称之为递归扩展变量(recursively expanded variable);递归扩展变量的引用是递归的.
  2. 使用**“:=”** 符号定义的变量,这种变量称之为简单扩展变量(simply expanded variables);make 只对其进行一次扫描和替换(变量只有第一次赋值有效);
  3. 使用“?=” 符号定义的变量,这种变量叫做条件赋值变量;条件赋值的意思是当变量以前没有定义时,就定义它并且将左边的值赋值给它,如果已经定义了那么就不再改变其值。条件赋值类似于提供了给变量赋缺省值的功能。

变量值的来源

● 对于前面所说到的自动变量,其值是在每一个规则中根据规则的上下文自动获得变量值的。
● 可以在运行 make 时,在 make 命令行上定义一个或多个变量
● 变量还可以来自于 Shell 环境,采用 Shell 中的 export 命令定义了一个 bar变量后 Makefile 的运行结果。

override 指令

ovrride 关键字,该关键字在Makefile 中定义的变量受到保护,不会被重新赋值,覆盖掉。

Makefile 函数

1. wildcard函数 patsubst 函数

wildcard函数 是通配符函数,通过它可以得到我们所需的文件
形式 :$(wildcard pattern)

patsubst 函数是用来进行 字符串替换 的,其形式是:

$(patsubst pattern, replacement, text)

在这里插入图片描述

2. addprefix 函数

addprefix 函数是用来在给字符串中的每个子串前加上一个前缀,其形式是:

$(addprefix prefix, names...)

3.filter

filter 函数用于从一个字符串中,根据模式得到满足模式的字符串,其形式是:

$(filter pattern..., text)

4. filter-out

filter-out 函数用于从一个字符串中根据模式滤除一部分字符串,其形式是:

$(filter-out pattern..., text)

5. patsubst 函数

patsubst 函数是用来进行字符串替换的,其形式是:

$(patsubst pattern, replacement, text)

6.strip

strip 函数用于去除变量中的多余的空格,其形式是:

$(strip string)

7.wilrdcard 函数

wildcard 是通配符函数,通过它可以得到我们所需的文件,这个函数如果我们在 Windows 或是Linux 命令行中的“*”。其形式是:

$(wildcard pattern)

条件语法

当 make 看到条件语法时将立即对其进行分析,这包括 ifdef、ifeq、ifndef 和 ifneq 四种语句形式。
Makefile 中的条件语法有三种形式,其中的 conditional-directive 可以是 ifdef、ifeq、ifndef 和 ifneq 中的任意一个。
conditional-directive
text-if-true
endif

conditional-directive
text-if-true
else
text-if-false
endif

conditional-directive
text-if-one-is-true
else conditional-directive
text-if-true
else
text-if-false
endif

Makefile 思想

写一个 Makefile 文件的第一步不是一个猛子扎进去试着写一个规则,而是先用面向依赖关系的方法想清楚,所要写的 Makefile 需要表达什么样的依赖关系,这一点非常的重要;

makefile 怎么确定文件是否发生了更新

通过文件的时间戳!
make 会检查所有规则当中的目标(文件)与先决条件(文件)之间的时间先后关系,从而来决定是否要重新创建规则中的目标。

Makefile 中通配符

在makefile 中使用"%"当通配符。

包含文件

Makefile 中的 include关键字,它如同 C/C++中的#include 预处理指令。
,在 Makefile 中,如果在 include 前加上一个‘-’号,当 make 处理这一包含指示时,如果文件不存在就会忽略这一错误。

命令

make 都是在一个新的 Shell 上运行它的,如果希望多个命令在同一个 Shell 中运行,则需要用‘;’将这些命令连起来。当命令很长时,为了方便阅读,我们需要将一行命令分成多行,这需要用‘\

通用模板

在这里插入图片描述

参考

  1. 《GUN make》
  2. 参考-Makefile实战 https://www.yuque.com/linuxer/xngi03/nfsm1k?

本专栏知识点是通过<零声教育>的系统学习,进行梳理总结写下文章,对c/c++linux课程感兴趣的读者,可以点击链接,详细查看详细的服务

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

技术鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值