android lichee编译脚本解析

时间:2021-12-02 19:55:36
#编译流程

#lichee 目录下

./build.sh -psun7i_android -k 3.4

 

#build.sh 解析

 

#!/bin/bash

 

set -e  

#"Exitimmediately if a simple command exits with a non-zero status."

#也就是说,在"set -e"之后出现的代码,一旦出现了返回值非零,整个脚本就会立即退出

 

buildroot/scripts/mkcommon.sh$@  #$@ 为参数 -p sun7i_android -k 3.4

 

#mkcommon.sh

#!/bin/bash

#

#scripts/mkcommon.sh

# (c) Copyright2013

# AllwinnerTechnology Co., Ltd. <www.allwinnertech.com>

# James Deng<csjamesdeng@allwinnertech.com>

#

# This program isfree software; you can redistribute it and/or modify

# it under theterms of the GNU General Public License as published by

# the FreeSoftware Foundation; either version 2 of the License, or

# (at your option)any later version.

 

BR_SCRIPTS_DIR=`dirname$0` #提取出运行目录 ./buildroot/scripts/

 

if ["$1" = "pack" ] ; then #如果是运行打包动作

    ${BR_SCRIPTS_DIR}/build_pack.sh  #运行打包脚本

    exit 0

fi

 

# source shflags

.${BR_SCRIPTS_DIR}/shflags/shflags  #加载命令行工具

 

.${BR_SCRIPTS_DIR}/mkcmd.sh       #加载shell编译脚本

 

# define option,format:

#   'long option' 'default value' 'help message''short option'

#命令行工具shflags使用

#三个参数含义分别为命令行参数名,参数默认值,以及参数的帮助信息

 

DEFINE_string'platform' 'sun7i' 'platform to build, e.g. sun7i' 'p'

DEFINE_string'kernel' '3.4' 'kernel to build, e.g. 3.3' 'k'

DEFINE_string'board' '' 'board to build, e.g. evb' 'b'

DEFINE_string'module' '' 'module to build, e.g. buildroot, kernel, uboot, clean' 'm'

DEFINE_boolean'independent' false 'output build to independent directory' 'i'

 

# parse thecommand-line

# 解析传进来的参数

FLAGS"$@" || exit $?

#语法:eval cmdLine

#eval会对后面的cmdLine进行两遍扫描,如果第一遍扫描后,cmdLine是个普通命令,则执行此命令;

#如果cmdLine中含有变量的间接引用,则保证间接引用的语义。

 

eval set --"${FLAGS_ARGV}"

                               #参数是: -p sun7i_android -k 3.4

chip=${FLAGS_platform%%_*}     #提取出chip    sun7i

platform=${FLAGS_platform##*_}#提取出平台   android

kernel=${FLAGS_kernel}        #提取出内核     3.4  

board=${FLAGS_board}           #提取出板子     这里空

module=${FLAGS_module}         #提取出模块     这里空

 

if ["${platform}" = "${chip}" ] ; then  #如果未指定平台,默认为linux

    platform="linux"

fi

 

if [ -z"${module}" ] ; then    #如果未指定模块,默认编译所有

    module="all"

fi

 

if ! init_chips${chip} || \               #初始化芯片参数: sun7i

            #查询该目录下{LICHEE_TOOLS_DIR}/pack/chips/是否有 以该芯片命名的目录

            #并导出该变量  exportLICHEE_CHIP=${chip}

   ! init_platforms ${chip} ${platform} ; then

            #检查是否支持该平台

            #并导出  exportLICHEE_PLATFORM=${platform}

    mk_error "invalid platform'${FLAGS_platform}'"

    exit 1

fi

 

if [ ${FLAGS_board}] && \  #如果指定了板子,检查是否支持该板子

   ! init_boards ${chip} ${platform} ${board} ;then

    mk_error "invalid board'${FLAGS_board}'"

    exit 1

fi

 

if ["${kernel}" = "3.3" ] ; then #如果指定了内核3.3 ,判断该目录是否存在

                                 # 3.4 就不检查了?

    LICHEE_KERN_DIR=${LICHEE_TOP_DIR}/linux-3.3

    if [ ! -d ${LICHEE_KERN_DIR} ] ; then

        mk_error "invalid kernel'${kernel}'"

        exit 1

    fi

fi

 

# init outputdirectory

init_outdir  #初始化输出目录,检查配置是否存在

             #这里默认配置:sun7ismp_android_defconfig,配置组成在check_kern_defconf 函数中

             #请自己查看

             #设置了导出目录:

             # exportLICHEE_PLAT_OUT="${LICHEE_OUT_DIR}/${LICHEE_PLATFORM}/common"

             #导出plat 目录 .../lichee/out/android/common

             #export LICHEE_BR_OUT="${LICHEE_PLAT_OUT}/buildroot"

             #导出 br  目录 ../lichee/out/android/common/buildroot

 

if [ ${module} ="all" ]; then

    mklichee

elif [ ${module} ="boot" ] ; then

    mkboot

elif [ ${module} ="buildroot" ] ; then

    mkbr

elif [ ${module} ="kernel" ] ; then

    mkkernel

elif [ ${module} ="uboot" ] ; then

    mkuboot

elif [ ${module} ="clean" ] ; then

    mkclean

elif [ ${module} ="mrproer" ] ; then

    mkmrproer

elif [ ${module} ="distclean" ] ; then

    mkdistclean

else

   mk_error "invalid module '${module}'"

    exit 1

fi

 

exit $?

 

#编译all

functionmklichee()

{

    mksetting #打印编译信息

 

    mk_info "build lichee ..."  #显示编译,带颜色显示

 

    #编译交叉编译工具 ----这里就不分析了

    #编译内核

    #编译uboot

    #编译文件系统

    mkbr && mkkernel && mkuboot&& mkrootfs

    [ $? -ne 0 ] && return 1

 

    mk_info "build lichee OK."

}

 

编译内核所做的事情:

#,根据平台配置,编译内核 ,把编译好的内核,模块 以及.config 拷到了output 目录下

#把output 目录下的所有内容,LICHEE_PLAT_OUT

#也就是 …/lichee/out/android/common

编译uboot 所做的事情

# 根据平台选择编译脚本 —–其实这一步没起作用,最终用的build.sh

# 先make distclean ,再根据芯片 sun7i进行编译,生成u-boot.bin

#所有这里可以选择把distclean 去掉,节约编译时间

# 把u-boot.bin拷贝到了 lichee/out/android/common 目录下

编译rootfs所做的事情:

#根据linux 或者dragonboard 做相应的操作

# 而这 do nothing ,skip

 

//———————————-other————————————

 

functionmkrootfs()

{

    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 dragonboardRootfs..."

        (cd${LICHEE_BR_DIR}/target/dragonboard; \

            if [ ! -d "./rootfs" ];then \

            echo "extract dragonboardrootfs.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."

}

 

 

# return true ifused default config

functioncheck_uboot_defconf()

{

    local defconf

    local ret=1

 

    defconf="${LICHEE_CHIP}_${LICHEE_PLATFORM}_${LICHEE_BOARD}"

                     #编译 sun7i_android

                     #这里少了一个.sh,脚本有问题:sun7i_android.sh

    if [ ! -f${LICHEE_UBOOT_DIR}/include/configs/${defconf} ] ; then

        ret=0

        defconf="${LICHEE_CHIP}"  #这里少了一个.sh 应该为:sun7i.sh

    fi

    export LICHEE_UBOOT_DEFCONF=${defconf}

 

    return ${ret}

}

function mkuboot()

{

    mk_info "build u-boot ..."

 

    local build_script

 

    if check_uboot_defconf ; then #查看配置是是否存在,指定编译脚本

        build_script="build.sh"  #运行此编译脚本

    else

       build_script="build_${LICHEE_CHIP}_${LICHEE_PLATFORM}_${LICHEE_BOARD}.sh"

    fi

 

    prepare_toolchain

    //运行编译脚本

    (cd ${LICHEE_UBOOT_DIR} && [ -x${build_script} ] && ./${build_script})

    [ $? -ne 0 ] && mk_error"build u-boot Failed" && return 1

 

    mk_info "build u-boot OK."

}

 

 

#关键的编译函数:

functionbuild_uboot()

{

    case "$1" in

        clean)

            make distcleanCROSS_COMPILE=arm-linux-gnueabi-

            ;;

        *)

            make distcleanCROSS_COMPILE=arm-linux-gnueabi-  #清楚所有配置

            make -j${jobs} ${LICHEE_CHIP}CROSS_COMPILE=arm-linux-gnueabi-

                #根据芯片 编译   这里是sun7i

            [ $? -ne 0 ] && exit 1

            #拷贝u-boot.bin 到输出目录

            cp -f u-boot.bin ../out/${LICHEE_PLATFORM}/common/

            ;;

    esac

}

 

 

functionmksetting()    #打印要编译的信息

{

    printf "\n"

    printf "mkscript currentsetting:\n"

    printf "        Chip: ${LICHEE_CHIP}\n"

    printf "    Platform: ${LICHEE_PLATFORM}\n"

    printf "       Board: ${LICHEE_BOARD}\n"

    printf "  Output Dir: ${LICHEE_PLAT_OUT}\n"

    printf "\n"

}

 

编译内核函数

 

functionmkkernel()

{

    mk_info "build kernel ..."

    local build_script

    if check_kern_defconf ; then #检查设置,编译配置文件

        if [ ${LICHEE_PLATFORM} ="linux" ] ; then

           build_script="scripts/build_${LICHEE_CHIP}.sh"

        else

           build_script="scripts/build_${LICHEE_CHIP}_${LICHEE_PLATFORM}.sh"

            #指定编译脚本 scripts/build_sun7i_android.sh

        fi

    else

        build_script="scripts/build_${LICHEE_CHIP}_${LICHEE_PLATFORM}_${LICHEE_BOARD}.sh"

    fi

 

    prepare_toolchain #准备交叉编译工具,就是导出环境变量

                     #lichee/out/android/common/buildroot/external-toolchain

 

    # mark kernel .config belong to whichplatform

    localconfig_mark="${LICHEE_KERN_DIR}/.config.mark" #标记编译平台 android

    if [ -f ${config_mark} ] ; then

        if ! grep -q"${LICHEE_PLATFORM}" ${config_mark} ; then

            mk_info "clean last time buildfor 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

    #进入内核目录 ,检查编译脚本是否可执行,执行该脚本

    #./scripts/build_sun7i_android.sh

    (cd ${LICHEE_KERN_DIR} && [ -x${build_script} ] && ./${build_script})

    [ $? -ne 0 ] && mk_error"build kernel Failed" && return 1

 

    mk_info "build kernel OK."

}

 

脚本#build_sun7i_android.sh 如下

 

#!/bin/bash

#

#scripts/build_sun7i_android.h

#

# (c) Copyright2013

# AllwinnerTechnology Co., Ltd. <www.allwinnertech.com>

# James Deng<csjamesdeng@allwinnertech.com>

#

# This program isfree software; you can redistribute it and/or modify

# it under theterms of the GNU General Public License as published by

# the FreeSoftware Foundation; either version 2 of the License, or

# (at your option)any later version.

 

set -e

 

cpu_cores=`cat/proc/cpuinfo | grep "processor" | wc -l`

if [ ${cpu_cores}-le 8 ] ; then

    jobs=${cpu_cores}

else

    jobs=`expr ${cpu_cores} / 2`

fi

 

# Setup commonvariables

export ARCH=arm

exportCROSS_COMPILE=arm-linux-gnueabi-

exportAS=${CROSS_COMPILE}as

exportLD=${CROSS_COMPILE}ld

exportCC=${CROSS_COMPILE}gcc

exportAR=${CROSS_COMPILE}ar

exportNM=${CROSS_COMPILE}nm

exportSTRIP=${CROSS_COMPILE}strip

exportOBJCOPY=${CROSS_COMPILE}objcopy

exportOBJDUMP=${CROSS_COMPILE}objdump

 

KERNEL_VERSION="3.4"

LICHEE_KDIR=`pwd`

LICHEE_MOD_DIR=${LICHEE_KDIR}/output/lib/modules/${KERNEL_VERSION}

export LICHEE_KDIR

 

build_standby()

{

    echo "build standby"

 

    # If .config is newer thaninclude/config/auto.conf, someone tinkered

    # with it and forgot to run make oldconfig.

    # if auto.conf.cmd is missing then we areprobably in a cleaned tree so

    # we execute the config step to be sure tocatch updated Kconfig files

    if [ .config -nt include/config/auto.conf-o \

        ! -f include/config/auto.conf.cmd ] ;then

        echo "Generating autoconf.h forstandby"

        make -f Makefile ARCH=armCROSS_COMPILE=${CROSS_COMPILE} \

            silentoldconfig

    fi

    make ARCH=${ARCH}CROSS_COMPILE=${CROSS_COMPILE} KDIR=${LICHEE_KDIR} \

        -C ${LICHEE_KDIR}/arch/arm/mach-sun7i/pm/standbyall

}

 

NAND_ROOT=${LICHEE_KDIR}/modules/nand

 

build_nand_lib()

{

    echo "build nand library${NAND_ROOT}/lib"

    if [ -d ${NAND_ROOT}/lib ]; then

        echo "build nand library now"

        make -C modules/nand/lib clean 2>/dev/null

        make -C modules/nand/lib lib install

    else

        echo "build nand with existinglibrary"

    fi

}

 

HDMI_ROOT=${LICHEE_KDIR}/drivers/video/sun7i/hdmi/aw

build_hdmi_lib()

{

    echo "build hdcp library${HDMI_ROOT}/hdcp"

    if [ -d ${HDMI_ROOT}/hdcp ]; then

        echo "build hdcp library now"

#       make -C ${HDMI_ROOT}/hdcp clean  2>/dev/null

        make -C ${HDMI_ROOT}/hdcp install

    else

        echo "build hdcp with existinglibrary"

    fi

}

 

build_kernel()

{

    echo "Building kernel"

 

    if [ ! -f .config ] ; then #如果配置文件不存在,则拷贝编译脚本

        printf "\n\033[0;31;1mUsingdefault config ...\033[0m\n\n"

        cparch/arm/configs/${LICHEE_KERN_DEFCONF} .config

    fi

 

    build_standby

    #编译内核

    make ARCH=armCROSS_COMPILE=${CROSS_COMPILE} -j${jobs} uImage modules

 

    #二进制拷贝

    ${OBJCOPY} -R .note.gnu.build-id -S -Obinary vmlinux bImage

 

    #删除原来的输出目录

    rm -rf output

    #创建模块输出目录

    mkdir -p ${LICHEE_MOD_DIR}

 

    #拷贝内核文件

    cp bImage output/

    #把配置文件也拷贝到了输出目录

    cp .config output/

 

    #把所有 模块拷贝到了 output/lib/modules/3.4/

    for file in $(find drivers sound cryptoblock fs security net -name "*.ko"); do

        cp $file ${LICHEE_MOD_DIR}

    done

    cp -f Module.symvers ${LICHEE_MOD_DIR}

 

    #cpdrivers/net/wireless/bcm4330/firmware/bcm4330.bin ${LICHEE_MOD_DIR}

    #cpdrivers/net/wireless/bcm4330/firmware/bcm4330.hcd ${LICHEE_MOD_DIR}

    #cpdrivers/net/wireless/bcm4330/firmware/nvram.txt${LICHEE_MOD_DIR}/bcm4330_nvram.txt

}

 

build_modules()

{

    echo "Building modules"

 

    if [ ! -f include/generated/utsrelease.h ];then

        printf "Please build kernelfirst\n"

        exit 1

    fi

 

    make -C modules/exampleLICHEE_MOD_DIR=${LICHEE_MOD_DIR} LICHEE_KDIR=${LICHEE_KDIR} \

        install

 

    build_nand_lib

    make -C modules/nandLICHEE_MOD_DIR=${LICHEE_MOD_DIR} LICHEE_KDIR=${LICHEE_KDIR} \

        install

 

    build_hdmi_lib

    make -C drivers/video/sun7i/hdmi/awLICHEE_MOD_DIR=${LICHEE_MOD_DIR} LICHEE_KDIR=${LICHEE_KDIR} \

        install

 

    (

    export LANG=en_US.UTF-8

    unset LANGUAGE

    make -C modules/maliLICHEE_MOD_DIR=${LICHEE_MOD_DIR} LICHEE_KDIR=${LICHEE_KDIR} \

        install

    )

 

    ##build ar6302 sdio wifi module

    #make -C modules/wifi/ar6302/AR6K_SDK_ISC.build_3.1_RC.329/hostCROSS_COMPILE=${CROSS_COMPILE} \

    #   ARCH=arm KERNEL_DIR=${LICHEE_KDIR} INSTALL_DIR=${LICHEE_MOD_DIR} \

    #   all install

    ##build ar6003 sdio wifi module

    #make -Cmodules/wifi/ar6003/AR6kSDK.build_3.1_RC.514/hostCROSS_COMPILE=${CROSS_COMPILE} \

    #   ARCH=arm KERNEL_DIR=${LICHEE_KDIR} INSTALL_DIR=${LICHEE_MOD_DIR} \

    #   all

    ##build usi-bmc4329 sdio wifi module

    #make -C modules/wifi/usi-bcm4329/v4.218.248.15/open-src/src/dhd/linux\

    #   CROSS_COMPILE=${CROSS_COMPILE} ARCH=arm LINUXVER=${KERNEL_VERSION} \

    #   LICHEE_MOD_DIR=${LICHEE_MOD_DIR} LINUXDIR=${LICHEE_KDIR} \

    #   INSTALL_DIR=${LICHEE_MOD_DIR} dhd-cdc-sdmmc-gpl

    ##build bcm40181 sdio wifi module5.90.125.69.2

    #make -Cmodules/wifi/bcm40181/5.90.125.69.2/open-src/src/dhd/linux \

    #   CROSS_COMPILE=${CROSS_COMPILE} ARCH=arm LINUXVER=${KERNEL_VERSION} \

    #   LICHEE_MOD_DIR=${LICHEE_MOD_DIR} LINUXDIR=${LICHEE_KDIR} \

    #   INSTALL_DIR=${LICHEE_MOD_DIR} OEM_ANDROID=1 dhd-cdc-sdmmc-gpl

    ##build bcm40183 sdio wifi module

    #make -Cmodules/wifi/bcm40183/5.90.125.95.3/open-src/src/dhd/linux \

    #   CROSS_COMPILE=${CROSS_COMPILE} ARCH=arm LINUXVER=${KERNEL_VERSION} \

    #   LICHEE_MOD_DIR=${LICHEE_MOD_DIR} LINUXDIR=${LICHEE_KDIR} \

    #   INSTALL_DIR=${LICHEE_MOD_DIR} OEM_ANDROID=1 dhd-cdc-sdmmc-gpl

}

 

gen_output()

