VERSION --arg-scope-and-set --pass-args 0.7

init-env:
    ARG --required from
    FROM $from
    DO --pass-args +INIT

# An image just to bundle the scripts for this directory.
tools-dir:
    # ("scratch" is the special container image that contains nothing at all)
    FROM scratch
    COPY --chmod=755 . /
    SAVE ARTIFACT /*

INIT:
    COMMAND
    COPY +tools-dir/__alias /usr/local/bin/__alias
    COPY +tools-dir/__boolstr /usr/local/bin/__boolstr
    LET is_alpine = $(__boolstr test -f /etc/alpine-release)
    LET is_ubuntu = $(__boolstr grep -qF UBUNTU_CODENAME /etc/os-release)
    LET is_archlinux = $(__boolstr test -f /etc/arch-release)
    RUN __alias __is_alpine $is_alpine
    RUN __alias __is_ubuntu $is_ubuntu
    RUN __alias __is_archlinux $is_archlinux
    COPY +tools-dir/__install /usr/local/bin/__install
    COPY +tools-dir/__str /usr/local/bin/__str
    COPY +tools-dir/__fail /usr/local/bin/__fail

# ADD_C_OMPILER :
#   Add a C compiler to the environment. Requires a --c_compiler argument to be given.
ADD_C_COMPILER:
    COMMAND
    ARG --required c_compiler
    ARG gcc_pkg=gcc
    ARG clang_pkg=clang
    ARG cc_pkg
    IF test "$cc_pkg" != ""
        # Caller has provided a package name
    ELSE IF test "$c_compiler" = gcc
        LET cc_pkg = $gcc_pkg
    ELSE IF test "$c_compiler" = clang
        LET cc_pkg = $clang_pkg
    ELSE
        RUN __fail "Unable to infer package name for --c_compiler “$%s” (check spelling or pass a “--cc_pkg” argument)" "$c_compiler"
    END
    RUN __install $cc_pkg
    ENV CC=$c_compiler

# ADD_CXX_COMPILER :
#   Add a C++ compiler to the environment. Requires a --cxx_compiler argument to be provied.
ADD_CXX_COMPILER:
    COMMAND
    ARG --required cxx_compiler
    # Remap the names "gcc" and "clang" to their compiler names
    IF test "$cxx_compiler" = gcc
        LET cxx_compiler = g++
    ELSE IF test "$cxx_compiler" = clang
        LET cxx_compiler = clang++
    END
    ARG cxx_compiler_bin=$cxx_compiler
    ARG cxx_pkg
    IF test "$cxx_pkg" != ""
        # Nothing to infer
    ELSE IF __is_archlinux
        # Arch bundles the C and C++ compilers in the same package
        IF test "$cxx_compiler" = g++
            LET cxx_pkg = "gcc"
        ELSE IF test "$cxx_compiler" = clang++
            LET cxx_pkg = clang
        END
    ELSE IF __is_ubuntu
        IF test "$cxx_compiler" = g++
            LET cxx_pkg = "gcc"
        ELSE IF test "$cxx_compiler" = clang++
            LET cxx_pkg = "clang"
        END
        SET cxx_pkg = "$cxx_pkg build-essential"
    ELSE IF __is_alpine
        IF test "$cxx_compiler" = g++
            LET cxx_pkg = $cxx_compiler
        ELSE IF test "$cxx_compiler" = clang++
            # Alpine bundles clang and clang++ together.
            # Old Alpine 3.16 bundles libstdc++ in g++, so we need to pull GCC along anyway
            LET cxx_pkg = clang g++
        END
    END
    IF test "$cxx_pkg" = ""
        RUN __fail "Unable to infer package name for --cxx_compiler “%s” on this platform (check spelling or pass a “--cxx_pkg” argument)" "$cxx_compiler"
    END
    RUN __install $cxx_pkg
    ENV CXX=$cxx_compiler_bin

# ADD_SASL :
#   Add SASL libraries to the environment. Requires --sasl and --purpose arguments to be
#   provided. The package names will be inferred from the environment, but can be explicitly
#   provided by passing --cyrus_dev_pkg and --cyrus_rt_pkg arguments
ADD_SASL:
    COMMAND
    ARG --required sasl
    ARG --required purpose
    ARG cyrus_dev_pkg
    ARG cyrus_rt_pkg
    LET to_install=""
    IF __str test "$sasl" -ieq Cyrus
        # Detect package names
        IF test "$cyrus_dev_pkg$cyrus_rt_pkg" != ""
            # Nothing to infer
        ELSE IF __is_ubuntu
            LET cyrus_dev_pkg = libsasl2-dev
            LET cyrus_rt_pkg = libsasl2-2
        ELSE IF __is_alpine
            LET cyrus_dev_pkg = cyrus-sasl-dev
            LET cyrus_rt_pkg = cyrus-sasl
        ELSE
            RUN __fail "Cannot infer the Cyrus SASL library package names. Set --cyrus_dev_pkg and --cyrus_rt_pkg or update the ADD_SASL utility"
        END
        # Set install targets
        IF test "$purpose" = test
            SET to_install = $cyrus_rt_pkg
        ELSE IF test "$purpose" = build
            SET to_install = $cyrus_dev_pkg $cyrus_rt_pkg
        END
    ELSE IF __str test "$sasl" -ieq off
        # Do nothing
    ELSE
        RUN __fail "Unknown value for --sasl “%s” (Expect one of “Cyrus” or “off”)" "$sasl"
    END
    IF test "$to_install" != ""
        RUN __install $to_install
    END

# ADD_TLS :
#   Add TLS libraries to the environment. Requires --tls and --purpose arguments to be
#   given. The package names can be inferred from the environment or can be provided explicitly
#   with the --openssl_dev_pkg, --openssl_rt_pkg, --libressl_dev_pkg, and --libressl_rt_pkg
#   command arguments.
ADD_TLS:
    COMMAND
    ARG --required tls
    ARG --required purpose
    ARG openssl_dev_pkg
    ARG openssl_rt_pkg
    ARG libressl_dev_pkg
    ARG libressl_rt_pkg
    LET to_install=""
    IF __str test "$tls" -ieq OpenSSL
        # Detect package names
        IF test "$openssl_dev_pkg$openssl_rt_pkg" != ""
            # Nothing to infer
        ELSE IF __is_alpine
            LET openssl_dev_pkg = openssl-dev
            LET openssl_rt_pkg = openssl
        ELSE IF __is_ubuntu
            LET openssl_dev_pkg = libssl-dev
            # APT will handle this as a regex to match a libssl runtime package:
            LET openssl_rt_pkg = libssl1.[0-9]
        ELSE IF __is_archlinux
            LET openssl_dev_pkg = openssl
            LET openssl_rt_pkg = openssl
        ELSE
            RUN __fail "Cannot infer the OpenSSL TLS library package names. Set --openssl_dev_pkg and --openssl_rt_pkg or update the ADD_TLS utility"
        END
        # Set install targets
        IF test "$purpose" = build
            SET to_install = $openssl_dev_pkg $openssl_rt_pkg
        ELSE IF test "$purpose" = test
            SET to_install = $openssl_rt_pkg
        ELSE
            RUN __fail "Unknown --purpose value “%s”" "$purpose"
        END
    ELSE IF __str test "$tls" -ieq LibreSSL
        # Detect package names
        IF test "$libressl_dev_pkg$libressl_rt_pkg" != ""
            # Nothing to infer
        ELSE IF __is_alpine
            LET libressl_dev_pkg = libressl-dev
            LET libressl_rt_pkg = libressl
        ELSE IF __is_ubuntu
            RUN __fail "Cannot infer the LibreSSL TLS library package names on Ubuntu, as Ubuntu does not ship LibreSSL packages. Set --openssl_dev_pkg and --openssl_rt_pkg or update the ADD_TLS utility."
        ELSE IF __is_archlinux
            LET libressl_dev_pkg = libressl
            LET libressl_rt_pkg = libressl
        ELSE
            RUN __fail "Cannot infer the LibreSSL TLS library package names. Set --openssl_dev_pkg and --openssl_rt_pkg or update the ADD_TLS utility"
        END
        # Set install targets
        IF test "$purpose" = build
            SET to_install = $libressl_dev_pkg $libressl_rt_pkg
        ELSE IF test "$purpose" = test
            SET to_install = $libressl_rt_pkg
        END
    ELSE IF __str test "$tls" -ieq "off"
        # Nothing to do
    ELSE
        RUN __fail "Unknown --tls value “%s” (Expect one of “OpenSSL”, “LibreSSL”, or “off”)" "$tls"
    END
    # Perform the install
    IF test "$to_install" != ""
        RUN __install $to_install
    END
