diff --git a/src/Microsoft.Android.Sdk.ILLink/PreserveLists/System.Private.CoreLib.xml b/src/Microsoft.Android.Sdk.ILLink/PreserveLists/System.Private.CoreLib.xml new file mode 100644 index 00000000000..c5aea679db6 --- /dev/null +++ b/src/Microsoft.Android.Sdk.ILLink/PreserveLists/System.Private.CoreLib.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/AddRidMetadataAttributeStep.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/AddRidMetadataAttributeStep.cs new file mode 100644 index 00000000000..6ee4fe3d2e7 --- /dev/null +++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/AddRidMetadataAttributeStep.cs @@ -0,0 +1,100 @@ +using System; + +using Mono.Cecil; +using Mono.Linker; +using Mono.Linker.Steps; + +#if ILLINK +using Microsoft.Android.Sdk.ILLink; +#endif + +namespace MonoDroid.Tuner; + +public class AddRidMetadataAttributeStep : BaseStep +{ + protected override void ProcessAssembly (AssemblyDefinition assembly) + { + if (!Annotations.HasAction (assembly)) { + return; + } + + var action = Annotations.GetAction (assembly); + if (action == AssemblyAction.Skip || action == AssemblyAction.Delete) { + return; + } + + string? rid = null; +#if ILLINK + if (!Context.TryGetCustomData ("XARuntimeIdentifier", out rid)) { + throw new InvalidOperationException ("Missing XARuntimeIdentifier custom data"); + } +#endif + if (String.IsNullOrEmpty (rid)) { + throw new InvalidOperationException ("RID must have a non-empty value"); + } + + AssemblyDefinition corlib = GetCorlib (); + MethodDefinition assemblyMetadataAttributeCtor = FindAssemblyMetadataAttributeCtor (corlib); + TypeDefinition systemString = GetSystemString (corlib); + + var attr = new CustomAttribute (assembly.MainModule.ImportReference (assemblyMetadataAttributeCtor)); + attr.ConstructorArguments.Add (new CustomAttributeArgument (systemString, "XamarinAndroidAbi")); // key + + // TODO: figure out how to get the RID... + attr.ConstructorArguments.Add (new CustomAttributeArgument (systemString, rid)); // value + + assembly.CustomAttributes.Add (attr); + + if (action == AssemblyAction.Copy) { + Annotations.SetAction (assembly, AssemblyAction.Save); + } + } + + TypeDefinition GetSystemString (AssemblyDefinition asm) => FindType (asm, "System.String", required: true); + + AssemblyDefinition GetCorlib () + { + const string ImportAssembly = "System.Private.CoreLib"; + AssemblyDefinition? asm = Context.Resolve (AssemblyNameReference.Parse (ImportAssembly)); + if (asm == null) { + throw new InvalidOperationException ($"Unable to import assembly '{ImportAssembly}'"); + } + + return asm; + } + + MethodDefinition FindAssemblyMetadataAttributeCtor (AssemblyDefinition asm) + { + const string AttributeType = "System.Reflection.AssemblyMetadataAttribute"; + + TypeDefinition assemblyMetadataAttribute = FindType (asm, AttributeType, required: true); + foreach (MethodDefinition md in assemblyMetadataAttribute!.Methods) { + if (!md.IsConstructor) { + continue; + } + + return md; + } + + throw new InvalidOperationException ($"Unable to find the {AttributeType} type constructor"); + } + + TypeDefinition? FindType (AssemblyDefinition asm, string typeName, bool required) + { + foreach (ModuleDefinition md in asm.Modules) { + foreach (TypeDefinition et in md.Types) { + if (String.Compare (typeName, et.FullName, StringComparison.Ordinal) != 0) { + continue; + } + + return et; + } + } + + if (required) { + throw new InvalidOperationException ($"Internal error: required type '{typeName}' in assembly {asm} not found"); + } + + return null; + } +} diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.ILLink.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.ILLink.targets index 7400de192ff..0461633d57b 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.ILLink.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.ILLink.targets @@ -40,6 +40,7 @@ This file contains the .NET 5-specific targets to customize ILLink https://github.com/dotnet/sdk/blob/a5393731b5b7b225692fff121f747fbbc9e8b140/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.ILLink.targets#L147 --> <_TrimmerCustomData Include="XATargetFrameworkDirectories" Value="$(_XATargetFrameworkDirectories)" /> + <_TrimmerCustomData Include="XARuntimeIdentifier" Value="$(RuntimeIdentifier)" Condition=" '$(_AndroidAddRuntimeIdentifierToAssemblies)' == 'true' " /> <_TrimmerCustomData Condition=" '$(_ProguardProjectConfiguration)' != '' " Include="ProguardConfiguration" @@ -94,6 +95,12 @@ This file contains the .NET 5-specific targets to customize ILLink BeforeStep="MarkStep" Type="MonoDroid.Tuner.FixLegacyResourceDesignerStep" /> + <_TrimmerCustomSteps + Condition=" '$(_AndroidAddRuntimeIdentifierToAssemblies)' == 'true' " + Include="$(_AndroidLinkerCustomStepAssembly)" + AfterStep="CleanStep" + Type="MonoDroid.Tuner.AddRidMetadataAttributeStep" + /> <_PreserveLists Include="$(MSBuildThisFileDirectory)..\PreserveLists\*.xml" />