#! /bin/sh # # mulle-clang installer # (c) 2016 Codeon GmbH, coded by Nat! # BSD-3 License [ "${TRACE}" = "YES" ] && set -x && : "$0" "$@" # # Set these variables, if you DONT want mulle-clang but plain clang/lldb # or use --llvm-clang --llvm-lldb (will also set BY_THE_BOOK to STRICT) # USE_LLVM_CLANG="NO" USE_LLVM_LLDB="NO" # required LLVM version LLVM_VERSION="10.0.0" #LLVM_RC="2" # leave empty for releases # our compiler version MULLE_CLANG_VERSION="${LLVM_VERSION}.2" # MULLE_CLANG_RC="prerelease" MULLE_LLDB_VERSION="${LLVM_VERSION}.0" # MULLE_LLDB_RC="prerelease" # STRICT means compile it like LLVM does (everything all the time) # only useful if you're creating installers IMO. I # You have three options # # STRICT : stuff will be placed into src/llvm/tools # SEPARATE : stuff will be parallel to src/llvm and build there # HACK : like STRICT, but place symlinks into src/llvm/tools and build there BY_THE_BOOK="STRICT" # # cmake min for 7 is 3.4.2 (so still good), try to keep as low as possible # for distributions with old cmakes. That said 3.5.2 works for me # CMAKE_VERSION_MAJOR="3" CMAKE_VERSION_MINOR="5" CMAKE_VERSION_PATCH="2" # # # CMAKE_VERSION="${CMAKE_VERSION_MAJOR}.${CMAKE_VERSION_MINOR}" CMAKE_PATCH_VERSION="${CMAKE_VERSION}.${CMAKE_VERSION_PATCH}" usage() { cat <&2 Usage: install-mulle-clang [options] [command] Build llvm and mulle-clang/mulle-lld. The version of llvm and mulle-clang being built is hardcoded into this script (see top). Options: EOF ( cat < : install prefix for clang --debug : build everything DEBUG (not recommended) --lldb-prefix : install prefix for lldb --llvm-debug : build llvm debug --llvm-prefix : install prefix for llvm --no-libcxx : do not download libcxx --no-compiler-rt : do not download compiler runtime and sanitizers --no-warn : do not warn if a previous build exists --no-python : disable python (for lldb) --python : enable python (for lldb) --prefix : default install prefix --target-arch : currently only ARM is supported on Ubuntu --vs32bit : compile for Visual Studo 32 bit EOF fi ) | sort >&2 if [ "${VERBOSE}" != "YES" ] then echo >&2 echo " (Use -v to see more options)" >&2 fi cat <&2 Commands: install : install links default : download and build download : download only build : build only uninstall : remove links EOF exit 1 } setup_fetch_environment() { if [ "${USE_LLVM_CLANG}" = "NO" ] then if [ -z "${MULLE_CLANG_RC}" ] then MULLE_CLANG_ARCHIVENAME="${MULLE_CLANG_VERSION}" else MULLE_CLANG_ARCHIVENAME="${MULLE_CLANG_VERSION}-${MULLE_CLANG_RC}" fi MULLE_CLANG_ARCHIVE="https://github.com/Codeon-GmbH/mulle-clang/archive/${MULLE_CLANG_ARCHIVENAME}.tar.gz" MULLE_CLANG_UNPACKNAME="mulle-clang-${MULLE_CLANG_ARCHIVENAME}" fi if [ "${USE_LLVM_LLDB}" = "NO" ] then if [ -z "${MULLE_LLDB_RC}" ] then MULLE_LLDB_ARCHIVENAME="${MULLE_LLDB_VERSION}" else MULLE_LLDB_ARCHIVENAME="${MULLE_LLDB_VERSION}-${MULLE_LLDB_RC}" fi MULLE_LLDB_ARCHIVE="https://github.com/Codeon-GmbH/mulle-lldb/archive/${MULLE_LLDB_ARCHIVENAME}.tar.gz" MULLE_LLDB_UNPACKNAME="mulle-lldb-${MULLE_LLDB_ARCHIVENAME}" fi if [ -z "${LLVM_RC}" ] then #regular releases # https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/llvm-10.0.0.src.tar.xz # https://github.com/llvm/llvm-project/releases/download/llvmorg-10.0.0/clang-10.0.0.src.tar.xz LLVM_ARCHIVE="https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/llvm-${LLVM_VERSION}.src.tar.xz" COMPILER_RT_ARCHIVE="https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/compiler-rt-${LLVM_VERSION}.src.tar.xz" LIBCXX_ARCHIVE="https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/libcxx-${LLVM_VERSION}.src.tar.xz" LIBCXXABI_ARCHIVE="https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/libcxxabi-${LLVM_VERSION}.src.tar.xz" if [ "${USE_LLVM_CLANG}" = "YES" ] then CLANG_ARCHIVE="https://github.com/llvm/llvm-project/releases/download/llvmorg-{LLVM_VERSION}/cfe-${LLVM_VERSION}.src.tar.xz" fi if [ "${USE_LLVM_LLDB}" = "YES" ] then LLDB_ARCHIVE="https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/lldb-${LLVM_VERSION}.src.tar.xz" fi else # prereleases, not yet change to github or whatever LLVM_ARCHIVE="https://prereleases.llvm.org/${LLVM_VERSION}/rc${LLVM_RC}/llvm-${LLVM_VERSION}rc${LLVM_RC}.src.tar.xz" COMPILER_RT_ARCHIVE="https://prereleases.org/releases/${LLVM_VERSION}/compiler-rt-${LLVM_VERSION}rc${LLVM_RC}.src.tar.xz" LIBCXX_ARCHIVE="https://prereleases.llvm.org/${LLVM_VERSION}/rc${LLVM_RC}/libcxx-${LLVM_VERSION}rc${LLVM_RC}.src.tar.xz" LIBCXXABI_ARCHIVE="https://prereleases.llvm.org/${LLVM_VERSION}/rc${LLVM_RC}/libcxxabi-${LLVM_VERSION}rc${LLVM_RC}.src.tar.xz" if [ "${USE_LLVM_CLANG}" = "YES" ] then CLANG_ARCHIVE="https://prereleases.llvm.org/${LLVM_VERSION}/rc${LLVM_RC}/clang-${LLVM_VERSION}rc${LLVM_RC}.src.tar.xz" fi if [ "${USE_LLVM_LLDB}" = "YES" ] then LLDB_ARCHIVE="https://prereleases.llvm.org/${LLVM_VERSION}/rc${LLVM_RC}/lldb-${LLVM_VERSION}rc${LLVM_RC}.src.tar.xz" fi fi } environment_initialize() { MULLE_UNAME="`uname -s | tr '[A-Z]' '[a-z]'`" case "${MULLE_UNAME}" in mingw*) CLANG_SUFFIX="-cl" EXE_EXTENSION=".exe" SYMLINK_PREFIX="~" SUDO= ;; *) SYMLINK_PREFIX="/usr/local" SUDO="sudo" ;; esac } log_initialize() { if [ -z "${NO_COLOR}" ] then case "${MULLE_UNAME}" in darwin|linux|freebsd|mingw*) C_RESET="\033[0m" # Useable Foreground colours, for black/white white/black C_RED="\033[0;31m" C_GREEN="\033[0;32m" C_BLUE="\033[0;34m" C_MAGENTA="\033[0;35m" C_CYAN="\033[0;36m" C_BR_RED="\033[0;91m" C_BOLD="\033[1m" C_FAINT="\033[2m" C_RESET_BOLD="${C_RESET}${C_BOLD}" trap 'printf "${C_RESET}"' TERM EXIT ;; esac fi C_ERROR="${C_RED}${C_BOLD}" C_WARNING="${C_RED}${C_BOLD}" C_INFO="${C_MAGENTA}${C_BOLD}" C_FLUFF="${C_GREEN}${C_BOLD}" C_VERBOSE="${C_CYAN}${C_BOLD}" } concat() { local i local s for i in "$@" do if [ -z "${i}" ] then continue fi if [ -z "${s}" ] then s="${i}" else s="${s} ${i}" fi done echo "${s}" } log_error() { printf "${C_ERROR}%b${C_RESET}\n" "$*" >&2 } log_warning() { printf "${C_WARNING}%b${C_RESET}\n" "$*" >&2 } log_info() { printf "${C_INFO}%b${C_RESET}\n" "$*" >&2 } log_fluff() { if [ ! -z "${FLUFF}" ] then printf "${C_FLUFF}%b${C_RESET}\n" "$*" >&2 fi } log_verbose() { if [ ! -z "${VERBOSE}" -a -z "${TERSE}" ] then printf "${C_VERBOSE}%b${C_RESET}\n" "$*" >&2 fi } fail() { log_error "$@" exit 1 } internal_fail() { fail "$@" } tar_fail() { case "${MULLE_UNAME}" in mingw*) log_warning "$@" "ignored, because we're on MinGW and crossing fingers, that just tests are affected" ;; *) fail "$@" ;; esac } exekutor_trace() { if [ "${MULLE_FLAG_EXECUTOR_DRY_RUN}" = "YES" -o "${MULLE_FLAG_LOG_EXECUTOR}" = "YES" ] then local arrow [ -z "${MULLE_EXECUTABLE_PID}" ] && internal_fail "MULLE_EXECUTABLE_PID not set" if [ "${PPID}" -ne "${MULLE_EXECUTABLE_PID}" ] then arrow="=[${PPID}]=>" else arrow="==>" fi if [ -z "${MULLE_EXECUTOR_LOG_DEVICE}" ] then echo "${arrow}" "$@" >&2 else echo "${arrow}" "$@" > "${MULLE_EXECUTOR_LOG_DEVICE}" fi fi } exekutor() { exekutor_trace "$@" if [ "${MULLE_FLAG_EXECUTOR_DRY_RUN}" != "YES" ] then "$@" fi } eval_exekutor() { exekutor_trace "$@" if [ "${MULLE_FLAG_EXECUTOR_DRY_RUN}" != "YES" ] then eval "$@" fi } is_root() { if [ "$EUID" != "" ] then [ "$EUID" -eq 0 ] else [ "`id -u`" -eq 0 ] fi } sudo_if_needed() { if [ -z "${SUDO}" ] || is_root then eval exekutor "$@" else command -v "${SUDO}" > /dev/null 2>&1 if [ $? -ne 0 ] then fail "Install ${SUDO} or run as root" fi eval exekutor ${SUDO} "$@" fi } fetch_brew() { case "${MULLE_UNAME}" in darwin) log_fluff "Installing OS X brew" exekutor ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" || fail "ruby" ;; linux) install_binary_if_missing "curl" install_binary_if_missing "python-setuptools" install_binary_if_missing "build-essential" install_binary_if_missing "ruby" log_fluff "Installing Linux brew" exekutor ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/linuxbrew/go/install)" || fail "ruby" ;; esac } install_with_brew() { PATH="$PATH:/usr/local/bin" command -v "brew" > /dev/null 2>&1 if [ $? -ne 0 ] then command -v "ruby" > /dev/null 2>&1 if [ $? -ne 0 ] then fail "You need to install $1 manually from $2" fi fetch_brew fi log_info "Download $1 using brew" PATH="$PATH:/usr/local/bin" exekutor brew install "$1" || exit 1 } install_library_if_missing() { # we just install if there is no sudo needed case "${MULLE_UNAME}" in darwin) install_with_brew "$@" || exit 1 ;; linux) # if command -v "brew" > /dev/null 2>&1 # then # install_with_brew "$@" || exit 1 # else if command -v "apt-get" > /dev/null 2>&1 then if ! dpkg -s "$1" > /dev/null 2>&1 then log_info "You may get asked for your password to install $1" sudo_if_needed apt-get install "$1" || exit 1 fi else if command -v "yum" > /dev/null 2>&1 then if ! yum list installed "$1" > /dev/null 2>&1 then log_info "You may get asked for your password to install $1" sudo_if_needed yum install "$1" || exit 1 fi else log_warning "You may need to install $1 manually from $2" fi fi # fi ;; FreeBSD) if command -v "pkg" > /dev/null 2>&1 then if ! pkg info"$1" > /dev/null 2>&1 then log_info "You may get asked for your password to install $1" sudo_if_needed pkg install "$1" || exit 1 fi else if command -v "pkg_add" > /dev/null 2>&1 then if ! pkg_info "$1" > /dev/null 2>&1 then log_info "You may get asked for your password to install $1" sudo_if_needed pkg_add -r "$1" || exit 1 fi else fail "You need to install $1 manually from $2" fi fi ;; *) fail "You need to install $1 manually from $2" ;; esac } # # third parameter is hackish apt-get install # hacked for ninja, should do this properly though # install_binary_if_missing() { if command -v "$1" > /dev/null 2>&1 then return fi case "${MULLE_UNAME}" in darwin) install_with_brew "$@" || exit 1 ;; linux) # if command -v "brew" > /dev/null 2>&1 # then # install_with_brew "$@" || exit 1 # else if command -v "apt-get" > /dev/null 2>&1 then log_info "You may get asked for your password to install $1" sudo_if_needed apt-get install "${3:-$1}" || exit 1 else if command -v "yum" > /dev/null 2>&1 then log_info "You may get asked for your password to install $1" sudo_if_needed yum install "$1" || exit 1 else fail "You need to install $1 manually from $2" fi fi # fi ;; FreeBSD) if command -v "pkg" > /dev/null 2>&1 then log_info "You may get asked for your password to install $1" sudo_if_needed pkg install "$1" || exit 1 else if command -v "pkg_add" > /dev/null 2>&1 then log_info "You may get asked for your password to install $1" sudo_if_needed pkg_add -r "$1" || exit 1 else fail "You need to install $1 manually from $2" fi fi ;; *) fail "You need to install $1 manually from $2" ;; esac } build_cmake() { log_fluff "Build cmake..." install_binary_if_missing "curl" "https://curl.haxx.se/" install_binary_if_missing "${CXX_COMPILER}" "https://gcc.gnu.org/install/download.html" install_binary_if_missing "tar" "from somewhere" install_binary_if_missing "make" "from somewhere" exekutor mkdir "${SRC_DIR}" 2> /dev/null set -e exekutor cd "${SRC_DIR}" if [ -d "cmake-${CMAKE_PATCH_VERSION}" ] then exekutor rm -rf "cmake-${CMAKE_PATCH_VERSION}" fi if [ ! -f "cmake-${CMAKE_PATCH_VERSION}.tar.gz" ] then exekutor curl -k -L -O "https://cmake.org/files/v${CMAKE_VERSION}/cmake-${CMAKE_PATCH_VERSION}.tar.gz" fi exekutor tar xfz "cmake-${CMAKE_PATCH_VERSION}.tar.gz" exekutor cd "cmake-${CMAKE_PATCH_VERSION}" exekutor ./configure "--prefix=${PREFIX}" # don't use ninja here exekutor make -B -j `get_core_count` install || exit 1 hash -r # apparently needed... exekutor cd "${OWD}" set +e } check_cmake_version() { local major local minor local version version="`cmake${BUILD_EXE_EXTENSION} -version 2> /dev/null | awk '{ print $3 }'`" if [ -z "${version}" ] then log_fluff "The cmake is not installed." return 2 fi major="`echo "${version}" | head -1 | cut -d. -f1`" if [ -z "${major}" ] then fail "Could not figure out where cmake is and what version it is." fi minor="`echo "${version}" | head -1 | cut -d. -f2`" if [ "${major}" -lt "${CMAKE_VERSION_MAJOR}" ] || [ "${major}" -eq "${CMAKE_VERSION_MAJOR}" -a "${minor}" -lt "${CMAKE_VERSION_MINOR}" ] then return 1 fi return 0 } check_and_build_cmake() { if [ -z "${BUILD_CMAKE}" ] then install_binary_if_missing "cmake${BUILD_EXE_EXTENSION}" "https://cmake.org/download/" fi check_cmake_version case $? in 0) return ;; 1) log_fluff "The cmake version is too old. cmake version ${CMAKE_VERSION} or better is required." ;; 2) : ;; esac log_fluff "Let's build cmake from scratch" build_cmake || fail "build_cmake failed" } get_core_count() { local count command -v "nproc" > /dev/null 2>&1 if [ $? -ne 0 ] then command -v "sysctl" > /dev/null 2>&1 if [ $? -ne 0 ] then log_fluff "can't figure out core count, assume 4" else count="`sysctl -n hw.ncpu`" fi else count="`nproc`" fi if [ -z "$count" ] then count=4 fi echo $count } # # but isn't that the same as MULLE_CLANG_VERSION ? # not neccessarily, if the script was curled and the # clone version differs # get_mulle_clang_version() { local src="$1" local fallback="$2" if [ ! -d "${src}" ] then fail "mulle-clang not downloaded yet" fi if [ ! -f "${src}/bin/install-mulle-clang" ] then fail "No MULLE_CLANG_VERSION version found in \"${src}\"" fi local version local rc version="`head -50 "${src}/bin/install-mulle-clang" \ | egrep '^MULLE_CLANG_VERSION=' \ | head -1 \ | sed 's/.*\"\(.*\)\".*/\1/'`" rc="`head -50 "${src}/bin/install-mulle-clang" \ | egrep '^MULLE_CLANG_RC=' \ | head -1 \ | sed 's/.*\"\(.*\)\".*/\1/'`" if [ -z "${version}" ] then log_warning "Could not find MULLE_CLANG_VERSION in download, using default" eval echo "${fallback}" else if [ -z "${rc}" ] then eval echo "${version}" else eval echo "${version}-RC${rc}" fi fi } get_runtime_load_version() { local src="$1" grep COMPATIBLE_MULLE_OBJC_RUNTIME_LOAD_VERSION "${src}/lib/CodeGen/CGObjCMulleRuntime.cpp" \ | head -1 \ | awk '{ print $3 }' } get_clang_vendor() { local src="$1" local compiler_version="$2" local runtime_load_version runtime_load_version="`get_runtime_load_version "${src}"`" if [ -z "${runtime_load_version}" ] then fail "Could not determine runtime load version" fi echo "mulle-clang `eval echo ${compiler_version}` (runtime-load-version: `eval echo ${runtime_load_version}`)" } # # Setup environment # setup_build_environment() { local version local minor local major if [ "${OPTION_PYTHON}" = 'YES' ] then install_binary_if_missing "python${BUILD_EXE_EXTENSION}" "https://www.python.org/downloads/release" fi # # Ninja is probably preferable if installed # Should configure this though somewhere # Unfortunately on mingw, compile errors in libcxx # as ninja picks up the wrong c. # if [ "${OPTION_NINJA}" = "YES" ] then install_binary_if_missing "ninja${BUILD_EXE_EXTENSION}" "https://github.com/ninja-build/ninja/releases" "ninja-build" CMAKE_GENERATOR="Ninja" MAKE="ninja${BUILD_EXE_EXTENSION}" MAKEFILE="build.ninja" MAKE_INSTALL_COMMAND="install" if [ "${OPTION_PARALLEL}" = "NO" ] then MAKE_FLAGS="-j 1" else local cores local loadavg cores="`get_core_count`" loadavg="`expr $cores / 4`" loadavg="`expr $cores - ${loadavg}`" if [ "${loadavg}" -gt 0 ] then MAKE_FLAGS="-l ${loadavg}" fi fi if [ "${VERBOSE}" = "YES" ] then MAKE_FLAGS="-v ${MAKE_FLAGS}" fi MAKE_BUILD_COMMAND="" fi # # make sure cmake and git and gcc are present (and in the path) # should check version # Set some defaults so stuff possibly just magically works. # case "${MULLE_UNAME}" in mingw*) log_fluff "Detected MinGW on Windows" PATH="$PATH:/c/Program Files/CMake/bin/cmake:/c/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin" install_binary_if_missing "xz" "https://tukaani.org/xz and then add the directory containing xz to your %PATH%" if [ "${OPTION_VS32BIT}" = "YES" ] then # can't use ninja then though CMAKE_FLAGS="${CMAKE_FLAGS} -Thost=x64" if [ ! -z "${MAKE}" ] then log_verbose "Falling back to msbuild, as you can't use -Thost=x64 with ${MAKE}... But then may run into problems later with visual studio (maybe)." MAKE= fi fi if [ -z "${MAKE}" ] then install_binary_if_missing "msbuild.exe" "https://www.visualstudio.com/de-de/downloads/download-visual-studio-vs.aspx and then add the directory containing nmake to your %PATH%" CMAKE_GENERATOR="Visual Studio 14 2015" MAKEFILE="INSTALL.vcxproj" # hmm MAKE="msbuild.exe" MAKE_FLAGS="/maxcpucount:`get_core_count`" MAKE_INSTALL_COMMAND="INSTALL.vcxproj" MAKE_BUILD_COMMAND="ALL_BUILD.vcxproj" fi CXX_COMPILER=cl.exe C_COMPILER=cl.exe ;; # # FreeBSD needs rpath set for c++ libraries # FreeBSD) CMAKE_FLAGS="${CMAKE_FLAGS} -DCMAKE_SHARED_LINKER_FLAGS=-Wl,-rpath,\\\$ORIGIN/../lib" ;; esac if [ -z "${MAKE}" ] then install_binary_if_missing "make${BUILD_EXE_EXTENSION}" "somewhere" CMAKE_GENERATOR="Unix Makefiles" MAKEFILE="Makefile" MAKE="make${BUILD_EXE_EXTENSION}" if [ "${OPTION_PARALLEL}" = "NO" ] then MAKE_FLAGS="-B -j `get_core_count`" else MAKE_FLAGS="-B" fi MAKE_INSTALL_COMMAND="install" MAKE_BUILD_COMMAND="" fi check_and_build_cmake if [ "${CXX_COMPILER}" = "g++${BUILD_EXE_EXTENSION}" ] then install_binary_if_missing "g++${BUILD_EXE_EXTENSION}" "https://gcc.gnu.org/install/download.html" else if [ "${CXX_COMPILER}" = "clang++${BUILD_EXE_EXTENSION}" ] then install_binary_if_missing "clang++${BUILD_EXE_EXTENSION}" "https://clang.llvm.org/get_started.html" else install_binary_if_missing "${CXX_COMPILER}" "somewhere (cpp compiler)" fi fi if [ "${C_COMPILER}" = "gcc${BUILD_EXE_EXTENSION}" ] then install_binary_if_missing "gcc${BUILD_EXE_EXTENSION}" "https://gcc.gnu.org/install/download.html" else if [ "${C_COMPILER}" = "clang${BUILD_EXE_EXTENSION}" ] then install_binary_if_missing "clang${BUILD_EXE_EXTENSION}" "https://clang.llvm.org/get_started.html" else install_binary_if_missing "${C_COMPILER}" "somewhere (c compiler)" fi fi if [ "${BUILD_LLDB}" = "YES" ] then install_binary_if_missing "swig${BUILD_EXE_EXTENSION}" "https://swig.org/download.html" case "${MULLE_UNAME}" in darwin) ;; linux) install_library_if_missing "python-dev" "https://www.python.org/downloads/release" install_library_if_missing "libncurses5-dev" "https://www.gnu.org/software/ncurses" install_library_if_missing "libxml2-dev" "https://xmlsoft.org" install_library_if_missing "libedit-dev" "https://thrysoee.dk/editline" ;; *) ;; esac fi } is_kosher_download() { if [ ! -f "${1}" ] then return 0 fi local size size="`du -k "${1}" | awk '{ print $1}'`" [ "${size}" -gt 16 ] } incremental_download() { local filename="$1" local url="$2" local name="$3" if [ ! -f "${filename}" ] then local partialfilename partialfilename="_${filename}" if ! is_kosher_download "${filename}" then exekutor rm "${partialfilename}" fi log_verbose "Downloading \"${name}\" from \"${url}\" ..." exekutor curl -L -C- -o "${partialfilename}" "${url}" || fail "curl failed" case "${filename}" in *gz) exekutor tar tfz "${partialfilename}" > /dev/null || tar_fail "tar archive corrupt" ;; *xz) exekutor tar tfJ "${partialfilename}" > /dev/null || tar_fail "tar archive corrupt" ;; esac exekutor mv "${partialfilename}" "${filename}" || exit 1 fi } extract_tar_gz_archive() { local filename="$1" local dst="$2" local name="$3" [ -d "${dst}" ] && fail "${dst} already exists" log_verbose "Unpacking into \"${dst}\" ..." local extractname extractname="`basename -- "${filename}" ".tar.gz"`" exekutor tar xfz "${filename}" || tar_fail ".tar.gz" exekutor mkdir -p "`dirname -- "${dst}"`" 2> /dev/null exekutor mv "${extractname}" "${dst}" || exit 1 } extract_tar_xz_archive() { local filename="$1" local dst="$2" local name="$3" [ -d "${dst}" ] && fail "${dst} already exists" log_verbose "Unpacking into \"${dst}\" ..." local extractname extractname="`basename -- "${filename}" ".tar.xz"`" exekutor tar xfJ "${filename}" || tar_fail ".tar.xz" exekutor mkdir -p "`dirname -- "${dst}"`" 2> /dev/null exekutor mv "${extractname}" "${dst}" || exit 1 } _llvm_module_download() { local name="$1" local archive="$2" local dst="$3" local filename filename="`basename -- "${archive}"`" incremental_download "${filename}" "${archive}" "${name}" && extract_tar_xz_archive "${filename}" "${dst}" "${name}" } download_llvm() { if [ ! -d "${LLVM_DIR}" ] then log_info "llvm ${LLVM_VERSION}" exekutor mkdir -p "`dirname -- "${SRC_DIR}"`" 2> /dev/null || exit 1 _llvm_module_download "llvm" "${LLVM_ARCHIVE}" "${SRC_DIR}/llvm" fi if [ -z "${NO_LIBCXX}" ] then if [ ! -d "${LLVM_DIR}/projects/libcxx" ] then _llvm_module_download "libcxx" "${LIBCXX_ARCHIVE}" "${LLVM_DIR}/projects/libcxx" else log_fluff "\"${LLVM_DIR}/projects/libcxx\" already exists" fi if [ ! -d "${LLVM_DIR}/projects/libcxxabi" ] then _llvm_module_download "libcxxabi" "${LIBCXXABI_ARCHIVE}" "${LLVM_DIR}/projects/libcxxabi" # PATCH for MACOS needed for 10.13 at least assume all lower case "${MULLE_UNAME}" in darwin) case "`sw_vers -productVersion`" in 10\.[0-9]\.*|10\.1[0123]*\.*) log_verbose "Patching out missing symbols for MacOS from libc++abi" sed -i.bak -e '/^__Z.*Du$/d' "${LLVM_DIR}/projects/libcxxabi/lib/itanium-base.exp" ;; esac ;; esac else log_fluff "\"${LLVM_DIR}/projects/libcxxabi\" already exists" fi else log_fluff "Skipped libcxx" fi if [ -z "${NO_COMPILER_RT}" ] then if [ ! -d "${LLVM_DIR}/projects/compiler-rt" ] then _llvm_module_download "compiler-rt" "${COMPILER_RT_ARCHIVE}" "${LLVM_DIR}/projects/compiler-rt" else log_fluff "\"${LLVM_DIR}/projects/compiler-rt\" already exists" fi else log_fluff "Skipped compiler-rt" fi if [ "${USE_LLVM_CLANG}" = "YES" ] then if [ ! -d "${LLVM_DIR}/tools/clang" ] then _llvm_module_download "clang" "${CLANG_ARCHIVE}" "${LLVM_DIR}/tools/clang" else log_fluff "\"${LLVM_DIR}/tools/clang\" already exists" fi fi if [ "${USE_LLVM_LLDB}" = "YES" ] then if [ ! -d "${LLVM_DIR}/tools/lldb" ] then _llvm_module_download "lldb" "${LLDB_ARCHIVE}" "${LLVM_DIR}/tools/lldb" else log_fluff "\"${LLVM_DIR}/tools/lldb\" already exists" fi fi } download_clang() { if [ ! -d "${MULLE_CLANG_DIR}" -a ! -L "${MULLE_CLANG_DIR}" ] then log_info "mulle-clang ${MULLE_CLANG_ARCHIVENAME}" incremental_download "${MULLE_CLANG_UNPACKNAME}.tar.gz" "${MULLE_CLANG_ARCHIVE}" "mulle-clang" && extract_tar_gz_archive "${MULLE_CLANG_UNPACKNAME}.tar.gz" "${MULLE_CLANG_DIR}" "mulle-clang" else log_fluff "\"${MULLE_CLANG_DIR}\" already exists" fi } download_lldb() { if [ ! -d "${MULLE_LLDB_DIR}" -a ! -L "${MULLE_LLDB_DIR}" ] then log_info "mulle-lldb ${MULLE_LLDB_ARCHIVENAME}" incremental_download "${MULLE_LLDB_UNPACKNAME}.tar.gz" "${MULLE_LLDB_ARCHIVE}" "mulle-lldb" && extract_tar_gz_archive "${MULLE_LLDB_UNPACKNAME}.tar.gz" "${MULLE_LLDB_DIR}" "mulle-lldb" else log_fluff "\"${MULLE_LLDB_DIR}\" already exists" fi } should_build() { local directory="$1" if [ ! -f "${directory}/${MAKEFILE}" ] then return 0 fi if [ ! -f "${directory}/CMakeCache.txt" ] then return 0 fi return 1 } r_generic_cmake_options() { # for msbuild C_COMPILER="`command -v "${C_COMPILER}"`" CXX_COMPILER="`command -v "${CXX_COMPILER}"`" RVAL="\ -Wno-dev \ -G '${CMAKE_GENERATOR}' \ -DCMAKE_INSTALL_MESSAGE='LAZY' \ " case "${MULLE_UNAME}" in windows) ;; *) RVAL="${RVAL} \ -DCMAKE_C_COMPILER='${C_COMPILER}' \ -DCMAKE_CXX_COMPILER='${CXX_COMPILER}'" ;; esac case "${MULLE_UNAME}" in linux) if [ "${OPTION_LINKER}" = "ld" ] then RVAL="${RVAL} \ -DCMAKE_EXE_LINKER_FLAGS=-Wl,--reduce-memory-overheads" fi ;; darwin) RVAL="${RVAL} \ -DCMAKE_CXX_FLAGS=-std=c++14" ;; esac } r_generic_clang_options() { local links links="mulle-clang;mulle-clang-cl;mulle-clang-cpp" case "${MULLE_UNAME}" in windowd|mingw*) links="${links};../msbuild-bin/cl" ;; esac RVAL="\ -DCLANG_VENDOR='${CLANG_VENDOR}' \ -DCLANG_LINKS_TO_CREATE='${links}' \ " } r_cross_armv7_linux_llvm_options() { local links # LLVM_TARGETS_TO_BUILD ARM;PowerPC;X86 RVAL="\ -DCMAKE_CROSSCOMPILING='True' \ -DLLVM_TABLEGEN='${LLVM_BIN}/llvm-tblgen' \ -DCLANG_TABLEGEN='${CLANG_BIN}/clang-tblgen' \ -DLLVM_DEFAULT_TARGET_TRIPLE='arm-linux-gnueabihf' \ -DLLVM_TARGET_ARCH='ARM' \ -DLLVM_ENABLE_PIC='False' \ -DCMAKE_CXX_FLAGS='--target=arm-linux-gnueabihf -march=armv7-a -mcpu=cortex-a9 -mfloat-abi=hard' \ " } # in llvm CMakeLists.txt #set(LLVM_ALL_TARGETS # AArch64 # AMDGPU # ARM # BPF # Hexagon # Lanai # Mips # MSP430 # NVPTX # PowerPC # Sparc # SystemZ # X86 # XCore # ) r_generic_llvm_options() { RVAL="\ -DLLVM_OPTIMIZED_TABLEGEN='ON' \ -DLLVM_ENABLE_CXX1Y:BOOL='OFF'" case "${MULLE_UNAME}" in windows) ;; *) if [ ! -z "${OPTION_LINKER}" ] then RVAL="${RVAL} \ -DLLVM_USE_LINKER='${OPTION_LINKER}'" fi ;; esac # -DBUILD_SHARED_LIBS=ON is broken in 7.0 due to gtest dependency if [ "${OPTION_TARGETS}" = "DEFAULT" ] then case "${LLVM_BUILD_TYPE}" in Release) OPTION_TARGETS='all' # see above ;; *) OPTION_TARGETS="Native" ;; esac fi if [ "${LLVM_BUILD_TYPE}" = "Release" ] then RVAL="${RVAL} \ -DLLVM_ENABLE_ASSERTIONS:BOOL='OFF'" fi RVAL="${RVAL} \ -DLLVM_TARGETS_TO_BUILD='${OPTION_TARGETS}'" } # # on Debian, llvm may not build properly with clang # use gcc, which is the default compiler for cmake # _build_llvm() { # # if on windows you notice that lldb doesnt compile # you want to throw it away with --no-lldb # # This is weird old code. # Better to specify LLVM_ENABLE_PROJECTS="clang, libcxx, libcxxabi, compiler-rt, lld, polly" ? # if [ "${BUILD_LLDB}" = "NO" -a "${BY_THE_BOOK}" != "SEPARATE" ] # then # if [ -d "${MULLE_LLDB_DIR}" ] # then # exekutor rm -rf "${MULLE_LLDB_DIR}" # if [ -f "${LLVM_BUILD_DIR}/CMakeCache.txt" ] # then # exekutor rm "${LLVM_BUILD_DIR}/CMakeCache.txt" # fi # fi # fi # # Build llvm # if should_build "${LLVM_BUILD_DIR}" || [ "${RUN_LLVM_CMAKE}" = "YES" ] then exekutor mkdir -p "${LLVM_BUILD_DIR}" 2> /dev/null [ -d "${LLVM_BUILD_DIR}" ] || fail "Not enough permissions to create \"${LLVM_BUILD_DIR}\"" local cmdline local RVAL cmdline="cmake${BUILD_EXE_EXTENSION}" r_generic_cmake_options cmdline="${cmdline} ${RVAL}" r_generic_llvm_options cmdline="${cmdline} ${RVAL}" r_generic_clang_options cmdline="${cmdline} ${RVAL}" if [ "${TARGET_ARCH}" = 'ARM' ] then r_cross_armv7_linux_llvm_options cmdline="${cmdline} ${RVAL}" fi cmdline="${cmdline} \ -DCMAKE_BUILD_TYPE='${LLVM_BUILD_TYPE}' \ -DCMAKE_INSTALL_PREFIX='${LLVM_INSTALL_PREFIX}'" if [ "${ENABLE_PYTHON}" = 'NO' ] then cmdline="${cmdline} -DLLDB_DISABLE_PYTHON:BOOL='ON'" # much less problems w/o phyton fi cmdline="${cmdline} ${CMAKE_FLAGS} '${BUILD_RELATIVE}/../${LLVM_DIR}'" ( exekutor cd "${LLVM_BUILD_DIR}" && eval_exekutor "${cmdline}" ) || exit 1 fi ( exekutor cd "${LLVM_BUILD_DIR}" && # hmm exekutor ${MAKE} ${MAKE_FLAGS} "$@" ) || exit 1 case "${MULLE_UNAME}" in windows|mingw*) if [ ! -x "${MULLE_CLANG_INSTALL_PREFIX}/bin/mulle-scan-build.bat" ] then log_verbose "Creating mulle-lldb link ..." # todo need redirect_exekutor here exekutor echo 'perl -S mulle-scan-build %*' > "${MULLE_CLANG_INSTALL_PREFIX}/bin/mulle-scan-build.bat" # this doesn't work and isn't necessary I think exekutor chmod 755 "${MULLE_CLANG_INSTALL_PREFIX}/bin/mulle-scan-build.bat" fi ;; esac } build_llvm() { log_info "Building llvm ${LLVM_VERSION} ..." _build_llvm "$@" } # # on Debian, clang doesn't build properly with gcc # use clang, if available (as CXX_COMPILER) # _build_clang() { # # Build mulle-clang # if should_build "${MULLE_CLANG_BUILD_DIR}" || [ "${RUN_CLANG_CMAKE}" = "YES" ] then exekutor mkdir -p "${MULLE_CLANG_BUILD_DIR}" 2> /dev/null local cmdline local RVAL cmdline="cmake${BUILD_EXE_EXTENSION}" r_generic_cmake_options cmdline="${cmdline} ${RVAL}" r_generic_llvm_options cmdline="${cmdline} ${RVAL}" r_generic_clang_options cmdline="${cmdline} ${RVAL}" cmdline="${cmdline} \ -DCMAKE_BUILD_TYPE='${MULLE_CLANG_BUILD_TYPE}' \ -DCMAKE_INSTALL_PREFIX='${MULLE_CLANG_INSTALL_PREFIX}'" # cmake -DCMAKE_BUILD_TYPE=Debug "../${MULLE_CLANG_DIR}" # try to build cmake with cmake ( exekutor cd "${MULLE_CLANG_BUILD_DIR}" && eval_exekutor "${cmdline} ${CMAKE_FLAGS} '${BUILD_RELATIVE}/../${MULLE_CLANG_DIR}'" ) || exit 1 fi ( exekutor cd "${MULLE_CLANG_BUILD_DIR}" && exekutor ${MAKE} ${MAKE_FLAGS} "$@" ) || exit 1 } build_clang() { log_info "Building mulle-clang ${MULLE_CLANG_VERSION} ..." _build_clang "$@" } download() { # # try to download most problematic first # instead of downloading llvm first for an hour... # but this won't work if we are doing it by the book # if [ "${BUILD_LLVM}" = "YES" -a "${BY_THE_BOOK}" != "SEPARATE" ] then download_llvm fi if [ "${BUILD_CLANG}" = "YES" ] then download_clang # # now we can derive some more values # MULLE_CLANG_VERSION="`get_mulle_clang_version "${MULLE_CLANG_DIR}" "${MULLE_CLANG_VERSION}"`" || exit 1 CLANG_VENDOR="`get_clang_vendor "${MULLE_CLANG_DIR}" "${MULLE_CLANG_VERSION}"`" || exit 1 log_verbose "CLANG_VENDOR=${CLANG_VENDOR}" log_verbose "MULLE_CLANG_VERSION=${MULLE_CLANG_VERSION}" fi if [ "${BUILD_LLDB}" = "YES" ] then download_lldb # # now we can derive some more values # # MULLE_LLDB_VERSION="`get_mulle_lldb_version "${MULLE_LLDB_DIR}" "${MULLE_LLDB_VERSION}"`" || exit 1 # LLDB_VENDOR="`get_lldb_vendor "${MULLE_LLDB_DIR}" "${MULLE_LLDB_VERSION}"`" || exit 1 # log_verbose "LLDB_VENDOR=${LLDB_VENDOR}" fi case "${BY_THE_BOOK}" in 'HACK') ( cd "${LLVM_DIR}/tools" exekutor ln -f -s "../../mulle-clang" "clang" exekutor ln -f -s "../../mulle-lldb" "lldb" ) ;; esac # should check if llvm is installed, if yes # check proper version and then use it if [ "${BUILD_LLVM}" = "YES" -a "${BY_THE_BOOK}" = "SEPARATE" ] then download_llvm fi } _build() { # should check if llvm is installed, if yes # check proper version and then use it if [ "${BUILD_LLVM}" = "YES" ] then if [ "${INSTALL_LLVM}" = "YES" ] then _build_llvm "${MAKE_INSTALL_COMMAND}" else _build_llvm "${MAKE_BUILD_COMMAND}" fi fi if [ "${BUILD_CLANG}" = "YES" -a "${BY_THE_BOOK}" = "SEPARATE" ] then _build_clang "${MAKE_INSTALL_COMMAND}" fi } build() { if [ "${OPTION_WARN}" = "YES" ] then if [ -d ${PREFIX}/lib -o \ -d ${PREFIX}/include -o \ -d ${PREFIX}/bin -o \ -d ${PREFIX}/libexec -o \ -d ${PREFIX}/share ] then log_warning "There are artifacts left over from a previous run. If you are upgrading to a new version of llvm, you should [CTRL]-[C] now and do: ${C_RESET}${C_BOLD}sudo rm -rf ${PREFIX}/bin ${BUILD_DIR} ${PREFIX}/include ${PREFIX}/lib ${PREFIX}/libexec ${PREFIX}/share" sleep 8 else if [ -d "${BUILD_DIR}" ] then log_warning "As there is an old ${BUILD_DIR} folder here, the previous build is likely to get reused. If this is not what you want, [CTRL]-[C] now and do: ${C_RESET}${C_BOLD}sudo rm -rf ${BUILD_DIR}" sleep 4 fi fi fi _build } _install_file() { local src="$1" local dstname="$2" local dstdir="$3" log_info "Install ${dstdir}/${dstname}" if [ ! -w "${dstdir}" ] then exekutor sudo_if_needed mkdir -p "${dstdir}" exekutor sudo_if_needed ln -s -f "${src}" "${dstdir}/${dstname}" else exekutor ln -s -f "${src}" "${dstdir}/${dstname}" fi } install_executable() { local src="$1" local dstname="$2" local dstdir="${3:-${SYMLINK_PREFIX}/bin}" if [ ! -x "${src}" ] then log_verbose "${src} absent, not installed." return 1 fi _install_file "${src}" "${dstname}" "${dstdir}" } install_file() { local src="$1" local dstname="$2" local dstdir="${3:-${SYMLINK_PREFIX}/bin}" if [ ! -f "${src}" ] then log_verbose "${src} absent, not installed." return 1 fi _install_file "${src}" "${dstname}" "${dstdir}" } install_mulle_clang_link() { log_info "Installing mulle-clang links ..." local clangexe clangexe="${MULLE_CLANG_INSTALL_PREFIX}/bin/clang${EXE_EXTENSION}" if [ ! -e "${clangexe}" ] then log_warning "\"${clangexe}\" not built yet" fail "download and build mulle-clang with ./install-mulle-clang before you can install" fi if [ ! -z "${CLANG_SUFFIX}" ] then install_executable "${MULLE_CLANG_INSTALL_PREFIX}/bin/mulle-clang${CLANG_SUFFIX}${EXE_EXTENSION}" \ "mulle-clang${CLANG_SUFFIX}${EXE_EXTENSION}" fi install_executable "${MULLE_CLANG_INSTALL_PREFIX}/bin/mulle-clang${EXE_EXTENSION}" \ "mulle-clang${EXE_EXTENSION}" install_executable "${MULLE_CLANG_INSTALL_PREFIX}/bin/llvm-nm${EXE_EXTENSION}" \ "mulle-nm${EXE_EXTENSION}" install_executable "${MULLE_CLANG_INSTALL_PREFIX}/bin/scan-build" \ "mulle-scan-build" case "${MULLE_UNAME}" in windows|mingw*) install_file "${MULLE_CLANG_INSTALL_PREFIX}/bin/mulle-scan-build.bat" \ "mulle-scan-build.bat" ;; esac } install_mulle_lldb_link() { log_info "Installing mulle-lldb links ..." if [ ! -f "${MULLE_CLANG_INSTALL_PREFIX}/bin/lldb${EXE_EXTENSION}" ] then fail "download and build mulle-lldb with ./bin/install-mulle-clang before you can install" fi install_executable "${MULLE_LLDB_INSTALL_PREFIX}/bin/lldb${EXE_EXTENSION}" \ mulle-lldb${EXE_EXTENSION} install_executable "${MULLE_LLDB_INSTALL_PREFIX}/bin/lldb-mi${EXE_EXTENSION}" \ mulle-lldb-mi${EXE_EXTENSION} } uninstall_executable() { local path="${1}${EXE_EXTENSION}" if [ -e "${path}" ] then log_fluff "remove ${path}" if [ ! -w "${path}" ] then exekutor sudo_if_needed rm "${path}" else exekutor rm "${path}" fi else log_fluff "${path} is already gone" fi } uninstall_mulle_clang_link() { local prefix="${1:-${MULLE_CLANG_INSTALL_PREFIX}}" log_info "Uninstalling mulle-clang links ..." if [ ! -z "${CLANG_SUFFIX}" ] then uninstall_executable "${prefix}/bin/mulle-clang${CLANG_SUFFIX}${EXE_EXTENSION}" fi uninstall_executable "${prefix}/bin/mulle-clang${EXE_EXTENSION}" uninstall_executable "${prefix}/bin/mulle-nm${EXE_EXTENSION}" uninstall_executable "${prefix}/bin/mulle-scan-build" uninstall_executable "${prefix}/bin/mulle-scan-build.bat" } uninstall_mulle_lldb_link() { local prefix="${1:-${MULLE_CLANG_INSTALL_PREFIX}}" log_info "Uninstalling mulle-lldb links ..." uninstall_executable "${prefix}/bin/mulle-lldb${EXE_EXTENSION}" uninstall_executable "${prefix}/bin/mulle-lldb-mi${EXE_EXTENSION}" } install_links() { [ "${USE_LLVM_CLANG}" = "NO" ] && install_mulle_clang_link if [ "${BUILD_LLDB}" = "YES" ] then [ "${USE_LLVM_LLDB}" = "NO" ] && install_mulle_lldb_link fi } uninstall_links() { [ "${USE_LLVM_CLANG}" = "NO" ] && uninstall_mulle_clang_link if [ "${BUILD_LLDB}" = "YES" ] then [ "${USE_LLVM_LLDB}" = "NO" ] && uninstall_mulle_lldb_link fi } main() { local OWD local PREFIX="DEFAULT" OWD="`pwd -P`" local BUILD_CLANG="${BUILD_CLANG:-YES}" local BUILD_LLVM="${BUILD_LLVM:-YES}" local BUILD_LLDB="${BUILD_LLDB:-YES}" local BUILD_RT="${BUILD_RT:-YES}" local INSTALL_LLVM="${INSTALL_LLVM:-YES}" local OPTION_NINJA="YES" local OPTION_PATCH_LLVM="YES" local OPTION_WARN="YES" local OPTION_VS32BIT="NO" local OPTION_LINKER="${LD:-DEFAULT}" local RUN_LLVM_CMAKE="DEFAULT" local TARGET_ARCH= local OPTION_TARGETS='DEFAULT' local OPTION_PARALLEL='DEFAULT' local ENABLE_PYTHON='DEFAULT' while [ $# -ne 0 ] do case "$1" in -h|--help|help) usage ;; -t|--trace) set -x ;; -f) RUN_LLVM_CMAKE="YES" ;; -n) MULLE_FLAG_EXECUTOR_DRY_RUN="YES" ;; -lx|-V) MULLE_FLAG_LOG_EXECUTOR="YES" ;; -v|--verbose) FLUFF= VERBOSE="YES" ;; -vv|-vvv|--very-verbose) FLUFF="YES" VERBOSE="YES" MULLE_FLAG_LOG_EXECUTOR="YES" ;; --all-in-one) BY_THE_BOOK="STRICT" ;; --all-in-one-with-symlinks) BY_THE_BOOK="HACK" ;; --separate|--seperate) BY_THE_BOOK="SEPARATE" BUILD_LLDB="NO" # implies ;; --build-cmake) BUILD_CMAKE="YES" ;; --with-clang|--build-clang) BUILD_CLANG="YES" ;; --python) ENABLE_PYTHON="YES" ;; --no-python) ENABLE_PYTHON="NO" ;; --linker) [ $# -eq 1 ] && fail "missing argument to $1" shift OPTION_LINKER="$1" ;; # can be useful when migrating to new llvm version --no-clang) BUILD_CLANG="NO" ;; --with-lldb|--build-lldb) BUILD_LLDB="YES" ;; --no-lldb) BUILD_LLDB="NO" ;; --vs32bit) OPTION_VS32BIT="YES" ;; --debug) LLVM_BUILD_TYPE="Debug" MULLE_CLANG_BUILD_TYPE="Debug" ;; --llvm-debug) LLVM_BUILD_TYPE="Debug" ;; --clang-debug) MULLE_CLANG_BUILD_TYPE="Debug" ;; --lldb-debug) LLDB_BUILD_TYPE="Debug" ;; --release) LLVM_BUILD_TYPE="Release" MULLE_CLANG_BUILD_TYPE="Release" ;; --release-version|-rv) [ $# -eq 1 ] && fail "missing argument to $1" shift LLVM_VERSION="$1" ;; --release-candidate|-rc) [ $# -eq 1 ] && fail "missing argument to $1" shift LLVM_RC="$1" ;; --prefix) [ $# -eq 1 ] && fail "missing argument to $1" shift PREFIX="$1" ;; --clang-prefix) [ $# -eq 1 ] && fail "missing argument to $1" shift MULLE_CLANG_INSTALL_PREFIX="$1" ;; --llvm-prefix) [ $# -eq 1 ] && fail "missing argument to $1" shift LLVM_INSTALL_PREFIX="$1" ;; --lldb-prefix) [ $# -eq 1 ] && fail "missing argument to $1" shift MULLE_LLDB_INSTALL_PREFIX="$1" ;; --symlink-prefix|--install-prefix) [ $# -eq 1 ] && fail "missing argument to $1" shift SYMLINK_PREFIX="$1" ;; --targets) [ $# -eq 1 ] && fail "missing argument to $1" shift OPTION_TARGETS="$1" ;; --target-arch) [ $# -eq 1 ] && fail "missing argument to $1" shift TARGET_ARCH="$1" ;; --no-parallel) OPTION_PARALLEL="NO" ;; --no-ninja) OPTION_NINJA="NO" ;; --no-libcxx) NO_LIBCXX="YES" ;; --no-compiler-rt) NO_COMPILER_RT="YES" ;; --no-warn) OPTION_WARN="NO" ;; --llvm-clang) USE_LLVM_CLANG="YES" BUILD_CLANG="NO" BY_THE_BOOK="STRICT" ;; --llvm-lldb) USE_LLVM_LLDB="YES" BUILD_LLDB="NO" BY_THE_BOOK="STRICT" ;; --wsl) MULLE_UNAME="windows" EXE_EXTENSION=".exe" BUILD_EXE_EXTENSION=".exe" ;; -*) echo "unknown option $1" >&2 exit 1 ;; *) break ;; esac shift done setup_fetch_environment COMMAND="${1:-default}" [ $# -eq 0 ] || shift # # it makes little sense to change these # SRC_DIR="src" LLVM_BUILD_TYPE="${LLVM_BUILD_TYPE:-Release}" LLDB_BUILD_TYPE="${LLDB_BUILD_TYPE:-${LLVM_BUILD_TYPE}}" MULLE_CLANG_BUILD_TYPE="${MULLE_CLANG_BUILD_TYPE:-${LLVM_BUILD_TYPE}}" LLVM_DIR="${SRC_DIR}/llvm" case "${BY_THE_BOOK}" in 'STRICT') # must use "clang" as name, because lldb will expect it there # and then use lldb also for consistency MULLE_CLANG_DIR="${LLVM_DIR}/tools/clang" MULLE_LLDB_DIR="${LLVM_DIR}/tools/lldb" ;; 'HACK'|'SEPARATE') MULLE_CLANG_DIR="${SRC_DIR}/mulle-clang" MULLE_LLDB_DIR="${SRC_DIR}/mulle-lldb" ;; esac BUILD_DIR="build" BUILD_RELATIVE=".." # different builds for OS Versions on OS X case "${MULLE_UNAME}" in darwin) osxversion="`sw_vers -productVersion | cut -d. -f 1-2`" BUILD_DIR="build-${osxversion}" if [ "${PREFIX}" = "DEFAULT" ] then PREFIX="${OWD}/${osxversion}" fi if [ "${ENABLE_PYTHON}" = "DEFAULT" ] then ENABLE_PYTHON='NO' fi ;; mingw) if [ "${BY_THE_BOOK}" = "HACK" ] then fail "No symlinks available on mingw. Use --all-in-one" fi ;; esac if [ "${ENABLE_PYTHON}" = "DEFAULT" ] then ENABLE_PYTHON='YES' # for vscode plugin fi if [ "${PREFIX}" = "DEFAULT" ] then PREFIX="${OWD}" fi [ -z "${PREFIX}" ] && fail "PREFIX is empty" # # just very experimental and rudimentary for now # We assume that PREFIX is set to an existing clang, and we then # just posfix the architecture onto it case "${TARGET_ARCH}" in "") HOST_PATH="$PATH" ;; "ARM"|"AArch64") # # Now with prefix set... get host compiler path first # HOST_PATH="${PREFIX}/bin:$PATH" PREFIX="${PREFIX}.${TARGET_ARCH}" BUILD_DIR="${BUILD_DIR}.${TARGET_ARCH}" if [ "${OPTION_TARGETS}" = "DEFAULT" ] then OPTION_TARGETS="ARM;AArch64" fi ;; *) fail "Can only use ARM for now. ${C_INFO}See: https://www.llvm.org/docs/HowToCrossCompileLLVM.html" ;; esac # # modify this so clang build separate picks up llvm_config # the disadvantage here is that on a subsequent run the new # compiler will be picked up, it will be different than the # host compiler and this will force a rebuild (that fails) # PATH="${PREFIX}/bin:${HOST_PATH}"; export PATH # shouldn't this be CC /CXX ? C_COMPILER="${CC}" if [ -z "${C_COMPILER}" ] then C_COMPILER="`command -v "clang"`" if [ -z "${C_COMPILER}" ] then C_COMPILER="`command -v "gcc"`" if [ -z "${C_COMPILER}" ] then C_COMPILER="gcc" fi fi C_COMPILER="`basename "${C_COMPILER}"`" fi CXX_COMPILER="${CXX}" CXX_COMPILER="${CXX_COMPILER:-${C_COMPILER}++}" if [ "${CXX_COMPILER}" = "gcc++" ] then CXX_COMPILER="g++" fi # # override for wsl # but this gets ignore eventually anyway # case "${MULLE_UNAME}" in windows) C_COMPILER="cl.exe" CXX_COMPILER="cl.exe" ;; esac # # since g++9/clang 9. or so -use-ld is not understood anymore # or passed incorrectly # if [ "${OPTION_LINKER}" = "DEFAULT" ] then local linker local linkerpreferences unset OPTION_LINKER case "${MULLE_UNAME}" in windows) linkerpreferences="link.exe" ;; mingw*) # todo: untested linkerpreferences="lld ld.lld ld link.exe" ;; *) linkerpreferences="lld ld.lld gold ld.gold ld" ;; esac for linker in ${linkerpreferences} do case "${CXX_COMPILER}" in g++) ;; *) if [ ! -z "`command -v "${linker}"`" ] then OPTION_LINKER="${linker}" log_verbose "Use linker=${linker}" break fi ;; esac done fi LLVM_INSTALL_PREFIX="${LLVM_INSTALL_PREFIX:-${PREFIX}}" MULLE_CLANG_INSTALL_PREFIX="${MULLE_CLANG_INSTALL_PREFIX:-${PREFIX}}" MULLE_LLDB_INSTALL_PREFIX="${MULLE_LLDB_INSTALL_PREFIX:-${PREFIX}}" [ -z "${LLVM_INSTALL_PREFIX}" ] && fail "LLVM_INSTALL_PREFIX is empty" LLVM_BUILD_DIR="${BUILD_DIR}/llvm.d" MULLE_CLANG_BUILD_DIR="${BUILD_DIR}/mulle-clang.d" MULLE_LLDB_BUILD_DIR="${BUILD_DIR}/mulle-lldb.d" # override this to use pre-installed llvm LLVM_BIN_DIR="${LLVM_BIN_DIR:-${LLVM_BUILD_DIR}/bin}" # if manually changed rerun cmake even if Makefile exists if [ "${LLVM_BUILD_TYPE}" != "Release" ] then RUN_LLVM_CMAKE="YES" fi if [ "${BY_THE_BOOK}" = "SEPARATE" ] then if [ "${BUILD_LLDB}" = "YES" ] then fail "You can't use --separate with --with-lldb" fi else if [ "${BUILD_CLANG}" = "YES" -a "${LLVM_BUILD_TYPE}" != "${MULLE_CLANG_BUILD_TYPE}" ] then fail "You need --separate to specify differing build types for llvm and clang" fi if [ "${BUILD_LLDB}" = "YES" -a "${LLVM_BUILD_TYPE}" != "${LLDB_BUILD_TYPE}" ] then fail "You need --separate to specify differing build types for llvm and lldb" fi fi # blurb a little, this has some advantages log_verbose "SYMLINK_PREFIX=${SYMLINK_PREFIX}" log_verbose "PREFIX=${PREFIX}" log_verbose "LLVM_INSTALL_PREFIX=${LLVM_INSTALL_PREFIX}" log_verbose "MULLE_CLANG_INSTALL_PREFIX=${MULLE_CLANG_INSTALL_PREFIX}" log_verbose "MULLE_LLDB_INSTALL_PREFIX=${MULLE_LLDB_INSTALL_PREFIX}" log_verbose "LLVM_BUILD_DIR=${LLVM_BUILD_DIR}" log_verbose "MULLE_CLANG_BUILD_DIR=${MULLE_CLANG_BUILD_DIR}" log_verbose "MULLE_LLDB_BUILD_DIR=${MULLE_LLDB_BUILD_DIR}" case "$COMMAND" in install) install_links "$@" ;; default) download setup_build_environment build ;; download) download ;; build) setup_build_environment build ;; rebuild) RUN_CLANG_CMAKE=NO RUN_LLVM_CMAKE=NO setup_build_environment build ;; uninstall) uninstall_links ;; *) fail "Unknown command \"$COMMAND\"" esac } MULLE_EXECUTABLE_PID="$$" environment_initialize log_initialize main "$@"