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