Skip to content

Commit 9121bea

Browse files
[Xamarin.Android.Build.Tasks] make "managed typemap" runtime agnostic (#9911)
Context: 684ede6 Context: b11471b For NativeAOT, we implemented a "managed" typemap that is trimmer-safe; see 684ede6 and b11471b. In order to test its performance characteristics, make this typemap useable for Mono and CoreCLR as well: * Move `NativeAotTypeManager`, `NativeAotValueManager`, and `TypeMapping` types to `Mono.Android.dll` * Rename `NativeAot*` types to `Managed*` * Add a new private `$(_AndroidTypeMapImplementation)` MSBuild property that can be set to `llvm-ir` or `managed`. * Add a new trimmer feature flag `Microsoft.Android.Runtime.RuntimeFeature.ManagedTypeMap`; when `true` uses the managed typemap on any runtime. I added a test that verifies `dotnet run` succeeds for all typemap implementations. Note that NativeAOT will *only* support the managed typemap. Update `JNIEnvInit.RegisterJniNatives()` to *not* require that `androidRuntime.TypeManager` be an `AndroidTypeManager`; this allows `ManagedTypeManager` to be used on MonoVM and CoreCLR.
1 parent 0d4f223 commit 9121bea

File tree

20 files changed

+92
-41
lines changed

20 files changed

+92
-41
lines changed

Diff for: build-tools/create-packs/Microsoft.Android.Runtime.proj

-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ projects that use the Microsoft.Android framework in .NET 6+.
4646
/>
4747
<_AndroidRuntimePackAssemblies
4848
Include="$(_MonoAndroidNETOutputRoot)$(AndroidLatestStableApiLevel)\System.IO.Hashing.dll"
49-
Condition=" '$(AndroidRuntime)' == 'NativeAOT' "
5049
NoSymbols="true"
5150
/>
5251
<_AndroidRuntimePackAssemblies Include="$(_MonoAndroidNETOutputRoot)$(AndroidLatestStableApiLevel)\Mono.Android.Export.dll" />

Diff for: src/Microsoft.Android.Runtime.NativeAOT/Android.Runtime.NativeAOT/JavaInteropRuntime.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ static void init (IntPtr jnienv, IntPtr klass)
3737
var settings = new DiagnosticSettings ();
3838
settings.AddDebugDotnetLog ();
3939

40-
var typeManager = new NativeAotTypeManager ();
40+
var typeManager = new ManagedTypeManager ();
4141
var options = new NativeAotRuntimeOptions {
4242
EnvironmentPointer = jnienv,
4343
TypeManager = typeManager,

Diff for: src/Microsoft.Android.Runtime.NativeAOT/Java.Interop/JreRuntime.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ static NativeAotRuntimeOptions CreateJreVM (NativeAotRuntimeOptions builder)
5858
throw new InvalidOperationException ($"Member `{nameof (NativeAotRuntimeOptions)}.{nameof (NativeAotRuntimeOptions.JvmLibraryPath)}` must be set.");
5959

6060
#if NET
61-
builder.TypeManager ??= new NativeAotTypeManager ();
61+
builder.TypeManager ??= new ManagedTypeManager ();
6262
#endif // NET
6363

6464
builder.ValueManager ??= new ManagedValueManager ();

Diff for: src/Microsoft.Android.Runtime.NativeAOT/Microsoft.Android.Runtime.NativeAOT.csproj

-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
<Target Name="_CopyToPackDirs">
3939
<ItemGroup>
4040
<_RuntimePackFiles Include="$(OutputPath)Microsoft.Android.Runtime.NativeAOT.dll" AndroidRID="%(AndroidAbiAndRuntimeFlavor.AndroidRID)" AndroidRuntime="%(AndroidAbiAndRuntimeFlavor.AndroidRuntime)" />
41-
<_RuntimePackFiles Include="$(OutputPath)System.IO.Hashing.dll" AndroidRID="%(AndroidAbiAndRuntimeFlavor.AndroidRID)" AndroidRuntime="%(AndroidAbiAndRuntimeFlavor.AndroidRuntime)" />
4241
</ItemGroup>
4342
<Message Importance="high" Text="$(TargetPath) %(AndroidAbiAndRuntimeFlavor.AndroidRID)" />
4443
<Copy

Diff for: src/Microsoft.Android.Sdk.ILLink/TypeMappingStep.cs

+6-7
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ namespace Microsoft.Android.Sdk.ILLink;
1919
/// </summary>
2020
public class TypeMappingStep : BaseStep
2121
{
22-
const string AssemblyName = "Microsoft.Android.Runtime.NativeAOT";
23-
const string TypeName = "Microsoft.Android.Runtime.TypeMapping";
22+
const string AssemblyName = "Mono.Android";
23+
const string TypeName = "Microsoft.Android.Runtime.ManagedTypeMapping";
2424
const string SystemIOHashingAssemblyPathCustomData = "SystemIOHashingAssemblyPath";
2525
readonly IDictionary<string, List<TypeDefinition>> TypeMappings = new Dictionary<string, List<TypeDefinition>> (StringComparer.Ordinal);
26-
AssemblyDefinition? MicrosoftAndroidRuntimeNativeAot;
26+
AssemblyDefinition? MonoAndroidAssembly;
2727

2828
delegate ulong HashMethod (ReadOnlySpan<byte> data, long seed = 0);
2929
HashMethod? _hashMethod;
@@ -36,8 +36,7 @@ protected override void Process ()
3636
protected override void ProcessAssembly (AssemblyDefinition assembly)
3737
{
3838
if (assembly.Name.Name == AssemblyName) {
39-
MicrosoftAndroidRuntimeNativeAot = assembly;
40-
return;
39+
MonoAndroidAssembly = assembly;
4140
}
4241
if (Annotations?.GetAction (assembly) == AssemblyAction.Delete)
4342
return;
@@ -51,11 +50,11 @@ protected override void EndProcess ()
5150
{
5251
Context.LogMessage ($"Writing {TypeMappings.Count} typemap entries");
5352

54-
if (MicrosoftAndroidRuntimeNativeAot is null) {
53+
if (MonoAndroidAssembly is null) {
5554
throw new InvalidOperationException ($"Unable to find {AssemblyName} assembly");
5655
}
5756

58-
var module = MicrosoftAndroidRuntimeNativeAot.MainModule;
57+
var module = MonoAndroidAssembly.MainModule;
5958
var type = module.GetType (TypeName);
6059
if (type is null) {
6160
throw new InvalidOperationException ($"Unable to find {TypeName} type");

Diff for: src/Mono.Android/Android.Runtime/AndroidRuntime.cs

+7-7
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ class AndroidRuntime : JniRuntime {
2323
internal AndroidRuntime (IntPtr jnienv,
2424
IntPtr vm,
2525
IntPtr classLoader,
26-
JniRuntime.JniTypeManager? typeManager,
27-
JniRuntime.JniValueManager? valueManager,
26+
JniRuntime.JniTypeManager typeManager,
27+
JniRuntime.JniValueManager valueManager,
2828
bool jniAddNativeMethodRegistrationAttributePresent)
2929
: base (new AndroidRuntimeOptions (jnienv,
3030
vm,
@@ -95,16 +95,16 @@ class AndroidRuntimeOptions : JniRuntime.CreationOptions {
9595
public AndroidRuntimeOptions (IntPtr jnienv,
9696
IntPtr vm,
9797
IntPtr classLoader,
98-
JniRuntime.JniTypeManager? typeManager,
99-
JniRuntime.JniValueManager? valueManager,
98+
JniRuntime.JniTypeManager typeManager,
99+
JniRuntime.JniValueManager valueManager,
100100
bool jniAddNativeMethodRegistrationAttributePresent)
101101
{
102102
EnvironmentPointer = jnienv;
103103
ClassLoader = new JniObjectReference (classLoader, JniObjectReferenceType.Global);
104104
InvocationPointer = vm;
105105
ObjectReferenceManager = new AndroidObjectReferenceManager ();
106-
TypeManager = typeManager ?? new AndroidTypeManager (jniAddNativeMethodRegistrationAttributePresent);
107-
ValueManager = valueManager ?? new AndroidValueManager ();
106+
TypeManager = typeManager;
107+
ValueManager = valueManager;
108108
UseMarshalMemberBuilder = false;
109109
JniAddNativeMethodRegistrationAttributePresent = jniAddNativeMethodRegistrationAttributePresent;
110110
}
@@ -512,7 +512,7 @@ public override void RegisterNativeMembers (
512512
[UnconditionalSuppressMessage ("Trimming", "IL2057", Justification = "Type.GetType() can never statically know the string value parsed from parameter 'methods'.")]
513513
[UnconditionalSuppressMessage ("Trimming", "IL2067", Justification = "Delegate.CreateDelegate() can never statically know the string value parsed from parameter 'methods'.")]
514514
[UnconditionalSuppressMessage ("Trimming", "IL2072", Justification = "Delegate.CreateDelegate() can never statically know the string value parsed from parameter 'methods'.")]
515-
public void RegisterNativeMembers (
515+
public override void RegisterNativeMembers (
516516
JniType nativeClass,
517517
[DynamicallyAccessedMembers (MethodsAndPrivateNested)] Type type,
518518
ReadOnlySpan<char> methods)

Diff for: src/Mono.Android/Android.Runtime/JNIEnvInit.cs

+13-3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using Java.Interop.Tools.TypeNameMappings;
1010

1111
using Microsoft.Android.Runtime;
12+
using RuntimeFeature = Microsoft.Android.Runtime.RuntimeFeature;
1213

1314
namespace Android.Runtime
1415
{
@@ -79,7 +80,7 @@ static Type TypeGetType (string typeName) =>
7980
JniType.GetCachedJniType (ref jniType, className);
8081

8182
ReadOnlySpan<char> methods = new ReadOnlySpan<char> ((void*) methods_ptr, methods_len);
82-
((AndroidTypeManager)androidRuntime!.TypeManager).RegisterNativeMembers (jniType, type, methods);
83+
androidRuntime!.TypeManager.RegisterNativeMembers (jniType, type, methods);
8384
}
8485

8586
// NOTE: should have different name than `Initialize` to avoid:
@@ -110,12 +111,21 @@ internal static unsafe void Initialize (JnienvInitializeArgs* args)
110111
java_class_loader = args->grefLoader;
111112

112113
BoundExceptionType = (BoundExceptionType)args->ioExceptionType;
114+
JniRuntime.JniTypeManager typeManager;
115+
JniRuntime.JniValueManager valueManager;
116+
if (RuntimeFeature.ManagedTypeMap) {
117+
typeManager = new ManagedTypeManager ();
118+
valueManager = new ManagedValueManager ();
119+
} else {
120+
typeManager = new AndroidTypeManager (args->jniAddNativeMethodRegistrationAttributePresent != 0);
121+
valueManager = RuntimeType == DotNetRuntimeType.MonoVM ? new AndroidValueManager () : new ManagedValueManager ();
122+
}
113123
androidRuntime = new AndroidRuntime (
114124
args->env,
115125
args->javaVm,
116126
args->grefLoader,
117-
null,
118-
RuntimeType != DotNetRuntimeType.MonoVM ? new ManagedValueManager () : null,
127+
typeManager,
128+
valueManager,
119129
args->jniAddNativeMethodRegistrationAttributePresent != 0
120130
);
121131
ValueManager = androidRuntime.ValueManager;

Diff for: src/Mono.Android/ILLink/ILLink.Substitutions.xml

+4
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,9 @@
44
<method signature="System.Boolean get_NegotiateAuthenticationIsEnabled()" body="stub" feature="Xamarin.Android.Net.UseNegotiateAuthentication" featurevalue="false" value="false" />
55
<method signature="System.Boolean get_NegotiateAuthenticationIsEnabled()" body="stub" feature="Xamarin.Android.Net.UseNegotiateAuthentication" featurevalue="true" value="true" />
66
</type>
7+
<type fullname="Microsoft.Android.Runtime.RuntimeFeature">
8+
<method signature="System.Boolean get_ManagedTypeMap()" body="stub" feature="Microsoft.Android.Runtime.RuntimeFeature.ManagedTypeMap" featurevalue="false" value="false" />
9+
<method signature="System.Boolean get_ManagedTypeMap()" body="stub" feature="Microsoft.Android.Runtime.RuntimeFeature.ManagedTypeMap" featurevalue="true" value="true" />
10+
</type>
711
</assembly>
812
</linker>

Diff for: src/Microsoft.Android.Runtime.NativeAOT/Android.Runtime.NativeAOT/NativeAotTypeManager.cs renamed to src/Mono.Android/Microsoft.Android.Runtime/ManagedTypeManager.cs

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
1+
using System;
2+
using System.Collections.Generic;
13
using System.Diagnostics.CodeAnalysis;
24
using System.Reflection;
35
using Java.Interop;
46
using Java.Interop.Tools.TypeNameMappings;
57

68
namespace Microsoft.Android.Runtime;
79

8-
partial class NativeAotTypeManager : JniRuntime.JniTypeManager {
10+
class ManagedTypeManager : JniRuntime.JniTypeManager {
911

1012
const DynamicallyAccessedMemberTypes Constructors = DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors;
1113
internal const DynamicallyAccessedMemberTypes Methods = DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods;
1214
internal const DynamicallyAccessedMemberTypes MethodsAndPrivateNested = Methods | DynamicallyAccessedMemberTypes.NonPublicNestedTypes;
1315

14-
public NativeAotTypeManager ()
16+
public ManagedTypeManager ()
1517
{
1618
}
1719

@@ -127,7 +129,7 @@ public override void RegisterNativeMembers (
127129

128130
protected override IEnumerable<Type> GetTypesForSimpleReference (string jniSimpleReference)
129131
{
130-
if (TypeMapping.TryGetType (jniSimpleReference, out var target)) {
132+
if (ManagedTypeMapping.TryGetType (jniSimpleReference, out var target)) {
131133
yield return target;
132134
}
133135
foreach (var t in base.GetTypesForSimpleReference (jniSimpleReference)) {
@@ -141,7 +143,7 @@ protected override IEnumerable<string> GetSimpleReferences (Type type)
141143
yield return r;
142144
}
143145

144-
if (TypeMapping.TryGetJniName (type, out var jniName)) {
146+
if (ManagedTypeMapping.TryGetJniName (type, out var jniName)) {
145147
yield return jniName;
146148
}
147149
}

Diff for: src/Microsoft.Android.Runtime.NativeAOT/Android.Runtime.NativeAOT/TypeMapping.cs renamed to src/Mono.Android/Microsoft.Android.Runtime/ManagedTypeMapping.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using System.Buffers.Binary;
23
using System.Diagnostics;
34
using System.Diagnostics.CodeAnalysis;
@@ -8,7 +9,7 @@
89

910
namespace Microsoft.Android.Runtime;
1011

11-
internal static class TypeMapping
12+
internal static class ManagedTypeMapping
1213
{
1314
internal static bool TryGetType (string jniName, [NotNullWhen (true)] out Type? type)
1415
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System;
2+
using System.Diagnostics.CodeAnalysis;
3+
4+
namespace Microsoft.Android.Runtime;
5+
6+
static class RuntimeFeature
7+
{
8+
const string FeatureSwitchPrefix = "Microsoft.Android.Runtime.RuntimeFeature.";
9+
10+
[FeatureSwitchDefinition ($"{FeatureSwitchPrefix}{nameof (ManagedTypeMap)}")]
11+
internal static bool ManagedTypeMap { get; } =
12+
AppContext.TryGetSwitch ($"{FeatureSwitchPrefix}{nameof (ManagedTypeMap)}", out bool isEnabled) ? isEnabled : false;
13+
}

Diff for: src/Mono.Android/Mono.Android.csproj

+5
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,10 @@
349349
<Compile Include="Java.Util.Concurrent.Atomic\AtomicInteger.cs" />
350350
<Compile Include="Java.Util.Concurrent.Atomic\AtomicLong.cs" />
351351
<Compile Include="Javax.Microedition.Khronos.Egl\EGLContext.cs" />
352+
<Compile Include="Microsoft.Android.Runtime\ManagedTypeManager.cs" />
353+
<Compile Include="Microsoft.Android.Runtime\ManagedTypeMapping.cs" />
352354
<Compile Include="Microsoft.Android.Runtime\ManagedValueManager.cs" />
355+
<Compile Include="Microsoft.Android.Runtime\RuntimeFeature.cs" />
353356
<Compile Include="Org.Apache.Http.Impl.Conn\DefaultClientConnection.cs" />
354357
<Compile Include="Org.Apache.Http.Impl.Cookie\BasicClientCookie.cs" />
355358
<Compile Include="System.Drawing/PointConverter.cs" />
@@ -373,6 +376,7 @@
373376
</ItemGroup>
374377

375378
<ItemGroup>
379+
<PackageReference Include="System.IO.Hashing" Version="$(SystemIOHashingPackageVersion)" />
376380
<PackageReference Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" Version="3.3.4">
377381
<PrivateAssets>all</PrivateAssets>
378382
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
@@ -415,6 +419,7 @@
415419
<_RefExtras Include="$(OutputPath)*.*" Exclude="$(OutputPath)*.dll" />
416420
<_SourceFiles Include="$(OutputPath)Mono.Android.*" />
417421
<_SourceFiles Include="$(OutputPath)Java.Interop.*" />
422+
<_SourceFiles Include="$(OutputPath)System.IO.Hashing.dll" />
418423
<_RuntimePackFiles Include="@(_SourceFiles)" AndroidRID="%(AndroidAbiAndRuntimeFlavor.AndroidRID)" AndroidRuntime="%(AndroidAbiAndRuntimeFlavor.AndroidRuntime)" />
419424
</ItemGroup>
420425
<Copy

Diff for: src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
<AndroidClassParser>class-parse</AndroidClassParser>
4444
<AndroidCodegenTarget Condition=" '$(AndroidCodegenTarget)' == '' ">XAJavaInterop1</AndroidCodegenTarget>
4545
<_AndroidJcwCodegenTarget Condition=" '$(_AndroidJcwCodegenTarget)' == '' and '$(_AndroidRuntime)' != 'NativeAOT' ">XAJavaInterop1</_AndroidJcwCodegenTarget>
46+
<_AndroidTypeMapImplementation Condition=" '$(_AndroidTypeMapImplementation)' == '' and '$(_AndroidRuntime)' != 'NativeAOT' ">llvm-ir</_AndroidTypeMapImplementation>
4647
<AndroidBoundInterfacesContainStaticAndDefaultInterfaceMethods Condition=" '$(AndroidBoundInterfacesContainStaticAndDefaultInterfaceMethods)' == '' ">true</AndroidBoundInterfacesContainStaticAndDefaultInterfaceMethods>
4748
<AndroidBoundInterfacesContainTypes Condition=" '$(AndroidBoundInterfacesContainTypes)' == '' ">true</AndroidBoundInterfacesContainTypes>
4849
<AndroidBoundInterfacesContainConstants Condition=" '$(AndroidBoundInterfacesContainConstants)' == '' ">true</AndroidBoundInterfacesContainConstants>

Diff for: src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.ILLink.targets

+1-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ This file contains the .NET 5-specific targets to customize ILLink
8787
Type="MonoDroid.Tuner.FixLegacyResourceDesignerStep"
8888
/>
8989
<_TrimmerCustomSteps
90-
Condition=" '$(_AndroidRuntime)' == 'NativeAOT' "
90+
Condition=" '$(_AndroidTypeMapImplementation)' == 'managed' "
9191
Include="$(_AndroidLinkerCustomStepAssembly)"
9292
AfterStep="CleanStep"
9393
Type="Microsoft.Android.Sdk.ILLink.TypeMappingStep"

Diff for: src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android.
1313
<PropertyGroup>
1414
<_AndroidRuntimePackRuntime>NativeAOT</_AndroidRuntimePackRuntime>
1515
<_AndroidJcwCodegenTarget Condition=" '$(_AndroidJcwCodegenTarget)' == '' ">JavaInterop1</_AndroidJcwCodegenTarget>
16+
<_AndroidTypeMapImplementation Condition=" '$(_AndroidTypeMapImplementation)' == '' ">managed</_AndroidTypeMapImplementation>
1617
<!-- .NET SDK gives: error NETSDK1191: A runtime identifier for the property 'PublishAot' couldn't be inferred. Specify a rid explicitly. -->
1718
<AllowPublishAotWithoutRuntimeIdentifier Condition=" '$(AllowPublishAotWithoutRuntimeIdentifier)' == '' ">true</AllowPublishAotWithoutRuntimeIdentifier>
1819
<!-- NativeAOT's targets currently gives an error about cross-compilation -->

Diff for: src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.RuntimeConfig.targets

+5
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ See: https://github.com/dotnet/runtime/blob/b13715b6984889a709ba29ea8a1961db469f
1212

1313
<PropertyGroup>
1414
<_BinaryRuntimeConfigPath>$(IntermediateOutputPath)$(ProjectRuntimeConfigFileName).bin</_BinaryRuntimeConfigPath>
15+
<_AndroidUseManagedTypeMap Condition=" '$(_AndroidTypeMapImplementation)' == 'managed' ">true</_AndroidUseManagedTypeMap>
1516
</PropertyGroup>
1617

1718
<ItemGroup>
@@ -46,6 +47,10 @@ See: https://github.com/dotnet/runtime/blob/b13715b6984889a709ba29ea8a1961db469f
4647
Value="$(AndroidAvoidEmitForPerformance)"
4748
Trim="true"
4849
/>
50+
<RuntimeHostConfigurationOption Include="Microsoft.Android.Runtime.RuntimeFeature.ManagedTypeMap"
51+
Value="$([MSBuild]::ValueOrDefault('$(_AndroidUseManagedTypeMap)', 'false'))"
52+
Trim="true"
53+
/>
4954
</ItemGroup>
5055

5156
<Target Name="_ParseRuntimeConfigFiles"

Diff for: src/Xamarin.Android.Build.Tasks/Tasks/GenerateTypeMappings.cs

+10
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Collections.Concurrent;
44
using System.Collections.Generic;
55
using System.IO;
6+
using Java.Interop.Tools.Cecil;
67
using Java.Interop.Tools.Diagnostics;
78
using Microsoft.Android.Build.Tasks;
89
using Microsoft.Build.Framework;
@@ -34,6 +35,8 @@ public class GenerateTypeMappings : AndroidTask
3435
[Output]
3536
public ITaskItem [] GeneratedBinaryTypeMaps { get; set; } = [];
3637

38+
public string TypemapImplementation { get; set; } = "llvm-ir";
39+
3740
AndroidRuntime androidRuntime;
3841

3942
public override bool RunTask ()
@@ -75,9 +78,16 @@ void WriteTypeMappings (NativeCodeGenState state)
7578
{
7679
if (androidRuntime == Xamarin.Android.Tasks.AndroidRuntime.NativeAOT) {
7780
// NativeAOT typemaps are generated in `Microsoft.Android.Sdk.ILLink.TypeMappingStep`
81+
Log.LogDebugMessage ("Skipping type maps for NativeAOT.");
7882
return;
7983
}
8084
Log.LogDebugMessage ($"Generating type maps for architecture '{state.TargetArch}'");
85+
86+
if (TypemapImplementation != "llvm-ir") {
87+
Log.LogDebugMessage ($"TypemapImplementation='{TypemapImplementation}' will write an empty native typemap.");
88+
state = new NativeCodeGenState (state.TargetArch, new TypeDefinitionCache (), state.Resolver, [], [], state.Classifier);
89+
}
90+
8191
var tmg = new TypeMapGenerator (Log, state, androidRuntime);
8292
if (!tmg.Generate (Debug, SkipJniAddNativeMethodRegistrationAttributeScan, TypemapOutputDirectory, GenerateNativeAssembly)) {
8393
throw new XamarinAndroidException (4308, Properties.Resources.XA4308);

Diff for: src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs

+8-13
Original file line numberDiff line numberDiff line change
@@ -160,26 +160,21 @@ public void NativeAOT ()
160160

161161
var linkedMonoAndroidAssembly = Path.Combine (intermediate, "android-arm64", "linked", "Mono.Android.dll");
162162
FileAssert.Exists (linkedMonoAndroidAssembly);
163+
var javaClassNames = new List<string> ();
164+
var types = new List<TypeReference> ();
165+
163166
using (var assembly = AssemblyDefinition.ReadAssembly (linkedMonoAndroidAssembly)) {
164167
var typeName = "Android.App.Activity";
165168
var methodName = "GetOnCreate_Landroid_os_Bundle_Handler";
166169
var type = assembly.MainModule.GetType (typeName);
167170
Assert.IsNotNull (type, $"{linkedMonoAndroidAssembly} should contain {typeName}");
168171
var method = type.Methods.FirstOrDefault (m => m.Name == methodName);
169172
Assert.IsNotNull (method, $"{linkedMonoAndroidAssembly} should contain {typeName}.{methodName}");
170-
}
171-
172-
var javaClassNames = new List<string> ();
173-
var types = new List<TypeReference> ();
174-
175-
var linkedRuntimeAssembly = Path.Combine (intermediate, "android-arm64", "linked", "Microsoft.Android.Runtime.NativeAOT.dll");
176-
FileAssert.Exists (linkedRuntimeAssembly);
177-
using (var assembly = AssemblyDefinition.ReadAssembly (linkedRuntimeAssembly)) {
178-
var type = assembly.MainModule.Types.FirstOrDefault (t => t.Name == "TypeMapping");
179-
Assert.IsNotNull (type, $"{linkedRuntimeAssembly} should contain TypeMapping");
180173

181-
var method = type.Methods.FirstOrDefault (m => m.Name == "GetJniNameByTypeNameHashIndex");
182-
Assert.IsNotNull (method, "TypeMapping should contain GetJniNameByTypeNameHashIndex");
174+
type = assembly.MainModule.Types.FirstOrDefault (t => t.Name == "ManagedTypeMapping");
175+
Assert.IsNotNull (type, $"{linkedMonoAndroidAssembly} should contain ManagedTypeMapping");
176+
method = type.Methods.FirstOrDefault (m => m.Name == "GetJniNameByTypeNameHashIndex");
177+
Assert.IsNotNull (method, $"{type.Name} should contain GetJniNameByTypeNameHashIndex");
183178

184179
foreach (var i in method.Body.Instructions) {
185180
if (i.OpCode != Mono.Cecil.Cil.OpCodes.Ldstr)
@@ -192,7 +187,7 @@ public void NativeAOT ()
192187
}
193188

194189
method = type.Methods.FirstOrDefault (m => m.Name == "GetTypeByJniNameHashIndex");
195-
Assert.IsNotNull (method, "TypeMapping should contain GetTypeByJniNameHashIndex");
190+
Assert.IsNotNull (method, $"{type.Name} should contain GetTypeByJniNameHashIndex");
196191

197192
foreach (var i in method.Body.Instructions) {
198193
if (i.OpCode != Mono.Cecil.Cil.OpCodes.Ldtoken)

Diff for: src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets

+1
Original file line numberDiff line numberDiff line change
@@ -1610,6 +1610,7 @@ because xbuild doesn't support framework reference assemblies.
16101610
GenerateNativeAssembly="$(_AndroidGenerateNativeAssembly)"
16111611
IntermediateOutputDirectory="$(IntermediateOutputPath)"
16121612
SkipJniAddNativeMethodRegistrationAttributeScan="$(_SkipJniAddNativeMethodRegistrationAttributeScan)"
1613+
TypemapImplementation="$(_AndroidTypeMapImplementation)"
16131614
TypemapOutputDirectory="$(_NativeAssemblySourceDir)">
16141615
</GenerateTypeMappings>
16151616

0 commit comments

Comments
 (0)