# -*- 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           github 1.0
PortGroup           mpi 1.0
PortGroup           python 1.0

github.setup        pytorch pytorch 2.3.0 v
# Change github.tarball_from to 'releases' or 'archive' next update
github.tarball_from tarball
revision            0
name                py-${github.project}
license             BSD
maintainers         nomaintainer
supported_archs     arm64 x86_64
fetch.type          git

# third_party/pthreadpool needs DISPATCH_APPLY_AUTO (as of torch 2.0.0), requiring 10.12+
# But builds fail for 10.12 - 10.14, so exclude those too
platforms           {darwin >= 19}

description         Tensors and dynamic neural networks in Python \
                    with strong GPU acceleration

long_description    PyTorch is a Python package that provides two \
                    high-level features: Tensor computation (like \
                    NumPy) with strong GPU acceleration\; Deep neural \
                    networks built on a tape-based autograd \
                    system. You can reuse your favorite Python \
                    packages such as NumPy, SciPy and Cython to extend \
                    PyTorch when needed.

homepage            https://pytorch.org/

python.versions     39 310 311 312

mpi.setup

# Compiler selection
compiler.cxx_standard 2017

compiler.blacklist-append *gcc*

variant mkl description {Enable Intel Math Kernel Library support} { }

# py-mkl supports x86_64 and 10.12 and later only
if {${configure.build_arch} eq "x86_64" && !($universal_possible && [variant_isset universal])
        && !(${os.platform} eq "darwin" && ${os.major} <= 15)} {
    default_variants-append +mkl
}

platform darwin {
    # MPS support added in 10.13
    if {${os.major} >= 17} {
        variant mps description {Enable Apple Metal Performance Shaders (MPS) support} {
            use_xcode       yes

            build.env-append \
                APPLE=ON \
                USE_MPS=ON \
                USE_PYTORCH_METAL=ON \
                USE_PYTORCH_METAL_EXPORT=ON

            notes-append \
"
The port ${subport} is built with Apple Metal Performance Shaders (MPS)\
support for GPU hardware acceleration. To enable Apple GPU devices,\
use device \"mps\". Matrix multiplication example:

    import torch

    mpsDevice = torch.device(\"mps\" if\
        torch.backends.mps.is_available() else \"cpu\")
    x = torch.randn((10_000, 1_000), device=mpsDevice)
    cov = (x.T @ x)/x.shape\[0]
"
        }

        default_variants-append +mps
    }

    # fix on macOS 12-13 with Xcode 14:
    if { ${os.major} == 21 && [vercmp ${xcodeversion} 14] >= 0 } {
        patchfiles-append   patch-macOS12-xcode14.diff
    } elseif { ${os.major} == 22 && [vercmp ${xcodeversion} 14] >= 0 } {
        patchfiles-append   patch-macOS13-xcode14.diff
    }
}

if {${name} ne ${subport}} {
    depends_build-append \
        port:git \
        path:bin/doxygen:doxygen \
        port:cctools \
        path:bin/cmake:cmake \
        path:bin/ninja:ninja \
        port:py${python.version}-astunparse \
        port:py${python.version}-requests \
        port:py${python.version}-setuptools

    depends_lib-append \
        path:share/pkgconfig/eigen3.pc:eigen3 \
        port:gmp \
        port:mpfr \
        path:lib/libopenblas.dylib:OpenBLAS \
        path:lib/opencv4/libopencv_core.dylib:opencv4 \
        port:zmq \
        port:zstd \
        port:onetbb \
        port:google-glog \
        port:gflags \
        port:leveldb \
        port:lmdb \
        port:libomp \
        port:py${python.version}-click \
        port:py${python.version}-cffi \
        port:py${python.version}-future \
        port:py${python.version}-numpy \
        port:py${python.version}-pybind11 \
        port:py${python.version}-typing_extensions \
        port:py${python.version}-yaml

    depends_run-append \
        port:py${python.version}-onnx

    pre-fetch {
        # error: RPC failed; curl 92 HTTP/2 stream 5 was not closed cleanly: CANCEL
        system -W ${workpath} "${git.cmd} config --global http.postBuffer 16777216"
    }

    post-fetch {
        system -W ${worksrcpath} "${git.cmd} submodule update --init --recursive"
    }

    # diff -Naur ./py-pytorch_orig ./py-pytorch_new | sed -E -e 's/\.\/py-pytorch_(orig|new)/\./g' | sed -E -e 's|/opt/local|@@PREFIX@@|g' > ~/Downloads/patch-pyproject_toml.diff
    patchfiles-append       patch-pyproject_toml.diff

    # Patch to fix init issue with google-glog 0.5.0, caused by breaking API change.
    # Refer to patch header for detailed background.
    # Upstream PyTorch issue: https://github.com/pytorch/pytorch/issues/58054
    # diff -NaurdwB ./py-pytorch-orig/c10/util/Logging.cpp ./py-pytorch-new/c10/util/Logging.cpp | sed -E -e 's/\.\/py-pytorch-(orig|new)/\.\//' | sed -E -e 's|/opt/local|@@PREFIX@@|g' > ~/Downloads/patch-glog-init-check.diff
    patchfiles-append       patch-glog-init-check.diff

    # Disable -Werror in third_party/fbgemm
    patchfiles-append       Werror.patch

    # Use Intel Math kernel Library
    if {[variant_isset mkl]} {
        patchfiles-append FindMKL-OMP.patch
        pre-build {
            # Hacks to get search paths into builds
            reinplace "s|/opt/intel/mkl|${python.prefix}|g" \
                cmake/Modules/FindMKL.cmake
            reinplace "s|mklvers \"intel64\"|mklvers \"\"|g" \
                cmake/Modules/FindMKL.cmake
            reinplace "s|MACPORTS_PREFIX|${prefix}|g" \
                cmake/Modules/FindMKL.cmake
        }
        depends_lib-append      port:py${python.version}-mkl
        depends_build-append    port:py${python.version}-mkl-include
    }

    compiler.cpath-append \
                    ${prefix}/include/libomp

    compiler.library_path-append \
                    ${prefix}/lib/libomp

    configure.cppflags-append \
                    -I${prefix}/include/libomp

    configure.ccache    yes

    # ZSTD support broke with 1.2.0-1.12.0. Check with future releases.
    build.env-append \
                    CMAKE_LIBRARY_PATH=${prefix}/lib:${prefix}/lib/libomp \
                    OpenCV_DIR=${prefix}/libexec/opencv4/cmake \
                    USE_CCACHE=OFF \
                    USE_CUDA=OFF \
                    USE_GFLAGS=ON \
                    USE_GLOG=ON \
                    USE_LEVELDB=ON \
                    USE_LITE_PROTO=ON \
                    USE_LMDB=ON \
                    USE_METAL=ON \
                    USE_NCCL=ON \
                    USE_OPENCV=ON \
                    USE_OPENMP=ON \
                    USE_ROCM=OFF \
                    USE_TBB=ON \
                    USE_SYSTEM_TBB=ON \
                    USE_ZMQ=ON \
                    USE_ZSTD=OFF

    post-destroot {
        set py_torch_root ${python.pkgd}/torch
        foreach slib [glob -directory ${destroot}${py_torch_root} *.so] {
            system "install_name_tool -add_rpath ${py_torch_root}/lib ${slib}"
        }

        set docdir ${prefix}/share/doc/${subport}
        xinstall -d ${destroot}${docdir}
        xinstall -m 0644 -W ${worksrcpath} LICENSE README.md \
            ${destroot}${docdir}
    }

    # pytorch's tests all use GPU compilation
    if { [lsearch ${build.env} {USE_CUDA=OFF}] != -1 } {
        test.run    yes
    }
} else {
    # overload the github livecheck regex to look for versions that
    # are just numbers and '.', no letters (e.g., "3.7.3_rc2").
    github.livecheck.regex  {([0-9.]+)}
}
