# -*- 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       mpi 1.0
PortGroup       active_variants 1.1

version         1.69.0
revision        11

set branch      [join [lrange [split ${version} .] 0 1] .]
set tag         [string map {. {}} ${branch}]

name            boost${tag}

checksums       rmd160  308544f184f04e4f192ac6a1118f6db787558ee6 \
                sha256  8f32d4617390d1c2d16f26a27ab60d97807b35440d45891fa340fc2648b04406 \
                size    95078138

license         Boost-1
categories      devel
platforms       darwin
maintainers     {mcalhoun @MarcusCalhoun-Lopez} \
                {mascguy @mascguy} \
                openmaintainer

description     Collection of portable C++ source libraries

long_description \
    Boost provides free portable peer-reviewed C++ \
    libraries. The emphasis is on portable libraries \
    which work well with the C++ Standard Library.

homepage        http://www.boost.org
master_sites    https://archives.boost.io/release/${version}/source
set distver     [join [split ${version} .] _]
distname        boost_${distver}
use_bzip2       yes

depends_lib     port:bzip2 \
                port:expat \
                path:lib/pkgconfig/icu-uc.pc:icu \
                port:libiconv \
                port:zlib

post-extract {
    fs-traverse dir ${workpath} {
        if {[file isdirectory ${dir}]} {
            file attributes ${dir} -permissions a+rx
        }
    }
}

# Install prefix for this port
set bprefix ${prefix}/libexec/boost/${branch}

# patch-apple-clang-no-libcxx.diff fixes a clang configuration error
# that occurs on OS X 10.7 and 10.8 due to the assumption that if
# clang is the compiler in use it must be using libc++.  Apple Clang
# uses libstdc++ by default on these OS versions.  The patch adds an
# additional BOOST_* configuration flag that is set if Apple clang is
# being used but libc++ is not.  This flag is then used to prevent
# boost or a dependent package from using functions such as
# std::forward that are only available in libc++.  Fixes build of
# libcdr on these OS versions without affecting build on 10.6 and less
# (where clang is not the default compiler) or 10.9 and up (where
# libc++ is the default).
patchfiles-append patch-apple-clang-no-libcxx.diff

# temporary patch to fix: explicit template instanciations in
# boost::serialization don't get exported with all compilers; this fix
# is already in the boost repo & will be part of a future release. See
# also the following tickets:
# https://trac.macports.org/ticket/48717
# https://svn.boost.org/trac/boost/ticket/11671
patchfiles-append patch-export_serialization_explicit_template_instantiations.diff

# revert the default tagged library name changes in 1.69.0 <
# libboost_<component>-<threading>-<arch>.dylib > back to 1.68.0
# format: libboost_<component>-<threading>.dylib; where <component> is
# the component name (e.g., system, thread), <threading> is either mt
# or st (multi or single), and <arch> is the build arch (x86, x64,
# p64, p32).
patchfiles-append patch-revert-lib-name-tagged.diff

# see https://github.com/boostorg/build/commit/b3a59d265929a213f02a451bb63cea75d668a4d9
# see https://github.com/boostorg/build/issues/440
# see https://trac.macports.org/ticket/65117
patchfiles-append patch-version_check.diff

# see https://trac.macports.org/wiki/UsingTheRightCompiler
patchfiles-append patch-compiler.diff
post-patch {
    reinplace "s|__MACPORTS_CXX__|${configure.cxx}|g" ${worksrcpath}/tools/build/src/tools/clang-darwin.jam
}

proc write_jam s {
    global worksrcpath
    set config [open ${worksrcpath}/user-config.jam a]
    puts ${config} ${s}
    close ${config}
}

compilers.choose   cc cxx
mpi.setup          -gcc

# clang: error: unknown argument: '-fcoalesce-templates'
compiler.blacklist-append {clang > 1100}

# NOTE: although technically Boost does not require C++11 compliance
# for building, doing so allows for building on more OSs than without.
# Further: Building Boost using C++11 compliance does not seem to then
# require ports depending on Boost to also require C++11 compliance,
# and requiring it does make such building easier for those ports.
configure.cxxflags-append -std=gnu++17
# ICU requires C++17
compiler.cxx_standard   2017

# It turns out that ccache and distcc can produce boost libraries that, although they
# compile without warning, have all sorts of runtime errors especially with pointer corruption.
# Since most people will now use MacPorts' pre-compiled boost, this should not be a problem.
configure.ccache    no
configure.distcc    no

configure.cmd       ./bootstrap.sh
configure.args      --without-libraries=python \
                    --without-libraries=mpi \
                    --with-icu=${prefix}

# boost build scripts default to clang on darwin
if {[string match *gcc* ${configure.compiler}]} {
    configure.args-append --with-toolset=gcc
}

# makecontext/swapcontext introduced in 10.6
# In 10.6.x Rosetta they do not work: https://trac.macports.org/ticket/64978
platform darwin {
    if {${os.major} < 10 || (${os.major} == 10 && ${configure.build_arch} eq "ppc")} {
        configure.args-append   --without-libraries=context \
                                --without-libraries=coroutine
    }
}

