#!/bin/bash

# Dependency: libedit-devel libxml2-devel ncurses-devel python-devel swig

# ======================================= 配置 =======================================
LLVM_VERSION=10.0.0
LIBEDIT_VERSION=20191231-3.1
PREFIX_DIR=/usr/local/llvm-$LLVM_VERSION;
#BUILD_TARGET_COMPOMENTS="clang;clang-tools-extra;compiler-rt;debuginfo-tests;libc;libclc;libcxx;libcxxabi;libunwind;lld;lldb;mlir;openmp;parallel-libs;polly;pstl";
BUILD_TARGET_COMPOMENTS="clang;clang-tools-extra;compiler-rt;libc;libclc;libcxx;libcxxabi;libunwind;lld;lldb;openmp;parallel-libs;polly;pstl";

# ======================= 非交叉编译 ======================= 
CHECK_TOTAL_MEMORY=$(cat /proc/meminfo | grep MemTotal | awk '{print $2}');
CHECK_AVAILABLE_MEMORY=$(cat /proc/meminfo | grep MemAvailable | awk '{print $2}');
BUILD_LLVM_LLVM_OPTION="-DLLVM_BUILD_EXAMPLES=OFF -DLLVM_BUILD_TESTS=OFF -DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=ON -DLLVM_ENABLE_EH=ON -DLLVM_ENABLE_RTTI=ON -DLLVM_ENABLE_PIC=ON -DLLVM_USE_INTEL_JITEVENTS=ON"; # -DLLVM_ENABLE_LTO=ON ,this may failed in llvm 3.9 
BUILD_OTHER_CONF_OPTION="";
BUILD_DOWNLOAD_ONLY=0;
BUILD_USE_LD="";
BUILD_TYPE="Release";
BUILD_JOBS_OPTION="-j";

# ======================= 内存大于13GB，使用动态链接库（linking libLLVM-XXX.so的时候会消耗巨量内存） =======================
if [ -z "$CHECK_AVAILABLE_MEMORY" ]; then
    CHECK_AVAILABLE_MEMORY=0;
fi

if [ -z "$CHECK_TOTAL_MEMORY" ]; then
    CHECK_TOTAL_MEMORY=0;
fi

# if [ $CHECK_AVAILABLE_MEMORY -gt 13631488 ] || [ $CHECK_TOTAL_MEMORY -gt 13631488 ]; then
#     BUILD_LLVM_LLVM_OPTION="$BUILD_LLVM_LLVM_OPTION -DLLVM_BUILD_LLVM_DYLIB=ON -DLLVM_LINK_LLVM_DYLIB=ON";
#     for BUILD_TARGET in ${BUILD_TARGET_COMPOMENTS//;/ }; do
#         if [ "libc" == "$BUILD_TARGET" ]; then
#             BUILD_LLVM_LLVM_OPTION="$BUILD_LLVM_LLVM_OPTION -DLLVM_BUILD_LLVM_C_DYLIB=ON";
#             break;
#         fi
#     done
# fi
  
# ======================================= 检测 ======================================= 
BUILD_FIND_PYTHON3=$(which python 2>/dev/null);
if [ $? -ne 0 ]; then
    BUILD_FIND_PYTHON3="";
else
    CHECK_PYTHON_VERSION=$("$BUILD_FIND_PYTHON3" -c "import sys; print(sys.version[0])");
    if [ $? -ne 0 ] || [ $CHECK_PYTHON_VERSION -lt 3 ]; then
        BUILD_FIND_PYTHON3="";
    fi
fi

if [ "x$BUILD_FIND_PYTHON3" != "x" ]; then
    echo "python3";
    BUILD_TARGET_COMPOMENTS="$BUILD_TARGET_COMPOMENTS;debuginfo-tests";
    BUILD_LLVM_LLVM_OPTION="$BUILD_LLVM_LLVM_OPTION -DPython_EXECUTABLE=$BUILD_FIND_PYTHON3 -DPython_FIND_VERSION=3";
fi

if [ -z "$CC" ]; then
    CC=$(which gcc);
    if [ $? -eq 0 ]; then
        CXX="$(dirname $CC)/g++";
    else
        CC=$(which clang);
        if [ $? -eq 0 ]; then
            CXX="$(dirname $CC)/clang++";
        else
            echo -e "\\033[32;1mCan not find gcc or clang.\\033[39;49;0m";
            exit 1;
        fi
    fi
fi
export CC="$CC";
export CXX="$CXX";

