Matthias Maennich | 6652d74 | 2019-02-01 22:20:44 +0000 | [diff] [blame^] | 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) |
| 50 | # |
| 51 | # LD |
| 52 | # Override linker (flags) to be used. |
| 53 | # |
| 54 | # Environment variables to influence the stages of the kernel build. |
| 55 | # |
| 56 | # SKIP_MRPROPER |
| 57 | # if defined, skip `make mrproper` |
| 58 | # |
| 59 | # SKIP_DEFCONFIG |
| 60 | # if defined, skip `make defconfig` |
| 61 | # |
| 62 | # POST_DEFCONFIG_CMDS |
| 63 | # Command evaluated after `make defconfig` and before `make`. |
| 64 | # |
| 65 | # IN_KERNEL_MODULES |
| 66 | # if defined, install kernel modules |
| 67 | # |
| 68 | # SKIP_EXT_MODULES |
| 69 | # if defined, skip building and installing of external modules |
| 70 | # |
| 71 | # EXTRA_CMDS |
| 72 | # Command evaluated after building and installing kernel and modules. |
| 73 | # |
| 74 | # SKIP_CP_KERNEL_HDR |
| 75 | # if defined, skip installing kernel headers. |
| 76 | # |
| 77 | # Note: For historic reasons, internally, OUT_DIR will be copied into |
| 78 | # COMMON_OUT_DIR, and OUT_DIR will be then set to |
| 79 | # ${COMMON_OUT_DIR}/${KERNEL_DIR}. This has been done to accommodate existing |
| 80 | # build.config files that expect ${OUT_DIR} to point to the output directory of |
| 81 | # the kernel build. |
| 82 | # |
| 83 | # The kernel is built in ${COMMON_OUT_DIR}/${KERNEL_DIR}. |
| 84 | # Out-of-tree modules are built in ${COMMON_OUT_DIR}/${EXT_MOD} where |
| 85 | # ${EXT_MOD} is the path to the module source code. |
| 86 | |
| 87 | set -e |
| 88 | |
| 89 | # rel_path <to> <from> |
| 90 | # Generate relative directory path to reach directory <to> from <from> |
| 91 | function rel_path() { |
| 92 | local to=$1 |
| 93 | local from=$2 |
| 94 | local path= |
| 95 | local stem= |
| 96 | local prevstem= |
| 97 | [ -n "$to" ] || return 1 |
| 98 | [ -n "$from" ] || return 1 |
| 99 | to=$(readlink -e "$to") |
| 100 | from=$(readlink -e "$from") |
| 101 | [ -n "$to" ] || return 1 |
| 102 | [ -n "$from" ] || return 1 |
| 103 | stem=${from}/ |
| 104 | while [ "${to#$stem}" == "${to}" -a "${stem}" != "${prevstem}" ]; do |
| 105 | prevstem=$stem |
| 106 | stem=$(readlink -e "${stem}/..") |
| 107 | [ "${stem%/}" == "${stem}" ] && stem=${stem}/ |
| 108 | path=${path}../ |
| 109 | done |
| 110 | echo ${path}${to#$stem} |
| 111 | } |
| 112 | |
| 113 | export ROOT_DIR=$(readlink -f $(dirname $0)/..) |
| 114 | |
| 115 | # For module file Signing with the kernel (if needed) |
| 116 | FILE_SIGN_BIN=scripts/sign-file |
| 117 | SIGN_SEC=certs/signing_key.pem |
| 118 | SIGN_CERT=certs/signing_key.x509 |
| 119 | SIGN_ALGO=sha512 |
| 120 | |
| 121 | source "${ROOT_DIR}/build/envsetup.sh" |
| 122 | |
| 123 | export MAKE_ARGS=$@ |
| 124 | export COMMON_OUT_DIR=$(readlink -m ${OUT_DIR:-${ROOT_DIR}/out/${BRANCH}}) |
| 125 | export OUT_DIR=$(readlink -m ${COMMON_OUT_DIR}/${KERNEL_DIR}) |
| 126 | export MODULES_STAGING_DIR=$(readlink -m ${COMMON_OUT_DIR}/staging) |
| 127 | export MODULES_PRIVATE_DIR=$(readlink -m ${COMMON_OUT_DIR}/private) |
| 128 | export DIST_DIR=$(readlink -m ${DIST_DIR:-${COMMON_OUT_DIR}/dist}) |
| 129 | export UNSTRIPPED_DIR=${DIST_DIR}/unstripped |
| 130 | export KERNEL_UAPI_HEADERS_DIR=$(readlink -m ${COMMON_OUT_DIR}/kernel_uapi_headers) |
| 131 | |
| 132 | cd ${ROOT_DIR} |
| 133 | |
| 134 | export CLANG_TRIPLE CROSS_COMPILE CROSS_COMPILE_ARM32 ARCH SUBARCH |
| 135 | |
| 136 | mkdir -p ${OUT_DIR} |
| 137 | echo "========================================================" |
| 138 | echo " Setting up for build" |
| 139 | if [ -z "${SKIP_MRPROPER}" ] ; then |
| 140 | set -x |
| 141 | (cd ${KERNEL_DIR} && make O=${OUT_DIR} mrproper) |
| 142 | set +x |
| 143 | fi |
| 144 | |
| 145 | if [ -z "${SKIP_DEFCONFIG}" ] ; then |
| 146 | set -x |
| 147 | (cd ${KERNEL_DIR} && make O=${OUT_DIR} ${DEFCONFIG}) |
| 148 | set +x |
| 149 | |
| 150 | if [ "${POST_DEFCONFIG_CMDS}" != "" ]; then |
| 151 | echo "========================================================" |
| 152 | echo " Running pre-make command(s):" |
| 153 | set -x |
| 154 | eval ${POST_DEFCONFIG_CMDS} |
| 155 | set +x |
| 156 | fi |
| 157 | fi |
| 158 | |
| 159 | echo "========================================================" |
| 160 | echo " Building kernel" |
| 161 | |
| 162 | if [ -n "${CC}" ]; then |
| 163 | CC_ARG="CC=${CC}" |
| 164 | fi |
| 165 | |
| 166 | if [ -n "${LD}" ]; then |
| 167 | LD_ARG="LD=${LD}" |
| 168 | fi |
| 169 | |
| 170 | set -x |
| 171 | (cd ${OUT_DIR} && \ |
| 172 | make O=${OUT_DIR} ${CC_ARG} ${LD_ARG} -j$(nproc) $@) |
| 173 | set +x |
| 174 | |
| 175 | rm -rf ${MODULES_STAGING_DIR} |
| 176 | mkdir -p ${MODULES_STAGING_DIR} |
| 177 | |
| 178 | if [ -n "${IN_KERNEL_MODULES}" ]; then |
| 179 | echo "========================================================" |
| 180 | echo " Installing kernel modules into staging directory" |
| 181 | |
| 182 | (cd ${OUT_DIR} && \ |
| 183 | make O=${OUT_DIR} ${CC_ARG} ${LD_ARG} INSTALL_MOD_STRIP=1 \ |
| 184 | INSTALL_MOD_PATH=${MODULES_STAGING_DIR} modules_install) |
| 185 | fi |
| 186 | |
| 187 | if [[ -z "${SKIP_EXT_MODULES}" ]] && [[ "${EXT_MODULES}" != "" ]]; then |
| 188 | echo "========================================================" |
| 189 | echo " Building external modules and installing them into staging directory" |
| 190 | |
| 191 | for EXT_MOD in ${EXT_MODULES}; do |
| 192 | # The path that we pass in via the variable M needs to be a relative path |
| 193 | # relative to the kernel source directory. The source files will then be |
| 194 | # looked for in ${KERNEL_DIR}/${EXT_MOD_REL} and the object files (i.e. .o |
| 195 | # and .ko) files will be stored in ${OUT_DIR}/${EXT_MOD_REL}. If we |
| 196 | # instead set M to an absolute path, then object (i.e. .o and .ko) files |
| 197 | # are stored in the module source directory which is not what we want. |
| 198 | EXT_MOD_REL=$(rel_path ${ROOT_DIR}/${EXT_MOD} ${KERNEL_DIR}) |
| 199 | # The output directory must exist before we invoke make. Otherwise, the |
| 200 | # build system behaves horribly wrong. |
| 201 | mkdir -p ${OUT_DIR}/${EXT_MOD_REL} |
| 202 | set -x |
| 203 | make -C ${EXT_MOD} M=${EXT_MOD_REL} KERNEL_SRC=${ROOT_DIR}/${KERNEL_DIR} \ |
| 204 | O=${OUT_DIR} ${CC_ARG} ${LD_ARG} -j$(nproc) "$@" |
| 205 | make -C ${EXT_MOD} M=${EXT_MOD_REL} KERNEL_SRC=${ROOT_DIR}/${KERNEL_DIR} \ |
| 206 | O=${OUT_DIR} ${CC_ARG} ${LD_ARG} INSTALL_MOD_STRIP=1 \ |
| 207 | INSTALL_MOD_PATH=${MODULES_STAGING_DIR} modules_install |
| 208 | set +x |
| 209 | done |
| 210 | |
| 211 | fi |
| 212 | |
| 213 | if [ "${EXTRA_CMDS}" != "" ]; then |
| 214 | echo "========================================================" |
| 215 | echo " Running extra build command(s):" |
| 216 | set -x |
| 217 | eval ${EXTRA_CMDS} |
| 218 | set +x |
| 219 | fi |
| 220 | |
| 221 | OVERLAYS_OUT="" |
| 222 | for ODM_DIR in ${ODM_DIRS}; do |
| 223 | OVERLAY_DIR=${ROOT_DIR}/device/${ODM_DIR}/overlays |
| 224 | |
| 225 | if [ -d ${OVERLAY_DIR} ]; then |
| 226 | OVERLAY_OUT_DIR=${OUT_DIR}/overlays/${ODM_DIR} |
| 227 | mkdir -p ${OVERLAY_OUT_DIR} |
| 228 | make -C ${OVERLAY_DIR} DTC=${OUT_DIR}/scripts/dtc/dtc OUT_DIR=${OVERLAY_OUT_DIR} |
| 229 | OVERLAYS=$(find ${OVERLAY_OUT_DIR} -name "*.dtbo") |
| 230 | OVERLAYS_OUT="$OVERLAYS_OUT $OVERLAYS" |
| 231 | fi |
| 232 | done |
| 233 | |
| 234 | mkdir -p ${DIST_DIR} |
| 235 | echo "========================================================" |
| 236 | echo " Copying files" |
| 237 | for FILE in ${FILES}; do |
| 238 | if [ -f ${OUT_DIR}/${FILE} ]; then |
| 239 | echo " $FILE" |
| 240 | cp -p ${OUT_DIR}/${FILE} ${DIST_DIR}/ |
| 241 | else |
| 242 | echo " $FILE does not exist, skipping" |
| 243 | fi |
| 244 | done |
| 245 | |
| 246 | for FILE in ${OVERLAYS_OUT}; do |
| 247 | OVERLAY_DIST_DIR=${DIST_DIR}/$(dirname ${FILE#${OUT_DIR}/overlays/}) |
| 248 | echo " ${FILE#${OUT_DIR}/}" |
| 249 | mkdir -p ${OVERLAY_DIST_DIR} |
| 250 | cp ${FILE} ${OVERLAY_DIST_DIR}/ |
| 251 | done |
| 252 | |
| 253 | MODULES=$(find ${MODULES_STAGING_DIR} -type f -name "*.ko") |
| 254 | if [ -n "${MODULES}" ]; then |
| 255 | echo "========================================================" |
| 256 | echo " Copying modules files" |
| 257 | if [ -n "${IN_KERNEL_MODULES}" -o "${EXT_MODULES}" != "" ]; then |
| 258 | for FILE in ${MODULES}; do |
| 259 | echo " ${FILE#${MODULES_STAGING_DIR}/}" |
| 260 | cp -p ${FILE} ${DIST_DIR} |
| 261 | done |
| 262 | fi |
| 263 | fi |
| 264 | |
| 265 | if [ "${UNSTRIPPED_MODULES}" != "" ]; then |
| 266 | echo "========================================================" |
| 267 | echo " Copying unstripped module files for debugging purposes (not loaded on device)" |
| 268 | mkdir -p ${UNSTRIPPED_DIR} |
| 269 | for MODULE in ${UNSTRIPPED_MODULES}; do |
| 270 | find ${MODULES_PRIVATE_DIR} -name ${MODULE} -exec cp {} ${UNSTRIPPED_DIR} \; |
| 271 | done |
| 272 | fi |
| 273 | |
| 274 | if [ -z "${SKIP_CP_KERNEL_HDR}" ]; then |
| 275 | echo "========================================================" |
| 276 | echo " Installing UAPI kernel headers:" |
| 277 | mkdir -p "${KERNEL_UAPI_HEADERS_DIR}/usr" |
| 278 | make -C ${OUT_DIR} O=${OUT_DIR} ${CC_ARG} INSTALL_HDR_PATH="${KERNEL_UAPI_HEADERS_DIR}/usr" -j$(nproc) headers_install |
| 279 | # The kernel makefiles create files named ..install.cmd and .install which |
| 280 | # are only side products. We don't want those. Let's delete them. |
| 281 | find ${KERNEL_UAPI_HEADERS_DIR} \( -name ..install.cmd -o -name .install \) -exec rm '{}' + |
| 282 | KERNEL_UAPI_HEADERS_TAR=${DIST_DIR}/kernel-uapi-headers.tar.gz |
| 283 | echo " Copying kernel UAPI headers to ${KERNEL_UAPI_HEADERS_TAR}" |
| 284 | tar -czf ${KERNEL_UAPI_HEADERS_TAR} --directory=${KERNEL_UAPI_HEADERS_DIR} usr/ |
| 285 | fi |
| 286 | |
| 287 | if [ -z "${SKIP_CP_KERNEL_HDR}" ] ; then |
| 288 | echo "========================================================" |
| 289 | KERNEL_HEADERS_TAR=${DIST_DIR}/kernel-headers.tar.gz |
| 290 | echo " Copying kernel headers to ${KERNEL_HEADERS_TAR}" |
| 291 | TMP_DIR="/tmp" |
| 292 | TMP_KERNEL_HEADERS_CHILD="kernel-headers" |
| 293 | TMP_KERNEL_HEADERS_DIR=$TMP_DIR/$TMP_KERNEL_HEADERS_CHILD |
| 294 | CURDIR=$(pwd) |
| 295 | mkdir -p $TMP_KERNEL_HEADERS_DIR |
| 296 | cd $ROOT_DIR/$KERNEL_DIR; find arch -name *.h -exec cp --parents {} $TMP_KERNEL_HEADERS_DIR \; |
| 297 | cd $ROOT_DIR/$KERNEL_DIR; find include -name *.h -exec cp --parents {} $TMP_KERNEL_HEADERS_DIR \; |
| 298 | cd $OUT_DIR; find -name *.h -exec cp --parents {} $TMP_KERNEL_HEADERS_DIR \; |
| 299 | tar -czvf $KERNEL_HEADERS_TAR --directory=$TMP_DIR $TMP_KERNEL_HEADERS_CHILD > /dev/null 2>&1 |
| 300 | rm -rf $TMP_KERNEL_HEADERS_DIR |
| 301 | cd $CURDIR |
| 302 | fi |
| 303 | |
| 304 | echo "========================================================" |
| 305 | echo " Files copied to ${DIST_DIR}" |
| 306 | |
| 307 | # No trace_printk use on build server build |
| 308 | if readelf -a ${DIST_DIR}/vmlinux 2>&1 | grep -q trace_printk_fmt; then |
| 309 | echo "========================================================" |
| 310 | echo "WARN: Found trace_printk usage in vmlinux." |
| 311 | echo "" |
| 312 | echo "trace_printk will cause trace_printk_init_buffers executed in kernel" |
| 313 | echo "start, which will increase memory and lead warning shown during boot." |
| 314 | echo "We should not carry trace_printk in production kernel." |
| 315 | echo "" |
| 316 | if [ ! -z "${STOP_SHIP_TRACEPRINTK}" ]; then |
| 317 | echo "ERROR: stop ship on trace_printk usage." 1>&2 |
| 318 | exit 1 |
| 319 | fi |
| 320 | fi |