# -*- 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           gitlab 1.0
PortGroup           select 1.0
PortGroup           deprecated 1.0
PortGroup           openssl 1.0

gitlab.instance     https://foss.heptapod.net
gitlab.setup        pypy pypy 7.3.9
revision            0

categories          lang python devel
license             MIT PSF
maintainers         {danchr @danchr} openmaintainer

platforms           darwin

homepage            https://www.pypy.org/
master_sites        https://downloads.python.org/${name}

depends_build       port:pkgconfig \
                    port:py27-docutils
depends_lib         port:libffi \
                    port:sqlite3 \
                    port:bzip2 \
                    port:gettext \
                    port:gdbm \
                    port:expat \
                    port:ncurses
depends_run         port:python_select
select.entries      [list python python-$subport $subport]

patchfiles          make_output.diff \
                    patch-no-cffi-at-build.diff \
                    ffiplatform.py.diff \
                    paths.diff

deprecated.eol_version no
use_configure       no

# no effort has been made to get the JIT working anywhere but x86-64,
# and without that, PyPy has little or no benefit over CPython; if
# you're looking for support for Apple Silicon - or ARM64 - see
# https://morepypy.blogspot.com/2020/12/mac-meets-arm64.html and
# https://trac.macports.org/ticket/63486#comment:3
supported_archs     x86_64

# a simple mapping from scripts to modules -- ideally, upstream
# provided these
array set module_scripts {
    pydoc pydoc
    2to3 lib2to3
    smtpd.py smtpd
}

subport pypy36 {
    set python.branch 3.6

    set module_scripts(venv) venv
    set module_scripts(idle) idlelib

    depends_lib-append port:xz

    depends_run-append port:python3_select
    select.entries-append [list python3 python3-$subport $subport]
}

subport pypy37 {
    set python.branch 3.7

    set module_scripts(venv) venv
    set module_scripts(idle) idlelib

    depends_lib-append port:xz

    depends_run-append port:python3_select
    select.entries-append [list python3 python3-$subport $subport]
}

subport pypy38 {
    set python.branch 3.8

    set module_scripts(venv) venv
    set module_scripts(idle) idlelib

    depends_lib-append port:xz

    depends_run-append port:python3_select
    select.entries-append [list python3 python3-$subport $subport]
}

subport pypy39 {
    set python.branch 3.9

    set module_scripts(venv) venv
    set module_scripts(idle) idlelib

    depends_lib-append port:xz

    depends_run-append port:python3_select
    select.entries-append [list python3 python3-$subport $subport]
}


subport pypy-tkinter {
    set python.branch   2.7
}

subport pypy36-tkinter {
    set python.branch   3.6
}

subport pypy37-tkinter {
    set python.branch   3.7
}

subport pypy38-tkinter {
    set python.branch   3.8
}

subport pypy39-tkinter {
    set python.branch   3.9
}

if {$subport == ${name}} {
    set python.branch 2.7

    depends_run-append port:python2_select
    select.entries-append [list python2 python2-$subport $subport]
}

if {${python.branch} == 2.7} {
    patchfiles-append   pypy2-darwin.py.diff

    checksums           rmd160  962c6d7a898769a78907af9f4044b3be9e246339 \
                        sha256  39b0972956f6548ce5828019dbae12503c32d6cbe91a2becf88d3e42cc52197b \
                        size    23328628

    set use_prefix no
} elseif {${python.branch} == 3.6} {
    version             7.3.3
    revision            4
    deprecated.eol_version yes
    livecheck.type      none
    openssl.branch      1.1

    patchfiles-append   pypy3-darwin.py.diff

    checksums           rmd160  02e9c76e0b381d1bb7ea2f828f221a4d7cdd403a \
                        sha256  a23d21ca0de0f613732af4b4abb0b0db1cc56134b5bf0e33614eca87ab8805af \
                        size    22484684

    if {${os.platform} eq "darwin" && ${os.major} >= 20} {
        patchfiles-append patch-big-sur-pypy36.diff
    }

    set use_prefix no
} elseif {${python.branch} == 3.7} {
    patchfiles-append   pypy3-darwin.py.diff

    checksums           rmd160  32498233dcf14e76cce466f4d246e58764a1775b \
                        sha256  70426163b194ee46009986eea6d9426098a3ffb552d9cdbd3dfaa64a47373f49 \
                        size    26092870

    set use_prefix no
} elseif {${python.branch} == 3.8} {
    patchfiles-append   pypy3-darwin.py.diff

    checksums           rmd160  e0724177307c1d21e4fe4e2977c3f72be1a9642f \
                        sha256  5b5d9d9256f12a129af8384e2f581bdfab3bc0fbbe3a0a480d9c1d2e95490eb1 \
                        size    26642176

    set use_prefix yes
} elseif {${python.branch} == 3.9} {
    patchfiles-append   pypy3-darwin.py.diff

    checksums           rmd160  a977b07ac5ae199054563eb0cfbb9f5ed8acd11d \
                        sha256  2abaa1e9fe1ec0e233c9fbc377a0c8e9a0634080a8f4f30eb6898301f6618c12 \
                        size    26976726

    set use_prefix yes
}

