嵌入式Linux驱动开发系列六:Makefile

news2024/10/6 14:23:00

Makefile是什么?

gcc hello.c -o hello

gcc aa.c bb.c cc.c dd.c ...

make工具和Makefile

make和Makefile是什么关系?

make工具:找出修改过的文件,根据依赖关系,找出受影响的相关文件,最后按照规则单独编译这些文件。

Makefile文件:记录依赖关系和编译规则。

必须要学精Makefile吗?

怎么学习Makefile?

Makefile的本质:无论多么复杂的语法,都是为了更好地解决项目文件之间的依赖关系。

 

 

Makefile三要素

Makefile三要素是什么?

目标、依赖、命令

怎么描述三要素的关系?

目标:依赖的文件或者是其他目标  ( 记得加TAB字符)

<tab>命令1 

<tab>命令2

<tab>...

实验演示

.PHONY:可以指定伪目标

gec@ubuntu:~/makefile/part_1$ sudo vi Makefile
gec@ubuntu:~/makefile/part_1$ sudo make
echo "targetb"
targetb
echo "targetc"
targetc
echo "targeta"
targeta
gec@ubuntu:~/makefile/part_1$ cat Makefile 
#Makefile格式
#目标:依赖的文件或其它目标
#Tab 命令1
#Tab 命令2
#第一个目标,是最终目标及make的默认目标
#目标a,依赖于目标targetc和targetb
#目标要执行的shell命令 ls -lh,列出目录下的内容
targeta: targetb targetc
	echo "targeta"

#目标b,无依赖
#目标要执行的shell命令,使用touch创建test.txt文件
targetb:
	echo "targetb"

#目标c,无依赖
#目标要执行的shell命令,pwd显示当前路径
targetc:
	 echo "targetc"
#目标d,无依赖
#由于abc目标都不依赖于目标d,所以直接make时目标d不会被执行
#可以使用make targetd命令执行
#  targetd:
#  rm -f test.txt
gec@ubuntu:~/makefile/part_1$ 

上图中包含的原理说明如下:

make命令:

在终端上执行make命令时,make会在当前目录下搜索名为“Makefile”或“makefile”的文件,然后 根据该文件的规则解析执行。如果要指定其它文件作为输入规则,可以通过“-f”参数指定输 入文件,如“make -f 文件名”。

此处make命令读取我们的Makefile文件后,发现targeta是Makefile的第一个目标,它会被当成默认目标执行。

又由于targeta依赖于targetc和targetb目标,所以在执行targeta自身的命令之前,会先去完成targetc和targetb。

targetc的命令为pwd,显示了当前的路径。

targetb的命令为touch test.txt ,创建了test.txt文件。

最后执行targeta自身的命令ls -lh ,列出当前目录的内容,可看到多了一个test.txt文件。

.PHONY 是一个在 Makefile 中使用的特殊目标标签(伪目标),用于指示某个目标不对应实际的文件。

通常,Makefile 中的目标都对应着需要生成的文件,而这些目标称为“真实目标”。但有时候,我们需要定义一些在执行 make 命令时需要执行的操作,而这些操作不产生对应的文件。这时就可以使用 .PHONY 来定义这样的目标。

.PHONY 的作用是告诉 make 工具,无论是否存在与之同名的文件,它所标记的目标都应该被认定为需要执行的操作。这样,在执行该目标时,make 将会按照你在 Makefile 中定义的命令来执行相应的操作,而不会检查是否有与之同名的文件存在。

使用 .PHONY 的一个常见场景是在 Makefile 中定义一些常用的操作,比如 clean 来清理临时文件,或者 all 来构建所有的目标。

示例:

.PHONY: clean clean: rm -f *.o

在上述示例中,.PHONY: clean 表示 clean 目标是一个伪目标,不对应任何文件。当执行 make clean 命令时,将会执行 rm -f *.o 命令,删除所有 .o 结尾的临时文件。

