Skip to content

Add Windows Native AOT release artifacts (win-x64, win-arm64) #177

Description

@FrankRay78

Summary

Extend the Native AOT release pipeline to Windows: add win-x64 and win-arm64 AOT artifacts alongside the Linux AOT artifacts delivered in #176, applying the same naming, validation, and clean-trim policy. This brings desktop Windows users to parity with Linux/IoT and rounds out the AOT story for the two most common platform families. macOS AOT remains a separate, later initiative.

Motivation

#176 delivers Linux AOT (linux-x64, linux-arm64) plus the cross-cutting groundwork — IsAotCompatible=true on both projects, clean-trim warning policy, XmlExtensions.cs rewrite, Humanizer resolution, and the matrix-extension pattern.

Once that lands, the work to ship Windows AOT is largely plumbing, not code:

  • Native AOT cannot be cross-compiled — win-x64 requires windows-latest, win-arm64 requires windows-11-arm (GA since April 2025, free for public repos). Linux runners cannot produce Windows AOT binaries.
  • Toolchain: windows-latest ships with MSVC v143 + the Windows 11 SDK pre-installed; no setup-msbuild or setup-vs step required.
  • All trim/AOT code fixes from Add Linux Native AOT release artifacts (linux-x64, linux-arm64) for IoT deployments #176 are platform-agnostic and apply unchanged.

The platform-specific surface that genuinely differs is small: archive format (.zip, already handled by the existing branch on win-*), .exe extension, .pdb companion files, and the SmartScreen/AV implications of unsigned native binaries.

Proposal

1. Workflow changes — release-binaries.yml

Add two further matrix.include: entries to the same matrix #176 extends:

  • win-x64-aotruns-on: windows-latest. AOT publish, PublishSingleFile=false, archive as .zip.
  • win-arm64-aotruns-on: windows-11-arm. Same flags, same archive format.

Both entries inherit the deployment: aot and publish_single_file: false shape from #176 unchanged. The publish step's existing if [[ "${{ matrix.runtime }}" == win-* ]] archive branch already produces .zip for Windows RIDs — no change needed there.

2. Naming convention

Inherits the convention locked in #176:

RID Filename
win-x64 netpace-{tag}-win-x64-aot.zip
win-arm64 netpace-{tag}-win-arm64-aot.zip

Total release-asset count rises from 14 (post-#176) to 16.

3. .pdb symbol files

Native AOT on Windows produces a .pdb next to the .exe. Two options:

  • Exclude .pdb from the release archive — smaller download, end users don't typically need symbols, matches the bare-binary posture of the Linux AOT archives.
  • Include .pdb — useful for end-user crash debugging on devices without a build environment.

Default (this issue): exclude. Symbol publishing (NuGet .snupkg or a separate symbol artifact) is its own initiative and out of scope here.

4. Smoke test

On each Windows runner, post-publish:

./NetPace.exe --version
./NetPace.exe --help

5. Globalization

Inherit whatever globalization mode #176 locks (recommendation in that issue is InvariantGlobalization=true for AOT publish only). No Windows-specific divergence — the AOT publish flags should be identical to Linux except for the runtime and runner.

6. Documentation

Out of scope

  • macOS AOT (osx-x64, osx-arm64) — separate follow-up issue. Different runner family (macos-13, macos-14), separate notarization considerations.
  • Code signing / Authenticode — unsigned native exes will trigger SmartScreen warnings on first download. Existing -standalone Windows builds aren't signed either; signing is a separate, larger initiative covering all release variants.
  • AntiVirus heuristic mitigation — submitting binaries to Microsoft Defender / other AV vendors for whitelisting belongs with the signing initiative, not here.
  • .pdb symbol distribution — see §3; out of scope until a symbol-publishing initiative exists.
  • win-arm64 cross-compile from windows-latest — supported by the SDK but loses the same-job smoke test; rejected in favour of the native ARM runner.
  • Renaming existing -standalone / -net8 suffixes for Windows — same compatibility argument as Add Linux Native AOT release artifacts (linux-x64, linux-arm64) for IoT deployments #176; preserved indefinitely here.
  • Tag format change — same as Add Linux Native AOT release artifacts (linux-x64, linux-arm64) for IoT deployments #176, unrelated churn.
  • Migrating away from self-contained for Windows — kept indefinitely; future deprecation may revisit.

Acceptance criteria

  • Pushing a tag (after this issue ships) produces 16 release archives: the 14 from post-Add Linux Native AOT release artifacts (linux-x64, linux-arm64) for IoT deployments #176 unchanged, plus netpace-{tag}-win-x64-aot.zip and netpace-{tag}-win-arm64-aot.zip.
  • Each Windows AOT archive contains a single native netpace.exe (no .dll, no .deps.json, no .runtimeconfig.json, no .pdb).
  • Each Windows AOT archive is materially smaller than its -standalone counterpart (aot.zip < standalone.zip size assertion in the validation step, mirroring Add Linux Native AOT release artifacts (linux-x64, linux-arm64) for IoT deployments #176 / Q6).
  • ./netpace.exe --version, ./netpace.exe --help, and ./netpace.exe servers exit 0 on their respective native runners (windows-latest / windows-11-arm).
  • dotnet publish src/NetPace.Console -c Release -r win-x64 -p:PublishAot=true completes with the trim/AOT warning codes (IL2026, IL2090, IL3050, IL3056) treated as errors and exits 0.
  • Same publish for -r win-arm64 exits 0.
  • windows-11-arm runner is confirmed available for FrankRay78/NetPace (public repo, free tier) — captured as a workflow comment so future contributors don't doubt it.
  • README.md, docs/RELEASING.md, CHANGELOG.md, and USER_GUIDE.md reflect the two new artifacts.
  • No regression in existing 14 archives; existing self-contained / framework-dependent / Linux-AOT artefacts remain byte-identical to a comparable post-Add Linux Native AOT release artifacts (linux-x64, linux-arm64) for IoT deployments #176 release.

Open questions / future work

  • SmartScreen / AV false positives — track via real release feedback once Windows AOT ships; remediation belongs with the code-signing initiative.
  • Symbol publishing — eventual .snupkg or separate symbol-artifact channel for AOT crash debugging.
  • macOS AOT follow-up — third and final platform issue in this series.
  • Drop self-contained for Windows — once Windows AOT is proven across two or three releases without regression, consider deprecating the win-*-standalone archives in line with the eventual Linux deprecation.
  • win-arm64 cross-compile fallback — if windows-11-arm runner availability becomes flaky or gets paywalled, document the cross-compile path as a contingency.

Confirmed decisions

  • Smoke-test depth: Windows AOT smoke runs --version and --help only — no servers, no retry/timeout wrapper. Matches the two-command contract shipped by Add Linux Native AOT release artifacts (linux-x64, linux-arm64) for IoT deployments #176; broader smoke enhancements belong in a separate cross-cutting issue.
  • CHANGELOG.md: Dropped from documentation scope and AC Upload speed test #8 — the project has no CHANGELOG.md; per-release notes are GitHub-auto-generated per docs/RELEASING.md#L67-L69.
  • Smoke-test shell: Use shell: bash on the smoke step (Git Bash ships with both Windows runners) with an if-branch for unzip vs tar -xzf. Binary is NetPace (case-sensitive) on all platforms — NetPace.exe on Windows.
  • Windows AOT runners: windows-latest (x64) for win-x64-aot, windows-11-arm (ARM64) for win-arm64-aot. Block on failure (no continue-on-error); cross-compile rejected to preserve the native smoke test, mirroring the Linux AOT runner choice in docs/RELEASING.md#L33-L35.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    embedded IOTFeatures, issues and bugs related to NetPace targeting the embedded IOT market.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions