194 lines
6.3 KiB
Plaintext
194 lines
6.3 KiB
Plaintext
|
|
# 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")
|
||
|
|
}
|
||
|
|
|
||
|
|
_rustc_base_path = rust_sysroot
|
||
|
|
|
||
|
|
# TODO(danakj): When we're using the Android prebuilt toolchain, there's no
|
||
|
|
# bindgen present. bindgen is for the host platform so using the linux one will
|
||
|
|
# work.
|
||
|
|
if (!use_chromium_rust_toolchain) {
|
||
|
|
_rustc_base_path = "//third_party/rust-toolchain"
|
||
|
|
}
|
||
|
|
|
||
|
|
_bindgen_path = "${_rustc_base_path}/bin/bindgen"
|
||
|
|
if (is_win) {
|
||
|
|
_bindgen_path = "${_bindgen_path}.exe"
|
||
|
|
}
|
||
|
|
|
||
|
|
# 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.
|
||
|
|
#
|
||
|
|
# bindgen_flags: (optional)
|
||
|
|
# the additional bindgen flags which are passed to the executable
|
||
|
|
#
|
||
|
|
# 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.")
|
||
|
|
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 + [
|
||
|
|
"deps",
|
||
|
|
"configs",
|
||
|
|
])
|
||
|
|
|
||
|
|
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 ]
|
||
|
|
|
||
|
|
depfile = "$target_out_dir/${target_name}.d"
|
||
|
|
outputs = [ out_gen_rs ]
|
||
|
|
|
||
|
|
lib_path = ""
|
||
|
|
if (is_linux) {
|
||
|
|
# Linux clang, and clang libs, use a shared libstdc++, which we must
|
||
|
|
# point to.
|
||
|
|
clang_ld_path = rebase_path(clang_base_path + "/lib", root_build_dir)
|
||
|
|
lib_path += "${clang_ld_path}:"
|
||
|
|
}
|
||
|
|
rust_ld_path = rebase_path(_rustc_base_path + "/lib", root_build_dir)
|
||
|
|
lib_path += "${rust_ld_path}"
|
||
|
|
|
||
|
|
args = [
|
||
|
|
"--exe",
|
||
|
|
rebase_path(_bindgen_path),
|
||
|
|
"--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",
|
||
|
|
lib_path,
|
||
|
|
]
|
||
|
|
|
||
|
|
if (defined(invoker.bindgen_flags)) {
|
||
|
|
args += [ "--bindgen-flags" ]
|
||
|
|
foreach(flag, invoker.bindgen_flags) {
|
||
|
|
args += [ flag ]
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
args += [
|
||
|
|
"--",
|
||
|
|
"{{defines}}",
|
||
|
|
"{{include_dirs}}",
|
||
|
|
"{{cflags}}",
|
||
|
|
"{{cflags_c}}",
|
||
|
|
]
|
||
|
|
|
||
|
|
# Clang ships with some headers, which are installed along side the binary,
|
||
|
|
# and which clang itself finds by default, but libclang does not (see also
|
||
|
|
# https://reviews.llvm.org/D95396 which would resolve this but was reverted).
|
||
|
|
clang_headers = rebase_path(
|
||
|
|
clang_base_path + "/lib/clang/" + clang_version + "/include",
|
||
|
|
root_build_dir)
|
||
|
|
if (is_win) {
|
||
|
|
args += [ "-imsvc" + clang_headers ]
|
||
|
|
} else {
|
||
|
|
args += [ "-isystem" + clang_headers ]
|
||
|
|
}
|
||
|
|
|
||
|
|
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}" ]
|
||
|
|
}
|
||
|
|
|
||
|
|
# 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" ]
|
||
|
|
|
||
|
|
# 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" ]
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|