Skip to content

fix(build): embed Windows manifest via target_sources, not /MANIFEST:EMBED#3947

Merged
jensenpat merged 2 commits into
aethersdr:mainfrom
gauthig:fix/3835-msvc-manifest-embed
Jul 1, 2026
Merged

fix(build): embed Windows manifest via target_sources, not /MANIFEST:EMBED#3947
jensenpat merged 2 commits into
aethersdr:mainfrom
gauthig:fix/3835-msvc-manifest-embed

Conversation

@gauthig

@gauthig gauthig commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Summary

  • CMake's Ninja vs_link_exe wrapper already owns MSVC manifest embedding (link.exe emits a side-car .manifest, then mt.exe merges/embeds it). Passing /MANIFEST:EMBED + /MANIFESTINPUT directly (added in fix(cmake): pair /MANIFESTINPUT with required /MANIFEST:EMBED #3237 to fix LNK1220) makes link.exe embed inline instead, so it emits no side-car manifest — CMake's mt.exe step then runs with an empty --manifests list and fails with c10100a7 on cmake 4.x.
  • Fix: list the .manifest file as a target source so CMake feeds it to its own vs_link_exe/mt.exe embed step natively, per the root-cause analysis in the aethersdr-agent triage comment on the issue.
  • Also adds a Windows 11 build section to README.md's "Building from Source" (the secondary ask in the issue), covering vcvars64.batscripts/setup/setup-fftw.ps1 → configure/build.

Test plan

  • I (the original reporter) reproduced the c10100a7 link failure on cmake 4.3.2 / MSVC 14.44 / VS 2022 BuildTools, applied this fix locally, and confirmed the link succeeds (per Principle XI — reporter-confirmed fix).
  • Inspected the generated build.ninja: LINK_FLAGS no longer carries /MANIFEST:EMBED//MANIFESTINPUT, and MANIFESTS now correctly lists packaging/windows/AetherSDR.exe.manifest for the mt.exe step.
  • CI (build, check-paths, check-windows) green on this PR.

Fixes #3835

…EMBED — Principle XI.

