-
Notifications
You must be signed in to change notification settings - Fork 544
[mono-runtimes] cross-arm64.exe
must be a 64-bit app
#552
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
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Fixes: https://bugzilla.xamarin.com/show_bug.cgi?id=54353 When using `mono` as an AOT cross-compiler, mono's "bitness" needs to match the "bitness" of the target ABI. For example, to generate AOT native code for 32-bit armeabi, the "host" `mono` needs to run in a 32-bit process. Similarly, to generate AOT native code for 64-bit aarch64-v8a ("arm64-v8a"), the "host" `mono` needs to run in a 64-bit process. Unfortunately...that wasn't the case: $ file bin/Debug/lib/mandroid/cross-arm64.exe bin/Debug/lib/mandroid/cross-arm64.exe: PE32 executable (console) Intel 80386, for MS Windows The result is that when attempting to generate AOT native libraries for arm64 *on Windows*, it would fail: $ xbuild /p:Configuration=Release /p:AndroidSupportedAbis=arm64-v8a /p:AotAssemblies=True /t:SignAndroidPackage Project.csproj ... [aot-compiler stderr] Can't cross-compile on 32-bit platforms to 64-bit architecture. (It would work on macOS, as `bin/Debug/bin/cross-arm64` is a 64-bit executable, as is required.) The fix is to correct the `@(_MonoCrossRuntime)` value for `cross-arm64-win` so that it used the `$(MingwCommandPrefix64)`-related values, *not* the `$(MingwCommandPrefix32)`-related values. This ensures that we use compiler settings to generate 64-bit binaries, resolving the error: $ file bin/Debug/lib/mandroid/cross-arm64.exe bin/Debug/lib/mandroid/cross-arm64.exe: PE32+ executable (console) x86-64, for MS Windows --- For the d15-2 branch, also apply a subset of commits dfea975 and a08cd80 so that the `bundle.zip` contents are consistent.
jonpryor
added a commit
that referenced
this pull request
Jan 8, 2020
Changes: dotnet/java-interop@3bf5333...c0cc770 Fixes: dotnet/java-interop#525 Fixes: dotnet/java-interop#543 * dotnet/java-interop@c0cc770: [generator] Support Kotlin's unsigned types (#539) (#553) * dotnet/java-interop@5009f32: [generator] Improve generic type lookup (#552)
jonpryor
pushed a commit
that referenced
this pull request
Jan 8, 2020
Fixes: dotnet/java-interop#525 Fixes: dotnet/java-interop#543 Context: dotnet/java-interop@476597b...4565369 Context: dotnet/java-interop@71afce5 Context: https://github.com/Kotlin/KEEP/blob/13b67668ccc5b4741ecc37d0dd050fd77227c035/proposals/unsigned-types.md Context: https://kotlinlang.org/docs/reference/basic-types.html#unsigned-integers Bumps to xamarin/Java.Interop/master@45653697 * dotnet/java-interop@4565369: [generator] Improve generic type lookup (#552) * dotnet/java-interop@71afce5: [generator] Support Kotlin's unsigned types (#539) * dotnet/java-interop@f26bc27: [Java.Interop] use Dictionary<string, *>(StringComparer.Ordinal) (#550) Kotlin has experimental (!) support for unsigned types, providing the following value types: * `kotlin.UByte`: marshals as a Java `byte`/JNI `B`; equivalent to C# `byte` * `kotlin.UInt`: marshals as an Java `int`/JNI `I`; equivalent to C# `uint` * `kotlin.ULong`: marshals as a Java `long`/JNI `J`; equivalent to C# `ulong` * `kotlin.UShort`: marshals as a Java `short`/JNI `S`; equivalent to C# `ushort` Kotlin also provides arrays of these types: * `kotlin.UByteArray`: marshals as a Java `byte[]`/JNI `[B`; equivalent to C# `byte[]`, * `kotlin.UIntArray`: marshals as an Java `int[]`/JNI `[I`; equivalent to C# `uint[]`. * `kotlin.ULongArray`: marshals as a Java `long[]`/JNI `[J`; equivalent to C# `ulong[]`. * `kotlin.UShortArray`: marshals as a Java `short[]`/JNI `[S`; equivalent to C# `ushort[]`. Kotlin methods which contain unsigned types are "mangled", containing characters which cannot be part of a valid Java identifier. As such, they cannot be invoked from Java code. They *can* be invoked via JNI. To bind these, we have two options: 1. We could ignore all members which use unsigned types, or 2. We could present a "Java-esque" view of the methods. (1) is potentially problematic, as it means that abstract classes and interfaces which contain them could become unbindable, making life more complicated than is necessarily ideal. (2) is viable, but ugly. Consider this Kotlin type: // Kotlin package example; public open class ExampleBase { public fun foo(value : UInt) {} } Run `javap` on the resulting output, and we observe: Compiled from "hello.kt" public class example.ExampleBase { public final void foo-WZ4Q5Ns(int); public example.ExampleBase(); } We could bind `example.ExampleBase.foo-WZ4Q5Ns(int)` in C# by replacing invalid characters with `_`, e.g.: // C# Binding partial class ExampleBase : Java.Lang.Object { [Register ("foo-WZ4Q5Ns", …)] public void Foo_WZ4Q5Ns (int value) {…} } ...but that would be *really* ugly. We could instead just take everything before the `-` as the method name for the C# method name -- resulting in `ExampleBase.Foo()` -- which results in a friendlier name from C#, but opens us up to "collisions" with method overloads: // Kotlin public open class ExampleBase2 { public fun foo(value : Int) {} public fun foo(value : UInt) {} } The C# `ExampleBase` type can't bind *both* `ExampleBase2.foo()` methods as `Foo(int)`. The chosen solution is to "more natively" support Kotlin unsigned types, which allows reasonable disambiguation: // C# binding partial class ExampleBase2 : Java.Lang.Object { [Register ("foo", …)] public void Foo (int value) {…} [Register ("foo-WZ4Q5Ns", …)] public void Foo (uint value) {…} } Java.Interop added support for emitting C# binding code which supports Kotlin unsigned types. For `kotlin.UByte`, `kotlin.UInt`, `kotlin.ULong`, and `kotlin.UShort`, no additional runtime changes are needed to support the binding. The `*Array` counterparts *do* require additional runtime changes. Consider this Kotlin type: // Kotlin class UnsignedInstanceMethods { public open fun uintArrayInstanceMethod (value: UIntArray) : UIntArray { return value; } } The binding for this method would be: // C# binding partial class UnsignedInstanceMethods { [Register ("uintArrayInstanceMethod--ajY-9A", "([I)[I", "")] public unsafe uint[] UintArrayInstanceMethod (uint[] value) { const string __id = "uintArrayInstanceMethod--ajY-9A.([I)[I"; IntPtr native_value = JNIEnv.NewArray ((int[])(object)value); try { JniArgumentValue* __args = stackalloc JniArgumentValue [1]; __args [0] = new JniArgumentValue (native_value); var __rm = _members.InstanceMethods.InvokeNonvirtualObjectMethod (__id, this, __args); return (uint[]) JNIEnv.GetArray (__rm.Handle, JniHandleOwnership.TransferLocalRef, typeof (uint)); } finally { if (value != null) { JNIEnv.DeleteLocalRef (native_value); } } } } The problem is the `JNIEnv.GetArray(…, typeof(uint))` invocation. This eventually hits various dictionaries within `JNIEnv`, which requires additional support so that `uint` can be marshaled properly. Previous versions of Xamarin.Android do not contain support for marshaling arrays of unsigned types. As such, support for using Kotlin bindings which contain unsigned types will require Xamarin.Android 10.2.0 and later. ~~ Installer ~~ Add `protobuf-net.dll` to our installers, as it is required to read the metadata that Kotlin puts within `.class` files. ~~ Unit Tests ~~ On-device tests for calling Kotlin code that uses unsigned types have been added. As we don't currently have a way of acquiring the Kotlin compiler for builds, the test `.jar` and Kotlin's `org.jetbrains.kotlin.kotlin-stdlib.jar` are copied into the repo. They are *not* redistributed. The source of the test `.jar` is provided for future use. ~~ Warnings ~~ Kotlin unsigned types are still experimental. If Kotlin changes how they are represented in Java bytecode, bindings which use them will break. Methods which use unsigned types *cannot* be virtual, nor can they be used in bound interfaces. This is because Java source code is currently used as an "intermediary" for Java <-> Managed transitions, and Java cannot override Kotlin "mangled" methods. If the virtual method is declared on a class, it will be bound as a non-`virtual` method. If the method is on an interface, it will be bound, but the interface will not actually be implementable; a [XA4213 build-time error][0] will be generated. [0]: dotnet/java-interop@3bf5333
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes: https://bugzilla.xamarin.com/show_bug.cgi?id=54353
When using
mono
as an AOT cross-compiler, mono's "bitness" needs tomatch the "bitness" of the target ABI. For example, to generate AOT
native code for 32-bit armeabi, the "host"
mono
needs to run in a32-bit process. Similarly, to generate AOT native code for 64-bit
aarch64-v8a ("arm64-v8a"), the "host"
mono
needs to run in a 64-bitprocess.
Unfortunately...that wasn't the case:
The result is that when attempting to generate AOT native libraries
for arm64 on Windows, it would fail:
(It would work on macOS, as
bin/Debug/bin/cross-arm64
is a 64-bitexecutable, as is required.)
The fix is to correct the
@(_MonoCrossRuntime)
value forcross-arm64-win
so that it used the$(MingwCommandPrefix64)
-related values, not the$(MingwCommandPrefix32)
-related values. This ensures that we usecompiler settings to generate 64-bit binaries, resolving the error:
For the d15-2 branch, also apply a subset of commits
dfea975 and a08cd80 so that the
bundle.zip
contents are consistent.