ORIGIN_COMPILER_CC="$(readlink -f "$CC")";
ORIGIN_COMPILER_CXX="$(readlink -f "$CXX")";

echo '
#include <stdio.h>
int main() {
    puts("test ld.gold");
    return 0;
}
' > contest.tmp.c;
$CC -o contest.tmp.exe -O2 -fuse-ld=gold contest.tmp.c;
if [ $? -eq 0 ]; then
    BUILD_USE_LD="gold";
fi
rm -f contest.tmp.exe contest.tmp.c;
 
# ======================= 检测完后等待时间 ======================= 
CHECK_INFO_SLEEP=3
 
# ======================= 安装目录初始化/工作目录清理 ======================= 
while getopts "b:cdg:hj:l:m:np:t:" OPTION; do
    case $OPTION in
        p)
            PREFIX_DIR="$OPTARG";
        ;;
        b)
            BUILD_TYPE="$OPTARG";
        ;;
        c)
            rm -rf $(ls -A -d -p * | grep -E "(.*)/$");
            echo -e "\\033[32;1mnotice: clear work dir(s) done.\\033[39;49;0m";
            exit 0;
        ;;
        d)
            BUILD_DOWNLOAD_ONLY=1;
            echo -e "\\033[32;1mDownload mode.\\033[39;49;0m";
        ;;
        h)
            echo "usage: $0 [options] -p=prefix_dir -c -h";
            echo "options:";
            echo "-b [build type]             Release (default), RelWithDebInfo, MinSizeRel, Debug";
            echo "-c                          clean build cache.";
            echo "-d                          download only.";
            echo "-h                          help message.";
            echo "-j [parallel jobs]          Build in parallel using the given number of jobs.";
            echo "-l [llvm configure option]  add llvm build options.";
            echo "-m [llvm cmake option]      add llvm build options.";
            echo "-g [gnu option]             add gcc,binutils,gdb build options.";
            echo "-n                          print toolchain version and exit.";
            echo "-p [prefix_dir]             set prefix directory.";
            echo "-t [build target]           set build target(all;clang;clang-tools-extra;compiler-rt;debuginfo-tests;libc;libclc;libcxx;libcxxabi;libunwind;lld;lldb;mlir;openmp;parallel-libs;polly;pstl).";
            exit 0;
        ;;
        t)
            if [ "x$BUILD_TARGET_COMPOMENTS" == "xall" ]; then
                BUILD_TARGET_COMPOMENTS="";
            fi
            if [ "+" == "${OPTARG:0:1}" ]; then
                BUILD_TARGET_COMPOMENTS="$BUILD_TARGET_COMPOMENTS ${OPTARG:1}";
            else
                BUILD_TARGET_COMPOMENTS="$OPTARG";
            fi
        ;;
        j)
            BUILD_JOBS_OPTION="-j$OPTARG";
        ;;
        l)
            BUILD_LLVM_CONF_OPTION="$BUILD_LLVM_CONF_OPTION $OPTARG";
        ;;
        m)
            BUILD_LLVM_CMAKE_OPTION="$BUILD_LLVM_CMAKE_OPTION $OPTARG";
        ;;
        n)
            echo $LLVM_VERSION;
            exit 0;
        ;;
        g)
            BUILD_TARGET_CONF_OPTION="$BUILD_TARGET_CONF_OPTION $OPTARG";
        ;;
        ?)  #当有不认识的选项的时候arg为?
            echo "unkonw argument detected";
            exit 1;
        ;;
    esac
done

if [ $BUILD_DOWNLOAD_ONLY -eq 0 ]; then
    mkdir -p "$PREFIX_DIR"
    PREFIX_DIR="$( cd "$PREFIX_DIR" && pwd )";
fi

# ======================= 转到脚本目录 ======================= 
WORKING_DIR="$PWD";

# ======================= 检测python =======================

# ======================= 如果是64位系统且没安装32位的开发包，则编译要gcc加上 --disable-multilib 参数, 不生成32位库 ======================= 
SYS_LONG_BIT=$(getconf LONG_BIT);
 
# ======================================= 搞起 ======================================= 
echo -e "\\033[31;1mcheck complete.\\033[39;49;0m"
 
# ======================= 准备环境, 把库和二进制目录导入，否则编译会找不到库或文件 ======================= 
echo "WORKING_DIR               = $WORKING_DIR";
echo "PREFIX_DIR                = $PREFIX_DIR";
echo "BUILD_TARGET_COMPOMENTS   = $BUILD_TARGET_COMPOMENTS";
echo "BUILD_LLVM_CONF_OPTION    = $BUILD_LLVM_CONF_OPTION";
echo "BUILD_LLVM_CMAKE_OPTION   = $BUILD_LLVM_CMAKE_OPTION";
echo "BUILD_OTHER_CONF_OPTION   = $BUILD_OTHER_CONF_OPTION";
echo "CHECK_INFO_SLEEP          = $CHECK_INFO_SLEEP";
echo "SYS_LONG_BIT              = $SYS_LONG_BIT";
echo "CC                        = $CC";
echo "CXX                       = $CXX";
echo "BUILD_USE_LD              = $BUILD_USE_LD";

 
echo -e "\\033[32;1mnotice: now, sleep for $CHECK_INFO_SLEEP seconds.\\033[39;49;0m"; 
sleep $CHECK_INFO_SLEEP
  
# ======================= 关闭交换分区，否则就爽死了 ======================= 
if [ $BUILD_DOWNLOAD_ONLY -eq 0 ]; then
    swapoff -a ;
fi

# ======================= 统一的包检查和下载函数 =======================
if [ ! -e "llvm-project-$LLVM_VERSION" ]; then
    git clone -b "llvmorg-$LLVM_VERSION" --depth 1 "https://github.com/llvm/llvm-project.git" "llvm-project-$LLVM_VERSION";
fi

if [ ! -e "llvm-project-$LLVM_VERSION/.git" ]; then
    echo -e "\\033[31;1mgit clone https://github.com/llvm/llvm-project.git failed.\\033[39;49;0m";
    exit 1;
fi

if [ ! -e "libedit-$LIBEDIT_VERSION.tar.gz" ]; then
    wget "http://thrysoee.dk/editline/libedit-$LIBEDIT_VERSION.tar.gz";
    if [ $? -ne 0 ]; then
        rm -f "libedit-$LIBEDIT_VERSION.tar.gz";
        echo -e "\\033[31;1mDownload from http://thrysoee.dk/editline/libedit-$LIBEDIT_VERSION.tar.gz failed.\\033[39;49;0m";
        exit 1;
    fi
fi

if [ $BUILD_DOWNLOAD_ONLY -ne 0 ]; then
    return 0;
fi

# Build libedit
echo "Building libedit...";
if [ -e "libedit-$LIBEDIT_VERSION" ] ; then
    rm -rf "libedit-$LIBEDIT_VERSION";
fi
tar -axvf "libedit-$LIBEDIT_VERSION.tar.gz";
cd "libedit-$LIBEDIT_VERSION";
./configure --prefix=$PREFIX_DIR --with-pic=yes;
make -j4 install;
cd "$WORKING_DIR";

export LLVM_DIR="$PWD/llvm-project-$LLVM_VERSION";

export STAGE_BUILD_CMAKE_OPTION="";

