U-Boot Makefile分析(1)配置脚本mkconfig分析

  我们在编译U-Boot之前,需要根据当前使用的板子进行配置,例如make s5p_goni_config,接着才能进行编译make。下面首先分析配置阶段U-Boot做了哪些事情。

  由于执行这些命令是在源码根目录下,所以需要到主Makefile中找一下s5p_goni_config这个目标,搜索结果显示没有匹配的信息,后来发现其实U-Boot设计者已经将配置选项设计成通用模式了:

%_config:: unconfig

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

  上面的写法比较通用,因为U-Boot支持很多板卡,不同使用者会使用不同的配置,如make mini2440_config; make smdk2410_config; make zynq_config等等,假如每个板卡都在Makefiile中占用一个目标,那么整个Makefile显得很冗余,不如用脚本处理下。

  回到上面的配置目标和依赖描述,显然s5p_goni_config是一个伪目标,依赖是unconfig,不知道为什么这里目标和依赖之间是两个冒号,小纠结。。。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

  伪目标下面的命令总是要执行的:删除include/config.h include/config.mk include/autoconf.mk include/autoconf.mk.dep,以及各个板卡的临时配置信息文件config.tmp。因此,每次我们执行make s5p_goni_config之类的配置命令时,都会先清除之前的配置。接下来呢?接下就要执行@$(MKCONFIG) -A $(@:_config=)了,$(MKCONFIG) 是在主Makefile前面部分定义的变量:

MKCONFIG := $(SRCTREE)/mkconfig

  mkconfig是源码根目录下的一个脚本文件,$(@:_config=)是makefile中变量替换的一种方式,表示把目标$@变量的_config部分替换为空,效果上就是删除_config后缀,因此我们就得到了下面的信息:

s5p_goni_config:: unconfig

  mkconfig -A s5p_goni

 

 接下来,我们的任务是分析mkconfig脚本,下面分析主要流程。

  首先定义以下变量,概括地说,mkconfig脚本的主要功能就是根据用户传入的参数,获取以下各变量的值,然后再自动产生一些头文件。

 

 1 APPEND=no 
 2 BOARD_NAME="" 
 3 TARGETS=""
 4 
 5 
 6 arch=""
 7 cpu=""
 8 board=""
 9 vendor=""
10 soc=""
11 options=""

  下面是关键的一步。

 1 if [ \( $# -eq 2 \) -a \( "$1" = "-A" \) ] ; then
 2     # Automatic mode
 3     line=`egrep -i "^[[:space:]]*${2}[[:space:]]" boards.cfg` || {
 4         echo "make: *** No rule to make target \`$2_config'.  Stop." >&2
 5         exit 1
 6     }
 7 
 8     set ${line}
 9     
10     [ $# = 3 ] && set ${line} ${1}
11 elif [ "${MAKEFLAGS+set}${MAKELEVEL+set}" = "setset" ] ; then
12     # only warn when using a config target in the Makefile
13     cat <<-EOF
14 
15     warning: Please migrate to boards.cfg.  Failure to do so will
16              mean removal of your board in the next release.
17 
18     EOF
19     sleep 5
20 fi

 

 

  显然我们的参数个数和内容是符合分支判断要求的,因此执行那条文本数据处理命令,目的是在boards.cfg文件中根据s5p_goni匹配一行信息,这条信息放在line变量中,如果返回值为空字符串那么就报错退出,提示没有用户所说的这块板子的相关配置。那么boards.cfg文件中是什么内容呢?它是目前U-Boot支持板卡的信息汇总,通过这个文件,我们可以知道U-Boot支持哪些架构、哪些处理器、哪些SoC、哪些board,是一个很好的参考,它的每一个entry都是有格式要求的:

Target   ARCH   CPU   Board name   Vendor   SoC     Option

s5p_goni  arm    armv7    goni    samsung  s5pc1xx 

zynq    arm    armv7    zynq     xilinx   zynq 

mini2440   arm    arm920t  mini2440  friendlyARM s3c24x0

 

  上面的格式很简单,不多说,如果将来想支持自己的板卡,那么加入自己的选项就好了。比如

tiny210 arm armv7   tiny210 frirndlyARM s5pc1xx

  

  回到脚本分析,set ${line}这条语句不简单,我由于不知道这句话的含义,纠结了很久,后来做实验才明白这句话的作用:改变当前脚本的参数$# $1 $2 $3...,这些参数的内容完全由{line}决定。此时它的内容就是s5p_goni那一行,那么

$# = 6

$1 = s5p_goni  $2 = arm  $3 = armv7  $4 = goni  $5 = samsung  $6 = s5pc1xx

 1 while [ $# -gt 0 ] ; do
 2     case "$1" in
 3     --) shift ; break ;;
 4     -a) shift ; APPEND=yes ;;
 5     -n) shift ; BOARD_NAME="${1%_config}" ; shift ;;
 6     -t) shift ; TARGETS="`echo $1 | sed 's:_: :g'` ${TARGETS}" ; shift ;;
 7     *)  break ;;
 8     esac
 9 done
