当前位置: 首页 > news >正文

【Linux】Makefile

Makefile常用用法介绍。

部分图片和经验来源于网络,还有正点原子的Linux驱动开发教程,若有侵权麻烦联系我删除,主要是做笔记的时候忘记写来源了,做完笔记很久才写博客。

 专栏目录:记录自己的嵌入式学习之路-CSDN博客


1    简单定义

        Makefile是一个包含了一系列指令的文件,这些指令定义了如何编译和链接程序。Makefile被make命令使用,make是一个构建自动化工具,它根据Makefile中定义的规则来决定哪些文件需要重新编译。


2    基本结构

        一个基本的Makefile包含以下部分:

        (1)    目标(Targets):通常是文件名,表示要生成的文件。

        (2)    依赖(Dependencies):目标文件依赖的文件列表。

        (3)    命令(Commands):生成目标文件需要执行的命令序列。

        

这个Makefile做了以下几件事:

  • 定义了一个名为all的伪目标,它依赖于hello目标。
  • hello目标依赖于hello.o文件,并且定义了如何从hello.o生成hello可执行文件。
  • hello.o目标依赖于hello.c源文件,并且定义了如何从hello.c编译生成hello.o对象文件。

编译时使用make all命令,这个命令告诉make去查找Makefile,并执行all目标下的指令。make会检查文件的修改时间,如果hello.o或hello.c被修改过,它会重新编译这些文件。


3    MAKEFILE中的变量

3.1    变量的赋值

(1)    = 赋值

        = 赋值相当地址赋值,每次拿出来的值都以最新的值为准,如下图打印的值应该为zuozhongkai。

        

(2)    := 赋值

        := 赋值就是正常的赋值,以赋值时候的值为准,如下图的结果就是zzk。

        

(3)    ?= 赋值

        curname ?= zuozhongkai

        上述代码的意思就是,如果变量curname前面没有被赋值,那么此变量就是“zuozhongkai”,如果前面已经赋过值了,那么就使用前面赋的值。

(4)    += 追加赋值

3.2    变量的引用

        在Makefile中,变量通过$(变量名)来引用。

        

3.3    自动化变量

        

3.4    CC变量

        CC变量存储编译器的名称,值通常为gcc。

        

3.5    CFLAGS变量

        CFLAGS变量用于存储编译选项。

        


4    模式规则

        目标中的“%”表示对文件名的匹配,“%”表示长度任意的非空字符串,比如“%.c”就是所有的以.c结尾的文件,类似与通配符,a.%.c就表示以a.开头,以.c结束的所有文件。

        当“%”出现在目标中的时候,目标中“%”所代表的值决定了依赖中的“%”值。

        模式规则基本都要配合自动化变量才能够使用。因为文件名一直在变化。


5    伪目标

        若有非编译的命令,如clean、all等,最好将其声明为伪目标,语法如下:

        .PHONY : clean

        使用伪目标可以避免文件中有同名文件时出现的问题:当目录中有一个文件就叫clean,那么如果没有声明伪目标,clean下的命令就因为clean没有依赖文件变化而不运行。加了伪目标就可以保证clean一定运行。


6    条件语句

        Makefile中的条件语句有ifeq、ifneq、ifdef、ifndef。其中ifeq用来比较两值是否相等,有n的就是比较其是否不相等。

        


7    Kbuild

        Kbuild是Linux内核的官方构建系统,它基于GNU Make。Kbuild通过预定义一系列的变量和目标,使得内核的编译和模块的构建变得简单。

7.1    核心变量

(1)    obj-y:用于定义编译进内核的目标文件(.o文件)。如果一个文件被添加到obj-y,它将被编译并链接到最终的内核映像中。

(2)    obj-m:用于定义编译成模块的目标文件。这些文件将被编译成.ko文件,可以作为模块加载到内核中。

(3)    <user_prog>-y或<user_prog>-objs:表示<user_prog>的依赖为后面的内容。如:

obj-m := led.o
led-y := hello.o leddriver.o

上面的语句表示最终要编译led.ko这个模块,而这个模块由hello.c和leddriver.c两个编译出来。实际上led.c反而是不需要存在的。

注:要想其编译一些别的文件夹下的源文件,可以加上路径,例如:

MODULE_NAME := ../../out/adc
KERN_DIR := /home/<user_name>/Source/kernel_source_emmc_flash
obj-m := $(MODULE_NAME).o
$(MODULE_NAME)-objs := adc_driver.o ../Utilities/utility.o

7.2    make过程中的常用参数

        -C <path>:表示在编译前先将当前工作目录改到path路径,一般path都是内核源码的路径。我的理解是相当于跳转到内核源码里面,引用它里面的Makefile。

        M=<path>:这个表示要编译的模块的源码,就是说告诉make,我要编译的模块的源码是path。若不给出O=<path>,那么默认编译得到的.o/.ko文件将被放到M指定的模块源码路径中。

        O=<path>:指定输出文件的路径。

        module:make命令后加上module表示将Makefile文件中obj-m的部分编译了,同时编译那些依赖于obj-m的obj-y文件,不依赖于obj-m的不编译,应该是这样。要是直接执行make,不加module的话只会编译obj-y的目标文件。

        ARCH=<arch>:指定目标平台的架构,arch为arm时说明目标架构为arm。

        CROSS_COMPILE:交叉编译器的前缀,指定了使用哪些交叉编译器工具链。

