1 #!/bin/bash 2 # 3 # Copyright (C) 2010 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 18 # This script is used to rebuild the Linux 32-bit cross-toolchain 19 # that allows you to generate 32-bit binaries that target Ubuntu 8.04 20 # (a.k.a. Hardy Heron) instead of the host system (which usually is 10.04, 21 # a.k.a. Lucid Lynx) 22 # 23 # Use --help for complete usage information. 24 # 25 # WARNING: At this time, the generated toolchain binaries will *not* run 26 # with GLibc 2.15, only the machine code it generates. 27 # 28 29 PROGNAME="`basename \"$0\"`" 30 PATCHES_DIR="$( cd "$( dirname "$0" )" && pwd )/toolchain-patches" 31 32 ########################################################################### 33 ########################################################################### 34 ##### 35 ##### C O N F I G U R A T I O N 36 ##### 37 ########################################################################### 38 ########################################################################### 39 40 panic () 41 { 42 echo "ERROR: $@" 43 exit 1 44 } 45 46 fail_panic () 47 { 48 if [ $? != 0 ] ; then 49 echo "ERROR: $@" 50 exit 1 51 fi 52 } 53 54 55 # We only support running this script on Linux 56 OS=$(uname -s) 57 if [ "$OS" != Linux ]; then 58 panic "This script can only run on Linux machines!" 59 fi 60 61 UBUNTU_ARCHS="i386 amd64" 62 63 # Used to set the host bitness of the generted toolchain binaries 64 # First call with the build machine's bitness, and later with 32 65 # if --32-bits option is used. 66 # $1: 32 or 64 67 set_host_bits () 68 { 69 HOST_BITS=$1 70 GMP_ABI=$1 71 case $1 in 72 32) 73 HOST_ARCH=i686 74 GCC_TARGET=i686-linux 75 GMP_TARGET=i386-linux 76 ;; 77 64) 78 HOST_ARCH=x86_64 79 GCC_TARGET=x86_64-linux 80 GMP_TARGET=x86_64-linux 81 ;; 82 *) 83 panic "Invalid host bitness (32 or 64 expected): $1" 84 esac 85 } 86 87 # Determine build machine bitness 88 BUILD_ARCH=$(uname -m) 89 case "$BUILD_ARCH" in 90 x86_64|amd64) 91 BUILD_BITS=64 92 BUILD_ARCH=x86_64 93 BUILD_GCC_TARGET=x86_64-linux 94 set_host_bits 64 95 ;; 96 i?86) 97 BUILD_BITS=32 98 BUILD_ARCH=i686 99 BUILD_GCC_TARGET=i686-linux 100 set_host_bits 32 101 ;; 102 *) 103 panic "Unknown build CPU architecture: $BUILD_ARCH" 104 esac 105 106 # Versions of various toolchain components, do not touch unless you know 107 # what you're doing! 108 109 BINUTILS_VERSION=2.23 110 GMP_VERSION=5.0.5 111 MPFR_VERSION=3.1.1 112 MPC_VERSION=1.0.1 113 GCC_VERSION=4.8 114 CLOOG_VERSION=0.18.0 115 ISL_VERSION=0.11.1 116 117 GLIBC_VERSION=2.15 118 119 GIT_CMD=git 120 GIT_DATE= 121 GIT_BRANCH=master 122 GIT_REFERENCE= 123 GIT_BASE= 124 GIT_BASE_DEFAULT=https://android.googlesource.com/toolchain 125 126 # Location where we're going to install the toolchain during the build 127 # This will depend on the phase of the build. 128 install_dir () { echo "$WORK_DIR/$PHASE/$TOOLCHAIN_NAME"; } 129 130 # Given an input string that looks like <major>.<minor>.<patch> 131 # Return <major>.<minor> only. 132 major_minor_only () { 133 local MAJOR=$(echo -n "$1" | cut -f1 -d.) 134 local MINOR=$(echo -n "$1" | cut -f2 -d.) 135 echo "$MAJOR.$MINOR" 136 } 137 138 # Location where we're going to install the final binaries 139 # If empty, TOOLCHAIN_ARCHIVE will be generated 140 PREFIX_DIR= 141 142 # Location of the final sysroot. This must be a sub-directory of INSTALL_DIR 143 # to ensure that the toolchain binaries are properly relocatable (i.e. can 144 # be used when moved to another directory). 145 sysroot_dir () { echo "$(install_dir)/sysroot"; } 146 147 # Try to parallelize the build for faster performance. 148 JOBS=$(cat /proc/cpuinfo | grep -c processor) 149 150 # The base URL of the Ubuntu mirror we're going to use. 151 UBUNTU_MIRROR=http://mirrors.us.kernel.org 152 153 # Ubuntu release name we want packages from. Can be a name or a number 154 # (i.e. "precise" or "12.04") 155 UBUNTU_RELEASE=precise 156 157 158 # The list of packages we need to download from the Ubuntu servers and 159 # extract into the original sysroot 160 # 161 # Call add_ubuntu_package <package-name> to add a package to the list, 162 # which will be processed later. 163 # 164 UBUNTU_PACKAGES= 165 166 add_ubuntu_package () 167 { 168 UBUNTU_PACKAGES="$UBUNTU_PACKAGES $@" 169 } 170 171 # The package files containing kernel headers for Hardy and the C 172 # library headers and binaries 173 add_ubuntu_package \ 174 linux-libc-dev \ 175 libc6 \ 176 libc6-dev \ 177 libcap2 \ 178 libcap-dev \ 179 libattr1 \ 180 libattr1-dev \ 181 libacl1 \ 182 libacl1-dev \ 183 184 # The X11 headers and binaries (for the emulator) 185 add_ubuntu_package \ 186 libx11-6 \ 187 libx11-dev \ 188 libxau6 \ 189 libxcb1-dev \ 190 libxdmcp6 \ 191 libxext-dev \ 192 libxfixes-dev \ 193 libxi-dev \ 194 x11proto-core-dev \ 195 x11proto-fixes-dev \ 196 x11proto-xext-dev \ 197 x11proto-input-dev \ 198 x11proto-kb-dev 199 200 # The OpenGL-related headers and libraries (for GLES emulation) 201 add_ubuntu_package \ 202 mesa-common-dev \ 203 libgl1-mesa-dev \ 204 libgl1-mesa-glx \ 205 libxxf86vm1 \ 206 libxext6 \ 207 libxdamage1 \ 208 libxfixes3 \ 209 libdrm2 210 211 # Audio libraries (required by the emulator) 212 add_ubuntu_package \ 213 libasound2 \ 214 libasound2-dev \ 215 libesd0-dev \ 216 libaudiofile-dev \ 217 libpulse0 \ 218 libpulse-dev 219 220 # ZLib and others. 221 add_ubuntu_package \ 222 zlib1g \ 223 zlib1g-dev \ 224 libncurses5 \ 225 libncurses5-dev \ 226 libtinfo5 \ 227 libtinfo-dev 228 229 230 231 ########################################################################### 232 ########################################################################### 233 ##### 234 ##### E N D O F C O N F I G U R A T I O N 235 ##### 236 ########################################################################### 237 ########################################################################### 238 239 # Parse all options 240 OPTION_HELP=no 241 VERBOSE=0 242 FORCE=no 243 ONLY_SYSROOT=no 244 ONLY_TOOLCHAIN_DIR= 245 BOOTSTRAP= 246 PARAMETERS= 247 FORCE_32= 248 LIST_TASKS= 249 250 for opt do 251 optarg=$(expr "x$opt" : 'x[^=]*=\(.*\)') 252 case $opt in 253 --help|-h|-\?) OPTION_HELP=yes 254 ;; 255 --verbose) VERBOSE=$(( $VERBOSE + 1 )) 256 ;; 257 --force) FORCE="yes" 258 ;; 259 --32-bits) FORCE_32=true 260 ;; 261 --ubuntu-mirror=*) UBUNTU_MIRROR=$optarg 262 ;; 263 --ubuntu-release=*) UBUNTU_RELEASE=$optarg 264 ;; 265 --prefix=*) PREFIX_DIR=$optarg 266 ;; 267 --work-dir=*) WORK_DIR=$optarg 268 ;; 269 --gcc-version=*) GCC_VERSION=$optarg 270 ;; 271 --binutils-version=*) BINUTILS_VERSION=$optarg 272 ;; 273 --gmp-version=*) GMP_VERSION=$optarg 274 ;; 275 --mpfr-version=*) MPFR_VERSION=$optarg 276 ;; 277 --mpc-version=*) MPC_VERSION=$optarg 278 ;; 279 --isl-version=*) ISL_VERSION=$optarg 280 ;; 281 --cloog-version=*) CLOOG_VERSION=$oparg 282 ;; 283 --git=*) GIT_CMD=$optarg 284 ;; 285 --git-date=*) GIT_DATE=$optarg 286 ;; 287 --git-branch=*) GIT_BRANCH=$optarg 288 ;; 289 --git-base=*) GIT_BASE=$optarg 290 ;; 291 --git-reference=*) GIT_REFERENCE=$optarg 292 ;; 293 --out-dir=*) OPTION_OUT_DIR=$optarg 294 ;; 295 --cc=*) OPTION_CC=$optarg 296 ;; 297 --jobs=*) JOBS=$optarg 298 ;; 299 -j*) JOBS=${opt#-j} 300 ;; 301 --only-sysroot) ONLY_SYSROOT=yes 302 ;; 303 --bootstrap) BOOTSTRAP=yes 304 ;; 305 --list-tasks) LIST_TASKS=yes 306 ;; 307 -*) 308 echo "unknown option '$opt', use --help" 309 exit 1 310 ;; 311 *) 312 if [ -z "$PARAMETERS" ]; then 313 PARAMETERS=$opt 314 else 315 PARAMETERS="$PARAMETERS $opt" 316 fi 317 esac 318 done 319 320 if [ "$OPTION_HELP" = "yes" ]; then 321 cat << EOF 322 323 Usage: $PROGNAME [options] [<path-to-toolchain-sources>] 324 325 This script is used to rebuild a custom Linux host toolchain that targets 326 GLibc $GLIBC_VERSION or higher. The machine code generated by this toolchain 327 will run properly on Ubuntu $UBUNTU_RELEASE or higher. 328 329 If you're running on a 32-bit system, it will generate a 32-bit toolchain. 330 If you're running on a 64-bit system, it will generate a 64-bit toolchain 331 unless you use the --32-bits option. 332 333 You can provide the path to a local copy of the toolchain sources repository 334 as a first parameter. If you don't, the sources will be downloaded and 335 extracted automatically into your work directory. 336 337 Note that this script will download various binary packages from Ubuntu 338 servers in order to prepare a compatible "sysroot". 339 340 By default, it generates a package archive ($TOOLCHAIN_ARCHIVE) but you can, 341 as an alternative, ask for direct installation with --prefix=<path> 342 343 Use the bootstrap option to re-generate the toolchain with itself. This is 344 useful if you want to ensure that the generated compiler binaries will work 345 properly on Ubuntu 8.04 or higher. By default, they will only run on systems 346 that match your build system's C library ABI, or higher. 347 348 Options: [defaults in brackets after descriptions] 349 EOF 350 echo "Standard options:" 351 echo " --help Print this message" 352 echo " --force Force-rebuild everything" 353 echo " --prefix=PATH Installation path [$PREFIX_DIR]" 354 echo " --ubuntu-mirror=URL Ubuntu mirror URL [$UBUNTU_MIRROR]" 355 echo " --ubuntu-release=NAME Ubuntu release name [$UBUNTU_RELEASE]" 356 echo " --work-dir=PATH Temporary work directory [/tmp/gcc.<random>]" 357 echo " --only-sysroot Only download and build sysroot packages" 358 echo " --verbose Verbose output. Can be used twice." 359 echo " --binutils-version=VERSION Binutils version number [$BINUTILS_VERSION]" 360 echo " --gcc-version=VERSION GCC version number [$GCC_VERSION]" 361 echo " --gmp-version=VERSION GMP version number [$GMP_VERSION]" 362 echo " --mpfr-version=VERSION MPFR version numner [$MPFR_VERSION]" 363 echo " --mpc-version=VERSION MPC version number [$MPC_VERSION]" 364 echo " --isl-version=VERSION ISL version number [$ISL_VERSION]" 365 echo " --cloog-version=VERSION Cloog version number [$CLOOG_VERSION]" 366 echo " --jobs=COUNT Run COUNT build jobs in parallel [$JOBS]" 367 echo " -j<COUNT> Same as --jobs=COUNT." 368 echo " --git=<cmd> Use this version of the git tool [$GIT_CMD]" 369 echo " --git-date=<date> Specify specific git date when download sources [none]" 370 echo " --git-branch=<name> Specify which branch to use when downloading the sources [$GIT_BRANCH]" 371 echo " --git-reference=<path> Use a git reference repository" 372 echo " --git-base=<url> Use this git repository base [$GIT_BASE]" 373 echo " --bootstrap Bootstrap toolchain (i.e. compile it with itself)" 374 echo " --32-bits Generate 32-bit toolchain on 64-bit build system." 375 echo "" 376 exit 1 377 fi 378 379 if [ "$FORCE_32" ]; then 380 if [ "$BUILD_BITS" = 64 ]; then 381 set_host_bits 32 382 else 383 echo "Warning: --32-bits option ignored on 32-bit build machine." 384 fi 385 fi 386 387 # Determine root working directory for our script 388 if [ -z "$WORK_DIR" ]; then 389 WORK_DIR=$(mktemp -d /tmp/$USER-gcc-$HOST_BITS-XXXXXX) 390 WORK_DIR_CLEANUP=true 391 else 392 mkdir -p "$WORK_DIR" 393 fail_panic "Could not create directory: $WORK_DIR" 394 WORK_DIR_CLEANUP=false 395 fi 396 397 if [ -z "$PARAMETERS" ] ; then 398 if [ -n "$GIT_REFERENCE" ] ; then 399 if [ ! -d "$GIT_REFERENCE" -o ! -d "$GIT_REFERENCE/build" ]; then 400 echo "ERROR: Invalid reference repository directory path: $GIT_REFERENCE" 401 exit 1 402 fi 403 if [ -n "$GIT_BASE" ]; then 404 echo "Using git clone reference: $GIT_REFERENCE" 405 else 406 # If we have a reference without a base, use it as a download base instead. 407 GIT_BASE=$GIT_REFERENCE 408 GIT_REFERENCE= 409 echo "Using git clone base: $GIT_BASE" 410 fi 411 elif [ -z "$GIT_BASE" ]; then 412 GIT_BASE=$GIT_BASE_DEFAULT 413 echo "Auto-config: --git-base=$GIT_BASE" 414 fi 415 416 # Location where we will download the toolchain sources 417 TOOLCHAIN_SRC_DIR=$WORK_DIR/toolchain-src 418 else 419 set_parameters () { 420 TOOLCHAIN_SRC_DIR="$1" 421 if [ ! -d "$TOOLCHAIN_SRC_DIR" ]; then 422 echo "ERROR: Not a directory: $1" 423 exit 1 424 fi 425 if [ ! -d "$TOOLCHAIN_SRC_DIR/build" ]; then 426 echo "ERROR: Missing directory: $1/build" 427 exit 1 428 fi 429 } 430 431 set_parameters $PARAMETERS 432 fi 433 434 # Location of original sysroot. This is where we're going to extract all 435 # binary Ubuntu packages. 436 ORG_SYSROOT_DIR=$WORK_DIR/sysroot 437 438 # Name of the final generated toolchain 439 TOOLCHAIN_NAME=$GCC_TARGET-glibc$GLIBC_VERSION-$(major_minor_only $GCC_VERSION) 440 441 # Name of the final toolchain binary tarball that this script will create 442 TOOLCHAIN_ARCHIVE=/tmp/$TOOLCHAIN_NAME.tar.bz2 443 444 # A file that will contain details about all the sources used to generate 445 # the final toolchain. This includes both SHA-1 for toolchain git repositories 446 # and SHA-1 hashes for downloaded Ubuntu packages. 447 SOURCES_LIST=$WORK_DIR/SOURCES 448 449 # Determine Make flags 450 MAKE_FLAGS="-j$JOBS" 451 452 # Create the work directory 453 mkdir -p "$WORK_DIR" 454 mkdir -p "$TOOLCHAIN_SRC_DIR" 455 456 # Location where we download packages from the Ubuntu servers 457 DOWNLOAD_DIR=$WORK_DIR/download 458 459 # Empty the SOURCES file 460 rm -f "$SOURCES_LIST" && touch "$SOURCES_LIST" 461 462 463 if [ "$VERBOSE" -ge 1 ] ; then 464 run () { 465 echo "## COMMAND: $@" 466 $@ 467 } 468 log () { 469 echo "$@" 470 } 471 if [ "$VERBOSE" -ge 2 ] ; then 472 log2 () { 473 echo "$@" 474 } 475 else 476 log2 () { 477 return 478 } 479 fi 480 else 481 run () { 482 "$@" >>$TMPLOG 2>&1 483 } 484 log () { 485 return 486 } 487 log2 () { 488 return 489 } 490 fi 491 492 # Sanitize a path list, we want to remove empty sub-dirs and 493 # leading/trailing columns. 494 sanitize_path_list () 495 { 496 local RESULT 497 RESULT=$(printf "%s\n" "$*" | tr ':' '\n' | awk '$1 != "" && $1 != "." { print $0; }' | tr '\n' ':') 498 printf "%s" ${RESULT%:} 499 } 500 501 PATH=$(sanitize_path_list $PATH) 502 LD_LIBRARY_PATH=$(sanitize_path_list $LD_LIBRARY_PATH) 503 504 BUILD_DIR=$WORK_DIR/build 505 mkdir -p $BUILD_DIR 506 507 TMPLOG=$BUILD_DIR/build.log 508 rm -rf $TMPLOG && touch $TMPLOG 509 510 build_dir_for () { echo "$BUILD_DIR/$PHASE/$1"; } 511 512 TIMESTAMPS_DIR=$BUILD_DIR/timestamps 513 mkdir -p $TIMESTAMPS_DIR 514 515 stamp_check () { 516 [ -f "$TIMESTAMPS_DIR/$1" ] 517 } 518 519 stamp_clear () { 520 rm -f "$TIMESTAMPS_DIR/$1" 521 } 522 523 stamp_set () { 524 touch "$TIMESTAMPS_DIR/$1" 525 } 526 527 if [ "$FORCE" = "yes" ] ; then 528 echo "Cleaning up timestamps (forcing the build)." 529 rm -f $TIMESTAMPS_DIR/* 530 fi 531 532 if [ "$VERBOSE" = 0 ] ; then 533 echo "To follow build, run: tail -F $TMPLOG" 534 fi 535 536 # returns 0 iff the string in $2 matches the pattern in $1 537 # $1: pattern 538 # $2: string 539 pattern_match () 540 { 541 echo "$2" | grep -q -E -e "$1" 542 } 543 544 # Find if a given shell program is available. 545 # We need to take care of the fact that the 'which <foo>' command 546 # may return either an empty string (Linux) or something like 547 # "no <foo> in ..." (Darwin). Also, we need to redirect stderr 548 # to /dev/null for Cygwin 549 # 550 # $1: variable name 551 # $2: program name 552 # 553 # Result: set $1 to the full path of the corresponding command 554 # or to the empty/undefined string if not available 555 # 556 find_program () 557 { 558 local PROG 559 PROG=`which $2 2>/dev/null` 560 if [ -n "$PROG" ] ; then 561 if pattern_match '^no ' "$PROG"; then 562 PROG= 563 fi 564 fi 565 eval $1="$PROG" 566 } 567 568 # Copy a directory, create target location if needed 569 # 570 # $1: source directory 571 # $2: target directory location 572 # 573 copy_directory () 574 { 575 local SRCDIR="$1" 576 local DSTDIR="$2" 577 if [ ! -d "$SRCDIR" ] ; then 578 panic "Can't copy from non-directory: $SRCDIR" 579 fi 580 log2 "Directory copy: $SRCDIR -> $DSTDIR" 581 mkdir -p "$DSTDIR" && (cd "$SRCDIR" && tar cf - *) | (tar xf - -C "$DSTDIR") 582 fail_panic "Cannot copy to directory: $DSTDIR" 583 } 584 585 find_program CMD_WGET wget 586 find_program CMD_CURL curl 587 find_program CMD_SCP scp 588 589 # Download a file with either 'curl', 'wget' or 'scp' 590 # 591 # $1: source URL (e.g. http://foo.com, ssh://blah, /some/path) 592 # $2: target file 593 download_file () 594 { 595 # Is this HTTP, HTTPS or FTP ? 596 if pattern_match "^(http|https|ftp):.*" "$1"; then 597 if [ -n "$CMD_WGET" ] ; then 598 run $CMD_WGET -O $2 $1 599 elif [ -n "$CMD_CURL" ] ; then 600 run $CMD_CURL -o $2 $1 601 else 602 echo "Please install wget or curl on this machine" 603 exit 1 604 fi 605 return 606 fi 607 608 # Is this SSH ? 609 # Accept both ssh://<path> or <machine>:<path> 610 # 611 if pattern_match "^(ssh|[^:]+):.*" "$1"; then 612 if [ -n "$CMD_SCP" ] ; then 613 scp_src=`echo $1 | sed -e s%ssh://%%g` 614 run $CMD_SCP $scp_src $2 615 else 616 echo "Please install scp on this machine" 617 exit 1 618 fi 619 return 620 fi 621 622 # Is this a file copy ? 623 # Accept both file://<path> or /<path> 624 # 625 if pattern_match "^(file://|/).*" "$1"; then 626 cp_src=`echo $1 | sed -e s%^file://%%g` 627 run cp -f $cp_src $2 628 return 629 fi 630 631 # Unknown schema 632 echo "ERROR: Unsupported source URI: $1" 633 exit 1 634 } 635 636 # A variant of 'download_file' used to specify the target directory 637 # $1: source URL 638 # $2: target directory 639 download_file_to () 640 { 641 local URL="$1" 642 local DIR="$2" 643 local DST="$DIR/`basename $URL`" 644 mkdir -p $DIR 645 download_file "$URL" "$DST" 646 } 647 648 # Pack a given archive 649 # 650 # $1: archive file path (including extension) 651 # $2: source directory for archive content 652 # $3+: list of files (including patterns), all if empty 653 pack_archive () 654 { 655 local ARCHIVE="$1" 656 local SRCDIR="$2" 657 local SRCFILES 658 local TARFLAGS ZIPFLAGS 659 shift; shift; 660 if [ -z "$1" ] ; then 661 SRCFILES="*" 662 else 663 SRCFILES="$@" 664 fi 665 if [ "`basename $ARCHIVE`" = "$ARCHIVE" ] ; then 666 ARCHIVE="`pwd`/$ARCHIVE" 667 fi 668 mkdir -p `dirname $ARCHIVE` 669 if [ "$VERBOSE" -ge 2 ] ; then 670 TARFLAGS="vcf" 671 ZIPFLAGS="-9r" 672 else 673 TARFLAGS="cf" 674 ZIPFLAGS="-9qr" 675 fi 676 case "$ARCHIVE" in 677 *.zip) 678 (cd $SRCDIR && run zip $ZIPFLAGS "$ARCHIVE" $SRCFILES) 679 ;; 680 *.tar) 681 (cd $SRCDIR && run tar $TARFLAGS "$ARCHIVE" $SRCFILES) 682 ;; 683 *.tar.gz) 684 (cd $SRCDIR && run tar z$TARFLAGS "$ARCHIVE" $SRCFILES) 685 ;; 686 *.tar.bz2) 687 (cd $SRCDIR && run tar j$TARFLAGS "$ARCHIVE" $SRCFILES) 688 ;; 689 *) 690 panic "Unsupported archive format: $ARCHIVE" 691 ;; 692 esac 693 } 694 695 no_trailing_slash () 696 { 697 echo ${1##/} 698 } 699 700 # Load the Ubuntu packages file. This is a long text file that will list 701 # each package for a given release. 702 # 703 # $1: Ubuntu mirror base URL (e.g. http://mirrors.us.kernel.org/) 704 # $2: Release name 705 # 706 get_ubuntu_packages_list () 707 { 708 local RELEASE=$2 709 local BASE="`no_trailing_slash \"$1\"`" 710 local SRCFILE DSTFILE 711 for UA in $UBUNTU_ARCHS; do 712 SRCFILE="$BASE/ubuntu/dists/$RELEASE/main/binary-$UA/Packages.bz2" 713 DSTFILE="$DOWNLOAD_DIR/Packages-$UA.bz2" 714 log "Trying to load $SRCFILE" 715 download_file "$SRCFILE" "$DSTFILE" 716 fail_panic "Could not download $SRCFILE" 717 (cd $DOWNLOAD_DIR && bunzip2 -cf Packages-$UA.bz2 > Packages-$UA) 718 fail_panic "Could not uncompress $DSTFILE to Packages-$UA" 719 done 720 721 # Write a small awk script used to extract filenames for a given package 722 cat > $DOWNLOAD_DIR/extract-filename.awk <<EOF 723 BEGIN { 724 # escape special characters in package name 725 gsub("\\\\.","\\\\.",PKG) 726 gsub("\\\\+","\\\\+",PKG) 727 FILE = "" 728 PACKAGE = "" 729 } 730 731 \$1 == "Package:" { 732 if (\$2 == PKG) { 733 PACKAGE = \$2 734 } else { 735 PACKAGE = "" 736 } 737 } 738 739 \$1 == "Filename:" && PACKAGE == PKG { 740 FILE = \$2 741 } 742 743 END { 744 print FILE 745 } 746 EOF 747 } 748 749 # Convert an unversioned package name into a .deb package URL 750 # 751 # $1: Package name without version information (e.g. libc6-dev) 752 # $2: Ubuntu mirror base URL 753 # $3: Ubuntu arch ("i386" or "amd64") 754 # 755 get_ubuntu_package_deb_url () 756 { 757 # The following is an awk command to parse the Packages file and extract 758 # the filename of a given package. 759 local BASE="`no_trailing_slash \"$1\"`" 760 local FILE=`awk -f "$DOWNLOAD_DIR/extract-filename.awk" -v PKG=$1 $DOWNLOAD_DIR/Packages-$3` 761 if [ -z "$FILE" ]; then 762 log "Could not find filename for package $1" 763 exit 1 764 fi 765 echo "$2/ubuntu/$FILE" 766 } 767 768 # Does the host compiler generate 32-bit machine code? 769 # If not, add the -m32 flag to the compiler name to ensure this. 770 # 771 compute_host_flags () 772 { 773 HOST_CC=${CC:-gcc} 774 HOST_CXX=${CXX-g++} 775 if [ -n "$USE_CCACHE" ]; then 776 echo -n "Checking for ccache..." 777 find_program CMD_CCACHE ccache 778 if [ -n "$CMD_CCACHE" ] ; then 779 echo "$HOST_CC" | tr ' ' '\n' | grep -q -e "ccache" 780 if [ $? = 0 ] ; then 781 echo "yes (ignored)" 782 else 783 echo "yes" 784 HOST_CC="ccache $HOST_CC" 785 HOST_CXX="ccache $HOST_CXX" 786 fi 787 else 788 echo "no" 789 fi 790 fi 791 echo -n "Checking compiler bitness... " 792 cat > "$BUILD_DIR"/conftest.c << EOF 793 #include <stdio.h> 794 int main(void) { 795 printf("%d\n",sizeof(void*)*8); 796 return 0; 797 } 798 EOF 799 $HOST_CC -o "$BUILD_DIR"/conftest "$BUILD_DIR"/conftest.c > "$BUILD_DIR"/conftest.log 2>&1 800 if [ $? != 0 ] ; then 801 echo "Could not compile test program!!" 802 echo "Error log is:" 803 cat "$BUILD_DIR"/conftest.log 804 rm "$BUID_DIR"/conftest.log 805 panic "Need a working build toolchain!" 806 fi 807 HOST_CC_BITS=$("$BUILD_DIR"/conftest) 808 echo -n "$HOST_CC_BITS" 809 case $HOST_CC_BITS in 810 32) # Nothing to do 811 ;; 812 64) # Do we need to force 32-bits 813 if [ "$FORCE_32" ]; then 814 echo " (forcing generation of 32-bit binaries)" 815 HOST_CC=$HOST_CC" -m32" 816 HOST_CXX=$HOST_CXX" -m32" 817 fi 818 ;; 819 *) 820 panic "Unknown bitness (32 or 64 expected) !!" 821 esac 822 echo "" 823 echo "Using build C compiler: $HOST_CC" 824 echo "Using build C++ compiler: $HOST_CXX" 825 echo "GCC target name: $GCC_TARGET" 826 echo "GMP target name: $GMP_TARGET" 827 echo "GMP ABI: $GMP_ABI" 828 export CC="$HOST_CC" 829 export CXX="$HOST_CXX" 830 } 831 832 compute_host_flags 833 834 # Return the value of a given named variable 835 # $1: variable name 836 # 837 # example: 838 # FOO=BAR 839 # BAR=ZOO 840 # echo `var_value $FOO` 841 # will print 'ZOO' 842 # 843 var_value () 844 { 845 eval echo \$$1 846 } 847 848 var_list_append () 849 { 850 local VARNAME=$1 851 local VARVAL=`var_value $VARNAME` 852 shift 853 if [ -z "$VARVAL" ] ; then 854 eval $VARNAME=\"$@\" 855 else 856 eval $VARNAME=\"$VARVAL $@\" 857 fi 858 } 859 860 var_list_prepend () 861 { 862 local VARNAME=$1 863 local VARVAL=`var_value $VARNAME` 864 shift 865 if [ -z "$VARVAL" ] ; then 866 eval $VARNAME=\"$@\" 867 else 868 eval $VARNAME=\"$@ $VARVAL\" 869 fi 870 } 871 872 _list_first () 873 { 874 echo $1 875 } 876 877 _list_rest () 878 { 879 shift 880 echo "$@" 881 } 882 883 _list_reverse () 884 { 885 local I1 I2 I3 I4 I5 I6 I7 I8 I9 REST RET 886 I1=$1; I2=$2; I3=$3; I4=$I4; I5=$I5; I6=$I6; I7=$I7; I8=$I8; I9=$I9 887 shift 9 888 RET=$I9${I8:+" "}$I8${I7:+" "}$I7${I6:+" "}$I6${I5:+" "}$I5${I4:+" "}$I4${I3:+" "}$I3${I2:+" "}$I2${I1:+" "}$I1 889 REST="$*" 890 if [ "$REST" ]; then 891 RET=$(_list_reverse $REST)$RET 892 fi 893 echo "$RET" 894 } 895 896 var_list_pop_first () 897 { 898 local VARNAME=$1 899 local VARVAL=`var_value $VARNAME` 900 local FIRST=`_list_first $VARVAL` 901 eval $VARNAME=\"`_list_rest $VARVAL`\" 902 echo "$FIRST" 903 } 904 905 _list_first () 906 { 907 echo $1 908 } 909 910 _list_rest () 911 { 912 shift 913 echo "$@" 914 } 915 916 var_list_first () 917 { 918 local VAL=`var_value $1` 919 _list_first $VAL 920 } 921 922 var_list_rest () 923 { 924 local VAL=`var_value $1` 925 _list_rest $VAL 926 } 927 928 ALL_TASKS= 929 930 # Define a new task for this build script 931 # $1: Task name (e.g. build_stuff) 932 # $2: Task description 933 # $3: Optional: command name (will be cmd_$1 by default) 934 # 935 task_define () 936 { 937 local TASK="$1" 938 local DESCR="$2" 939 local COMMAND="${3:-cmd_$1}" 940 941 var_list_append ALL_TASKS $TASK 942 task_set $TASK name "$TASK" 943 task_set $TASK descr "$DESCR" 944 task_set $TASK cmd "$COMMAND" 945 task_set $TASK deps "" 946 } 947 948 # Variant of task define for dual tasks 949 # This really defines two tasks named '<task>_1' and '<task>_2" 950 # $1: Task base name 951 # $2: Task description 952 # $3: Optional: command name (will be cmd_$1 by default) 953 task2_define () 954 { 955 local TASK="$1" 956 local DESCR="$2" 957 local COMMAND="${3:-cmd_$1}" 958 959 task_define "${TASK}_1" "$DESCR 1/2" "phase_1 $COMMAND" 960 task_define "${TASK}_2" "$DESCR 2/2" "phase_2 $COMMAND" 961 } 962 963 task_set () 964 { 965 local TASK="$1" 966 local FIELD="$2" 967 shift; shift; 968 eval TASK_${TASK}__${FIELD}=\"$@\" 969 } 970 971 task_get () 972 { 973 var_value TASK_$1__$2 974 } 975 976 # return the list of dependencies for a given task 977 task_get_deps () 978 { 979 task_get $1 deps 980 } 981 982 task_get_cmd () 983 { 984 task_get $1 cmd 985 } 986 987 task_get_descr () 988 { 989 task_get $1 descr 990 } 991 992 # $1: task name 993 # $2+: other tasks this task depends on. 994 task_depends () 995 { 996 local TASK="$1" 997 shift; 998 var_list_append TASK_${TASK}__deps $@ 999 } 1000 1001 # $1: dual task name 1002 # $2+: other non-dual tasks this dual task depends on 1003 task2_depends1 () 1004 { 1005 local TASK="$1" 1006 shift 1007 var_list_append TASK_${TASK}_1__deps $@ 1008 var_list_append TASK_${TASK}_2__deps $@ 1009 } 1010 1011 # $1: dual task name 1012 # $2+: other dual tasks this dual task depends on 1013 task2_depends2 () 1014 { 1015 local TASK="$1" 1016 local DEP 1017 shift 1018 for DEP; do 1019 var_list_append TASK_${TASK}_1__deps ${DEP}_1 1020 var_list_append TASK_${TASK}_2__deps ${DEP}_2 1021 done 1022 } 1023 1024 task_dump () 1025 { 1026 local TASK 1027 for TASK in $ALL_TASKS; do 1028 local DEPS="`task_get_deps $TASK`" 1029 local CMD="`task_get_cmd $TASK`" 1030 local DESCR="`task_get_descr $TASK`" 1031 echo "TASK $TASK: $DESCR: $CMD" 1032 echo "> $DEPS" 1033 done 1034 } 1035 1036 task_visit () 1037 { 1038 task_set $TASK visit 1 1039 } 1040 1041 task_unvisit () 1042 { 1043 task_set $TASK visit 0 1044 } 1045 1046 task_is_visited () 1047 { 1048 [ `task_get $TASK visit` = 1 ] 1049 } 1050 1051 task_queue_reset () 1052 { 1053 TASK_QUEUE= 1054 } 1055 1056 task_queue_push () 1057 { 1058 var_list_append TASK_QUEUE $1 1059 } 1060 1061 task_queue_pop () 1062 { 1063 local FIRST=`var_list_first TASK_QUEUE` 1064 TASK_QUEUE=`var_list_rest TASK_QUEUE` 1065 } 1066 1067 do_all_tasks () 1068 { 1069 local TASK 1070 local TASK_LIST= 1071 task_queue_reset 1072 # Clear visit flags 1073 for TASK in $ALL_TASKS; do 1074 task_unvisit $TASK 1075 done 1076 task_queue_push $1 1077 while [ -n "$TASK_QUEUE" ] ; do 1078 TASK=`task_queue_pop` 1079 if task_is_visited $TASK; then 1080 continue 1081 fi 1082 # Prepend the task to the list if its timestamp is not set 1083 if stamp_check $TASK; then 1084 var_list_prepend TASK_LIST $TASK 1085 fi 1086 # Add all dependencies to the work-queue 1087 local SUBTASK 1088 for SUBTASK in `task_get_deps $TASK`; do 1089 task_queue_push $SUBTASK 1090 done 1091 task_visit $TASK 1092 done 1093 1094 # Now, TASK_LIST contains the 1095 } 1096 1097 1098 # Return the first item of a space-separated list 1099 list_first () { 1100 set -- "$@" 1101 echo "$1" 1102 } 1103 1104 # Append an item to a given list 1105 list_append () { 1106 local ITEM=$1 1107 shift; 1108 echo $@${@:+" "}$1 1109 } 1110 1111 # Return the second-to-last items of a space-separated list 1112 list_rest () { 1113 set -- "$@" 1114 shift 1115 echo "$@" 1116 } 1117 1118 # Reverse a space-separated list 1119 list_reverse () 1120 { 1121 set -- "$@" 1122 local I1 I2 I3 I4 I5 I6 I7 I8 I9 REST RET 1123 I1=$1; I2=$2; I3=$3; I4=$4; I5=$5; I6=$6; I7=$7; I8=$8; I9=$9 1124 shift; shift; shift; shift; shift; shift; shift; shift; shift; 1125 RET=$I9${I9:+" "}$I8${I8:+" "}$I7${I7:+" "}$I6${I6:+" "}$I5${I5:+" "}$I4${I4:+" "}$I3${I3:+" "}$I2${I2:+" "}$I1 1126 REST="$*" 1127 if [ -n "$REST" ]; then 1128 RET=$(list_reverse $REST)" "$RET 1129 fi 1130 echo "$RET" 1131 } 1132 1133 # Used to build the list of tasks with a tree post-order traversal, i.e. 1134 # the list starts at the leaves and finishes with the top level task, 1135 # so that if task(A) depends on task(B), then A will always appear _after_ 1136 # B in the result. 1137 # 1138 # $1: space-separated list of tasks to visit 1139 # Out: list of all tasks in post-order 1140 # 1141 task_build_postorder_list () 1142 { 1143 local TASK 1144 local STACK="$1" 1145 local RET="" 1146 for TASK in $ALL_TASKS; do 1147 stamp_clear $TASK.visit 1148 done 1149 while true; do 1150 # Peek at stack 1151 TASK=$(list_first $STACK) 1152 #echo >&2 "STACK: ($TASK) '$STACK'" 1153 if [ -z "$TASK" ]; then 1154 break 1155 fi 1156 HAS_DEPS= 1157 for DEP in $(task_get_deps $TASK); do 1158 #echo >&2 "CHECK: '$DEP'" 1159 if ! stamp_check $DEP.visit; then 1160 STACK=$DEP" "$STACK 1161 #echo >&2 "PUSH: '$DEP' => '$STACK'" 1162 HAS_DEPS=1 1163 fi 1164 done 1165 1166 if [ -z "$HAS_DEPS" ]; then 1167 #echo >&2 "ADD: $TASK -> '$RET'" 1168 STACK=$(list_rest $STACK) 1169 if ! stamp_check $TASK.visit; then 1170 RET=$RET${RET:+" "}$TASK 1171 stamp_set $TASK.visit 1172 fi 1173 fi 1174 done 1175 for TASK in $ALL_TASKS; do 1176 stamp_clear $TASK.visit 1177 done 1178 echo "$RET" 1179 } 1180 1181 run_task () 1182 { 1183 # Build the list of tasks, in reverse order (from leafs to last) 1184 local TASKS=$(task_build_postorder_list $1) 1185 # Do all tasks 1186 local TASK DEP DESCR 1187 1188 # Dump list of tasks: 1189 # echo "ALL TASKS:" 1190 # for TASK in $TASKS; do 1191 # echo " $TASK" 1192 # done 1193 1194 # Clean timestamps of any tasks whose any of its dependents needs 1195 # to be re-done. 1196 # 1197 for TASK in $TASKS; do 1198 for DEP in $(task_get_deps $TASK); do 1199 if ! stamp_check $DEP; then 1200 #echo "Redo: $TASK due to $DEP" 1201 stamp_clear $TASK 1202 break 1203 fi 1204 done 1205 done 1206 1207 for TASK in $TASKS; do 1208 DESCR=$(task_get_descr $TASK) 1209 if stamp_check $TASK; then 1210 echo "Skipping: $DESCR" 1211 continue 1212 fi 1213 echo "Running: $DESCR" 1214 if [ "$VERBOSE" -ge 1 ] ; then 1215 (eval $(task_get_cmd $TASK)) 1216 else 1217 (eval $(task_get_cmd $TASK)) >> $TMPLOG 2>&1 1218 fi 1219 if [ $? != 0 ] ; then 1220 echo "ERROR: Cannot $DESCR" 1221 exit 1 1222 fi 1223 1224 stamp_set $TASK 1225 done 1226 } 1227 1228 # This function is used to clone a source repository either from a given 1229 # git base or a git reference. 1230 # $1: project/subdir name 1231 # $2: path to SOURCES file 1232 toolchain_clone () 1233 { 1234 local GITFLAGS 1235 GITFLAGS= 1236 if [ "$GIT_REFERENCE" ]; then 1237 GITFLAGS="$GITFLAGS --shared --reference $GIT_REFERENCE/$1" 1238 fi 1239 echo "cleaning up toolchain/$1" 1240 rm -rf $1 1241 fail_panic "Could not clean $(pwd)/$1" 1242 echo "downloading sources for toolchain/$1" 1243 if [ -d "$GIT_BASE/$1" ]; then 1244 log "cloning $GIT_BASE/$1" 1245 run $GIT_CMD clone $GITFLAGS $GIT_BASE/$1 $1 1246 else 1247 log "cloning $GITPREFIX/$1.git" 1248 run $GIT_CMD clone $GITFLAGS $GIT_BASE/$1.git $1 1249 fi 1250 fail_panic "Could not clone $GIT_BASE/$1.git ?" 1251 cd $1 1252 if [ "$GIT_BRANCH" != "master" ] ; then 1253 log "checking out $GIT_BRANCH branch of $1.git" 1254 run $GIT_CMD checkout -b $GIT_BRANCH origin/$GIT_BRANCH 1255 fail_panic "Could not checkout $1 ?" 1256 fi 1257 # If --git-date is used, or we have a default 1258 if [ -n "$GIT_DATE" ] ; then 1259 REVISION=`git rev-list -n 1 --until="$GIT_DATE" HEAD` 1260 echo "Using sources for date '$GIT_DATE': toolchain/$1 revision $REVISION" 1261 run $GIT_CMD checkout $REVISION 1262 fail_panic "Could not checkout $1 ?" 1263 fi 1264 (printf "%-32s " "toolchain/$1.git: " && git log -1 --format=oneline) >> $2 1265 cd .. 1266 } 1267 1268 task_define download_toolchain_sources "Download toolchain sources from $GIT_BASE " 1269 cmd_download_toolchain_sources () 1270 { 1271 local SUBDIRS="binutils build gcc gdb gold gmp mpfr mpc isl cloog" 1272 (mkdir -p $TOOLCHAIN_SRC_DIR && cd $TOOLCHAIN_SRC_DIR && 1273 # Create a temporary SOURCES file for the toolchain sources only 1274 # It's content will be copied to the final SOURCES file later. 1275 SOURCES_LIST=$TOOLCHAIN_SRC_DIR/SOURCES 1276 rm -f $SOURCES_LIST && touch $SOURCES_LIST 1277 for SUB in $SUBDIRS; do 1278 toolchain_clone $SUB $SOURCES_LIST 1279 done 1280 ) 1281 } 1282 1283 task_define download_ubuntu_packages_list "Download Ubuntu packages list" 1284 cmd_download_ubuntu_packages_list () 1285 { 1286 mkdir -p $DOWNLOAD_DIR 1287 get_ubuntu_packages_list "$UBUNTU_MIRROR" "$UBUNTU_RELEASE" 1288 fail_panic "Unable to download packages list, try --ubuntu-mirror=<url> to use another archive mirror" 1289 } 1290 1291 task_define download_packages "Download Ubuntu packages" 1292 task_depends download_packages download_ubuntu_packages_list 1293 cmd_download_packages () 1294 { 1295 local PACKAGE PKGURL 1296 1297 rm -f $DOWNLOAD_DIR/SOURCES && touch $DOWNLOAD_DIR/SOURCES 1298 for PACKAGE in $UBUNTU_PACKAGES; do 1299 echo "Downloading $PACKAGE" 1300 for UA in $UBUNTU_ARCHS; do 1301 PKGURL=`get_ubuntu_package_deb_url $PACKAGE $UBUNTU_MIRROR $UA` 1302 echo "URL: $PKGURL" 1303 download_file_to $PKGURL $DOWNLOAD_DIR 1304 fail_panic "Could not download $PKGURL" 1305 done 1306 done 1307 sha1sum $DOWNLOAD_DIR/*.deb | while read LINE; do 1308 PACKAGE=$(basename $(echo $LINE | awk '{ print $2;}')) 1309 SHA1=$(echo $LINE | awk '{ print $1; }') 1310 printf "%-64s %s\n" $PACKAGE $SHA1 >> $DOWNLOAD_DIR/SOURCES 1311 done 1312 } 1313 1314 task_define build_sysroot "Build sysroot" 1315 task_depends build_sysroot download_packages 1316 1317 cmd_build_sysroot () 1318 { 1319 local PACKAGE PKGURL SRC_PKG 1320 mkdir -p $SRC_PKG $ORG_SYSROOT_DIR 1321 for PACKAGE in $UBUNTU_PACKAGES; do 1322 for UA in $UBUNTU_ARCHS; do 1323 PKGURL=`get_ubuntu_package_deb_url $PACKAGE $UBUNTU_MIRROR $UA` 1324 SRC_PKG=$DOWNLOAD_DIR/`basename $PKGURL` 1325 echo "Extracting $SRC_PKG" 1326 dpkg -x $SRC_PKG $ORG_SYSROOT_DIR/$UA 1327 done 1328 done 1329 } 1330 1331 # Now, we need to patch libc.so which is actually a linker script 1332 # referencing /lib* and /usr/lib*. Do the same for libpthread.so 1333 patch_library () 1334 { 1335 echo "Patching $1" 1336 sed -i -e "s: /usr/lib[^ ]*/: :g;s: /lib[^ ]*/: :g" $1 1337 } 1338 1339 # Used to setup phase 1 the run a command 1340 phase_1 () 1341 { 1342 PHASE=1 1343 $@ 1344 } 1345 1346 # Used to setup phase 2 then run a command 1347 phase_2 () 1348 { 1349 PHASE=1 1350 BINPREFIX=$(install_dir)/bin/${GCC_TARGET}- 1351 CC=${BINPREFIX}gcc 1352 CXX=${BINPREFIX}g++ 1353 LD=${BINPREFIX}ld 1354 AR=${BINPREFIX}ar 1355 AS=${BINPREFIX}as 1356 RANLIB=${BINPREFIX}ranlib 1357 STRIP=${BINPREFIX}strip 1358 CC_FOR_TARGET=${BINPREFIX}gcc 1359 export CC CXX LD AR AS RANLIB STRIP CC_FOR_TARGET 1360 PHASE=2 1361 $@ 1362 } 1363 1364 # Return the list of all symbolic links in a given directory, excluding 1365 # any links in its sub-directories. 1366 # $1: Sub-directory path. 1367 find_symlinks_in () { 1368 (cd $1 && find . -maxdepth 1 -type l) | sed -e 's|^\./||g' 1369 } 1370 1371 task2_define copy_sysroot "Fix and copy sysroot" 1372 task2_depends1 copy_sysroot build_sysroot 1373 cmd_copy_sysroot () 1374 { 1375 local SL 1376 1377 # Copy the content of $ORG_SYSROOT_DIR/.../lib to $(sysroot_dir)/usr/lib32 1378 copy_directory $ORG_SYSROOT_DIR/i386/lib $(sysroot_dir)/usr/lib32 1379 copy_directory $ORG_SYSROOT_DIR/i386/usr/lib $(sysroot_dir)/usr/lib32 1380 copy_directory $ORG_SYSROOT_DIR/i386/usr/include $(sysroot_dir)/usr/include 1381 1382 copy_directory $ORG_SYSROOT_DIR/amd64/lib $(sysroot_dir)/usr/lib 1383 copy_directory $ORG_SYSROOT_DIR/amd64/usr/lib $(sysroot_dir)/usr/lib 1384 copy_directory $ORG_SYSROOT_DIR/amd64/usr/include $(sysroot_dir)/usr/include 1385 1386 # Ubuntu precise release has .so files in 1387 # /usr/lib/x86_64-linux-gnu and /usr/lib32/i386-linux-gnu. 1388 for LIB in $(sysroot_dir)/usr/lib/x86_64-linux-gnu \ 1389 $(sysroot_dir)/usr/lib32/i386-linux-gnu; do 1390 mv $LIB/* `dirname $LIB` && rmdir $LIB 1391 fail_panic "Cannot move files in $LIB" 1392 done 1393 1394 for LIB in lib lib32; do 1395 # We need to fix the symlink like librt.so -> /lib*/librt.so.1 1396 # in $(sysroot_dir)/usr/$LIB, they should point to librt.so.1 instead now. 1397 SYMLINKS=$(find_symlinks_in $(sysroot_dir)/usr/$LIB) 1398 cd $(sysroot_dir)/usr/$LIB 1399 for SL in $SYMLINKS; do 1400 # convert /$LIB/libfoo.so.<n> into 'libfoo.so.<n>' for the target 1401 local DST=$(readlink $SL 2>/dev/null) 1402 local DST2=`basename $DST` 1403 if [ "$DST2" != "$DST" ]; then 1404 echo "Fixing symlink $SL --> $DST" 1405 rm $SL && ln -s $DST2 $SL 1406 fi 1407 done 1408 patch_library libc.so 1409 patch_library libpthread.so 1410 done 1411 } 1412 1413 task_define patch_toolchain_sources "Patch toolchain sources." 1414 task_depends patch_toolchain_sources download_toolchain_sources 1415 cmd_patch_toolchain_sources () 1416 { 1417 log "PATCHES_DIR = $PATCHES_DIR" 1418 if [ ! -d "$PATCHES_DIR" ]; then 1419 log "$PATCHES_DIR doesn't exist" 1420 return 0 1421 fi 1422 1423 local PATCHES=`(cd $PATCHES_DIR && find . -name "*.patch" | sort ) 2> /dev/null` 1424 if [ -z "$PATCHES" ] ; then 1425 log "No patches files in $PATCHES_DIR" 1426 return 0 1427 fi 1428 1429 PATCHES=`echo $PATCHES | sed -e s%^\./%%g` 1430 for PATCH in $PATCHES; do 1431 PATCHDIR=`dirname $PATCH` 1432 PATCHNAME=`basename $PATCH` 1433 log "Applying $PATCHNAME into $TOOLCHAIN_SRC_DIR/$PATCHDIR" 1434 (cd $TOOLCHAIN_SRC_DIR/$PATCHDIR && patch -p1 < $PATCHES_DIR/$PATCH) 1435 fail_panic "Patch failure!! Please check your patches directory!" 1436 done 1437 1438 log "Done patching." 1439 } 1440 1441 task_define prepare_toolchain_sources "Prepare toolchain sources." 1442 if [ -n "$GIT_BASE" -o -n "$GIT_REFERENCE" ]; then 1443 task_depends prepare_toolchain_sources patch_toolchain_sources 1444 fi 1445 cmd_prepare_toolchain_sources () 1446 { 1447 return 1448 } 1449 1450 task2_define configure_binutils "Configure binutils-$BINUTILS_VERSION" 1451 task2_depends1 configure_binutils prepare_toolchain_sources 1452 task2_depends2 configure_binutils copy_sysroot 1453 cmd_configure_binutils () 1454 { 1455 OUT_DIR=$(build_dir_for binutils) 1456 mkdir -p $OUT_DIR && cd $OUT_DIR && 1457 run $TOOLCHAIN_SRC_DIR/binutils/binutils-$BINUTILS_VERSION/configure \ 1458 --prefix=$(install_dir) \ 1459 --with-sysroot=$(sysroot_dir) \ 1460 --target=$GCC_TARGET \ 1461 --enable-gold=default \ 1462 --with-host-libstdcxx='-static-libgcc -Wl,-Bstatic,-lstdc++,-Bdynamic -lm' \ 1463 --with-gold-ldflags='-static-libgcc -static-libstdc++' \ 1464 --with-bugurl=http://source.android.com/source/report-bugs.html 1465 } 1466 1467 task2_define build_binutils "Build binutils-$BINUTILS_VERSION" 1468 task2_depends2 build_binutils configure_binutils 1469 cmd_build_binutils () 1470 { 1471 cd $(build_dir_for binutils) && 1472 make $MAKE_FLAGS 1473 } 1474 1475 task2_define install_binutils "Install binutils-$BINUTILS_VERSION" 1476 task2_depends2 install_binutils build_binutils 1477 cmd_install_binutils () 1478 { 1479 cd $(build_dir_for binutils) && 1480 make install 1481 } 1482 1483 task2_define extract_gmp "Extract sources for gmp-$GMP_VERSION" 1484 task2_depends1 extract_gmp prepare_toolchain_sources 1485 cmd_extract_gmp () 1486 { 1487 OUT_DIR=$(build_dir_for gmp) 1488 GMP_TARBALL=$TOOLCHAIN_SRC_DIR/gmp/gmp-$GMP_VERSION.tar.bz2 1489 if [ ! -f "$GMP_TARBALL" ]; then 1490 GMP_TARBALL=$TOOLCHAIN_SRC_DIR/tarballs/gmp-$GMP_VERSION.tar.bz2 1491 if [ ! -f "$GMP_TARBALL" ]; then 1492 panic "Can't find gmp-$GMP_VERSION sources!!" 1493 fi 1494 fi 1495 mkdir -p $OUT_DIR && cd $OUT_DIR && 1496 tar xjf "$GMP_TARBALL" 1497 } 1498 1499 task2_define configure_gmp "Configure gmp-$GMP_VERSION" 1500 task2_depends2 configure_gmp extract_gmp install_binutils 1501 cmd_configure_gmp () 1502 { 1503 export ABI=$GMP_ABI && 1504 cd $(build_dir_for gmp) && mkdir -p build && cd build && 1505 ../gmp-$GMP_VERSION/configure \ 1506 --prefix=$(install_dir) \ 1507 --host=$GMP_TARGET \ 1508 --with-sysroot=$(install_dir) \ 1509 --disable-shared 1510 } 1511 1512 task2_define build_gmp "Build gmp-$GMP_VERSION" 1513 task2_depends2 build_gmp configure_gmp 1514 cmd_build_gmp () 1515 { 1516 export ABI=$GMP_ABI && 1517 cd $(build_dir_for gmp)/build && 1518 make $MAKE_FLAGS 1519 } 1520 1521 task2_define install_gmp "Install gmp-$GMP_VERSION" 1522 task2_depends2 install_gmp build_gmp 1523 cmd_install_gmp () 1524 { 1525 cd $(build_dir_for gmp)/build && 1526 make install 1527 } 1528 1529 # Third, build mpfr 1530 task2_define extract_mpfr "Extract sources from mpfr-$MPFR_VERSION" 1531 task2_depends1 extract_mpfr prepare_toolchain_sources 1532 cmd_extract_mpfr () 1533 { 1534 OUT_DIR=$(build_dir_for mpfr) 1535 MPFR_TARBALL=$TOOLCHAIN_SRC_DIR/mpfr/mpfr-$MPFR_VERSION.tar.bz2 1536 if [ ! -f "$MPFR_TARBALL" ]; then 1537 MPFR_TARBALL=$TOOLCHAIN_SRC_DIR/tarballs/mpfr-$MPFR_VERSION.tar.bz2 1538 if [ ! -f "$MPFR_TARBALL" ]; then 1539 panic "Can't find mpfr-$MPFR_VERSION sources!!" 1540 fi 1541 fi 1542 mkdir -p $OUT_DIR && cd $OUT_DIR && 1543 tar xjf "$MPFR_TARBALL" 1544 } 1545 1546 task2_define configure_mpfr "Configure mpfr-$MPFR_VERSION" 1547 task2_depends2 configure_mpfr extract_mpfr install_gmp 1548 cmd_configure_mpfr () 1549 { 1550 cd $(build_dir_for mpfr) && mkdir -p build && cd build && 1551 run ../mpfr-$MPFR_VERSION/configure \ 1552 --prefix=$(install_dir) \ 1553 --host=$GMP_TARGET \ 1554 --with-gmp=$(install_dir) \ 1555 --with-sysroot=$(sysroot_dir) \ 1556 --disable-shared 1557 } 1558 1559 task2_define build_mpfr "Build mpfr-$MPFR_VERSION" 1560 task2_depends2 build_mpfr configure_mpfr 1561 cmd_build_mpfr () 1562 { 1563 cd $(build_dir_for mpfr)/build && 1564 run make $MAKE_FLAGS 1565 } 1566 1567 task2_define install_mpfr "Install mpfr-$MPFR_VERSION" 1568 task2_depends2 install_mpfr build_mpfr 1569 cmd_install_mpfr () 1570 { 1571 cd $(build_dir_for mpfr)/build && 1572 run make install 1573 } 1574 1575 task2_define extract_mpc "Extract sources for mpc-$MPC_VERSION" 1576 task2_depends1 extract_mpc prepare_toolchain_sources 1577 cmd_extract_mpc () 1578 { 1579 OUT_DIR=$(build_dir_for mpc) 1580 MPC_TARBALL=$TOOLCHAIN_SRC_DIR/mpc/mpc-$MPC_VERSION.tar.gz 1581 if [ ! -f "$MPC_TARBALL" ]; then 1582 MPC_TARBALL=$TOOLCHAIN_SRC_DIR/tarballs/mpc-$MPC_VERSION.tar.gz 1583 if [ ! -f "$MPC_TARBALL" ]; then 1584 panic "Can't find mpc-$MPC_VERSION sources!!" 1585 fi 1586 fi 1587 mkdir -p $OUT_DIR && cd $OUT_DIR && 1588 tar xzf "$MPC_TARBALL" 1589 } 1590 1591 task2_define configure_mpc "Configure mpc-$MPC_VERSION" 1592 task2_depends2 configure_mpc extract_mpc install_mpfr 1593 cmd_configure_mpc () 1594 { 1595 cd $(build_dir_for mpc) && mkdir -p build && cd build && 1596 run ../mpc-$MPC_VERSION/configure \ 1597 --prefix=$(install_dir) \ 1598 --host=$GMP_TARGET \ 1599 --with-gmp=$(install_dir) \ 1600 --with-mpfr=$(install_dir) \ 1601 --disable-shared 1602 } 1603 1604 task2_define build_mpc "Build mpc-$MPC_VERSION" 1605 task2_depends2 build_mpc configure_mpc 1606 cmd_build_mpc () 1607 { 1608 cd $(build_dir_for mpc)/build && 1609 run make $MAKE_FLAGS 1610 } 1611 1612 task2_define install_mpc "Install mpc-$MPC_VERSION" 1613 task2_depends2 install_mpc build_mpc 1614 cmd_install_mpc () 1615 { 1616 cd $(build_dir_for mpc)/build && 1617 run make install 1618 } 1619 1620 task2_define extract_isl "Extract sources for isl-$ISL_VERSION" 1621 task2_depends2 extract_isl prepare_toolchain_sources 1622 cmd_extract_isl () 1623 { 1624 OUT_DIR=$(build_dir_for isl) 1625 ISL_TARBALL=$TOOLCHAIN_SRC_DIR/isl/isl-$ISL_VERSION.tar.bz2 1626 if [ ! -f "$ISL_TARBALL" ]; then 1627 panic "Can't find isl-$ISL_VERSION sources!!" 1628 fi 1629 mkdir -p $OUT_DIR && cd $OUT_DIR && 1630 tar xf "$ISL_TARBALL" 1631 } 1632 1633 task2_define configure_isl "Configuring isl-$ISL_VERSION" 1634 task2_depends2 configure_isl extract_isl install_gmp 1635 cmd_configure_isl () 1636 { 1637 cd $(build_dir_for isl) && mkdir -p build && cd build && 1638 run ../isl-$ISL_VERSION/configure \ 1639 --prefix=$(install_dir) \ 1640 --host=$GMP_TARGET \ 1641 --with-gmp-prefix=$(install_dir) \ 1642 --with-sysroot=$(sysroot_dir) \ 1643 --disable-shared 1644 } 1645 1646 task2_define build_isl "Building isl-$ISL_VERSION" 1647 task2_depends2 build_isl configure_isl 1648 cmd_build_isl () 1649 { 1650 cd $(build_dir_for isl)/build && 1651 run make $MAKE_FLAGS 1652 } 1653 1654 task2_define install_isl "Installing isl-$ISL_VERSION" 1655 task2_depends2 install_isl build_isl 1656 cmd_install_isl () 1657 { 1658 cd $(build_dir_for isl)/build && 1659 make install 1660 } 1661 1662 task2_define configure_cloog "Configure Cloog-$CLOOG_VERSION" 1663 task2_depends2 configure_cloog prepare_toolchain_sources install_gmp install_isl 1664 cmd_configure_cloog () { 1665 mkdir -p $(build_dir_for cloog)/build && cd $(build_dir_for cloog)/build && 1666 run $TOOLCHAIN_SRC_DIR/cloog/cloog-$CLOOG_VERSION/configure \ 1667 --prefix=$(install_dir) \ 1668 --host=$GMP_TARGET \ 1669 --with-gmp-prefix=$(install_dir) \ 1670 --with-sysroot=$(sysroot_dir) \ 1671 --disable-shared 1672 } 1673 1674 task2_define build_cloog "Building Cloog-$CLOOG_VERSION" 1675 task2_depends2 build_cloog configure_cloog 1676 cmd_build_cloog () 1677 { 1678 cd $(build_dir_for cloog)/build && 1679 run make $MAKE_FLAGS 1680 } 1681 1682 task2_define install_cloog "Installing Cloog-$CLOOG_VERSION" 1683 task2_depends2 install_cloog build_cloog 1684 cmd_install_cloog () 1685 { 1686 cd $(build_dir_for cloog)/build && 1687 run make install 1688 } 1689 1690 # Fourth, the compiler itself 1691 task2_define configure_gcc "Configure gcc-$GCC_VERSION" 1692 task2_depends1 configure_gcc prepare_toolchain_sources 1693 task2_depends2 configure_gcc install_binutils install_gmp install_mpfr install_mpc install_cloog 1694 cmd_configure_gcc () 1695 { 1696 local EXTRA_CONFIGURE_FLAGS= 1697 if [ "$GCC_VERSION" != "4.6" ]; then 1698 EXTRA_CONFIGURE_FLAGS="--with-cloog=$(install_dir)" 1699 fi 1700 OUT_DIR=$(build_dir_for gcc) 1701 mkdir -p $OUT_DIR && cd $OUT_DIR && 1702 export CC=$HOST_CC && 1703 export CC_FOR_TARGET="$HOST_CC" && 1704 run $TOOLCHAIN_SRC_DIR/gcc/gcc-$GCC_VERSION/configure \ 1705 --enable-multiarch \ 1706 --with-arch-32=i686 \ 1707 --with-abi=m64 \ 1708 --prefix=$(install_dir) \ 1709 --with-sysroot=$(sysroot_dir) \ 1710 --disable-nls \ 1711 --with-gmp=$(install_dir) \ 1712 --with-mpfr=$(install_dir) \ 1713 --with-mpc=$(install_dir) \ 1714 --target=$GCC_TARGET \ 1715 --with-arch=x86-64 \ 1716 --with-multilib-list=m32,m64 \ 1717 --disable-plugin \ 1718 --disable-docs \ 1719 --disable-bootstrap \ 1720 --disable-libgomp \ 1721 --disable-libmudflap \ 1722 --disable-libquadmath \ 1723 --enable-target-optspace \ 1724 --enable-gold=default \ 1725 --enable-languages=c,c++ \ 1726 $EXTRA_CONFIGURE_FLAGS 1727 } 1728 1729 task2_define build_gcc "Build gcc-$GCC_VERSION" 1730 task2_depends2 build_gcc configure_gcc 1731 cmd_build_gcc () 1732 { 1733 cd $(build_dir_for gcc) && 1734 make $MAKE_FLAGS 1735 } 1736 1737 task2_define install_gcc "Install gcc-$GCC_VERSION" 1738 task2_depends2 install_gcc build_gcc 1739 cmd_install_gcc () 1740 { 1741 cd $(build_dir_for gcc) && 1742 make install 1743 } 1744 1745 task2_define cleanup_toolchain "Cleanup toolchain" 1746 task2_depends2 cleanup_toolchain install_gcc 1747 cmd_cleanup_toolchain () 1748 { 1749 # Remove un-needed directories and files 1750 rm -rf $(install_dir)/share 1751 rm -rf $(install_dir)/man 1752 rm -rf $(install_dir)/info 1753 rm -rf $(install_dir)/libexec/*/*/install-tools 1754 #rm -rf $(install_dir)/$GCC_TARGET/bin 1755 find $(install_dir) -name "*.la" -exec rm -f {} \; 1756 1757 (strip $(install_dir)/bin/*) 1758 (strip $(install_dir)/libexec/gcc/$GCC_TARGET/*/*) 1759 true 1760 } 1761 1762 task2_define package_toolchain "Package final toolchain" 1763 task2_depends2 package_toolchain cleanup_toolchain 1764 cmd_package_toolchain () 1765 { 1766 # Copy this script to the install directory 1767 cp -f $0 $(install_dir) 1768 fail_panic "Could not copy build script to install directory" 1769 1770 if [ -d "$PATCHES_DIR" ]; then 1771 # Copy patches to the install directory 1772 cp -rf "$PATCHES_DIR" $(install_dir) 1773 fail_panic "Could not copy patch directory to install directory" 1774 fi 1775 1776 # Copy the SOURCES file as well 1777 cp $DOWNLOAD_DIR/SOURCES $(install_dir)/PACKAGE_SOURCES && 1778 cp $TOOLCHAIN_SRC_DIR/SOURCES $(install_dir)/TOOLCHAIN_SOURCES 1779 fail_panic "Could not copy SOURCES files to install directory" 1780 1781 # Package everything 1782 pack_archive $TOOLCHAIN_ARCHIVE "`dirname $(install_dir)`" "`basename $(install_dir)`" 1783 } 1784 1785 task2_define install_toolchain "Install final toolchain" 1786 task2_depends2 install_toolchain cleanup_toolchain 1787 cmd_install_toolchain () 1788 { 1789 copy_directory "$(install_dir)" "$PREFIX_DIR/$TOOLCHAIN_NAME" 1790 cp -f $0 "$PREFIX_DIR/$TOOLCHAIN_NAME/" 1791 } 1792 1793 # Make sure that the second toolchain depends on the first one 1794 task_depends configure_binutils_2 install_gcc_1 1795 1796 if [ "$ONLY_SYSROOT" = "yes" ]; then 1797 MAIN_TASK=copy_sysroot 1798 COMPLETION_TEXT="Done, see sysroot files in $(sysroot_dir)" 1799 elif [ -n "$PREFIX_DIR" ]; then 1800 if [ -z "$BOOTSTRAP" ]; then 1801 MAIN_TASK=install_toolchain_1 1802 else 1803 MAIN_TASK=install_toolchain_2 1804 fi 1805 COMPLETION_TEXT="Done, see $PREFIX_DIR/$TOOLCHAIN_NAME" 1806 else 1807 if [ -z "$BOOTSTRAP" ]; then 1808 MAIN_TASK=package_toolchain_1 1809 else 1810 MAIN_TASK=package_toolchain_2 1811 fi 1812 COMPLETION_TEXT="Done, see $TOOLCHAIN_ARCHIVE" 1813 fi 1814 1815 if [ "$LIST_TASKS" ]; then 1816 task_dump 1817 else 1818 run_task $MAIN_TASK 1819 echo "$COMPLETION_TEXT" 1820 fi 1821