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