configure.universal_args

post-configure {

    reinplace -E "s|-install_name \"|&${bprefix}/lib/|" \
        ${worksrcpath}/tools/build/src/tools/darwin.jam

    set compileflags ""
    if {[string length ${configure.sdkroot}] != 0} {
        set compileflags "<compileflags>\"-isysroot ${configure.sdkroot}\""
    }

    set cxx_stdlibflags {}
    if {[string match *clang* ${configure.cxx}] && ${configure.cxx_stdlib} ne ""} {
        set cxx_stdlibflags -stdlib=${configure.cxx_stdlib}
    }

    # see https://trac.macports.org/ticket/55857
    # see https://svn.boost.org/trac10/ticket/13454
    write_jam "using darwin : : ${configure.cxx} : <asmflags>\"${configure.cflags} [get_canonical_archflags cc]\" <cflags>\"${configure.cflags} [get_canonical_archflags cc]\" <cxxflags>\"${configure.cxxflags} [get_canonical_archflags cxx] ${cxx_stdlibflags}\" ${compileflags} <linkflags>\"${configure.ldflags} ${cxx_stdlibflags}\" : ;"

}

build.cmd       ${worksrcpath}/b2
build.target
build.args      -d2 \
                --layout=tagged \
                --debug-configuration \
                --user-config=user-config.jam \
                -sBZIP2_INCLUDE=${prefix}/include \
                -sBZIP2_LIBPATH=${prefix}/lib \
                -sEXPAT_INCLUDE=${prefix}/include \
                -sEXPAT_LIBPATH=${prefix}/lib \
                -sZLIB_INCLUDE=${prefix}/include \
                -sZLIB_LIBPATH=${prefix}/lib \
                -sICU_PATH=${prefix} \
                variant=release \
                threading=single,multi \
                link=static,shared \
                runtime-link=shared \
                -j${build.jobs} \
                --no-cmake-config

destroot.cmd    ${worksrcpath}/b2
destroot.post_args

pre-destroot {
    destroot.args {*}${build.args} --prefix=${destroot}${bprefix}
    system "find ${worksrcpath} -type f -name '*.gch' -exec rm {} \\;"
}

proc boost_docs_install {} {
    global bprefix destroot worksrcpath name

    set docdir ${bprefix}/share/doc/${name}
    xinstall -d ${destroot}${docdir}
    set l [expr [string length ${worksrcpath}] + 1]
    fs-traverse f [glob -directory ${worksrcpath} *] {
        set dest ${destroot}${docdir}/[string range ${f} ${l} end]
        if {[file isdirectory ${f}]} {
            if {[file tail ${f}] eq "example"} {
                copy ${f} ${dest}
                continue
            }
            xinstall -d ${dest}
        } elseif {[lsearch -exact {css htm html png svg} [string range [file extension ${f}] 1 end]] != -1} {
            xinstall -m 644 ${f} ${dest}
        }
    }
}

post-destroot {
    if {[variant_isset docs]} {
        boost_docs_install
    }
}

set pythons_suffixes {27 37}

set pythons_ports {}
foreach s ${pythons_suffixes} {
    lappend pythons_ports python${s}
}

proc python_dir {} {
    global pythons_suffixes
    foreach s ${pythons_suffixes} {
        if {[variant_isset python${s}]} {
            set p python[string index ${s} 0].[string index ${s} 1]
            return [file normalize [exec ${p} -c "import sys; print(sys.prefix)"]/lib/${p}/site-packages]
        }
    }
    error "Python support not enabled."
}

foreach s ${pythons_suffixes} {
    set p python${s}
    set v [string index ${s} 0].[string index ${s} 1]
    set i [lsearch -exact ${pythons_ports} ${p}]
    set c [lreplace ${pythons_ports} ${i} ${i}]
    if { ${s} > 30 } { set bppatch "patch-boost-python3.diff" } else { set bppatch "" }
    variant ${p} description "Build Boost.Python for Python ${v}" conflicts {*}${c} debug "

        # There is a conflict with python and debug support, so we should really change the 'variant' line above
        # to end with 'conflicts ${c} debug' above. However, we leave it enabled for those who want to try it.
        # The issue has been reported to both the MacPorts team and the boost team, as per:
        # <http://trac.macports.org/ticket/23667> and <https://svn.boost.org/trac/boost/ticket/4461>

        depends_lib-append      port:${p}
        configure.args-delete   --without-libraries=python
        configure.args-append   --with-python=${prefix}/bin/python${v} --with-python-root=${prefix}/bin/python${v}

        patchfiles-append   ${bppatch} patch-tools-build-src-tools-python.jam.diff \
                            patch-tools-build-src-tools-python-2.jam.diff

        post-patch {
            reinplace s|@FRAMEWORKS_DIR@|${frameworks_dir}| ${worksrcpath}/tools/build/src/tools/python.jam
        }
    "
}

if {![variant_isset debug]} {
    set selected_python python27
    foreach s ${pythons_suffixes} {
        if {[variant_isset python${s}]} {
            set selected_python python${s}
        }
    }
    default_variants +${selected_python}
}

