Merge pull request #101 from napi-rs/0.4

refactor: decouple sys module of new napi-rs into a crate
This commit is contained in:
LongYinan 2020-07-15 01:21:13 +08:00 committed by GitHub
commit 8e46241cbb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 176 additions and 150 deletions

View file

@ -33,7 +33,7 @@ jobs:
- name: Run tests - name: Run tests
run: | run: |
docker run --rm -v $(pwd)/.cargo:/root/.cargo -v $(pwd):/napi-rs -w /napi-rs builder cargo test -p napi-rs --lib -- --nocapture docker run --rm -v $(pwd)/.cargo:/root/.cargo -v $(pwd):/napi-rs -w /napi-rs builder cargo test -p napi-sys --lib -- --nocapture
- name: Unit test - name: Unit test
run: | run: |

View file

@ -58,7 +58,7 @@ jobs:
timeout-minutes: 5 timeout-minutes: 5
with: with:
command: test command: test
args: -p napi-rs --lib -- --nocapture args: -p napi-sys --lib -- --nocapture
- name: Unit tests - name: Unit tests
run: | run: |

View file

@ -58,7 +58,7 @@ jobs:
timeout-minutes: 5 timeout-minutes: 5
with: with:
command: test command: test
args: -p napi-rs --lib -- --nocapture args: -p napi-sys --lib -- --nocapture
- name: Unit tests - name: Unit tests
run: | run: |

View file

@ -54,7 +54,7 @@ jobs:
timeout-minutes: 5 timeout-minutes: 5
with: with:
command: test command: test
args: -p napi-rs --lib -- --nocapture args: -p napi-sys --lib -- --nocapture
- name: Unit tests - name: Unit tests
run: | run: |

View file

@ -57,14 +57,14 @@ jobs:
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
with: with:
command: check command: check
args: -p napi-rs -vvv args: --all --bins --examples --tests -vvv
- name: Tests - name: Tests
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
timeout-minutes: 5 timeout-minutes: 5
with: with:
command: test command: test
args: -p napi-rs --lib -- --nocapture args: -p napi-sys --lib -- --nocapture
- name: Unit tests - name: Unit tests
run: | run: |

1
.gitignore vendored
View file

@ -9,6 +9,7 @@ build/LICENSE
napi/LICENSE napi/LICENSE
napi/README.md napi/README.md
napi-derive/LICENSE napi-derive/LICENSE
sys/LICENSE
# Created by https://www.gitignore.io/api/node # Created by https://www.gitignore.io/api/node
# Edit at https://www.gitignore.io/?templates=node # Edit at https://www.gitignore.io/?templates=node

View file

@ -3,6 +3,7 @@ members = [
"./build", "./build",
"./napi", "./napi",
"./napi-derive", "./napi-derive",
"./napi-derive-example" "./napi-derive-example",
"./sys"
] ]
exclude = ["./test_module"] exclude = ["./test_module"]

View file

@ -8,8 +8,8 @@ edition = "2018"
crate-type = ["cdylib"] crate-type = ["cdylib"]
[dependencies] [dependencies]
napi-rs = { path = "../napi" } napi = { path = "../napi" }
napi-rs-derive = { path = "../napi-derive" } napi-derive = { path = "../napi-derive" }
[build-dependencies] [build-dependencies]
napi-build = { path = "../build" } napi-build = { path = "../build" }

View file

@ -1,7 +1,7 @@
#[macro_use] #[macro_use]
extern crate napi_rs as napi; extern crate napi;
#[macro_use] #[macro_use]
extern crate napi_rs_derive; extern crate napi_derive;
use napi::{CallContext, Error, JsNumber, JsUnknown, Module, Result, Status}; use napi::{CallContext, Error, JsNumber, JsUnknown, Module, Result, Status};
use std::convert::TryInto; use std::convert::TryInto;

View file

@ -1,6 +1,6 @@
[package] [package]
name = "napi-rs-derive" name = "napi-derive"
version = "0.2.0" version = "0.4.0"
authors = ["LongYinan <lynweklm@gmail.com>"] authors = ["LongYinan <lynweklm@gmail.com>"]
edition = "2018" edition = "2018"
description = "N-API procedural macros" description = "N-API procedural macros"

View file

@ -82,24 +82,24 @@ pub fn js_function(attr: TokenStream, input: TokenStream) -> TokenStream {
#signature #(#fn_block)* #signature #(#fn_block)*
#visibility extern "C" fn #fn_name( #visibility extern "C" fn #fn_name(
raw_env: napi_rs::sys::napi_env, raw_env: napi::sys::napi_env,
cb_info: napi_rs::sys::napi_callback_info, cb_info: napi::sys::napi_callback_info,
) -> napi_rs::sys::napi_value { ) -> napi::sys::napi_value {
use std::io::Write; use std::io::Write;
use std::mem; use std::mem;
use std::os::raw::c_char; use std::os::raw::c_char;
use std::ptr; use std::ptr;
use std::ffi::CString; use std::ffi::CString;
use napi_rs::{JsUnknown, Env, Status, NapiValue, CallContext}; use napi::{JsUnknown, Env, Status, NapiValue, CallContext};
let mut argc = #arg_len_span as usize; let mut argc = #arg_len_span as usize;
let mut raw_args = let mut raw_args =
unsafe { mem::MaybeUninit::<[napi_rs::sys::napi_value; #arg_len_span as usize]>::uninit().assume_init() }; unsafe { mem::MaybeUninit::<[napi::sys::napi_value; #arg_len_span as usize]>::uninit().assume_init() };
let mut raw_this = ptr::null_mut(); let mut raw_this = ptr::null_mut();
let mut has_error = false; let mut has_error = false;
unsafe { unsafe {
let status = napi_rs::sys::napi_get_cb_info( let status = napi::sys::napi_get_cb_info(
raw_env, raw_env,
cb_info, cb_info,
&mut argc as *mut usize as *mut u64, &mut argc as *mut usize as *mut u64,
@ -120,10 +120,10 @@ pub fn js_function(attr: TokenStream, input: TokenStream) -> TokenStream {
Err(e) => { Err(e) => {
let message = format!("{}", e); let message = format!("{}", e);
unsafe { unsafe {
napi_rs::sys::napi_throw_error(raw_env, ptr::null(), CString::from_vec_unchecked(message.into()).as_ptr() as *const c_char); napi::sys::napi_throw_error(raw_env, ptr::null(), CString::from_vec_unchecked(message.into()).as_ptr() as *const c_char);
} }
let mut undefined = ptr::null_mut(); let mut undefined = ptr::null_mut();
unsafe { napi_rs::sys::napi_get_undefined(raw_env, &mut undefined) }; unsafe { napi::sys::napi_get_undefined(raw_env, &mut undefined) };
undefined undefined
} }
} }

View file

@ -1,6 +1,6 @@
[package] [package]
name = "napi-rs" name = "napi"
version = "0.3.1" version = "0.4.0"
authors = ["Nathan Sobo <nathan@github.com>", "Yinan Long <lynweklm@gmail.com>"] authors = ["Nathan Sobo <nathan@github.com>", "Yinan Long <lynweklm@gmail.com>"]
license = "MIT" license = "MIT"
description = "N-API bindings" description = "N-API bindings"
@ -13,6 +13,9 @@ edition = "2018"
libuv = ["futures"] libuv = ["futures"]
tokio_rt = ["futures", "tokio", "once_cell"] tokio_rt = ["futures", "tokio", "once_cell"]
[dependencies]
napi-sys = { version = "0.4", path = "../sys" }
[dependencies.futures] [dependencies.futures]
version = "0.3" version = "0.3"
optional = true optional = true
@ -27,14 +30,5 @@ version = "1.4"
optional = true optional = true
[target.'cfg(windows)'.build-dependencies]
flate2 = "1.0"
reqwest = { version = "0.10", features = ["native-tls", "blocking"] }
tar = "0.4"
[build-dependencies] [build-dependencies]
bindgen = "0.54"
glob = "0.3"
napi-build = { version = "0.1", path = "../build" } napi-build = { version = "0.1", path = "../build" }
regex = "1.3"
semver = "0.10"

View file

@ -1,118 +1,5 @@
extern crate bindgen;
#[cfg(windows)]
extern crate flate2;
extern crate glob;
extern crate napi_build; extern crate napi_build;
#[cfg(windows)]
extern crate reqwest;
extern crate semver;
#[cfg(windows)]
extern crate tar;
use glob::glob;
use std::env;
use std::path::PathBuf;
use std::process::Command;
// https://stackoverflow.com/questions/37498864/finding-executable-in-path-with-rust
const NODE_PRINT_EXEC_PATH: &'static str = "console.log(process.execPath)";
fn main() { fn main() {
napi_build::setup(); napi_build::setup();
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/sys/**/*.*").unwrap() {
println!(
"cargo:rerun-if-changed={}",
entry.unwrap().to_str().unwrap()
);
}
if node_major_version < 10 {
panic!("node version is too low")
}
let node_include_path = find_node_include_path(node_full_version.trim_end());
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
let mut sys_bindigs_path = PathBuf::from("src");
sys_bindigs_path.push("sys");
sys_bindigs_path.push("bindings.h");
bindgen::Builder::default()
.header(sys_bindigs_path.to_str().unwrap().to_owned())
.clang_arg(String::from("-I") + node_include_path.to_str().unwrap())
.rustified_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(target_os = "windows")]
fn find_node_include_path(node_full_version: &str) -> PathBuf {
let mut node_exec_path = PathBuf::from(
String::from_utf8(
Command::new("node")
.arg("-e")
.arg(NODE_PRINT_EXEC_PATH)
.output()
.unwrap()
.stdout,
)
.expect("can not find executable node"),
)
.parent()
.unwrap()
.to_path_buf();
node_exec_path.push(format!("node-headers-{}.tar.gz", node_full_version));
let mut header_dist_path = PathBuf::from(&PathBuf::from(&node_exec_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 header_file_download_url = String::from_utf8(
Command::new("node")
.args(vec!["-e", "console.log(process.release.headersUrl)"])
.output()
.unwrap()
.stdout,
)
.unwrap();
let resp = reqwest::blocking::get(&header_file_download_url).expect("request failed");
tar::Archive::new(flate2::read::GzDecoder::new(resp))
.unpack(&unpack_path)
.expect("Unpack headers file failed");
};
header_dist_path
}
#[cfg(not(target_os = "windows"))]
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")
} }

View file

@ -65,7 +65,6 @@ mod module;
#[cfg(all(feature = "libuv", napi4))] #[cfg(all(feature = "libuv", napi4))]
mod promise; mod promise;
mod status; mod status;
pub mod sys;
mod task; mod task;
#[cfg(napi4)] #[cfg(napi4)]
pub mod threadsafe_function; pub mod threadsafe_function;
@ -75,6 +74,8 @@ mod tokio_rt;
mod uv; mod uv;
mod version; mod version;
pub use napi_sys as sys;
pub use call_context::CallContext; pub use call_context::CallContext;
pub use env::*; pub use env::*;
pub use error::{Error, Result}; pub use error::{Error, Result};

20
sys/Cargo.toml Normal file
View file

@ -0,0 +1,20 @@
[package]
name = "napi-sys"
version = "0.4.0"
authors = ["LongYinan <lynweklm@gmail.com>"]
edition = "2018"
readme = "README.md"
repository = "https://github.com/Brooooooklyn/napi-rs"
license = "MIT"
keywords = ["NodeJS", "FFI", "NAPI", "n-api"]
[target.'cfg(windows)'.build-dependencies]
flate2 = "1.0"
reqwest = { version = "0.10", features = ["native-tls", "blocking"] }
tar = "0.4"
[build-dependencies]
bindgen = "0.54"
glob = "0.3"
regex = "1.3"
semver = "0.10"

5
sys/README.md Normal file
View file

@ -0,0 +1,5 @@
# napi-sys
Low-level N-API bindings for Node.js addons written in Rust.
See the [napi](https://github.com/napi-rs/napi-rs) for the high-level API.

115
sys/build.rs Normal file
View file

@ -0,0 +1,115 @@
extern crate bindgen;
#[cfg(windows)]
extern crate flate2;
extern crate glob;
#[cfg(windows)]
extern crate reqwest;
extern crate semver;
#[cfg(windows)]
extern crate tar;
use glob::glob;
use std::env;
use std::path::PathBuf;
use std::process::Command;
// https://stackoverflow.com/questions/37498864/finding-executable-in-path-with-rust
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 < 10 {
panic!("node version is too low")
}
let node_include_path = find_node_include_path(node_full_version.trim_end());
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
let mut sys_bindigs_path = PathBuf::from("src");
sys_bindigs_path.push("bindings.h");
bindgen::Builder::default()
.header(sys_bindigs_path.to_str().unwrap().to_owned())
.clang_arg(String::from("-I") + node_include_path.to_str().unwrap())
.rustified_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(target_os = "windows")]
fn find_node_include_path(node_full_version: &str) -> PathBuf {
let mut node_exec_path = PathBuf::from(
String::from_utf8(
Command::new("node")
.arg("-e")
.arg(NODE_PRINT_EXEC_PATH)
.output()
.unwrap()
.stdout,
)
.expect("can not find executable node"),
)
.parent()
.unwrap()
.to_path_buf();
node_exec_path.push(format!("node-headers-{}.tar.gz", node_full_version));
let mut header_dist_path = PathBuf::from(&PathBuf::from(&node_exec_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 header_file_download_url = String::from_utf8(
Command::new("node")
.args(vec!["-e", "console.log(process.release.headersUrl)"])
.output()
.unwrap()
.stdout,
)
.unwrap();
let resp = reqwest::blocking::get(&header_file_download_url).expect("request failed");
tar::Archive::new(flate2::read::GzDecoder::new(resp))
.unpack(&unpack_path)
.expect("Unpack headers file failed");
};
header_dist_path
}
#[cfg(not(target_os = "windows"))]
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")
}

2
sys/src/lib.rs Normal file
View file

@ -0,0 +1,2 @@
mod sys;
pub use sys::*;

View file

@ -9,8 +9,8 @@ crate-type = ["cdylib"]
[dependencies] [dependencies]
futures = "0.3" futures = "0.3"
napi-rs = { path = "../napi", features = ["libuv", "tokio_rt"] } napi = { path = "../napi", features = ["libuv", "tokio_rt"] }
napi-rs-derive = { path = "../napi-derive" } napi-derive = { path = "../napi-derive" }
tokio = { version = "0.2", features = ["default", "fs"]} tokio = { version = "0.2", features = ["default", "fs"]}
[build-dependencies] [build-dependencies]

View file

@ -1,7 +1,7 @@
#[macro_use] #[macro_use]
extern crate napi_rs as napi; extern crate napi;
#[macro_use] #[macro_use]
extern crate napi_rs_derive; extern crate napi_derive;
use napi::{CallContext, Error, JsString, JsUnknown, Module, Result, Status}; use napi::{CallContext, Error, JsString, JsUnknown, Module, Result, Status};