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>


     
  • 相关阅读:
    docker 部署aps.net MVC到windows容器
    docker 搭建私有仓库 harbor
    解决关于:Oracle数据库 插入数据中文乱码 显示问号???
    ionic cordova build android error: commamd failed with exit code eacces
    cordova build android Command failed with exit code EACCES
    Xcode 10 iOS12 "A valid provisioning profile for this executable was not found
    使用remix发布部署 发币 智能合约
    区块链: 编译发布智能合约
    mac 下常用命令备忘录
    JQuery fullCalendar 时间差 排序获取距当前最近的时间。
  • 原文地址:https://www.cnblogs.com/Ph-one/p/4923838.html
Copyright © 2011-2022 走看看