总结来说,.PHONY 是用来定义伪目标的,它告诉 make 工具,该目标不对应任何文件,而是需要执行一些特定的操作

 

 

在Makefile的实际应用中,通常会把编译和最终的链接过程分开

 也就是说,我们的hello_main目标文件本质上并不是依赖hello_main.c和hello_func.c文件,而是依 赖于hello_main.o和hello_func.o,把这两个文件链接起来就能得到我们最终想要的hello_main目 标文件。另外,由于make有一条默认规则,当找不到xxx. o文件时,会查找目录下的同名xxx.c文件进行编译。根据这样 的规则,我们可把Makefile改修改如下。

#Makefile格式
#目标文件:依赖的文件
#Tab 命令1
#Tab 命令2
hello_main: hello_main.o hello_func.o
   gcc -o hello_main hello_main.o hello_func.o
#以下是make的默认规则,下面两行可以不写
#hello_main.o: hello_main.c
# gcc -c hello_main.c

#以下是make的默认规则,下面两行可以不写
#hello_func.o: hello_func.c
# gcc -c hello_func.c

以上代码的第5~6行把依赖文件由C文件改成了.o文件,gcc编译命令也做 了相应的修改。第8~13行分别是hello_main.o文件和hello_func.o文件的依赖和 编译命令,不过由于C编译成同名的.o文件是make的默认规则,所以这部分内容通常不会写上去。

Makefile的变量、模式匹配

变量

系统变量

自定义变量

=,延迟赋值

:=, 立即赋值

?=,空赋值(像const)

只有当这个变量为空时赋值才有效

+=,追加赋值

当我们用追加赋值给某个变量赋值时,不会覆盖该变量的值,而是在该变量原来的值后面加上新赋的值

 

自动化变量

$<:第一个依赖文件

$^:全部的依赖文件

$@:目标

 

优化

模式匹配

%:匹配任意多个非空字符

shell:*通配符

默认规则

.o文件默认使用当前目录下对应.c文件来进行编译

Makefile条件分支

条件分支

如果相等
ifeq (var1,var2)
...
else
...
endif
ifneq (var1,var2)
...
else
...
endif

Makefile的常用函数

Makefie官方手册:

GNU Make Manual - GNU Project - Free Software Foundation

patsubst:

 文本匹配成新的模式

notdir:

  1. $(notdir <names...>)
  • 名称:取文件函数——notdir。

  • 功能:从文件名序列 <names> 中取出非目录部分。非目录部分是指最後一个反斜杠( / )之后的部分。

  • 返回:返回文件名序列 <names> 的非目录部分。

  • 示例: $(notdir src/foo.c hacks) 返回值是 foo.c hacks 。

wildcard:

示例:

(wildcard *.c) 

 返回值为当前目录下所有.c 源文件列表。

foreach:

Makefile解决头文件依赖

1、写一个头文件,并把头文件添加到编译器的头文件路径中。

gcc -I +"头文件"

2、实时检查头文件的更新情况,一旦头文件发生变化,应该要重新编译所有相关文件。

gcc -MM

ARCH ?= x86 


ifeq ($(ARCH),x86)
        CC=gcc

else 
        CC=arm-linux-gnueabihf-gcc
endif



