#!/bin/bash # # setup-prefix.sh VERSION=2007.07.07 # Script for setting up "Prefix Gentoo" # Author: rabbe@gentoo.se # # This script was derived from the "Gentoo Prefix Portage Bootstrap # Process for Solaris" webpage at # . # Successful bootstrapping has been verified for Solaris/x86 and # Solaris/sparc. More work is needed on Linux/x86. # # Changes have been made by trial-and-error to make the script run # all the way unattended. Root privileges are not required. It is # likely that the script to some extent reflects the particular set # of bootstrapping tools (GCC compiler etc) being used. # # Numbers N.nn refer to the Code Listing numbers of the webpage. Extra # steps have been introduced where needed. # # The script is sectioned into "levels", each level corresponding to # a Code Listing in the webpage. Whenever a new level has been reached # a timestamp is placed in the $EPREFIX/bootstrap/progress directory. # # It is the intention that the script should die as soon as something # goes wrong, with an indication of the troublesome level. After fixing # the problem the script can be restarted and will then skip over levels # that have already been reached. By removing selected timestamps the # script will re-run the corresponding bootstrap steps. # # The script finishes in less than 10 hours on a Solaris x86 system # (hardware details unknown). The final size of $EPREFIX is of the # order 0.8 GB. # # FILES CREATED BY THIS SCRIPT # # Lots of files under $EPREFIX # Certain config files under $HOME/.subversion/ # # BOOTSTRAPPING TOOLS REQUIRED # # Quite a few software components are required for a successful # bootstrap installation. Here is an attempt at a list (likely to # be incomplete): # # gcc + ar + ld # gmake or make # grep + egrep + fgrep + or ggrep + gegrep + gfgrep # ginstall or install # # TODO # # - Is it really necessary to have `hash -r' in some places? # - Investigate FIXMEs. ######################################################################## # Inspect and revise these settings as needed. # Prefix path: Everything that this script creates goes here. export EPREFIX=/var/tmp/gentoo # Paths to bootstrapping tools, uncomment and adjust as appropriate # (the paths must match actual paths in your system). # # BST_TOOLS=/usr/sfw/bin # BST_GCC=/usr/sfw/bin:/usr/sfw/sparc-sun-solaris2.10/bin # Proxy settings: Define these variables if behind an HTTP proxy. # Only the simplest kind of proxy configuration is supported. # PROXYHOST=proxyhost.tinkerers-united.net # PROXYPORT=8080 # Flags that go into make.conf at a late stage: FINAL_USEFLAGS="unicode nls" FINAL_CFLAGS="-O2 -pipe" # Extra packages to be emerged: GOODIES="" # GOODIES="$GOODIES app-portage/gentoolkit" # GOODIES="$GOODIES app-editors/emacs" # Set UNMASK_EMACS to "true" if emacs should be emerged on # sparc-solaris even though it is masked. Use at your own # risk. UNMASK_EMACS=false ######################################################################## # Be careful if you make changes below this line. # FIXME: Nothing goes in $EPREFIX/tmp/bin, leave it out entirely? # FIXME: $EPREFIX/usr/sbin is needed for env-update. Addition to webpage? ARCHIVE=http://overlays.gentoo.org/proj/alt/browser/trunk/prefix-overlay/scripts BOOTSCRIPT=bootstrap-prefix.sh BST_PROGRESS=$EPREFIX/bootstrap/progress BST_BIN=$EPREFIX/bootstrap/bin BST_TMP_BACKUP=$EPREFIX/backup-tmp UNAME_COMMAND="`which uname`" export PATH="$BST_TOOLS:$BST_BIN:$PATH" export PATH="$EPREFIX/usr/bin:$EPREFIX/bin:$EPREFIX/tmp/usr/bin:$EPREFIX/tmp/bin:$PATH" export PATH="$EPREFIX/usr/sbin:$PATH" export PATH="$PATH:$BST_GCC" if ! which install >/dev/null && [ -x /usr/sbin/install ]; then export PATH="$PATH:/usr/sbin" fi if [ -n "$PROXYHOST" -a -n "$PROXYPORT" ]; then export http_proxy="http://$PROXYHOST:$PROXYPORT" fi BEGINNING=$((0)) not_done_level() { [ ! -f $BST_PROGRESS/$1 ]; } done_level() { echo "PID: $$, date: `date`" >$BST_PROGRESS/$1; } die() { echo "[$LEVEL] $1" >&2; exit 1; } appendline() { if [ ! -f "$1" ] && ! touch "$1"; then die "failed to create file $1" fi if ! grep "$2" "$1" >/dev/null; then echo "$2" >>"$1" || die "failed to append to file $1" fi } trace() { local banner banner="====== [$LEVEL] ======" echo $banner echo "running for `howlong`" echo "current PATH is:" env | grep '^PATH=' | tr ':' '\n' | sed -e 's|PATH=||' -e 's|^| |' echo $banner | sed -e 's|.|=|g' } howlong() { local now local hasrun local minutes local zero for X in $EPREFIX/bin $EPREFIX/tmp/bin $EPREFIX/tmp/usr/bin; do if [ -x $X/date ]; then if [ $BEGINNING -eq 0 ]; then BEGINNING=`$X/date --utc +%s` echo "0:00 h" else now=`$X/date --utc +%s` hasrun=$(((now - BEGINNING) / 60)) # runtime in minutes minutes=$((hasrun % 60)) [ $minutes -lt 10 ] && zero='0' [ $minutes -ge 10 ] && zero='' echo "$((hasrun / 60)):${zero}$((minutes)) h" fi fi break done echo "0:00 h" } ######################################################################## # Execution begins! [ -z "$BST_GCC" ] && die "BST_GCC has not been set" [ -z "$BST_TOOLS" ] && die "BST_TOOLS has not been set" case "`$UNAME_COMMAND -s`" in Linux) case "`$UNAME_COMMAND -p`" in i686) PLATFORM=linux-x86;; *) die "unsupported platform: `uname -a`" esac;; SunOS) case "`$UNAME_COMMAND -p`" in sparc) PLATFORM=solaris-sparc;; i386) PLATFORM=solaris-x86;; *) die "unsupported platform: `uname -a`" esac;; *) die "unsupported platform: `uname -a`" esac LEVEL=0 # For the record: Versions of bootstrapping tools. if not_done_level $LEVEL; then trace mkdir -p $BST_PROGRESS echo $VERSION >$BST_PROGRESS/script-version.txt if gcc --version >/dev/null 2>&1; then gcc --version >$BST_PROGRESS/gcc-version.txt else die "no gcc" fi if make --version >/dev/null 2>&1; then make --version >$BST_PROGRESS/make-version.txt elif gmake --version >/dev/null 2>&1; then gmake --version >$BST_PROGRESS/gmake-version.txt else die "no make and no gmake" fi if install --version >/dev/null 2>&1; then install --version >$BST_PROGRESS/install-version.txt elif ginstall --version >/dev/null 2>&1; then ginstall --version >$BST_PROGRESS/ginstall-version.txt elif which install >/dev/null 2>&1; then which install >$BST_PROGRESS/install-abspath.txt else die "no install and no ginstall" fi done_level $LEVEL fi LEVEL=1.3-pre if not_done_level $LEVEL; then trace rm -rf $BST_BIN mkdir -p $BST_BIN wget --output-document=$BST_BIN/$BOOTSCRIPT \ $ARCHIVE/bootstrap-prefix.sh?format=txt || die "failed to wget boot script" chmod 755 $BST_BIN/$BOOTSCRIPT done_level $LEVEL fi LEVEL=1.3 # DEVIATION: Don't emerge grep yet, since it can't be done. # FIXME: If actually building sed here there is a syntax error message reported # by `sh' when emerging `sed'. if not_done_level $LEVEL; then trace $BOOTSCRIPT $EPREFIX tree || die "get tree failed" $BOOTSCRIPT $EPREFIX/tmp wget || die "build wget failed" $BOOTSCRIPT $EPREFIX/tmp sed || die "build sed failed" $BOOTSCRIPT $EPREFIX/tmp python || die "build python failed" $BOOTSCRIPT $EPREFIX/tmp coreutils || die "build coreutils failed" $BOOTSCRIPT $EPREFIX/tmp findutils || die "build findutils failed" $BOOTSCRIPT $EPREFIX/tmp tar || die "build tar failed" $BOOTSCRIPT $EPREFIX/tmp patch || die "build patch failed" # WORKAROUND: Bootstrap compilation of 'grep' does not # work on x86, bug 173937. The workaround is to place # very simple wrappers in $EPREFIX/tmp/local/bin and # hope for the best. if [ $PLATFORM = solaris-x86 ]; then mkdir -p $EPREFIX/tmp/local/bin for X in grep fgrep egrep; do echo "exec $BST_TOOLS/$X "'"$@"' >$EPREFIX/tmp/local/bin/$X chmod +x $EPREFIX/tmp/local/bin/$X done else $BOOTSCRIPT $EPREFIX grep || die "build grep failed" fi $BOOTSCRIPT $EPREFIX/tmp gawk || die "build gawk failed" $BOOTSCRIPT $EPREFIX portage || die "build portage failed" done_level $LEVEL fi if [ $PLATFORM = solaris-x86 ]; then export PATH="$EPREFIX/tmp/local/bin:$PATH" fi export LDFLAGS="-L${EPREFIX}/usr/lib -R${EPREFIX}/usr/lib -L${EPREFIX}/lib -R${EPREFIX}/lib" export CPPFLAGS="-I${EPREFIX}/usr/include" hash -r LEVEL=1.6-defer # Perhaps this step can't be done; it seems to fail with version 3.4.3 # of the bootstrap GCC. Perhaps it is OK to rely on $EPREFIX/tmp/usr/bin/sed # for a while. if not_done_level $LEVEL; then trace echo "[$LEVEL] nothing to do here, actual work is deferred" done_level $LEVEL fi LEVEL=1.7 # DEVIATION: Emerge bison here since yacc was asked for if not_done_level $LEVEL; then trace # Emerging m4 does not go well, there are complaints on # grep being used with "illegal option -q", see if it # helps to set DEFAULT_PATH? # # Same workaround applied for other packages too as needed. env DEFAULT_PATH=$PATH \ emerge -v --oneshot bison || die "emerge bison failed" env DEFAULT_PATH=$PATH \ emerge -v --oneshot bash || die "emerge bash failed" done_level $LEVEL fi LEVEL=1.8 # Noticed when emerging gcc-config: "grep: illegal option: -q", needs the DEFAULT_PATH trick? if not_done_level $LEVEL; then trace # DEVIATION: No need to emerge m4, since bison pulled it in env DEFAULT_PATH=$PATH \ emerge -v --oneshot --nodeps sys-apps/baselayout-prefix || die "emerge baselayout-prefix failed" env DEFAULT_PATH=$PATH \ emerge -v --oneshot --nodeps sys-devel/flex || die "emerge flex failed" env DEFAULT_PATH=$PATH \ emerge -v --oneshot --nodeps sys-devel/binutils-config || die "emerge binutils-config failed" env DEFAULT_PATH=$PATH \ emerge -v --oneshot --nodeps sys-devel/binutils || die "emerge binutils failed" if ld --version >/dev/null 2>&1; then echo "[$LEVEL] binutils version is:" >$BST_PROGRESS/binutils-version.txt ld --version >>$BST_PROGRESS/binutils-version.txt else die "failed to record binutils version" fi env DEFAULT_PATH=$PATH \ emerge -v --oneshot --nodeps sys-devel/gcc-config || die "emerge gcc-config failed" done_level $LEVEL fi LEVEL=1.8-gcc-dependencies if not_done_level $LEVEL; then trace # Apply the wisdom of 173963, that is do not say --nodeps # (see bug 173963). # # However, leaving out --nodeps causes sed to be pulled in. # We want to defer that. This code emerges all dependencies # except sed. for X in \ dev-libs/libiconv \ sys-libs/zlib \ virtual/libiconv \ sys-apps/texinfo \ sys-devel/gnuconfig; do env DEFAULT_PATH=$PATH \ emerge -v --oneshot --nodeps $X || die "emerge $X failed" done done_level $LEVEL fi LEVEL=1.8-gcc if not_done_level $LEVEL; then trace # Workaround for bug 184437: The configure script uses the # CONFIG_SHELL for running config.sub, and it turns out that # CONFIG_SHELL is $EPREFIX/bin/sh which may not exist. WORKAROUND_184437=""; if [ ! -x $EPREFIX/bin/sh ]; then ( cd $EPREFIX/bin; ln -s bash sh ) WORKAROUND_184437=true fi env DEFAULT_PATH=$PATH \ emerge -v --oneshot --nodeps sys-devel/gcc || die "emerge sys-devel/gcc failed" if [ -n "$WORKAROUND_184437" ]; then ( cd $EPREFIX/bin; rm sh ) fi done_level $LEVEL fi LEVEL=1.6-catchup # We skipped building 'sed' before, try to do it now # instead. if not_done_level $LEVEL; then trace emerge -v --oneshot sed || die "emerge sed failed" done_level $LEVEL fi LEVEL=1.9 # Start using the newly built GCC, so set a PATH accordingly. We still # need the bootstrap-compiled wget (in $EPREFIX/tmp/usr/bin). Also for # i386 we still need the bootstrap version of GNU grep # (in $EPREFIX/tmp/local/bin), whereas for sparc we use the # bootstrap-compiled grep in $EPREFIX/tmp/usr/bin. env-update || die "failed to env-update" source $EPREFIX/etc/profile if [ $PLATFORM = solaris-x86 ]; then export PATH=`echo $PATH \ | sed -e "s|$EPREFIX/sbin:|$EPREFIX/sbin:$EPREFIX/tmp/usr/bin:$EPREFIX/tmp/bin:$EPREFIX/tmp/local/bin:|"` else export PATH=`echo $PATH \ | sed -e "s|$EPREFIX/sbin:|$EPREFIX/sbin:$EPREFIX/tmp/usr/bin:$EPREFIX/tmp/bin:|"` fi if not_done_level $LEVEL; then trace emerge -v --oneshot --nodeps \ "=autoconf-2.1*" "=autoconf-2.6*" "autoconf-wrapper" || die "emerge autoconf failed" emerge -v --oneshot --nodeps \ "=automake-1.4*" "=automake-1.5*" "=automake-1.6*" \ "=automake-1.7*" "=automake-1.8*" "automake-wrapper" || die "emerge automake failed" done_level $LEVEL fi LEVEL=1.10-defer if not_done_level $LEVEL; then trace echo "[$LEVEL] nothing to do here, actual work is deferred" done_level $LEVEL fi LEVEL=1.11 if not_done_level $LEVEL; then trace emerge -v --oneshot --nodeps texinfo || die "emerge texinfo failed" done_level $LEVEL fi LEVEL=1.12 if not_done_level $LEVEL; then trace emerge -v --oneshot --nodeps \ "=automake-1.9*" "=automake-1.10*" || die "emerge automake failed" done_level $LEVEL fi LEVEL=1.12b # Workaround: For some reason we need to build grep at this point # on x86. Without doing so the "configure" step will fail when # building libtool. Once we have built grep we can drop the # $EPREFIX/tmp/local/bin path component. if not_done_level $LEVEL; then trace if [ $PLATFORM = solaris-x86 ]; then emerge -v --oneshot grep || die "emerge grep failed" fi done_level $LEVEL fi if [ $PLATFORM = solaris-x86 ]; then export PATH=`echo $PATH | sed -e "s|$EPREFIX/tmp/local/bin:||"` fi LEVEL=1.12c # Mask version 1.5.23b of libtool. The problem with version 1.5.23b is # reported in bug 181802 (it might not be a critical issue). if not_done_level $LEVEL; then trace if [ ! -f $EPREFIX/etc/portage/package.mask ] \ || ! grep --silent =sys-devel/libtool-1.5.23b $EPREFIX/etc/portage/package.mask; then mkdir -p $EPREFIX/etc/portage echo "=sys-devel/libtool-1.5.23b" >$EPREFIX/etc/portage/package.mask fi emerge -v --oneshot --nodeps libtool || die "emerge libtool failed" done_level $LEVEL fi LEVEL=1.13-defer if not_done_level $LEVEL; then trace echo "[$LEVEL] nothing to do here, actual work is deferred" done_level $LEVEL fi LEVEL=1.14 # Emerging wget with depndencies pulls in python, # and for building python we need a recent version # of patch. Sooner or later we need it anyway. if not_done_level $LEVEL; then trace emerge -v --oneshot patch || die "emerge patch failed" done_level $LEVEL fi LEVEL=1.10-catchup # Emerging wget with --nodeps causes an error ("--with-ssl was # given, but OpenSSL is not available"). There does not seem to be # a USE flag for turning off the SSL dependency. Keep --nodeps but # emerge openssl first. if not_done_level $LEVEL; then trace emerge -v --oneshot --nodeps dev-libs/openssl || die "emerge openssl failed" emerge -v --oneshot --nodeps wget || die "emerge wget failed" done_level $LEVEL fi LEVEL=1.13-catchup if not_done_level $LEVEL; then trace emerge -v --oneshot --nodeps sys-apps/coreutils || die "emerge coreutils failed" hash -r ## the console output says to do so done_level $LEVEL fi LEVEL=1.15 if not_done_level $LEVEL; then trace # This ugly fix was introduced because 2.4.4-r4 won't emerge on # sparc (patching fails for some incomprehensible reason). # FIXME: Later on this code should be removed. if [ $PLATFORM = solaris-sparc ]; then if ! -f $EPREFIX/etc/portage/package.unmask \ || ! grep 'dev-lang/python-2.5.1-r2' $EPREFIX/etc/portage/package.unmask; then echo "=dev-lang/python-2.5.1-r2" >>$EPREFIX/etc/portage/package.unmask fi emerge -v --oneshot --nodeps =dev-lang/python-2.5.1-r2 || die "emerge python failed" else emerge -v --oneshot --nodeps dev-lang/python || die "emerge python failed" fi emerge -v --oneshot --nodeps findutils || die "emerge findutils failed" emerge -v --oneshot --nodeps tar || die "emerge tar failed" if [ $PLATFORM != solaris-x86 ]; then emerge -v --oneshot --nodeps grep || die "emerge grep failed" fi emerge -v --oneshot --nodeps make || die "emerge make failed" emerge -v --oneshot --nodeps bison || die "emerge bison failed" done_level $LEVEL fi LEVEL=1.16 if not_done_level $LEVEL; then trace env FEATURES="-collision-protect" \ emerge -v --oneshot --nodeps portage || die "emerge portage failed" done_level $LEVEL fi LEVEL=1.17 if not_done_level $LEVEL; then trace emerge -v --oneshot gawk || die "emerge gawk failed" done_level $LEVEL fi LEVEL=1.18 if not_done_level $LEVEL; then trace rm -rf $BST_TMP_BACKUP mkdir -p $BST_TMP_BACKUP mv $EPREFIX/tmp/* $BST_TMP_BACKUP hash -r done_level $LEVEL fi LEVEL=1.19-pre # It appears that emerging 'libperl' will fail in 1.19, # at least on sparc, unless we have emerged 'db' first. # FIXME: Investigate if this is a sparc-only issue. if not_done_level $LEVEL; then trace # Note: 'db' has a 'bootstrap' USE-flag, should it be # used here maybe? # Apparently 'db' causes problems in step 1.23 # for x86-solaris, so do this for sparc only. if [ $PLATFORM = solaris-sparc ]; then emerge -v db || die "emerge db failed" fi done_level $LEVEL fi LEVEL=1.19 if not_done_level $LEVEL; then trace # This should not be needed, but there was a lockfile # problem when emerging python, so maybe this is # beneficial: rm -rf $EPREFIX/var/tmp/portage emerge -v -e system || die "emerge -e system failed" if ld --version; then echo "[$LEVEL], level completed, binutils version is:" >>$BST_PROGRESS/binutils-version.txt ld --version >>$BST_PROGRESS/binutils-version.txt else die "failed to record binutils version" fi done_level $LEVEL fi LEVEL=1.20 if not_done_level $LEVEL; then trace emerge -v subversion || die "emerge subversion failed" done_level $LEVEL fi LEVEL=1.21 if not_done_level $LEVEL; then trace # Configure proxy for subversion, if it seems # to be needed. Run this code twice: the first lap # creates the config directory and files and fails # because we have not done the proxy configuration; # on the second lap we configure for proxy and should # succeed. If we are not behind a proxy we should # succeed on the first attempt. COUNT=$((0)) RESULT=$((999)) while [ $COUNT -lt 2 -a $RESULT -ne 0 ]; do SVNCONF=$HOME/.subversion/servers TMPFILE=/tmp/setup-prefix-$$ if [ -n "$PROXYHOST" -a -n "$PROXYPORT" -a -f $SVNCONF ]; then cat $SVNCONF \ | sed \ -e '/^\[global/,$s|^# http-proxy-host =.*|http-proxy-host = '"$PROXYHOST"'|' \ -e '/^\[global/,$s|^# http-proxy-port =.*|http-proxy-port = '"$PROXYPORT"'|' \ >$TMPFILE if cmp $TMPFILE $SVNCONF >/dev/null 2>&1; then rm $TMPFILE else mv $TMPFILE $SVNCONF fi fi emerge -v --sync; RESULT=$? COUNT=$((COUNT+1)) done [ $RESULT -eq 0 ] || die "emerge --sync failed" done_level $LEVEL fi LEVEL=1.22 if not_done_level $LEVEL; then trace echo USE='"'${FINAL_USEFLAGS}'"' >> $EPREFIX/etc/make.conf echo CFLAGS='"'${FINAL_CFLAGS}'"' >> $EPREFIX/etc/make.conf done_level $LEVEL fi LEVEL=1.23 # Use a clean PATH now, and no special settings. env-update || die "failed to env-update" source /etc/profile unset LDFLAGS unset CPPFLAGS if not_done_level $LEVEL; then trace emerge -v -e world || die "emerge world failed" if ld --version; then echo "[$LEVEL] , level completed, binutils version is:" >>$BST_PROGRESS/binutils-version.txt ld --version >>$BST_PROGRESS/binutils-version.txt else die "failed to record binutils version" fi done_level $LEVEL fi LEVEL=1.24 if not_done_level $LEVEL; then trace ( # FIXME ... is the mkdir really needed? mkdir -p $EPREFIX/usr/portage/scripts cd $EPREFIX/usr/portage/scripts $BST_BIN/$BOOTSCRIPT $EPREFIX startscript || die "failed to create startscript" rm -rf $BST_TMP_BACKUP done_level $LEVEL ) fi LEVEL=goodies if not_done_level $LEVEL; then trace if [ $PLATFORM = solaris-sparc -a "$UNMASK_EMACS" = true ]; then appendline $EPREFIX/etc/portage/package.keywords 'app-admin/eselect-emacs ~x86-solaris' appendline $EPREFIX/etc/portage/package.keywords 'app-editors/emacs ~x86-solaris' fi for P in $GOODIES; do emerge -v $P || die "failed to emerge $P" done done_level $LEVEL fi LEVEL=alldone if not_done_level $LEVEL; then trace fi