写大型C工程makefile构建~

629c33eaca92772b1cbae50443e4f604.gif

正文


最开始学习linux应用开发编写的时候,估计大部分伙伴们都是在一个目录里面编译整个工程,主要是linux通常没有非常合适的集成开发环境。

以前单目录的方式实在太过捡漏,在linux环境中进行C代码工程开发很多时候需要编写一个相对比较通用的makefile,一劳永逸,能自动查找并归类每个目录的文件进行编译。

可能很多朋友会选择一些cmake,scons等自动化构建工具,但也有部分伙计编写makefile也完全够用,嵌入式平台迭代速度不快的话基本上可以成为传承级代码,那么今天大致梳理了一下makefile中构建大型一点的工程需要用到的一些编译语法与函数。

1

常用的特殊变量

这些符号是Makefile中的特殊变量,用于在规则中引用文件名和目标,

  • $^ 用于表示所有的依赖文件列表,多个文件以空格分隔。在规则中,它可以用来引用所有依赖文件的列表。例如:

target: dependency1 dependency2 dependency3
    command $^

在这个例子中,$^ 将会展开为 dependency1 dependency2 dependency3

  • $@ 用于表示目标文件的名称。在规则中,它可以用来引用目标文件的名称。例如:

target: dependency1 dependency2 dependency3
    command $@

在这个例子中,$@ 将会展开为 target

  • $<用于表示规则中的第一个依赖文件。通常在单目标多源文件的情况下使用。例如:

target: dependency1 dependency2
    command $<

在这个例子中,$< 将会展开为 dependency1

  • $? 用于表示所有比目标文件新的依赖文件列表。通常在需要重新生成目标文件的情况下使用。例如:

target: dependency1 dependency2
    command $?

在这个例子中,如果 dependency1dependency2 新,则 $? 将会展开为 dependency1;如果 dependency2dependency1 新,则 $? 将会展开为 dependency2;如果两者都是相同的时间戳,则 $? 将为空。

  • $* 用于表示规则中目标文件的文件名部分(不包括扩展名)。通常在需要将目标文件名作为参数传递给命令时使用。例如:

%.o: %.c
    gcc -c $< -o $@
    ./process $*

在这个例子中,如果目标文件是 example.o,则 $* 将会展开为 example

除了上面提到的 $^$@$<$?$*,Makefile 中还有一些其他常用的特殊变量。

  • $(MAKE): 用于表示 make 命令的名称。这在递归调用 make 的时候非常有用。

  • $(CC): 用于表示 C 编译器的名称,默认情况下是 cc。你可以在 Makefile 中使用这个变量来指定编译器。

  • $(CFLAGS): 用于表示传递给编译器的参数。这个变量通常用于指定编译选项,比如警告选项、优化选项等。

  • $(LDFLAGS): 用于表示传递给链接器的参数。这个变量通常用于指定链接选项,比如库路径、库文件等。

  • $(RM): 用于表示删除文件的命令,默认情况下是 rm -f。你可以在 Makefile 中使用这个变量来指定删除文件的命令。

比如$(CFLAGS) 是一个在 Makefile 中常用的特殊变量,用于指定传递给编译器的参数,可以使用它来设置编译选项,比如警告选项、优化选项等。

通常是在 Makefile 中定义 $(CFLAGS) 变量,并在编译规则中使用。例如:

CC = gcc
CFLAGS = -Wall -O2

# 编译规则
%.o: %.c
    $(CC) $(CFLAGS) -c $< -o $@

# 默认目标
all: program

# 目标程序
program: file1.o file2.o
    $(CC) $(CFLAGS) $^ -o $@

# 清理规则
clean:
    rm -f *.o program

在这个示例中,$(CFLAGS) 被设置为 -Wall -O2,表示编译器应该使用所有警告选项并进行优化。然后,在编译规则中,$(CFLAGS) 被用于传递给编译器。

这样做的好处是,如果你需要修改编译选项,只需修改 $(CFLAGS) 的值,而不必在每个编译规则中都修改。这样可以使得 Makefile 更加易于维护和管理。

包括前面的特殊变量都是可以使得Makefile更加灵活和易于维护,在规则中引用文件名和目标名,而不必重复键入。

2

$(wildcard pattern)

这个规则函数看起来比较唬人,wildcard pattern英文名字就是"wildcard" 这个单词的字面意思是"通配符",那么整体就是表示为通配符表示的文件名模式,