10 
11 [ $# -lt 4 ] && exit 1
12 [ $# -gt 7 ] && exit 1
13 
14 # Strip all options and/or _config suffixes
15 CONFIG_NAME="${1%_config}"
16 
17 [ "${BOARD_NAME}" ] || BOARD_NAME="${1%_config}"
18 
19 arch="$2"
20 cpu=`echo $3 | awk 'BEGIN {FS = ":"} ; {print $1}'`
21 spl_cpu=`echo $3 | awk 'BEGIN {FS = ":"} ; {print $2}'`
22 if [ "$4" = "-" ] ; then
23     board=${BOARD_NAME}
24 else
25     board="$4"
26 fi
27 [ $# -gt 4 ] && [ "$5" != "-" ] && vendor="$5"
28 [ $# -gt 5 ] && [ "$6" != "-" ] && soc="$6"
29 [ $# -gt 6 ] && [ "$7" != "-" ] && {
30     tmp="${7%:*}"
31     if [ "$tmp" ] ; then
32         CONFIG_NAME="$tmp"
33     fi
34     # Check if we only have a colon...
35     if [ "${tmp}" != "$7" ] ; then
36         options=${7#*:}
37         TARGETS="`echo ${options} | sed 's:,: :g'` ${TARGETS}"
38     fi
39 }
40 
41 if [ "${ARCH}" -a "${ARCH}" != "${arch}" ]; then
42     echo "Failed: \$ARCH=${ARCH}, should be '${arch}' for ${BOARD_NAME}" 1>&2
43     exit 1
44 fi
45 
46 if [ "$options" ] ; then
47     echo "Configuring for ${BOARD_NAME} - Board: ${CONFIG_NAME}, Options: ${options}"
48 else
49     echo "Configuring for ${BOARD_NAME} board..."
50 fi

  上面代码的while循环对于当前这个板卡是没有作用的,且明显参数个数是满足继续运行的要求的,接下来就开始赋值了

CONFIG_NAME = s5p_goni

BOARD_NAME = s5p_goni

arch = arm

cpu = armv7

spl_cpu = 

board = goni

vendor = samsung

soc = s5pc1xx

  这里我们没有第七个参数,因此相关的option置空,那么配置的时候屏幕会输出一句“Configuring for s5p_goni board...”。

  重要的变量都得到了,下面开始第二项重要工作,建立相关软链接和头文件。

 1 if [ "$SRCTREE" != "$OBJTREE" ] ; then
 2     mkdir -p ${OBJTREE}/include
 3     mkdir -p ${OBJTREE}/include2
 4     cd ${OBJTREE}/include2
 5     rm -f asm
 6     ln -s ${SRCTREE}/arch/${arch}/include/asm asm
 7     LNPREFIX=${SRCTREE}/arch/${arch}/include/asm/
 8     cd ../include
 9     mkdir -p asm
10 else
11     cd ./include
12     rm -f asm
13     ln -s ../arch/${arch}/include/asm asm
14 fi

  上面SRCTREE与OBJTREE是相同的,代表所有源码都在本地,再本地编译链接,得到目标,因此执行else分支:再当前shell运行的子进程中进入include文件夹下,删除其下面的asm(asm是一个软链接文件),接着为arch/arm/include/asm文件夹建立软链接asm。

 1 rm -f asm/arch
 2 
 3 if [ -z "${soc}" ] ; then
 4     ln -s ${LNPREFIX}arch-${cpu} asm/arch
 5 else
 6     ln -s ${LNPREFIX}arch-${soc} asm/arch
 7 fi
 8 
 9 if [ "${arch}" = "arm" ] ; then
10     rm -f asm/proc
11     ln -s ${LNPREFIX}proc-armv asm/proc
12 fi

  首先删除asm/arch,注意!此处的asm已经是软链接了,所以删除的是arch/arm/include/asm/arch(其实arch也是软链接文件)。soc变量长度非零,因此为arch/arm/include/asm/arch-s5pc1xx 建立软链接asm/arch。其实上面两段代码的作用就是建立asm和arch两个软链接,以后在C语言包含头文件时,头文件的路径写起来就比较方便。

 1 ( echo "ARCH   = ${arch}"
 2     if [ ! -z "$spl_cpu" ] ; then
 3     echo 'ifeq ($(CONFIG_SPL_BUILD),y)'
 4     echo "CPU    = ${spl_cpu}"
 5     echo "else"
 6     echo "CPU    = ${cpu}"
 7     echo "endif"
 8     else
 9     echo "CPU    = ${cpu}"
10     fi
11     echo "BOARD  = ${board}"
12 
13     [ "${vendor}" ] && echo "VENDOR = ${vendor}"
14     [ "${soc}"    ] && echo "SOC    = ${soc}"
15     exit 0 ) > config.mk
16 
17 # Assign board directory to BOARDIR variable
18 if [ -z "${vendor}" ] ; then
19     BOARDDIR=${board}
20 else
21     BOARDDIR=${vendor}/${board}
22 fi

  向include/config.mk中写入一些信息:

ARCH = arm
CPU = armv7
BOARD = goni
VENDOR = samsung
SOC = s5pc1xx

  打开include/config.mk发现其内容和上述一致。上面最后一句BOARDDIR=samsung/goni,其实这就提示我们,在boards.cfg文件中添加信息后,还要在board目录下建立vendor/board目录,两者都要有,mkdir -p vendor/board。

 1 if [ "$APPEND" = "yes" ]    # Append to existing config file
 2 then
 3     echo >> config.h
 4 else
 5     > config.h      # Create new config file
 6 fi
 7 echo "/* Automatically generated - do not edit */" >>config.h
 8 
 9 for i in ${TARGETS} ; do
10     i="`echo ${i} | sed '/=/ {s/=/  /;q; } ; { s/$/ 1/; }'`"
11     echo "#define CONFIG_${i}" >>config.h ;
12 done
13 
14 cat << EOF >> config.h
15 #define CONFIG_BOARDDIR board/$BOARDDIR
16 #include <config_cmd_defaults.h>
17 #include <config_defaults.h>
18 #include <configs/${CONFIG_NAME}.h>
19 #include <asm/config.h>
20 EOF
21 
22 exit 0

  我们这块板子并没有append option,所以直接建立config.h文件,建立的方式比较简单:> config.h,第一次见到这种建立空白文件的方式,新技能get!接着在该文件的头部添加一句提示语。最后,向config.h写入一些信息,这里只是包含一些其他头文件:

#define CONFIG_BOARDDIR  board/samsung/goni

#include <config_cmd_defaults.h>

#define <config_defaults.h>

#define <configs/s5p_goni.h>  //这就对应当前板子的头文件,应该放在include/configs目录下。

#include <asm/config.h>

注意脚本中向文件写内容方式:

cat << EOF >> filename

line1

line2

....

EOF

 

转载于:https://www.cnblogs.com/tech-lqh/p/8404456.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值