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,96 @@ 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 state = TypeMapObjectsFileAdapter . Create ( arch , assemblies , Log ) ;
104
+
105
+ // An error was already logged to Log.LogError
106
+ if ( state is null )
107
+ return ;
108
+
109
+ var tmg = new TypeMapGenerator ( Log , state , androidRuntime ) { RunCheckedBuild = RunCheckedBuild } ;
110
+ tmg . Generate ( Debug , SkipJniAddNativeMethodRegistrationAttributeScan , TypemapOutputDirectory ) ;
111
+
112
+ AddOutputTypeMaps ( tmg , state . TargetArch ) ;
113
+ }
114
+
65
115
void WriteTypeMappings ( NativeCodeGenState state )
66
116
{
67
117
if ( androidRuntime == Xamarin . Android . Tasks . AndroidRuntime . NativeAOT ) {
@@ -76,11 +126,17 @@ void WriteTypeMappings (NativeCodeGenState state)
76
126
state = new NativeCodeGenState ( state . TargetArch , new TypeDefinitionCache ( ) , state . Resolver , [ ] , [ ] , state . Classifier ) ;
77
127
}
78
128
79
- var tmg = new TypeMapGenerator ( Log , state , androidRuntime ) ;
129
+ var tmg = new TypeMapGenerator ( Log , new NativeCodeGenStateAdapter ( state ) , androidRuntime ) { RunCheckedBuild = RunCheckedBuild } ;
80
130
tmg . Generate ( Debug , SkipJniAddNativeMethodRegistrationAttributeScan , TypemapOutputDirectory ) ;
81
131
82
- string abi = MonoAndroidHelper . ArchToAbi ( state . TargetArch ) ;
132
+ AddOutputTypeMaps ( tmg , state . TargetArch ) ;
133
+ }
134
+
135
+ void AddOutputTypeMaps ( TypeMapGenerator tmg , AndroidTargetArch arch )
136
+ {
137
+ string abi = MonoAndroidHelper . ArchToAbi ( arch ) ;
83
138
var items = new List < ITaskItem > ( ) ;
139
+
84
140
foreach ( string file in tmg . GeneratedBinaryTypeMaps ) {
85
141
var item = new TaskItem ( file ) ;
86
142
string fileName = Path . GetFileName ( file ) ;
0 commit comments