FROM ubuntu:16.04

MAINTAINER Hugo Beauzée-Luyssen <hugo@beauzee.fr>

#FIXME: Remove vim once debuging is complete
# git-svn is only used to get sensible version numbers in clang version printouts
RUN apt-get update -qq && apt-get install -qqy \
    git wget bzip2 file libwine-development-dev unzip libtool pkg-config cmake \
    build-essential automake texinfo ragel yasm p7zip-full gettext autopoint \
    vim python git-svn


RUN git config --global user.name "VideoLAN Buildbot" && \
    git config --global user.email buildbot@videolan.org

WORKDIR /build

# release_50 should work just as well as the pinned hash, except for arm64 support.
# When cloning master and checking out a pinned old hash, we can't use --depth=1.
RUN git clone -b master https://github.com/llvm-mirror/llvm.git && \
    cd llvm/tools && \
    git clone -b master https://github.com/llvm-mirror/clang.git && \
    git clone -b master https://github.com/llvm-mirror/lld.git && \
    cd .. && \
    git checkout ee09c63e57866e6d47964f0094a7d884ae99b7ef && \
    git svn init https://llvm.org/svn/llvm-project/llvm/trunk && \
    git config svn-remote.svn.fetch :refs/remotes/origin/master && \
    git svn rebase -l && \
    cd tools/clang && \
    git checkout c778ea4b266d5fdcf3ab2d2509b19083bc43a91e && \
    git svn init https://llvm.org/svn/llvm-project/cfe/trunk && \
    git config svn-remote.svn.fetch :refs/remotes/origin/master && \
    git svn rebase -l && \
    cd ../lld && \
    git checkout ccf03952480f7b995f53263f0b529a57497230ff


#RUN cd llvm/projects && \
#    git clone -b release_40 --depth=1 https://github.com/llvm-mirror/libcxx.git && \
#    git clone -b release_40 --depth=1 https://github.com/llvm-mirror/libcxxabi.git && \
#    git clone https://github.com/llvm-mirror/libunwind.git -b release_40 --depth=1

RUN mkdir /build/patches

COPY patches/lld-*.patch /build/patches/

RUN cd llvm/tools/lld && \
    git am /build/patches/lld-*.patch

#RUN cd llvm/projects/libcxx && \
#    git am /build/patches/libcxx-*.patch

RUN mkdir /build/prefix

# Build LLVM
RUN cd llvm && mkdir build && cd build && cmake \
    -DCMAKE_INSTALL_PREFIX="/build/prefix" \
    -DCMAKE_BUILD_TYPE=Release \
    -DLLVM_ENABLE_ASSERTIONS=OFF \
    -DLLVM_ENABLE_EH=ON \
    -DLLVM_ENABLE_THREADS=ON \
    -DLLVM_ENABLE_RTTI=ON \
    -DLLVM_ENABLE_FFI=OFF \
    -DLLVM_ENABLE_SPHINX=OFF \
    -DLLVM_TARGETS_TO_BUILD="ARM;AArch64;X86" \
    -DCMAKE_CXX_FLAGS="-D_GNU_SOURCE -D_LIBCPP_HAS_NO_CONSTEXPR" \
    ../ && \
    make -j4 && \
    make install

RUN git clone --depth=1 git://git.code.sf.net/p/mingw-w64/mingw-w64 && \
    cd mingw-w64 && \
    git checkout 1e81200e88f19e440bbe646bfb410159ff8b0d51
COPY patches/mingw-*.patch /build/patches/
RUN cd mingw-w64 && \
    git am /build/patches/mingw-*.patch


#FIXME: Move this UP!
ENV TOOLCHAIN_PREFIX=/build/prefix
ENV PATH=$TOOLCHAIN_PREFIX/bin:$PATH

RUN cd mingw-w64/mingw-w64-headers && \
    for arch in armv7 aarch64 i686 x86_64; do \
      mkdir build-${arch} && cd build-${arch} && \
        ../configure --host=${arch}-w64-mingw32 --prefix=$TOOLCHAIN_PREFIX/${arch}-w64-mingw32 \
        --enable-secure-api && \
        make install && \
      cd ..; \
    done

# Install the usual $TUPLE-clang binary
RUN mkdir /build/wrappers
COPY wrappers/clang-target-wrapper /build/wrappers
RUN for arch in armv7 aarch64 i686 x86_64; do \
      for exec in clang clang++; do \
        cp wrappers/clang-target-wrapper $TOOLCHAIN_PREFIX/bin/${arch}-w64-mingw32-${exec}; \
      done; \
    done

#ENV CC=armv7-w64-mingw32-clang
#ENV CXX=armv7-w64-mingw32-clang++
ENV AR=llvm-ar 
ENV RANLIB=llvm-ranlib 
ENV LD=lld
ENV AS=llvm-as
ENV NM=llvm-nm

# Build mingw with our freshly built cross compiler
# Since somewhere between llvm 3.8 and 3.9, SVN rev 273373, git mirror commit
# d319cd64a4a15,, llvm-ar tries to detect the format (gnu vs bsd) of the
# existing .a file. For files generated by genlib, it seems to detect the
# wrong format, leading to lld later segfaulting when trying to link.
# Force the flag -format gnu to llvm-ar in this step to work around this issue.
RUN cd mingw-w64/mingw-w64-crt && \
    mkdir build-arm32 && cd build-arm32 && \
    CC=armv7-w64-mingw32-clang \
    AR="llvm-ar -format gnu" DLLTOOL=llvm-dlltool ../configure --host=armv7-w64-mingw32 --prefix=$TOOLCHAIN_PREFIX/armv7-w64-mingw32 \
        --disable-lib32 --disable-lib64 --enable-libarm32 && \
    make -j4 && make install && \
    cd .. && \
    mkdir build-arm64 && cd build-arm64 && \
    CC=aarch64-w64-mingw32-clang \
    AR="llvm-ar -format gnu" DLLTOOL=llvm-dlltool ../configure --host=aarch64-w64-mingw32 --prefix=$TOOLCHAIN_PREFIX/aarch64-w64-mingw32 \
        --disable-lib32 --disable-lib64 --enable-libarm64 && \
    make -j4 && make install && \
    cd .. && \
    mkdir build-i686 && cd build-i686 && \
    CC=i686-w64-mingw32-clang \
    AR="llvm-ar -format gnu" DLLTOOL=llvm-dlltool ../configure --host=i686-w64-mingw32 --prefix=$TOOLCHAIN_PREFIX/i686-w64-mingw32 \
        --enable-lib32 --disable-lib64 && \
    make -j4 && make install && \
    cd .. && \
    mkdir build-x86_64 && cd build-x86_64 && \
    CC=x86_64-w64-mingw32-clang \
    AR="llvm-ar -format gnu" DLLTOOL=llvm-dlltool ../configure --host=x86_64-w64-mingw32 --prefix=$TOOLCHAIN_PREFIX/x86_64-w64-mingw32 \
        --enable-lib64 --disable-lib32 && \
    make -j4 && make install && \
    cd ..

#RUN cp /build/mingw-w64/mingw-w64-libraries/winpthreads/include/* $MINGW_PREFIX/include/

RUN git clone -b master https://github.com/llvm-mirror/compiler-rt.git && \
    cd compiler-rt && \
    git checkout 8293838e866814d904640f6359954d00852f2421

