PortSystem              1.0
PortGroup               compiler_blacklist_versions 1.0
PortGroup               active_variants 1.1


name                    libcxx
epoch                   1
version                 5.0.1
revision                4
categories              lang
platforms               darwin
license                 MIT NCSA
maintainers             {jeremyhu @jeremyhu}
description             libc++ is a new implementation of the C++ standard library with support for C++11 and portions of C++14.
long_description        ${description} \
                        Because objects cannot be passed between different versions of the C++ runtime, this port must \
                        replace the host version in order to be used.  On Snow Leopard and earlier, this is done \
                        automatically because there is no existing host version of this library.  On Lion and later, \
                        users must build the port with +replacemnt_libcxx and install the root manually if they wish \
                        to replace the existing host implementation.

homepage                https://libcxx.llvm.org/

master_sites            https://releases.llvm.org/${version}/
dist_subdir             llvm

use_xz                  yes

set libcxxabi_distname  libcxxabi-${version}.src
set libcxx_distname     libcxx-${version}.src

distfiles               ${libcxxabi_distname}${extract.suffix} \
                        ${libcxx_distname}${extract.suffix}

checksums               libcxxabi-5.0.1.src.tar.xz \
                        rmd160  93b74a0644c1afd565938fba5e21b200b206c72a \
                        sha256  5a25152cb7f21e3c223ad36a1022faeb8a5ac27c9e75936a5ae2d3ac48f6e854 \
                        libcxx-5.0.1.src.tar.xz \
                        rmd160  1e5a22e62515382488f232039e31f0b12c08ca4f \
                        sha256  fa8f99dd2bde109daa3276d529851a3bce5718d46ce1c5d0806f46caa3e57c00

use_configure no

set roots_path ${prefix}/var/system_roots/
set root_name  ${name}-${version}-${revision}

set libcxxabi_worksrcpath   [file join ${workpath} ${libcxxabi_distname}]
set libcxx_worksrcpath      [file join ${workpath} ${libcxx_distname}]

platform darwin {
    if {${os.major} < 9} {
        pre-fetch {
            ui_error "${name} is not supported on Tiger or earlier."
            error "unsupported platform"
        }
    }

    if {${os.major} < 11} {
        post-activate {
            set dirs /
            if {${os.subplatform} eq "macosx"} {
                lappend dirs ${developer_dir}/SDKs/MacOSX[join [lrange [split ${macosx_version} .] 0 1] .].sdk
            }
            foreach d ${dirs} {
                system -W ${d} "tar xzf ${roots_path}/${root_name}.tgz"
            }
        }
    }
}

variant replacemnt_libcxx description {EXPERTS ONLY: Build a replacement libcxxabi and libcxx even if it is already part of the base OS.} {}

