From 084dfb1bdb13c5118182fe34cf8167c05cb7fbc9 Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Tue, 16 Jun 2026 04:10:01 +0300 Subject: [PATCH] fix(windows): embed the app icon into the .exe The Windows executable carried no icon, so Explorer, the taskbar, the Start-menu tile and file-association entries showed a generic icon. Embed AppIcon.ico via winresource in build.rs, and generate the .ico from the logo before the build (it was produced after the build, too late to embed). Local and non-Windows builds skip the step when the .ico is absent. Fixes #107. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/release.yml | 23 ++++++++++--------- Cargo.lock | 43 ++++++++++++++++++++++++++++++++++- Cargo.toml | 5 ++++ build.rs | 16 +++++++++++++ 4 files changed, 75 insertions(+), 12 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6265c7fb8..34a36c5b0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -75,6 +75,18 @@ jobs: - name: Install Rust uses: dtolnay/rust-toolchain@stable + - name: Convert SVG icon to ICO + shell: pwsh + run: | + # ImageMagick is pre-installed on windows-latest. The + # auto-resize generates every size Explorer / Add-Remove + # Programs / the Start Menu shortcut may request from a + # single source SVG. Must run BEFORE the build so build.rs + # can embed the icon into the .exe (issue #107). + magick assets/logo.svg ` + -define icon:auto-resize=16,24,32,48,64,128,256 ` + packaging/windows/AppIcon.ico + - name: Build run: cargo build --release @@ -96,17 +108,6 @@ jobs: timestamp-rfc3161: http://timestamp.acs.microsoft.com timestamp-digest: SHA256 - - name: Convert SVG icon to ICO - shell: pwsh - run: | - # ImageMagick is pre-installed on windows-latest. The - # auto-resize generates every size Explorer / Add-Remove - # Programs / the Start Menu shortcut may request from a - # single source SVG. - magick assets/logo.svg ` - -define icon:auto-resize=16,24,32,48,64,128,256 ` - packaging/windows/AppIcon.ico - - name: Build MSI installer shell: pwsh run: | diff --git a/Cargo.lock b/Cargo.lock index 86132e6fd..81ee7aaf8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -36,6 +36,7 @@ dependencies = [ "truck-shapeops", "ureq", "windows-sys 0.61.2", + "winresource", ] [[package]] @@ -3137,7 +3138,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b577e2d69827c4740cba2b52efaad1c4cc7c73042860b199710b3575c68438d" dependencies = [ "bytecount", - "memchr 1.0.2", + "memchr 2.8.1", "nom 8.0.0", ] @@ -4829,6 +4830,15 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "serde_spanned" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" +dependencies = [ + "serde_core", +] + [[package]] name = "servo_arc" version = "0.1.1" @@ -5446,6 +5456,21 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "toml" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "toml_writer", + "winnow 1.0.3", +] + [[package]] name = "toml_datetime" version = "0.6.11" @@ -5493,6 +5518,12 @@ dependencies = [ "winnow 1.0.3", ] +[[package]] +name = "toml_writer" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db" + [[package]] name = "tracing" version = "0.1.44" @@ -6776,6 +6807,16 @@ dependencies = [ "memchr 2.8.1", ] +[[package]] +name = "winresource" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0986a8b1d586b7d3e4fe3d9ea39fb451ae22869dcea4aa109d287a374d866087" +dependencies = [ + "toml", + "version_check", +] + [[package]] name = "wit-bindgen" version = "0.51.0" diff --git a/Cargo.toml b/Cargo.toml index 456cc1a27..ce154a069 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,11 @@ build = "build.rs" [workspace] members = ["crates/ocs_plugin_api"] +# Embed the application icon into the Windows .exe so Explorer, the taskbar, +# the Start-menu tile and file-association entries show it (issue #107). +[target.'cfg(windows)'.build-dependencies] +winresource = "0.1" + [dependencies] # Stable, dependency-free add-on contract (manifest + ribbon/CadModule types). # Plugin authors target this crate's semver, not OpenCADStudio internals. diff --git a/build.rs b/build.rs index baa65b3c4..582907c38 100644 --- a/build.rs +++ b/build.rs @@ -26,6 +26,22 @@ use std::path::Path; const PRIORITY: &[&str] = &["home", "model", "insert", "annotate", "view", "manage"]; fn main() { + // Windows: embed AppIcon.ico into the .exe so the executable carries its + // own icon (Explorer, taskbar, Start-menu tile, file associations). The + // .ico is produced from assets/logo.svg by the release workflow before the + // build; when it is absent (local/dev builds) this is skipped. See #107. + #[cfg(windows)] + { + println!("cargo:rerun-if-changed=packaging/windows/AppIcon.ico"); + if Path::new("packaging/windows/AppIcon.ico").exists() { + let mut res = winresource::WindowsResource::new(); + res.set_icon("packaging/windows/AppIcon.ico"); + if let Err(e) = res.compile() { + println!("cargo:warning=failed to embed Windows icon: {e}"); + } + } + } + let mods_dir = Path::new("src/modules"); println!("cargo:rerun-if-changed=src/modules");