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

test(examples): 💍 example run in wasm #571

Merged
merged 1 commit into from
May 16, 2024
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: 2 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
[env]
CARGO_WORKSPACE_DIR = {value = "", relative = true}
[alias]
run-wasm = "run --package cli -- run-wasm --template ./cli/template"
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ Please only add new entries below the [Unreleased](#unreleased---releasedate) he
- **dev-helper**: Support specific the comparison of image tests. (#573 @M-Adoo)
- **dev-helper**: If test images differ, both actual and difference images are saved with the expected image. (#573 @M-Adoo)

- **example**: run example in web wasm (#571 @wjian23)

### Documented

- **core**: Explained when to use `unsubscribe` with `watch!`. (#556, @M-Adoo)
Expand Down
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ members = [
"tests",
"dev-helper",
"examples/*",
"cli",
]
resolver = "2"

Expand Down Expand Up @@ -68,7 +69,7 @@ quote = "1.0.16"
rayon = "1.5.1"
rctree = "0.5.0"
rustybuzz = "0.11.0"
rxrust = {version = "1.0.0-beta.6", default-features = false, features = ["futures-scheduler"]}
rxrust = { git ="https://github.com/rxRust/rxRust", default-features = false, features = ["futures-scheduler"]}
scoped_threadpool = "0.1.9"
triomphe = "0.1.11"
serde = "1.0"
Expand Down
11 changes: 11 additions & 0 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "cli"
version = "0.1.0"
edition = "2021"
publish = false

[dependencies]
xshell = "0.2.3"
clap = {version = "4.5.4", features = ["cargo", "derive"] }
anyhow = { version = "1.0" }
fs_extra = "1.3.0"
8 changes: 8 additions & 0 deletions cli/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
## Cli for ribir build
### SubCommand
**run-wasm**: build the example to wasm
1. compile to target wasm32-unknown-unknown
2. use wasm-bindgen to export relative function to js
3. serve the wasm in 127.0.0.1:8000 by simpl-http-server

you can see more usage information by --help.
29 changes: 29 additions & 0 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
mod program_check;
mod run_wasm;

use anyhow::Result;
use clap::ArgMatches;
use run_wasm::run_wasm;

trait CliCommand {
fn name(&self) -> &str;
fn command(&self) -> clap::Command;
fn exec(&self, args: &ArgMatches) -> Result<()>;
}

fn main() {
let mut cli = clap::Command::new("cli").bin_name("cli");

let commands = [run_wasm()];

for cmd in &commands {
cli = cli.subcommand(cmd.command());
}
let matches = cli.get_matches();

if let Some((sub_cmd, matches)) = matches.subcommand() {
if let Some(cmd) = commands.iter().find(|cmd| cmd.name() == sub_cmd) {
let _ = cmd.exec(matches);
}
}
}
36 changes: 36 additions & 0 deletions cli/src/program_check.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/// ** This implementation is base on [https://github.com/gfx-rs/wgpu/blob/trunk/xtask/src/util.rs]!**
use std::{io, process::Command};

pub(crate) struct Program {
pub binary_name: &'static str,
pub crate_name: &'static str,
}

pub(crate) fn check_all_programs(programs: &[Program]) -> anyhow::Result<()> {
let mut failed = Vec::new();
for Program { binary_name, crate_name } in programs {
let mut cmd = Command::new(binary_name);
cmd.arg("--help");
let output = cmd.output();
match output {
Ok(_output) => {
println!("Checking for {binary_name} in PATH: ✅");
}
Err(e) if matches!(e.kind(), io::ErrorKind::NotFound) => {
eprintln!("Checking for {binary_name} in PATH: ❌");
failed.push(*crate_name);
}
Err(e) => {
eprintln!("Checking for {binary_name} in PATH: ❌");
panic!("Unknown IO error: {:?}", e);
}
}
}

if !failed.is_empty() {
eprintln!("Please install them with: cargo install {}", failed.join(" "));
anyhow::bail!("Missing programs in PATH");
}

Ok(())
}
130 changes: 130 additions & 0 deletions cli/src/run_wasm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
use std::{path::PathBuf, str::FromStr};

use anyhow::Result;
use clap::{command, CommandFactory, FromArgMatches, Parser};

use crate::{
program_check::{check_all_programs, Program},
CliCommand,
};

pub fn run_wasm() -> Box<dyn CliCommand> { Box::new(RunWasm {}) }

struct RunWasm {}

#[derive(Parser, Debug)]
#[command(name = "run-wasm")]
/// run as web wasm
struct Wasm {
/// Package of which to run
#[arg(short, long)]
package: String,

/// Name of output, default to web_wasm
#[arg(short, long)]
name: Option<String>,

/// Direction path to output, default to target/wasm
#[arg(short, long)]
out_dir: Option<PathBuf>,

/// Build release, default build to debug
#[arg(short, long)]
release: bool,

/// Just build the wasm files, don't serve them
#[arg(long, name = "no-server")]
no_server: bool,

/// Template files need to copy to Output dir
#[arg(short, long)]
template: Option<PathBuf>,
}

impl CliCommand for RunWasm {
fn name(&self) -> &str { "run-wasm" }

fn command(&self) -> clap::Command { Wasm::command() }

fn exec(&self, args: &clap::ArgMatches) -> Result<()> {
let args = Wasm::from_arg_matches(args)?;

let mut dependencies =
vec![Program { crate_name: "wasm-bindgen-cli", binary_name: "wasm-bindgen" }];

if !args.no_server {
dependencies
.push(Program { crate_name: "simple-http-server", binary_name: "simple-http-server" });
}
check_all_programs(&dependencies)?;

let root_path = PathBuf::from_str(env!("CARGO_WORKSPACE_DIR"))?;
let package = args.package;
let name = args.name.unwrap_or("web_wasm".to_string());

let out_dir = args
.out_dir
.unwrap_or(PathBuf::from("./target/wasm"));
let output =
if out_dir.is_relative() { root_path.clone().join(&out_dir) } else { out_dir.clone() };

let shell = xshell::Shell::new()?;
let release_flg = if args.release { Some("--release") } else { None };

xshell::cmd!(
shell,
"cargo build -p {package} --lib {release_flg...} --target wasm32-unknown-unknown"
)
.quiet()
.run()?;

shell.change_dir(env!("CARGO_WORKSPACE_DIR"));
let target_path = if args.release {
"target/wasm32-unknown-unknown/release"
} else {
"target/wasm32-unknown-unknown/debug"
};

xshell::cmd!(
shell,
"wasm-bindgen {target_path}/{package}.wasm --target web
--no-typescript --out-dir {output} --out-name {name}"
)
.quiet()
.run()?;

if let Some(mut path) = args.template.clone() {
if path.is_relative() {
path = root_path.clone().join(path);
}
if path.is_dir() {
fs_extra::dir::copy(
&path,
&output,
&fs_extra::dir::CopyOptions::new()
.overwrite(true)
.content_only(true),
)?;
} else {
let file_name = output.clone().join(path.file_name().unwrap());
fs_extra::file::copy(
&path,
file_name,
&fs_extra::file::CopyOptions::new().overwrite(true),
)?;
}
}

if !args.no_server {
shell.change_dir(root_path);
xshell::cmd!(
shell,
"simple-http-server {out_dir} -c wasm,html,js -i --coep --coop --nocache"
)
.quiet()
.run()?;
}

Ok(())
}
}
21 changes: 21 additions & 0 deletions cli/template/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>

<head>
<meta charset="UTF-8" />
<title>Ribir</title>
</head>

<body>
<canvas class="ribir_canvas" style="width: 400px;height: 600px;" width="800" height="1200"></canvas>
<script type="module">
import init, { run } from "./web_wasm.js";
async function startup() {
await init();
run();
}
await startup()
</script>
</body>

</html>
4 changes: 0 additions & 4 deletions core/src/animation/stagger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,6 @@
//! };
//! ```

// fixme: rxRust not use std::time::Instant in web
#[cfg(target_family = "wasm")]
use std::time::Instant;

use ribir_algo::Sc;
use ribir_macros::rdl;

Expand Down
8 changes: 8 additions & 0 deletions examples/counter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,11 @@ ribir_dev_helper = {path = "../../dev-helper"}

[features]
wgpu = ["ribir/wgpu"]

[target.'cfg(target_arch = "wasm32")'.dependencies]
wasm-bindgen = "0.2.92"

[lib]
crate-type = ["cdylib", "rlib"]
path = "src/lib.rs"

4 changes: 4 additions & 0 deletions examples/counter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@ You can run with:
``` sh
cargo run -p counter
```
or run in web:
``` sh
cargo run-wasm -p counter
```
9 changes: 9 additions & 0 deletions examples/counter/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,11 @@
mod counter;
pub use counter::counter;
use ribir::prelude::*;

#[cfg_attr(target_arch = "wasm32", wasm_bindgen::prelude::wasm_bindgen)]
pub fn run() {
App::run(counter())
.with_app_theme(material::purple::light())
.with_size(Size::new(300., 150.))
.with_title("Counter ribir");
}
22 changes: 12 additions & 10 deletions examples/counter/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
mod counter;
use counter::counter;
use ribir::prelude::*;
use counter::run;

fn main() { run(); }

fn main() {
App::run(counter())
.with_title("Counter")
.with_app_theme(material::purple::light());
}
#[cfg_attr(target_arch = "wasm32", wasm_bindgen::prelude::wasm_bindgen)]
pub fn bin() {}

#[cfg(test)]
use ribir::core::test_helper::*;
use counter::counter;
#[cfg(test)]
use ribir::material as ribir_material;
use ribir::{
core::test_helper::*,
material as ribir_material,
prelude::{AppCtx, Size},
};
#[cfg(test)]
use ribir_dev_helper::*;

#[cfg(test)]
widget_image_test!(counter, wnd_size = Size::new(400., 600.), comparison = 0.001);
10 changes: 10 additions & 0 deletions examples/messages/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,13 @@ ribir_dev_helper = {path = "../../dev-helper"}

[features]
wgpu = ["ribir/wgpu"]

[target.'cfg(target_arch = "wasm32")'.dependencies]
wasm-bindgen = "0.2.92"

[lib]
crate-type = ["cdylib", "rlib"]
path = "src/lib.rs"

[package.metadata.wasm-pack.profile.release]
wasm-opt = false
5 changes: 5 additions & 0 deletions examples/messages/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,8 @@ You can run with:
``` sh
cargo run -p messages
```

or run in web:
``` sh
cargo run-wasm -p messages
```
9 changes: 9 additions & 0 deletions examples/messages/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,11 @@
mod messages;
pub use messages::messages;
use ribir::prelude::*;

#[cfg_attr(target_arch = "wasm32", wasm_bindgen::prelude::wasm_bindgen)]
pub fn run() {
App::run(messages())
.with_app_theme(material::purple::light())
.with_size(Size::new(400., 600.))
.with_title("Messages");
}
Loading
Loading