Skip to content

[linker] Trim Export attributes after registration. - #26313

Open
rolfbjarne wants to merge 21 commits into
mainfrom
dev/rolf/dev-rolf-remove-export-attributes
Open

[linker] Trim Export attributes after registration.#26313
rolfbjarne wants to merge 21 commits into
mainfrom
dev/rolf/dev-rolf-remove-export-attributes

Conversation

@rolfbjarne

@rolfbjarne rolfbjarne commented Jul 27, 2026

Copy link
Copy Markdown
Member

Summary

  • Remove Foundation.ExportAttribute, Foundation.ActionAttribute, and Foundation.OutletAttribute instances through the ObjCRuntime.TrimExportAttributes ILLink feature after the managed registrar has consumed them.
  • Recover selector metadata needed by post-processing from isolated pre-trim assemblies, without mixing Cecil metadata universes.
  • Add the nullable TrimExportAttributes MSBuild property: unset enables automatic removal, true requires removal, and false preserves the attributes.
  • Document the property and add focused policy tests plus a dedicated ExportAttributeRemovalApp integration-test fixture.

Safety

Removal is considered only when PrepareAssemblies=true, PostProcessAssemblies=true, and Registrar=trimmable-static. It is enabled only when dynamic registration is unsupported, the blockliteral-setupblock and static-block-to-delegate-lookup optimizations are enabled, the managed registrar emits no reflective block/delegate fallback, and the app does not use the NSXpcInterface overloads that obtain selectors from MethodInfo.

In automatic mode, each blocker emits its corresponding warning (MX4192-MX4197) and preserves the attributes. When removal is explicitly enabled, the same diagnostics are errors. Explicitly disabling removal preserves the existing behavior without diagnostics.

Validation

  • 12 focused ComputeExportAttributeRemovalStepTests cases.
  • 8 ExportAttributeRemovalEligibility and ExportAttributeRemovalWithNSXpcInterfaceUsage integration cases.
  • Xamarin.MacDev.Tasks builds for net10.0 and netstandard2.0.

In the test fixture, Export-derived instances drop from 122 to 0 in Microsoft.iOS.dll and from 3 to 0 in the app assembly. The stripped Microsoft.iOS.dll decreases from 130,048 to 81,920 bytes (48,128 bytes, or 37%).

Contributes towards #16678

🤖 Pull request created by Copilot

Remove Export, Action, and Outlet attribute instances after managed registration when static analysis proves runtime metadata fallback is unnecessary. Preserve selector access during post-processing through isolated pre-trim assemblies, and disable or reject removal when safety blockers are found.

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

Copilot-Session: 7d63bf91-7585-4d3e-9db4-a17531b71907
Move Export, Action, Outlet, protocol-wrapper, and NSXpc fixtures out of MySimpleApp into a dedicated iOS test application.

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

Copilot-Session: 7d63bf91-7585-4d3e-9db4-a17531b71907
Copilot AI review requested due to automatic review settings July 27, 2026 18:33
@rolfbjarne
rolfbjarne requested a review from mauroa as a code owner July 27, 2026 18:33

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 introduces an optimization to remove Foundation.ExportAttribute, Foundation.ActionAttribute, and Foundation.OutletAttribute instances after managed registration, when static analysis determines runtime metadata fallback isn’t needed. It threads a new TrimExportAttributes decision through assembly preparation/post-processing, emits a feature switch (ObjCRuntime.TrimExportAttributes) to drive ILLink attribute-instance removal, and adds tests + documentation for the new behavior.

Changes:

  • Add TrimExportAttributes eligibility computation (with explicit blockers) in the assembly-preparer pipeline and expose the result back to MSBuild.
  • Enable ILLink to remove Export/Action/Outlet attribute instances when ObjCRuntime.TrimExportAttributes=true, while preserving required registrar metadata via pre-trim assemblies during post-processing.
  • Add unit/integration tests and document the new TrimExportAttributes MSBuild property.

Reviewed changes

