ZYNQ - 嵌入式Linux开发 -05- Linux C编程和Makefile(二)

简介: ZYNQ - 嵌入式Linux开发 -05- Linux C编程和Makefile

Makefile变量


跟 C 语言一样 Makefile 也支持变量,对于重复输入的内容,可以进行定义变量进行简化Makefile的编写。和C语言不太一样的是,Makefile 中的变量都是

字符串。所以简化上面的Makefile文件后为下所示:

obj = main.o test.o test1.o
main: $(obj)
  gcc -o main $(obj)
#main:main.o test.o test1.o
# gcc -o main main.o test.o test1.o
main.o:main.c
  gcc -c main.c
test.o:test.c
  gcc -c test.c
test1.o:test1.c
  gcc -c test1.c
clean:
  rm *.o
  rm main

赋值符 “=”

使用“=”在给变量的赋值的时候,不一定要用已经定义好的值,也可以使用后面定义的值。可以将变量的真实值推到后面去定义,也就是变量的真实值取决于它所引用的变量的最后一次有效值。

赋值符 “:=”

赋值符“:=”和“=”类似,但是不同的是,“:=”不会使用后面定义的变量,只能使用前面已经定义好的,这就是“=”和“:=”两个的区别。

赋值符 “?=”

如果变量前面没有被赋值,那么此变量就是赋值符右边的值,如果前面已经赋过值了,那么就使用前面赋的值。

变量追加 “+=”

Makefile 中的变量是字符串,有时候我们需要给前面已经定义好的变量添加一些字符串进去,此时就要使用到符号“+=”。

模式规则与自动化变量


上述 Makefile 中第 3~8 行是将对应的.c 源文件编译为.o 文件,每一个 C 文件都要写一个对应的规则,如果工程中 C 文件很多,这样操作会增加冗余工作量。所以可以使用 Makefile 中的模式规则,通过模式规则就可以使用一条规则来将所有的.c 文件编译为对应的.o 文件。

模式规则中,至少在规则的目标定定义中要包涵“%”,否则就是一般规则,目标中的“%”表示对文件名的匹配,“%”表示长度任意的非空字符串,比如“%.c”就是所有的以.c 结尾的文件,类似与通配符,a.%.c 就表示以 a.开头,以.c 结束的所有文件。

当“%”出现在目标中的时候,目标中“%”所代表的值决定了依赖中的“%”值,使用方法如下:

%.o : %.c
  命令

对于规则中把c文件编译为o文件已经简化,为了简化命令操作,同时引入自动化变量的内容。目标和依赖都是一系列的文件,每一次对模式规则进行解析的时候都会是不同的目标和依赖文件,而命令只有一行。自动化变量可以把命令进行通用化处理。

自动化变量 就是这种变量会把模式中所定义的一系列的文件自动的挨个取

出,直至所有的符合模式的文件都取完,自动化变量只应该出现在规则的命令中。

image.png

使用自动化变量来完成Makefile,最终代码如下所示:

obj = main.o test.o test1.o
main: $(obj)
  gcc -o main $(obj)
%.o : %.c
  gcc -c $<
clean:
  rm *.o
  rm main

Makefile 伪目标


Makefile 有一种特殊的目标——伪目标,一般的目标名都是要生成的文件,而伪目标不代表真正的目标名,在执行 make 命令的时候通过指定这个伪目标来执行其所在规则的定义的命令。

使用伪目标的主要是为了避免 Makefile 中定义的只执行命令的目标和工作目录下的实际文件出现名字冲突,有时候我们需要编写一个规则用来执行一些命令,但是这个规则不是用来创建文件的。比如在该文件下创建了一个clean文件,而在Makefile中又创建了一个clean的命令,此时执行make clean时,无法进行正常执行Makefile中的清除指令。为了解决这个“共存”问题,可以对clean进行声明为伪目标。

.PHONY : clean

Makefile 条件判断


Makefile 也支持条件判断,语法有两种如下:

<条件关键字>
  <条件为真时执行的语句>
endif

以及:

<条件关键字>
  <条件为真时执行的语句>
else
  <条件为假时执行的语句>
endif

其中条件关键字有 4 个: ifeq、 ifneq、 ifdef 和 ifndef,这四个关键字其实分为两对、 ifeq 与 ifneq、 ifdef与 ifndef,先来看一下 ifeq 和 ifneq, ifeq 用来判断是否相等, ifneq 就是判断是否不相等, ifeq 用法如下:

ifeq (<参数 1>, <参数 2>)
ifeq ‘<参数 1 >’,‘ <参数 2>’
ifeq “<参数 1>”, “<参数 2>”
ifeq “<参数 1>”, ‘<参数 2>’
ifeq ‘<参数 1>’, “<参数 2>”

上述用法中都是用来比较“参数 1”和“参数 2”是否相同,如果相同则为真,“参数 1”和“参数 2”可以为函数返回值,ifneq 的用法类似。

Makefile 函数


Makefile 支持函数,不支持我们自定义函数,只能使用定义好的函数。函数的用法如下:

$(函数名 参数集合)   or   ${函数名 参数集合}

调用函数和调用普通变量一样,使用符号“” 来 标 识 。 参 数 集 合 是 函 数 的 多 个 参 数 , 参 数 之 间 以 逗 号 “ , ” 隔 开 , 函 数 名 和 参 数 之 间 以 “ 空 格 ” 分 隔 开 , 函 数 的 调 用 以 “ ”来标识。参数集合是函数的多个参数,参数之间以逗号“,”隔开,函数名和参数之间以“空格”分隔开,函数的调用以“”来标识。参数集合是函数的多个参数,参数之间以逗号“,”隔开,函数名和参数之间以“空格”分隔开,函数的调用以“”开头。

函数 subst

函数 subst 用来完成字符串替换,调用形式如下:

$(subst <from>,<to>,<text>)

此函数的功能是将字符串中的内容替换为,函数返回被替换以后的字符串。

函数 patsubst

函数 patsubst 用来完成模式字符串替换,使用方法如下:

$(patsubst <pattern>,<replacement>,<text>)

此函数查找字符串中的单词是否符合模式,如果匹配就用来替换掉,可以使用包括通配符“ %”,表示任意长度的字符串,函数返回值就是替换后的字符串。如果中也包涵“%”,那么中的“%”将是中的那个“%”所代表的字符串。

比如:

$(patsubst %.c,%.o,a.c b.c c.c)

将字符串“a.c b.c c.c”中的所有符合“%.c”的字符串,替换为“%.o”,替换完成以后的字符串为“a.o

b.o c.o”。

函数 dir

函数 dir 用来获取目录,使用方法如下:

$(dir <names…>)

此函数用来从文件名序列中提取出目录部分,返回值是文件名序列的目录部分。

函数 notdir

函数 notdir 看名字就是知道去除文件中的目录部分,也就是提取文件名,用法如下:

$(notdir <names…>)

此函数用与从文件名序列中提取出文件名非目录部分。

函数 foreach

foreach 函数用来完成循环,用法如下:

$(foreach <var>, <list>,<text>)

此函数的意思就是把参数中的单词逐一取出来放到参数中,然后再执行所包含的表达

式。每次都会返回一个字符串,循环的过程中, 中所包含的每个字符串会以空格隔开,最后当整个循环结束时, 所返回的每个字符串所组成的整个字符串将会是函数 foreach 函数的返回值。

函数 wildcard

通配符“%”只能用在规则中,只有在规则中它才会展开,如果在变量定义和函数使用时,通配符不会自动展开,这个时候就要用到函数 wildcard,使用方法如下:

$(wildcard PATTERN…)

比如:

$(wildcard *.c)

上面的代码是用来获取当前目录下所有的.c 文件,类似“%”。

References


  1. 正点原子开发视频
  2. 正点原子ZYNQ之linux开发教程
  3. 跟我一起写 Makefile
目录
相关文章
|
JavaScript Linux 网络安全
Termux安卓终端美化与开发实战:从下载到插件优化,小白也能玩转Linux
Termux是一款安卓平台上的开源终端模拟器,支持apt包管理、SSH连接及Python/Node.js/C++开发环境搭建,被誉为“手机上的Linux系统”。其特点包括零ROOT权限、跨平台开发和强大扩展性。本文详细介绍其安装准备、基础与高级环境配置、必备插件推荐、常见问题解决方法以及延伸学习资源,帮助用户充分利用Termux进行开发与学习。适用于Android 7+设备,原创内容转载请注明来源。
5529 77
|
Ubuntu 搜索推荐 Linux
详解Ubuntu的strings与grep命令:Linux开发的实用工具。
这就是Ubuntu中的strings和grep命令,透明且强大。我希望你喜欢这个神奇的世界,并能在你的Linux开发旅程上,通过它们找到你的方向。记住,你的电脑是你的舞台,在上面你可以做任何你想做的事,只要你敢于尝试。
583 32
|
Rust Ubuntu Java
[Linux工具] Makefile
Makefile是Linux环境下用于自动化编译和链接程序的配置文件,常用于简化大型项目的编译流程。通过定义目标文件、依赖文件及生成命令,Makefile能高效管理编译任务。它不仅适用于C语言项目,还可扩展到其他编程语言和非编程任务中。
[Linux工具] Makefile
|
NoSQL Linux 开发工具
Linux环境基础开发工具的使用(yum、vim、gcc、g++、gdb、make/Makefile)
本文介绍了yum 包管理工具、Vim 编辑器、gcc/g++ 编译器、gdb 调试器、编译原理及 Makefile 的使用,同时还配备了如何使用,以及图解。旨在帮助读者更好地理解和应用这些工具与技术。
621 0
|
Unix Linux C语言
【Linux】 Linux makefile 教程
本文详细介绍了 Linux 环境下 Makefile 的基本结构、语法和使用方法,并通过一个简单的 C++ 项目示例演示了 Makefile 的实际应用。Makefile 是一个强大而灵活的工具,通过合理配置,可以极大地简化项目的编译和管理过程,提高开发效率。希望本文能帮助您更好地理解和应用 Makefile,在实际项目中高效管理代码的编译和构建。
990 20
|
Unix Linux C语言
【Linux】 Linux makefile 教程
本文详细介绍了 Linux 环境下 Makefile 的基本结构、语法和使用方法,并通过一个简单的 C++ 项目示例演示了 Makefile 的实际应用。Makefile 是一个强大而灵活的工具,通过合理配置,可以极大地简化项目的编译和管理过程,提高开发效率。希望本文能帮助您更好地理解和应用 Makefile,在实际项目中高效管理代码的编译和构建。
418 16
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
796 13
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
961 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
消息中间件 缓存 Unix
[面试必备]嵌入式Linux内核开发必须了解的三十道题
[面试必备]嵌入式Linux内核开发必须了解的三十道题
|
Linux Go 人机交互
嵌入式linux之go语言开发(十三)LittlevGL,漂亮的嵌入式GUI的go语言绑定
嵌入式linux之go语言开发(十三)LittlevGL,漂亮的嵌入式GUI的go语言绑定