| #!/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 <config file name>] [-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 "$@" |