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