# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:filetype=tcl:et:sw=4:ts=4:sts=4

PortSystem          1.0
PortGroup           cmake 1.1
PortGroup           muniversal 1.0

# clang-11 is the last clang which can be build with the last version of cmake to not require c++11.
name                clang-11-bootstrap

version             11.1.0
revision            6
epoch               0

platforms           {darwin < 23}
categories          lang
maintainers         nomaintainer

license             NCSA

description         clang-11 with minimal MacPorts patches pegged at version ${version}.
long_description    ${description} This port depends only on bootstrap dependencies.

homepage            https://llvm.org/


master_sites        https://github.com/llvm/llvm-project/releases/download/llvmorg-${version}
distname            llvm-project-${version}.src

checksums           rmd160  f566b4b75c8f30418f19069a9a84864ead766401 \
                    sha256  74d2529159fd118c3eac6f90107b5611bccc6f647fdea104024183e8d5e25831 \
                    size    84065492

# no Clang / LLVM for PowerPC yet
supported_archs     arm64 i386 x86_64

depends_extract     port:xz-bootstrap
depends_skip_archcheck-append \
                    xz-bootstrap

extract.suffix      .tar.xz
extract.cmd         ${prefix}/libexec/xz-bootstrap/bin/xz

depends_build-append \
                    port:python27-bootstrap
depends_skip_archcheck-append \
                    python27-bootstrap

# Use cmake-bootstrap
depends_build-replace \
                    path:bin/cmake:cmake port:cmake-bootstrap
depends_skip_archcheck-append \
                    cmake-bootstrap
configure.cmd       ${prefix}/libexec/cmake-bootstrap/bin/cmake


worksrcdir          llvm-project/llvm
patch.dir           ${workpath}/llvm-project

post-extract {
    ln -s ${workpath}/${distname}                       ${workpath}/llvm-project
    ln -s ${workpath}/llvm-project/clang                ${worksrcpath}/tools/clang
    ln -s ${workpath}/llvm-project/compiler-rt          ${worksrcpath}/projects/compiler-rt
    ln -s ${workpath}/llvm-project/libcxx               ${worksrcpath}/projects/libcxx
    ln -s ${workpath}/llvm-project/libcxxabi            ${worksrcpath}/projects/libcxxabi
    ln -s ${workpath}/llvm-project/lld                  ${worksrcpath}/projects/lld
    ln -s ${workpath}/llvm-project/clang-tools-extra    ${worksrcpath}/tools/clang/tools/extra
}

patch.pre_args-replace  -p0 -p1
# all patches are available as git tree: https://github.com/catap/llvm-project/tree/clang-11-bootstrap
patchfiles          0001-Define-EXC_MASK_CRASH-and-MACH_EXCEPTION_CODES-if-th.patch \
                    0002-MacPorts-Only-Don-t-embed-the-deployment-target-in-t.patch \
                    0003-Fix-build-issues-pre-Lion-due-to-missing-a-strnlen-d.patch \
                    0004-Fix-build-issues-pre-Lion-due-to-missing-a-memmem-de.patch \
                    0005-Threading-Only-call-pthread_setname_np-on-SnowLeopar.patch \
                    0006-Only-call-setpriority-PRIO_DARWIN_THREAD-0-PRIO_DARW.patch \
                    0007-dsymutil-fix-build-on-Leopard.patch \
                    0008-lib-Support-Unix-Path.inc-define-COPYFILE_CLONE-if-n.patch \
                    0009-MacPorts-Only-Fix-name-of-scan-view-executable-insid.patch \
                    0009-x86-pad-for-align.diff \
                    0010-default-to-libcxx-on-all-systems.patch \
                    0011-Default-to-fragile-ObjC-runtime-when-targeting-darwi.patch \
                    0012-Fixup-libstdc-header-search-paths-for-older-versions.patch \
                    0013-Fix-float.h-to-work-on-Snow-Leopard-and-earlier.patch \
                    0014-compiler-rt-add-some-defs-missing-in-older-SDKs.patch \
                    0015-10.5-and-less-compiler-rt-work-around-no-libdispatch.patch \
                    0016-Fix-missing-long-long-math-prototypes-when-using-the.patch \
                    0017-implement-atomic-using-mutex-lock_guard-for-64b-ops-.patch \
                    0018-libcxx-src-chrono.cpp-fix-build-by-older-SDKs.patch \
                    0019-compiler-rt-allow-build-before-10.7.patch \
                    0020-compiler-rt-added-CMAKE_OSX_DEPLOYMENT_TARGET-fallba.patch \
                    0021-add-back-runtime-libraries-used-on-10.4-and-10.5.patch \
                    0022-Don-t-look-into-sysroot-for-C-headers-if-they-are-fo.patch \
                    0023-disable-DirectoryWatcher-when-builds-by-GCC.patch \
                    0024-Use-for-long-options-in-help-text.patch \
                    0025-compatibility-with-xar-on-macOS-10.5.patch \
                    0026-clang-support-macports-libstdcxx.patch \
                    0027-compiler-rt-fix-building-by-GCC.patch \
                    0028-compiler-rt-allow-to-define-required-archs.patch \
                    0029-compiler-rt-atomic-which-can-be-compiled-by-GCC.patch \
                    0035-clang-Implement-the-using_if_exists-attribute.patch \
                    0036-clang-Parse-Add-parsing-support-for-C-attributes-on-.patch

