#编译流程
#lichee 目录下
./build.sh -p sun7i_android -k 3.4
#build.sh 解析
#!/bin/bash
set -e #"Exit immediately 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) Copyright 2013
# Allwinner Technology Co., Ltd.
# James Deng
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software 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 the command-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/是否有 以该芯片命名的目录
#并导出该变量 export LICHEE_CHIP=${chip}
! init_platforms ${chip} ${platform} ; then
#检查是否支持该平台
#并导出 export LICHEE_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 output directory
init_outdir #初始化输出目录,检查配置是否存在
#这里默认配置:sun7ismp_android_defconfig,配置组成在check_kern_defconf 函数中
#请自己查看
#设置了导出目录:
# export LICHEE_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
function mklichee()
{
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 ————————————
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."
}
# return true if used default config
function check_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."
}
#关键的编译函数:
function build_uboot()
{
case "$1" in
clean)
make distclean CROSS_COMPILE=arm-linux-gnueabi-
;;
*)
make distclean CROSS_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
}
function mksetting() #打印要编译的信息
{
printf "\n"
printf "mkscript current setting:\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"
}
编译内核函数
function mkkernel()
{
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 which platform
local config_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 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
#进入内核目录 ,检查编译脚本是否可执行,执行该脚本
#./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) Copyright 2013
# Allwinner Technology Co., Ltd.
# James Deng
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software 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 common variables
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabi-
export AS=${CROSS_COMPILE}as
export LD=${CROSS_COMPILE}ld
export CC=${CROSS_COMPILE}gcc
export AR=${CROSS_COMPILE}ar
export NM=${CROSS_COMPILE}nm
export STRIP=${CROSS_COMPILE}strip
export OBJCOPY=${CROSS_COMPILE}objcopy
export OBJDUMP=${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 than include/config/auto.conf, someone tinkered
# with it and forgot to run make oldconfig.
# if auto.conf.cmd is missing then we are probably in a cleaned tree so
# we execute the config step to be sure to catch updated Kconfig files
if [ .config -nt include/config/auto.conf -o \
! -f include/config/auto.conf.cmd ] ; then
echo "Generating autoconf.h for standby"
make -f Makefile ARCH=arm CROSS_COMPILE=${CROSS_COMPILE} \
silentoldconfig
fi
make ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE} KDIR=${LICHEE_KDIR} \
-C ${LICHEE_KDIR}/arch/arm/mach-sun7i/pm/standby all
}
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 existing library"
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 existing library"
fi
}
build_kernel()
{
echo "Building kernel"
if [ ! -f .config ] ; then #如果配置文件不存在,则拷贝编译脚本
printf "\n\033[0;31;1mUsing default config ...\033[0m\n\n"
cp arch/arm/configs/${LICHEE_KERN_DEFCONF} .config
fi
build_standby
#编译内核
make ARCH=arm CROSS_COMPILE=${CROSS_COMPILE} -j${jobs} uImage modules
#二进制拷贝
${OBJCOPY} -R .note.gnu.build-id -S -O binary 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 crypto block fs security net -name "*.ko"); do
cp $file ${LICHEE_MOD_DIR}
done
cp -f Module.symvers ${LICHEE_MOD_DIR}
#cp drivers/net/wireless/bcm4330/firmware/bcm4330.bin ${LICHEE_MOD_DIR}
#cp drivers/net/wireless/bcm4330/firmware/bcm4330.hcd ${LICHEE_MOD_DIR}
#cp drivers/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 kernel first\n"
exit 1
fi
make -C modules/example LICHEE_MOD_DIR=${LICHEE_MOD_DIR} LICHEE_KDIR=${LICHEE_KDIR} \
install
build_nand_lib
make -C modules/nand LICHEE_MOD_DIR=${LICHEE_MOD_DIR} LICHEE_KDIR=${LICHEE_KDIR} \
install
build_hdmi_lib
make -C drivers/video/sun7i/hdmi/aw LICHEE_MOD_DIR=${LICHEE_MOD_DIR} LICHEE_KDIR=${LICHEE_KDIR} \
install
(
export LANG=en_US.UTF-8
unset LANGUAGE
make -C modules/mali LICHEE_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/host CROSS_COMPILE=${CROSS_COMPILE} \
# ARCH=arm KERNEL_DIR=${LICHEE_KDIR} INSTALL_DIR=${LICHEE_MOD_DIR} \
# all install
##build ar6003 sdio wifi module
#make -C modules/wifi/ar6003/AR6kSDK.build_3.1_RC.514/host CROSS_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 module 5.90.125.69.2
#make -C modules/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 -C modules/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/example LICHEE_MOD_DIR=${LICHEE_MOD_DIR} LICHEE_KDIR=${LICHEE_KDIR} clean
(
export LANG=en_US.UTF-8
unset LANGUAGE
make -C modules/mali LICHEE_MOD_DIR=${LICHEE_MOD_DIR} LICHEE_KDIR=${LICHEE_KDIR} clean
)
##build ar6302 sdio wifi module
#make -C modules/wifi/ar6302/AR6K_SDK_ISC.build_3.1_RC.329/host CROSS_COMPILE=${CROSS_COMPILE} \
# ARCH=arm KERNEL_DIR=${LICHEE_KDIR} INSTALL_DIR=${LICHEE_MOD_DIR} \
# clean
##build ar6003 sdio wifi module
#make -C modules/wifi/ar6003/AR6kSDK.build_3.1_RC.514/host CROSS_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 module 5.90.125.69.2
#make -C modules/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 -C modules/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
function init_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}
}
function init_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 to out///common directory only when
# both buildroot and kernel use default config file.
function init_outdir()
{
if check_br_defconf && check_kern_defconf ; then
#check_kern_defconf 检查配置是否存在
export LICHEE_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
else
export LICHEE_PLAT_OUT="${LICHEE_OUT_DIR}/${LICHEE_PLATFORM}/${LICHEE_BOARD}"
export LICHEE_BR_OUT="${LICHEE_PLAT_OUT}/buildroot"
fi
mkdir -p ${LICHEE_BR_OUT} #创建目录
}