if {${os.major} < 11 || [variant_isset replacemnt_libcxx]} {
    variant universal {}
    default_variants +universal

    if {${os.major} < 11} {
        variant emulated_tls description {build libcxxabi and libcxx with support for emulated thread_local storage} {}

        # only selected clang versions support emulated_tls, and the emulated_tls variant
        # needs to be enabled to build libcxx with emulated_tls support
        foreach ver {5.0 6.0 7.0} {
            if {[file exists ${prefix}/bin/clang-mp-${ver}]} {
                if {[active_variants clang-${ver} emulated_tls]} {
                  default_variants-append +emulated_tls
                  compiler.whitelist-prepend macports-clang-${ver}
                }
            }
        }
    }

    compiler.blacklist *gcc* {clang < 500}

    # clang 3.5 and newer are conditionally blacklisted to prevent dependency cycles
    foreach ver {3.5 3.6 3.7 3.8 3.9 4.0 5.0 6.0 7.0 devel} {
        if {![file exists ${prefix}/bin/clang-mp-${ver}]} {
            compiler.blacklist-append macports-clang-${ver}
        }
    }

    supported_archs i386 x86_64 ppc

    if {[variant_isset universal] && [lsearch ${universal_archs} ppc] != -1} {
        # http://trac.macports.org/wiki/LibcxxOnOlderSystems#Leopardppc
        # older clang compilers produce unreliable ppc code
        compiler.blacklist-append macports-clang-3.4
    }

    post-extract {
        # delete cxa_noexception.cpp as we're not using the cmake build system
        # cmake would choose either cxa_exceptions or cxa_noexceptions
        # but the buildit script just builds every file in the src directory and you can't have both
        delete ${libcxxabi_worksrcpath}/src/cxa_noexception.cpp

        if {![variant_isset emulated_tls]} {
            # cmake doesn't include this for darwin builds, so nuke it here as well
            # however, this file is essential for emulated-tls to function
            delete ${libcxxabi_worksrcpath}/src/cxa_thread_atexit.cpp
        }

        file mkdir ${workpath}/build
        file copy ${filespath}/Makefile ${workpath}/build
    }

    patch.dir ${workpath}
    patch.pre_args -p0

    # patches for libc++abi buildit
    patchfiles-append \
        0001-libcxxabi-Update-buildit-script-to-read-EXTRA_LDFLAGS-from-the.patch \
        0002-libcxxabi-Define-_LIBCPP_BUILDING_LIBRARY-during-build-to-supp.patch \
        0003-libcxxabi-buildit-Use-undefined-dynamic_lookup-when-linking.patch    \
        0004-libcxxabi-buildit-add-nostdinc++.diff

    if {[variant_isset emulated_tls]} {
      # add emutls.c support for cxa_thread_atexit directly into libcxxabi
      # these files were taken from clang-7.0's compiler-rt subproject
      patchfiles-append \
        0005-libcxxabi-add-emutls.patch                                           \
        0006-libcxxabi-buildit-build-emutls.patch                                 \
        0007-libcxxabi-include-expose-cxa-thread-atexit.patch                     \
        0008-libcxxabi-cxa-thread-atexit-no-weak-atexit-impl.patch
    }

    # restore libc++ buildit and patches for libc++ buildit
    patchfiles-append \
        1001-Revert-Remove-the-buildit-and-testit-scripts-they-ha.patch          \
        1002-libcxx-buildit-build-fix-for-Leopard.patch \
        1003-libcxx-buildit-Set-compatibility-version-to-RC_ProjectSourc.patch \
        1004-libcxx-MacPorts-Use-LIBCXXABI_PATH-for-path-to-build-time-l.patch \
        1005-libcxx-buildit-Fix-CFLAGS-for-Leopard-and-Snow-Leopard-to-i.patch

    # patches for libc++ include files
    patchfiles-append \
        2001-Fix-local-and-iterator-when-building-with-Lion-and-n.patch    \
        2002-Fix-missing-long-long-math-prototypes-when-using-the.patch    \
        2003-implement-atomic-using-mutex-lock_guard-for-64b-ops-.patch    \
        2004-libcxx-includes-Fix-up-thread-constexpr-for-GCC-where-the-PPC-port-cant-do-longlong-constexpr.patch

    post-patch {
        system "chmod 755 ${libcxx_worksrcpath}/lib/buildit"
    }

    build.dir ${workpath}/build
    if {[vercmp [macports_version] 2.5.99] >= 0} {
    build.env-append \
        CC=${configure.cc} \
        CXX=${configure.cxx} \
        RC_XBS=1 \
        RC_ProjectSourceVersion=${version} \
        "RC_CFLAGS=[get_canonical_archflags] -I${libcxxabi_worksrcpath}/include -I${libcxx_worksrcpath}/include ${configure.optflags}" \
        TRIPLE=-apple-darwin${os.major}
    } else {
    build.env-append \
        CC="${configure.cc}" \
        CXX="${configure.cxx}" \
        RC_XBS=1 \
        RC_ProjectSourceVersion="${version}" \
        RC_CFLAGS="[get_canonical_archflags] -I${libcxxabi_worksrcpath}/include -I${libcxx_worksrcpath}/include ${configure.optflags}" \
        TRIPLE="-apple-darwin${os.major}"
    }
    build.args-append \
        LIBCXXABI_PATH=${libcxxabi_worksrcpath} \
        LIBCXX_PATH=${libcxx_worksrcpath} \
        LIBCXXABI_DYLIB_PATH=${build.dir}/libc++abi.dylib

    # We want to use the host's libc++ everywhere because we want to ensure
    # that only *ONE* copy of this library is in any process's address space.
    # On Snow Leopard and earlier, this port provides this library in /usr for
    # binary compatibility with Lion and later.
    #
    # On newer OS version, this port does not install the content to /usr and
    # just leaves it to expert users who may want to replace their system
    # runtime.

    destroot {
        xinstall -m 755 -d ${destroot}${roots_path}/${root_name}/usr/lib

        xinstall -m 755 ${libcxxabi_worksrcpath}/lib/libc++abi.dylib ${destroot}${roots_path}/${root_name}/usr/lib

        xinstall -m 755 ${libcxx_worksrcpath}/lib/libc++.1.dylib ${destroot}${roots_path}/${root_name}/usr/lib
        ln -s libc++.1.dylib ${destroot}${roots_path}/${root_name}/usr/lib/libc++.dylib

        xinstall -m 755 -d ${destroot}${roots_path}/${root_name}/usr/include
        xinstall -m 755 ${libcxxabi_worksrcpath}/include/__cxxabi_config.h ${destroot}${roots_path}/${root_name}/usr/include
        xinstall -m 755 ${libcxxabi_worksrcpath}/include/cxxabi.h ${destroot}${roots_path}/${root_name}/usr/include

        system -W ${destroot}${roots_path}/${root_name} "tar czf ../${root_name}.tgz ."
        delete ${destroot}${roots_path}/${root_name}
    }
} else {
    supported_archs noarch
    distfiles
    build {}
    destroot {
        xinstall -d ${destroot}${prefix}/share/doc/${name}
        system "echo ${name} is an empty port on this OS version because the functionality is already provided by the OS. > ${destroot}${prefix}/share/doc/${name}/README.txt"
    }
}

livecheck.type none