# sterilize MacPorts build environment; we want nothing picked up from MP prefix
compiler.cpath
compiler.library_path

configure.cxx_stdlib

configure.cflags
configure.cxxflags
configure.cppflags
configure.optflags
configure.ldflags

configure.universal_cflags
configure.universal_cxxflags
configure.universal_cppflags
configure.universal_ldflags
configure.universal_args

configure.ccache    no
configure.distcc    no

# sterilize PATH
configure.env-append \
                    PATH=${workpath}/bins:/usr/bin:/bin:/usr/sbin:/sbin
build.env-append    PATH=${workpath}/bins:/usr/bin:/bin:/usr/sbin:/sbin

cmake.build_type    Release
cmake.generator     {Unix Makefiles}

# Install everything into libexec
cmake.install_prefix \
                    ${prefix}/libexec/${name}
cmake.install_rpath

configure.pre_args-replace \
                    {*}[cmake::system_prefix_path] \
                    -DCMAKE_SYSTEM_PREFIX_PATH="${cmake.install_prefix}\;/usr"

configure.pre_args-replace \
                    {*}[cmake::rpath_flags] \
                    -DCMAKE_BUILD_WITH_INSTALL_RPATH:BOOL=OFF

configure.pre_args-delete \
                    {*}[cmake::module_path]

configure.pre_args-delete \
                    {*}[cmake::ccaching]

configure.pre_args-delete \
                    -DCMAKE_INSTALL_NAME_DIR="${cmake.install_prefix}/lib"

platform darwin {
    if {${os.major} == 14} {
        patchfiles-append \
                    0030-fix-building-on-10.10-by-GCC-10.patch
    }

    if {${os.major} <= 11} {
        # xpc.h available 10.7 but doesn't support nullable features
        # xpc.h works currently on 10.8+
        # toggle enabled in https://reviews.llvm.org/D59808
        configure.args-append \
                    -DCLANGD_BUILD_XPC=OFF
    }

    if {${os.major} <= 10} {
        # avoid need for thread_local_storage
        configure.args-append \
                    -DCLANG_ENABLE_CLANGD=OFF \
                    -DLLVM_ENABLE_BACKTRACES=OFF

        # reexported_symbols_list is available on 10.7+ only, used by libcxx
        patchfiles-append \
                    0031-fix-build-of-shared-libc-.dylib-on-10.7.patch

        # the libcxx installed by MacPorts on darwin 10 and less does not correspond to Apple's builtin libcxx
        patchfiles-append \
                    0032-disable-Apple-libc-Availability-tests.patch
    }

    if {${os.major} <= 9} {
        # TO DO: the blocks functionality can be replaced by libblocksruntime
        # this might be integrated into clang on < 10.6
        patchfiles-append \
                    0033-Leopard-Default-to-fno-blocks.patch
    }
}

