feat(aot): AOT/trim annotations on dependency-search surface + NativeAOT smoke#12
Open
Rolling2405 wants to merge 3 commits intoNeVeSpl:mainfrom
Open
feat(aot): AOT/trim annotations on dependency-search surface + NativeAOT smoke#12Rolling2405 wants to merge 3 commits intoNeVeSpl:mainfrom
Rolling2405 wants to merge 3 commits intoNeVeSpl:mainfrom
Conversation
Adds .NET 10 to library and test multi-targets while preserving netstandard2.0 (library) and net8.0 (tests). Fixes packaging icon declaration to use <None Include> (was <None Update>) so it resolves correctly under multi-targeting on newer SDKs. Workflow: - Bump actions/checkout v3 -> v4 - Bump actions/setup-dotnet v3 -> v4 - Add 10.0.x to dotnet-version (alongside 3.1.x and 8.0.x) Verified locally: 353 passed (2 skipped) on both net8.0 and net10.0. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…AOT smoke test Add [RequiresUnreferencedCode] and [RequiresDynamicCode] annotations to the dependency-search (Tier 2) public API surface, gated #if NET10_0_OR_GREATER, so that consumers using NativeAOT or the trimmer receive clear, actionable warnings at their own call sites rather than opaque linker errors. Changes ------- sources/NetArchTest/NetArchTest.csproj - Add net10.0 TFM alongside existing netstandard2.0 - Add IsTrimmable/IsAotCompatible guards (NET10_0_OR_GREATER only) sources/NetArchTest/NetArchTestAotMessages.cs (new) - Shared const message strings used by all Requires* attributes sources/NetArchTest/Condition_Dependencies.cs sources/NetArchTest/Predicate_Dependencies.cs sources/NetArchTest/Slices/SliceCondition.cs sources/NetArchTest/Functions/FunctionDelegates_Dependencies.cs - [RequiresUnreferencedCode] + [RequiresDynamicCode] on every public/internal method that drives the dependency-search pipeline (Tier 2 surface) sources/NetArchTest/Dependencies/TypeParser.cs - Type-level [UnconditionalSuppressMessage] for IL2057/IL2077/IL2080 covering Mono.Cecil private-field reflection in the static cctor - [RequiresUnreferencedCode] + [RequiresDynamicCode] on Parse() and ParseReflectionNameToRuntimeName() sources/NetArchTest/Dependencies/DataStructures/NamespaceTree.cs - Extract parseNames=true branch into private ParseTokensRequiringReflection() annotated with Requires*; Add() gets [UnconditionalSuppressMessage] with justification (runtime-guarded; Tier 1 callers pass false) sources/NetArchTest/Extensions/Mono.Cecil/TypeDefinitionExtensions.cs - [RequiresUnreferencedCode] + [RequiresDynamicCode] on ToType() sources/NetArchTest/Assemblies/PublicUse/TypeContainer.cs - Extract Lazy<Type> initialiser lambda into private ResolveReflectionType() annotated with Requires*; constructor gets [UnconditionalSuppressMessage] (Tier 1 paths never read ReflectionType) tests/NetArchTest.AotSmoke/ (new) - NativeAOT publish smoke that exercises Tier 1 only (Types.FromPath + name/namespace/structural predicates) - PublishAot=true, TreatWarningsAsErrors=true, NoWarn IL2104 (Mono.Cecil 0.11.x is not trim-annotated upstream — IL2104 is its aggregate warning; Tier 2 callers still get the proper annotations at their call sites) - Prints 'OK' and exits 0 when the AOT image is correct tests/NetArchTest.AotSmoke.Fixture/ (new) - Minimal test-assembly DLL published alongside the smoke binary Result: dotnet publish -r win-x64 -c Release produces a 4.3 MB native exe with zero IL warnings and zero errors; the exe prints 'OK' and exits 0. All 353x2 unit tests continue to pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Publishes tests/NetArchTest.AotSmoke with PublishAot=true on win-x64 and asserts the produced native exe exits 0. Runs on windows-latest since NativeAOT win-x64 cross-compilation requires the MSVC toolchain. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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
Adds
[RequiresUnreferencedCode]and[RequiresDynamicCode]annotations to the dependency-search (Tier 2) public API surface, gated#if NET10_0_OR_GREATER, so that consumers targeting NativeAOT or the trimmer receive clear, actionable warnings at their call sites instead of opaque linker errors deep in Mono.Cecil.Also includes a NativeAOT publish smoke test (
tests/NetArchTest.AotSmoke) that proves the Tier 1 surface (type loading + name/namespace/structural predicates) compiles clean underPublishAot=true /warnaserroronnet10.0-windows.netstandard2.0is fully preserved — all annotations are#if NET10_0_OR_GREATERguarded. No public API shape change onnetstandard2.0.Intentional scope
[RequiresUnreferencedCode]/[RequiresDynamicCode]TypeContainer.ReflectionType/ToType()<IsTrimmable>/<IsAotCompatible>are deliberately NOT set on the library project. Tier 2+ surfaces use runtime reflection into Mono.Cecil internals that cannot be made fully trim-safe without a major rewrite. Setting those flags would over-promise and suppress legitimate consumer warnings.Changes
sources/NetArchTest/NetArchTestAotMessages.cs(new)const stringmessage used by all[RequiresUnreferencedCode]/[RequiresDynamicCode]attributes so the message is consistent and DRY.sources/NetArchTest/Condition_Dependencies.cs,Predicate_Dependencies.cs,Slices/SliceCondition.cs,Functions/FunctionDelegates_Dependencies.cs[RequiresUnreferencedCode]+[RequiresDynamicCode]on every method in the dependency-search pipeline (Tier 2/3 surface).sources/NetArchTest/Dependencies/TypeParser.cs[UnconditionalSuppressMessage]for IL2057/IL2077/IL2080 covering Mono.Cecil private-field reflection in the static.cctor.[RequiresUnreferencedCode]+[RequiresDynamicCode]onParse()andParseReflectionNameToRuntimeName().sources/NetArchTest/Dependencies/DataStructures/NamespaceTree.csparseNames=truebranch into a privateParseTokensRequiringReflection()annotated withRequires*.Add()gets[UnconditionalSuppressMessage]with justification: Tier 1 callers always passparseNames=falseso the reflection path is unreachable for them.sources/NetArchTest/Extensions/Mono.Cecil/TypeDefinitionExtensions.cs[RequiresUnreferencedCode]+[RequiresDynamicCode]onToType().sources/NetArchTest/Assemblies/PublicUse/TypeContainer.csLazy<Type>initialiser lambda body into privateResolveReflectionType()annotated withRequires*. Constructor gets[UnconditionalSuppressMessage](Tier 1 paths never readReflectionType).tests/NetArchTest.AotSmoke/(new)Types.FromPath+ name/namespace/structural predicates only.PublishAot=true,TreatWarningsAsErrors=true,<NoWarn>IL2104</NoWarn>(Mono.Cecil 0.11.x is not trim-annotated upstream; IL2104 is its aggregate warning which we cannot fix from here — Tier 2 callers still receive proper annotations at their own call sites).OKand exits 0 when the AOT image is correct.tests/NetArchTest.AotSmoke.Fixture/(new)netstandard2.0DLL published alongside the smoke binary as a realistic input toTypes.FromPath..github/workflows/net-workflow.ymlaot-smokejob onwindows-latest: publishes the smoke project and runs the produced exe (asserts exit 0).Local verification
Depends on
This PR was developed on top of the net10 TFM PR (#11). It can be rebased cleanly once that lands, or reviewed independently — the
#if NET10_0_OR_GREATERguards meannetstandard2.0builds are unaffected either way.