# delayed until ${python.branch} is set
set gitlab.tag_prefix   release-pypy${python.branch}-v
distname                ${name}${python.branch}-v${version}-src

description         A fast interpreter for Python ${python.branch}
long_description \
    PyPy is a replacement for CPython ${python.branch}. The main reason to use it \
    instead of CPython is speed, as it generally runs faster.

openssl.configure   build_flags

build.env           PYPY_USESSION_DIR=${workpath} PYPY_LOCALBASE=${prefix} \
                    PYPY_NO_EMBED_DEPENDENCIES=1 \
                    "CFLAGS=${configure.cc_archflags} ${configure.cppflags}" \
                    "LDFLAGS=${configure.ld_archflags} ${configure.ldflags}"

build.dir           ${worksrcpath}/pypy/goal
build.args          --batch --verbose \
                    --cc=${configure.cc} --opt=jit --lto --compile \
                    --make-jobs=${build.jobs}
build.target        ../../rpython/bin/rpython
build.post_args     targetpypystandalone

destroot.env        {*}${build.env}
destroot.env-append CC=${configure.cc} \
                    "LDSHARED=${configure.cc} -pthread -shared -undefined dynamic_lookup"


destroot.dir        ${worksrcpath}/pypy/tool/release
destroot.args       --builddir ${workpath} \
                    --archive-name ${subport} \
                    --without-_tkinter --no-embedded-dependencies
destroot.target     package.py
destroot.post_args

post-patch {
    # sanity check, useful when upgrading, as upstream tends to move these around
    if { ![catch {exec grep --exclude "*.orig" -Ilwre /sw -e ${prefix} ${worksrcpath}} result] } {
        ui_warn "patching potentially didn't catch all references to /sw and ${prefix}:\n$result"
    }

    reinplace "s|__PREFIX__|${prefix}|" \
        ${worksrcpath}/extra_tests/ctypes_tests/conftest.py \
        ${worksrcpath}/pypy/tool/cpyext/extbuild.py \
        ${worksrcpath}/lib_pypy/cffi/ffiplatform.py \
        ${worksrcpath}/lib_pypy/_tkinter/tklib_build.py

    if {${python.branch} == "2.7"} {
        reinplace "/MACOSX_DEPLOYMENT_TARGET/s/10\\.\\(\[0-9\]*\\)/${macosx_deployment_target}/" \
            lib-python/2.7/distutils/sysconfig_pypy.py
    }

    # sanity check, likewise
    if { ![catch {exec grep --exclude "*.orig" -lIwre __PREFIX__ ${worksrcpath}} result] } {
        ui_warn "patching potentially didn't catch all references to __PREFIX__:\n$result"
    }
}

# Which Python binary should we use? Building PyPy is _very_ resource
# intensive, and one of the best cases for using PyPy itself over
# CPython.
if {$subport ne $name} {
    # just use our own pypy2 for building pypy3
    depends_build-append port:pypy
    build.cmd       ${prefix}/lib/pypy/bin/pypy
} else {
    # use a binary distribution of pypy itself
    checksums-prepend       ${distname}${extract.suffix}

    if {${os.major} >= 20} {
        # older versions cannot import C extensions on macOS 11 and later
        set bootstrapper        "pypy2.7-v${version}-osx64"
        distfiles-append        ${bootstrapper}${extract.suffix}
        checksums-append \
            ${bootstrapper}${extract.suffix} \
            rmd160  192d5d6cdc41123c22dc5c9f7e20acb6e8872510 \
            sha256  77314f5a6b2cc35d24e6f952bef89f5da612b90e4127a8034aed708d9ae483c4 \
            size    23915729
    } else {
        # for compatibility, don't bump this needlessly
        set bootstrapper        "pypy-5.1.0-osx64"
        distfiles-append        ${bootstrapper}${extract.suffix}
        checksums-append \
            ${bootstrapper}${extract.suffix} \
            rmd160  fb209f68f77de56037faed5920678887608cdb0a \
            sha256  7e270c66347158dd794c101c4817f742f760ed805aa0d10abe19ba4a78a75118 \
            size    19466885
    }

    build.cmd       ${workpath}/${bootstrapper}/bin/pypy
}

# a lot of memory is used before the C compiler even runs, so limit build.jobs
# according to available memory more tightly than the default
if {![catch {sysctl hw.memsize} memsize]} {
    incr memsize -4000000000
    if {$memsize <= 0} {
        build.jobs 1
    } elseif {${build.jobs} > $memsize / 1000000000 + 1} {
        build.jobs [expr {$memsize / 1000000000 + 1}]
    }
}