Copilot reviewed 19 out of 20 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tools/mtouch/Errors.resx Adds new MX4192 localized message for Export-attribute-removal blockers.
tools/mtouch/Errors.designer.cs Adds generated accessor for MX4192.
tools/linker/RegistrarRemovalTrackingStep.cs Detects NSXpcInterface MethodInfo selector-reflection usage as a blocker.
tools/dotnet-linker/Steps/ManagedRegistrarStep.cs Adds blockers when managed registrar must use runtime block wrapper fallback paths.
tools/dotnet-linker/LinkerConfiguration.cs Clarifies comments around DynamicRegistrationSupported and tracking step behavior.
tools/common/StaticRegistrar.cs Extends attribute lookup to consult pre-trim assemblies during post-processing for selected registrar attributes.
tools/common/Application.cs Adds TrimExportAttributes + TrimExportAttributesBlockers state and broadens pre-trim-resolver comments.
tools/assembly-preparer/ComputeExportAttributeRemovalStep.cs New step computing eligibility, setting MSBuild output, and warning/erroring on blockers.
tools/assembly-preparer/AssemblyPreparer.cs Plumbs TrimExportAttributes, adds eligibility step, and enforces registrar compatibility.
tests/dotnet/UnitTests/PrepareAssembliesTest.cs Adds end-to-end build assertions for eligibility + NSXpcInterface blocker behavior.
tests/dotnet/ExportAttributeRemovalApp/shared.csproj New test app shared project to validate attribute removal in assemblies.
tests/dotnet/ExportAttributeRemovalApp/iOS/ExportAttributeRemovalApp.csproj New iOS test app project wrapper.
tests/dotnet/ExportAttributeRemovalApp/AppDelegate.cs New test app code containing Export/Action/Outlet usage + optional NSXpcInterface path.
tests/common/DotNet.cs Extends AssertBuildFailure to support specifying a target.
tests/assembly-preparer/ComputeExportAttributeRemovalStepTests.cs New unit tests covering eligibility computation and blockers.
src/ILLink.LinkAttributes.xml.in Adds feature-gated RemoveAttributeInstances for Export/Action/Outlet.
msbuild/Xamarin.Shared/Xamarin.Shared.targets Passes TrimExportAttributes into assembly-preparer and tracks it in incremental inputs.
msbuild/Xamarin.MacDev.Tasks/Tasks/PrepareAssemblies.cs Adds task plumbing for TrimExportAttributes and MSBuild output file cleanup on failure.
dotnet/targets/Xamarin.Shared.Sdk.targets Enables runtime host config option based on assembly-preparer output; validates TrimExportAttributes usage.
docs/building-apps/build-properties.md Documents the new TrimExportAttributes MSBuild property and behavior.
Files not reviewed (1)
  • tools/mtouch/Errors.designer.cs: Generated file
Comments suppressed due to low confidence (2)

msbuild/Xamarin.Shared/Xamarin.Shared.targets:3694

  • $(_TrimExportAttributes) isn't set anywhere in this targets file, so the assembly-preparer will always receive an empty value here and won't honor an explicit TrimExportAttributes=true/false property. Pass $(TrimExportAttributes) directly instead.
			TrimExportAttributes="$(_TrimExportAttributes)"

msbuild/Xamarin.Shared/Xamarin.Shared.targets:3747

  • Same as the preparation path: TrimExportAttributes is passed as $(_TrimExportAttributes), but that property isn't defined in this targets file, so the post-processing assembly-preparer won't see the user's setting. Pass $(TrimExportAttributes) directly.
			TrimExportAttributes="$(_TrimExportAttributes)"

Comment thread tools/assembly-preparer/AssemblyPreparer.cs Outdated
Comment thread msbuild/Xamarin.Shared/Xamarin.Shared.targets
@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

🔥 Failed to compute test summaries on VSTS: test results 🔥

Failed to compute test summaries: Cannot bind argument to parameter 'InputObject' because it is null..

Pipeline on Agent
Merge 788b5ab into 78f1fbf

@vs-mobiletools-engineering-service2

This comment has been minimized.

