全志V40/A40I的lichee 的编译

首先了解一下全志编译lichee的步骤

回顾编译方式:

一般来说都是先配置一下芯片所包含的信息。

	source build.sh config 

全志V40/A40I的lichee 的编译_第1张图片
编译;

		source build.sh

摘要:
全志V40/A40I的lichee 的编译_第2张图片


正文

上面执行build.sh config 。那么主要深究的是这个过程,是怎么去编译。将我们需要的芯片产商平台,内核版本,系统类型,具体系列。编译进去的。

build.sh代码:
在这里插入图片描述
这是一个比较简单的脚本代码。 跳到buildroot/scripts/目录下执行mkcommon.sh 附带一个参数 $@ 。
看图说话;
全志V40/A40I的lichee 的编译_第3张图片
①首先build.sh 脚本执行下来直接到mkcommon.sh脚本,有两个分支②。
②shflags配置和执行mksetup.sh脚本。
③mksetup脚本包含了两个函数 select-board 和 init_defconf 。
④调用到架构内核的配置。
注:select_board和init_defconf函数mkcmd.sh 脚本里面(里面包含大量函数)。
那么先分析mkcommon.sh,在分析shflags和mksetup.sh,主要分析select-board 和 init_defconf 函数, 最后分析到架构上面去。

分析mkcommon.sh

在整一个脚本里面分为五大块执行,分开看可以更加清晰看到整栋源码楼

  • start
  • source shflags
  • define option, format:
  • parse the command-line
  • init default config

start

#!/bin/bash				
BR_SCRIPTS_DIR=`dirname $0`	  *$0  就是自身目录名字 *

source shflags

. ${BR_SCRIPTS_DIR}/shflags/shflags      *执行shflags*
[ -f .buildconfig ] && . .buildconfig           *如果buildconfig 存在即编译 *
. ${BR_SCRIPTS_DIR}/mkcmd.sh			 *执行mkcmd.sh 里面包含大量的命令*

[ -f .buildconfig ] && . .buildconfig

if [ "x$1" = "xconfig" ] ; then	 *判断传来参数是否config*					
. ${BR_SCRIPTS_DIR}/mksetup.sh
exit $?
elif [ "x$1" = "xpack" ] ; then	 *判断传来参数是否 pack*				
	init_defconf
	mkpack
exit $?
elif [ "x$1" = "xpack_debug" ] ; then *判断传来参数是否pack_debug*				
	init_defconf
	mkpack -d card0
exit $?
elif [ "x$1" = "xpack_dump" ] ; then *判断传来参数是否pack_dump*				
	init_defconf
	mkpack -m dump
exit $?
elif [ "x$1" = "xpack_secure" ] ; then *判断传来参数是否pack_secure*		
	init_defconf
	mkpack -s secure
exit $?
elif [ "x$1" = "xpack_prev_refurbish" ] ; then  *判断传来参数是否pack_prev_refurbish*		
    init_defconf
    mkpack -s secure -f prev_refurbish
    exit $?
elif [ "x$1" = "xpack_prvt" ] ; then   *判断传来参数是否pack_prev_refurbish*
	init_defconf
	mkpack -f prvt
exit $?
elif [ "x$1" = "xpack_nor" ] ;then  *判断传来参数是否xpack_nor*
    init_defconf
if [ "x$2" = "xdebug" ] ; then  *判断传来第二个参数是否debug*
    mkpack -f spinor -d card0
 else
    mkpack -f spinor
fi
exit $?
elif [ "x$1" = "xclean" ] ;then  *判断传来参数是否xclean*
	init_defconf
	mkclean
exit $?
elif [ "x$1" = "xdistclean" ] ;then *判断传来参数是否xdistclean*
	init_defconf
	mkdistclean