# memory usage bug in gcc 4.2 on x86_64
compiler.blacklist gcc-4.2

platform darwin {
    # use arch -foo if available
    if {${os.major} >= 9} {
        build.cmd arch -${build_arch} ${build.cmd}
    }

    # LTO causes the the buildbots to time out on older releases
    if {${os.major} < 15} {
        build.args-delete --lto
    } else {
        # speed up the build by using thin LTO
        patchfiles-append patch-lto-thin.diff
    }
}

# Install support files, but only if not in a proper subport
if {![regexp \- $subport]} {
    post-destroot {
        if {${use_prefix} == yes} {
            system -W "${workpath}" "tar -xjvf ${subport}.tar.bz2 -C ${destroot}${prefix} -s ,${subport}/,,"

            # first, relocate the binaries we want to keep
            xinstall -d ${destroot}${prefix}/bin~
            file rename ${destroot}${prefix}/bin/pypy3 ${destroot}${prefix}/bin~/${subport}
            ln -s ${subport} ${destroot}${prefix}/bin~/${name}-${python.branch}

            file rename ${destroot}${prefix}/bin/libpypy3-c.dylib ${destroot}${prefix}/lib

            delete -force ${destroot}${prefix}/bin
            file rename ${destroot}${prefix}/bin~ ${destroot}${prefix}/bin

            system "install_name_tool -rpath @executable_path/ @executable_path/../lib ${destroot}${prefix}/bin/pypy38"

            xinstall -d ${destroot}${prefix}/share/doc/${subport}
            file rename ${destroot}${prefix}/LICENSE ${destroot}${prefix}/share/doc/${subport}
            file rename ${destroot}${prefix}/README.rst ${destroot}${prefix}/share/doc/${subport}
        } else {
            xinstall -d ${destroot}${prefix}/lib/${subport}

            system -W "${workpath}" "tar -xjvf ${subport}.tar.bz2 -C ${destroot}${prefix}/lib"

            file delete ${destroot}${prefix}/lib/${subport}.tar.bz2
            ln -s ../lib/${subport}/bin/${name} ${destroot}${prefix}/bin/${subport}
            ln -s ../lib/${subport}/bin/${name} ${destroot}${prefix}/bin/${name}-${python.branch}
        }

        xinstall -d ${destroot}${prefix}/share/man/man1
        system -W ${worksrcpath}/pypy/doc/man \
            "rst2man-2.7.py pypy.1.rst ${destroot}${prefix}/share/man/man1/${subport}.1"
        system -W ${worksrcpath}/pypy/doc/man \
            "rst2man-2.7.py pypy.1.rst ${destroot}${prefix}/share/man/man1/${name}-${python.branch}.1"

        foreach script [array names module_scripts] {
            set module $module_scripts($script)
            set scriptdirpath "${destroot}${prefix}/lib/${subport}/bin"
            set scriptpath "${scriptdirpath}/${script}"

            xinstall -d "${scriptdirpath}"
            xinstall -m 755 ${filespath}/module-script.sh $scriptpath
            reinplace "s+__PYPY__+${prefix}/bin/${subport}+" $scriptpath
            reinplace "s+__MODULE__+${module}+" $scriptpath
        }
    }
}

# Factor Tk into a separate subport, like CPython
if {[string match "pypy*-tkinter" ${subport}]} {
    set pypy_version    [string range ${subport} 0 [string first "-" ${subport}]-1]
    set pypy_root       ${prefix}/lib/${pypy_version}

    description         PyPy bindings for Python ${python.branch} to the Tk widget set
    long_description    ${description}
    categories          lang python graphics

    depends_build       port:pkgconfig \
                        port:tcl
    depends_lib         port:${pypy_version} \
                        port:tk

    openssl.branch      no_version

    build.dir           ${worksrcpath}
    build.cmd           ${prefix}/bin/${pypy_version}
    build.args          lib_pypy/_tkinter/tklib_build.py
    build.target
    build.post_args
    build.env-append    CC=${configure.cc} \
                        "LDSHARED=${configure.cc} -pthread -shared -undefined dynamic_lookup"

    select.entries

    destroot {
        xinstall -m 755 -d ${destroot}${pypy_root}/lib_pypy/_tkinter
        xinstall -m 755 \
            [glob -directory ${worksrcpath}/lib_pypy/_tkinter tklib_cffi.*.so] \
            ${destroot}${pypy_root}/lib_pypy/_tkinter
    }

    post-destroot { }
}

if {${os.major} < 11 && ${os.platform} eq "darwin"} {
    known_fail yes

    # https://trac.macports.org/ticket/59191
    pre-fetch {
        ui_error "${name} ${version} requires macOS 10.7 or newer."
        return -code error "incompatible macOS version"
    }
}

gitlab.livecheck.regex (\[0-9.]+)

if {[regexp \- $subport]} {
    # don't check the tkinter subports
    livecheck.type none
}