{

    echo "Copy output to target ..."

    rm -rf ${LICHEE_PLAT_OUT}/lib

    cp -rf ${LICHEE_KDIR}/output/*${LICHEE_PLAT_OUT}

}

 

clean_kernel()

{

    echo "Cleaning kernel"

    make distclean

    rm -rf output/*

}

 

clean_modules()

{

    echo "Cleaning modules"

    make -C modules/exampleLICHEE_MOD_DIR=${LICHEE_MOD_DIR} LICHEE_KDIR=${LICHEE_KDIR} clean

 

    (

    export LANG=en_US.UTF-8

    unset LANGUAGE

    make -C modules/maliLICHEE_MOD_DIR=${LICHEE_MOD_DIR} LICHEE_KDIR=${LICHEE_KDIR} clean

    )

 

    ##build ar6302 sdio wifi module

    #make -Cmodules/wifi/ar6302/AR6K_SDK_ISC.build_3.1_RC.329/hostCROSS_COMPILE=${CROSS_COMPILE} \

    #   ARCH=arm KERNEL_DIR=${LICHEE_KDIR} INSTALL_DIR=${LICHEE_MOD_DIR} \

    #   clean

    ##build ar6003 sdio wifi module

    #make -Cmodules/wifi/ar6003/AR6kSDK.build_3.1_RC.514/hostCROSS_COMPILE=${CROSS_COMPILE} \

    #   ARCH=arm KERNEL_DIR=${LICHEE_KDIR} INSTALL_DIR=${LICHEE_MOD_DIR} \

    #   clean

    ##build usi-bmc4329 sdio wifi module

    #make -C modules/wifi/usi-bcm4329/v4.218.248.15/open-src/src/dhd/linux\

    #   CROSS_COMPILE=${CROSS_COMPILE} ARCH=arm LINUXVER=${KERNEL_VERSION} \

    #   LICHEE_MOD_DIR=${LICHEE_MOD_DIR} LINUXDIR=${LICHEE_KDIR} \

    #   INSTALL_DIR=${LICHEE_MOD_DIR} clean

    ##build bcm40181 sdio wifi module5.90.125.69.2

    #make -Cmodules/wifi/bcm40181/5.90.125.69.2/open-src/src/dhd/linux \

    #   CROSS_COMPILE=${CROSS_COMPILE} ARCH=arm LINUXVER=${KERNEL_VERSION} \

    #   LICHEE_MOD_DIR=${LICHEE_MOD_DIR} LINUXDIR=${LICHEE_KDIR} \

    #   INSTALL_DIR=${LICHEE_MOD_DIR} clean

    ##build bcm40183 sdio wifi module

    #make -Cmodules/wifi/bcm40183/5.90.125.95.3/open-src/src/dhd/linux \

    #   CROSS_COMPILE=${CROSS_COMPILE} ARCH=arm LINUXVER=${KERNEL_VERSION} \

    #   LICHEE_MOD_DIR=${LICHEE_MOD_DIR} LINUXDIR=${LICHEE_KDIR} \

    #   INSTALL_DIR=${LICHEE_MOD_DIR} OEM_ANDROID=1 clean

}

 

case"$1" in

    kernel)

        build_kernel

        ;;

    modules)

        build_modules

        ;;

    clean)

        clean_modules

        clean_kernel

        ;;

    *)

        build_kernel  #编译内核 ,把编译好的内核,模块 拷到了output 目录下

        build_modules #变所有模块

        gen_output   #把output 目录下的所有内核,LICHEE_PLAT_OUT

                     #也就是 .../lichee/out/android/common

        ;;

esac

 

functioninit_chips()

{

    local chip=$1  #传进来的参数:sun7i

    local cnt=0

    local ret=1

    for chipdir in${LICHEE_TOOLS_DIR}/pack/chips/* ; do

        chips[$cnt]=`basename $chipdir`

        if [ ${chips[$cnt]} = ${chip} ] ;then  #检测是否有该芯片的目录

            ret=0

            export LICHEE_CHIP=${chip}

        fi

        ((cnt+=1))

    done

 

    return ${ret}

}

 

functioninit_platforms()

{

    local chip=$1 #传进来的芯片 sun7i

    local platform=$2 #传进来的平台 android

    local cnt=0

    local ret=1

    for platdir in${LICHEE_TOOLS_DIR}/pack/chips/${chip}/configs/* ; do

        platforms[$cnt]=`basename $platdir`

        if [ ${platforms[$cnt]} = ${platform} ]; then  #检查是否支持该平台打包

            ret=0

            export LICHEE_PLATFORM=${platform}

        fi

        ((cnt+=1))

    done

 

    return ${ret}

}

 

# output toout/<chip>/<platform>/common directory only when

# both buildrootand kernel use default config file.

functioninit_outdir()

{

    if check_br_defconf &&check_kern_defconf ; then

            #check_kern_defconf  检查配置是否存在

        exportLICHEE_PLAT_OUT="${LICHEE_OUT_DIR}/${LICHEE_PLATFORM}/common"

            #导出plat 目录 .../lichee/out/android/common

        exportLICHEE_BR_OUT="${LICHEE_PLAT_OUT}/buildroot"

           #导出 br  目录 ../lichee/out/android/common/buildroot

 

    else

        exportLICHEE_PLAT_OUT="${LICHEE_OUT_DIR}/${LICHEE_PLATFORM}/${LICHEE_BOARD}"

        exportLICHEE_BR_OUT="${LICHEE_PLAT_OUT}/buildroot"

    fi

 

    mkdir -p ${LICHEE_BR_OUT} #创建目录

}

 

 

android编译命令分析

 

 

 

一.lichee下的编译

cong@dell:/work/ct/lichee$./build.sh -p sun7i_android

1.  ./build.sh -p sun7i_androi

 

    buildroot/scripts/mkcommon.sh $@

 

在lichee/buildroot/scripts/mkcommon.sh中

     根据module参数来执行不同的命令,默认是mklichee

 

    BR_SCRIPTS_DIR=buildroot/scripts

    chip=sun7i platform=android board= module=

    . ${BR_SCRIPTS_DIR}/mkcmd.sh

    mklichee

 

2.mklichee

在lichee/buildroot/scripts/mkcmd.sh中

 

    function mklichee()

    {

        mksetting                      //一些打印

        mk_info "build lichee..."     //一些打印

        

        mkbr                         //2.1解压交叉工具链

        mkkernel                     //2.2编译standby+内核+ko模块

        mkuboot                      //2.3编译uboot 

        mkrootfs                     //2.4解压交叉工具链 

    

        mk_info "build lichee OK."

    }

 

2.1 mkbr

在lichee/buildroot/scripts/mkcmd.sh中mkbr

mkbr的意思是: 解压交叉编译工具链

 

    function mkbr()

    {

       build_script="scripts/build_${LICHEE_CHIP}_${LICHEE_PLATFORM}.sh"

        (cd ${LICHEE_BR_DIR} && [ -x${build_script} ] && ./${build_script})

    }

 

即: cd /work/ct/lichee/buildroot && [-x scripts/build_sun7i_android.sh ] && ./scripts/build_sun7i_android.sh

会调用/work/ct/lichee/buildroot/scripts/build_sun7i_android.sh来检查

    /work/ct/lichee/out/android/common/buildroot/external-toolchain这个目录下是否存在.install的文件,不存在则解压

2.2 mkkernel

在lichee/buildroot/scripts/mkcmd.sh中mkkernel

 

    function mkkernel()

    {

       build_script="scripts/build_${LICHEE_CHIP}_${LICHEE_PLATFORM}.sh"

 

        prepare_toolchain                                 //检查编译工具链,如果不存在则调用上面的mkbr

 

        // 在/work/ct/lichee/linux-3.3/.config.mark中写入字符串"android"作为标记

        localconfig_mark="${LICHEE_KERN_DIR}/.config.mark"

        if [ -f ${config_mark} ] ; then

            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."

    }

 

(cd/work/ct/lichee/linux-3.3 && [ -x scripts/build_sun7i_android.sh ]&& ./scripts/build_sun7i_android.sh)

  2.2.1 mkkernel的具体编译

在/work/ct/lichee/linux-3.3/scripts/build_sun7i_android.sh中

因为没有参数,所以要执行三步: build_kernel, build_modules 和 gen_output

        build_kernel

                a. 将 arch/arm/configs/sun7ismp_android_defconfig拷贝到 ./.config

                b. build_standby      在/work/ct/lichee/linux-3.3/arch/arm/mach-sun7i/pm/standby中

                c. 编译内核 uImage 和 modules,

                                  将vmlinux objcopy -O binary就成了bImage,这样 [buz]Image都有了

                                  再将 [buz]Image--> lichee/linux-3.3/output

                                  将所有的ko -->./lichee/linux-3.3/output/lib/modules/3.3/下

        build_modules     编译放在 ./lichee/linux-3.3/modules中的驱动

        gen_output         把上述所有的内容拷贝到: /work/ct/lichee/out/android/common

    所以/work/ct/lichee/linux-3.3/output/ 与 /work/ct/lichee/out/android/common/中的内容基本一样(少了buildroot)

2.3 mkuboot

 在lichee/buildroot/scripts/mkcmd.sh中mkuboot

 

    function mkuboot()

    {

        mk_info "build u-boot ..."

 

        local build_script

 

        if check_uboot_defconf ; then

            build_script="build.sh"

        else

           build_script="build_${LICHEE_CHIP}_${LICHEE_PLATFORM}_${LICHEE_BOARD}.sh"

        fi

 

       prepare_toolchain        //检查编译工具链,如果不存在则调用上面的mkbr

      

        //即执行./ct/lichee/u-boot/build.sh

        (cd ${LICHEE_UBOOT_DIR} && [ -x${build_script} ] && ./${build_script})

        [ $? -ne 0 ] && mk_error"build u-boot Failed" && return 1

 

       mk_info "build u-boot OK."

    }

 

2.3.1 mkuboot的具体编译

    cd /work/ct/lichee/u-boot && [ -xbuild.sh ] && ./build.sh

 

    function build_uboot()

    {

        case "$1" in      //$1是空的

            clean)

                make distclean CROSS_COMPILE=arm-linux-gnueabi-

                ;;

            *)

                make distcleanCROSS_COMPILE=arm-linux-gnueabi-

                make -j8 ${LICHEE_CHIP}CROSS_COMPILE=arm-linux-gnueabi-

                [ $? -ne 0 ] && exit 1

                //真正编译的命令是:

               make -j8 sun7iCROSS_COMPILE=arm-linux-gnueabi-

                cp -f u-boot.bin../out/${LICHEE_PLATFORM}/common/

                ;;

        esac

    }

    if [ -n "${LICHEE_CHIP}" ] ;then    //LICHEE_CHIP=sun7i

        build_uboot $1

        exit 0

    fi

 

make -j8 sun7iCROSS_COMPILE=arm-linux-gnueabi-

然后将编译出来的u-boot.bin复制到/work/ct/lichee/out/android/common中

2.4 mkrootfs

 在lichee/buildroot/scripts/mkcmd.sh中mkrootfs

平台是android时,只是打印而己

2.5总结一下

    mkbr mkkernel mkuboot 都是放到 lichee/out/android/common目录下

 

    cong@dell:/work/ct$ ls/work/ct/lichee/out/android/common

    bImage buildroot lib u-boot.bin uImagezImage

 

mkbr -->/work/ct/lichee/out/android/common/{buildroot,lib}

mkkernel -->/work/ct/lichee/out/android/common/{bImage,uImage,zImage}

mkuboot -->/work/ct/lichee/out/android/common/u-boot.bin

3.附录

3.1 编译命令 

根据buildroot/scripts/mkcommon.sh中的解析可以有如下命令

 

    ./build.sh -p sun7i_android -m boot

    ./build.sh -p sun7i_android -m buildroot

    ./build.sh -p sun7i_android -m kernel

    ./build.sh -p sun7i_android -m uboot

    ./build.sh -p sun7i_android -m clean

    ./build.sh -p sun7i_android -m mrproer

    ./build.sh -p sun7i_android -m distclean

 

可单独编译 boot, kernel等.

3.2 standby中的Makefile

在/work/ct/lichee/linux-3.3/arch/arm/mach-sun7i/pm/standby中这个Makefile脚本写得实在是太...

修改成如下形式,这样在没有修改时就不会每次都编译了

 

    standby:$(STANDBY_OBJ)

        @$(CROSS_COMPILE)ld -T$(STANDBY_LD_FILE) -EL $(STANDBY_OBJ) -o $(STANDBY_OUPUTFILE).elf -Map$(STANDBY_OUPUTFILE).map

        @$(CROSS_COMPILE)objdump -D $(STANDBY_OUPUTFILE).elf> $(STANDBY_OUPUTFILE).lst

        @$(CROSS_COMPILE)objcopy -O binary$(STANDBY_OUPUTFILE).elf $(STANDBY_OUPUTFILE).bin

        cp standby.bin standby.code

    %.o : %.c

        $(CC) $(INCLUDE) $(CFLAGS) -c $<

 

此处还有一个编译错误,需要将linux-3.3/arch/arm/mach-sun7i/pm/mem_divlibc.c中的__div0注掉

./../mem_serial.o:(.ARM.exidx+0x0):undefined reference to `__aeabi_unwind_cpp_pr0'

./../mem_int.o:(.ARM.exidx+0x0):undefined reference to `__aeabi_unwind_cpp_pr1'

网上都说在编译时加上-nostdlib选项,但是不管用

lichee/linux-3.3/arch/arm/mach-sun7i/pm/pm_debug.c中添加:

 

    static void __aeabi_unwind_cpp_pr0(void)

    {

    };

 

    static void __aeabi_unwind_cpp_pr1(void)

    {

    };

 

二.android下的编译

1. source./build/envsetup.sh

    添加命令

    including device/softwinner/sugar-cubietruck/vendorsetup.sh

    including sdk/bash_completion/adb.bash

2. lunch

lunch是定义在 ./build/envsetup.sh中的一个命令

lunch后面参数代表的是平台

 

    function lunch()

    {

        //a. 只执行lunch则会打印lunch的菜单

        //b. 执行lunch 16,会根据参数16从LUNCH_MENU_CHOICES找出16所代表的字符串

            //这儿的16代表sugar_cubietruck-eng

 

        local product=$(echo -n $selection |sed -e "s/-.*$//")

        check_product $product       //sugar_cubietruck

      

 

        local variant=$(echo -n $selection |sed -e "s/^[^\-]*-//")

        check_variant $variant      //variant=eng

 

        export TARGET_PRODUCT=$product

        export TARGET_BUILD_VARIANT=$variant

        export TARGET_BUILD_TYPE=release

 

        set_stuff_for_environment     //设置环境变量

        printconfig                  

    }

 

2.1 设置环境变量

 

    function set_stuff_for_environment()

    {

        settitle             //设置变量PROMPT_COMMAND

        set_java_home        //如果没有设置变量JAVA_HOME,则用默认设置

        setpaths             //设置路径及环境变量

        set_sequence_number  //设置BUILD_ENV_SEQUENCE_NUMBER=10

 

        export ANDROID_BUILD_TOP=$(gettop)

    }

 

ANDROID_BUILD_PATHS=

/work/ct/android42/out/host/linux-x86/bin:

/work/ct/android42/development/scripts: 

/work/ct/android42/development/emulator/qtools:

/work/ct/android42/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin:

/work/ct/android42/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.6/bin:

/work/ct/android42/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.6/bin:

/work/ct/android42/prebuilts/gcc/linux-x86/mips/mipsel-linux-android-4.6/bin:

ANDROID_PRE_BUILD_PATHS=/opt/android/jdk1.6.0_45/bin:

ANDROID_PRODUCT_OUT=/work/ct/android42/out/target/product/sugar-cubietruck

ANDROID_HOST_OUT=/work/ct/android42/out/host/linux-x86

ANDROID_BUILD_TOP=/work/ct/android42

3.extract-bsp

./device/softwinner/common/vendorsetup.sh

拷贝编译出来的内核及驱动文件

 

    function extract-bsp()

    {

        LICHEE_DIR=$ANDROID_BUILD_TOP/../lichee

       LINUXOUT_DIR=$LICHEE_DIR/out/android/common

        LINUXOUT_MODULE_DIR=$LICHEE_DIR/out/android/common/lib/modules/*/*

        CURDIR=$PWD

        cd $DEVICE

         // 删除kernel文件,并将/work/ct/lichee/out/android/common/bImage拷贝到

        // 目录/work/ct/android42/device/softwinner/sugar-cubietruck下,改名为kernel

        if [ -f kernel ]; then

            rm kernel

        fi

        cp $LINUXOUT_DIR/bImage kernel

 

        //删除ko目录

        //将/work/ct/lichee/out/android/common/lib/modules/3.3/中的所有内容拷贝到

         /work/ct/android42/device/softwinner/sugar-cubietruck/modules/modules

        if [ -d modules ]; then

            rm -rf modules

        fi  

        mkdir -p modules/modules

        cp -rf $LINUXOUT_MODULE_DIRmodules/modules 

        chmod 0755 modules/modules/*

 

        //生成文件: create modules.mk

    (cat << EOF) >./modules/modules.mk

    # modules.mk generate by extract-files.sh ,do not edit it !!!!

    PRODUCT_COPY_FILES += \\

        \$(callfind-copy-subdir-files,*,\$(LOCAL_PATH)/modules,system/vendor/modules)

 

    EOF

 

        cd $CURDIR

    }

 

4. make -j8

4.1 make bootimage

在文件build/core/Makefile中

 

    INSTALLED_BOOTIMAGE_TARGET :=$(PRODUCT_OUT)/boot.img

     $(INSTALLED_BOOTIMAGE_TARGET):$(MKBOOTIMG) $(INTERNAL_BOOTIMAGE_FILES)

        $(call pretty,"Target boot image:$@")

        $(hide) $(MKBOOTIMG)$(INTERNAL_BOOTIMAGE_ARGS) $(BOARD_MKBOOTIMG_ARGS) --output $@

        $(hide) $(callassert-max-image-size,$@,$(BOARD_BOOTIMAGE_PARTITION_SIZE),raw)

    endif # TARGET_BOOTIMAGE_USE_EXT2

 

即: out/host/linux-x86/bin/mkbootimg  --kernelout/target/product/sugar-cubietruck/kernel --ramdiskout/target/product/sugar-cubietruck/ramdisk.img --base 0x40000000  --output out/target/product/sugar-cubietruck/boot.img

其中 mkbootimg是在system/core/mkbootimg/mkbootimg.c中生成的

boot.img的构成如下:

 

     header大小为661字节   (padding 2048字节对齐)

    kenel               (padding 2048字节对齐)

    ramdisk.img         (padding 2048字节对齐)

 

4.2 make ramdisk

在文件build/core/Makefile中

 

    BUILT_RAMDISK_TARGET :=$(PRODUCT_OUT)/ramdisk.img

 

    INSTALLED_RAMDISK_TARGET :=$(BUILT_RAMDISK_TARGET)

    $(INSTALLED_RAMDISK_TARGET): $(MKBOOTFS)$(INTERNAL_RAMDISK_FILES) | $(MINIGZIP)

        $(call pretty,"Target ram disk:$@")

        $(hide) $(MKBOOTFS) $(TARGET_ROOT_OUT)| $(MINIGZIP) > $@

        $(warning "cong: $(hide)$(MKBOOTFS) $(TARGET_ROOT_OUT) | $(MINIGZIP) > $@")

 

即: out/host/linux-x86/bin/mkbootfsout/target/product/sugar-cubietruck/root | out/host/linux-x86/bin/minigzip >out/target/product/sugar-cubietruck/ramdisk.img

其中mkbootfs是在./system/core/cpio/mkbootfs.c中生成的

 

 

 

5.pack

android42/device/softwinner/common/vendorsetup.sh

 

    function pack()

    {

        T=$(gettop)

        export ANDROID_IMAGE_OUT=$OUT

        export PACKAGE=$T/../lichee/tools/pack

 

        sh $DEVICE/package.sh $1

    }

 

最终会调用

cong@dell:/work/ct/android42$vi ../lichee/tools/pack/pack

主流程会调用: do_prepare 与 do_pack_android

 

    function do_prepare()

    {   

        //功能: 将./lichee/tools/pack/chips/sun7i/eFex/ 拷贝到 ./lichee/tools/pack/

        cp -r chips/${PACK_CHIP}/eFex .  

       cp -r chips/${PACK_CHIP}/eGon .

        cp -r chips/${PACK_CHIP}/wboot .

        //将./lichee/tools/pack/下的out目录清空

        rm -rf out/

        mkdir -p out/

    }

 

 

PACK_CHIP=sun7i,PACK_PLATFORM=android,PACK_BOARD=sugar-cubietruck

 

    function do_pack_android()

    {

        cp -fchips/${PACK_CHIP}/configs/${PACK_PLATFORM}/default/* out/

        cp -fchips/${PACK_CHIP}/configs/${PACK_PLATFORM}/${PACK_BOARD}/*.fex out/

        cp -fchips/${PACK_CHIP}/configs/${PACK_PLATFORM}/${PACK_BOARD}/*.cfg out/ 2>>/dev/null

           

        //以下两句好像没有什么作用

        do_debug

        do_parse       //调用../lichee/tools/pack/pctools/linux/mod_update/script_parse这个python调本

                      

        cp -rf eFex/split_xxxx.fex wboot/bootfswboot/bootfs.ini out/

       

        cp -f eGon/boot0_nand.binout/boot0_nand.bin

        cp -f eGon/boot1_nand.binout/boot1_nand.fex

        cp -f eGon/boot0_sdcard.binout/boot0_sdcard.fex

        cp -f eGon/boot1_sdcard.binout/boot1_sdcard.fex

       

        cd out/

        stan_cmd cp ${LICHEE_OUT}/u-boot.binbootfs/linux/                   //更新u-boot.bin

       

        sed -i 's/\\bootfs/\/bootfs/g'bootfs.ini              //修改配置文件中的windows路径,将\替换为/

        sed -i 's/\\\\/\//g' image.cfg                         //修改配置文件中的windows路径,将\替换为/

        sed -i 's/imagename/;imagename/g'image.cfg            //修改配置文件,注掉image.cfg中的imagename

        //重新生成image.cfg中的imagename

        local IMG_NAME

        if [ $PACK_DEBUG = "card0" ]; then

           IMG_NAME="${PACK_CHIP}_${PACK_PLATFORM}_${PACK_BOARD}_${PACK_DEBUG}.img"

        else

           IMG_NAME="${PACK_CHIP}_${PACK_PLATFORM}_${PACK_BOARD}.img"

        fi  

        echo "imagename =${IMG_NAME}" >> image.cfg

        echo "" >> image.cfg

       

        busybox unix2dos sys_config.fex

        busybox unix2dos sys_partition.fex

       //调用./lichee/boot/pack/pctools/linux/mod_update/下的命令

        pack_cmd script sys_config.fex

        pack_cmd script sys_partition.fex

       

        cp sys_config.bin bootfs/script.bin

        //调用./lichee/boot/pack/pctools/linux/mod_update/下的命令

        pack_cmd update_mbr sys_partition.bin 4

        pack_cmd update_boot0 boot0_nand.binsys_config.bin NAND

        pack_cmd update_boot0 boot0_sdcard.fexsys_config.bin SDMMC_CARD

        pack_cmd update_boot1 boot1_nand.fexsys_config.bin NAND

        pack_cmd update_boot1 boot1_sdcard.fexsys_config.bin SDMMC_CARD

       

        pack_cmd fsbuild bootfs.ini split_xxxx.fex

        mv bootfs.fex bootloader.fex

       

        u_boot_env_gen env.cfg env.fex

       

        ln -s ${ANDROID_IMAGE_OUT}/boot.imgboot.fex

        ln -s ${ANDROID_IMAGE_OUT}/system.imgsystem.fex

        ln -s ${ANDROID_IMAGE_OUT}/recovery.imgrecovery.fex

       

        pack_cmd dragon image.cfgsys_partition.fex

       

        if [ -e ${IMG_NAME} ]; then

            mv ${IMG_NAME} ../${IMG_NAME}

            echo '----------image isat----------'

            echo -e '\033[0;31;1m'

            echo ${ROOT_DIR}/${IMG_NAME}

            echo -e '\033[0m'

        fi

        cd ..

    }