• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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