function build_llvm_toolchain() {
    STAGE_BUILD_EXT_CMAKE_OPTION="";
    STAGE_BUILD_EXT_COMPILER_FLAGS="-DCMAKE_INSTALL_RPATH_USE_LINK_PATH=YES";
    if [ ! -z "$CC" ]; then
        STAGE_BUILD_EXT_CMAKE_OPTION="$STAGE_BUILD_EXT_CMAKE_OPTION -DCMAKE_C_COMPILER=$CC";
    fi
    if [ ! -z "$CXX" ]; then
        STAGE_BUILD_EXT_CMAKE_OPTION="$STAGE_BUILD_EXT_CMAKE_OPTION -DCMAKE_CXX_COMPILER=$CXX";
    fi
    if [ ! -z "$BUILD_USE_LD" ]; then
        CMAKE_RUNTIME_LINKER_FLAGS="$CMAKE_RUNTIME_LINKER_FLAGS -DLLVM_USE_LINKER=$BUILD_USE_LD";
    fi

    if [ ! -z "$CMAKE_CXX_FLAGS" ]; then
        if [ "${CMAKE_CXX_FLAGS:0:1}" == " " ]; then
            CMAKE_CXX_FLAGS="${CMAKE_CXX_FLAGS:1}";
        fi
        STAGE_BUILD_EXT_COMPILER_FLAGS="$STAGE_BUILD_EXT_COMPILER_FLAGS -DCMAKE_CXX_FLAGS='$CMAKE_CXX_FLAGS'";
    fi
    if [ ! -z "$CMAKE_C_FLAGS" ]; then
        if [ "${CMAKE_C_FLAGS:0:1}" == " " ]; then
            CMAKE_C_FLAGS="${CMAKE_C_FLAGS:1}";
        fi
        STAGE_BUILD_EXT_COMPILER_FLAGS="$STAGE_BUILD_EXT_COMPILER_FLAGS -DCMAKE_C_FLAGS='$CMAKE_C_FLAGS'";
    fi
    if [ ! -z "$CMAKE_RUNTIME_LINKER_FLAGS" ]; then
        if [ "${CMAKE_RUNTIME_LINKER_FLAGS:0:1}" == " " ]; then
            CMAKE_RUNTIME_LINKER_FLAGS="${CMAKE_RUNTIME_LINKER_FLAGS:1}";
        fi
        STAGE_BUILD_EXT_COMPILER_FLAGS="$STAGE_BUILD_EXT_COMPILER_FLAGS -DCMAKE_EXE_LINKER_FLAGS='$CMAKE_RUNTIME_LINKER_FLAGS' -DCMAKE_MODULE_LINKER_FLAGS='$CMAKE_RUNTIME_LINKER_FLAGS' -DCMAKE_SHARED_LINKER_FLAGS='$CMAKE_RUNTIME_LINKER_FLAGS'";
    fi

    which ninja > /dev/null 2>&1;
    if [ $? -eq 0 ]; then
        BUILD_WITH_NINJA="-G Ninja";
    else
        which ninja-build > /dev/null 2>&1;
        if [ $? -eq 0 ]; then
            BUILD_WITH_NINJA="-G Ninja";
        else
            BUILD_WITH_NINJA="";
        fi
    fi

    # ready to build 
    # if [ ! -e "$STAGE_BUILD_PREFIX_DIR/bin/llvm-config" ]; then
    cd "$LLVM_DIR";
    # clean build cache
    if [ -e "/dev/shm/build-install-llvm/build_stage_$STAGE_BUILD_STEP" ]; then
        rm -rf "/dev/shm/build-install-llvm/build_stage_$STAGE_BUILD_STEP";
    fi
    if [ -e "$LLVM_DIR/build_stage_$STAGE_BUILD_STEP" ]; then
        rm -rf "$LLVM_DIR/build_stage_$STAGE_BUILD_STEP";
    fi
    CHECK_AVAILABLE_MEMORY=$(cat /proc/meminfo | grep MemAvailable | awk '{print $2}');
    # Use memory disk to build if we have enough memory(16GB)
    if [ ! -z "$CHECK_AVAILABLE_MEMORY" ]; then
        if [ $CHECK_AVAILABLE_MEMORY -gt 16777216 ]; then
            mkdir -p "/dev/shm/build-install-llvm/build_stage_$STAGE_BUILD_STEP";
            ln -s "/dev/shm/build-install-llvm/build_stage_$STAGE_BUILD_STEP" "$LLVM_DIR/build_stage_$STAGE_BUILD_STEP";
        fi
    fi
    if [ ! -e "$LLVM_DIR/build_stage_$STAGE_BUILD_STEP" ]; then
        mkdir -p "$LLVM_DIR/build_stage_$STAGE_BUILD_STEP" ;
    fi
    cd "$LLVM_DIR/build_stage_$STAGE_BUILD_STEP" ;
    echo "cmake $LLVM_DIR/llvm $BUILD_WITH_NINJA -DCMAKE_INSTALL_PREFIX=$STAGE_BUILD_PREFIX_DIR -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_FIND_ROOT_PATH=$PREFIX_DIR $BUILD_LLVM_LLVM_OPTION $STAGE_BUILD_CMAKE_OPTION $STAGE_BUILD_EXT_CMAKE_OPTION $STAGE_BUILD_EXT_COMPILER_FLAGS -DLLVM_ENABLE_PROJECTS=$BUILD_TARGET_COMPOMENTS";
    cmake "$LLVM_DIR/llvm" $BUILD_WITH_NINJA -DCMAKE_INSTALL_PREFIX=$STAGE_BUILD_PREFIX_DIR -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_FIND_ROOT_PATH=$PREFIX_DIR $BUILD_LLVM_LLVM_OPTION $STAGE_BUILD_CMAKE_OPTION $STAGE_BUILD_EXT_CMAKE_OPTION $STAGE_BUILD_EXT_COMPILER_FLAGS "-DLLVM_ENABLE_PROJECTS=$BUILD_TARGET_COMPOMENTS";
    if [ 0 -ne $? ]; then
        echo -e "\\033[31;1mError: build llvm $STAGE_BUILD_PREFIX_DIR failed when run cmake.\\033[39;49;0m";
        return 1;
    fi

    # 这里会消耗茫茫多内存，所以尝试先开启多进程编译，失败之后降级到单进程
    cmake --build . $BUILD_JOBS_OPTION --config $BUILD_TYPE ;
    cmake --build . -j2 --config $BUILD_TYPE ;
    cmake --build . --config $BUILD_TYPE ;
    if [ 0 -ne $? ]; then
        echo -e "\\033[31;1mError: build llvm $STAGE_BUILD_PREFIX_DIR failed when run cmake --build ..\\033[39;49;0m";
        return 1;
    fi

    # llvm script bug
    # if [ ! -e "lib/python2.7" ]; then
    #     mkdir -p lib/python2.7 ;
    # fi
    cmake --build . --target install;
    if [ 0 -ne $? ]; then
        echo -e "\\033[31;1mError: build llvm $STAGE_BUILD_PREFIX_DIR failed when install.\\033[39;49;0m";
        return 1;
    fi

    if [ -e "/dev/shm/build-install-llvm/build_stage_$STAGE_BUILD_STEP" ]; then
        cd ..;
        rm -rf "/dev/shm/build-install-llvm/build_stage_$STAGE_BUILD_STEP";
        rm -rf "$LLVM_DIR/build_stage_$STAGE_BUILD_STEP";
    fi
    return 0 ;
}

