bevy
bevy copied to clipboard
`embedded_asset!` is broken on Windows Wasm builds
Bevy version
0.14.0
Relevant system information
rustc --version:rustc 1.81.0-nightly (6292b2af6 2024-07-02)- Running Windows 11
`AdapterInfo { name: "NVIDIA GeForce GTX 1080 Ti", vendor: 4318, device: 6918, device_type: DiscreteGpu, driver: "NVIDIA", driver_info: "555.99", backend: Vulkan }`
What you did
There's a minimal reproduction here: https://github.com/janhohenheim/asset-crash
The relevant code is just this main.rs:
use bevy::{asset::embedded_asset, prelude::*};
fn main() {
let mut app = App::new();
app.add_plugins(DefaultPlugins);
embedded_asset!(app, "splash.png");
app.run();
}
The setup is:
- crate
- src/
main.rssplash.png
- src/
What went wrong
Running this with cargo run works.
Running it on Wasm on Windows instead gives me:
Failed to find src_prefix "src" in "src\\screen\\splash\\mod.rs"
This is the part of the Bevy code that panics: https://github.com/bevyengine/bevy/blob/main/crates/bevy_asset/src/io/embedded/mod.rs#L141 And this is the PR that introduced it: https://github.com/bevyengine/bevy/pull/10383
Note that this is not reproducible on Linux
Additional information
The minimal example has a workaround. Move crate/src/splash.png into crate/assets/splash.png and embed it with embedded_asset!(app, "../assets/splash.png");.
For reasons unknown to me, doing the same workaround on https://github.com/TheBevyFlock/bevy-template does not work.
I also tried running the embedded assets example with cargo build --example ... and that one works.
Using load_internal_binary_asset like this works as well:
load_internal_binary_asset!(
app,
SPLASH_IMAGE_HANDLE,
"splash.png",
|bytes, _path: String| {
Image::from_buffer(
bytes,
ImageType::Extension("png"),
default(),
true,
ImageSampler::linear(),
RenderAssetUsages::RENDER_WORLD | RenderAssetUsages::MAIN_WORLD,
)
.unwrap()
}
);
load_internal_binary_asset! doesn't have this issue, but it's awkward to use.
Bevy doesn't seem to use embedded_asset! anywhere internally -- it only uses load_internal_binary_asset! -- so bugs like this take longer to surface.
This seems like a rustc bug. The argument to embedded_asset! that behaves weirdly comes straight from the built-in file! macro, and it seems like it has an edge case. Here is a code snippet I ran inside the bevy template:
let path: &Path = file!().as_ref();
let components = path.components().into_iter().collect::<Vec<_>>();
panic!("path: {} components: {:?}", path.display(), components);
This results in:
Windows native:
path: src\screen\splash.rs components: [Normal("src"), Normal("screen"), Normal("splash.rs")]
Windows wasm:
path: src\screen\splash.rs components: [Normal("src\\screen\\splash.rs")]
And, just to top it off, windows native in a separate project I made to test this:
path: src/main.rs components: [Normal("src"), Normal("main.rs")]
I don't know why file! has both behaviors on Windows yet, but it makes sense that the Windows paths aren't parsed properly on wasm.
@kristoff3r that last point sounds like an explanation for why the workaround I reported works in one project but not the other
I found the difference between the 2 projects, it happens when a project has both a lib.rs and a main.rs.
So as far as I can tell the file macro gives unix paths in crates without a lib.rs, and windows path with lib.rs.
@kristoff3r did you submit a bug report to rustc? If so, could you link it? If not, do you want me to file one for you? Marking this as blocked in the meantime
I also encountered this problem when compiling Android targets on Windows:
07-12 10:40:10.005 7706 7734 I RustStdoutStderr: thread '<unnamed>' panicked at D:\rust\cargo\registry\src\index.crate
s.io-6f17d22bba15001f\bevy_asset-0.14.0\src\io\embedded\mod.rs:141:13:
07-12 10:40:10.005 7706 7734 I RustStdoutStderr: Failed to find src_prefix "src" in "src\\menu.rs"
07-12 10:40:10.005 7706 7734 I RustStdoutStderr: note: run with `RUST_BACKTRACE=1` environment variable to display a b
acktrace
The path in Windows is so unique that it does not use the common slash '/'.
Perhaps the easiest way to change it is to put file! () call is changed tofile!().replace(r"\", "/") 。
I hope there will be good progress as soon as possible, thank you.
I found the difference between the 2 projects, it happens when a project has both a
lib.rsand amain.rs.So as far as I can tell the
filemacro gives unix paths in crates without alib.rs, and windows path withlib.rs.
Nooooo wayyy That's the reason?
FYI, i cannot load assets at all on windows with main.rs and lib.rs: I get the following error:
2024-08-04T21:49:03.430604Z ERROR bevy_asset::server: Path not found: C:\Users\<path to project dir>\assets\Spaceship.glb#Scene0
I can guarantee that the path actually exists
Oops - no it was not the reason - i was using PathBuf::new("Spaceship.glb#Scene0")
That was a headscratcher! Should i make an issue for a better error message - i assume PathBuf is just not a supported AssetPath?
Woops - seems like the label stays part of the path when converting to AssetPath from a PathBuf or Path.
I would delete this impl or parse the label here.
This is another issue, sorry for spamming it in here: #14618
I reproduced this with Bevy main (after 0.16.0). So this is still an issue on WASM + Windows.
P.S. Thank you @janhohenheim for the fantastic MRE!