Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 26 additions & 9 deletions dotnet/targets/Xamarin.Shared.Sdk.targets
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,9 @@
- NativeAOT supported platforms in all configurations
- ios/tvos device builds in all configurations
- macOS/MacCatalyst builds in release configuration
(On .NET 11+ NativeAOT defaults to 'trimmable-static' instead - that's set earlier, at
evaluation time, in Xamarin.Shared.Sdk.props. The trimmable-static registrar is only smaller
under NativeAOT, so the other runtimes keep managed-static.)
- Set 'partial-static' for:
- when no assemblies are trimmed and when MarshalManagedExceptionMode is default (or not set)
- Otherwise set 'dynamic'
Expand Down Expand Up @@ -601,6 +604,21 @@
<ItemGroup Condition="'$(_DynamicRegistrationSupported)' != ''">
<RuntimeHostConfigurationOption Include="ObjCRuntime.Runtime.DynamicRegistrationSupported" Value="$(_DynamicRegistrationSupported)" Trim="true" />
</ItemGroup>
<!--
When using the trimmable static registrar together with PrepareAssemblies, we can tell the trimmer to
remove the [ProtocolMember] attributes. This makes it possible to trim away types that are only
referenced from these attributes (such as generic types in optional protocol members).
The assembly-preparer's post-processing pass still needs these attributes (it runs the registrar again
after the trimmer), so it reads them from the pre-trim (prepared) assemblies instead.
Only do this when the dynamic registrar has been removed (DynamicRegistrationSupported == false): the
dynamic registrar reads these attributes via reflection at runtime, so they must be kept when it's
present (otherwise the trimmer errors out with IL2045). This is computed here, and not in
_ComputeLinkerInputs, because _DynamicRegistrationSupported isn't known until this target has run.
See src/TrimAttributes.LinkDescription.xml and tools/assembly-preparer/AssemblyPreparer.cs.
-->
<ItemGroup Condition="'$(Registrar)' == 'trimmable-static' And '$(_DynamicRegistrationSupported)' == 'false'">
<RuntimeHostConfigurationOption Include="ObjCRuntime.TrimProtocolMemberAttributes" Value="true" Trim="true" />
</ItemGroup>
</Target>

<!--
Expand Down Expand Up @@ -876,15 +894,6 @@
<RuntimeHostConfigurationOption Include="ObjCRuntime.Runtime.Arch.IsSimulator" Value="$(_IsSimulatorFeature)" Trim="true" />
<RuntimeHostConfigurationOption Include="ObjCRuntime.Runtime.IsManagedStaticRegistrar" Value="$(_IsManagedStaticRegistrarFeature)" Trim="true" />
<RuntimeHostConfigurationOption Include="ObjCRuntime.Runtime.IsTrimmableStaticRegistrar" Value="$(_IsTrimmableStaticRegistrarFeature)" Trim="true" />
<!--
When using the trimmable static registrar together with PrepareAssemblies, we can tell the trimmer to
remove the [ProtocolMember] attributes. This makes it possible to trim away types that are only
referenced from these attributes (such as generic types in optional protocol members).
The assembly-preparer's post-processing pass still needs these attributes (it runs the registrar again
after the trimmer), so it reads them from the pre-trim (prepared) assemblies instead.
See src/TrimAttributes.LinkDescription.xml and tools/assembly-preparer/AssemblyPreparer.cs.
-->
<RuntimeHostConfigurationOption Include="ObjCRuntime.TrimProtocolMemberAttributes" Value="true" Trim="true" Condition="'$(Registrar)' == 'trimmable-static' And '$(PrepareAssemblies)' == 'true'" />
<RuntimeHostConfigurationOption Include="ObjCRuntime.Runtime.IsNativeAOT" Value="$(_IsNativeAOTFeature)" Trim="true" />
<RuntimeHostConfigurationOption Include="ObjCRuntime.Runtime.IsCoreCLR" Value="true" Trim="true" Condition="'$(UseMonoRuntime)' != 'true'" />
<RuntimeHostConfigurationOption Include="ObjCRuntime.Runtime.IsCoreCLR" Value="false" Trim="true" Condition="'$(UseMonoRuntime)' == 'true'" />
Expand Down Expand Up @@ -1214,6 +1223,14 @@
<OutputPath>$(_StrippedAssemblyDirectory)\%(ResolvedFileToPublish.OriginalRelativePath)</OutputPath>
</_AssembliesToBeStripped>

<!-- Some assemblies added to ResolvedFileToPublish don't have OriginalRelativePath set (e.g. the
TypeMap assemblies the trimmable-static registrar generates). Without it the OutputPath above
collapses to the bare stripped directory, and ILStrip fails trying to write to a directory
("Access to the path '.../stripped/' is denied"). Fall back to the file name in that case. -->
<_AssembliesToBeStripped Condition="'%(_AssembliesToBeStripped.OriginalRelativePath)' == ''">
<OutputPath>$(_StrippedAssemblyDirectory)\%(Filename)%(Extension)</OutputPath>
</_AssembliesToBeStripped>

<!-- Use forward slashes in OutputPath, otherwise ILStrip will create filenames that resemble the part of
the relative path of the item that uses backslashes, instead of writing the file to the location of the
relative path. -->
Expand Down
6 changes: 6 additions & 0 deletions tests/linker/link all/LinkAllTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,12 @@ public void LinkedAwayGenericTypeAsOptionalMemberInProtocol ()
if (!global::XamarinTests.ObjCRuntime.Registrar.IsTrimmableStaticRegistrar)
Assert.Ignore ("This test only applies to the trimmable static registrar.");

// The [ProtocolMember] attributes (which reference NSSet<T>) are only trimmed away when the dynamic
// registrar has been removed - it reads these attributes via reflection at runtime, so they're kept
// when it's present. Without trimming the attributes, NSSet<T> stays too, so there's nothing to verify.
if (global::ObjCRuntime.Runtime.DynamicRegistrationSupported)
Assert.Ignore ("This test only applies when the dynamic registrar has been removed.");

// https://github.com/dotnet/macios/issues/3523
// Don't use constants here, because the linker can see what we're trying to do and keeps the type we're verifying has been removed.
string prefix = NamespacePrefix;
Expand Down
Loading