UBOOT的编译过程一

本文详细解析了UBOOT编译过程中make tiny4412_config的步骤,包括删除旧配置文件、自动配置、设置BOARD_NAME、参数处理、创建链接文件和生成配置头文件等内容,深入理解UBOOT的编译机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#make tiny4412_config

一切从顶层目录中的makefile 中开始寻找答案:

%_config::    unconfig
    @$(MKCONFIG) -A $(@:_config=)

其中%是通配符代表所有可能的字符

当make 之后先执行unconfig:

unconfig:
    @rm -f $(obj)include/config.h $(obj)include/config.mk \
        $(obj)board/*/config.tmp $(obj)board/*/*/config.tmp \
        $(obj)include/autoconf.mk $(obj)include/autoconf.mk.dep

obj := $(OBJTREE)/

OBJTREE        := $(if $(BUILD_DIR),$(BUILD_DIR),$(CURDIR))

其中BUILD_DIR是通过o=来指定的一个目录

其中CURDIR是内部变量

插讲:$(if CONDITION,THEN-PART[,ELSE-PART]) 
¾  函数功能:第一个参数“CONDITION” ,在函数执行时忽略其前导和结尾空字符,如果包含对其他变量或者函数的引用则进行展开。如果“CONDITION”的展开结果非空,则条件为真,就将第二个参数“THEN_PATR”作为函数的计算表达式;“CONDITION”的展开结果为空,将第三个参数“ELSE-PART”作为函数的表达式,函数的返回结果为有效表达式的计算结果。 
¾  返回值:根据条件决定函数的返回值是第一个或者第二个参数表达式的计算结果。当不存在第三个参数“ELSE-PART” ,并且“CONDITION”展开为空,函数返回空。 
¾  函数说明:函数的条件表达式“CONDITION”决定了函数的返回值只能是“THEN-PART”或者“ELSE-PART”两个之一的计算结果。 
¾  函数示例: 
SUBDIR += $(if $(SRC_DIR) $(SRC_DIR),/home/src) 
函数的结果是:如果“SRC_DIR”变量值不为空,则将变量“SRC_DIR”指定
的目录作为一个子目录;否则将目录“/home/src”作为一个子目录。

回到正题,对于unconfig命令就是一种将删除上一个make XXX_config产生的文件。主要是一些产生autoconfig.h(用于.h文件中),auto.config(用于makefile中)

 对于@$(MKCONFIG) -A $(@:_config=)这个命令:

1,我们先讲$(@:_config=)这句话主要是对tiny4412_config进行处理。刚才那个命令的意思是将字符中的_config替换成等号右边的字符,没有就是为空,所以处理之后为tiny4412。

2,@$(MKCONFIG)

MKCONFIG    := $(SRCTREE)/mkconfig

SRCTREE        := $(CURDIR)

也就是顶层目录中的mkconfig。通过它去进一步解析这个命令。所以上面命令变成mkconfig -A tiny4412其中-A表示要自动配置。

好,继续贴代码来分析

if [ \( $# -eq 2 \) -a \( "$1" = "-A" \) ] ; then
    # Automatic mode
    line=`egrep -i "^[[:space:]]*${2}[[:space:]]" boards.cfg` || {
        echo "make: *** No rule to make target \`$2_config'.  Stop." >&2
        exit 1
    }

    set ${line}
    # add default board name if needed
    [ $# = 3 ] && set ${line} ${1}
fi

上面的代码就去boards.cfg里面去找tiny4412,找到了就把赋于line

while [ $# -gt 0 ] ; do
    case "$1" in
    --) shift ; break ;;
    -a) shift ; APPEND=yes ;;
    -n) shift ; BOARD_NAME="${1%_config}" ; shift ;;
    -t) shift ; TARGETS="`echo $1 | sed 's:_: :g'` ${TARGETS}" ; shift ;;
    *)  break ;;
    esac
done

$#为shell中的一个特殊变量,代表传入参数的个数,-gt是大于的意思,该行的意思是“当传入参数个数大于0时”进入循环
case "$1" in接着下面的几行意思表示,判断第一个参数中是否有-- -a -n参数,我们传入的参数都没有这些,所以他们根本没机会执行到

[ "${BOARD_NAME}" ] || BOARD_NAME="$1"
有或的意思,如果||前的[]中不为NULL,那么||后面的就屏蔽了,很不幸,这里||前面部分却为NULL,所以BOARD_NAME=tiny4412(第一个参数的值)

继续贴代码:

[ $# -lt 4 ] && exit 1
[ $# -gt 7 ] && exit 1

参数个数正确性判断不能小于4个,也不能大于7个。
 

# Strip all options and/or _config suffixes
CONFIG_NAME="${1%_config}"

[ "${BOARD_NAME}" ] || BOARD_NAME="${1%_config}"

arch="$2"
cpu="$3"
if [ "$4" = "-" ] ; then
    board=${BOARD_NAME}
else
    board="$4"
fi

board = tiny4412

根据相应的点对各个基本的板子参数进行赋值。知道了 target:tiny4412, arch: arm , cpu: armv7, board name: tiny4412, vendor:samsung, soc:exynos

[ $# -gt 4 ] && [ "$5" != "-" ] && vendor="$5"
[ $# -gt 5 ] && [ "$6" != "-" ] && soc="$6"
[ $# -gt 6 ] && [ "$7" != "-" ] && {
    # check if we have a board config name in the options field
    # the options field mave have a board config name and a list
    # of options, both separated by a colon (':'); the options are
    # separated by commas (',').
    #
    # Check for board name
    tmp="${7%:*}"
    if [ "$tmp" ] ; then
        CONFIG_NAME="$tmp"
    fi
    # Check if we only have a colon...
    if [ "${tmp}" != "$7" ] ; then
        options=${7#*:}
        TARGETS="`echo ${options} | sed 's:,: :g'` ${TARGETS}"
    fi
}

if [ "${ARCH}" -a "${ARCH}" != "${arch}" ]; then
    echo "Failed: \$ARCH=${ARCH}, should be '${arch}' for ${BOARD_NAME}" 1>&2
    exit 1
fi

if [ "$options" ] ; then
    echo "Configuring for ${BOARD_NAME} - Board: ${CONFIG_NAME}, Options: ${options}"
else
    echo "Configuring for ${BOARD_NAME} board..."

fi

主要是对板子的基本信息进行处理。target:tiny4412, arch: arm , cpu: armv7, board name: tiny4412, vendor:samsung, soc:exynos

接下来判断"$SRCTREE" != "$OBJTREE"是否成立,显然不成立(参考顶层Makefile),所以略过没必要的行,如下:

if [ "$SRCTREE" != "$OBJTREE" ] ; then
    mkdir -p ${OBJTREE}/include
    mkdir -p ${OBJTREE}/include2
    cd ${OBJTREE}/include2
    rm -f asm
    ln -s ${SRCTREE}/arch/${arch}/include/asm asm
    LNPREFIX=${SRCTREE}/arch/${arch}/include/asm/
    cd ../include
    rm -f asm
    ln -s ${SRCTREE}/arch/${arch}/include/asm asm
else
    cd ./include
    rm -f asm
    ln -s ../arch/${arch}/include/asm asm
fi

else分支中先进入inlcude目录,然后删除上一次编译时配置生成的asm文件,最后生成链接文件asm指向asm

rm -f asm/arch

删除arch/arm/include/asm/arch链接文件

if [ -z "${soc}" ] ; then
    ln -s ${LNPREFIX}arch-${cpu} asm/arch
else
    ln -s ${LNPREFIX}arch-${soc} asm/arch
fi

如果soc参数字符串长度为0或者为NULL,那么条件成立,但是实际上条件不成立,soc=exynos,所以生成一个链接文件asm/arch--->arch-exynos

if[ "${arch}" = "arm" ] ; then
    rm -f asm/proc
    ln -s ${LNPREFIX}proc-armv asm/proc
fi

创建链接文件asm/proc--->proc-armv
 

#
# Create include file for Make
#
echo "ARCH   = ${arch}"  >  config.mk
echo "CPU    = ${cpu}"   >> config.mk
echo "BOARD  = ${board}" >> config.mk

[ "${vendor}" ] && echo "VENDOR = ${vendor}" >> config.mk

[ "${soc}"    ] && echo "SOC    = ${soc}"    >> config.mk

在include目录中创建config.mk文件,内容如下:
ARCH = arm
CPU  = armv7
BOARD= tiny4412
SOC  = exynos

# Assign board directory to BOARDIR variable
if [ -z "${vendor}" ] ; then
    BOARDDIR=${board}
else
    BOARDDIR=${vendor}/${board}
fi

#
# Create board specific header file
#
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

for i in ${TARGETS} ; do
    i="`echo ${i} | sed '/=/ {s/=/\t/;q } ; { s/$/\t1/ }'`"
    echo "#define CONFIG_${i}" >>config.h ;
done

在include目录中创建头文件config.h,内容为:
/* Automatically generated - do not edit */
#include <configs/tiny4412.h>

cat << EOF >> config.h
#define CONFIG_BOARDDIR board/$BOARDDIR
#include <config_defaults.h>
#include <configs/${CONFIG_NAME}.h>
#include <asm/config.h>
EOF

BOARDDIR=${vendor}/${board}

所以BOARDDIR=samsung/tiny4412

插讲:

cat << EOF:

两个都是获取stdin,并在EOF处结束stdin,输出stdout。

但是<<-是什么意思呢?

先来看man中的说明:

If the redirection operator is <<-, then all leading tab characters are stripped from input lines and  the  line  containing  delimiter.   

翻译过来的意思就是:如果重定向的操作符是<<-,那么分界符(EOF)所在行的开头部分的制表符(Tab)都将被去除。

这可以解决由于脚本中的自然缩进产生的制表符。

通俗一点的解释:

在我们使用cat <<EOF时,我们输入完成后,需要在一个新的一行输入EOF结束stdin的输入。EOF必须顶行写,前面不能用制表符或者空格。

比如,下面的语句就不会出错:

    cat <<EOF
    Hello,world!
    EOF

如果结束分解符EOF前有制表符或者空格,则EOF不会被当做结束分界符,只会继续被当做stdin来输入。
而<<-就是为了解决这一问题:

    cat <<-EOF
    Hello,world!
          EOF

上面的写法,虽然最后的EOF前面有多个制表符和空格,但仍然会被当做结束分界符,表示stdin的结束。
这就是<<和<<-的区别。exit 0

总结:

1. 打印  Configuring for fs2410 board...
2. 在include目录下创建3个链接文件    Create link to architecture specific headers
 ./include
  asm--->asm
 ./include/asm
  arch--->arch-exynos
  proc--->proc-armv
3. 在include目录中创建config.mk文件 Create include file for Make
 ARCH = arm
 CPU  = armv7
 BOARD= tiny4412
 SOC  = exynos
4. 创建板级特殊头文件config.h   Create board specific header file
 /* Automatically generated - do not edit */
 #include <configs/tiny4412.h>
#define CONFIG_BOARDDIR board/samsung/tiny4412
#include <config_defaults.h>
#include <configs/tiny4412.h>
#include <asm/config.h>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值