exit $?
elif [ $# -eq 0 ] ; then
	init_defconf                   *执行 init_defconf 函数*
	mklichee						 *执行 mklichee函数*
exit $?

fi

define option, format:

DEFINE_string 'platform' '' 'platform to build, e.g. sun9iw1p1' 'p'
DEFINE_string 'kernel' 'linux-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'
FLAGS_HELP="Top level build script for lichee

Examples:
1. Set the config option
    $ ./build.sh config
2. Build lichee using preset config value
    $ ./build.sh
3. Pack a linux, dragonboard image
    $ ./build.sh pack
4. Build lichee using command argument
    $ ./build.sh -p 
"

parse the command-line

FLAGS "$@" || exit $?
eval set -- "${FLAGS_ARGV}"

chip=${FLAGS_platform%%_*}
platform=${FLAGS_platform##*_}
kernel=${FLAGS_kernel}
board=${FLAGS_board}
module=${FLAGS_module}

	if [ "${platform}" = "${chip}" ] ; then
	    platform="linux"
	fi

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

if ! init_chips ${chip} || \
   ! init_platforms ${platform} ; then
    mk_error "invalid platform '${FLAGS_platform}'"
    exit 1
fi

if ! init_kern_ver ${kernel} ; then
	mk_error "invalid kernel '${FLAGS_kernel}'"
	exit 1
fi

if [ ${FLAGS_board} ] && \
   ! init_boards ${chip} ${board} ; then
    mk_error "invalid board '${FLAGS_board}'"
    exit 1
fi

init default config

init_defconf
if [ ${module} = "all" ]; then
    mklichee
elif [ ${module} = "boot" ] ; then
    mkboot
elif [ ${module} = "buildroot" ] ; then
    mkbr
elif [ ${module} = "kernel" ] ; then
    mkkernel
elif [ ${module} = "clean" ] ; then
    mkclean
elif [ ${module} = "distclean" ] ; then
    mkdistclean
else
    mk_error "invalid module '${module}'"
    exit 1
fi

exit $?

到这里mkcommon.sh文件的所有命令都执行完成;



蕴涵大量函数的脚本:mkcmd.sh

这个脚本里面身包含了功能性函数,换句话说就是将里面的所有函数命令都包含出来。

这个函数类似我们查看其他库的 -help  命令一样。 使用这个函数介绍mkcmd.sh 这个脚本里面
大体包含什么东西。
function mkhelp()
{
   printf "
    mkscript - lichee build script
    : 1.0.0
   : james
   
  :
    mkboot      build boot
    mkbr        build buildroot
    mkkernel    build kernel
    mkrootfs    build rootfs for linux, dragonboard
    mklichee    build total lichee
    
    mkclean     clean current board output
    mkdistclean clean entires output
    mkpack      pack firmware for lichee
    mkhelp      show this message" 
}

回到mkcommon.sh文件的主体:

	#!/bin/bash				
	BR_SCRIPTS_DIR=`dirname $0`	  *$0  就是自身目录名字 *
*	. ${BR_SCRIPTS_DIR}/shflags/shflags      *执行shflags*
	[ -f .buildconfig ] && . .buildconfig   *如果buildconfig 存在即编译 *
	. ${BR_SCRIPTS_DIR}/mkcmd.sh   *执行mkcmd.sh 里面包含大量的命令*
	[ -f .buildconfig ] && . .buildconfig

既然这个mkcmd.sh的脚本就是配置函数的那么不详细看,用到在去到那里面找。回到mkcommon.sh脚本里面,停留在一大堆循环的最开始的位置。

	if [ "x$1" = "xconfig" ] ; then	

当一开始我们执行下面命令的时候。

source   build.sh config 

config作为配置参数传进来也就是 $1.。判断成立然后执行下面这个脚本。

	. ${BR_SCRIPTS_DIR}/mksetup.sh

## 分析mksetup.sh脚本里面包含了什么东西

. buildroot/scripts/mkcmd.sh *加载mkcmd.sh 里面的命令函数*
function mksetup()
{
    rm -f .buildconfig
    printf "\n"
    printf "Welcome to mkscript setup progress\n"

    select_board		*select_board函数 选择系列配置*
    init_defconf	    *init_defconf函数初始化定义配置*
}

分析这两个函数,都在mkcmd.sh文件里面。

select_board函数

全志V40/A40I的lichee 的编译_第4张图片
通过层层查找下去会发现这里面是一个这样的结构。
全志V40/A40I的lichee 的编译_第5张图片
经过层层分析之后最后得到一个这样的结构。
select_board—>select_kern_ver->select_plaform->select_chip
这个结构使我们非常熟悉的一个图解。每个函数在里面都实习了自己的选项和功能。也就是下图
全志V40/A40I的lichee 的编译_第6张图片
我们所熟悉这个选项结构就是在上面编译出来。

init_defconf 函数
那么看看init_defconf 函数在里面干了些什么东西。
全志V40/A40I的lichee 的编译_第7张图片
在里面出来表明路径和配置之外,特别注重的就是这句命令,他就是这个函数里面的太阳。

	defconf=`awk '$1=="'$pattern'" {print $2,$3}' buildroot/scripts/mkrule`
	注:在 buildroot/scripts/mkrule文件下,按照“$pattern” 字符串来查找这个文件的一
	个行字符。 并且将同行第二段和第三段字符打印出来。 在这里需要自行补课awk命令。

那么必须要进入到这mkrule文件里面分析。
全志V40/A40I的lichee 的编译_第8张图片
里面却是一堆这样的东西。那么这些玩意是什么呢?
我们将其中的一行(第一行)抽离出来看。将他们分成3段来看。这就是上面提到的$1,$2 ,$3。他们各自代表里面的一段,其实里面就是可以看成 $1=sun8iw1p1_android
全志V40/A40I的lichee 的编译_第9张图片

	defconf=`awk '$1=="'$pattern'" {print $2,$3}' buildroot/scripts/mkrule`

意思就是通过 $1 找到对应的行,然后将后面两段的指令都给执行了。在这里详细讲解一下所谓$1 ,$2 ,$3里面究竟是什么东西。

一、sun8iw1p1_android ($1) 其实是我们芯片和平台来的。但是一定的格式命名要求符合,chip_platform。并且chip和platform是必须与芯片平台保持一致。在对照上面图片。其实$1 就是你自己选择芯片和平台。他直接拿过来使用了。所以才有行代码。对应起来每一项都是自己选择么. 。我们之前选择的每一次决定都影响着之后的编译路径。

pattern="${LICHEE_CHIP}_${LICHEE_PLATFORM}_${LICHEE_BOARD}"
相等于:
LICHEE_CHIP = chip  
LICHEE_PLATFORM = android 
LICHEE_BOARD = board 

全志V40/A40I的lichee 的编译_第10张图片

二、 sun8i_defconfig ($2) 也就是所谓中间段。这个是配置我们的buildroot配置的。
具体的位置 。里面包含了产商写的配置文件。

 /lichee/buildroot/configs

全志V40/A40I的lichee 的编译_第11张图片
三、sun8iw1p1smp_android_defconfig ($3) 在最后的一段里面。这个是配置内核文件。
文件具体位置。里面文件很多有各个产商的内核配置代码。意思就是说当我们编译$1这个平台的芯片和对应的平台。 使用到对应配置内核文件。

	/lichee/linux-3.10/arch/arm/configs

全志V40/A40I的lichee 的编译_第12张图片
所以到这里就比较清晰了。其实init_deconf函数,就是将自己选择平台和芯片型号。都会给你找到对应的配置文件和内核文件。他们全部都编译进去。最后有关于init_deconf函数的代码不再分析了仅仅是调整输出目录。配置环境等等。
init_defconf函数分析完了那么整一个mksetup.sh函数了。那么现在还是再次回到mkcommon.sh文件主体里面。会发现到了函数已经到、
define option,
format:
parse the command-line
init default config
这些配置和判断操作了。 代码十分简单看一下就可以了解大概状况。 所以不再详细source build.sh config 这个命令了。但是我们一旦配置完之后是不是还会执行

source build.sh

这个编译命令。那么下面就是开始介绍我们一旦编译 build.sh 这个文件。整体的源码是怎么操作走势如何。


译 source build.sh

前面的操作都是一样的,但是由于没有带参数进来到mkcommon.sh文件。所以在大循环里面将会进入到这个循环里面了。 init_defconf在上面分析了,那么mklichee这个函数要进行分析。
在这里插入图片描述

函数:mklichee

全志V40/A40I的lichee 的编译_第13张图片
其中里面的mk_info函数就是一个打印函数,那么就要去到check_eev函数里面遨游。
发现里面也是空空的东西,仅仅是判断这些文件是否存在,做一个出错判断。
全志V40/A40I的lichee 的编译_第14张图片
mklichee函数那么只剩下 mkbr && mkkernel && mkrootfs 这句可以分析的了。里面应该还是三个函数并且都要求同是成立,不然就返回1。

mkbr && mkkernel && mkrootfs
[ $? -ne 0 ] && return 1

那么接下来就是里面的三个函数mkbr ,mkkernel ,mkrootfs。看得是十分熟悉名字应该就是我们的buildroot,内核,根文件系统。

###################################################################
在mkcmd.sh文件里面有着这些定义好的路径,要细心对应观察 里面是都会用到的路径。 在下面就不在详细讲解了

	#define importance variable
	LICHEE_TOP_DIR=`pwd`
	LICHEE_BR_DIR=${LICHEE_TOP_DIR}/buildroot
	LICHEE_KERN_DIR=${LICHEE_TOP_DIR}/${LICHEE_KERN_VER}
	LICHEE_TOOLS_DIR=${LICHEE_TOP_DIR}/tools
	LICHEE_OUT_DIR=${LICHEE_TOP_DIR}/out

###################################################################
函数:mkbr
去到LICHEE_BR_DIR 目录下,然后判断scripts/build.sh是否存在。存在即执行 scripts/build.sh脚本。

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

mkkernel函数

function mkkernel() {
	 mk_info "build kernel ..."
	 local build_script="scripts/build.sh"   
	 prepare_toolchain					 /*	prepare_toolchain  函数*/
	    
    # mark kernel .config belong to which platform
    local config_mark="${LICHEE_KERN_DIR}/.config.mark"    ‘去到LCHEE_KERN_DIR路径’

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

分段来讲解这个作用于内核的函数:
如果/external-toolchain文件存在的话,进去里面编译 mkbr函数。后面就是配置一下各个文件环境。
①: prepare_toolchain 函数

function prepare_toolchain(){
    mk_info "prepare toolchain of ${LICHEE_CHIP}..."
    tooldir=${LICHEE_BR_OUT}/external-toolchain
    if [ ! -d ${tooldir} ] ; then
		mk_info "The toolchain doesn't exsit. So compile the buildroot ..."
        mkbr
    fi

    if ! echo $PATH | grep -q "${tooldir}" ; then
        export PATH=${tooldir}/bin:$PATH
    fi
}

小提一下mkbr函数; 就是执行scripts/build.sh这个脚本。

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

② : if [ -f ${config_mark} ]
判断这个文件是否存在,存在将会执行循环里面的函数③。不存在将会执行下面这个命令。将平台写进到 ${config_mark}文件里面。 这种类型sysfs操作和proc文件操作。

	 echo "${LICHEE_PLATFORM}" > ${config_mark}

③ (cd ${LICHEE_KERN_DIR} && [ -x KaTeX parse error: Expected 'EOF', got '&' at position 18: …uild_script} ] &̲& ./{build_script} “clean”)
在这里也就说明一下,③和④都是相对来说的。③的功能相对就是一个清空复位的操作。可以明显看到向./${build_script} 里面配置一个 " clean "进去。


④(cd ${LICHEE_KERN_DIR} && [ -x KaTeX parse error: Expected 'EOF', got '&' at position 18: …uild_script} ] &̲& ./{build_script})
这里说下目录去到那里了不然跟丢了不知道跑到那个目录下了这主要是判断这个文件

	 LICHEE_KERN_DIR = lichee/linux-3.10。

scripts/build.sh 是否存在,并且执行。build.sh里面配置ARM架构,连接模块,连接库文件等等一些内核操作。

函数: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}
	if [ -f "${LICHEE_BR_OUT}/images/rootfs.squashfs" ]; then
		cp ${LICHEE_BR_OUT}/images/rootfs.squashfs ${LICHEE_PLAT_OUT}
	fi
        if [ "x$PACK_TINY_ANDROID" = "xtrue" ];then
            packtinyandroid
        fi
    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."
}