configure.args-append \
                    -DCLANG_ENABLE_ARCMT=OFF \
                    -DCLANG_ENABLE_STATIC_ANALYZER=OFF \
                    -DCOMPILER_RT_ENABLE_IOS=OFF \
                    -DCOMPILER_RT_ENABLE_TVOS=OFF \
                    -DCOMPILER_RT_ENABLE_WATCHOS=OFF \
                    -DDARWIN_PREFER_PUBLIC_SDK=ON \
                    -DLLVM_BINDINGS_LIST=none \
                    -DLLVM_BUILD_UTILS=OFF \
                    -DLLVM_ENABLE_LIBEDIT=OFF \
                    -DLLVM_ENABLE_LIBXML2=OFF \
                    -DLLVM_ENABLE_PROJECTS="clang\;compiler-rt" \
                    -DLLVM_ENABLE_TERMINFO=OFF \
                    -DLLVM_ENABLE_ZLIB=OFF \
                    -DLLVM_INCLUDE_BENCHMARKS=OFF \
                    -DLLVM_INCLUDE_DOCS=OFF \
                    -DLLVM_INCLUDE_EXAMPLES=OFF \
                    -DLLVM_INCLUDE_GO_TESTS=OFF \
                    -DLLVM_INCLUDE_TESTS=OFF \
                    -DLLVM_INCLUDE_UTILS=OFF \
                    -DPYTHON_EXECUTABLE=${prefix}/libexec/python27-bootstrap/bin/python2.7

if {${configure.build_arch} eq "arm64"} {
    configure.args-append \
                    -DLLVM_TARGETS_TO_BUILD="AArch64\;X86"
} else {
    configure.args-append \
                    -DLLVM_TARGETS_TO_BUILD=X86
}

if {${configure.sdkroot} ne ""} {
    configure.args-append \
                    -DDARWIN_osx_SYSROOT="${configure.sdkroot}" \
                    -DDEFAULT_SYSROOT="${configure.sdkroot}"
} else {
    # compiler-rt does a broad search for an SDK it likes, but this
    # search fails on older systems that don't have a MacOSX.sdk
    configure.args-append \
                    -DDARWIN_osx_SYSROOT=/
}

if {${os.major} <= 18} {
    # on systems that might build i386, we need atomic builtins
    # https://trac.macports.org/ticket/58712
    configure.args-append \
                    -DCOMPILER_RT_EXCLUDE_ATOMIC_BUILTIN=OFF
}

if {${os.major} < 11} {
    variant emulated_tls description { enable c11/c++11 thread_local_storage support on older systems using emulated-tls } {
        # use emulated-tls to support thread_local on systems prior to 10.7
        patchfiles-append \
                    0034-Support-emulated-TLS-before-10.7.patch
    }

    default_variants-append \
                    +emulated_tls
}

# Be default Catalina and Mojave support a single arch at MacPorts
if {${os.major} < 18 || ${os.major} > 19} {
    default_variants-append     +universal
}

compiler.cxx_standard \
                    2011

# macOS 10.14 the first one which minimal version of toolchain can build it
if {${os.platform} eq "darwin" && ${os.major} < 18} {

    configure.compiler.add_deps \
                    no

    depends_build-append \
                    port:gcc10-bootstrap

    # Leopard is the first macOS which supports Roseta
    # See: https://trac.macports.org/ticket/67284
    if {${os.major} > 8} {
        pre-configure {
            file mkdir ${workpath}/bins

            set gcc [open "${workpath}/bins/gcc" w 0755]
            puts ${gcc} "#!/bin/sh"
            puts ${gcc} "arch -arch $\{BUILD_ARCH:-${configure.build_arch}\} ${prefix}/libexec/gcc10-bootstrap/bin/gcc \"\$@\""
            close ${gcc}

            set gxx [open "${workpath}/bins/g++" w 0755]
            puts ${gxx} "#!/bin/sh"
            puts ${gxx} "arch -arch $\{BUILD_ARCH:-${configure.build_arch}\} ${prefix}/libexec/gcc10-bootstrap/bin/g++ \"\$@\""
            close ${gxx}
        }

        configure.cc        ${workpath}/bins/gcc
        configure.cxx       ${workpath}/bins/g++
    } else {
        configure.cc        ${prefix}/libexec/gcc10-bootstrap/bin/gcc
        configure.cxx       ${prefix}/libexec/gcc10-bootstrap/bin/g++
    }

    # prevent it from linking against gcc's libstdc++.6.dylib and libgcc_s.1.1.dylib
    configure.ldflags-append \
                    -static-libstdc++ -static-libgcc

    # Profiling can't be build by GCC with unknown reason.
    # Some part of profiling is used by cc_kext also.
    configure.args-append \
                    -DCOMPILER_RT_BUILD_PROFILE=OFF \
                    -DDARWIN_osx_SKIP_CC_KEXT=ON

    # sanitizer_common is using os/trace.h which can't be build by GCC
    # Xray and Sanitizer forces to build sanitizer_common => disable both
    configure.args-append \
                    -DCOMPILER_RT_BUILD_SANITIZERS=OFF \
                    -DCOMPILER_RT_BUILD_XRAY=OFF

}

