-
Notifications
You must be signed in to change notification settings - Fork 569
Run FixLegacyResourceDesigner before trimming #11084
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
70f7f30
77de75d
e9edefd
f0059fd
64d4ed1
924649e
8be3817
f12d747
83a8f64
6e870ef
4c4c091
5e3ba1f
432b1b2
548ba35
7b72611
0dbbbee
6420522
3629ccf
db70715
77e20ff
c1f3ceb
bcac9af
78fc39b
8e45623
1b8748b
122e9a4
2f8b72e
b28ccdf
ac02d09
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,94 @@ | ||
| #nullable enable | ||
|
|
||
| using System.Collections.Generic; | ||
| using System.IO; | ||
| using Java.Interop.Tools.Cecil; | ||
| using Microsoft.Android.Build.Tasks; | ||
| using Microsoft.Build.Framework; | ||
| using Microsoft.Build.Utilities; | ||
| using Mono.Cecil; | ||
| using MonoDroid.Tuner; | ||
|
|
||
| namespace Xamarin.Android.Tasks; | ||
|
|
||
| /// <summary> | ||
| /// Runs <see cref="FixLegacyResourceDesignerStep"/> 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). | ||
| /// | ||
| /// Modified assemblies are written to <see cref="OutputDirectory"/> rather than in-place, | ||
| /// to avoid mutating files in the shared NuGet cache or shared intermediate output paths. | ||
| /// </summary> | ||
| public class PreTrimmingFixLegacyDesigner : AndroidTask | ||
| { | ||
| public override string TaskPrefix => "PTD"; | ||
|
|
||
| [Required] | ||
| public ITaskItem [] Assemblies { get; set; } = []; | ||
|
|
||
| [Required] | ||
| public string TargetName { get; set; } = ""; | ||
|
|
||
| [Required] | ||
| public string OutputDirectory { get; set; } = ""; | ||
|
|
||
| public bool Deterministic { get; set; } | ||
|
|
||
| [Output] | ||
| public ITaskItem []? ModifiedAssemblies { get; set; } | ||
|
|
||
| public override bool RunTask () | ||
| { | ||
| Directory.CreateDirectory (OutputDirectory); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🤖 Consider cleaning the output directory at the start, or switching the swap target to use the // Clean stale prelink copies from previous runs
if (Directory.Exists (OutputDirectory)) {
Directory.Delete (OutputDirectory, recursive: true);
}
Directory.CreateDirectory (OutputDirectory);Rule: Incremental build correctness (Postmortem
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems like |
||
|
|
||
| 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); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🤖 💡 Documentation — The removed code in // MSBuildLinkContext wraps the resolver; do not dispose it separately
// as LinkContext.Dispose would double-dispose the resolver.
var linkContext = new MSBuildLinkContext (resolver, Log);Rule: Comments explain "why", not "what" (Postmortem |
||
| var fixLegacyStep = new FixLegacyResourceDesignerStep (); | ||
| fixLegacyStep.Initialize (linkContext); | ||
|
|
||
| var modified = new List<ITaskItem> (); | ||
|
|
||
| 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)) { | ||
| var outputPath = Path.Combine (OutputDirectory, Path.GetFileName (item.ItemSpec)); | ||
| Log.LogDebugMessage ($" Writing modified assembly: {outputPath}"); | ||
| assembly.Write (outputPath, new WriterParameters { | ||
| WriteSymbols = assembly.MainModule.HasSymbols, | ||
| DeterministicMvid = Deterministic, | ||
| }); | ||
|
|
||
| var outputItem = new TaskItem (outputPath); | ||
| item.CopyMetadataTo (outputItem); | ||
| outputItem.SetMetadata ("OriginalPath", item.ItemSpec); | ||
| modified.Add (outputItem); | ||
| } | ||
| } | ||
|
|
||
| ModifiedAssemblies = modified.ToArray (); | ||
|
|
||
| return !Log.HasLoggedErrors; | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤖 💡 Incremental builds — This swap uses an
Exists()check on the filesystem to decide whichResolvedFileToPublishitems to redirect toprelink/. If the stale prelink cleanup suggested inPreTrimmingFixLegacyDesigner.csis not adopted, an alternative fix here would be to persist_PreTrimmingModifiedAssemblyitems to a file (or use a response-file pattern) and read that back, so only assemblies actually modified in the current (or most recent) task run get swapped.Rule: Incremental build correctness