#!/bin/sh # # A small script used to rebuild the Android goldfish kernel image # See docs/KERNEL.TXT for usage instructions. # export LANG=C export LC_ALL=C PROGNAME=$(basename "$0") MACHINE=goldfish VARIANT=goldfish OUTPUT=/tmp/kernel-qemu CROSSPREFIX=arm-linux-androideabi- CONFIG=goldfish GCC_VERSION=4.9 VALID_ARCHS="arm x86 x86_64 mips arm64 mips64" # Determine the host architecture, and which default prebuilt tag we need. # For the toolchain auto-detection. # HOST_OS=`uname -s` case "$HOST_OS" in Darwin) HOST_OS=darwin HOST_TAG=darwin-x86 BUILD_NUM_CPUS=$(sysctl -n hw.ncpu) ;; Linux) # note that building 32-bit binaries on x86_64 is handled later HOST_OS=linux HOST_TAG=linux-x86 BUILD_NUM_CPUS=$(grep -c processor /proc/cpuinfo) ;; *) echo "ERROR: Unsupported OS: $HOST_OS" exit 1 esac # Default number of parallel jobs during the build: cores * 2 JOBS=$(( $BUILD_NUM_CPUS * 2 )) ARCH=arm OPTION_HELP=no OPTION_ARMV7=yes OPTION_OUT= OPTION_CROSS= OPTION_ARCH= OPTION_CONFIG= OPTION_SAVEDEFCONFIG=no OPTION_JOBS= OPTION_VERBOSE= OPTION_GCC_VERSION= CCACHE= case "$USE_CCACHE" in "") CCACHE= ;; *) # use ccache bundled in AOSP source tree CCACHE=${ANDROID_BUILD_TOP:-$(dirname $0)/../..}/prebuilts/misc/$HOST_TAG/ccache/ccache [ -x $CCACHE ] || CCACHE= ;; esac for opt do optarg=$(expr "x$opt" : 'x[^=]*=\(.*\)') case $opt in --help|-h|-\?) OPTION_HELP=yes ;; --arch=*) OPTION_ARCH=$optarg ;; --armv5) OPTION_ARMV7=no ;; --armv7) OPTION_ARMV7=yes ;; --ccache=*) CCACHE=$optarg ;; --config=*) OPTION_CONFIG=$optarg ;; --cross=*) OPTION_CROSS=$optarg ;; --gcc-version=*) OPTION_GCC_VERSION=$optarg ;; -j*|--jobs=*) OPTION_JOBS=$optarg ;; --out=*) OPTION_OUT=$optarg ;; --savedefconfig) OPTION_SAVEDEFCONFIG=yes ;; --verbose) OPTION_VERBOSE=true ;; *) echo "unknown option '$opt', use --help" exit 1 esac done if [ $OPTION_HELP = "yes" ] ; then echo "Rebuild the prebuilt kernel binary for Android's emulator." echo "" echo "options (defaults are within brackets):" echo "" echo " --help print this message" echo " --arch=<arch> change target architecture [$ARCH]" echo " --armv5 build ARMv5 binaries" echo " --armv7 build ARMv7 binaries (default. see note below)" echo " --out=<directory> output directory [$OUTPUT]" echo " --cross=<prefix> cross-toolchain prefix [$CROSSPREFIX]" echo " --config=<name> kernel config name [$CONFIG]" echo " --savedefconfig run savedefconfig" echo " --ccache=<path> use compiler cache [${CCACHE:-not set}]" echo " --gcc-version=<version> use specific GCC version [$GCC_VERSION]" echo " --verbose show build commands" echo " -j<number> launch <number> parallel build jobs [$JOBS]" echo "" echo "NOTE: --armv7 is equivalent to --config=goldfish_armv7. It is" echo " ignored if --config=<name> is used." echo "" exit 0 fi if [ ! -f include/linux/vermagic.h ]; then echo "ERROR: You must be in the top-level kernel source directory to run this script." exit 1 fi # Extract kernel version, we'll need to put this in the final binaries names # to ensure the emulator can trivially know it without probing the binary with # 'file' or other unreliable heuristics. KERNEL_MAJOR=$(awk '$1 == "VERSION" { print $3; }' Makefile) KERNEL_MINOR=$(awk '$1 == "PATCHLEVEL" { print $3; }' Makefile) KERNEL_PATCH=$(awk '$1 == "SUBLEVEL" { print $3; }' Makefile) KERNEL_VERSION="$KERNEL_MAJOR.$KERNEL_MINOR.$KERNEL_PATCH" echo "Found kernel version: $KERNEL_VERSION" if [ -n "$OPTION_ARCH" ]; then ARCH=$OPTION_ARCH fi if [ -n "$OPTION_GCC_VERSION" ]; then GCC_VERSION=$OPTION_GCC_VERSION else if [ "$ARCH" = "x86" ]; then # Work-around a nasty bug. # Hence 132637 is 2.6.29. if [ "$KERNEL_VERSION" = "2.6.29" ]; then GCC_VERSION=4.6 echo "WARNING: android-goldfish-$KERNEL_VERSION doesn't build --arch=$ARCH with GCC 4.7" fi fi if [ "$ARCH" = "arm64" ]; then # There is no GCC 4.7 toolchain to build AARCH64 binaries. GCC_VERSION=4.8 fi if [ "$ARCH" = "mips64" ]; then GCC_VERSION=4.9 fi if [ "$ARCH" = "mips" ]; then GCC_VERSION=4.9 fi echo "Autoconfig: --gcc-version=$GCC_VERSION" fi if [ -n "$OPTION_CONFIG" ]; then CONFIG=$OPTION_CONFIG else case $ARCH in arm) CONFIG=goldfish_armv7 if [ "$OPTION_ARMV7" = "no" ]; then CONFIG=goldfish fi ;; x86) # Warning: this is ambiguous, should be 'goldfish' before 3.10, # and 'i386_emu" after it. if [ -f "arch/x86/configs/i386_emu_defconfig" ]; then CONFIG=i386_emu else CONFIG=goldfish fi ;; x86_64) CONFIG=x86_64_emu ;; mips) CONFIG=goldfish ;; mips64) CONFIG=ranchu64 ;; arm64) CONFIG=ranchu ;; *) echo "ERROR: Invalid arch '$ARCH', try one of $VALID_ARCHS" exit 1 esac echo "Auto-config: --config=$CONFIG" fi # Check output directory. if [ -n "$OPTION_OUT" ] ; then if [ ! -d "$OPTION_OUT" ] ; then echo "Output directory '$OPTION_OUT' does not exist ! Aborting." exit 1 fi OUTPUT=$OPTION_OUT else OUTPUT=$OUTPUT/${ARCH}-${KERNEL_VERSION} case $CONFIG in vbox*) OUTPUT=${OUTPUT}-vbox ;; goldfish) if [ "$ARCH" = "arm" ]; then OUTPUT=${OUTPUT}-armv5 fi ;; esac echo "Auto-config: --out=$OUTPUT" mkdir -p $OUTPUT fi if [ -n "$OPTION_CROSS" ] ; then CROSSPREFIX="$OPTION_CROSS" CROSSTOOLCHAIN=${CROSSPREFIX}$GCC_VERSION else case $ARCH in arm) CROSSPREFIX=arm-linux-androideabi- ;; x86) CROSSPREFIX=x86_64-linux-android- # NOTE: kernel-toolchain/toolbox.sh will add -m32 ;; x86_64) CROSSPREFIX=x86_64-linux-android- ;; mips) CROSSPREFIX=mips64el-linux-android- ;; mips64) CROSSPREFIX=mips64el-linux-android- ;; arm64) CROSSPREFIX=aarch64-linux-android- ;; *) echo "ERROR: Unsupported architecture!" exit 1 ;; esac CROSSTOOLCHAIN=${CROSSPREFIX}$GCC_VERSION echo "Auto-config: --cross=$CROSSPREFIX" fi ZIMAGE=zImage case $ARCH in x86|x86_64) ZIMAGE=bzImage ;; arm64) ZIMAGE=Image ;; mips) ZIMAGE= ;; mips64) ZIMAGE= ;; esac # If the cross-compiler is not in the path, try to find it automatically CROSS_COMPILER="${CROSSPREFIX}gcc" CROSS_COMPILER_VERSION=$($CROSS_COMPILER --version 2>/dev/null) if [ $? != 0 ] ; then BUILD_TOP=$ANDROID_BUILD_TOP if [ -z "$BUILD_TOP" ]; then # Assume this script is under external/qemu/distrib/ in the # Android source tree. BUILD_TOP=$(dirname $0)/../.. if [ ! -d "$BUILD_TOP/prebuilts" ]; then BUILD_TOP= else BUILD_TOP=$(cd $BUILD_TOP && pwd) fi fi case $ARCH in x86_64) # x86_46 binaries are under prebuilts/gcc/<host>/x86 !! PREBUILT_ARCH=x86 ;; arm64) PREBUILT_ARCH=aarch64 ;; mips64) PREBUILT_ARCH=mips ;; *) PREBUILT_ARCH=$ARCH ;; esac CROSSPREFIX=$BUILD_TOP/prebuilts/gcc/$HOST_TAG/$PREBUILT_ARCH/$CROSSTOOLCHAIN/bin/$CROSSPREFIX echo "Checking for ${CROSSPREFIX}gcc" if [ "$BUILD_TOP" -a -f ${CROSSPREFIX}gcc ]; then echo "Auto-config: --cross=$CROSSPREFIX" else echo "It looks like $CROSS_COMPILER is not in your path ! Aborting." exit 1 fi fi if [ "$CCACHE" ] ; then echo "Using ccache program: $CCACHE" CROSSPREFIX="$CCACHE $CROSSPREFIX" fi export CROSS_COMPILE="$CROSSPREFIX" ARCH SUBARCH=$ARCH if [ "$OPTION_JOBS" ]; then JOBS=$OPTION_JOBS else echo "Auto-config: -j$JOBS" fi # Special magic redirection with our magic toolbox script # This is needed to add extra compiler flags to compiler. # See kernel-toolchain/android-kernel-toolchain-* for details # export REAL_CROSS_COMPILE="$CROSS_COMPILE" CROSS_COMPILE=$(dirname "$0")/kernel-toolchain/android-kernel-toolchain- MAKE_FLAGS= if [ "$OPTION_VERBOSE" ]; then MAKE_FLAGS="$MAKE_FLAGS V=1" fi case $CONFIG in defconfig) MAKE_DEFCONFIG=$CONFIG ;; *) MAKE_DEFCONFIG=${CONFIG}_defconfig ;; esac ORG_ARCH=$ARCH case $ARCH in mips64) # MIPS64 Kernel code base is under arch/mips ARCH=mips ;; esac # Do the build # rm -f include/asm && make $MAKE_DEFCONFIG && # configure the kernel make -j$JOBS $MAKE_FLAGS # build it if [ $? != 0 ] ; then echo "Could not build the kernel. Aborting !" exit 1 fi if [ "$OPTION_SAVEDEFCONFIG" = "yes" ]; then case $ARCH in x86_64) DEFCONFIG_ARCH=x86 ;; *) DEFCONFIG_ARCH=$ARCH ;; esac make savedefconfig mv -f defconfig arch/$DEFCONFIG_ARCH/configs/${CONFIG}_defconfig fi # Note: The exact names of the output files are important for the Android build, # do not change the definitions lightly. KERNEL_PREFIX=kernel-$KERNEL_VERSION # Naming conventions for the kernel image files: # # 1) The kernel image is called kernel-qemu, except for 32-bit ARM # where it must be called kernel-qemu-armv7 # # 2) The debug symbol file is called vmlinux-qemu, except for 32-bit # ARM where it must be called vmlinux-qemu-armv7 # OUTPUT_KERNEL=kernel-qemu OUTPUT_VMLINUX=vmlinux-qemu if [ "$CONFIG" = "goldfish_armv7" ]; then OUTPUT_KERNEL=${OUTPUT_KERNEL}-armv7 OUTPUT_VMLINUX=${OUTPUT_VMLINUX}-armv7 fi cp -f vmlinux $OUTPUT/$OUTPUT_VMLINUX if [ ! -z $ZIMAGE ]; then cp -f arch/$ARCH/boot/$ZIMAGE $OUTPUT/$OUTPUT_KERNEL else cp -f vmlinux $OUTPUT/$OUTPUT_KERNEL fi echo "Kernel $CONFIG prebuilt images ($OUTPUT_KERNEL and $OUTPUT_VMLINUX) copied to $OUTPUT successfully !" cp COPYING $OUTPUT/LINUX_KERNEL_COPYING cat > $OUTPUT/README <<EOF This directory contains kernel images to be used with the Android emulator program, for the $ORG_ARCH CPU architecture. It was built with the $PROGNAME script. For more details, read: \$AOSP/external/qemu/docs/ANDROID-KERNEL.TXT EOF exit 0