export STAGE_BUILD_STEP=1;
STAGE_BUILD_PREFIX_DIR_1="$PREFIX_DIR-stage-1";
export STAGE_BUILD_PREFIX_DIR="$STAGE_BUILD_PREFIX_DIR_1";
build_llvm_toolchain ;

if [ 0 -ne $? ] ; then
    if [ $BUILD_DOWNLOAD_ONLY -eq 0 ]; then
        echo -e "\\033[31;1mError: build llvm $STAGE_BUILD_PREFIX_DIR failed on stage 1.\\033[39;49;0m";
        exit 1;
    fi
fi

echo -e "\\033[32;1mbuild llvm $STAGE_BUILD_PREFIX_DIR success on stage 1.\\033[39;49;0m";

cd "$WORKING_DIR";

CXX_ABI_PATH=$(find "$STAGE_BUILD_PREFIX_DIR/include" -name "cxxabi.h");
if [ ! -z "$CXX_ABI_PATH" ]; then
    # CXX_ABI_DIR=${CXX_ABI_PATH%%/cxxabi.h};
    # export LDFLAGS="$LDFLAGS -lc++ -lc++abi";
    # export STAGE_BUILD_CMAKE_OPTION="$STAGE_BUILD_CMAKE_OPTION -DLIBCXX_CXX_ABI=libcxxabi -DLIBCXX_CXX_ABI_INCLUDE_PATHS=$CXX_ABI_DIR";
    # CMAKE_CXX_FLAGS="$CMAKE_CXX_FLAGS -stdlib=libc++";
    export STAGE_BUILD_CMAKE_OPTION="$STAGE_BUILD_CMAKE_OPTION -DLLVM_ENABLE_LIBCXX=ON" ;
fi
# export STAGE_BUILD_CMAKE_OPTION="$STAGE_BUILD_CMAKE_OPTION -DLLVM_TOOLS_BINARY_DIR=$STAGE_BUILD_PREFIX_DIR/bin";
export STAGE_BUILD_CMAKE_OPTION="$STAGE_BUILD_CMAKE_OPTION -DLLVM_ENABLE_MODULES=ON -DLLVM_ENABLE_LTO=ON";


if [ "x$BUILD_TARGET_COMPOMENTS" == "xall" ]; then
    export STAGE_BUILD_CMAKE_OPTION="$STAGE_BUILD_CMAKE_OPTION -DCOMPILER_RT_USE_BUILTINS_LIBRARY=ON -DLIBUNWIND_USE_COMPILER_RT=ON -DLIBCXX_USE_COMPILER_RT=ON -DLIBCXXABI_US    E_COMPILER_RT=ON -DLIBCXXABI_USE_LLVM_UNWINDER=ON";
    BUILD_TARGET_HAS_COMPILER_RT=1;
    BUILD_TARGET_HAS_LIBCXX=1;
    BUILD_TARGET_HAS_LIBCXX_ABI=1;
    BUILD_TARGET_HAS_LIBUNWIND=1;
    BUILD_TARGET_HAS_LLD=1;