Comment thread tests/dotnet/UnitTests/PrepareAssembliesTest.cs Outdated
Comment thread tests/dotnet/UnitTests/PrepareAssembliesTest.cs Outdated
Comment thread tools/assembly-preparer/ComputeExportAttributeRemovalStep.cs Outdated
Comment thread tools/linker/RegistrarRemovalTrackingStep.cs Outdated
Comment thread tools/linker/RegistrarRemovalTrackingStep.cs Outdated
Comment thread tools/linker/RegistrarRemovalTrackingStep.cs Outdated
Comment thread msbuild/Xamarin.MacDev.Tasks/Tasks/PrepareAssemblies.cs Outdated
Comment thread tools/assembly-preparer/AssemblyPreparer.cs Outdated
Comment thread tools/assembly-preparer/AssemblyPreparer.cs Outdated
Comment thread tools/common/StaticRegistrar.cs Outdated
Use typed localized blockers, centralize Export trimming state, clarify API detection and MSBuild output ownership, and cover automatic registrar fallback behavior.

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

Copilot-Session: 7d63bf91-7585-4d3e-9db4-a17531b71907
@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

MSBuild cannot bind textual boolean values to nullable Boolean task parameters. Accept the property as text at the task boundary and preserve nullable semantics when passing it to the assembly preparer.

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

Copilot-Session: 7d63bf91-7585-4d3e-9db4-a17531b71907
@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@rolfbjarne rolfbjarne added the ready-to-review This PR is ready to review/merge. label Jul 29, 2026
@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

dalexsoto
dalexsoto previously approved these changes Jul 31, 2026
@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@rolfbjarne

Copy link
Copy Markdown
Member Author

/apply-gist https://gist.github.com/vs-mobiletools-engineering-service2/0ce222692eb35485baaf2758d779241b

@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

✅ Applied expected app size files from gist.

Comment thread msbuild/Xamarin.Shared/Xamarin.Shared.targets Outdated
@rolfbjarne rolfbjarne removed the ready-to-review This PR is ready to review/merge. label Sep 3, 2026
Pass the effective TrimExportAttributes value through the shared custom linker options file instead of duplicating it as a PrepareAssemblies task input. Append the preparation result so post-processing reads the resolved value from the same configuration source.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7d63bf91-7585-4d3e-9db4-a17531b71907
@vs-mobiletools-engineering-service2

This comment has been minimized.

Add CopyToWindows support to the remoted WriteLinesToFile task and use it for the custom linker options file, eliminating duplicate local writes during Windows builds.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 7d63bf91-7585-4d3e-9db4-a17531b71907
@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

⚠️ AppSizeTest expected files changed ⚠️

The AppSizeTest detected changes in the expected app size files.

To update the expected files, add a comment with the following command:

/apply-gist https://gist.github.com/vs-mobiletools-engineering-service2/81d442e53f7691459fdfa3a78c1941b3
Updated files
  • MacOSX-CoreCLR-R2R-size.txt
  • MacOSX-NativeAOT-size.txt
  • MacOSX-NativeAOT-TrimmableStatic-size.txt

Pipeline on Agent
Hash: 1bb3072dc370884458e9900991c1a9417a5dad9e [PR build]

rolfbjarne and others added 2 commits September 4, 2026 07:39
The test invokes MobileILStrip directly, which cannot process ReadyToRun images. Keep the test focused on export attribute removal by producing regular IL assemblies.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@vs-mobiletools-engineering-service2

This comment has been minimized.

@vs-mobiletools-engineering-service2

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The post-processing PreTrimAssemblies MSBuild wiring can be empty when PostProcessAssemblies=true without PrepareAssemblies=true, which can break pre-trim attribute recovery and needs a fallback fix.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review details

Files not reviewed (1)

  • tools/mtouch/Errors.designer.cs: Generated file
  • Files reviewed: 32/33 changed files
  • Comments generated: 1
  • Review effort level: Lite

Comment thread msbuild/Xamarin.Shared/Xamarin.Shared.targets
…ove-export-attributes

