Skip to content

Commit

Permalink
Add an example that uses Bevy, and fiddle with removing vars
Browse files Browse the repository at this point in the history
It looks like some environment variables that Cargo sets for OUR build
script are accidentally being leaked down to the build scripts of
other libraries we depend on! Oh no!
  • Loading branch information
JWorthe committed Feb 16, 2021
1 parent 14f0537 commit 5213255
Show file tree
Hide file tree
Showing 11 changed files with 280 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .semaphore/semaphore.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,8 @@ blocks:
- cd example
- cargo build --verbose
- cargo test --verbose
- cd ../tests/bevy
- cargo build --verbose
- cargo test --verbose
- cache store rustup $RUSTUP_HOME
- cache store cargo $CARGO_HOME
7 changes: 7 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,13 @@ fn run_wasm_pack(opt: &WebBundlerOpt, retries: u32) -> Result<()> {

std::env::set_var("CARGO_TARGET_DIR", target_dir.as_os_str());

// TODO: Review which of these vars actually need to be unset, and
// which extra additionally need to be unset. We should probably
// also reset them at the end of this function.
std::env::remove_var("CARGO_CFG_TARGET_FAMILY");
std::env::remove_var("CARGO_CFG_TARGET_FEATURE");
std::env::remove_var("CARGO_CFG_UNIX");

let build_opts = BuildOptions {
path: Some(opt.src_dir.clone()),
scope: None,
Expand Down
2 changes: 2 additions & 0 deletions tests/bevy/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
target
web-target
14 changes: 14 additions & 0 deletions tests/bevy/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[workspace]
members = [
"backend",
"frontend",
]

[profile.release]
lto = true
opt-level = 'z'
codegen-units = 1

[profile.release.build-override]
opt-level = 'z'
codegen-units = 1
25 changes: 25 additions & 0 deletions tests/bevy/backend/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
[package]
name = "backend"
version = "0.0.0"
edition = "2018"

[dependencies]
warp = "0.3"
mime_guess = "2"

[dependencies.tokio]
version = "1"
features = ["full"]

[dependencies.rust-embed]
version="5"
features= ["compression", "interpolate-folder-path"]

[build-dependencies.web-bundler]
path = "../../.."

# depend on the frontend project here not because we actually use it,
# but because we want to trigger a rerun of the build.rs script if
# anything in it changes.
[build-dependencies.frontend]
path = "../frontend"
23 changes: 23 additions & 0 deletions tests/bevy/backend/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use std::{env, path::PathBuf, process};
use web_bundler::WebBundlerOpt;

fn main() {
let out_dir = PathBuf::from(env::var("OUT_DIR").expect("expected OUT_DIR to be set by Cargo"));

let opt = WebBundlerOpt {
src_dir: "../frontend".into(),
dist_dir: out_dir.join("ui"),
tmp_dir: out_dir.join("tmp"),
base_url: Some("/".into()),
wasm_version: env::var("CARGO_PKG_VERSION")
.expect("expected CARGO_PKG_VERSION to be set by Cargo"),
release: env::var("PROFILE").expect("expected PROFILE to be set by Cargo") != "debug",
workspace_root: "..".into(),
additional_watch_dirs: Vec::new(),
};

if let Err(why) = web_bundler::run(opt) {
println!("Failed to build frontend. Error: {}", why);
process::exit(1);
}
}
104 changes: 104 additions & 0 deletions tests/bevy/backend/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
use rust_embed::RustEmbed;
use warp::{filters::BoxedFilter, http::header::HeaderValue, path::Tail, reply::Response, Filter};

#[tokio::main]
async fn main() {
let routes = warp::path!("api" / ..)
.and(warp::path::tail())
.map(|_| "Please pretend there's an API here.")
.or(ui_routes());

warp::serve(routes).bind(([127, 0, 0, 1], 3030)).await;
}

#[derive(RustEmbed)]
#[folder = "$OUT_DIR/ui"]
struct PortalWebAssets;

pub fn ui_routes() -> BoxedFilter<(impl warp::Reply,)> {
let static_files = warp::get()
.and(warp::path::tail())
.and_then(|path: Tail| async move { serve(path.as_str()).await })
.boxed();

let spa_mode_index = warp::get()
.and(warp::path::tail())
.and_then(|path: Tail| async move {
let first_path_segment = path.as_str().split('/').next();
let last_path_segment = path.as_str().split('/').last();
let is_api_path = first_path_segment == Some("api");
let is_index_html = last_path_segment == Some("index.html");
let is_file_like_path = last_path_segment
.map(|segment| segment.contains('.'))
.unwrap_or(false);

if !is_api_path && (is_index_html || !is_file_like_path) {
serve("index.html").await
} else {
Err(warp::reject::not_found())
}
})
.boxed();

// Order is important here. Serve a file if it exists, then fall back to index.html as a default.
static_files.or(spa_mode_index).boxed()
}

async fn serve(path: &str) -> Result<impl warp::Reply, warp::Rejection> {
if let Some(asset) = PortalWebAssets::get(path) {
let mime = mime_guess::from_path(path).first_or_octet_stream();

let mut res = Response::new(asset.into());
res.headers_mut().insert(
"content-type",
HeaderValue::from_str(mime.as_ref()).unwrap(),
);
Ok(res)
} else {
Err(warp::reject::not_found())
}
}

#[cfg(test)]
mod test {
use super::*;
use warp::http::status::StatusCode;

#[tokio::test]
async fn test_html() {
let filter = ui_routes();
let response = warp::test::request().path("/").reply(&filter).await;

assert_eq!(response.status(), StatusCode::OK);

let response_body: String = String::from_utf8(response.body().to_vec()).unwrap();

assert!(response_body
.contains("<style>button{background:black;color:white;font-size:100px}\n</style>"));
assert!(response_body.contains("<title>Seed Quickstart</title>"));

assert!(response_body.contains("<script type=\"module\">"));
}

#[tokio::test]
async fn test_wasm() {
let filter = ui_routes();
let response = warp::test::request()
.path("/app-0.0.0.wasm")
.reply(&filter)
.await;

assert_eq!(response.status(), StatusCode::OK);
}

#[tokio::test]
async fn test_static_file() {
let filter = ui_routes();
let response = warp::test::request()
.path("/static/star.png")
.reply(&filter)
.await;

assert_eq!(response.status(), StatusCode::OK);
}
}
21 changes: 21 additions & 0 deletions tests/bevy/frontend/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[package]
name = "frontend"
version = "0.1.0"
authors = ["David Ed Mellum <david@edmellum.com>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

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

[target.'cfg(target_arch = "wasm32")'.dependencies]
bevy = {version = "0.4.0", default-features = false, features = ["bevy_gltf", "bevy_winit", "render", "png"]}
bevy_webgl2 = {version="0.4.0"}
winit = {version = "0.24.0"}
rand = "0.7"
getrandom = {version="0.1", features=["wasm-bindgen"]}
wasm-bindgen = "0.2"

[package.metadata.wasm-pack.profile.release]
wasm-opt = ['-Os']
17 changes: 17 additions & 0 deletions tests/bevy/frontend/css/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
body {
background: linear-gradient(
135deg,
white 0%,
white 49%,
black 49%,
black 51%,
white 51%,
white 100%
);
background-repeat: repeat;
background-size: 20px 20px;
}

canvas {
background-color: white;
}
14 changes: 14 additions & 0 deletions tests/bevy/frontend/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

{{ stylesheet | safe }}

<title>Bevy Example</title>
</head>
<body>
{{ javascript | safe }}
</body>
</html>
50 changes: 50 additions & 0 deletions tests/bevy/frontend/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#![cfg(target_arch = "wasm32")]

use bevy::prelude::*;
use wasm_bindgen::prelude::*;

// This example comes from the Bevy_WebGL2 App Template: https://github.com/mrk-its/bevy_webgl2_app_template

#[wasm_bindgen(start)]
pub fn start() {
let mut app = App::build();
app.add_resource(Msaa { samples: 4 })
.add_plugins(DefaultPlugins);
#[cfg(target_arch = "wasm32")]
app.add_plugin(bevy_webgl2::WebGL2Plugin);
app.add_startup_system(setup.system()).run();
}

/// set up a simple 3D scene
fn setup(
commands: &mut Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
) {
// add entities to the world
commands
// plane
.spawn(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Plane { size: 5.0 })),
material: materials.add(Color::rgb(0.3, 0.5, 0.3).into()),
..Default::default()
})
// cube
.spawn(PbrBundle {
mesh: meshes.add(Mesh::from(shape::Cube { size: 1.0 })),
material: materials.add(Color::rgb(0.8, 0.7, 0.6).into()),
transform: Transform::from_translation(Vec3::new(0.0, 0.5, 0.0)),
..Default::default()
})
// light
.spawn(LightBundle {
transform: Transform::from_translation(Vec3::new(4.0, 8.0, 4.0)),
..Default::default()
})
// camera
.spawn(Camera3dBundle {
transform: Transform::from_translation(Vec3::new(-2.0, 2.5, 5.0))
.looking_at(Vec3::default(), Vec3::unit_y()),
..Default::default()
});
}

0 comments on commit 5213255

Please sign in to comment.