post-destroot {
    # To avoid checking for all Python variants, don't fail if no libs exist
    foreach f [glob -nocomplain ${destroot}${bprefix}/lib/*python*.dylib] {
        set tf [file tail ${f}]
        ln -s ${tf} ${destroot}${bprefix}/lib/[string map "${selected_python} python3" ${tf}]
        ln -s ${tf} ${destroot}${bprefix}/lib/[string map "${selected_python} python"  ${tf}]
    }
}

default_variants +no_single +no_static

variant debug description {Builds debug versions of the libraries as well} {
    build.args-delete   variant=release
    build.args-append   variant=debug,release
}

variant no_static description {Disable building static libraries} {
    build.args-delete   link=static,shared
    build.args-append   link=shared
}

variant no_single description {Disable building single-threaded libraries} {
    build.args-delete   threading=single,multi
    build.args-append   threading=multi
}

patchfiles-append patch-disable-numpy-extension.diff

variant regex_match_extra description \
    "Enable access to extended capture information of submatches in Boost.Regex" {
    notes-append "
    You enabled the +regex_match_extra variant\; see the following page for an\
    exhaustive list of the consequences of this feature:

    http://www.boost.org/doc/libs/${distver}/libs/regex/doc/html/boost_regex/ref/sub_match.html
"

    post-patch {
        reinplace {/#define BOOST_REGEX_MATCH_EXTRA/s:^// ::} \
            ${worksrcpath}/boost/regex/user.hpp
    }
}

variant docs description {Enable building documentation} {
    # No configure changes, etc; we simply check 'variant_isset' elsewhere
}

post-destroot {
    delete file {*}[glob ${destroot}${bprefix}/include/boost/python/numpy*]
}

if {[mpi_variant_isset]} {

    # see https://trac.macports.org/ticket/49748
    # see http://www.openradar.me/25313838
    configure.ldflags-append -Lstage/lib

    # There is a conflict with debug support.
    # The issue has been reported to both the MacPorts team and the boost team, as per:
    # <http://trac.macports.org/ticket/23667> and <https://svn.boost.org/trac/boost/ticket/4461>
    if {[variant_isset debug]} {
        return -code error "+debug variant conflicts with mpi"
    }

    configure.args-delete   --without-libraries=mpi

    post-configure {
        write_jam "using mpi : ${mpi.cxx} : : ${mpi.exec} ;"
    }

    if {![catch python_dir]} {

        patchfiles-append patch-libs-mpi-build-Jamfile.v2.diff

        post-destroot {
            set site_packages [python_dir]
            xinstall -d ${destroot}${site_packages}/boost
            xinstall -m 644 ${worksrcpath}/libs/mpi/build/__init__.py \
                ${destroot}${site_packages}/boost

            set f ${destroot}${bprefix}/lib/mpi.so
            if {[info exists ${f}]} {
                set l ${site_packages}/boost/mpi.so
                move ${f} ${destroot}${l}
                system "install_name_tool -id ${l} ${destroot}${l}"
            }
        }
    }
}

livecheck.type  none

if {!${universal_possible} || ![variant_isset universal]} {
    # Honour 'configure.build_arch', if not universal as per #28327
    if {[lsearch ${configure.build_arch} ppc*] != -1} {
        build.args-append   architecture=power
        if {${os.arch} ne "powerpc"} {
            build.args-append   --disable-long-double
        }
    } else {
        if {[lsearch ${configure.build_arch} *86*] != -1} {
            build.args-append   architecture=x86
        } else {
            pre-fetch {
                error "Current value of 'configure.build_arch' is not supported."
            }
        }
    }
    if {[lsearch ${configure.build_arch} *64] != -1} {
        build.args-append   address-model=64
    } else {
        build.args-append   address-model=32
    }
}

variant universal {
    build.args-append   pch=off

    if {[lsearch ${configure.universal_archs} ppc*] != -1} {
        if {[lsearch ${configure.universal_archs} *86*] != -1} {
            build.args-append   architecture=combined
        } else {
            build.args-append   architecture=power
        }

        if {${os.arch} ne "powerpc"} {
            build.args-append   --disable-long-double
        }
    } else {
        build.args-append   architecture=x86
    }

    if {[lsearch ${configure.universal_archs} *64] != -1} {
        if {[lsearch ${configure.universal_archs} i386] != -1 || [lsearch ${configure.universal_archs} ppc] != -1} {
            build.args-append   address-model=32_64
            if {[lsearch ${configure.universal_archs} ppc64] == -1} {
                post-patch {
                    reinplace "/local support-ppc64 =/s/= 1/= /" ${worksrcpath}/tools/build/src/tools/darwin.jam
                }
            }
        } else {
            build.args-append   address-model=64
        }
    } else {
        build.args-append   address-model=32
    }
}

platform powerpc {
    build.args-append   --disable-long-double
}

platform darwin 8 powerpc {
    if {[variant_isset universal]} {
        build.args-append   macosx-version=10.4
    }
}
