Skip to content

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

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

[linker] Trim Export attributes after registration.#26313
rolfbjarne wants to merge 3 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%).

Fixes #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

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: 616fa5dc677cf0a0b9ff021d2b6e49339ef7e0b9 [PR build]

@vs-mobiletools-engineering-service2

Copy link
Copy Markdown
Collaborator

🔥 [CI Build #616fa5d] Test results 🔥

Test results

❌ Tests failed on VSTS: test results

0 tests crashed, 34 tests failed, 169 tests passed.

Failures

❌ dotnettests tests (iOS)

1 tests failed, 0 tests passed.

Failed tests

  • DotNet tests: Failed (Execution failed with exit code 1)
    • Xamarin.Tests.DynamicRegistrationSupportedTest.SkippedWhenPlatfo...: 'dotnet build' failed with exit code 1
      Full command: /Users/cloudtest/vss/_work/1/s/macios/builds/downloads/dotnet-sdk-10.0.400-...
    • Xamarin.Tests.DynamicRegistrationSupportedTest.UserSpecifiedValu...: 'dotnet build' failed with exit code 1
      Full command: /Users/cloudtest/vss/_work/1/s/macios/builds/downloads/dotnet-sdk-10.0.400-...
    • Xamarin.Tests.DynamicRegistrationSupportedTest.UserSpecifiedValu...: 'dotnet build' failed with exit code 1
      Full command: /Users/cloudtest/vss/_work/1/s/macios/builds/downloads/dotnet-sdk-10.0.400-...
    • ... and 9 more

Html Report (VSDrops) Download

❌ linker tests (iOS)

5 tests failed, 10 tests passed.

Failed tests

  • link all/iOS - simulator/Release: Failed
  • dont link/iOS - simulator/Debug (PrepareAssemblies, MonoVM, Dynamic Registrar): BuildFailure
  • dont link/iOS - simulator/Debug (PrepareAssemblies, MonoVM, Managed Static Registrar): BuildFailure
  • dont link/iOS - simulator/Release (PrepareAssemblies, MonoVM, Dynamic Registrar): BuildFailure
  • dont link/iOS - simulator/Release (PrepareAssemblies, MonoVM, Managed Static Registrar): BuildFailure ( (failed to parse the logs: The Writer is closed or in error state.))

Html Report (VSDrops) Download

❌ linker tests (MacCatalyst)

5 tests failed, 10 tests passed.

Failed tests

  • dont link/Mac Catalyst/Debug (PrepareAssemblies, MonoVM, Dynamic Registrar): BuildFailure
  • dont link/Mac Catalyst/Debug (PrepareAssemblies, MonoVM, Managed Static Registrar): BuildFailure ( (failed to parse the logs: The Writer is closed or in error state.))
  • dont link/Mac Catalyst/Release (PrepareAssemblies, MonoVM, Dynamic Registrar): BuildFailure
  • dont link/Mac Catalyst/Release (PrepareAssemblies, MonoVM, Managed Static Registrar): BuildFailure
  • link all/Mac Catalyst/Debug (don't bundle original resources): BuildFailure

Html Report (VSDrops) Download

❌ linker tests (macOS)

10 tests failed, 11 tests passed.

Failed tests

  • dont link/macOS/Debug (PrepareAssemblies, CoreCLR, Dynamic Registrar): BuildFailure
  • dont link/macOS/Debug (PrepareAssemblies, CoreCLR, Managed Static Registrar): BuildFailure
  • dont link/macOS/Debug (PrepareAssemblies, CoreCLR, Trimmable Static Registrar): BuildFailure ( (failed to parse the logs: The Writer is closed or in error state.))
  • dont link/macOS/Release (PrepareAssemblies, CoreCLR, Dynamic Registrar): BuildFailure
  • dont link/macOS/Release (PrepareAssemblies, CoreCLR, Managed Static Registrar): BuildFailure
  • dont link/macOS/Release (PrepareAssemblies, CoreCLR, Trimmable Static Registrar): BuildFailure ( (failed to parse the logs: The Writer is closed or in error state.))
  • link sdk/macOS/Debug (PrepareAssemblies, CoreCLR, Trimmable Static Registrar): BuildFailure
  • link sdk/macOS/Release (PrepareAssemblies, CoreCLR, Trimmable Static Registrar): BuildFailure
  • link all/macOS/Debug (PrepareAssemblies, CoreCLR, Trimmable Static Registrar): BuildFailure ( (failed to parse the logs: The Writer is closed or in error state.))
  • link all/macOS/Release (PrepareAssemblies, CoreCLR, Trimmable Static Registrar): BuildFailure ( (failed to parse the logs: The Writer is closed or in error state.))

Html Report (VSDrops) Download

❌ linker tests (tvOS)

4 tests failed, 11 tests passed.

Failed tests

  • dont link/tvOS - simulator/Debug (PrepareAssemblies, MonoVM, Dynamic Registrar): BuildFailure
  • dont link/tvOS - simulator/Debug (PrepareAssemblies, MonoVM, Managed Static Registrar): BuildFailure
  • dont link/tvOS - simulator/Release (PrepareAssemblies, MonoVM, Dynamic Registrar): BuildFailure
  • dont link/tvOS - simulator/Release (PrepareAssemblies, MonoVM, Managed Static Registrar): BuildFailure ( (failed to parse the logs: The Writer is closed or in error state.))

Html Report (VSDrops) Download

❌ monotouch tests (iOS)

2 tests failed, 17 tests passed.

Failed tests

  • monotouch-test/iOS - simulator/Debug (PrepareAssemblies): BuildFailure
  • monotouch-test/iOS - simulator/Debug (PrepareAssemblies, inline dlfcn, dont link): BuildFailure

Html Report (VSDrops) Download

❌ monotouch tests (MacCatalyst)

2 tests failed, 16 tests passed.

Failed tests

  • monotouch-test/Mac Catalyst/Debug (PrepareAssemblies): BuildFailure
  • monotouch-test/Mac Catalyst/Debug (PrepareAssemblies, inline dlfcn, dont link): BuildFailure

Html Report (VSDrops) Download

❌ monotouch tests (macOS)

3 tests failed, 16 tests passed.

Failed tests

  • monotouch-test/macOS/Debug (PrepareAssemblies): BuildFailure ( (failed to parse the logs: The Writer is closed or in error state.))
  • monotouch-test/macOS/Debug (PrepareAssemblies, inline dlfcn, dont link): BuildFailure
  • monotouch-test/macOS/Release (static registrar, all optimizations): TimedOut (Execution timed out after 1200 seconds.
    Test run crashed)

Html Report (VSDrops) Download

❌ monotouch tests (tvOS)

2 tests failed, 17 tests passed.

Failed tests

  • monotouch-test/tvOS - simulator/Debug (PrepareAssemblies): BuildFailure
  • monotouch-test/tvOS - simulator/Debug (PrepareAssemblies, inline dlfcn, dont link): BuildFailure

Html Report (VSDrops) Download

Successes

✅ assembly-processing: All 1 tests passed. Html Report (VSDrops) Download
✅ cecil: 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 4 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 Monterey (12): All 5 tests passed. Html Report (VSDrops) Download
✅ Tests on macOS Ventura (13): All 5 tests passed. Html Report (VSDrops) Download
✅ 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: 616fa5dc677cf0a0b9ff021d2b6e49339ef7e0b9 [PR build]

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Investigate whether we can remove more attributes in the linker

3 participants