#!/bin/bash -e set -o pipefail ROOT_DIR=$(cd $(dirname $0); pwd) CUR_DIR=$(pwd) if [ -n "${MAKE_JOBS}" ]; then CPUS=${MAKE_JOBS} else CPUS=$(nproc) #CPUS=$(($(nproc)/2)) fi #### TODO LIST ########################### # 1. support for OUT_DIR specification # 2. support for repo sync multiple configs # into one workspace ########################################## ### variables could be changed via parameters build_config="" build_config_url="" MIRROR="" DEFAULT_MANIFEST_URL="https://android.googlesource.com/platform/manifest" skip_init=false skip_sync=false PINNED_MANIFEST="" NO_BUILD=false INSTALL_PACKAGE=false REPO_GROUPS="default,-notdefault" DEFAULT_MANIFEST_BRANCH="master" ########### workarounds ################## # workaround for boot_fat.uefi.img for error: # AssertionError: Can only handle FAT with 1 reserved sector # git clone https://github.com/dosfstools/dosfstools -b v3.0.28 # cd dosfstools && make export PATH=${ROOT_DIR}/dosfstools:${PATH} # workaround to use openjdk-8 for oreo builds export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/ export PATH=${JAVA_HOME}/bin:$PATH ########### contants ##################### REPO_URL="" BASE_MANIFEST="default.xml" default_build_config_url_prefix="https://android-git.linaro.org/android-build-configs.git/plain" ######## functions define ################ function export_config(){ local f_config=$1 while read line; do if echo "${line}"|tr -d '[:blank:]'|grep -q '^$'; then continue fi if ! echo $line |grep -q '^#'; then eval "export $line" fi done < ${f_config} } function repo_sync_patch(){ build_config_tmp="" if [ -n "${build_config}" ]; then # case when -c|--config specified if [ -n "${PINNED_MANIFEST}" ]; then # need to get the exact same build config file in the pinned manifest abc_line=$(grep android-build-configs ${PINNED_MANIFEST}|tr -d '"') abc_commit='' for field in ${abc_line}; do if echo ${field}|grep 'revision=' ; then abc_commit=$(echo ${field}|sed 's/revision=//') fi done if [ -z "${abc_commit}" ]; then echo "Failed to find the commit information for android-build-configs repository in ${PINNED_MANIFEST}" echo "Please check first, and try it again" exit 1 fi pinned_config_url=https://android-git.linaro.org/android-build-configs.git/plain/${build_config}?id=${abc_commit} f_tmp=$(mktemp -u lcr-pinned-XXX) wget ${pinned_config_url} -O ${f_tmp} export_config ${f_tmp} #rm -fr ${f_tmp} elif [ -n "${build_config_url}" ]; then build_config_tmp=$(mktemp -u lcr-XXX) build_config_remote_url=${build_config_url} if echo "${build_config_remote_url}"|grep -q '^/'; then cp -vf "${build_config_remote_url}" ${build_config_tmp} else wget ${build_config_remote_url} -O ${build_config_tmp} fi export_config ${build_config_tmp} rm -f android-build-configs/${build_config} elif [ ! -f android-build-configs/${build_config} ]; then f_tmp=$(mktemp -u lcr-XXX) build_config_remote_url="${default_build_config_url_prefix}/${build_config}" wget ${build_config_remote_url} -O ${f_tmp} export_config ${f_tmp} else export_config android-build-configs/${build_config} fi #else # case when -tp|--target-product specified fi if ! ${skip_init}; then opt_group=${opt_repo_groups:-${REPO_GROUPS}} if [ -n "${MIRROR}" ]; then url_manifest="${MIRROR}" elif [ -n "${MANIFEST_URL}" ]; then url_manifest="${MANIFEST_URL}" else url_manifest="${DEFAULT_MANIFEST_URL}" fi if [ -n "${REPO_URL}" ]; then opt_repo_url="--repo-url=${REPO_URL}" else opt_repo_url="" fi while ! repo init \ -u "${url_manifest}" \ -m "${BASE_MANIFEST}" \ -g "${opt_group}" \ ${opt_repo_url} \ -b "${MANIFEST_BRANCH:-${DEFAULT_MANIFEST_BRANCH}}"; do sleep 30 done fi # only clone or update local_manifests when pinned manifest file not exist if [ -z "${PINNED_MANIFEST}" ]; then if [ -z "${LOCAL_MANIFEST}" ]; then # remove local_manifests when LOCAL_MANIFEST not specified ${skip_init} || rm -fr .repo/local_manifests elif [ -d .repo/local_manifests ]; then cd .repo/local_manifests git pull cd - else git clone "${LOCAL_MANIFEST}" -b "${LOCAL_MANIFEST_BRANCH}" .repo/local_manifests fi elif [ -d .repo/local_manifests ]; then echo "Please remove the .repo/local_manifests directory first" echo "Otherwise duplicate of projects error might be reported" exit 1 fi if [ -n "${PINNED_MANIFEST}" ]; then PINNED_MANIFEST_name=$(basename ${PINNED_MANIFEST}) PINNED_MANIFEST_dir=$(cd $(dirname ${PINNED_MANIFEST}); pwd) PINNED_MANIFEST_ABS="${PINNED_MANIFEST_dir}/${PINNED_MANIFEST_name}" repo_sync_cmd="repo sync -c --force-sync -j${CPUS} -m ${PINNED_MANIFEST_ABS}" else repo_sync_cmd="repo sync -c --force-sync -j${CPUS}" fi while ! ${repo_sync_cmd}; do echo "Try again for repo sync in one minute" sleep 60 done mkdir -p out/pinned-manifest repo manifest -r -o out/pinned-manifest/$(date +%Y-%m-%d-%H-%M)-pinned-manifest.xml for patch in ${PATCHSETS}; do ./android-patchsets/${patch} done if [ -n "${build_config_tmp}" ] && [ ! -f android-build-configs/${build_config} ]; then mkdir -p android-build-configs cp -vf "${build_config_tmp}" "android-build-configs/${build_config}" fi } function build_with_config(){ local f_config="android-build-configs/${build_config}" if [ -f "${f_config}" ]; then export_config "${f_config}" fi if [ -n "${HOOK_PRE_ANDROID_BUILD}" ]; then ./android-build-configs/hooks/${HOOK_PRE_ANDROID_BUILD} fi set +x echo "source build/envsetup.sh" source build/envsetup.sh set -x local lunch_str="" if [ -n "${LUNCH}" ]; then lunch_str="${LUNCH}" elif [ -n "${TARGET_PRODUCT}" ]; then if [ -n "${OPT_TARGET_BUILD_VARIANT}" ]; then lunch_str="${TARGET_PRODUCT}-${OPT_TARGET_BUILD_VARIANT}" elif [ -n "${TARGET_BUILD_VARIANT}" ]; then lunch_str="${TARGET_PRODUCT}-${TARGET_BUILD_VARIANT}" else lunch_str="${TARGET_PRODUCT}-userdebug" fi elif [ -n "${OPT_TARGET_PRODUCT}" ]; then if [ -n "${OPT_TARGET_BUILD_VARIANT}" ]; then lunch_str="${OPT_TARGET_PRODUCT}-${OPT_TARGET_BUILD_VARIANT}" elif [ -n "${TARGET_BUILD_VARIANT}" ]; then lunch_str="${OPT_TARGET_PRODUCT}-${TARGET_BUILD_VARIANT}" else lunch_str="${OPT_TARGET_PRODUCT}-userdebug" fi else echo "Please specify at least one of LUNCH or TARGET_PRODUCT" exit 1 fi set +x echo "lunch ${lunch_str}" lunch ${lunch_str} MAKE_TARGETS=${MAKE_TARGETS:-droidcore} set -x echo "Start to build: make ${MAKE_TARGETS} -j${CPUS}" |tee -a time.log date +%Y-%m-%d-%H-%M >>time.log (time LANG=C make ${MAKE_TARGETS} -j${CPUS} ) 2>&1 |tee build-${TARGET_PRODUCT}.log date +%Y-%m-%d-%H-%M >>time.log if [ -n "${HOOK_POST_ANDROID_BUILD}" ]; then ./android-build-configs/hooks/${HOOK_POST_ANDROID_BUILD} fi } function print_usage(){ echo "$(basename $0) [-si|--skip_init] [-c|--config ] [-m|--mirror mirror_url] [-pm|--pinned-manifest]" echo "$(basename $0) [-si|--skip_init] [-tp|--target-product target-product-name] [-tv|--target-variant target-build-variant] [-m|--mirror mirror_url] [-pm|--pinned-manifest]" echo -e "\t -ss|--skip-sync: skip to run repo sync and apply patchsets, for cases like only build" echo -e "\t -si|--skip-init: skip to run repo init, for cases like run on hackbox" echo -e "\t -c|--config branch: build config file name under:" echo -e "\t\t\thttps://android-git.linaro.org/android-build-configs.git/tree" echo -e "\t -cu|--config-url branch: url for the build config file name under, must be absolute path when use local files" echo -e "\t -m|--mirror mirror_url: specify the url where you want to sync from" echo -e "\t -g|--groups groups: repo groups used when run repo init" echo -e "\t -pm|--pinned-manifest file_path: specify the path where you put the pinned manifest file" echo -e "\t -nb|--no-build: only repo sync all the projects and apply patches, but do not do any build operations" echo -e "\t -ip|--install-packages: install host packages required for android building" echo -e "\t -tp|--target-product: specify the TARGET_PRODUCT to be built" echo -e "\t -tv|--target-variant: specify the TARGET_BUILD_VARIANT to be built" echo "$(basename $0) [-h|--help]" echo -e "\t -h|--help: print this usage" } function parseArgs(){ while [ -n "$1" ]; do case "X$1" in X-ss|X--skip-sync) skip_sync=true shift ;; X-si|X--skip-init) skip_init=true shift ;; X-c|X--config) if [ -z "$2" ]; then echo "Please specify the build config file name for the -c|--config option" exit 1 fi build_config="$2" shift 2 ;; X-cu|X--config-url) if [ -z "$2" ]; then echo "Please specify the url of the build config file name for the -cu|--config-url option" exit 1 fi build_config_url="$2" shift 2 ;; X-m|X--mirror) if [ -z "$2" ]; then echo "Please specify the repo sync mirror url with the -c|--config option" exit 1 fi MIRROR="$2" shift 2 ;; X-b|X--branch) if [ -z "$2" ]; then echo "Please specify the manifest branch for the -b|--branch option" exit 1 fi MANIFEST_BRANCH="$2" shift 2 ;; X-ru|X--repo-url) if [ -z "$2" ]; then echo "Please specify the manifest branch for the -ru|--repo-url option" exit 1 fi REPO_URL="$2" shift 2 ;; X-g|X--groups) if [ -z "$2" ]; then echo "Please specify the repo groups for the -g|--groups option" exit 1 fi opt_repo_groups="$2" shift 2 ;; X-pm|X--pinned-manifest) if [ -z "$2" ]; then echo "Please specify the path for the pinned manifest file with the -pm|--pinned-manifest option" exit 1 fi PINNED_MANIFEST="$2" shift 2 ;; X-tp|X--target-product) if [ -z "$2" ]; then echo "Please specify the product name for the -tp|--target-product option" exit 1 fi OPT_TARGET_PRODUCT="$2" shift 2 ;; X-tv|X--target-variant) if [ -z "$2" ]; then echo "Please specify the build variant value for the -tv|--target-variant option" exit 1 fi OPT_TARGET_BUILD_VARIANT="$2" shift 2 ;; X-nb|X--no-build) NO_BUILD=true shift 1 ;; X-ip|X--install-package) INSTALL_PACKAGE=true shift 1 ;; X-h|X--help) print_usage exit 1 ;; X-*) echo "Unknown option: $1" print_usage exit 1 ;; X*) echo "Unknown option: $1" print_usage exit 1 ;; esac done if [ -z "${OPT_TARGET_PRODUCT}" ] && [ -z "${build_config}" ]; then echo "Please specify the value for either -tp|--target-product option or -c|--config option" print_usage exit 1 fi } function install_packages(){ # Some of the packges might be not necessary anymore for # android build, but not going to figure them out here. sudo apt-get update packages="acpica-tools bc bison build-essential ccache curl flex genisoimage" packages="${packages} git git-core g++-multilib gnupg gperf lib32ncurses5-dev lib32z-dev" packages="${packages} libc6-dev-i386 libdrm-intel1 libgl1-mesa-dev liblz4-tool libssl-dev" packages="${packages} libx11-dev libxml2-utils linaro-image-tools lzop mtools openjdk-8-jdk" packages="${packages} patch python-crypto python-mako python-parted python-pip python-requests" packages="${packages} python-wand python-yaml rsync time u-boot-tools unzip uuid-dev" packages="${packages} vim-common wget x11proto-core-dev xsltproc zip zlib1g-dev" ## packages needed by OP-TEE packages="${packages} python-pyelftools" sudo apt-get install -y ${packages} } function main(){ parseArgs "$@" if ! ${skip_sync}; then repo_sync_patch elif [ ! -f android-build-configs/${build_config} ] && [ -z "${OPT_TARGET_PRODUCT}" ]; then if [ -z "${build_config_url}" ]; then build_config_remote_url="${default_build_config_url_prefix}/${build_config}" else build_config_remote_url=${build_config_url} fi if echo "${build_config_remote_url}"|grep -q '^/'; then cp -vf "${build_config_remote_url}" android-build-configs/${build_config} else wget ${build_config_remote_url} -O android-build-configs/${build_config} fi export_config android-build-configs/${build_config} fi if ${INSTALL_PACKAGE}; then install_packages fi if ! ${NO_BUILD}; then build_with_config fi } main "$@"