CMake's Ninja vs_link_exe wrapper already owns MSVC manifest embedding:
link.exe emits a side-car .manifest, then mt.exe merges/embeds it. Passing
/MANIFEST:EMBED + /MANIFESTINPUT directly (added in aethersdr#3237 to fix LNK1220)
tells link.exe to embed inline instead, so it emits no side-car manifest —
CMake's mt.exe step then runs with an empty --manifests list and fails with
c10100a7 on cmake 4.x.

Fix: list the .manifest file as a target source so CMake feeds it to its
own vs_link_exe/mt.exe embed step natively. No linker flags needed.
Verified by inspecting the generated build.ninja: LINK_FLAGS no longer
carries the conflicting flags, and MANIFESTS now correctly lists the
.manifest file for the mt.exe step.

Also adds a Windows 11 build section to README.md's "Building from
Source", covering vcvars64.bat -> setup-fftw.ps1 -> cmake configure/build,
per the secondary ask in the issue.

Fixes aethersdr#3835
@gauthig gauthig requested a review from a team as a code owner July 1, 2026 15:42

@aethersdr-agent aethersdr-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the careful fix and the clear root-cause writeup, @gauthig — this correctly untangles the /MANIFEST:EMBED vs. CMake's vs_link_exe/mt.exe machinery.

The approach is sound. Listing the .manifest as a target source is the CMake-native way to embed it: CMake feeds it to its own mt.exe step, so the two no longer fight over who owns embedding. I confirmed there's no double-embed hazard — packaging/windows/AetherSDR.rc only declares IDI_ICON1 ICON, not an RT_MANIFEST resource, so nothing else is trying to embed a manifest. The change is correctly scoped inside the if(MSVC) block and uses CMAKE_SOURCE_DIR consistently with the WIN_RC handling just above it. Both files are in scope for the issue.

One minor, non-blocking note on the README: the new Windows 11 section lists Ninja as a prerequisite but the configure command (cmake -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo) doesn't pass -G Ninja. With VS Build Tools installed, CMake's default generator is the Visual Studio generator, not Ninja — so a reader following the steps verbatim won't actually exercise the Ninja path this fix was reproduced against. The fix works under both generators, so this is purely a docs-consistency nit; consider adding -G Ninja (or dropping Ninja from the prereq list) to match intent.

Nice work — the reporter-confirmed link success plus the build.ninja inspection is exactly the kind of evidence that makes a build fix easy to trust.


🤖 aethersdr-agent · cost: $1.5081 · model: claude-opus-4-8

The Windows section as submitted wouldn't produce a working build if followed
verbatim:

- Missing `-G Ninja`: on Windows CMake defaults to the multi-config Visual
  Studio generator, which ignores -DCMAKE_BUILD_TYPE=RelWithDebInfo (and
  `cmake --build` without --config builds Debug) — and takes a different
  manifest-embed path than the Ninja vs_link_exe one this PR fixes.
- No Qt discovery hint: find_package(Qt6 6.2 REQUIRED) can't locate Qt on
  Windows without CMAKE_PREFIX_PATH / Qt6_DIR, so a bare `cmake -B build`
  aborts at configure.
- vcvars64.bat was hardcoded to the Build Tools edition; Community/Pro/
  Enterprise live under different paths.
- Prereq said Qt 6.8+ while the source-build floor is 6.7.

Add -G Ninja + a CMAKE_PREFIX_PATH example, note the edition-dependent vcvars
path, and align the Qt floor to 6.7 (6.8.3 shipped). Keeps the useful bones
of the original (vcvars -> setup-fftw.ps1 -> configure/build).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@jensenpat jensenpat left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving — the fix is correct and it's the right long-term idiom. Verified against CMake's own source (Source/cmcmd.cxx, cmVSLink) plus the repo history; two findings worth putting on the record:

One correction to the root-cause attribution: it's the incremental link path, not cmake 4.x

vs_link_exe parses only /INCREMENTAL[:YES|NO] and /MANIFEST:NO from the link command — it does not recognize /MANIFEST:EMBED. What actually forks the behavior is the link mode:

  • Incremental (Debug / RelWithDebInfo, whose default MSVC linker flags are /debug /INCREMENTAL): vs_link_exe runs its rc/link/mt embed dance and expects link.exe to emit a side-car manifest. The hand-passed /MANIFEST:EMBED makes link.exe embed inline and emit no side-car, so mt.exe gets zero /manifest inputs plus /notify_updatec10100a7. This behaves identically on cmake 3.x — the code path is years old.
  • Non-incremental (Release, /INCREMENTAL:NO): vs_link_exe delegates embedding to link.exe entirely and runs no mt step, so the hand-passed flags happen to work.

That's why CI never caught it despite already running CMake 4.3.4 on the windows-2025-vs2026 image: check-windows builds Release. You were simply the first person to do an incremental MSVC build since #3237 merged. (Bonus: pre-#3237, incremental builds on lenient toolsets likely shipped with no DPI manifest at all, since the lone /MANIFESTINPUT was ignored — this PR closes that hole too.)

The squash commit message will carry the corrected attribution so future archaeology on these six lines doesn't chase cmake versions.

This PR became release-blocking this morning

#3934 (merged Jul 1) switched windows-installer.yml — the Microsoft Store / release pipeline — from Release to RelWithDebInfo for PDB/.appxsym symbol packaging. That moves the release link onto the incremental path, so without this fix the next v* tag fails at link with exactly this c10100a7. No run of that workflow has executed since the switch; this PR needs to land first.

Verification story

  • Reporter-confirmed on the incremental path (RelWithDebInfo, cmake 4.3.2, MSVC 14.44) ✔
  • check-windows green on the non-incremental path (Release, cmake 4.3.4, MSVC 19.51) ✔ — and on that path vs_link_exe itself appends /MANIFEST:EMBED,ID=1 + /MANIFESTINPUT:<manifest>, i.e. exactly what #3237 hand-coded, now generated coherently. Release artifacts should carry a byte-equivalent embedded manifest.
  • No double-embed hazard: AetherSDR.rc declares only the icon, no RT_MANIFEST.
  • Post-merge I'll dispatch windows-installer.yml on main to validate the full RelWithDebInfo Store path — the check-dpi-awareness.ps1 step hard-gates the embed, and it exercises #3934's -RequirePdb plumbing in the same run.

Follow-up (not this PR): consider aligning check-windows to RelWithDebInfo so PR CI exercises the same link path the release pipeline ships.

Thanks @gauthig for the careful repro and bisect — exemplary first contribution.

@jensenpat jensenpat merged commit f609bfa into aethersdr:main Jul 1, 2026
6 checks passed
ten9876 added a commit that referenced this pull request Jul 2, 2026
#3961)

## Release documentation prep for **v26.7.1** (2026-07-02)

29 commits since v26.6.5. Docs-only + version bump — no code behavior
change.

### Version bump 26.6.5 → 26.7.1
The three canonical locations (per `AGENTS.md`):
- `CMakeLists.txt:2` — `project(AetherSDR VERSION 26.7.1)` →
`AETHERSDR_VERSION` (the app's version string)
- `README.md` — Current version line
- `AGENTS.md` — Current version line

### `CHANGELOG.md`
Promoted `[Unreleased]` → **`## [v26.7.1] — 2026-07-02`** in house style
(v-prefix, em-dash, "N commits since…" opener + headline), authored from
all merged PRs and categorized:
- **Added:** 3D stacked-trace spectrum (#3899), 3D dBm scale (#3937),
in-process NVIDIA BNR + AFX download-on-demand (#3902), TX meter
mouse-over readouts (#3936), SWR manual sweep range (#3885), CW sidetone
capture (#3895), KiwiSDR metadata scaffolding (#3898), bridge verbs
(#3920)
- **Changed:** BNR container/NIM backend removed, 60 fps + per-pixel GPU
FFT trace (#3958), FlexLib-sourced model capabilities (#3954/#2177), RX
speaker-latency cut (#3897), Display pane sections (#3935)
- **Fixed:** #3922, #3926, #3941, #3940, #3942, #3921, #3903, #3892,
#3924, #3891, #3890, #3900, #3947
- Fresh empty `[Unreleased]` restored above the release block.
Internal/CI/docs/self-fix PRs (#3931/#3916/#3934/#3929) omitted per
house style.

### `ROADMAP.md`
- Cycle header → "post-v26.7.1"
- NVIDIA BNR removed from **In flight** (shipped this cycle)
- Five v26.7.1 highlights prepended to **Recently shipped**

### `README.md`
- Highlights: GPU spectrum bullet now notes the **per-pixel FFT trace at
up to 60 fps** and the **3D stacked-trace** spectrum mode

### Reviewer notes
- Touches protected paths (`*.md` + `AGENTS.md` Tier-1 +
`CMakeLists.txt`) — needs `@aethersdr/infrastructure` sign-off.
- Tagging `v26.7.1` and cutting the release build are **not** part of
this PR (docs prep only).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Windows build fails with cmake 4.x: /MANIFEST:EMBED breaks vs_link_exe mt.exe step

3 participants