Skip to content

[dotnet-linker] Use [DynamicDependency] attributes instead of manual marking when marking static registrar methods.#25018

Draft
rolfbjarne wants to merge 1 commit intodev/rolf/use-dynamic-dependency-attributes-applypreserveattributefrom
dev/rolf/use-dynamic-dependency-attributes-markstaticregistrar
Draft

[dotnet-linker] Use [DynamicDependency] attributes instead of manual marking when marking static registrar methods.#25018
rolfbjarne wants to merge 1 commit intodev/rolf/use-dynamic-dependency-attributes-applypreserveattributefrom
dev/rolf/use-dynamic-dependency-attributes-markstaticregistrar

Conversation

@rolfbjarne
Copy link
Copy Markdown
Member

This makes it easier to move this code out of a custom linker step in the future.

Contributes towards #17693.

…marking when marking static registrar methods.

This makes it easier to move this code out of a custom linker step in the future.

Contributes towards #17693.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Updates the dotnet-linker pipeline to preserve static-registrar-related delegate proxy Invoke methods by injecting [DynamicDependency] attributes, moving away from manual marking to support future removal of custom linker steps (per #17693).

Changes:

  • Add MarkForStaticRegistrarStep (an AssemblyModifierStep) that adds dynamic dependency attributes for delegate proxy Invoke methods.
  • Disable the existing MarkForStaticRegistrar mark substep when the new step runs (via a flag in DerivedLinkContext).
  • Wire the new step into the MSBuild trimmer custom steps behind a new _UseDynamicDependenciesForMarkStaticRegistrar property.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
tools/dotnet-linker/MarkForStaticRegistrarStep.cs New assembly-modifier step that injects dynamic dependency attributes to preserve delegate proxy Invoke methods for the static registrar.
tools/dotnet-linker/MarkForStaticRegistrar.cs Skips the existing mark substep when the new pre-MarkStep custom step has run.
tools/common/DerivedLinkContext.cs Adds a DidRunMarkForStaticRegistrarStep flag to coordinate between the two implementations.
dotnet/targets/Xamarin.Shared.Sdk.targets Adds a new build property and enables the new step before MarkStep when dynamic dependencies are enabled.

Comment on lines +55 to +59
var getDelegateProxyType = DerivedLinkContext.StaticRegistrar.GetDelegateProxyType (method);
if (getDelegateProxyType is null)
return false;

var invokeMethod = getDelegateProxyType.Methods.SingleOrDefault (m => m.Name == "Invoke");
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

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

The local name getDelegateProxyType is misleading (it’s a TypeDefinition, not a getter). Rename to something like delegateProxyType to avoid confusion, especially since the next lines treat it as a type instance.

Suggested change
var getDelegateProxyType = DerivedLinkContext.StaticRegistrar.GetDelegateProxyType (method);
if (getDelegateProxyType is null)
return false;
var invokeMethod = getDelegateProxyType.Methods.SingleOrDefault (m => m.Name == "Invoke");
var delegateProxyType = DerivedLinkContext.StaticRegistrar.GetDelegateProxyType (method);
if (delegateProxyType is null)
return false;
var invokeMethod = delegateProxyType.Methods.SingleOrDefault (m => m.Name == "Invoke");

Copilot uses AI. Check for mistakes.
Comment on lines +52 to +58
if (!StaticRegistrar.IsDelegate (method.ReturnType.Resolve ()))
return false;

var getDelegateProxyType = DerivedLinkContext.StaticRegistrar.GetDelegateProxyType (method);
if (getDelegateProxyType is null)
return false;

Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

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

ProcessDelegateProxyAttribute resolves method.ReturnType for every method in every linked assembly. Since this step iterates all methods, this can add significant overhead and may also trigger type resolution failures for otherwise-dead code. Consider first checking whether a delegate proxy type exists (or the presence of DelegateProxyAttribute on method.MethodReturnType) and only then resolving types.

Suggested change
if (!StaticRegistrar.IsDelegate (method.ReturnType.Resolve ()))
return false;
var getDelegateProxyType = DerivedLinkContext.StaticRegistrar.GetDelegateProxyType (method);
if (getDelegateProxyType is null)
return false;
var getDelegateProxyType = DerivedLinkContext.StaticRegistrar.GetDelegateProxyType (method);
if (getDelegateProxyType is null)
return false;
var returnType = method.ReturnType.Resolve ();
if (!StaticRegistrar.IsDelegate (returnType))
return false;

Copilot uses AI. Check for mistakes.
@@ -553,6 +553,7 @@
<_UseDynamicDependenciesForGeneratedCodeOptimizations Condition="'$(_UseDynamicDependenciesForGeneratedCodeOptimizations)' == ''">$(_UseDynamicDependenciesInsteadOfMarking)</_UseDynamicDependenciesForGeneratedCodeOptimizations>
<_UseDynamicDependenciesForApplyPreserveAttribute Condition="'$(_UseDynamicDependenciesForApplyPreserveAttribute)' == '' And '$(_XamarinRuntime)' == 'NativeAOT'">true</_UseDynamicDependenciesForApplyPreserveAttribute>
<_UseDynamicDependenciesForApplyPreserveAttribute Condition="'$(_UseDynamicDependenciesForApplyPreserveAttribute)' == ''">$(_UseDynamicDependenciesInsteadOfMarking)</_UseDynamicDependenciesForApplyPreserveAttribute>
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

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

