#!/bin/sh # # Copyright (C) 2009 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # This shell script is used to rebuild the Android NDK's prebuilt binaries. # # The source tarballs must be located in $ANDROID_NDK_ROOT/build/archive # They will be located in $ANDROID_NDK_ROOT/build/toolchain after compilation # # include common function and variable definitions source `dirname $0`/../core/ndk-common.sh # number of jobs to run in parallel when running make JOBS=$HOST_NUM_CPUS TOOLCHAIN_NAME=arm-eabi-4.2.1 PLATFORM=android-3 ABI=arm OPTION_HELP=no OPTION_PLATFORM= OPTION_FORCE_32=no OPTION_REBUILD=no VERBOSE=no for opt do optarg=`expr "x$opt" : 'x[^=]*=\(.*\)'` case "$opt" in --help|-h|-\?) OPTION_HELP=yes ;; --verbose) if [ "$VERBOSE" = "yes" ] ; then VERBOSE2=yes else VERBOSE=yes fi ;; --toolchain=*) TOOLCHAIN_NAME=$optarg ;; --platform=*) PLATFORM=$optarg ;; --abi=*) ABI=$optarg ;; --force-download) OPTION_FORCE_DOWNLOAD=yes OPTION_FORCE_BUILD=yes ;; --force-build) OPTION_FORCE_BUILD=yes ;; --verbose) VERBOSE=yes ;; *) echo "unknown option '$opt', use --help" exit 1 esac done if [ $OPTION_HELP = "yes" ] ; then echo "Rebuild the prebuilt binaries for the Android NDK toolchain." echo "" echo "options:" echo "" echo " --help print this message" echo " --toolchain=<name> toolchain name (default is $TOOLCHAIN_NAME)" echo " --platform=<name> generate toolchain from platform <name> (default is $PLATFORM)" echo " --abi=<name> generate toolchain from abi <name> (default is $ABI)" echo " --build-out=<path> set Android build out directory" echo " --force-download force a download and unpacking of the toolchain sources" echo " --force-build force a rebuild of the sources" echo "" exit 0 fi # Force generation of 32-bit binaries on 64-bit systems case $HOST_TAG in *-x86_64) HOST_CFLAGS="$HOST_CFLAGS -m32" HOST_LDFLAGS="$HOST_LDFLAGS -m32" force_32bit_binaries # to modify HOST_TAG and others ;; esac TMPLOG=/tmp/android-toolchain-build-$$.log rm -rf $TMPLOG if [ $VERBOSE = yes ] ; then run () { echo "##### NEW COMMAND" echo $@ $@ 2>&1 | tee $TMPLOG } else echo "To follow build long, please use in another terminal: tail -F $TMPLOG" run () { echo "##### NEW COMMAND" >> $TMPLOG echo "$@" >> $TMPLOG $@ 1>$TMPLOG 2>&1 } fi ANDROID_NDK_ROOT=`cd $ANDROID_NDK_ROOT && pwd` ANDROID_NDK_ARCHIVE=$ANDROID_NDK_ROOT/build/toolchains/archive ANDROID_PLATFORMS_ROOT=$ANDROID_NDK_ROOT/build/platforms # where all generated files will be placed OUT=$ANDROID_NDK_ROOT/out/$TOOLCHAIN_NAME PACKAGE_OUT=$OUT/packages TIMESTAMP_OUT=$OUT/timestamps # where the sysroot is located ANDROID_SYSROOT=$ANDROID_NDK_ROOT/build/platforms/$PLATFORM/arch-$ABI # where the toolchain binaries will be placed ANDROID_TOOLCHAIN_OUT=$OUT/toolchain ANDROID_TOOLCHAIN_SRC=$ANDROID_TOOLCHAIN_OUT/src ANDROID_TOOLCHAIN_BUILD=$ANDROID_TOOLCHAIN_OUT/build # where the gdbserver binaries will be placed ANDROID_GDBSERVER_OUT=$OUT/gdbserver ANDROID_GDBSERVER_BUILD=$ANDROID_GDBSERVER_OUT/build ANDROID_GDBSERVER_DEST=$ANDROID_SYSROOT/usr/bin # Let's check that we have a working md5sum here A_MD5=`echo "A" | md5sum | cut -d' ' -f1` if [ "$A_MD5" != "bf072e9119077b4e76437a93986787ef" ] ; then echo "Please install md5sum on this machine" exit 2 fi # And wget too WGET=`which wget` CURL=`which curl` SCP=`which scp` # download a file with either 'curl', 'wget' or 'scp' # $1: source # $2: target download_file () { # is this HTTP, HTTPS or FTP ? echo $1 | grep -q -e "^\(http\|https\):.*" if [ $? = 0 ] ; then if [ -n "$WGET" ] ; then $WGET -O $2 $1 elif [ -n "$CURL" ] ; then $CURL -o $2 $1 else echo "Please install wget or curl on this machine" exit 1 fi return fi # is this SSH ? echo $1 | grep -q -e "^ssh:.*" if [ $? = 0 ] ; then if [ -n "$SCP" ] ; then scp_src=`echo $1 | sed -e s%ssh://%%g` $SCP $scp_src $2 else echo "Please install scp on this machine" exit 1 fi return fi echo $1 | grep -q -e "^/.*" if [ $? = 0 ] ; then cp -f $1 $2 fi } TOOLCHAIN_SRC=$ANDROID_TOOLCHAIN_SRC TOOLCHAIN_BUILD=$ANDROID_TOOLCHAIN_BUILD TOOLCHAIN_PREFIX=$ANDROID_NDK_ROOT/build/prebuilt/$HOST_TAG/$TOOLCHAIN_NAME GDBSERVER_BUILD=$ANDROID_GDBSERVER_BUILD timestamp_check () { [ -f $TIMESTAMP_OUT/$1/timestamp-$2 ] } timestamp_set () { mkdir -p $TIMESTAMP_OUT/$1 touch $TIMESTAMP_OUT/$1/timestamp-$2 } timestamp_clear () { rm -f $TIMESTAMP_OUT/$1/timestamp-* } timestamp_force () { rm -f $TIMESTAMP_OUT/$1/timestamp-$2 } # this function will be used to download and verify a toolchain # package # $1: directory name under build/archive (e.g. 'android-toolchain') # download_package () { WORKSPACE=$ANDROID_NDK_ARCHIVE/$1 if [ ! -d $WORKSPACE ] ; then echo "No directory named $1 under $ANDROID_NDK_ARCHIVE" exit 2 fi SOURCES=$WORKSPACE/sources.txt if [ ! -f $SOURCES ] ; then echo "Missing sources.txt in $WORKSPACE" exit 2 fi # First line must be file name PKGNAME=`cat $SOURCES | sed 1q` # Second line must be md5sum PKGSUM=`cat $SOURCES | sed 1d | sed 1q` if [ -z "$PKGNAME" -o -z "$PKGSUM" ] ; then echo "Corrupted file: $SOURCES" exit 2 fi # Try to download the package if it is not there # the Third line of sources.txt, and all others behind # must be wget urls or something. PACKAGE_TARBALL=$PACKAGE_OUT/$PKGNAME if [ ! -f $PACKAGE_TARBALL ] ; then cat $SOURCES | sed 1,2d | while read src; do echo $src | grep -q -e "^/.*" if [ $? = 0 ] ; then if [ -f $src ] ; then echo "Copy : $PKGNAME" echo " from `dirname $src`" echo " into $PACKAGE_TARBALL" run cp -f $src $PACKAGE_TARBALL if [ $? = 0 ] ; then break fi echo "Copy : Problem copying from $src" else echo "Copy : Can't find $src (skipping)" fi continue fi echo $src | grep -q -e "^\(http\|https\|ftp\|ssh\):.*" if [ $? = 0 ] ; then echo "Download: $PKGNAME" echo " from $src" echo " into $PACKAGE_TARBALL" download_file $src $PACKAGE_TARBALL if [ $? = 0 ] ; then break fi continue else "Copy : Unknown method in $src" fi done if [ ! -f $PACKAGE_TARBALL ] ; then echo "ERROR: Could not copy or download $PKGNAME !" echo "Your probably need to edit $WORKSPACE/sources.txt" exit 1 fi fi if ! timestamp_check $1 verify ; then SUM=`md5sum $PACKAGE_TARBALL | cut -d " " -f 1` if [ "$SUM" != "$PKGSUM" ] ; then echo "ERROR: Invalid MD5 Sum for $PACKAGE_TARBALL" echo " Expected $PKGSUM" echo " Computed $SUM" echo "You might want to use the --force-download option." exit 2 fi echo "Verified: $PACKAGE_TARBALL" timestamp_set $1 verify timestamp_force $1 unpack fi eval PKG_$1=$PACKAGE_TARBALL } # Unpack a given package in a target location # $1: package name # $2: target directory # unpack_package () { WORKSPACE=$ANDROID_NDK_ARCHIVE/$1 SRCDIR=$2 SRCPKG=`var_value PKG_$1` if ! timestamp_check $1 unpack; then echo "Unpack : $1 sources" echo " from $SRCPKG" echo " into $SRCDIR" rm -rf $SRCDIR mkdir -p $SRCDIR TARFLAGS=xjf if [ $VERBOSE = yes ]; then TARFLAGS="v$TARFLAGS" fi run tar $TARFLAGS $SRCPKG -C $SRCDIR if [ $? != 0 ] ; then echo "ERROR: Could not unpack $1, See $TMPLOG" exit 1 fi timestamp_set $1 unpack timestamp_force $1 configure fi } if [ $OPTION_FORCE_DOWNLOAD ] ; then rm -rf $PACKAGE_OUT $ANDROID_TOOLCHAIN_SRC timestamp_force toolchain unpack timestamp_force toolchain verify fi if [ $OPTION_FORCE_BUILD ] ; then rm -rf $ANDROID_TOOLCHAIN_BUILD timestamp_clear toolchain timestamp_clear gdbserver fi # checks, we need more checks.. mkdir -p $PACKAGE_OUT if [ $? != 0 ] ; then echo "Can't create download/archive directory for toolchain tarballs" exit 2 fi download_package toolchain unpack_package toolchain $ANDROID_TOOLCHAIN_SRC # remove all info files from the unpacked toolchain sources # they create countless little problems during the build # if you don't have exactly the configuration expected by # the scripts. # find $ANDROID_TOOLCHAIN_SRC -type f -a -name "*.info" -print0 | xargs -0 rm -f # configure the toolchain if ! timestamp_check toolchain configure; then echo "Configure: toolchain build" mkdir -p $TOOLCHAIN_BUILD && cd $TOOLCHAIN_BUILD && export CFLAGS="$HOST_CFLAGS" && export LDFLAGS="$HOST_LDFLAGS" && run \ $TOOLCHAIN_SRC/configure --target=arm-eabi \ --disable-nls \ --prefix=$TOOLCHAIN_PREFIX \ --with-sysroot=$ANDROID_SYSROOT if [ $? != 0 ] ; then echo "Error while trying to configure toolchain build. See $TMPLOG" exit 1 fi timestamp_set toolchain configure timestamp_force toolchain build fi # build the toolchain if ! timestamp_check toolchain build ; then echo "Building : toolchain [this can take a long time]." cd $TOOLCHAIN_BUILD && export CFLAGS="$HOST_CFLAGS" && export LDFLAGS="$HOST_LDFLAGS" && run make -j$JOBS if [ $? != 0 ] ; then echo "Error while building toolchain. See $TMPLOG" exit 1 fi timestamp_set toolchain build timestamp_force toolchain install fi # install the toolchain to its final location if ! timestamp_check toolchain install ; then echo "Install : toolchain binaries." cd $TOOLCHAIN_BUILD && run make install if [ $? != 0 ] ; then echo "Error while installing toolchain. See $TMPLOG" exit 1 fi # don't forget to copy the GPL and LGPL license files cp -f $TOOLCHAIN_SRC/COPYING $TOOLCHAIN_SRC/COPYING.LIB $TOOLCHAIN_PREFIX # remove some unneeded files rm -f $TOOLCHAIN_PREFIX/bin/*-gccbug rm -rf $TOOLCHAIN_PREFIX/man $TOOLCHAIN_PREFIX/info # strip binaries to reduce final package size strip $TOOLCHAIN_PREFIX/bin/* strip $TOOLCHAIN_PREFIX/arm-eabi/bin/* strip $TOOLCHAIN_PREFIX/libexec/gcc/*/*/cc1 strip $TOOLCHAIN_PREFIX/libexec/gcc/*/*/cc1plus strip $TOOLCHAIN_PREFIX/libexec/gcc/*/*/collect2 timestamp_set toolchain install timestamp_force gdbserver configure fi # configure the gdbserver build now if ! timestamp_check gdbserver configure; then echo "Configure: gdbserver build." mkdir -p $GDBSERVER_BUILD cd $GDBSERVER_BUILD && CFLAGS="-g -O2 -static -mandroid -I$ANDROID_SYSROOT/usr/include" \ LDFLAGS= \ CC="$TOOLCHAIN_PREFIX/bin/arm-eabi-gcc" \ run $TOOLCHAIN_SRC/gdb-6.6/gdb/gdbserver/configure \ --host=arm-eabi-linux \ --with-sysroot=$ANDROID_SYSROOT if [ $? != 0 ] ; then echo "Could not configure gdbserver build. See $TMPLOG" exit 1 fi timestamp_set gdbserver configure timestamp_force gdbserver build fi # build gdbserver if ! timestamp_check gdbserver build; then echo "Building : gdbserver." cd $GDBSERVER_BUILD && run make -j$JOBS if [ $? != 0 ] ; then echo "Could not build gdbserver. See $TMPLOG" exit 1 fi timestamp_set gdbserver build timestamp_force gdbserver install fi # install gdbserver # # note that we install it in the toolchain bin directory # not in $SYSROOT/usr/bin # if ! timestamp_check gdbserver install; then echo "Install : gdbserver." DEST=$TOOLCHAIN_PREFIX/bin mkdir -p $DEST && $TOOLCHAIN_PREFIX/bin/arm-eabi-strip $GDBSERVER_BUILD/gdbserver && run cp -f $GDBSERVER_BUILD/gdbserver $DEST/gdbserver if [ $? != 0 ] ; then echo "Could not install gdbserver. See $TMPLOG" exit 1 fi timestamp_set gdbserver install timestamp_force package toolchain fi # package the toolchain TOOLCHAIN_TARBALL=/tmp/prebuilt-$TOOLCHAIN_NAME-$HOST_TAG.tar.bz2 if ! timestamp_check package toolchain; then echo "Package : $HOST_ARCH toolchain binaries" echo " into $TOOLCHAIN_TARBALL" cd $ANDROID_NDK_ROOT && TARFLAGS="cjf" if [ $VERBOSE = yes ] ; then TARFLAGS="v$TARFLAGS" fi run tar $TARFLAGS $TOOLCHAIN_TARBALL build/prebuilt/$HOST_TAG/$TOOLCHAIN_NAME if [ $? != 0 ] ; then echo "ERROR: Cannot package prebuilt toolchain binaries. See $TMPLOG" exit 1 fi timestamp_set package toolchain else echo "prebuilt toolchain is in $TOOLCHAIN_TARBALL" fi echo "Done." rm -f $TMPLOG