Skip to content

Commit e8fd09f

Browse files
jonathanpeppersgrendello
authored andcommitted
[Xamarin.Android.Build.Tasks] use mono.android.jar only for $(AndroidCodegenTarget)=XAJavaInterop1 (#9813)
`mono.android.jar` and `mono.android.dex` are compiled with `$(AndroidCodegenTarget)=XAJavaInterop1`. This causes problems if you build a project with `$(AndroidCodegenTarget)=JavaInterop1` as the wrong set of Java stubs will be used. For example, `dotnet new maui` using NativAOT we can get a crash such as: E .hellonativeaot: No implementation found for void mono.android.Runtime.register(java.lang.String, java.lang.Class, java.lang.String) (tried Java_mono_android_Runtime_register and Java_mono_android_Runtime_register__Ljava_lang_String_2Ljava_lang_Class_2Ljava_lang_String_2) - is the library loaded, e.g. System.loadLibrary? Which is caused by `mono.android.Runtime.register()` being called by `mono/android/view/View_OnClickListenerImplementor.java` which is compiled with `$(AndroidCodegenTarget)=XAJavaInterop1`. To fix this: * Several places already check if `$(_AndroidUseMarshalMethods)=true` and skip usage of `mono.android.jar`. * Add an additional check to verify `$(AndroidCodegenTarget)=XAJavaInterop1` Previously, `$(AndroidCodegenTarget)` was also allowed to be blank and default to `XAJavaInterop1`, but it seems better to explicitly set it. I also updated `BuildTest2.NativAOT()` to verify that `mono/android/views/View_OnClickListenerImplementor.java` is generated on disk.
1 parent 465d6c8 commit e8fd09f

File tree

3 files changed

+19
-8
lines changed

3 files changed

+19
-8
lines changed

src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -440,11 +440,12 @@ IList<string> MergeManifest (NativeCodeGenState codeGenState, Dictionary<string,
440440
List<TypeDefinition> allJavaTypes = scanner.GetJavaTypes (assemblies.Values, res);
441441
var javaTypesForJCW = new List<TypeDefinition> ();
442442

443+
// When marshal methods or non-JavaPeerStyle.XAJavaInterop1 are in use we do not want to skip non-user assemblies (such as Mono.Android) - we need to generate JCWs for them during
444+
// application build, unlike in Debug configuration or when marshal methods are disabled, in which case we use JCWs generated during Xamarin.Android
445+
// build and stored in a jar file.
446+
bool shouldSkipNonUserAssemblies = !useMarshalMethods && codeGenerationTarget == JavaPeerStyle.XAJavaInterop1;
443447
foreach (TypeDefinition type in allJavaTypes) {
444-
// When marshal methods are in use we do not want to skip non-user assemblies (such as Mono.Android) - we need to generate JCWs for them during
445-
// application build, unlike in Debug configuration or when marshal methods are disabled, in which case we use JCWs generated during Xamarin.Android
446-
// build and stored in a jar file.
447-
if ((!useMarshalMethods && !userAssemblies.ContainsKey (type.Module.Assembly.Name.Name)) || JavaTypeScanner.ShouldSkipJavaCallableWrapperGeneration (type, cache)) {
448+
if ((shouldSkipNonUserAssemblies && !userAssemblies.ContainsKey (type.Module.Assembly.Name.Name)) || JavaTypeScanner.ShouldSkipJavaCallableWrapperGeneration (type, cache)) {
448449
continue;
449450
}
450451
javaTypesForJCW.Add (type);

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,10 @@ public void NativeAOT ()
207207
"Should get log message about duplicate IOnClickListenerInvoker!");
208208
}
209209

210+
// Verify that Java stubs for Mono.Android.dll were generated, instead of using mono.android.jar/dex
211+
var onLayoutChangeListenerImplementor = Path.Combine (intermediate, "android", "src", "mono", "android", "view", "View_OnClickListenerImplementor.java");
212+
FileAssert.Exists (onLayoutChangeListenerImplementor);
213+
210214
var dexFile = Path.Combine (intermediate, "android", "bin", "classes.dex");
211215
FileAssert.Exists (dexFile);
212216
foreach (var className in mono_classes) {

src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.
271271
<AndroidApkSigningAlgorithm Condition=" '$(AndroidApkSigningAlgorithm)' == '' ">SHA256withRSA</AndroidApkSigningAlgorithm>
272272
<AndroidApkDigestAlgorithm Condition=" '$(AndroidApkDigestAlgorithm)' == '' ">SHA-256</AndroidApkDigestAlgorithm>
273273
<AndroidManifestMerger Condition=" '$(AndroidManifestMerger)' == '' ">manifestmerger.jar</AndroidManifestMerger>
274+
<AndroidCodegenTarget Condition=" '$(AndroidCodegenTarget)' == '' ">XAJavaInterop1</AndroidCodegenTarget>
274275

275276
<!-- Default Java heap size to 1GB (-Xmx1G) if not specified-->
276277
<JavaMaximumHeapSize Condition=" '$(JavaMaximumHeapSize)' == '' ">1G</JavaMaximumHeapSize>
@@ -1382,7 +1383,9 @@ because xbuild doesn't support framework reference assemblies.
13821383
<PropertyGroup>
13831384
<_AndroidJarAndDexDirectory>$(_XATargetFrameworkDirectories)</_AndroidJarAndDexDirectory>
13841385
</PropertyGroup>
1385-
<GetMonoPlatformJar Condition=" '$(_AndroidUseMarshalMethods)' != 'True' " TargetFrameworkDirectory="$(_AndroidJarAndDexDirectory)">
1386+
<GetMonoPlatformJar
1387+
Condition=" '$(_AndroidUseMarshalMethods)' != 'True' and '$(AndroidCodegenTarget)' == 'XAJavaInterop1' "
1388+
TargetFrameworkDirectory="$(_AndroidJarAndDexDirectory)">
13861389
<Output TaskParameter="MonoPlatformJarPath" PropertyName="MonoPlatformJarPath" />
13871390
<Output TaskParameter="MonoPlatformDexPath" PropertyName="MonoPlatformDexPath" />
13881391
</GetMonoPlatformJar>
@@ -1410,12 +1413,12 @@ because xbuild doesn't support framework reference assemblies.
14101413
/>
14111414

14121415
<Copy
1413-
Condition=" '$(_AndroidUseMarshalMethods)' != 'True' "
1416+
Condition=" '$(_AndroidUseMarshalMethods)' != 'True' and '$(AndroidCodegenTarget)' == 'XAJavaInterop1' "
14141417
SourceFiles="$(MonoPlatformJarPath)"
14151418
DestinationFiles="$(IntermediateOutputPath)android\bin\mono.android.jar"
14161419
SkipUnchangedFiles="true" />
14171420
<Touch
1418-
Condition=" '$(_AndroidUseMarshalMethods)' != 'True' "
1421+
Condition=" '$(_AndroidUseMarshalMethods)' != 'True' and '$(AndroidCodegenTarget)' == 'XAJavaInterop1' "
14191422
Files="$(IntermediateOutputPath)android\bin\mono.android.jar" />
14201423

14211424
<Touch Files="$(_AndroidStaticResourcesFlag)" AlwaysCreate="true" />
@@ -1424,7 +1427,10 @@ because xbuild doesn't support framework reference assemblies.
14241427
<FileWrites Include="$(_AndroidIntermediateJavaSourceDirectory)mono\MonoRuntimeProvider.java" />
14251428
<FileWrites Include="$(_AndroidIntermediateJavaSourceDirectory)mono\JavaInteropTypeManager.java" />
14261429
<FileWrites Include="$(MonoAndroidIntermediateAssemblyDir)machine.config" />
1427-
<FileWrites Condition=" '$(_AndroidUseMarshalMethods)' != 'True' " Include="$(IntermediateOutputPath)android\bin\mono.android.jar" />
1430+
<FileWrites
1431+
Condition=" '$(_AndroidUseMarshalMethods)' != 'True' and '$(AndroidCodegenTarget)' == 'XAJavaInterop1' "
1432+
Include="$(IntermediateOutputPath)android\bin\mono.android.jar"
1433+
/>
14281434
<FileWrites Include="$(_AndroidStaticResourcesFlag)" />
14291435
</ItemGroup>
14301436
</Target>

0 commit comments

Comments
 (0)