Skip to content

Commit

Permalink
Merge pull request #435 from neon-bindings/windows-electron
Browse files Browse the repository at this point in the history
Windows electron
  • Loading branch information
kjvalencik authored Sep 13, 2019
2 parents 838a3ab + 4fab044 commit b9296f4
Show file tree
Hide file tree
Showing 16 changed files with 2,651 additions and 6 deletions.
7 changes: 6 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ before_install:
- node -v
- npm -v

# Required for electron tests
before_script:
- "export DISPLAY=:99.0"
- "sh -e /etc/init.d/xvfb start"
- sleep 3 # give xvfb some time to start

addons:
apt:
sources:
Expand All @@ -37,7 +43,6 @@ addons:

script: |
cargo test --release -- --nocapture
(cd test/dynamic/native && cargo test --release)
jobs:
include:
Expand Down
5 changes: 2 additions & 3 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
os: Visual Studio 2015
os: unstable
image: Visual Studio 2015

environment:
RUST_BACKTRACE: 1
Expand Down Expand Up @@ -40,8 +41,6 @@ build: false

test_script:
- cargo test --release
- cd test/dynamic/native
- cargo test --release

cache:
- target
Expand Down
9 changes: 9 additions & 0 deletions crates/neon-build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,14 @@ pub fn setup() {
println!("cargo:rustc-link-search={}\\{}", node_root_dir, configuration);
println!("cargo:rustc-link-search=native={}", &node_lib_path.display());
println!("cargo:rustc-link-lib={}", &node_lib_file_path.file_stem().unwrap().to_str().unwrap());

// Link `win_delay_load_hook.obj` for windows electron
let node_runtime_env = "npm_config_runtime";
println!("cargo:rerun-if-env-changed={}", node_runtime_env);
if env::var(node_runtime_env).map(|s| s == "electron") == Ok(true) {
println!("cargo:rustc-cdylib-link-arg=win_delay_load_hook.obj");
println!("cargo:rustc-cdylib-link-arg=delayimp.lib");
println!("cargo:rustc-cdylib-link-arg=/DELAYLOAD:node.exe");
}
}
}
33 changes: 31 additions & 2 deletions crates/neon-runtime/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ fn main() {
let out_dir = env::var("OUT_DIR").unwrap();
let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();

let out_dir = Path::new(&out_dir);
let native_from = Path::new(&crate_dir).join("native");
let native_to = Path::new(&out_dir).join("native");
let native_to = out_dir.join("native");

// 1. Copy the native runtime library into the build directory.
copy_native_library(&native_from, &native_to);
Expand All @@ -22,6 +23,9 @@ fn main() {

// 3. Link the library from the object file using gcc.
link_library(&native_to);

// 4. Copy native build artifacts
copy_build_artifacts(&native_to, &out_dir);
}

fn copy_files(dir_from: impl AsRef<Path>, dir_to: impl AsRef<Path>) {
Expand Down Expand Up @@ -179,7 +183,32 @@ fn link_library(native_dir: &Path) {
.join("neon.obj")
};

cc::Build::new().object(object_path).compile("libneon.a");
cc::Build::new().cpp(true).object(object_path).compile("libneon.a");
}

#[cfg(unix)]
fn copy_build_artifacts(_native_dir: &Path, _out_dir: &Path) {}

#[cfg(windows)]
fn copy_build_artifacts(native_dir: &Path, out_dir: &Path) {
let configuration = if debug() { "Debug" } else { "Release" };
let win_delay_file = "win_delay_load_hook.obj";
let win_delay_dest = out_dir.join(win_delay_file);
let win_delay_source = native_dir
.join("build")
.join(configuration)
.join("obj")
.join("neon")
.join(win_delay_file);

// Win delay hook is only needed for electron, warn instead of crash if not found
if let Err(err) = fs::copy(win_delay_source, win_delay_dest) {
if err.kind() == std::io::ErrorKind::NotFound {
eprintln!("warning: {} could not be found", win_delay_file);
} else {
panic!("{:?}", err);
}
}
}

fn debug() -> bool {
Expand Down
23 changes: 23 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,29 @@ mod tests {
run("npm test", &test_dynamic);
}

#[test]
fn dynamic_cargo_test() {
let _guard = TEST_MUTEX.lock();

log("dynamic_cargo_test");

let test_dynamic_cargo = project_root().join("test").join("dynamic").join("native");
run("cargo test --release", &test_dynamic_cargo);
}

#[test]
fn electron_test() {
let _guard = TEST_MUTEX.lock();

log("electron_test");

cli_setup();

let test_electron = project_root().join("test").join("electron");
run("npm install", &test_electron);
run("npm test", &test_electron);
}

#[test]
fn package_test() {
let _guard = TEST_MUTEX.lock();
Expand Down
3 changes: 3 additions & 0 deletions test/electron/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# neon-electron-quick-start

This is a minimal Electron application based on the [Quick Start Guide](https://electronjs.org/docs/tutorial/quick-start) within the Electron documentation combined with [Neon](https://neon-bindings.com).
14 changes: 14 additions & 0 deletions test/electron/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Neon Electron Test</title>
</head>
<body>
<script>
document.write(`<h1 id="header">${require('./native').hello()}</h1>`);
</script>

<script src="./renderer.js"></script>
</body>
</html>
54 changes: 54 additions & 0 deletions test/electron/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Modules to control application life and create native browser window
const {app, BrowserWindow} = require('electron')
const path = require('path')

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow

function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
preload: path.join(__dirname, 'preload.js')
}
})

// and load the index.html of the app.
mainWindow.loadFile('index.html')

// Open the DevTools.
// mainWindow.webContents.openDevTools()

// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)

// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') app.quit()
})

app.on('activate', function () {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) createWindow()
})

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
17 changes: 17 additions & 0 deletions test/electron/native/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "electron-tests"
version = "0.1.0"
edition = "2018"
authors = ["The Neon Community"]
license = "MIT/Apache-2.0"
build = "build.rs"

[lib]
name = "tests"
crate-type = ["cdylib"]

[build-dependencies]
neon-build = {path = "../../../crates/neon-build"}

[dependencies]
neon = {path = "../../../"}
3 changes: 3 additions & 0 deletions test/electron/native/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
neon_build::setup();
}
12 changes: 12 additions & 0 deletions test/electron/native/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use neon::prelude::*;
use neon::register_module;

fn hello(mut cx: FunctionContext) -> JsResult<JsString> {
Ok(cx.string("Hello, World!"))
}

register_module!(mut cx, {
cx.export_function("hello", hello)?;

Ok(())
});
Loading

0 comments on commit b9296f4

Please sign in to comment.