ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2021-10-23

2021-10-23 09:59:28  阅读:231  来源: 互联网

标签:10 变量 文件 SRCDIRS 23 bsp 2021 INCDIRS TARGET


有没有一个比较通用的makefile呢?

写在前面:

这个通用mkaefile文档,来源于正电原子学习板中提到的一种,当然这不代表这个就是最合适的,这只是我在学习过程中遇到的文档中,觉得最厉害的一个。

重点还是以学习为主,学学一般的makefile文件是怎么写的,以及makefile的基础知识。

上代码:(上接我写那个bsp推文)

项目源:Linux驱动开发: Makefile+driver 可直接下载其中的5_ledc_bsp,都是整理好的。

CROSS_COMPILE ?= arm-linux-gnueabihf-#这一行针对不同的编译器是可以进行更改的
TARGET		  ?= bsp#这个目标名字也是,针对不同到历程也是要改的

CC			  := $(CROSS_COMPILE)gcc
LD			  := $(CROSS_COMPILE)ld
OBJCOPY		  := $(CROSS_COMPILE)objcopy
OBJDUMP		  := $(CROSS_COMPILE)objdump
#变量 INCDIRS 包含整个工程的.h 头文件目录,文件中的所有头文件目录都要添加到变量INCDIRS中
INCDIRS		  := imx6ul \
				bsp/clk \
				bsp/led \
				bsp/delay
#SRCDIRS 包含的是整个工程的所有.c 和.S 文件目录
SRCDIRS 	  := project \
			  := bsp/clk \
			  := bsp/led \
			  := bsp/delay
#变量 INCLUDE 使用到了函数 patsubst,通过函数 patsubst 给变量 INCDIRS 添加一个“-I”,因为 Makefile 语法要求指明头文件目录的时候需要加上“-I”
INCLUDE		  := $(patsubst %, -I %, $(INCDIRS))

#变量 SFILES 保存工程中所有的.s 汇编文件(包含绝对路径),变量 SRCDIRS 已经存放了工程中所有的.c 和.S 文件,所以我们只需要从里面挑出所有的.S 汇编文件即可
SFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.S))

#变量 CFILES 和变量 SFILES 一样,只是 CFILES 保存工程中所有的.c 文件(包含绝对路径)
CFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c))

#使用函数 notdir 将 SFILES 和 CFILES 中的路径去掉
SFILENDIR := $(notdir $(SFILES))
CFILENDIR := $(notdir $(CFILES))

#默认所有的文件编译出来的.o 文件和源文件在同一个目录中
SOBJS := $(patsubst %, obj/%, $(SFILENDIR:.S=.o))
COBJS := $(patsubst %, obj/%, $(CFILENDIR:.c=.o))

#变量 OBJS 是变量 SOBJS 和 COBJS 的集合
OBJS := $(SOBJS) $(COBJS)

#VPATH 是指定搜索目录的,这里指定的搜素目录就是变量 SRCDIRS 所保存的目录,这样当编译的时候所需的.S 和.c 文件就会在 SRCDIRS 中指定的目录中查找
VPATH := $(SRCDIRS)

.PHONY: clean

$(TARGET).bin : $(OBJS)
	$(LD) -Timx6ul.lds -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 $@ $<

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

不管做什么事,最重要的就是框架和逻辑,要明白自己所要达成的目的是什么?

就像昨天听师兄们开题,第一个上台的师兄被院长问了一个问题:你知道开题意义是什么? 师兄说是:发现问题,解决问题。

没错,就是要发现问题,确定目标,选择方法,实践,达到目标,解决问题。(其实有时候是自己创造问题来解决)

写makefile文档的目的是什么?

简化我们的操作步骤,更高效的编译,来获得目标文件。

写makefile文档会面临哪些问题?

这可就多了,针对不同的项目框架,目录结构,是不一样的,这里只是针对本项目的:

  • 不同的支持文件放在不同的文件夹里
  • 生成的文件要放在指定文件夹里

这是比较难的两个点。咱们一步一步来,直至完成上面的目标!!

开始写了

1)编译准备工作

CROSS_COMPILE ?= arm-linux-gnueabihf-#这一行针对不同的编译器是可以进行更改的
TARGET		  ?= bsp#这个目标名字也是,针对不同到历程也是要改的

CC			  := $(CROSS_COMPILE)gcc
LD			  := $(CROSS_COMPILE)ld
OBJCOPY		  := $(CROSS_COMPILE)objcopy
OBJDUMP		  := $(CROSS_COMPILE)objdump

首先当然是确定交叉编译工具链了,这个要根据你的实际情况来写,还有目标文件不要忘记了。

gcc、ld、objcopy、objdump是一条龙服务。

2)然后是文件路径

这里的文件路径包括 头文件所在路径,以及.c和.s文件虽在路径,用于后面的查找。

#变量 INCDIRS 包含整个工程的.h 头文件目录,文件中的所有头文件目录都要添加到变量INCDIRS中
INCDIRS		  := imx6ul \
				bsp/clk \
				bsp/led \
				bsp/delay
#SRCDIRS 包含的是整个工程的所有.c 和.S 文件目录
SRCDIRS 	  := project \
			  := bsp/clk \
			  := bsp/led \
			  := bsp/delay

3)对路径进行处理,置于不同的变量中

#变量 INCLUDE 使用到了函数 patsubst,通过函数 patsubst 给变量 INCDIRS 添加一个“-I”,因为 Makefile 语法要求指明头文件目录的时候需要加上“-I”
INCLUDE		  := $(patsubst %, -I %, $(INCDIRS))

这里提到了一个函数patsubat,用于替换通配符。

就是,把$(INCDIRS)中所有符合 %的,全部替换成 -I %,也就是在所有的头文件前面加上了-I。


#变量 SFILES 保存工程中所有的.s 汇编文件(包含绝对路径),变量 SRCDIRS 已经存放了工程中所有的.c 和.S 文件,所以我们只需要从里面挑出所有的.S 汇编文件即可
SFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.S))

#变量 CFILES 和变量 SFILES 一样,只是 CFILES 保存工程中所有的.c 文件(包含绝对路径)
CFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c))

先说foreach,这个函数就像是for循环,具体用法如下:

$(foreach <var>,<list>,<text>)

这个函数的意思是,把参数<list>;中的单词逐一取出放到参数<var>;所指定的变量中,然后再执行< text>;所包含的表达式。每一次<text>;会返回一个字符串,循环过程中,<text>;的所返回的每个字符串会以空格分隔,最后当整个循环结束时,<text>;所返回的每个字符串所组成的整个字符串(以空格分隔)将会是foreach函数的返回值。

再说wildcard这个函数,这个函数简单些,就是拓展通配符,把目标文件的绝对路径找到并进行拼接。


#使用函数 notdir 将 SFILES 和 CFILES 中的路径去掉
SFILENDIR := $(notdir $(SFILES))
CFILENDIR := $(notdir $(CFILES))

函数notdir,去除路径,会的所有的.s和.c文件。

经过上面一顿操作,看看咱们现在都有了哪些变量:

  1. 放.c于.s文件的CFILENDIR、SFILENDIR(无路径)
  2. 放头文件.h的INCLUDE
  3. 当然还有交叉编译用的各种工具变量

4)确定分目标文件

前面我们有了连接之后的总目标,现在我们要定义各个分目标。

#默认所有的文件编译出来的.o 文件和源文件在同一个目录中
SOBJS := $(patsubst %, obj/%, $(SFILENDIR:.S=.o))
COBJS := $(patsubst %, obj/%, $(CFILENDIR:.c=.o))

这里有一个新的用法:

对于一个已经定义的变量,可以使用“替换引用”将其值中的后缀字符(串)使用指定的字符(字符串)替换。格式为“$(VAR:A=B)”(或者“${VAR:A=B}”),意思是,替换变量“VAR”中所有“A”字符结尾的字为“B”结尾的字。“结尾”的含义是空格之前(变量值多个字之间使用空格分开)。而对于变量其它部分的“A”字符不进行替换。

这样我们就得到C文件、S文件的目标文件格式。

最后再集合一下:

#变量 OBJS 是变量 SOBJS 和 COBJS 的集合
OBJS := $(SOBJS) $(COBJS)

5)开始编译、连接、反编译

$(TARGET).bin : $(OBJS)
	$(LD) -Timx6ul.lds -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 $@ $<

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

这些就属于基础操作了。

END!!!

写在最后:

如果在学习的过程中遇到更好的makefile,我还会继续进行更新,大家有问题,也可以私信我交流,毕竟我也是刚开始学,肯定会有很多错误的。

祝大家,早安,午安,晚安!

标签:10,变量,文件,SRCDIRS,23,bsp,2021,INCDIRS,TARGET
来源: https://blog.csdn.net/weixin_43824188/article/details/120917231

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有