Build and ship a reference assembly for WinRT.Runtime#2453
Open
Sergio0694 wants to merge 9 commits into
Open
Conversation
* Add WindowsRuntimeImplementationOnlyMemberAttribute Introduce an internal sealed attribute to mark implementation-only members for WinRT runtime. The attribute targets all members, is non-inherited, and is conditional on WINDOWS_RUNTIME_REFERENCE_ASSEMBLY so it is emitted only in reference assemblies; this makes it explicit which members are implementation-only and allows them to be stripped from the runtime DLL. Added at src/WinRT.Runtime2/Attributes/WindowsRuntimeImplementationOnlyMemberAttribute.cs. * Use [WindowsRuntimeImplementationOnlyMember] for implementation-only members Replace the combination of [EditorBrowsable(Never)] and [Obsolete(...)] with the single [WindowsRuntimeImplementationOnlyMember] attribute on implementation-only members across WinRT.Runtime. Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com> * Remove WindowsRuntimeConstants.cs Delete WindowsRuntimeConstants.cs which contained constants for WinRT private implementation detail messaging, the PrivateImplementationDetailObsoleteDiagnosticId (CSWINRT3001), and the CsWinRT diagnostics URL format. These constants have been removed from the project. * Remove CSWINRT3001 NoWarn suppression Delete the NoWarn entry and its comment for CSWINRT3001 from src/WinRT.Runtime2/WinRT.Runtime.csproj so warnings about '[Obsolete]' private implementation details are no longer suppressed. This change surfaces those warnings for visibility during builds. * Delete CSWINRT3001 diagnostic documentation This diagnostic is no longer applicable now that the private implementation detail [Obsolete] attributes have been removed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Use [WindowsRuntimeImplementationOnlyMember] in IActivationFactoryImpl This file was missed in the bulk conversion to the new attribute; it still referenced the now-deleted WindowsRuntimeConstants type, which would break the build. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Remove CSWINRT3001 warning suppressions Remove pragma suppressions and documentation references for the CSWINRT3001 diagnostic. Deleted several "#pragma warning disable CSWINRT3001" (and matching restores) from source files and code-generation templates, and removed CSWINRT3001 from the suppressed warnings list and obsolete-marker table in docs. Affected files include .github/copilot-instructions.md, docs/interop.md, various tests and shim sources, and cswinrt code/template headers. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Extract the bulk of WindowsRuntimeObject's implementation into a new partial file (WindowsRuntimeObject.Impl.cs) and update WindowsRuntimeObject.cs to be a partial declaration. The change relocates constructors, caching fields, dynamic cast/QueryInterface logic, virtual method table helpers, and exception stubs into the new file while removing now-unneeded usings from the original file. This refactor preserves existing behavior but improves code organization and maintainability by separating surface declaration from detailed implementation.
* Adjust reference assembly build for WinRT.Runtime Prevent the SDK-produced reference assembly from leaking implementation-only types by customizing the ref-assembly build. When not building the explicit CsWinRT reference assembly, ProduceReferenceAssembly is disabled and WINDOWS_RUNTIME_IMPLEMENTATION_ASSEMBLY is defined to simplify #if usage. When CsWinRTBuildReferenceAssembly is true, WINDOWS_RUNTIME_REFERENCE_ASSEMBLY is defined and expected warnings (CS8597, IDE0005, IDE0380) are suppressed. A BeforeTargets CoreCompile target removes files that opt out of reference assemblies (via WINDOWS_RUNTIME_IMPLEMENTATION_ONLY_FILE), ABI sources, and several implementation-only folders so the packaged reference assembly omits private implementation details. * Guard Windows metadata by assembly type Wrap Windows runtime metadata and platform/contract attributes with build-time symbols to differentiate reference vs implementation assemblies. Many files now conditionally include Windows.Foundation.Metadata usings and apply [ContractVersion]/[SupportedOSPlatform] for WINDOWS_RUNTIME_REFERENCE_ASSEMBLY and [WindowsRuntimeMetadata]/[WindowsRuntimeClassName]/marshalling attributes for WINDOWS_RUNTIME_IMPLEMENTATION_ASSEMBLY. Removed unconditional SupportedOSPlatform/usings where appropriate and added #if guards across foundation, collections, streams, async adapters and task/asyncinfo helpers to allow building both reference and implementation variants. Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com> * Disable CS1574 in WindowsRuntimeFeatureSwitches Suppress CS1574 (XML doc 'cref' not found) warnings in WindowsRuntimeFeatureSwitches.cs by adding `#pragma warning disable CS1574` before the namespace declaration. This prevents spurious documentation warnings during the build, likely caused by cref references to internal or conditional types. * Move WindowsRuntimeInspectable to NativeObjects Rename/move WindowsRuntimeInspectable.cs from src/WinRT.Runtime2/ to src/WinRT.Runtime2/NativeObjects/ to reorganize project structure. File content unchanged (100% similarity). * Split WindowsRuntimeObject into partial file Move the core implementation into a new partial file (src/WinRT.Runtime2/WindowsRuntimeObject.Impl.cs) and make WindowsRuntimeObject partial. The impl file contains caching, dynamic cast lookup, generated COM vtable handling, QueryInterface logic, activation constructors and an exceptions helper; redundant usings/implementation were removed from WindowsRuntimeObject.cs to keep the public surface unchanged. * Add build guards for reference vs implementation Introduce compile-time guards to separate reference and implementation builds. Many files were marked as implementation-only by adding a WINDOWS_RUNTIME_IMPLEMENTATION_ONLY_FILE define; APIs and method bodies were wrapped with WINDOWS_RUNTIME_REFERENCE_ASSEMBLY / WINDOWS_RUNTIME_IMPLEMENTATION_ASSEMBLY conditionals (throw null in reference builds, real code in implementation builds). Adjustments touch attributes, interop/activation, marshalling, async helpers, buffer/stream utilities, and WindowsRuntimeMarshal/RestrictedErrorInfo/RestrictedErrorInfoExceptionMarshaller. Also updated the project file to exclude the Marshalling folder from the reference build. This enables producing lightweight reference assemblies while keeping full implementations in the implementation assembly. * Use explicit #elif WINDOWS_RUNTIME_IMPLEMENTATION_ASSEMBLY in WinRT.Runtime Replace the plain #else branch following #if WINDOWS_RUNTIME_REFERENCE_ASSEMBLY with an explicit #elif WINDOWS_RUNTIME_IMPLEMENTATION_ASSEMBLY for clarity. The two constants are mutually exclusive and exhaustive, so the behavior is unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add banned API analyzer and ref-assembly config Add Microsoft.CodeAnalysis.BannedApiAnalyzers to central package versions and include it as a private analyzer when building the reference assembly. Add a BannedSymbols.txt listing the WindowsRuntimeImplementationOnlyMemberAttribute to prevent implementation-only types from being exposed in the published ref assembly. Rearrange and annotate the WinRT.Runtime.csproj property groups for implementation vs reference assembly builds, set RS0030 as an error to fail on leaked private APIs, and wire BannedSymbols.txt as an AdditionalFiles input for the analyzer. * Mark implementation-only sources; adjust csproj Add #define WINDOWS_RUNTIME_IMPLEMENTATION_ONLY_FILE to several implementation-only sources (Activation/WindowsRuntimeActivationArgsReference.cs, WindowsRuntimeActivationFactoryCallback.cs, WindowsRuntimeActivationTypes.cs, Windows.Foundation/TrustLevel.cs) so they can be excluded from reference-assembly builds. Tidy WinRT.Runtime.csproj Compile Remove entries (self-closing tags / spacing) and add exclusion for Windows.UI.Xaml.Interop to ensure implementation-only folders are removed from reference builds.
…2448) * Bring back WindowsRuntimeConstants for the WindowsRuntimeObject constructor Re-add the type removed in #2434, now holding the dedicated obsolete message, diagnostic id (CSWINRT3001) and URL format used to flag the reference-assembly-only WindowsRuntimeObject constructor. Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com> * Add a reference-assembly-only constructor for WindowsRuntimeObject After #2446 all WindowsRuntimeObject constructors live in the implementation-only WindowsRuntimeObject.Impl.cs and are stripped from the reference assembly, so the compiler would synthesize a protected parameterless constructor. That constructor is absent from the implementation assembly and would throw MissingMethodException at runtime if a user type derived from WindowsRuntimeObject. Explicitly define it for the reference assembly only, marked obsolete (CSWINRT3001) and hidden, so deriving from WindowsRuntimeObject produces a build diagnostic instead. Only generated projections may derive from it. Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com> * Add back the CSWINRT3001 diagnostics doc Re-add the diagnostics doc removed in #2434, updated for the new scenario (deriving from WindowsRuntimeObject is not supported), and rename it to match the diagnostic id (updating the solution reference, which was previously dangling). Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Make the dual reference-assembly build for WinRT.Runtime (set up via the 'CsWinRTBuildReferenceAssembly' switch) functional end to end, so the NuGet package ships a proper reference assembly under 'ref\net10.0'. The reference build recompiles WinRT.Runtime with all implementation-only types stripped out, producing a lightweight metadata-only assembly along with an XML doc that is likewise stripped to the public reference surface. NuGet binds the compiler to the 'ref' assembly (and the runtime to the 'lib' assembly), and the compiler resolves XML docs next to the compile-time assembly, so the stripped XML is shipped next to the reference assembly in 'ref\net10.0' (IntelliSense then shows only the public surface). The 'lib' folder ships only the implementation assembly; its XML doc is not packaged, since it would never be surfaced and only documents implementation details. The reference build is run as AnyCPU, matching how the solution builds the implementation assembly, so its outputs land in the platform-less 'bin\<config>\net10.0' and 'obj\<config>\net10.0\ref' folders. Because the reference build overwrites the 'bin' outputs, the implementation assembly is staged out before it runs, and both are packaged from the staging folder. - nuget: ship 'ref\net10.0\WinRT.Runtime.dll' and its XML (lib has dll only) - build.cmd: stage the impl dll, build the reference assembly, stage ref dll + xml - CsWinRT-Build-Steps.yml: build and stage the reference assembly and its XML - CsWinRT-PublishToNuGet-Steps.yml: add the 'net10_runtime_ref(_xml)' props Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add docs for reference assembly and impl-only API Document the WinRT.Runtime dual-build (implementation + stripped reference assembly) and the implementation-only API workflow. Updates include: explaining CsWinRTBuildReferenceAssembly and compilation symbols (WINDOWS_RUNTIME_IMPLEMENTATION_ASSEMBLY / WINDOWS_RUNTIME_REFERENCE_ASSEMBLY / WINDOWS_RUNTIME_IMPLEMENTATION_ONLY_FILE), ProduceReferenceAssembly=false behavior, the WindowsRuntimeImplementationOnlyMember attribute, BannedSymbols.txt + Microsoft.CodeAnalysis.BannedApiAnalyzers guard, reference-only WindowsRuntimeObject() constructor and CSWINRT3001 diagnostic, and packaging into ref\net10.0 alongside lib\net10.0. Also update interop-generator SKILL and reference docs to note that generator-consumed runtime APIs are marked as implementation-only and stripped from the reference assembly to ensure version compatibility. * Add docs for implementation-only WinRT.Runtime types Add a new "Implementation-only types consumed from WinRT.Runtime" section to .github/skills/interop-generator/SKILL.md describing the categories of implementation-only APIs the generator calls (ABI marshallers, scalar/object/delegate marshallers, array marshallers, native object wrappers, interface method implementations, collection adapters, ComWrappers/object-reference types, event sources, type-map groups/attributes, IID table/error helpers). Explain that these APIs live only in the WinRT.Runtime implementation assembly, that generated code emits [IgnoresAccessChecksTo] to reach them, and note the need to version-match cswinrtinteropgen to the targeted WinRT.Runtime. Also update .github/skills/update-interop-generator-instructions/SKILL.md to add a verification step to ensure the implementation-only types inventory is current and reconciled with References/InteropReferences.cs and the WinRT.Runtime implementation.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Introduce a dedicated reference assembly for
WinRT.Runtime, built alongside the implementation assembly with every implementation-only type and member stripped out, and ship it in theMicrosoft.Windows.CsWinRTNuGet package underref\net10.0\. A new[WindowsRuntimeImplementationOnlyMember]attribute and a banned-API analyzer make the implementation-only surface explicit and prevent it from ever leaking into the public API.Motivation
WinRT.Runtimeexposes a large set of public-but-private-implementation-detail APIs (marshallers, vtables, native object wrappers, collection adapters, ABI types, and so on) that exist solely to be consumed by generated code: the CsWinRT projections and the interop generator (WinRT.Interop.dll). Previously these were marked[Obsolete]+[EditorBrowsable(Never)]to hide them from IntelliSense, but they were still part of the public surface that consumers compiled against. That cluttered the API, risked accidental use, and meant the implementation-only surface was effectively versioned like public API.Building a separate reference assembly that strips these APIs out entirely gives consumers a clean public surface to compile against, lets the implementation-only APIs evolve freely without semantic-versioning concerns, and makes the rules enforceable: deriving from
WindowsRuntimeObjectis now blocked at compile time (CSWINRT3001) because its constructor exists only in the reference assembly, and the banned-API analyzer fails the build if any implementation-only type ever leaks into the reference surface. This is the runtime-side foundation that complements the reference-projection model used by the rest of CsWinRT 3.0.Changes
[WindowsRuntimeImplementationOnlyMember]attribute (Use a dedicated attribute to mark implementation-only members #2434) — newinternal sealed,[Conditional("WINDOWS_RUNTIME_REFERENCE_ASSEMBLY")]marker insrc/WinRT.Runtime2/Attributes/that replaces the previous[Obsolete]+[EditorBrowsable(Never)]combination used to mark private implementation-detail types and members. Applied throughoutABI/,InteropServices/,NativeObjects/,Windows.Foundation/, and the marker attributes underAttributes/. Removes the oldWindowsRuntimeConstantsprivate-implementation-detail messaging and the corresponding warning suppression.WindowsRuntimeObjectpartial split (Split WindowsRuntimeObject into a partial implementation file #2446) — splits the base type intoWindowsRuntimeObject.cs(shared/reference surface, including the explicit interface implementations asthrow nullstubs) andWindowsRuntimeObject.Impl.cs(implementation-only half), so the implementation can be excluded from the reference assembly.src/WinRT.Runtime2/WinRT.Runtime.csprojnow builds twice: the implementation assembly by default and a stripped reference assembly whenCsWinRTBuildReferenceAssembly=true. Adds theWINDOWS_RUNTIME_IMPLEMENTATION_ASSEMBLY/WINDOWS_RUNTIME_REFERENCE_ASSEMBLYcompilation symbols, setsProduceReferenceAssembly=falseon the implementation build, and adds aRemoveWindowsRuntimeImplementationOnlyFilestarget that excludes implementation-only sources (files definingWINDOWS_RUNTIME_IMPLEMENTATION_ONLY_FILE, plus whole folders such asABI/,NativeObjects/, and most ofInteropServices/) from the reference build.Microsoft.CodeAnalysis.BannedApiAnalyzers(src/Directory.Packages.props) and listsWindowsRuntimeImplementationOnlyMemberAttributeinsrc/WinRT.Runtime2/BannedSymbols.txtwithRS0030promoted to an error, so the build fails if any implementation-only type ever leaks into the reference surface.CSWINRT3001(Add a reference-assembly-only constructor for WindowsRuntimeObject #2448) — a parameterlessprotected WindowsRuntimeObject()constructor exists only in the reference assembly, marked[Obsolete(..., DiagnosticId = "CSWINRT3001")]. User code that derives fromWindowsRuntimeObjectnow gets theCSWINRT3001warning and, because the constructor is absent from the implementation assembly, aMissingMethodExceptionat runtime. Only CsWinRT-generated projections may derive from it. Addsdocs/diagnostics/cswinrt3001.md.Microsoft.Windows.CsWinRTNuGet package now ships the implementation assembly underlib\net10.0\and the reference assembly (with its XML documentation trimmed to the reference surface) underref\net10.0\. The dual build and staging are wired throughnuget/Microsoft.Windows.CsWinRT.nuspec,src/build.cmd, and the Azure Pipelines build/publish steps..github/copilot-instructions.md) and the interop generator skill docs (.github/skills/...) to describe the reference assembly, the[WindowsRuntimeImplementationOnlyMember]attribute, theCSWINRT3001diagnostic, and the implementation-only API surface consumed by the interop generator.