Replace old build_demo_web.sh with trunk

This commit is contained in:
Emil Ernerfeldt 2022-08-20 00:07:09 +02:00
parent 5c63648c02
commit eda9850038
22 changed files with 154 additions and 1888 deletions

45
.github/workflows/pages.yml vendored Normal file
View file

@ -0,0 +1,45 @@
name: Github Pages
# By default, runs if you push to master. keeps your deployed app in sync with master branch.
on:
push:
branches:
- master
# to only run when you do a new github release, comment out above part and uncomment the below trigger.
# on:
# release:
# types:
# - published
permissions:
contents: write # for committing to gh-pages branch.
jobs:
build-github-pages:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2 # repo checkout
- uses: actions-rs/toolchain@v1 # get rust toolchain for wasm
with:
profile: minimal
toolchain: stable
target: wasm32-unknown-unknown
override: true
- name: Rust Cache # cache the rust build artefacts
uses: Swatinem/rust-cache@v1
- name: Download and install Trunk binary
run: wget -qO- https://github.com/thedodd/trunk/releases/latest/download/trunk-x86_64-unknown-linux-gnu.tar.gz | tar -xzf-
- name: Build # build
# "${GITHUB_REPOSITORY#*/}" evaluates into the name of the repository
# using --public-url something will allow trunk to modify all the href paths like from favicon.ico to repo_name/favicon.ico .
# this is necessary for github pages where the site is deployed to username.github.io/repo_name and all files must be requested
# relatively as eframe_template/favicon.ico. if we skip public-url option, the href paths will instead request username.github.io/favicon.ico which
# will obviously return error 404 not found.
run: ./trunk build --release --public-url "${GITHUB_REPOSITORY#*/}"
- name: Deploy
uses: JamesIves/github-pages-deploy-action@v4
with:
folder: dist
# this option will not maintain any history of your previous pages deployment
# set to false if you want all page build to be committed to your gh-pages branch history
single-commit: true

View file

@ -182,8 +182,8 @@ jobs:
- uses: actions/checkout@v2
- uses: EmbarkStudios/cargo-deny-action@v1
wasm_bindgen:
name: wasm-bindgen
trunk:
name: trunk
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
@ -193,8 +193,10 @@ jobs:
toolchain: 1.61.0
target: wasm32-unknown-unknown
override: true
- run: ./sh/setup_web.sh
- run: ./sh/wasm_bindgen_check.sh
- name: Download and install Trunk binary
run: wget -qO- https://github.com/thedodd/trunk/releases/latest/download/trunk-x86_64-unknown-linux-gnu.tar.gz | tar -xzf-
- name: Build
run: ./trunk build
android:
name: android

3
.gitignore vendored
View file