if {${os.major} < 11} {
    # see https://trac.macports.org/ticket/61778
    depends_run-append  port:libstdcxx_clang_fix
}

post-patch {
    reinplace "s|@@MACPORTS_GCC_INCLUDE_DIR@@|${prefix}/include/gcc/c++|g" \
        ${worksrcpath}/tools/clang/lib/Frontend/InitHeaderSearch.cpp \
        ${worksrcpath}/tools/clang/lib/Driver/ToolChains/Darwin.cpp
    reinplace "s|@@MACPORTS_HOST_NAME@@|${configure.build_arch}-apple-darwin${os.major}|g" \
        ${worksrcpath}/tools/clang/lib/Driver/ToolChains/Darwin.cpp
    reinplace "s|@@MACPORTS_libstdc++@@|${prefix}/lib/libgcc/libstdc++.6.dylib|g" \
        ${worksrcpath}/tools/clang/lib/Driver/ToolChains/Darwin.cpp

    # GCC was built for ${configure.build_arch}-apple-darwin${os.major}
    # if GCC was also built universal, it has an extra include directory
    # if ${configure.build_arch} is 32-bit, there is an extra 64-bit subdirectory
    # if ${configure.build_arch} is 64-bit, there is an extra 32-bit subdirectory
    # MacPorts GCC cannot compile across platforms
    switch ${configure.build_arch} {
        x86_64 {
            reinplace {s|@@MACPORTS_TEST_32_64@@|getTriple().getArch() == llvm::Triple::x86_64 ? "" : "i386"|g} \
                ${worksrcpath}/tools/clang/lib/Driver/ToolChains/Darwin.cpp
        }
        i386 {
            reinplace {s|@@MACPORTS_TEST_32_64@@|getTriple().getArch() == llvm::Triple::x86_64 ? "x86_64" : ""|g} \
                ${worksrcpath}/tools/clang/lib/Driver/ToolChains/Darwin.cpp
        }
        ppc64 {
            reinplace {s|@@MACPORTS_TEST_32_64@@|getTriple().getArch() == llvm::Triple::ppc64 ? "" : "ppc"|g} \
                ${worksrcpath}/tools/clang/lib/Driver/ToolChains/Darwin.cpp
        }
        ppc {
            reinplace {s|@@MACPORTS_TEST_32_64@@|getTriple().getArch() == llvm::Triple::ppc64 ? "ppc64" : ""|g} \
                ${worksrcpath}/tools/clang/lib/Driver/ToolChains/Darwin.cpp
        }
        arm64 {
            reinplace {s|@@MACPORTS_TEST_32_64@@|""|g} \
                ${worksrcpath}/tools/clang/lib/Driver/ToolChains/Darwin.cpp
        }
    }
}

if {${universal_possible} && [variant_isset universal]} {
    foreach arch ${universal_archs_supported} {
        lappend merger_configure_env(${arch}) BUILD_ARCH=${arch}
        lappend merger_build_env(${arch}) BUILD_ARCH=${arch}
        lappend merger_configure_args(${arch}) \
                            -DCOMPILER_RT_TOOLCHAIN_ARCHES=${arch} \
                            -DDARWIN_osx_BUILTIN_ALL_POSSIBLE_ARCHS=${arch}
    }
} else {
    configure.args-append   -DCOMPILER_RT_TOOLCHAIN_ARCHES=${configure.build_arch} \
                            -DDARWIN_osx_BUILTIN_ALL_POSSIBLE_ARCHS=${configure.build_arch}
}

merger_arch_flag            yes
merger_arch_compiler        yes
merger_must_run_binaries    yes

post-destroot {
    system "ditto ${worksrcpath}/projects/libcxx/include ${destroot}${cmake.install_prefix}/include/c++/v1"
}

notes "
To use this bootstrap version of clang instead of the default compiler, add the \
following lines to the Portfile:

depends_build-append    port:${name}
configure.cc            \$\{prefix\}/libexec/${name}/bin/clang
configure.cxx           \$\{prefix\}/libexec/${name}/bin/clang++
"

livecheck.type      none
