summaryrefslogtreecommitdiffstats
path: root/tools/profiler/rust-api/build.rs
diff options
context:
space:
mode:
Diffstat (limited to 'tools/profiler/rust-api/build.rs')
-rw-r--r--tools/profiler/rust-api/build.rs118
1 files changed, 118 insertions, 0 deletions
diff --git a/tools/profiler/rust-api/build.rs b/tools/profiler/rust-api/build.rs
new file mode 100644
index 0000000000..2dd70ed55c
--- /dev/null
+++ b/tools/profiler/rust-api/build.rs
@@ -0,0 +1,118 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+//! Build script for the Gecko Profiler bindings.
+//!
+//! This file is executed by cargo when this crate is built. It generates the
+//! `$OUT_DIR/bindings.rs` file which is then included by `src/gecko_bindings/mod.rs`.
+
+#[macro_use]
+extern crate lazy_static;
+
+use bindgen::{Builder, CargoCallbacks, CodegenConfig};
+use std::env;
+use std::fs;
+use std::path::PathBuf;
+
+lazy_static! {
+ static ref OUTDIR_PATH: PathBuf = PathBuf::from(env::var_os("OUT_DIR").unwrap()).join("gecko");
+}
+
+const BINDINGS_FILE: &str = "bindings.rs";
+
+lazy_static! {
+ static ref BINDGEN_FLAGS: Vec<String> = {
+ // Load build-specific config overrides.
+ let path = mozbuild::TOPOBJDIR.join("tools/profiler/rust-api/extra-bindgen-flags");
+ println!("cargo:rerun-if-changed={}", path.to_str().unwrap());
+ fs::read_to_string(path).expect("Failed to read extra-bindgen-flags file")
+ .split_whitespace()
+ .map(std::borrow::ToOwned::to_owned)
+ .collect()
+ };
+ static ref SEARCH_PATHS: Vec<PathBuf> = vec![
+ mozbuild::TOPOBJDIR.join("dist/include"),
+ mozbuild::TOPOBJDIR.join("dist/include/nspr"),
+ ];
+}
+
+fn search_include(name: &str) -> Option<PathBuf> {
+ for path in SEARCH_PATHS.iter() {
+ let file = path.join(name);
+ if file.is_file() {
+ return Some(file);
+ }
+ }
+ None
+}
+
+fn add_include(name: &str) -> String {
+ let file = match search_include(name) {
+ Some(file) => file,
+ None => panic!("Include not found: {}", name),
+ };
+ let file_path = String::from(file.to_str().unwrap());
+ println!("cargo:rerun-if-changed={}", file_path);
+ file_path
+}
+
+fn generate_bindings() {
+ let mut builder = Builder::default()
+ .enable_cxx_namespaces()
+ .with_codegen_config(CodegenConfig::TYPES | CodegenConfig::VARS | CodegenConfig::FUNCTIONS)
+ .disable_untagged_union()
+ .size_t_is_usize(true);
+
+ for dir in SEARCH_PATHS.iter() {
+ builder = builder.clang_arg("-I").clang_arg(dir.to_str().unwrap());
+ }
+
+ builder = builder
+ .clang_arg("-include")
+ .clang_arg(add_include("mozilla-config.h"));
+
+ for item in &*BINDGEN_FLAGS {
+ builder = builder.clang_arg(item);
+ }
+
+ let bindings = builder
+ .header(add_include("GeckoProfiler.h"))
+ .header(add_include("ProfilerBindings.h"))
+ .allowlist_function("gecko_profiler_.*")
+ .allowlist_var("mozilla::profiler::detail::RacyFeatures::sActiveAndFeatures")
+ .allowlist_type("mozilla::profiler::detail::RacyFeatures")
+ .rustified_enum("mozilla::StackCaptureOptions")
+ .rustified_enum("mozilla::MarkerSchema_Location")
+ .rustified_enum("mozilla::MarkerSchema_Format")
+ .rustified_enum("mozilla::MarkerSchema_Searchable")
+ // Converting std::string to an opaque type makes some platforms build
+ // successfully. Otherwise, it fails to build because MarkerSchema has
+ // some std::strings as its fields.
+ .opaque_type("std::string")
+ // std::vector needs to be converted to an opaque type because, if it's
+ // not an opaque type, bindgen can't find its size properly and
+ // MarkerSchema's total size reduces. That causes a heap buffer overflow.
+ .opaque_type("std::vector")
+ .raw_line("pub use self::root::*;")
+ // Tell cargo to invalidate the built crate whenever any of the
+ // included header files changed.
+ .parse_callbacks(Box::new(CargoCallbacks))
+ // Finish the builder and generate the bindings.
+ .generate()
+ // Unwrap the Result and panic on failure.
+ .expect("Unable to generate bindings");
+
+ let out_file = OUTDIR_PATH.join(BINDINGS_FILE);
+ bindings
+ .write_to_file(out_file)
+ .expect("Couldn't write bindings!");
+}
+
+fn main() {
+ println!("cargo:rerun-if-changed=build.rs");
+ println!("cargo:out_dir={}", env::var("OUT_DIR").unwrap());
+
+ fs::create_dir_all(&*OUTDIR_PATH).unwrap();
+ generate_bindings();
+}