编译系统的方法有很多种,使用Docker 或者是使用jenkins编译,方法千万种.网上有很多的方法,这里就不再说了篇文章主要是针对本地编译.

最近学习了脚本,也尝试写了一个Android系统编译的脚本,重点分析一下脚本,算是对之前学习脚本的一个小小的总结.

1.一套Android源码

2.Ubuntu环境 以及JDK环境

正常本地编译步骤

1.source build/envsetup.sh

2.lunch xxx

3.make -j8 2>&1 |tee build.log (make就可以,这样写两个目的:1.多核编译 2.输出编译的log)

为了偷懒,也为了自己学的脚本有用武之地,写了一个 脚本进行编译,放到源码根目录使用方法如下:

./androidbuild.sh  all/systemimg/bootimg userdebug/user

./androidbuild.sh  all/systemimg/bootimg userdebug/user clean

androidbuild.sh 内容如下:

主要逻辑还是用的版本编译步骤,只是简化成了脚本

TARGET="msm8953_64" 这个需要改变成你想要的版本前缀

#!/bin/bash
##############################编译Android 系统脚本######################################
# 设置编译环境变量
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:${JRE_HOME}/bin:$PATH

#设置所在目录
export ROOT_PATH=$(pwd)
#设置编译的版本  
TARGET="msm8953_64"

#查看CUP 处理个数 最大允许4核

cpu_count=`cat /proc/cpuinfo |grep processor|wc -l`
if [ "$cpu_count" -gt "4" ];then
	cpu_count=4
fi

# 设置编译环缓存文件
setup_ccache() {
    export CCACHE_DIR=../.ccache
    export USE_CCACHE=1
}

#删除编译缓存
delete_ccache() {
    prebuilts/misc/linux-x86/ccache/ccache -C
    rm -rf $CCACHE_DIR
}

create_ccache() {
    echo -e "\nINFO: Setting CCACHE with 10 GB\n"
    setup_ccache
    delete_ccache
    prebuilts/misc/linux-x86/ccache/ccache -M 10G
}

