Skip to content

Commit 3f9938a

Browse files
committed
Merge branch 'main' into dev/grendel/clr-host
* main: [NativeAOT] fix typemap logic involving duplicates (#9794) Bump to dotnet/sdk@2f1799bcac 10.0.100-preview.2.25114.7 (#9801)
2 parents b3823db + 6b1789b commit 3f9938a

File tree

5 files changed

+100
-16
lines changed

5 files changed

+100
-16
lines changed

eng/Version.Details.xml

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
<Dependencies>
22
<ProductDependencies>
3-
<Dependency Name="Microsoft.NET.Sdk" Version="10.0.100-preview.2.25108.4">
3+
<Dependency Name="Microsoft.NET.Sdk" Version="10.0.100-preview.2.25114.7">
44
<Uri>https://github.com/dotnet/sdk</Uri>
5-
<Sha>c0f88f2416d2e61f302411bdfbab3b2e87b9d35c</Sha>
5+
<Sha>2f1799bcacae4e3b7915c4c06165aec55601e3ef</Sha>
66
</Dependency>
7-
<Dependency Name="Microsoft.NET.ILLink.Tasks" Version="10.0.0-preview.2.25107.7" CoherentParentDependency="Microsoft.NET.Sdk">
7+
<Dependency Name="Microsoft.NET.ILLink.Tasks" Version="10.0.0-preview.2.25112.7" CoherentParentDependency="Microsoft.NET.Sdk">
88
<Uri>https://github.com/dotnet/runtime</Uri>
9-
<Sha>7324dd154599807cad1e4c65b2fcf3acd0a01bfe</Sha>
9+
<Sha>751acdef8e947ab5bd602721ea0cd7884c5a3e4a</Sha>
1010
</Dependency>
11-
<Dependency Name="Microsoft.NETCore.App.Ref" Version="10.0.0-preview.2.25107.7" CoherentParentDependency="Microsoft.NET.Sdk">
11+
<Dependency Name="Microsoft.NETCore.App.Ref" Version="10.0.0-preview.2.25112.7" CoherentParentDependency="Microsoft.NET.Sdk">
1212
<Uri>https://github.com/dotnet/runtime</Uri>
13-
<Sha>7324dd154599807cad1e4c65b2fcf3acd0a01bfe</Sha>
13+
<Sha>751acdef8e947ab5bd602721ea0cd7884c5a3e4a</Sha>
1414
</Dependency>
1515
<Dependency Name="Microsoft.NET.Workload.Emscripten.Current.Manifest-10.0.100.Transport" Version="10.0.0-preview.2.25105.3" CoherentParentDependency="Microsoft.NETCore.App.Ref">
1616
<Uri>https://github.com/dotnet/emsdk</Uri>

eng/Versions.props

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
<Project>
22
<!--Package versions-->
33
<PropertyGroup>
4-
<MicrosoftNETSdkPackageVersion>10.0.100-preview.2.25108.4</MicrosoftNETSdkPackageVersion>
4+
<MicrosoftNETSdkPackageVersion>10.0.100-preview.2.25114.7</MicrosoftNETSdkPackageVersion>
55
<MicrosoftDotnetSdkInternalPackageVersion>$(MicrosoftNETSdkPackageVersion)</MicrosoftDotnetSdkInternalPackageVersion>
6-
<MicrosoftNETILLinkTasksPackageVersion>10.0.0-preview.2.25107.7</MicrosoftNETILLinkTasksPackageVersion>
7-
<MicrosoftNETCoreAppRefPackageVersion>10.0.0-preview.2.25107.7</MicrosoftNETCoreAppRefPackageVersion>
6+
<MicrosoftNETILLinkTasksPackageVersion>10.0.0-preview.2.25112.7</MicrosoftNETILLinkTasksPackageVersion>
7+
<MicrosoftNETCoreAppRefPackageVersion>10.0.0-preview.2.25112.7</MicrosoftNETCoreAppRefPackageVersion>
88
<MicrosoftDotNetApiCompatPackageVersion>7.0.0-beta.22103.1</MicrosoftDotNetApiCompatPackageVersion>
99
<MicrosoftDotNetBuildTasksFeedPackageVersion>10.0.0-beta.24476.2</MicrosoftDotNetBuildTasksFeedPackageVersion>
1010
<MicrosoftNETWorkloadEmscriptenCurrentManifest100100TransportVersion>10.0.0-preview.2.25105.3</MicrosoftNETWorkloadEmscriptenCurrentManifest100100TransportVersion>

src/Microsoft.Android.Sdk.ILLink/TypeMappingStep.cs

+40-6
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public class TypeMappingStep : BaseStep
1616
{
1717
const string AssemblyName = "Microsoft.Android.Runtime.NativeAOT";
1818
const string TypeName = "Microsoft.Android.Runtime.NativeAotTypeManager";
19-
readonly IDictionary<string, TypeDefinition> TypeMappings = new Dictionary<string, TypeDefinition> (StringComparer.Ordinal);
19+
readonly IDictionary<string, List<TypeDefinition>> TypeMappings = new Dictionary<string, List<TypeDefinition>> (StringComparer.Ordinal);
2020
AssemblyDefinition? MicrosoftAndroidRuntimeNativeAot;
2121

2222
protected override void ProcessAssembly (AssemblyDefinition assembly)
@@ -66,7 +66,7 @@ protected override void EndProcess ()
6666
var il = method.Body.GetILProcessor ();
6767
var addMethod = module.ImportReference (typeof (IDictionary<string, Type>).GetMethod ("Add"));
6868
var getTypeFromHandle = module.ImportReference (typeof (Type).GetMethod ("GetTypeFromHandle"));
69-
foreach (var (javaKey, typeDefinition) in TypeMappings) {
69+
foreach (var (javaName, list) in TypeMappings) {
7070
/*
7171
* IL_0000: ldarg.0
7272
* IL_0001: ldfld class [System.Runtime]System.Collections.Generic.IDictionary`2<string, class [System.Runtime]System.Type> Microsoft.Android.Runtime.NativeAotTypeManager::TypeMappings
@@ -77,22 +77,56 @@ protected override void EndProcess ()
7777
*/
7878
il.Emit (Mono.Cecil.Cil.OpCodes.Ldarg_0);
7979
il.Emit (Mono.Cecil.Cil.OpCodes.Ldfld, field);
80-
il.Emit (Mono.Cecil.Cil.OpCodes.Ldstr, javaKey);
81-
il.Emit (Mono.Cecil.Cil.OpCodes.Ldtoken, module.ImportReference (typeDefinition));
80+
il.Emit (Mono.Cecil.Cil.OpCodes.Ldstr, javaName);
81+
il.Emit (Mono.Cecil.Cil.OpCodes.Ldtoken, module.ImportReference (SelectTypeDefinition (javaName, list)));
8282
il.Emit (Mono.Cecil.Cil.OpCodes.Call, getTypeFromHandle);
8383
il.Emit (Mono.Cecil.Cil.OpCodes.Callvirt, addMethod);
8484
}
8585

8686
il.Emit (Mono.Cecil.Cil.OpCodes.Ret);
8787
}
8888

89+
TypeDefinition SelectTypeDefinition (string javaName, List<TypeDefinition> list)
90+
{
91+
if (list.Count == 1)
92+
return list[0];
93+
94+
var best = list[0];
95+
foreach (var type in list) {
96+
if (type == best)
97+
continue;
98+
// Types in Mono.Android assembly should be first in the list
99+
if (best.Module.Assembly.Name.Name != "Mono.Android" &&
100+
type.Module.Assembly.Name.Name == "Mono.Android") {
101+
best = type;
102+
continue;
103+
}
104+
// We found the `Invoker` type *before* the declared type
105+
// Fix things up so the abstract type is first, and the `Invoker` is considered a duplicate.
106+
if ((type.IsAbstract || type.IsInterface) &&
107+
!best.IsAbstract &&
108+
!best.IsInterface &&
109+
type.IsAssignableFrom (best, Context)) {
110+
best = type;
111+
continue;
112+
}
113+
}
114+
foreach (var type in list) {
115+
if (type == best)
116+
continue;
117+
Context.LogMessage ($"Duplicate typemap entry for {javaName} => {type.FullName}");
118+
}
119+
return best;
120+
}
121+
89122
void ProcessType (AssemblyDefinition assembly, TypeDefinition type)
90123
{
91124
if (type.HasJavaPeer (Context)) {
92125
var javaName = JavaNativeTypeManager.ToJniName (type, Context);
93-
if (!TypeMappings.TryAdd (javaName, type)) {
94-
Context.LogMessage ($"Duplicate typemap entry for {javaName}");
126+
if (!TypeMappings.TryGetValue (javaName, out var list)) {
127+
TypeMappings.Add (javaName, list = new List<TypeDefinition> ());
95128
}
129+
list.Add (type);
96130
}
97131

98132
if (!type.HasNestedTypes)

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs

-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ public void DotNetBuild (string runtimeIdentifiers, bool isRelease, bool aot, bo
4141
new Package { Id = "Microsoft.AspNetCore.Components.WebView", Version = "8.0.*" },
4242
new Package { Id = "Microsoft.Extensions.FileProviders.Embedded", Version = "8.0.*" },
4343
new Package { Id = "Microsoft.JSInterop", Version = "8.0.*" },
44-
new Package { Id = "System.Text.Json", Version = "8.0.*" },
4544
},
4645
Sources = {
4746
new BuildItem ("EmbeddedResource", "Resource.resx") {

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs

+51
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,11 @@ public void NativeAOT ()
135135
proj.SetProperty ("PublishAot", "true");
136136
proj.SetProperty ("PublishAotUsingRuntimePack", "true");
137137
proj.SetProperty ("AndroidNdkDirectory", AndroidNdkPath);
138+
proj.SetProperty ("_ExtraTrimmerArgs", "--verbose");
139+
140+
// Required for java/util/ArrayList assertion below
141+
proj.MainActivity = proj.DefaultMainActivity
142+
.Replace ("//${AFTER_ONCREATE}", "new Android.Runtime.JavaList (); new Android.Runtime.JavaList<int> ();");
138143

139144
using var b = CreateApkBuilder ();
140145
Assert.IsTrue (b.Build (proj), "Build should have succeeded.");
@@ -165,6 +170,43 @@ public void NativeAOT ()
165170
Assert.IsNotNull (method, $"{linkedMonoAndroidAssembly} should contain {typeName}.{methodName}");
166171
}
167172

173+
var typemap = new Dictionary<string, TypeReference> ();
174+
var linkedRuntimeAssembly = Path.Combine (intermediate, "linked", "Microsoft.Android.Runtime.NativeAOT.dll");
175+
FileAssert.Exists (linkedRuntimeAssembly);
176+
using (var assembly = AssemblyDefinition.ReadAssembly (linkedRuntimeAssembly)) {
177+
var type = assembly.MainModule.Types.FirstOrDefault (t => t.Name == "NativeAotTypeManager");
178+
Assert.IsNotNull (type, $"{linkedRuntimeAssembly} should contain NativeAotTypeManager");
179+
var method = type.Methods.FirstOrDefault (m => m.Name == "InitializeTypeMappings");
180+
Assert.IsNotNull (method, "NativeAotTypeManager should contain InitializeTypeMappings");
181+
182+
foreach (var i in method.Body.Instructions) {
183+
if (i.OpCode != Mono.Cecil.Cil.OpCodes.Ldstr)
184+
continue;
185+
if (i.Operand is not string javaName)
186+
continue;
187+
if (i.Next.Operand is not TypeReference t)
188+
continue;
189+
typemap.Add (javaName, t);
190+
}
191+
192+
// Basic types
193+
AssertTypeMap ("java/lang/Object", "Java.Lang.Object");
194+
AssertTypeMap ("java/lang/String", "Java.Lang.String");
195+
AssertTypeMap ("[Ljava/lang/Object;", "Java.Interop.JavaArray`1");
196+
AssertTypeMap ("java/util/ArrayList", "Android.Runtime.JavaList");
197+
AssertTypeMap ("android/app/Activity", "Android.App.Activity");
198+
AssertTypeMap ("android/widget/Button", "Android.Widget.Button");
199+
Assert.IsFalse (StringAssertEx.ContainsText (b.LastBuildOutput,
200+
"Duplicate typemap entry for java/util/ArrayList => Android.Runtime.JavaList`1"),
201+
"Should get log message about duplicate Android.Runtime.JavaList`1!");
202+
203+
// Special *Invoker case
204+
AssertTypeMap ("android/view/View$OnClickListener", "Android.Views.View/IOnClickListener");
205+
Assert.IsFalse (StringAssertEx.ContainsText (b.LastBuildOutput,
206+
"Duplicate typemap entry for android/view/View$OnClickListener => Android.Views.View/IOnClickListenerInvoker"),
207+
"Should get log message about duplicate IOnClickListenerInvoker!");
208+
}
209+
168210
var dexFile = Path.Combine (intermediate, "android", "bin", "classes.dex");
169211
FileAssert.Exists (dexFile);
170212
foreach (var className in mono_classes) {
@@ -180,6 +222,15 @@ public void NativeAOT ()
180222
foreach (var nativeaot_file in nativeaot_files) {
181223
Assert.IsTrue (zip.ContainsEntry (nativeaot_file, caseSensitive: true), $"APK must contain `{nativeaot_file}`.");
182224
}
225+
226+
void AssertTypeMap(string javaName, string managedName)
227+
{
228+
if (typemap.TryGetValue (javaName, out var reference)) {
229+
Assert.AreEqual (managedName, reference.ToString ());
230+
} else {
231+
Assert.Fail ($"InitializeTypeMappings should contain Ldstr \"{javaName}\"!");
232+
}
233+
}
183234
}
184235

185236
[Test]

0 commit comments

Comments
 (0)