v8 147.3.0

Rust bindings to V8
Documentation
# Copyright 2021 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import("//build/rust/gni_impl/rust_target.gni")

# Defines a Rust static library which can be used by downstream Rust or C++
# targets. This is a single Rust compilation unit consisting of potentially
# multiple .rs files.
#
# We term this 'rust_static_library' because it is used most analogously
# to a C++ 'static_library' in Chromium. Like the C++ one, it can be compiled
# independently into an intermediate linking target. The output contains the
# object file(s) of the GN target's sources, and not its dependencies.
#
# Parameters
#
#   sources
#     List of source files which this crate is allowed to compile, which is
#     used to determine the impact of source code changes on other GN targets.
#     This is not used by the Rust compiler, as it discovers source files by
#     following `mod` declarations starting at the `crate_root`. The
#     discovered source files must match this list. (This is not yet enforced,
#     but will be.)
#
#   edition (optional)
#     Edition of the Rust language to be used.
#     Options are "2015", "2018", "2021", and "2024". Defaults to "2024".
#
#   allow_unsafe (optional)
#     Set to true to allow unsafe code in this target. Defaults to false.
#
#   configs (optional)
#     A list of config labels (in the GN meaning) applying to this target.
#
#   rustflags (optional)
#     Explicit flags for rustc command line. (Use 'edition' or 'features'
#     where possible).
#
#   deps (optional)
#     List of GN targets on which this crate depends. These may be Rust
#     or non-Rust targets.
#
#   public_deps (optional)
#     List of GN targets on which this crate depends, and which are exported
#     into the dependency list of any crate that depends on it. Dependency
#     crates that appear in the public API should be included here.
#
#   test_deps (optional)
#     List of GN targets on which this crate's tests depend, in addition
#     to deps.
#
#   is_gtest_unittests (optional)
#     Should only be set to true for rlibs of gtest unit tests. This ensures
#     all objects in the rlib are linked into the final target, rather than
#     pruning dead code, so that the tests themselves are not discarded by the
#     linker.
#
#   mutually_dependent_target (optional)
#   mutually_dependent_public_deps (optional)
#     These is for use by the mixed_target() template.
#
#     If this Rust code is intrinsically paired with some C/C++ code,
#     with bidirectional calls between the two, then this would
#     be a circular dependency. GN does not allow circular dependencies,
#     (other than for header files per allow_circular_includes_from).
#     But this is common for a 'component' which has both Rust and C++
#     code. You should structure things such that the C++ code depends
#     on the Rust code in the normal way:
#        static_library("cpp_stuff") {
#          deps = [ "rust_stuff" ]
#          # ..
#        }
#     but that the Rust target also notes the C++ target using this
#     'mutually_dependent_target' parameter.
#        rust_static_library("rust_stuff") {
#          mutually_dependent_target = "cpp_stuff"
#          mutually_dependent_public_deps = _cpp_stuff_public_deps
#          # ..
#        }
#
#     This causes the Rust unit tests, if generated, to depend on the mutually
#     dependent target, since depending on the Rust code only would be
#     insufficient. And it allows any C++ bindings generated from the Rust code
#     to include headers from the mutually_dependent_target by depending on its
#     public_deps.
#
#   build_native_rust_unit_tests (optional)
#     Builds native unit tests (under #[cfg(test)]) written inside the Rust
#     crate. This will create a `<name>_unittests` executable in the output
#     directory when set to true.
#
#   unit_test_target (optional)
#     Overrides the default name for the unit tests target
#
#   crate_root (optional)
#     Location of the crate root.
#     This defaults to `./src/lib.rs` and should only be changed when
#     absolutely necessary (such as in the case of generated code).
#
#   features (optional)
#     A list of conditional compilation flags to enable. This can be used
#     to set features for crates built in-tree which are also published to
#     crates.io. Each feature in the list will be passed to rustc as
#     '--cfg feature=XXX'
#
#   cxx_bindings (optional)
#     A list of Rust files which contain #[cxx::bridge] mods and should
#     therefore have C++ bindings generated. See https://cxx.rs.
#     This will automatically add appropriate dependencies: there's no
#     need to depend on the cxx crate or any generated bindings.
#
#   cpp_api_from_rust (optional)
#     A dictionary that if present opts-into using Crubit's tools to generate
#     a C++ `.h` file with C++ bindings for public Rust APIs exported by the
#     create.  The dictionary may have the following additional entries:
#
#       target_name
#         The name of the C++ `source_set` that `build/rust/*.gni` should create
#         and which will provide the auto-generated bindings.
#
#       features (optional)
#         Not implemented yet.  A list of strings that may enable additional,
#         experimental Crubit features - see
#         https://github.com/google/crubit/blob/main/features/README.md
#
#   allow_circular_includes_from (optional)
#     If cxx_bindings is present, this will allow the generated cxx bindings to
#     include headers from the listed targets. Generally, this should only be
#     used to include headers from C++ shim libraries that are logically part
#     of the cxx bindings.
#
#     TODO(crbug.com/469057512): this option may be replaced with an equivalent
#     formulation in the future, which moves the circularity under the hood.
#
#   data, testonly, visibility (optional)
#     Same meaning as in other GN targets.
#
#   crate_name (optional)
#     Discouraged - first-party code should prefer to use the auto-generated,
#     target-based crate name which is guaranteed to be globally unique (and
#     still ergonomic to import and use via the `chromium::import!` macro).
#
#   inputs (optional)
#     Additional input files needed for compilation (such as `include!`ed files)
#
#   test_inputs (optional)
#     Same as above but for the unit tests target
#
#   rustc_metadata (optional)
#     Override the metadata identifying the target's version. This allows e.g.
#     linking otherwise conflicting versions of the same Rust library. The
#     metadata string will also be appended to the output library names.
#     Should be used sparingly, since generally we should have one version and
#     build of each target.
#
# Example of usage:
#
#   rust_static_library("foo_bar") {
#     deps = [
#       "//boo/public/rust/bar",
#       "//third_party/rust/crates:argh",
#       "//third_party/rust/crates:serde",
#       "//third_party/rust/crates:slab",
#     ]
#     sources = [ "src/lib.rs" ]
#   }
#
# This template is intended to serve the same purpose as 'rustc_library'
# in Fuchsia.
template("rust_static_library") {
  _target_name = target_name

  _configs = []
  _all_dependent_configs = []

  if (defined(invoker.configs)) {
    _configs += invoker.configs
  }

  # TODO(dcheng): Is there any value in allowing rust_shared_library() to also
  # set `is_gtest_unittest` to true?
  if (defined(invoker.is_gtest_unittests) && invoker.is_gtest_unittests) {
    _output_dir = rebase_path(target_out_dir, root_build_dir)

    config("${_target_name}_alwayslink") {
      # Targets using the #[gtest(...)] proc macro register their tests with
      # static initializers. A rust library target generates a .rlib, which is
      # a regular static library with extra metadata. However, if nothing
      # outside the .rlib references functions in the .rlib—as is often the
      # case with a target containing only tests—the linker will not pull in
      # the .rlib into the final test binary at all, so the tests won't run.
      #
      # C++ works around this by using source sets and directly passes the .o
      # files to the linker, but Rust does not have a parallel to this. Instead,
      # force the linker to always include the whole archive.

      # NOTE: TargetName=>CrateName mangling algorithm should be updated
      # simultaneously in 3 places: here, //build/rust/rust_target.gni,
      # //build/rust/chromium_prelude/import_attribute.rs
      if (defined(invoker.crate_name)) {
        _crate_name = invoker.crate_name
      } else {
        _dir_hash = string_hash(get_label_info(":${_target_name}", "dir"))
        _crate_name = "${_target_name}_${_dir_hash}"
      }

      _rlib_path = "${_output_dir}/lib${_crate_name}.rlib"
      if (current_os == "aix") {
        # The AIX linker does not implement an option for this.
      } else if (is_win) {
        ldflags = [ "/WHOLEARCHIVE:${_rlib_path}" ]
      } else {
        ldflags = [ "-LinkWrapper,add-whole-archive=${_rlib_path}" ]
      }
    }
    _all_dependent_configs += [ ":${target_name}_alwayslink" ]
    _configs += [ "//build/rust:is_gtest_unittests" ]
  }

  rust_target(_target_name) {
    forward_variables_from(invoker,
                           "*",
                           TESTONLY_AND_VISIBILITY + [ "configs" ])
    forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
    library_configs = _configs
    all_dependent_configs = _all_dependent_configs
    target_type = "rust_library"
  }
}

set_defaults("rust_static_library") {
  configs = default_compiler_configs
}