[RTOS 学习记录] 工程管理工具make及makefile

[RTOS 学习记录] 工程管理工具make及makefile

image-20240421150217202

这篇文章是我阅读《嵌入式实时操作系统μCOS-II原理及应用》后的读书笔记,记录目的是为了个人后续回顾复习使用。
前置内容:

开发工具 Borland C/C++ 3.1 精简版

文章目录

  • 1 make 工具
  • 2 makefile 的内容结构
  • 3 程序段标号的作用
    • 3.1 makefile 示例代码
    • 3.2 代码说明
    • 3.3 第一次运行
    • 3.4 第二次运行
    • 3.5 第三次运行
    • 3.6 结论
  • 4 makefile 实现编译、链接工作
    • 4.1 示例代码
    • 4.2 makefile 代码说明
    • 4.3 makefile 的执行
  • 5 程序段标号的目标作用
    • 5.1 makefile 示例代码
    • 5.2 伪目标
      • 5.2.1 第一次运行
  • 6 makefile 文件的命名
  • 7 makefile 中的变量

1 make 工具

一个开发平台提供给我们,用于管理工程或项目的实用程序,它可以按照我们用户编写的makefile脚本文件对工程项目进行管理。

2 makefile 的内容结构

makefile是一个脚本文件,文件内容中有许多我们在命令行中常常用到的各种命令。

makefile程序段的格式如下:

程序段的标号(target): 关联程序段1的标号 关联程序段2的标号 ...命令集
关联程序段1的标号:命令集
关联程序段2的标号:命令集
...

注意:命令集中的所有命令行必须缩进一个tab键。

一个makefile文件有若干个程序段,程序段的开头必须有一个target进行标注,区分各个程序段。不同的程序段之间可以进行关联,此时在target后面以空格为界罗列相关联程序段的target。每个程序段有一组实现工程项目管理的命令集。

3 程序段标号的作用

标号可以看作是对应程序段的名称,我们可以在make命令的后面使用标号来指定需要执行的程序段。

3.1 makefile 示例代码

按照makefile的内容格式编写一个makefile脚本文件,命名为makefile(makefile的默认名称):

mkdir1:md dir1
mkdir2:md dir2
rmdir:rd dir1rd dir2

3.2 代码说明

上面编写的makefile文件中一共有3个程序段:mkdir1、mkdir2 和 rmdir。作用分别是:

  1. mkdir1——在当前目录下创建一个名为dir1的文件夹
  2. mkdir2——在当前目录下创建一个名为dir2的文件夹
  3. rmdir——删除前面两个步骤创建的两个文件夹dir1和dir2

3.3 第一次运行

在命令行窗口中使用 cd EXP2_3 进入此次示例makefile文件所在的目录中,输入 make 命令并且回车执行。可以看到,执行完成后在当前目录新建了一个名为dir1的文件夹,如下图所示:

image-20240421154600345

根据执行结果,我们知道了make执行了makefile中的第一个程序段mkdir1,其余两个程序段mkdir2rmdir都没有被执行。

3.4 第二次运行

输入命令 make mkdir2 并且回车执行,可以看到,执行完毕后当前目录下又新建了一个名为dir2的文件夹,如下图所示:

image-20240421155052461

3.5 第三次运行

输入命令 make rmdir 并且回车执行,可以看到,执行后dir1和dir2这两个文件夹都被删除了,如下图所示:

image-20240421155302943

3.6 结论

当使用 make 命令时,makefile的第一个程序段会被执行,即makefile的首段程序段是make.exe的默认执行程序段,makefile的其他程序段需要执行时必须在make命令后面显式地指定标号。

4 makefile 实现编译、链接工作

由于makefile的程序段中的命令集中可以使用一切命令行命令,所以我们可以把源文件的编译和链接工作步骤编写到makefile中,然后通过执行makefile脚本文件“自动的”完成编译、链接工作。

4.1 示例代码

一个具有3个源文件应用程序的示例如下:

头文件 printA.h

#ifndef _PRINTA_H_
#define _PRINTA_H_extern const char *msgA;#endif

源文件 printA.c

#include "printA.h"const char *msgA = "AAAAA";

头文件 printB.h

#ifndef _PRINTB_H_
#define _PRINTB_H_extern const char *msgB;#endif

源文件 printB.c

#include "printB.h"const char *msgB = "BBBBB";

源文件 test.c

#include <stdio.h>
#include "printA.h"
#include "printB.h"int main(void)
{unsigned char i = 0;for (i=0; i<5; i++){printf("%s\n", msgA);printf("   %s\n", msgB);}return 0;
}

链接文件 TESTLINK

C:\BC\LIB\C0L.OBJ +
PRINTA.OBJ +
PRINTB.OBJ +
TEST.OBJ
TEST
TEST
C:\BC\LIB\CL.LIB

接下来就编写一个具有4个程序段的makefile脚本文件,实现源文件的编译、中间目标文件的链接,最终生成可执行文件TEST.EXE。

make脚本文件 makefile

##############################################
#             创建可执行文件(exe)
TEST.EXE:TLINK   @TESTLINK##############################################
#           创建各个目标文件(obj)
PRINTA.OBJ:BCC -c -ml -IC:\BC\INCLUDE -LC:\BC\LIB PRINTA.C
PRINTB.OBJ:BCC -c -ml -IC:\BC\INCLUDE -LC:\BC\LIB PRINTB.C
TEST.OBJ:BCC -c -ml -IC:\BC\INCLUDE -LC:\BC\LIB TEST.C

4.2 makefile 代码说明

为了增强可读性,此次示例的makefile代码中使用了文件名称作为程序段的标号,而且该文件正是对应程序段的命令集中的命令所要实现的目标结果。

第2~4个程序段分别完成对3个源文件printA.c、printB.c和test.c的编译,然后得到3个中间目标文件printA.obj、printB.obj和test.obj。第1个程序段即首段程序段完成各个中间目标文件的链接,最终得到可执行文件TEST.EXE。

4.3 makefile 的执行

分别依次使用 make PRINTA.OBJmake PRINTB.OBJmake TEST.OBJmake 完成示例应用程序的编译、链接,如下图所示:

image-20240421165535513

image-20240421165621705

image-20240421165657126

image-20240421165732331

运行可执行程序 TEST.EXE,可以看到屏幕上重复5次打印了字符串,如下图所示:

image-20240421165907435

5 程序段标号的目标作用

前面的示例makefile文件中,我们使用了文件名:PRINTA.OBJPRINTB.OBJTEST.OBJ 作为它们各自程序段的标号,而该文件名对应的文件正是它的程序段命令集所要生成的文件,因此我们把满足这种关系的程序段标号又称作程序段的目标,例如:PRINTA.OBJ 是它对应程序段的目标,PRINTB.OBJ 是它对应程序段的目标,TEST.OBJ 是它对应程序段的目标等等。