TARGET=mp3
#OBJS=main.o mp3.o
BUILD_DIR=build
SRC_DIR=module1 module2
INC_DIR=include
CFLAGS=$(patsubst %,-I%,$(INC_DIR))
INCLUDES=$(foreach dir,$(INC_DIR),$(wildcard $(dir)/*.h))


SOURCES= $(foreach dir,$(SRC_DIR),$(wildcard $(dir)/*.c))

OBJS=$(patsubst %.c,$(BUILD_DIR)/%.o,$(notdir $(SOURCES)))
VPATH=$(SRC_DIR)




$(BUILD_DIR)/$(TARGET):$(OBJS)
        $(CC) $^ -o $@


#main.o:main.c
#       $(CC) -c main.c -o main.o
#mp3.o:mp3.c
#       $(CC) -c mp3.c -o mp3.o

$(BUILD_DIR)/%.o:%.c $(INCLUDES) | creat_build
        $(CC) -c $< -o $@ $(CFLAGS)

.PHONY:clean creat_build

clean:                                                                                                                                                                                                      
        rm -r $(BUILD_DIR)
creat_build:
        mkdir -p $(BUILD_DIR)

 

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

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

相关文章

SpringBoot + Vue 简单前后端分离项目的增删改查

SpringBoot 是提供一种快速整合的方式 文章目录 前期准备新建数据库新建项目config 配置包application.yml 后端业务开发po 类mapper 接口service 接口service 实现类controller 类 测试增加数据测试删除数据测试修改数据测试查新数据测试 前端页面开发查询页面删除功能添加页面…

2023年国内低代码平台盘点:TOP 10活跃领军者,助力企业智能应用快速构建

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

实战实例 | 郑航无人驾驶航空器系统工程专业综合实验平台建设项目

郑州航空工业管理学院 无人驾驶航空器系统工程专业综合实验平台建设项目 关键词&#xff1a;飞控开发、仿真训练、组装调试、无人机集群 解决方案&#xff1a;多智能体协同创新实验室解决方案 | 项目背景 无人机行业是当前发展迅速、技术综合性强和应用前景好的朝阳行业。基…

CCLINK IE FIELD BASIC转MODBUS-TCP网关cclink与以太网的区别

协议的不同&#xff0c;数据读取困难&#xff0c;这是很多生产管理系统的难题。但是现在&#xff0c;捷米JM-CCLKIE-TCP通讯网关&#xff0c;让这个问题变得非常简单。这款通讯网关可以将各种MODBUS-TCP设备接入到CCLINK IE FIELD BASIC网络中&#xff0c;连接到MODBUS-TCP总线…

echo用法、linxu课堂练习题、作业题

一、课堂练习 练习一&#xff1a; 4、普通用户修改密码&#xff1a; root修改密码&#xff1a; 5、修改主机名&#xff1a;hostnamectl hostname 主机名 查看&#xff1a;hostnamectl或者cat etc/hostname 练习二&#xff1a; 1、 mkdir /root/html touch /root/html/index.…

基于摄影测量的数字孪生建设

在这篇博文中&#xff0c;我们将了解如何使用无人机拍摄的照片在数字孪生中创建现实世界环境的 3D 模型。 数字孪生是物理系统的虚拟表示&#xff0c;定期更新数据以模仿其所表示的资产的结构、状态和行为。 数字孪生可以通过在单一管理平台中连接多个数据源并提供可行的见解来…

十一、结合数字孪生与时间技术进行多维分析设计与实施

大数据可视化中心以主题为分析对象,选择业务分类下的某个主题,可以在数据面板中展示其二维图表,在地图中标记其空间分布,并叠加其相应的二维或三维图层。 1、界面设计 其主界面设计详上图,各部分功能介绍如下: 1.1、主题与图层面板,从上到下,从左到右分别是: ①折…

Linux--core dump打开的情况下,运行下面的代码,会发生什么?

代码&#xff1a; #include <iostream> #include <signal.h> #include <unistd.h>using namespace std;void catchSig(int signum) {cout<< "进程捕捉到了一个信号&#xff0c;正在处理中&#xff1a; "<< signum << " p…

基于Spring Boot的招聘网站的设计与实现(Java+spring boot+MySQL)

获取源码或者论文请私信博主 演示视频&#xff1a; 基于Spring Boot的招聘网站的设计与实现&#xff08;Javaspring bootMySQL&#xff09; 使用技术&#xff1a; 前端&#xff1a;html css javascript jQuery ajax thymeleaf 微信小程序 后端&#xff1a;Java springboot框…

Linux 进程间通信, 管道

文章目录 前言一、常见的进程间通信方式二、如何实现管道通信三、示例代码解析四、管道的读写行为总结 前言 在多进程编程中&#xff0c;进程间通信&#xff08;Inter-Process Communication&#xff0c;IPC&#xff09;是一种重要的技术手段&#xff0c;它使得不同进程可以安…

函数的声明和定义

1、函数声明 //告诉编译器有一个函数叫什么&#xff0c;参数是什么&#xff0c;返回类型是什么。但是具体是不是存在&#xff0c;函数声明决定不了。 //函数的声明一般出现在函数的使用之前。要满足先声明后使用。 //函数的声明一般要放在头文件中的。 2、函数的定义 //函数…

Linux(进程间通信详解)

进程间通信&#xff0c;顾名思义&#xff0c;就是进程与进程之间互通信交流&#xff0c;OS保证了各进程之间相互独立&#xff0c;但这不意味着进程与进程之间就互相隔离开&#xff0c;在不少的情况下&#xff0c;进程之间需要相互配合共同完成某项6任务&#xff0c;这就要求各进…

8月9日算法刷题【6道题】

8月9日算法刷题 一、排序1. 成绩排序&#xff08;清华大学考研机试题&#xff09;考点&#xff1a;结构体排序在结构体中定义排序使用比较器定义排序 注意问题&#xff1a;需要处理 值相等时 先后顺序 2. 成绩排序2( 清华大学考研机试题 )1. 从尾到头打印链表本题考点栈 2. 在O…

hgdbdevelop弹窗无法使用

瀚高数据库 目录 环境 文档用途 详细信息 环境 系统平台&#xff1a;Microsoft Windows (64-bit) 10 版本&#xff1a;4.5 文档用途 解决双击exe程序出现弹窗&#xff0c;点击Disable Modules and Continue没反应 详细信息 1.打开管理工具exe程序&#xff0c;出现弹窗如下图&…

【运维小能手】交换机二层环路问题如何处理

1 网络业务故障&#xff0c;如何确认存在环路&#xff1f; 网络业务故障后&#xff0c;如发生二层环路&#xff0c;通常会存端口流量数据风暴和反复大量的MAC漂移现象。因此&#xff0c;在骨干链路所在的节点&#xff0c;通过如下三步操作&#xff1a; 图1&#xff1a;环…

向量检索在大模型应用场景的技术和实践

一、向量检索应用简介 向量是多维数学空间里的一个点&#xff0c;在各维度上的坐标的一串数字。这个点就是来源于真实世界的物体进行数字化之后在数学空间的投影。那么不同点之间有一个数学关系&#xff0c;就是距离&#xff0c;距离远近就代表两个物体的相似程度。 非结构化数…

Semantic and Syntactic Enhanced Aspect Sentiment Triplet Extraction

创新点 图-序列双重表示: 通过将句子中的语义和句法关系表示为图&#xff0c;并使用图神经网络&#xff08;GNNs&#xff09;进行编码&#xff0c;同时保留原始句子的顺序信息&#xff0c;S3E2能够更精确地捕捉三元组元素之间的复杂关系。许多传统方法可能只依赖于线性或浅层表…

分支和循环语句(1)(C语言)

目录 什么是语句&#xff1f; 分支语句&#xff08;选择结构&#xff09; if语句 悬空else if书写形式的对比 switch语句 在switch语句中的 break default子句 循环语句 while循环 while语句中的break和continue for循环 语法 break和continue在for循环中 for语句和…

vue3 vite gzip

1、首先前端项目里安装 vite-plugin-compression 插件 yarn add vite-plugin-compression 2、在 vite.config.js 中 import vue from vitejs/plugin-vue import { defineConfig } from vite import compressPlugin from vite-plugin-compressionexport default defineConf…

【TI毫米波雷达笔记】sdk传参时的type避坑

【TI毫米波雷达笔记】sdk传参时的type避坑 这个函数要传一个结构体进去 然后结构体里面有个adcoutcfg结构体变量 adcoutcfg结构体里面共有三个变量 一个adcbitformat结构体 另外两保留 点开adcbitformat结构体发现是个32位段 一共四级结构体 那么请问 为什么adcoutcfg变量不直…