diff --git a/Cargo.toml b/Cargo.toml index 4f4a73781..59fbe64ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,11 @@ homepage = "http://neon.rustbridge.io" repository = "https://github.com/rustbridge/neon" license = "MIT/Apache-2.0" exclude = ["neon.jpg"] +build = "build.rs" + +# This name is arbitrary, but allows us to re-export the location of node.lib +# to dependent packages so they can link on Windows. +links = "neon-sys" [dependencies] cslice = { version = "=0.1.1", path = "crates/cslice" } diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 000000000..5fc1a6939 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,35 @@ +os: Visual Studio 2015 + +platform: + - x64 + - x86 + +environment: + NODEJS_VERSION: "6" + matrix: + - NODE_ARCHITECTURE: x64 + RUST_TOOLCHAIN: stable-x86_64-pc-windows-msvc + + - NODE_ARCHITECTURE: x86 + RUST_TOOLCHAIN: stable-i686-pc-windows-msvc + +install: + - ps: Install-Product node $env:NODEJS_VERSION $env:NODE_ARCHITECTURE + - node -e "console.log(process.arch, process.versions)" + + - curl -sSf -o rustup-init.exe https://win.rustup.rs + - rustup-init.exe -y --default-toolchain %RUST_TOOLCHAIN% + - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin + - rustup show + - rustc -V + - cargo -V + +build: false + +test_script: + - cd tests + - npm test + +cache: + - target + - C:\Users\appveyor\.cargo\registry diff --git a/build.rs b/build.rs new file mode 100644 index 000000000..eb423cfab --- /dev/null +++ b/build.rs @@ -0,0 +1,8 @@ +use std::env; + +fn main() { + if cfg!(windows) { + println!("cargo:node_root_dir={}", env::var("DEP_NEON_NODE_ROOT_DIR").unwrap()); + println!("cargo:node_lib_file={}", env::var("DEP_NEON_NODE_LIB_FILE").unwrap()); + } +} diff --git a/crates/neon-sys/binding.gyp b/crates/neon-sys/binding.gyp index 07a65591e..ace89f069 100644 --- a/crates/neon-sys/binding.gyp +++ b/crates/neon-sys/binding.gyp @@ -1,7 +1,19 @@ { - "targets": [{ - "target_name": "neon", - "sources": [ "src/neon.cc" ], - "include_dirs": [ " bool { - match env::var("DEBUG") { - Ok(s) => s == "true", - Err(_) => false - } -} - -fn mode() -> &'static str { - if debug() { "Debug" } else { "Release" } -} +fn main() { + // 1. Build the object file from source using node-gyp. + build_object_file(); -fn object_path(libname: &str) -> String { - format!("build/{}/obj.target/{}/src/{}.o", mode(), libname, libname) + // 2. Link the library from the object file using gcc. + link_library(); } fn build_object_file() { + let npm_command = if cfg!(unix) { "npm" } else { "npm.cmd" }; + let node_gyp_command = if cfg!(unix) { "node-gyp" } else { "node-gyp.cmd" }; + + if cfg!(windows) { + // Downcase all the npm environment variables to ensure they are read by node-gyp. + for (key, value) in env::vars() { + if key.starts_with("NPM_CONFIG") { + env::remove_var(&key); + env::set_var(key.to_lowercase(), value); + } + } + } + // Ensure that all package.json dependencies and dev dependencies are installed. - Command::new("npm").arg("install").status().ok() - .expect(r#"failed to run "npm install" for neon-sys"#); + Command::new(npm_command).args(&["install", "--silent"]).status().ok().expect("Failed to run \"npm install\" for neon-sys!"); + + // Run `node-gyp configure` in verbose mode to read node_root_dir on Windows. + let mut configure_args = vec!["configure", "--verbose"]; + if debug() { + configure_args.push("--debug"); + } + + let output = Command::new(node_gyp_command) + .args(&configure_args) + .output() + .expect("Failed to run \"node-gyp configure\" for neon-sys!"); - // Run the package.json `configure` script, which invokes `node-gyp configure` from the local node_modules. - Command::new("npm").arg("run").arg(if debug() { "configure-debug" } else { "configure-release" }).status().ok().unwrap(); + if cfg!(windows) { + let node_gyp_output = String::from_utf8_lossy(&output.stderr); + let node_root_dir_flag_pattern = "'-Dnode_root_dir="; + let node_root_dir_start_index = node_gyp_output + .find(node_root_dir_flag_pattern) + .map(|i| i + node_root_dir_flag_pattern.len()) + .expect("Couldn't find node_root_dir in node-gyp output."); + let node_root_dir_end_index = node_gyp_output[node_root_dir_start_index..].find("'").unwrap() + node_root_dir_start_index; + println!("cargo:node_root_dir={}", &node_gyp_output[node_root_dir_start_index..node_root_dir_end_index]); + let node_lib_file_flag_pattern = "'-Dnode_lib_file="; + let node_lib_file_start_index = node_gyp_output + .find(node_lib_file_flag_pattern) + .map(|i| i + node_lib_file_flag_pattern.len()) + .expect("Couldn't find node_lib_file in node-gyp output."); + let node_lib_file_end_index = node_gyp_output[node_lib_file_start_index..].find(".lib").unwrap() + node_lib_file_start_index; + println!("cargo:node_lib_file={}", &node_gyp_output[node_lib_file_start_index..node_lib_file_end_index]); + } + + // Run `node-gyp build` (appending -d in debug mode). + let mut build_args = vec!["build"]; + if debug() { + build_args.push("--debug"); + } - // Run the package.json `build` script, which invokes `node-gyp build` from the local node_modules. - Command::new("npm").arg("run").arg(if debug() { "build-debug" } else { "build-release" }).status().ok().unwrap(); + Command::new(node_gyp_command) + .stderr(Stdio::null()) // Prevent cargo build from hanging on Windows. + .args(&build_args) + .status() + .ok() + .expect("Failed to run \"node-gyp build\" for neon-sys!"); } +// Link the built object file into a static library. fn link_library() { - // Link the built object file into a static library. - gcc::Config::new() - .object(object_path("neon")) - .compile("libneon.a"); -} + let configuration = if debug() { "Debug" } else { "Release" }; + let object_path = if cfg!(unix) { + format!("build/{}/obj.target/neon/src/neon.o", configuration) + } else { + format!("build\\{}\\obj\\neon\\neon.obj", configuration) + }; -fn main() { - // 1. Build the object file from source using node-gyp. - build_object_file(); + gcc::Config::new().object(object_path).compile("libneon.a"); +} - // 2. Link the library from the object file using gcc. - link_library(); +fn debug() -> bool { + match env::var("DEBUG") { + Ok(s) => s == "true", + Err(_) => false + } } diff --git a/crates/neon-sys/package.json b/crates/neon-sys/package.json index 3d2e97938..d2221d50e 100644 --- a/crates/neon-sys/package.json +++ b/crates/neon-sys/package.json @@ -1,14 +1,10 @@ { "main": "index.js", "scripts": { - "configure-release": "node-gyp configure", - "build-release": "node-gyp build", - "configure-debug": "node-gyp configure -d", - "build-debug": "node-gyp build -d" + "preinstall": "echo 'Skipping node-gyp installation as part of npm install.'" }, "devDependencies": { - "nan": "^2.3.2", - "node-gyp": "^3.3.1" + "nan": "^2.3.2" }, "dependencies": { "bindings": "1.2.1" diff --git a/crates/neon-sys/src/array.rs b/crates/neon-sys/src/array.rs index 84a85474e..f6358b2a6 100644 --- a/crates/neon-sys/src/array.rs +++ b/crates/neon-sys/src/array.rs @@ -1,6 +1,6 @@ use raw::{Local, Isolate}; -extern "system" { +extern "C" { #[link_name = "NeonSys_Array_New"] pub fn new(out: &mut Local, isolate: *mut Isolate, length: u32); diff --git a/crates/neon-sys/src/buffer.rs b/crates/neon-sys/src/buffer.rs index a6100ceed..1c9565612 100644 --- a/crates/neon-sys/src/buffer.rs +++ b/crates/neon-sys/src/buffer.rs @@ -3,7 +3,7 @@ use cslice::CMutSlice; // Suppress a spurious rustc warning about the use of CMutSlice. #[allow(improper_ctypes)] -extern "system" { +extern "C" { #[link_name = "NeonSys_Buffer_New"] pub fn new(out: &mut Local, size: u32) -> bool; diff --git a/crates/neon-sys/src/call.rs b/crates/neon-sys/src/call.rs index fdae07395..75408cd23 100644 --- a/crates/neon-sys/src/call.rs +++ b/crates/neon-sys/src/call.rs @@ -1,6 +1,6 @@ use raw::{FunctionCallbackInfo, Isolate, Local}; -extern "system" { +extern "C" { #[link_name = "NeonSys_Call_SetReturn"] pub fn set_return(info: &FunctionCallbackInfo, value: Local); diff --git a/crates/neon-sys/src/class.rs b/crates/neon-sys/src/class.rs index a1cfb59c6..9b294b320 100644 --- a/crates/neon-sys/src/class.rs +++ b/crates/neon-sys/src/class.rs @@ -1,7 +1,7 @@ use std::os::raw::c_void; use raw::{Isolate, Local}; -extern "system" { +extern "C" { #[link_name = "NeonSys_Class_GetClassMap"] pub fn get_class_map(isolate: *mut Isolate) -> *mut c_void; diff --git a/crates/neon-sys/src/convert.rs b/crates/neon-sys/src/convert.rs index b0954dfb5..b78b90eec 100644 --- a/crates/neon-sys/src/convert.rs +++ b/crates/neon-sys/src/convert.rs @@ -1,6 +1,6 @@ use raw::Local; -extern "system" { +extern "C" { #[link_name = "NeonSys_Convert_ToObject"] pub fn to_object(out: &mut Local, value: &Local) -> bool; diff --git a/crates/neon-sys/src/error.rs b/crates/neon-sys/src/error.rs index 7226fd92d..b257a5457 100644 --- a/crates/neon-sys/src/error.rs +++ b/crates/neon-sys/src/error.rs @@ -1,6 +1,6 @@ use raw::Local; -extern "system" { +extern "C" { #[link_name = "NeonSys_Error_Throw"] pub fn throw(val: Local); diff --git a/crates/neon-sys/src/fun.rs b/crates/neon-sys/src/fun.rs index d38ac8828..69dae698c 100644 --- a/crates/neon-sys/src/fun.rs +++ b/crates/neon-sys/src/fun.rs @@ -1,7 +1,7 @@ use std::os::raw::c_void; use raw::{FunctionCallbackInfo, Local}; -extern "system" { +extern "C" { #[link_name = "NeonSys_Fun_New"] pub fn new(out: &mut Local, isolate: *mut c_void, callback: *mut c_void, kernel: *mut c_void) -> bool; diff --git a/crates/neon-sys/src/mem.rs b/crates/neon-sys/src/mem.rs index fd2ddf045..361f170b7 100644 --- a/crates/neon-sys/src/mem.rs +++ b/crates/neon-sys/src/mem.rs @@ -1,6 +1,6 @@ use raw::Local; -extern "system" { +extern "C" { #[link_name = "NeonSys_Mem_SameHandle"] pub fn same_handle(h1: Local, h2: Local) -> bool; diff --git a/crates/neon-sys/src/module.rs b/crates/neon-sys/src/module.rs index 3a5227811..1b194ab14 100644 --- a/crates/neon-sys/src/module.rs +++ b/crates/neon-sys/src/module.rs @@ -1,7 +1,7 @@ use std::os::raw::c_void; use raw::Local; -extern "system" { +extern "C" { #[link_name = "NeonSys_Module_ExecKernel"] pub fn exec_kernel(kernel: *mut c_void, callback: extern fn(*mut c_void, *mut c_void, *mut c_void), exports: Local, scope: *mut c_void); diff --git a/crates/neon-sys/src/neon.cc b/crates/neon-sys/src/neon.cc index 025bc8783..563e156e6 100644 --- a/crates/neon-sys/src/neon.cc +++ b/crates/neon-sys/src/neon.cc @@ -221,7 +221,7 @@ extern "C" void NeonSys_Scope_Enter(v8::HandleScope *scope, v8::Isolate *isolate } extern "C" void NeonSys_Scope_Exit(v8::HandleScope *scope) { - scope->~HandleScope(); + scope->HandleScope::~HandleScope(); } extern "C" size_t NeonSys_Scope_Sizeof() { diff --git a/crates/neon-sys/src/object.rs b/crates/neon-sys/src/object.rs index 15222f8e3..cf83a69c3 100644 --- a/crates/neon-sys/src/object.rs +++ b/crates/neon-sys/src/object.rs @@ -1,6 +1,6 @@ use raw::{Isolate, Local}; -extern "system" { +extern "C" { #[link_name = "NeonSys_Object_New"] pub fn new(out: &mut Local); diff --git a/crates/neon-sys/src/primitive.rs b/crates/neon-sys/src/primitive.rs index d274e26e7..2286d5106 100644 --- a/crates/neon-sys/src/primitive.rs +++ b/crates/neon-sys/src/primitive.rs @@ -1,6 +1,6 @@ use raw::{Local, Isolate}; -extern "system" { +extern "C" { #[link_name = "NeonSys_Primitive_Undefined"] pub fn undefined(out: &mut Local); diff --git a/crates/neon-sys/src/scope.rs b/crates/neon-sys/src/scope.rs index 6860d7a01..179359e7b 100644 --- a/crates/neon-sys/src/scope.rs +++ b/crates/neon-sys/src/scope.rs @@ -1,7 +1,7 @@ use std::os::raw::c_void; use raw::{HandleScope, EscapableHandleScope, Local}; -extern "system" { +extern "C" { #[link_name = "NeonSys_Scope_Escape"] pub fn escape(out: &mut Local, scope: *mut EscapableHandleScope, value: Local); diff --git a/crates/neon-sys/src/string.rs b/crates/neon-sys/src/string.rs index 957823b60..4b9942cbe 100644 --- a/crates/neon-sys/src/string.rs +++ b/crates/neon-sys/src/string.rs @@ -1,6 +1,6 @@ use raw::{Local, Isolate}; -extern "system" { +extern "C" { #[link_name = "NeonSys_String_New"] pub fn new(out: &mut Local, isolate: *mut Isolate, data: *const u8, len: i32) -> bool; diff --git a/crates/neon-sys/src/tag.rs b/crates/neon-sys/src/tag.rs index b4c5e30b9..4529270ea 100644 --- a/crates/neon-sys/src/tag.rs +++ b/crates/neon-sys/src/tag.rs @@ -16,7 +16,7 @@ pub enum Tag { Other } -extern "system" { +extern "C" { #[link_name = "NeonSys_Tag_Of"] pub fn of(val: Local) -> Tag; diff --git a/tests/native/Cargo.toml b/tests/native/Cargo.toml index e9efed6ad..829405773 100644 --- a/tests/native/Cargo.toml +++ b/tests/native/Cargo.toml @@ -3,6 +3,7 @@ name = "tests" version = "0.1.0" authors = ["The Neon Community"] license = "MIT/Apache-2.0" +build = "build.rs" [lib] name = "tests" diff --git a/tests/native/build.rs b/tests/native/build.rs new file mode 100644 index 000000000..59242e3b2 --- /dev/null +++ b/tests/native/build.rs @@ -0,0 +1,12 @@ +use std::env; + +fn main() { + if cfg!(windows) { + let debug = env::var("DEBUG").ok().map_or(false, |s| s == "true"); + let configuration = if debug { "Debug" } else { "Release" }; + let node_root_dir = env::var("DEP_NEON_SYS_NODE_ROOT_DIR").unwrap(); + let node_lib_file = env::var("DEP_NEON_SYS_NODE_LIB_FILE").unwrap(); + println!("cargo:rustc-link-search={}\\{}", node_root_dir, configuration); + println!("cargo:rustc-link-lib={}", node_lib_file); + } +}