@ -1,5 +1,6 @@
.DS_Store
**/target
/.*.json
/.vscode
/dist
/media/*
.DS_Store

1
Cargo.lock generated
View file

@ -1261,6 +1261,7 @@ dependencies = [
"serde",
"tracing-subscriber",
"tracing-wasm",
"web-sys",
"wgpu",
]

2
Trunk.toml Normal file
View file

@ -0,0 +1,2 @@
[build]
filehash = false

View file

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View file

@ -1,3 +0,0 @@
This folder contains the files required for the egui web demo hosted at <https://www.egui.rs/>.
The reason the folder is called "docs" is because that is the name that GitHub requires in order to host a web page from the `master` branch of a repository.

File diff suppressed because it is too large Load diff

Binary file not shown.

View file

@ -1,12 +0,0 @@
<!DOCTYPE html>
<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<head>
<meta http-equiv="refresh" content="0; url = https://www.egui.rs/#http" />
</head>
<body>
</body>
</html>

View file

@ -11,9 +11,6 @@ default-run = "egui_demo_app"
[package.metadata.docs.rs]
all-features = true
[lib]
crate-type = ["cdylib", "rlib"]
[features]
default = ["glow", "persistence"]
@ -70,3 +67,4 @@ tracing-subscriber = "0.3"
[target.'cfg(target_arch = "wasm32")'.dependencies]
console_error_panic_hook = "0.1.6"
tracing-wasm = "0.2"
web-sys = { version = "0.3", features = [] }

View file

@ -5,7 +5,11 @@ View the demo app online at <https://egui.rs>.
Run it locally with `cargo run --release -p egui_demo_app`.
`egui_demo_app` can be compiled to WASM and viewed in a browser locally with:
`egui_demo_app` can be compiled to WASM and viewed in a browser locally using [Trunk](https://trunkrs.dev/).
First install trunk with `cargo install --locked trunk`.
Run `trunk serve` to build and serve on `http://127.0.0.1:8080`. It will rebuild automatically if you edit the project.
```sh
./sh/start_server.sh &

View file

@ -5,9 +5,6 @@ mod backend_panel;
pub(crate) mod frame_history;
mod wrap_app;
#[cfg(target_arch = "wasm32")]
use eframe::web::AppRunnerRef;
pub use wrap_app::WrapApp;
/// Time of day as seconds since midnight. Used for clock in demo app.
@ -16,66 +13,3 @@ pub(crate) fn seconds_since_midnight() -> f64 {
let time = chrono::Local::now().time();
time.num_seconds_from_midnight() as f64 + 1e-9 * (time.nanosecond() as f64)
}
// ----------------------------------------------------------------------------
#[cfg(target_arch = "wasm32")]
use eframe::wasm_bindgen::{self, prelude::*};
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen]
pub struct WebHandle {
handle: AppRunnerRef,
}
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen]
impl WebHandle {
#[wasm_bindgen]
#[cfg(target_arch = "wasm32")]
pub fn stop_web(&self) -> Result<(), wasm_bindgen::JsValue> {
let mut app = self.handle.lock();
let res = app.destroy();
// let numw = Arc::weak_count(&app);
// let nums = Arc::strong_count(&app);
// tracing::debug!("runner ref {:?}, {:?}", numw, nums);
res
}
}
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen]
pub fn init_wasm_hooks() {
// Make sure panics are logged using `console.error`.
console_error_panic_hook::set_once();
// Redirect tracing to console.log and friends:
tracing_wasm::set_as_global_default();
}
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen]
pub fn start_separate(canvas_id: &str) -> Result<WebHandle, wasm_bindgen::JsValue> {
let web_options = eframe::WebOptions::default();
let handle = eframe::start_web(
canvas_id,
web_options,
Box::new(|cc| Box::new(WrapApp::new(cc))),
)
.map(|handle| WebHandle { handle });
handle
}
/// This is the entry-point for all the web-assembly.
/// This is called once from the HTML.
/// It loads the app, installs some callbacks, then returns.
/// You can add more callbacks like this if you want to call in to your code.
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen]
pub fn start(canvas_id: &str) -> Result<WebHandle, wasm_bindgen::JsValue> {
init_wasm_hooks();
start_separate(canvas_id)
}

View file

@ -2,7 +2,10 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
use egui_demo_app::WrapApp;
// When compiling natively:
#[cfg(not(target_arch = "wasm32"))]
fn main() {
// Log to stdout (if you run with `RUST_LOG=debug`).
tracing_subscriber::fmt::init();
@ -20,6 +23,79 @@ fn main() {
eframe::run_native(
"egui demo app",
options,
Box::new(|cc| Box::new(egui_demo_app::WrapApp::new(cc))),
Box::new(|cc| Box::new(WrapApp::new(cc))),
);
}
#[cfg(target_arch = "wasm32")]
use eframe::web::AppRunnerRef;
#[cfg(target_arch = "wasm32")]
use eframe::wasm_bindgen::{self, prelude::*};
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen]
pub struct WebHandle {
handle: AppRunnerRef,
}
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen]
impl WebHandle {
#[wasm_bindgen]
#[cfg(target_arch = "wasm32")]
pub fn stop_web(&self) -> Result<(), wasm_bindgen::JsValue> {
let mut app = self.handle.lock();
let res = app.destroy();
// let numw = Arc::weak_count(&app);
// let nums = Arc::strong_count(&app);
// tracing::debug!("runner ref {:?}, {:?}", numw, nums);
res
}
}
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen]
pub fn init_wasm_hooks() {
// Make sure panics are logged using `console.error`.
console_error_panic_hook::set_once();
// Redirect tracing to console.log and friends:
tracing_wasm::set_as_global_default();
}
#[cfg(target_arch = "wasm32")]
#[wasm_bindgen]
pub fn start_separate(canvas_id: &str) -> Result<WebHandle, wasm_bindgen::JsValue> {
let web_options = eframe::WebOptions::default();
let handle = eframe::start_web(
canvas_id,
web_options,
Box::new(|cc| Box::new(WrapApp::new(cc))),
)
.map(|handle| WebHandle { handle });
handle
}
/// This is the entry-point for all the web-assembly.
/// This is called once from the HTML.
/// It loads the app, installs some callbacks, then returns.
/// You can add more callbacks like this if you want to call in to your code.
#[cfg(target_arch = "wasm32")]
fn main() {
fn remove_loading_text() -> Option<()> {
web_sys::window()?
.document()?
.get_element_by_id("loading_text")?
.remove();
None
}
let canvas_id = "the_canvas_id";
init_wasm_hooks();
start_separate(canvas_id).unwrap();
remove_loading_text();
}

View file

@ -7,6 +7,15 @@
<head>
<title>egui An immediate mode GUI written in Rust</title>
<!-- config for our rust wasm binary. go to https://trunkrs.dev/assets/#rust for more customization -->
<link data-trunk rel="rust" data-wasm-opt="2" href="egui_demo_app" />
<!-- this is the base url relative to which other urls will be constructed. trunk will insert this from the public-url option -->
<base data-trunk-public-url />
<link data-trunk rel="icon" href="assets/favicon.ico">
<link data-trunk rel="copy-file" href="assets/CNAME">
<style>
html {
/* Remove touch delay: */
@ -91,72 +100,21 @@
transform: rotate(360deg);
}
}
</style>
</head>
<body>
<!-- The WASM code will resize the canvas dynamically -->
<!-- The canvas id is hardcoded in `egui_demo_app/src/main.rs` so, make sure they match -->
<canvas id="the_canvas_id"></canvas>
<div class="centered" id="center_text">
<div class="centered" id="loading_text">
<p style="font-size:16px">
Loading…
</p>
<div class="lds-dual-ring"></div>
</div>
<script>
// The `--no-modules`-generated JS from `wasm-bindgen` attempts to use
// `WebAssembly.instantiateStreaming` to instantiate the wasm module,
// but this doesn't work with `file://` urls. This example is frequently
// viewed by simply opening `index.html` in a browser (with a `file://`
// url), so it would fail if we were to call this function!
//
// Work around this for now by deleting the function to ensure that the
// `no_modules.js` script doesn't have access to it. You won't need this
// hack when deploying over HTTP.
delete WebAssembly.instantiateStreaming;
</script>
<!-- this is the JS generated by the `wasm-bindgen` CLI tool -->
<script src="egui_demo_app.js"></script>
<script>
// We'll defer our execution until the wasm is ready to go.
// Here we tell bindgen the path to the wasm file so it can start
// initialization and return to us a promise when it's done.
console.debug("loading wasm…");
wasm_bindgen("./egui_demo_app_bg.wasm")
.then(on_wasm_loaded)
.catch(on_wasm_error);
function on_wasm_loaded() {
console.debug("wasm loaded. starting app…");
// This call installs a bunch of callbacks and then returns:
const handle = wasm_bindgen.start("the_canvas_id");
// call `handle.stop_web()` to stop
// uncomment to quick result
// setTimeout(() => {handle.stop_web(); handle.free())}, 2000)
console.debug("app started.");
document.getElementById("center_text").remove();
}
function on_wasm_error(error) {
console.error("Failed to start: " + error);
document.getElementById("center_text").innerHTML = `
<p>
An error occurred during loading:
</p>
<p style="font-family:Courier New">
${error}
</p>
<p style="font-size:14px">
Make sure you use a modern browser with WebGL and WASM enabled.
</p>`;
}
</script>
</body>
</html>

