-
Notifications
You must be signed in to change notification settings - Fork 569
Expand file tree
/
Copy pathPostTrimmingPipeline.cs
More file actions
87 lines (76 loc) · 2.82 KB
/
PostTrimmingPipeline.cs
File metadata and controls
87 lines (76 loc) · 2.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#nullable enable
using System.Collections.Generic;
using System.IO;
using Java.Interop.Tools.Cecil;
using Microsoft.Android.Build.Tasks;
using Microsoft.Build.Framework;
using Mono.Cecil;
using MonoDroid.Tuner;
namespace Xamarin.Android.Tasks;
/// <summary>
/// An MSBuild task that runs post-trimming assembly modifications in a single pass.
///
/// This opens each assembly once (via DirectoryAssemblyResolver with ReadWrite) and
/// runs all registered steps on it, then writes modified assemblies in-place. Currently
/// runs StripEmbeddedLibrariesStep and (optionally) AddKeepAlivesStep.
///
/// Runs in the inner build after ILLink but before ReadyToRun/crossgen2 compilation,
/// so that R2R images are generated from the already-modified assemblies.
/// </summary>
public class PostTrimmingPipeline : AndroidTask
{
public override string TaskPrefix => "PTP";
[Required]
public ITaskItem [] Assemblies { get; set; } = [];
public bool AddKeepAlives { get; set; }
public bool Deterministic { get; set; }
public override bool RunTask ()
{
using var resolver = new DirectoryAssemblyResolver (
this.CreateTaskLogger (), loadDebugSymbols: true,
loadReaderParameters: new ReaderParameters { ReadWrite = true });
var cache = new TypeDefinitionCache ();
foreach (var assembly in Assemblies) {
var dir = Path.GetFullPath (Path.GetDirectoryName (assembly.ItemSpec) ?? "");
if (!resolver.SearchDirectories.Contains (dir)) {
resolver.SearchDirectories.Add (dir);
}
}
var steps = new List<IAssemblyModifierPipelineStep> ();
steps.Add (new StripEmbeddedLibrariesStep (Log));
if (AddKeepAlives) {
// Memoize the corlib resolution so the attempt (and any error logging) happens at most once,
// regardless of how many assemblies/methods need KeepAlive injection.
AssemblyDefinition? corlibAssembly = null;
bool corlibResolutionAttempted = false;
steps.Add (new PostTrimmingAddKeepAlivesStep (cache,
() => {
if (!corlibResolutionAttempted) {
corlibResolutionAttempted = true;
try {
corlibAssembly = resolver.Resolve (AssemblyNameReference.Parse ("System.Private.CoreLib"));
} catch (AssemblyResolutionException ex) {
Log.LogErrorFromException (ex, showStackTrace: false);
}
}
return corlibAssembly;
},
(msg) => Log.LogDebugMessage (msg)));
}
foreach (var item in Assemblies) {
var assembly = resolver.GetAssembly (item.ItemSpec);
var context = new StepContext (item, item);
foreach (var step in steps) {
step.ProcessAssembly (assembly, context);
}
if (context.IsAssemblyModified) {
Log.LogDebugMessage ($" Writing modified assembly: {item.ItemSpec}");
assembly.Write (new WriterParameters {
WriteSymbols = assembly.MainModule.HasSymbols,
DeterministicMvid = Deterministic,
});
}
}
return !Log.HasLoggedErrors;
}
}