blob: caad79e8132b9de44a476282ba530f370ef2e208 [file] [log] [blame]
# 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")
# Template to build Rust/C bindings with bindgen.
#
# This template expands to a static_library containing the Rust side of the
# bindings. Simply treat it as a public dependency.
#
# 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.
#
# Rust targets depending on the output must include! the generated file.
#
template("rust_bindgen") {
assert(defined(invoker.header),
"Must specify the C header file to make bindings for.")
_target_name = target_name
_testonly = false
if (defined(invoker.testonly)) {
_testonly = invoker.testonly
}
if (defined(invoker.visibility)) {
_visibility = invoker.visibility
}
_deps = []
if (defined(invoker.deps)) {
_deps += invoker.deps
}
action(_target_name) {
testonly = _testonly
if (defined(_visibility)) {
visibility = _visibility
}
sources = [ invoker.header ]
# Several important compiler flags come from default_compiler_configs
configs = default_compiler_configs
if (defined(invoker.configs)) {
configs += invoker.configs
}
bindgen_target = "//third_party/rust/bindgen/v0_60:bindgen($host_toolchain)"
bindgen_obj_dir = get_label_info(bindgen_target, "root_out_dir")
bindgen_executable = "${bindgen_obj_dir}/bindgen"
if (is_win) {
bindgen_executable = "${bindgen_executable}.exe"
}
output_dir = "$target_gen_dir"
out_gen_rs = "$output_dir/${target_name}.rs"
script = rebase_path("//build/rust/run_bindgen.py")
inputs = [ bindgen_executable ]
depfile = "$target_out_dir/${target_name}.d"
outputs = [ out_gen_rs ]
deps = [ bindgen_target ]
# 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.
deps += _deps
args = [
"--exe",
rebase_path(bindgen_executable),
"--header",
rebase_path(invoker.header, root_build_dir),
"--depfile",
rebase_path(depfile, root_build_dir),
"--output",
rebase_path(out_gen_rs, root_build_dir),
"--ld-library-path",
rebase_path(clang_base_path + "/lib", root_build_dir),
]
args += [
"--",
"{{defines}}",
"{{include_dirs}}",
"{{cflags}}",
"{{cflags_c}}",
# This path contains important C headers (e.g. stddef.h) and {{cflags}}
# does not include it. Normally this path is implicitly added by clang but
# it does not happen for libclang.
#
# Add it last so includes from deps and configs take precedence.
"-isystem" + rebase_path(
clang_base_path + "/lib/clang/" + clang_version + "/include",
root_build_dir),
# Passes C comments through as rustdoc attributes.
"-fparse-all-comments",
# Default configs include "-fvisibility=hidden", and for some reason this
# causes bindgen not to emit function bindings. Override it.
"-fvisibility=default",
]
}
}