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

PortSystem              1.0
PortGroup               python 1.0
PortGroup               github 1.0
PortGroup               compilers 1.0
PortGroup               compiler_blacklist_versions 1.0

name                    py-numpy
categories-append       math
license                 BSD
maintainers             {michaelld @michaelld} openmaintainer
description             The core utilities for the scientific library scipy for Python
long_description        {*}${description}

github.setup            numpy numpy 1.26.2 v
revision                0

checksums               rmd160  637c49bcd078536865dd7f720a85bd1f7bbd2de2 \
                        sha256  f65738447676ab5777f11e6bbbdb8ce11b785e105f690bc45966574816b6d3ea \
                        size    15664248

if {${name} ne ${subport}} {
    # the python PortGroup puts compiler names in build.env and destroot.env
    # for this to be done correctly, the following must be located before python.versions
    pre-build    { set_compilers }
    pre-destroot { set_compilers }
}

python.versions         27 35 36 37 38 39 310 311 312

# http://trac.macports.org/ticket/34562
python.consistent_destroot yes

# TODO: Fix the +universal variant.  This port is a fairly deep dependency and needs to be able to support +universal.
# https://trac.macports.org/ticket/48263
#universal_variant no

# some older Clang say they support SIMD when they don't
compiler.blacklist-append {clang < 1100}

# require a C/C++11 compliant compiler, to match SciPy and allow some
# older macOS to build this port.
compiler.c_standard   2011
compiler.cxx_standard 2011

# default livecheck
github.livecheck.regex {(\d+(?:\.\d+)+)}