示例:

SRCS := $(wildcard *.c)

在这个例子中,$(wildcard *.c) 将匹配当前目录下所有以 .c 结尾的文件,并将符合条件的文件名列表赋值给变量 SRCS。

另一个示例:

FILES := $(wildcard src/*.c include/*.h)

这个示例相信是很多编写C程序的makefile中经常用到的,$(wildcard src/.c include/.h) 将匹配 src 目录下的所有 .c 文件和 include 目录下的所有 .h 文件,并将结果合并为一个文件列表赋值给变量 FILES。

3

$(patsubst pattern,replacement,text)

在 Makefile 中,$(patsubst pattern,replacement,text) 是一个用于模式替换的函数,将文本中符合指定模式的部分替换为指定的字符串。

这个函数通常用于对文件名或路径进行模式匹配和替换,非常适合在 Makefile 中进行文件名的转换操作。

$(patsubst pattern,replacement,text)

参数:

pattern:要匹配的模式,可以包含通配符 * 和 ?。

replacement:要替换成的字符串。

text:要进行模式替换的文本。

比如如下这个简单的例子:

SOURCES := file1.c file2.c file3.c

OBJECTS := $(patsubst %.c,%.o,$(SOURCES))

将会把 SOURCES 变量中以 .c 结尾的文件名替换为以 .o 结尾的文件名,最终将得到 OBJECTS 变量的赋值结果为 “file1.o file2.o file3.o”。

4

addprefix

Makefile 中,$(addprefix prefix,names…) 是一个函数,用于将指定的前缀添加到一组空格分隔的文件名中。

这个函数通常用于将相同的前缀添加到一组文件名或路径中,非常适合在 Makefile 中进行路径拼接操作。

语法:

$(addprefix prefix,names...)

参数:

prefix:要添加的前缀。

names…:一组空格分隔的文件名或路径。

示例:

SOURCES := file1.c file2.c file3.c

OBJS := $(addprefix obj/,$(SOURCES:.c=.o))

在这个例子将会在 SOURCES 变量中的每个文件名后面添加 obj/ 前缀,并将处理后的结果赋值给 OBJS 变量。最终得到的 OBJS 变量的值为 “obj/file1.o obj/file2.o obj/file3.o”。

5

notdir 

$(notdir names…) 是一个函数,用于获取一组文件名或路径中的文件名部分,并将其返回。

这个函数通常用于从给定的路径中提取文件名部分,非常适合在 Makefile 中进行文件处理操作。

语法:

$(notdir names...)

参数:

names…:一组空格分隔的文件名或路径。

示例:

SRCS := src/file1.c src/file2.c src/file3.c

OBJS := $(notdir $(SRCS))

$(notdir $(SRCS)) 将会从 SRCS 变量中的每个文件路径中提取文件名部分,并将处理后的结果赋值给 OBJS 变量,最终得到的 OBJS 变量的值为 “file1.c file2.c file3.c”。

6

foreach 

foreach是Makefile使用频率非常之高的函数,foreach 函数用于迭代处理一个以空格分隔的列表,并针对列表中的每个元素执行相同的操作。

这个函数通常用于循环处理一组变量或文件名,并执行相同的规则或命令。

语法:

$(foreach var, list, text)

参数:

var:用于表示当前列表中的每个元素的变量。

list:以空格分隔的列表。

text:要对列表中的每个元素执行的操作或命令。

示例:

FILES := file1.c file2.c file3.c

OBJS := $(foreach file, $(FILES), $(file:.c=.o))

$(foreach file, $(FILES), $(file:.c=.o)) 将会遍历 FILES 变量中的每个文件名,并将每个文件名的 .c 扩展名替换成 .o,最终得到 OBJS 变量的值为 “file1.o file2.o file3.o”。

7

最后总结 

好了,基本上使用上介绍这些函数能够解决大部分的文件查找和文件名替换工作,最终就是编译了,对于C的编译过程无非就是编译、链接、清除,就是不细说了。

其实makefile主要就是自动化构建,把我们的源文件、库文件加工处理,那么只要我们的源文件位置没有大变动、编译过程无特别的要求,那么通用化makefile模板做好以后,后续就只需要进行源文件位置的添加和编译选项额修改,跟用那么集成开发环境添加一个一个的路径是一样的。

最后

      好了,今天就跟大家分享这么多了,如果你觉得有所收获,一定记得点个~

bug菌唯一、永久、免费分享嵌入式技术知识平台~

推荐专辑  点击蓝色字体即可跳转

☞  MCU进阶专辑 d3efae1b629fe0143db8199c0cdee9e4.gif

☞  嵌入式C语言进阶专辑 977c537b2645891900a52158cbeb21ca.gif

☞  “bug说”专辑 83db37f66dd764f6e5aa2914fb7bb9ae.gif

☞ 专辑|Linux应用程序编程大全

☞ 专辑|学点网络知识

☞ 专辑|手撕C语言

☞ 专辑|手撕C++语言

☞ 专辑|经验分享

☞ 专辑|电能控制技术

☞ 专辑 | 从单片机到Linux

023af59bd7513bd61cf0b8ce9b2b300a.gif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/668762.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

海康 面阵相机命名规则

海康 面阵相机命名规则 https://www.v-club.com/vCollage/vCollageDetail/516?subjectIdRMse6nPiyo

Nginx(openresty) 开启gzip压缩功能 提高web网站传输速度

1 开启nginx gzip压缩后&#xff0c;网页的图片&#xff0c;css、js等静态资源的大小会减少&#xff0c;节约带宽&#xff0c;提高传输效率&#xff0c;给用户快的体验,给用户更好的体验. 2 安装 #centos 8.5 yum install gzip 3 配置 #建议统一配置在http段 vim /usr/loca…

汇舟问卷:兼职做国外问卷三小时挣200

在繁忙的都市生活中&#xff0c;许多人为了生计而日夜奔波。对于大多数人来说&#xff0c;白天的工作已经足够充实&#xff0c;但依然有很多人选择在下班时间&#xff0c;多做些什么&#xff0c;为自己带来一份额外​的收入。 目前下班做的兼职工作不是跑滴滴&#xff0c;就是…

发表《Science Advances》!量子近似优化算法实现再突破

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 文丨慕一/娴睿 排版丨沛贤 深度好文&#xff1a;1500字丨6分钟阅读 摘要&#xff1a;摩根大通、美国能源部&#xff08;DOE&#xff09;阿贡国家实验室和 Quantinuum 的研究人员证明了量子近似…

NetApp财季报告亮点:全闪存阵列需求强劲,云计算收入增长放缓但AI领域前景乐观

在最新的财季报告中&#xff0c;NetApp的收入因全闪存阵列的强劲需求而显著增长。截至2024年4月26日的2024财年第四季度&#xff0c;NetApp的收入连续第三个季度上升&#xff0c;达到了16.7亿美元&#xff0c;较前一年同期增长6%&#xff0c;超出公司指导中值。净利润为2.91亿美…

MySQL-事务日志

事务的隔离性由 锁机制 实现 事务的原子性、一致性、隔离性 由事务的 redo日志 和 undo 日志来保证 redo log 称为 重做日志&#xff0c;提供再写入操作&#xff0c;恢复提交事务修改的页操作&#xff0c;用来保证事务的持久性。undo log 称为 回滚日志&#xff0c;回滚行记录…

揭秘c语言作用域

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文主要整理c语言中 与作用域相关的知识点 本文适合对象:无编程基础&#xff0c;因为解释的比较多&#xff0c;所以不适合有基础的人快速掌握了 作用域描述 其实就是起作用的区域。比如个变量&#xff0c;函数…

System-Verilog 实现DE2-115倒车雷达模拟

System-Verilog 实现DE2-115倒车雷达模拟 引言&#xff1a; 随着科技的不断进步&#xff0c;汽车安全技术也日益成为人们关注的焦点。在众多汽车安全辅助系统中&#xff0c;倒车雷达以其实用性和高效性脱颖而出&#xff0c;成为现代汽车不可或缺的一部分。倒车雷达系统利用超声…

轻松拿捏C语言——【内存函数】

&#x1f970;欢迎关注 轻松拿捏C语言系列&#xff0c;来和 小哇 一起进步&#xff01;✊ &#x1f389;创作不易&#xff0c;请多多支持&#x1f389; &#x1f308;感谢大家的阅读、点赞、收藏和关注&#x1f495; &#x1f339;如有问题&#xff0c;欢迎指正~~ 目录&#x1…

简单说说我对集成学习算法的一点理解

概要 集成学习&#xff08;Ensemble Learning&#xff09;是一种机器学习技术框架&#xff0c;它通过构建并结合多个学习器&#xff08;也称为个体学习器或基学习器&#xff09;来完成学习任务。 集成学习旨在通过组合多个基学习器的预测结果来提高整体模型的性能。每个基学习…

《mysql轻松学习·二》

1、创建数据表 contacts&#xff1a;数据表名 auto_increament&#xff1a;自动增长 primary key&#xff1a;主键 engineInnoDB default charsetutf8; 默认字符集utf8&#xff0c;不写就默认utf8 对数据表的操作&#xff1a; alter table 数据表名 add sex varchar(1); //添…

MySQL 一条SQL查询/更新语句是如何执行的?

MySQL 一条SQL查询语句是如何执行的&#xff1f; 1 连接器 首先客户端需要先跟服务端进行连接 2 查询缓存 MySQL 5.7 以及之前的版本会查询MySQL缓存&#xff0c;存储是键值对形式的 分析器 对SQL进行词法分析【会生成词法树】以及语法分析 词法分析&#xff1a; 主要负…

安卓ANR检测、分析、优化面面谈

前言 一个引发讨论的楔子&#xff0c;以下三种现象有什么区别&#xff1a; App停止运行App暂无响应App闪退 答案&#xff1a; 产生原因不同&#xff1a;停止运行是UNCheckExceptionError暂无响应是ANRDialog闪退是CheckExceptionError 本文讨论的主题是ANR的定义、分类、复现…

CISCN 2023 初赛 被加密的生产流量

题目附件给了 modbus.pcap 存在多个协议 但是这道题多半是 考 modbus 会发现 每次的 Query 末尾的两个字符 存在规律 猜测是base家族 可以尝试提取流量中的数据 其中Word Count字段中的22871 是10进制转16进制在转ascii字符串 先提取 过滤器判断字段 tshark -r modbus.pcap …

大学校园广播“录编播”与IP校园公共广播系统技术方案

一、项目概述 1、校园IP网络广播系统概述 大学校园广播系统是学校整个弱电系统中的子系统&#xff0c;它是每个学校不可缺少的基础设施之一&#xff0c;在传递校园文化、传播校园新闻资讯方面发挥着重要的作用。近几年来&#xff0c;虽然视频技术和网络技术在飞速发展&#xf…

沟通程序化(1):跟着鬼谷子学沟通—“飞箝”之术

沟通的基础需要倾听&#xff0c;但如果对方听不进你的话&#xff0c;即便你说的再有道理&#xff0c;对方也很难入心。让我们看看鬼谷子的“飞箝”之术能给我们带来什么样的启发吧&#xff01; “飞箝”之术&#xff0c;源自中国古代兵法家、纵横家鼻祖鬼谷子的智慧&#xff0…

基于分步傅立叶数值算法的一维非线性薛定谔方程求解matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于分步傅立叶数值算法的一维非线性薛定谔方程求解matlab仿真. 2.测试软件版本以及运行结果展示 MATLAB2022A版本运行 3.核心程序 ........................…

appium元素定位工具_uiautomatorviewer.bat

特点&#xff1a; uiautomatorviewer是android-sdk自带的元素定位工具uiautomatorviewer只能用于安卓系统&#xff1b;它是通过截屏分析XML布局文件方式&#xff0c;来提供控件信息的查看服务 uiautomatorviewer.bat 基本使用 路径&#xff1a;这个工具是Android SDK中自带&…

【C++】C++11新特性:新的类功能、可变参数模板、STL容器中的empalce相关接口函数、lambda表达式、包装器(function、bind)

目录 一、新的类功能 1.1 移动构造函数和移动赋值运算符重载 1.2 强制生成默认函数的关键字default 1.3 禁止生成默认函数的关键字delete 1.4 其它的类功能 二、可变参数模板 三、STL容器中的empalce相关接口函数 四、lambda表达式 4.1 lambda的引入 4.2 lambda表达式…

Ollama教程,本地部署大模型Ollama,docker安装方法,仅供学习使用

不可商用&#xff01;&#xff01;仅仅提供学习使用&#xff01; 先上视频教学&#xff1a; Ollama教程&#xff0c;本地部署大模型Ollama&#xff0c;docker安装方法&#xff0c;仅供学习使用&#xff01; 资料获取 &#xff1a; Ollama下载包和安装文档在这里&#xff1…