#!/bin/sh
#
# Copyright (c) 2019 David Demelier <markand@malikania.fr>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#

PKGNAME=llvm
PKGVERSION=13.0.0
PKGREVISION=1
PKGLICENSE="MIT AND Custom"
PKGSUMMARY="low level virtual machine compiler infrastructure"
PKGDOWNLOAD="https://github.com/llvm/llvm-project/archive/refs/tags/llvmorg-$PKGVERSION.tar.gz"
PKGDEPENDS="python:build cmake:build"
PKGOPTIONS="DOXYGEN FFI LIBEDIT LZMA NCURSES SPHINX TARGETS XML ZLIB"
PKGSPLIT="clang compiler-rt lld lldb libcxx libcxxabi libunwind openmp"
PKGPRESERVE="lib/libLLVM-13.so"

PKGDEPENDS_CLANG="compiler-rt libcxx lld"
PKGDEPENDS_LLD="libcxx"
PKGDEPENDS_LIBCXX="libcxxabi libunwind"
PKGDEPENDS_LIBCXXABI="libunwind"

PKGPRESERVE_CLANG="lib/libclang.so.13.0.0"
PKGPRESERVE_LIBCXX="lib/libc++.so.1.0"
PKGPRESERVE_LIBCXXABI="lib/libcxxabi.so.1.0"
PKGPRESERVE_LIBUNWIND="lib/libunwind.so.1.0"

: ${CHOST:=$(uname -m)-linux-musl}
: ${CC:=clang}
: ${CFLAGS:=-O2}
: ${CXX:=clang++}
: ${CXXFLAGS:=-O2}
: ${DOXYGEN:=no}        # TODO: does not install correctly.
: ${FFI:=no}
: ${LIBEDIT:=yes}
: ${LZMA:=yes}
: ${XML:=yes}
: ${NCURSES:=yes}
: ${SPHINX:=no}         # TODO: set to on once sphinx is there.
: ${TARGETS:=all}
: ${ZLIB:=yes}

if [ "$DOXYGEN" = "yes" ]; then
	PKGDEPENDS="doxygen:build $PKGDEPENDS"
	with_doxygen="-DLLVM_ENABLE_DOXYGEN=On"
else
	with_doxygen="-DLLVM_ENABLE_DOXYGEN=Off"
fi

if [ "$FFI" = "yes" ]; then
	PKGDEPENDS="libffi $PKGDEPENDS"
	with_ffi="-DLLVM_ENABLE_FFI=On"
else
	with_ffi="-DLLVM_ENABLE_FFI=Off"
fi

if [ "$LIBEDIT" = "yes" ]; then
	PKGDEPENDS="libedit $PKGDEPENDS"
	with_libedit="-DLLVM_ENABLE_LIBEDIT=On"
else
	with_libedit="-DLLVM_ENABLE_LIBEDIT=Off"
fi

if [ "$LZMA" = "yes" ]; then
	PKGDEPENDS_LLDB="xz $PKGDEPENDS"
	with_lzma="-DLLDB_ENABLE_LZMA=On"
else
	with_lzma="-DLLDB_ENABLE_LZMA=Off"
fi

if [ "$XML" = "yes" ]; then
	PKGDEPENDS="libxml2 $PKGDEPENDS"
	PKGDEPENDS_LLD="libxml2 $PKGDEPENDS_LLD"
	PKGDEPENDS_LLDB="libxml2 $PKGDEPENDS_LLDB"
	with_xml="-DLLVM_ENABLE_LIBXML2=On"
else
	with_xml="-DLLVM_ENABLE_LIBXML2=Off"
fi

if [ "$NCURSES" = "yes" ]; then
	PKGDEPENDS="ncurses $PKGDEPENDS"
	with_ncurses="-DLLVM_ENABLE_TERMINFO=On"
else
	with_ncurses="-DLLVM_ENABLE_TERMINFO=Off"
fi

if [ "$SPHINX" = "yes" ]; then
	PKGDEPENDS="dev/sphinx:build $PKGDEPENDS"
	with_sphinx="-DLLVM_ENABLE_SPHINX=On"
else
	with_sphinx="-DLLVM_ENABLE_SPHINX=Off"
fi

if [ "$ZLIB" = "yes" ]; then
	PKGDEPENDS="zlib $PKGDEPENDS"
	PKGDEPENDS_LLD="zlib $PKGDEPENDS_LLD"
	PKGDEPENDS_LLDB="zlib $PKGDEPENDS_LLDB"
	with_zlib="-DLLVM_ENABLE_ZLIB=On"
else
	with_zlib="-DLLVM_ENABLE_ZLIB=Off"
fi