# Manually build compiler-rt as a standalone project
RUN cd compiler-rt && \
    mkdir build-armv7 && cd build-armv7 && cmake \
    -DCMAKE_C_COMPILER=armv7-w64-mingw32-clang \
    -DCMAKE_SYSTEM_NAME=Windows \
    -DCMAKE_AR=$TOOLCHAIN_PREFIX/bin/$AR \
    -DCMAKE_RANLIB=$TOOLCHAIN_PREFIX/bin/$RANLIB \
    -DCMAKE_C_COMPILER_WORKS=1 \
    -DLLVM_CONFIG_PATH=$TOOLCHAIN_PREFIX/bin/llvm-config \
    -DCMAKE_C_COMPILER_TARGET=armv7-windows-gnu \
    -DCOMPILER_RT_DEFAULT_TARGET_ONLY=TRUE \
    ../lib/builtins && \
    make -j4 && \
    mkdir -p /build/prefix/lib/clang/6.0.0/lib/windows && \
    cp lib/windows/libclang_rt.builtins-armv7.a /build/prefix/lib/clang/6.0.0/lib/windows/libclang_rt.builtins-arm.a && \
    cd .. && \
    mkdir build-aarch64 && cd build-aarch64 && cmake \
    -DCMAKE_C_COMPILER=aarch64-w64-mingw32-clang \
    -DCMAKE_SYSTEM_NAME=Windows \
    -DCMAKE_AR=$TOOLCHAIN_PREFIX/bin/$AR \
    -DCMAKE_RANLIB=$TOOLCHAIN_PREFIX/bin/$RANLIB \
    -DCMAKE_C_COMPILER_WORKS=1 \
    -DLLVM_CONFIG_PATH=$TOOLCHAIN_PREFIX/bin/llvm-config \
    -DCMAKE_C_COMPILER_TARGET=aarch64-windows-gnu \
    -DCOMPILER_RT_DEFAULT_TARGET_ONLY=TRUE \
    ../lib/builtins && \
    make -j4 && \
    mkdir -p /build/prefix/lib/clang/6.0.0/lib/windows && \
    cp lib/windows/libclang_rt.builtins-aarch64.a /build/prefix/lib/clang/6.0.0/lib/windows && \
    cd .. && \
    mkdir build-i686 && cd build-i686 && cmake \
    -DCMAKE_C_COMPILER=i686-w64-mingw32-clang \
    -DCMAKE_SYSTEM_NAME=Windows \
    -DCMAKE_AR=$TOOLCHAIN_PREFIX/bin/$AR \
    -DCMAKE_RANLIB=$TOOLCHAIN_PREFIX/bin/$RANLIB \
    -DCMAKE_C_COMPILER_WORKS=1 \
    -DLLVM_CONFIG_PATH=$TOOLCHAIN_PREFIX/bin/llvm-config \
    -DCMAKE_C_COMPILER_TARGET=i686-windows-gnu \
    -DCOMPILER_RT_DEFAULT_TARGET_ONLY=TRUE \
    ../lib/builtins && \
    make -j4 && \
    mkdir -p /build/prefix/lib/clang/6.0.0/lib/windows && \
    cp lib/windows/libclang_rt.builtins-i686.a /build/prefix/lib/clang/6.0.0/lib/windows && \
    cd .. && \
    mkdir build-x86_64 && cd build-x86_64 && cmake \
    -DCMAKE_C_COMPILER=x86_64-w64-mingw32-clang \
    -DCMAKE_SYSTEM_NAME=Windows \
    -DCMAKE_AR=$TOOLCHAIN_PREFIX/bin/$AR \
    -DCMAKE_RANLIB=$TOOLCHAIN_PREFIX/bin/$RANLIB \
    -DCMAKE_C_COMPILER_WORKS=1 \
    -DLLVM_CONFIG_PATH=$TOOLCHAIN_PREFIX/bin/llvm-config \
    -DCMAKE_C_COMPILER_TARGET=x86_64-windows-gnu \
    -DCOMPILER_RT_DEFAULT_TARGET_ONLY=TRUE \
    ../lib/builtins && \
    make -j4 && \
    mkdir -p /build/prefix/lib/clang/6.0.0/lib/windows && \
    cp lib/windows/libclang_rt.builtins-x86_64.a /build/prefix/lib/clang/6.0.0/lib/windows

#RUN cd mingw-w64/mingw-w64-libraries && cd winstorecompat && \
#    autoreconf -vif && \
#    mkdir build && cd build && \
#    ../configure --host=$TARGET_TUPLE --prefix=$MINGW_PREFIX && make && make install

