全志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 "\n"
     printf "Welcome to mkscript setup progress\n"

    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 "\033[47;30mINFO: $*\033[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 "\nUsing default config ...\n\n"
         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\n"
     else
         printf "installing external toolchain\n"
         printf "please wait for a few minutes ...\n"
         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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM