# -*- 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           cmake 1.1

github.setup        materialx MaterialX 1.38.2 v
name                materialx
revision            1
categories          graphics
platforms           darwin
license             Apache-2
maintainers         @jasonliu--

homepage            https://www.materialx.org
description         library for describing materials and textures in \
                    computer graphics applications
long_description    MaterialX is an open standard specification and \
                    library API, developed at Lucasfilm and Industrial \
                    Light & Magic, for describing and transferring \
                    rich material and look-development content between \
                    applications and renderers. MaterialX addresses \
                    the need for a common, open standard to represent \
                    the data values and relationships required to \
                    transfer the complete look of a computer graphics \
                    model from one application or rendering platform \
                    to another, including shading networks, patterns \
                    and texturing, complex nested materials, and \
                    geometric assignments.

github.tarball_from downloads
extract.rename      yes

checksums           rmd160  42a0c04554dec0d118a9cdf2b2e6010fde2a2311 \
                    sha256  640c2005ea84e7b57e287b59bceb57b31a5f7f751a150c4a6967292feadec9ea \
                    size    69168871

# MaterialX requires C++2011 but OpenImageIO uses C++2014
compiler.cxx_standard 2014

# enforce to using the same compiler that is used for osl
set llvm_version    14
# pin the used version for LLVM before 10.13 to
# which is forced by used version of osl
if {${os.platform} eq "darwin" && ${os.major} < 18} {
    set llvm_version    11
}

compiler.blacklist-append clang
compiler.fallback macports-clang-${llvm_version}

post-patch {
    reinplace -E {s|CMAKE_CXX_STANDARD 11|CMAKE_CXX_STANDARD 14|} \
            ${worksrcpath}/CMakeLists.txt

}

if {${os.major} < 16} {
    # Add AppKit wrapper header to compiler library paths
    configure.cflags-prepend        -isystem ${filespath}/old_appkit_compat
    configure.cxxflags-prepend      -isystem ${filespath}/old_appkit_compat
    configure.objcflags-prepend     -isystem ${filespath}/old_appkit_compat
    configure.objcxxflags-prepend   -isystem ${filespath}/old_appkit_compat
}

configure.args-append   -DMATERIALX_BUILD_TESTS=OFF \
                        -DMATERIAL_BUILD_SHARED_LIBS=ON

post-destroot {
    # MaterialX's build files puts files into a ${prefix}/cmake folder
    # during the build, and doesn't provide an easy way to re-target
    # the location. So we manually move the folder to a location that
    # actually makes sense.
    xinstall -d ${destroot}${prefix}/share/cmake
    move ${destroot}${prefix}/cmake \
         ${destroot}${prefix}/share/cmake/MaterialX
    xinstall -d ${destroot}${prefix}/share/cmake/Modules
    xinstall -m 644 {*}[glob ${worksrcpath}/cmake/modules/*] \
        ${destroot}${prefix}/share/cmake/Modules

    # MaterialX puts many output files into the resources/ and
    # libraries/ directories, which MaterialX's build files assume are
    # located in ${CMAKE_INSTALL_PREFIX}. Since leaving these
    # directories as ${prefix}/resources and ${prefix}/libraries
    # violates MacPorts' mtree layout, we move them to a location that
    # actually makes sense.
    set mtlx_share_path ${destroot}${prefix}/share/MaterialX
    if {![file exists $mtlx_share_path]} {
        xinstall -d $mtlx_share_path
    }
    set dirs [list resources libraries]
    foreach dir $dirs {
        if {[file exists ${destroot}${prefix}/$dir]} {
            move ${destroot}${prefix}/$dir $mtlx_share_path
        }
    }

    if {[file exists ${destroot}${prefix}/CHANGELOG.md]} {
        move ${destroot}${prefix}/CHANGELOG.md $mtlx_share_path
    }
    if {[file exists ${destroot}${prefix}/README.md]} {
        move ${destroot}${prefix}/README.md $mtlx_share_path
    }

    fs-traverse f $mtlx_share_path/resources {
        if {[file isfile $f] && [file tail $f] eq "CMakeLists.txt"} {
            delete $f
        }
    }
}

livecheck.regex     releases/tag/v(\\d+\\.\\d+\\.\\d+)

variant viewer description {Build the MaterialX viewer} {
    depends_lib-append      port:nanogui-wjakob

    post-patch {
        reinplace "/return searchPath/i\\
\\    // Default search path for MacPorts shared directory.\\
\\    mx::FilePath macportsSharePath = mx::FilePath(\"${prefix}/share/MaterialX\");\\
\\    if (macportsSharePath.exists())\\
\\    {\\
\\        searchPath.append(macportsSharePath);\\
\\        searchPath.append(macportsSharePath / \"resources\");\\
\\    }\\
\\
" \
            ${worksrcpath}/source/MaterialXView/Main.cpp
    }

    configure.args-append   -DMATERIALX_BUILD_VIEWER=ON \
                            -DMATERIALX_NANOGUI_EXTERNAL=ON \
                            -DNANOGUI_EXTRA_LIBS=glfw \
                            -DNANOGUI_EXTRA_INCS="${prefix}/include\;${prefix}/include/eigen3\;${prefix}/include/nanovg"

    notes-append    "To view the examples, you can launch the viewer\
                    by running `MaterialXView` in a terminal window,\
                    and then loading the files located in\
                    ${prefix}/share/MaterialX/resources."
}

variant oiio requires viewer \
    description {Enable support for additional image formats in the MaterialX viewer} \
{
    depends_lib-append      port:openimageio

    patchfiles-append       patch-MaterialXRender-oiio-reference.diff

    configure.args-append   -DMATERIALX_BUILD_OIIO=ON
}

variant docs description {Build documentation} {
    depends_build-append    path:bin/doxygen:doxygen

    post-patch {
        # The CMake script that is supposed to generate the
        # doxymentation is missing an 'ALL' argument in its
        # add_custom_target() command, which means that it never gets
        # executed during the MacPorts build process. So we add it here.
        # Reference:
        # https://stackoverflow.com/questions/34878276/build-doxygen-from-cmake-script
        reinplace -E {s|(add_custom_target.MaterialXDocs)|\1 ALL|} \
            ${worksrcpath}/documents/CMakeLists.txt

        # By default, MaterialX puts its generated doxymentation into
        # ${CMAKE_INSTALL_PREFIX}/documents. We change it so that
        # MaterialX places the doxymentation into a location that
        # conforms with MacPorts' mtree layout.
        reinplace -E {s|(CMAKE_INSTALL_PREFIX.*)documents|\1share/doc|} \
            ${worksrcpath}/documents/CMakeLists.txt

        foreach d [list Contributing Images Specification] {
            reinplace "\$a\\
\\
install(DIRECTORY \${CMAKE_CURRENT_SOURCE_DIR}/$d\\
\\        DESTINATION \"\${CMAKE_INSTALL_PREFIX}/share/doc/MaterialX\"\\
\\        MESSAGE_NEVER)\\
" \
                ${worksrcpath}/documents/CMakeLists.txt
        }
    }

    configure.args-append   -DMATERIALX_BUILD_DOCS=ON

    post-destroot {
        set materialxdocs ${destroot}${prefix}/share/doc/MaterialXDocs
        if {[file exists $materialxdocs]} {
            foreach f [glob -directory $materialxdocs *] {
                move $f ${destroot}${prefix}/share/doc/MaterialX
            }
            delete $materialxdocs
        }
    }
}

variant tests description {Build unit tests} {
    # MaterialX unit tests need to be able to call the Open Shading
    # Language (OSL) compiler, which is an executable binary. However,
    # OSL is not needed to build the unit tests, and MaterialX doesn't
    # link to any libs from OSL; hence the reason for using depends_run.
    depends_run-append      bin:oslc:osl

    patchfiles-append       patch-MaterialXTest-reference_impl.diff

    configure.args-replace  -DMATERIALX_BUILD_TESTS=OFF \
                            -DMATERIALX_BUILD_TESTS=ON
    configure.args-append   -DMATERIALX_OSLC_EXECUTABLE=${prefix}/bin/oslc \
                            -DMATERIALX_TESTRENDER_EXECUTABLE=${prefix}/bin/testrender \
                            -DMATERIALX_OSL_INCLUDE_PATH=${prefix}/share/OSL/shaders

    post-destroot {
        set mdl ${destroot}${prefix}/mdl
        if {[file exists $mdl]} {
            move $mdl ${destroot}${prefix}/share/MaterialX/
        }
    }
}

default_variants    +viewer +oiio +docs +tests

### The following code was adapted from the portfiles
### of ports such as openvdb and openimageio

set pythons_suffixes    {36 37 38 39 310 311}

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

foreach s ${pythons_suffixes} {
    set p python${s}
    set v [string index ${s} 0].[string range ${s} 1 end]
    set i [lsearch -exact ${pythons_ports} ${p}]
    set c [lreplace ${pythons_ports} ${i} ${i}]
    variant ${p} conflicts {*}${c} \
        description "Build the Python ${v} bindings (PyMaterialX)" {}
    if {[variant_isset ${p}]} {
        # Note: We basically need to import the value of ${v}, otherwise
        # all foreach iterations will end up with the same value of
        # ${v}! This appears to be related to how Tcl does scoping.
        set selected_v          ${v}
        depends_lib-append      port:${p} \
                                port:pybind11

        patchfiles-append       patch-python-paths.diff
        post-patch {
            reinplace {/pybind11Tools/s/^/#/} \
                ${worksrcpath}/source/PyMaterialX/CMakeLists.txt
        }

        configure.args-append   -DMATERIALX_BUILD_PYTHON=ON \
                                -DMATERIALX_PYTHON_VERSION=$selected_v \
                                -DPYTHON_INSTALL_PREFIX=${destroot}${frameworks_dir}/Python.framework/Versions/$selected_v/

        post-destroot {
            # MaterialX insists on outputting all Python-related
            # products into the ${CMAKE_INSTALL_PREFIX}/python
            # directory. Since leaving this directory as
            # ${prefix}/python violates MacPorts' mtree layout, we move
            # its contents to a location that actually makes sense.
            if {[file exists ${destroot}${prefix}/python/MaterialX]} {
                foreach so [glob ${destroot}${prefix}/python/MaterialX/*.so] {
                    move $so ${destroot}${prefix}/lib/
                }
                set remaining_files \
                    [glob -nocomplain ${destroot}${prefix}/python/MaterialX/*]
                if {[llength $remaining_files] == 0} {
                    delete ${destroot}${prefix}/python
                }
            }
        }
    }
}
