Skip to content

Commit e088ddd

Browse files
authored
use bindgen for rust-mozjs glue (#391)
* use bindgen for rust-mozjs glue * workspace bindgen * SMall fixups
1 parent 9b762f9 commit e088ddd

File tree

9 files changed

+160
-638
lines changed

9 files changed

+160
-638
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,7 @@ edition = "2021"
1010
[workspace.dependencies]
1111
cc = "1"
1212
libc = "0.2"
13+
bindgen = { version = "0.66", default-features = false, features = [
14+
"runtime",
15+
"which-rustfmt",
16+
] }

mozjs/Cargo.toml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,6 @@ libc.workspace = true
3535
libz-sys = "1.1"
3636

3737
[build-dependencies]
38-
bindgen = { version = "0.66", default-features = false, features = [
39-
"runtime",
40-
"which-rustfmt",
41-
] }
38+
bindgen.workspace = true
4239
cc.workspace = true
4340
walkdir = "2"

rust-mozjs/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@ mozjs_sys = { path = "../mozjs" }
2626

2727
[build-dependencies]
2828
cc.workspace = true
29+
bindgen.workspace = true

rust-mozjs/build.rs

Lines changed: 125 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,52 +5,154 @@
55
use std::env;
66
use std::path::PathBuf;
77

8-
fn main() {
9-
let mut build = cc::Build::new();
10-
let outdir = env::var("DEP_MOZJS_OUTDIR").unwrap();
11-
let include_path: PathBuf = [&outdir, "dist", "include"].iter().collect();
8+
fn cc_flags(bindgen: bool) -> Vec<&'static str> {
9+
let mut result = vec!["-DSTATIC_JS_API"];
1210

13-
build
14-
.cpp(true)
15-
.file("src/jsglue.cpp")
16-
.flag("-DSTATIC_JS_API")
17-
.include(include_path);
1811
if env::var("CARGO_FEATURE_DEBUGMOZJS").is_ok() {
19-
build.define("DEBUG", "");
12+
result.push("-DDEBUG");
2013

21-
if cfg!(target_os = "windows") {
22-
build.flag("-Od");
23-
} else {
24-
build.flag("-g");
25-
build.flag("-O0");
14+
// bindgen doesn't like this
15+
if !bindgen {
16+
if cfg!(target_os = "windows") {
17+
result.push("-Od");
18+
} else {
19+
result.push("-g");
20+
result.push("-O0");
21+
}
2622
}
2723
}
2824

2925
if env::var("CARGO_FEATURE_PROFILEMOZJS").is_ok() {
30-
build.flag_if_supported("-fno-omit-frame-pointer");
26+
result.push("-fno-omit-frame-pointer");
3127
}
3228

33-
build.flag_if_supported("-Wno-c++0x-extensions");
34-
build.flag_if_supported("-Wno-return-type-c-linkage");
35-
build.flag_if_supported("-Wno-invalid-offsetof");
36-
build.flag_if_supported("-Wno-unused-parameter");
29+
result.push("-Wno-c++0x-extensions");
30+
result.push("-Wno-return-type-c-linkage");
31+
result.push("-Wno-invalid-offsetof");
32+
result.push("-Wno-unused-parameter");
33+
34+
result
35+
}
36+
37+
fn main() {
38+
//let mut build = cxx_build::bridge("src/jsglue.rs"); // returns a cc::Build;
39+
let mut build = cc::Build::new();
40+
let outdir = env::var("DEP_MOZJS_OUTDIR").unwrap();
41+
let include_path: PathBuf = [&outdir, "dist", "include"].iter().collect();
42+
43+
build
44+
.cpp(true)
45+
.file("src/jsglue.cpp")
46+
.include(&include_path);
47+
for flag in cc_flags(false) {
48+
build.flag_if_supported(flag);
49+
}
3750

3851
let confdefs_path: PathBuf = [&outdir, "js", "src", "js-confdefs.h"].iter().collect();
39-
if build.get_compiler().is_like_msvc() {
52+
let msvc = if build.get_compiler().is_like_msvc() {
4053
build.flag(&format!("-FI{}", confdefs_path.to_string_lossy()));
4154
build.define("WIN32", "");
4255
build.flag("-Zi");
4356
build.flag("-GR-");
4457
build.flag("-std:c++17");
58+
true
4559
} else {
4660
build.flag("-fPIC");
4761
build.flag("-fno-rtti");
4862
build.flag("-std=c++17");
49-
build.define("JS_NO_JSVAL_JSID_STRUCT_TYPES", "");
5063
build.flag("-include");
5164
build.flag(&confdefs_path.to_string_lossy());
52-
}
65+
false
66+
};
5367

5468
build.compile("jsglue");
5569
println!("cargo:rerun-if-changed=src/jsglue.cpp");
70+
let mut builder = bindgen::Builder::default()
71+
.header("./src/jsglue.cpp")
72+
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
73+
.size_t_is_usize(true)
74+
.formatter(bindgen::Formatter::Rustfmt)
75+
.clang_arg("-x")
76+
.clang_arg("c++")
77+
.clang_args(cc_flags(true))
78+
.clang_args(["-I", &include_path.to_string_lossy()])
79+
.enable_cxx_namespaces()
80+
.allowlist_file("./src/jsglue.cpp")
81+
.allowlist_recursively(false);
82+
83+
if msvc {
84+
builder = builder.clang_args([
85+
&format!("-FI{}", confdefs_path.to_string_lossy()),
86+
"-DWIN32",
87+
"-GR-",
88+
"-std=c++17",
89+
])
90+
} else {
91+
builder = builder
92+
.clang_args(["-fPIC", "-fno-rtti", "-std=c++17"])
93+
.clang_args(["-include", &confdefs_path.to_str().expect("UTF-8")])
94+
}
95+
96+
for ty in BLACKLIST_TYPES {
97+
builder = builder.blocklist_type(ty);
98+
}
99+
100+
for ty in OPAQUE_TYPES {
101+
builder = builder.opaque_type(ty);
102+
}
103+
104+
for &(module, raw_line) in MODULE_RAW_LINES {
105+
builder = builder.module_raw_line(module, raw_line);
106+
}
107+
let bindings = builder
108+
.generate()
109+
.expect("Unable to generate bindings to jsglue");
110+
111+
// Write the bindings to the $OUT_DIR/bindings.rs file.
112+
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()).join("gluebindings.rs");
113+
bindings
114+
.write_to_file(out_path)
115+
.expect("Couldn't write bindings!");
56116
}
117+
118+
/// Types that have generic arguments must be here or else bindgen does not generate <T>
119+
/// as it treats them as opaque types
120+
const BLACKLIST_TYPES: &'static [&'static str] = &[
121+
"JS::.*",
122+
"already_AddRefed",
123+
// we don't want it null
124+
"EncodedStringCallback",
125+
];
126+
127+
/// Types that should be treated as an opaque blob of bytes whenever they show
128+
/// up within a whitelisted type.
129+
///
130+
/// These are types which are too tricky for bindgen to handle, and/or use C++
131+
/// features that don't have an equivalent in rust, such as partial template
132+
/// specialization.
133+
const OPAQUE_TYPES: &'static [&'static str] = &[
134+
"JS::Auto.*Impl",
135+
"JS::StackGCVector.*",
136+
"JS::PersistentRooted.*",
137+
"JS::detail::CallArgsBase.*",
138+
"js::detail::UniqueSelector.*",
139+
"mozilla::BufferList",
140+
"mozilla::Maybe.*",
141+
"mozilla::UniquePtr.*",
142+
"mozilla::Variant",
143+
"mozilla::Hash.*",
144+
"mozilla::detail::Hash.*",
145+
"RefPtr_Proxy.*",
146+
];
147+
148+
/// Map mozjs_sys mod namespaces to bindgen mod namespaces
149+
const MODULE_RAW_LINES: &'static [(&'static str, &'static str)] = &[
150+
("root", "pub(crate) use mozjs_sys::jsapi::*;"),
151+
("root", "pub use crate::glue::EncodedStringCallback;"),
152+
("root::js", "pub(crate) use mozjs_sys::jsapi::js::*;"),
153+
(
154+
"root::mozilla",
155+
"pub(crate) use mozjs_sys::jsapi::mozilla::*;",
156+
),
157+
("root::JS", "pub(crate) use mozjs_sys::jsapi::JS::*;"),
158+
];

rust-mozjs/src/generate_wrappers.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ grep_heur() {
3030
# clone file and reformat
3131
cp target/debug/build/mozjs_sys-*/out/build/jsapi.rs target/jsapi.rs
3232
rustfmt target/jsapi.rs --config max_width=1000
33-
cp rust-mozjs/src/glue.rs target/glue.rs
33+
cp target/debug/build/mozjs-*/out/gluebindings.rs target/glue.rs
3434
rustfmt target/glue.rs --config max_width=1000
3535

3636
# parse file

0 commit comments

Comments
 (0)