"""Generates C++ bindings from Rust APIs."""

load(
    "@rules_rust//rust:defs.bzl",
    "rust_library",
    "rust_proc_macro",
)
load("//common/bazel_support:external_binaries.bzl", "EXTERNAL_BINARIES")
load(
    "//common:crubit_wrapper_macros_oss.bzl",
    "crubit_rust_binary",
    "crubit_rust_test",
    "crubit_sh_test",
)

package(
    default_applicable_licenses = ["//:license"],
    default_visibility = ["//:__subpackages__"],
)

# `supported_platforms` can be used as a select condition to distinguish
# platforms where cc_bindings_from_rs (aka cpp_api_from_rust) is supported from
# those where it is not.
#
# See `//:supported_platforms` for platforms where both
# directions of Crubit are supported, and for guidance on which to use.

rust_library(
    name = "cpp_api_from_rust_lib",
    srcs = ["lib.rs"],
    edition = "2024",
    deps = [
        ":cmdline",
        ":run_compiler",
        ":rustversion",
        "//cc_bindings_from_rs/generate_bindings",
        "//common:arc_anyhow",
        "//common:code_gen_utils",
        "//common:crubit_feature",
        "//common:error_report",
        "//common:kythe_metadata",
        "//common:token_stream_printer",
        "@crate_index//:clap",  # v4
        "@crate_index//:flagset",  # v0_4
        "@crate_index//:itertools",  # v0_13
        "@crate_index//:quote",  # v1
    ],
)

crubit_rust_binary(
    name = "cargo-cpp_api_from_rust",
    srcs = ["cargo-cpp_api_from_rust.rs"],
    # Do not add a fake dependency on Crubit, because it will introduce a dependency cycle.
    crubit_dep = False,
    deps = [
        ":cmdline",
        ":cpp_api_from_rust_lib",
        ":toposort",
        "//common:arc_anyhow",
        "@crate_index//:cargo_metadata",  # v0_23
        "@crate_index//:clap",  # v4
        "@crate_index//:clap_cargo",  # v0_12
    ],
)

crubit_rust_binary(
    name = "cc_bindings_from_rs",
    srcs = ["cc_bindings_from_rs.rs"],
    # Do not add a fake dependency on Crubit, because it will introduce a dependency cycle.
    crubit_dep = False,
    # This is built by cargo on presubmit, so should not go stale.
    # It doesn't work in Bazel because a cargo-clap feature we need is not enabled.
    tags = [
        "manual",
        "norapid",
        "not_run",
        "notap",
    ],
    visibility = ["//visibility:public"],
    deps = [
        ":cmdline",
        ":cpp_api_from_rust_lib",
        "//common:arc_anyhow",
        "@crate_index//:clap",  # v4
        "@crate_index//:itertools",  # v0_13
    ],
)

# This target exists to add the correct [dev-dependencies] to the cargo-cpp_api_from_rust's
# Cargo.toml.
crubit_rust_test(
    name = "cargo_cpp_api_from_rust_test",
    crate = ":cargo-cpp_api_from_rust",
    tags = [
        "manual",
        "norapid",
        "not_run",
        "notap",
    ],
    deps = [
        "@crate_index//:tempfile",  # v3
    ],
)

crubit_rust_test(
    name = "cc_bindings_from_rs_test",
    crate = ":cpp_api_from_rust_lib",
    # We don't yet support running cc_bindings_from_rs itself on macOS (we only target macOS).
    tags = ["not_run:mac"],
    deps = [
        ":run_compiler_test_support",
        "//common:external_binaries",
        "@crate_index//:regex",  # v1
        "@crate_index//:tempfile",  # v3
    ],
)

crubit_sh_test(
    name = "cc_bindings_from_rs_sh_test",
    srcs = ["cc_bindings_from_rs_sh_test.sh"],
    data = [
        ":cc_bindings_from_rs",
    ],
    # We don't yet support running cc_bindings_from_rs itself on macOS (we only target macOS).
    tags = ["not_run:mac"],
    deps = [
        "//util/shell/gbash",
        "//util/shell/gbash:unit",
    ],
)

rust_library(
    name = "cmdline",
    srcs = [
        "cmdline.rs",
    ],
    edition = "2024",
    deps = [
        "//common:crubit_feature",
        "//common:dyn_format",
        "@crate_index//:anyhow",  # v1
        "@crate_index//:clap",  # v4
        "@crate_index//:flagset",  # v0_4
    ],
)

crubit_rust_test(
    name = "cmdline_test",
    crate = ":cmdline",
    # We don't yet support running rustc itself on macOS (we only target macOS).
    tags = ["not_run:mac"],
    deps = [
        ":run_compiler_test_support",
        "@crate_index//:itertools",  # v0_13
        "@crate_index//:tempfile",  # v3
    ],
)

rust_library(
    name = "crubit_attr",
    srcs = ["crubit_attr.rs"],
    edition = "2024",
    deps = [
        ":rustversion",
        "@crate_index//:anyhow",  # v1
    ],
)

crubit_rust_test(
    name = "crubit_attr_test",
    srcs = ["crubit_attr_test.rs"],
    # We don't yet support running rustc itself on macOS (we only target macOS).
    tags = ["not_run:mac"],
    deps = [
        ":crubit_attr",
        ":run_compiler_test_support",
        "@crate_index//:anyhow",  # v1
    ],
)

rust_library(
    name = "run_compiler",
    srcs = [
        "run_compiler.rs",
    ],
    edition = "2024",
    deps = [
        ":rustversion",
        "//common:arc_anyhow",
        "@crate_index//:either",  # v1
    ],
)

crubit_rust_test(
    name = "run_compiler_test",
    crate = ":run_compiler",
    # We don't yet support running rustc itself on macOS (we only target macOS).
    tags = ["not_run:mac"],
    deps = [
        ":run_compiler_test_support",
        "@crate_index//:tempfile",  # v3
    ],
)

rust_library(
    name = "run_compiler_test_support",
    testonly = True,
    srcs = [
        "run_compiler_test_support.rs",
    ],
    data = [
        "@rust_linux_x86_64__x86_64-unknown-linux-gnu__nightly_tools//:rust_std-x86_64-unknown-linux-gnu",
    ],
    edition = "2024",
    rustc_flags = [
        "--cfg=bazel",
        "--cfg=oss",
    ],
    deps = [
        ":rustversion",
        "@crate_index//:itertools",  # v0_13
        "@rules_rust//tools/runfiles",
    ],
)

crubit_rust_test(
    name = "run_compiler_test_support_test",
    crate = ":run_compiler_test_support",
    rustc_flags = ["--cfg=oss"],
    # We don't yet support running rustc itself on macOS (we only target macOS).
    tags = ["not_run:mac"],
)

rust_library(
    name = "toposort",
    srcs = ["toposort.rs"],
    edition = "2024",
)

crubit_rust_test(
    name = "toposort_test",
    crate = ":toposort",
)

rust_proc_macro(
    name = "rustversion_impl",
    srcs = ["rustversion_impl.rs"],
    deps = [
        "@crate_index//:proc-macro2",
        "@crate_index//:quote",  # v1
        "@crate_index//:syn",  # v1
    ],
)

crubit_rust_test(
    name = "rustversion_impl_test",
    crate = ":rustversion_impl_proc_macro_internal",
)

rust_library(
    name = "rustversion",
    srcs = ["rustversion.rs"],
    edition = "2024",
    proc_macro_deps = [
        ":rustversion_impl",
        "@crate_index//:rustversion",  # v1
    ],
)
