| #!/bin/bash |
| |
| # This script performs an automated self-hosted build of dragonegg. In |
| # other words it builds dragonegg, then builds GCC and LLVM with dragonegg, |
| # then uses those and dragonegg to rebuild dragonegg. It does this a couple |
| # of times until it reckons you must be fed up. At which point it checks |
| # that the dragonegg plugin is not changing at each iteration. |
| # |
| # This is all extreme overkill if all you want to do is try out dragonegg! If |
| # that's your goal then I suggest you consult the README file one directory up. |
| |
| DRAGONEGG_SOURCE=$PWD/dragonegg # Where to check out the dragonegg source |
| GCC_SOURCE=$PWD/gcc # Where to check out the GCC source |
| LLVM_SOURCE=$PWD/llvm # Where to check out the LLVM source |
| |
| DRAGONEGG_BUILD_BASE=$PWD/dragonegg-build # Where to build dragonegg |
| GCC_BUILD_BASE=$PWD/gcc-build # Where to build GCC |
| LLVM_BUILD_BASE=$PWD/llvm-build # Where to build LLVM |
| GCC_INSTALL_BASE=$PWD/gcc-install # Where to install GCC |
| |
| |
| STAGES="0 1 2" # Determines how many times we build GCC, LLVM and dragonegg |
| |
| #USE_PER_STAGE_BUILD_DIRECTORIES=0 # Do not use per-stage build directories |
| USE_PER_STAGE_BUILD_DIRECTORIES=1 # Use per-stage build directories, helps |
| # when debugging self-host failures |
| |
| USE_PER_STAGE_INSTALL_DIRECTORIES=0 # Do not use per-stage install |
| # directories |
| #USE_PER_STAGE_INSTALL_DIRECTORIES=1 # Use per-stage install directories |
| # NOTE: turning on per-stage install directories automatically disables testing |
| # that dragonegg object files did not change from one stage to the next. This |
| # is because the GCC install directory name gets embedded in the object files |
| # due to use of __FILE__ in headers included from the GCC install directory. |
| |
| |
| # How to configure GCC. As a minimum you need to enable C and C++, but you can |
| # also enable other languages if you like. You must specify --enable-lto. The |
| # other flags are optional. The reason for --disable-multilib is that GCC fails |
| # to build on my machine without it (this is a GCC issue, and has nothing to do |
| # with dragonegg or LLVM). |
| GCC_OPTIONS="--enable-lto --enable-languages=c,c++ --disable-bootstrap \ |
| --disable-multilib --enable-checking" |
| |
| # How to configure LLVM. These are all optional. On my machine, the debugger |
| # refuses to work with dragonegg unless I build LLVM with --disable-threads. |
| LLVM_OPTIONS="--enable-optimized --enable-assertions \ |
| --disable-threads" |
| |
| |
| COMPARE="cmp --ignore-initial=16" # How to compare object files |
| MAKE="nice -n 20 make -j -l3" # How to run make |
| |
| |
| set -o errexit # Exit if any command fails |
| shopt -s nullglob |
| |
| # Turn off plugin version checking, otherwise the check may fail if all stages |
| # are not built on the same day, since the version contains the build date. |
| export dragonegg_disable_version_check=yes |
| |
| # Check out or update the dragonegg source |
| if [ -a $DRAGONEGG_SOURCE ] ; then |
| echo "Updating dragonegg" |
| svn update $DRAGONEGG_SOURCE |
| else |
| echo "Checking out dragonegg" |
| svn co http://llvm.org/svn/llvm-project/dragonegg/trunk $DRAGONEGG_SOURCE |
| fi |
| |
| |
| # Check out or update the LLVM source |
| if [ -a $LLVM_SOURCE ] ; then |
| echo "Updating LLVM" |
| svn update $LLVM_SOURCE |
| else |
| echo "Checking out LLVM" |
| svn co http://llvm.org/svn/llvm-project/llvm/trunk $LLVM_SOURCE |
| fi |
| |
| |
| # Check out or update the GCC source |
| if [ -a $GCC_SOURCE ] ; then |
| echo "Reverting any applied patches" |
| svn revert -R $GCC_SOURCE/gcc |
| echo "Updating GCC" |
| svn update $GCC_SOURCE |
| else |
| echo "Checking out GCC" |
| svn co svn://gcc.gnu.org/svn/gcc/trunk $GCC_SOURCE |
| fi |
| |
| |
| # Apply any needed patches to GCC |
| for PATCH in $DRAGONEGG_SOURCE/gcc-patches/*.diff ; do |
| echo "Applying patch $PATCH" |
| patch -d $GCC_SOURCE -p1 < $PATCH |
| done |
| |
| PLUGIN_OPTION= # No plugin yet |
| PREV_DRAGONEGG_BUILD= # No previous dragonegg |
| for STAGE in $STAGES ; do |
| |
| if (( USE_PER_STAGE_BUILD_DIRECTORIES )) ; then |
| DRAGONEGG_BUILD=$DRAGONEGG_BUILD_BASE-$STAGE |
| GCC_BUILD=$GCC_BUILD_BASE-$STAGE |
| LLVM_BUILD=$LLVM_BUILD_BASE-$STAGE |
| else |
| DRAGONEGG_BUILD=$DRAGONEGG_BUILD_BASE |
| GCC_BUILD=$GCC_BUILD_BASE |
| LLVM_BUILD=$LLVM_BUILD_BASE |
| fi |
| |
| if (( USE_PER_STAGE_INSTALL_DIRECTORIES )) ; then |
| GCC_INSTALL=$GCC_INSTALL_BASE-$STAGE |
| else |
| GCC_INSTALL=$GCC_INSTALL_BASE |
| fi |
| |
| # ==> begin: Build and install GCC |
| echo "Building stage $STAGE GCC" |
| rm -fr $GCC_BUILD |
| mkdir -p $GCC_BUILD |
| cd $GCC_BUILD |
| # NOTE: the configure arguments need to be the same at each stage, because |
| # they are recorded in the plugin version information. If they differed, |
| # then object files from different stages would not compare the same. This |
| # is the reason for configuring with the same prefix at each stage, even if |
| # we intend to install in a different directory each time. |
| $GCC_SOURCE/configure --prefix=$GCC_INSTALL_BASE $GCC_OPTIONS |
| $MAKE |
| |
| echo "Installing stage $STAGE GCC" |
| rm -fr $GCC_INSTALL $GCC_INSTALL_BASE |
| $MAKE install |
| if [ "$GCC_INSTALL_BASE" != "$GCC_INSTALL" ] ; then |
| # Move the just built GCC to its definitive install directory. |
| mv $GCC_INSTALL_BASE $GCC_INSTALL |
| fi |
| # <== end: Build and install GCC |
| |
| |
| # From now on compile using the newly built GCC |
| export CC="$GCC_INSTALL/bin/gcc $PLUGIN_OPTION" |
| export CXX="$GCC_INSTALL/bin/g++ $PLUGIN_OPTION" |
| export GCC=$CC # Tells dragonegg what to build against |
| |
| # The built libstdc++ and libgcc may be more recent than the system versions. |
| # Set the library path so that programs compiled with the just built GCC will |
| # start successfully, rather than failing due to shared library dependencies. |
| export LD_LIBRARY_PATH=`$CC -print-search-dirs | grep "^libraries:" | \ |
| sed "s/^libraries: *=//"`:$LD_LIBRARY_PATH |
| |
| |
| # ==> begin: Build LLVM using the just built GCC |
| echo "Building stage $STAGE LLVM" |
| rm -fr $LLVM_BUILD |
| mkdir -p $LLVM_BUILD |
| cd $LLVM_BUILD |
| $LLVM_SOURCE/configure $LLVM_OPTIONS |
| $MAKE |
| # <== end: Build LLVM using the just built GCC |
| |
| |
| # From now on 'llvm-config' will be the just built one. |
| export LLVM_CONFIG=$LLVM_BUILD/*/bin/llvm-config |
| |
| |
| # ==> begin: Build dragonegg using the just built GCC and LLVM. |
| echo "Building pre-stage $STAGE dragonegg" |
| rm -fr $DRAGONEGG_BUILD-pre |
| mkdir -p $DRAGONEGG_BUILD-pre |
| cd $DRAGONEGG_BUILD-pre |
| $MAKE -f $DRAGONEGG_SOURCE/Makefile clean |
| SRC_DIR=$DRAGONEGG_SOURCE $MAKE -f $DRAGONEGG_SOURCE/Makefile |
| # <== end: Build dragonegg using the just built GCC and DRAGONEGG. |
| |
| |
| # Compile using the just built dragonegg. |
| PLUGIN_OPTION="-fplugin=$DRAGONEGG_BUILD-pre/dragonegg.so" |
| export CC="$GCC_INSTALL/bin/gcc $PLUGIN_OPTION" |
| export CXX="$GCC_INSTALL/bin/g++ $PLUGIN_OPTION" |
| export GCC=$CC # Tells dragonegg what to build against |
| |
| |
| # ==> begin: Build dragonegg again using the just built dragonegg |
| echo "Building stage $STAGE dragonegg with itself" |
| rm -fr $DRAGONEGG_BUILD |
| mkdir -p $DRAGONEGG_BUILD |
| cd $DRAGONEGG_BUILD |
| $MAKE -f $DRAGONEGG_SOURCE/Makefile clean |
| SRC_DIR=$DRAGONEGG_SOURCE $MAKE -f $DRAGONEGG_SOURCE/Makefile |
| # <== end: Build dragonegg again using the just built dragonegg |
| |
| |
| # Compile using the self-built dragonegg. |
| PLUGIN_OPTION="-fplugin=$DRAGONEGG_BUILD/dragonegg.so" |
| export CC="$GCC_INSTALL/bin/gcc $PLUGIN_OPTION" |
| export CXX="$GCC_INSTALL/bin/g++ $PLUGIN_OPTION" |
| export GCC=$CC # Tells dragonegg what to build against |
| |
| |
| # ==> begin: Compare the dragonegg objects with those from the previous stage |
| if (( !USE_PER_STAGE_INSTALL_DIRECTORIES )) ; then |
| |
| if [ "x$PREV_DRAGONEGG_BUILD" != "x" ] ; then |
| echo "Comparing $DRAGONEGG_BUILD objects to $PREV_DRAGONEGG_BUILD objects" |
| cd $DRAGONEGG_BUILD |
| for O in *.o ; do |
| P=$PREV_DRAGONEGG_BUILD/$O |
| $COMPARE $O $P |
| done |
| fi |
| |
| fi |
| # <== end: Compare the dragonegg objects with those from the previous stage |
| |
| |
| PREV_DRAGONEGG_BUILD=$DRAGONEGG_BUILD |
| done |