#RUN cd /build/mingw-w64/mingw-w64-tools/widl && \
#    mkdir build && cd build && \
#    CC=gcc \
#    ../configure --prefix=$TOOLCHAIN_PREFIX --target=$TARGET_TUPLE && \
#    make -j4 && \
#    make install 

RUN git clone -b master https://github.com/llvm-mirror/libcxx.git && \
    git clone -b master https://github.com/llvm-mirror/libcxxabi.git && \
    cd libcxx && \
    git checkout d4c8905691de47a521409a6316c94b0009a91fef && \
    cd ../libcxxabi && \
    git checkout b157fdd968a4e1093645ec7c65213736c4bc7ea6

#    git clone -b release_40 --depth=1 https://github.com/llvm-mirror/libunwind.git

COPY patches/libcxx-*.patch /build/patches/
RUN cd libcxx && \
    git am /build/patches/libcxx-*.patch

#COPY patches/libcxxabi-*.patch /build/patches/
#RUN cd libcxxabi && \
#    git am /build/patches/libcxxabi-*.patch

# COPY patches/libunwind-*.patch /build/patches/
#RUN cd libunwind && \
#    git am /build/patches/libunwind-*.patch

#RUN cd libunwind && mkdir build && cd build && \
#    CXXFLAGS="-nodefaultlibs -D_LIBUNWIND_IS_BAREMETAL" \
#    LDFLAGS="/build/prefix/armv7-w64-mingw32/lib/crt2.o /build/prefix/armv7-w64-mingw32/lib/crtbegin.o -lmingw32 /build/prefix/bin/../lib/clang/4.0.1/lib/windows/libclang_rt.builtins-arm.a -lmoldname -lmingwex -lmsvcrt -ladvapi32 -lshell32 -luser32 -lkernel32 /build/prefix/armv7-w64-mingw32/lib/crtend.o" \
#    cmake \
#        -DCMAKE_CXX_COMPILER_WORKS=TRUE \
#        -DLLVM_ENABLE_LIBCXX=TRUE \
#        -DCMAKE_BUILD_TYPE=Release \
#        -DLIBUNWIND_ENABLE_SHARED=OFF \
#        ..

#RUN cd libunwind/build && make -j4
#RUN cd libunwind/build && make install

RUN cd libcxxabi && mkdir build && cd build && \
    cmake \
        -DCMAKE_BUILD_TYPE=Release \
        -DCMAKE_INSTALL_PREFIX=$TOOLCHAIN_PREFIX/armv7-w64-mingw32 \
        -DCMAKE_C_COMPILER=armv7-w64-mingw32-clang \
        -DCMAKE_CXX_COMPILER=armv7-w64-mingw32-clang++ \
        -DCMAKE_CROSSCOMPILING=TRUE \
        -DCMAKE_SYSTEM_NAME=Windows \
        -DCMAKE_C_COMPILER_WORKS=TRUE \
        -DCMAKE_CXX_COMPILER_WORKS=TRUE \
        -DCMAKE_AR=$TOOLCHAIN_PREFIX/bin/$AR \
        -DCMAKE_RANLIB=$TOOLCHAIN_PREFIX/bin/$RANLIB \
        -DLIBCXXABI_USE_COMPILER_RT=ON \
        -DLIBCXXABI_ENABLE_EXCEPTIONS=OFF \
        -DLIBCXXABI_ENABLE_THREADS=OFF \
        -DLIBCXXABI_TARGET_TRIPLE=armv7-w64-mingw32 \
        -DLIBCXXABI_SYSROOT=$TOOLCHAIN_PREFIX/armv7-w64-mingw32 \
        -DLIBCXXABI_ENABLE_SHARED=OFF \
        -DLIBCXXABI_LIBCXX_INCLUDES=../../libcxx/include \
        -DLLVM_NO_OLD_LIBSTDCXX=TRUE \
        -DCXX_SUPPORTS_CXX11=TRUE \
        -DCMAKE_CXX_FLAGS="-fno-exceptions -D_WIN32_WINNT=0x600 -D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS -Xclang -flto-visibility-public-std" \
        .. && \
    make -j4

