# This file is licensed under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

"""Repository rules to configure the terminfo used by LLVM.

Most users should pick one of the explicit rules to configure their use of terminfo
with LLVM:
- `llvm_terminfo_system` will detect and link against a terminfo-implementing
  system library (non-hermetically).
- 'llvm_terminfo_disable` will disable terminfo completely.

If you would like to make your build configurable, you can use
`llvm_terminfo_from_env`. By default, this will disable terminfo, but will
inspect the environment variable (most easily set with a `--repo_env` flag to
the Bazel invocation) `BAZEL_LLVM_TERMINFO_STRATEGY`. If it is set to
`system` then it will behave the same as `llvm_terminfo_system`. Any other
setting will disable terminfo the same as not setting it at all.
"""

def _llvm_terminfo_disable_impl(repository_ctx):
    repository_ctx.template(
        "BUILD",
        repository_ctx.attr._disable_build_template,
        executable = False,
    )

_terminfo_disable_attrs = {
    "_disable_build_template": attr.label(
        default = Label("//utils/bazel/deps_impl:terminfo_disable.BUILD"),
        allow_single_file = True,
    ),
}

llvm_terminfo_disable = repository_rule(
    implementation = _llvm_terminfo_disable_impl,
    attrs = _terminfo_disable_attrs,
)

def _find_c_compiler(repository_ctx):
    """Returns the path to a plausible C compiler.

    This routine will only reliably work on roughly POSIX-y systems as it
    ultimately falls back on the `cc` binary. Fortunately, the thing we are
    trying to use it for (detecting if a trivial source file can compile and
    link against a particular library) requires very little.
    """
    cc_env = repository_ctx.os.environ.get("CC")
    cc = None
    if cc_env:
        if "/" in cc_env:
            return repository_ctx.path(cc_env)
        else:
            return repository_ctx.which(cc_env)

    # Look for Clang, GCC, and the POSIX / UNIX specified C compiler
    # binaries.
    for compiler in ["clang", "gcc", "c99", "c89", "cc"]:
        cc = repository_ctx.which(compiler)
        if cc:
            return cc

    return None

def _try_link(repository_ctx, cc, source, linker_flags):
    """Returns `True` if able to link the source with the linker flag.

    Given a source file that contains references to library routines, this
    will check that when linked with the provided linker flag, those
    references are successfully resolved. This routine assumes a generally
    POSIX-y and GCC-ish compiler and environment and shouldn't be expected to
    work outside of that.
    """
    cmd = [
        cc,
        # Force discard the linked executable.
        "-o",
        "/dev/null",
        # Leave language detection to the compiler.
        source,
    ]

    # The linker flag must be valid for a compiler invocation of the link step,
    # so just append them to the command.
    cmd += linker_flags
    exec_result = repository_ctx.execute(cmd, timeout = 20)
    return exec_result.return_code == 0

def _llvm_terminfo_system_impl(repository_ctx):
    # LLVM doesn't need terminfo support on Windows, so just disable it.
    if repository_ctx.os.name.lower().find("windows") != -1:
        _llvm_terminfo_disable_impl(repository_ctx)
        return

    if len(repository_ctx.attr.system_linkopts) > 0:
        linkopts = repository_ctx.attr.system_linkopts
    else:
        required = repository_ctx.attr.system_required

        # Find a C compiler we can use to detect viable linkopts on this system.
        cc = _find_c_compiler(repository_ctx)
        if not cc:
            if required:
                fail("Failed  to find a C compiler executable")
            else:
                _llvm_terminfo_disable_impl(repository_ctx)
                return

        # Get the source file we use to detect successful linking of terminfo.
        source = repository_ctx.path(repository_ctx.attr._terminfo_test_source)

        # Collect the candidate linkopts and wrap them into a list. Ideally,
        # these would be provided as lists, but Bazel doesn't currently
        # support that. See: https://github.com/bazelbuild/bazel/issues/12178
        linkopts_candidates = [[x] for x in repository_ctx.attr.candidate_system_linkopts]

        # For each candidate, try to use it to link our test source file.
        for linkopts_candidate in linkopts_candidates:
            if _try_link(repository_ctx, cc, source, linkopts_candidate):
                linkopts = linkopts_candidate
                break

        # If we never found a viable linkopts candidate, either error or disable
        # terminfo for LLVM.
        if not linkopts:
            if required:
                fail("Failed to detect which linkopt would successfully provide the " +
                     "necessary terminfo functionality")
            else:
                _llvm_terminfo_disable_impl(repository_ctx)
                return

    repository_ctx.template(
        "BUILD",
        repository_ctx.attr._system_build_template,
        substitutions = {
            "{TERMINFO_LINKOPTS}": str(linkopts),
        },
        executable = False,
    )

def _merge_attrs(attrs_list):
    attrs = {}
    for input_attrs in attrs_list:
        attrs.update(input_attrs)
    return attrs

_terminfo_system_attrs = _merge_attrs([_terminfo_disable_attrs, {
    "_system_build_template": attr.label(
        default = Label("//utils/bazel/deps_impl:terminfo_system.BUILD"),
        allow_single_file = True,
    ),
    "_terminfo_test_source": attr.label(
        default = Label("//utils/bazel/deps_impl:terminfo_test.c"),
        allow_single_file = True,
    ),
    "candidate_system_linkopts": attr.string_list(
        default = [
            "-lterminfo",
            "-ltinfo",
            "-lcurses",
            "-lncurses",
            "-lncursesw",
        ],
        doc = "Candidate linkopts to test and see if they can link " +
              "successfully.",
    ),
    "system_required": attr.bool(
        default = False,
        doc = "Require that one of the candidates is detected successfully on POSIX platforms where it is needed.",
    ),
    "system_linkopts": attr.string_list(
        default = [],
        doc = "If non-empty, a specific array of linkopts to use to " +
              "successfully link against the terminfo library. No " +
              "detection is performed if this option is provided, it " +
              "directly forces the use of these link options. No test is " +
              "run to determine if they are valid or work correctly either.",
    ),
}])

llvm_terminfo_system = repository_rule(
    implementation = _llvm_terminfo_system_impl,
    configure = True,
    local = True,
    attrs = _terminfo_system_attrs,
)

def _llvm_terminfo_from_env_impl(repository_ctx):
    terminfo_strategy = repository_ctx.os.environ.get("BAZEL_LLVM_TERMINFO_STRATEGY")
    if terminfo_strategy == "system":
        _llvm_terminfo_system_impl(repository_ctx)
    else:
        _llvm_terminfo_disable_impl(repository_ctx)

llvm_terminfo_from_env = repository_rule(
    implementation = _llvm_terminfo_from_env_impl,
    configure = True,
    local = True,
    attrs = _merge_attrs([_terminfo_disable_attrs, _terminfo_system_attrs]),
    environ = ["BAZEL_LLVM_TERMINFO_STRATEGY", "CC"],
)
