#!/bin/bash -e # helpers pushd () { command pushd "$@" > /dev/null; } popd () { command popd "$@" > /dev/null; } DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" CPUS=$( cat /proc/cpuinfo | grep processor | wc -l ) cd "$DIR" # toolchain version TOOLCHAIN_VERSION=1 # package versions used GCC_VERSION=8.3.0 BINUTILS_VERSION=2.32 GDB_VERSION=8.2.1 CMAKE_VERSION=3.14.2 CPPCHECK_VERSION=1.87 LLVM_VERSION=8.0.0 SWIG_VERSION=3.0.12 # used only for LLVM compilation # check for installed dependencies DISTRO="$( egrep '^(VERSION_)?ID=' /etc/os-release | sort | cut -d '=' -f 2- | sed 's/"//g' | paste -s -d '-' )" case "$DISTRO" in debian-9) DEPS_MANAGER=apt-get DEPS_COMPILE=( coreutils gcc g++ build-essential make # generic build tools wget # used for archive download gnupg # used for archive signature verification tar gzip bzip2 xz-utils unzip # used for archive unpacking zlib1g-dev # zlib library used for all builds libexpat1-dev libipt-dev libbabeltrace-dev libbabeltrace-ctf-dev liblzma-dev python3-dev texinfo # for gdb libcurl4-openssl-dev # for cmake libreadline-dev # for cmake and llvm libffi-dev libxml2-dev # for llvm libedit-dev libpcre3-dev automake bison # for swig ) DEPS_RUN=( make # generic build tools tar gzip bzip2 xz-utils # used for archive unpacking zlib1g # zlib library used for all builds libexpat1 libipt1 libbabeltrace1 libbabeltrace-ctf1 liblzma5 python3 # for gdb libcurl3 # for cmake libreadline7 # for cmake and llvm libffi6 libxml2 # for llvm ) ;; debian-10) DEPS_MANAGER=apt-get DEPS_COMPILE=( coreutils gcc g++ build-essential make # generic build tools wget # used for archive download gnupg # used for archive signature verification tar gzip bzip2 xz-utils unzip # used for archive unpacking zlib1g-dev # zlib library used for all builds libexpat1-dev libipt-dev libbabeltrace-dev liblzma-dev python3-dev texinfo # for gdb libcurl4-openssl-dev # for cmake libreadline-dev # for cmake and llvm libffi-dev libxml2-dev # for llvm libedit-dev libpcre3-dev automake bison # for swig ) DEPS_RUN=( make # generic build tools tar gzip bzip2 xz-utils # used for archive unpacking zlib1g # zlib library used for all builds libexpat1 libipt2 libbabeltrace1 liblzma5 python3 # for gdb libcurl4 # for cmake libreadline7 # for cmake and llvm libffi6 libxml2 # for llvm ) ;; ubuntu-18.04) DEPS_MANAGER=apt-get DEPS_COMPILE=( coreutils gcc g++ build-essential make # generic build tools wget # used for archive download gnupg # used for archive signature verification tar gzip bzip2 xz-utils unzip # used for archive unpacking zlib1g-dev # zlib library used for all builds libexpat1-dev libipt-dev libbabeltrace-dev liblzma-dev python3-dev texinfo # for gdb libcurl4-openssl-dev # for cmake libreadline-dev # for cmake and llvm libffi-dev libxml2-dev # for llvm libedit-dev libpcre3-dev automake bison # for swig ) DEPS_RUN=( make # generic build tools tar gzip bzip2 xz-utils # used for archive unpacking zlib1g # zlib library used for all builds libexpat1 libipt1 libbabeltrace1 liblzma5 python3 # for gdb libcurl4 # for cmake libreadline7 # for cmake and llvm libffi6 libxml2 # for llvm ) ;; centos-7) DEPS_MANAGER=yum DEPS_COMPILE=( coreutils gcc gcc-c++ make # generic build tools wget # used for archive download gnupg2 # used for archive signature verification tar gzip bzip2 xz unzip # used for archive unpacking zlib-devel # zlib library used for all builds expat-devel libipt-devel libbabeltrace-devel xz-devel python3-devel texinfo # for gdb libcurl-devel # for cmake readline-devel # for cmake and llvm libffi-devel libxml2-devel # for llvm libedit-devel pcre-devel automake bison # for swig ) DEPS_RUN=( make # generic build tools tar gzip bzip2 xz # used for archive unpacking zlib # zlib library used for all builds expat libipt libbabeltrace xz-libs python3 # for gdb readline # for cmake and llvm libffi libxml2 # for llvm ) ;; *) echo "Unknown distribution: $DISTRO!" exit 1 ;; esac find_missing_dependencies () { local message="$1"; shift local missing="" while [ "$1" != "" ]; do if [ "$DEPS_MANAGER" == "apt-get" ]; then if ! dpkg -s $1 >/dev/null 2>/dev/null; then missing="$1 $missing" fi elif [ "$DEPS_MANAGER" == "yum" ]; then if ! yum list installed $1 >/dev/null 2>/dev/null; then missing="$1 $missing" fi else echo "Invalid package manager: $DEPS_MANAGER!" exit 1 fi shift done if [ "$missing" != "" ]; then echo "$message: $missing" exit 1 fi } find_missing_dependencies "Missing dependencies" ${DEPS_COMPILE[@]} find_missing_dependencies "All dependencies are installed, but the following runtime libraries were not found (they are probably invalid)" ${DEPS_RUN[@]} # check installation directory NAME=toolchain-v$TOOLCHAIN_VERSION PREFIX=/opt/$NAME mkdir -p $PREFIX >/dev/null 2>/dev/null || true if [ ! -d $PREFIX ] || [ ! -w $PREFIX ]; then echo "Please make sure that the directory '$PREFIX' exists and is writable by the current user!" echo echo "If unsure, execute these commands as root:" echo " mkdir $PREFIX && chown $USER:$USER $PREFIX" echo echo "Press when you have created the directory and granted permissions." # wait for the directory to be created while true; do read if [ ! -d $PREFIX ] || [ ! -w $PREFIX ]; then echo echo "You can't continue before you have created the directory and granted permissions!" echo echo "Press when you have created the directory and granted permissions." else break fi done fi # create archives directory mkdir -p archives # download all archives pushd archives if [ ! -f gcc-$GCC_VERSION.tar.gz ]; then wget https://ftp.gnu.org/gnu/gcc/gcc-$GCC_VERSION/gcc-$GCC_VERSION.tar.gz fi if [ ! -f binutils-$BINUTILS_VERSION.tar.gz ]; then wget https://ftp.gnu.org/gnu/binutils/binutils-$BINUTILS_VERSION.tar.gz fi if [ ! -f gdb-$GDB_VERSION.tar.gz ]; then wget https://ftp.gnu.org/gnu/gdb/gdb-$GDB_VERSION.tar.gz fi if [ ! -f cmake-$CMAKE_VERSION.tar.gz ]; then wget https://github.com/Kitware/CMake/releases/download/v$CMAKE_VERSION/cmake-$CMAKE_VERSION.tar.gz fi if [ ! -f swig-$SWIG_VERSION.tar.gz ]; then wget https://github.com/swig/swig/archive/rel-$SWIG_VERSION.tar.gz -O swig-$SWIG_VERSION.tar.gz fi if [ ! -f cppcheck-$CPPCHECK_VERSION.tar.gz ]; then wget https://github.com/danmar/cppcheck/archive/$CPPCHECK_VERSION.tar.gz -O cppcheck-$CPPCHECK_VERSION.tar.gz fi if [ ! -f llvm-$LLVM_VERSION.src.tar.xz ]; then wget https://releases.llvm.org/$LLVM_VERSION/llvm-$LLVM_VERSION.src.tar.xz wget https://releases.llvm.org/$LLVM_VERSION/cfe-$LLVM_VERSION.src.tar.xz wget https://releases.llvm.org/$LLVM_VERSION/lld-$LLVM_VERSION.src.tar.xz wget https://releases.llvm.org/$LLVM_VERSION/compiler-rt-$LLVM_VERSION.src.tar.xz wget https://releases.llvm.org/$LLVM_VERSION/clang-tools-extra-$LLVM_VERSION.src.tar.xz fi if [ ! -f pahole-gdb-master.zip ]; then wget https://github.com/PhilArmstrong/pahole-gdb/archive/master.zip -O pahole-gdb-master.zip fi # verify all archives # NOTE: Verification can fail if the archive is signed by another developer. I # haven't added commands to download all developer GnuPG keys because the # download is very slow. If the verification fails for you, figure out who has # signed the archive and download their public key instead. GPG="gpg --homedir .gnupg" KEYSERVER="hkp://keyserver.ubuntu.com" mkdir -p .gnupg chmod 700 .gnupg # verify gcc if [ ! -f gcc-$GCC_VERSION.tar.gz.sig ]; then wget https://ftp.gnu.org/gnu/gcc/gcc-$GCC_VERSION/gcc-$GCC_VERSION.tar.gz.sig fi # list of valid gcc gnupg keys: https://gcc.gnu.org/mirrors.html $GPG --keyserver $KEYSERVER --recv-keys 0xA328C3A2C3C45C06 $GPG --verify gcc-$GCC_VERSION.tar.gz.sig gcc-$GCC_VERSION.tar.gz # verify binutils if [ ! -f binutils-$BINUTILS_VERSION.tar.gz.sig ]; then wget https://ftp.gnu.org/gnu/binutils/binutils-$BINUTILS_VERSION.tar.gz.sig fi $GPG --keyserver $KEYSERVER --recv-keys 0xDD9E3C4F $GPG --verify binutils-$BINUTILS_VERSION.tar.gz.sig binutils-$BINUTILS_VERSION.tar.gz # verify gdb if [ ! -f gdb-$GDB_VERSION.tar.gz.sig ]; then wget https://ftp.gnu.org/gnu/gdb/gdb-$GDB_VERSION.tar.gz.sig fi $GPG --keyserver $KEYSERVER --recv-keys 0xFF325CF3 $GPG --verify gdb-$GDB_VERSION.tar.gz.sig gdb-$GDB_VERSION.tar.gz # verify cmake if [ ! -f cmake-$CMAKE_VERSION-SHA-256.txt ] || [ ! -f cmake-$CMAKE_VERSION-SHA-256.txt.asc ]; then wget https://github.com/Kitware/CMake/releases/download/v$CMAKE_VERSION/cmake-$CMAKE_VERSION-SHA-256.txt wget https://github.com/Kitware/CMake/releases/download/v$CMAKE_VERSION/cmake-$CMAKE_VERSION-SHA-256.txt.asc # Because CentOS 7 doesn't have the `--ignore-missing` flag for `sha256sum` # we filter out the missing files from the sums here manually. cat cmake-$CMAKE_VERSION-SHA-256.txt | grep "cmake-$CMAKE_VERSION.tar.gz" > cmake-$CMAKE_VERSION-SHA-256-filtered.txt fi $GPG --keyserver $KEYSERVER --recv-keys 0xC6C265324BBEBDC350B513D02D2CEF1034921684 sha256sum -c cmake-$CMAKE_VERSION-SHA-256-filtered.txt $GPG --verify cmake-$CMAKE_VERSION-SHA-256.txt.asc cmake-$CMAKE_VERSION-SHA-256.txt # verify llvm, cfe, lld, clang-tools-extra if [ ! -f llvm-$LLVM_VERSION.src.tar.xz.sig ]; then wget https://releases.llvm.org/$LLVM_VERSION/llvm-$LLVM_VERSION.src.tar.xz.sig wget https://releases.llvm.org/$LLVM_VERSION/cfe-$LLVM_VERSION.src.tar.xz.sig wget https://releases.llvm.org/$LLVM_VERSION/lld-$LLVM_VERSION.src.tar.xz.sig wget https://releases.llvm.org/$LLVM_VERSION/compiler-rt-$LLVM_VERSION.src.tar.xz.sig wget https://releases.llvm.org/$LLVM_VERSION/clang-tools-extra-$LLVM_VERSION.src.tar.xz.sig fi # list of valid llvm gnupg keys: https://releases.llvm.org/download.html $GPG --keyserver $KEYSERVER --recv-keys 0x345AD05D $GPG --verify llvm-$LLVM_VERSION.src.tar.xz.sig llvm-$LLVM_VERSION.src.tar.xz $GPG --verify cfe-$LLVM_VERSION.src.tar.xz.sig cfe-$LLVM_VERSION.src.tar.xz $GPG --verify lld-$LLVM_VERSION.src.tar.xz.sig lld-$LLVM_VERSION.src.tar.xz $GPG --verify compiler-rt-$LLVM_VERSION.src.tar.xz.sig compiler-rt-$LLVM_VERSION.src.tar.xz $GPG --verify clang-tools-extra-$LLVM_VERSION.src.tar.xz.sig clang-tools-extra-$LLVM_VERSION.src.tar.xz popd # create build directory mkdir -p build pushd build # compile gcc if [ ! -f $PREFIX/bin/gcc ]; then if [ -d gcc-$GCC_VERSION ]; then rm -rf gcc-$GCC_VERSION fi tar -xvf ../archives/gcc-$GCC_VERSION.tar.gz pushd gcc-$GCC_VERSION ./contrib/download_prerequisites mkdir build && pushd build # influenced by: https://buildd.debian.org/status/fetch.php?pkg=gcc-8&arch=amd64&ver=8.3.0-6&stamp=1554588545 ../configure -v \ --build=x86_64-linux-gnu \ --host=x86_64-linux-gnu \ --target=x86_64-linux-gnu \ --prefix=$PREFIX \ --disable-multilib \ --with-system-zlib \ --enable-checking=release \ --enable-languages=c,c++,fortran \ --enable-gold=yes \ --enable-ld=yes \ --enable-lto \ --enable-bootstrap \ --disable-vtable-verify \ --disable-werror \ --without-included-gettext \ --enable-threads=posix \ --enable-nls \ --enable-clocale=gnu \ --enable-libstdcxx-debug \ --enable-libstdcxx-time=yes \ --enable-gnu-unique-object \ --enable-libmpx \ --enable-plugin \ --enable-default-pie \ --with-target-system-zlib \ --with-tune=generic \ --without-cuda-driver #--program-suffix=$( printf "$GCC_VERSION" | cut -d '.' -f 1,2 ) \ make -j$CPUS # make -k check # run test suite make install popd && popd fi # activate toolchain export PATH=$PREFIX/bin:$PATH export LD_LIBRARY_PATH=$PREFIX/lib64 # compile binutils if [ ! -f $PREFIX/bin/ld.gold ]; then if [ -d binutils-$BINUTILS_VERSION ]; then rm -rf binutils-$BINUTILS_VERSION fi tar -xvf ../archives/binutils-$BINUTILS_VERSION.tar.gz pushd binutils-$BINUTILS_VERSION mkdir build && pushd build # influenced by: https://buildd.debian.org/status/fetch.php?pkg=binutils&arch=amd64&ver=2.32-7&stamp=1553247092 env \ CC=gcc \ CXX=g++ \ CFLAGS="-g -O2" \ CXXFLAGS="-g -O2" \ LDFLAGS="" \ ../configure \ --build=x86_64-linux-gnu \ --host=x86_64-linux-gnu \ --prefix=$PREFIX \ --enable-ld=default \ --enable-gold \ --enable-lto \ --enable-plugins \ --enable-shared \ --enable-threads \ --with-system-zlib \ --enable-deterministic-archives \ --disable-compressed-debug-sections \ --enable-new-dtags \ --disable-werror make -j$CPUS # make -k check # run test suite make install popd && popd fi # compile gdb if [ ! -f $PREFIX/bin/gdb ]; then if [ -d gdb-$GDB_VERSION ]; then rm -rf gdb-$GDB_VERSION fi tar -xvf ../archives/gdb-$GDB_VERSION.tar.gz pushd gdb-$GDB_VERSION mkdir build && pushd build # https://buildd.debian.org/status/fetch.php?pkg=gdb&arch=amd64&ver=8.2.1-2&stamp=1550831554&raw=0 env \ CC=gcc \ CXX=g++ \ CFLAGS="-g -O2 -fstack-protector-strong -Wformat -Werror=format-security" \ CXXFLAGS="-g -O2 -fstack-protector-strong -Wformat -Werror=format-security" \ CPPFLAGS="-Wdate-time -D_FORTIFY_SOURCE=2 -fPIC" \ LDFLAGS="-Wl,-z,relro" \ PYTHON="" \ ../configure \ --build=x86_64-linux-gnu \ --host=x86_64-linux-gnu \ --prefix=$PREFIX \ --disable-maintainer-mode \ --disable-dependency-tracking \ --disable-silent-rules \ --disable-gdbtk \ --disable-shared \ --without-guile \ --with-system-gdbinit=$PREFIX/etc/gdb/gdbinit \ --with-system-readline \ --with-expat \ --with-system-zlib \ --with-lzma \ --with-babeltrace \ --with-intel-pt \ --enable-tui \ --with-python=python3 make -j$CPUS make install popd && popd fi # install pahole if [ ! -d $PREFIX/share/pahole-gdb ]; then unzip ../archives/pahole-gdb-master.zip mv pahole-gdb-master $PREFIX/share/pahole-gdb fi # setup system gdbinit if [ ! -f $PREFIX/etc/gdb/gdbinit ]; then mkdir -p $PREFIX/etc/gdb cat >$PREFIX/etc/gdb/gdbinit <> build-flags.cmake echo 'set(CMAKE_USE_RELATIVE_PATHS ON CACHE BOOL "Use relative paths" FORCE)' >> build-flags.cmake echo 'set(CMAKE_C_FLAGS "-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2" CACHE STRING "C flags" FORCE)' >> build-flags.cmake echo 'set(CMAKE_CXX_FLAGS "-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2" CACHE STRING "C++ flags" FORCE)' >> build-flags.cmake echo 'set(CMAKE_SKIP_BOOTSTRAP_TEST ON CACHE BOOL "Skip BootstrapTest" FORCE)' >> build-flags.cmake echo 'set(BUILD_CursesDialog ON CACHE BOOL "Build curses GUI" FORCE)' >> build-flags.cmake mkdir build && pushd build ../bootstrap \ --prefix=$PREFIX \ --init=../build-flags.cmake \ --parallel=$CPUS \ --system-curl make -j$CPUS # make test # run test suite make install popd && popd fi # compile cppcheck if [ ! -f $PREFIX/bin/cppcheck ]; then if [ -d cppcheck-$CPPCHECK_VERSION ]; then rm -rf cppcheck-$CPPCHECK_VERSION fi tar -xvf ../archives/cppcheck-$CPPCHECK_VERSION.tar.gz pushd cppcheck-$CPPCHECK_VERSION env \ CC=gcc \ CXX=g++ \ PREFIX=$PREFIX \ CFGDIR=$PREFIX/share/cppcheck/cfg \ make -j$CPUS env \ CC=gcc \ CXX=g++ \ PREFIX=$PREFIX \ CFGDIR=$PREFIX/share/cppcheck/cfg \ make install popd fi # compile swig if [ ! -d swig-$SWIG_VERSION/install ]; then if [ -d swig-$SWIG_VERSION ]; then rm -rf swig-$SWIG_VERSION fi tar -xvf ../archives/swig-$SWIG_VERSION.tar.gz mv swig-rel-$SWIG_VERSION swig-$SWIG_VERSION pushd swig-$SWIG_VERSION ./autogen.sh mkdir build && pushd build ../configure --prefix=$DIR/build/swig-$SWIG_VERSION/install make -j$CPUS make install popd && popd fi # compile llvm if [ ! -f $PREFIX/bin/clang ]; then if [ -d llvm-$LLVM_VERSION ]; then rm -rf llvm-$LLVM_VERSION fi tar -xvf ../archives/llvm-$LLVM_VERSION.src.tar.xz mv llvm-$LLVM_VERSION.src llvm-$LLVM_VERSION tar -xvf ../archives/cfe-$LLVM_VERSION.src.tar.xz mv cfe-$LLVM_VERSION.src llvm-$LLVM_VERSION/tools/clang tar -xvf ../archives/lld-$LLVM_VERSION.src.tar.xz mv lld-$LLVM_VERSION.src/ llvm-$LLVM_VERSION/tools/lld tar -xvf ../archives/compiler-rt-$LLVM_VERSION.src.tar.xz mv compiler-rt-$LLVM_VERSION.src/ llvm-$LLVM_VERSION/projects/compiler-rt tar -xvf ../archives/clang-tools-extra-$LLVM_VERSION.src.tar.xz mv clang-tools-extra-$LLVM_VERSION.src/ llvm-$LLVM_VERSION/tools/clang/tools/extra pushd llvm-$LLVM_VERSION mkdir build && pushd build # activate swig export PATH=$DIR/build/swig-$SWIG_VERSION/install/bin:$PATH # influenced by: https://buildd.debian.org/status/fetch.php?pkg=llvm-toolchain-7&arch=amd64&ver=1%3A7.0.1%7E%2Brc2-1%7Eexp1&stamp=1541506173&raw=0 cmake .. \ -DGCC_INSTALL_PREFIX=$PREFIX \ -DCMAKE_C_COMPILER=$PREFIX/bin/gcc \ -DCMAKE_CXX_COMPILER=$PREFIX/bin/g++ \ -DCMAKE_CXX_LINK_FLAGS="-L$PREFIX/lib64 -Wl,-rpath,$PREFIX/lib64" \ -DCMAKE_INSTALL_PREFIX=$PREFIX \ -DCMAKE_BUILD_TYPE=RelWithDebInfo \ -DCMAKE_CXX_FLAGS_RELWITHDEBINFO="-O2 -DNDEBUG" \ -DCMAKE_CXX_FLAGS=' -fuse-ld=gold -fPIC -Wno-unused-command-line-argument -Wno-unknown-warning-option' \ -DCMAKE_C_FLAGS=' -fuse-ld=gold -fPIC -Wno-unused-command-line-argument -Wno-unknown-warning-option' \ -DLLVM_LINK_LLVM_DYLIB=ON \ -DLLVM_INSTALL_UTILS=ON \ -DLLVM_VERSION_SUFFIX= \ -DLLVM_BUILD_LLVM_DYLIB=ON \ -DLLVM_ENABLE_RTTI=ON \ -DLLVM_ENABLE_FFI=ON \ -DLLVM_BINUTILS_INCDIR=$PREFIX/include/ \ -DLLVM_USE_PERF=yes \ -DLIBCLANG_LIBRARY_VERSION=1 \ -DCLANG_ENABLE_BOOTSTRAP=ON make -j$CPUS make -j$CPUS check-clang # run clang test suite make -j$CPUS check-lld # run lld test suite make install popd && popd fi # create README if [ ! -f $PREFIX/README.md ]; then cat >$PREFIX/README.md <$PREFIX/activate <