build_gcc   [plain text]


#!/bin/sh
# APPLE LOCAL file B&I

set -x

# -arch arguments are different than configure arguments. We need to
# translate them.

TRANSLATE_ARCH="sed -e s/ppc/powerpc/ -e s/i386/i686/"

# Build GCC the "Apple way".
# Parameters:

# The first parameter is a space-separated list of the architectures
# the compilers will run on.  For instance, "ppc i386".  If the
# current machine isn't in the list, it will (effectively) be added.
HOSTS=`echo $1 | $TRANSLATE_ARCH `

# The second parameter is a space-separated list of the architectures the
# compilers will generate code for.  If the current machine isn't in
# the list, a compiler for it will get built anyway, but won't be
# installed.
TARGETS=`echo $2 | $TRANSLATE_ARCH`

# The GNU makefile target ('bootstrap' by default).
BOOTSTRAP=${BOOTSTRAP-bootstrap}

# The B&I build srcript (~rc/bin/buildit) accepts an '-othercflags'
# command-line flag, and captures the argument to that flag in
# $RC_NONARCH_CFLAGS (and mysteriously prepends '-pipe' thereto).
# We will allow this to override the default $CFLAGS and $CXXFLAGS.

CFLAGS=${RC_NONARCH_CFLAGS/-pipe/}
CFLAGS=${CFLAGS:-"-g -O2"}

# This isn't a parameter; it is the architecture of the current machine.
BUILD=`arch | $TRANSLATE_ARCH`

# The third parameter is the path to the compiler sources.  There should
# be a shell script named 'configure' in this directory.  This script
# makes a copy...
ORIG_SRC_DIR="$3"

# The fourth parameter is the location where the compiler will be installed,
# normally "/usr".  You can move it once it's built, so this mostly controls
# the layout of $DEST_DIR.
DEST_ROOT="$4"

# The fifth parameter is the place where the compiler will be copied once
# it's built.
DEST_DIR="$5"

# The sixth parameter is a directory in which to place information (like
# unstripped executables and generated source files) helpful in debugging
# the resulting compiler.
SYM_DIR="$6"

# The current working directory is where the build will happen.
# It may already contain a partial result of an interrupted build,
# in which case this script will continue where it left off.
DIR=`pwd`

# This isn't a parameter; it's the version of the compiler that we're
# about to build.  It's included in the names of various files and
# directories in the installed image.
VERS=`sed -n -e '/version_string/s/.*\"\([^ \"]*\)[ \"].*/\1/p' \
  < $ORIG_SRC_DIR/gcc/version.c || exit 1`

# This isn't a parameter either, it's the major version of the compiler
# to be built.  It's VERS but only up to the second '.' (if there is one).
MAJ_VERS=`echo $VERS | sed 's/\([0-9]*\.[0-9]*\)[.-].*/\1/'`

########################################
# Run the build.

