Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[nativeaot] run Mono.Android-Tests #9846

Draft
wants to merge 12 commits into
base: main
Choose a base branch
from

Conversation

jonathanpeppers
Copy link
Member

This is WIP, it doesn't even build quite yet.

@jonathanpeppers jonathanpeppers mentioned this pull request Feb 24, 2025
10 tasks
jonathanpeppers added a commit to dotnet/java-interop that referenced this pull request Feb 25, 2025
Context: dotnet/android#9846

When trying to build `Mono.Android-Tests` for NativeAOT, I get many
warnings like this (that are upgraded to errors):

    src\Java.Interop.GenericMarshaler\Java.Interop.GenericMarshaler\JniPeerInstanceMethodsExtensions.cs(10874,17):
    error IL2091: 'T' generic argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors' in 'Java.Interop.JniRuntime.JniValueManager.GetValueMarshaler<T>()'. The generic parameter 'T16' of 'Java.Interop.GenericMarshaler.JniPeerInstanceMethodsExtensions.InvokeGenericVirtualObjectMethod<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>(JniInstanceMethods, String, IJavaPeerable, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.
    Build failed with 2992 error(s) in 4.8s

To solve this here, we can import:

    <Import Project="..\..\build-tools\trim-analyzers\trim-analyzers.props" />

To see all the warnings *here*, and then I added the missing
attributes to solve the warnings.
jonpryor pushed a commit to dotnet/java-interop that referenced this pull request Feb 26, 2025
Context: dotnet/android#9846

When trying to build `Mono.Android-Tests` for NativeAOT, I get many
warnings like this (that are upgraded to errors):

	src\Java.Interop.GenericMarshaler\Java.Interop.GenericMarshaler\JniPeerInstanceMethodsExtensions.cs(10874,17):
	error IL2091: 'T' generic argument does not satisfy 'DynamicallyAccessedMemberTypes.PublicConstructors', 'DynamicallyAccessedMemberTypes.NonPublicConstructors' in 'Java.Interop.JniRuntime.JniValueManager.GetValueMarshaler<T>()'. The generic parameter 'T16' of 'Java.Interop.GenericMarshaler.JniPeerInstanceMethodsExtensions.InvokeGenericVirtualObjectMethod<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>(JniInstanceMethods, String, IJavaPeerable, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16)' does not have matching annotations. The source value must declare at least the same requirements as those declared on the target location it is assigned to.
	Build failed with 2992 error(s) in 4.8s

To solve this here, we can import:

	<Import Project="..\..\build-tools\trim-analyzers\trim-analyzers.props" />

To see all the warnings *here*, and then I added the missing
attributes to solve the warnings.
@jonathanpeppers jonathanpeppers force-pushed the dev/peppers/mono.android-tests-nativeaot branch 2 times, most recently from 3e1f3c0 to b4c9a2e Compare February 27, 2025 16:38
jonathanpeppers added a commit to jonathanpeppers/runtime that referenced this pull request Feb 27, 2025
Context: dotnet/android#9846

Trying to build our `Mono.Android-Tests` suite for NativeAOT, it fails
with:

    EXEC Failed to load assembly 'System.IO'

Which is caused by passing:

    --root:System.IO

I couldn't find anything in the Android workload that would cause this.

It appears the `Microsoft.NETCore.Native.targets` have an issue caused
by this specific project:

* When adding to `@(_IlcRootedAssemblies)` it does an `Exists()` check

* So `Exists('System.IO.Compression')` is called. This is *true*
  because there is a folder in the working directory named
  `System.IO.Compression`!

https://github.com/dotnet/android/tree/main/tests/Mono.Android-Tests/Mono.Android-Tests/System.IO.Compression

* `%(FileName)` is then `System.IO` as `.Compression` is stripped as
  the `%(Extension)` metadata.

I believe the fix here is to use `System.IO.File.Exists()` instead of
MSBuild's `Exists()` as it returns `true` for files *and* folders.
jonathanpeppers added a commit to dotnet/runtime that referenced this pull request Feb 27, 2025
Context: dotnet/android#9846

Trying to build our `Mono.Android-Tests` suite for NativeAOT, it fails
with:

    EXEC Failed to load assembly 'System.IO'

Which is caused by passing:

    --root:System.IO

I couldn't find anything in the Android workload that would cause this.

It appears the `Microsoft.NETCore.Native.targets` have an issue caused
by this specific project:

* When adding to `@(_IlcRootedAssemblies)` it does an `Exists()` check

* So `Exists('System.IO.Compression')` is called. This is *true*
  because there is a folder in the working directory named
  `System.IO.Compression`!

https://github.com/dotnet/android/tree/main/tests/Mono.Android-Tests/Mono.Android-Tests/System.IO.Compression

* `%(FileName)` is then `System.IO` as `.Compression` is stripped as
  the `%(Extension)` metadata.

I believe the fix here is to use `System.IO.File.Exists()` instead of
MSBuild's `Exists()` as it returns `true` for files *and* folders.
jonpryor pushed a commit that referenced this pull request Feb 28, 2025
Context: #9846

Running `tests/Mono.Android-Tests` on NativeAOT crashes with:

	E NUnit   : Error: System.NotSupportedException: NotSupported_CodeBase (TaskId:30)
	E NUnit   :    at System.Reflection.Runtime.Assemblies.RuntimeAssemblyInfo.get_CodeBase() + 0x34 (TaskId:30)
	E NUnit   :    at NUnit.Framework.Internal.AssemblyHelper.GetAssemblyPath(Assembly) + 0x10 (TaskId:30)
	E NUnit   :    at NUnit.Framework.Internal.NUnitLiteTestAssemblyBuilder.Build(Assembly, IDictionary) + 0x8c (TaskId:30)
	E NUnit   :    at NUnit.Framework.Internal.NUnitLiteTestAssemblyRunner.Load(Assembly, IDictionary) + 0x28 (TaskId:30)
	E NUnit   :    at Xamarin.Android.UnitTests.NUnit.NUnitTestRunner.Run(IList`1) + 0x1ac (TaskId:30)
	E NUnit   :    at Xamarin.Android.UnitTests.TestInstrumentation`1.RunTests(Bundle&) + 0xc8 (TaskId:30)
	E NUnit   :    at Xamarin.Android.UnitTests.TestInstrumentation`1.OnStart() + 0x48 (TaskId:30)

It appears we can just remove all usage of `Assembly.CodeBase` from
NUnitLite to get past this error.
jonpryor pushed a commit that referenced this pull request Feb 28, 2025
…#9858)

Context: #9846
Context: dbb0b92
Context: d70db5b

While trying to *build* `tests/Mono.Android-Tests` with NativeAOT:

	dotnet-local.cmd build tests/Mono.Android-Tests/Mono.Android-Tests/Mono.Android.NET-Tests.csproj ^
	  -p:TestsFlavor=NativeAOT -p:PublishAot=true -c Release -bl -t:Install

it would fail to build:

	tests\Mono.Android-Tests\Java.Interop-Tests\obj\Release\net10.0-android\generated\src\Net.Dot.Jni.Test.MyJavaInterfaceImpl.cs(19,81):
	error CS1056: Unexpected character '`'

The offending code?

	public partial class MyJavaInterfaceImpl : global::Java.Interop.JavaObjectArray`1, global::Net.Dot.Jni.Test.IJavaInterface {
	}

which is deeply, *deeply*, wrong.

Further investigation showed that the problem was that
`Java.Interop-Tests` was trying to bind Java code, and in this case
was using `generator --codegen-target=JavaInterop1` output.

This is output we've never tried to use before in .NET for Android;
`generator --codegen-target=JavaInterop1` is experimental
(and @jonpryor's playground; see dotnet/java-interop#858), and
shouldn't be used *now* (if ever).

Ultimately, we realized that commit d70db5b was *wrong*, in that it
merged two different things:

 1. Java stub generation's "codegen target", previously settable by
    an MSBuild property `$(_AndroidCodeGenerationTarget)`
    (introduced in dbb0b92)

 2. C# `generator`s "codegen target" or `$(AndroidCodegenTarget)`

The problem was `$(_AndroidCodeGenerationTarget)` was just poorly
named making me think it was the same as `$(AndroidCodegenTarget)`.

Partially revert d70db5b and use the name `$(_AndroidJcwCodegenTarget)`
instead.

NativeAOT now defaults to:

  * `$(_AndroidJcwCodegenTarget)=JavaInterop1`
  * `$(AndroidCodegenTarget)=XAJavaInterop1`
jonpryor pushed a commit that referenced this pull request Mar 3, 2025
Context: #9846

`Mono.Android` has various test failures under NativeAOT such as:

	I NUnit   : CastJavaLangObjectArrayToByteArrayThrows
	E NUnit   :      [FAIL]
	E NUnit   :  :   Expected: <System.InvalidCastException>
	E NUnit   :   But was:  <System.DllNotFoundException> (DllNotFound_Linux, xa-internal-api,
	E NUnit   : dlopen failed: library "xa-internal-api.so" not found
	E NUnit   : dlopen failed: library "libxa-internal-api.so" not found
	E NUnit   : dlopen failed: library "xa-internal-api" not found
	E NUnit   : dlopen failed: library "libxa-internal-api" not found
	E NUnit   : )
	E NUnit   :    at System.Runtime.InteropServices.NativeLibrary.LoadLibErrorTracker.Throw(String) + 0x4c
	E NUnit   :    at Internal.Runtime.CompilerHelpers.InteropHelpers.FixupModuleCell(InteropHelpers.ModuleFixupCell*) + 0x134
	E NUnit   :    at Internal.Runtime.CompilerHelpers.InteropHelpers.ResolvePInvokeSlow(InteropHelpers.MethodFixupCell*) + 0x40
	E NUnit   :    at Android.Runtime.RuntimeNativeMethods.monodroid_TypeManager_get_java_class_name(IntPtr klass) + 0x2c
	E NUnit   :    at Java.Interop.TypeManager.GetClassName(IntPtr) + 0x10
	E NUnit   :    at Android.Runtime.JNIEnv.AssertCompatibleArrayTypes(IntPtr, Type) + 0x58
	E NUnit   :    at Android.Runtime.JNIEnv.GetArray[T](IntPtr array_ptr) + 0x24
	E NUnit   :    at Java.LangTests.ObjectArrayMarshaling.<>c__DisplayClass0_0.<CastJavaLangObjectArrayToByteArrayThrows>b__0() + 0x18
	E NUnit   :    at NUnit.Framework.Assert.Throws(IResolveConstraint, TestDelegate, String, Object[]) + 0xc4
	E NUnit   :    at Java.LangTests.ObjectArrayMarshaling.CastJavaLangObjectArrayToByteArrayThrows() + 0x150
	E NUnit   :    at libMono.Android.NET-Tests!<BaseAddress>+0x152f704
	E NUnit   :    at System.Reflection.DynamicInvokeInfo.Invoke(Object, IntPtr, Object[], BinderBundle, Boolean) + 0x10c

I updated the remaining calls in `JNIEnv.cs` to use
`JniEnvironment.Types.GetJniTypeNameFromClass()` instead.
jonpryor pushed a commit that referenced this pull request Mar 3, 2025
Context: #9846

Mono.Android-Tests running on NativeAOT can have a failure such as:

	I NUnit   : Indexer
	E NUnit   :      [FAIL]
	E NUnit   :  : System.DllNotFoundException : DllNotFound_Linux, xa-internal-api,
	E NUnit   : dlopen failed: library "xa-internal-api.so" not found
	E NUnit   : dlopen failed: library "libxa-internal-api.so" not found
	E NUnit   : dlopen failed: library "xa-internal-api" not found
	E NUnit   : dlopen failed: library "libxa-internal-api" not found
	E NUnit   :    at System.Runtime.InteropServices.NativeLibrary.LoadLibErrorTracker.Throw(String) + 0x4c
	E NUnit   :    at Internal.Runtime.CompilerHelpers.InteropHelpers.FixupModuleCell(InteropHelpers.ModuleFixupCell*) + 0x134
	E NUnit   :    at Internal.Runtime.CompilerHelpers.InteropHelpers.ResolvePInvokeSlow(InteropHelpers.MethodFixupCell*) + 0x40
	E NUnit   :    at Android.Runtime.RuntimeNativeMethods.monodroid_TypeManager_get_java_class_name(IntPtr klass) + 0x2c
	E NUnit   :    at Java.Interop.TypeManager.GetClassName(IntPtr) + 0x10
	E NUnit   :    at Java.Interop.JavaConvert.GetTypeMapping(IntPtr) + 0x28
	E NUnit   :    at Java.Interop.JavaConvert.FromJniHandle(IntPtr handle, JniHandleOwnership transfer, Type targetType) + 0x84
	E NUnit   :    at Android.Runtime.JavaList.InternalGet(Int32, Type) + 0x90
	E NUnit   :    at Java.InteropTests.JavaListTest`1.Indexer() + 0xfc
	E NUnit   :    at libMono.Android.NET-Tests!<BaseAddress>+0x152f744
	E NUnit   :    at System.Reflection.DynamicInvokeInfo.Invoke(Object, IntPtr, Object[], BinderBundle, Boolean) + 0x10c

We can update `JavaConvert.GetTypeMapping()` to use
`JniEnvironment.Types.GetJniTypeNameFromClass()` the same way it is
[done in dotnet/java-interop][0].

With this change the test passes:

	I NUnit   : Indexer
	I NUnit   :      Passed

[0]: https://github.com/dotnet/java-interop/blob/719e615910923bbce10e74b05bcc6b9585d4e176/src/Java.Interop/Java.Interop/JniEnvironment.Types.cs#L214-L220
@jonathanpeppers jonathanpeppers force-pushed the dev/peppers/mono.android-tests-nativeaot branch from 52a9160 to 18bba78 Compare March 3, 2025 18:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant