16a1139eab
canvas_bg.wasm shipped at 36.2 MB — plain release (opt-level 3, thin
LTO) piped through wasm-opt -O2. Download size, not throughput, is the
binding constraint for the browser canvas, so solitaire_web now builds
with a dedicated wasm-release profile: opt-level "s", fat LTO, one
codegen unit. Local result: 23.2 MB after the unchanged wasm-opt -O2
pass — 35.9% smaller.
The binaryen pass stays at -O2 (the -Oz grey-screen miscompile note in
build_wasm.sh still applies). profile.strip is deliberately NOT set: on
wasm it also removes the target_features custom section, which makes
wasm-opt reject the module ('all used features should be allowed' on
trunc_sat).
Verified with the new artifact: all 5 play_canvas e2e specs pass (debug
bridge, draw3 param, apply/undo, replay diagnostics, 40-seed autoplay
invariants). Headless pixel verification is inconclusive in this
environment — wgpu cannot create a usable adapter locally and panics
identically on the OLD artifact too — so visual parity should be
confirmed against production after the next deploy.
pkg/ artifacts are intentionally not committed: the web-wasm-rebuild
workflow is the single source of truth and will regenerate them with
this profile on merge.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
175 lines
6.2 KiB
TOML
175 lines
6.2 KiB
TOML
[workspace]
|
|
members = [
|
|
"solitaire_core",
|
|
"solitaire_sync",
|
|
"solitaire_data",
|
|
"solitaire_engine",
|
|
"solitaire_server",
|
|
"solitaire_app",
|
|
"solitaire_assetgen",
|
|
"solitaire_wasm",
|
|
"solitaire_web",
|
|
]
|
|
resolver = "2"
|
|
|
|
[workspace.package]
|
|
edition = "2024"
|
|
version = "0.1.0"
|
|
license = "MIT"
|
|
rust-version = "1.95"
|
|
|
|
# Pedantic correctness lints applied across every member crate via
|
|
# `[lints] workspace = true`.
|
|
[workspace.lints.rust]
|
|
# Workspace-wide ban on `unsafe`. The sole exception is `solitaire_app`,
|
|
# which sets its own `deny`-level lints (see its Cargo.toml) because the
|
|
# Android cdylib entry point must reconstruct raw JNI handles. Every other
|
|
# crate reaches Android JNI through the safe `solitaire_data::android_jni`
|
|
# bridge and stays fully unsafe-free.
|
|
unsafe_code = "forbid"
|
|
single_use_lifetimes = "warn"
|
|
trivial_casts = "warn"
|
|
unused_lifetimes = "warn"
|
|
unused_qualifications = "warn"
|
|
variant_size_differences = "warn"
|
|
unexpected_cfgs = "warn"
|
|
|
|
[workspace.dependencies]
|
|
serde = { version = "1", features = ["derive"] }
|
|
serde_json = "1"
|
|
uuid = { version = "1", features = ["v4", "serde"] }
|
|
chrono = { version = "0.4", features = ["serde", "wasmbind"] }
|
|
thiserror = "2"
|
|
rand = "0.9"
|
|
async-trait = "0.1"
|
|
tokio = { version = "1", features = ["full"] }
|
|
dirs = "6"
|
|
keyring = "4"
|
|
keyring-core = "1"
|
|
reqwest = { version = "0.13", features = ["json", "rustls", "rustls-native-certs"], default-features = false }
|
|
arboard = { version = "3", default-features = false }
|
|
jni = { version = "0.21", default-features = false }
|
|
|
|
solitaire_core = { path = "solitaire_core" }
|
|
solitaire_sync = { path = "solitaire_sync" }
|
|
solitaire_data = { path = "solitaire_data" }
|
|
solitaire_engine = { path = "solitaire_engine" }
|
|
klondike = { version = "0.4.0", registry = "Quaternions", features = ["serde"] }
|
|
card_game = { version = "0.4.1", registry = "Quaternions", features = ["serde"] }
|
|
|
|
# Bevy with `default-features = false` to avoid the unused
|
|
# `bevy_audio → rodio + symphonia + cpal 0.15 + alsa 0.9` chain.
|
|
# Audio is handled directly by `kira` in `audio_plugin.rs`, so the
|
|
# `bevy_audio` feature is intentionally omitted. The features below
|
|
# enumerate every leaf of the standard `2d` + `ui` meta-features that
|
|
# we actually use; new features should only be added with a
|
|
# corresponding use site.
|
|
bevy = { version = "0.18", default-features = false, features = [
|
|
# default_app
|
|
"async_executor",
|
|
"bevy_asset",
|
|
"bevy_input_focus",
|
|
"bevy_log",
|
|
"bevy_state",
|
|
"bevy_window",
|
|
"custom_cursor",
|
|
"reflect_auto_register",
|
|
# default_platform (desktop subset)
|
|
"std",
|
|
"bevy_winit",
|
|
"default_font",
|
|
"multi_threaded",
|
|
# winit prefers Wayland when WAYLAND_DISPLAY is set on the
|
|
# session and falls through to X11 otherwise. Without `wayland`,
|
|
# winit-on-Wayland-session falls back to XWayland which renders
|
|
# the game in an X11 frame inside the Wayland compositor.
|
|
"wayland",
|
|
"x11",
|
|
# Android: NativeActivity glue. The feature is target-gated inside
|
|
# bevy_internal — desktop builds compile it out, so leaving it on
|
|
# the always-on list is harmless on Linux/macOS/Windows. Pairs with
|
|
# cargo-apk's NativeActivity wrapper (cargo-apk 0.10+ uses this by
|
|
# default). Switch to `android-game-activity` later if we want
|
|
# AndroidX GameActivity for Google Play Games integration.
|
|
"android-native-activity",
|
|
# common_api
|
|
"bevy_color",
|
|
"bevy_image",
|
|
"bevy_mesh",
|
|
"bevy_shader",
|
|
"bevy_text",
|
|
"png",
|
|
# 2d rendering
|
|
"bevy_camera",
|
|
"bevy_render",
|
|
"bevy_core_pipeline",
|
|
"bevy_sprite",
|
|
"bevy_sprite_render",
|
|
# UI rendering
|
|
"bevy_ui",
|
|
"bevy_ui_render",
|
|
] }
|
|
kira = "0.12"
|
|
|
|
# SVG rasterisation pipeline for the runtime card-theme system.
|
|
# usvg parses + simplifies; resvg renders to a tiny-skia Pixmap;
|
|
# tiny-skia provides the CPU rasteriser. All three are maintained
|
|
# together by the resvg-rs project and version in lockstep.
|
|
usvg = "0.47"
|
|
resvg = "0.47"
|
|
tiny-skia = "0.12"
|
|
|
|
# Theme manifest format. RON keeps the file human-editable while
|
|
# preserving Rust-style structures the importer can validate.
|
|
ron = "0.12"
|
|
|
|
# Importer-only: reads user-supplied theme zip archives, validates
|
|
# their contents, and unpacks them into the user themes directory.
|
|
# Default features are disabled to keep the dependency footprint small;
|
|
# only `deflate` is needed because the importer rejects other
|
|
# compression methods anyway (see Phase 7 spec).
|
|
zip = { version = "8.6", default-features = false, features = ["deflate"] }
|
|
# Image decoding for avatar bytes received from the server.
|
|
# Features mirror what Bevy already enables via bevy_image.
|
|
image = { version = "0.25", default-features = false, features = ["png", "jpeg", "webp", "gif"] }
|
|
|
|
# Importer-only test dependency: tests build zip archives in a
|
|
# scratch directory so they don't pollute the real user themes path
|
|
# on the developer's machine.
|
|
tempfile = "3.27"
|
|
|
|
axum = "0.8"
|
|
sqlx = { version = "0.8", features = ["runtime-tokio-rustls", "sqlite", "macros", "migrate"] }
|
|
jsonwebtoken = { version = "10", default-features = false, features = ["rust_crypto"] }
|
|
bcrypt = "0.19"
|
|
tower_governor = "0.8"
|
|
tracing = "0.1"
|
|
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
|
dotenvy = "0.15"
|
|
|
|
[profile.dev]
|
|
opt-level = 1
|
|
|
|
[profile.dev.package."*"]
|
|
opt-level = 3
|
|
|
|
[profile.release]
|
|
opt-level = 3
|
|
lto = "thin"
|
|
|
|
# Size-focused profile for the browser canvas build (solitaire_web →
|
|
# canvas_bg.wasm). Download size is the constraint on the web, not peak
|
|
# throughput: fat LTO + one codegen unit + opt-level "s" cut the Bevy wasm
|
|
# bundle substantially versus plain release. This is rustc-side sizing only —
|
|
# the binaryen pass in build_wasm.sh stays at wasm-opt -O2 because -Oz has
|
|
# miscompiled Bevy's render pipeline before (grey screen on first load).
|
|
[profile.wasm-release]
|
|
inherits = "release"
|
|
opt-level = "s"
|
|
lto = "fat"
|
|
codegen-units = 1
|
|
# No `strip`: on wasm it also removes the target_features custom section,
|
|
# which makes wasm-opt reject the module ("all used features should be
|
|
# allowed" on trunc_sat). wasm-opt drops the name section in its output
|
|
# anyway, so strip buys nothing here.
|