关于这函数的作用,一进来就判断平台是不是Linux,很明显我们的平台是android,内核是Linux-3.10。所以就没有进入循环里面。
主要实现这两行代码:

去到这个文件目录下:
		cd  ${LICHEE_BR_DIR}/target/dragonboard
创建 一个modules目录:
·		${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)

到这里就将真个编译流程都走完一遍了,但是会发现一些到内核配置和根文件系统等等的build.sh 脚本都没有详细讲解, 包含了产家的配置等需要自己去看看或者稍微浏览一下这个是产家提供的一些对应芯片内容。

还有一个章节就是讲解:source build.sh clean
全志V40/A40I的lichee 的编译_第15张图片
那么回到 mkcommon.sh 脚本里面。在第二大层的循环分支里面包含了:

	elif [ "x$1" = "xclean" ] ;then
	init_defconf
	mkclean
	exit $?								

里面的里面主要的两个函数,一个init_defconf在前面已经讲过了。只要分析
mkclean这个函数:

	function mkclean() {
    clkernel
	mk_info "clean product output in ${LICHEE_PLAT_OUT} ..."
	cd ${LICHEE_PLAT_OUT}
	ls | grep -v "buildroot" | xargs rm -rf     *  查找到有关的内容删除掉*
	cd - > /dev/null
}

这个函数相对简单点,一进来直接跑到 clkernel 函数里面的进行操作。看这个名字就知道应该是释放有关内核的资源。 clkernel函数相关:

function clkernel() {
    mk_info "clean kernel ..."
    local build_script="scripts/build.sh"
    prepare_toolchain
    (cd ${LICHEE_KERN_DIR} && [ -x ${build_script} ] && ./${build_script} "clean")
    mk_info "clean kernel OK."
}	

首先进入这个函数里面的话,那么直接执行这个函数了 prepare_toolchain。然后去到
对应的配置内核的目录下。判断这个文件(${build_script})是否存在并且,传clean进去
,放之前配置内核的东西都往下面传递全部释放之前使用到的动态资源。
现在主要分析prepare_toolchain函数:其实里面就是一个工具链。

function prepare_toolchain()  {
    mk_info "prepare toolchain of ${LICHEE_CHIP}..."
    tooldir=${LICHEE_BR_OUT}/external-toolchain
    if [ ! -d ${tooldir} ] ; then
		mk_info "The toolchain doesn't exsit. So compile the buildroot ..."
        mkbr
    fi

    if ! echo $PATH | grep -q "${tooldir}" ; then
        export PATH=${tooldir}/bin:$PATH
    fi
}

当工具链不存在的话编译buildroot,构建buildroot。

在这里就分析有关于lichee目录下的build.sh脚本以及他们常用传参,也就完结了。里面其实还有很多可以使用的参数作为测试版本,调试版本等等。需要细心观察了。

关注微信公众号:(技术Code城)

你可能感兴趣的:(Android_笔记,笔记,全志系列)