Commit cf4aba3
Add CsWinRTMarshallingMode option for non-Windows TFM marshalling (#2482)
* Support enum-typed arguments in the response file parser
Add case-insensitive, name-based enum parsing to ResponseFileParser and
matching name-based serialization to ResponseFileBuilder, so generator args
can expose enum-typed options that round-trip through response files (and
debug repros) deterministically. Numeric values are rejected to avoid
silently accepting out-of-range enum inputs.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Add base class library assembly detection to the generator core
Add BaseClassLibraryIdentity, which identifies .NET base class library (BCL)
and shared-framework assemblies by their well-known Microsoft public key
tokens. This is used to let the interop generator skip framework assemblies
when discovering user-defined/CCW/generic types. The token set was validated
against the Microsoft.NETCore.App, Microsoft.WindowsDesktop.App, and
Microsoft.AspNetCore.App shared frameworks.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Add CsWinRTMarshallingMode to the interop generator
Introduce the CsWinRTMarshallingMode option ('all', 'minimal', 'strict'),
controlling which assemblies are analyzed when discovering user-defined/CCW
types and generic instantiations:
- 'all' (default): analyze every assembly, including those that don't
reference any CsWinRT assembly. This lets projects that don't target a
Windows TFM (e.g. a class library with just MVVM viewmodels) contribute
the marshalling code their types need.
- 'minimal': analyze every assembly except those from the BCL, to reduce
binary size.
- 'strict': only analyze assemblies referencing the Windows Runtime
assembly (the historical behavior).
Assemblies that reference the Windows Runtime assembly are always analyzed,
regardless of the mode. Adds the CsWinRTMarshallingMode enum, the
--marshalling-mode argument (defaulting to 'all'), an IsBaseClassLibraryModule
module helper, and factors the discovery filter into ShouldProcessModule.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Wire CsWinRTMarshallingMode through the MSBuild task and targets
Add a MarshallingMode parameter to the RunCsWinRTInteropGenerator task (with
validation against the well-known values) that emits '--marshalling-mode' to
the response file. Add the user-facing CsWinRTMarshallingMode MSBuild property
(defaulting to 'all'), pass it to the task, and include it in the generator's
property-inputs cache hash so changing the mode correctly re-runs generation.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Document CsWinRTMarshallingMode
Document the new CsWinRTMarshallingMode option in docs/usage.md and
nuget/readme.md, and update the interop generator skill with the new
--marshalling-mode argument and the mode-based input filtering behavior.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Default the marshalling mode to 'minimal'
Change the default CsWinRTMarshallingMode from 'all' to 'minimal', so the
interop generator analyzes every assembly (even those not targeting a Windows
TFM) except the .NET base class library (BCL) by default. This keeps the
usability win for plain .NET projects while avoiding the binary-size and
analysis cost of crawling the BCL. The enum members are kept ordered from
least to most restrictive (All, Minimal, Strict); the default is expressed via
[DefaultValue] and the MSBuild/task defaults.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Polish MarshallingMode task member ordering and XML docs
Move the 'DefaultMarshallingMode' constant and 'ValidMarshallingModes'
static field to the top of the class (constants and static fields before
instance members), and quote the mode string literals in the XML docs
(e.g. <c>"all"</c>) to make clear they are string values.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Skip legacy-runtime assemblies during interop discovery
With the marshalling mode defaulting to 'minimal', the interop generator now
analyzes assemblies that don't reference the Windows Runtime, including
third-party libraries that target .NET Standard or .NET Framework (e.g. Roslyn
and BenchmarkDotNet, referenced by the SourceGenerator2Test and Benchmarks
projects). Such assemblies are scoped to a legacy corlib ('netstandard' or
'mscorlib'), while the emit phase builds its references from the application's
modern .NET runtime corlib ('System.Runtime'). Because AsmResolver's
'SignatureComparer' treats these corlib scopes as distinct, generic collection
instantiations from those assemblies (e.g. 'IEnumerator<char>',
'IEnumerator<object>') failed the emit-time well-known interface IID lookup,
producing CSWINRTINTEROPGEN0055/0020 errors.
Legacy/portable-runtime assemblies cannot reference the Windows Runtime 3.0
projections in the first place, so they never contain marshalling-relevant
types. Skip them during discovery via the new 'ModuleDefinition.TargetsLegacyRuntime'
check. This restores the pre-marshalling-mode behavior for such assemblies
(previously only Windows-Runtime-referencing assemblies, which always target a
modern .NET runtime, were ever analyzed).
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Add CsWinRTMarshallingEnabledAssembly opt-in item and diagnostics
Add the 'CsWinRTMarshallingEnabledAssembly' MSBuild item, which lets users
force the interop generator to analyze specific assemblies for discovery,
regardless of the marshalling mode. This enables fine-tuning for size: for
example, using the 'strict' mode while opting in a few specific assemblies
known to be needed, without switching to 'minimal' (which increases binary
size more).
The item flows through the RunCsWinRTInteropGenerator task as the
'--marshalling-enabled-assembly-names' argument, and is matched (by assembly
name, ignoring the '.dll' extension and any directory) in 'ShouldProcessModule'
so opted-in assemblies are always analyzed.
Add three diagnostics for the opt-in entries:
- CSWINRTINTEROPGEN0098 (warning): an entry doesn't match any referenced
assembly (likely a typo or stale reference).
- CSWINRTINTEROPGEN0099 (message): an entry already targets Windows and is
therefore always analyzed, so it's redundant and can be removed.
- CSWINRTINTEROPGEN0100 (message): the marshalling mode is 'all' (which
already analyzes everything), so all entries are redundant.
Add a WellKnownInteropMessage type (surfaced by MSBuild as a build message
rather than a warning) to support the two informational diagnostics.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Document CsWinRTMarshallingEnabledAssembly and the legacy-runtime skip
Document the new CsWinRTMarshallingEnabledAssembly opt-in item in docs/usage.md
and nuget/readme.md, and update the interop generator skill with the new
--marshalling-enabled-assembly-names argument, the three opt-in diagnostics
(CSWINRTINTEROPGEN0098-0100), and the legacy-runtime skip behavior. Also bump
the interop generator error ID range in the copilot instructions.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Extract a helper for comma-separated response file arguments
Move the inline 'MarshallingEnabledAssemblies' comma-joining logic in
RunCsWinRTInteropGenerator into a new AppendResponseFileOptionalCommand overload
(taking an ITaskItem[]), keeping GenerateResponseFileCommands easy to read and
consistent with the other AppendResponseFile* helpers.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Move the generator message type to the shared core project
Move WellKnownInteropMessage from the interop generator to the shared
WinRT.Generator.Core project (renamed WellKnownGeneratorMessage) so all
generators can use it. Its Log method now writes through a provided logger
delegate (ConsoleApp.Log from ConsoleAppFramework) instead of calling
Console.WriteLine directly, so any future change to that logger is reflected
here too.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Correct the legacy-runtime skip documentation
The previous rationale for skipping legacy/portable-runtime assemblies was
inaccurate: such assemblies can still use custom-mapped types (e.g.
'IEnumerable<T>') that would need marshalling. The actual reason the skip is
relevant is that the entire interop generator infrastructure identifies
well-known types by comparing against type references scoped to the modern .NET
corlib (e.g. 'System.Runtime'), which the emit phase also uses. Legacy-runtime
assemblies declare those types against a different corlib ('netstandard' or
'mscorlib'), which AsmResolver's SignatureComparer treats as a distinct scope,
so the generator can't match them. Update the TargetsLegacyRuntime doc comment,
the discovery comment, and the usage/skill docs accordingly.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Move the legacy-runtime skip into ShouldProcessModule
The 'TargetsLegacyRuntime' check is part of the 'should this module be analyzed'
decision, so move it (and its explanatory comment) from LoadAndProcessModule
into ShouldProcessModule, keeping LoadAndProcessModule easier to read. The check
runs first (before the opt-in check), preserving the existing behavior that
legacy-runtime assemblies are skipped even when explicitly opted in.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>1 parent 7228284 commit cf4aba3
16 files changed
Lines changed: 557 additions & 8 deletions
File tree
- .github
- skills/interop-generator
- docs
- nuget
- src
- WinRT.Generator.Core
- Errors
- Parsing
- References
- WinRT.Generator.Tasks
- WinRT.Interop.Generator
- Errors
- Extensions
- Generation
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
711 | 711 | | |
712 | 712 | | |
713 | 713 | | |
714 | | - | |
| 714 | + | |
715 | 715 | | |
716 | 716 | | |
717 | 717 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
61 | 61 | | |
62 | 62 | | |
63 | 63 | | |
64 | | - | |
65 | | - | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
66 | 67 | | |
67 | 68 | | |
68 | 69 | | |
| |||
230 | 231 | | |
231 | 232 | | |
232 | 233 | | |
| 234 | + | |
| 235 | + | |
233 | 236 | | |
234 | 237 | | |
235 | 238 | | |
| |||
282 | 285 | | |
283 | 286 | | |
284 | 287 | | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
285 | 297 | | |
286 | 298 | | |
287 | 299 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
136 | 136 | | |
137 | 137 | | |
138 | 138 | | |
| 139 | + | |
139 | 140 | | |
140 | 141 | | |
141 | 142 | | |
142 | 143 | | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
143 | 180 | | |
144 | 181 | | |
145 | 182 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
45 | 45 | | |
46 | 46 | | |
47 | 47 | | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
48 | 61 | | |
49 | 62 | | |
50 | 63 | | |
| |||
133 | 146 | | |
134 | 147 | | |
135 | 148 | | |
| 149 | + | |
| 150 | + | |
136 | 151 | | |
137 | 152 | | |
138 | 153 | | |
| |||
185 | 200 | | |
186 | 201 | | |
187 | 202 | | |
| 203 | + | |
| 204 | + | |
188 | 205 | | |
189 | 206 | | |
190 | 207 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
33 | 33 | | |
34 | 34 | | |
35 | 35 | | |
| 36 | + | |
| 37 | + | |
36 | 38 | | |
37 | 39 | | |
38 | 40 | | |
| |||
Lines changed: 48 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
89 | 89 | | |
90 | 90 | | |
91 | 91 | | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
92 | 99 | | |
93 | 100 | | |
94 | 101 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
261 | 261 | | |
262 | 262 | | |
263 | 263 | | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
264 | 284 | | |
265 | 285 | | |
266 | 286 | | |
| |||
0 commit comments