# 校验使用脚本输入的参数变量
if [ $# -eq 0 ]; then
    echo -e "ERROR: Missing argument: build param\n"
	echo -e "eg:[Donot make clean] ./androidbuild.sh all/systemimg/bootimg userdebug/user"
	echo -e "eg:[make clean]       ./androidbuild.sh all/systemimg/bootimg userdebug/user clean"
    exit 1
fi
# 校验使用脚本输入的参数变量
if [ $# -gt 3 ]; then
    echo -e "\nERROR: Extra inputs. \n"
    exit 1
fi

#创建文件保存编译log
if [ -z $LOG_FILE ]; then
    LOG_FILE=$TARGET-$2
	echo $LOG_FILE
fi

#环境预热 也就是普通编译的第一步
source ./build/envsetup.sh

#设置 lunch 的目标版本
if [ "$2" == "eng" -o "$2" == "userdebug" -o "$2" == "user" ]; then
	lunch $TARGET-$2
else
	echo -e "Error: Wrong inputs. please input eng/userdebug/user"
	exit 1
fi

#是否清除上一次的编译缓存 进行重新编译
if [ "$3" == "clean" ]; then
    echo -e "\nINFO: Notice make clean!!!!!!!!\n"
	for time in {10..1}
	do
		echo -e "\nINFO: Make Clean in $time ..."
		sleep 1
	done
    # 执行 clean操作
	make clean
else
    # 如果不是 删除上次生成好的编译文件
	rm -rf out/target/product/msm8953_64/system/
	rm -rf out/target/product/msm8953_64/kernel
	rm -rf out/target/product/msm8953_64/*.zip
	rm -rf out/target/product/msm8953_64/obj/PACKAGING/target_files_intermediates/*
	rm -rf out/target/product/msm8953_64/*.img
	rm -rf out/target/product/msm8953_64/*.bin
	rm -rf out/target/product/msm8953_64/*.txt
fi

# 执行 更新api 主要针对对framework进行了修改的操作,不然系统识别不到你的新更改
make update-api -j$cpu_count

# 分为三个编译 主要使用的是make命令
# 编译镜像
if [ "$1" == "systemimg" ]; then
    echo -e "\nINFO: Build systemimage for $TARGET\n"
    make systemimage -j$cpu_count  | tee $LOG_FILE.log
# 编译boot
elif [ "$1" == "bootimg" ]; then
    echo -e "\nINFO: Build bootimage for $TARGET\n"
    make bootimage -j$cpu_count | tee $LOG_FILE.log
# 编译全部
elif [ "$1" == "all" ]; then
    echo -e "\nINFO: Build all image and otapackage for $TARGET\n"
    make -j$cpu_count  | tee $LOG_FILE-img.log
    make otapackage -j$cpu_count  | tee $LOG_FILE-ota.log
else
	echo -e "Error: Wrong inputs. please input all/ota/systemimg/bootimg"
	exit 1
fi

# 上一条命令执行后退出的状态  正常退出返回 0 非正常退出返回 1
if [ ! $? -eq 0 ]; then
    echo "make error"
    exit -1
fi

#后面为编译完成后的操作
############################保存编译文件的存放文件夹###################################
yourdate=`date +%Y_%m_%d`
echo $yourdate

local_backuppath=$ROOT_PATH"/IMAGES_"$yourdate
echo $local_backuppath
mkdir -p $local_backuppath

###########################将编译好的文件拷贝到上面的文件夹########################################
cp out/target/product/msm8953_64/$TARGET*.zip $local_backuppath
cp out/target/product/msm8953_64/*.img $local_backuppath
cp out/target/product/msm8953_64/obj/PACKAGING/target_files_intermediates/$TARGET*.zip  $local_backuppath
echo "######## 拷贝完成 ########"

if false; then
############################保存编译的app 到 APPVERSION.txt 
  仅仅是用于查看 apk 列表########################################
APKPATH=$ROOT_PATH"/out/target/product/msm8953_64/system/app"
echo "print log to APPVERSION.txt"

app_lists=`find $APKPATH | grep ".apk" | grep -vE "Bluetooth|CertInstaller|HTMLViewer|KeyChain|Wallpapers|MDummyAPK|MTv|UserDictionaryProvider|PacProcessor"`

APPVERSION=$local_backuppath/AppVersion.txt
# 如果 AppVersion.txt 存在则为上次编译的文件 执行删除操作
if [ -f $APPVERSION ];then
	rm $APPVERSION
fi

PROPPATH=$ROOT_PATH"/out/target/product/msm8953_64/system/build.prop"
#用等号分割 获取 ro.build.date.utc 版本
utc=`cat $PROPPATH | grep "ro.build.date.utc" | awk -F "=" '{print $2}'`
# 用等号分割 获取 ro.build.description版本
description=`cat $PROPPATH | grep "ro.build.description=" | awk -F "=" '{print $2}'`
# 将以上信息存储到 AppVersion.txt
echo ">>>>>>>" > $APPVERSION
echo "utc="$utc >> $APPVERSION
echo "description="$description >> $APPVERSION
echo "<<<<<<<" >> $APPVERSION

for app in $app_lists
do
    #    echo $app
    info=`out/host/linux-x86/bin/aapt dump badging $app  | grep -E "package: name=|application: label="`
    apkName=`echo $app | awk -F"/" '{print $NF}'`
    appName=`echo $info | grep "application: label=" | awk -F"label=" '{print $NF}' | awk -F"'" '{print $2}'`
    packageName=`echo $info | grep "package: name=" | awk -F"'" '{print $2}'`
	versionCode=`echo $info | grep "versionCode=" | awk -F"'" '{print $4}'`
    versionName=`echo $info | grep "versionName=" | awk -F"'" '{print $6}'`
# 将本地编译好的 APP 信息写入 AppVersion.txt 仅仅是用于查看
    echo "apkName="$apkName >> $APPVERSION
    echo "appName="$appName >> $APPVERSION
    echo "packageName="$packageName >> $APPVERSION
    echo "versionCode="$versionCode >> $APPVERSION
    echo "versionName="$versionName >> $APPVERSION
    echo "-----------------------------\n"  >> $APPVERSION
done
fi

可以根据自己意愿进行修改