zoukankan      html  css  js  c++  java
  • Uboot 2014.07 makefile分析

    uboot的官网可以通过谷歌搜索得到,显示结果第一个链接就是。
    官网::
    http://www.denx.de/wiki/U-Boot
    ftp下载:
    ftp://ftp.denx.de/pub/u-boot/


    本文以uboot 2014.07为例,一般第一步总是类似这样:
    make smdkc100_config
    然后执行make

    先看Makefile第481 行
    %_config:: outputmakefile
    @$(MKCONFIG) -A $(@:_config=)
    当输入make smdkc100_config时,就会匹配到%_config目标,%是通配符,即输入XXX_config格式的目标就会匹配到%_config。
    MKCONFIG的定义在前面:
    MKCONFIG := $(srctree)/mkconfig
    export MKCONFIG

    srctree的定义:
    srctree := $(if $(KBUILD_SRC),$(KBUILD_SRC),$(CURDIR))//if KBUILD_SRC被定义,则srctree=KBUILD_SRC,else = CURDIR,

    KBUILD_SRC的定义:
    ifeq ($(KBUILD_SRC),)
    # OK, Make called in directory where kernel src resides
    # Do we want to locate output files in a separate directory?
    #O就是output目录变量,使用方法:make O= XXXDIR
    ifeq ("$(origin O)", "command line")
    #如果O变量来自命令行(origin返回变量的来源)
      KBUILD_OUTPUT := $(O)
    endif

    事实上我没用O去定义KBUILD_SRC变量,所以srctree=当前目录,也就是uboot的目录
    objtree := $(CURDIR)
    src := $(srctree)

    以上语句可翻译为:
    smdkc100_config:: outputmakefile
    ./mkconfig -A $(@:_config=)

    这里的规则用了双冒号 :: 
    1.        双冒号规则中,当依赖文件比目标更新时。规则将会被执行。对于一个没有依赖而只有命令行的双冒号规则,当引用此目标时,规则的命令将会被无条件执行。而普通规则,当规则的目标文件存在时,此规则的命令永远不会被执行(目标文件永远是最新的)。

    $(@:_config=):请看Gnu Make中文手册5.3.1 变量的替换引用。
    $(@)代表目标smdkc100_config,$(@:_config=):表示用等号后面的内容替代掉:和=之间的内容,=后面为空,那么_config就等于被删去了,$(@:_config=)就代表smdkc100
    ./mkconfig -A $(@:_config=)


    现在可以看mkconfig文件了。mkconfig没有目标,从第一句开始执行:
    第一个if段:

    if [ ( $# -eq 2 ) -a ( "$1" = "-A" ) ] ; then
    # Automatic mode
    line=`awk '($0 !~ /^#/ && $7 ~ /^'"$2"'$/) { print $1, $2, $3, $4, $5, $6, $7, $8 }' $srctree/boards.cfg`
    if [ -z "$line" ] ; then
    echo "make: *** No rule to make target \`$2_config'.  Stop." >&2
    exit 1
    fi

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

    ######    $#表示传入参数个数,由上可知$# = 2,符合条件。 -a表示逻辑与。$1表示第一个参数,等于-A,符合条件,所以then后面的语句被执行。
    这段代码符号比较多,看起来比较复杂,请百度shell 符号,你会有所收获。

    line=`awk**************`
    用倒引号``把命令的输出作为字串,如果是"",则里面的内容不被当做命令执行,而是当做纯粹的字符串,但可引用变量
    '  '单引号内的内容作为字串,但变量$符号不会起作用(忽略任何引用),
    单括号()内可以的内容可以执行命令,也就是说,()内先执行,再用''把()的输出当做纯字串,大括号同理。
    //斜杠表示里面的内容是正则表达式。
    ($0 !~ /^#/ && $7 ~ /^'"$2"'$/)
    在awk命令里,$不是shell变量符号,而是域标记。但是也有例外:双引号""中的$可以引用变量(参见《LINUX与UNIX SHELL编程指南》67页,9.2.2节,“域和记录”和第15章,引号),所以这里的$7 为boards.cfg里的域7,而$2则表示mkconfig的第二个参数,没错,就是smdkc100,/^'"$2"'$/表示只包含变量$2的行,依然是smdkc100。
    $0表示所有域,$0 !~ /^#/ 意思是,awk排除以#开头的行,这句话用来排除那些以#开头的注释内容。$7 ~ /^'"$2"'$/表示记录的域7必须为smdkc100。

    boards.cfg只有下面这行符合条件:
    Active  arm         armv7          s5pc1xx     samsung         smdkc100            smdkc100
    然后执行{ print $1, $2, $3, $4, $5, $6, $7, $8 }
    这样line就等于Active  arm         armv7          s5pc1xx     samsung         smdkc100            smdkc100

    接下来:
    set ${line}
    # add default board name if needed
    [ $# = 3 ] && set ${line} ${1}

    set命令
    参见《高级bash脚本编程指南》202页
    set 命令用来修改内部脚本变量的值.一个作用就是触发选项标志位来帮助决定脚本的行
    为.另一个应用就是以一个命令的结果(set `command`)来重新设置脚本的位置参数.脚本
    将会从命令的输出中重新分析出位置参数。

    所以mkconfig 的位置参数被重新定义为$(line)的内容,即:
    $1=Active  $2=arm         $3=armv7          $4=s5pc1xx     $5=samsung         $6=smdkc100            $7=smdkc100  $8=-(注意是短破折号,不是空格)
    补充一下,以上排列为:
    # Status, Arch, CPU:SPLCPU, SoC, Vendor, Board name, Target, Options
     
    对于[ $# = 3 ] && set ${line} ${1}:
    &&的说明参见《LINUX与UNIX SHELL编程指南》6.1 使用&&
    这里先判断$# 是否等于 3(明显不等),相等则执行&&右边的命令。那么,直接跳过吧。

    1 while [ $# -gt 0 ] ; do
    2     case "$1" in
    3     --) shift ; break ;;
    4     -a) shift ; APPEND=yes ;;
    5     -n) shift ; BOARD_NAME="${7%_config}" ; shift ;;
    6     -t) shift ; TARGETS="`echo $1 | sed 's:_: :g'` ${TARGETS}" ; shift ;;
    7     *)  break ;;
    8     esac
    9 done
    其实上面的参数都不会匹配到。(没有指定-a -n -t选项)
    这里只说一下${7%_config},结果等于smdkc100 ,请百度shell 截取 变量。
    %号截取,删除右边字符,保留左边字符
    echo ${var%/*}
    %/* 表示从右边开始,删除第一个 / 号及右边的字符


    实际上$7本身等于smdkc100了,那么${7%_config}依然是smdkc100。
    后面的代码比较简单了,实现如下功能:

    变量arch="arm"
    建立软连接:
    archarmincludeasmarch-s5pc1xx 生成链接符号 archarmincludeasmarch


    进入include目录
    01 # Create include file for Make
    02 #
    03 ( echo "ARCH   = ${arch}"
    04     if [ ! -z "$spl_cpu" ] ; then
    05 echo 'ifeq ($(CONFIG_SPL_BUILD),y)'
    06 echo "CPU    = ${spl_cpu}"
    07 echo "else"
    08 echo "CPU    = ${cpu}"
    09 echo "endif"
    10     else
    11 echo "CPU    = ${cpu}"
    12     fi
    13     echo "BOARD  = ${board}"
    14  
    15     [ "${vendor}" ] && echo "VENDOR = ${vendor}"
    16     [ "${soc}"    ] && echo "SOC    = ${soc}"
    17     exit 0 ) > config.mk
    include目录下生成config.mk,内容为:
    ARCH   = arm
    CPU    = armv7
    BOARD  = smdkc100
    VENDOR = samsung
    SOC    = s5pc1xx

    include目录下创建config.h

    for i in ${TARGETS} ; do
    i="`echo ${i} | sed '/=/ {s/=/ /;q; } ; { s/$/ 1/; }'`"
    echo "#define CONFIG_${i}" >>config.h ;
    done
     ${TARGETS} 为空,所以以上for循环不会被执行。

    01 echo "#define CONFIG_SYS_ARCH  "${arch}""  >> config.h
    02 echo "#define CONFIG_SYS_CPU   "${cpu}""   >> config.h
    03 echo "#define CONFIG_SYS_BOARD "${board}"" >> config.h
    04  
    05 [ "${vendor}" ] && echo "#define CONFIG_SYS_VENDOR "${vendor}"" >> config.h
    06  
    07 [ "${soc}"    ] && echo "#define CONFIG_SYS_SOC    "${soc}""    >> config.h
    08  
    09 [ "${board}"  ] && echo "#define CONFIG_BOARDDIR board/$BOARDDIR" >> config.h
    10 cat << EOF >> config.h
    11 #include <config_cmd_defaults.h>
    12 #include <config_defaults.h>
    13 #include <configs/${CONFIG_NAME}.h>
    14 #include <asm/config.h>
    15 #include <config_fallbacks.h>
    16 #include <config_uncmd_spl.h>
    17 EOF
    18  
    19 exit 0
    1 cat << EOF >> config.h表示以下内容追加到config.h中,直到出现EOF标记为止。
    最终config.h内容为:

    01 /* Automatically generated - do not edit */
    02 #define CONFIG_SYS_ARCH  "arm"
    03 #define CONFIG_SYS_CPU   "armv7"
    04 #define CONFIG_SYS_BOARD "smdkc100"
    05 #define CONFIG_SYS_VENDOR "samsung"
    06 #define CONFIG_SYS_SOC    "s5pc1xx"
    07 #define CONFIG_BOARDDIR board/samsung/smdkc100
    08 #include <config_cmd_defaults.h>
    09 #include <config_defaults.h>
    10 #include <configs/smdkc100.h>
    11 #include <asm/config.h>
    12 #include <config_fallbacks.h>
    13 #include <config_uncmd_spl.h>


     
  • 相关阅读:
    ios 动画与2D、3D绘图
    ios UI设计与开发 按钮、图标和图片
    算法基础
    快速排序
    ios网络开发 同步下载和异步下载
    用C#调用Execl
    SQL函数大全
    出差
    窗体间的互操作
    垂直滚动条代码
  • 原文地址:https://www.cnblogs.com/Ph-one/p/4923838.html
Copyright © 2011-2022 走看看