我们前面已经提到了[makefile允许关联程序段](#makefile 的内容结构),即makefile允许我们把程序段编写成如下形式:

目标(标号): 生成目标所需的文件名(依赖文件,简称“依赖”)命令集

为了强调程序段目标与其所需文件之间的关系,我们把生成目标所需的文件称作依赖文件,简称依赖

因此,我们可以把一个工程的编译、链接工作所需的多个程序段关联起来,从而仅需要执行一次 make 命令即可完成所有的编译和链接工作。

对于上述示例的makefile来说,如果要把生成TEST.EXE文件的程序段和生成其依赖文件的程序段关联起来,那么按照上述格式,makefile的第一个程序段就为:

TEST.EXE: PRINTA.OBJ PRINTB.OBJ TEST.OBJTLINK @TESTLINK

该程序段的含义是:本程序段的目标(标号)为 TEST.EXE,该目标(标号)需要由 PRINTA.OBJPRINTB.OBJTEST.OBJ 三个文件来生成,其命令则为 TLINK @TESTLINK

如果目标所依赖的文件都存在,满足生成目标所需要的条件,则连接命令 TLINK 被执行,否则程序会以 PRINTA.OBJPRINTB.OBJTEST.OBJ 为转移目标转向以它们为标号的程序段。也就是说,目标:依赖文件名 的这种格式是一种多分支条件转移语句。当生成目标的条件不满足(依赖文件不存在)时,程序的执行将要发生转移,其转移目标就是以依赖文件名为标号或目标的程序段。

实际上,make工具在执行makefile的各个程序段时,首先会检查目标(target)文件是否已经存在,如果存在,则会进一步检查该目标所依赖文件的时间戳(文件属性中的“创建时间”、“修改时间”等时间信息),只有当依赖文件比现有目标新时,其命令集才会被执行。其目的就是:尽量不做不必要的重复编译工作。

5.1 makefile 示例代码

为了格式上的整齐,凡是以目标为标号的程序段都要写上目标的依赖。

make 文件 makefile

##############################################
#             创建可执行文件(exe)
TEST.EXE: PRINTA.OBJ PRINTB.OBJ TEST.OBJTLINK   @TESTLINK
##############################################
#           创建各个目标文件(obj)
PRINTA.OBJ: PRINTA.C PRINTA.HBCC -c -ml -IC:\BC\INCLUDE -LC:\BC\LIB PRINTA.C
PRINTB.OBJ: PRINTB.C PRINTB.HBCC -c -ml -IC:\BC\INCLUDE -LC:\BC\LIB PRINTB.C
TEST.OBJ: TEST.C PRINTA.H PRINTB.HBCC -c -ml -IC:\BC\INCLUDE -LC:\BC\LIB TEST.C

5.2 伪目标

由上可知,makefile的target有目标和标号两种作用:当它是文件名时,它既是标号也是目标;而当它只是一个标识时,它就是标号。听起来很混乱,所以为了明确起见,人们把makefile中的target全部叫做目标,把那种仅起标号作用的目标则叫做“伪目标”。
在makefile中,伪目标所对应的程序段是一个不与其他程序段相关联的程序段,所以在需要执行它们时,必须在make命令中显式地使用其标号,除非它是makefile的第一个程序段(几乎没人这样做)。它们通常被用来完成一些创建目录、删除目录、复制文件、移动文件及删除文件等项目管理任务。

例如,可以为示例makefile添加一个标号为 CLEAN 的伪目标代码段,该段的任务就是为了用户目录的整洁,在已生成了最终可执行文件后,删除那些中间目标文件 PRINTA.OBJPRINTB.OBJTEST.OBJ
修改后的makefile如下:

##############################################
#             创建可执行文件(exe)
TEST.EXE: PRINTA.OBJ PRINTB.OBJ TEST.OBJTLINK   @TESTLINK
##############################################
#           创建各个目标文件(obj)
PRINTA.OBJ: PRINTA.C PRINTA.HBCC -c -ml -IC:\BC\INCLUDE -LC:\BC\LIB PRINTA.C
PRINTB.OBJ: PRINTB.C PRINTB.HBCC -c -ml -IC:\BC\INCLUDE -LC:\BC\LIB PRINTB.C
TEST.OBJ: TEST.C PRINTA.H PRINTB.HBCC -c -ml -IC:\BC\INCLUDE -LC:\BC\LIB TEST.C
CLEAN:DEL PRINTA.OBJDEL PRINTB.OBJDEL TEST.OBJ

5.2.1 第一次运行

使用 make 命令执行 makefile 的第一个程序段,生成最终可执行文件 TEST.EXE,如下图所示:

image-20240422091935127

image-20240422092035300

执行 make clean 表示显示地使用 CLEAN 参数执行 makefile 文件中的 CLEAN 程序段,将中间目标文件删除,如下图所示:

image-20240422092319854

image-20240422092334231

6 makefile 文件的命名

makefile是make文件的默认名称,如果用户不喜欢该名称,则完全可以自行对其进行命名(包括扩展名),但在make命令中要使用参数f,即:

make -f 文件名

7 makefile 中的变量

通常,在一个makefile中会有很多经常要重复使用的元素,例如示例makefile中的编译命令 BCC、编译命令中的参数 -c -ml -IC:\BC\INCLUDE -LC:\BC\LIB 等等。显然,用一些比较简洁且语义清楚的符号变量来表示它们更好,因此makefile允许人们定义变量。

变量格式:

变量名 = 变量的值

引用变量格式:

$(变量名)

使用变量改写示例makefile后,代码如下:

其中,前面带有符号“#”的为注释行;如果依赖文件表示行过长,也可以反斜杠“\”为换行符分行书写。

##############################################
#             makefile
##############################################
#        用变量来表示所使用的开发工具
BORLAND = C:\BC
CC = $(BORLAND)\BIN\BCC
LINK = $(BORLAND)\BIN\TLINK
##############################################
#               编译选项说明
#
# -l    生成80286实模式代码
# -c    编译为.obj文件
# -I    指示包含头文件所在路径
# -k    采用标准栈帧
# -L    指示库文件所在路径
# -ml   Large memory内存模式
# -n    指示生成目标文件的位置
##############################################
#             C编译选项变量
C_FLAGS = -c -ml -l -n.\ -k -I$(BORLAND)\INCLUDE -L$(BORLAND)\LIB
##############################################
#             链接选项变量
LINK_FLAGS = 
##############################################
#             创建可执行文件(exe)
TEST.EXE:       \PRINTA.OBJ      \PRINTB.OBJ      \TEST.OBJ$(LINK) $(LINK_FLAGS) @TESTLINK
##############################################
#           创建各个目标文件(obj)
PRINTA.OBJ:         \PRINTA.c        \PRINTA.h$(CC) $(C_FLAGS) PRINTA.c
PRINTB.OBJ:         \PRINTB.C        \PRINTB.H$(CC) $(C_FLAGS) PRINTB.C
TEST.OBJ:       \TEST.C      \PRINTA.H        \PRINTB.H$(CC) $(C_FLAGS) TEST.C
# 以下为伪目标代码段
CLEAN:DEL PRINTA.OBJDEL PRINTB.OBJDEL TEST.OBJ

运行结果如下图:

make

image-20240422094447941

image-20240422094550617

make clean

image-20240422094621696

image-20240422094647703

可以看到,使用变量后,make执行时会自动将makefile中引用的变量替换成变量的值。

参考资料:

《嵌入式实时操作系统μCOS-II原理及应用》

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

HBase的简单学习三

一 过滤器 1.1相关概念 1.过滤器可以根据列族、列、版本等更多的条件来对数据进行过滤&#xff0c; 基于 HBase 本身提供的三维有序&#xff08;行键&#xff0c;列&#xff0c;版本有序&#xff09;&#xff0c;这些过滤器可以高效地完成查询过滤的任务&#xff0c;带有过滤…

线性模型算法

简介 本文章介绍机器学习中的线性模型有关内容&#xff0c;我将尽可能做到详细得介绍线性模型的所有相关内容 前置 什么是回归 回归的就是整合&#xff0b;预测 回归处理的问题可以预测&#xff1a; 预测房价 销售额的预测 设定贷款额度 可以根据事物的相关特征预测出对…

eCharts 折线图 一段是实线,一段是虚线的实现效果

在lineStyle里写了不生效的话&#xff0c;可以尝试数据拼接 option {xAxis: {type: category,data: [Mon, Tue, Wed, Thu, Fri, Sat, Sun]},yAxis: {type: value},series: [{data: [150, 230, 224,218 ,,,],type: line},{data: [,,, 218, 135, 147, 260],type: line,lineStyl…

在excel中,如何在一个表中删除和另一个表中相同的数据?

现在有A表&#xff0c;是活动全部人员的姓名和学号&#xff0c;B表是该活动中获得优秀人员的姓名和学号&#xff0c; 怎么提取没有获得优秀人员的名单&#xff1f; 这里提供两个使用excel基础功能的操作方法。 1.条件格式自动筛选 1.1按住Ctrl键&#xff0c;选中全表中的姓…

Interpreter 解释器

意图 给定一个语言&#xff0c;定义它的文法的一种表示&#xff0c;并定义一个解释器&#xff0c;这个解释器使用该表示来解释语言中的句子。 结构 AbstractExpression声明一个程序的解释操作&#xff0c;这个接口为抽象语法树中所有结点所共享。TerminalExpression实现与文法…

Ts类型体操详讲 之 extends infer (下)

目录 1、函数 &#xff08;1&#xff09;提取参数类型 &#xff08;2&#xff09;提取返回值类型 2、构造器 &#xff08;1&#xff09;提取构造器返回值 &#xff08;2&#xff09;提取构造器参数类型 3、索引类型 本章我们继续上节的内容继续&#xff0c;展示我们对ex…

聚观早报 | TCL召开电视新品发布会;OceanBase 4.3发布

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 4月22日消息 TCL召开电视新品发布会 OceanBase 4.3发布 科大讯飞推出耳背式助听器 F1联想中国大奖赛开赛 蔚来展…

引领4G拾音新时代:DuDuTalk双定向拾音设备上市,助力现场管理步入智能化

近日&#xff0c;继DuDuTalk的4G智能拾音工牌&#xff08;挂牌和胸牌&#xff09;之后&#xff0c;赛思云科技在线下沟通场景智能语音采集方案领域的又一突破性产品4G双定向桌面拾音终端全新上市。 该产品是面向营业网点、市政大厅、医疗诊室、售票窗口、贵宾室等环境的柜台服…

AD 21、22 软件安装教程

AD2022安装包链接 链接&#xff1a;https://pan.baidu.com/s/1oMNbXibQ1Zjl0RTLdPDVGw 提取码&#xff1a;xfs4 软件下载 1.以管理员身份运行 2. 3. 4. 5.路径最好改为C盘以外的&#xff0c;如D盘&#xff0c;要新建一个空文件夹 6. 7.下载好以后 8.在Crack文件夹下找…

全网最全的平行坐标图(parallel coordinates plot)的绘制攻略

早上起来拥抱太阳&#xff0c;写小论文&#xff0c;看到人家的图怎么那么好看&#xff01;&#xff01;&#xff1f;&#xff1f; 这不得赶紧抄下来&#xff0c;我也发一个顶刊&#xff1f;于是开始思考如何解决绘制这个问题&#xff0c;目前现有的大部分解决方案都是直接调库…

[负债学习]支线Python4.21

三的东西&#xff0c;一个是环境&#xff0c;一个是基础语法&#xff0c;第3个是代码的案例。 我们先从头开始讲一下计算机&#xff0c;它主要由4个部分组成cpu的中央处理器和一个储存和一个输出和出。而储存的话主要是由内存和外存而cpu&#xff0c;中央处理器全称叫做通用计…

Linux——进程基本概念下篇

Linux——进程基本概念下篇 文章目录 Linux——进程基本概念下篇一、环境变量1.1 环境变量的定义1.2 环境变量的相关命令1.3 命令行参数1.4 本地变量和环境变量1.5 常规命令和内建命令 二、进程地址空间2.1 地址空间的概念2.2 页表和MMU2.3 地址空间的作用2.4 地址空间的好处 一…

SpringBoot+Vue多模块项目宝塔部署(保姆级教程)

目录 服务器推荐 安装宝塔 进入宝塔 安装软件 安装 nginx ​编辑 安装mysql 安装java 配置数据库 启动模块下加打包插件 修改配置文件 添加java项目 放行端口 前端访问 本篇博文将向各位详细的介绍项目部署到服务器的详细过程&#xff0c;以及我配置过程中遇到的…

详细分析MySQL中的distinct函数(附Demo)

目录 前言1. 基本知识2. 基础Demo3. 进阶Demo 前言 该函数主要用于去重&#xff0c;对于细节知识&#xff0c;此文详细补充说明 1. 基本知识 DISTINCT 是一种用于查询结果中去除重复行的关键字 在查询数据库时&#xff0c;可能会得到重复的结果行&#xff0c;但有时只需要这…

【YOLOv8改进[Neck]】使用BiFPN助力V8更优秀

目录 一 BiFPN(双向特征金字塔网络) 1 BiFPN 2 EfficientDet 二 使用BiFPN助力模型更优秀 1 整体修改 2 配置文件 3 训练 其他 一 BiFPN(双向特征金字塔网络) BiFPN(双向特征金字塔网络&#xff0c; 2020)用于特征融合层。 官方论文地址&#xff1a;https://arxiv.org…

javaScript中的this 指向

this 指向总结 this 关键字是一个非常重要的语法点。 this 可以用在构造函数之中&#xff0c;表示实例对象。除此之外&#xff0c;this 还可以用在别的场合。但不管是什么场合&#xff0c;this 都有一个共同点&#xff1a;它总是返回一个对象。 关于 this 的指向&#xff0c…

研究发现:90%的Java服务容易第三方漏洞的影响

Datadog最新发布的“2024年DevSecOps状况”报告显示&#xff0c;Java服务在受Datadog最新发布的“2024年DevSecOps状况”报告显示&#xff0c;Java服务在受到第三方漏洞影响方面最为严重。 报告指出&#xff0c;90%的Java服务存在一个或多个严重或高危漏洞&#xff0c;这些漏…

uni打包ios应用

简单写了一个打开蓝牙的 配置一下manifest.json 打开蓝牙 进行云打包 准备好私钥&#xff08;私钥密码&#xff09;,profile点击打包> 出来一个.ipa文件 用数据线连上ios手机&#xff0c;直接安装到手机 如下&#xff1a; 关于密钥和profile文件的操作使用Appuploader生成…

unity 录制360全景渲染图

1.打开pakcageManager &#xff0c;选择packages为 unityRegisty&#xff0c;找到unityRecorder插件下载&#xff0c;点击右下角instant安装&#xff0c;如果插件列表为空&#xff0c;检查是否连接网络&#xff0c;重启Unity 2.打开录制面板 3.add recorder 选择ImageSequence …

使用文本到图像模型的一步图像翻译

使用文本到图像模型的一步图像翻译 摘要IntroductionRelated WorkMethod One-Step Image Translation with Text-to-Image Models 摘要 在这项工作中&#xff0c;作者解决了现有条件扩散模型的两个局限性&#xff1a;由于迭代去噪过程导致的推理速度慢以及模型微调对配对数据依…