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

这篇具有很好参考价值的文章主要介绍了嵌入式Linux驱动开发系列六:Makefile。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Makefile是什么?

gcc hello.c -o hello

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

make工具和Makefile

make和Makefile是什么关系?

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

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

必须要学精Makefile吗?

嵌入式Linux驱动开发系列六:Makefile,linux,驱动开发,运维

怎么学习Makefile?

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

 嵌入式Linux驱动开发系列六:Makefile,linux,驱动开发,运维

嵌入式Linux驱动开发系列六:Makefile,linux,驱动开发,运维

嵌入式Linux驱动开发系列六:Makefile,linux,驱动开发,运维

嵌入式Linux驱动开发系列六:Makefile,linux,驱动开发,运维

嵌入式Linux驱动开发系列六:Makefile,linux,驱动开发,运维

 嵌入式Linux驱动开发系列六:Makefile,linux,驱动开发,运维

嵌入式Linux驱动开发系列六:Makefile,linux,驱动开发,运维

嵌入式Linux驱动开发系列六:Makefile,linux,驱动开发,运维

嵌入式Linux驱动开发系列六:Makefile,linux,驱动开发,运维

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 工具,该目标不对应任何文件,而是需要执行一些特定的操作

 嵌入式Linux驱动开发系列六:Makefile,linux,驱动开发,运维

 嵌入式Linux驱动开发系列六:Makefile,linux,驱动开发,运维

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

嵌入式Linux驱动开发系列六:Makefile,linux,驱动开发,运维

 也就是说,我们的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的变量、模式匹配

变量

系统变量

嵌入式Linux驱动开发系列六:Makefile,linux,驱动开发,运维

自定义变量

=,延迟赋值

嵌入式Linux驱动开发系列六:Makefile,linux,驱动开发,运维

:=, 立即赋值

嵌入式Linux驱动开发系列六:Makefile,linux,驱动开发,运维

?=,空赋值(像const)

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

嵌入式Linux驱动开发系列六:Makefile,linux,驱动开发,运维

+=,追加赋值

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

 嵌入式Linux驱动开发系列六:Makefile,linux,驱动开发,运维

自动化变量

$<:第一个依赖文件

嵌入式Linux驱动开发系列六:Makefile,linux,驱动开发,运维

$^:全部的依赖文件

嵌入式Linux驱动开发系列六:Makefile,linux,驱动开发,运维

$@:目标

 嵌入式Linux驱动开发系列六:Makefile,linux,驱动开发,运维

优化

嵌入式Linux驱动开发系列六:Makefile,linux,驱动开发,运维

嵌入式Linux驱动开发系列六:Makefile,linux,驱动开发,运维

模式匹配

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

shell:*通配符

嵌入式Linux驱动开发系列六:Makefile,linux,驱动开发,运维

默认规则

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

嵌入式Linux驱动开发系列六:Makefile,linux,驱动开发,运维

Makefile条件分支

条件分支
如果相等
ifeq (var1,var2)
...
else
...
endif
ifneq (var1,var2)
...
else
...
endif

嵌入式Linux驱动开发系列六:Makefile,linux,驱动开发,运维

Makefile的常用函数

Makefie官方手册:

GNU Make Manual - GNU Project - Free Software Foundation

patsubst:

 文本匹配成新的模式

嵌入式Linux驱动开发系列六:Makefile,linux,驱动开发,运维

notdir:

嵌入式Linux驱动开发系列六:Makefile,linux,驱动开发,运维

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

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

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

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

嵌入式Linux驱动开发系列六:Makefile,linux,驱动开发,运维

wildcard:

嵌入式Linux驱动开发系列六:Makefile,linux,驱动开发,运维

示例:

(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)

嵌入式Linux驱动开发系列六:Makefile,linux,驱动开发,运维

 文章来源地址https://www.toymoban.com/news/detail-637249.html

