Expose a rust_static_library instead of raw rs file from rust_bindgen
Originally, `rust_bindgen` would originally expose an `action` which generates a `.rs` file (and sometimes `.c` file if wrap_static_inline is true). This would move the burden of knowing how to correctly bundle the generated file on the user where they would have to define a custom `BINDGEN_RS_FILE` flag which has to be loaded from the code. In order to eliminate the overhead, the user will treat the `rust_bindgen` as a `rust_static_library` which can be used by importing it using `chromium::import` or `use ..` whether it's first-party or not. The different design also allows the rust toolchain owners to take finer control on what's being done and what's exposed exactly from `rust_bindgen` by tweaking the `bindings.rs` file. This also fixes Cronet in AOSP where Soong (AOSP build system) does not allow a target to access another target's output through its path which what most clients of `rust_bindgen` did through the custom rustflag. In order to stay backward compatible with older consumers of `rust_bindgen`, we created `rust_bindgen_generator` which generates the raw rust which allows flexibility in usage. Bug: 373864033 Change-Id: I3d72aa8ecd11151235d3dd387b313c9d0309d4a6 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5953710 Auto-Submit: Mohannad Farrag <aymanm@google.com> Commit-Queue: David Benjamin <davidben@chromium.org> Reviewed-by: Dale Curtis <dalecurtis@chromium.org> Commit-Queue: danakj <danakj@chromium.org> Reviewed-by: danakj <danakj@chromium.org> Reviewed-by: David Benjamin <davidben@chromium.org> Cr-Commit-Position: refs/heads/main@{#1374672}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
3e6695f6b0
commit
63ce6fc17e
@ -2490,12 +2490,6 @@ rust_static_library("rust_logger") {
|
||||
crate_root = "logging/rust_logger.rs"
|
||||
|
||||
cxx_bindings = [ "logging/rust_logger.rs" ]
|
||||
|
||||
_bindgen_output = get_target_outputs(":rust_log_bindgen")
|
||||
inputs = _bindgen_output
|
||||
rustenv =
|
||||
[ "RUST_LOG_INTEGRATION_BINDGEN_RS_FILE=" +
|
||||
rebase_path(_bindgen_output[0], get_path_info(crate_root, "dir")) ]
|
||||
}
|
||||
|
||||
if (is_linux || is_chromeos) {
|
||||
|
@ -6,12 +6,12 @@ use log::Level::{Debug, Error, Info, Trace, Warn};
|
||||
use log::{LevelFilter, Metadata, Record};
|
||||
use std::ffi::CString;
|
||||
|
||||
mod rust_log_integration {
|
||||
include!(env!("RUST_LOG_INTEGRATION_BINDGEN_RS_FILE"));
|
||||
chromium::import! {
|
||||
"//base:rust_log_bindgen";
|
||||
}
|
||||
|
||||
use rust_log_integration::root::logging::internal::print_rust_log;
|
||||
use rust_log_integration::root::logging::internal::{
|
||||
use rust_log_bindgen::logging::internal::print_rust_log;
|
||||
use rust_log_bindgen::logging::internal::{
|
||||
RustLogSeverity_DEBUG, RustLogSeverity_ERROR, RustLogSeverity_INFO, RustLogSeverity_TRACE,
|
||||
RustLogSeverity_WARNING,
|
||||
};
|
||||
|
16
build/rust/bindings.rs
Normal file
16
build/rust/bindings.rs
Normal file
@ -0,0 +1,16 @@
|
||||
// Copyright 2024 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[allow(non_snake_case)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
mod bindings {
|
||||
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
|
||||
}
|
||||
|
||||
#[cfg(cpp)]
|
||||
pub use bindings::root::*;
|
||||
#[cfg(not(cpp))]
|
||||
pub use bindings::*;
|
@ -5,6 +5,7 @@
|
||||
import("//build/config/clang/clang.gni")
|
||||
import("//build/config/rust.gni")
|
||||
import("//build/config/sysroot.gni")
|
||||
import("//build/rust/rust_bindgen_generator.gni")
|
||||
import("//build/rust/rust_static_library.gni")
|
||||
|
||||
if (is_win) {
|
||||
@ -27,9 +28,8 @@ if (host_os == "win") {
|
||||
|
||||
# Template to build Rust/C bindings with bindgen.
|
||||
#
|
||||
# This template expands to an action that generates the Rust side of the
|
||||
# bindings. Add it as a dependency and then incorporate
|
||||
# `get_target_outputs(target_name)[0]` into your Rust crate.
|
||||
# This template expands to a rust_static_library that exports the
|
||||
# bindings generated from bindgen at the root of the library.
|
||||
#
|
||||
# Parameters:
|
||||
#
|
||||
@ -59,269 +59,58 @@ if (host_os == "win") {
|
||||
# build. Additionally, `get_target_outputs` will return both the Rust file and
|
||||
# a generated C file, but callers can rely on the Rust file being first.
|
||||
#
|
||||
# Rust targets depending on the output must `include!` the generated file, which
|
||||
# can be done as follows. Export `BINDGEN_RS_FILE` in the Rust GN target:
|
||||
# ```
|
||||
# bindgen_output = get_target_outputs(":<rust_bindgen_target>")
|
||||
# inputs = bindgen_output
|
||||
# rustenv = [
|
||||
# "BINDGEN_RS_FILE=" +
|
||||
# rebase_path(bindgen_output[0], get_path_info(crate_root, "dir"))
|
||||
# ]
|
||||
# ```
|
||||
# And then include the generated header file in the Rust library:
|
||||
# ```
|
||||
# #[allow(dead_code)]
|
||||
# #[allow(non_upper_case_globals)]
|
||||
# #[allow(non_camel_case_types)]
|
||||
# #[allow(non_snake_case)]
|
||||
# mod ffi {
|
||||
# include!(env!("BINDGEN_RS_FILE"));
|
||||
# }
|
||||
# ```
|
||||
# If using `cpp = true`, consider adding this to the bottom of the `ffi` module,
|
||||
# below the `include!`:
|
||||
# ```
|
||||
# pub use root::*;
|
||||
# ```
|
||||
#
|
||||
# For a small, self-contained example please see:
|
||||
# * C header: //build/rust/tests/bindgen_test
|
||||
# * C++ header: //build/rust/tests/bindgen_cpp_test
|
||||
template("rust_bindgen") {
|
||||
assert(defined(invoker.header),
|
||||
"Must specify the C/C++ header file to make bindings for.")
|
||||
_wrap_static_fns = defined(invoker.wrap_static_fns) && invoker.wrap_static_fns
|
||||
# "_generator" will be added to the rust_bindgen_generator target.
|
||||
_rust_bindgen_generator_name = target_name + "_generator"
|
||||
_wrap_static_fns = false
|
||||
if (defined(invoker.wrap_static_fns) && invoker.wrap_static_fns) {
|
||||
_wrap_static_fns = true
|
||||
}
|
||||
rust_bindgen_generator(_rust_bindgen_generator_name) {
|
||||
forward_variables_from(invoker,
|
||||
"*",
|
||||
[
|
||||
"library_name",
|
||||
"output_name",
|
||||
] + TESTONLY_AND_VISIBILITY)
|
||||
|
||||
if (!defined(invoker.cpp)) {
|
||||
_cpp = false
|
||||
} else {
|
||||
_cpp = invoker.cpp
|
||||
# This will allow the rust_static_library to depend on the `rust_bindgen_generator`
|
||||
# through visibility.
|
||||
library_name = target_name
|
||||
|
||||
# We know the library that is going to consume this rust_bindgen and we're sure
|
||||
# that only a single bindgen is there. So rename the bindings to avoid passing
|
||||
# envflags.
|
||||
# envflags are usually problematic for Cronet as Soong does not support it (b/181221467).
|
||||
output_name = "bindings"
|
||||
}
|
||||
|
||||
_bindgen_target_name = target_name
|
||||
action(_bindgen_target_name) {
|
||||
# bindgen relies on knowing the {{defines}} and {{include_dirs}} required
|
||||
# to build the C++ headers which it's parsing. These are passed to the
|
||||
# script's args and are populated using deps and configs.
|
||||
rust_static_library(target_name) {
|
||||
forward_variables_from(invoker,
|
||||
TESTONLY_AND_VISIBILITY + [
|
||||
"configs",
|
||||
"deps",
|
||||
"public_configs",
|
||||
"public_deps",
|
||||
"crate_name",
|
||||
"cpp",
|
||||
])
|
||||
|
||||
sources = [ invoker.header ]
|
||||
|
||||
if (!defined(configs)) {
|
||||
configs = []
|
||||
}
|
||||
|
||||
# Several important compiler flags come from default_compiler_configs
|
||||
configs += default_compiler_configs
|
||||
|
||||
output_dir = "$target_gen_dir"
|
||||
out_gen_rs = "$output_dir/${target_name}.rs"
|
||||
|
||||
script = rebase_path("//build/rust/run_bindgen.py")
|
||||
inputs = [
|
||||
_bindgen_path,
|
||||
"//build/action_helpers.py",
|
||||
"//build/gn_helpers.py",
|
||||
"//build/rust/filter_clang_args.py",
|
||||
]
|
||||
|
||||
depfile = "$target_out_dir/${target_name}.d"
|
||||
outputs = [ out_gen_rs ]
|
||||
|
||||
args = [
|
||||
"--exe",
|
||||
rebase_path(_bindgen_path, root_build_dir),
|
||||
"--header",
|
||||
rebase_path(invoker.header, root_build_dir),
|
||||
"--depfile",
|
||||
rebase_path(depfile, root_build_dir),
|
||||
"--output",
|
||||
rebase_path(out_gen_rs, root_build_dir),
|
||||
"--libclang-path",
|
||||
rebase_path(_libclang_path, root_build_dir),
|
||||
]
|
||||
|
||||
crate_root = "//build/rust/bindings.rs"
|
||||
sources = [ crate_root ]
|
||||
bindgen_deps = [ ":$_rust_bindgen_generator_name" ]
|
||||
allow_unsafe = true
|
||||
if (_wrap_static_fns) {
|
||||
if (_cpp) {
|
||||
out_gen_c = "$output_dir/${target_name}.cc"
|
||||
} else {
|
||||
out_gen_c = "$output_dir/${target_name}.c"
|
||||
}
|
||||
outputs += [ out_gen_c ]
|
||||
args += [
|
||||
"--wrap-static-fns",
|
||||
rebase_path(out_gen_c, root_build_dir),
|
||||
# Add a dependency on the static_fns library for simplicity if
|
||||
# it's declared.
|
||||
deps = [ ":${_rust_bindgen_generator_name}_static_fns" ]
|
||||
}
|
||||
if (defined(cpp) && cpp) {
|
||||
# This cfg is used to control the bindings public export.
|
||||
rustflags = [
|
||||
"--cfg",
|
||||
"cpp",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_linux) {
|
||||
# Linux clang, and clang libs, use a shared libstdc++, which we must
|
||||
# point to.
|
||||
args += [
|
||||
"--ld-library-path",
|
||||
rebase_path(clang_base_path + "/lib", root_build_dir),
|
||||
]
|
||||
}
|
||||
|
||||
args += [ "--bindgen-flags" ]
|
||||
if (defined(invoker.bindgen_flags)) {
|
||||
foreach(flag, invoker.bindgen_flags) {
|
||||
args += [ flag ]
|
||||
}
|
||||
}
|
||||
if (_cpp) {
|
||||
args += [ "enable-cxx-namespaces" ]
|
||||
}
|
||||
|
||||
# Everything below is passed through to libclang.
|
||||
args += [ "--" ]
|
||||
|
||||
if (_cpp) {
|
||||
args += [
|
||||
"-x",
|
||||
"c++",
|
||||
]
|
||||
}
|
||||
|
||||
args += [
|
||||
"{{defines}}",
|
||||
"{{include_dirs}}",
|
||||
"{{cflags}}",
|
||||
]
|
||||
if (_cpp) {
|
||||
args += [ "{{cflags_cc}}" ]
|
||||
} else {
|
||||
args += [ "{{cflags_c}}" ]
|
||||
}
|
||||
|
||||
# libclang will run the system `clang` to find the "resource dir" which it
|
||||
# places before the directory specified in `-isysroot`.
|
||||
# https://github.com/llvm/llvm-project/blob/699e0bed4bfead826e210025bf33e5a1997c018b/clang/lib/Tooling/Tooling.cpp#L499-L510
|
||||
#
|
||||
# This means include files are pulled from the wrong place if the `clang`
|
||||
# says the wrong thing. We point it to our clang's resource dir which will
|
||||
# make it behave consistently with our other command line flags and allows
|
||||
# system headers to be found.
|
||||
clang_resource_dir =
|
||||
rebase_path(clang_base_path + "/lib/clang/" + clang_version,
|
||||
root_build_dir)
|
||||
args += [
|
||||
"-resource-dir",
|
||||
clang_resource_dir,
|
||||
]
|
||||
|
||||
# The `--sysroot` flag is not working as expected and gets ignored (we don't
|
||||
# fully understand why, see b/328510249). But we add `-isystem` to point at
|
||||
# the headers in the sysroot which are otherwise not found.
|
||||
if (sysroot != "") {
|
||||
if (is_win) {
|
||||
args +=
|
||||
[ "-I" + rebase_path(sysroot + "/usr/include/", root_build_dir) ]
|
||||
} else {
|
||||
args += [
|
||||
"-isystem",
|
||||
rebase_path(sysroot + "/usr/include/", root_build_dir),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
if (is_win) {
|
||||
# On Windows we fall back to using system headers from a sysroot from
|
||||
# depot_tools. This is negotiated by python scripts and the result is
|
||||
# available in //build/toolchain/win/win_toolchain_data.gni. From there
|
||||
# we get the `include_flags_imsvc` which point to the system headers.
|
||||
if (host_cpu == "x86") {
|
||||
win_toolchain_data = win_toolchain_data_x86
|
||||
} else if (host_cpu == "x64") {
|
||||
win_toolchain_data = win_toolchain_data_x64
|
||||
} else if (host_cpu == "arm64") {
|
||||
win_toolchain_data = win_toolchain_data_arm64
|
||||
} else {
|
||||
error("Unsupported host_cpu, add it to win_toolchain_data.gni")
|
||||
}
|
||||
args += win_toolchain_data.include_flags_imsvc_list
|
||||
}
|
||||
|
||||
# Passes C comments through as rustdoc attributes.
|
||||
if (is_win) {
|
||||
args += [ "/clang:-fparse-all-comments" ]
|
||||
} else {
|
||||
args += [ "-fparse-all-comments" ]
|
||||
}
|
||||
|
||||
# Default configs include "-fvisibility=hidden", and for some reason this
|
||||
# causes bindgen not to emit function bindings. Override it.
|
||||
if (!is_win) {
|
||||
args += [ "-fvisibility=default" ]
|
||||
}
|
||||
|
||||
if (is_win) {
|
||||
# We pass MSVC style flags to clang on Windows, and libclang needs to be
|
||||
# told explicitly to accept them.
|
||||
args += [ "--driver-mode=cl" ]
|
||||
|
||||
# On Windows, libclang adds arguments that it then fails to understand.
|
||||
# -fno-spell-checking
|
||||
# -fallow-editor-placeholders
|
||||
# These should not cause bindgen to fail.
|
||||
args += [ "-Wno-unknown-argument" ]
|
||||
|
||||
# C++ mode makes bindgen pass /TP to libclang (to parse as C++) which
|
||||
# then libclang says is unused.
|
||||
args += [ "-Wno-unused-command-line-argument" ]
|
||||
|
||||
# Replace these two arguments with a version that clang-cl can parse.
|
||||
args += [
|
||||
"/clang:-fno-spell-checking",
|
||||
"/clang:-fallow-editor-placeholders",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_cfi) {
|
||||
# LLVM searches for a default CFI ignorelist at (exactly)
|
||||
# $(cwd)/lib/clang/$(llvm_version)/share/cfi_ignorelist.txt
|
||||
# Even if we provide a custom -fsanitize-ignorelist, the absence
|
||||
# of this default file will cause a fatal error. clang finds
|
||||
# it within third_party/llvm-build, but for bindgen our cwd
|
||||
# is the $out_dir. We _could_ create this file at the right
|
||||
# location within the outdir using a "copy" target, but as
|
||||
# we don't actually generate code within bindgen, the easier
|
||||
# option is to tell bindgen to ignore all CFI ignorelists.
|
||||
args += [ "-fno-sanitize-ignorelist" ]
|
||||
}
|
||||
}
|
||||
|
||||
if (_wrap_static_fns) {
|
||||
source_set("${target_name}_static_fns") {
|
||||
forward_variables_from(invoker,
|
||||
TESTONLY_AND_VISIBILITY + [
|
||||
"deps",
|
||||
"configs",
|
||||
"public_configs",
|
||||
"public_deps",
|
||||
])
|
||||
bindgen_output = get_target_outputs(":${_bindgen_target_name}")
|
||||
if (!defined(deps)) {
|
||||
deps = []
|
||||
}
|
||||
deps += [ ":${_bindgen_target_name}" ]
|
||||
|
||||
if (_cpp) {
|
||||
sources = filter_include(bindgen_output, [ "*.cc" ])
|
||||
} else {
|
||||
sources = filter_include(bindgen_output, [ "*.c" ])
|
||||
}
|
||||
|
||||
# bindgen generates a C file whose include is relative to the directory it
|
||||
# runs from.
|
||||
include_dirs = [ root_build_dir ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
361
build/rust/rust_bindgen_generator.gni
Normal file
361
build/rust/rust_bindgen_generator.gni
Normal file
@ -0,0 +1,361 @@
|
||||
# Copyright 2022 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/config/clang/clang.gni")
|
||||
import("//build/config/rust.gni")
|
||||
import("//build/config/sysroot.gni")
|
||||
import("//build/rust/rust_static_library.gni")
|
||||
|
||||
if (is_win) {
|
||||
import("//build/toolchain/win/win_toolchain_data.gni")
|
||||
}
|
||||
|
||||
_bindgen_path = "${rust_bindgen_root}/bin/bindgen"
|
||||
if (host_os == "win") {
|
||||
_bindgen_path = "${_bindgen_path}.exe"
|
||||
}
|
||||
|
||||
# On Windows, the libclang.dll is beside the bindgen.exe, otherwise it is in
|
||||
# ../lib.
|
||||
_libclang_path = rust_bindgen_root
|
||||
if (host_os == "win") {
|
||||
_libclang_path += "/bin"
|
||||
} else {
|
||||
_libclang_path += "/lib"
|
||||
}
|
||||
|
||||
# Template to build Rust/C bindings with bindgen.
|
||||
#
|
||||
# If you're developing first-party code then consider using `rust_bindgen`
|
||||
# instead of `rust_bindgen_generator` to simplify your build targets.
|
||||
#
|
||||
# This template expands to an action that generates the Rust side of the
|
||||
# bindings. Add it as a dependency through `bindgen_deps` on your
|
||||
# rust_target then incorporate it into your library through
|
||||
#
|
||||
# mod bindings {
|
||||
# include!(concat!(env!("OUT_DIR"), "/{rust_bindgen_generator_target_name}.rs"));
|
||||
# }
|
||||
#
|
||||
# Parameters:
|
||||
#
|
||||
# header:
|
||||
# The .h file to generate bindings for.
|
||||
#
|
||||
# deps: (optional)
|
||||
# C targets on which the headers depend in order to build successfully.
|
||||
#
|
||||
# configs: (optional)
|
||||
# C compilation targets determine the correct list of -D and -I flags based
|
||||
# on their dependencies and any configs applied. The same applies here. Set
|
||||
# any configs here as if this were a C target.
|
||||
#
|
||||
# cpp: (optional)
|
||||
# Use C++ mode to consume the header instead of C mode (the default).
|
||||
#
|
||||
# bindgen_flags: (optional)
|
||||
# The additional bindgen flags which are passed to the executable. A `--` will
|
||||
# be prepended to each flag. So use `bindgen_flags = [ "foo" ]` to pass
|
||||
# `--foo` to bindgen.
|
||||
#
|
||||
# wrap_static_fns: (optional)
|
||||
# If set to true, enables binding `static` and `static inline` functions in
|
||||
# the header. Setting this causes the template to emit a source_set target
|
||||
# named "${target_name}_static_fns", which must be incorporated into the
|
||||
# build. Additionally, `get_target_outputs` will return both the Rust file and
|
||||
# a generated C file, but callers can rely on the Rust file being first.
|
||||
template("rust_bindgen_generator") {
|
||||
assert(defined(invoker.header),
|
||||
"Must specify the C/C++ header file to make bindings for.")
|
||||
_wrap_static_fns = defined(invoker.wrap_static_fns) && invoker.wrap_static_fns
|
||||
|
||||
if (!defined(invoker.cpp)) {
|
||||
_cpp = false
|
||||
} else {
|
||||
_cpp = invoker.cpp
|
||||
}
|
||||
|
||||
# This is only created if the bindgen has wrap_static_fns to true
|
||||
_static_fn_target_name = target_name + "_static_fns"
|
||||
if (defined(invoker.library_name)) {
|
||||
_library_name = invoker.library_name
|
||||
}
|
||||
|
||||
_bindgen_target_name = target_name
|
||||
action(target_name) {
|
||||
# bindgen relies on knowing the {{defines}} and {{include_dirs}} required
|
||||
# to build the C++ headers which it's parsing. These are passed to the
|
||||
# script's args and are populated using deps and configs.
|
||||
forward_variables_from(invoker,
|
||||
TESTONLY_AND_VISIBILITY + [
|
||||
"configs",
|
||||
"deps",
|
||||
"public_configs",
|
||||
"public_deps",
|
||||
"output_name",
|
||||
])
|
||||
sources = [ invoker.header ]
|
||||
if (!defined(configs)) {
|
||||
configs = []
|
||||
}
|
||||
|
||||
# Get rid of the visibility, the user should not control visibility.
|
||||
# We have to do it that way otherwise we might get "visibility not used"
|
||||
# errors.
|
||||
visibility = []
|
||||
|
||||
# This should only be allowed to be used by third_party code.
|
||||
# First-party code should use `rust_bindgen` template.
|
||||
# We're intentionally not allowing visibility to be forwarded
|
||||
# to prevent people from doing visibility = ["*"] which will
|
||||
# allow a rust_bindgen_generator to be used by 1P folks.
|
||||
visibility = [ "//third_party/*" ]
|
||||
if (defined(_library_name)) {
|
||||
# Allow both the rust target and the copy target to be able to depend on
|
||||
# the rust_bindgen_generator.
|
||||
visibility += [
|
||||
# This can be deleted once boringssl and crabbyavif switch
|
||||
# rust_bindgen_generator targets from `deps` to `bindgen_deps`.
|
||||
":${_library_name}",
|
||||
":${_library_name}_${_bindgen_target_name}_copy",
|
||||
]
|
||||
}
|
||||
|
||||
if (_wrap_static_fns) {
|
||||
visibility += [ ":$_static_fn_target_name" ]
|
||||
}
|
||||
|
||||
# Several important compiler flags come from default_compiler_configs
|
||||
configs += default_compiler_configs
|
||||
|
||||
output_dir = "$target_gen_dir"
|
||||
if (!defined(output_name)) {
|
||||
output_name = target_name
|
||||
}
|
||||
|
||||
output_file = "$output_dir/${output_name}.rs"
|
||||
|
||||
script = rebase_path("//build/rust/run_bindgen.py")
|
||||
inputs = [
|
||||
_bindgen_path,
|
||||
"//build/action_helpers.py",
|
||||
"//build/gn_helpers.py",
|
||||
"//build/rust/filter_clang_args.py",
|
||||
]
|
||||
|
||||
depfile = "$target_out_dir/${target_name}.d"
|
||||
outputs = [ output_file ]
|
||||
|
||||
args = [
|
||||
"--exe",
|
||||
rebase_path(_bindgen_path, root_build_dir),
|
||||
"--header",
|
||||
rebase_path(invoker.header, root_build_dir),
|
||||
"--depfile",
|
||||
rebase_path(depfile, root_build_dir),
|
||||
"--output",
|
||||
rebase_path(output_file, root_build_dir),
|
||||
"--libclang-path",
|
||||
rebase_path(_libclang_path, root_build_dir),
|
||||
]
|
||||
|
||||
if (_wrap_static_fns) {
|
||||
if (_cpp) {
|
||||
out_gen_c = "$output_dir/${target_name}.cc"
|
||||
} else {
|
||||
out_gen_c = "$output_dir/${target_name}.c"
|
||||
}
|
||||
outputs += [ out_gen_c ]
|
||||
args += [
|
||||
"--wrap-static-fns",
|
||||
rebase_path(out_gen_c, root_build_dir),
|
||||
]
|
||||
}
|
||||
|
||||
if (is_linux) {
|
||||
# Linux clang, and clang libs, use a shared libstdc++, which we must
|
||||
# point to.
|
||||
args += [
|
||||
"--ld-library-path",
|
||||
rebase_path(clang_base_path + "/lib", root_build_dir),
|
||||
]
|
||||
}
|
||||
|
||||
args += [ "--bindgen-flags" ]
|
||||
if (defined(invoker.bindgen_flags)) {
|
||||
foreach(flag, invoker.bindgen_flags) {
|
||||
args += [ flag ]
|
||||
}
|
||||
}
|
||||
if (_cpp) {
|
||||
args += [ "enable-cxx-namespaces" ]
|
||||
}
|
||||
|
||||
# Everything below is passed through to libclang.
|
||||
args += [ "--" ]
|
||||
|
||||
if (_cpp) {
|
||||
args += [
|
||||
"-x",
|
||||
"c++",
|
||||
]
|
||||
}
|
||||
|
||||
args += [
|
||||
"{{defines}}",
|
||||
"{{include_dirs}}",
|
||||
"{{cflags}}",
|
||||
]
|
||||
if (_cpp) {
|
||||
args += [ "{{cflags_cc}}" ]
|
||||
} else {
|
||||
args += [ "{{cflags_c}}" ]
|
||||
}
|
||||
|
||||
# libclang will run the system `clang` to find the "resource dir" which it
|
||||
# places before the directory specified in `-isysroot`.
|
||||
# https://github.com/llvm/llvm-project/blob/699e0bed4bfead826e210025bf33e5a1997c018b/clang/lib/Tooling/Tooling.cpp#L499-L510
|
||||
#
|
||||
# This means include files are pulled from the wrong place if the `clang`
|
||||
# says the wrong thing. We point it to our clang's resource dir which will
|
||||
# make it behave consistently with our other command line flags and allows
|
||||
# system headers to be found.
|
||||
clang_resource_dir =
|
||||
rebase_path(clang_base_path + "/lib/clang/" + clang_version,
|
||||
root_build_dir)
|
||||
args += [
|
||||
"-resource-dir",
|
||||
clang_resource_dir,
|
||||
]
|
||||
|
||||
# The `--sysroot` flag is not working as expected and gets ignored (we don't
|
||||
# fully understand why, see b/328510249). But we add `-isystem` to point at
|
||||
# the headers in the sysroot which are otherwise not found.
|
||||
if (sysroot != "") {
|
||||
if (is_win) {
|
||||
args +=
|
||||
[ "-I" + rebase_path(sysroot + "/usr/include/", root_build_dir) ]
|
||||
} else {
|
||||
args += [
|
||||
"-isystem",
|
||||
rebase_path(sysroot + "/usr/include/", root_build_dir),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
if (is_win) {
|
||||
# On Windows we fall back to using system headers from a sysroot from
|
||||
# depot_tools. This is negotiated by python scripts and the result is
|
||||
# available in //build/toolchain/win/win_toolchain_data.gni. From there
|
||||
# we get the `include_flags_imsvc` which point to the system headers.
|
||||
if (host_cpu == "x86") {
|
||||
win_toolchain_data = win_toolchain_data_x86
|
||||
} else if (host_cpu == "x64") {
|
||||
win_toolchain_data = win_toolchain_data_x64
|
||||
} else if (host_cpu == "arm64") {
|
||||
win_toolchain_data = win_toolchain_data_arm64
|
||||
} else {
|
||||
error("Unsupported host_cpu, add it to win_toolchain_data.gni")
|
||||
}
|
||||
args += win_toolchain_data.include_flags_imsvc_list
|
||||
}
|
||||
|
||||
# Passes C comments through as rustdoc attributes.
|
||||
if (is_win) {
|
||||
args += [ "/clang:-fparse-all-comments" ]
|
||||
} else {
|
||||
args += [ "-fparse-all-comments" ]
|
||||
}
|
||||
|
||||
# Default configs include "-fvisibility=hidden", and for some reason this
|
||||
# causes bindgen not to emit function bindings. Override it.
|
||||
if (!is_win) {
|
||||
args += [ "-fvisibility=default" ]
|
||||
}
|
||||
|
||||
if (is_win) {
|
||||
# We pass MSVC style flags to clang on Windows, and libclang needs to be
|
||||
# told explicitly to accept them.
|
||||
args += [ "--driver-mode=cl" ]
|
||||
|
||||
# On Windows, libclang adds arguments that it then fails to understand.
|
||||
# -fno-spell-checking
|
||||
# -fallow-editor-placeholders
|
||||
# These should not cause bindgen to fail.
|
||||
args += [ "-Wno-unknown-argument" ]
|
||||
|
||||
# C++ mode makes bindgen pass /TP to libclang (to parse as C++) which
|
||||
# then libclang says is unused.
|
||||
args += [ "-Wno-unused-command-line-argument" ]
|
||||
|
||||
# Replace these two arguments with a version that clang-cl can parse.
|
||||
args += [
|
||||
"/clang:-fno-spell-checking",
|
||||
"/clang:-fallow-editor-placeholders",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_cfi) {
|
||||
# LLVM searches for a default CFI ignorelist at (exactly)
|
||||
# $(cwd)/lib/clang/$(llvm_version)/share/cfi_ignorelist.txt
|
||||
# Even if we provide a custom -fsanitize-ignorelist, the absence
|
||||
# of this default file will cause a fatal error. clang finds
|
||||
# it within third_party/llvm-build, but for bindgen our cwd
|
||||
# is the $out_dir. We _could_ create this file at the right
|
||||
# location within the outdir using a "copy" target, but as
|
||||
# we don't actually generate code within bindgen, the easier
|
||||
# option is to tell bindgen to ignore all CFI ignorelists.
|
||||
args += [ "-fno-sanitize-ignorelist" ]
|
||||
}
|
||||
if (!defined(_library_name)) {
|
||||
not_needed([ _bindgen_target_name ])
|
||||
}
|
||||
}
|
||||
|
||||
if (_wrap_static_fns) {
|
||||
source_set(_static_fn_target_name) {
|
||||
forward_variables_from(invoker,
|
||||
TESTONLY_AND_VISIBILITY + [
|
||||
"deps",
|
||||
"configs",
|
||||
"public_configs",
|
||||
"public_deps",
|
||||
])
|
||||
bindgen_output = get_target_outputs(":${_bindgen_target_name}")
|
||||
if (!defined(deps)) {
|
||||
deps = []
|
||||
}
|
||||
deps += [ ":${_bindgen_target_name}" ]
|
||||
|
||||
if (_cpp) {
|
||||
sources = filter_include(bindgen_output, [ "*.cc" ])
|
||||
} else {
|
||||
sources = filter_include(bindgen_output, [ "*.c" ])
|
||||
}
|
||||
|
||||
# bindgen generates a C file whose include is relative to the directory it
|
||||
# runs from.
|
||||
include_dirs = [ root_build_dir ]
|
||||
|
||||
# Get rid of the visibility, the user should not control visibility.
|
||||
# We have to do it that way otherwise we might get "visibility not used"
|
||||
# errors.
|
||||
visibility = []
|
||||
if (defined(_library_name)) {
|
||||
# Allow both the rust target declared through `rust_bindgen` to depend
|
||||
# on this library.
|
||||
visibility = [ ":${_library_name}" ]
|
||||
} else {
|
||||
# This should only be allowed to be used by third_party code.
|
||||
# First-party code should use `rust_bindgen` template.
|
||||
# We're intentionally not allowing visibility to be forwarded
|
||||
# to prevent people from doing visibility = ["*"] which will
|
||||
# allow a rust_bindgen_generator to be used by 1P folks.
|
||||
visibility = [ "//third_party/*" ]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
not_needed([ _static_fn_target_name ])
|
||||
}
|
||||
}
|
@ -17,6 +17,10 @@ if (enable_rust_cxx) {
|
||||
# understand some handy variables such as "edition" and "features" and also to
|
||||
# build any associated unit tests.
|
||||
#
|
||||
# `bindgen_deps` field exists only for 3P cargo sys crates that uses
|
||||
# `rust_bindgen_generator` templates. For 1P code, `rust_bindgen` should
|
||||
# be used and should go directly in the `deps` field.
|
||||
#
|
||||
# Normally, you should not use this directly. Use either
|
||||
# - cargo_crate.gni - for 3p crates only
|
||||
# - rust_static_library.gni - for 1p Rust code
|
||||
@ -163,6 +167,34 @@ template("rust_target") {
|
||||
if (defined(invoker.deps)) {
|
||||
_deps += invoker.deps
|
||||
}
|
||||
if (defined(invoker.bindgen_deps)) {
|
||||
_bindgen_inputs = []
|
||||
|
||||
# This iteration assumes that no targets have the same name which is
|
||||
# very rare to happen and if it does. An error will be thrown as we
|
||||
# try to create two targets with the same name, the error might not
|
||||
# be descriptive enough so maybe adding a check action would be better.
|
||||
foreach(bindgen_dep, invoker.bindgen_deps) {
|
||||
_copy_target_name =
|
||||
target_name + "_" + get_label_info(bindgen_dep, "name") + "_copy"
|
||||
copy(_copy_target_name) {
|
||||
_bindgen_output_files = get_target_outputs(bindgen_dep)
|
||||
|
||||
# `rust_bindgen_generator` promises that the first output file is always .rs.
|
||||
sources = [ _bindgen_output_files[0] ]
|
||||
outputs = [ "$_env_out_dir/{{source_name_part}}.rs" ]
|
||||
deps = [ bindgen_dep ]
|
||||
}
|
||||
|
||||
# The bindgen-generated rs files are inputs to this library for the library
|
||||
# to `include!` them.
|
||||
# The output of the copy action is always a single file so just copy everything.
|
||||
_bindgen_inputs += get_target_outputs(":$_copy_target_name")
|
||||
|
||||
# Depend on the bindgen generation to make the above `_bindgen_inputs`.
|
||||
_deps += [ ":$_copy_target_name" ]
|
||||
}
|
||||
}
|
||||
_public_deps = []
|
||||
if (defined(invoker.public_deps)) {
|
||||
_public_deps += invoker.public_deps
|
||||
@ -406,6 +438,14 @@ template("rust_target") {
|
||||
sources += [ _crate_root ]
|
||||
}
|
||||
|
||||
if (!defined(inputs)) {
|
||||
inputs = []
|
||||
}
|
||||
|
||||
if (defined(_bindgen_inputs)) {
|
||||
inputs += _bindgen_inputs
|
||||
}
|
||||
|
||||
if (!defined(output_name)) {
|
||||
# Note that file names of libraries must start with the crate name in
|
||||
# order for the compiler to find transitive dependencies in the
|
||||
|
@ -27,9 +27,4 @@ rust_executable("bindgen_cpp_test") {
|
||||
crate_root = "main.rs"
|
||||
|
||||
allow_unsafe = true # Needed for FFI.
|
||||
|
||||
bindgen_output = get_target_outputs(":cpp_lib_bindgen")
|
||||
inputs = bindgen_output
|
||||
rustenv = [ "BINDGEN_RS_FILE=" +
|
||||
rebase_path(bindgen_output[0], get_path_info(crate_root, "dir")) ]
|
||||
}
|
||||
|
@ -2,17 +2,13 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[allow(non_snake_case)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
mod ffi {
|
||||
include!(env!("BINDGEN_RS_FILE"));
|
||||
pub use root::*;
|
||||
chromium::import! {
|
||||
"//build/rust/tests/bindgen_cpp_test:cpp_lib_bindgen";
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let from_cpp = unsafe { ffi::functions::normal_fn(ffi::functions::kNumber) };
|
||||
let from_cpp =
|
||||
unsafe { cpp_lib_bindgen::functions::normal_fn(cpp_lib_bindgen::functions::kNumber) };
|
||||
println!("2 == {from_cpp}");
|
||||
assert_eq!(2, from_cpp);
|
||||
}
|
||||
|
@ -27,11 +27,6 @@ rust_static_library("rust_lib") {
|
||||
crate_root = "lib.rs"
|
||||
|
||||
allow_unsafe = true # Needed for FFI.
|
||||
|
||||
bindgen_output = get_target_outputs(":cpp_lib_bindgen")
|
||||
inputs = bindgen_output
|
||||
rustenv = [ "BINDGEN_RS_FILE=" +
|
||||
rebase_path(bindgen_output[0], get_path_info(crate_root, "dir")) ]
|
||||
}
|
||||
|
||||
executable("bindgen_cpp_test_with_cpp_linkage") {
|
||||
|
@ -2,18 +2,14 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[allow(non_snake_case)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
mod ffi {
|
||||
include!(env!("BINDGEN_RS_FILE"));
|
||||
pub use root::*;
|
||||
chromium::import! {
|
||||
"//build/rust/tests/bindgen_cpp_test_with_cpp_linkage:cpp_lib_bindgen";
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn rust_main() {
|
||||
let from_cpp = unsafe { ffi::functions::normal_fn(ffi::functions::kNumber) };
|
||||
let from_cpp =
|
||||
unsafe { cpp_lib_bindgen::functions::normal_fn(cpp_lib_bindgen::functions::kNumber) };
|
||||
println!("2 == {from_cpp}");
|
||||
assert_eq!(2, from_cpp);
|
||||
}
|
||||
|
@ -29,16 +29,10 @@ rust_static_library("bindgen_static_fns_test_lib") {
|
||||
deps = [
|
||||
":c_lib",
|
||||
":c_lib_bindgen",
|
||||
":c_lib_bindgen_static_fns",
|
||||
]
|
||||
sources = [ "src/lib.rs" ]
|
||||
build_native_rust_unit_tests = true
|
||||
crate_root = "src/lib.rs"
|
||||
|
||||
bindgen_output = get_target_outputs(":c_lib_bindgen")
|
||||
inputs = bindgen_output
|
||||
rustenv = [ "BINDGEN_RS_FILE=" +
|
||||
rebase_path(bindgen_output[0], get_path_info(crate_root, "dir")) ]
|
||||
}
|
||||
|
||||
rust_executable("bindgen_static_fns_test") {
|
||||
|
@ -2,16 +2,12 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
mod c_ffi {
|
||||
#![allow(dead_code)]
|
||||
#![allow(non_snake_case)]
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(non_upper_case_globals)]
|
||||
include!(env!("BINDGEN_RS_FILE"));
|
||||
chromium::import! {
|
||||
"//build/rust/tests/bindgen_static_fns_test:c_lib_bindgen";
|
||||
}
|
||||
|
||||
pub fn mul_three_numbers_in_c(a: u32, b: u32, c: u32) -> u32 {
|
||||
unsafe { c_ffi::mul_three_numbers(a, b, c) }
|
||||
unsafe { c_lib_bindgen::mul_three_numbers(a, b, c) }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -35,11 +35,6 @@ rust_static_library("bindgen_test_lib") {
|
||||
sources = [ "src/lib.rs" ]
|
||||
build_native_rust_unit_tests = true
|
||||
crate_root = "src/lib.rs"
|
||||
|
||||
bindgen_output = get_target_outputs(":c_lib_bindgen")
|
||||
inputs = bindgen_output
|
||||
rustenv = [ "BINDGEN_RS_FILE=" +
|
||||
rebase_path(bindgen_output[0], get_path_info(crate_root, "dir")) ]
|
||||
}
|
||||
|
||||
rust_executable("bindgen_test") {
|
||||
|
@ -2,16 +2,12 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[allow(non_snake_case)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[allow(non_upper_case_globals)]
|
||||
mod c_ffi {
|
||||
include!(env!("BINDGEN_RS_FILE"));
|
||||
chromium::import! {
|
||||
"//build/rust/tests/bindgen_test:c_lib_bindgen";
|
||||
}
|
||||
|
||||
pub fn add_two_numbers_in_c(a: u32, b: u32) -> u32 {
|
||||
unsafe { c_ffi::add_two_numbers(a, b) }
|
||||
unsafe { c_lib_bindgen::add_two_numbers(a, b) }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
12
third_party/boringssl/BUILD.gn
vendored
12
third_party/boringssl/BUILD.gn
vendored
@ -12,7 +12,7 @@ import("src/gen/sources.gni")
|
||||
|
||||
if (enable_rust) {
|
||||
import("//build/rust/cargo_crate.gni")
|
||||
import("//build/rust/rust_bindgen.gni")
|
||||
import("//build/rust/rust_bindgen_generator.gni")
|
||||
}
|
||||
|
||||
# Config for us and everybody else depending on BoringSSL.
|
||||
@ -49,7 +49,8 @@ all_sources = bcm_internal_headers + bcm_sources + crypto_internal_headers +
|
||||
all_headers = crypto_headers + ssl_headers + pki_headers + pki_internal_headers
|
||||
|
||||
if (enable_rust) {
|
||||
rust_bindgen("raw_bssl_sys_bindings") {
|
||||
rust_bindgen_generator("raw_bssl_sys_bindings") {
|
||||
output_name = "bindgen"
|
||||
header = "src/rust/bssl-sys/wrapper.h"
|
||||
deps = [ ":boringssl" ]
|
||||
bindgen_flags = [
|
||||
@ -78,13 +79,18 @@ if (enable_rust) {
|
||||
edition = "2021"
|
||||
deps = [
|
||||
":boringssl",
|
||||
":raw_bssl_sys_bindings",
|
||||
":raw_bssl_sys_bindings", # Delete once the source code has changed.
|
||||
":raw_bssl_sys_bindings_static_fns",
|
||||
]
|
||||
|
||||
visibility = [
|
||||
":*", # private, should only be exposed through bssl_crypto
|
||||
]
|
||||
|
||||
bindgen_deps = [ ":raw_bssl_sys_bindings" ]
|
||||
|
||||
# This is no longer necessary and can be deleted once the source
|
||||
# code is changed to use `OUT_DIR` always.
|
||||
bindgen_output = get_target_outputs(":raw_bssl_sys_bindings")
|
||||
inputs = bindgen_output
|
||||
rustenv =
|
||||
|
24
third_party/crabbyavif/BUILD.gn
vendored
24
third_party/crabbyavif/BUILD.gn
vendored
@ -2,10 +2,10 @@
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
import("//build/rust/rust_bindgen.gni")
|
||||
import("//build/rust/rust_bindgen_generator.gni")
|
||||
import("//build/rust/rust_static_library.gni")
|
||||
|
||||
rust_bindgen("crabbyavif_dav1d_bindings") {
|
||||
rust_bindgen_generator("crabbyavif_dav1d_bindings") {
|
||||
header = "src/sys/dav1d-sys/wrapper.h"
|
||||
deps = [ "//third_party/dav1d:dav1d_headers" ]
|
||||
configs = [ "//third_party/dav1d:dav1d_config" ]
|
||||
@ -33,8 +33,15 @@ rust_static_library("crabbyavif_dav1d_sys") {
|
||||
|
||||
sources = [ "src/sys/dav1d-sys/src/lib.rs" ]
|
||||
|
||||
deps = [ ":crabbyavif_dav1d_bindings" ]
|
||||
deps = [
|
||||
":crabbyavif_dav1d_bindings", # Kept for backward compatibility, delete
|
||||
# once the source code has changed
|
||||
]
|
||||
|
||||
bindgen_deps = [ ":crabbyavif_dav1d_bindings" ]
|
||||
|
||||
# This is no longer necessary and can be deleted once the source
|
||||
# code is changed to use `OUT_DIR` always.
|
||||
_bindgen_output = get_target_outputs(":crabbyavif_dav1d_bindings")
|
||||
inputs = _bindgen_output
|
||||
rustenv =
|
||||
@ -42,7 +49,7 @@ rust_static_library("crabbyavif_dav1d_sys") {
|
||||
rebase_path(_bindgen_output[0], get_path_info(crate_root, "dir")) ]
|
||||
}
|
||||
|
||||
rust_bindgen("crabbyavif_libyuv_bindings") {
|
||||
rust_bindgen_generator("crabbyavif_libyuv_bindings") {
|
||||
header = "src/sys/libyuv-sys/wrapper.h"
|
||||
configs = [ "//third_party/libyuv:libyuv_config" ]
|
||||
bindgen_flags = [
|
||||
@ -117,8 +124,15 @@ rust_static_library("crabbyavif_libyuv_sys") {
|
||||
|
||||
sources = [ "src/sys/libyuv-sys/src/lib.rs" ]
|
||||
|
||||
deps = [ ":crabbyavif_libyuv_bindings" ]
|
||||
deps = [
|
||||
":crabbyavif_libyuv_bindings", # Kept for backward compatibility, delete
|
||||
# once the source code has changed
|
||||
]
|
||||
|
||||
bindgen_deps = [ ":crabbyavif_libyuv_bindings" ]
|
||||
|
||||
# This is no longer necessary and can be deleted once the source
|
||||
# code is changed to use `OUT_DIR` always.
|
||||
_bindgen_output = get_target_outputs(":crabbyavif_libyuv_bindings")
|
||||
inputs = _bindgen_output
|
||||
rustenv =
|
||||
|
Reference in New Issue
Block a user