• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/bin/sh
2#
3# Copyright (C) 2009 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#  This shell script is used to rebuild the Android NDK's prebuilt binaries.
18#
19#  The source tarballs must be located in $ANDROID_NDK_ROOT/build/archive
20#  They will be located in $ANDROID_NDK_ROOT/build/toolchain after compilation
21#
22
23# include common function and variable definitions
24. `dirname $0`/../core/ndk-common.sh
25
26# number of jobs to run in parallel when running make
27JOBS=$HOST_NUM_CPUS
28
29TOOLCHAIN_NAME=arm-eabi-4.2.1
30PLATFORM=android-3
31ABI=arm
32GCC_VERSION=4.2.1
33GDB_VERSION=6.6
34
35OPTION_HELP=no
36OPTION_PLATFORM=
37OPTION_FORCE_32=no
38OPTION_REBUILD=no
39OPTION_GCC_VERSION=
40OPTION_GDB_VERSION=
41OPTION_TOOLCHAIN_NAME=
42OPTION_PACKAGE=
43
44VERBOSE=no
45for opt do
46    optarg=`expr "x$opt" : 'x[^=]*=\(.*\)'`
47    case "$opt" in
48    --help|-h|-\?) OPTION_HELP=yes
49    ;;
50    --verbose)
51        if [ "$VERBOSE" = "yes" ] ; then
52            VERBOSE2=yes
53        else
54            VERBOSE=yes
55        fi
56        ;;
57    --gcc-version=*)
58        OPTION_GCC_VERSION=$optarg
59        ;;
60    --gdb-version=*)
61        OPTION_GDB_VERSION=$optarg
62        ;;
63    --toolchain=*)
64        OPTION_TOOLCHAIN_NAME=$optarg
65        ;;
66    --package=*)
67        OPTION_PACKAGE="$optarg"
68        ;;
69    --platform=*)
70        PLATFORM=$optarg
71        ;;
72    --abi=*)
73        ABI=$optarg
74        ;;
75    --force-download)
76        OPTION_FORCE_DOWNLOAD=yes
77        OPTION_FORCE_BUILD=yes
78        ;;
79    --force-build)
80        OPTION_FORCE_BUILD=yes
81        ;;
82    --verbose)
83        VERBOSE=yes
84        ;;
85    *)
86        echo "unknown option '$opt', use --help"
87        exit 1
88    esac
89done
90
91if [ $OPTION_HELP = "yes" ] ; then
92    echo "Rebuild the prebuilt binaries for the Android NDK toolchain."
93    echo "This script will automatically download the sources from the"
94    echo "Internet, unless you use the --package=<file> option to specify"
95    echo "the exact source package to use."
96    echo ""
97    echo "See build/tools/download-toolchain-sources.sh for a tool that"
98    echo "can create a compatible source package from the current"
99    echo "git repositories."
100    echo ""
101    echo "options (defaults are within brackets):"
102    echo ""
103    echo "  --help                   print this message"
104    echo "  --gcc-version=<version>  select GCC version [$GCC_VERSION]"
105    echo "  --gdb-version=<version>  select GDB version [$GDB_VERSION]"
106    echo "  --toolchain=<name>       toolchain name (default is $TOOLCHAIN_NAME)"
107    echo "  --package=<file>         specify download source package"
108    echo "  --platform=<name>        generate toolchain from platform <name> (default is $PLATFORM)"
109    echo "  --abi=<name>             generate toolchain from abi <name> (default is $ABI)"
110    echo "  --build-out=<path>       set Android build out directory"
111    echo "  --force-download         force a download and unpacking of the toolchain sources"
112    echo "  --force-build            force a rebuild of the sources"
113    echo ""
114    exit 0
115fi
116
117# Force generation of 32-bit binaries on 64-bit systems
118case $HOST_TAG in
119    *-x86_64)
120        HOST_CFLAGS="$HOST_CFLAGS -m32"
121        HOST_LDFLAGS="$HOST_LDFLAGS -m32"
122        force_32bit_binaries  # to modify HOST_TAG and others
123        ;;
124esac
125
126TMPLOG=/tmp/android-toolchain-build-$$.log
127rm -rf $TMPLOG
128
129if [ $VERBOSE = yes ] ; then
130    run ()
131    {
132        echo "##### NEW COMMAND"
133        echo "$@"
134        $@ 2>&1
135    }
136    log ()
137    {
138        echo "LOG: $@"
139    }
140else
141    echo "To follow build, please use in another terminal: tail -F $TMPLOG"
142    run ()
143    {
144        echo "##### NEW COMMAND" >> $TMPLOG
145        echo "$@" >> $TMPLOG
146        $@ >>$TMPLOG 2>&1
147    }
148    log ()
149    {
150        echo "$@" > /dev/null
151    }
152fi
153
154if [ -n "$OPTION_GCC_VERSION" ] ; then
155    GCC_VERSION="$OPTION_GCC_VERSION"
156    log "Using gcc version $GCC_VERSION"
157else
158    log "Using default gcc version $GCC_VERSION"
159fi
160
161if [ -n "$OPTION_GDB_VERSION" ] ; then
162    GDB_VERSION="$OPTION_GDB_VERSION"
163    log "Using gdb version $GDB_VERSION"
164else
165    log "Using default gdb version $GDB_VERSION"
166fi
167
168if [ -n "$OPTION_TOOLCHAIN_NAME" ] ; then
169    TOOLCHAIN_NAME="$OPTION_TOOLCHAIN_NAME"
170    log "Using toolchain name '$TOOLCHAIN_NAME'"
171else
172    TOOLCHAIN_NAME=arm-eabi-$GCC_VERSION
173    log "Using default toolchain name '$TOOLCHAIN_NAME'"
174fi
175
176if [ -n "$OPTION_PACKAGE" ] ; then
177    if [ ! -f "$OPTION_PACKAGE" ] ; then
178        echo "Package is not a file: $OPTION_PACKAGE"
179        exit 1
180    fi
181fi
182
183ANDROID_NDK_ROOT=`cd $ANDROID_NDK_ROOT && pwd`
184ANDROID_NDK_ARCHIVE=$ANDROID_NDK_ROOT/build/toolchains/archive
185ANDROID_PLATFORMS_ROOT=$ANDROID_NDK_ROOT/build/platforms
186
187# where all generated files will be placed
188OUT=$ANDROID_NDK_ROOT/out/$TOOLCHAIN_NAME
189PACKAGE_OUT=$OUT/packages
190TIMESTAMP_OUT=$OUT/timestamps
191
192# where the sysroot is located
193ANDROID_SYSROOT=$ANDROID_NDK_ROOT/build/platforms/$PLATFORM/arch-$ABI
194
195# where the toolchain binaries will be placed
196ANDROID_TOOLCHAIN_OUT=$OUT/toolchain
197ANDROID_TOOLCHAIN_SRC=$ANDROID_TOOLCHAIN_OUT/src
198ANDROID_TOOLCHAIN_BUILD=$ANDROID_TOOLCHAIN_OUT/build
199
200# where the gdbserver binaries will be placed
201ANDROID_GDBSERVER_OUT=$OUT/gdbserver
202ANDROID_GDBSERVER_BUILD=$ANDROID_GDBSERVER_OUT/build
203ANDROID_GDBSERVER_DEST=$ANDROID_SYSROOT/usr/bin
204
205# Let's check that we have a working md5sum here
206A_MD5=`echo "A" | md5sum | cut -d' ' -f1`
207if [ "$A_MD5" != "bf072e9119077b4e76437a93986787ef" ] ; then
208    echo "Please install md5sum on this machine"
209    exit 2
210fi
211
212# And wget too
213WGET=`which wget`
214CURL=`which curl`
215SCP=`which scp`
216
217# download a file with either 'curl', 'wget' or 'scp'
218# $1: source
219# $2: target
220download_file ()
221{
222    # is this HTTP, HTTPS or FTP ?
223    echo $1 | grep -q -e "^\(http\|https\):.*"
224    if [ $? = 0 ] ; then
225        if [ -n "$WGET" ] ; then
226            $WGET -O $2 $1
227        elif [ -n "$CURL" ] ; then
228            $CURL -o $2 $1
229        else
230            echo "Please install wget or curl on this machine"
231            exit 1
232        fi
233        return
234    fi
235
236    # is this SSH ?
237    echo $1 | grep -q -e "^ssh:.*"
238    if [ $? = 0 ] ; then
239        if [ -n "$SCP" ] ; then
240            scp_src=`echo $1 | sed -e s%ssh://%%g`
241            $SCP $scp_src $2
242        else
243            echo "Please install scp on this machine"
244            exit 1
245        fi
246        return
247    fi
248
249    echo $1 | grep -q -e "^/.*"
250    if [ $? = 0 ] ; then
251        cp -f $1 $2
252    fi
253}
254
255TOOLCHAIN_SRC=$ANDROID_TOOLCHAIN_SRC
256TOOLCHAIN_BUILD=$ANDROID_TOOLCHAIN_BUILD
257TOOLCHAIN_PREFIX=$ANDROID_NDK_ROOT/build/prebuilt/$HOST_TAG/$TOOLCHAIN_NAME
258TOOLCHAIN_LICENSES=$ANDROID_NDK_ROOT/build/tools/toolchain-licenses
259
260GDBSERVER_BUILD=$ANDROID_GDBSERVER_BUILD
261
262timestamp_check ()
263{
264    [ -f $TIMESTAMP_OUT/$1/timestamp-$2 ]
265}
266
267timestamp_set ()
268{
269    mkdir -p $TIMESTAMP_OUT/$1
270    touch $TIMESTAMP_OUT/$1/timestamp-$2
271}
272
273timestamp_clear ()
274{
275    rm -f $TIMESTAMP_OUT/$1/timestamp-*
276}
277
278timestamp_force ()
279{
280    rm -f $TIMESTAMP_OUT/$1/timestamp-$2
281}
282
283# this function will be used to download and verify a toolchain
284# package
285# $1: directory name under build/archive  (e.g. 'android-toolchain')
286#
287download_package ()
288{
289    WORKSPACE=$ANDROID_NDK_ARCHIVE/$1
290    if [ ! -d $WORKSPACE ] ; then
291        echo "No directory named $1 under $ANDROID_NDK_ARCHIVE"
292        exit 2
293    fi
294    SOURCES=$WORKSPACE/sources.txt
295    if [ ! -f $SOURCES ] ; then
296        echo "Missing sources.txt in $WORKSPACE"
297        exit 2
298    fi
299    # First line must be file name
300    PKGNAME=`cat $SOURCES | sed 1q`
301    # Second line must be md5sum
302    PKGSUM=`cat $SOURCES | sed 1d | sed 1q`
303    if [ -z "$PKGNAME" -o -z "$PKGSUM" ] ; then
304        echo "Corrupted file: $SOURCES"
305        exit 2
306    fi
307
308    # Try to download the package if it is not there
309    # the Third line of sources.txt, and all others behind
310    # must be wget urls or something.
311    PACKAGE_TARBALL=$PACKAGE_OUT/$PKGNAME
312    if [ ! -f $PACKAGE_TARBALL ] ; then
313        cat $SOURCES | sed 1,2d | while read src; do
314            echo $src | grep -q -e "^/.*"
315            if [ $? = 0 ] ; then
316                if [ -f $src ] ; then
317                    echo "Copy    : $PKGNAME"
318                    echo "          from `dirname $src`"
319                    echo "          into $PACKAGE_TARBALL"
320                    run cp -f $src $PACKAGE_TARBALL
321                    if [ $? = 0 ] ; then
322                        break
323                    fi
324                    echo "Copy    : Problem copying from $src"
325                else
326                    echo "Copy    : Can't find $src (skipping)"
327                fi
328                continue
329            fi
330            echo $src | grep -q -e "^\(http\|https\|ftp\|ssh\):.*"
331            if [ $? = 0 ] ; then
332                echo "Download: $PKGNAME"
333                echo "          from $src"
334                echo "          into $PACKAGE_TARBALL"
335                download_file $src $PACKAGE_TARBALL
336                if [ $? = 0 ] ; then
337                    break
338                fi
339                continue
340            else
341                "Copy    : Unknown method in $src"
342            fi
343        done
344        if [ ! -f $PACKAGE_TARBALL ] ; then
345            echo "ERROR: Could not copy or download $PKGNAME !"
346            echo "Your probably need to edit $WORKSPACE/sources.txt"
347            exit 1
348        fi
349    fi
350
351    if ! timestamp_check $1 verify ; then
352        SUM=`md5sum $PACKAGE_TARBALL | cut -d " " -f 1`
353        if [ "$SUM" != "$PKGSUM" ] ; then
354            echo "ERROR: Invalid MD5 Sum for $PACKAGE_TARBALL"
355            echo "    Expected $PKGSUM"
356            echo "    Computed $SUM"
357            echo "You might want to use the --force-download option."
358            exit 2
359        fi
360
361        echo "Verified: $PACKAGE_TARBALL"
362        timestamp_set   $1 verify
363        timestamp_force $1 unpack
364    fi
365    eval PKG_$1=$PACKAGE_TARBALL
366}
367
368# Unpack a given package in a target location
369# $1: package name
370# $2: target directory
371#
372unpack_package ()
373{
374    WORKSPACE=$ANDROID_NDK_ARCHIVE/$1
375    SRCDIR=$2
376    SRCPKG=`var_value PKG_$1`
377    if ! timestamp_check $1 unpack; then
378        echo "Unpack  : $1 sources"
379        echo "          from $SRCPKG"
380        echo "          into $SRCDIR"
381        run rm -rf $SRCDIR
382        run mkdir -p $SRCDIR
383        TARFLAGS=xjf
384        if [ $VERBOSE2 = yes ]; then
385          TARFLAGS="v$TARFLAGS"
386        fi
387        run tar $TARFLAGS $SRCPKG -C $SRCDIR
388        if [ $? != 0 ] ; then
389            echo "ERROR: Could not unpack $1, See $TMPLOG"
390            exit 1
391        fi
392        timestamp_set   $1 unpack
393        timestamp_force $1 configure
394    fi
395}
396
397if [ $OPTION_FORCE_DOWNLOAD ] ; then
398    rm -rf $PACKAGE_OUT $ANDROID_TOOLCHAIN_SRC
399    timestamp_force toolchain unpack
400    timestamp_force toolchain verify
401fi
402
403if [ $OPTION_FORCE_BUILD ] ; then
404    rm -rf $ANDROID_TOOLCHAIN_BUILD
405    timestamp_clear toolchain
406    timestamp_clear gdbserver
407fi
408
409# checks, we need more checks..
410mkdir -p $PACKAGE_OUT
411if [ $? != 0 ] ; then
412    echo "Can't create download/archive directory for toolchain tarballs"
413    exit 2
414fi
415
416if [ -n "$OPTION_PACKAGE" ] ; then
417    PKG_toolchain="$OPTION_PACKAGE"
418else
419    download_package toolchain
420fi
421
422unpack_package   toolchain $ANDROID_TOOLCHAIN_SRC
423
424# remove all info files from the unpacked toolchain sources
425# they create countless little problems during the build
426# if you don't have exactly the configuration expected by
427# the scripts.
428#
429find $ANDROID_TOOLCHAIN_SRC -type f -a -name "*.info" -print0 | xargs -0 rm -f
430
431# configure the toolchain
432if ! timestamp_check toolchain configure; then
433    echo "Configure: toolchain build"
434    BUILD_SRCDIR=$TOOLCHAIN_SRC/build
435	if [ ! -d $BUILD_SRCDIR ] ; then
436        BUILD_SRCDIR=$TOOLCHAIN_SRC
437    fi
438    mkdir -p $TOOLCHAIN_BUILD &&
439    cd $TOOLCHAIN_BUILD &&
440    export ABI="32" &&  # needed to build a 32-bit gmp
441    export CFLAGS="$HOST_CFLAGS" &&
442    export LDFLAGS="$HOST_LDFLAGS" && run \
443    $BUILD_SRCDIR/configure --target=arm-eabi \
444                             --disable-nls \
445                             --prefix=$TOOLCHAIN_PREFIX \
446                             --with-sysroot=$ANDROID_SYSROOT \
447                             --with-gcc-version=$GCC_VERSION \
448                             --with-gdb-version=$GDB_VERSION
449    if [ $? != 0 ] ; then
450        echo "Error while trying to configure toolchain build. See $TMPLOG"
451        exit 1
452    fi
453    timestamp_set   toolchain configure
454    timestamp_force toolchain build
455fi
456
457# build the toolchain
458if ! timestamp_check toolchain build ; then
459    echo "Building : toolchain [this can take a long time]."
460    cd $TOOLCHAIN_BUILD &&
461    export CFLAGS="$HOST_CFLAGS" &&
462    export LDFLAGS="$HOST_LDFLAGS" &&
463    run make -j$JOBS
464    if [ $? != 0 ] ; then
465        echo "Error while building toolchain. See $TMPLOG"
466        exit 1
467    fi
468    timestamp_set   toolchain build
469    timestamp_force toolchain install
470fi
471
472# install the toolchain to its final location
473if ! timestamp_check toolchain install ; then
474    echo "Install  : toolchain binaries."
475    cd $TOOLCHAIN_BUILD &&
476    run make install
477    if [ $? != 0 ] ; then
478        echo "Error while installing toolchain. See $TMPLOG"
479        exit 1
480    fi
481    # don't forget to copy the GPL and LGPL license files
482    cp -f $TOOLCHAIN_LICENSES/COPYING $TOOLCHAIN_LICENSES/COPYING.LIB $TOOLCHAIN_PREFIX
483    # remove some unneeded files
484    rm -f $TOOLCHAIN_PREFIX/bin/*-gccbug
485    rm -rf $TOOLCHAIN_PREFIX/man $TOOLCHAIN_PREFIX/info
486    # strip binaries to reduce final package size
487    strip $TOOLCHAIN_PREFIX/bin/*
488    strip $TOOLCHAIN_PREFIX/arm-eabi/bin/*
489    strip $TOOLCHAIN_PREFIX/libexec/gcc/*/*/cc1
490    strip $TOOLCHAIN_PREFIX/libexec/gcc/*/*/cc1plus
491    strip $TOOLCHAIN_PREFIX/libexec/gcc/*/*/collect2
492    timestamp_set   toolchain install
493    timestamp_force gdbserver configure
494fi
495
496# configure the gdbserver build now
497if ! timestamp_check gdbserver configure; then
498    echo "Configure: gdbserver build."
499	if [ -d $TOOLCHAIN_SRC/gdb ] ; then
500		GDB_SRCDIR=$TOOLCHAIN_SRC/gdb/gdb-$GDB_VERSION
501    else
502        GDB_SRCDIR=$TOOLCHAIN_SRC/gdb-$GDB_VERSION
503    fi
504    mkdir -p $GDBSERVER_BUILD
505    cd $GDBSERVER_BUILD &&
506    export CC="$TOOLCHAIN_PREFIX/bin/arm-eabi-gcc" &&
507    export CFLAGS="-g -O2 -static -mandroid"  &&
508    export LDFLAGS= &&
509    run $GDB_SRCDIR/gdb/gdbserver/configure \
510    --host=arm-eabi-linux \
511    --with-sysroot=$ANDROID_SYSROOT
512    if [ $? != 0 ] ; then
513        echo "Could not configure gdbserver build. See $TMPLOG"
514        exit 1
515    fi
516    timestamp_set   gdbserver configure
517    timestamp_force gdbserver build
518fi
519
520# build gdbserver
521if ! timestamp_check gdbserver build; then
522    echo "Building : gdbserver."
523    cd $GDBSERVER_BUILD &&
524    run make -j$JOBS
525    if [ $? != 0 ] ; then
526        echo "Could not build gdbserver. See $TMPLOG"
527        exit 1
528    fi
529    timestamp_set   gdbserver build
530    timestamp_force gdbserver install
531fi
532
533# install gdbserver
534#
535# note that we install it in the toolchain bin directory
536# not in $SYSROOT/usr/bin
537#
538if ! timestamp_check gdbserver install; then
539    echo "Install  : gdbserver."
540    DEST=$TOOLCHAIN_PREFIX/bin
541    mkdir -p $DEST &&
542    $TOOLCHAIN_PREFIX/bin/arm-eabi-strip $GDBSERVER_BUILD/gdbserver &&
543    run cp -f $GDBSERVER_BUILD/gdbserver $DEST/gdbserver
544    if [ $? != 0 ] ; then
545        echo "Could not install gdbserver. See $TMPLOG"
546        exit 1
547    fi
548    timestamp_set   gdbserver install
549    timestamp_force package toolchain
550fi
551
552# package the toolchain
553TOOLCHAIN_TARBALL=/tmp/android-ndk-prebuilt-$TOOLCHAIN_NAME-$HOST_TAG.tar.bz2
554if ! timestamp_check package toolchain; then
555    echo "Package  : $HOST_ARCH toolchain binaries"
556    echo "           into $TOOLCHAIN_TARBALL"
557    cd $ANDROID_NDK_ROOT &&
558    TARFLAGS="cjf"
559    if [ $VERBOSE = yes ] ; then
560      TARFLAGS="v$TARFLAGS"
561    fi
562    run tar $TARFLAGS $TOOLCHAIN_TARBALL build/prebuilt/$HOST_TAG/$TOOLCHAIN_NAME
563    if [ $? != 0 ] ; then
564        echo "ERROR: Cannot package prebuilt toolchain binaries. See $TMPLOG"
565        exit 1
566    fi
567    timestamp_set package toolchain
568    echo "prebuilt toolchain is in $TOOLCHAIN_TARBALL"
569else
570    echo "prebuilt toolchain is in $TOOLCHAIN_TARBALL"
571fi
572
573echo "Done."
574rm -f $TMPLOG
575