• 全志A33编译脚本分析


    0x00 环境说明:

    分析所使用的SDK为锐尔威视的开发板的资料中的Linux-SDK

    0x01 脚本分析:

    顶层目录下的build.sh:

    buildroot/scripts/mkcommon.sh $@

    本质上是调用的  buildroot/scripts/mkcommon.sh 并直接把所有的参数传过去

    mkcommon.sh前几行:

    BR_SCRIPTS_DIR=`dirname $0`

    # source shflags
    . ${BR_SCRIPTS_DIR}/shflags/shflags

    . ${BR_SCRIPTS_DIR}/mkcmd.sh

    设置目录,导入相关命令

    然后是:

    [ -f .buildconfig ] && . .buildconfig

    .buildconfig 文件存在时source该文件

    往后是:

    if [ "x$1" = "xconfig" ] ; then
         . ${BR_SCRIPTS_DIR}/mksetup.sh
         exit $?
    elif [ "x$1" = "xpack" ] ; then
         init_defconf
         mkpack
         exit $?
    elif [ "x$1" = "xpack_debug" ] ; then
         init_defconf
         mkpack -d card0
         exit $?
    elif [ "x$1" = "xpack_dump" ] ; then
         init_defconf
         mkpack -m dump
         exit $?
    elif [ "x$1" = "xpack_prvt" ] ; then
         init_defconf
         mkpack -f prvt
         exit $?
    elif [ $# -eq 0 ] ; then
         init_defconf
         mklichee
         exit $?
    fi

    根据传入的参数进行相关的操作,从上到下判断的参数依次是:

    1、config

    2、pack

    3、pack_debug

    4、pack_dump

    5、pack_prvt

    6、参数为空

    step1:“./build.sh  config”

    按照编译时的操作顺序,首先执行时传入的参数为 config,调用的是 该目录下的 mksetup.sh:

    . buildroot/scripts/mkcmd.sh

    function mksetup()
    {
         rm -f .buildconfig
         printf " "
         printf "Welcome to mkscript setup progress "

        select_board

        init_defconf
    }

    mksetup

    可以知道具体流程如下:

    1、导入 buildroot/scripts/mkcmd.sh 中符号(函数)

    2、删除配置文件 .buildconfig(顶层目录)

    3、打印提示信息

    4、执行 mkcmd.sh 中的 select_board

    5、执行 mkcmd.sh 中的 init_defconf

    在 select_board 中需要用户设置 chip、platform、kernel、board 等配置

    在 init_defconf 则主要设置一些编译时所需要的路径信息

    最终会在顶层目录的 .buildconfig 文件中生成如下信息(不同的选择会有所差异):

    export LICHEE_CHIP=sun8iw5p1
    export LICHEE_PLATFORM=dragonboard
    export LICHEE_KERN_VER=linux-3.4
    export LICHEE_BOARD=vstar

    step2:“cp  a33_vstar_defconfig  .config”

    在 Linux 内核的顶层目录下生成编译配置文件 .config

    后续可以通过命令修改配置:

    make  menuconfig

    当然也可以直接进行编辑

    step3:“./build.sh ”

    编译时直接调用 build.sh,不传入任何参数,在 mkcommon.sh 中执行的是第六条分支:

    elif [ $# -eq 0 ] ; then
         init_defconf
         mklichee
         exit $?
    fi

    其中 init_defconf 确保环境的初始化

    编译时主要执行的命令是 mklichee

    在 mkcmd.sh 文件中查看 mklichee 的实现:

    function mklichee()
    {

        mk_info "----------------------------------------"
         mk_info "build lichee ..."
         mk_info "chip: $LICHEE_CHIP"
         mk_info "platform: $LICHEE_PLATFORM"
         mk_info "kernel: $LICHEE_KERN_VER"
         mk_info "board: $LICHEE_BOARD"
         mk_info "output: out/${LICHEE_CHIP}/${LICHEE_PLATFORM}/${LICHEE_BOARD}"
         mk_info "----------------------------------------"
        
         check_env

        mkbr && mkkernel && mkrootfs
         [ $? -ne 0 ] && return 1
        
         mk_info "----------------------------------------"
         mk_info "build lichee OK."
         mk_info "----------------------------------------"
    }

    其中 mk_info 设置打印字符串的格式:

    function mk_info()
    {
         echo -e "33[47;30mINFO: $*33[0m"
    }

    mklichee 大致流程为:

    1、打印相关配置信息

    2、调用 check_env 检查环境

    3、依次调用 mkbr、mkkernel、mkrootfs

    4、检查执行结果

    mkbr:

    function mkbr()
    {
         mk_info "build buildroot ..."

        local build_script="scripts/build.sh"
         (cd ${LICHEE_BR_DIR} && [ -x ${build_script} ] && ./${build_script})
         [ $? -ne 0 ] && mk_error "build buildroot Failed" && return 1

        mk_info "build buildroot OK."
    }

    该命令实现:进入顶层目录下的 buildroot 文件夹,并执行该文件夹下的 scripts/build.sh

    buildroot/scripts/build.sh 先进行编译环境的配置,然后执行:

    case "$1" in
         clean)
             rm -rf ${LICHEE_BR_OUT}
             ;;
         *)
             if [ "x${LICHEE_PLATFORM}" = "xlinux" ] ; then
                 build_buildroot
                 export PATH=${LICHEE_BR_OUT}/external-toolchain/bin:$PATH
                 build_external
             else
                 build_toolchain
             fi
             ;;
    esac

    调用时未传入任何参数,直接跳过第一种参数为 “clean” 时的情况,后续为:

    1、当 platform 配置为 linux 时,调用build_buildroot、导出路径、调用build_external

    2、当 platform 配置其他情况(android/dragonboard)时,直接调用 build_toolchain

    其中 build_buildroot 与 build_external :

    build_buildroot()
    {
         if [ ! -f ${LICHEE_BR_OUT}/.config ] ; then
             printf " Using default config ... "
             make O=${LICHEE_BR_OUT} -C ${LICHEE_BR_DIR} ${LICHEE_BR_DEFCONF}
         fi

        make O=${LICHEE_BR_OUT} -C ${LICHEE_BR_DIR} LICHEE_GEN_ROOTFS=n
             BR2_JLEVEL=${LICHEE_JLEVEL}
    }

    build_external()
    {
         for dir in ${EXTERNAL_DIR}/* ; do
             if [ -f ${dir}/Makefile ]; then
                 BUILD_COMMAND="make -C ${dir} ${BUILD_OPTIONS} all"
                 eval $BUILD_COMMAND
                 BUILD_COMMAND="make -C ${dir} ${BUILD_OPTIONS} install"
                 eval $BUILD_COMMAND
             fi
         done
    }

    build_buildroot 编译生成 交叉工具链(arm-linux-gnueabi),其中:

    LICHEE_PLAT_OUT="${LICHEE_OUT_DIR}/${LICHEE_CHIP}/${LICHEE_PLATFORM}/${out_dir}"

    LICHEE_BR_OUT="${LICHEE_PLAT_OUT}/buildroot"

    build_external 编译扩展的软件工具包,其中:

    EXTERNAL_DIR=${LICHEE_BR_DIR}/external-packages

    build_toolchain:

    build_toolchain()
    {
         local tooldir="${LICHEE_BR_OUT}/external-toolchain"
         mkdir -p ${tooldir}
         if [ -f ${tooldir}/.installed ] ; then
             printf "external toolchain has been installed "
         else
             printf "installing external toolchain "
             printf "please wait for a few minutes ... "
             tar --strip-components=1
                 -jxf ${LICHEE_BR_DIR}/dl/gcc-linaro.tar.bz2
                 -C ${tooldir}
             [ $? -eq 0 ] && touch ${tooldir}/.installed
         fi

        export PATH=${tooldir}/bin:${PATH}
    }

    作用是直接安装交叉工具链(gcc-linaro),路径为:${LICHEE_BR_DIR}/dl/gcc-linaro.tar.bz2

    mkbr到这里就分析完了,下面看mkkernel:

    function mkkernel()
    {
         mk_info "build kernel ..."

        local build_script="scripts/build.sh"

        prepare_toolchain

        # mark kernel .config belong to which platform
         local config_mark="${LICHEE_KERN_DIR}/.config.mark"
         if [ -f ${config_mark} ] ; then
             if ! grep -q "${LICHEE_PLATFORM}" ${config_mark} ; then
                 mk_info "clean last time build for different platform"
                 (cd ${LICHEE_KERN_DIR} && [ -x ${build_script} ] && ./${build_script} "clean")
                 echo "${LICHEE_PLATFORM}" > ${config_mark}
             fi
         else
             echo "${LICHEE_PLATFORM}" > ${config_mark}
         fi

        (cd ${LICHEE_KERN_DIR} && [ -x ${build_script} ] && ./${build_script})
         [ $? -ne 0 ] && mk_error "build kernel Failed" && return 1

        mk_info "build kernel OK."
    }

    流程为处理配置文件之后调用 linux3.4/scripts/build.sh 编译Linux内核:

    case "$1" in
    kernel)
         build_kernel
         ;;
    modules)
         build_modules
         ;;
    clean)
         clean_kernel
         clean_modules
         ;;
    *)
         build_kernel
         build_modules
         build_ramfs
         gen_output
         ;;
    esac

    下面分析 mkrootfs:

    function mkrootfs()
    {
         mk_info "build rootfs ..."
        
         if [ ${LICHEE_PLATFORM} = "linux" ] ; then
             make O=${LICHEE_BR_OUT} -C ${LICHEE_BR_DIR} target-generic-getty-busybox
             [ $? -ne 0 ] && mk_error "build rootfs Failed" && return 1
             make O=${LICHEE_BR_OUT} -C ${LICHEE_BR_DIR} target-finalize
             [ $? -ne 0 ] && mk_error "build rootfs Failed" && return 1
             make O=${LICHEE_BR_OUT} -C ${LICHEE_BR_DIR} LICHEE_GEN_ROOTFS=y rootfs-ext4
             [ $? -ne 0 ] && mk_error "build rootfs Failed" && return 1
             cp ${LICHEE_BR_OUT}/images/rootfs.ext4 ${LICHEE_PLAT_OUT}
         elif [ ${LICHEE_PLATFORM} = "dragonboard" ] ; then
             echo "Regenerating dragonboard Rootfs..."
             (
                 cd ${LICHEE_BR_DIR}/target/dragonboard;
                 if [ ! -d "./rootfs" ]; then
                 echo "extract dragonboard rootfs.tar.gz";
                 tar zxf rootfs.tar.gz;
                 fi
             )
             mkdir -p ${LICHEE_BR_DIR}/target/dragonboard/rootfs/lib/modules
             rm -rf ${LICHEE_BR_DIR}/target/dragonboard/rootfs/lib/modules/*
             cp -rf ${LICHEE_KERN_DIR}/output/lib/modules/* ${LICHEE_BR_DIR}/target/dragonboard/rootfs/lib/modules/
             (cd ${LICHEE_BR_DIR}/target/dragonboard; ./build.sh)
             cp ${LICHEE_BR_DIR}/target/dragonboard/rootfs.ext4 ${LICHEE_PLAT_OUT}
         else
             mk_info "skip make rootfs for ${LICHEE_PLATFORM}"
         fi

        mk_info "build rootfs OK."
    }

    作用是生成根文件系统,按照配置的平台的不同分为以下情况:

    1、linux:从头开始编译根文件系统

    2、dragonboard:直接解压打包好的根文件系统(rootfs.tar.gz),然后加入相关的驱动模块

    3、android:直接跳过,android的根文件系统不在这里生成

    如果需要进行根文件系统的定制修改,需要分析 mkrootfs 的一些细节

     

    0x02 简单汇总:

    最后贴上笔者分析过程中的简单笔记,分析的时候可以凑合着看

    build.sh-> buildroot/scripts/mkcommon.sh $@

    . ./mkcmd.sh(导入相关编译命令)
    [ -f .buildconfig ] && . .buildconfig

    $1==config:
         mksetup.sh
             rm -f .buildconfig(build.sh目录下)
             select_board
             init_defconf(配置输出路径)
                 LICHEE_PLAT_OUT:/root/a33_linux/dragonboard/out/sun8iw5p1/linux/common
                 LICHEE_BR_OUT:/root/a33_linux/dragonboard/out/sun8iw5p1/linux/common/buildroot

    $1==pack:
         init_defconf
         mkpack
             check_env
             (cd ${LICHEE_TOOLS_DIR}/pack &&
                 ./pack -c ${LICHEE_CHIP} -p ${LICHEE_PLATFORM} -b ${LICHEE_BOARD} $@)
    ./pack -c sun8iw5p1 -p linux -b vstar
                
    $1为空:
         init_defconf
         mklichee
             mk_info(打印一些配置信息)
             check_env(检查配置,即检查之前有没有运行"./build.sh config"命令)
             mkbr && mkkernel && mkrootfs
                 mkbr:(编译buildroot)
                     执行scripts/build.sh
                 mkkernel:(编译内核)
                     prepare_toolchain(检查工具链)
                     使用${LICHEE_KERN_DIR}/.config.mark文件中的平台设置
                     执行scripts/build.sh
                 mkrootfs:(编译rootfs)
                     linux:
                         make O=${LICHEE_BR_OUT} -C ${LICHEE_BR_DIR} target-generic-getty-busybox
                         make O=${LICHEE_BR_OUT} -C ${LICHEE_BR_DIR} target-finalize
                         make O=${LICHEE_BR_OUT} -C ${LICHEE_BR_DIR} LICHEE_GEN_ROOTFS=y rootfs-ext4
                         cp ${LICHEE_BR_OUT}/images/rootfs.ext4 ${LICHEE_PLAT_OUT}               
                     dragonboard:
                         cd ${LICHEE_BR_DIR}/target/dragonboard
                         tar zxf rootfs.tar.gz
                         mkdir -p ${LICHEE_BR_DIR}/target/dragonboard/rootfs/lib/modules
                         rm -rf ${LICHEE_BR_DIR}/target/dragonboard/rootfs/lib/modules/*     
                         cp -rf ${LICHEE_KERN_DIR}/output/lib/modules/* ${LICHEE_BR_DIR}/target/dragonboard/rootfs/lib/modules/
                         (cd ${LICHEE_BR_DIR}/target/dragonboard; ./build.sh)
                         cp ${LICHEE_BR_DIR}/target/dragonboard/rootfs.ext4 ${LICHEE_PLAT_OUT}               
                     Android:(Android不在这里编译根文件系统)
    #make O=/root/a33_linux/dragonboard/out/sun8iw5p1/linux/common/buildroot
                    
    scripts/build.sh:
    $1==clean:   
         rm -rf ${LICHEE_BR_OUT}
    默认:
         ${LICHEE_PLATFORM}==linux:
             build_buildroot
             export PATH=${LICHEE_BR_OUT}/external-toolchain/bin:$PATH
             build_external
         默认:
             build_toolchain

  • 相关阅读:
    shFlags简介
    ubuntu下mediawiki的使用
    保护眼睛(ubuntu 和 chrome)
    ubuntu14.04下安装ngnix,mediawiki,nodebb,everything,gitlab
    JavaScript之闭包就是个子公司
    第三次作业——个人作业——软件产品案例分析
    第二次作业——结对项目之需求分析与原型设计
    《软件工程实践》第一次作业
    2016的软件工程开始啦
    Spring-Boot-应用可视化监控
  • 原文地址:https://www.cnblogs.com/DarkBright/p/11068042.html
Copyright © 2020-2023  润新知