Here's a quick setup for cross-compiling Bevy games from WSL2 to Windows with quick iteration cycles. My 2020 laptop with Intel graphics compiles and starts both of my bevy demos in a few seconds for quick edit / try it turnarounds.
This setup leans into two things: dynamic linking bevy to make development builds quicker, and launching the Windows exe from the WSL shell. While WSL2 can do some graphics I find it flaky and this setup gets me the best of both.
Here are some of the steps. I'm assuming you have a WSL2 instance that's already able to build your Bevy 0.16 project. The main thing you'll need is xwin, which takes most of the pain out of cross-compiling to Windows.
# Install xwin for Windows SDK access
cargo install xwin cargo-xwin
# Download Windows CRT/SDK (one-time setup)
xwin --accept-license splat --output ~/.xwin
Ensure your bevy dependencies in Cargo.toml includes dynamic_linking. Mine looks like this.
[dependencies]
bevy = { version = "0.16", default-features = false, features = [
"bevy_asset", "bevy_gilrs", "bevy_scene", "bevy_winit",
"bevy_core_pipeline", "bevy_pbr", "bevy_gltf", "bevy_render",
"bevy_sprite", "bevy_text", "bevy_ui", "multi_threaded",
"dynamic_linking"
] }
I use a build-windows.sh script to wrap up the build. This script sets RUSTFLAGS
to ensure the exe's directory is included in the defaulit DLL search path.
#!/bin/bash
set -e
target="x86_64-pc-windows-msvc"
cargo xwin build --target $target
exe_path="target/$target/debug/bloblins-rust.exe"
required_dlls=$(objdump -p "$exe_path" | awk '/DLL Name/{print $3}')
sysroot=$(rustc --print sysroot)
rust_lib_dir="$sysroot/lib/rustlib/$target/lib"
for dll_name in $required_dlls; do
# skip system DLLs
if [[ "$dll_name" =~ ^(KERNEL32|USER32|ADVAPI32).*\.dll$ ]]; then
continue
fi
# copy dlls to the exe directory
if [[ -f "target/$target/debug/deps/$dll_name" ]]; then
cp "target/$target/debug/deps/$dll_name" "target/$target/debug/"
elif [[ -f "$rust_lib_dir/$dll_name" ]]; then
cp "$rust_lib_dir/$dll_name" "target/$target/debug/"
fi
done
And a simple run.sh for launching:
#!/bin/bash
cd target/x86_64-pc-windows-msvc/debug
./bloblins-rust.exe "$@"
Daily workflow looks like:
# Quick syntax check
cargo c
# Build with DLL management
./build.sh
# Run with arguments
./run.sh --headless --fps 60
# Lint before commit
cargo clippy
cargo fmt
This gets me sub-10-second iteration cycles for most changes. The key tricks are using cargo c for quick validation, automatic DLL management in the build script, and optimizing dependencies separately from my main code. Dynamic linking on Linux keeps builds fast, while the cross-compilation handles the Windows target without leaving WSL2.