Makefile 是一个非常强大的构建自动化工具,用于管理项目的编译、链接和其他构建任务。以下是一个详细的 Makefile 使用文档,包括基本概念、语法、示例和常见任务。

1. 基本概念

  • 目标 (Targets):在 Makefile 中,目标是要生成的文件或执行的操作的名称。目标可以是文件名,也可以是伪目标,用于执行特定任务而不生成文件。
  • 依赖项 (Dependencies):依赖项是与目标相关联的文件或其他目标,它们在目标生成之前必须存在或已经生成。
  • 规则 (Rules):规则定义了如何生成目标以及生成目标所需的命令。
  • 命令 (Commands):命令是在生成目标时要执行的操作。命令必须以 Tab 键开头。
  • 变量 (Variables):变量用于存储文本或命令,并可以在整个 Makefile 中重复使用。
  • 伪目标 (Phony Targets):伪目标是不代表实际文件的目标,而是用于执行特定操作的标记。

2. Makefile 语法

一个基本的 Makefile 规则的语法如下:

target: dependencies
command
  • target:要生成的目标的名称。
  • dependencies:生成目标所需的文件或其他目标的列表。
  • command:生成目标的命令,必须以 Tab 键开头。

3. 示例 Makefile

以下是一个简单的示例 Makefile,用于编译一个 C 程序:

CC = gcc
CFLAGS = -Wall
TARGET = myprogram
SOURCES = main.c utils.c $(TARGET): $(SOURCES)
$(CC) $(CFLAGS) -o $(TARGET) $(SOURCES) clean:
rm -f $(TARGET)

这个 Makefile 使用了变量 CCCFLAGSTARGETSOURCES,并定义了一个 all 目标用于编译程序,以及一个 clean 目标用于清理生成的文件。

4. 常见任务

4.1 编译项目

all: $(TARGET)

$(TARGET): $(SOURCES)
$(CC) $(CFLAGS) -o $(TARGET) $(SOURCES)

4.2 清理生成的文件

clean:
rm -f $(TARGET)

4.3 使用变量

CC = gcc
CFLAGS = -Wall
TARGET = myprogram
SOURCES = main.c utils.c $(TARGET): $(SOURCES)
$(CC) $(CFLAGS) -o $(TARGET) $(SOURCES)

4.4 伪目标

.PHONY: clean

clean:
rm -f $(TARGET)

5. 高级用法

除了基本用法外,还支持一些高级用法,可以用来处理更复杂的构建需求。以下是一些高级用法的详细介绍:

5.1 条件语句和函数

条件语句

Makefile 支持条件语句,可以根据条件来执行不同的规则或命令。通常使用 ifeqifdef 这两个条件语句。

ifeq ($(VARIABLE), value)
# 条件为真时的规则和命令
else
# 条件为假时的规则和命令
endif

例如,可以根据是否定义了 DEBUG 变量来设置不同的编译选项:

ifeq ($(DEBUG), 1)
CFLAGS = -g
else
CFLAGS = -O2
endif
函数

Makefile 还提供了一些内置函数,用于处理文本和文件列表。以下是一些常见的函数:

  • $(shell command):执行 shell 命令并返回结果。
  • $(wildcard pattern):匹配文件名模式并返回符合条件的文件列表。
  • $(foreach var, list, text):对列表中的每个元素执行指定的操作。
  • $(strip string):删除字符串开头和结尾的空白字符。
  • $(subst find,replace,text):替换文本中的字符串。
  • $(filter pattern, text):从文本中筛选出匹配指定模式的字符串。
  • $(patsubst pattern,replacement,text):用指定字符串替换文本中的模式。
  • $(notdir names):从文件路径中提取文件名。

这些函数可以在 Makefile 中用于各种目的,例如文件操作、文本处理和条件判断。

5.2 自动化依赖关系生成

通常,Makefile 中的依赖关系需要手动维护。但是,对于 C/C++ 项目,您可以使用编译器提供的 -M 选项来自动生成依赖关系。例如:

SOURCES = main.c utils.c
DEPS = $(SOURCES:.c=.d) %.d: %.c
$(CC) -M $< -o $@ -include $(DEPS)

在这个示例中,%.d: %.c 规则用于自动生成 .d 文件,其中包含了 .c 文件的依赖关系。然后使用 -include 指令来包含这些 .d 文件,以自动跟踪依赖关系。

5.3 多目录项目

对于大型项目,通常需要将 Makefile 拆分成多个子目录,每个子目录都有自己的 Makefile。然后,可以使用递归或变量传递来管理这些子目录之间的依赖关系。例如:

SUBDIRS = dir1 dir2

all: $(SUBDIRS)

$(SUBDIRS):
$(MAKE) -C $@ clean:
for dir in $(SUBDIRS); do \
$(MAKE) -C $$dir clean; \
done

在这个示例中,SUBDIRS 变量包含了子目录的列表。$(MAKE) 是一个 Makefile 中的特殊变量,用于启动另一个 Makefile。

5.4 高级变量操作

Makefile 支持高级的变量操作,包括字符串操作、条件赋值、变量展开等。以下是一些示例:

字符串操作
STR1 = hello
STR2 = world
STR3 = $(STR1) $(STR2)

在这个示例中,STR3 的值将是 "hello world"

条件赋值
FOO ?= default_value

如果 FOO 变量未定义,则将其赋值为 default_value

变量展开
VAR1 = $(VAR2)
VAR2 = value