其实ARCHCROSS_COMPILE两个都可以直接在Makefile中直接指定,而不是在使用make命令的时候指定。

其实,无论是O=、M=、ARCH=还是CROSS_COMPILE=,本质上只是在命令行中指定Makefile文件中指定变量的值而已,和在Makefile文件中修改区别不大,但是Makefile可以通过ifeq ("$(origin O)", "command line")来判断这个值是否来自于命令行的指定。


8    Makefile技巧

8.1    无视错误继续执行

        若某些命令哪怕错误也要继续执行下面的任务,就在这个命令前加上“-”,如:

all:-make cleanecho “无论前面是否执行成功都会输出这行”

8.2    利用命令的输出

        $(shell <cmd>)

        这样得出来的就是命令的输出值,就像$(shell pwd)得到的就是执行pwd的结果,即当前路径。

8.3    三元if函数

        $(if <condition>, <then-part>, <else-part>)

8.4    替换函数

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

        此函数用于在 text中查找符合 pattern的部分,如果匹配的话就用 replacement替换掉。pattern是可以包含通配符“%”,如果 replacement 中也包含通配符“%”,那么 replacement 中的这个“%”将是 pattern中的那个“%”所代表的字符串。

        【注意】:千万不要在任何,后面加空格,会被视为内容的一部分。

8.5    数值的硬拼接

        CUR_DIR := $(shell pwd)/..

        相当于给路径加了个/..,需要注意的是/前面千万不能有空格,不然就相当于拼接多了一个空格。

8.6    数值的项目增加

        PHONY += AAA

        PHONY += BBB

        就是将不同的项目合起来在一起,最后PHONY的值就是“AAA BBB”

8.7    项目Make编译的常见清理命令

(1)    make clean

        这个目标通常用于删除大多数生成的文件,但保留一些基础文件,以便可以快速重新构建项目,特别是外部模块。

        通常保留的文件包括配置脚本生成的配置文件,因为重新生成这些文件可能需要用户输入或复杂的检测过程。

        make clean 旨在减少构建准备时间,同时避免删除需要额外工作才能重新生成的文件。

(2)    make mrproper

        这个目标删除当前配置的所有生成文件,包括make clean保留的文件。

        mrproper 通常删除所有由配置过程生成的文件,如配置日志和 config.h 文件,这意味着你需要重新运行配置脚本来重新生成这些文件。

        这个目标用于确保构建过程从完全干净的状态开始,没有任何旧的构建生成的文件。

(3)    make distclean

        这个目标除了执行make mrproper的操作外,还会删除额外的文件,如编辑器备份文件、补丁应用后的遗留文件等。

        distclean 旨在确保分发包(tarball)中的文件在提取后,构建环境与原始开发者的构建环境完全一致。

这个目标用于维护一个干净的源代码树,准备进行版本控制更新或分发源代码。


9    其他注意事项

        命令列表中的每条命令必须以TAB键开始,不能使用空格!


10   其他注意事项

        一些优秀的Makefile相关博客:

linux内核模块编译makefile - 裸睡的猪 - 博客园https://www.cnblogs.com/ggzhangxiaochao/p/13358941.htmlmake命令的参数选项(执行make时可以添加哪些选项)_make 参数-CSDN博客https://blog.csdn.net/oqqHuTu12345678/article/details/125630342

相关文章:

  • AI大模型基础设施:主流的几款开源AI大语言模型的本地部署成本
  • kafka学习笔记(四、生产者(客户端)深入研究(二)——消费者协调器与_consumer_offsets剖析)
  • windows系统搭建自己的ftp服务器,保姆级教程(用户验证+无验证)
  • 简单的Qwen3的本地部署、分析与常见报错
  • CSS学习笔记14——移动端相关知识(rem,媒体查询,less)
  • RDMA高性能网络通信实践
  • 计算机视觉(CV)技术的优势和挑战(本片为InsCode)
  • 【分享】deepseek 超强ai助手 1.1.8最新版 不卡顿
  • jenkins 远程执行 定时 执行shell
  • SQL数据库系统全解析:从入门到实践
  • H7-TOOL固件2.29发布,支持各种第3方串口桥接功能,RTT自动重连,CAN/RTT/UART窗口独立同时刷新,增加多款脱机烧录(2025-04-30)
  • 多模态大语言模型arxiv论文略读(五十三)
  • Discover SubtitleMaster, the Ultimate Translation Tool for Creators!
  • Vue之脚手架与组件化开发
  • Linux 命令如何同时支持文件参数与管道输入?
  • 时序建模演进之路:从 MLP、RNN 到 LSTM 与 GRU
  • 【Leetcode 每日一题】2071. 你可以安排的最多任务数目
  • 使用Delphi 和 CrossVcl 开发基于VCL的 macOS 和 Linux 应用程序简介
  • C#中的LINQ:简化数据查询与操作
  • Rust多线程性能优化:打破Arc+锁的瓶颈,效率提升10倍
  • “三桶油”一季度净赚966亿元:业绩分化加剧,有人欢喜有人愁
  • 美乌矿产协议签署被曝“临门一脚”时生变,美方提附加条件
  • 八成盈利,2024年沪市主板公司实现净利润4.35万亿元
  • 《求是》杂志发表习近平总书记重要文章《激励新时代青年在中国式现代化建设中挺膺担当》
  • 美国通过《删除法案》:打击未经同意发布他人私密图像,包括“深度伪造”
  • 直播电商行业代表呼吁:携手并肩伸出援手助力外贸企业攻坚克难