Skip to content

Move stub exe generation to MSBuild task with multi-stub support#2369

Open
Sergio0694 wants to merge 10 commits intostaging/3.0from
dev/stub-exe-task
Open

Move stub exe generation to MSBuild task with multi-stub support#2369
Sergio0694 wants to merge 10 commits intostaging/3.0from
dev/stub-exe-task

Conversation

@Sergio0694
Copy link
Copy Markdown
Member

Summary

Move the inline MSVC compilation logic from the _CsWinRTGenerateStubExe MSBuild target into a new GenerateCsWinRTStubExes MSBuild task, and add support for generating multiple stub .exe files with per-item customization.

Motivation

The existing _CsWinRTGenerateStubExe target can only generate a single stub .exe. Users who need multiple stubs (e.g. with different subsystems like Windows vs Console) are forced to copy the entire target and maintain it locally, which is error-prone and hard to keep in sync with CsWinRT updates. By moving the logic into a proper MSBuild task that accepts a collection of items, users can declaratively specify all the stubs they need.

Changes

  • src/WinRT.Generator.Tasks/GenerateCsWinRTStubExes.cs: new MSBuild task that generates one or more stub .exe files by invoking MSVC. Takes a StubExes item group as input, with optional per-item metadata:
    • OutputType: controls PE subsystem (WinExe for WINDOWS, else CONSOLE)
    • Win32Manifest: path to manifest to embed
    • AppContainer: whether to set /APPCONTAINER
    • Platform: target platform (arm64, x64, x86)
    • SourceText: inline C source code for the stub
    • SourceFile: path to a custom .c source file
  • nuget/Microsoft.Windows.CsWinRT.targets: refactored _CsWinRTGenerateStubExe target to use the new task. Adds UsingTask registration, documents the CsWinRTStubExe item schema with usage examples, and handles ResolvedFileToPublish for all generated stubs. When no CsWinRTStubExe items are defined, a default item named after the assembly is added, preserving backward compatibility.

Usage example

<ItemGroup>
  <CsWinRTStubExe Include="MyApp.Console" OutputType="Exe" />
  <CsWinRTStubExe Include="MyApp.Windowed" OutputType="WinExe" />
  <CsWinRTStubExe Include="MyApp.Custom" SourceFile="src\CustomStub.c" />
</ItemGroup>

Sergio0694 and others added 8 commits March 25, 2026 17:59
Add a new MSBuild task that generates one or more stub .exe files by
invoking MSVC (cl.exe). Each item in the StubExes input describes one
stub to generate, with optional metadata for OutputType, Win32Manifest,
AppContainer, and Platform. This replaces the inline MSBuild logic from
the _CsWinRTGenerateStubExe target with a proper C# task that supports
generating multiple stubs in a single build.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…task

Refactor the _CsWinRTGenerateStubExe target to delegate all MSVC
compilation logic to the new GenerateCsWinRTStubExes MSBuild task.

The target now supports multiple stub .exe generation through the
CsWinRTStubExe item group. Each item's identity is the output binary
name, with optional metadata for OutputType, Win32Manifest, AppContainer,
and Platform. When no items are defined, the target adds a default item
named after the assembly, preserving the original single-stub behavior.

The target still handles resolving all environment-specific paths (MSVC
toolchain, Windows SDK, cl.exe location) and passes them to the task,
which handles the actual compilation and output management.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add two new optional metadata properties to CsWinRTStubExe items:

- SourceText: inline C source code written directly to a .c file and
  compiled. Takes highest precedence.
- SourceFile: path to a custom .c source file, copied and compiled.
  Takes precedence over the default source template.

When neither is specified, the default CsWinRT source template
(StubExe.c from the NuGet package) is used, preserving backward
compatibility. The SourceFilePath task parameter is no longer required,
allowing all items to provide their own source without a default.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Rename the task parameter from SourceFilePath to DefaultSourceFilePath
for clarity, since it serves as the fallback when no per-item SourceText
or SourceFile metadata is specified. Update the corresponding MSBuild
target property reference to match.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the string-based CETCompat property (which compared against
the literal 'false') with a proper bool defaulting to true. The
MSBuild target now evaluates the condition and passes a boolean value.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Split Execute into three phases: ValidateParameters (task-level checks),
ValidateStubExeItem (per-item checks for platform, source resolution),
and GenerateStubExe (compilation only, assumes valid input). This makes
GenerateStubExe simpler and ensures all validation errors are reported
before any compilation begins.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove unused using directives from GenerateCsWinRTStubExes.cs and RunCsWinRTInteropGenerator.cs to clean up imports and avoid compiler/IDE warnings. No functional changes; purely a readability/cleanup tweak.
Remove unused using directives from GenerateCsWinRTStubExes.cs and RunCsWinRTInteropGenerator.cs to clean up imports and avoid compiler/IDE warnings. No functional changes; purely a readability/cleanup tweak.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR refactors stub .exe generation for NativeAOT shared-library scenarios by moving the MSVC invocation logic out of an MSBuild target and into a dedicated MSBuild task, enabling generation of multiple stub executables with per-item customization.

Changes:

  • Added a new GenerateCsWinRTStubExes MSBuild task that can generate multiple stub executables by invoking cl.exe.
  • Refactored _CsWinRTGenerateStubExe in the NuGet .targets file to call the new task and to support a default stub item for backward compatibility.
  • Removed unused using directives from an existing generator task.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 9 comments.

File Description
src/WinRT.Generator.Tasks/RunCsWinRTInteropGenerator.cs Removes unused using directives.
src/WinRT.Generator.Tasks/GenerateCsWinRTStubExes.cs New MSBuild task implementing multi-stub generation via MSVC.
nuget/Microsoft.Windows.CsWinRT.targets Switches stub generation from inline Exec to the new task and documents the item schema.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sergio0694 and others added 2 commits March 25, 2026 20:02
- Extend MSVC/SDK path validation to cover all include and lib paths
  (WindowsSdkUmIncludePath, MsvcLibPath, WindowsSdkUcrtLibPath,
  WindowsSdkUmLibPath), not just the two that were checked before
- Quote the manifest path in /MANIFESTINPUT to handle paths with spaces
- Fix AdditionalPath to only pass the extra directory, not the full
  PATH (the task already appends to the existing PATH)
- Validate stub names are simple file names (no path separators, no
  '..' traversal, no invalid filename chars) to prevent path traversal
- Resolve Win32Manifest paths to full paths so they work correctly
  regardless of the cl.exe working directory
- Wrap file operations in GenerateStubExe in try/catch for clear error
  messages, and ensure DestinationDirectory exists
- Use async event-based reads (BeginOutputReadLine/BeginErrorReadLine)
  for stdout/stderr to avoid potential deadlocks from full pipe buffers
- Fix AdditionalPath doc to say 'append' and clarify callers should not
  include the current PATH
- Make Platform a task-level setting (DefaultPlatform) instead of
  per-item metadata, since the MSVC/SDK lib paths are resolved once for
  the whole task and per-item Platform would not actually switch them

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add inline comments in GenerateCsWinRTStubExes.cs to clarify handling of stdout/stderr and the sequence of starting asynchronous reads (BeginOutputReadLine/BeginErrorReadLine) before waiting for process exit. Improves code readability by documenting intent around receiving stdio lines and blocking until completion.
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.

2 participants