在这个示例中,VAR1 的值将是 value,因为 Make 会递归地展开变量。


声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。

Author: mengbin

blog: mengbin

Github: mengbin92

cnblogs: 恋水无意


Makefile 入门教程的更多相关文章

  1. Makefile入门教程

    Makefile介绍 make是一个命令工具,它解释Makefile 中的指令(应该说是规则).在Makefile文件中描述了整个工程所有文件的编译顺序.编译规则.Makefile 有自己的书写格式. ...

  2. CMake快速入门教程-实战

    http://www.ibm.com/developerworks/cn/linux/l-cn-cmake/ http://blog.csdn.net/dbzhang800/article/detai ...

  3. 转:CMake快速入门教程-实战

    CMake快速入门教程:实战 收藏人:londonKu     2012-05-07 | 阅:10128  转:34    |   来源   |  分享               0. 前言一个多月 ...

  4. 转:asm.js 和 Emscripten 入门教程

    转:http://www.ruanyifeng.com/blog/2017/09/asmjs_emscripten.html asm.js 和 Emscripten 入门教程 作者: 阮一峰 日期:  ...

  5. CMake入门教程(转帖)

    本文转自:https://www.cnblogs.com/never--more/p/6921837.html CMake入门教程 参考文献:http://www.ibm.com/developerw ...

  6. Linux 新手入门教程

    Linux 新手入门教程 1991年10月5日,Linus Torvalds 在互联网上发布消息,宣布他自己开发的内核系统诞生了.他将内核源代码保存在芬兰最大的 FTP 网站上,命名为 Linux,取 ...

  7. 《Redis5.x入门教程》之准备工作、数据类型

    关注公众号:CoderBuff,回复"redis"获取<Redis5.x入门教程>完整版PDF. 第一章 · 准备工作 Redis安装 Redis5.0.7下载地址:h ...

  8. [深度学习] fast-reid入门教程

    fast-reid入门教程 ReID,全拼为Re-identification,目的是利用各种智能算法在图像数据库中找到与要搜索的目标相似的对象.ReID是图像检索的一个子任务,本质上是图像检索而不是 ...

  9. wepack+sass+vue 入门教程(三)

    十一.安装sass文件转换为css需要的相关依赖包 npm install --save-dev sass-loader style-loader css-loader loader的作用是辅助web ...

  10. wepack+sass+vue 入门教程(二)

    六.新建webpack配置文件 webpack.config.js 文件整体框架内容如下,后续会详细说明每个配置项的配置 webpack.config.js直接放在项目demo目录下 module.e ...

随机推荐

  1. 深入了解ApacheZeppelin:如何构建高效的数据科学平台

    目录 引言 随着数据科学和人工智能的快速发展,如何构建高效的数据科学平台已经成为一个重要议题.Apache Zeppelin是一个开源的数据科学平台,其提供了一种简单.高效的方式来处理和存储数据,并且 ...

  2. LeetCode 双周赛 107(2023/06/24)滑动窗口与离散化

    本文已收录到 AndroidFamily,技术和职场问题,请关注公众号 [彭旭锐] 和 [BaguTree Pro] 知识星球提问. 往期回顾:LeetCode 单周赛第 348 场 · 数位 DP ...

  3. 自己动手实现rpc框架(二) 实现集群间rpc通信

    自己动手实现rpc框架(二) 实现集群间rpc通信 1. 集群间rpc通信 上一篇博客中MyRpc框架实现了基本的点对点rpc通信功能.而在这篇博客中我们需要实现MyRpc的集群间rpc通信功能. 自 ...

  4. “easyExcel”导入的代码实现

    使用easyExcel在导入数据事有很好的使用性,方便操作. 添加依赖: <dependency> <groupId>com.alibaba</groupId> & ...

  5. RTC+AI|“即智”数智人创新内容生产体验,为企业降本增效再提速

    号称"史上最卷"的618年中大促落下帷幕,几大电商巨头在直播投入和短视频内容建设上持续加码,短视频+直播电商的营销模式成为618期间的主要输出. 以某美妆专场直播间为例,主播现场手 ...

  6. 如何根据oops函数偏移快速定位源码?

    如何根据函数偏移快速定位源码? 在内核栈的输出中,你一定注意到每一个函数的输出格式都是函数名+偏移量,而这儿的偏移就是调用下一个函数的位置.那么,能不能根据函数名+偏移量直接定位源码的位置呢? 答案是 ...

  7. 一对多数据的多选筛选([EF,ABP]但是sql思路通用)

    一对多数据的多选筛选([EF,ABP]但是sql思路通用) 标题起的并不是特别准确,但是现在又没有更加准确的描述,暂时这样了 业务需求: 数据格式为一条数据,对应多条二级数据,暂时表示为主信息为&qu ...

  8. 信奥赛题1001:Hello,World!

    这个题实在是太简单的了,无法比喻,直接付代码! //c++ #include<bits/stdc++.h> using namespace std; int main() { cout&l ...

  9. TFS 更换电脑名称后映射失效

    TFS 更换电脑名称后映射失效 建议不要随便更改电脑名 环境 Visual Studio 2019 : Win10 操作步骤 查找 TFS 的相关配置文件.如果你知道你之前的电脑名字可以跳过这一步:如 ...

  10. sql-lab通关

    page1-less1-22 联合查询 第一关 发现是有回显的,且传入的参数是通过'1'包裹的,所以我们的payload,如下 测试列数 ?id=1' order by 3 --+ //超过第一条语句 ...