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