# Copyright 2018 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import("//build/toolchain/rbe.gni")
import("//build/toolchain/restat.gni")

# Defines a Rust procedural macro
#
# Parameters
#
#   output_name (optional)
#   name (optional, deprecated)
#     Name of the crate as defined in its manifest file. If not specified, it is
#     assumed to be the same as the target name.
#
#   version (optional)
#     Semver version of the crate as seen on crates.io.
#
#   edition (optional)
#     Edition of the Rust language to be used.
#     Options are "2015" and "2018". Defaults to "2018".
#
#   configs (optional)
#     A list of config labels applying to this target.
#
#   enforce_source_listing (optional)
#     When true, enforces that any source files used by the Rust compiler are
#     listed in `sources`. Defaults to true.
#
#   sources (optional)
#     List of source files which this crate is allowed to compile. Only
#     allowed when `enforce_source_listing = true`.
#     The Rust compiler discovers source files by following `mod` declarations
#     starting at the `source_root`. The discovered source files must match this
#     list.
#
#   inputs (optional)
#     List of additional non-source files read by the compiler. These are typically
#     configuration or test-data files included in the build with the `include_str!`
#     macro. Only allowed when `enforce_source_listing = true`.
#
#   deps (optional)
#     List of rust_library GN targets on which this crate depends.
#     Third party crates can be included through paths like
#     "//third_party/rust_crates:<cratename>".
#
#   source_root (optional)
#     Location of the crate root (e.g. `src/main.rs` or `src/lib.rs`).
#     This defaults to `./src/main.rs` for binaries and `./src/lib.rs` for libraries,
#     and should only be changed when absolutely necessary
#     (such as in the case of generated code).
#
#   output_dir (optional)
#     Directory that the resulting macro should be placed in.
#     See: `gn help output_dir`
#
#   disable_rbe (optional)
#     Set to true to force this target to build locally, overriding the global `enable_rbe`.
#
# Example of usage:
#
#   rustc_macro("foo") {
#     deps = [
#       "//garnet/public/rust/bar",
#       "//third_party/rust_crates:serde",
#       "//third_party/rust_crates:slab",
#     ]
#     sources = [ "src/lib.rs" ]
#   }
template("rustc_macro") {
  # Compiling procedural macros is... a bit awkward.
  #
  # Even though they're provided to crates that use them as if they were normal
  # external crates, they're actually '.so'/'.dylib's that are compiled for the host machine
  # and then linked into the compiler, so they and all their dependencies should
  # be built for the host target.
  #
  # Once this is done, the resulting artifacts are copied into the Fuchsia target
  # directories to act as if they had been built for Fuchsia. In order to avoid
  # conflicts, the outputs of the original (host) artifact are built with a
  # `_proc_macro` suffix added onto the end, which is removed when they're copied
  # into the final target directory.
  forward_variables_from(invoker, [ "visibility" ])

  proc_macro_target = "${target_name}_proc_macro"

  assert(!(defined(invoker.output_name) && defined(invoker.name)),
         "Only one of output_name and name may be specified.")

  # The 'is_host' var is true in situations that we don't want, such as
  # sanitizers and cross-compiling for _other_ hosts.
  #
  # We only want this to be run in _this_ machine's host_toolchain, and then
  # only in its base variant.

  # This confirms that this is running on _this_ machine's host_toolchain.
  in_host_compiler_toolchain = current_toolchain == host_toolchain

  # This confirms that it's also running on the base variant of the host_toolchain.
  in_host_base_variant =
      in_host_compiler_toolchain && current_toolchain == toolchain_variant.base

  # The actual host-target build of the proc macro crate.
  if (in_host_base_variant) {
    package_name = target_name
    if (defined(invoker.output_name)) {
      package_name = invoker.output_name
    } else if (defined(invoker.name)) {
      package_name = invoker.name
    }
    crate_name = string_replace(package_name, "-", "_")

    if (!defined(invoker.source_root)) {
      source_root = "src/lib.rs"
    } else {
      source_root = invoker.source_root
    }

    _sources = []
    _deps = []

    if (!defined(invoker.enforce_source_listing) ||
        invoker.enforce_source_listing == true) {
      # fail early when the user forgets to list sources
      assert(defined(invoker.sources), "sources must be listed")
      _sources = invoker.sources
    } else {
      not_needed(invoker, [ "sources" ])

      # This is a hack to workaround the fact that a GN `tool` invocation can't receive arbitrary input.
      # Add a sentinel value so that enforcement is skipped.
      _sources = [ "//build/rust/__SKIP_ENFORCEMENT__.rs" ]

      # Opting out of strict sources check requires that the package is present
      # in a global allow-list.
      _deps += [ "//build/rust:disable_strict_sources_check_allowlist" ]
    }

    rust_proc_macro(proc_macro_target) {
      configs = []
      configs = invoker.configs

      not_needed(invoker,
                 [
                   "version",
                   "non_rust_deps",
                   "force_opt",
                 ])
      crate_root = source_root
      output_name = crate_name

      deps = _deps
      if (defined(invoker.deps)) {
        deps += invoker.deps
      }

      if (defined(invoker.non_rust_deps)) {
        data_deps = invoker.non_rust_deps
      }

      sources = _sources

      if (defined(invoker.edition) && invoker.edition == "2015") {
        configs -= [ "//build/config/rust:edition_2018" ]
        configs += [ "//build/config/rust:edition_2015" ]
      }

      forward_variables_from(invoker,
                             [
                               "inputs",
                               "output_dir",
                               "testonly",
                               "visibility",
                             ])

      inputs = []
      if (defined(invoker.inputs)) {
        inputs = invoker.inputs
      }
      _use_rbe = enable_rbe
      if (defined(invoker.disable_rbe) && invoker.disable_rbe) {
        _use_rbe = false
      }
      if (_use_rbe) {
        # Depend on Rust/RBE scripts and tools
        inputs += rust_rbe_deps
      }
      if (restat_rust) {
        inputs += [
          python_exe_src,
          restat_wrapper,
        ]
      }
    }
  } else {
    not_needed(invoker, "*")
  }

  # proc_macros are loadable modules that are used by the rustc compiler itself,
  # and as such, need to be compiled in the _base_ (non-sanitizer) variant of
  # host toolchain.
  #
  # The following creates a set of dependencies through groups that
  # link from the current toolchain to the base toolchain of the host_toolchain
  # variant:
  #
  # target_name($current_toolchain)   // omitted if already in host.
  #  |- target_name($host_toolchain)
  #      |- proc_macro_target($host_toolchain_base)

  # If not in _this_ machine's host_toolchain, switch to it.
  if (!in_host_compiler_toolchain) {
    group(target_name) {
      public_deps = [ ":${target_name}($host_toolchain)" ]
    }

    # the proc_macro_target isn't used.
    not_needed([ "proc_macro_target" ])
  } else {
    # now in the proper host_toolchain, have the group depend on the base of the host
    # toolchain's variant
    group(target_name) {
      public_deps = [ ":${proc_macro_target}(${toolchain_variant.base})" ]
    }
  }
}
