1 // This Source Code Form is subject to the terms of the Mozilla Public
2 // License, v. 2.0. If a copy of the MPL was not distributed with this
3 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
4 
5 extern crate glob;
6 extern crate num_cpus;
7 
8 use std::env;
9 use std::path;
10 use std::process::{Command, Stdio};
11 
main()12 fn main() {
13     let out_dir = env::var("OUT_DIR").expect("Should have env var OUT_DIR");
14     let target = env::var("TARGET").expect("Should have env var TARGET");
15 
16     let js_src = env::var("CARGO_MANIFEST_DIR").expect("Should have env var CARGO_MANIFEST_DIR");
17 
18     env::set_var("MAKEFLAGS", format!("-j{}", num_cpus::get()));
19 
20     // The Rust package used in Spidermonkey inherits the default profile from the toplevel
21     // Cargo directory. In particular, both profiles (dev or release) set panic=abort,
22     // which defines an exception handling personality that will trigger calls to abort().
23     // The Rust bindings package wants to be able to unwind at runtime, so override the
24     // profile's value here.
25     env::set_var("RUSTFLAGS", "-C panic=unwind");
26 
27     env::set_current_dir(&js_src).unwrap();
28 
29     let variant = if cfg!(feature = "debugmozjs") {
30         "plaindebug"
31     } else {
32         "plain"
33     };
34 
35     let python = env::var("PYTHON3").unwrap_or("python3".into());
36     let mut cmd = Command::new(&python);
37     cmd.args(&[
38         "./devtools/automation/autospider.py",
39         // Only build SpiderMonkey, don't run all the tests.
40         "--build-only",
41         // Disable Mozilla's jemalloc; Rust has its own jemalloc that we
42         // can swap in instead and everything using a single malloc is
43         // good.
44         "--no-jemalloc",
45         // Don't try to clobber the output directory. Without
46         // this option, the build will fail because the directory
47         // already exists but wasn't created by autospider.
48         "--dep",
49         "--objdir",
50         &out_dir,
51         &variant,
52     ])
53     .env("NO_RUST_PANIC_HOOK", "1")
54     .env("SOURCE", &js_src)
55     .env("PWD", &js_src)
56     .stdout(Stdio::inherit())
57     .stderr(Stdio::inherit());
58     println!("Running command: {:?}", cmd);
59     let result = cmd.status().expect("Should spawn autospider OK");
60     assert!(result.success(), "autospider should exit OK");
61 
62     println!("cargo:rustc-link-search=native={}/js/src/build", out_dir);
63     println!("cargo:rustc-link-search=native={}/js/src", out_dir);
64     println!("cargo:rustc-link-lib=static=js_static");
65 
66     maybe_add_spidermonkey_rust_lib();
67 
68     println!("cargo:rustc-link-search=native={}/dist/bin", out_dir);
69     println!("cargo:rustc-link-lib=nspr4");
70 
71     if target.contains("windows") {
72         println!("cargo:rustc-link-lib=winmm");
73         if target.contains("gnu") {
74             println!("cargo:rustc-link-lib=stdc++");
75         }
76     } else {
77         println!("cargo:rustc-link-lib=stdc++");
78     }
79 
80     println!("cargo:outdir={}", out_dir);
81 }
82 
83 /// Find if Spidermonkey built the Spidermonkey Rust library, and add it to the
84 /// link if it was the case.
maybe_add_spidermonkey_rust_lib()85 fn maybe_add_spidermonkey_rust_lib() {
86     let out_dir = env::var("OUT_DIR").expect("cargo should invoke us with the OUT_DIR env var set");
87 
88     let mut target_build_dir = path::PathBuf::from(out_dir);
89     target_build_dir.push("../../");
90 
91     let mut build_dir = target_build_dir.display().to_string();
92     build_dir.push_str("mozjs_sys-*/out/*/debug");
93 
94     let entries = match glob::glob(&build_dir) {
95         Err(_) => {
96             return;
97         }
98         Ok(entries) => entries,
99     };
100 
101     for entry in entries {
102         if let Ok(path) = entry {
103             let path = path
104                 .canonicalize()
105                 .expect("Should canonicalize debug build path");
106             let path = path.to_str().expect("Should be utf8");
107             println!("cargo:rustc-link-search=native={}", path);
108             println!("cargo:rustc-link-lib=static=jsrust");
109             return;
110         }
111     }
112 }
113