# Conflicts:
#	tests/dotnet/UnitTests/expected/MacCatalyst-CoreCLR-Interpreter-preservedapis.txt
#	tests/dotnet/UnitTests/expected/MacCatalyst-CoreCLR-R2R-preservedapis.txt
#	tests/dotnet/UnitTests/expected/MacOSX-CoreCLR-R2R-size.txt
#	tests/dotnet/UnitTests/expected/MacOSX-NativeAOT-TrimmableStatic-size.txt
#	tests/dotnet/UnitTests/expected/MacOSX-NativeAOT-size.txt
#	tests/dotnet/UnitTests/expected/TVOS-CoreCLR-Interpreter-preservedapis.txt
#	tests/dotnet/UnitTests/expected/TVOS-CoreCLR-R2R-preservedapis.txt
#	tests/dotnet/UnitTests/expected/iOS-CoreCLR-Interpreter-preservedapis.txt
#	tests/dotnet/UnitTests/expected/iOS-CoreCLR-R2R-preservedapis.txt
#	tools/mtouch/Errors.resx
Merging origin/main introduced MT4192, which collided (by number) with
this branch's MX4192-MX4197 range and broke the resx sort-order check.
Shifted this branch's codes to MX4193-MX4198.
@rolfbjarne
rolfbjarne enabled auto-merge (squash) September 7, 2026 18:02
@rolfbjarne rolfbjarne added the ready-to-review This PR is ready to review/merge. label Sep 7, 2026
@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

✅ API diff for current PR / commit

NET (empty diffs)

✅ API diff vs stable

NET (empty diffs)

ℹ️ Generator diff

Generator Diff: vsdrops (html) vsdrops (raw diff) gist (raw diff) - Please review changes)

Pipeline on Agent
Hash: 7fda88acb555c61b70bf48c3bea5ffa2182a14ef [PR build]

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

🚀 [CI Build #7fda88a] Test results 🚀

Test results

✅ All tests passed on VSTS: test results.

🎉 All 264 tests passed 🎉

Tests counts

✅ assembly-processing: All 1 tests passed. Html Report (VSDrops) Download
✅ cecil: All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (iOS): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (MacCatalyst): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (macOS): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (Multiple platforms): All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (tvOS): All 1 tests passed. Html Report (VSDrops) Download
✅ framework: All 2 tests passed. Html Report (VSDrops) Download
✅ fsharp: All 4 tests passed. Html Report (VSDrops) Download
✅ generator: All 5 tests passed. Html Report (VSDrops) Download
✅ interdependent-binding-projects: All 4 tests passed. Html Report (VSDrops) Download
✅ introspection: All 7 tests passed. Html Report (VSDrops) Download
✅ linker (iOS): All 31 tests passed. Html Report (VSDrops) Download
✅ linker (MacCatalyst): All 31 tests passed. Html Report (VSDrops) Download
✅ linker (macOS): All 21 tests passed. Html Report (VSDrops) Download
✅ linker (tvOS): All 31 tests passed. Html Report (VSDrops) Download
✅ monotouch (iOS): All 25 tests passed. Html Report (VSDrops) Download
✅ monotouch (MacCatalyst): All 25 tests passed. Html Report (VSDrops) Download
✅ monotouch (macOS): All 20 tests passed. Html Report (VSDrops) Download
✅ monotouch (tvOS): All 25 tests passed. Html Report (VSDrops) Download
✅ msbuild: All 2 tests passed. Html Report (VSDrops) Download
✅ sharpie: All 1 tests passed. Html Report (VSDrops) Download
✅ windows: All 3 tests passed. Html Report (VSDrops) Download
✅ xcframework: All 4 tests passed. Html Report (VSDrops) Download
✅ xtro: All 1 tests passed. Html Report (VSDrops) Download

macOS tests

✅ Tests on macOS Sonoma (14): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Sequoia (15): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Tahoe (26): All 5 tests passed. Html Report (VSDrops) Download

Linux Build Verification

Linux build succeeded

Pipeline on Agent
Hash: 7fda88acb555c61b70bf48c3bea5ffa2182a14ef [PR build]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

copilot ready-to-review This PR is ready to review/merge.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants