自动化标准Makefile与lds

news/2024/4/30 2:45:52

makefile的自动化,需要使用变量,以及自动变量。
实行命令行与参数的分离。

命令行只与变量打交道,而变量则携带不同的参数,这样,通过修改变量,命令的执行结果不同。
可以简单理解为,命令行是个函数,变量则是传递给函数的参数列表。
对参数列表的不同赋值,调用函数,返回的结果是不同的。

++++++++++++++++++++++++++++++++
objs变量。
用于收集所需的依赖目标,常见的是收集.o文件。

objs = start.o main.o ledc.bin : $(objs)

主目标。
BIN文件,依赖于一个O文件列表,这个O文件列表,由一个变量,即objs来收集。

CROSS = arm-linux-gnueabihf
ledc.bin : $(objs)$(CROSS)-ld -Timx6u.lds $^ -o ledc.elf $(CROSS)-objcopy -O binary -S ledc.elf $@$(CROSS)-objdump -D -m arm ledc.elf > ledc.dis

GCC工具的前缀,由一个变量,即CROSS来描述。如果需要用不同的GCC工具,则只需要修改变量即可,不需要动命令行。
这里面用到了自动化变量。
自动化变量,是make的解析工具解析出的字符串。
解析工具的输入源,是当前所处的规则的目标集,包括当前目标和依赖目标集。
$@,是当前目标集,上述例子里,当前目标集只有一个元素,它是ledc.bin这个目标。
$^,是依赖目标集中的所有目标。即全依赖集,all depend obj

另外,还有一些,如
$<,是依赖目标集中的首元,
$?,是依赖目标集的子集,它表示较新依赖目标集,全依赖集中,所有比当前目标较新的依赖目标,都收集到这个依赖目标集中去。

+++++++++++++++++++++++++++++
通配规则。
通配符%,
遍历展开成多个规则。

%.o : %.c$(CROSS)-gcc -Wall -nostdlib -c  -O2 -o $@ $<
%.o : %.S$(CROSS)-gcc -Wall -nostdlib -c  -O2 -o $@ $<

make工具,遍历检查依赖目标集,
如果发现某个目标,其表达式符合后缀为.o这个特征,且其名称,有对应的后缀为.c的文件,则为其生成一个对应的规则。
如果发现某个目标,其表达式符合后缀为.o这个特征,且其名称,有对应的后缀为.S的文件,则为其生成一个对应的规则。

++++++++++++++++++++++++++++++++++++++
清除clean。

clean:rm -rf *.o ledc.bin ledc.elf ledc.dis

+++++++++++++++++++++++++++++++++++++
链接脚本LDS。

SECTIONS{. = 0x87800000;.text :{start.o*(.text)}.rodata ALIGN(4) : {*(.rodata*)}.data ALIGN(4) : {*(.data)}__bss_start=.;.bss ALIGN(4) : {*(.bss) *(COMMON)}__bss_end=.;
}

"."表示current address counter。默认初始值是0。可以被赋值,也可以赋值给其他Label。
随着描述块的使用,CAC会自动向前计数。
LDS中,赋值语句,用分号结束。
上例中,
首先对CAC赋值,使其偏移到0x87800000地址上。
然后,描述了一个从该地址开始部署的代码段。
.text : {}
用冒号分隔,前面是section的命名,后面用花括号,详细描述section内部的布局部署。
上例中,
指定了从start.o中抽取.text段,作为首元使用。

++++++++++++++++++++++++++++++++++++
Kernel风格的makefile。

CROSS_COMPILE ?= arm-linux-gnueabihf-
NAME		  ?= ledcCC 			:= $(CROSS_COMPILE)gcc
LD 			:= $(CROSS_COMPILE)ld 
OBJCOPY 	:= $(CROSS_COMPILE)objcopy 
OBJDUMP   	:= $(CROSS_COMPILE)objdump 

通过两层变量定义,归一化GCC工具集的名称。

OBJS := start.o main.o

用变量来收集依赖目标集。

$(NAME).bin	: $(OBJS)$(LD) -Timx6u.lds -o $(NAME).elf $^$(OBJCOPY) -O binary -S $(NAME).elf $@$(OBJDUMP) -D -m arm $(NAME).elf > $(NAME).dis

利用变量,使规则定义变得模板化,
使命令行变得模板化。
模板化的精髓,就是尽可能多的使用变量,使用宏。

%.o : %.c $(CC) -Wall -nostdlib -c -O2 -o $@ $<%.o : %.S $(CC) -Wall -nostdlib -c -O2 -o $@ $<

模式匹配的通配规则。

clean:rm -rf *.o $(NAME).bin $(NAME).elf $(NAME).dis

最后放一个清除目标。

+++++++++++++++++++++++++++++++++++++++
kernel风格,含有多个子文件夹的工程的makefile。

CROSS_COMPILE ?= arm-linux-gnueabihf-
TARGET		  ?= ledc
LDS_NAME     ?= imx6u.ldsCC 				:= $(CROSS_COMPILE)gcc
LD 				:= $(CROSS_COMPILE)ld
OBJCOPY 		:= $(CROSS_COMPILE)objcopy
OBJDUMP			:= $(CROSS_COMPILE)objdump

通过两层变量定义,归一化GCC工具集的名称。

INCUDIRS		:= 	imx6u \bsp/clk \bsp/led \bsp/delayINCLUDE 		:= 	$(patsubst %, -I %, $(INCUDIRS))

定义include所在的路径,
每个子目录添加进去,联行符用\。

函数调用,是$()形式的,或者${}形式的。

patsubst函数,是基于模式匹配的字符串替换函数。
首参,是模式匹配用的通配符,
第二参,是替换成的字符串模式,
第三参,是待解析的字符串。
函数功能是,
首先解析字符串,成为字符串组,每遇到一个分隔符,就获得一个组员,
然后,遍历字符串组,对每个组员进行模式匹配,并替换成模式匹配所指定的字符串,
产生的结果,也是一个结果字符串组,
然后,重组结果字符串,将结果字符串组员间,插入分隔符,再重组成一个最后的结果字符串。

上述命令行的作用是,为每个include子目录,添加-I字符。

SRCDIRS			:= 	project \bsp/clk \bsp/led \bsp/delay

定义src所在的路径,
每个子目录添加进去。

SFILES			:= $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.S))
CFILES			:= $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c))

foreach函数,
首参,是指定一个循环变量,
第二参,是待解析字符串,
第三参,是循环体表达式。
函数功能是,
首先解析字符串,成为字符串组,每遇到一个分隔符,就获得一个组员,
然后,遍历字符串组,对每个组员开始循环,
循环时,将当前的字符串组员,赋值给循环变量,
然后,执行循环体表达式,循环体表达式中所使用到的循环变量的值,就是当前循环阶段,循环变量被赋的值。
循环体表达式的每次循环产生的结果,也形成一个结果字符串组。
最后,重组结果字符串,将结果字符串组员间,插入分隔符,再重组成一个最后的结果字符串。

wildcard关键字,是执行通配符展开的。
表示将所有符合通配符匹配的文件名字符串,全部列举出来,形成一个长串,用分隔符分隔开。

SFILENDIR		:= $(notdir $(SFILES))
CFILENDIR		:= $(notdir $(CFILES))SOBJS			:= $(patsubst %, obj/%, $(SFILENDIR:.S=.o))
COBJS			:= $(patsubst %, obj/%, $(CFILENDIR:.c=.o))

notdir函数,
首参,是一个待解析字符串,
函数功能是,
首先解析字符串,成为字符串组,每遇到一个分隔符,就获得一个组员,
然后,遍历字符串组,对每个组员进行去路径处理,
产生的结果,也是一个结果字符串组,
然后,重组结果字符串,将结果字符串组员间,插入分隔符,再重组成一个最后的结果字符串。

注意这里的变量预处理功能,

$(SFILENDIR:.S=.o)

冒号后,是变量预处理法则。
首先是解析变量字符串,形成字符串组,
然后对每个组员进行预处理,
最后再将结果字符串组,重组为结果字符串。
上例中,预处理是,用.o替换.S。

OBJS			:= $(SOBJS)$(COBJS)

将Sobjs和Cobjs合并,成为总的objs。

VPATH			:= $(SRCDIRS)

定义特殊变量VPATH,此处和变量SRCDIRS的值一样。

.PHONY:clean

定义伪目标。

$(TARGET).bin : $(OBJS)$(LD) -T$(LDS_NAME) -o $(TARGET).elf $^$(OBJCOPY) -O binary -S $(TARGET).elf $@$(OBJDUMP) -D -m arm $(TARGET).elf > $(TARGET).dis

定义主目标的规则。
可以看出,主目标已经高度模板化了。

$(SOBJS) : obj/%.o : %.S$(CC) -Wall -nostdlib -c -O2 $(INCLUDE) -o $@ $<$(COBJS) : obj/%.o : %.c$(CC) -Wall -nostdlib -c -O2 $(INCLUDE) -o $@ $<

定义依赖目标集的规则。
这里,依赖目标集的规则,是基于模式匹配的,最终由make工具逐个展开。是动态生成的。
所以,这个模式匹配规则,也被称为静态模式。
可以看出,依赖目标集也高度模板化了。

clean:rm -rf $(TARGET).elf $(TARGET).bin $(TARGET).dis $(OBJS)

定义清除目标。

+++++++++++++++++++++++++++++++++++++
含有多个子文件夹的工程的lds。
LDS是基于pwd工作的,
由于使用了子文件夹,所以在LDS中的O文件,需要使用相对路径,指定到子文件夹下。

SECTIONS{. = 0X87800000;.text : {obj/start.o*(.text)}.rodata ALIGN(4) : {*(.rodata*)}.data ALIGN(4) : {*(.data)}__bss_start=.;.bss ALIGN(4) : {*(.bss) *(COMMON)}__bss_end=.;
}

上例中,
start.o,位于子文件夹obj下了。

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

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

相关文章

最新在线工具箱网站系统源码

内容目录 一、详细介绍二、效果展示1.部分代码2.效果图展示 三、学习资料下载 一、详细介绍 系统内置高达72种站长工具、开发工具、娱乐工具等功能。此系统支持本地调用API&#xff0c;同时还自带免费API接口&#xff0c; 是一个多功能性工具程序&#xff0c;支持后台管理、上…

docker进行jenkins接口自动化测试持续集成实战

文章目录 一、接口功能自动化测试项目源码讲解二、接口功能自动化测试运行环境配置1、下载jdk&#xff0c;maven&#xff0c;git&#xff0c;allure并配置对应的环境变量2、使用docker安装jenkins3、配置接口测试的运行时环境选择对应节点4、jenkins下载插件5、jenkins配置环境…

promise.all方式使用

romise.all( ).then( ) 处理多个异步任务&#xff0c;且所有的异步任务都得到结果时的情况。 比如&#xff1a;用户点击按钮&#xff0c;会弹出一个弹出对话框&#xff0c;对话框中有两部分数据呈现&#xff0c;这两部分数据分别是不同的后端接口获取的数据。 弹框弹出后的初…

Vue3学习笔记+报错记录

文章目录 1.创建Vue3.0工程1.1使用vue-cli创建1.2 使用vite创建工程1.3.分析Vue3工程结构 2.常用Composition2.1 拉开序幕的setup2.2 ref函数_处理基本类型2.3 ref函数_处理对象类型2.4 ref函数使用总结 1.创建Vue3.0工程 1.1使用vue-cli创建 查看vue/cli版本&#xff0c;确保…

Java-运算符

运算符 Java语言支持如下运算符&#xff1a; 算术运算符&#xff1a;&#xff0c;-&#xff0c;*&#xff0c;/&#xff0c;%&#xff0c;&#xff0c;--复制运算符&#xff1a;关系运算符&#xff1a;>, <, >, <, , !instanceof逻辑运算符&#xff1a;&&…

vue中内置指令v-model的作用和常见使用方法介绍以及在自定义组件上支持

文章目录 一、v-model是什么二、什么是语法糖三、v-model常见的用法1、对于输入框&#xff08;input&#xff09;&#xff1a;2、对于复选框&#xff08;checkbox&#xff09;&#xff1a;3、对于选择框&#xff08;select&#xff09;&#xff1a;4、对于组件&#xff08;comp…