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

[Linux_IMX6ULL应用开发]-Makefile

目录

Makefile的规则

Makefile的语法

通配符

假想目标

变量

Makefile的函数

foreach函数

filter和filter-out

wildcard

patsubst

修改头文件无法make解决

CFLAGS


Makefile的规则

当我们在使用gcc进行编译链接的时候,我们需要手动在shell窗口键入命令。比如说我们目前有两个c文件,想要对它们进行编译生成test可执行文件

gcc -o test a.c b.c

通过执行如上代码,我们可以生成一个test可执行文件

那么问题就来了,如果存在几千个文件同时需要进行编译链接的话,难道也需要这样一个个键入命令生成吗,所以,我们在嵌入式系统中,使用的是makefile进行批处理

同时,如上代码还有一个缺点,那就是如果修改了a.c文件,那么执行如上命令的时候,即使b.c文件没有动过,也会被重新编译一次,如果文件很多,这是很消耗时间的

Makefile的最核心的规则如下

基于这个核心规则,把如下的命令转化为makefile

gcc -o test a.c b.c
#test可执行文件依赖a.o b.o
test : a.o b.ogcc -o test a.o b.o#a.o依赖a.c
a.o : a.c#编译生成a.o但是不链接gcc -c -o a.o a.c#b.o依赖b.c
b.o : b.c#编译生成b.o但是不链接gcc -c -o b.o b.c

新建一个Makefile文件,然后键入如上内容,然后直接输入命令make就可以完成编译和链接了


Makefile的语法

通配符

原先通过a.o和b.o链接生成test可执行文件的makefile过于的繁琐,因为每有一个文件,都要在下方新添加一个编译规则

test : a.o b.ogcc -o $@ $^
%.o : %.cgcc -c -o $@ $<

假想目标

当我们需要通过makefile一键清除生成的文件和目标的时候,可以添加一个clean

test : a.o b.ogcc -o $@ $^
%.o : %.cgcc -c -o $@ $<
clean:rm *.o test

删除test可执行文件以及所有.o后缀的文件

由此可知,如果make没有带目标名,那么它是生成规则的第一个目标,比如说只键入make,那么它就是执行第一个目标,生成test文件,如果是make clean,那么就是执行clean处的操作

由于makefile执行的条件是,目标文件不存在或者依赖文件比目标文件新,如果存在如下情况,那么make clean就无法正常执行

创建了一个名为clean的文件,makefile会判断clean文件已经存在,并且没有依赖比目标文件新,则无法正常执行,此时如果有这种情况那么我们就需要使用假想目标

假想目标(有时也称为伪目标或标签)不代表一个真正的文件名。它更多的是作为一个目标集合或动作,用于在执行make命令时指定并执行其所在规则定义的命令。假想目标不生成文件,只是作为几个命令组成特殊规则的名称。可以理解为,假想目标只执行命令,不是用于生成文件

test : a.o b.ogcc -o $@ $^
%.o : %.cgcc -c -o $@ $<
clean:rm *.o test
.PHONY : clean

添加最后一行后,便可以正常执行make clean,即使存在clean文件


变量

:=         为即时变量,假如 A:= C ,那么A就是执行到这一句的时候C的值,后续不管C在怎么改变,A都不会因为C的改变而改变。它可以确保变量的值在赋值时就是确定的,并且在整个Makefile中保持不变,除非被重新赋值。

=        为延时变量,假如 A=C,那么直到结束,C不管改变多少次,C最终是多少A就是多少

?=      延时变量如果是第1次定义才起效,如果在前面该变量已定义则忽略这句

+=      附加


Makefile的函数

foreach函数

$(foreach var,list,text)

类似与for循环,把list中的字符串通过空格划分,然后执行text中的表达式,然后赋值给var,直到list结束

输出结果为a.o b.o c.o,分出的第一个字符为a,执行增加.o的操作,赋值给f,以此叠加直到list也就是A中无法在通过空格划分出字符

filter和filter-out

#在text中取出符合pattern的值
$(filter pattern...,text)#在text中取出不符合pattern的值
$(filter-out pattern...,text)

示例如下

文件夹中存在如下不同格式的文件,如何筛选出只包含.c为后缀的文件呢

通过执行shell命令ls列举出所有文件,然后赋值给C,然后使用filter函数,在C变量中,把满足以c为后缀的变量赋值给D,就可以获得只以c为后缀的文件了

如果我们在这里使用的是filter-out函数,那就是排除以.c为后缀的文件,那么获得的就是

D = a.d b.d c.d d.d了 

wildcard

此函数可以从该文件夹目录中取出指定的文件的格式

#pattern定义了文件名格式$(wildcard pattern)

执行的结果如下

patsubst

$(patsubst pattern,replacement,text)

把text中的所有满足pattern的内容替换为replacement的内容,其他的内容不会进行改变,除了满足的变量进行操作外,不满足的也不会被剔除

执行的结果如下


修改头文件无法make解决

当我们在使用makefile的时候,可能会存在如下的问题

假设我有如下三个文件,a.c b.c c.c ,c.c文件包含了c.h这个头文件,当我们make生成了可执行文件之后,我们修改头文件,然后打算重新编译的时候会被告知无法重新进行编译,因为,我们的makefile中没有文件依赖h文件生成

那么我们如何解决这个问题呢,这里就需要用到依赖文件,通过如下makefile,即使只是头文件被修改了,重新进行make编译也是可以编译的,因为这里我们使用了依赖文件,头文件被更改了,依赖文件也会被更改

OBJ = a.o b.o c.o
DEPEND_FILE:=$(patsubst %,.%.d,$(OBJ))
DEPEND_FILE:=$(wildcard $(DEPEND_FILE))test : $(OBJ)gcc -o $@ $^@echo depend_file = $(DEPEND_FILE)ifneq ($(DEPEND_FILE),)
include $(DEPEND_FILE)
endif%.o : %.cgcc -c -o $@ $< -MD -MF .$@.dclean_d:rm $(DEPEND_FILE)clean:rm *.o test

总的来说,就是通过获取对应文件的依赖文件,并包含进makefile当中,只要包含进去,makefile会自动识别出当哪些头文件发生变化的时候,需要对哪些文件进行重新编译


CFLAGS

CFLAGS可以理解为一个宏,可以再上面添加各种的编译参数

一般来说,项目的文件夹是这样的结构

h文件是单独放在一个文件夹里面的,那么当我们在包含此头文件的时候,就不能使用""而是应该使用<>,那么,我们就要在编译参数里面指定头文件的路径

相关文章:

  • Spark-Scala语言实战(1)
  • 前端跨平台开发框架:简化多端开发的利器
  • 【深度学习】手动实现RNN循环神经网络
  • C#-面向对象基本概念
  • C语言课后作业 20 题+考研上机应用题
  • Python爬虫获取接口数据
  • STM32CubeIDE基础学习-EXTI外部中断实验
  • 如何在代理的IP被封后立刻换下一个IP继续任务
  • 稳定出刊检索:2024年财务会计与法律金融国际学术会议(ICFALF 2024)
  • 深入浅出前端本地储存(1)
  • 数据结构的概念大合集04(队列)
  • Go——切片
  • C语言之快速排序
  • 蓝桥杯之动态规划冲刺
  • matlab 混沌系统李雅普洛夫指数谱相图分岔图和庞加莱界面
  • Android系统模拟器绘制实现概述
  • CentOS从零开始部署Nodejs项目
  • ECMAScript入门(七)--Module语法
  • Elasticsearch 参考指南(升级前重新索引)
  • HTTP 简介
  • Python学习之路13-记分
  • rc-form之最单纯情况
  • Terraform入门 - 3. 变更基础设施
  • 分布式任务队列Celery
  • 力扣(LeetCode)357
  • 腾讯优测优分享 | Android碎片化问题小结——关于闪光灯的那些事儿
  • 微信小程序填坑清单
  • 我是如何设计 Upload 上传组件的
  • ​RecSys 2022 | 面向人岗匹配的双向选择偏好建模
  • ###STL(标准模板库)
  • $forceUpdate()函数
  • (2.2w字)前端单元测试之Jest详解篇
  • (day6) 319. 灯泡开关
  • (js)循环条件满足时终止循环
  • (二)【Jmeter】专栏实战项目靶场drupal部署
  • (二)什么是Vite——Vite 和 Webpack 区别(冷启动)
  • (附源码)springboot高校宿舍交电费系统 毕业设计031552
  • (附源码)计算机毕业设计SSM教师教学质量评价系统
  • (官网安装) 基于CentOS 7安装MangoDB和MangoDB Shell
  • (六)vue-router+UI组件库
  • (七)Java对象在Hibernate持久化层的状态
  • (三)c52学习之旅-点亮LED灯
  • (四)c52学习之旅-流水LED灯
  • (一)Mocha源码阅读: 项目结构及命令行启动
  • (转)详解PHP处理密码的几种方式
  • ******之网络***——物理***
  • ./和../以及/和~之间的区别
  • .net 受管制代码
  • .net打印*三角形
  • @Bean注解详解
  • [ Linux Audio 篇 ] 音频开发入门基础知识
  • [2013][note]通过石墨烯调谐用于开关、传感的动态可重构Fano超——
  • [20171113]修改表结构删除列相关问题4.txt
  • [2544]最短路 (两种算法)(HDU)
  • [28期] lamp兄弟连28期学员手册,请大家务必看一下