mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-11-24 06:16:30 +03:00
414 lines
14 KiB
Plaintext
414 lines
14 KiB
Plaintext
# 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/rust.gni")
|
|
import("//build/rust/rust_autocxx.gni")
|
|
import("//build/rust/rust_unit_test.gni")
|
|
|
|
# Creates a Rust target (rlib, executable, proc macro etc.) with
|
|
# ability to understand some handy variables such as "edition" and
|
|
# "features" and also to build any associated unit tests.
|
|
#
|
|
# Normally, you should not use this directly. Use either
|
|
# - cargo_crate.gni - for 3p crates only
|
|
# - rust_static_library.gni - for 1p Rust code
|
|
# - mixed_static_library.gni - for 1p C++ and Rust code together.
|
|
#
|
|
# Because the common use of this is rust_static_library, all the documentation
|
|
# for the supported options is given in rust_static_library.gni. Please refer
|
|
# over there.
|
|
#
|
|
# If you're using rust_target directly, you will also need to specify:
|
|
# target_type
|
|
# executable, rust_library etc. per GN norms
|
|
#
|
|
# support_use_from_cpp (bool)
|
|
# Whether both C++ and Rust may link against this. If so, the Rust standard
|
|
# library will be explicitly included for C++ to link against. This is
|
|
# always true if cxx_bindings is non-empty, in which case [auto]cxx
|
|
# will also be implicitly depended on.
|
|
#
|
|
# There is one area where this differs from `rust_static_library`: configs.
|
|
# Here, you must specify `executable_configs` or `library_configs`
|
|
# depending on the type of thing you're generating. This is so that
|
|
# different defaults can be provided.
|
|
|
|
template("rust_target") {
|
|
# Only one of `crate_root` or `generate_crate_root` can be specified, or
|
|
# neither.
|
|
assert(!defined(invoker.crate_root) ||
|
|
!(defined(invoker.generate_crate_root) && invoker.generate_crate_root))
|
|
|
|
_target_name = target_name
|
|
_crate_name = target_name
|
|
if (defined(invoker.crate_name)) {
|
|
_crate_name = invoker.crate_name
|
|
}
|
|
|
|
if (defined(invoker.output_dir) && invoker.output_dir != "") {
|
|
_out_dir = invoker.output_dir
|
|
} else {
|
|
_out_dir = target_out_dir
|
|
}
|
|
|
|
if (defined(invoker.generate_crate_root) && invoker.generate_crate_root) {
|
|
generated_file("${_target_name}_crate_root") {
|
|
outputs = [ "${target_gen_dir}/${target_name}.rs" ]
|
|
contents = [
|
|
"// Generated crate root for ${_target_name}.",
|
|
"// @generated",
|
|
"",
|
|
]
|
|
foreach(rs, invoker.sources) {
|
|
rs_path_from_root = rebase_path(rs, target_gen_dir)
|
|
contents += [ "#[path = \"${rs_path_from_root}\"]" ]
|
|
|
|
# Drop the file extension from the module name.
|
|
rs_modname = string_replace(rs, ".rs", "")
|
|
|
|
# Replace invalid "/" chars in the source file path.
|
|
rs_modname = string_replace(rs_modname, "/", "_")
|
|
|
|
# Since source files are specified relative to the BUILD.gn they may
|
|
# also have ".." path components.
|
|
rs_modname = string_replace(rs_modname, "..", "dotdot")
|
|
contents += [
|
|
"mod ${rs_modname};",
|
|
"",
|
|
]
|
|
}
|
|
}
|
|
_crate_root =
|
|
string_join("", get_target_outputs(":${_target_name}_crate_root"))
|
|
} else if (defined(invoker.crate_root)) {
|
|
_crate_root = invoker.crate_root
|
|
} else if (invoker.target_type == "executable") {
|
|
_crate_root = "src/main.rs"
|
|
} else {
|
|
_crate_root = "src/lib.rs"
|
|
}
|
|
|
|
_testonly = false
|
|
if (defined(invoker.testonly)) {
|
|
_testonly = invoker.testonly
|
|
}
|
|
if (defined(invoker.visibility)) {
|
|
_visibility = invoker.visibility
|
|
}
|
|
|
|
_rustflags = []
|
|
if (defined(invoker.rustflags)) {
|
|
_rustflags += invoker.rustflags
|
|
}
|
|
if (defined(invoker.features)) {
|
|
foreach(i, invoker.features) {
|
|
_rustflags += [ "--cfg=feature=\"${i}\"" ]
|
|
}
|
|
}
|
|
_edition = "2021"
|
|
if (defined(invoker.edition)) {
|
|
_edition = invoker.edition
|
|
}
|
|
_configs = [ string_join("",
|
|
[
|
|
"//build/rust:edition_",
|
|
_edition,
|
|
]) ]
|
|
if (invoker.target_type == "executable") {
|
|
if (defined(invoker.executable_configs)) {
|
|
_configs += invoker.executable_configs
|
|
}
|
|
} else {
|
|
if (defined(invoker.library_configs)) {
|
|
_configs += invoker.library_configs
|
|
}
|
|
}
|
|
_forward_to_host_toolchain = false
|
|
if (invoker.target_type == "rust_proc_macro") {
|
|
# TODO(crbug.com/gn/104): GN rust_proc_macro targets are missing this
|
|
# command line flag, for the proc_macro crate which is provided by rustc for
|
|
# compiling proc-macros.
|
|
_rustflags += [
|
|
"--extern",
|
|
"proc_macro",
|
|
]
|
|
|
|
if (current_toolchain != host_toolchain) {
|
|
_forward_to_host_toolchain = true
|
|
}
|
|
_main_target_suffix = "${target_name}__proc_macro"
|
|
} else {
|
|
_main_target_suffix = "__rlib"
|
|
}
|
|
|
|
_deps = []
|
|
if (defined(invoker.deps)) {
|
|
_deps += invoker.deps
|
|
}
|
|
_public_deps = []
|
|
if (defined(invoker.public_deps)) {
|
|
_public_deps += invoker.public_deps
|
|
}
|
|
|
|
_build_unit_tests = false
|
|
if (defined(invoker.build_native_rust_unit_tests)) {
|
|
_build_unit_tests =
|
|
invoker.build_native_rust_unit_tests && can_build_rust_unit_tests
|
|
}
|
|
|
|
# Declares that the Rust crate generates bindings between C++ and Rust via the
|
|
# Cxx/autocxx crates. It may generate C++ headers and/or use the cxx crate macros
|
|
# to generate Rust code internally, depending on what bindings are declared. If
|
|
# set, it's a set of rust files that include Cxx or autocxx bindings declarations.
|
|
_cxx_bindings = []
|
|
if (defined(invoker.cxx_bindings)) {
|
|
_cxx_bindings = invoker.cxx_bindings
|
|
}
|
|
_rustenv = []
|
|
if (defined(invoker.rustenv)) {
|
|
_rustenv += invoker.rustenv
|
|
}
|
|
foreach(_autocxx_generated, _cxx_bindings) {
|
|
# TODO(crbug.com/1306841): Currently we support only a single
|
|
# include_cpp! macro per target and this ugly environment
|
|
# variable is necessary. Meanwhile, this path must match that of
|
|
# out_gen0_rs in rust_autocxx.gni.
|
|
_rustenv += [ "AUTOCXX_RS_FILE=" + rebase_path(
|
|
"$target_gen_dir/$_autocxx_generated/gen0.include.rs") ]
|
|
}
|
|
|
|
# Normally we generate a C++ bindings group only if there are C++ bindings,
|
|
# since it's not useful otherwise. But mixed targets want to be able to depend
|
|
# on the Rust side regardless, or other Rust targets that provide interop
|
|
# without using Cxx to generate bindings (such as via #[no_mangle] functions).
|
|
_support_use_from_cpp = _cxx_bindings != []
|
|
if (defined(invoker.support_use_from_cpp) && invoker.support_use_from_cpp) {
|
|
_support_use_from_cpp = true
|
|
}
|
|
|
|
if (defined(invoker.mutually_dependent_target)) {
|
|
_mutually_dependent_target = invoker.mutually_dependent_target
|
|
_mutually_dependent_public_deps = invoker.mutually_dependent_public_deps
|
|
} else {
|
|
assert(!defined(_mutually_dependent_public_deps))
|
|
}
|
|
|
|
# TODO(danakj): This could be a hash generated from the input crate, such as
|
|
# from its path, in which case the BUILD.gn would not need to specify
|
|
# anything. But GN doesn't give us a hash function to make that easy.
|
|
_metadata = "0"
|
|
if (defined(invoker.epoch)) {
|
|
_metadata = invoker.epoch
|
|
}
|
|
|
|
# We require that all source files are listed, even though this is
|
|
# not a requirement for rustc. The reason is to ensure that tools
|
|
# such as `gn deps` give the correct answer, and thus we trigger
|
|
# the right test suites etc. on code change.
|
|
# TODO(crbug.com/1256930) - verify this is correct
|
|
assert(defined(invoker.sources), "sources must be listed")
|
|
|
|
if (_forward_to_host_toolchain) {
|
|
# Redirect to the host toolchain.
|
|
group(_target_name) {
|
|
testonly = _testonly
|
|
if (defined(_visibility)) {
|
|
visibility = _visibility
|
|
}
|
|
public_deps =
|
|
[ ":${_target_name}${_main_target_suffix}($host_toolchain)" ]
|
|
}
|
|
|
|
not_needed(invoker, "*")
|
|
not_needed([
|
|
"_build_unit_tests",
|
|
"_crate_root",
|
|
"_crate_name",
|
|
"_cxx_bindings",
|
|
"_deps",
|
|
"_metadata",
|
|
"_mutually_dependent_public_deps",
|
|
"_mutually_dependent_target",
|
|
"_out_dir",
|
|
"_public_deps",
|
|
"_rustenv",
|
|
"_support_use_from_cpp",
|
|
"_test_deps",
|
|
"_testonly",
|
|
"_visibility",
|
|
"proc_macro_target",
|
|
])
|
|
} else {
|
|
group(_target_name) {
|
|
testonly = _testonly
|
|
if (defined(_visibility)) {
|
|
visibility = _visibility
|
|
}
|
|
|
|
# Both the C++ bindings (if present) and the Rust crate should be treated
|
|
# like direct dependencies, so we expose them both in public_deps.
|
|
public_deps = [ ":${_target_name}${_main_target_suffix}" ]
|
|
|
|
if (_support_use_from_cpp) {
|
|
if (_cxx_bindings != []) {
|
|
public_deps += [ ":${_target_name}_autocxx_generated" ]
|
|
|
|
# Additionally, C++ bindings generated by Cxx can include C++ types
|
|
# that come from the Cxx library, such as `rust::Str`. So any C++
|
|
# target that depends on a rust target directly may need access to Cxx
|
|
# as well, which means it must appear in public_deps.
|
|
public_deps += [ "//build/rust:cxx_cppdeps" ]
|
|
} else {
|
|
# If we're supporting use from C++ but not using Cxx bindings, then we
|
|
# just need to make sure C++ links in the Rust stdlib.
|
|
deps = [ "//build/rust/std" ]
|
|
}
|
|
} else {
|
|
# Mixed targets (which define the below) always enable use from C++.
|
|
assert(!defined(_mutually_dependent_target))
|
|
}
|
|
}
|
|
|
|
_rust_deps = _deps
|
|
_rust_public_deps = _public_deps
|
|
_autocxx_deps = _deps + _public_deps
|
|
|
|
# In a mixed target, the C++ bindings may include headers from the C++
|
|
# part of the mixed target. Those headers rely on being used with the
|
|
# correct dependencies present.
|
|
if (defined(_mutually_dependent_public_deps)) {
|
|
_autocxx_deps += _mutually_dependent_public_deps
|
|
}
|
|
|
|
# The Rust target (and unit tests) need the autocxx & cxx crates when using
|
|
# them to generate bindings - both are in autocxx_rustdeps. We also need
|
|
# to depend upon the autocxx code generation step, since when we build
|
|
# our Rust code, a procedural macro will look for a file generated by that
|
|
# codegen step.
|
|
if (_cxx_bindings != []) {
|
|
_rust_deps += [ "//build/rust:autocxx_rustdeps" ]
|
|
|
|
# Generated bindings are a public dep so that the unit tests can include
|
|
# them.
|
|
_rust_public_deps += [ ":${_target_name}_autocxx_generated" ]
|
|
}
|
|
|
|
# You must go through the groups above to get to these targets.
|
|
_visibility = []
|
|
_visibility = [ ":${_target_name}" ]
|
|
|
|
target(invoker.target_type, "${_target_name}${_main_target_suffix}") {
|
|
forward_variables_from(invoker,
|
|
"*",
|
|
TESTONLY_AND_VISIBILITY + [
|
|
"features",
|
|
"deps",
|
|
"public_deps",
|
|
"rustflags",
|
|
"rustenv",
|
|
"configs",
|
|
"output_dir",
|
|
"unit_test_target",
|
|
])
|
|
|
|
testonly = _testonly
|
|
visibility = _visibility
|
|
crate_name = _crate_name
|
|
crate_root = _crate_root
|
|
configs = []
|
|
configs = _configs
|
|
deps = _rust_deps
|
|
public_deps = _rust_public_deps
|
|
rustflags = _rustflags
|
|
rustflags += [ string_join("",
|
|
[
|
|
"-Cmetadata=",
|
|
_metadata,
|
|
]) ]
|
|
rustenv = _rustenv
|
|
rustenv += [ "OUT_DIR=" + rebase_path(_out_dir) ]
|
|
|
|
# The Rust tool() declarations, like C++ ones, use the output_name and
|
|
# output_dir, so that GN targets can override these if needed. Here we
|
|
# give them their default values, or allow them to be overridden.
|
|
output_dir = _out_dir
|
|
if (!defined(output_name) || output_name == "") {
|
|
output_name = crate_name
|
|
}
|
|
}
|
|
|
|
if (_cxx_bindings != []) {
|
|
rust_autocxx("${_target_name}_autocxx_generated") {
|
|
testonly = _testonly
|
|
|
|
visibility = [ ":${_target_name}${_main_target_suffix}" ]
|
|
if (defined(_visibility)) {
|
|
visibility += _visibility
|
|
}
|
|
sources = _cxx_bindings
|
|
deps = _autocxx_deps
|
|
configs = _configs
|
|
|
|
if (is_component_build) {
|
|
# In a component_build the cxx bindings may be linked into a shared
|
|
# library at any point up the dependency tree, so always export.
|
|
export_symbols = true
|
|
} else if (invoker.target_type == "shared_library") {
|
|
export_symbols = true
|
|
} else {
|
|
export_symbols = false
|
|
}
|
|
}
|
|
} else {
|
|
not_needed([
|
|
"_autocxx_deps",
|
|
"_mutually_dependent_public_deps",
|
|
])
|
|
}
|
|
|
|
if (_build_unit_tests) {
|
|
_unit_test_target = "${_target_name}_unittests"
|
|
if (defined(invoker.unit_test_target)) {
|
|
_unit_test_target = invoker.unit_test_target
|
|
}
|
|
|
|
rust_unit_test(_unit_test_target) {
|
|
forward_variables_from(invoker, [ "sources" ])
|
|
testonly = true
|
|
crate_root = _crate_root
|
|
rustflags = _rustflags
|
|
output_dir = _out_dir
|
|
deps = _rust_deps + _public_deps
|
|
if (defined(invoker.test_deps)) {
|
|
deps += invoker.test_deps
|
|
}
|
|
if (defined(_mutually_dependent_target)) {
|
|
# This routes through the C++ mixed target rule to get back to the
|
|
# Rust $_target_name.
|
|
public_deps = [ _mutually_dependent_target ]
|
|
} else {
|
|
public_deps = [ ":${_target_name}" ]
|
|
}
|
|
if (defined(invoker.executable_configs)) {
|
|
configs = []
|
|
configs = invoker.executable_configs
|
|
}
|
|
rustenv = _rustenv
|
|
}
|
|
} else {
|
|
not_needed([
|
|
"_crate_root",
|
|
"_crate_name",
|
|
"_metadata",
|
|
"_mutually_dependent_target",
|
|
])
|
|
}
|
|
}
|
|
}
|
|
|
|
set_defaults("rust_target") {
|
|
executable_configs = default_executable_configs
|
|
library_configs = default_compiler_configs
|
|
}
|