# Create the source tree we'll actually use to build, deleting
# tcl since it doesn't actually build properly in a cross environment
# and we don't really need it.
SRC_DIR=$DIR/src
rm -rf $SRC_DIR || exit 1
mkdir $SRC_DIR || exit 1
ln -s $ORIG_SRC_DIR/* $SRC_DIR/ || exit 1
rm -rf $SRC_DIR/tcl $SRC_DIR/expect $SRC_DIR/dejagnu || exit 1

# These are the configure and build flags that are used.
CONFIGFLAGS="--disable-checking \
  --prefix=$DEST_ROOT \
  --mandir=\${prefix}/share/man \
  --enable-languages=c,objc,c++,obj-c++ \
  --program-transform-name=/^[cg][^+.-]*$/s/$/-$MAJ_VERS/ \
  --with-gxx-include-dir=\${prefix}/include/gcc/darwin/$MAJ_VERS/c++ \
  --build=$BUILD-apple-darwin"

# For 64-bit bringup
if [ "$VERS" == "3.5.0" ]; then
  CONFIGFLAGS="$CONFIGFLAGS --enable-bringup --disable-shared --enable-static"
fi

# Figure out how many make processes to run.
SYSCTL=`sysctl -n hw.activecpu`

# hw.activecpu only available in 10.2.6 and later
if [ -z "$SYSCTL" ]; then
  SYSCTL=`sysctl -n hw.ncpu`
fi

# sysctl -n hw.* does not work when invoked via B&I chroot /BuildRoot. 
# Builders can default to 2, since even if they are single processor, 
# nothing else is running on the machine.
if [ -z "$SYSCTL" ]; then
  SYSCTL=2
fi

# The $LOCAL_MAKEFLAGS variable can be used to override $MAKEFLAGS.
MAKEFLAGS=${LOCAL_MAKEFLAGS-"-j $SYSCTL"}

# Build the native GCC.  Do this even if the user didn't ask for it
# because it'll be needed for the bootstrap.
mkdir -p $DIR/obj-$BUILD-$BUILD $DIR/dst-$BUILD-$BUILD || exit 1
cd $DIR/obj-$BUILD-$BUILD || exit 1
if [ \! -f $DIR/$BUILD-configured ] ; then
 $SRC_DIR/configure $CONFIGFLAGS \
   --host=$BUILD-apple-darwin --target=$BUILD-apple-darwin || exit 1
 touch $DIR/$BUILD-configured || exit 1
fi
make $MAKEFLAGS $BOOTSTRAP CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" || exit 1
make $MAKEFLAGS DESTDIR=$DIR/dst-$BUILD-$BUILD install-gcc install-target \
  CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" || exit 1

# Add the compiler we just built to the path, giving it appropriate names.
D=$DIR/dst-$BUILD-$BUILD/usr/bin
ln -f $D/gcc-$MAJ_VERS $D/gcc || exit 1
ln -f $D/gcc $D/$BUILD-apple-darwin-gcc || exit 1
PATH=$DIR/dst-$BUILD-$BUILD/usr/bin:$PATH

# The cross-tools' build process expects to find certain programs
# under names like 'i386-apple-darwin-ar'; so make them.
# Annoyingly, ranlib changes behaviour depending on what you call it,
# so we have to use a shell script for indirection, grrr.
rm -rf $DIR/bin || exit 1
mkdir $DIR/bin || exit 1
for prog in ar nm ranlib ; do
  for t in `echo $TARGETS $HOSTS | sort -u`; do
    P=$DIR/bin/${t}-apple-darwin-${prog}
    echo '#!/bin/sh' > $P || exit 1
    echo 'exec /usr/bin/'${prog}' $*' >> $P || exit 1
    chmod a+x $P || exit 1
  done
done
PATH=$DIR/bin:$PATH

# Build the cross-compilers, using the compiler we just built.
for t in $TARGETS ; do
 if [ $t != $BUILD ] ; then
  mkdir -p $DIR/obj-$BUILD-$t $DIR/dst-$BUILD-$t || exit 1
   cd $DIR/obj-$BUILD-$t || exit 1
   $SRC_DIR/configure $CONFIGFLAGS  \
     --program-prefix=$t-apple-darwin- \
     --host=$BUILD-apple-darwin --target=$t-apple-darwin || exit 1
   make $MAKEFLAGS all CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" || exit 1
   make $MAKEFLAGS DESTDIR=$DIR/dst-$BUILD-$t install-gcc install-target \
     CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" || exit 1

    # Add the compiler we just built to the path.
   PATH=$DIR/dst-$BUILD-$t/usr/bin:$PATH
 fi
done

# Rearrange various libraries, for no really good reason.
for t in $TARGETS ; do
  DT=$DIR/dst-$BUILD-$t
  D=`echo $DT/usr/lib/gcc/$t-apple-darwin/$VERS`
  if [ $t == $BUILD ] ; then
    mv $DT/usr/lib/libstdc++.a $D || exit 1
    mv $DT/usr/lib/libsupc++.a $D || exit 1
    # 64-bit bringup
    if [ -f $DT/usr/lib/ppc64/libstdc++.a ]; then
	mv $DT/usr/lib/ppc64/libstdc++.a $D/ppc64 || exit 1
	mv $DT/usr/lib/ppc64/libsupc++.a $D/ppc64 || exit 1
    fi
  else
    DD=$DT/usr/${t}-apple-darwin/lib
    mv $DD/libstdc++.a $D || exit 1
    mv $DD/libsupc++.a $D || exit 1
    # 64-bit bringup
    if [ -f $DD/ppc64/libstdc++.a ]; then
	mv $DD/ppc64/libstdc++.a $D/ppc64 || exit 1
	mv $DD/ppc64/libsupc++.a $D/ppc64 || exit 1
    fi
  fi
  mv $D/static/libgcc.a $D/libgcc_static.a || exit 1
  mv $D/kext/libgcc.a $D/libcc_kext.a || exit 1
  rm -r $D/static $D/kext || exit 1
done

# Build the cross-hosted compilers.
for h in $HOSTS ; do
  if [ $h != $BUILD ] ; then
    for t in $TARGETS ; do
      mkdir -p $DIR/obj-$h-$t $DIR/dst-$h-$t || exit 1
      cd $DIR/obj-$h-$t || exit 1
      if [ $h = $t ] ; then
	pp=
      else
	pp=$t-apple-darwin-
      fi

      $SRC_DIR/configure $CONFIGFLAGS \
        --program-prefix=$pp \
        --host=$h-apple-darwin --target=$t-apple-darwin || exit 1
      make $MAKEFLAGS all-gcc CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" || exit 1
      make $MAKEFLAGS DESTDIR=$DIR/dst-$h-$t install-gcc \
        CFLAGS="$CFLAGS" CXXFLAGS="$CFLAGS" || exit 1
    done
  fi
done

########################################
# Construct the actual destination root, by copying stuff from
# $DIR/dst-* to $DEST_DIR, with occasional 'lipo' commands.

cd $DEST_DIR || exit 1

# Clean out DEST_DIR in case -noclean was passed to buildit.
rm -rf * || exit 1

# HTML documentation
HTMLDIR="/Developer/ADC Reference Library/documentation/DeveloperTools"
mkdir -p ".$HTMLDIR" || exit 1
cp -Rp $DIR/obj-$BUILD-$BUILD/gcc/doc/HTML/* ".$HTMLDIR/" || exit 1

# Manual pages
mkdir -p .$DEST_ROOT/share || exit 1
cp -Rp $DIR/dst-$BUILD-$BUILD$DEST_ROOT/share/man .$DEST_ROOT/share/ \
  || exit 1

# libexec
LIBEXEC_FILES=` \
  ls $DIR/dst-$BUILD-$BUILD$DEST_ROOT/libexec/gcc/$BUILD-apple-darwin/$VERS  \
    | grep -v install-tools || exit 1`
for t in $TARGETS ; do
  DL=$DEST_ROOT/libexec/gcc/$t-apple-darwin/$VERS
  mkdir -p .$DL || exit 1
  for f in $LIBEXEC_FILES ; do
    lipo -output .$DL/$f -create $DIR/dst-*-$t$DL/$f || exit 1
  done
done

# bin
# The native drivers ('native' is different in different architectures).
BIN_FILES=`ls $DIR/dst-$BUILD-$BUILD$DEST_ROOT/bin | grep '^[^-]*-[0-9.]*$' \
  | grep -v gccbug | grep -v gcov || exit 1`
mkdir .$DEST_ROOT/bin
for f in $BIN_FILES ; do 
  lipo -output .$DEST_ROOT/bin/$f -create $DIR/dst-*$DEST_ROOT/bin/$f || exit 1
done
# gcov, which is special only because it gets built multiple times and lipo
# will complain if we try to add two architectures into the same output.
TARG0=`echo $TARGETS | cut -d ' ' -f 1`
lipo -output .$DEST_ROOT/bin/gcov-$MAJ_VERS -create \
  $DIR/dst-*-$TARG0$DEST_ROOT/bin/*gcov* || exit 1
# The fully-named drivers, which have the same target on every host.
for t in $TARGETS ; do
  lipo -output .$DEST_ROOT/bin/$t-apple-darwin-gcc-$VERS -create \
    $DIR/dst-*-$t$DEST_ROOT/bin/$t-apple-darwin-gcc-$VERS || exit 1
  lipo -output .$DEST_ROOT/bin/$t-apple-darwin-g++-$VERS -create \
    $DIR/dst-*-$t$DEST_ROOT/bin/$t-apple-darwin-g++ || exit 1
done

# lib
mkdir -p .$DEST_ROOT/lib/gcc || exit 1
for t in $TARGETS ; do
  cp -Rp $DIR/dst-$BUILD-$t$DEST_ROOT/lib/gcc/$t-apple-darwin \
    .$DEST_ROOT/lib/gcc || exit 1
done

SHARED_LIBS=`ls $DIR/dst-$BUILD-$BUILD$DEST_ROOT/lib | grep '\.dylib$'`
for l in $SHARED_LIBS ; do
  F=$DIR/dst-$BUILD-$BUILD$DEST_ROOT/lib/$l
  if [ \! -L $F ] ; then
    if [ -f $DIR/dst-$BUILD-*$DEST_ROOT/*-apple-darwin/lib/$l ] ; then
      lipo -output .$DEST_ROOT/lib/$l -create $F \
	$DIR/dst-$BUILD-*$DEST_ROOT/*-apple-darwin/lib/$l || exit 1
    else
      cp -p $F .$DEST_ROOT/lib/$l || exit 1
    fi
    F1=`echo $l \
	| sed 's/\(\.[0-9]\{1,\}\)\(\.[0-9]\{1,\}\)\{1,\}\.dylib/\1.dylib/'`
    F0=`echo $l | sed 's/\(\.[0-9]\{1,\}\)\{1,\}\.dylib/.dylib/'`
    ln -s $l .$DEST_ROOT/lib/$F1 || exit 1
    for t in $TARGETS ; do
      ln -s ../../../$F1 .$DEST_ROOT/lib/gcc/$t-apple-darwin/$VERS/$F0 \
        || exit 1
    done
  fi
done

for l in $SHARED_LIBS ; do
  F=$DEST_ROOT/lib/$l
  F1=`echo $l \
        | sed 's/\(\.[0-9]\{1,\}\)\(\.[0-9]\{1,\}\)\{1,\}\.dylib/\1.dylib/'`
  if [ -f .$F ] ; then

    # Now that we've lipo'ed things together, change the install name
    # to match the official path.  The destination should always be
    # shorter than the full name, so this should always work.  The
    # install name should be the symlink with the major version number
    # so that apps using the library (and the install name) will link
    # against the symlink and get the latest version.
    # Also change dependent library names so that libstdc++.6.0.2.dylib
    # (for example) links against libgcc.1.dylib to avoid link errors.

    install_name_tool -id $DEST_ROOT/lib/$F1 .$F

    # At this point, l is the name of the library we're rewriting.
    # .$DEST_ROOT/lib/$F1 is the major version of the library.

    # For every other shared library: change the name from short name to major
    for subl in $SHARED_LIBS ; do
      SUBF=.$DEST_ROOT/lib/$subl
      if [ -f $SUBF ] ; then
        install_name_tool -change $DEST_ROOT/lib/$l $DEST_ROOT/lib/$F1 $SUBF
      fi
    done

    # For every other library and architecture, check to see if any of the
    # dependent library names happens to be the bogus name given during a cross
    # compile.
    for usinglib in $SHARED_LIBS ; do
      USINGPATH=.$DEST_ROOT/lib/$usinglib
      if [ -f $USINGPATH ] ; then
        for t1 in $TARGETS ; do
          BADPATH=$DEST_ROOT/$t-apple-darwin/lib/$l 
          GOODPATH=$DEST_ROOT/lib/$F1
          # Deal with the weird names generated for cross compiler portions.
          install_name_tool -change $BADPATH $GOODPATH $USINGPATH
        done
      fi
    done
  fi
done  

# include
HEADERPATH=$DEST_ROOT/include/gcc/darwin/$MAJ_VERS
mkdir -p .$HEADERPATH || exit 1
cp -Rp $DIR/dst-$BUILD-$BUILD$HEADERPATH/c++ \
  .$HEADERPATH/ || exit 1
for t in $TARGETS ; do
  DS=$HEADERPATH/c++
  [ $t = $BUILD ] || \
    cp -Rp $DIR/dst-$BUILD-$t$DS/$t-apple-darwin .$DS/ || exit 1
done

# Some headers are installed from more-hdrs/.  They all share
# one common feature: they shouldn't be installed here.  Sometimes,
# they should be part of FSF GCC and installed from there; sometimes,
# they should be installed by some completely different package; sometimes,
# they only exist for codewarrior compatibility and codewarrior should provide
# its own.  We take care not to install the headers if Libc is already
# providing them.
cd $SRC_DIR/more-hdrs
for h in `echo [^C]*` ; do
  if [ ! -f /usr/include/$h -o -L /usr/include/$h ] ; then
    cp -R $h $DEST_DIR$HEADERPATH/$h || exit 1
    for t in $TARGETS ; do
      THEADERPATH=$DEST_DIR$DEST_ROOT/lib/gcc/${t}-apple-darwin/$VERS/include
      [ -f $THEADERPATH/$h ] || \
        ln -s ../../../../../include/gcc/darwin/$MAJ_VERS/$h $THEADERPATH/$h || \
        exit 1
    done
  fi
done

# Install man pages using version number.
# Only g++ man page needs rename. gcc, cpp and gcov man page are already 
# installed using proper name.
mv $DEST_DIR$DEST_ROOT/share/man/man1/g++.1 \
   $DEST_DIR$DEST_ROOT/share/man/man1/g++-$MAJ_VERS.1
ln -f $DEST_DIR$DEST_ROOT/share/man/man1/g++-$MAJ_VERS.1 \
   $DEST_DIR$DEST_ROOT/share/man/man1/c++-$MAJ_VERS.1
for t in $TARGETS ; do
  ln -f $DEST_DIR$DEST_ROOT/share/man/man1/gcc-$MAJ_VERS.1 \
     $DEST_DIR$DEST_ROOT/share/man/man1/$t-apple-darwin-gcc-$VERS.1
  ln -f $DEST_DIR$DEST_ROOT/share/man/man1/g++-$MAJ_VERS.1 \
     $DEST_DIR$DEST_ROOT/share/man/man1/$t-apple-darwin-g++-$VERS.1
done

# Build driver-driver using fully-named drivers
for t in $TARGETS ; do
    $DEST_DIR$DEST_ROOT/bin/$t-apple-darwin-gcc-$VERS                          \
	$ORIG_SRC_DIR/gcc/config/darwin-driver.c                               \
	-DPDN="\"-apple-darwin-gcc-$VERS\""                                    \
	-DIL="\"$DEST_ROOT/bin/\"" -I  $ORIG_SRC_DIR/include                   \
	-I  $ORIG_SRC_DIR/gcc -I  $ORIG_SRC_DIR/gcc/config                     \
	-liberty -L$DIR/dst-$BUILD-$t$DEST_ROOT/lib/                           \
	-L$DIR/dst-$BUILD-$t$DEST_ROOT/$t-apple-darwin/lib/                    \
	-o $DEST_DIR/$DEST_ROOT/bin/tmp-$t-gcc-$MAJ_VERS || exit 1

    $DEST_DIR$DEST_ROOT/bin/$t-apple-darwin-gcc-$VERS                          \
	$ORIG_SRC_DIR/gcc/config/darwin-driver.c                               \
	-DPDN="\"-apple-darwin-g++-$VERS\""                                    \
	-DIL="\"$DEST_ROOT/bin/\"" -I  $ORIG_SRC_DIR/include                   \
	-I  $ORIG_SRC_DIR/gcc -I  $ORIG_SRC_DIR/gcc/config                     \
	-liberty -L$DIR/dst-$BUILD-$t$DEST_ROOT/lib/                           \
	-L$DIR/dst-$BUILD-$t$DEST_ROOT/$t-apple-darwin/lib/                    \
	-o $DEST_DIR/$DEST_ROOT/bin/tmp-$t-g++-$MAJ_VERS || exit 1
done

lipo -output $DEST_DIR/$DEST_ROOT/bin/gcc-$MAJ_VERS -create \
  $DEST_DIR/$DEST_ROOT/bin/tmp-*-gcc-$MAJ_VERS || exit 1

lipo -output $DEST_DIR/$DEST_ROOT/bin/g++-$MAJ_VERS -create \
  $DEST_DIR/$DEST_ROOT/bin/tmp-*-g++-$MAJ_VERS || exit 1

ln -f $DEST_DIR/$DEST_ROOT/bin/g++-$MAJ_VERS $DEST_DIR/$DEST_ROOT/bin/c++-$MAJ_VERS || exit 1

rm $DEST_DIR/$DEST_ROOT/bin/tmp-*-gcc-$MAJ_VERS || exit 1 
rm $DEST_DIR/$DEST_ROOT/bin/tmp-*-g++-$MAJ_VERS || exit 1


########################################
# Save the source files and objects needed for debugging

cd $SYM_DIR || exit 1

# Clean out SYM_DIR in case -noclean was passed to buildit.
rm -rf * || exit 1

# Save executables and libraries.
cd $DEST_DIR || exit 1
find . \( -perm -0111 -or -name \*.a \) -type f -print \
  | cpio -pdml $SYM_DIR || exit 1
# Save source files.
mkdir $SYM_DIR/src || exit 1
cd $DIR || exit 1
find obj-* -name \*.\[chy\] -print | cpio -pdml $SYM_DIR/src || exit 1

########################################
# Strip the executables and libraries
find $DEST_DIR -perm -0111 \! -name \*.dylib -type f -print \
  | xargs strip || exit 1
find $DEST_DIR \( -name \*.a -or -name \*.dylib \) -type f -print \
  | xargs strip -SX || exit 1
find $DEST_DIR -name \*.a -type f -print \
  | xargs ranlib || exit 1

if [ "$MAJ_VERS" = "3.5" ]; then
    rm -f `find $DEST_DIR -name \*.dylib -print`
    rm -f $DEST_DIR$DEST_ROOT/share/man/man7/fsf-funding.7
    rm -f $DEST_DIR$DEST_ROOT/share/man/man7/gfdl.7
    rm -f $DEST_DIR$DEST_ROOT/share/man/man7/gpl.7
fi

# Done!
exit 0