提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
- 前言
- 一、工程优化
- 二、路径添加
- 三、Makefile编写
- 四、链接脚本和下载
- 总结
提示:以下是本篇文章正文内容,下面案例可供参考
一、工程优化将不同功能的源码文件放到不同的目录中。另外我们也需要将源码文件中,所有完成同一个功能的代码提取出来放到一个单独的文件中,也就是对程序分功能管理
新建一个工程,在工程里面建立 bsp、 imx6ul、 obj 和 project 这 4 个文件夹
bsp:存放驱动文件 imx6ul:存放跟芯片有关的文件,如SDK库文件 obj:存放编译生成的.o 文件 project:应用文件,也就是start.S 和 main.c 文件
在驱动bsp 文件夹下创建三个子文件夹: clk、 delay 和 led,分别用来存放时钟驱动文件、延时驱动文件和 LED 驱动文件
大致如下图:
设置VSCODE头文件路径, 先创建.vscode目录,然后打开c/c++配置器,会在.vscode目录下生成一个叫做c_cpp_properties.json的文件,然后在includePath下按如下方式添加路径
CROSS_COMPILE ?= arm-linux-gnueabihf-
TARGET ?= bsp
CC := $(CROSS_COMPILE)gcc
LD := $(CROSS_COMPILE)ld
OBJCOPY := $(CROSS_COMPILE)objcopy
OBJDUMP := $(CROSS_COMPILE)objdump
INCDIRS := imx6ul \
bsp/clk \
bsp/led \
bsp/delay
SRCDIRS := project \
bsp/clk \
bsp/led \
bsp/delay
INCLUDE := $(patsubst %, -I %, $(INCDIRS))
SFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.S))
CFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c))
SFILENDIR := $(notdir $(SFILES))
CFILENDIR := $(notdir $(CFILES))
SOBJS := $(patsubst %, obj/%, $(SFILENDIR:.S=.o))
COBJS := $(patsubst %, obj/%, $(CFILENDIR:.c=.o))
OBJS := $(SOBJS) $(COBJS)
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 $@ $,< text>)
查找< text >中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否 符合模式< pattern>,如果匹配的话,则以< replacement>替换。这里, < pattern>可以包括通配符“ %”,表示任意长度的字串。
INCLUDE := $(patsubst %, -I %, $(INCDIRS))
通过函数 patsubst 给变量 INCDIRS 添加一个“-I”,因为Makefile指定头文件路径,需要-I 原来的路径就变为
INCLUDE := -I imx6ul -I bsp/clk -I bsp/led -I bsp/delay
3.变量 SFILES 保存工程中所有的.s 汇编文件(包含绝对路径),变量 SRCDIRS 已经存放了工程中所有的.c 和.S 文件,所以只需要从里面挑出所有的.S 汇编文件即可
foreach函数,作用:用来做循环用的 函数原型:
$(foreach < var>,< list>,< text>)
把参数中的单词逐一取出放到参数所指定的变量中,然后再执行
所包含的表达式。每一次
会返回一个字符串,循环过程中,
的所返回的每个字符串会以空格分隔,最后当整个循环结束时,
所返回的每个字符串所组成的整个字符串(以空格分隔)将会是 foreach 函数的返回值
wildcard函数, 用来明确表示通配符,在Makefile规则中,通配符会被自动展开,但在变量的定义和函数引用时,通配符将失效。这种情况下如果需要通配符有效,就需要使用函数wildcard 比如,$(wildcard *.c)”来获取工作目录下的所有的.c文件列表
SFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.S))
CFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c))
这里SFILES将会被展开为:
SFILES = project/start.S
CFILES = project/main.c bsp/clk/bsp_clk.c bsp/led/bsp_led.c bsp/delay/bsp_delay.c
4.变量 SFILENDIR 和 CFILENDIR 包含所有的.S 汇编文件和.c 文件,相比变量 SFILES 和 CFILES, SFILENDIR 和 CFILNDIR 只是文件名,不包含文件的绝对路径,使用函数 notdir 将 SFILES 和 CFILES 中的路径去掉即可
函数原型
$(notdir < names…>)
从文件名序列< names>中取出目录部分。目录部分是指最后一个反斜杠(“/”)之前的部分,也就是提前目录下的函数
SFILENDIR := $(notdir $(SFILES))
CFILENDIR := $(notdir $(CFILES))
变成了如下
SFILENDIR = start.S
CFILENDIR = main.c bsp_clk.c bsp_led.c bsp_delay.c
5.变量SOBJS 和 COBJS 是.S 和.c 文件编译以后对应的.o 文件目录,默认所有的文件编译出来的.o 文件和源文件在同一个目录中,这里我们将所有的.o 文件都放到 obj 文件夹下,变量 OBJS 是变量 SOBJS 和 COBJS 的集合 内容如下
SOBJS = obj/start.o
COBJS = obj/main.o obj/bsp_clk.o obj/bsp_led.o obj/bsp_delay.o
OBJS = obj/start.o obj/main.o obj/bsp_clk.o obj/bsp_led.o obj/bsp_delay.o
==6.VPATH作用:指定搜索目录 ==
VPATH := $(SRCDIRS)
这里指定的搜素目录就是变量SRCDIRS 所保存的目录,当编译的时候所需的.S 和.c 文件就会在 SRCDIRS 中指定的目录中查找
7.(.PHONY)用来指明该目标是一个伪目标 这里提供一个清除它们的“目标”以备完整地重编译而用,但是不生成clean这个文件,这就是一个伪目标
“伪目标”并不是一个文件,只是一个标签,由于“伪目标”不是文件,所以 make 无法生成它的依赖关系和决定它是否要执行。只有通过显示地指明这个“目标”才能让其生效,“伪目标”的取名不能和文件名重名
为了避免和文件重名的这种情况,我们可以使用一个特殊的标记“.PHONY”来显示地指明一个目标是“伪目标”,向 make 说明,不管是否有这个文件,这个目标就是“伪目标”
8.Makefile静态模式 ,静态模式可以更加容易地定义多目标的规则,可以让我们的规则变得更加的有弹性和灵活 < targets …>: < target-pattern>: < prereq-patterns …>
targets :定义了一系列的目标文件,可以有通配符,是目标的一个集合 target-parrtern :指明了 targets 的模式,也就是的目标集模式 prereq-parrterns :目标的依赖模式,它对 target-parrtern 形成的模式再进行一次依赖目标的定义
$(OBJS): obj/%.o : %.S
表示将所有的.S文件编译为.o并且存放到obj目录下去
后面的都很熟悉,编译,链接,反汇编
四、链接脚本和下载
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 文件路径
最后就可以下载程序了…
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?