[tools] Add a new 'trimmable-static' registrar, that uses trimmable type maps. Fixes #23108.#25079
[tools] Add a new 'trimmable-static' registrar, that uses trimmable type maps. Fixes #23108.#25079rolfbjarne wants to merge 22 commits intomainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces a new trimmable-static registrar mode that leverages .NET “Interop Type Maps” to support trimmable registrations, wiring the new mode through the linker, runtime, MSBuild targets, and test variations.
Changes:
- Add a new linker step (
TrimmableRegistrarStep) that emits type-map assemblies/attributes used for type mapping and proxy lookup. - Extend runtime + native runtime flags and lookup paths to support
trimmable-static, including proxy-attribute based construction and unmanaged entrypoint lookup fallback. - Add new build/test plumbing (MSBuild properties, runtimeconfig host options, xharness variations) to exercise the new registrar mode.
Reviewed changes
Copilot reviewed 37 out of 37 changed files in this pull request and generated 17 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/dotnet-linker/Steps/TrimmableRegistrarStep.cs | New linker step that generates typemap assemblies and proxy attribute types/mappings. |
| tools/dotnet-linker/Steps/RegistrarStep.cs | Treat TrimmableStatic similarly to managed-static in registrar output flow. |
| tools/dotnet-linker/Steps/ManagedRegistrarStep.cs | Enable managed-registrar step for trimmable-static to generate UCO trampolines. |
| tools/dotnet-linker/LinkerConfiguration.cs | Add EntryAssembly helper and new linker config values for typemap output/name. |
| tools/dotnet-linker/CecilExtensions.cs | Add TryFindSingle helper for Cecil collections. |
| tools/dotnet-linker/AppBundleRewriter.cs | Add typemap-related Cecil lookups and System.Console assembly support. |
| tools/dotnet-linker/.vscode/launch.json | Adds a VS Code launcher configuration for debugging the linker. |
| tools/common/Target.cs | Emit a runtime flag indicating trimmable-static registrar usage. |
| tools/common/StaticRegistrar.cs | Adjust static registrar generation for trimmable-static and extend dlsym signature usage. |
| tools/common/Optimizations.cs | Allow static-registrar-related optimizations for trimmable-static. |
| tools/common/Assembly.cs | Treat trimmable-static like other static registrar modes for -force_load decisions. |
| tools/common/Application.cs | Add RegistrarMode value + parsing + typemap config values. |
| tests/xharness/Jenkins/TestVariationsFactory.cs | Add CI variations for trimmable-static registrar. |
| tests/monotouch-test/Foundation/StringTest.cs | Adds extra logging in a test case (currently noisy). |
| tests/monotouch-test/dotnet/shared.csproj | Notes/placeholder for enabling trimmable-static registrar in tests. |
| tests/monotouch-test/dotnet/macOS/monotouch-test.csproj | Adds host configuration option for TypeMappingEntryAssembly. |
| tests/monotouch-test/dotnet/macOS/Makefile | Adds convenience targets for trimmable-static registrar runs. |
| tests/monotouch-test/dotnet/macOS/.vscode/tasks.json | Adds VS Code build task for monotouch-test macOS. |
| tests/monotouch-test/dotnet/macOS/.vscode/launch.json | Adds VS Code launch profiles for running monotouch-test macOS. |
| tests/dotnet/MySimpleApp/shared.csproj | Sets registrar to trimmable-static for MySimpleApp. |
| tests/common/test-variations.csproj | Defines new test variations for trimmable-static registrar. |
| tests/common/shared-dotnet.mk | Minor build log output improvement. |
| src/ObjCRuntime/TypeMaps.cs | New runtime helper to lazily initialize typemap dictionaries. |
| src/ObjCRuntime/Runtime.cs | Add trimmable-static runtime flag + proxy-based construction + new unmanaged lookup signature. |
| src/ObjCRuntime/RegistrarHelper.cs | Extend unmanaged lookup to optionally resolve via typemap/proxy attribute. |
| src/ObjCRuntime/Registrar.cs | Add IsStubClass convenience property on ObjCType. |
| src/ObjCRuntime/Class.cs | Add trimmable typemap lookup path and introduce proxy attribute base types/universe markers. |
| src/ILLink.Substitutions.tvOS.xml | Add substitutions for IsTrimmableStaticRegistrar. |
| src/ILLink.Substitutions.macOS.xml | Add substitutions for IsTrimmableStaticRegistrar. |
| src/ILLink.Substitutions.MacCatalyst.xml | Add substitutions for IsTrimmableStaticRegistrar. |
| src/ILLink.Substitutions.iOS.xml | Add substitutions for IsTrimmableStaticRegistrar. |
| src/frameworks.sources | Include new ObjCRuntime/TypeMaps.cs in build. |
| scripts/rsp-to-csproj/rsp-to-csproj.cs | Add Link="..." metadata for generated csproj items when applicable. |
| runtime/xamarin/runtime.h | Add trimmable-static registrar flag setter + extend registrar dlsym signature. |
| runtime/runtime.m | Implement trimmable-static registrar flag + pass objc class name to unmanaged lookup. |
| runtime/delegates.t4 | Extend managed delegate signature for unmanaged lookup to include objc class name. |
| dotnet/targets/Xamarin.Shared.Sdk.targets | Wire registrar mode to linker steps, typemap output publishing, and host config options. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
33e1906 to
12d0980
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
07bfcf7 to
e758700
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
🤖 Re: this comment about splitting the compound I verified this by building The trimmer handles the compound The only downside is a few bytes of vestigial IL (push constant + pop, or unconditional branch) left behind as artifacts of the substitution, but functionally the dead code elimination works correctly. So splitting into two |
This comment has been minimized.
This comment has been minimized.
Both the 2-arg and 3-arg TypeMapAttribute constructors produced the same auto-generated cache key (fullname + "::" + name), causing GetMethodReference to return the wrong constructor. Fix by using explicit distinct cache keys with parameter type suffixes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The linker's TypeMapHandler has a subtle interaction where the TypeMapAssociationAttribute<SkippedObjectiveCTypeUniverse> for types with generic variants (like NSOrderedSet/NSOrderedSet<T>) causes MarkInstantiated to be called directly on the non-generic type, bypassing MarkRequirementsForInstantiatedTypes. This poisons the IsInstantiated flag, preventing ProcessType from ever being called for these types, which means their TypeMapAttribute entries are trimmed by the linker. Fix this by using the 2-arg (unconditional) TypeMapAttribute constructor for types that are the 'actual' target of SkippedObjectiveCTypeUniverse associations. These entries are preserved whenever the group is seen (i.e., when GetOrCreateExternalTypeMapping<NSObject>() is called). Ref: dotnet/runtime#127504 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
/review |
✅ [PR Build #4133c8e] Build passed (Detect API changes) ✅Pipeline on Agent |
✅ [PR Build #4133c8e] Build passed (Build packages) ✅Pipeline on Agent |
✅ API diff for current PR / commitNET (empty diffs)✅ API diff vs stableNET (empty diffs)ℹ️ Generator diffGenerator Diff: vsdrops (html) vsdrops (raw diff) gist (raw diff) - Please review changes) Pipeline on Agent |
✅ [CI Build #4133c8e] Build passed (Build macOS tests) ✅Pipeline on Agent |
🔥 [CI Build #4133c8e] Test results 🔥Test results❌ Tests failed on VSTS: test results 0 tests crashed, 2 tests failed, 167 tests passed. Failures❌ interdependent-binding-projects tests2 tests failed, 2 tests passed.Failed tests
Html Report (VSDrops) Download Successes✅ cecil: All 1 tests passed. Html Report (VSDrops) Download macOS tests✅ Tests on macOS Monterey (12): All 5 tests passed. Html Report (VSDrops) Download Linux Build VerificationPipeline on Agent |
Adopt Interop (Trimmable) Type maps
This pull request adds support for Interop (trimmable) type maps, by adding a new registrar,
trimmable-static, which is really just a variation/evolution of themanaged-staticregistrar.The advantage is that (as the name says) the generated managed code is trimmable, which means it can be generated outside of the trimmer and doesn't need a custom linker step (for simplicity and to ease the implementation it's currently implemented as a custom linker step, but one that runs before any trimming is done, which makes it easy to move to a pre-trimming MSBuild task later on, together with all the other pre-trimming tasks that must be done).
The main difference between the
trimmable-staticandmanaged-staticregistrars, is that withtrimmable-staticwe don't generate any lookup code after the trimmer has executed (theManagedRegistrarLookupTablesstep), we generate the trimmable type maps instead (in a newTrimmableRegistrarstep).In a future change, we'll move the trimmable static registrar code outside of the linker, so it doesn't run as a custom linker step.
There's a significant amount of (disabled) debug logging; this will be removed once the type map support is more tested and stable.
References:
Fixes #23108.