Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/target
target/
javy.wat
javy.wasm
index.js
Expand Down
18 changes: 10 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,21 @@
.DEFAULT_GOAL := cli

cli: core
cd crates/cli && cargo build --release
cd crates/cli && cargo build && cd -
Copy link
Member

@saulecabrera saulecabrera Aug 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should put back the release option here? Maybe it's not as critical, I don't feel strongly but sometimes there's a need to check the release profile for debugging. Alternatively we can just manually run the commands, I believe that this is less critical than my comment above (about allowing to copy the release binary)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would try to build everything in debug mode for now, it just makes local development so much faster since we don't have to go through the many optimization layers.


check-benchmarks:
cd crates/benchmarks \
&& cargo check --benches --release
cd crates/benchmarks \
&& cargo check --benches --release \
&& cd -

core:
cd crates/core \
&& cargo build --release --target=wasm32-wasi
&& cargo build --release --target=wasm32-wasi \
&& cd -

test-core:
cd crates/core \
&& cargo wasi test --features standalone-wasi -- --nocapture
cd crates/core \
&& cargo wasi test --features standalone-wasi -- --nocapture

tests: check-benchmarks test-core

Expand All @@ -24,13 +26,13 @@ fmt-quickjs-sys:
cd crates/quickjs-sys/ \
&& cargo fmt -- --check \
&& cargo clippy -- -D warnings \
&& cd - \
&& cd -

fmt-core:
cd crates/core/ \
&& cargo fmt -- --check \
&& cargo clippy -- -D warnings \
&& cd - \
&& cd -

fmt-cli:
cd crates/cli/ \
Expand Down
4 changes: 4 additions & 0 deletions crates/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,7 @@ which = "4.2"
structopt = "0.3"
anyhow = "1.0"
tempfile = "3.2.0"

[build-dependencies]
which = "4.2"

112 changes: 70 additions & 42 deletions crates/cli/build.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
use std::env;
use std::path::PathBuf;
use std::fs;
use std::io;
use std::io::Write;
use std::path::{Path, PathBuf};
use std::process::Command;

fn main() {
copy_prebuilt_binaries();
Expand All @@ -14,56 +18,20 @@ fn main() {
// When using clippy, we need to write a stubbed engine.wasm file to ensure compilation succeeds. This
// skips building the actual engine.wasm binary that would be injected into the CLI binary.
fn stub_engine_for_clippy() {
let out_dir: PathBuf = env::var("OUT_DIR")
.expect("failed to retrieve out dir")
.into();
let engine_path = PathBuf::from(env::var("OUT_DIR").unwrap()).join("engine.wasm");

let engine_path = out_dir.join("engine.wasm");
if !engine_path.exists() {
std::fs::write(engine_path, "").expect("failed to write empty engine.wasm stub");
std::fs::write(engine_path, &[]).expect("failed to write empty engine.wasm stub");
println!("cargo:warning=using stubbed engine.wasm for static analysis purposes...");
}
}

fn copy_engine_binary() {
let profile = env::var("PROFILE").expect("Couldn't retrieve profile");
if profile != "release" {
eprintln!("only --release is supported due to https://github.com/bytecodealliance/wizer/issues/27");
std::process::exit(1);
}

let out_dir: PathBuf = env::var("OUT_DIR")
.expect("failed to retrieve out dir")
.into();

let engine_path: PathBuf = std::env::var("CARGO_MANIFEST_DIR")
.map(PathBuf::from)
.ok()
.map(|mut b| {
b.pop();
b.pop();
b.join("target")
.join("wasm32-wasi")
.join(profile)
.join("javy_core.wasm")
})
.expect("failed to create path");

println!("cargo:rerun-if-changed={:?}", engine_path);

// Only copy the file when it exists. Cargo will take care of re-running this script when the file changes.
if engine_path.exists() {
std::fs::copy(&engine_path, out_dir.join("engine.wasm"))
.unwrap_or_else(|_| panic!("failed to copy engine from {:?}", engine_path));
}
}

// Copy OS specific pre-built binaries to a known location. The binaries will be embedded in the final binary and
// extracted to a temporary location if it's not already installed.
fn copy_prebuilt_binaries() {
let target_dir = PathBuf::from(std::env::var("OUT_DIR").unwrap());
let target_os = PathBuf::from(std::env::var("CARGO_CFG_TARGET_OS").unwrap());
let root = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
let target_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
let target_os = PathBuf::from(env::var("CARGO_CFG_TARGET_OS").unwrap());
let root = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());

let vendor_dir = root.join("vendor").join(target_os);
let target_vendor_dir = target_dir.join("vendor");
Expand All @@ -79,3 +47,63 @@ fn copy_prebuilt_binaries() {
}
});
}

// Copy the engine binary build from the `core` crate, and run wasm-strip + wasm-opt against it as suggested by https://github.com/bytecodealliance/wizer/issues/27.
fn copy_engine_binary() {
let mut engine_path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
engine_path.pop();
engine_path.pop();
let engine_path = engine_path.join("target/wasm32-wasi/release/javy_core.wasm");

println!("cargo:rerun-if-changed={:?}", engine_path);

if engine_path.exists() {
let copied_engine_path = PathBuf::from(env::var("OUT_DIR").unwrap()).join("engine.wasm");

fs::copy(&engine_path, &copied_engine_path).unwrap();
optimize_engine(&copied_engine_path);
}
}

fn optimize_engine(engine_path: impl AsRef<Path>) {
if env::var("JAVY_SKIP_ENGINE_OPTIMIZATIONS").is_ok() {
return;
}

run_wasm_strip(&engine_path);
run_wasm_opt(&engine_path);
}

fn run_wasm_strip(engine_path: impl AsRef<Path>) {
let wasm_strip = which::which("wasm-strip")
.unwrap_or_else(|_| PathBuf::from(env::var("OUT_DIR").unwrap()).join("vendor/wasm-opt"));

let output = Command::new(wasm_strip)
.arg(engine_path.as_ref())
.output()
.unwrap();

println!("wasm-strip status: {}", output.status);
io::stdout().write_all(&output.stdout).unwrap();
io::stderr().write_all(&output.stderr).unwrap();
assert!(output.status.success());
}

fn run_wasm_opt(engine_path: impl AsRef<Path>) {
let wasm_opt = which::which("wasm-opt")
.unwrap_or_else(|_| PathBuf::from(env::var("OUT_DIR").unwrap()).join("vendor/wasm-opt"));

let output = Command::new(wasm_opt)
.arg(engine_path.as_ref())
.arg("-O3")
.arg("--dce")
.arg("-o")
.arg(engine_path.as_ref())
.output()
.unwrap();

println!("wasm-opt status: {}", output.status);
io::stdout().write_all(&output.stdout).unwrap();
io::stderr().write_all(&output.stderr).unwrap();
assert!(output.status.success());
}