u-boot makefile/config分析
u-boot makefile/config分析
本分析采用的不是官方u-boot,而是采用九鼎移植之后的u-boot,原u-boot版本为1.3.4。
u-boot是我目前接触的除了无人机飞控外最复杂的软件系统。所有类似于这种的大型开源项目,软件一定是采用makefile或者cmake进行组织,我之前一直极力避开makefile的学习,导致我根本没有办法好好参与一个开源项目。
一、概述
1.目录结构
- 九鼎
目录名 | 存放文件的作用 |
---|---|
api | 平台无关接口,具体可参看README |
api_example | |
board | u-boot支持的开发板,board-vendor-board三级结构 |
common | 主要是cmd相关 |
cpu | SoC相关的,用于串口中断等Soc内部外设初始化,start.S也在其中 |
disk | |
doc | |
drivers | 主要是开发板上必须用到的一些驱动,如网卡驱动、Inand/SD卡、NandFlash等的驱动,来自于linux源码 |
examples | |
fs | filesystem,文件系统。这个也是从linux源代码中移植过来的。 |
include | |
lib_xxx | 架构相关的库文件 |
libfdt | 设备树相关,与内核传参有关 |
nand_spl | |
net | 网络相关 |
onenandxxx | |
post | |
sd_fusing | 实现了烧录uboot镜像到SD卡的代码 |
tools |
文件名 | 文件作用 |
---|---|
.gitignore | |
arm_config.mk | |
Changelog | |
config.mk | |
COPYING | 版权声明,GPL许可证 |
CREDITS | 鸣谢 |
image_split | 分割uboot.bin到BL1的 |
MAINTAINERS | 维护者 |
MAKEALL | 帮助编译uboot、 |
Makefile | 主makefile |
mk | 快速编译脚本 |
mkconfig | 主要的配置脚本 |
mkmovi | 和iNand/SD卡启动有关的脚本 |
README | |
rules.mk | makefile规则 |
- 三星
与九鼎相比,支持更多板子与CPU架构。 - 官方
这里分析的版本是2020.04-rc1版本,与之前版本,目录结构没有太大的变化。
arch被单独列出来,cmd从common中被分离,有专门的config目录,里面列举了许多板子的配置文件,而这些文件本来是配置后生成的。env环境变量相关单独使用一个目录,其他的以我目前的水平还看不出来。
2.使用
u-boot的使用需要经过两个阶段。
-
config
首先需要到u-boot根目录下执行make x210_sd_config
,如果出现Configuring for x210_sd board...,说明配置完成。 -
make
直接make编译,编译前需要注意工具链的设置是否正确。
一般分为两个方面。一部分为编译环境中有没有安装正确的编译链工具。另一方面为检查makefile文件中编译器的设置是否正确。
多核电脑可以使用make -jx
,x为核心数,使编译加快。
二、主makefile分析
1.版本
VERSION = 1
PATCHLEVEL = 3
SUBLEVEL = 4
EXTRAVERSION = 0nism
U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
VERSION_FILE = $(obj)include/version_autogenerated.h
version_autogenerated.h为编译时生成
2.主机
HOSTARCH := $(shell uname -m |
sed -e s/i.86/i386/
-e s/sun4u/sparc64/
-e s/arm.*/arm/
-e s/sa110/arm/
-e s/powerpc/ppc/
-e s/ppc64/ppc/
-e s/macppc/ppc/)
HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' |
sed -e 's/(cygwin).*/cygwin/')
uname -m用于了解主机的架构
uname -s用于了解主机的操作系统
3.静默编译
# Allow for silent builds
ifeq (,$(findstring s,$(MAKEFLAGS)))
XECHO = echo
else
XECHO = :
endif
使用make -s
即可静默编译
4.编译方法
u-boot的编译的obj文件可以选择原地编译或者输出至特定目录。
第一种可以make O=/tmp/build all
。第二种可以设置环境变量export BUILD_DIR=/tmp/build
然后再make
。O=
的优先级高于BUILD_DIR
。
5.include/config.mk
配置过程中生成的重要配置文件,包含许多编译所需要的宏。
include $(obj)include/config.mk
export ARCH CPU BOARD VENDOR SOC
# ARCH arm
# CPU s5pc11x
# BOARD x210
# VENDOR samsung
# SOC s5pc110
6.CROSS_COMPILE
决定交叉编译工具链前缀,前缀加后缀的结合就可以用来定义各种工具链中的工具。
ifeq ($(ARCH),arm)
CROSS_COMPILE = /usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-
endif
7./config.mk
载入其他相关配置。
8.添加obj和相关库文件
9.真正的编译流程
# 执行根目录下MKCONFIG配置,传入6个参数,第一个参数为x210_sd。
x210_sd_config : unconfig
@$(MKCONFIG) $(@:_config=) arm s5pc11x x210 samsung s5pc110
@echo "TEXT_BASE = 0xc3e00000" > $(obj)board/samsung/x210/config.mk
10.重要编译宏
define | description | attribute |
---|---|---|
VERSION | 1 | |
PATCHLEVEL | 3 | |
SUBLEVEL | 4 | |
EXTRAVERSION | 0nism | |
U_BOOT_VERSION | $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) | |
VERSION_FILE | $(obj)include/version_autogenerated.h | |
XECHO | 静默编译 | |
HOSTARCH | 环境变量 | |
HOSTOS | 环境变量 | |
BUILD_DIR | ||
OBJTREE | $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR)) | 环境变量 |
SRCTREE | $(CURDIR) | 环境变量 |
TOPDIR | $(SRCTREE) | 环境变量 |
LNDIR | $(OBJTREE) | |
MKCONFIG | $(SRCTREE)/mkconfig | 环境变量 |
REMOTE_BUILD | 是否远程编译 | 环境变量 |
obj | 环境变量 | |
src | 环境变量 | |
$(obj)include/config.mk | 宏集合 | 配置中生成 |
ARCH | arm | 环境变量 |
CPU | s5pc11x | 环境变量 |
BOARD | x210 | 环境变量 |
VENDOR | samsung | 环境变量 |
SOC | s5pc110 | 环境变量 |
CROSS_COMPILE | 确定交叉编译工具链前缀 | 环境变量 |
$(TOPDIR)/config.mk | 配置集合 | 配置中生成 |
OBJS | ||
LIBS | ||
LIBBOARD |
三、重要配置文件./config.mk分析
该文件被主makefile预先包含,用于提供交叉编译工具链名称位置以及参数。还包含一些简单的编译规则。
1.编译工具定义
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
CC = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
LDR = $(CROSS_COMPILE)ldr
STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
RANLIB = $(CROSS_COMPILE)RANLIB
2.载入自动生成的开发板配置
# sinclude = -include 表示未找到文件不停止执行
# autoconf.mk是配置时自动生成的
sinclude $(OBJTREE)/include/autoconf.mk
ifdef ARCH
sinclude $(TOPDIR)/$(ARCH)_config.mk # include architecture dependend rules
endif
ifdef CPU
sinclude $(TOPDIR)/cpu/$(CPU)/config.mk # include CPU specific rules
endif
ifdef SOC
sinclude $(TOPDIR)/cpu/$(CPU)/$(SOC)/config.mk # include SoC specific rules
endif
ifdef VENDOR
BOARDDIR = $(VENDOR)/$(BOARD)
else
BOARDDIR = $(BOARD)
endif
ifdef BOARD
sinclude $(TOPDIR)/board/$(BOARDDIR)/config.mk # include board specific rules
endif
3.决定链接脚本
# 定义CONFIG_NAND_U_BOOT宏,链接名为u-boot-nand.lds,否则为u-boot.lds
ifndef LDSCRIPT
#LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds.debug
ifeq ($(CONFIG_NAND_U_BOOT),y)
LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot-nand.lds
else
LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds
endif
endif
4.TEXT_BASE
# line 159-161
ifneq ($(TEXT_BASE),)
CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE)
endif
# line 202-204
ifneq ($(TEXT_BASE),)
LDFLAGS += -Ttext $(TEXT_BASE)
endif
5.其他
其他部分为简单的编译规则,例如原地编译规则等。还有编译器与预编译器参数设置。
四、配置过程分析
当输入make x210_sd_config
时,就会按照主makefile文件分析的一样,执行mkconfig。
1.传入参数
从makefile中可以知道,传入了6个参数
$(@:_config=) arm s5pc11x x210 samsung s5pc110
arg | description |
---|---|
$1 | x210_sd,是将x210_sd_config的后半部分去掉 |
$2 | arm |
$3 | s5pc11x |
$4 | x210 |
$5 | samsumg |
$6 | s5pc110 |
2.命名BOARD_NAME
[ "${BOARD_NAME}" ] || BOARD_NAME="$1"
3.判断参数数量
[ $# -lt 4 ] && exit 1
[ $# -gt 6 ] && exit 1
大于四,小于六
4.创建符号链接
第一个链接为./include/asm ./inlcude/asm-arm
第二个链接为./include/asm-arm/arch ./include/arch-s5pc110
第三个链接为./include/regs.h ./include/s5pc110.h
删除第二个
第四个链接为./include/asm-arm/arch ./include/asm-arm/arch-s5pc11x
第五个链接为./include/asm-arm/proc ./include/asm-arm/proc-armv
5.创建inlcude/config.mk
echo "ARCH = $2" > config.mk
echo "CPU = $3" >> config.mk
echo "BOARD = $4" >> config.mk
[ "$5" ] && [ "$5" != "NULL" ] && echo "VENDOR = $5" >> config.mk
[ "$6" ] && [ "$6" != "NULL" ] && echo "SOC = $6" >> config.mk
6.创建目标开发板的指定头文件
if [ "$APPEND" = "yes" ] # Append to existing config file
then
echo >> config.h
else
> config.h # Create new config file
fi
echo "/* Automatically generated - do not edit */" >>config.h
echo "#include <configs/$1.h>" >>config.h
创建include/config.h 内容为
"/* Automatically generated - do not edit */"
和#include <configs/$1.h>