Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Download and link node.lib on Windows #583

Merged
merged 11 commits into from
Sep 18, 2020
7 changes: 7 additions & 0 deletions .github/workflows/windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,16 @@ jobs:
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: Install libclang
uses: KyleMayes/install-llvm-action@7770802
with:
version: "10"
directory: ${{ runner.temp }}/llvm
# - name: update node-gyp to latest
# # https://github.com/nodejs/node-gyp/issues/1933#issuecomment-586915535
# run: npm install -g node-gyp@latest
- run: npm config set msvs_version 2019
- name: run cargo test
run: cargo test --release
env:
LIBCLANG_PATH: ${{ runner.temp }}/llvm/bin
73 changes: 73 additions & 0 deletions crates/neon-build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,79 @@ cfg_if! {
println!("cargo:rustc-cdylib-link-arg=/DELAYLOAD:node.exe");
}
}
} else if #[cfg(windows)] {
// ^ automatically not neon-sys
use std::io::{Error, ErrorKind, Write, Result};
use std::process::Command;
use std::path::Path;

fn node_version() -> Result<String> {
let output = Command::new("node").arg("-v").output()?;
if !output.status.success() {
let _ = std::io::stderr().write_all(&output.stderr);
panic!("Could not download node.lib. There is likely more information from stderr above.");
}
let stdout = String::from_utf8(output.stdout).map_err(|error| {
Error::new(ErrorKind::InvalidData, error)
})?;
Ok(stdout.trim().to_string())
}

fn download_node_lib(version: &str, arch: &str) -> Result<Vec<u8>> {
let script = r#"
var url = process.argv[1]
require("https").get(url, function (res) {
res.pipe(process.stdout);
});
"#;
let url = format!("https://nodejs.org/dist/{version}/win-{arch}/node.lib", version = version, arch = arch);

let output = Command::new("node")
.arg("-e").arg(script)
.arg(url)
.output()?;

Ok(output.stdout)
}

/// Set up the build environment by setting Cargo configuration variables.
pub fn setup() {
// If the user specified a node.lib path, we do not need to download
if let Some(node_lib_path) = std::env::var_os("NEON_NODE_LIB") {
let node_lib_path = Path::new(&node_lib_path);
// Clearing the file name returns the root+directory name
let dir = node_lib_path.with_file_name("");
let basename = node_lib_path.file_stem().expect("Could not parse lib name from NEON_NODE_LIB. Does the path include the full file name?");

println!("cargo:rustc-link-search=native={}", dir.display());
// `basename` is an OsStr, we can output it anyway by re-wrapping it in a Path
// Both `dir` and `basename` will be mangled (contain replacement characters) if
// they are not UTF-8 paths. If we don't mangle them though, Cargo will: so
// non-UTF-8 paths are simply not supported.
println!("cargo:rustc-link-lib={}", Path::new(basename).display());
return;
}

let version = std::env::var("npm_config_target")
.or_else(|_| node_version())
.expect("Could not determine Node.js version");
let arch = if std::env::var("CARGO_CFG_TARGET_ARCH").unwrap() == "x86" {
"x86"
} else {
"x64"
};

let node_lib_store_path = format!(r"{}/node-{}.lib", env!("OUT_DIR"), arch);

// Download node.lib if it does not exist
if let Err(_) = std::fs::metadata(&node_lib_store_path) {
let node_lib = download_node_lib(&version, arch).expect("Could not download `node.lib`");
std::fs::write(&node_lib_store_path, &node_lib).expect("Could not save `node.lib`");
}

println!("cargo:rustc-link-search=native={}", env!("OUT_DIR"));
println!("cargo:rustc-link-lib=node-{}", arch);
}
} else if #[cfg(target_os = "macos")] {
/// Set up the build environment by setting Cargo configuration variables.
pub fn setup() {
Expand Down
5 changes: 2 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ mod tests {
};

eprintln!("Running Neon test: {} {} {}", shell, command_flag, cmd);

assert!(Command::new(&shell)
.current_dir(dir)
.args(&[&command_flag, cmd])
Expand Down Expand Up @@ -495,11 +495,10 @@ mod tests {
if std::env::var("CI") == Ok("true".to_string()) {
run("cargo package", &test_package);
} else {
run("cargo package --allow-dirty", &test_package);
run("cargo package --allow-dirty", &test_package);
}
}

#[cfg(not(windows))]
#[test]
fn napi_test() {
let _guard = TEST_MUTEX.lock();
Expand Down