View file

@ -1,98 +0,0 @@
#!/usr/bin/env bash
set -eu
script_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )
cd "$script_path/.."
CRATE_NAME="egui_demo_app"
# NOTE: persistence use up about 400kB (10%) of the WASM!
FEATURES="glow,http,persistence,screen_reader"
OPEN=false
OPTIMIZE=false
while test $# -gt 0; do
case "$1" in
-h|--help)
echo "build_demo_web.sh [--optimize] [--open]"
echo ""
echo " --optimize: Enable optimization step"
echo " Runs wasm-opt."
echo " NOTE: --optimize also removes debug symbols which are otherwise useful for in-browser profiling."
echo ""
echo " --open: Open the result in a browser"
exit 0
;;
-O|--optimize)
shift
OPTIMIZE=true
;;
--open)
shift
OPEN=true
;;
*)
break
;;
esac
done
./sh/setup_web.sh
# This is required to enable the web_sys clipboard API which eframe 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
export RUSTFLAGS=--cfg=web_sys_unstable_apis
# Clear output from old stuff:
rm -f "docs/${CRATE_NAME}_bg.wasm"
echo "Building rust…"
BUILD=release
(cd $CRATE_NAME &&
cargo build \
--release \
--lib \
--target wasm32-unknown-unknown \
--no-default-features \
--features ${FEATURES}
)
# Get the output directory (in the workspace it is in another location)
TARGET=`cargo metadata --format-version=1 | jq --raw-output .target_directory`
echo "Generating JS bindings for wasm…"
TARGET_NAME="${CRATE_NAME}.wasm"
WASM_PATH="${TARGET}/wasm32-unknown-unknown/$BUILD/$TARGET_NAME"
wasm-bindgen "${WASM_PATH}" --out-dir docs --no-modules --no-typescript
# if this fails with "error: cannot import from modules (`env`) with `--no-modules`", you can use:
# wasm2wat target/wasm32-unknown-unknown/release/egui_demo_app.wasm | rg env
# wasm2wat target/wasm32-unknown-unknown/release/egui_demo_app.wasm | rg "call .now\b" -B 20 # What calls `$now` (often a culprit)
# to get wasm-strip: apt/brew/dnf install wabt
# wasm-strip docs/${CRATE_NAME}_bg.wasm
if [[ "${OPTIMIZE}" = true ]]; then
echo "Optimizing wasm…"
# to get wasm-opt: apt/brew/dnf install binaryen
wasm-opt "docs/${CRATE_NAME}_bg.wasm" -O2 --fast-math -o "docs/${CRATE_NAME}_bg.wasm" # add -g to get debug symbols
fi
echo "Finished docs/${CRATE_NAME}_bg.wasm"
if [[ "${OPEN}" == true ]]; then
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
# Linux, ex: Fedora
xdg-open http://localhost:8888/index.html
elif [[ "$OSTYPE" == "msys" ]]; then
# Windows
start http://localhost:8888/index.html
else
# Darwin/MacOS, or something else
open http://localhost:8888/index.html
fi
fi

