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

Use different artifact names for wasm/js in debug builds #1428

Merged
merged 14 commits into from
Feb 28, 2023
8 changes: 8 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ re_analytics = { path = "crates/re_analytics", version = "0.2.0" }
re_arrow_store = { path = "crates/re_arrow_store", version = "0.2.0" }
re_build_build_info = { path = "crates/re_build_build_info", version = "0.2.0" }
re_build_info = { path = "crates/re_build_info", version = "0.2.0" }
re_build_web_viewer = { path = "crates/re_build_web_viewer", version = "0.2.0" }
re_data_store = { path = "crates/re_data_store", version = "0.2.0" }
re_error = { path = "crates/re_error", version = "0.2.0" }
re_format = { path = "crates/re_format", version = "0.2.0" }
Expand Down
20 changes: 20 additions & 0 deletions crates/re_build_web_viewer/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[package]
name = "re_build_web_viewer"
authors.workspace = true
description = "Build the rerun web-viewer Wasm from source"
edition.workspace = true
homepage.workspace = true
include.workspace = true
license.workspace = true
publish = true
readme = "README.md"
repository.workspace = true
rust-version.workspace = true
version.workspace = true

[package.metadata.docs.rs]
all-features = true


[dependencies]
cargo_metadata = "0.15"
13 changes: 13 additions & 0 deletions crates/re_build_web_viewer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# `re_build_web_viewer`

Binary and library for building the Rerun web viewer.

This is also called by the `build.rs` of `re_web_server`.

```
cargo r -p re_build_web_viewer -- --debug
````

```
cargo r -p re_build_web_viewer -- --release
````
146 changes: 146 additions & 0 deletions crates/re_build_web_viewer/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
use cargo_metadata::camino::Utf8PathBuf;

fn target_directory() -> Utf8PathBuf {
let metadata = cargo_metadata::MetadataCommand::new()
.manifest_path("./Cargo.toml")
.features(cargo_metadata::CargoOpt::NoDefaultFeatures)
.exec()
.unwrap();
metadata.target_directory
}

/// Build `re_viewer` as Wasm, generate .js bindings for it, and place it all into the `./web_viewer` folder.
pub fn build(release: bool) {
eprintln!("Building web viewer wasm…");
eprintln!("We assume you've already run ./scripts/setup_web.sh");

let crate_name = "re_viewer";

// Where we tell cargo to build to.
// We want this to be different from the default target folder
// in order to support recursive cargo builds (calling `cargo` from within a `build.rs`).
let target_wasm_dir = Utf8PathBuf::from(format!("{}_wasm", target_directory()));

// Repository root
let root_dir = target_wasm_dir.parent().unwrap();

// Where we will place the final .wasm and .js artifacts.
let build_dir = root_dir.join("web_viewer");

assert!(
build_dir.exists(),
"Failed to find dir {build_dir}. CWD: {:?}, CARGO_MANIFEST_DIR: {:?}",
std::env::current_dir(),
std::env!("CARGO_MANIFEST_DIR")
);

let target_name = if release {
crate_name.to_owned()
} else {
format!("{crate_name}_debug")
};

// The two files we are building:
let wasm_path = build_dir.join(format!("{target_name}_bg.wasm"));
let js_path = build_dir.join(format!("{target_name}.js"));

// Clean old versions:
std::fs::remove_file(wasm_path.clone()).ok();
std::fs::remove_file(js_path).ok();

// --------------------------------------------------------------------------------
eprintln!("Compiling rust to wasm in {target_wasm_dir}…");

let mut cmd = std::process::Command::new("cargo");
cmd.args([
"build",
"--target-dir",
target_wasm_dir.as_str(),
"-p",
crate_name,
"--lib",
"--target",
"wasm32-unknown-unknown",
]);
if release {
cmd.arg("--release");
}

// This is required to enable the web_sys clipboard API which egui_web uses
// https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.Clipboard.html
// https://rustwasm.github.io/docs/wasm-bindgen/web-sys/unstable-apis.html
cmd.env("RUSTFLAGS", "--cfg=web_sys_unstable_apis");

// When executing this script from a Rust build script, do _not_, under any circumstances,
// allow pre-encoded `RUSTFLAGS` to leak into the current environment.
// These pre-encoded flags are generally generated by Cargo itself when loading its
// configuration from e.g. `$CARGO_HOME/config.toml`; which means they will contain
// values that only make sense for the native target host, not for a wasm build.
cmd.env("CARGO_ENCODED_RUSTFLAGS", "");

eprintln!("> {cmd:?}");
let status = cmd
.current_dir(root_dir)
.status()
.expect("Failed to build Wasm");
assert!(status.success(), "Failed to build Wasm");

// --------------------------------------------------------------------------------
eprintln!("Generating JS bindings for wasm…");

let build = if release { "release" } else { "debug" };

let target_wasm_path = target_wasm_dir
.join("wasm32-unknown-unknown")
.join(build)
.join(format!("{crate_name}.wasm"));

let mut cmd = std::process::Command::new("wasm-bindgen");
cmd.args([
target_wasm_path.as_str(),
"--out-dir",
build_dir.as_str(),
"--out-name",
target_name.as_str(),
"--no-modules",
"--no-typescript",
]);
if !release {
cmd.arg("--debug");
}

eprintln!("> {cmd:?}");
let status = cmd
.current_dir(root_dir)
.status()
.expect("Failed to run wasm-bindgen");
assert!(status.success(), "Failed to run wasm-bindgen");

// --------------------------------------------------------------------------------
// Optimize the wasm

if release {
eprintln!("Optimizing wasm with wasm-opt…");

// to get wasm-opt: apt/brew/dnf install binaryen
let mut cmd = std::process::Command::new("wasm-opt");

// TODO(emilk): add `-g` to keep debug symbols; useful for profiling release builds in the in-browser profiler.
cmd.args([
wasm_path.as_str(),
"-O2",
"--fast-math",
"-o",
wasm_path.as_str(),
]);

eprintln!("> {cmd:?}");
let status = cmd
.current_dir(root_dir)
.status()
.expect("Failed to run wasm-opt");
assert!(status.success(), "Failed to run wasm-opt");
}

eprintln!("Finished {wasm_path}");
}
46 changes: 46 additions & 0 deletions crates/re_build_web_viewer/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use std::process::ExitCode;

fn main() -> ExitCode {
let mut release = None;

for arg in std::env::args().skip(1) {
match arg.as_str() {
"--help" => {
print_help();
return ExitCode::SUCCESS;
}
"--debug" => {
assert!(release.is_none(), "Can't set both --release and --debug");
release = Some(false);
}
"--release" => {
assert!(release.is_none(), "Can't set both --release and --debug");
release = Some(true);
}
_ => {
print_help();
return ExitCode::FAILURE;
}
}
}

let Some(release) = release else {
eprintln!("You need to pass either --debug or --release");
return ExitCode::FAILURE;
};

re_build_web_viewer::build(release);
ExitCode::SUCCESS
}

fn print_help() {
eprintln!(
r"Build the web-viewer.

--help: Print this help text
--debug: Build a debug binary
--release: Compile for release, and run wasm-opt.
NOTE: --release also removes debug symbols which are otherwise useful for in-browser profiling.
"
);
}
1 change: 1 addition & 0 deletions crates/re_web_server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,4 @@ re_analytics = { workspace = true, optional = true }
[build-dependencies]
glob = "0.3.0"
cargo_metadata = "0.15"
re_build_web_viewer.workspace = true
Loading