build(windows): embed the icon, VERSIONINFO and a longPathAware manifest

winresource, not winres: winres has been unmaintained since 2021 and this
is its maintained fork. Gated to cfg(windows) as a target build-dependency,
so no other platform resolves it at all.

The manifest declares longPathAware and NOTHING else. Qt 6 sets
PerMonitorV2 itself at startup and a manifest DPI declaration is immutable,
so the two together either log a permanent COM error 0x5 or degrade
scaling - Qt owns DPI awareness.

The .ico carries 256/128/64/48/32. The four small entries are BMP and only
256 is PNG: measured on this box, System.Drawing.Icon (GDI+) throws
ArgumentOutOfRangeException in ToBitmap() on a PNG-payload entry, while WIC
decodes it. 256 has to be PNG because the directory encodes its size as 0.
Pixels verified against the source PNG at four points including an
asymmetric one, which is what proves the BGRA order and the bottom-up flip.

cc
This commit is contained in:
vicrodh committed 2026-08-27 03:46:29 -06:00
1 parent 77f7840ae7
commit 7135c841cb
5 files changed
+79 -1

No files matched your search

+27 -1
View File
@@ -4578,6 +4578,7 @@ dependencies = [
"tokio",
"urlencoding",
"uuid 1.22.0",
"winresource",
"zbus 5.15.0",
]
@@ -4722,7 +4723,7 @@ dependencies = [
"tempfile",
"tiny_http",
"tokio",
"toml",
"toml 0.9.12+spec-1.1.0",
"urlencoding",
"uuid 1.22.0",
"windows-sys 0.61.2",
@@ -6347,6 +6348,21 @@ dependencies = [
"winnow 0.7.15",
]
[[package]]
name = "toml"
version = "1.0.6+spec-1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "399b1124a3c9e16766831c6bba21e50192572cdd98706ea114f9502509686ffc"
dependencies = [
"indexmap",
"serde_core",
"serde_spanned",
"toml_datetime 1.0.0+spec-1.1.0",
"toml_parser",
"toml_writer",
"winnow 0.7.15",
]
[[package]]
name = "toml_datetime"
version = "0.7.5+spec-1.1.0"
@@ -7599,6 +7615,16 @@ dependencies = [
"memchr",
]
[[package]]
name = "winresource"
version = "0.1.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0986a8b1d586b7d3e4fe3d9ea39fb451ae22869dcea4aa109d287a374d866087"
dependencies = [
"toml 1.0.6+spec-1.1.0",
"version_check",
]
[[package]]
name = "wit-bindgen"
version = "0.51.0"
+6
View File
@@ -165,6 +165,12 @@ cxx-qt-build = "0.7"
qt-build-utils = "0.7"
cc = "1"
[target.'cfg(windows)'.build-dependencies]
# Icon + VERSIONINFO + the longPathAware manifest, embedded as PE resources.
# winresource, not winres: winres has been unmaintained since 2021 and this
# is its maintained fork.
winresource = "0.1"
# macOS only: the Dock-icon activation policy behind the "Hide Dock icon when
# closed to menu bar" setting (Spotify behaviour — close puts the app in the
# menu bar and drops the Dock icon; minimize still goes to the Dock).
+27
View File
@@ -904,4 +904,31 @@ fn main() {
})
.cc_builder(apply_msvc_qt_flags)
.build();
embed_windows_resources();
}
/// Icon, VERSIONINFO and the manifest, as PE resources.
///
/// The manifest declares `longPathAware` and NOTHING ELSE. Never add
/// `dpiAware`/`dpiAwareness`: Qt 6 sets PerMonitorV2 itself at startup, a
/// manifest declaration is immutable, and the two together either log a
/// permanent COM error 0x5 or silently degrade scaling.
///
/// `build.rs` runs with `crates/qbz-qt` as its working directory, hence
/// `../../packaging`.
#[cfg(windows)]
fn embed_windows_resources() {
println!("cargo:rerun-if-changed=../../packaging/icons/icon.ico");
println!("cargo:rerun-if-changed=../../packaging/windows/qbz.exe.manifest");
let mut res = winresource::WindowsResource::new();
res.set_icon("../../packaging/icons/icon.ico");
res.set_manifest_file("../../packaging/windows/qbz.exe.manifest");
res.set("ProductName", "QBZ");
res.set("FileDescription", "QBZ — Qobuz hi-res player");
res.set("LegalCopyright", "MIT — github.com/vicrodh/qbz");
res.compile().expect("windows resource");
}
#[cfg(not(windows))]
fn embed_windows_resources() {}