diff --git a/src/Microsoft.Android.Sdk.ILLink/Microsoft.Android.Sdk.ILLink.csproj b/src/Microsoft.Android.Sdk.ILLink/Microsoft.Android.Sdk.ILLink.csproj
index b0fc296935d..6c4368fd7d2 100644
--- a/src/Microsoft.Android.Sdk.ILLink/Microsoft.Android.Sdk.ILLink.csproj
+++ b/src/Microsoft.Android.Sdk.ILLink/Microsoft.Android.Sdk.ILLink.csproj
@@ -16,8 +16,6 @@
-
-
diff --git a/src/Xamarin.Android.Build.Tasks/Linker/External/Linker.Steps/BaseStep.cs b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker.Steps/BaseStep.cs
index c1aa1ded94a..a3a5bb11066 100644
--- a/src/Xamarin.Android.Build.Tasks/Linker/External/Linker.Steps/BaseStep.cs
+++ b/src/Xamarin.Android.Build.Tasks/Linker/External/Linker.Steps/BaseStep.cs
@@ -89,11 +89,7 @@ public virtual void LogMessage (string message)
public virtual void LogError (int code, string message)
{
-#if ILLINK
- Context.LogMessage (MessageContainer.CreateCustomErrorMessage (message, code, origin: new MessageOrigin ()));
-#else // !ILLINK
Context.LogError ($"XA{code}", message);
-#endif // !ILLINK
}
}
}
diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs
index 7606f022e7a..7028aea33e0 100644
--- a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs
+++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixLegacyResourceDesignerStep.cs
@@ -14,18 +14,11 @@
using Mono.Linker.Steps;
using Mono.Tuner;
-#if ILLINK
-using Resources = Microsoft.Android.Sdk.ILLink.Properties.Resources;
-#else // !ILLINK
using Resources = Xamarin.Android.Tasks.Properties.Resources;
-#endif // ILLINK
namespace MonoDroid.Tuner
{
- public class FixLegacyResourceDesignerStep : LinkDesignerBase
-#if !ILLINK
- , Xamarin.Android.Tasks.IAssemblyModifierPipelineStep
-#endif // !ILLINK
+ public class FixLegacyResourceDesignerStep : LinkDesignerBase, Xamarin.Android.Tasks.IAssemblyModifierPipelineStep
{
internal const string DesignerAssemblyName = "_Microsoft.Android.Resource.Designer";
internal const string DesignerAssemblyNamespace = "_Microsoft.Android.Resource.Designer";
@@ -36,14 +29,6 @@ public class FixLegacyResourceDesignerStep : LinkDesignerBase
Dictionary lookup;
Dictionary lookupCaseInsensitive;
- protected override void EndProcess ()
- {
- if (designerAssembly != null) {
- LogMessage ($" Setting Action on {designerAssembly.Name} to Link.");
- Annotations.SetAction (designerAssembly, AssemblyAction.Link);
- }
- }
-
protected override void LoadDesigner ()
{
if (designerLoaded)
@@ -72,7 +57,6 @@ protected override void LoadDesigner ()
}
}
-#if !ILLINK
public void ProcessAssembly (AssemblyDefinition assembly, Xamarin.Android.Tasks.StepContext context)
{
// Only run this step on non-main user Android assemblies
@@ -81,7 +65,6 @@ public void ProcessAssembly (AssemblyDefinition assembly, Xamarin.Android.Tasks.
context.IsAssemblyModified |= ProcessAssemblyDesigner (assembly);
}
-#endif // !ILLINK
internal override bool ProcessAssemblyDesigner (AssemblyDefinition assembly)
{
diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs
index 5f7f7fc1f74..6e50b10d7d7 100644
--- a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs
+++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/LinkDesignerBase.cs
@@ -4,16 +4,12 @@
using Mono.Linker;
using Mono.Linker.Steps;
using System;
-using System.Linq;
using Xamarin.Android.Tasks;
using System.Collections.Generic;
using System.Globalization;
using Mono.Cecil.Cil;
using System.Text.RegularExpressions;
using Mono.Collections.Generic;
-#if ILLINK
-using Microsoft.Android.Sdk.ILLink;
-#endif
namespace MonoDroid.Tuner {
@@ -21,26 +17,14 @@ public abstract class LinkDesignerBase : BaseStep
{
protected IMetadataResolver Cache => Context;
- public
-#if !ILLINK
- override
-#endif
- void LogMessage (string message)
+ public override void LogMessage (string message)
{
Context.LogMessage (message);
}
- public
-#if !ILLINK
- override
-#endif
- void LogError (int code, string error)
+ public override void LogError (int code, string error)
{
-#if ILLINK
- Context.LogMessage (MessageContainer.CreateCustomErrorMessage (error, code, origin: new MessageOrigin ()));
-#else // !ILLINK
Context.LogError ($"XA{code}", error);
-#endif // !ILLINK
}
public virtual AssemblyDefinition Resolve (AssemblyNameReference name)
diff --git a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets
index 5c154d9e05c..e19d986acda 100644
--- a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets
+++ b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets
@@ -226,6 +226,11 @@ Copyright (C) 2016 Xamarin. All rights reserved.
In additon we MUST set the `PostprocessAssembly` metadata to `true` so that the file
is processed by the ILLink step. If we do not do this then the reference to
`netstandard.dll` is not replaced with `System.Private.CoreLib` and the app crashes.
+
+ No TrimmerRootDescriptor is needed: PreTrimmingFixLegacyDesigner rewrites library
+ assemblies *before* ILLink, replacing designer field loads with calls to the designer
+ assembly's property getters. ILLink then naturally preserves only the referenced
+ properties through its mark step, allowing everything else to be trimmed.
-->
+
<_RemoveRegisterFlag>$(MonoAndroidIntermediateAssemblyDir)shrunk\shrunk.flag
@@ -167,7 +168,7 @@
+ DependsOnTargets="GetReferenceAssemblyPaths;_CreatePropertiesCache;_AddResourceDesignerToPublishFiles">
true
<_ExtraTrimmerArgs Condition=" '$(_EnableSerializationDiscovery)' != 'false' ">--enable-serialization-discovery $(_ExtraTrimmerArgs)
@@ -204,12 +205,6 @@
<_TrimmerCustomSteps Include="$(_AndroidLinkerCustomStepAssembly)" Type="Microsoft.Android.Sdk.ILLink.PreserveJavaInterfaces" />
- <_TrimmerCustomSteps
- Condition=" '$(AndroidUseDesignerAssembly)' == 'true' "
- Include="$(_AndroidLinkerCustomStepAssembly)"
- BeforeStep="MarkStep"
- Type="MonoDroid.Tuner.FixLegacyResourceDesignerStep"
- />
<_TrimmerCustomSteps
Condition=" '$(_AndroidTypeMapImplementation)' == 'managed' "
Include="$(_AndroidLinkerCustomStepAssembly)"
@@ -229,6 +224,25 @@
+
+
+
+ <_PreTrimmingAssembly Include="@(ResolvedFileToPublish)" Condition=" '%(Extension)' == '.dll' and '%(ResolvedFileToPublish.PostprocessAssembly)' == 'true' " />
+
+
+
+
+/// Runs on assemblies that are about to be
+/// trimmed by ILLink. This rewrites library assemblies so their resource field accesses
+/// (ldsfld) become calls to the designer assembly's property getters.
+///
+/// Running this *before* ILLink means the trimmer sees the rewritten IL and can freely
+/// trim unused designer types/fields. This avoids the need to root the entire designer
+/// assembly during trimming (which causes an APK size regression).
+///
+public class PreTrimmingFixLegacyDesigner : AndroidTask
+{
+ public override string TaskPrefix => "PTD";
+
+ [Required]
+ public ITaskItem [] Assemblies { get; set; } = [];
+
+ [Required]
+ public string TargetName { get; set; } = "";
+
+ public bool Deterministic { get; set; }
+
+ public override bool RunTask ()
+ {
+ using var resolver = new DirectoryAssemblyResolver (
+ this.CreateTaskLogger (), loadDebugSymbols: true);
+
+ foreach (var assembly in Assemblies) {
+ var dir = Path.GetFullPath (Path.GetDirectoryName (assembly.ItemSpec) ?? "");
+ if (!resolver.SearchDirectories.Contains (dir)) {
+ resolver.SearchDirectories.Add (dir);
+ }
+ }
+
+ var linkContext = new MSBuildLinkContext (resolver, Log);
+ var fixLegacyStep = new FixLegacyResourceDesignerStep ();
+ fixLegacyStep.Initialize (linkContext);
+
+ foreach (var item in Assemblies) {
+ // Match the filtering in FixLegacyResourceDesignerStep.ProcessAssembly:
+ // skip the main assembly and framework/BCL assemblies.
+ if (Path.GetFileNameWithoutExtension (item.ItemSpec) == TargetName) {
+ continue;
+ }
+ if (MonoAndroidHelper.IsFrameworkAssembly (item)) {
+ continue;
+ }
+
+ var assembly = resolver.GetAssembly (item.ItemSpec);
+ if (fixLegacyStep.ProcessAssemblyDesigner (assembly)) {
+ Log.LogDebugMessage ($" Writing modified assembly: {item.ItemSpec}");
+ assembly.Write (item.ItemSpec, new WriterParameters {
+ WriteSymbols = assembly.MainModule.HasSymbols,
+ DeterministicMvid = Deterministic,
+ });
+ }
+ }
+
+ return !Log.HasLoggedErrors;
+ }
+}
diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj
index c58aa29aa6e..4070a690f88 100644
--- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj
+++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj
@@ -45,7 +45,7 @@
-
+
diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs
index 04e52ee9839..8a8194f3cfe 100644
--- a/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs
+++ b/tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs
@@ -1420,10 +1420,9 @@ private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e)
using (var b = CreateApkBuilder (Path.Combine ("temp", TestName, app.ProjectName))) {
b.BuildLogFile = "build1.log";
b.ThrowOnBuildFailure = false;
- // TODO: fix for NativeAOT
- if (!addResource && runtime != AndroidRuntime.NativeAOT) {
+ if (!addResource) {
Assert.IsFalse (b.Build (app, doNotCleanupOnUpdate: true), $"Build of {app.ProjectName} should have failed.");
- Assert.IsTrue (b.LastBuildOutput.ContainsText (isRelease ? "IL8000" : "XA8000"));
+ Assert.IsTrue (b.LastBuildOutput.ContainsText ("XA8000"));
Assert.IsTrue (b.LastBuildOutput.ContainsText ("@styleable/SKCanvasView"), "Expected '@styleable/SKCanvasView' in build output.");
Assert.IsTrue (b.LastBuildOutput.ContainsText ("@styleable/SKCanvasView_ignorePixelScaling"), "Expected '@styleable/SKCanvasView_ignorePixelScaling' in build output.");
return;