Makefile编译实战

简介: Makefile编译实战

makefile 原理


Makefile 其实只是一个指示 make 程序(有时称之为 make 命令)如何为我们工作的命令文件,我们说 Makefile 其实是在说 make,这一点要有很清晰的认识。而对于我们的项目来说,Makefile 是指linux下软件项目的编译环境。


Makefile 概念

一个是目标(target),另一个就是依赖(dependency)。目标就是指要干什么,或说运行 make 后生成什么,而依赖是告诉 make 如何去做以实现目标。在 Makefile 中,目标和依赖是通过规则(rule)来表达的。 驾驭 Makefile,最为重要的是要学会采用目标和依赖关系来思考所需解决的问题。


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


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


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

Makefile 三要素

c8bf3fb6728e1cb6895da5c1f89e527e_2e53b0b3d3f44b23bb70fc23920e5cca.png


工作原理

规则


什么是规则

一个规则是由目标(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课程感兴趣的读者,可以点击链接,详细查看详细的服务

目录
相关文章
|
前端开发 iOS开发
canvas生成图片模糊的解决方案
canvas生成图片模糊的解决方案
2268 1
canvas生成图片模糊的解决方案
|
12月前
|
存储 数据挖掘 数据处理
Pandas 数据筛选:条件过滤
Pandas 是 Python 最常用的数据分析库之一,提供了强大的数据结构和工具。本文从基础到高级,介绍如何使用 Pandas 进行条件过滤,包括单一条件、多个条件过滤、常见问题及解决方案,以及动态和复杂条件过滤的高级用法。希望本文能帮助你更好地利用 Pandas 处理数据。
786 78
|
弹性计算 运维 网络安全
上云“加速器”——基于云效流水线快速上线企业门户网站
阿里云提出使用云效将项目代码部署到ECS,快速构建企业门户网站。该方案融合云原生技术和持续交付,通过云效流水线简化从开发到部署的全过程,实现快速迭代。文章详细阐述了技术架构,包括客户端、云解析DNS、VPC、ECS等组件,以及部署流程,包括准备阶段、部署网站服务、解析域名和可选的静态资源加速。此外,还介绍了如何使用云效平台创建流水线,实现自动化构建与部署,以及如何通过一键部署简化流程。整个方案旨在降低运维成本,提高速度和灵活性,同时提供域名备案和SSL证书配置的指导。
195259 76
上云“加速器”——基于云效流水线快速上线企业门户网站
|
12月前
|
机器学习/深度学习 数据采集 搜索推荐
使用Python实现深度学习模型:智能食品消费行为预测
使用Python实现深度学习模型:智能食品消费行为预测
286 8
|
存储 人工智能 文字识别
AI与OCR:数字档案馆图像扫描与文字识别技术实现与项目案例
本文介绍了纸质档案数字化的技术流程,包括高精度扫描、图像预处理、自动边界检测与切割、文字与图片分离抽取、档案识别与文本提取,以及识别结果的自动保存。通过去噪、增强对比度、校正倾斜等预处理技术,提高图像质量,确保OCR识别的准确性。平台还支持多字体识别、批量处理和结构化存储,实现了高效、准确的档案数字化。具体应用案例显示,该技术在江西省某地质资料档案馆中显著提升了档案管理的效率和质量。
1410 1
|
安全 测试技术 API
一图看懂API测试9种方法
一图看懂API测试九种方法:冒烟测试验证基本功能,功能测试确保符合规格,集成测试检查组件协同工作,回归测试防止新变更引入问题,负载测试评估性能稳定性,压力测试挑战极限负载,安全测试发现并修复漏洞,用户界面测试确保UI与API协调,模糊测试提升异常数据处理鲁棒性。
|
监控 安全 网络安全
|
机器学习/深度学习 人工智能 PyTorch
面向AI Native应用的高效迁移学习策略
【8月更文第1天】随着人工智能技术的发展,越来越多的应用场景需要定制化的AI解决方案。然而,从零开始训练一个深度学习模型往往需要大量的标注数据和计算资源。迁移学习提供了一种有效的方法来解决这个问题,它利用预训练模型的知识,通过少量的数据就能达到很好的性能。本文将深入探讨面向AI Native应用的高效迁移学习策略,并通过实例展示如何针对具体场景进行模型微调。
476 6
面向AI Native应用的高效迁移学习策略
|
存储 JSON JavaScript
cJSON开源项目详细解剖1
cJSON开源项目详细解剖
439 0
|
算法 安全 网络安全
【区块链】深入解析Proof of Work (PoW): 区块链技术的核心驱动力
在区块链技术的宏伟蓝图中,Proof of Work(工作量证明,简称PoW)算法扮演着基石的角色。自比特币白皮书发布以来,PoW已成为确保去中心化网络安全、维护数据完整性的关键机制。本文将深入探讨PoW的工作原理、优势、挑战以及其对区块链生态系统的影响,力求为读者提供一个全面而深入的理解。
618 0

热门文章

最新文章