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.hversion_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 s5pc1106.CROSS_COMPILE
决定交叉编译工具链前缀,前缀加后缀的结合就可以用来定义各种工具链中的工具。
ifeq ($(ARCH),arm)
CROSS_COMPILE = /usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-
endif7./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.mk10.重要编译宏
| 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)RANLIB2.载入自动生成的开发板配置
# 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
endif3.决定链接脚本
# 定义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
endif4.TEXT_BASE
# line 159-161
ifneq ($(TEXT_BASE),)
CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE)
endif
# line 202-204
ifneq ($(TEXT_BASE),)
LDFLAGS += -Ttext $(TEXT_BASE)
endif5.其他
其他部分为简单的编译规则,例如原地编译规则等。还有编译器与预编译器参数设置。
四、配置过程分析
当输入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.mk6.创建目标开发板的指定头文件
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>
浙公网安备 33010602011771号