The new property _UseDynamicDependenciesForMarkStaticRegistrar is a bit inconsistent with the step/type name (MarkForStaticRegistrar*) and the other properties (...ForApplyPreserveAttribute, etc.). Consider aligning the property name (or adding a short comment) so it’s easier to grep and understand later.

Suggested change
<_UseDynamicDependenciesForApplyPreserveAttribute Condition="'$(_UseDynamicDependenciesForApplyPreserveAttribute)' == ''">$(_UseDynamicDependenciesInsteadOfMarking)</_UseDynamicDependenciesForApplyPreserveAttribute>
<_UseDynamicDependenciesForApplyPreserveAttribute Condition="'$(_UseDynamicDependenciesForApplyPreserveAttribute)' == ''">$(_UseDynamicDependenciesInsteadOfMarking)</_UseDynamicDependenciesForApplyPreserveAttribute>
<!-- Controls whether Xamarin.Linker.Steps.MarkForStaticRegistrarStep uses DynamicDependency attributes instead of direct marking. -->

Copilot uses AI. Check for mistakes.
@vs-mobiletools-engineering-service2
Copy link
Copy Markdown
Collaborator

✅ [CI Build #653b289] Build passed (Build packages) ✅

Pipeline on Agent
Hash: 653b289c44da4eb8f29ef54e492fe86993629f8a [PR build]

@vs-mobiletools-engineering-service2
Copy link
Copy Markdown
Collaborator

✅ [PR Build #653b289] Build passed (Detect API changes) ✅

Pipeline on Agent
Hash: 653b289c44da4eb8f29ef54e492fe86993629f8a [PR build]

@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: 653b289c44da4eb8f29ef54e492fe86993629f8a [PR build]

@vs-mobiletools-engineering-service2
Copy link
Copy Markdown
Collaborator

✅ [CI Build #653b289] Build passed (Build macOS tests) ✅

Pipeline on Agent
Hash: 653b289c44da4eb8f29ef54e492fe86993629f8a [PR build]

@vs-mobiletools-engineering-service2
Copy link
Copy Markdown
Collaborator

🔥 [CI Build #653b289] Test results 🔥

Test results

❌ Tests failed on VSTS: test results

0 tests crashed, 28 tests failed, 128 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.AppSizeTest.MonoVM_Interpreter(iOS,"ios-arm64"): Multiple failures or warnings in test:
  1. The file 'System.ComponentModel.TypeConverter.dll' was removed from the app bundle.
    ...
    * Xamarin.Tests.AppSizeTest.MonoVM(iOS,"ios-arm64"): Multiple failures or warnings in test:
  2. The file 'System.ComponentModel.TypeConverter.aotdata.arm64' was removed from the ap...
    * Xamarin.Tests.AppSizeTest.NativeAOT(iOS,"ios-arm64"): 'dotnet build' failed with exit code 1
    Full command: /Users/builder/azdo/_work/1/s/macios/builds/downloads/dotnet-sdk-10.0.300-p...
    * ... and 6 more

Html Report (VSDrops) Download

❌ dotnettests tests (MacCatalyst)

1 tests failed, 0 tests passed.

Failed tests

  • DotNet tests: Failed (Execution failed with exit code 1)
    • Xamarin.Tests.DotNetProjectTest.PublishAot(MacCatalyst,"maccatal...: 'dotnet build' failed with exit code 1
      Full command: /Users/builder/azdo/_work/1/s/macios/builds/downloads/dotnet-sdk-10.0.300-p...
    • Xamarin.Tests.DotNetProjectTest.PublishAot(MacCatalyst,"maccatal...: 'dotnet build' failed with exit code 1
      Full command: /Users/builder/azdo/_work/1/s/macios/builds/downloads/dotnet-sdk-10.0.300-p...
    • Xamarin.Tests.DotNetProjectTest.PublishAot(MacCatalyst,"maccatal...: 'dotnet build' failed with exit code 1
      Full command: /Users/builder/azdo/_work/1/s/macios/builds/downloads/dotnet-sdk-10.0.300-p...
    • ... and 1 more

Html Report (VSDrops) Download

❌ dotnettests tests (macOS)

1 tests failed, 0 tests passed.

Failed tests

  • DotNet tests: Failed (Execution failed with exit code 1)
    • Xamarin.Tests.DotNetProjectTest.BuildAndExecuteAppWithNativeDyna...: 'dotnet build' failed with exit code 1
      Full command: /Users/builder/azdo/_work/1/s/macios/builds/downloads/dotnet-sdk-10.0.300-p...
    • Xamarin.Tests.DotNetProjectTest.BuildProjectsWithExtensions(MacO...: 'dotnet build' failed with exit code 1
      Full command: /Users/builder/azdo/_work/1/s/macios/builds/downloads/dotnet-sdk-10.0.300-p...
    • Xamarin.Tests.DotNetProjectTest.BuildProjectsWithExtensions(MacO...: 'dotnet build' failed with exit code 1
      Full command: /Users/builder/azdo/_work/1/s/macios/builds/downloads/dotnet-sdk-10.0.300-p...
    • ... and 7 more

Html Report (VSDrops) Download

❌ dotnettests tests (tvOS)

1 tests failed, 0 tests passed.

Failed tests

  • DotNet tests: Failed (Execution failed with exit code 1)
    • Xamarin.Tests.DotNetProjectTest.BuildProjectsWithExtensions(TVOS...: 'dotnet build' failed with exit code 1
      Full command: /Users/builder/azdo/_work/1/s/macios/builds/downloads/dotnet-sdk-10.0.300-p...
    • Xamarin.Tests.DotNetProjectTest.BuildProjectsWithExtensionsAndFr...: 'dotnet build' failed with exit code 1
      Full command: /Users/builder/azdo/_work/1/s/macios/builds/downloads/dotnet-sdk-10.0.300-p...
    • Xamarin.Tests.DotNetProjectTest.LinkedWithNativeLibraries(TVOS,"...: Frameworks
      Expected: equivalent to < "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", "/System/Library/...
    • ... and 2 more

Html Report (VSDrops) Download

❌ linker tests

5 tests failed, 39 tests passed.

Failed tests

  • link all/macOS/Release: Failed (Test run failed.
    Tests run: 93 Passed: 82 Inconclusive: 0 Failed: 1 Ignored: 10)
  • link all/Mac Catalyst/Release: Failed (Test run failed.
    Tests run: 97 Passed: 86 Inconclusive: 0 Failed: 1 Ignored: 10)
  • trimmode link/macOS/Release: Failed (Test run failed.
    Tests run: 120 Passed: 117 Inconclusive: 0 Failed: 1 Ignored: 2)
  • trimmode link/Mac Catalyst/Release: Failed (Test run failed.
    Tests run: 133 Passed: 129 Inconclusive: 0 Failed: 1 Ignored: 3)
  • trimmode link/iOS - simulator/Release: LaunchFailure

Html Report (VSDrops) Download

❌ monotouch tests (iOS)

2 tests failed, 9 tests passed.

Failed tests

  • monotouch-test/iOS - simulator/Release (NativeAOT, ARM64): BuildFailure
  • monotouch-test/iOS - simulator/Release (NativeAOT, x64): BuildFailure

Html Report (VSDrops) Download

❌ monotouch tests (MacCatalyst)

3 tests failed, 12 tests passed.

Failed tests

  • monotouch-test/Mac Catalyst/Release (NativeAOT): BuildFailure
  • monotouch-test/Mac Catalyst/Release (NativeAOT, ARM64): BuildFailure
  • monotouch-test/Mac Catalyst/Release (NativeAOT, x64): BuildFailure ( (failed to parse the logs: The Writer is closed or in error state.))

Html Report (VSDrops) Download

❌ monotouch tests (macOS)

3 tests failed, 9 tests passed.

Failed tests

  • monotouch-test/macOS/Release (NativeAOT): BuildFailure ( (failed to parse the logs: The Writer is closed or in error state.))
  • monotouch-test/macOS/Release (NativeAOT, ARM64): BuildFailure
  • monotouch-test/macOS/Release (NativeAOT, x64): BuildFailure

Html Report (VSDrops) Download

❌ monotouch tests (tvOS)

11 tests failed, 0 tests passed.

Failed tests

  • monotouch-test/tvOS - simulator/Debug: BuildFailure
  • monotouch-test/tvOS - simulator/Debug (LinkSdk): BuildFailure
  • monotouch-test/tvOS - simulator/Debug (static registrar): BuildFailure
  • monotouch-test/tvOS - simulator/Release (all optimizations): BuildFailure
  • monotouch-test/tvOS - simulator/Debug (ARM64): BuildFailure
  • monotouch-test/tvOS - simulator/Release (NativeAOT, ARM64): BuildFailure
  • monotouch-test/tvOS - simulator/Debug (managed static registrar): BuildFailure
  • monotouch-test/tvOS - simulator/Release (managed static registrar, all optimizations): BuildFailure
  • monotouch-test/tvOS - simulator/Release (NativeAOT, x64): BuildFailure
  • monotouch-test/tvOS - simulator/Debug (interpreter): BuildFailure
  • monotouch-test/tvOS - simulator/Release (interpreter): BuildFailure

Html Report (VSDrops) Download

Successes

✅ cecil: All 1 tests passed. Html Report (VSDrops) Download
✅ dotnettests (Multiple platforms): 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 6 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: 653b289c44da4eb8f29ef54e492fe86993629f8a [PR build]

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants