[go: nahoru, domu]

blob: 496a6d857d26dc542ee1c59e5b111aac9110b736 [file] [log] [blame]
# Copyright 2021 The Chromium 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/config/clang/clang.gni")
import("//build/config/rust.gni")
import("//build/config/sysroot.gni")
set_defaults("rust_cxx") {
native_header_deps = []
}
# Template to build Rust/C++ bindings using the tooling
# described at https://cxx.rs.
#
# (Specifically, this builds the C++ side of the bindings.
# The Rust side of the bindings are not 'built' as such, but
# automatically expanded by the Rust compiler by virtue of a
# proc macro which is a simple dependency relationship on the
# Rust target).
#
# This template expands to a source_set containing the
# C++ side of the bindings. Simply treat it as a dependency.
#
# If you're using this, consider whether you should be using
# rust_source_set.gni or mixed_source_set.gni which have
# facilities to do the same code generation in an easier
# way.
#
# Parameters:
#
# inputs:
# The .rs files containing a #[cxx::bridge] section.
#
# native_header_deps (optional)
# C++ targets on which the headers depend in order to build
# successfully.
#
# generate_source_set (optional; default is true)
# Whether to generate a source_set target here.
# (See below for why you might choose false)
#
# export_symbols (optional; default is 'is_component_build')
# Whether the C++ side of the bindings should be exported
# from any shared objects in which it finds itself.
# This is not necessary if the Rust and C++ side of the
# bindings will always find themselves within the same binary,
# which is usually the case in a non-component build.
# Even in a component build, the Rust and C++ code will
# often find itself within the same binary and no exporting
# is required. However, there may be other binaries - most
# commonly Rust unit test executables - which contain the
# Rust side of the bindings but not the C++ side. In such
# a case, it's important that the C++ side symbols are
# exported such that the Rust unit tests can link against
# them. This does the equivalent of adding BASE_EXPORT
# or similar.
# Example:
# Non-component build:
# group of libfoo.a, foo.rlib # contain
# # C++ and Rust side bindings, always both linked
# # into final targets
# foo_rs_unittests # contains Rust side bindings,
# # and any C++ dependencies which will include
# # all of the libfoo code.
# Component build:
# libfoo.so # contains C++ and Rust side bindings
# foo_rs_unittests # contains Rust side test code,
# # but links against libfoo.so to get the C++
# # side bindings. So libfoo.so must make those
# # symbols visible.
#
# Consumers of this template may alternatively depend upon
# the :${target_name}_gen target if you wish to include
# the generated source code in an *existing* source set.
# To do this:
# * depend on the target name with a _gen suffix;
# * for each of the inputs, include in your sources:
# file_name.rs.h
# file_name.rs.cc
# * ensure you also depend upon //build/rust:cxx_cppdeps
#
# A good way to get the file names is:
# process_file_template(list-of-bindings-rs-files,
# [ "{{source_gen_dir}}/{{source_file_part}}.h",
# "{{source_gen_dir}}/{{source_file_part}}.cc" ]
#
# You might want to depend on this template in this mode if
# you have an existing source_set which is referred to
# using 'visibility' rules throughout the codebase.
#
template("rust_cxx") {
assert(defined(invoker.inputs), "Must specify the Rust file to use as input.")
action_foreach("${target_name}_gen") {
sources = invoker.inputs
output_h = "{{source_gen_dir}}/{{source_file_part}}.h"
output_cc = "{{source_gen_dir}}/{{source_file_part}}.cc"
cxxbridge_target =
"//third_party/rust/cxxbridge_cmd/v1:cxxbridge($host_toolchain)"
cxxbridge_out_dir = get_label_info(cxxbridge_target, "root_out_dir")
cxxbridge_executable = "${cxxbridge_out_dir}/cxxbridge"
if (is_win) {
cxxbridge_executable = "${cxxbridge_executable}.exe"
}
script = "//build/rust/run_cxxbridge.py"
inputs = [
cxxbridge_executable,
script,
]
outputs = [
output_h,
output_cc,
]
deps = [ cxxbridge_target ]
args = [
"--exe",
rebase_path(cxxbridge_executable, root_build_dir),
"--header",
output_h,
"--cc",
output_cc,
"{{source}}",
"--",
]
if (!defined(export_symbols)) {
export_symbols = is_component_build
}
if (export_symbols) {
# See explanation of 'export_symbols' above for what this
# does. Implementation note: we could have required users
# of this template to specify a preprocessor symbol, e.g.
# BASE_EXPORT, which would vary per-component. However,
# since we're building only the definition of the bindings,
# not any header files, the export specifications are
# predictable and we don't need to foist that complexity
# on users of this template. The default behavior here
# should be correct. If this proves to be insufficient in
# future, this template should be modified to accept a
# parameter where users can specify 'BASE_EXPORT' or the
# equivalent for their component.
# cxxbridge --cxx-impl-annotations adds this annotation
# to each exported C++ function.
args += [ "--cxx-impl-annotations" ]
if (is_win) {
args += [ "__declspec(dllexport)" ]
} else {
args += [ "__attribute__((visibility(\"default\")))" ]
}
}
# Anyone building the header files we generate needs to have
# RUST_CXX_NO_EXCEPTIONS defined so that they build without
# exception support.
public_configs = [ "//build/rust:cxx_cppconfig" ]
}
if (!defined(invoker.generate_source_set) || invoker.generate_source_set) {
source_set(target_name) {
sources = get_target_outputs(":${target_name}_gen")
deps = [ "//build/rust:cxx_cppdeps" ]
deps += invoker.native_header_deps
public_deps = [ ":${target_name}_gen" ]
}
}
}