Skip to content

Commit

Permalink
Move rust-mozjs's build script to mozjs-sys (#409)
Browse files Browse the repository at this point in the history
* Rename mozjs-sys jsglue static to jsapi

This also move libjsapi.a to the same place as jsapi.rs in $OUT_DIR/build

* Move mozjs's jsglue to mozjs-sys

* Cargo fmt
  • Loading branch information
wusyong authored Dec 29, 2023
1 parent 0a2efb9 commit 7184f65
Show file tree
Hide file tree
Showing 10 changed files with 1,465 additions and 1,469 deletions.
170 changes: 161 additions & 9 deletions mozjs-sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ const ENV_VARS: &'static [&'static str] = &[
const EXTRA_FILES: &'static [&'static str] = &[
"makefile.cargo",
"src/rustfmt.toml",
"src/jsglue.hpp",
"src/jsglue.cpp",
"src/jsapi.hpp",
"src/jsapi.cpp",
];

/// Which version of moztools we expect
Expand All @@ -54,9 +54,10 @@ fn main() {

fs::create_dir_all(&build_dir).expect("could not create build dir");

build_spidermonkey(&build_dir);
build_jsapi(&build_dir);
build_jsglue(&build_dir);
build_jsapi_bindings(&build_dir);
jsglue::build(&build_dir);

if env::var_os("MOZJS_FORCE_RERUN").is_none() {
for var in ENV_VARS {
Expand Down Expand Up @@ -158,7 +159,7 @@ fn find_moztools() -> Option<PathBuf> {
}
}

fn build_jsapi(build_dir: &Path) {
fn build_spidermonkey(build_dir: &Path) {
let target = env::var("TARGET").unwrap();
let make;

Expand Down Expand Up @@ -269,7 +270,7 @@ fn build_jsapi(build_dir: &Path) {
}
}

fn build_jsglue(build_dir: &Path) {
fn build_jsapi(build_dir: &Path) {
let mut build = cc::Build::new();
build.cpp(true);

Expand All @@ -287,11 +288,11 @@ fn build_jsglue(build_dir: &Path) {
}
build
.flag(&config)
.file("src/jsglue.cpp")
.file("src/jsapi.cpp")
.include(build_dir.join("dist/include"))
.include(build_dir.join("js/src"))
.out_dir(build_dir.join("glue"))
.compile("jsglue");
.out_dir(build_dir)
.compile("jsapi");
}

/// Invoke bindgen on the JSAPI headers to produce raw FFI bindings for use from
Expand All @@ -310,7 +311,7 @@ fn build_jsapi_bindings(build_dir: &Path) {

let mut builder = bindgen::builder()
.rust_target(bindgen::RustTarget::Stable_1_59)
.header("./src/jsglue.hpp")
.header("./src/jsapi.hpp")
// Translate every enum with the "rustified enum" strategy. We should
// investigate switching to the "constified module" strategy, which has
// similar ergonomics but avoids some potential Rust UB footguns.
Expand Down Expand Up @@ -550,3 +551,154 @@ fn ignore(path: &Path) -> bool {
.any(|&ignored| extension == ignored)
})
}

mod jsglue {
use std::env;
use std::path::{Path, PathBuf};

fn cc_flags(bindgen: bool) -> Vec<&'static str> {
let mut result = vec!["-DSTATIC_JS_API"];

if env::var("CARGO_FEATURE_DEBUGMOZJS").is_ok() {
result.push("-DDEBUG");

// bindgen doesn't like this
if !bindgen {
if cfg!(target_os = "windows") {
result.push("-Od");
} else {
result.push("-g");
result.push("-O0");
}
}
}

if env::var("CARGO_FEATURE_PROFILEMOZJS").is_ok() {
result.push("-fno-omit-frame-pointer");
}

result.push("-Wno-c++0x-extensions");
result.push("-Wno-return-type-c-linkage");
result.push("-Wno-invalid-offsetof");
result.push("-Wno-unused-parameter");

result
}

pub fn build(outdir: &Path) {
//let mut build = cxx_build::bridge("src/jsglue.rs"); // returns a cc::Build;
let mut build = cc::Build::new();
let include_path: PathBuf = outdir.join("dist/include");

build
.cpp(true)
.file("src/jsglue.cpp")
.include(&include_path);
for flag in cc_flags(false) {
build.flag_if_supported(flag);
}

let confdefs_path: PathBuf = outdir.join("js/src/js-confdefs.h");
let msvc = if build.get_compiler().is_like_msvc() {
build.flag(&format!("-FI{}", confdefs_path.to_string_lossy()));
build.define("WIN32", "");
build.flag("-Zi");
build.flag("-GR-");
build.flag("-std:c++17");
true
} else {
build.flag("-fPIC");
build.flag("-fno-rtti");
build.flag("-std=c++17");
build.flag("-include");
build.flag(&confdefs_path.to_string_lossy());
false
};

build.compile("jsglue");
println!("cargo:rerun-if-changed=src/jsglue.cpp");
let mut builder = bindgen::Builder::default()
.header("./src/jsglue.cpp")
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.size_t_is_usize(true)
.formatter(bindgen::Formatter::Rustfmt)
.clang_arg("-x")
.clang_arg("c++")
.clang_args(cc_flags(true))
.clang_args(["-I", &include_path.to_string_lossy()])
.enable_cxx_namespaces()
.allowlist_file("./src/jsglue.cpp")
.allowlist_recursively(false);

if msvc {
builder = builder.clang_args([
"-fms-compatibility",
&format!("-FI{}", confdefs_path.to_string_lossy()),
"-DWIN32",
"-std=c++17",
])
} else {
builder = builder
.clang_args(["-fPIC", "-fno-rtti", "-std=c++17"])
.clang_args(["-include", &confdefs_path.to_str().expect("UTF-8")])
}

for ty in BLACKLIST_TYPES {
builder = builder.blocklist_type(ty);
}

for ty in OPAQUE_TYPES {
builder = builder.opaque_type(ty);
}

for &(module, raw_line) in MODULE_RAW_LINES {
builder = builder.module_raw_line(module, raw_line);
}
let bindings = builder
.generate()
.expect("Unable to generate bindings to jsglue");

bindings
.write_to_file(outdir.join("gluebindings.rs"))
.expect("Couldn't write bindings!");
}

/// Types that have generic arguments must be here or else bindgen does not generate <T>
/// as it treats them as opaque types
const BLACKLIST_TYPES: &'static [&'static str] = &[
"JS::.*",
"already_AddRefed",
// we don't want it null
"EncodedStringCallback",
];

/// Types that should be treated as an opaque blob of bytes whenever they show
/// up within a whitelisted type.
///
/// These are types which are too tricky for bindgen to handle, and/or use C++
/// features that don't have an equivalent in rust, such as partial template
/// specialization.
const OPAQUE_TYPES: &'static [&'static str] = &[
"JS::Auto.*Impl",
"JS::StackGCVector.*",
"JS::PersistentRooted.*",
"JS::detail::CallArgsBase.*",
"js::detail::UniqueSelector.*",
"mozilla::BufferList",
"mozilla::Maybe.*",
"mozilla::UniquePtr.*",
"mozilla::Variant",
"mozilla::Hash.*",
"mozilla::detail::Hash.*",
"RefPtr_Proxy.*",
];

/// Map mozjs_sys mod namespaces to bindgen mod namespaces
const MODULE_RAW_LINES: &'static [(&'static str, &'static str)] = &[
("root", "pub(crate) use crate::jsapi::*;"),
("root", "pub use crate::glue::EncodedStringCallback;"),
("root::js", "pub(crate) use crate::jsapi::js::*;"),
("root::mozilla", "pub(crate) use crate::jsapi::mozilla::*;"),
("root::JS", "pub(crate) use crate::jsapi::JS::*;"),
];
}
4 changes: 3 additions & 1 deletion mozjs/src/glue.rs → mozjs-sys/src/glue.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
//! Rust wrappers for mozjs's glue module

mod generated {
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
include!(concat!(env!("OUT_DIR"), "/gluebindings.rs"));
include!(concat!(env!("OUT_DIR"), "/build/gluebindings.rs"));
}

use core::mem;
Expand Down
Loading

0 comments on commit 7184f65

Please sign in to comment.