# This script download and compile all the versions of clang (including rc)
# With offloading support. 

# QUICK START
# 1. Set the VERSIONS variable to be the clang/LLVM version you'd like to install
# 2. Set the ONLY_FINAL flag to anything else but false, if you don't want the RCs 
# 3. Set $INSTALLATION_PREFIX to the folder where you want to install clang/LLVM
# 4. If your base GCC is greater than 7.2, Cuda will complain. So you can se 
#    $GCC_CUDA_SUPPORTED to a lower version to avoid this issue.
# 5. If you set dry run to "echo" it will not do anything but just show you what the 
#    commands are
VERSION_OPTIONS=(500 501 502 600 601 700 701)
VERSIONS=${VERSIONS:-${VERSION_OPTIONS}}
ONLY_FINAL=${ONLY_FINAL:-false}
OUTLOGFILE=${PWD}/out.log
ERRLOGFILE=${PWD}/err.log
DRY_RUN=echo 

# Configuration
INSTALLATION_PREFIX=${INSTALLATION_PREFIX:-/software/apps}
MAKE_NUM_THREADS=${MAKE_NUM_THREADS:-1}
GCC_CUDA_SUPPORTED=${GCC_CUDA_SUPPORTED:-/usr/bin/gcc}
CCOMP=${CC}
CXXCOMP=${CXX}
BASE_URL=http://llvm.org/svn/llvm-project

echo " ==== OBTAINING THE LLVM REPOS === "

for version in ${VERSIONS[@]}; do 
    if [ ! -d RELEASE_$version ]; then 
        echo " ==== OBTAINING RELEASE $version === "
        if [ "$ONLY_FINAL" = "false" ]; then
            $DRY_RUN svn co $BASE_URL/llvm/tags/RELEASE_$version 2>>$ERRLOGFILE >>$OUTLOGFILE
        else
            mkdir RELEASE_$version
            cd RELEASE_$version
            $DRY_RUN svn co $BASE_URL/llvm/tags/RELEASE_$version/final 2>>$ERRLOGFILE >>$OUTLOGFILE
            cd ..
        fi
    else 
        echo "Repository RELEASE_$version Already clone"
    fi
done

# CLang 
printf "\n"
echo " ==== OBTAINING THE CLANG REPOSITORIES ==== "
for release_version in RELEASE*; do
    if [ -d "${release_version}" ]; then
        cd $release_version
        if [ "$ONLY_FINAL" = "false" ]; then
            for rc_verson in rc* final; do
                if [ -d "${rc_version}" ]; then
                    echo " ==== ADDING CLANG TO RELEASE $release_version/$rc_version ==== "
                    cd $rc_version/tools
                    if [ ! -d "clang" ]; then
                        $DRY_RUN svn co $BASE_URL/cfe/tags/$release_version/$rc_version clang  2>> $ERRLOGFILE >> $OUTLOGFILE
                    fi
                    cd ../..
                fi
            done
        else
            if [ -d "final" ]; then
                echo " ==== ADDING CLANG TO RELEASE $release_version/final ==== "
                cd final/tools
                if [ ! -d "clang" ]; then
                    $DRY_RUN svn co $BASE_URL/cfe/tags/$release_version/final clang  2>> $ERRLOGFILE >> $OUTLOGFILE
                fi
                cd ../..
            fi
        fi

        cd ..
    fi
done

# Compile-rt and OpenMP
printf "\n"
echo " ==== OBTAINING THE COMPILE-RT AND OMP REPOSITORIES ==== "
for release_version in RELEASE*; do
    if [ -d "${release_version}" ]; then
        cd $release_version
        if [ "$ONLY_FINAL" = "false" ]; then
            for rc_version in rc* final; do
                if [ -d "${rc_version}" ]; then
                    echo " ==== ADDING COMPILE-RT and OMP TO RELEASE $release_version/$rc_version ==== "
                    cd $rc_version/projects
                    if [ ! -d "compiler-rt" ]; then
                        $DRY_RUN svn co $BASE_URL/compiler-rt/tags/$release_version/$rc_version compiler-rt  2>> $ERRLOGFILE >> $OUTLOGFILE
                    fi
                    if [ ! -d "openmp" ]; then
                        $DRY_RUN svn co $BASE_URL/openmp/tags/$release_version/$rc_version openmp 2>> $ERRLOGFILE >> $OUTLOGFILE
                    fi
                    cd ../..
                fi
            done
        else
            if [ -d "final" ]; then
                echo " ==== ADDING COMPILE-RT and OMP TO RELEASE $release_version/final ==== "
                cd final/projects
                if [ ! -d "compiler-rt" ]; then
                    $DRY_RUN svn co $BASE_URL/compiler-rt/tags/$release_version/final compiler-rt  2>> $ERRLOGFILE >> $OUTLOGFILE
                fi
                if [ ! -d "openmp" ]; then
                    $DRY_RUN svn co $BASE_URL/openmp/tags/$release_version/final openmp 2>> $ERRLOGFILE >> $OUTLOGFILE
                fi
                cd ../..
            fi
        fi
        cd ..
    fi
