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