From 4253b9335de78bb06b0be6eb24bb261382a4346f Mon Sep 17 00:00:00 2001 From: meh Date: Mon, 7 Sep 2026 11:01:48 +0700 Subject: [PATCH] build!: gate the GPU renderer behind the runtime feature `anyrender_vello` was a hard dependency. `mod runtime` is the only thing that names `VelloWindowRenderer`, and that module is already behind the `runtime` feature, so the renderer was reachable by exactly the consumers who could never use it: a headless build linked wgpu, wgpu-hal, wgpu-core, naga and two versions of vello to serve a socket that reads a semantic tree. `qa-inspect-host` did everything a consumer can do -- `default-features = false`, `features = ["agent-control"]` -- and still got a GPU stack, because no feature governed the dependency. Same shape as `system-fonts` sitting in `blitz-dom`'s default list. The intent was written down, in this feature's own comment: "a headless consumer gets the inspection and activation surface with no Tauri in its graph ... for a binary that never opens a window". Nothing enforced it, so it was not true. Optional, and added to `runtime`. No code changes: every use site was already gated. Measured on x86_64-unknown-linux-gnu, matching wgpu, naga and the GPU vello: --no-default-features --features agent-control 0 --features runtime 58 The graph check is why this survived. It looked for `tauri v|gtk|glib|webkit| soup` and passed a build carrying wgpu, so it now looks for renderers as well, and pins the target rather than inheriting the runner's. `ps-anyrender-vello-cpu` is deliberately still allowed. It arrives through `blitz-script` behind `debug-control`, which serves the `screenshot` endpoint, and rasterising is what that endpoint is for. Whether a pure inspection host should offer screenshots at all is a separate question and not one a grep should decide. Breaking for anyone depending on this crate with `default-features = false` and relying on the renderer being present regardless; they enable `runtime`. Headless clippy clean, `--all-features` checks. Releases 0.3.5. --- .github/workflows/ci.yml | 26 +++++++++++++++++++++++--- Cargo.toml | 2 +- crates/tauri-runtime-blitz/Cargo.toml | 19 +++++++++++++++++-- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c9364bc..7fd3094 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -92,12 +92,32 @@ jobs: run: | cargo clippy -p tauri-runtime-blitz \ --no-default-features --features agent-control -- -D warnings - - name: No window stack in the graph + # Renderers as well as window stacks. This checked for `tauri`, GTK and + # WebKit and passed while the headless build linked wgpu, two versions of + # vello, naga and wgpu-hal: `anyrender_vello` was a hard dependency, so + # the only consumers who could reach it were the ones that could never + # use it. `mod runtime` is the sole user and was already behind the + # `runtime` feature, so nothing but the manifest had to change. + # + # `ps-anyrender-vello-cpu` is deliberately not banned. It arrives through + # `blitz-script` behind `debug-control`, which is what serves the + # `screenshot` endpoint, and rasterising is what that endpoint is for. + # Whether a pure inspection host should offer it at all is a separate + # question; this check is about not linking a GPU stack by accident. + # + # The target is pinned rather than inherited, so the answer does not + # depend on which runner this lands on. + - name: No window stack or GPU renderer in the graph run: | found=$(cargo tree -p tauri-runtime-blitz --edges normal \ + --target x86_64-unknown-linux-gnu \ --no-default-features --features agent-control \ - | grep -ciE 'tauri v|gtk|glib|webkit|soup' || true) + | grep -ciE 'tauri v|gtk|glib|webkit|soup|wgpu|naga|ps-vello v|anyrender-vello v' || true) if [ "$found" != "0" ]; then - echo "the headless build pulled in $found window-stack crates" >&2 + echo "the headless build pulled in $found window-stack or renderer crates" >&2 + cargo tree -p tauri-runtime-blitz --edges normal \ + --target x86_64-unknown-linux-gnu \ + --no-default-features --features agent-control \ + | grep -iE 'tauri v|gtk|glib|webkit|soup|wgpu|naga|ps-vello v|anyrender-vello v' >&2 || true exit 1 fi diff --git a/Cargo.toml b/Cargo.toml index 532edbb..d3403ee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ resolver = "3" members = ["crates/tauri-runtime-blitz"] [workspace.package] -version = "0.3.4" +version = "0.3.5" edition = "2024" license = "MIT OR Apache-2.0" publish = true diff --git a/crates/tauri-runtime-blitz/Cargo.toml b/crates/tauri-runtime-blitz/Cargo.toml index 2adb648..8b22122 100644 --- a/crates/tauri-runtime-blitz/Cargo.toml +++ b/crates/tauri-runtime-blitz/Cargo.toml @@ -9,7 +9,7 @@ homepage.workspace = true repository.workspace = true [dependencies] -anyrender_vello = { package = "ps-anyrender-vello", version = "^0.14.0" } +anyrender_vello = { package = "ps-anyrender-vello", version = "^0.14.0", optional = true } anyrender_vello_hybrid = { package = "ps-anyrender-vello-hybrid", version = "^0.10.0", optional = true } style = { version = "0.20.0", package = "stylo" } # Plain defaults, which as of ps-blitz 0.4.4 no longer include `system-fonts`. @@ -65,7 +65,22 @@ default = ["agent-control", "runtime"] # Off, a headless consumer gets the inspection and activation surface with no # Tauri in its graph, which on Linux is the difference between a build and GTK # development headers for a binary that never opens a window. -runtime = ["dep:tauri", "dep:tauri-runtime", "dep:tauri-utils"] +# +# `anyrender_vello` belongs here too, and did not. `mod runtime` is the only +# thing that names `VelloWindowRenderer`, and that module is already behind this +# feature, so the renderer was reachable by exactly the consumers that could +# never use it. A headless build linked wgpu, two versions of vello, naga and +# wgpu-hal to serve a socket that reads a semantic tree. +# +# Same shape as `system-fonts` sitting in `blitz-dom`'s defaults: the intent was +# written down in this comment, and nothing enforced it. The graph check below +# now looks for renderers as well as window stacks. +runtime = [ + "dep:tauri", + "dep:tauri-runtime", + "dep:tauri-utils", + "dep:anyrender_vello", +] agent-control = ["blitz-shell/debug-control", "dep:blitz-control-protocol", "dep:blitz-dom", "dep:blitz-traits", "dep:endpoint-libs", "dep:keyboard-types", "dep:serde", "dep:serde_json", "dep:tokio"] debug-control = ["blitz-script/debug-control", "blitz-shell/debug-control"] diagnostics = [