2
2
using System ;
3
3
using System . Collections . Concurrent ;
4
4
using System . Collections . Generic ;
5
+ using System . Diagnostics ;
5
6
using System . IO ;
7
+ using System . Linq ;
6
8
using Java . Interop . Tools . Cecil ;
7
9
using Microsoft . Android . Build . Tasks ;
8
10
using Microsoft . Build . Framework ;
@@ -20,48 +22,99 @@ public class GenerateTypeMappings : AndroidTask
20
22
21
23
public bool Debug { get ; set ; }
22
24
25
+ [ Output ]
26
+ public ITaskItem [ ] GeneratedBinaryTypeMaps { get ; set ; } = [ ] ;
27
+
23
28
[ Required ]
24
29
public string IntermediateOutputDirectory { get ; set ; } = "" ;
25
30
26
31
public bool SkipJniAddNativeMethodRegistrationAttributeScan { get ; set ; }
27
32
28
33
[ Required ]
29
- public string TypemapOutputDirectory { get ; set ; } = "" ;
34
+ public ITaskItem [ ] ResolvedAssemblies { get ; set ; } = [ ] ;
30
35
31
- [ Output ]
32
- public ITaskItem [ ] GeneratedBinaryTypeMaps { get ; set ; } = [ ] ;
36
+ // This property is temporary and is used to ensure that the new "linker step"
37
+ // JLO scanning produces the same results as the old process. It will be removed
38
+ // once the process is complete.
39
+ public bool RunCheckedBuild { get ; set ; }
40
+
41
+ [ Required ]
42
+ public string [ ] SupportedAbis { get ; set ; } = [ ] ;
33
43
34
44
public string TypemapImplementation { get ; set ; } = "llvm-ir" ;
35
45
46
+ [ Required ]
47
+ public string TypemapOutputDirectory { get ; set ; } = "" ;
48
+
36
49
AndroidRuntime androidRuntime ;
37
50
38
51
public override bool RunTask ( )
39
52
{
40
- androidRuntime = MonoAndroidHelper . ParseAndroidRuntime ( AndroidRuntime ) ;
53
+ // Temporarily used to ensure we still generate the same as the old code
54
+ if ( RunCheckedBuild ) {
55
+ androidRuntime = MonoAndroidHelper . ParseAndroidRuntime ( AndroidRuntime ) ;
56
+
57
+ // Retrieve the stored NativeCodeGenState
58
+ var nativeCodeGenStates = BuildEngine4 . GetRegisteredTaskObjectAssemblyLocal < ConcurrentDictionary < AndroidTargetArch , NativeCodeGenState > > (
59
+ MonoAndroidHelper . GetProjectBuildSpecificTaskObjectKey ( GenerateJavaStubs . NativeCodeGenStateRegisterTaskKey , WorkingDirectory , IntermediateOutputDirectory ) ,
60
+ RegisteredTaskObjectLifetime . Build
61
+ ) ;
62
+
63
+ NativeCodeGenState ? templateCodeGenState = null ;
64
+
65
+ foreach ( var kvp in nativeCodeGenStates ) {
66
+ NativeCodeGenState state = kvp . Value ;
67
+ templateCodeGenState = state ;
68
+ WriteTypeMappings ( state ) ;
69
+ }
41
70
42
- // Retrieve the stored NativeCodeGenState
43
- var nativeCodeGenStates = BuildEngine4 . GetRegisteredTaskObjectAssemblyLocal < ConcurrentDictionary < AndroidTargetArch , NativeCodeGenState > > (
44
- MonoAndroidHelper . GetProjectBuildSpecificTaskObjectKey ( GenerateJavaStubs . NativeCodeGenStateRegisterTaskKey , WorkingDirectory , IntermediateOutputDirectory ) ,
45
- RegisteredTaskObjectLifetime . Build
46
- ) ;
71
+ if ( templateCodeGenState is null )
72
+ throw new InvalidOperationException ( $ "Internal error: no native code generator state defined") ;
47
73
48
- NativeCodeGenState ? templateCodeGenState = null ;
74
+ // Set for use by <GeneratePackageManagerJava/> task later
75
+ NativeCodeGenState . TemplateJniAddNativeMethodRegistrationAttributePresent = templateCodeGenState . JniAddNativeMethodRegistrationAttributePresent ;
49
76
50
- foreach ( var kvp in nativeCodeGenStates ) {
51
- NativeCodeGenState state = kvp . Value ;
52
- templateCodeGenState = state ;
53
- WriteTypeMappings ( state ) ;
77
+ return ! Log . HasLoggedErrors ;
54
78
}
55
79
56
- if ( templateCodeGenState is null )
57
- throw new InvalidOperationException ( $ "Internal error: no native code generator state defined") ;
80
+ if ( androidRuntime == Xamarin . Android . Tasks . AndroidRuntime . NativeAOT ) {
81
+ // NativeAOT typemaps are generated in `Microsoft.Android.Sdk.ILLink.TypeMappingStep`
82
+ Log . LogDebugMessage ( "Skipping type maps for NativeAOT." ) ;
83
+ return ! Log . HasLoggedErrors ;
84
+ }
58
85
59
- // Set for use by <GeneratePackageManagerJava/> task later
60
- NativeCodeGenState . TemplateJniAddNativeMethodRegistrationAttributePresent = templateCodeGenState . JniAddNativeMethodRegistrationAttributePresent ;
86
+ GenerateAllTypeMappings ( ) ;
61
87
62
88
return ! Log . HasLoggedErrors ;
63
89
}
64
90
91
+ void GenerateAllTypeMappings ( )
92
+ {
93
+ var allAssembliesPerArch = MonoAndroidHelper . GetPerArchAssemblies ( ResolvedAssemblies , SupportedAbis , validate : true ) ;
94
+
95
+ foreach ( var set in allAssembliesPerArch )
96
+ GenerateTypeMap ( set . Key , set . Value . Values . ToList ( ) ) ;
97
+ }
98
+
99
+ void GenerateTypeMap ( AndroidTargetArch arch , List < ITaskItem > assemblies )
100
+ {
101
+ Log . LogDebugMessage ( $ "Generating type maps for architecture '{ arch } '") ;
102
+
103
+ var sw = Stopwatch . StartNew ( ) ;
104
+ var state = TypeMapObjectsFileAdapter . Create ( arch , assemblies , Log ) ;
105
+ Log . LogDebugMessage ( $ "Type map deserialization took { sw . ElapsedMilliseconds } ms") ;
106
+ sw . Restart ( ) ;
107
+ // An error was already logged to Log.LogError
108
+ if ( state is null )
109
+ return ;
110
+
111
+ var tmg = new TypeMapGenerator ( Log , state , androidRuntime ) ;
112
+ tmg . Generate ( Debug , SkipJniAddNativeMethodRegistrationAttributeScan , TypemapOutputDirectory ) ;
113
+
114
+ Log . Equals ( $ "Type map generation took { sw . ElapsedMilliseconds } ms") ;
115
+ AddOutputTypeMaps ( tmg , state . TargetArch ) ;
116
+ }
117
+
65
118
void WriteTypeMappings ( NativeCodeGenState state )
66
119
{
67
120
if ( androidRuntime == Xamarin . Android . Tasks . AndroidRuntime . NativeAOT ) {
@@ -76,11 +129,17 @@ void WriteTypeMappings (NativeCodeGenState state)
76
129
state = new NativeCodeGenState ( state . TargetArch , new TypeDefinitionCache ( ) , state . Resolver , [ ] , [ ] , state . Classifier ) ;
77
130
}
78
131
79
- var tmg = new TypeMapGenerator ( Log , state , androidRuntime ) ;
132
+ var tmg = new TypeMapGenerator ( Log , new NativeCodeGenStateAdapter ( state ) , androidRuntime ) ;
80
133
tmg . Generate ( Debug , SkipJniAddNativeMethodRegistrationAttributeScan , TypemapOutputDirectory ) ;
81
134
82
- string abi = MonoAndroidHelper . ArchToAbi ( state . TargetArch ) ;
135
+ AddOutputTypeMaps ( tmg , state . TargetArch ) ;
136
+ }
137
+
138
+ void AddOutputTypeMaps ( TypeMapGenerator tmg , AndroidTargetArch arch )
139
+ {
140
+ string abi = MonoAndroidHelper . ArchToAbi ( arch ) ;
83
141
var items = new List < ITaskItem > ( ) ;
142
+
84
143
foreach ( string file in tmg . GeneratedBinaryTypeMaps ) {
85
144
var item = new TaskItem ( file ) ;
86
145
string fileName = Path . GetFileName ( file ) ;
0 commit comments