done

# Start compiling
printf "\n"
echo " ==== STARTING COMPILATION ==== "

for release_version in RELEASE*; do
    if [ -d "${release_version}" ]; then
        cd $release_version
        if [ "$ONLY_FINAL" = "false" ]; then
            for rc_version in rc* final; do
                if [ -d "${rc_version}" ]; then
                    echo " ==== STARTING COMPILATION PROCESS  $release_version/$rc_version ==== "
                    TARGET_INSTALL=$INSTALLATION_PREFIX/clang/$(grep -oh "[0-9]*" <<< $release_version)/$rc_version
                    echo " -> Installing in $TARGET_INSTALL"
                    mkdir -p build_$rc_version
                    cd build_$rc_version
                    echo " ==== CMAKE ===="
                    $DRY_RUN cmake ../$rc_version -DCMAKE_C_COMPILER=$CC \
                    -DCMAKE_CXX_COMPILER=$CXX \
                    -DCMAKE_BUILD_TYPE="Release" \
                    -DCMAKE_INSTALL_PREFIX=$TARGET_INSTALL \
                    -DLIBOOMPTARGET_OPENMP_HEADER_FOLDER=$TARGET_INSTALL/include \
                    -DLIBOMPTARGET_OPENMP_HOST_RTL_FOLDER=$TARGET_INSTALL/lib \
                    -DLIBOMPTARGET_NVPTX_COMPUTE_CAPABILITIES=35 \
                    -DOPENMP_ENABLE_LIBOMPTARGET=ON \
                    -DLIBOMPTARGET_NVPTX_ENABLE_BCLIB=true \
                    -DCLANG_OPENMP_NVPTX_DEFAULT_ARCH=sm_35 \
                    -DLIBOMPTARGET_NVPTX_ALTERNATE_HOST_COMPILER=$GCC_CUDA_SUPPORTED \
                    -DLIBOMPTARGET_NVPTX_CUDA_COMPILER=/software/apps/clang/7.0.0/bin/clang 2>> $ERRLOGFILE >> $OUTLOGFILE
                    echo " ==== MAKE ===="
                    $DRY_RUN make -j $MAKE_NUM_THREADS 2>> $ERRLOGFILE >> $OUTLOGFILE
                    echo " ==== MAKE INSTALL ===="
                    $DRY_RUN make install -j $MAKE_NUM_THREADS 2>> $ERRLOGFILE >> $OUTLOGFILE
                    cd ..
                fi
            done
        else
            if [ -d "final" ]; then
                echo " ==== STARTING COMPILATION PROCESS  $release_version/final ==== "
                TARGET_INSTALL=$INSTALLATION_PREFIX/clang/$(grep -oh "[0-9]*" <<< $release_version)/final
                echo " -> Installing in $TARGET_INSTALL"
                mkdir -p build_final
                cd build_final
                echo " ==== CMAKE ===="
                $DRY_RUN cmake ../final -DCMAKE_C_COMPILER=$CC \
                -DCMAKE_CXX_COMPILER=$CXX \
                -DCMAKE_BUILD_TYPE="Release" \
                -DCMAKE_INSTALL_PREFIX=$TARGET_INSTALL \
                -DLIBOOMPTARGET_OPENMP_HEADER_FOLDER=$TARGET_INSTALL/include \
                -DLIBOMPTARGET_OPENMP_HOST_RTL_FOLDER=$TARGET_INSTALL/lib \
                -DLIBOMPTARGET_NVPTX_COMPUTE_CAPABILITIES=35 \
                -DOPENMP_ENABLE_LIBOMPTARGET=ON \
                -DLIBOMPTARGET_NVPTX_ENABLE_BCLIB=true \
                -DCLANG_OPENMP_NVPTX_DEFAULT_ARCH=sm_35 \
                -DLIBOMPTARGET_NVPTX_ALTERNATE_HOST_COMPILER=$GCC_CUDA_SUPPORTED \
                -DLIBOMPTARGET_NVPTX_CUDA_COMPILER=/software/apps/clang/7.0.0/bin/clang 2>> $ERRLOGFILE >> $OUTLOGFILE
                echo " ==== MAKE ===="
                $DRY_RUN make -j $MAKE_NUM_THREADS 2>> $ERRLOGFILE >> $OUTLOGFILE
                echo " ==== MAKE INSTALL ===="
                $DRY_RUN make install -j $MAKE_NUM_THREADS 2>> $ERRLOGFILE >> $OUTLOGFILE
                cd ..
            fi
        fi
        cd ..
    fi
done