View file

@ -5,4 +5,4 @@ cd "$script_path/.."
# Pre-requisites:
rustup target add wasm32-unknown-unknown
cargo install wasm-bindgen-cli --version 0.2.82
cargo install --locked trunk

View file

@ -1,18 +0,0 @@
#!/usr/bin/env bash
set -eu
script_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )
cd "$script_path/.."
# Starts a local web-server that serves the contents of the `doc/` folder,
# i.e. the web-version of `egui_demo_app`.
PORT=8888
echo "ensuring basic-http-server is installed…"
cargo install basic-http-server
echo "starting server…"
echo "serving at http://localhost:${PORT}"
(cd docs && basic-http-server --addr 127.0.0.1:${PORT} .)
# (cd docs && python3 -m http.server ${PORT} --bind 127.0.0.1)

View file

@ -1,39 +0,0 @@
#!/usr/bin/env bash
set -eu
script_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )
cd "$script_path/.."
./sh/setup_web.sh
CRATE_NAME="egui_demo_app"
FEATURES="glow,http,persistence,screen_reader"
# This is required to enable the web_sys clipboard API which eframe 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
export RUSTFLAGS=--cfg=web_sys_unstable_apis
echo "Building rust…"
BUILD=debug # debug builds are faster
(cd $CRATE_NAME &&
cargo build \
--lib \
--target wasm32-unknown-unknown \
--no-default-features \
--features ${FEATURES}
)
TARGET="target"
echo "Generating JS bindings for wasm…"
rm -f "${CRATE_NAME}_bg.wasm" # Remove old output (if any)
TARGET_NAME="${CRATE_NAME}.wasm"
wasm-bindgen "${TARGET}/wasm32-unknown-unknown/$BUILD/$TARGET_NAME" \
--out-dir . --no-modules --no-typescript
# Remove output:
rm -f "${CRATE_NAME}_bg.wasm"
rm -f "${CRATE_NAME}.js"

View file

@ -3,4 +3,4 @@ set -eu
script_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd -P )
cd "$script_path"
./build_demo_web.sh && ls -lh ../docs/*.wasm
trunk build --release && ls -lh ../dist/*.wasm