RUN cd libcxx && mkdir build && cd build && \
    cmake \
        -DCMAKE_BUILD_TYPE=Release \
        -DCMAKE_INSTALL_PREFIX=$TOOLCHAIN_PREFIX/armv7-w64-mingw32 \
        -DCMAKE_C_COMPILER=armv7-w64-mingw32-clang \
        -DCMAKE_CXX_COMPILER=armv7-w64-mingw32-clang++ \
        -DCMAKE_CROSSCOMPILING=TRUE \
        -DCMAKE_SYSTEM_NAME=Windows \
        -DCMAKE_C_COMPILER_WORKS=TRUE \
        -DCMAKE_CXX_COMPILER_WORKS=TRUE \
        -DCMAKE_AR=$TOOLCHAIN_PREFIX/bin/$AR \
        -DCMAKE_RANLIB=$TOOLCHAIN_PREFIX/bin/$RANLIB \
        -DLIBCXX_INSTALL_HEADERS=ON \
        -DLIBCXX_ENABLE_EXCEPTIONS=OFF \
        -DLIBCXX_ENABLE_THREADS=OFF \
        -DLIBCXX_ENABLE_MONOTONIC_CLOCK=OFF \
        -DLIBCXX_ENABLE_SHARED=OFF \
        -DLIBCXX_SUPPORTS_STD_EQ_CXX11_FLAG=TRUE \
        -DLIBCXX_HAVE_CXX_ATOMICS_WITHOUT_LIB=TRUE \
        -DLIBCXX_ENABLE_EXPERIMENTAL_LIBRARY=OFF \
        -DLIBCXX_ENABLE_FILESYSTEM=OFF \
        -DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=TRUE \
        -DLIBCXX_CXX_ABI=libcxxabi \
        -DLIBCXX_CXX_ABI_INCLUDE_PATHS=../../libcxxabi/include \
        -DLIBCXX_CXX_ABI_LIBRARY_PATH=../../libcxxabi/build/lib \
        -DCMAKE_CXX_FLAGS="-fno-exceptions -D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS -Xclang -flto-visibility-public-std" \
        .. && \
    make -j4 && \
    make install

RUN cd /build/prefix/include && ln -s /build/prefix/armv7-w64-mingw32/include/c++ .

# gaspp is no longer required with clang 5.0
#RUN mkdir gaspp && cd gaspp && \
#    wget -q https://raw.githubusercontent.com/libav/gas-preprocessor/master/gas-preprocessor.pl && \
#    chmod +x gas-preprocessor.pl

#ENV PATH=/build/gaspp:$PATH
#
#ENV AS="gas-preprocessor.pl ${CC}"
#ENV ASCPP="gas-preprocessor.pl ${CC}"
#ENV CCAS="gas-preprocessor.pl ${CC}"
#ENV LDFLAGS="-lmsvcr120_app ${LDFLAGS}"

RUN mkdir -p /build/hello
COPY hello.c hello.cpp /build/hello/
RUN cd /build/hello && \
    armv7-w64-mingw32-clang hello.c -o hello-armv7.exe && \
    aarch64-w64-mingw32-clang hello.c -o hello-aarch64.exe && \
    x86_64-w64-mingw32-clang hello.c -o hello-x86_64.exe && \
    i686-w64-mingw32-clang hello.c -o hello-i686.exe

RUN cd /build/hello && armv7-w64-mingw32-clang++ hello.cpp -o hello-cpp.exe -fno-exceptions -D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS -Xclang -flto-visibility-public-std -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS

RUN git clone --depth=1 git://git.libav.org/libav.git

RUN cd /build/libav && \
    mkdir build && cd build && \
    ../configure --arch=aarch64 --target-os=mingw32 --cc=aarch64-w64-mingw32-clang --ar=llvm-ar --nm=llvm-nm --enable-cross-compile --enable-gpl && \
    make -j4 all testprogs

