# -*- 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               cmake 1.1
PortGroup               github 1.0
PortGroup               legacysupport 1.1

github.setup            ggerganov llama.cpp 9967 b
revision                0
# This line is for displaying commit in CLI only
set git-commit          4f37f51

categories              llm
maintainers             {i0ntempest @i0ntempest} openmaintainer
license                 MIT

description             LLM inference in C/C++
long_description        The main goal of ${name} is to enable LLM inference \
                        with minimal setup and state-of-the-art performance \
                        on a wide variety of hardware – locally and in the cloud.

checksums               rmd160  c57c0ceb27061260bc90f0356613e311819018de \
                        sha256  1c25cc05128b42c744b2bc6b7d7edd389561db669363818d41fb29a514f775e3 \
                        size    35681892
github.tarball_from     archive

# error: 'filesystem' file not found on 10.14
legacysupport.newest_darwin_requires_legacy \
                        18
legacysupport.use_mp_libcxx \
                        yes

# The port installs a lot of excutables. When running those on libstdc++-based systems,
# you will see these warnings: llama-cli(33262) malloc: *** error for object 0xa04dc754: pointer being freed was not allocated
# They seem to be harmless in this case, however if they start breaking something, the fix will be:
# legacysupport.redirect_bins llama-cli (and/or whichever other binary needed).

depends_build-append    path:bin/git:git \
                        path:bin/pkg-config:pkgconfig

# TODO: depend on cpp-httplib port, see: https://github.com/ggml-org/llama.cpp/issues/20100
depends_lib-append      port:curl

# Minor fix
patchfiles-append       patch-fix-cpp-httplib.diff

patchfiles-append       environ.patch

patchfiles-append       inttypes.patch

# CMake relies on git for version info. We need to set them manually.
post-patch {
    reinplace "s|@LLAMA_BUILD_NUMBER@|${version}|" ${worksrcpath}/common/build-info.cpp.in
    reinplace "s|@LLAMA_BUILD_COMMIT@|${git-commit}|" ${worksrcpath}/common/build-info.cpp.in
}

compiler.cxx_standard   2017

configure.args-append   -DGGML_CCACHE=OFF \
                        -DGGML_LTO=ON \
                        -DGGML_OPENMP=OFF \
                        -DLLAMA_CURL=ON

# error: use of undeclared identifier 'MTLGPUFamilyApple7' on 10.14
if {${os.platform} eq "darwin" && ${os.subplatform} eq "macosx" && \
    (${os.major} >= 20 && ${configure.sdk_version} >= 11)} {
    configure.args-append \
                        -DGGML_METAL=ON \
                        -DGGML_METAL_EMBED_LIBRARY=ON \
                        -DGGML_METAL_MACOSX_VERSION_MIN=${macos_version_major}
} else {
    configure.args-append \
                        -DGGML_METAL=OFF \
                        -DGGML_METAL_EMBED_LIBRARY=OFF
}

# For bundled cpp-httplib until fixed properly.
if {${os.platform} eq "darwin" && ${os.major} < 11} {
    configure.cppflags-append \
                        -DCPPHTTPLIB_DISABLE_MACOSX_AUTOMATIC_ROOT_CERTIFICATES
}

# ___atomic_fetch_add_8
if {[string match *gcc* ${configure.compiler}] && ${configure.build_arch} in [list arm i386 ppc]} {
    configure.ldflags-append \
                    -latomic
}

# TODO: use normal variants instead of forcing specific BLAS.
variant blas description "Uses BLAS, improves performance" {
    configure.args-append \
                        -DGGML_BLAS=ON
    if {${os.platform} eq "darwin" && ${os.subplatform} eq "macosx"} {
        configure.args-append \
                        -DGGML_ACCELLERATE=ON \
                        -DGGML_BLAS_VENDOR=Apple

        # https://github.com/ggml-org/llama.cpp/issues/12765
        if {[string match *gcc* ${configure.compiler}]} {
            configure.cxxflags-append \
                        -fpermissive
        }
    } else {
        configure.args-append \
                        -DGGML_ACCELLERATE=OFF \
                        -DGGML_BLAS_VENDOR=OpenBLAS

        depends_lib-append  path:lib/libopenblas.dylib:OpenBLAS
    }
}

variant openmp description "Enable parallelism support using OpenMP" {
    compiler.openmp_version \
                        4.5
    compiler.blacklist-append \
                        {macports-clang-[0-9].*}
    configure.args-replace \
                        -DGGML_OPENMP=OFF \
                        -DGGML_OPENMP=ON
    if {[string match *clang* ${configure.compiler}]} {
        configure.ldflags-append \
                        -L${prefix}/lib/libomp -lomp
    }
}

variant model_converters description "Install extra model conversion Python scripts" {
    post-destroot {
        xinstall -d ${destroot}${prefix}/share/${name}
        xinstall -m 644 {*}[glob ${worksrcpath}/convert*.py] ${destroot}${prefix}/share/${name}
    }

    notes-append "
        Model conversion scripts have been installed to:

            ${prefix}/share/${name}/

        These scripts should be executed in a Python virtual environment with at least\
        these dependencies installed:
            numpy
            pytorch
            transformers
            gguf
    "
}

# This can replace the variant above once we have all the dependencies updated and fixed
# See: https://github.com/macports/macports-ports/pull/27526
# variant model_converters description "Install extra model conversion Python scripts" {
#    set ::python_branch   3.12
#    set ::python_version  [string map {. ""} ${::python_branch}]
#    depends_run-append    port:python${::python_version} \
#                          port:py${::python_version}-numpy \
#                          port:py${::python_version}-pytorch \
#                          port:py${::python_version}-transformers \
#                          port:py${::python_version}-gguf
#
#    post-patch {
#        reinplace "s|#!/usr/bin/env python3|#!${prefix}/bin/python${::python_branch}|" {*}[glob ${worksrcpath}/convert*.py]
#    }
#
#    post-destroot {
#        xinstall -d ${destroot}${prefix}/libexec/${name}
#        xinstall -m 755 {*}[glob ${worksrcpath}/convert*.py] ${destroot}${prefix}/libexec/${name}
#        foreach file [glob -directory ${destroot}${prefix}/libexec/${name} *.py] {
#            set filebasename [file rootname [file tail $file]]
#            set link ${destroot}${prefix}/bin/[lindex [split ${name} .] 0]-[string map {_ -} ${filebasename}]
#            set target [string replace ${file} 0 [string length ${destroot}]-1]
#            ui_debug "Creating symlink: ${link} => ${target}"
#            ln -s ${target} ${link}
#        }
#    }
# }

variant native description "Force local build and optimize for CPU" {
    configure.args-append \
                        -DGGML_NATIVE=ON
}

default_variants        +blas +openmp