if {${name} ne ${subport}} {
    set PATCH_PY_EXT ""
    if {${python.version} == 27} {
        github.setup        numpy numpy 1.16.6 v
        checksums           rmd160  cbb34cf0981ea142ff45722d05a9daad20a134ea \
                            sha256  2dce87065d5de1a83485cfb3de5e4e793787890f5c1dcc3536a9cabf2e1620af \
                            size    4691852
        revision            4
        set PATCH_PY_EXT    ".27"
        patchfiles-append   patch-cpu-detection.py.27.patch
        livecheck.url       https://numpy.org/doc/stable/release.html
        livecheck.regex     {(1\.16(?:\.\d+)+)}
    } elseif {${python.version} == 35} {
        github.setup        numpy numpy 1.18.5 v
        checksums           rmd160  c14f2725afe0f7420d69a6f9ed5744639a2d2b31 \
                            sha256  4a421fdf82dbb3dce7e62400f69c43722b530db109c3321c6c95452f166560d9 \
                            size    5167349
        revision            3
        patchfiles-append   patch-cpu-detection.py.35.patch
        set PATCH_PY_EXT    ".35"
        livecheck.url       https://numpy.org/doc/stable/release.html
        livecheck.regex     {(1\.18(?:\.\d+)+)}
    } elseif {${python.version} == 36} {
        github.setup        numpy numpy 1.19.5 v
        checksums           rmd160 66861032bbd7c1f7e7741d913c9edf6c0b8be68a \
                            sha256 40e0a919cb8741556f8402cb7ec862b3b27903725ba59af44fd5b88620c5a7e1 \
                            size   7037758
        revision            2
        # because I pushed 1.20 and it requires Py37+ and so reverting back to 1.19
        epoch               1
        set PATCH_PY_EXT    ".36"
        livecheck.url       https://numpy.org/doc/stable/release.html
        livecheck.regex     {(1\.19(?:\.\d+)+)}
    } elseif {${python.version} == 37} {
        github.setup        numpy numpy 1.21.6 v
        checksums           rmd160  e8824bb384025421d8c637f1671b7010c9a79471 \
                            sha256  d4efc6491a1cdc00f9eca9bf2c1aa13671776f6941c7321ddf75b45c862f0c2c \
                            size    9445717
        revision            1
        github.tarball_from releases
        set PATCH_PY_EXT    ".37"
        livecheck.regex     {(1\.21(?:\.\d+)+)}
        python.pep517       no
    } elseif {${python.version} == 38} {
        github.setup        numpy numpy 1.24.1 v
        checksums           rmd160  dd2df59cb48926eb460143f617a552b8009af11d \
                            sha256  2386da9a471cc00a1f47845e27d916d5ec5346ae9696e01a8a34760858fe9dd2 \
                            size    10903184
        revision            1
        github.tarball_from releases
        set PATCH_PY_EXT    ".38"
        livecheck.regex     {(1\.24(?:\.\d+)+)}
        if {${python.pep517}} {
            build.args      --skip-dependency-check
        }
    } else {
        github.tarball_from releases
        # This is a temporary fix due to:
        # https://github.com/numpy/numpy/issues/25406
        # https://github.com/mesonbuild/meson-python/pull/553
        if {${os.platform} eq "darwin" && ${os.major} < 12} {
            python.pep517   no
        } else {
            depends_build-append \
                            port:ninja
        }
        depends_lib-append  port:py${python.version}-pyproject_metadata
        patchfiles-append   patch-build_cython_path.diff
        build.env-append    CYTHON=${prefix}/bin/cython-${python.branch}
        post-extract {
            # https://github.com/numpy/numpy/pull/24970
            system "chmod -x ${worksrcpath}/numpy/_build_utils/tempita.py"
        }
    }

    patchfiles-append       patch-numpy_core_setup.py${PATCH_PY_EXT}.diff \
                            patch-numpy_tests_test_scripts.py${PATCH_PY_EXT}.diff \
                            patch-fcompiler_g95${PATCH_PY_EXT}.diff \
                            patch-arm64_min${PATCH_PY_EXT}.diff
    if {[variant_isset atlas] || [variant_isset openblas]} {
        # force LDFLAGS for correct linking of the modules
        # for non-Apple GCC compilers
        patchfiles-append   patch-numpy_linalg_setup.py${PATCH_PY_EXT}.diff
    }

    compilers.setup         -clang -gcc44 -gcc45 \
                            -gcc46 -gcc47 -gcc48 -g95

    depends_lib-append      port:fftw-3 \
                            path:bin/cython-${python.branch}:py${python.version}-cython

    if {${python.version} < 312} {
        build.env-append    SETUPTOOLS_USE_DISTUTILS=stdlib
        destroot.env-append SETUPTOOLS_USE_DISTUTILS=stdlib
    }

    pre-build {
        build.env-append        ARCHFLAGS=[get_canonical_archflags ld]
    }

    pre-destroot {
        destroot.env-append     ARCHFLAGS=[get_canonical_archflags ld]
    }

    variant atlas conflicts openblas mkl description "Use MacPorts ATLAS Libraries" {
        depends_lib-append      port:atlas
    }

    variant openblas conflicts atlas mkl description "Use MacPorts OpenBLAS Libraries" {
        depends_lib-append  path:lib/libopenblas.dylib:OpenBLAS

        # See: https://trac.macports.org/ticket/66685
        supported_archs     arm64 ppc ppc64 x86_64
    }

    variant mkl conflicts atlas openblas description "Use MacPorts MKL Libraries" {
        depends_lib-append  port:py${python.version}-mkl \
                            port:py${python.version}-mkl-include

        # set absolute path to remove references to @rpath/libmkl_rt.2.dylib
        post-destroot {
            foreach soname [exec find ${destroot}${python.pkgd}/numpy -name "*.so"] {
                system "install_name_tool -change @rpath/libmkl_rt.2.dylib ${python.prefix}/lib/libmkl_rt.2.dylib ${soname}"
            }
        }
    }

    # Make +openblas a default variant, at least temporarily, to
    # overcome issues with polyfit. see also:
    # https://trac.macports.org/ticket/56954
    # https://github.com/numpy/numpy/issues/12230
    # However, +gfortran+openblas is broken on i386, see above
    if {![variant_isset atlas] &&
        ![variant_isset openblas] &&
        ![variant_isset mkl] &&
        ${configure.build_arch} ni {i386 arm64}} {
        default_variants-append +openblas
    }

    # when using ATLAS (whether by default or specified by the user via
    # the +atlas variant) ...
    if {[variant_isset atlas]} {

        # when using non-Apple GCC for universal install, it can
        # create binaries only for the native OS architecture, at
        # either 32 or 64 bits.  Restrict the supported archs
        # accordingly.
        if {${os.arch} eq "i386"} {
            supported_archs         i386 x86_64
        } elseif {${os.arch} eq "powerpc"} {
            supported_archs         ppc ppc64
        }

        pre-fetch {
            # numpy needs fortran; so we only need to check if atlas is
            # compiled with +nofortran
            if {![catch {set result [active_variants atlas "" nofortran]}]} {
                if {!$result} {
                    return -code error \
"You have selected the +atlas variant but atlas was built with +nofortran.\
numpy needs a fortran enabled atlas. Please rebuild atlas without the +nofortran\
variant."
                }
            }
        }

        # use MacPorts atlas
        build.env-append    OPENBLAS=None \
                            MKLROOT=None \
                            ATLAS=${prefix}/lib \
                            LAPACK=${prefix}/lib \
                            BLAS=${prefix}/lib
        destroot.env-append OPENBLAS=None \
                            MKLROOT=None \
                            ATLAS=${prefix}/lib \
                            LAPACK=${prefix}/lib \
                            BLAS=${prefix}/lib

    } elseif {[variant_isset openblas]} {

        # use MacPorts OpenBLAS
        build.env-append    OPENBLAS=${prefix}/lib \
                            MKLROOT=None \
                            ATLAS=None
        destroot.env-append OPENBLAS=${prefix}/lib \
                            MKLROOT=None \
                            ATLAS=None

    } elseif {[variant_isset mkl]} {

        # use MacPorts MKL
        post-patch {
            reinplace "s|mkl_rt|mkl_rt.2|g" ${worksrcpath}/numpy/distutils/system_info.py
        }

        build.env-append    OPENBLAS=None \
                            MKLROOT=${python.prefix} \
                            ATLAS=None
        destroot.env-append OPENBLAS=None \
                            MKLROOT=${python.prefix} \
                            ATLAS=None

    } else {
        # use Accelerate BLAS
        build.env-append    OPENBLAS=None \
                            ATLAS=None \
                            MKLROOT=None \
                            LAPACK=/usr/lib \
                            BLAS=/usr/lib
        destroot.env-append OPENBLAS=None \
                            ATLAS=None \
                            MKLROOT=None \
                            LAPACK=/usr/lib \
                            BLAS=/usr/lib
    }

    platform darwin 8 {
        if {${python.version} < 37} {
            patchfiles-append patch-Tiger-without-dflcn-header.diff
        }
    }

    post-patch {

        # https://trac.macports.org/ticket/46392
        if {${os.arch} eq "powerpc"} {
            reinplace "s,'-O3','-O2'," \
                ${worksrcpath}/numpy/distutils/fcompiler/gnu.py
        }

        if { [use_wrapper] } {
            # Prepare wrappers
            file copy -force ${filespath}/wrapper-template \
                ${worksrcpath}/c-wrapper
            file copy -force ${filespath}/wrapper-template \
                ${worksrcpath}/f-wrapper
            file copy -force ${filespath}/wrapper-template \
                ${worksrcpath}/cxx-wrapper

            reinplace   "s|@@@|${configure.cc}|" ${worksrcpath}/c-wrapper
            reinplace   "s|---|\\\\.c|" ${worksrcpath}/c-wrapper
            reinplace   "s|&&&|${prefix}|" ${worksrcpath}/c-wrapper

            reinplace   "s|@@@|${configure.cxx}|" ${worksrcpath}/cxx-wrapper
            reinplace   "s#---#(\\\\.C|\\\\.cpp|\\\\.cc)#" \
                ${worksrcpath}/cxx-wrapper
            reinplace   "s|&&&|${prefix}|" ${worksrcpath}/cxx-wrapper

            reinplace   "s|@@@|${configure.f90}|" ${worksrcpath}/f-wrapper
            reinplace   "s|---|\\\\.f|" ${worksrcpath}/f-wrapper
            reinplace   "s|&&&|${prefix}|" ${worksrcpath}/f-wrapper
        }

        if {[variant_isset atlas]} {
            # We must link against libSatlas or libTatlas, not libAtlas
            if {[file exists ${prefix}/lib/libtatlas.dylib]} {
                reinplace -E \
                    "s|_lib_atlas = \\\['atlas'\\\]|_lib_atlas = \\\['tatlas'\\\]|" \
                    ${worksrcpath}/numpy/distutils/system_info.py
            } elseif {[file exists ${prefix}/lib/libsatlas.dylib]} {
                reinplace -E \
                    "s|_lib_atlas = \\\['atlas'\\\]|_lib_atlas = \\\['satlas'\\\]|" \
                    ${worksrcpath}/numpy/distutils/system_info.py
            } else {
                return -code error "Unable to find Atlas dylibs. Bailing out."
            }
        }
    }

    if {![fortran_variant_isset]} {
        default_variants-append +gfortran
    }

    # determine if special wrapper values are needed for compiler names
    # a procedure is needed since variants from PortGroup compilers must
    # be evaluated before it can be determined if clang is being used
    proc use_wrapper {} {
        global configure.cc

        if {[variant_exists universal] && [variant_isset universal]} {
            if {[variant_isset atlas]} {
                # uses fortran as a linker, which does not handle multiple -arch values properly
                return 1
            }
            if {![string match *clang* ${configure.cc}]} {
                # gcc compilers do not handle multiple -arch values properly
                return 1
            }
        }
        return 0
    }

    # set compiler names
    proc set_compilers {} {
        global configure.cc configure.cxx configure.fc worksrcpath

        if {[use_wrapper]} {
            # override values set in compilers PortGroup
            configure.cc  ${worksrcpath}/c-wrapper
            configure.cxx ${worksrcpath}/cxx-wrapper
            configure.fc  ${worksrcpath}/f-wrapper
            configure.f77 ${worksrcpath}/f-wrapper
            configure.f90 ${worksrcpath}/f-wrapper
        }
    }
}