到了这里,关于嵌入式Linux驱动开发系列六:Makefile的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 正点原子嵌入式linux驱动开发——Linux CAN驱动

    CAN是目前应用非常广泛的现场总线之一,主要应用于汽车电子和工业领域 ,尤其是汽车领域,汽车上大量的传感器与模块都是通过CAN总线连接起来的。CAN总线目前是自动化领域发展的热点技术之一,由于其高可靠性,CAN总线目前广泛的应用于工业自动化、船舶、汽车、医疗和

    2024年02月06日
    浏览(78)
  • 正点原子嵌入式linux驱动开发——Linux WIFI驱动

    WIFI的使用已经很常见了,手机、平板、汽车等等,虽然可以使用有线网络,但是有时候很多设备存在布线困难的情况,此时WIFI就是一个不错的选择。 正点原子STM32MP1开发板支持USB和SDIO这两种接口的WIFI ,本章就来学习一下如何在STM32MP1开发板上使用USB和SDIO这两种WIFI。 正点原

    2024年02月05日
    浏览(71)
  • 嵌入式Linux驱动开发——常见框架梳理

    本文主要介绍了Linux驱动开发中一些常用的驱动框架,platform、input、iic、spi等,硬件平台使用的是正点原子的imx6ull开发板。 不管什么框架最后都是要追溯到配置IO的电气属性和复用功能 如果要使用外部中断,设备树节点中还需添加相关信息,什么边沿触发 1:module_init和mod

    2024年02月15日
    浏览(66)
  • 嵌入式Linux驱动开发 04:基于设备树的驱动开发

    前面文章 《嵌入式Linux驱动开发 03:平台(platform)总线驱动模型》 引入了资源和驱动分离的概念,这篇文章将在前面基础上更进一步,引入设备树的概念。 在平台总线驱动模型中资源和驱动已经从逻辑上和代码组织上进行了分离,但每次调整资源还是会涉及到内核,所以现

    2024年02月16日
    浏览(69)
  • 正点原子嵌入式linux驱动开发——Linux 网络设备驱动

    网络驱动是linux里面驱动三巨头之一 ,linux下的网络功能非常强大,嵌入式linux中也常常用到网络功能。前面已经讲过了字符设备驱动和块设备驱动,本章就来学习一下linux里面的 网络设备驱动 。 本次笔记中讨论的都是有线网络! 提起网络,一般想到的硬件就是“网卡”。在

    2024年01月17日
    浏览(70)
  • 【嵌入式Linux驱动】驱动开发调试相关的关系记录

    https://www.processon.com/mindmap/64537772b546c76a2f37bd2f

    2024年02月02日
    浏览(56)
  • 嵌入式Linux驱动开发(LCD屏幕专题)(三)

    1. 硬件相关的操作 LCD驱动程序的核心就是: 分配fb_info 设置fb_info 注册fb_info 硬件相关的设置 硬件相关的设置又可以分为3部分: 引脚设置 时钟设置 LCD控制器设置 2. 在设备树里指定LCD参数 3. 编程 3.1 从设备树获得参数 时序参数、引脚极性等信息,都被保存在一个display_timi

    2024年02月09日
    浏览(62)
  • 嵌入式Linux驱动开发(LCD屏幕专题)(一)

    总的分辨率是 yres*xres。 以下三种方式表示颜色 每个屏幕都有一个内存(framebuffer)如下图,内存中每块数据对用屏幕上的一个像素点,设置好LCD后,只需把颜色数据写入framebuffer即可。 Framebuffer驱动属于字符设备驱动,我们先说字符设备驱动框架如下图: 驱动主设备号 构造

    2024年02月09日
    浏览(61)
  • 嵌入式linux驱动开发篇之设备树

    设备树(Device Tree)是一种用于描述嵌入式系统硬件组件及其连接关系的数据结构。它被广泛用于嵌入式 Linux 系统,尤其是针对使用多种不同架构和平台的嵌入式系统。它是一种与硬件描述相关的中间表示形式,将硬件信息抽象成一种可移植的格式,使得操作系统和引导加载

    2024年02月22日
    浏览(68)
  • 嵌入式Linux驱动开发 02:将驱动程序添加到内核中

    在上一篇文章 《嵌入式Linux驱动开发 01:基础开发与使用》 中我们已经实现了最基础的驱动功能。在那篇文章中我们的驱动代码是独立于内核代码存放的,并且我们的驱动编译后也是一个独立的模块。在实际使用中将驱动代码放在内核代码中,并将驱动编译到内核中也是比较

    2023年04月09日
    浏览(73)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包