125 lines
3.8 KiB
Rust
125 lines
3.8 KiB
Rust
extern crate bindgen;
|
|
extern crate glob;
|
|
extern crate semver;
|
|
#[cfg(target_os = "windows")]
|
|
extern crate tar;
|
|
|
|
use glob::glob;
|
|
|
|
use std::env;
|
|
use std::path::PathBuf;
|
|
use std::process::Command;
|
|
|
|
#[cfg(not(any(target_os = "windows", napidocsrs)))]
|
|
const NODE_PRINT_EXEC_PATH: &'static str = "console.log(process.execPath)";
|
|
|
|
fn main() {
|
|
let node_full_version =
|
|
String::from_utf8(Command::new("node").arg("-v").output().unwrap().stdout).unwrap();
|
|
let node_version = semver::Version::parse(node_full_version.as_str().get(1..).unwrap()).unwrap();
|
|
|
|
let node_major_version = node_version.major;
|
|
|
|
println!("cargo:rerun-if-env-changed=NODE_INCLUDE_PATH");
|
|
for entry in glob("./src/**/*.*").unwrap() {
|
|
println!(
|
|
"cargo:rerun-if-changed={}",
|
|
entry.unwrap().to_str().unwrap()
|
|
);
|
|
}
|
|
|
|
if node_major_version < 8 && node_version.minor < 9 {
|
|
panic!("node version is too low")
|
|
}
|
|
|
|
let node_include_path_buf = find_node_include_path(node_full_version.trim_end());
|
|
|
|
let node_include_path = match env::var("NODE_INCLUDE_PATH") {
|
|
Ok(node_include_path) => node_include_path,
|
|
Err(_) => node_include_path_buf.to_str().unwrap().to_owned(),
|
|
};
|
|
|
|
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
|
|
|
let mut sys_bindings_path = PathBuf::from("src");
|
|
sys_bindings_path.push("bindings.h");
|
|
|
|
let mut bindgen_builder = bindgen::Builder::default()
|
|
.derive_default(true)
|
|
.header(sys_bindings_path.to_str().unwrap().to_owned())
|
|
.clang_arg(format!("-I{}", node_include_path))
|
|
.clang_arg("-target")
|
|
.clang_arg(env::var("TARGET").unwrap());
|
|
|
|
if let Ok(uv_include_path) = env::var("NAPI_RS_INCLUDE_PATH") {
|
|
bindgen_builder = bindgen_builder.clang_arg(format!("-I{}", uv_include_path));
|
|
}
|
|
if cfg!(target_os = "freebsd") {
|
|
bindgen_builder = bindgen_builder.clang_arg(format!(
|
|
"-I{}",
|
|
node_include_path_buf.parent().unwrap().to_str().unwrap()
|
|
));
|
|
}
|
|
|
|
bindgen_builder
|
|
.newtype_enum("(napi_|uv_).+")
|
|
.whitelist_function("(napi_|uv_|extras_).+")
|
|
.whitelist_type("(napi_|uv_|extras_).+")
|
|
.generate()
|
|
.expect("Unable to generate napi bindings")
|
|
.write_to_file(out_path.join("bindings.rs"))
|
|
.expect("Unable to write napi bindings");
|
|
}
|
|
|
|
#[cfg(all(target_os = "windows", not(napidocsrs)))]
|
|
fn find_node_include_path(node_full_version: &str) -> PathBuf {
|
|
let mut out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
|
out_path.push(format!("node-headers-{}.tar.gz", node_full_version));
|
|
let mut header_dist_path = PathBuf::from(&PathBuf::from(&out_path).parent().unwrap());
|
|
let unpack_path = PathBuf::from(&header_dist_path);
|
|
header_dist_path.push(format!("node-{}", node_full_version));
|
|
header_dist_path.push("include");
|
|
header_dist_path.push("node");
|
|
if !header_dist_path.exists() {
|
|
let script = r#"require('https').get(process.release.headersUrl, function (res) {
|
|
res.pipe(require('zlib').createUnzip()).pipe(process.stdout)
|
|
})"#;
|
|
|
|
let tar_binary = Command::new("node")
|
|
.arg("-e")
|
|
.arg(script)
|
|
.output()
|
|
.expect("Download headers file failed")
|
|
.stdout;
|
|
tar::Archive::new(tar_binary.as_slice())
|
|
.unpack(&unpack_path)
|
|
.expect("Unpack headers file failed");
|
|
};
|
|
header_dist_path
|
|
}
|
|
|
|
#[cfg(napidocsrs)]
|
|
fn find_node_include_path(_node_full_version: &str) -> PathBuf {
|
|
let mut current = env::current_dir().unwrap();
|
|
current.push(".node-headers");
|
|
current
|
|
}
|
|
|
|
#[cfg(not(any(target_os = "windows", napidocsrs)))]
|
|
fn find_node_include_path(_node_full_version: &str) -> PathBuf {
|
|
let node_exec_path = String::from_utf8(
|
|
Command::new("node")
|
|
.arg("-e")
|
|
.arg(NODE_PRINT_EXEC_PATH)
|
|
.output()
|
|
.unwrap()
|
|
.stdout,
|
|
)
|
|
.unwrap();
|
|
PathBuf::from(node_exec_path)
|
|
.parent()
|
|
.unwrap()
|
|
.parent()
|
|
.unwrap()
|
|
.join("include/node")
|
|
}
|