build()
{
	rm -rf llvm-project-llvmorg-$PKGVERSION
	tar -xvf llvmorg-$PKGVERSION.tar.gz
	cd llvm-project-llvmorg-$PKGVERSION

	cmake -S llvm -B build \
		-DCLANG_DEFAULT_CXX_STDLIB=libc++ \
		-DCLANG_DEFAULT_LINKER=lld \
		-DCLANG_DEFAULT_RTLIB=compiler-rt \
		-DCLANG_DEFAULT_UNWINDLIB=libunwind \
		-DCMAKE_BUILD_TYPE=Release \
		-DCMAKE_INSTALL_PREFIX=/ \
		-DCMAKE_INSTALL_MANDIR=/share/man \
		-DCOMPILER_RT_BUILD_LIBFUZZER=Off \
		-DCOMPILER_RT_BUILD_MEMPROF=Off \
		-DCOMPILER_RT_BUILD_ORC=Off \
		-DCOMPILER_RT_BUILD_PROFILE=Off \
		-DCOMPILER_RT_BUILD_SANITIZERS=Off \
		-DCOMPILER_RT_BUILD_XRAY=Off \
		-DCOMPILER_RT_EXCLUDE_ATOMIC_BUILTIN=Off \
		-DLIBCXXABI_INCLUDE_TESTS=Off \
		-DLIBCXXABI_USE_COMPILER_RT=On \
		-DLIBCXXABI_USE_LLVM_UNWINDER=On \
		-DLIBCXX_CXX_ABI=libcxxabi \
		-DLIBCXX_HAS_MUSL_LIBC=On \
		-DLIBCXX_INCLUDE_DOCS=Off \
		-DLIBCXX_INCLUDE_TESTS=Off \
		-DLIBUNWIND_INCLUDE_DOCS=Off \
		-DLIBUNWIND_INCLUDE_TESTS=Off \
		-DLIBUNWIND_USE_COMPILER_RT=On \
		-DLLVM_BUILD_BENCHMARKS=Off \
		-DLLVM_BUILD_DOCS=Off \
		-DLLVM_BUILD_EXAMPLES=Off \
		-DLLVM_BUILD_LLVM_DYLIB=On \
		-DLLVM_BUILD_TESTS=Off \
		-DLLVM_BUILD_TOOLS=On \
		-DLLVM_BUILD_UTILS=Off \
		-DLLVM_ENABLE_BINDINGS=Off \
		-DLLVM_ENABLE_DOXYGEN=Off \
		-DLLVM_ENABLE_EH=On \
		-DLLVM_ENABLE_LIBCXX=On \
		-DLLVM_ENABLE_LLD=On \
		-DLLVM_ENABLE_OCAMLDOC=Off \
		-DLLVM_ENABLE_PROJECTS="clang;lld;lldb;compiler-rt;libunwind;libcxxabi;libcxx;openmp" \
		-DLLVM_ENABLE_RTTI=On \
		-DLLVM_ENABLE_SPHINX=Off \
		-DLLVM_INCLUDE_BENCHMARKS=Off \
		-DLLVM_INCLUDE_DOCS=Off \
		-DLLVM_INCLUDE_EXAMPLES=Off \
		-DLLVM_INCLUDE_GO_TESTS=Off \
		-DLLVM_INCLUDE_TESTS=Off \
		-DLLVM_INCLUDE_TOOLS=On \
		-DLLVM_INCLUDE_UTILS=Off \
		-DLLVM_INSTALL_BINUTILS_SYMLINKS=On \
		-DLLVM_INSTALL_TOOLCHAIN_ONLY=On \
		-DLLVM_INSTALL_UTILS=Off \
		-DLLVM_TARGETS_TO_BUILD=$TARGETS \
		$with_doxygen \
		$with_ffi \
		$with_libcxx \
		$with_libedit \
		$with_lld \
		$with_lzma \
		$with_ncurses \
		$with_sphinx \
		$with_xml \
		$with_zlib
	cmake --build build -j4
	DESTDIR=$DESTDIR cmake --build build --target install

	# libcxxabi
	mkdir -p $DESTDIR-libcxxabi/lib
	mv $DESTDIR/lib/libc++abi* $DESTDIR-libcxxabi/lib

	# libcxx
	mkdir -p $DESTDIR-libcxx/include $DESTDIR-libcxx/lib
	mv $DESTDIR/lib/libc++* $DESTDIR-libcxx/lib
	mv $DESTDIR/include/c++ $DESTDIR-libcxx/include

	# libunwind
	mkdir -p $DESTDIR-libunwind/lib
	mv $DESTDIR/lib/libunwind* $DESTDIR-libunwind/lib

	# lldb
	mkdir -p $DESTDIR-lldb/bin $DESTDIR-lldb/lib
	mv $DESTDIR/bin/lldb* $DESTDIR-lldb/bin
	mv $DESTDIR/lib/liblldb* $DESTDIR-lldb/lib

	# openmp
	mkdir -p $DESTDIR/include $DESTDIR-openmp/lib
	mv $DESTDIR/lib/libomp* $DESTDIR-openmp/lib
	mv $DESTDIR/include/ompt-multiplex.h $DESTDIR-openmp/include

	# compiler-rt
	mkdir -p $DESTDIR-compiler-rt/lib/clang/$PKGVERSION
	mv $DESTDIR/lib/clang/$PKGVERSION/lib $DESTDIR-compiler-rt/lib/clang/$PKGVERSION

	# clang
	mkdir -p \
		$DESTDIR-clang/bin \
		$DESTDIR-clang/include \
		$DESTDIR-clang/lib \
		$DESTDIR-clang/share/man
	mv $DESTDIR/bin/clang* $DESTDIR-clang/bin
	mv $DESTDIR/include/clang-c $DESTDIR-clang/include
	mv $DESTDIR/lib/clang $DESTDIR-clang/lib
	mv $DESTDIR/lib/libclang* $DESTDIR-clang/lib
	mv $DESTDIR/libexec $DESTDIR-clang
	mv $DESTDIR/share/clang $DESTDIR-clang/share
	mv $DESTDIR/share/scan-build $DESTDIR-clang/share
	mv $DESTDIR/share/scan-view $DESTDIR-clang/share

	# lld
	mkdir -p $DESTDIR-lld/bin
	mv $DESTDIR/bin/lld* $DESTDIR-lld/bin

	cd ..
	rm -rf $PKGNAME-$PKGVERSION.src
}
