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

name                    mysql9
version                 9.7.2

categories              databases

homepage                https://dev.mysql.com

maintainers             {gmail.com:herby.gillot @herbygillot} \
                        openmaintainer

# Set revision_client and revision_server to 0 on version bump.
set revision_client     0
set revision_server     0

set name_mysql          ${name}
set version_branch      [join [lrange [split ${version} .] 0 1] .]

# Oracle supports 9.7 on macOS 14 and 15, arm64 only; this floor is six majors
# lower. A MacPorts clang supplies the language standard, legacysupport the
# libc gaps, and the patches below cover a linker flag and one test component.
# Verified by building 9.7.2 on 10.14 and running MTR: 5473 of 5475 passed over
# 1284 server restarts, the two failures an optimizer row estimate and a row
# ordering. 10.13 rides on that evidence rather than its own.
platforms               {darwin >= 17}

if {$subport eq $name} {
    PortGroup           muniversal                  1.0
    PortGroup           cmake                       1.1
    PortGroup           select                      1.0
    PortGroup           openssl                     1.0
    PortGroup           legacysupport               1.1

    description         Multithreaded SQL database server
    long_description    MySQL is an open-source, multi-threaded SQL database.
    # https://downloads.mysql.com/docs/licenses/mysqld-9.7-gpl-en.pdf
    license             {GPL-2 OpenSSLException}

    revision            ${revision_client}

    master_sites        mysql:MySQL-${version_branch}:mysql

    distname            mysql-${version}

    distfiles           ${distname}${extract.suffix}:mysql

    checksums           ${distname}${extract.suffix} \
                        rmd160  49cb98c8819861f9b3788b1e3bd836f2b0f6d146 \
                        sha256  e5a676c7cb73738dc6ea33db2093806ebd512b629a139b897fcab68fcd81aaa4 \
                        size    429211578

    depends_build-append \
                        path:bin/pkg-config:pkgconfig  \
                        port:bison

    depends_lib-append  path:lib/pkgconfig/icu-uc.pc:icu \
                        port:curl           \
                        port:cyrus-sasl2    \
                        port:libedit        \
                        port:libfido2       \
                        path:lib/libldap.dylib:openldap       \
                        port:lz4            \
                        port:protobuf3-cpp  \
                        port:zlib           \
                        port:zstd

    depends_run-append  port:mysql_select

    select.group        mysql
    select.file         ${filespath}/${name_mysql}

    use_parallel_build  yes

    compiler.cxx_standard 2023

    # 9.7 needs <source_location> and std::stringstream::view(), which arrive
    # together in libc++ 17. cxx_standard 2023 admits Apple clang 15 on a
    # language check alone, so Ventura picks it and then fails against
    # MacOSX13.sdk's libc++ 15; no Xcode past 15 runs there, leaving only a
    # MacPorts clang. 17, not the 16 mysql8 pins for the hang in
    # https://trac.macports.org/ticket/70323, which does not recur here: 16
    # has just <source_location> and dies at 71%.
    if {${os.major} == 22} {
        configure.compiler macports-clang-17
    }

    # Sonoma and later ship Apple clang 16 with libc++ 17 only if Xcode is
    # current; Sonoma also runs Xcode 15, as the buildbot does. That Apple
    # clang 15 lacks P0960 parenthesized aggregate initialisation as well as
    # libc++ 17, and fails 22 objects in on
    # libs/mysql/strconv/decode/parse_options.h. cxx_standard alone will not
    # exclude it: base maps anything >= 2020 onto the same clang 16 minimum,
    # having no C++23 row. Blacklist it so those hosts take a MacPorts clang.
    compiler.blacklist-append {clang < 1600}

    cmake.build_type    Release

    # The macOS 26 (Tahoe) SDK ships a heavily modularized libc++ that no longer
    # pulls in <type_traits> transitively through <array>/<memory>/<string>.
    # A number of MySQL 9.7 headers (e.g. libs/mysql/gtid/tag_plain.h) and some
    # bundled sources use std::is_trivial_v and friends without including it
    # directly, so force <type_traits> into every C++ translation unit.
    configure.cxxflags-append -include type_traits

    configure.args-append \
        -DWITH_UNIT_TESTS=OFF \
        -DINSTALL_MYSQLTESTDIR=

    # cmake substitutes FIND_PROC into mysqld_safe, which uses it to test a
    # stale pid file against the process list. It sets FIND_PROC outright only
    # for Linux and Solaris; elsewhere it probes with ps, and on Darwin comes
    # up empty, leaving the generated script a bare `if` that will not parse.
    # The SysV form it would otherwise use is wrong here too, matching the bare
    # pid in any ps column, so set a Darwin-compatible test of our own: ask
    # about the one pid, and match only its command.
    configure.args-append \
        -DFIND_PROC='ps -p \$PID -o command= | grep -v mysqld_safe | grep -- \$MYSQLD > /dev/null'

    # Disable MySQL NDB (Network Database) Cluster. Note that -DWITH_NDB=OFF
    # does not do this; it is already off, and storage/ndb is pulled in as a
    # plugin regardless.
    configure.args-append \
        -DWITHOUT_NDBCLUSTER_STORAGE_ENGINE=1

    # MySQL installs its libraries into a private, per-port directory
    # (lib/${name_mysql}/mysql) and manages its own per-target RPATHs, whereas
    # the cmake PortGroup assumes everything lives in ${prefix}/lib. Override the
    # two PortGroup defaults built on that assumption. These go on configure.args
    # (evaluated after configure.pre_args on the cmake command line), so for both
    # cache variables the last -D wins:
    #   - build against the build tree, not the not-yet-installed RPATH, since
    #     MySQL runs freshly-built tools during its own build; and
    #   - give the installed dylibs their real install-name directory.
    configure.args-append \
        -DCMAKE_BUILD_WITH_INSTALL_RPATH:BOOL=OFF \
        -DCMAKE_INSTALL_NAME_DIR:PATH=${prefix}/lib/${name_mysql}/mysql

    # Build configuration
    configure.args-append \
        -DBISON_EXECUTABLE="${prefix}/bin/bison" \
        -DFORCE_UNSUPPORTED_COMPILER=ON \
        -DINSTALL_LAYOUT:STRING=MACPORTS \
        -DMYSQL_DATADIR:PATH="${prefix}/var/db/${name_mysql}" \
        -DMYSQL_UNIX_ADDR:PATH="${prefix}/var/run/${name_mysql}/mysqld.sock" \
        -DSYSCONFDIR:PATH="${prefix}/etc/${name_mysql}" \
        -DWITH_CURL=system      \
        -DWITH_EDITLINE=system  \
        -DWITH_FIDO=system      \
        -DWITH_ICU=system       \
        -DWITH_LDAP=system      \
        -DWITH_LZ4=system       \
        -DWITH_PROTOBUF=system  \
        -DWITH_SASL=system      \
        -DWITH_ZLIB=system      \
        -DWITH_ZSTD=system

    # WITH_SSL=system makes MySQL use the openssl / libcrypto libraries in place
    # rather than copying them into its own tree. The openssl PortGroup already
    # injects -DOPENSSL_ROOT_DIR=[openssl::install_area] (kept; the pre-configure
    # block below only trims the PortGroup's other ssl flags), which cmake's
    # FindOpenSSL uses to locate the MacPorts openssl -- so no separate
    # CMAKE_PREFIX_PATH is needed here.
    configure.args-append \
        -DWITH_SSL=system

    configure.args-append \
        -DWITH_ROUTER:BOOL=OFF

    patch.pre_args-replace  -p0 -p1
    patchfiles      patch-cmake-install_layout.cmake.diff \
                    patch-CMakeLists-no-homebrew.diff \
                    patch-no_warn_duplicate_libraries.diff \
                    patch-no-test-components.diff

    post-extract {
        file mkdir ${cmake.build_dir}/macports
        copy ${filespath}/macports-default.cnf \
            ${filespath}/my.cnf \
            ${cmake.build_dir}/macports/
    }

    pre-configure {
        # Drop the two openssl PortGroup flags that would put MySQL into its
        # copy-into-the-build-tree SSL mode; OPENSSL_ROOT_DIR is deliberately left
        # in place (see WITH_SSL=system above).
        configure.args-delete \
            -DOPENSSL_INCLUDE_DIR=[openssl::include_dir] \
            -DWITH_SSL=[openssl::install_area]
    }

    post-patch {
        reinplace "s|@NAME@|${name_mysql}|g" \
            ${worksrcpath}/cmake/install_layout.cmake
        reinplace "s|@NAME@|${name_mysql}|g" \
            ${cmake.build_dir}/macports/macports-default.cnf \
            ${cmake.build_dir}/macports/my.cnf
        reinplace "s|@PREFIX@|${prefix}|g" \
            ${cmake.build_dir}/macports/macports-default.cnf \
            ${cmake.build_dir}/macports/my.cnf
    }

    post-destroot {
        # proc portdestroot::destroot_finish fails to find and compress our man pages
        # so borrow the compress command and run on our files now.
        set gzip [findBinary gzip ${portutil::autoconf::gzip_path}]

        foreach manpage [glob -type f ${destroot}${prefix}/share/man/${name_mysql}/man\[1-9\]/*] {
            # Fix paths in manpages
            reinplace -q "s|/etc/|${prefix}/etc/${name_mysql}/|g" ${manpage}
            # Compress all manpages with gzip
            system "$gzip -9vf ${manpage}"
        }

        xinstall -m 0755 -o root -d ${destroot}${prefix}/etc/${name_mysql}

        copy ${cmake.build_dir}/macports/macports-default.cnf \
            ${destroot}${prefix}/etc/${name_mysql}/

        xinstall -m 0755 -o root -d \
            ${destroot}${prefix}/share/${name_mysql}/support-files/macports

        copy ${cmake.build_dir}/macports/my.cnf \
            ${destroot}${prefix}/share/${name_mysql}/support-files/macports/
    }

    post-install {
        if {![file exists ${prefix}/etc/LaunchDaemons/org.macports.${name_mysql}-server/org.macports.${name_mysql}-server.plist]} {
            ui_msg "The ${name_mysql} client has been installed."
            ui_msg "To install the ${name_mysql} server, install the ${name_mysql}-server port."
        }
    }

    post-activate {
        if {![file exists ${prefix}/etc/${name_mysql}/my.cnf]} {
            copy ${prefix}/share/${name_mysql}/support-files/macports/my.cnf \
                ${prefix}/etc/${name_mysql}/
        }
    }

    notes "
On activation if no ${prefix}/etc/${name_mysql}/my.cnf file exists one
will be created which loads
${prefix}/etc/${name_mysql}/macports-default.cnf.

If a ${prefix}/etc/${name_mysql}/my.cnf file exists MacPorts does not
touch it and any changes you make to ${prefix}/etc/${name_mysql}/my.cnf
will be preserved (e.g., during port upgrades, deactivations or
activations). ${prefix}/etc/${name_mysql}/my.cnf is a good place to
customize your ${name_mysql} installation.

Any changes made to ${prefix}/etc/${name_mysql}/macports-default.cnf
will be lost during port upgrades, deactivations or activations so you
are advised to not make changes here. Currently
${prefix}/etc/${name_mysql}/macports-default.cnf contains only one
directive; to disable networking. With disabled networking it is
possible to install and have running all the MacPorts mysql ports
simultaneously.

To set ${name_mysql} as your preferred version of MySQL, use `port select`,
as follows:

\$ sudo port select mysql ${name_mysql}
"

    # dev.mysql.com 403s automated fetches and the download CDN offers no directory
    # listing, so neither can drive livecheck. Instead scan the official mysql-server
    # GitHub tags, filtered to this port's release series (mysql-${version_branch}.*)
    # via GitHub's matching-refs API, so the series' newest tag is always found no
    # matter how many other series were tagged more recently.
    livecheck.type      regex
    livecheck.url       https://api.github.com/repos/mysql/mysql-server/git/matching-refs/tags/mysql-${version_branch}.
    livecheck.regex     {mysql-([0-9.]+)}
}

subport ${name_mysql}-server {
    revision            ${revision_server}
    license             BSD
    description         Run ${name_mysql} as server
    long_description    {*}${description}

    supported_archs     noarch
    distfiles

    depends_run         port:${name_mysql}

    set mysqluser       _mysql
    add_users ${mysqluser} group=${mysqluser} realname=MySQL\ Server

    set log_file ${prefix}/var/log/${name_mysql}/mysql.log

    use_configure       no

    build {}

    startupitem.create      yes
    startupitem.executable  ${prefix}/lib/${name_mysql}/bin/mysqld
    startupitem.user        ${mysqluser}
    startupitem.group       ${mysqluser}
    startupitem.logfile     ${log_file}

    destroot {
        xinstall -d -m 0755 -o ${mysqluser} -g ${mysqluser} \
            [file dirname ${destroot}${log_file}]

        touch ${destroot}${log_file}
        file attributes ${destroot}${log_file} -o ${mysqluser} -g ${mysqluser}

        xinstall -m 0755 -o root -d \
            ${destroot}${prefix}/var/run

        xinstall -m 0755 -o ${mysqluser} -g ${mysqluser} -d \
            ${destroot}${prefix}/etc/${name_mysql} \
            ${destroot}${prefix}/var/db/${name_mysql} \
            ${destroot}${prefix}/var/log/${name_mysql} \
            ${destroot}${prefix}/var/run/${name_mysql}

        xinstall -m 0700 -o ${mysqluser} -g ${mysqluser} -d \
            ${destroot}${prefix}/var/db/${name_mysql}-files \
            ${destroot}${prefix}/var/db/${name_mysql}-keyring

        destroot.keepdirs-append  \
            ${destroot}${prefix}/var/db/${name_mysql} \
            ${destroot}${prefix}/var/db/${name_mysql}-files \
            ${destroot}${prefix}/var/db/${name_mysql}-keyring \
            ${destroot}${prefix}/var/log/${name_mysql} \
            ${destroot}${prefix}/var/run/${name_mysql}
    }

    notes "
A new install must be initialized before the server will start. Run:

\$ sudo ${prefix}/lib/${name_mysql}/bin/mysqld --initialize --user=${mysqluser}
\$ sudo port load ${name_mysql}-server
\$ ${prefix}/lib/${name_mysql}/bin/mysql_secure_installation

The first command creates the necessary files for the MySQL database service.
(Remember to make a note of the auto-generated root password from this step.)
Without it the server exits at startup reporting that it cannot open
ibdata1. The second command starts the MySQL service. The last command helps
to improve the security of your running MySQL instance.

If you are upgrading your ${subport} installation instead of a fresh install,
then the running server from the previous version is stopped. So post-upgrade
of ${subport}, please run the following to start the updated server:

\$ sudo port load ${name_mysql}-server

Your databases in ${prefix}/var/db/${name_mysql} are left untouched by an
upgrade.

Once enabled, the MySQL logs can be found in:
[file dirname $log_file]
"

    livecheck.type          none
}
