#!/bin/sh
set -eux
: ${CLANG=14}
: ${MSAN_LIBDIR=..}
: ${PARALLEL=$(nproc)}

export CC=clang-$CLANG CXX=clang++-$CLANG

if [ ! -f /etc/apt/sources.list.d/llvm-toolchain.list ]; then
    # Put the correct deb URL from https://apt.llvm.org/
    echo "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic main" | \
        sudo tee -a /etc/apt/sources.list.d/llvm-toolchain.list
    wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key|sudo apt-key add -
    sudo apt update
fi

sudo apt -o APT::Get::Assume-Yes=true install \
    clang-$CLANG libc++-$CLANG-dev libc++abi-$CLANG-dev automake
apt -o APT::Get::Assume-Yes=true source \
    llvm-toolchain-$CLANG libgnutls28-dev libnettle8 libidn2 libgmp10

cd llvm-toolchain-$CLANG-$CLANG.*/
mkdir -p libc++msan
cd libc++msan
cmake ../libcxx -DCMAKE_BUILD_TYPE=RelWithDebInfo -DLLVM_USE_SANITIZER=Memory
cmake --build . -- -j$PARALLEL
mkdir -p ../libc++abi
cd ../libc++abi
cmake ../libcxxabi -DCMAKE_BUILD_TYPE=RelWithDebInfo -DLLVM_USE_SANITIZER=Memory \
    -DLIBCXXABI_LIBCXX_INCLUDES=../libc++msan/include/c++/v1
cmake --build . -- -j$PARALLEL
cd ../..

export CFLAGS="-fno-omit-frame-pointer -O2 -g -fsanitize=memory"
export CXXFLAGS="$CFLAGS"
export LDFLAGS=-fsanitize=memory

cd gnutls28-*/
aclocal
automake --add-missing
test -f config.h ||
./configure --with-included-libtasn1 --with-included-unistring \
	    --without-p11-kit --disable-hardware-acceleration
make -j$PARALLEL
cd ..

cd nettle-*/
test -f config.h ||
./configure --disable-assembler
make -j$PARALLEL
cd ..

cd libidn2-*/
test -f config.h ||
./configure --enable-valgrind-tests=no
make -j$PARALLEL
cd ..

cd gmp-*/
test -f config.h ||
./configure --disable-assembly
make -j$PARALLEL
cd ..

copy_libs()
{
    cp -a "$@" llvm-toolchain-$CLANG-$CLANG*/libc++msan/lib/libc++.so* \
        llvm-toolchain-$CLANG-$CLANG*/libc++abi/lib/libc++abi.so* \
        gnutls28-*/lib/.libs/libgnutls.so* \
        nettle-*/.lib/lib*.so.* \
        gmp-*/.libs/libgmp.so* \
        libidn2-*/lib/.libs/libidn2.so* \
        "$MSAN_LIBDIR"
    
    cp -aL nettle-*/.lib/lib*.so "$MSAN_LIBDIR"
}

rm -f "$MSAN_LIBDIR"/*.so*
# If some links are broken, use copy_libs -L
copy_libs

cp -a llvm-toolchain-$CLANG-$CLANG*/libc++msan/include/c++/v1 "$MSAN_LIBDIR/include"
cp -a llvm-toolchain-$CLANG-$CLANG*/libcxxabi/include/*.h "$MSAN_LIBDIR/include"

set +x
msan_libs=`readlink -f "$MSAN_LIBDIR"`
echo "Use the following clang++ options:"
echo "-std=c++11 -stdlib=libc++ -lc++abi \\"
echo "-O2 -Wno-unused-command-line-argument \\"
echo "-L${msan_libs} \\"
echo "-I${msan_libs}/include \\"
echo "-Wl,-rpath,${msan_libs}"
echo "Note: -O2 is required (-O0 segfaults)!"
