-
Notifications
You must be signed in to change notification settings - Fork 569
Expand file tree
/
Copy pathGenerateTypeMappings.cs
More file actions
166 lines (127 loc) · 6 KB
/
GenerateTypeMappings.cs
File metadata and controls
166 lines (127 loc) · 6 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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#nullable enable
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Java.Interop.Tools.Cecil;
using Microsoft.Android.Build.Tasks;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Xamarin.Android.Tools;
namespace Xamarin.Android.Tasks;
// Note: If/When this is converted to an incremental task, every build still needs to set:
// NativeCodeGenState.TemplateJniAddNativeMethodRegistrationAttributePresent
public class GenerateTypeMappings : AndroidTask
{
public override string TaskPrefix => "GTM";
[Required]
public string AndroidRuntime { get; set; } = "";
public bool Debug { get; set; }
public bool EnableMarshalMethods { get;set; }
[Output]
public ITaskItem [] GeneratedBinaryTypeMaps { get; set; } = [];
[Required]
public string IntermediateOutputDirectory { get; set; } = "";
public bool SkipJniAddNativeMethodRegistrationAttributeScan { get; set; }
[Required]
public ITaskItem [] ResolvedAssemblies { get; set; } = [];
[Required]
public string [] SupportedAbis { get; set; } = [];
public string TypemapImplementation { get; set; } = "llvm-ir";
[Required]
public string TypemapOutputDirectory { get; set; } = "";
AndroidRuntime androidRuntime;
readonly List<ITaskItem> generatedBinaryTypeMaps = new List<ITaskItem> ();
public override bool RunTask ()
{
var useMarshalMethods = !Debug && EnableMarshalMethods;
androidRuntime = MonoAndroidHelper.ParseAndroidRuntime (AndroidRuntime);
if (androidRuntime == Xamarin.Android.Tasks.AndroidRuntime.NativeAOT) {
// NativeAOT typemaps are generated in `Microsoft.Android.Sdk.ILLink.TypeMappingStep`
Log.LogDebugMessage ("Skipping type maps for NativeAOT.");
return !Log.HasLoggedErrors;
}
// If using marshal methods, we cannot use the .typemap.xml files currently because
// the type token ids were changed by the marshal method rewriter after we wrote the .xml files.
if (!useMarshalMethods)
GenerateAllTypeMappings ();
// Generate typemaps from the native code generator state (produced by the marshal method rewriter)
if (useMarshalMethods)
GenerateAllTypeMappingsFromNativeState (useMarshalMethods);
GeneratedBinaryTypeMaps = generatedBinaryTypeMaps.ToArray ();
return !Log.HasLoggedErrors;
}
void GenerateAllTypeMappings ()
{
var allAssembliesPerArch = MonoAndroidHelper.GetPerArchAssemblies (ResolvedAssemblies, SupportedAbis, validate: true);
foreach (var set in allAssembliesPerArch)
GenerateTypeMap (set.Key, set.Value.Values.ToList ());
}
void GenerateTypeMap (AndroidTargetArch arch, List<ITaskItem> assemblies)
{
Log.LogDebugMessage ($"Generating type maps for architecture '{arch}'");
var state = TypeMapObjectsFileAdapter.Create (arch, assemblies, Log);
// An error was already logged to Log.LogError
if (state is null)
return;
if (TypemapImplementation != "llvm-ir") {
Log.LogDebugMessage ($"TypemapImplementation='{TypemapImplementation}' will write an empty native typemap.");
state.XmlFiles.Clear ();
}
var tmg = new TypeMapGenerator (Log, state, androidRuntime);
tmg.Generate (Debug, SkipJniAddNativeMethodRegistrationAttributeScan, TypemapOutputDirectory);
// Set for use by <GeneratePackageManagerJava/> task later
NativeCodeGenState.TemplateJniAddNativeMethodRegistrationAttributePresent = state.JniAddNativeMethodRegistrationAttributePresent;
AddOutputTypeMaps (tmg, state.TargetArch);
}
void GenerateAllTypeMappingsFromNativeState (bool useMarshalMethods)
{
// Retrieve the stored NativeCodeGenState
var nativeCodeGenStates = BuildEngine4.GetRegisteredTaskObjectAssemblyLocal<ConcurrentDictionary<AndroidTargetArch, NativeCodeGenState>> (
MonoAndroidHelper.GetProjectBuildSpecificTaskObjectKey (GenerateJavaStubs.NativeCodeGenStateRegisterTaskKey, WorkingDirectory, IntermediateOutputDirectory),
RegisteredTaskObjectLifetime.Build
);
if (nativeCodeGenStates is null)
throw new InvalidOperationException ($"Internal error: {nameof (NativeCodeGenState)} not found");
NativeCodeGenState? templateCodeGenState = null;
foreach (var kvp in nativeCodeGenStates) {
NativeCodeGenState state = kvp.Value;
templateCodeGenState = state;
GenerateTypeMapFromNativeState (state, useMarshalMethods);
}
if (templateCodeGenState is null)
throw new InvalidOperationException ($"Internal error: no native code generator state defined");
// Set for use by <GenerateNativeApplicationConfigSources/> task later
if (useMarshalMethods)
NativeCodeGenState.TemplateJniAddNativeMethodRegistrationAttributePresent = templateCodeGenState.JniAddNativeMethodRegistrationAttributePresent;
}
void GenerateTypeMapFromNativeState (NativeCodeGenState state, bool useMarshalMethods)
{
if (androidRuntime == Xamarin.Android.Tasks.AndroidRuntime.NativeAOT) {
// NativeAOT typemaps are generated in `Microsoft.Android.Sdk.ILLink.TypeMappingStep`
Log.LogDebugMessage ("Skipping type maps for NativeAOT.");
return;
}
Log.LogDebugMessage ($"Generating type maps from native state for architecture '{state.TargetArch}'");
if (TypemapImplementation != "llvm-ir") {
Log.LogDebugMessage ($"TypemapImplementation='{TypemapImplementation}' will write an empty native typemap.");
state = new NativeCodeGenState (state.TargetArch, new TypeDefinitionCache (), state.Resolver, [], [], state.Classifier);
}
var tmg = new TypeMapGenerator (Log, new NativeCodeGenStateAdapter (state), androidRuntime);
tmg.Generate (Debug, SkipJniAddNativeMethodRegistrationAttributeScan, TypemapOutputDirectory);
AddOutputTypeMaps (tmg, state.TargetArch);
}
void AddOutputTypeMaps (TypeMapGenerator tmg, AndroidTargetArch arch)
{
string abi = MonoAndroidHelper.ArchToAbi (arch);
foreach (string file in tmg.GeneratedBinaryTypeMaps) {
var item = new TaskItem (file);
string fileName = Path.GetFileName (file);
item.SetMetadata ("DestinationSubPath", $"{abi}/{fileName}");
item.SetMetadata ("DestinationSubDirectory", $"{abi}/");
item.SetMetadata ("Abi", abi);
generatedBinaryTypeMaps.Add (item);
}
}
}