#!/bin/bash

# Two stages self build

set -e                     # Terminate script at the first line that fails.
set -o pipefail            # Return the first non-zero pipe command error.
set -x                     # Print commands as they are executed

# This script performs an automated build on x86_64-apple-darwin10 of
# cross llvm-gcc for i686-pc-mingw32 as
# --build=x86_64-apple-darwin10
# --host=x86_64-apple-darwin10
# --target=i686-pc-mingw32
#
# Then using this cross llvm-gcc for i686-pc-mingw32 it builds a self-hosted
# llvm-gcc for i686-pc-mingw32 as
# --build=x86_64-apple-darwin10
# --host=i686-pc-mingw32
# --target=i686-pc-mingw32
#
# This script assumes the valid native compiler for x86_64-apple-darwin10
# is in place and available as well as cross tools, libraries and
# headers for i686-pc-mingw32.

# The usage:
# Run this build from the build from the build root directory as
# build-self-4-mingw32 [<step>] [<extra args>]

# Expected project tree structure:
# <build root>
#    +-- ${LLVM_src}
#    +-- ${LLVM_GCC_src}
#    +-- ${LLVM_obj_1}        # cross llvm     (Stage 1) build directory
#    +-- ${LLVM_GCC_obj_1}    # cross llvm-gcc (Stage 1) build directory
#    +-- ${LLVM_obj_2}        # self  llvm     (Stage 2) build directory
#    +-- ${LLVM_GCC_obj_2}    # self  llvm-gcc (Stage 2) build directory
#    +-- ${INSTALL}           # where the result gets installed

LLVM_src=llvm.src             # The LLVM source code root directory name.
LLVM_GCC_src=llvm-gcc.src     # The LLVM-GCC source code root directory name.
LLVM_obj_1=llvm-1.obj         # The LLVM build root directory name.
LLVM_GCC_obj_1=llvm-gcc-1.obj # The LLVM-GCC build root directory name.
LLVM_obj_2=llvm-2.obj         # The LLVM build root directory name for Stage2.
LLVM_GCC_obj_2=llvm-gcc-2.obj # The LLVM-GCC build root directory name for Stage2.
INSTALL=install               # Where the result will be installed.

# CFLAGS and CXXFLAGS must not be set during the building of cross-tools.
unset CFLAGS
unset CXXFLAGS

BUILD_ROOT=$PWD                           # Where build happens.
PRIVATE_INSTALL=${BUILD_ROOT}/${INSTALL}  # Where the result will be installed.

#------------------------------------------------------------------------------
# Define build steps, parse and validate input parameters
#------------------------------------------------------------------------------

# This script supports the following steps:
do_clean=no                 # Clean up the build directory.
do_copy_cross_tools=no      # Copy cross-tools. 
do_configure_llvm_1=no      # Configure LLVM.
do_make_llvm_1=no           # Make LLVM.
do_test_llvm_1=no           # Test LLVM.
do_configure_llvmgcc_1=no   # Configure LLVM-GCC.
do_make_llvmgcc_1=no        # Make LLVM-GCC.
do_install_llvmgcc_1=no     # Install LLVM-GCC.
do_configure_llvm_2=no      # Configure LLVM for Stage2.
do_make_llvm_2=no           # Make LLVM for Stage2.
do_test_llvm_2=no           # Test LLVM for Stage2.
do_configure_llvmgcc_2=no   # Configure LLVM-GCC for Stage2.
do_make_llvmgcc_2=no        # Make LLVM-GCC for Stage2.
do_install_llvmgcc_2=no     # Install LLVM-GCC for Stage2.

do_all=no                   # Runs all steps at once when requested.

# Set step parameter
if (( $# == 0 )) ; then
   do_all=yes
fi
# else
if (( ! $# == 0 )) ; then
   # First check that the parameter actually defines a step.
   case $1 in
      clean               |  \
      copy_cross_tools    |  \
      configure_llvm_1    |  \
      make_llvm_1         |  \
      test_llvm_1         |  \
      configure_llvmgcc_1 |  \
      make_llvmgcc_1      |  \
      install_llvmgcc_1   |  \
      configure_llvm_2    |  \
      make_llvm_2         |  \
      test_llvm_2         |  \
      configure_llvmgcc_2 |  \
      make_llvmgcc_2      |  \
      install_llvmgcc_2   |  \
      all)
         eval do_$1=yes    # Set the flag for the requested step .
         shift             # Remove it since is is ours and already precessed.
         ;;

      *)
         # Not our parameter. Pass it as is.
   esac
fi

# Set all steps if do_all requested
if [ "$do_all" == "yes" ] ; then
   # Set all steps to yes
   do_clean=yes
   do_copy_cross_tools=yes
   do_configure_llvm_1=yes
   do_make_llvm_1=yes
   do_test_llvm_1=yes
   do_configure_llvmgcc_1=yes
   do_make_llvmgcc_1=yes
   do_install_llvmgcc_1=yes  
   do_configure_llvm_2=yes
   do_make_llvm_2=yes
   do_test_llvm_2=yes
   do_configure_llvmgcc_2=yes
   do_make_llvmgcc_2=yes
   do_install_llvmgcc_2=yes
fi

#------------------------------------------------------------------------------
# Step: Clean up.
#------------------------------------------------------------------------------
if [ "$do_clean" == "yes" ] ; then

   # Remove everything from where we will be installing the result.
   rm -rf ${PRIVATE_INSTALL}
   mkdir -p ${PRIVATE_INSTALL}
   chmod a+rx ${PRIVATE_INSTALL}

fi

#------------------------------------------------------------------------------
# Step: Copy cross-tools.
#------------------------------------------------------------------------------
if [ "$do_copy_cross_tools" == "yes" ] ; then

   # We need a local copy of binutils, system libraries and headers,
   # since we will be installing there.
   cp -RL /cross-tools/ ${PRIVATE_INSTALL}

fi

#==============================================================================
# STAGE 1 builds cross llvm-gcc for i686-pc-mingw32.
#==============================================================================

#------------------------------------------------------------------------------
# Step: Configure LLVM.
#------------------------------------------------------------------------------
if [ "$do_configure_llvm_1" == "yes" ] ; then

   # Remove previously build files if any.
   rm -rf ${BUILD_ROOT}/${LLVM_obj_1}
   mkdir -p ${BUILD_ROOT}/${LLVM_obj_1}
   chmod a+rx ${BUILD_ROOT}/${LLVM_obj_1}
   cd ${BUILD_ROOT}/${LLVM_obj_1}

   ../${LLVM_src}/configure --prefix=${PRIVATE_INSTALL}          \
      --build=x86_64-apple-darwin10 --host=x86_64-apple-darwin10 \
      --target=i686-pc-mingw32                                   \
      --enable-optimize                                          \
      --without-llvmgcc --without-llvmgxx                        \
      $@  # Extra args if any

fi

#------------------------------------------------------------------------------
# Step: Make LLVM.
#------------------------------------------------------------------------------
if [ "$do_make_llvm_1" == "yes" ] ; then

   cd ${BUILD_ROOT}/${LLVM_obj_1}
   # NOTE: Do not use make ENABLE_OPTIMIZED=1. Some tests fail because of that.
   nice -n 20 make VERBOSE=1 \
      $@  # Extra args if any, like -j16 for example.

fi

#------------------------------------------------------------------------------
# Step: Test LLVM.
#------------------------------------------------------------------------------
if [ "$do_test_llvm_1" == "yes" ] ; then

   cd ${BUILD_ROOT}/${LLVM_obj_1}
   make check-lit VERBOSE=1  \
      $@  # Extra args if any, like -j16 for example.

fi

#------------------------------------------------------------------------------
# Step: Configure LLVM-GCC.
#------------------------------------------------------------------------------
if [ "$do_configure_llvmgcc_1" == "yes" ] ; then

   # Remove previous build files if any.
   rm -rf ${BUILD_ROOT}/${LLVM_GCC_obj_1}
   mkdir -p ${BUILD_ROOT}/${LLVM_GCC_obj_1}
   chmod a+rx ${BUILD_ROOT}/${LLVM_GCC_obj_1}
   cd ${BUILD_ROOT}/${LLVM_GCC_obj_1}
   
   ../${LLVM_GCC_src}/configure --prefix=${PRIVATE_INSTALL}      \
      --build=x86_64-apple-darwin10 --host=x86_64-apple-darwin10 \
      --with-local-prefix=/tools                                 \
      --target=i686-pc-mingw32                                   \
      --program-prefix=i686-pc-mingw32-                          \
      --enable-llvm=${BUILD_ROOT}/${LLVM_obj_1}                  \
      --enable-languages=c,c++                                   \
      --disable-multilib --disable-nls --disable-shared          \
      --disable-sjlj-exceptions --disable-__cxa_atexit           \
      $@  # Extra args if any

fi

#------------------------------------------------------------------------------
# Step: Make LLVM-GCC.
#------------------------------------------------------------------------------
if [ "$do_make_llvmgcc_1" == "yes" ] ; then

   cd ${BUILD_ROOT}/${LLVM_GCC_obj_1}
   nice -n 20 make          \
      $@  # Extra args if any

fi

#------------------------------------------------------------------------------
# Step: Install LLVM-GCC.
#------------------------------------------------------------------------------
if [ "$do_install_llvmgcc_1" == "yes" ] ; then

   cd ${BUILD_ROOT}/${LLVM_GCC_obj_1}
   nice -n 20 make install  \
      $@  # Extra args if any

fi

#==============================================================================
# STAGE 2 builds self-hosted llvm-gcc for i686-pc-mingw32.
#==============================================================================

#------------------------------------------------------------------------------
# Step: Stage2. Configure LLVM.
#------------------------------------------------------------------------------
if [ "$do_configure_llvm_2" == "yes" ] ; then

   # Make sure our just built tools will be selected first.
   # Note: Always set this, even when do_all has been requested.
   export PATH=${PRIVATE_INSTALL}/bin:${PATH}

   # Remove previous build files if any.
   rm -rf ${BUILD_ROOT}/${LLVM_obj_2}
   mkdir -p ${BUILD_ROOT}/${LLVM_obj_2}
   chmod a+rx ${BUILD_ROOT}/${LLVM_obj_2}
   cd ${BUILD_ROOT}/${LLVM_obj_2}

   ../${LLVM_src}/configure --prefix=${PRIVATE_INSTALL}          \
      --build=x86_64-apple-darwin10 --host=i686-pc-mingw32       \
      --target=i686-pc-mingw32                                   \
      --enable-optimize                                          \
      --with-llvmgcc=${PRIVATE_INSTALL}/bin/llvm-gcc             \
      --with-llvmgxx=${PRIVATE_INSTALL}/bin/llvm-g++

fi

#------------------------------------------------------------------------------
# Step: Stage2. Make LLVM.
#------------------------------------------------------------------------------
if [ "$do_make_llvm_2" == "yes" ] ; then

   if [ "$do_all" == "no" ] ; then
      # Make sure our just built tools will be selected first.
      export PATH=${PRIVATE_INSTALL}/bin:${PATH}
   fi

   cd ${BUILD_ROOT}/${LLVM_obj_2}
   # NOTE: Do not use make ENABLE_OPTIMIZED=1. Some tests fail because of that.
   nice -n 20 make VERBOSE=1 \
      $@  # Extra args if any, like -j16 for example.

fi

#------------------------------------------------------------------------------
# Step: Stage2. Test LLVM.
#------------------------------------------------------------------------------ 
if [ "$do_test_llvm_2" == "yes" ] ; then

   if [ "$do_all" == "no" ] ; then
      # Make sure our just built tools will be selected first.
      export PATH=${PRIVATE_INSTALL}/bin:${PATH}
   fi

   cd ${BUILD_ROOT}/${LLVM_obj_2}
   make check-lit VERBOSE=1  \
      $@  # Extra args if any

fi

#------------------------------------------------------------------------------
# Step: Stage2. Configure LLVM-GCC.
#------------------------------------------------------------------------------
if [ "$do_configure_llvmgcc_2" == "yes" ] ; then

   if [ "$do_all" == "no" ] ; then
      # Make sure our just built tools will be selected first.
      export PATH=${PRIVATE_INSTALL}/bin:${PATH}
   fi

   # Remove previous build files if any.
   rm -rf ${BUILD_ROOT}/${LLVM_GCC_obj_2}
   mkdir -p ${BUILD_ROOT}/${LLVM_GCC_obj_2}
   chmod a+rx ${BUILD_ROOT}/${LLVM_GCC_obj_2}
   cd ${BUILD_ROOT}/${LLVM_GCC_obj_2}

   ../${LLVM_GCC_src}/configure --prefix=${PRIVATE_INSTALL}      \
      --build=x86_64-apple-darwin10 --host=i686-pc-mingw32       \
      --with-local-prefix=/tools                                 \
      --target=i686-pc-mingw32                                   \
      --program-prefix=llvm-                                     \
      --enable-llvm=${BUILD_ROOT}/${LLVM_obj_2}                  \
      --enable-languages=c,c++                                   \
      --disable-multilib --disable-nls --disable-shared          \
      --disable-sjlj-exceptions --disable-__cxa_atexit           \
      $@  # Extra args if any

fi
#------------------------------------------------------------------------------
# Step: Stage2. Make LLVM-GCC.
#------------------------------------------------------------------------------
if [ "$do_make_llvmgcc_2" == "yes" ] ; then

   if [ "$do_all" == "no" ] ; then
      # Make sure our just built tools will be selected first.
      export PATH=${PRIVATE_INSTALL}/bin:${PATH}
   fi

   cd ${BUILD_ROOT}/${LLVM_GCC_obj_2}
   nice -n 20 make          \
      $@  # Extra args if any

fi

#------------------------------------------------------------------------------
# Step: Install LLVM-GCC.
#------------------------------------------------------------------------------
if [ "$do_install_llvmgcc_2" == "yes" ] ; then

   if [ "$do_all" == "no" ] ; then
      # Make sure our just built tools will be selected first.
      export PATH=${PRIVATE_INSTALL}/bin:${PATH} 
   fi

   cd ${BUILD_ROOT}/${LLVM_GCC_obj_2}
   nice -n 20 make install  \
      $@  # Extra args if any

fi