else
    BUILD_TARGET_HAS_COMPILER_RT=0;
    BUILD_TARGET_HAS_LIBCXX=0;
    BUILD_TARGET_HAS_LIBCXX_ABI=0;
    BUILD_TARGET_HAS_LIBUNWIND=0;
    BUILD_TARGET_HAS_LLD=0;
    for BUILD_TARGET in ${BUILD_TARGET_COMPOMENTS//;/ }; do
        if [ "compiler-rt" == "$BUILD_TARGET" ]; then
            BUILD_TARGET_HAS_COMPILER_RT=1;
        elif [ "libcxx" == "$BUILD_TARGET" ]; then
            BUILD_TARGET_HAS_LIBCXX=1;
        elif [ "libcxxabi" == "$BUILD_TARGET" ]; then
            BUILD_TARGET_HAS_LIBCXX_ABI=1;
        elif [ "libunwind" == "$BUILD_TARGET" ]; then
            BUILD_TARGET_HAS_LIBUNWIND=1;
        elif [ "lld" == "$BUILD_TARGET" ]; then
            BUILD_TARGET_HAS_LLD=1;
        fi
    done

    if [ $BUILD_TARGET_HAS_COMPILER_RT -ne 0 ] && [ $BUILD_TARGET_HAS_LIBCXX -ne 0 ] && [ $BUILD_TARGET_HAS_LIBCXX_ABI -ne 0 ] && [ $BUILD_TARGET_HAS_LIBUNWIND -ne 0 ] && [ $BUILD_TARGET_HAS_LLD -ne 0 ]; then
        export STAGE_BUILD_CMAKE_OPTION="$STAGE_BUILD_CMAKE_OPTION -DCOMPILER_RT_USE_BUILTINS_LIBRARY=ON";
    fi

    if [ $BUILD_TARGET_HAS_COMPILER_RT -ne 0 ] && [ $BUILD_TARGET_HAS_LIBUNWIND -ne 0 ]; then
        export STAGE_BUILD_CMAKE_OPTION="$STAGE_BUILD_CMAKE_OPTION -DLIBUNWIND_USE_COMPILER_RT=ON";
    fi

    if [ $BUILD_TARGET_HAS_COMPILER_RT -ne 0 ] && [ $BUILD_TARGET_HAS_LIBCXX -ne 0 ]; then
        export STAGE_BUILD_CMAKE_OPTION="$STAGE_BUILD_CMAKE_OPTION -DLIBCXX_USE_COMPILER_RT=ON";
    fi

    if [ $BUILD_TARGET_HAS_COMPILER_RT -ne 0 ] && [ $BUILD_TARGET_HAS_LIBCXX_ABI -ne 0 ]; then
        export STAGE_BUILD_CMAKE_OPTION="$STAGE_BUILD_CMAKE_OPTION -DLIBCXXABI_USE_COMPILER_RT=ON";
    fi

    if [ $BUILD_TARGET_HAS_LIBUNWIND -ne 0 ] && [ $BUILD_TARGET_HAS_LIBCXX_ABI -ne 0 ]; then
        export STAGE_BUILD_CMAKE_OPTION="$STAGE_BUILD_CMAKE_OPTION -DLIBCXXABI_USE_LLVM_UNWINDER=ON";
    fi
fi

# ================================== 自举编译 ==================================

# ================================== 环境覆盖 ==================================
export LD_LIBRARY_PATH=$STAGE_BUILD_PREFIX_DIR/lib:$LD_LIBRARY_PATH
export PATH=$STAGE_BUILD_PREFIX_DIR/bin:$PATH

echo "add $STAGE_BUILD_PREFIX_DIR/bin to PTAH";
echo "add $STAGE_BUILD_PREFIX_DIR/lib to LD_LIBRARY_PATH";

export CC=$STAGE_BUILD_PREFIX_DIR/bin/clang ;
export CXX=$STAGE_BUILD_PREFIX_DIR/bin/clang++ ;
export AR="$STAGE_BUILD_PREFIX_DIR/bin/llvm-ar" ;
export AS="$STAGE_BUILD_PREFIX_DIR/bin/llvm-as" ;
export NM="$STAGE_BUILD_PREFIX_DIR/bin/llvm-nm" ;
export RANDLIB="$STAGE_BUILD_PREFIX_DIR/bin/llvm-ranlib" ;
export OBJCOPY="$STAGE_BUILD_PREFIX_DIR/bin/llvm-objcopy" ;
export OBJDUMP="$STAGE_BUILD_PREFIX_DIR/bin/llvm-objdump" ;
export STRIP="$STAGE_BUILD_PREFIX_DIR/bin/llvm-strip" ;
export STAGE_BUILD_CMAKE_OPTION="$STAGE_BUILD_CMAKE_OPTION -DCMAKE_AR=$AR -DCMAKE_RANLIB=$RANDLIB -DCMAKE_NM=$NM -DCMAKE_OBJCOPY=$OBJCOPY -DCMAKE_OBJDUMP=$OBJDUMP -DCMAKE_STRIP=$STRIP";

CHECK_IS_WINDOWS=0;
CHECK_IS_MACOS=0;
CHECK_IS_UNIX=0;
"$CC" -dM -E - < /dev/null | grep -i _win32 ;
if [ $? -eq 0 ]; then
    CHECK_IS_WINDOWS=1;
fi
"$CC" -dM -E - < /dev/null | grep -i _win64 ;
if [ $? -eq 0 ]; then
    CHECK_IS_WINDOWS=1;
fi
"$CC" -dM -E - < /dev/null | grep -i __linux ;
if [ $? -eq 0 ]; then
    CHECK_IS_UNIX=1;
fi
"$CC" -dM -E - < /dev/null | grep -i __unix ;
if [ $? -eq 0 ]; then
    CHECK_IS_UNIX=1;
fi
"$CC" -dM -E - < /dev/null | grep -i __apple ;
if [ $? -eq 0 ]; then
    CHECK_IS_MACOS=1;
fi


if [ $CHECK_IS_UNIX -ne 0 ] && [ -e "$STAGE_BUILD_PREFIX_DIR/bin/ld.lld" ]; then
    export LD="$STAGE_BUILD_PREFIX_DIR/bin/ld.lld" ;
    export STAGE_BUILD_CMAKE_OPTION="$STAGE_BUILD_CMAKE_OPTION -DLLVM_ENABLE_LLD=YES -DCMAKE_LINKER=$LD" ;
    LD_LOADER_SCRIPT="export LD=\"$LD\"";
elif [ $CHECK_IS_MACOS -ne 0 ] && [ -e "$STAGE_BUILD_PREFIX_DIR/bin/ld64.lld" ]; then
    export LD="$STAGE_BUILD_PREFIX_DIR/bin/ld64.lld" ;
    export STAGE_BUILD_CMAKE_OPTION="$STAGE_BUILD_CMAKE_OPTION -DLLVM_ENABLE_LLD=YES -DCMAKE_LINKER=$LD" ;
    LD_LOADER_SCRIPT="export LD=\"$LD\"";
elif [ $CHECK_IS_WINDOWS -ne 0 ] && [ -e "$STAGE_BUILD_PREFIX_DIR/bin/lld-link" ]; then
    export LD="$STAGE_BUILD_PREFIX_DIR/bin/lld-link" ;
    export STAGE_BUILD_CMAKE_OPTION="$STAGE_BUILD_CMAKE_OPTION -DLLVM_ENABLE_LLD=YES -DCMAKE_LINKER=$LD" ;
    LD_LOADER_SCRIPT="export LD=\"$LD\"";
elif [ -e "$STAGE_BUILD_PREFIX_DIR/bin/lld" ]; then
    export LD="$STAGE_BUILD_PREFIX_DIR/bin/lld" ;
    export STAGE_BUILD_CMAKE_OPTION="$STAGE_BUILD_CMAKE_OPTION -DLLVM_ENABLE_LLD=YES -DCMAKE_LINKER=$LD" ;
    LD_LOADER_SCRIPT="export LD=\"$LD\"";
fi
BUILD_USE_LD="";

# 自举编译， 脱离对gcc的依赖
# export STAGE_BUILD_PREFIX_DIR="$PREFIX_DIR";
export STAGE_BUILD_STEP=2;
export STAGE_BUILD_PREFIX_DIR="$PREFIX_DIR";
build_llvm_toolchain ;

if [ ! -e "$PREFIX_DIR/bin/clang" ] ; then
    if [ $BUILD_DOWNLOAD_ONLY -eq 0 ]; then
        echo -e "\\033[31;1mError: build llvm $STAGE_BUILD_PREFIX_DIR failed on stage 2.\\033[39;49;0m";
        exit 1;
    fi
fi

rm -rf "$STAGE_BUILD_PREFIX_DIR_1";

if [ $BUILD_DOWNLOAD_ONLY -eq 0 ]; then

    DEP_COMPILER_HOME="$(dirname "$(dirname "$ORIGIN_COMPILER_CXX")")";
    echo "#!/bin/bash

if [ \"x\$GCC_HOME_DIR\" == \"x\" ]; then
    GCC_HOME_DIR=\"$DEP_COMPILER_HOME\";
fi" > "$PREFIX_DIR/load-llvm-envs.sh" ;

    echo '
LLVM_HOME_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )";

if [ "x/" == "x$GCC_HOME_DIR" ] || [ "x/usr" == "x$GCC_HOME_DIR" ] || [ "x/usr/local" == "x$GCC_HOME_DIR" ] || [ "x$LLVM_HOME_DIR" == "x$GCC_HOME_DIR" ]; then
    if [ "x$LD_LIBRARY_PATH" == "x" ]; then
        export LD_LIBRARY_PATH="$LLVM_HOME_DIR/lib" ;
    else
        export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$LLVM_HOME_DIR/lib:$LLVM_HOME_DIR/lib64" ;
    fi
    
    export PATH="$LLVM_HOME_DIR/bin:$LLVM_HOME_DIR/libexec:$PATH" ;
else
    if [ "x$LD_LIBRARY_PATH" == "x" ]; then
        export LD_LIBRARY_PATH="$LLVM_HOME_DIR/lib:$GCC_HOME_DIR/lib:$GCC_HOME_DIR/lib64" ;
    else
        export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$LLVM_HOME_DIR/lib:$GCC_HOME_DIR/lib:$GCC_HOME_DIR/lib64" ;
    fi
    
    export PATH="$LLVM_HOME_DIR/bin:$LLVM_HOME_DIR/libexec:$GCC_HOME_DIR/bin:$PATH" ;
fi
export CC="$LLVM_HOME_DIR/bin/clang" ;
export CXX="$LLVM_HOME_DIR/bin/clang++" ;
export AR="$LLVM_HOME_DIR/bin/llvm-ar" ;
export AS="$LLVM_HOME_DIR/bin/llvm-as" ;
$LD_LOADER_SCRIPT" ;
export RANLIB="$LLVM_HOME_DIR/bin/llvm-ranlib" ;
export NM="$LLVM_HOME_DIR/bin/llvm-nm" ;
export STRIP="$LLVM_HOME_DIR/bin/llvm-strip" ;
export OBJCOPY="$LLVM_HOME_DIR/bin/llvm-objcopy" ;
export OBJDUMP="$LLVM_HOME_DIR/bin/llvm-objdump" ;
export READELF="$LLVM_HOME_DIR/bin/llvm-readelf" ;

# Maybe need add --gcc-toolchain=$GCC_HOME_DIR to compile options
"$@"
' >> "$PREFIX_DIR/load-llvm-envs.sh" ;
    chmod +x "$PREFIX_DIR/load-llvm-envs.sh";

    LLVM_CONFIG_PATH="$PREFIX_DIR/bin/llvm-config";
    echo -e "\\033[33;1mAddition, run the cmds below to add environment var(s).\\033[39;49;0m";
    echo -e "\\033[31;1mexport PATH=$($LLVM_CONFIG_PATH --bindir):$PATH\\033[39;49;0m";
    echo -e "\\033[33;1mBuild LLVM done.\\033[39;49;0m";
    echo "";
    echo -e "\\033[32;1mSample flags to build exectable file:.\\033[39;49;0m";
    echo -e "\\033[35;1m\tCC=$STAGE_BUILD_PREFIX_DIR/bin/clang\\033[39;49;0m";
    echo -e "\\033[35;1m\tCXX=$STAGE_BUILD_PREFIX_DIR/bin/clang++\\033[39;49;0m";
    echo -e "\\033[35;1m\tCFLAGS=$($LLVM_CONFIG_PATH --cflags) -std=libc++\\033[39;49;0m";
    if [ ! -z "$(find $($LLVM_CONFIG_PATH --libdir) -name libc++abi.so)" ]; then
        echo -e "\\033[35;1m\tCXXFLAGS=$($LLVM_CONFIG_PATH --cxxflags) -std=libc++\\033[39;49;0m";
        echo -e "\\033[35;1m\tLDFLAGS=$($LLVM_CONFIG_PATH --ldflags) -lc++ -lc++abi\\033[39;49;0m";
    else
        echo -e "\\033[35;1m\tCXXFLAGS=$($LLVM_CONFIG_PATH --cxxflags)\\033[39;49;0m";
        echo -e "\\033[35;1m\tLDFLAGS=$($LLVM_CONFIG_PATH --ldflags)\\033[39;49;0m";
    fi
    echo -e "\\033[35;1m\tMaybe need add --gcc-toolchain=$GCC_HOME_DIR to compile options\\033[39;49;0m";
else
    echo -e "\\033[35;1mDownloaded: $BUILD_TARGET_COMPOMENTS.\\033[39;49;0m";
fi

