1#!/bin/bash 2 3# Copyright (C) 2019 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17# Usage: 18# build/build.sh <make options>* 19# or: 20# OUT_DIR=<out dir> DIST_DIR=<dist dir> build/build.sh <make options>* 21# 22# Example: 23# OUT_DIR=output DIST_DIR=dist build/build.sh -j24 24# 25# 26# The following environment variables are considered during execution: 27# 28# BUILD_CONFIG 29# Build config file to initialize the build environment from. The location 30# is to be defined relative to the repo root directory. 31# Defaults to 'build.config'. 32# 33# OUT_DIR 34# Base output directory for the kernel build. 35# Defaults to <REPO_ROOT>/out/<BRANCH>. 36# 37# DIST_DIR 38# Base output directory for the kernel distribution. 39# Defaults to <OUT_DIR>/dist 40# 41# EXT_MODULES 42# Space separated list of external kernel modules to be build. 43# 44# UNSTRIPPED_MODULES 45# Space separated list of modules to be copied to <DIST_DIR>/unstripped 46# for debugging purposes. 47# 48# CC 49# Override compiler to be used. (e.g. CC=clang) Specifying CC=gcc 50# effectively unsets CC to fall back to the default gcc detected by kbuild 51# (including any target triplet). To use a custom 'gcc' from PATH, use an 52# absolute path, e.g. CC=/usr/local/bin/gcc 53# 54# LD 55# Override linker (flags) to be used. 56# 57# Environment variables to influence the stages of the kernel build. 58# 59# SKIP_MRPROPER 60# if defined, skip `make mrproper` 61# 62# SKIP_DEFCONFIG 63# if defined, skip `make defconfig` 64# 65# PRE_DEFCONFIG_CMDS 66# Command evaluated before `make defconfig` 67# 68# POST_DEFCONFIG_CMDS 69# Command evaluated after `make defconfig` and before `make`. 70# 71# POST_KERNEL_BUILD_CMDS 72# Command evaluated after `make`. 73# 74# IN_KERNEL_MODULES 75# if defined, install kernel modules 76# 77# SKIP_EXT_MODULES 78# if defined, skip building and installing of external modules 79# 80# EXTRA_CMDS 81# Command evaluated after building and installing kernel and modules. 82# 83# SKIP_CP_KERNEL_HDR 84# if defined, skip installing kernel headers. 85# 86# Note: For historic reasons, internally, OUT_DIR will be copied into 87# COMMON_OUT_DIR, and OUT_DIR will be then set to 88# ${COMMON_OUT_DIR}/${KERNEL_DIR}. This has been done to accommodate existing 89# build.config files that expect ${OUT_DIR} to point to the output directory of 90# the kernel build. 91# 92# The kernel is built in ${COMMON_OUT_DIR}/${KERNEL_DIR}. 93# Out-of-tree modules are built in ${COMMON_OUT_DIR}/${EXT_MOD} where 94# ${EXT_MOD} is the path to the module source code. 95 96set -e 97 98# rel_path <to> <from> 99# Generate relative directory path to reach directory <to> from <from> 100function rel_path() { 101 local to=$1 102 local from=$2 103 local path= 104 local stem= 105 local prevstem= 106 [ -n "$to" ] || return 1 107 [ -n "$from" ] || return 1 108 to=$(readlink -e "$to") 109 from=$(readlink -e "$from") 110 [ -n "$to" ] || return 1 111 [ -n "$from" ] || return 1 112 stem=${from}/ 113 while [ "${to#$stem}" == "${to}" -a "${stem}" != "${prevstem}" ]; do 114 prevstem=$stem 115 stem=$(readlink -e "${stem}/..") 116 [ "${stem%/}" == "${stem}" ] && stem=${stem}/ 117 path=${path}../ 118 done 119 echo ${path}${to#$stem} 120} 121 122export ROOT_DIR=$(readlink -f $(dirname $0)/..) 123 124# For module file Signing with the kernel (if needed) 125FILE_SIGN_BIN=scripts/sign-file 126SIGN_SEC=certs/signing_key.pem 127SIGN_CERT=certs/signing_key.x509 128SIGN_ALGO=sha512 129 130source "${ROOT_DIR}/build/envsetup.sh" 131 132export MAKE_ARGS=$@ 133export MODULES_STAGING_DIR=$(readlink -m ${COMMON_OUT_DIR}/staging) 134export MODULES_PRIVATE_DIR=$(readlink -m ${COMMON_OUT_DIR}/private) 135export UNSTRIPPED_DIR=${DIST_DIR}/unstripped 136export KERNEL_UAPI_HEADERS_DIR=$(readlink -m ${COMMON_OUT_DIR}/kernel_uapi_headers) 137 138cd ${ROOT_DIR} 139 140export CLANG_TRIPLE CROSS_COMPILE CROSS_COMPILE_ARM32 ARCH SUBARCH 141 142# CC=gcc is effectively a fallback to the default gcc including any target 143# triplets. If the user wants to use a custom compiler, they are still able to 144# pass an absolute path, e.g. CC=/usr/bin/gcc. 145[ "${CC}" == "gcc" ] && unset CC 146 147if [ -n "${CC}" ]; then 148 CC_ARG="CC=${CC}" 149fi 150 151if [ -n "${LD}" ]; then 152 LD_ARG="LD=${LD}" 153fi 154 155CC_LD_ARG="${CC_ARG} ${LD_ARG}" 156 157mkdir -p ${OUT_DIR} 158echo "========================================================" 159echo " Setting up for build" 160if [ -z "${SKIP_MRPROPER}" ] ; then 161 set -x 162 (cd ${KERNEL_DIR} && make ${CC_LD_ARG} O=${OUT_DIR} mrproper) 163 set +x 164fi 165 166if [ "${PRE_DEFCONFIG_CMDS}" != "" ]; then 167 echo "========================================================" 168 echo " Running pre-defconfig command(s):" 169 set -x 170 eval ${PRE_DEFCONFIG_CMDS} 171 set +x 172fi 173 174if [ -z "${SKIP_DEFCONFIG}" ] ; then 175set -x 176(cd ${KERNEL_DIR} && make ${CC_LD_ARG} O=${OUT_DIR} ${DEFCONFIG}) 177set +x 178 179if [ "${POST_DEFCONFIG_CMDS}" != "" ]; then 180 echo "========================================================" 181 echo " Running pre-make command(s):" 182 set -x 183 eval ${POST_DEFCONFIG_CMDS} 184 set +x 185fi 186fi 187 188echo "========================================================" 189echo " Building kernel" 190 191set -x 192(cd ${OUT_DIR} && \ 193 make O=${OUT_DIR} ${CC_LD_ARG} -j$(nproc) $@) 194set +x 195 196if [ "${POST_KERNEL_BUILD_CMDS}" != "" ]; then 197 echo "========================================================" 198 echo " Running post-kernel-build command(s):" 199 set -x 200 eval ${POST_KERNEL_BUILD_CMDS} 201 set +x 202fi 203 204rm -rf ${MODULES_STAGING_DIR} 205mkdir -p ${MODULES_STAGING_DIR} 206 207if [ -n "${IN_KERNEL_MODULES}" ]; then 208 echo "========================================================" 209 echo " Installing kernel modules into staging directory" 210 211 (cd ${OUT_DIR} && \ 212 make O=${OUT_DIR} ${CC_LD_ARG} INSTALL_MOD_STRIP=1 \ 213 INSTALL_MOD_PATH=${MODULES_STAGING_DIR} modules_install) 214fi 215 216if [[ -z "${SKIP_EXT_MODULES}" ]] && [[ "${EXT_MODULES}" != "" ]]; then 217 echo "========================================================" 218 echo " Building external modules and installing them into staging directory" 219 220 for EXT_MOD in ${EXT_MODULES}; do 221 # The path that we pass in via the variable M needs to be a relative path 222 # relative to the kernel source directory. The source files will then be 223 # looked for in ${KERNEL_DIR}/${EXT_MOD_REL} and the object files (i.e. .o 224 # and .ko) files will be stored in ${OUT_DIR}/${EXT_MOD_REL}. If we 225 # instead set M to an absolute path, then object (i.e. .o and .ko) files 226 # are stored in the module source directory which is not what we want. 227 EXT_MOD_REL=$(rel_path ${ROOT_DIR}/${EXT_MOD} ${KERNEL_DIR}) 228 # The output directory must exist before we invoke make. Otherwise, the 229 # build system behaves horribly wrong. 230 mkdir -p ${OUT_DIR}/${EXT_MOD_REL} 231 set -x 232 make -C ${EXT_MOD} M=${EXT_MOD_REL} KERNEL_SRC=${ROOT_DIR}/${KERNEL_DIR} \ 233 O=${OUT_DIR} ${CC_LD_ARG} -j$(nproc) "$@" 234 make -C ${EXT_MOD} M=${EXT_MOD_REL} KERNEL_SRC=${ROOT_DIR}/${KERNEL_DIR} \ 235 O=${OUT_DIR} ${CC_LD_ARG} INSTALL_MOD_STRIP=1 \ 236 INSTALL_MOD_PATH=${MODULES_STAGING_DIR} modules_install 237 set +x 238 done 239 240fi 241 242if [ "${EXTRA_CMDS}" != "" ]; then 243 echo "========================================================" 244 echo " Running extra build command(s):" 245 set -x 246 eval ${EXTRA_CMDS} 247 set +x 248fi 249 250OVERLAYS_OUT="" 251for ODM_DIR in ${ODM_DIRS}; do 252 OVERLAY_DIR=${ROOT_DIR}/device/${ODM_DIR}/overlays 253 254 if [ -d ${OVERLAY_DIR} ]; then 255 OVERLAY_OUT_DIR=${OUT_DIR}/overlays/${ODM_DIR} 256 mkdir -p ${OVERLAY_OUT_DIR} 257 make -C ${OVERLAY_DIR} DTC=${OUT_DIR}/scripts/dtc/dtc OUT_DIR=${OVERLAY_OUT_DIR} 258 OVERLAYS=$(find ${OVERLAY_OUT_DIR} -name "*.dtbo") 259 OVERLAYS_OUT="$OVERLAYS_OUT $OVERLAYS" 260 fi 261done 262 263mkdir -p ${DIST_DIR} 264echo "========================================================" 265echo " Copying files" 266for FILE in ${FILES}; do 267 if [ -f ${OUT_DIR}/${FILE} ]; then 268 echo " $FILE" 269 cp -p ${OUT_DIR}/${FILE} ${DIST_DIR}/ 270 else 271 echo " $FILE does not exist, skipping" 272 fi 273done 274 275for FILE in ${OVERLAYS_OUT}; do 276 OVERLAY_DIST_DIR=${DIST_DIR}/$(dirname ${FILE#${OUT_DIR}/overlays/}) 277 echo " ${FILE#${OUT_DIR}/}" 278 mkdir -p ${OVERLAY_DIST_DIR} 279 cp ${FILE} ${OVERLAY_DIST_DIR}/ 280done 281 282MODULES=$(find ${MODULES_STAGING_DIR} -type f -name "*.ko") 283if [ -n "${MODULES}" ]; then 284 echo "========================================================" 285 echo " Copying modules files" 286 if [ -n "${IN_KERNEL_MODULES}" -o "${EXT_MODULES}" != "" ]; then 287 for FILE in ${MODULES}; do 288 echo " ${FILE#${MODULES_STAGING_DIR}/}" 289 cp -p ${FILE} ${DIST_DIR} 290 done 291 fi 292fi 293 294if [ "${UNSTRIPPED_MODULES}" != "" ]; then 295 echo "========================================================" 296 echo " Copying unstripped module files for debugging purposes (not loaded on device)" 297 mkdir -p ${UNSTRIPPED_DIR} 298 for MODULE in ${UNSTRIPPED_MODULES}; do 299 find ${MODULES_PRIVATE_DIR} -name ${MODULE} -exec cp {} ${UNSTRIPPED_DIR} \; 300 done 301fi 302 303if [ -z "${SKIP_CP_KERNEL_HDR}" ]; then 304 echo "========================================================" 305 echo " Installing UAPI kernel headers:" 306 mkdir -p "${KERNEL_UAPI_HEADERS_DIR}/usr" 307 make -C ${OUT_DIR} O=${OUT_DIR} ${CC_LD_ARG} INSTALL_HDR_PATH="${KERNEL_UAPI_HEADERS_DIR}/usr" -j$(nproc) headers_install 308 # The kernel makefiles create files named ..install.cmd and .install which 309 # are only side products. We don't want those. Let's delete them. 310 find ${KERNEL_UAPI_HEADERS_DIR} \( -name ..install.cmd -o -name .install \) -exec rm '{}' + 311 KERNEL_UAPI_HEADERS_TAR=${DIST_DIR}/kernel-uapi-headers.tar.gz 312 echo " Copying kernel UAPI headers to ${KERNEL_UAPI_HEADERS_TAR}" 313 tar -czf ${KERNEL_UAPI_HEADERS_TAR} --directory=${KERNEL_UAPI_HEADERS_DIR} usr/ 314fi 315 316if [ -z "${SKIP_CP_KERNEL_HDR}" ] ; then 317 echo "========================================================" 318 KERNEL_HEADERS_TAR=${DIST_DIR}/kernel-headers.tar.gz 319 echo " Copying kernel headers to ${KERNEL_HEADERS_TAR}" 320 TMP_DIR="${OUT_DIR}/tmp" 321 TMP_KERNEL_HEADERS_CHILD="kernel-headers" 322 TMP_KERNEL_HEADERS_DIR=$TMP_DIR/$TMP_KERNEL_HEADERS_CHILD 323 CURDIR=$(pwd) 324 mkdir -p $TMP_KERNEL_HEADERS_DIR 325 cd $ROOT_DIR/$KERNEL_DIR; find arch -name *.h -exec cp --parents {} $TMP_KERNEL_HEADERS_DIR \; 326 cd $ROOT_DIR/$KERNEL_DIR; find include -name *.h -exec cp --parents {} $TMP_KERNEL_HEADERS_DIR \; 327 cd $OUT_DIR; find -name *.h -exec cp --parents {} $TMP_KERNEL_HEADERS_DIR \; 328 tar -czvf $KERNEL_HEADERS_TAR --directory=$TMP_DIR $TMP_KERNEL_HEADERS_CHILD > /dev/null 2>&1 329 rm -rf $TMP_KERNEL_HEADERS_DIR 330 cd $CURDIR 331fi 332 333echo "========================================================" 334echo " Files copied to ${DIST_DIR}" 335 336# No trace_printk use on build server build 337if readelf -a ${DIST_DIR}/vmlinux 2>&1 | grep -q trace_printk_fmt; then 338 echo "========================================================" 339 echo "WARN: Found trace_printk usage in vmlinux." 340 echo "" 341 echo "trace_printk will cause trace_printk_init_buffers executed in kernel" 342 echo "start, which will increase memory and lead warning shown during boot." 343 echo "We should not carry trace_printk in production kernel." 344 echo "" 345 if [ ! -z "${STOP_SHIP_TRACEPRINTK}" ]; then 346 echo "ERROR: stop ship on trace_printk usage." 1>&2 347 exit 1 348 fi 349fi 350