From 3ed9431180ee129f6502cab084c139c19f270685 Mon Sep 17 00:00:00 2001 From: Marek Habersack Date: Mon, 8 Feb 2021 10:59:35 +0100 Subject: [PATCH 1/2] [monodroid] Build the Xamarin.Android runtime for net6 This commit makes changes to build the native Xamarin.Android runtime against Mono VM shipped from the `dotnet/runtime` repository in nuget packages which also contain header files necessary to embed Mono in Xamarin.Android. Xamarin.Android runtime is now built separately for the "legacy" target, using Mono from the SDK archives, and for net6. This change required introduction of new target directories in `$XA_INSTALL_ROOT/lib`: * arm64-v8a-net6 * armeabi-v7a-net6 * x86_64-net6 * x86-net6 These directories now contain only the shared libraries together comprising the Xamarin.Android runtime: * libmono-android.*.so * libxamarin-debug-app-helper*.so * libxamarin-app.so Mono runtime libraries are not copied from their respective nuget packages. Compared to the "legacy" builds, we are missing the `libMonoPosixHelper.so` library. The helper DSO will be eventually placed in a `Mono.Posix` nuget, once we are able to separate `Mono.Posix` files from the Mono sources and place them in a separate repository. `xaprepare` is modified to generate MSBuild and cmake fragments responsible for building net6 runtime binaries. Native runtime now doesn't export any p/invoke entry points, instead it uses the new `PINVOKE_OVERRIDE` mechanism to handle the p/invoke dispatch internally. This allows us to not only hide the public symbols, but also remove the `libxa-internal-api.so` library completely. --- .external | 2 +- .gitmodules | 4 + Configuration.props | 3 + ThirdPartyNotices.txt | 29 + build-tools/automation/azure-pipelines.yaml | 2 +- .../create-packs/Directory.Build.targets | 8 +- .../Microsoft.Android.Runtime.proj | 3 +- build-tools/create-pkg/create-pkg.targets | 4 + build-tools/create-vsix/create-vsix.targets | 2 + .../installers/create-installers.targets | 12 +- build-tools/scripts/Ndk.projitems.in | 8 + .../scripts/xa_build_configuration.cmake.in | 4 + .../GeneratedMonodroidCmakeFiles.cs | 24 +- .../ConfigAndData/BuildAndroidPlatforms.cs | 14 +- .../xaprepare/ConfigAndData/CmakeBuilds.cs | 69 ++ .../xaprepare/ConfigAndData/Configurables.cs | 21 + .../xaprepare/Steps/Step_GenerateFiles.cs | 26 +- .../xaprepare/ThirdPartyNotices/bionic.cs | 31 + .../xaprepare/ThirdPartyNotices/robin-map.cs | 19 + .../xaprepare/xaprepare/xaprepare.csproj | 6 + external/robin-map | 1 + src-ThirdParty/bionic/bionic_futex.hh | 84 +++ src-ThirdParty/bionic/cxa_guard.cc | 130 ++++ .../WorkloadManifest.in.json | 3 +- .../Xamarin.ProjectTools/Common/Builder.cs | 6 +- .../Xamarin.Android.Common.targets | 7 +- src/java-runtime/java-runtime.targets | 19 +- .../java/mono/android/MonoPackageManager.java | 8 +- .../mono/android/debug-net6/BuildConfig.java | 6 + .../java/mono/android/debug/BuildConfig.java | 1 + .../android/release-net6/BuildConfig.java | 6 + .../mono/android/release/BuildConfig.java | 1 + src/monodroid/CMakeLists.txt | 112 ++- src/monodroid/jni/cpu-arch.hh | 7 +- src/monodroid/jni/cxx-abi/string.cc | 13 + src/monodroid/jni/cxx-abi/terminate.cc | 17 + src/monodroid/jni/embedded-assemblies.cc | 65 +- src/monodroid/jni/embedded-assemblies.hh | 16 +- .../jni/{jni.c => java_interop_api.c} | 29 +- src/monodroid/jni/java_interop_api.h | 230 ++++++ src/monodroid/jni/mono_android_Runtime.h | 2 + src/monodroid/jni/monodroid-glue-designer.cc | 147 ++++ src/monodroid/jni/monodroid-glue-internal.hh | 81 +- src/monodroid/jni/monodroid-glue.cc | 245 +++--- src/monodroid/jni/monodroid-glue.hh | 7 +- src/monodroid/jni/pinvoke-override-api.cc | 714 ++++++++++++++++++ src/monodroid/jni/util.hh | 4 + src/monodroid/monodroid.targets | 42 ++ 48 files changed, 2044 insertions(+), 250 deletions(-) create mode 100644 build-tools/scripts/xa_build_configuration.cmake.in create mode 100644 build-tools/xaprepare/xaprepare/ThirdPartyNotices/bionic.cs create mode 100644 build-tools/xaprepare/xaprepare/ThirdPartyNotices/robin-map.cs create mode 160000 external/robin-map create mode 100644 src-ThirdParty/bionic/bionic_futex.hh create mode 100644 src-ThirdParty/bionic/cxa_guard.cc create mode 100644 src/java-runtime/java/mono/android/debug-net6/BuildConfig.java create mode 100644 src/java-runtime/java/mono/android/release-net6/BuildConfig.java create mode 100644 src/monodroid/jni/cxx-abi/string.cc create mode 100644 src/monodroid/jni/cxx-abi/terminate.cc rename src/monodroid/jni/{jni.c => java_interop_api.c} (98%) create mode 100644 src/monodroid/jni/java_interop_api.h create mode 100644 src/monodroid/jni/monodroid-glue-designer.cc create mode 100644 src/monodroid/jni/pinvoke-override-api.cc diff --git a/.external b/.external index 4860877f91c..01e4987437b 100644 --- a/.external +++ b/.external @@ -1,2 +1,2 @@ -xamarin/monodroid:main@2e93b630e47701dae56f426fe5934846d571832b +xamarin/monodroid:main@dade1f497271f3ae5ceb1fe8c6c672b399a369ec mono/mono:2020-02@c66141a8c7ba2566c578c2dd012b2b723e006213 diff --git a/.gitmodules b/.gitmodules index 3fda7ea93db..8650c47f269 100644 --- a/.gitmodules +++ b/.gitmodules @@ -43,3 +43,7 @@ path = external/xamarin-android-tools url = https://github.com/xamarin/xamarin-android-tools branch = main +[submodule "external/robin-map"] + path = external/robin-map + url = https://github.com/Tessil/robin-map.git + branch = master diff --git a/Configuration.props b/Configuration.props index 1ac20529783..5e87a5827f3 100644 --- a/Configuration.props +++ b/Configuration.props @@ -75,8 +75,11 @@ $(AndroidToolchainDirectory)\dotnet\ $(DotNetPreviewPath)dotnet + 6.0.100 $(DotNetPreviewVersionBand)-preview.1.21109.8 + + 6.0.0-preview.2.21108.2 6.0.0 $(ILLinkVersionBand)-alpha.1.21109.1 $(AndroidToolchainDirectory)\wix\ diff --git a/ThirdPartyNotices.txt b/ThirdPartyNotices.txt index 31a8d5b57b0..d84d5f7a3e8 100644 --- a/ThirdPartyNotices.txt +++ b/ThirdPartyNotices.txt @@ -15,6 +15,7 @@ The attached notices are provided for information only. 2. bazelbuild/bazel (https://github.com/bazelbuild/bazel/) 3. force-net/crc32.net (https://github.com/force-net/Crc32.NET) 4. nunit/nunitlite (https://github.com/nunit/nunitlite/) +5. tessil/robin-map (https://github.com/Tessil/robin-map) %% android/platform/tools/base NOTICES AND INFORMATION BEGIN HERE ================================================================= @@ -487,3 +488,31 @@ THE SOFTWARE. ===================================================== END OF nunit/nunitlite NOTICES AND INFORMATION +%% tessil/robin-map NOTICES AND INFORMATION BEGIN HERE +====================================================== +MIT License + +Copyright (c) 2017 Thibaut Goetghebuer-Planchon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +====================================================== +END OF tessil/robin-map NOTICES AND INFORMATION + diff --git a/build-tools/automation/azure-pipelines.yaml b/build-tools/automation/azure-pipelines.yaml index 0352b83ed7a..7d5f66349ea 100644 --- a/build-tools/automation/azure-pipelines.yaml +++ b/build-tools/automation/azure-pipelines.yaml @@ -53,7 +53,7 @@ variables: TestAssembliesArtifactName: test-assemblies NUnitConsoleVersion: 3.11.1 DotNetCoreVersion: 3.1.405 - DotNet5Version: 5.0.100 + DotNet5Version: 5.0.200 HostedMacImage: macOS-10.15 HostedWinVS2019: Hosted Windows 2019 with VS2019 VSEngWinVS2019: Xamarin-Android-Win2019-1120 diff --git a/build-tools/create-packs/Directory.Build.targets b/build-tools/create-packs/Directory.Build.targets index 173ccd7ed0a..43efa9ab75a 100644 --- a/build-tools/create-packs/Directory.Build.targets +++ b/build-tools/create-packs/Directory.Build.targets @@ -77,10 +77,10 @@ - - - - + + + + diff --git a/build-tools/create-packs/Microsoft.Android.Runtime.proj b/build-tools/create-packs/Microsoft.Android.Runtime.proj index 2e89e21a009..cdf18885614 100644 --- a/build-tools/create-packs/Microsoft.Android.Runtime.proj +++ b/build-tools/create-packs/Microsoft.Android.Runtime.proj @@ -11,7 +11,7 @@ projects that use the Microsoft.Android framework in .NET 5. android-arm64 - arm64-v8a + arm64-v8a-net6 Microsoft.Android.Runtime.$(AndroidRID) Microsoft.Android runtime components. Please do not reference directly. <_AndroidRuntimePackAssemblyPath>runtimes\$(AndroidRID)\lib\net6.0 @@ -39,7 +39,6 @@ projects that use the Microsoft.Android framework in .NET 5. <_AndroidRuntimePackAssemblies Include="$(_MonoAndroidNETOutputDir)Mono.Android.Export.dll" /> <_AndroidRuntimePackAssets Include="$(XAInstallPrefix)xbuild\Xamarin\Android\lib\$(AndroidABI)\libmono-android.debug.so" /> <_AndroidRuntimePackAssets Include="$(XAInstallPrefix)xbuild\Xamarin\Android\lib\$(AndroidABI)\libmono-android.release.so" /> - <_AndroidRuntimePackAssets Include="$(XAInstallPrefix)xbuild\Xamarin\Android\lib\$(AndroidABI)\libxa-internal-api.so" /> <_AndroidRuntimePackAssets Include="$(XAInstallPrefix)xbuild\Xamarin\Android\lib\$(AndroidABI)\libxamarin-debug-app-helper.so" /> diff --git a/build-tools/create-pkg/create-pkg.targets b/build-tools/create-pkg/create-pkg.targets index e9d24dc0b0a..bdd498a5616 100644 --- a/build-tools/create-pkg/create-pkg.targets +++ b/build-tools/create-pkg/create-pkg.targets @@ -27,6 +27,10 @@ $(XAFrameworkDir)\lib\xamarin.android\xbuild-frameworks\MonoAndroid + + + + Microsoft/Framework/MonoAndroid/$([System.IO.Path]::GetDirectoryName(%(RelativePath))) + + Xamarin/Android/$([System.IO.Path]::GetDirectoryName(%(RelativePath))) diff --git a/build-tools/installers/create-installers.targets b/build-tools/installers/create-installers.targets index ea061103c1a..51f3f728e0f 100644 --- a/build-tools/installers/create-installers.targets +++ b/build-tools/installers/create-installers.targets @@ -227,10 +227,14 @@ <_MSBuildFiles Include="$(MSBuildSrcDir)\startup-xf.aotprofile" /> <_MSBuildFiles Include="$(MSBuildSrcDir)\r8.jar" /> <_MSBuildFiles Include="$(MSBuildSrcDir)\bundletool.jar" ExcludeFromAndroidNETSdk="true" /> - <_MSBuildFiles Include="$(MSBuildSrcDir)\java_runtime.jar" /> - <_MSBuildFiles Include="$(MSBuildSrcDir)\java_runtime_fastdev.jar" /> - <_MSBuildFiles Include="$(MSBuildSrcDir)\java_runtime.dex" /> - <_MSBuildFiles Include="$(MSBuildSrcDir)\java_runtime_fastdev.dex" /> + <_MSBuildFiles Include="$(MSBuildSrcDir)\java_runtime.jar" ExcludeFromAndroidNETSdk="true" /> + <_MSBuildFiles Include="$(MSBuildSrcDir)\java_runtime_fastdev.jar" ExcludeFromAndroidNETSdk="true" /> + <_MSBuildFiles Include="$(MSBuildSrcDir)\java_runtime.dex" ExcludeFromAndroidNETSdk="true" /> + <_MSBuildFiles Include="$(MSBuildSrcDir)\java_runtime_fastdev.dex" ExcludeFromAndroidNETSdk="true" /> + <_MSBuildFiles Include="$(MSBuildSrcDir)\java_runtime_net6.jar" ExcludeFromLegacy="true" /> + <_MSBuildFiles Include="$(MSBuildSrcDir)\java_runtime_fastdev_net6.jar" ExcludeFromLegacy="true" /> + <_MSBuildFiles Include="$(MSBuildSrcDir)\java_runtime_net6.dex" ExcludeFromLegacy="true" /> + <_MSBuildFiles Include="$(MSBuildSrcDir)\java_runtime_fastdev_net6.dex" ExcludeFromLegacy="true" /> <_MSBuildFiles Include="$(MSBuildSrcDir)\manifestmerger.jar" /> <_MSBuildFiles Include="$(MSBuildSrcDir)\protobuf-net.dll" /> <_MSBuildFiles Include="$(MSBuildSrcDir)\SgmlReaderDll.dll" /> diff --git a/build-tools/scripts/Ndk.projitems.in b/build-tools/scripts/Ndk.projitems.in index 14a9400db15..8f1971136d4 100644 --- a/build-tools/scripts/Ndk.projitems.in +++ b/build-tools/scripts/Ndk.projitems.in @@ -3,9 +3,13 @@ @NDK_RELEASE@ @NDK_ARMEABI_V7_API@ + @NDK_ARMEABI_V7_API_NET6@ @NDK_ARM64_V8A_API@ + @NDK_ARM64_V8A_API_NET6@ @NDK_X86_API@ + @NDK_X86_API_NET6@ @NDK_X86_64_API@ + @NDK_X86_64_API_NET6@ @@ -13,24 +17,28 @@ Include="armeabi-v7a" Condition=" $(AndroidSupportedTargetJitAbisForConditionalChecks.Contains (':armeabi-v7a:')) "> $(AndroidNdkApiLevel_ArmV7a) + $(AndroidNdkApiLevel_ArmV7a_NET6) $(AndroidNdkApiLevel_ArmV8a) + $(AndroidNdkApiLevel_ArmV8a_NET6) $(AndroidNdkApiLevel_X86) + $(AndroidNdkApiLevel_X86_NET6) $(AndroidNdkApiLevel_X86_64) + $(AndroidNdkApiLevel_X86_64_NET6) diff --git a/build-tools/scripts/xa_build_configuration.cmake.in b/build-tools/scripts/xa_build_configuration.cmake.in new file mode 100644 index 00000000000..ad6da1b812a --- /dev/null +++ b/build-tools/scripts/xa_build_configuration.cmake.in @@ -0,0 +1,4 @@ +set(NETCORE_APP_RUNTIME_DIR_ARM "@NETCORE_APP_RUNTIME_ANDROID_ARM@") +set(NETCORE_APP_RUNTIME_DIR_ARM64 "@NETCORE_APP_RUNTIME_ANDROID_ARM64@") +set(NETCORE_APP_RUNTIME_DIR_X86 "@NETCORE_APP_RUNTIME_ANDROID_X86@") +set(NETCORE_APP_RUNTIME_DIR_X86_64 "@NETCORE_APP_RUNTIME_ANDROID_X86_64@") diff --git a/build-tools/xaprepare/xaprepare/Application/GeneratedMonodroidCmakeFiles.cs b/build-tools/xaprepare/xaprepare/Application/GeneratedMonodroidCmakeFiles.cs index 94d3af6553e..fa1b0647f6b 100644 --- a/build-tools/xaprepare/xaprepare/Application/GeneratedMonodroidCmakeFiles.cs +++ b/build-tools/xaprepare/xaprepare/Application/GeneratedMonodroidCmakeFiles.cs @@ -40,16 +40,20 @@ public override void Generate (Context context) static readonly Dictionary ApiLevelVariableNames = new Dictionary (StringComparer.Ordinal) { { AbiNames.TargetJit.AndroidArmV7a, "NDK_LEGACY_API_ARMV7A" }, + { BuildAndroidPlatforms.AndroidArmV7a_NET6, "NDK_NET6_API_ARMV7A" }, { AbiNames.TargetJit.AndroidArmV8a, "NDK_LEGACY_API_ARMV8A" }, + { BuildAndroidPlatforms.AndroidArmV8a_NET6, "NDK_NET6_API_ARMV8A" }, { AbiNames.TargetJit.AndroidX86, "NDK_LEGACY_API_X86" }, + { BuildAndroidPlatforms.AndroidX86_NET6, "NDK_NET6_API_X86" }, { AbiNames.TargetJit.AndroidX86_64, "NDK_LEGACY_API_X86_64" }, + { BuildAndroidPlatforms.AndroidX86_64_NET6, "NDK_NET6_API_X86_64" }, }; static readonly Dictionary JitAbis = new Dictionary (StringComparer.Ordinal) { - { AbiNames.TargetJit.AndroidArmV7a, String.Empty }, - { AbiNames.TargetJit.AndroidArmV8a, String.Empty }, - { AbiNames.TargetJit.AndroidX86, String.Empty }, - { AbiNames.TargetJit.AndroidX86_64, String.Empty }, + { AbiNames.TargetJit.AndroidArmV7a, BuildAndroidPlatforms.AndroidArmV7a_NET6 }, + { AbiNames.TargetJit.AndroidArmV8a, BuildAndroidPlatforms.AndroidArmV8a_NET6 }, + { AbiNames.TargetJit.AndroidX86, BuildAndroidPlatforms.AndroidX86_NET6 }, + { AbiNames.TargetJit.AndroidX86_64, BuildAndroidPlatforms.AndroidX86_64_NET6 }, }; static readonly Dictionary HostAbis = new Dictionary (StringComparer.Ordinal) { @@ -107,9 +111,13 @@ void GenerateShellConfig (Context context, StreamWriter sw) sw.WriteLine (); WriteApiLevelVariable (AbiNames.TargetJit.AndroidArmV7a); + WriteApiLevelVariable (BuildAndroidPlatforms.AndroidArmV7a_NET6); WriteApiLevelVariable (AbiNames.TargetJit.AndroidArmV8a); + WriteApiLevelVariable (BuildAndroidPlatforms.AndroidArmV8a_NET6); WriteApiLevelVariable (AbiNames.TargetJit.AndroidX86); + WriteApiLevelVariable (BuildAndroidPlatforms.AndroidX86_NET6); WriteApiLevelVariable (AbiNames.TargetJit.AndroidX86_64); + WriteApiLevelVariable (BuildAndroidPlatforms.AndroidX86_64_NET6); sw.WriteLine (); string indent = "\t"; @@ -240,8 +248,8 @@ void WriteShellRuntimeCommand (StreamWriter sw, Dictionary abis, foreach (var kvp in abis) { string abi = kvp.Key; - string apiLevelVarName = kvp.Key; - string outputDirName = abi; + string apiLevelVarName = command.IsNet6 ? kvp.Value : kvp.Key; + string outputDirName = command.IsNet6 ? $"{abi}-net6" : abi; string isMxe = "no"; string mxeBitness = String.Empty; bool forMxe = false; @@ -353,7 +361,6 @@ void GenerateMonodroidTargets (Context context, StreamWriter sw) { "@NATIVE_API_LEVEL@", "" }, { "@ABI@", "%(AndroidSupportedTargetJitAbi.Identity)" }, { "@OUTPUT_DIRECTORY@", "" }, - }; var hostRuntimeReplacements = new Dictionary (StringComparer.Ordinal) { @@ -419,12 +426,13 @@ string EnsureRequired (string name, string v) void WriteMSBuildConfigureAndroidRuntimeCommands (StreamWriter sw, string indent, CmakeBuilds.RuntimeCommand command, Dictionary replacements) { const string LegacyOutputDirectory = "$(OutputPath)%(AndroidSupportedTargetJitAbi.Identity)"; + const string Net6OutputDirectory = LegacyOutputDirectory + "-net6"; WriteMSBuildConfigureRuntimeCommands ( sw, indent, $"$(IntermediateOutputPath)%(AndroidSupportedTargetJitAbi.Identity)-{command.Suffix}", - LegacyOutputDirectory, + command.IsNet6 ? Net6OutputDirectory : LegacyOutputDirectory, "@(AndroidSupportedTargetJitAbi)", CmakeBuilds.ConfigureAndroidRuntimeCommandsCommonFlags, command, diff --git a/build-tools/xaprepare/xaprepare/ConfigAndData/BuildAndroidPlatforms.cs b/build-tools/xaprepare/xaprepare/ConfigAndData/BuildAndroidPlatforms.cs index cb1c4b41a56..4567610119a 100644 --- a/build-tools/xaprepare/xaprepare/ConfigAndData/BuildAndroidPlatforms.cs +++ b/build-tools/xaprepare/xaprepare/ConfigAndData/BuildAndroidPlatforms.cs @@ -42,11 +42,17 @@ class BuildAndroidPlatforms new AndroidPlatform (apiName: "S", apiLevel: 31, platformID: "S", include: "v11.0.99", framework: "v11.0.99", stable: false), }; + // These are here until we can drop "legacy" targets and use only .NET6+ + public const string AndroidArmV7a_NET6 = AbiNames.TargetJit.AndroidArmV7a + "_NET6"; + public const string AndroidArmV8a_NET6 = AbiNames.TargetJit.AndroidArmV8a + "_NET6"; + public const string AndroidX86_NET6 = AbiNames.TargetJit.AndroidX86 + "_NET6"; + public const string AndroidX86_64_NET6 = AbiNames.TargetJit.AndroidX86_64 + "_NET6"; + public static readonly Dictionary NdkMinimumAPI = new Dictionary { - { AbiNames.TargetJit.AndroidArmV7a, 16 }, - { AbiNames.TargetJit.AndroidArmV8a, 21 }, - { AbiNames.TargetJit.AndroidX86, 16 }, - { AbiNames.TargetJit.AndroidX86_64, 21 }, + { AbiNames.TargetJit.AndroidArmV7a, 16 }, { AndroidArmV7a_NET6, 21 }, + { AbiNames.TargetJit.AndroidArmV8a, 21 }, { AndroidArmV8a_NET6, 21 }, + { AbiNames.TargetJit.AndroidX86, 16 }, { AndroidX86_NET6, 21 }, + { AbiNames.TargetJit.AndroidX86_64, 21 }, { AndroidX86_64_NET6, 21 }, }; } } diff --git a/build-tools/xaprepare/xaprepare/ConfigAndData/CmakeBuilds.cs b/build-tools/xaprepare/xaprepare/ConfigAndData/CmakeBuilds.cs index 4b5a247e460..d3b03f10470 100644 --- a/build-tools/xaprepare/xaprepare/ConfigAndData/CmakeBuilds.cs +++ b/build-tools/xaprepare/xaprepare/ConfigAndData/CmakeBuilds.cs @@ -20,6 +20,7 @@ public sealed class RuntimeCommand public string Suffix = String.Empty; public string MSBuildApiLevel = String.Empty; public List? ExtraOptions = null; + public bool IsNet6 = false; public bool IsHost = false; }; @@ -83,6 +84,7 @@ public sealed class RuntimeCommand public static readonly List AsanExtraOptions = new List { "-DENABLE_CLANG_ASAN=ON", + "-DANDROID_STL=\"c++_static\"", }; public static readonly List UbsanExtraOptions = new List { @@ -91,6 +93,19 @@ public sealed class RuntimeCommand "-DANDROID_CPP_FEATURES=\"rtti exceptions\"", }; + const string enableNet6 = "-DENABLE_NET6=ON"; + public static readonly List Net6ExtraOptions = new List { + enableNet6, + }; + + public static readonly List Net6AsanExtraOptions = new List (AsanExtraOptions) { + enableNet6, + }; + + public static readonly List Net6UbsanExtraOptions = new List (UbsanExtraOptions) { + enableNet6, + }; + public static readonly List AndroidRuntimeCommands = new List { // Debug builds new RuntimeCommand { @@ -116,6 +131,33 @@ public sealed class RuntimeCommand ExtraOptions = UbsanExtraOptions, }, + new RuntimeCommand { + Suffix = "net6-Debug", + Configuration = "Release", + BuildType = "Debug", + MSBuildApiLevel = msbuildApiLevelNet6, + ExtraOptions = Net6ExtraOptions, + IsNet6 = true, + }, + + new RuntimeCommand { + Suffix = "net6-asan-Debug", + Configuration = "Release", + BuildType = "Debug", + MSBuildApiLevel = msbuildApiLevelNet6, + ExtraOptions = Net6AsanExtraOptions, + IsNet6 = true, + }, + + new RuntimeCommand { + Suffix = "net6-ubsan-Debug", + Configuration = "Release", + BuildType = "Debug", + MSBuildApiLevel = msbuildApiLevelNet6, + ExtraOptions = Net6UbsanExtraOptions, + IsNet6 = true, + }, + // Release builds new RuntimeCommand { @@ -140,6 +182,33 @@ public sealed class RuntimeCommand MSBuildApiLevel = msbuildApiLevelLegacy, ExtraOptions = UbsanExtraOptions, }, + + new RuntimeCommand { + Suffix = "net6-Release", + Configuration = "Debug", + BuildType = "Release", + MSBuildApiLevel = msbuildApiLevelNet6, + ExtraOptions = Net6ExtraOptions, + IsNet6 = true, + }, + + new RuntimeCommand { + Suffix = "net6-asan-Release", + Configuration = "Debug", + BuildType = "Release", + MSBuildApiLevel = msbuildApiLevelNet6, + ExtraOptions = Net6AsanExtraOptions, + IsNet6 = true, + }, + + new RuntimeCommand { + Suffix = "net6-ubsan-Release", + Configuration = "Debug", + BuildType = "Release", + MSBuildApiLevel = msbuildApiLevelNet6, + ExtraOptions = Net6UbsanExtraOptions, + IsNet6 = true, + }, }; public static readonly List HostRuntimeCommands = new List { diff --git a/build-tools/xaprepare/xaprepare/ConfigAndData/Configurables.cs b/build-tools/xaprepare/xaprepare/ConfigAndData/Configurables.cs index 90eee6e1251..94811ca21dc 100644 --- a/build-tools/xaprepare/xaprepare/ConfigAndData/Configurables.cs +++ b/build-tools/xaprepare/xaprepare/ConfigAndData/Configurables.cs @@ -367,6 +367,12 @@ public static partial class Paths public static string MonoArchiveLocalPath => Path.Combine (ctx.Properties.GetRequiredValue (KnownProperties.AndroidToolchainCacheDirectory), MonoArchiveFileName); public static string MonoArchiveWindowsLocalPath => Path.Combine (ctx.Properties.GetRequiredValue (KnownProperties.AndroidToolchainCacheDirectory), MonoArchiveWindowsFileName); + // .NET 6 + public static string NetcoreAppRuntimeAndroidARM => GetCachedPath (ref netcoreAppRuntimeAndroidARM, () => GetNetcoreAppRuntimePath (ctx, "arm")); + public static string NetcoreAppRuntimeAndroidARM64 => GetCachedPath (ref netcoreAppRuntimeAndroidARM64, () => GetNetcoreAppRuntimePath (ctx, "arm64")); + public static string NetcoreAppRuntimeAndroidX86 => GetCachedPath (ref netcoreAppRuntimeAndroidX86, () => GetNetcoreAppRuntimePath (ctx, "x86")); + public static string NetcoreAppRuntimeAndroidX86_64 => GetCachedPath (ref netcoreAppRuntimeAndroidX86_64, () => GetNetcoreAppRuntimePath (ctx, "x64")); + // CMake public static string CmakeMSBuildPropsName = "cmake-config.props"; public static string CmakeShellScriptsPropsName = "cmake-config.sh"; @@ -392,6 +398,17 @@ public static partial class Paths return Directory.Exists (path) ? path : Path.Combine (MonoSdksTpnExternalPath, "llvm"); }); + static string GetNetcoreAppRuntimePath (Context ctx, string androidTarget) + { + return Path.Combine ( + XAPackagesDir, + $"microsoft.netcore.app.runtime.android-{androidTarget}", + ctx.Properties.GetRequiredValue (KnownProperties.DotNetRuntimePacksVersion), + "runtimes", + $"android-{androidTarget}" + ); + } + static string DetermineNugetPackagesDir (Context ctx) { return Path.GetFullPath ( @@ -470,6 +487,10 @@ static string GetCachedPath (ref string? variable, Func creator) static string? configurationPropsGeneratedPath; static string? windowsBinutilsInstallDir; static string? hostBinutilsInstallDir; + static string? netcoreAppRuntimeAndroidARM; + static string? netcoreAppRuntimeAndroidARM64; + static string? netcoreAppRuntimeAndroidX86; + static string? netcoreAppRuntimeAndroidX86_64; static string? monodroidSourceDir; } } diff --git a/build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.cs b/build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.cs index f36482a88be..97a9a524c5a 100644 --- a/build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.cs +++ b/build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.cs @@ -48,12 +48,14 @@ protected override async Task Execute (Context context) return new List { Get_MonoGitHash_props (context), Get_Configuration_Generated_Props (context), + Get_Cmake_XA_Build_Configuration (context), new GeneratedMonodroidCmakeFiles (Configurables.Paths.BuildBinDir), }; } else { return new List { Get_Configuration_OperatingSystem_props (context), Get_Configuration_Generated_Props (context), + Get_Cmake_XA_Build_Configuration (context), new GeneratedMonodroidCmakeFiles (Configurables.Paths.BuildBinDir), Get_Ndk_projitems (context), Get_XABuildConfig_cs (context), @@ -81,12 +83,30 @@ protected override async Task Execute (Context context) partial void AddUnixPostBuildSteps (Context context, List steps); partial void AddOSSpecificSteps (Context context, List steps); + GeneratedFile Get_Cmake_XA_Build_Configuration (Context context) + { + const string OutputFileName = "xa_build_configuration.cmake"; + + var replacements = new Dictionary (StringComparer.Ordinal) { + { "@NETCORE_APP_RUNTIME_ANDROID_ARM@", Utilities.EscapePathSeparators (Configurables.Paths.NetcoreAppRuntimeAndroidARM) }, + { "@NETCORE_APP_RUNTIME_ANDROID_ARM64@", Utilities.EscapePathSeparators (Configurables.Paths.NetcoreAppRuntimeAndroidARM64) }, + { "@NETCORE_APP_RUNTIME_ANDROID_X86@", Utilities.EscapePathSeparators (Configurables.Paths.NetcoreAppRuntimeAndroidX86) }, + { "@NETCORE_APP_RUNTIME_ANDROID_X86_64@", Utilities.EscapePathSeparators (Configurables.Paths.NetcoreAppRuntimeAndroidX86_64) }, + }; + + return new GeneratedPlaceholdersFile ( + replacements, + Path.Combine (Configurables.Paths.BuildToolsScriptsDir, $"{OutputFileName}.in"), + Path.Combine (Configurables.Paths.BuildBinDir, OutputFileName) + ); + } + GeneratedFile Get_Configuration_Generated_Props (Context context) { const string OutputFileName = "Configuration.Generated.props"; var replacements = new Dictionary (StringComparer.Ordinal) { - { "@XA_PACKAGES_DIR@", Configurables.Paths.XAPackagesDir }, + { "@XA_PACKAGES_DIR@", Configurables.Paths.XAPackagesDir }, }; return new GeneratedPlaceholdersFile ( @@ -162,9 +182,13 @@ GeneratedFile Get_Ndk_projitems (Context context) var replacements = new Dictionary (StringComparer.Ordinal) { { "@NDK_RELEASE@", BuildAndroidPlatforms.AndroidNdkVersion }, { "@NDK_ARMEABI_V7_API@", BuildAndroidPlatforms.NdkMinimumAPI [AbiNames.TargetJit.AndroidArmV7a].ToString () }, + { "@NDK_ARMEABI_V7_API_NET6@", BuildAndroidPlatforms.NdkMinimumAPI [BuildAndroidPlatforms.AndroidArmV7a_NET6].ToString () }, { "@NDK_ARM64_V8A_API@", BuildAndroidPlatforms.NdkMinimumAPI [AbiNames.TargetJit.AndroidArmV8a].ToString () }, + { "@NDK_ARM64_V8A_API_NET6@", BuildAndroidPlatforms.NdkMinimumAPI [BuildAndroidPlatforms.AndroidArmV8a_NET6].ToString () }, { "@NDK_X86_API@", BuildAndroidPlatforms.NdkMinimumAPI [AbiNames.TargetJit.AndroidX86].ToString () }, + { "@NDK_X86_API_NET6@", BuildAndroidPlatforms.NdkMinimumAPI [BuildAndroidPlatforms.AndroidX86_NET6].ToString () }, { "@NDK_X86_64_API@", BuildAndroidPlatforms.NdkMinimumAPI [AbiNames.TargetJit.AndroidX86_64].ToString () }, + { "@NDK_X86_64_API_NET6@", BuildAndroidPlatforms.NdkMinimumAPI [BuildAndroidPlatforms.AndroidX86_64_NET6].ToString () }, }; return new GeneratedPlaceholdersFile ( diff --git a/build-tools/xaprepare/xaprepare/ThirdPartyNotices/bionic.cs b/build-tools/xaprepare/xaprepare/ThirdPartyNotices/bionic.cs new file mode 100644 index 00000000000..fcc87a3ae7b --- /dev/null +++ b/build-tools/xaprepare/xaprepare/ThirdPartyNotices/bionic.cs @@ -0,0 +1,31 @@ +using System; + +namespace Xamarin.Android.Prepare +{ + [TPN] + class google_bionic_TPN : ThirdPartyNotice + { + static readonly Uri url = new Uri ("https://android.googlesource.com/platform/bionic/"); + + public override string LicenseFile => String.Empty; + public override string Name => "google/bionic"; + public override Uri SourceUrl => url; + public override string LicenseText => @" +Copyright (C) 2006 The Android Open Source Project + +Licensed under the Apache License, Version 2.0 (the ""License""); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an ""AS IS"" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +"; + + public override bool Include (bool includeExternalDeps, bool includeBuildDeps) => includeExternalDeps; + } +} diff --git a/build-tools/xaprepare/xaprepare/ThirdPartyNotices/robin-map.cs b/build-tools/xaprepare/xaprepare/ThirdPartyNotices/robin-map.cs new file mode 100644 index 00000000000..560f8d62cdb --- /dev/null +++ b/build-tools/xaprepare/xaprepare/ThirdPartyNotices/robin-map.cs @@ -0,0 +1,19 @@ +using System; +using System.IO; + +namespace Xamarin.Android.Prepare +{ + [TPN] + class tessil_robin_map_TPN : ThirdPartyNotice + { + static readonly Uri url = new Uri ("https://github.com/Tessil/robin-map"); + static readonly string licenseFile = Path.Combine (Configurables.Paths.ExternalDir, "robin-map", "LICENSE"); + + public override string LicenseFile => licenseFile; + public override string Name => "tessil/robin-map"; + public override Uri SourceUrl => url; + public override string LicenseText => String.Empty; + + public override bool Include (bool includeExternalDeps, bool includeBuildDeps) => includeBuildDeps; + } +} diff --git a/build-tools/xaprepare/xaprepare/xaprepare.csproj b/build-tools/xaprepare/xaprepare/xaprepare.csproj index 1e95fdd4157..0c13e86bbc6 100644 --- a/build-tools/xaprepare/xaprepare/xaprepare.csproj +++ b/build-tools/xaprepare/xaprepare/xaprepare.csproj @@ -60,4 +60,10 @@ + + + + + + diff --git a/external/robin-map b/external/robin-map new file mode 160000 index 00000000000..a603419b9a0 --- /dev/null +++ b/external/robin-map @@ -0,0 +1 @@ +Subproject commit a603419b9a0687c9148e02c8bd5e3db180bb9ac0 diff --git a/src-ThirdParty/bionic/bionic_futex.hh b/src-ThirdParty/bionic/bionic_futex.hh new file mode 100644 index 00000000000..094ec5028ff --- /dev/null +++ b/src-ThirdParty/bionic/bionic_futex.hh @@ -0,0 +1,84 @@ +/* + * Ported to Xamarin.Android from: https://android.googlesource.com/platform/bionic/+/refs/tags/android-11.0.0_r31/libc/private/bionic_futex.h + */ + +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef _BIONIC_FUTEX_H +#define _BIONIC_FUTEX_H + +#include +#include +#include +#include +#include +#include +#include + +struct timespec; + +static inline __always_inline long __futex(volatile void* ftx, int op, int value, + const timespec* timeout, int bitset) { + // Our generated syscall assembler sets errno, but our callers (pthread functions) don't want to. + int saved_errno = errno; + long result = syscall(__NR_futex, ftx, op, value, timeout, NULL, bitset); + if (__predict_false(result == -1)) { + result = -errno; + errno = saved_errno; + } + return result; +} + +static inline long __futex_wake(volatile void* ftx, int count) { + return __futex(ftx, FUTEX_WAKE, count, nullptr, 0); +} + +static inline long __futex_wake_ex(volatile void* ftx, bool shared, int count) { + return __futex(ftx, shared ? FUTEX_WAKE : FUTEX_WAKE_PRIVATE, count, nullptr, 0); +} + +static inline long __futex_wait(volatile void* ftx, int value, const timespec* timeout) { + return __futex(ftx, FUTEX_WAIT, value, timeout, 0); +} + +static inline long __futex_wait_ex(volatile void* ftx, bool shared, int value) { + return __futex(ftx, (shared ? FUTEX_WAIT_BITSET : FUTEX_WAIT_BITSET_PRIVATE), value, nullptr, + static_cast(FUTEX_BITSET_MATCH_ANY)); +} + +__LIBC_HIDDEN__ long __futex_wait_ex(volatile void* ftx, bool shared, int value, + bool use_realtime_clock, const timespec* abs_timeout); + +static inline long __futex_pi_unlock(volatile void* ftx, bool shared) { + return __futex(ftx, shared ? FUTEX_UNLOCK_PI : FUTEX_UNLOCK_PI_PRIVATE, 0, nullptr, 0); +} + +__LIBC_HIDDEN__ long __futex_pi_lock_ex(volatile void* ftx, bool shared, bool use_realtime_clock, + const timespec* abs_timeout); + +#endif /* _BIONIC_FUTEX_H */ diff --git a/src-ThirdParty/bionic/cxa_guard.cc b/src-ThirdParty/bionic/cxa_guard.cc new file mode 100644 index 00000000000..099d8f476eb --- /dev/null +++ b/src-ThirdParty/bionic/cxa_guard.cc @@ -0,0 +1,130 @@ +// +// Ported to Xamarin.Android from: https://android.googlesource.com/platform/bionic/+/refs/tags/android-11.0.0_r31/libc/bionic/__cxa_guard.cpp +// + +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "bionic_futex.hh" + +// This file contains C++ ABI support functions for one time +// constructors as defined in the "Run-time ABI for the ARM Architecture" +// section 4.4.2 +// +// ARM C++ ABI and Itanium/x86 C++ ABI has different definition for +// one time construction: +// +// ARM C++ ABI defines the LSB of guard variable should be tested +// by compiler-generated code before calling __cxa_guard_acquire et al. +// +// The Itanium/x86 C++ ABI defines the low-order _byte_ should be +// tested instead. +// +// Meanwhile, guard variable are 32bit aligned for ARM, and 64bit +// aligned for x86. +// +// Reference documentation: +// +// section 3.2.3 of ARM IHI 0041C (for ARM) +// section 3.3.2 of the Itanium C++ ABI specification v1.83 (for x86). +// +// There is no C++ ABI available for other ARCH. But the gcc source +// shows all other ARCH follow the definition of Itanium/x86 C++ ABI. + +#if defined(__arm__) +// The ARM C++ ABI mandates that guard variables are 32-bit aligned, 32-bit +// values. The LSB is tested by the compiler-generated code before calling +// __cxa_guard_acquire. +union _guard_t { + atomic_int state; + int32_t aligner; +}; + +#else +// The Itanium/x86 C++ ABI (used by all other architectures) mandates that +// guard variables are 64-bit aligned, 64-bit values. The LSB is tested by +// the compiler-generated code before calling __cxa_guard_acquire. +union _guard_t { + atomic_int state; + int64_t aligner; +}; + +#endif + +// Set construction state values according to reference documentation. +// 0 is the initialization value. +// Arm requires ((*gv & 1) == 1) after __cxa_guard_release, ((*gv & 3) == 0) after __cxa_guard_abort. +// X86 requires first byte not modified by __cxa_guard_acquire, first byte is non-zero after +// __cxa_guard_release. + +#define CONSTRUCTION_NOT_YET_STARTED 0 +#define CONSTRUCTION_COMPLETE 1 +#define CONSTRUCTION_UNDERWAY_WITHOUT_WAITER 0x100 +#define CONSTRUCTION_UNDERWAY_WITH_WAITER 0x200 + +extern "C" int __cxa_guard_acquire(_guard_t* gv) { + int old_value = atomic_load_explicit(&gv->state, memory_order_acquire); + // In the common CONSTRUCTION_COMPLETE case we have to ensure that all the stores performed by + // the construction function are observable on this CPU after we exit. A similar constraint may + // apply in the CONSTRUCTION_NOT_YET_STARTED case with a prior abort. + + while (true) { + if (old_value == CONSTRUCTION_COMPLETE) { + return 0; + } else if (old_value == CONSTRUCTION_NOT_YET_STARTED) { + if (!atomic_compare_exchange_weak_explicit(&gv->state, &old_value, + CONSTRUCTION_UNDERWAY_WITHOUT_WAITER, + memory_order_acquire /* or relaxed in C++17 */, + memory_order_acquire)) { + continue; + } + return 1; + } else if (old_value == CONSTRUCTION_UNDERWAY_WITHOUT_WAITER) { + if (!atomic_compare_exchange_weak_explicit(&gv->state, &old_value, + CONSTRUCTION_UNDERWAY_WITH_WAITER, + memory_order_acquire /* or relaxed in C++17 */, + memory_order_acquire)) { + continue; + } + } + + __futex_wait_ex(&gv->state, false, CONSTRUCTION_UNDERWAY_WITH_WAITER); + old_value = atomic_load_explicit(&gv->state, memory_order_acquire); + } +} + +extern "C" void __cxa_guard_release(_guard_t* gv) { + // Release fence is used to make all stores performed by the construction function + // visible in other threads. + int old_value = atomic_exchange_explicit(&gv->state, CONSTRUCTION_COMPLETE, memory_order_release); + if (old_value == CONSTRUCTION_UNDERWAY_WITH_WAITER) { + __futex_wake_ex(&gv->state, false, INT_MAX); + } +} + +extern "C" void __cxa_guard_abort(_guard_t* gv) { + // Release fence is used to make all stores performed by the construction function + // visible in other threads. + int old_value = atomic_exchange_explicit(&gv->state, CONSTRUCTION_NOT_YET_STARTED, memory_order_release); + if (old_value == CONSTRUCTION_UNDERWAY_WITH_WAITER) { + __futex_wake_ex(&gv->state, false, INT_MAX); + } +} diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.NET.Workload.Android/WorkloadManifest.in.json b/src/Xamarin.Android.Build.Tasks/Microsoft.NET.Workload.Android/WorkloadManifest.in.json index e856c4e1dc1..e74c9547d6e 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.NET.Workload.Android/WorkloadManifest.in.json +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.NET.Workload.Android/WorkloadManifest.in.json @@ -17,7 +17,8 @@ "version": "@SDK_PACK_VERSION@", "alias-to": { "osx-x64": "Microsoft.Android.Sdk.osx-x64", - "win-x64": "Microsoft.Android.Sdk.win-x64" + "win-x64": "Microsoft.Android.Sdk.win-x64", + "linux-x64": "Microsoft.Android.Sdk.linux-x64" } }, "Microsoft.Android.Sdk.BundleTool": { diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Builder.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Builder.cs index e5bdd637424..06258e10dab 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Builder.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Builder.cs @@ -17,6 +17,8 @@ public class Builder : IDisposable const string SigSegvError = "Got a SIGSEGV while executing native code"; const string ConsoleLoggerError = "[ERROR] FATAL UNHANDLED EXCEPTION: System.ArgumentException: is negative"; + string Arm32AbiDir => UseDotNet ? "armeabi-v7a-net6" : "armeabi-v7a"; + /// /// If true, use `dotnet build` and IShortFormProject throughout the tests /// @@ -80,7 +82,7 @@ public string BuildOutputDirectory { get { var outdir = Environment.GetEnvironmentVariable ("XA_BUILD_OUTPUT_PATH"); string configuration = Environment.GetEnvironmentVariable ("CONFIGURATION") ?? XABuildPaths.Configuration; - var libmonodroidPath = Path.Combine ("lib", "xamarin.android", "xbuild", "Xamarin", "Android", "lib", "armeabi-v7a", "libmono-android.release.so"); + var libmonodroidPath = Path.Combine ("lib", "xamarin.android", "xbuild", "Xamarin", "Android", "lib", Arm32AbiDir, "libmono-android.release.so"); if (String.IsNullOrEmpty(outdir)) outdir = Path.GetFullPath (Path.Combine (Root, "..", "..", "..", "..", "..", "..", "..", "out")); if (!Directory.Exists (Path.Combine (outdir, "lib")) || !File.Exists (Path.Combine (outdir, libmonodroidPath))) @@ -105,7 +107,7 @@ public string BuildOutputDirectory { public string AndroidMSBuildDirectory { get { var msbuildDir = Path.Combine (BuildOutputDirectory, "lib", "xamarin.android", "xbuild", "Xamarin", "Android"); - if (Directory.Exists (msbuildDir) && File.Exists (Path.Combine (msbuildDir, "lib", "armeabi-v7a", "libmono-android.release.so"))) + if (Directory.Exists (msbuildDir) && File.Exists (Path.Combine (msbuildDir, "lib", Arm32AbiDir, "libmono-android.release.so"))) return msbuildDir; return TestEnvironment.MonoAndroidToolsDirectory; diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 491562ff420..53bfeee4bb3 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -1261,8 +1261,11 @@ because xbuild doesn't support framework reference assemblies. - <_RuntimeJar>$(MSBuildThisFileDirectory)\java_runtime.jar - <_RuntimeDex>$(MSBuildThisFileDirectory)\java_runtime.dex + <_RuntimeJar Condition=" '$(UsingAndroidNETSdk)' != 'True' ">$(MSBuildThisFileDirectory)\java_runtime.jar + <_RuntimeDex Condition=" '$(UsingAndroidNETSdk)' != 'True' ">$(MSBuildThisFileDirectory)\java_runtime.dex + + <_RuntimeJar Condition=" '$(UsingAndroidNETSdk)' == 'True' ">$(MSBuildThisFileDirectory)\java_runtime_net6.jar + <_RuntimeDex Condition=" '$(UsingAndroidNETSdk)' == 'True' ">$(MSBuildThisFileDirectory)\java_runtime_net6.dex diff --git a/src/java-runtime/java-runtime.targets b/src/java-runtime/java-runtime.targets index 99cb0d31c05..0f17932c4d7 100644 --- a/src/java-runtime/java-runtime.targets +++ b/src/java-runtime/java-runtime.targets @@ -7,14 +7,29 @@ $(OutputPath)java_runtime.dex $(IntermediateOutputPath)release $(IntermediateOutputPath)release.txt - ..\..\src-ThirdParty\bazel\java\mono\android\debug\MultiDexLoader.java;java\mono\android\debug\BuildConfig.java + ..\..\src-ThirdParty\bazel\java\mono\android\debug\MultiDexLoader.java;java\mono\android\debug\BuildConfig.java;java\mono\android\debug-net6\BuildConfig.java;java\mono\android\release-net6\BuildConfig.java <_RuntimeOutput Include="$(OutputPath)java_runtime_fastdev.jar"> $(OutputPath)java_runtime_fastdev.jar $(OutputPath)java_runtime_fastdev.dex $(IntermediateOutputPath)fastdev $(IntermediateOutputPath)fastdev.txt - ..\..\src-ThirdParty\bazel\java\mono\android\release\MultiDexLoader.java;java\mono\android\release\BuildConfig.java + ..\..\src-ThirdParty\bazel\java\mono\android\release\MultiDexLoader.java;java\mono\android\release\BuildConfig.java;java\mono\android\release-net6\BuildConfig.java;java\mono\android\debug-net6\BuildConfig.java + + + <_RuntimeOutput Include="$(OutputPath)java_runtime_net6.jar"> + $(OutputPath)java_runtime_net6.jar + $(OutputPath)java_runtime_net6.dex + $(IntermediateOutputPath)release-net6 + $(IntermediateOutputPath)release-net6.txt + ..\..\src-ThirdParty\bazel\java\mono\android\debug\MultiDexLoader.java;java\mono\android\debug-net6\BuildConfig.java;java\mono\android\debug\BuildConfig.java;java\mono\android\release\BuildConfig.java + + <_RuntimeOutput Include="$(OutputPath)java_runtime_fastdev_net6.jar"> + $(OutputPath)java_runtime_fastdev_net6.jar + $(OutputPath)java_runtime_fastdev_net6.dex + $(IntermediateOutputPath)fastdev-net6 + $(IntermediateOutputPath)fastdev-net6.txt + ..\..\src-ThirdParty\bazel\java\mono\android\release\MultiDexLoader.java;java\mono\android\release-net6\BuildConfig.java;java\mono\android\release\BuildConfig.java;java\mono\android\debug\BuildConfig.java diff --git a/src/java-runtime/java/mono/android/MonoPackageManager.java b/src/java-runtime/java/mono/android/MonoPackageManager.java index 96048d65c12..52451489f33 100644 --- a/src/java-runtime/java/mono/android/MonoPackageManager.java +++ b/src/java-runtime/java/mono/android/MonoPackageManager.java @@ -79,13 +79,9 @@ public static void LoadApplication (Context context, ApplicationInfo runtimePack } System.loadLibrary("xamarin-app"); - // .net5+ APKs don't contain `libmono-native.so` but we can't just perform a file existence check - // because we might be running with embedded DSOs enabled in which case the check would fail and we - // would have to catch the exception anyway in this case. - try { + if (!BuildConfig.DotNetRuntime) { + // .net5+ APKs don't contain `libmono-native.so` System.loadLibrary("mono-native"); - } catch (java.lang.UnsatisfiedLinkError ex) { - Log.i ("monodroid", "Failed to preload libmono-native.so (may not exist), ignoring", ex); } System.loadLibrary("monodroid"); diff --git a/src/java-runtime/java/mono/android/debug-net6/BuildConfig.java b/src/java-runtime/java/mono/android/debug-net6/BuildConfig.java new file mode 100644 index 00000000000..e05ba068714 --- /dev/null +++ b/src/java-runtime/java/mono/android/debug-net6/BuildConfig.java @@ -0,0 +1,6 @@ +package mono.android; + +public class BuildConfig { + public static boolean Debug = true; + public static boolean DotNetRuntime = true; +} diff --git a/src/java-runtime/java/mono/android/debug/BuildConfig.java b/src/java-runtime/java/mono/android/debug/BuildConfig.java index 198c2d10df9..575b166ca60 100644 --- a/src/java-runtime/java/mono/android/debug/BuildConfig.java +++ b/src/java-runtime/java/mono/android/debug/BuildConfig.java @@ -2,4 +2,5 @@ public class BuildConfig { public static boolean Debug = true; + public static boolean DotNetRuntime = false; } diff --git a/src/java-runtime/java/mono/android/release-net6/BuildConfig.java b/src/java-runtime/java/mono/android/release-net6/BuildConfig.java new file mode 100644 index 00000000000..498a947ff8c --- /dev/null +++ b/src/java-runtime/java/mono/android/release-net6/BuildConfig.java @@ -0,0 +1,6 @@ +package mono.android; + +public class BuildConfig { + public static boolean Debug = false; + public static boolean DotNetRuntime = true; +} diff --git a/src/java-runtime/java/mono/android/release/BuildConfig.java b/src/java-runtime/java/mono/android/release/BuildConfig.java index e709a143496..4070a147bb1 100644 --- a/src/java-runtime/java/mono/android/release/BuildConfig.java +++ b/src/java-runtime/java/mono/android/release/BuildConfig.java @@ -2,4 +2,5 @@ public class BuildConfig { public static boolean Debug = false; + public static boolean DotNetRuntime = false; } diff --git a/src/monodroid/CMakeLists.txt b/src/monodroid/CMakeLists.txt index 8b9c6f2bd60..b3d75cd85a1 100644 --- a/src/monodroid/CMakeLists.txt +++ b/src/monodroid/CMakeLists.txt @@ -22,6 +22,7 @@ set(CMAKE_C_EXTENSIONS OFF) option(ENABLE_CLANG_ASAN "Enable the clang AddressSanitizer support" OFF) option(ENABLE_CLANG_UBSAN "Enable the clang UndefinedBehaviorSanitizer support" OFF) +option(ENABLE_NET6 "Enable compilation for .NET6" OFF) option(ENABLE_TIMING "Build with timing support" OFF) option(STRIP_DEBUG "Strip debugging information when linking" ON) option(DISABLE_DEBUG "Disable the built-in debugging code" OFF) @@ -32,6 +33,14 @@ else() set(DEBUG_BUILD False) endif() +if(ANDROID) + if(ANDROID_STL STREQUAL none) + set(USES_LIBSTDCPP False) + else() + set(USES_LIBSTDCPP True) + endif() +endif() + # Environment checks if(NOT DEFINED MONO_PATH) @@ -106,11 +115,13 @@ endif() set(EXTERNAL_DIR "../../external") set(JAVA_INTEROP_SRC_PATH "${EXTERNAL_DIR}/Java.Interop/src/java-interop") set(SOURCES_DIR ${CMAKE_SOURCE_DIR}/jni) +set(BIONIC_SOURCES_DIR "../../src-ThirdParty/bionic") set(LZ4_SRC_DIR "${EXTERNAL_DIR}/lz4/lib") set(LZ4_INCLUDE_DIR ${LZ4_SRC_DIR}) set(XA_BIN_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../bin/${XA_BUILD_CONFIGURATION}") set(XA_BUILD_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../bin/Build${XA_BUILD_CONFIGURATION}") set(XA_LIB_TOP_DIR "${XA_BIN_DIR}/lib/xamarin.android/xbuild/Xamarin/Android/lib") +set(ROBIN_MAP_DIR "${EXTERNAL_DIR}/robin-map") if(NOT ANDROID) if(WIN32 OR MINGW) @@ -130,12 +141,29 @@ if(NOT ANDROID) endif() endif() +include("${XA_BUILD_DIR}/xa_build_configuration.cmake") + +if(ENABLE_NET6) + if(ANDROID_ABI MATCHES "^arm64-v8a") + set(NET6_RUNTIME_DIR "${NETCORE_APP_RUNTIME_DIR_ARM64}") + elseif(ANDROID_ABI MATCHES "^armeabi-v7a") + set(NET6_RUNTIME_DIR "${NETCORE_APP_RUNTIME_DIR_ARM}") + elseif(ANDROID_ABI MATCHES "^x86_64") + set(NET6_RUNTIME_DIR "${NETCORE_APP_RUNTIME_DIR_X86_64}") + elseif(ANDROID_ABI MATCHES "^x86") + set(NET6_RUNTIME_DIR "${NETCORE_APP_RUNTIME_DIR_X86}") + else() + message(FATAL "${ANDROID_ABI} is not supported for .NET6 builds") + endif() +endif() + set(LZ4_SOURCES "${LZ4_SRC_DIR}/lz4.c" ) # Include directories include_directories(${CMAKE_CURRENT_BINARY_DIR}/include/ ${CMAKE_SOURCE_DIR}/include) +include_directories(${ROBIN_MAP_DIR}/include) if(NOT ANDROID) string(REPLACE " " ";" JDK_INCLUDE_LIST ${JDK_INCLUDE}) @@ -176,7 +204,12 @@ if (WIN32) include_directories(BEFORE "jni/win32") endif() -include_directories("${XA_BIN_DIR}/include/mono-2.0") +if(ENABLE_NET6) + include_directories("${NET6_RUNTIME_DIR}/native/include/mono-2.0") +else() + include_directories("${XA_BIN_DIR}/include/mono-2.0") +endif() + include_directories("jni") include_directories("${XA_BIN_DIR}/include") include_directories("${XA_BIN_DIR}/include/${ANDROID_ABI}/eglib") @@ -196,11 +229,17 @@ xa_macos_prepare_arm64() # Compiler defines -add_compile_definitions(DHAVE_CONFIG_H) +add_compile_definitions(TSL_NO_EXCEPTIONS) +add_compile_definitions(HAVE_CONFIG_H) add_compile_definitions(_REENTRANT) add_compile_definitions(JI_DLL_EXPORT) add_compile_definitions(MONO_DLL_EXPORT) +if(ENABLE_NET6) + add_compile_definitions(NET6) + add_compile_definitions(JI_NO_VISIBILITY) +endif() + if(DEBUG_BUILD AND NOT DISABLE_DEBUG) add_compile_definitions(DEBUG) endif() @@ -341,8 +380,13 @@ endif() # Library directories if(ANDROID) - set(XA_LIBRARY_OUTPUT_DIRECTORY "${XA_LIB_TOP_DIR}/${ANDROID_ABI}") - link_directories("${XA_LIBRARY_OUTPUT_DIRECTORY}") + if(ENABLE_NET6) + set(XA_LIBRARY_OUTPUT_DIRECTORY "${XA_LIB_TOP_DIR}/${ANDROID_ABI}-net6") + link_directories("${NET6_RUNTIME_DIR}/native") + else() + set(XA_LIBRARY_OUTPUT_DIRECTORY "${XA_LIB_TOP_DIR}/${ANDROID_ABI}") + link_directories("${XA_LIBRARY_OUTPUT_DIRECTORY}") + endif() endif() if(WIN32 OR MINGW) @@ -399,7 +443,6 @@ set(XAMARIN_MONODROID_SOURCES ${SOURCES_DIR}/globals.cc ${SOURCES_DIR}/logger.cc ${SOURCES_DIR}/monodroid-glue.cc - ${SOURCES_DIR}/xa-internal-api.cc ${SOURCES_DIR}/osbridge.cc ${SOURCES_DIR}/shared-constants.cc ${SOURCES_DIR}/timezones.cc @@ -414,9 +457,18 @@ if(ANDROID) list(APPEND XAMARIN_MONODROID_SOURCES ${LZ4_SOURCES} ) + + if(NOT USES_LIBSTDCPP) + list(APPEND XAMARIN_MONODROID_SOURCES + ${BIONIC_SOURCES_DIR}/cxa_guard.cc + ${SOURCES_DIR}/cxx-abi/string.cc + ${SOURCES_DIR}/cxx-abi/terminate.cc + ) + endif() else() list(APPEND XAMARIN_MONODROID_SOURCES ${SOURCES_DIR}/designer-assemblies.cc + ${SOURCES_DIR}/monodroid-glue-designer.cc ${JAVA_INTEROP_SRC_PATH}/java-interop-gc-bridge-mono.cc ${JAVA_INTEROP_SRC_PATH}/java-interop-jvm.cc ) @@ -429,11 +481,23 @@ if(UNIX) ) endif() -set(XAMARIN_INTERNAL_API_SOURCES - ${SOURCES_DIR}/jni.c - ${SOURCES_DIR}/internal-pinvoke-api.cc - ${JAVA_INTEROP_SRC_PATH}/java-interop-util.cc - ) +if(ANDROID AND ENABLE_NET6) + list(APPEND XAMARIN_MONODROID_SOURCES + ${SOURCES_DIR}/pinvoke-override-api.cc + ${SOURCES_DIR}/java_interop_api.c + ${JAVA_INTEROP_SRC_PATH}/java-interop-util.cc + ) +else() + list(APPEND XAMARIN_MONODROID_SOURCES + ${SOURCES_DIR}/xa-internal-api.cc + ) + + set(XAMARIN_INTERNAL_API_SOURCES + ${SOURCES_DIR}/java_interop_api.c + ${SOURCES_DIR}/internal-pinvoke-api.cc + ${JAVA_INTEROP_SRC_PATH}/java-interop-util.cc + ) +endif() set(XAMARIN_APP_STUB_SOURCES ${SOURCES_DIR}/application_dso_stub.cc @@ -451,21 +515,23 @@ set(XAMARIN_DEBUG_APP_HELPER_SOURCES # Build configure_file(jni/host-config.h.in ${CMAKE_CURRENT_BINARY_DIR}/include/host-config.h) -add_library( - ${XAMARIN_INTERNAL_API_LIB} - SHARED - ${XAMARIN_INTERNAL_API_SOURCES} - ) +if(NOT (ANDROID AND ENABLE_NET6)) + add_library( + ${XAMARIN_INTERNAL_API_LIB} + SHARED + ${XAMARIN_INTERNAL_API_SOURCES} + ) -target_compile_options( - ${XAMARIN_INTERNAL_API_LIB} - PRIVATE -fvisibility=default - ) + target_compile_options( + ${XAMARIN_INTERNAL_API_LIB} + PRIVATE -fvisibility=default + ) -target_link_options( - ${XAMARIN_INTERNAL_API_LIB} - PRIVATE -fvisibility=default - ) + target_link_options( + ${XAMARIN_INTERNAL_API_LIB} + PRIVATE -fvisibility=default + ) +endif() add_library( ${XAMARIN_APP_STUB_LIB} diff --git a/src/monodroid/jni/cpu-arch.hh b/src/monodroid/jni/cpu-arch.hh index 5d66b8a959a..9be5d356e5c 100644 --- a/src/monodroid/jni/cpu-arch.hh +++ b/src/monodroid/jni/cpu-arch.hh @@ -10,5 +10,8 @@ #define CPU_KIND_X86 ((unsigned short)4) #define CPU_KIND_X86_64 ((unsigned short)5) -MONO_API void _monodroid_detect_cpu_and_architecture (unsigned short *built_for_cpu, unsigned short *running_on_cpu, unsigned char *is64bit); -#endif +#if !defined(NET6) +MONO_API +#endif // def NET6 +void _monodroid_detect_cpu_and_architecture (unsigned short *built_for_cpu, unsigned short *running_on_cpu, unsigned char *is64bit); +#endif // ndef NET6 diff --git a/src/monodroid/jni/cxx-abi/string.cc b/src/monodroid/jni/cxx-abi/string.cc new file mode 100644 index 00000000000..53b5731defc --- /dev/null +++ b/src/monodroid/jni/cxx-abi/string.cc @@ -0,0 +1,13 @@ +// +// Defining the macro will make the the explicit instantations below truely hidden +// +#define _LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS + +#include + +_LIBCPP_BEGIN_NAMESPACE_STD + +template class __attribute__ ((__visibility__("hidden"))) __basic_string_common; +template class __attribute__ ((__visibility__("hidden"))) basic_string; + +_LIBCPP_END_NAMESPACE_STD diff --git a/src/monodroid/jni/cxx-abi/terminate.cc b/src/monodroid/jni/cxx-abi/terminate.cc new file mode 100644 index 00000000000..624274a30d8 --- /dev/null +++ b/src/monodroid/jni/cxx-abi/terminate.cc @@ -0,0 +1,17 @@ +// +// Simple implementation of std::terminate() for Xamarin.Android +// +// Does NOT support terminate handlers, since we don't use them. +// +#include +#include +#include + +namespace std { + [[noreturn]] void + terminate () noexcept + { + __android_log_write (ANDROID_LOG_FATAL, "monodroid", "std::terminate() called. Aborting."); + abort (); + } +} diff --git a/src/monodroid/jni/embedded-assemblies.cc b/src/monodroid/jni/embedded-assemblies.cc index 845272eda90..c526ad5b18f 100644 --- a/src/monodroid/jni/embedded-assemblies.cc +++ b/src/monodroid/jni/embedded-assemblies.cc @@ -133,8 +133,20 @@ EmbeddedAssemblies::get_assembly_data (const MonoBundledAssembly *e, char*& asse } MonoAssembly* +#if defined (NET6) && defined (NET6_ALC_WORKS) +EmbeddedAssemblies::open_from_bundles (MonoAssemblyName* aname, MonoAssemblyLoadContextGCHandle alc_gchandle, MonoError *error) +#else // !(def NET6 && def NET6_ALC_WORKS) EmbeddedAssemblies::open_from_bundles (MonoAssemblyName* aname, bool ref_only) +#endif // def NET6 && def NET6_ALC_WORKS { +#if defined (NET6) + // NET6 doesn't support reference-only loads, define the variable here to minimize ifdefs in the code below +#if defined (NET6_ALC_WORKS) + constexpr bool ref_only = false; +#else // def NET6_ALC_WORKS + ref_only = false; +#endif // ndef NET6_ALC_WORKS +#endif // def NET6 const char *culture = mono_assembly_name_get_culture (aname); const char *asmname = mono_assembly_name_get_name (aname); @@ -176,19 +188,51 @@ EmbeddedAssemblies::open_from_bundles (MonoAssemblyName* aname, bool ref_only) get_assembly_data (e, assembly_data, assembly_data_size); - if ((image = mono_image_open_from_data_with_name (assembly_data, assembly_data_size, 0, nullptr, ref_only, name.get ())) != nullptr && - (a = mono_assembly_load_from_full (image, name.get (), &status, ref_only)) != nullptr) { - mono_config_for_assembly (image); - break; +#if defined (NET6) && defined (NET6_ALC_WORKS) + image = mono_image_open_from_data_alc ( + alc_gchandle, + assembly_data, + assembly_data_size, + 0 /* need_copy */, + nullptr /* status */, + name.get () + ); +#else // (def NET6 && def NET6_ALC_WORKS) + image = mono_image_open_from_data_with_name (assembly_data, assembly_data_size, 0, nullptr, ref_only, name.get ()); +#endif // !(def NET6 && def NET6_ALC_WORKS) + if (image == nullptr) { + continue; + } + + a = mono_assembly_load_from_full (image, name.get (), &status, ref_only); + if (a == nullptr) { + continue; } + + mono_config_for_assembly (image); + break; } - if (a && utils.should_log (LOG_ASSEMBLY)) { + if (a != nullptr && utils.should_log (LOG_ASSEMBLY)) { log_info_nocheck (LOG_ASSEMBLY, "open_from_bundles: loaded assembly: %p\n", a); } + +#if defined (NET6) && defined (NET6_ALC_WORKS) + if (error != nullptr) { + error->error_code = a == nullptr ? MONO_ERROR_NONE : MONO_ERROR_FILE_NOT_FOUND; + } +#endif // def NET6 && def NET6_ALC_WORKS return a; } +#if defined (NET6) && defined (NET6_ALC_WORKS) +MonoAssembly* +EmbeddedAssemblies::open_from_bundles (MonoAssemblyLoadContextGCHandle alc_gchandle, MonoAssemblyName *aname, [[maybe_unused]] char **assemblies_path, [[maybe_unused]] void *user_data, MonoError *error) +{ + log_warn (LOG_DEFAULT, __PRETTY_FUNCTION__); + return embeddedAssemblies.open_from_bundles (aname, alc_gchandle, error); +} +#else // def NET6 && def NET6_ALC_WORKS MonoAssembly* EmbeddedAssemblies::open_from_bundles_full (MonoAssemblyName *aname, UNUSED_ARG char **assemblies_path, UNUSED_ARG void *user_data) { @@ -200,12 +244,23 @@ EmbeddedAssemblies::open_from_bundles_refonly (MonoAssemblyName *aname, UNUSED_A { return embeddedAssemblies.open_from_bundles (aname, true); } +#endif // !(def NET6 && def NET6_ALC_WORKS) void EmbeddedAssemblies::install_preload_hooks () { +#if defined (NET6) && defined (NET6_ALC_WORKS) + mono_install_assembly_preload_hook_v3 ( + open_from_bundles, + nullptr /* user_data */, + 0 /* append */ + ); +#else // def NET6 && def NET6_ALC_WORKS mono_install_assembly_preload_hook (open_from_bundles_full, nullptr); +#if !defined (NET6) // Reference-only loads don't exist in NET6 mono_install_assembly_refonly_preload_hook (open_from_bundles_refonly, nullptr); +#endif // !def NET6 +#endif // !(def NET6 && def NET6_ALC_WORKS) } template diff --git a/src/monodroid/jni/embedded-assemblies.hh b/src/monodroid/jni/embedded-assemblies.hh index 0eaaf8c9767..2ce875dbe1f 100644 --- a/src/monodroid/jni/embedded-assemblies.hh +++ b/src/monodroid/jni/embedded-assemblies.hh @@ -6,6 +6,10 @@ #include #include +#if defined (NET6) +#include +#endif + #include "strings.hh" #include "xamarin-app.hh" @@ -72,7 +76,11 @@ namespace xamarin::android::internal { MonoReflectionType* typemap_java_to_managed (const char *java_type_name); size_t register_from (const char *apk_file, monodroid_should_register should_register); void gather_bundled_assemblies_from_apk (const char* apk, monodroid_should_register should_register); +#if defined (NET6) && defined (NET6_ALC_WORKS) + MonoAssembly* open_from_bundles (MonoAssemblyName* aname, MonoAssemblyLoadContextGCHandle alc_gchandle, MonoError *error); +#else // def NET6 && def NET6_ALC_WORKS MonoAssembly* open_from_bundles (MonoAssemblyName* aname, bool ref_only); +#endif // !(def NET6 && def NET6_ALC_WORKS) #if defined (DEBUG) || !defined (ANDROID) template bool typemap_read_header (int dir_fd, const char *file_type, const char *dir_path, const char *file_path, uint32_t expected_magic, H &header, size_t &file_size, int &fd); @@ -86,9 +94,12 @@ namespace xamarin::android::internal { bool register_debug_symbols_for_assembly (const char *entry_name, MonoBundledAssembly *assembly, const mono_byte *debug_contents, int debug_size); static md_mmap_info md_mmap_apk_file (int fd, uint32_t offset, uint32_t size, const char* filename, const char* apk); - +#if defined (NET6) && defined (NET6_ALC_WORKS) + static MonoAssembly* open_from_bundles (MonoAssemblyLoadContextGCHandle alc_gchandle, MonoAssemblyName *aname, char **assemblies_path, void *user_data, MonoError *error); +#else // def NET6 && def NET6_ALC_WORKS static MonoAssembly* open_from_bundles_full (MonoAssemblyName *aname, char **assemblies_path, void *user_data); static MonoAssembly* open_from_bundles_refonly (MonoAssemblyName *aname, char **assemblies_path, void *user_data); +#endif // !(def NET6 && def NET6_ALC_WORKS) static void get_assembly_data (const MonoBundledAssembly *e, char*& assembly_data, uint32_t& assembly_data_size); void zip_load_entries (int fd, const char *apk_name, monodroid_should_register should_register); @@ -132,5 +143,8 @@ namespace xamarin::android::internal { }; } +#if !defined (NET6) MONO_API int monodroid_embedded_assemblies_set_assemblies_prefix (const char *prefix); +#endif // ndef NET6 + #endif /* INC_MONODROID_EMBEDDED_ASSEMBLIES_H */ diff --git a/src/monodroid/jni/jni.c b/src/monodroid/jni/java_interop_api.c similarity index 98% rename from src/monodroid/jni/jni.c rename to src/monodroid/jni/java_interop_api.c index 111f401226f..c4602190919 100644 --- a/src/monodroid/jni/jni.c +++ b/src/monodroid/jni/java_interop_api.c @@ -1,35 +1,10 @@ /* * Generated file; DO NOT EDIT! * - * To make changes, edit Java.Interop/tools/jnienv-gen and rerun + * To make changes, edit Java.Interop/build-tools/jnienv-gen and rerun */ -#include - -typedef jmethodID jstaticmethodID; -typedef jfieldID jstaticfieldID; -typedef jobject jglobal; - -/* VS 2010 and later have stdint.h */ -#if defined(_MSC_VER) - - #define JI_API_EXPORT __declspec(dllexport) - #define JI_API_IMPORT __declspec(dllimport) - -#else /* defined(_MSC_VER */ - - #define JI_API_EXPORT __attribute__ ((visibility ("default"))) - #define JI_API_IMPORT - -#endif /* !defined(_MSC_VER) */ - -#if defined(JI_DLL_EXPORT) - #define JI_API JI_API_EXPORT -#elif defined(JI_DLL_IMPORT) - #define JI_API JI_API_IMPORT -#else /* !defined(JI_DLL_IMPORT) && !defined(JI_API_IMPORT) */ - #define JI_API -#endif /* JI_DLL_EXPORT... */ +#include "java_interop_api.h" JI_API jint java_interop_jnienv_get_version (JNIEnv *env) diff --git a/src/monodroid/jni/java_interop_api.h b/src/monodroid/jni/java_interop_api.h new file mode 100644 index 00000000000..012c34a2948 --- /dev/null +++ b/src/monodroid/jni/java_interop_api.h @@ -0,0 +1,230 @@ +/* + * Generated file; DO NOT EDIT! + * + * To make changes, edit Java.Interop/build-tools/jnienv-gen and rerun + */ + +#if !defined (__JAVA_INTEROP_NATIVE_H) +#define __JAVA_INTEROP_NATIVE_H + +#include + +typedef jmethodID jstaticmethodID; +typedef jfieldID jstaticfieldID; +typedef jobject jglobal; + +#if !defined(JI_NO_VISIBILITY) + /* VS 2010 and later have stdint.h */ + #if defined(_MSC_VER) + + #define JI_API_EXPORT __declspec(dllexport) + #define JI_API_IMPORT __declspec(dllimport) + + #else /* defined(_MSC_VER */ + + #define JI_API_EXPORT __attribute__ ((visibility ("default"))) + #define JI_API_IMPORT + + #endif /* !defined(_MSC_VER) */ + + #if defined(JI_DLL_EXPORT) + #define JI_API JI_API_EXPORT + #elif defined(JI_DLL_IMPORT) + #define JI_API JI_API_IMPORT + #else /* !defined(JI_DLL_IMPORT) && !defined(JI_API_IMPORT) */ + #define JI_API + #endif /* JI_DLL_EXPORT... */ +#else // JI_NO_VISIBILITY + #define JI_API +#endif // JI_NO_VISIBILITY + +JI_API jint java_interop_jnienv_get_version (JNIEnv *env); +JI_API jclass java_interop_jnienv_define_class (JNIEnv *env, jthrowable *_thrown, const char* name, jobject loader, const jbyte* buffer, jsize bufferLength); +JI_API jclass java_interop_jnienv_find_class (JNIEnv *env, jthrowable *_thrown, const char* classname); +JI_API jobject java_interop_jnienv_to_reflected_method (JNIEnv *env, jthrowable *_thrown, jclass type, jmethodID method, jboolean isStatic); +JI_API jclass java_interop_jnienv_get_superclass (JNIEnv *env, jclass type); +JI_API jboolean java_interop_jnienv_is_assignable_from (JNIEnv *env, jclass class1, jclass class2); +JI_API jobject java_interop_jnienv_to_reflected_field (JNIEnv *env, jthrowable *_thrown, jclass type, jfieldID field, jboolean isStatic); +JI_API jint java_interop_jnienv_throw (JNIEnv *env, jthrowable toThrow); +JI_API jint java_interop_jnienv_throw_new (JNIEnv *env, jclass type, const char* message); +JI_API jthrowable java_interop_jnienv_exception_occurred (JNIEnv *env); +JI_API void java_interop_jnienv_exception_describe (JNIEnv *env); +JI_API void java_interop_jnienv_exception_clear (JNIEnv *env); +JI_API void java_interop_jnienv_fatal_error (JNIEnv *env, const char* message); +JI_API jint java_interop_jnienv_push_local_frame (JNIEnv *env, jint capacity); +JI_API jobject java_interop_jnienv_pop_local_frame (JNIEnv *env, jobject result); +JI_API jglobal java_interop_jnienv_new_global_ref (JNIEnv *env, jobject instance); +JI_API void java_interop_jnienv_delete_global_ref (JNIEnv *env, jobject instance); +JI_API void java_interop_jnienv_delete_local_ref (JNIEnv *env, jobject instance); +JI_API jboolean java_interop_jnienv_is_same_object (JNIEnv *env, jobject object1, jobject object2); +JI_API jobject java_interop_jnienv_new_local_ref (JNIEnv *env, jobject instance); +JI_API jint java_interop_jnienv_ensure_local_capacity (JNIEnv *env, jint capacity); +JI_API jobject java_interop_jnienv_alloc_object (JNIEnv *env, jthrowable *_thrown, jclass type); +JI_API jobject java_interop_jnienv_new_object (JNIEnv *env, jthrowable *_thrown, jclass type, jmethodID method); +JI_API jobject java_interop_jnienv_new_object_a (JNIEnv *env, jthrowable *_thrown, jclass type, jmethodID method, jvalue* args); +JI_API jclass java_interop_jnienv_get_object_class (JNIEnv *env, jobject instance); +JI_API jboolean java_interop_jnienv_is_instance_of (JNIEnv *env, jobject instance, jclass type); +JI_API jmethodID java_interop_jnienv_get_method_id (JNIEnv *env, jthrowable *_thrown, jclass type, const char* name, const char* signature); +JI_API jobject java_interop_jnienv_call_object_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method); +JI_API jobject java_interop_jnienv_call_object_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method, jvalue* args); +JI_API jboolean java_interop_jnienv_call_boolean_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method); +JI_API jboolean java_interop_jnienv_call_boolean_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method, jvalue* args); +JI_API jbyte java_interop_jnienv_call_byte_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method); +JI_API jbyte java_interop_jnienv_call_byte_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method, jvalue* args); +JI_API jchar java_interop_jnienv_call_char_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method); +JI_API jchar java_interop_jnienv_call_char_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method, jvalue* args); +JI_API jshort java_interop_jnienv_call_short_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method); +JI_API jshort java_interop_jnienv_call_short_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method, jvalue* args); +JI_API jint java_interop_jnienv_call_int_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method); +JI_API jint java_interop_jnienv_call_int_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method, jvalue* args); +JI_API jlong java_interop_jnienv_call_long_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method); +JI_API jlong java_interop_jnienv_call_long_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method, jvalue* args); +JI_API jfloat java_interop_jnienv_call_float_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method); +JI_API jfloat java_interop_jnienv_call_float_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method, jvalue* args); +JI_API jdouble java_interop_jnienv_call_double_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method); +JI_API jdouble java_interop_jnienv_call_double_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method, jvalue* args); +JI_API void java_interop_jnienv_call_void_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method); +JI_API void java_interop_jnienv_call_void_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method, jvalue* args); +JI_API jobject java_interop_jnienv_call_nonvirtual_object_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method); +JI_API jobject java_interop_jnienv_call_nonvirtual_object_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method, jvalue* args); +JI_API jboolean java_interop_jnienv_call_nonvirtual_boolean_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method); +JI_API jboolean java_interop_jnienv_call_nonvirtual_boolean_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method, jvalue* args); +JI_API jbyte java_interop_jnienv_call_nonvirtual_byte_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method); +JI_API jbyte java_interop_jnienv_call_nonvirtual_byte_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method, jvalue* args); +JI_API jchar java_interop_jnienv_call_nonvirtual_char_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method); +JI_API jchar java_interop_jnienv_call_nonvirtual_char_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method, jvalue* args); +JI_API jshort java_interop_jnienv_call_nonvirtual_short_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method); +JI_API jshort java_interop_jnienv_call_nonvirtual_short_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method, jvalue* args); +JI_API jint java_interop_jnienv_call_nonvirtual_int_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method); +JI_API jint java_interop_jnienv_call_nonvirtual_int_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method, jvalue* args); +JI_API jlong java_interop_jnienv_call_nonvirtual_long_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method); +JI_API jlong java_interop_jnienv_call_nonvirtual_long_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method, jvalue* args); +JI_API jfloat java_interop_jnienv_call_nonvirtual_float_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method); +JI_API jfloat java_interop_jnienv_call_nonvirtual_float_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method, jvalue* args); +JI_API jdouble java_interop_jnienv_call_nonvirtual_double_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method); +JI_API jdouble java_interop_jnienv_call_nonvirtual_double_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method, jvalue* args); +JI_API void java_interop_jnienv_call_nonvirtual_void_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method); +JI_API void java_interop_jnienv_call_nonvirtual_void_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method, jvalue* args); +JI_API jfieldID java_interop_jnienv_get_field_id (JNIEnv *env, jthrowable *_thrown, jclass type, const char* name, const char* signature); +JI_API jobject java_interop_jnienv_get_object_field (JNIEnv *env, jobject instance, jfieldID field); +JI_API jboolean java_interop_jnienv_get_boolean_field (JNIEnv *env, jobject instance, jfieldID field); +JI_API jbyte java_interop_jnienv_get_byte_field (JNIEnv *env, jobject instance, jfieldID field); +JI_API jchar java_interop_jnienv_get_char_field (JNIEnv *env, jobject instance, jfieldID field); +JI_API jshort java_interop_jnienv_get_short_field (JNIEnv *env, jobject instance, jfieldID field); +JI_API jint java_interop_jnienv_get_int_field (JNIEnv *env, jobject instance, jfieldID field); +JI_API jlong java_interop_jnienv_get_long_field (JNIEnv *env, jobject instance, jfieldID field); +JI_API jfloat java_interop_jnienv_get_float_field (JNIEnv *env, jobject instance, jfieldID field); +JI_API jdouble java_interop_jnienv_get_double_field (JNIEnv *env, jobject instance, jfieldID field); +JI_API void java_interop_jnienv_set_object_field (JNIEnv *env, jobject instance, jfieldID field, jobject value); +JI_API void java_interop_jnienv_set_boolean_field (JNIEnv *env, jobject instance, jfieldID field, jboolean value); +JI_API void java_interop_jnienv_set_byte_field (JNIEnv *env, jobject instance, jfieldID field, jbyte value); +JI_API void java_interop_jnienv_set_char_field (JNIEnv *env, jobject instance, jfieldID field, jchar value); +JI_API void java_interop_jnienv_set_short_field (JNIEnv *env, jobject instance, jfieldID field, jshort value); +JI_API void java_interop_jnienv_set_int_field (JNIEnv *env, jobject instance, jfieldID field, jint value); +JI_API void java_interop_jnienv_set_long_field (JNIEnv *env, jobject instance, jfieldID field, jlong value); +JI_API void java_interop_jnienv_set_float_field (JNIEnv *env, jobject instance, jfieldID field, jfloat value); +JI_API void java_interop_jnienv_set_double_field (JNIEnv *env, jobject instance, jfieldID field, jdouble value); +JI_API jstaticmethodID java_interop_jnienv_get_static_method_id (JNIEnv *env, jthrowable *_thrown, jclass type, const char* name, const char* signature); +JI_API jobject java_interop_jnienv_call_static_object_method (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method); +JI_API jobject java_interop_jnienv_call_static_object_method_a (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method, jvalue* args); +JI_API jboolean java_interop_jnienv_call_static_boolean_method (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method); +JI_API jboolean java_interop_jnienv_call_static_boolean_method_a (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method, jvalue* args); +JI_API jbyte java_interop_jnienv_call_static_byte_method (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method); +JI_API jbyte java_interop_jnienv_call_static_byte_method_a (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method, jvalue* args); +JI_API jchar java_interop_jnienv_call_static_char_method (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method); +JI_API jchar java_interop_jnienv_call_static_char_method_a (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method, jvalue* args); +JI_API jshort java_interop_jnienv_call_static_short_method (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method); +JI_API jshort java_interop_jnienv_call_static_short_method_a (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method, jvalue* args); +JI_API jint java_interop_jnienv_call_static_int_method (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method); +JI_API jint java_interop_jnienv_call_static_int_method_a (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method, jvalue* args); +JI_API jlong java_interop_jnienv_call_static_long_method (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method); +JI_API jlong java_interop_jnienv_call_static_long_method_a (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method, jvalue* args); +JI_API jfloat java_interop_jnienv_call_static_float_method (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method); +JI_API jfloat java_interop_jnienv_call_static_float_method_a (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method, jvalue* args); +JI_API jdouble java_interop_jnienv_call_static_double_method (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method); +JI_API jdouble java_interop_jnienv_call_static_double_method_a (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method, jvalue* args); +JI_API void java_interop_jnienv_call_static_void_method (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method); +JI_API void java_interop_jnienv_call_static_void_method_a (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method, jvalue* args); +JI_API jstaticfieldID java_interop_jnienv_get_static_field_id (JNIEnv *env, jthrowable *_thrown, jclass type, const char* name, const char* signature); +JI_API jobject java_interop_jnienv_get_static_object_field (JNIEnv *env, jclass type, jstaticfieldID field); +JI_API jboolean java_interop_jnienv_get_static_boolean_field (JNIEnv *env, jclass type, jstaticfieldID field); +JI_API jbyte java_interop_jnienv_get_static_byte_field (JNIEnv *env, jclass type, jstaticfieldID field); +JI_API jchar java_interop_jnienv_get_static_char_field (JNIEnv *env, jclass type, jstaticfieldID field); +JI_API jshort java_interop_jnienv_get_static_short_field (JNIEnv *env, jclass type, jstaticfieldID field); +JI_API jint java_interop_jnienv_get_static_int_field (JNIEnv *env, jclass type, jstaticfieldID field); +JI_API jlong java_interop_jnienv_get_static_long_field (JNIEnv *env, jclass type, jstaticfieldID field); +JI_API jfloat java_interop_jnienv_get_static_float_field (JNIEnv *env, jclass type, jstaticfieldID field); +JI_API jdouble java_interop_jnienv_get_static_double_field (JNIEnv *env, jclass type, jstaticfieldID field); +JI_API void java_interop_jnienv_set_static_object_field (JNIEnv *env, jclass type, jstaticfieldID field, jobject value); +JI_API void java_interop_jnienv_set_static_boolean_field (JNIEnv *env, jclass type, jstaticfieldID field, jboolean value); +JI_API void java_interop_jnienv_set_static_byte_field (JNIEnv *env, jclass type, jstaticfieldID field, jbyte value); +JI_API void java_interop_jnienv_set_static_char_field (JNIEnv *env, jclass type, jstaticfieldID field, jchar value); +JI_API void java_interop_jnienv_set_static_short_field (JNIEnv *env, jclass type, jstaticfieldID field, jshort value); +JI_API void java_interop_jnienv_set_static_int_field (JNIEnv *env, jclass type, jstaticfieldID field, jint value); +JI_API void java_interop_jnienv_set_static_long_field (JNIEnv *env, jclass type, jstaticfieldID field, jlong value); +JI_API void java_interop_jnienv_set_static_float_field (JNIEnv *env, jclass type, jstaticfieldID field, jfloat value); +JI_API void java_interop_jnienv_set_static_double_field (JNIEnv *env, jclass type, jstaticfieldID field, jdouble value); +JI_API jstring java_interop_jnienv_new_string (JNIEnv *env, jthrowable *_thrown, jchar* unicodeChars, jsize length); +JI_API jsize java_interop_jnienv_get_string_length (JNIEnv *env, jstring stringInstance); +JI_API const jchar* java_interop_jnienv_get_string_chars (JNIEnv *env, jstring stringInstance, jboolean* isCopy); +JI_API void java_interop_jnienv_release_string_chars (JNIEnv *env, jstring stringInstance, jchar* chars); +JI_API jsize java_interop_jnienv_get_array_length (JNIEnv *env, jarray array); +JI_API jobjectArray java_interop_jnienv_new_object_array (JNIEnv *env, jthrowable *_thrown, jsize length, jclass elementClass, jobject initialElement); +JI_API jobject java_interop_jnienv_get_object_array_element (JNIEnv *env, jthrowable *_thrown, jobjectArray array, jsize index); +JI_API void java_interop_jnienv_set_object_array_element (JNIEnv *env, jthrowable *_thrown, jobjectArray array, jsize index, jobject value); +JI_API jbooleanArray java_interop_jnienv_new_boolean_array (JNIEnv *env, jsize length); +JI_API jbyteArray java_interop_jnienv_new_byte_array (JNIEnv *env, jsize length); +JI_API jcharArray java_interop_jnienv_new_char_array (JNIEnv *env, jsize length); +JI_API jshortArray java_interop_jnienv_new_short_array (JNIEnv *env, jsize length); +JI_API jintArray java_interop_jnienv_new_int_array (JNIEnv *env, jsize length); +JI_API jlongArray java_interop_jnienv_new_long_array (JNIEnv *env, jsize length); +JI_API jfloatArray java_interop_jnienv_new_float_array (JNIEnv *env, jsize length); +JI_API jdoubleArray java_interop_jnienv_new_double_array (JNIEnv *env, jsize length); +JI_API jboolean* java_interop_jnienv_get_boolean_array_elements (JNIEnv *env, jbooleanArray array, jboolean* isCopy); +JI_API jbyte* java_interop_jnienv_get_byte_array_elements (JNIEnv *env, jbyteArray array, jboolean* isCopy); +JI_API jchar* java_interop_jnienv_get_char_array_elements (JNIEnv *env, jcharArray array, jboolean* isCopy); +JI_API jshort* java_interop_jnienv_get_short_array_elements (JNIEnv *env, jshortArray array, jboolean* isCopy); +JI_API jint* java_interop_jnienv_get_int_array_elements (JNIEnv *env, jintArray array, jboolean* isCopy); +JI_API jlong* java_interop_jnienv_get_long_array_elements (JNIEnv *env, jlongArray array, jboolean* isCopy); +JI_API jfloat* java_interop_jnienv_get_float_array_elements (JNIEnv *env, jfloatArray array, jboolean* isCopy); +JI_API jdouble* java_interop_jnienv_get_double_array_elements (JNIEnv *env, jdoubleArray array, jboolean* isCopy); +JI_API void java_interop_jnienv_release_boolean_array_elements (JNIEnv *env, jbooleanArray array, jboolean* elements, jint mode); +JI_API void java_interop_jnienv_release_byte_array_elements (JNIEnv *env, jbyteArray array, jbyte* elements, jint mode); +JI_API void java_interop_jnienv_release_char_array_elements (JNIEnv *env, jcharArray array, jchar* elements, jint mode); +JI_API void java_interop_jnienv_release_short_array_elements (JNIEnv *env, jshortArray array, jshort* elements, jint mode); +JI_API void java_interop_jnienv_release_int_array_elements (JNIEnv *env, jintArray array, jint* elements, jint mode); +JI_API void java_interop_jnienv_release_long_array_elements (JNIEnv *env, jlongArray array, jlong* elements, jint mode); +JI_API void java_interop_jnienv_release_float_array_elements (JNIEnv *env, jfloatArray array, jfloat* elements, jint mode); +JI_API void java_interop_jnienv_release_double_array_elements (JNIEnv *env, jdoubleArray array, jdouble* elements, jint mode); +JI_API void java_interop_jnienv_get_boolean_array_region (JNIEnv *env, jthrowable *_thrown, jbooleanArray array, jsize start, jsize length, jboolean* buffer); +JI_API void java_interop_jnienv_get_byte_array_region (JNIEnv *env, jthrowable *_thrown, jbyteArray array, jsize start, jsize length, jbyte* buffer); +JI_API void java_interop_jnienv_get_char_array_region (JNIEnv *env, jthrowable *_thrown, jcharArray array, jsize start, jsize length, jchar* buffer); +JI_API void java_interop_jnienv_get_short_array_region (JNIEnv *env, jthrowable *_thrown, jshortArray array, jsize start, jsize length, jshort* buffer); +JI_API void java_interop_jnienv_get_int_array_region (JNIEnv *env, jthrowable *_thrown, jintArray array, jsize start, jsize length, jint* buffer); +JI_API void java_interop_jnienv_get_long_array_region (JNIEnv *env, jthrowable *_thrown, jlongArray array, jsize start, jsize length, jlong* buffer); +JI_API void java_interop_jnienv_get_float_array_region (JNIEnv *env, jthrowable *_thrown, jlongArray array, jsize start, jsize length, jfloat* buffer); +JI_API void java_interop_jnienv_get_double_array_region (JNIEnv *env, jthrowable *_thrown, jdoubleArray array, jsize start, jsize length, jdouble* buffer); +JI_API void java_interop_jnienv_set_boolean_array_region (JNIEnv *env, jthrowable *_thrown, jbooleanArray array, jsize start, jsize length, jboolean* buffer); +JI_API void java_interop_jnienv_set_byte_array_region (JNIEnv *env, jthrowable *_thrown, jbyteArray array, jsize start, jsize length, jbyte* buffer); +JI_API void java_interop_jnienv_set_char_array_region (JNIEnv *env, jthrowable *_thrown, jcharArray array, jsize start, jsize length, const jchar* buffer); +JI_API void java_interop_jnienv_set_short_array_region (JNIEnv *env, jthrowable *_thrown, jshortArray array, jsize start, jsize length, jshort* buffer); +JI_API void java_interop_jnienv_set_int_array_region (JNIEnv *env, jthrowable *_thrown, jintArray array, jsize start, jsize length, jint* buffer); +JI_API void java_interop_jnienv_set_long_array_region (JNIEnv *env, jthrowable *_thrown, jlongArray array, jsize start, jsize length, jlong* buffer); +JI_API void java_interop_jnienv_set_float_array_region (JNIEnv *env, jthrowable *_thrown, jfloatArray array, jsize start, jsize length, jfloat* buffer); +JI_API void java_interop_jnienv_set_double_array_region (JNIEnv *env, jthrowable *_thrown, jdoubleArray array, jsize start, jsize length, jdouble* buffer); +JI_API jint java_interop_jnienv_register_natives (JNIEnv *env, jthrowable *_thrown, jclass type, const JNINativeMethod* methods, jint numMethods); +JI_API jint java_interop_jnienv_unregister_natives (JNIEnv *env, jclass type); +JI_API jint java_interop_jnienv_monitor_enter (JNIEnv *env, jobject instance); +JI_API jint java_interop_jnienv_monitor_exit (JNIEnv *env, jobject instance); +JI_API jint java_interop_jnienv_get_java_vm (JNIEnv *env, JavaVM** vm); +JI_API void* java_interop_jnienv_get_primitive_array_critical (JNIEnv *env, jarray array, jboolean* isCopy); +JI_API void java_interop_jnienv_release_primitive_array_critical (JNIEnv *env, jarray array, void* carray, jint mode); +JI_API jweak java_interop_jnienv_new_weak_global_ref (JNIEnv *env, jobject instance); +JI_API void java_interop_jnienv_delete_weak_global_ref (JNIEnv *env, jobject instance); +JI_API jboolean java_interop_jnienv_exception_check (JNIEnv *env); +JI_API jobject java_interop_jnienv_new_direct_byte_buffer (JNIEnv *env, jthrowable *_thrown, void* address, jlong capacity); +JI_API void* java_interop_jnienv_get_direct_buffer_address (JNIEnv *env, jobject buffer); +JI_API jlong java_interop_jnienv_get_direct_buffer_capacity (JNIEnv *env, jobject buffer); +JI_API jobjectRefType java_interop_jnienv_get_object_ref_type (JNIEnv *env, jobject instance); + +#endif // __JAVA_INTEROP_NATIVE_H diff --git a/src/monodroid/jni/mono_android_Runtime.h b/src/monodroid/jni/mono_android_Runtime.h index 40f51c63825..0e5aa37d095 100644 --- a/src/monodroid/jni/mono_android_Runtime.h +++ b/src/monodroid/jni/mono_android_Runtime.h @@ -39,6 +39,7 @@ JNIEXPORT void JNICALL Java_mono_android_Runtime_register JNIEXPORT void JNICALL Java_mono_android_Runtime_notifyTimeZoneChanged (JNIEnv *, jclass); +#if !defined (ANDROID) /* * Class: mono_android_Runtime * Method: createNewContext @@ -70,6 +71,7 @@ JNIEXPORT void JNICALL Java_mono_android_Runtime_switchToContext */ JNIEXPORT void JNICALL Java_mono_android_Runtime_destroyContexts (JNIEnv *, jclass, jintArray); +#endif // ndef ANDROID /* * Class: mono_android_Runtime diff --git a/src/monodroid/jni/monodroid-glue-designer.cc b/src/monodroid/jni/monodroid-glue-designer.cc new file mode 100644 index 00000000000..422e45e3c12 --- /dev/null +++ b/src/monodroid/jni/monodroid-glue-designer.cc @@ -0,0 +1,147 @@ +// +// Android designer support code, not used on devices +// +#include "globals.hh" +#include "mono_android_Runtime.h" +#include "monodroid-glue-internal.hh" + +using namespace xamarin::android::internal; + +// DO NOT USE ON NORMAL X.A +// This function only works with the custom TypeManager embedded with the designer process. +force_inline static void +reinitialize_android_runtime_type_manager (JNIEnv *env) +{ + jclass typeManager = env->FindClass ("mono/android/TypeManager"); + env->UnregisterNatives (typeManager); + + jmethodID resetRegistration = env->GetStaticMethodID (typeManager, "resetRegistration", "()V"); + env->CallStaticVoidMethod (typeManager, resetRegistration); + + env->DeleteLocalRef (typeManager); +} + +inline void +MonodroidRuntime::shutdown_android_runtime (MonoDomain *domain) +{ + MonoClass *runtime = get_android_runtime_class (domain); + MonoMethod *method = mono_class_get_method_from_name (runtime, "Exit", 0); + + utils.monodroid_runtime_invoke (domain, method, nullptr, nullptr, nullptr); +} + +inline jint +MonodroidRuntime::Java_mono_android_Runtime_createNewContextWithData (JNIEnv *env, jclass klass, jobjectArray runtimeApksJava, jobjectArray assembliesJava, + jobjectArray assembliesBytes, jobjectArray assembliesPaths, jobject loader, jboolean force_preload_assemblies) +{ + log_info (LOG_DEFAULT, "CREATING NEW CONTEXT"); + reinitialize_android_runtime_type_manager (env); + MonoDomain *root_domain = mono_get_root_domain (); + mono_jit_thread_attach (root_domain); + + jstring_array_wrapper runtimeApks (env, runtimeApksJava); + jstring_array_wrapper assemblies (env, assembliesJava); + jstring_array_wrapper assembliePaths (env, assembliesPaths); + MonoDomain *domain = create_and_initialize_domain (env, klass, runtimeApks, assemblies, assembliesBytes, assembliePaths, loader, /*is_root_domain:*/ false, force_preload_assemblies); + mono_domain_set (domain, FALSE); + int domain_id = mono_domain_get_id (domain); + current_context_id = domain_id; + log_info (LOG_DEFAULT, "Created new context with id %d\n", domain_id); + return domain_id; +} + +inline void +MonodroidRuntime::Java_mono_android_Runtime_switchToContext (JNIEnv *env, jint contextID) +{ + log_info (LOG_DEFAULT, "SWITCHING CONTEXT"); + MonoDomain *domain = mono_domain_get_by_id ((int)contextID); + if (current_context_id != (int)contextID) { + mono_domain_set (domain, TRUE); + // Reinitialize TypeManager so that its JNI handle goes into the right domain + reinitialize_android_runtime_type_manager (env); + } + current_context_id = (int)contextID; +} + +inline void +MonodroidRuntime::Java_mono_android_Runtime_destroyContexts (JNIEnv *env, jintArray array) +{ + MonoDomain *root_domain = mono_get_root_domain (); + mono_jit_thread_attach (root_domain); + current_context_id = -1; + + jint *contextIDs = env->GetIntArrayElements (array, nullptr); + jsize count = env->GetArrayLength (array); + + log_info (LOG_DEFAULT, "Cleaning %d domains", count); + + for (jsize i = 0; i < count; i++) { + int domain_id = contextIDs[i]; + MonoDomain *domain = mono_domain_get_by_id (domain_id); + + if (domain == nullptr) + continue; + log_info (LOG_DEFAULT, "Shutting down domain `%d'", contextIDs[i]); + shutdown_android_runtime (domain); + osBridge.remove_monodroid_domain (domain); + designerAssemblies.clear_for_domain (domain); + } + osBridge.on_destroy_contexts (); + for (jsize i = 0; i < count; i++) { + int domain_id = contextIDs[i]; + MonoDomain *domain = mono_domain_get_by_id (domain_id); + + if (domain == nullptr) + continue; + log_info (LOG_DEFAULT, "Unloading domain `%d'", contextIDs[i]); + mono_domain_unload (domain); + } + env->ReleaseIntArrayElements (array, contextIDs, JNI_ABORT); + + reinitialize_android_runtime_type_manager (env); + + log_info (LOG_DEFAULT, "All domain cleaned up"); +} + +JNIEXPORT jint +JNICALL Java_mono_android_Runtime_createNewContextWithData (JNIEnv *env, jclass klass, jobjectArray runtimeApksJava, jobjectArray assembliesJava, jobjectArray assembliesBytes, jobjectArray assembliesPaths, jobject loader, jboolean force_preload_assemblies) +{ + return monodroidRuntime.Java_mono_android_Runtime_createNewContextWithData ( + env, + klass, + runtimeApksJava, + assembliesJava, + assembliesBytes, + assembliesPaths, + loader, + force_preload_assemblies + ); +} + +/* !DO NOT REMOVE! Used by older versions of the Android Designer (pre-16.4) */ +JNIEXPORT jint +JNICALL Java_mono_android_Runtime_createNewContext (JNIEnv *env, jclass klass, jobjectArray runtimeApksJava, jobjectArray assembliesJava, jobject loader) +{ + return monodroidRuntime.Java_mono_android_Runtime_createNewContextWithData ( + env, + klass, + runtimeApksJava, + assembliesJava, + nullptr, // assembliesBytes + nullptr, // assembliesPaths + loader, + false // force_preload_assemblies + ); +} + +JNIEXPORT void +JNICALL Java_mono_android_Runtime_switchToContext (JNIEnv *env, [[maybe_unused]] jclass klass, jint contextID) +{ + monodroidRuntime.Java_mono_android_Runtime_switchToContext (env, contextID); +} + +JNIEXPORT void +JNICALL Java_mono_android_Runtime_destroyContexts (JNIEnv *env, [[maybe_unused]] jclass klass, jintArray array) +{ + monodroidRuntime.Java_mono_android_Runtime_destroyContexts (env, array); +} diff --git a/src/monodroid/jni/monodroid-glue-internal.hh b/src/monodroid/jni/monodroid-glue-internal.hh index 1dc9dfee2b7..9369f5a29b4 100644 --- a/src/monodroid/jni/monodroid-glue-internal.hh +++ b/src/monodroid/jni/monodroid-glue-internal.hh @@ -2,6 +2,7 @@ #ifndef __MONODROID_GLUE_INTERNAL_H #define __MONODROID_GLUE_INTERNAL_H +#include #include #include "android-system.hh" #include "osbridge.hh" @@ -10,10 +11,65 @@ #include #include +#if defined (NET6) +// NDEBUG causes robin_map.h not to include which, in turn, prevents indirect inclusion of . +// conflicts with our std::mutex definition in cppcompat.hh +#if !defined (NDEBUG) +#define NDEBUG +#define NDEBUG_UNDEFINE +#endif + +// hush some compiler warnings +#if defined (__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-parameter" +#endif // __clang__ + +#include + +#if defined (__clang__) +#pragma clang diagnostic pop +#endif // __clang__ + +#if defined (NDEBUG_UNDEFINE) +#undef NDEBUG +#undef NDEBUG_UNDEFINE +#endif + +#include +#include + +// This should be defined in the public Mono headers +typedef void * (*PInvokeOverrideFn) (const char *libraryName, const char *entrypointName); +#endif + namespace xamarin::android::internal { class MonodroidRuntime { +#if defined (NET6) + using pinvoke_api_map = tsl::robin_map< + std::string, + void*, + std::hash, + std::equal_to, + std::allocator>, + true + >; + + using pinvoke_api_map_ptr = pinvoke_api_map*; + using pinvoke_library_map = tsl::robin_map< + std::string, + pinvoke_api_map_ptr, + std::hash, + std::equal_to, + std::allocator>, + true + >; + + static constexpr pinvoke_library_map::size_type LIBRARY_MAP_INITIAL_BUCKET_COUNT = 1; +#endif // def NET6 + #if defined (DEBUG) && !defined (WINDOWS) struct RuntimeOptions { bool debug = false; @@ -61,6 +117,7 @@ namespace xamarin::android::internal #else true; #endif + #define MAKE_API_DSO_NAME(_ext_) "libxa-internal-api." # _ext_ #if defined (WINDOWS) static constexpr char API_DSO_NAME[] = MAKE_API_DSO_NAME (dll); @@ -70,6 +127,12 @@ namespace xamarin::android::internal static constexpr char API_DSO_NAME[] = MAKE_API_DSO_NAME (so); #endif // defined(WINDOWS) public: + static constexpr bool is_net6 = +#if NET6 + true; +#else // def NET6 + false; +#endif // ndef NET6 static constexpr int XA_LOG_COUNTERS = MONO_COUNTER_JIT | MONO_COUNTER_METADATA | MONO_COUNTER_GC | MONO_COUNTER_GENERICS | MONO_COUNTER_INTERP; public: @@ -77,10 +140,13 @@ namespace xamarin::android::internal void Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass klass, jstring lang, jobjectArray runtimeApksJava, jstring runtimeNativeLibDir, jobjectArray appDirs, jobject loader, jobjectArray assembliesJava, jint apiLevel, jboolean isEmulator); +#if !defined (ANDROID) jint Java_mono_android_Runtime_createNewContextWithData (JNIEnv *env, jclass klass, jobjectArray runtimeApksJava, jobjectArray assembliesJava, jobjectArray assembliesBytes, jobjectArray assembliesPaths, jobject loader, jboolean force_preload_assemblies); void Java_mono_android_Runtime_switchToContext (JNIEnv *env, jint contextID); void Java_mono_android_Runtime_destroyContexts (JNIEnv *env, jintArray array); + void shutdown_android_runtime (MonoDomain *domain); +#endif jint Java_JNI_OnLoad (JavaVM *vm, void *reserved); int get_android_api_level () const @@ -139,10 +205,18 @@ namespace xamarin::android::internal #if defined (WINDOWS) || defined (APPLE_OS_X) static const char* get_my_location (bool remove_file_name = true); #endif // defined(WINDOWS) || defined(APPLE_OS_X) +#if defined (NET6) + static void* load_library_entry (std::string const& library_name, std::string const& entrypoint_name, pinvoke_api_map_ptr api_map); + static void* fetch_or_create_pinvoke_map_entry (std::string const& library_name, std::string const& entrypoint_name, pinvoke_api_map_ptr api_map, bool need_lock); + static void* monodroid_pinvoke_override (const char *library_name, const char *entrypoint_name); + static void* monodroid_dlopen (const char *name, int flags, char **err); +#endif // def NET6 static void* monodroid_dlopen (const char *name, int flags, char **err, void *user_data); static void* monodroid_dlsym (void *handle, const char *name, char **err, void *user_data); static void* monodroid_dlopen_log_and_return (void *handle, char **err, const char *full_name, bool free_memory, bool need_api_init = false); +#if !defined (NET6) static void init_internal_api_dso (void *handle); +#endif // ndef NET6 int LocalRefsAreIndirect (JNIEnv *env, jclass runtimeClass, int version); void create_xdg_directory (jstring_wrapper& home, size_t home_len, const char *relativePath, size_t relative_path_len, const char *environmentVariableName); void create_xdg_directories_and_environment (jstring_wrapper &homeDir); @@ -168,7 +242,6 @@ namespace xamarin::android::internal } MonoClass* get_android_runtime_class (MonoDomain *domain); - void shutdown_android_runtime (MonoDomain *domain); MonoDomain* create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks, bool is_root_domain); MonoDomain* create_and_initialize_domain (JNIEnv* env, jclass runtimeClass, jstring_array_wrapper &runtimeApks, jstring_array_wrapper &assemblies, jobjectArray assembliesBytes, jstring_array_wrapper &assembliesPaths, @@ -227,8 +300,14 @@ namespace xamarin::android::internal */ int current_context_id = -1; +#if defined (NET6) + static std::mutex pinvoke_map_write_lock; + static pinvoke_api_map xa_pinvoke_map; + static pinvoke_library_map other_pinvoke_map; +#else // def NET6 static std::mutex api_init_lock; static void *api_dso_handle; +#endif // !def NET6 }; } #endif diff --git a/src/monodroid/jni/monodroid-glue.cc b/src/monodroid/jni/monodroid-glue.cc index f7dc3ec1c51..634fd108ad6 100644 --- a/src/monodroid/jni/monodroid-glue.cc +++ b/src/monodroid/jni/monodroid-glue.cc @@ -1,7 +1,6 @@ #include #include #include -#include #include #include @@ -99,11 +98,17 @@ using namespace xamarin::android::internal; // implementation details as it would prevent mkbundle from working #include "mkbundle-api.h" +#if !defined (NET6) #include "config.include" +#endif // ndef NET6 #include "machine.config.include" +#if defined (NET6) +std::mutex MonodroidRuntime::pinvoke_map_write_lock; +#else // def NET6 std::mutex MonodroidRuntime::api_init_lock; void *MonodroidRuntime::api_dso_handle = nullptr; +#endif // ndef NET6 #ifdef WINDOWS static const char* get_xamarin_android_msbuild_path (void); @@ -395,9 +400,7 @@ MonodroidRuntime::gather_bundled_assemblies (jstring_array_wrapper &runtimeApks, size_t cur_num_assemblies = embeddedAssemblies.register_from (apk_file.get_cstr ()); - if (strstr (apk_file.get_cstr (), "/Mono.Android.DebugRuntime") == nullptr && - strstr (apk_file.get_cstr (), "/Mono.Android.Platform.ApiLevel_") == nullptr) - *out_user_assemblies_count += (cur_num_assemblies - prev_num_assemblies); + *out_user_assemblies_count += (cur_num_assemblies - prev_num_assemblies); prev_num_assemblies = cur_num_assemblies; } } @@ -1013,7 +1016,7 @@ MonodroidRuntime::init_android_runtime (MonoDomain *domain, JNIEnv *env, jclass } } -inline MonoClass* +MonoClass* MonodroidRuntime::get_android_runtime_class (MonoDomain *domain) { MonoAssembly *assm = utils.monodroid_load_assembly (domain, "Mono.Android"); @@ -1023,15 +1026,6 @@ MonodroidRuntime::get_android_runtime_class (MonoDomain *domain) return runtime; } -inline void -MonodroidRuntime::shutdown_android_runtime (MonoDomain *domain) -{ - MonoClass *runtime = get_android_runtime_class (domain); - MonoMethod *method = mono_class_get_method_from_name (runtime, "Exit", 0); - - utils.monodroid_runtime_invoke (domain, method, nullptr, nullptr, nullptr); -} - inline void MonodroidRuntime::propagate_uncaught_exception (MonoDomain *domain, JNIEnv *env, jobject javaThread, jthrowable javaException) { @@ -1066,6 +1060,7 @@ MonodroidRuntime::convert_dl_flags (int flags) return lflags; } +#if !defined (NET6) force_inline void MonodroidRuntime::init_internal_api_dso (void *handle) { @@ -1113,9 +1108,10 @@ MonodroidRuntime::init_internal_api_dso (void *handle) exit (FATAL_EXIT_MONO_MISSING_SYMBOLS); } } +#endif // ndef NET6 force_inline void* -MonodroidRuntime::monodroid_dlopen_log_and_return (void *handle, char **err, const char *full_name, bool free_memory, bool need_api_init) +MonodroidRuntime::monodroid_dlopen_log_and_return (void *handle, char **err, const char *full_name, bool free_memory, [[maybe_unused]] bool need_api_init) { if (handle == nullptr && err != nullptr) { *err = utils.monodroid_strdup_printf ("Could not load library: Library '%s' not found.", full_name); @@ -1125,14 +1121,77 @@ MonodroidRuntime::monodroid_dlopen_log_and_return (void *handle, char **err, con delete[] full_name; } +#if !defined (NET6) if (!need_api_init) return handle; - init_internal_api_dso (handle); +#endif // ndef NET6 return handle; } +#if defined (NET6) && defined (ANDROID) +force_inline void* +MonodroidRuntime::monodroid_dlopen (const char *name, int flags, char **err) +{ + unsigned int dl_flags = monodroidRuntime.convert_dl_flags (flags); + void *h = androidSystem.load_dso_from_any_directories (name, dl_flags); + if (h != nullptr) { + return monodroid_dlopen_log_and_return (h, err, name, false /* name_needs_free */); + } + + if (!utils.ends_with (name, ".dll.so")) { + return monodroid_dlopen_log_and_return (h, err, name, false /* name_needs_free */); + } + + char *basename_part = const_cast (strrchr (name, '/')); + if (basename_part != nullptr) { + basename_part++; + } else { + basename_part = (char*)name; + } + + constexpr char LIBAOT_PREFIX[] = "libaot-"; + constexpr size_t LIBAOT_PREFIX_SIZE = sizeof(LIBAOT_PREFIX); + + size_t base_len = strlen (basename_part); + size_t len = base_len + LIBAOT_PREFIX_SIZE; // includes the trailing \0 + static_local_string basename (len); + + basename.append (LIBAOT_PREFIX).append (basename_part); + + h = androidSystem.load_dso_from_any_directories (basename.get (), dl_flags); + + if (h != nullptr && XA_UNLIKELY (utils.should_log (LOG_ASSEMBLY))) { + log_info_nocheck (LOG_ASSEMBLY, "Loaded AOT image '%s'", basename.get ()); + } + + return h; +} + +void* +MonodroidRuntime::monodroid_dlopen (const char *name, int flags, char **err, [[maybe_unused]] void *user_data) +{ + log_warn (LOG_DEFAULT, "MonodroidRuntime::monodroid_dlopen (\"%s\", 0x%x, %p, %p)", name, flags, err, user_data); + if (name == nullptr) { + log_warn (LOG_ASSEMBLY, "monodroid_dlopen got a null name. This is not supported in NET6+"); + return nullptr; + } + + constexpr char DSO_EXTENSION[] = ".so"; + constexpr size_t DSO_EXTENSION_SIZE = sizeof(DSO_EXTENSION); + + if (utils.ends_with (name, DSO_EXTENSION)) { + return monodroid_dlopen (name, flags, err); + } + + size_t len = ADD_WITH_OVERFLOW_CHECK (size_t, strlen (name), DSO_EXTENSION_SIZE); // includes the trailing \0 + static_local_string full_name (len); + + full_name.append (name).append (DSO_EXTENSION); + return monodroid_dlopen (full_name.get (), flags, err); +} +#else // def NET6 && def ANDROID void* MonodroidRuntime::monodroid_dlopen (const char *name, int flags, char **err, [[maybe_unused]] void *user_data) { @@ -1252,6 +1311,7 @@ MonodroidRuntime::monodroid_dlopen (const char *name, int flags, char **err, [[m return h; } +#endif // !(def NET6 && def ANDROID) void* MonodroidRuntime::monodroid_dlsym (void *handle, const char *name, char **err, [[maybe_unused]] void *user_data) @@ -1635,6 +1695,20 @@ MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass kl total_time.mark_start (); } +#if defined (NET6) + { + PInvokeOverrideFn pinvoke_override_cb = monodroid_pinvoke_override; + char ptr_str[20]; + snprintf (ptr_str, sizeof(ptr_str), "%p", pinvoke_override_cb); + + const char* property_keys[] { "PINVOKE_OVERRIDE" }; + const char* property_values[] { ptr_str }; + + log_warn (LOG_DEFAULT, "Initializing .NET6 Mono VM (override callback at %p, passed as %s", pinvoke_override_cb, ptr_str); + monovm_initialize (1, property_keys, property_values); + } +#endif // def NET6 + jstring_array_wrapper applicationDirs (env, appDirs); android_api_level = apiLevel; @@ -1710,8 +1784,9 @@ MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass kl #endif // defined(WINDOWS) || defined(APPLE_OS_X) if (dso_handle == nullptr) dso_handle = androidSystem.load_dso_from_any_directories (API_DSO_NAME, JAVA_INTEROP_LIB_LOAD_GLOBALLY); +#if !defined (NET6) init_internal_api_dso (dso_handle); - +#endif // ndef NET6 mono_dl_fallback_register (monodroid_dlopen, monodroid_dlsym, nullptr, nullptr); set_profile_options (); @@ -1722,7 +1797,9 @@ MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass kl debug.start_debugging_and_profiling (); #endif +#if !defined (NET6) mono_config_parse_memory (reinterpret_cast (monodroid_config)); +#endif // ndef NET6 mono_register_machine_config (reinterpret_cast (monodroid_machine_config)); log_info (LOG_DEFAULT, "Probing for Mono AOT mode\n"); @@ -1928,97 +2005,6 @@ JNICALL Java_mono_android_Runtime_register (JNIEnv *env, [[maybe_unused]] jclass monodroidRuntime.Java_mono_android_Runtime_register (env, managedType, nativeClass, methods); } -// DO NOT USE ON NORMAL X.A -// This function only works with the custom TypeManager embedded with the designer process. -static void -reinitialize_android_runtime_type_manager (JNIEnv *env) -{ - jclass typeManager = env->FindClass ("mono/android/TypeManager"); - env->UnregisterNatives (typeManager); - - jmethodID resetRegistration = env->GetStaticMethodID (typeManager, "resetRegistration", "()V"); - env->CallStaticVoidMethod (typeManager, resetRegistration); - - env->DeleteLocalRef (typeManager); -} - -inline jint -MonodroidRuntime::Java_mono_android_Runtime_createNewContextWithData (JNIEnv *env, jclass klass, jobjectArray runtimeApksJava, jobjectArray assembliesJava, - jobjectArray assembliesBytes, jobjectArray assembliesPaths, jobject loader, jboolean force_preload_assemblies) -{ - log_info (LOG_DEFAULT, "CREATING NEW CONTEXT"); - reinitialize_android_runtime_type_manager (env); - MonoDomain *root_domain = mono_get_root_domain (); - mono_jit_thread_attach (root_domain); - - jstring_array_wrapper runtimeApks (env, runtimeApksJava); - jstring_array_wrapper assemblies (env, assembliesJava); - jstring_array_wrapper assembliePaths (env, assembliesPaths); - MonoDomain *domain = create_and_initialize_domain (env, klass, runtimeApks, assemblies, assembliesBytes, assembliePaths, loader, /*is_root_domain:*/ false, force_preload_assemblies); - mono_domain_set (domain, FALSE); - int domain_id = mono_domain_get_id (domain); - current_context_id = domain_id; - log_info (LOG_DEFAULT, "Created new context with id %d\n", domain_id); - return domain_id; -} - -inline void -MonodroidRuntime::Java_mono_android_Runtime_switchToContext (JNIEnv *env, jint contextID) -{ - log_info (LOG_DEFAULT, "SWITCHING CONTEXT"); - MonoDomain *domain = mono_domain_get_by_id ((int)contextID); - if (current_context_id != (int)contextID) { - mono_domain_set (domain, TRUE); - // Reinitialize TypeManager so that its JNI handle goes into the right domain - reinitialize_android_runtime_type_manager (env); - } - current_context_id = (int)contextID; -} - -inline void -MonodroidRuntime::Java_mono_android_Runtime_destroyContexts (JNIEnv *env, jintArray array) -{ - MonoDomain *root_domain = mono_get_root_domain (); - mono_jit_thread_attach (root_domain); - current_context_id = -1; - - jint *contextIDs = env->GetIntArrayElements (array, nullptr); - jsize count = env->GetArrayLength (array); - - log_info (LOG_DEFAULT, "Cleaning %d domains", count); - - for (jsize i = 0; i < count; i++) { - int domain_id = contextIDs[i]; - MonoDomain *domain = mono_domain_get_by_id (domain_id); - - if (domain == nullptr) - continue; - log_info (LOG_DEFAULT, "Shutting down domain `%d'", contextIDs[i]); - shutdown_android_runtime (domain); - osBridge.remove_monodroid_domain (domain); -#ifndef ANDROID - designerAssemblies.clear_for_domain (domain); -#endif - } - osBridge.on_destroy_contexts (); -#ifndef ANDROID - for (jsize i = 0; i < count; i++) { - int domain_id = contextIDs[i]; - MonoDomain *domain = mono_domain_get_by_id (domain_id); - - if (domain == nullptr) - continue; - log_info (LOG_DEFAULT, "Unloading domain `%d'", contextIDs[i]); - mono_domain_unload (domain); - } -#endif // !defined(ANDROID) - env->ReleaseIntArrayElements (array, contextIDs, JNI_ABORT); - - reinitialize_android_runtime_type_manager (env); - - log_info (LOG_DEFAULT, "All domain cleaned up"); -} - char* MonodroidRuntime::get_java_class_name_for_TypeManager (jclass klass) { @@ -2058,49 +2044,6 @@ get_jnienv (void) return osBridge.ensure_jnienv (); } -JNIEXPORT jint -JNICALL Java_mono_android_Runtime_createNewContextWithData (JNIEnv *env, jclass klass, jobjectArray runtimeApksJava, jobjectArray assembliesJava, jobjectArray assembliesBytes, jobjectArray assembliesPaths, jobject loader, jboolean force_preload_assemblies) -{ - return monodroidRuntime.Java_mono_android_Runtime_createNewContextWithData ( - env, - klass, - runtimeApksJava, - assembliesJava, - assembliesBytes, - assembliesPaths, - loader, - force_preload_assemblies - ); -} - -/* !DO NOT REMOVE! Used by older versions of the Android Designer (pre-16.4) */ -JNIEXPORT jint -JNICALL Java_mono_android_Runtime_createNewContext (JNIEnv *env, jclass klass, jobjectArray runtimeApksJava, jobjectArray assembliesJava, jobject loader) -{ - return monodroidRuntime.Java_mono_android_Runtime_createNewContextWithData ( - env, - klass, - runtimeApksJava, - assembliesJava, - nullptr, // assembliesBytes - nullptr, // assembliesPaths - loader, - false // force_preload_assemblies - ); -} - -JNIEXPORT void -JNICALL Java_mono_android_Runtime_switchToContext (JNIEnv *env, [[maybe_unused]] jclass klass, jint contextID) -{ - monodroidRuntime.Java_mono_android_Runtime_switchToContext (env, contextID); -} - -JNIEXPORT void -JNICALL Java_mono_android_Runtime_destroyContexts (JNIEnv *env, [[maybe_unused]] jclass klass, jintArray array) -{ - monodroidRuntime.Java_mono_android_Runtime_destroyContexts (env, array); -} - JNIEXPORT void JNICALL Java_mono_android_Runtime_propagateUncaughtException (JNIEnv *env, [[maybe_unused]] jclass klass, jobject javaThread, jthrowable javaException) { diff --git a/src/monodroid/jni/monodroid-glue.hh b/src/monodroid/jni/monodroid-glue.hh index 1f0adad5020..956f93ac5c6 100644 --- a/src/monodroid/jni/monodroid-glue.hh +++ b/src/monodroid/jni/monodroid-glue.hh @@ -8,14 +8,17 @@ #include #include +#if !defined (NET6) #ifdef __cplusplus extern "C" { -#endif +#endif // __cplusplus MONO_API int monodroid_get_system_property (const char *name, char **value); MONO_API int monodroid_getpagesize (void); #ifdef __cplusplus } -#endif +#endif // __cplusplus +#endif // NET6 + int monodroid_get_system_property_from_overrides (const char *name, char ** value); JNIEnv* get_jnienv (void); diff --git a/src/monodroid/jni/pinvoke-override-api.cc b/src/monodroid/jni/pinvoke-override-api.cc new file mode 100644 index 00000000000..fa2e1837a3f --- /dev/null +++ b/src/monodroid/jni/pinvoke-override-api.cc @@ -0,0 +1,714 @@ +#include +#include +#include +#include + +extern "C" { +#include "java_interop_api.h" +} + +#include "globals.hh" +#include "monodroid-glue.hh" +#include "monodroid-glue-internal.hh" +#include "timing.hh" +#include "java-interop.h" +#include "cpu-arch.hh" + +extern "C" { + int _monodroid_getifaddrs (struct _monodroid_ifaddrs **ifap); + void _monodroid_freeifaddrs (struct _monodroid_ifaddrs *ifa); +} + +mono_bool _monodroid_get_network_interface_up_state (const char *ifname, mono_bool *is_up); +mono_bool _monodroid_get_network_interface_supports_multicast (const char *ifname, mono_bool *supports_multicast); +int _monodroid_get_dns_servers (void **dns_servers_array); + +using namespace xamarin::android; +using namespace xamarin::android::internal; + +static unsigned int +monodroid_get_log_categories () +{ + return log_categories; +} + +static int +monodroid_get_system_property (const char *name, char **value) +{ + return androidSystem.monodroid_get_system_property (name, value); +} + +static int +monodroid_embedded_assemblies_set_assemblies_prefix (const char *prefix) +{ + embeddedAssemblies.set_assemblies_prefix (prefix); + return 0; +} + +static void +monodroid_log (LogLevel level, LogCategories category, const char *message) +{ + switch (level) { + case LogLevel::Verbose: + case LogLevel::Debug: + log_debug_nocheck (category, message); + break; + + case LogLevel::Info: + log_info_nocheck (category, message); + break; + + case LogLevel::Warn: + case LogLevel::Silent: // warn is always printed + log_warn (category, message); + break; + + case LogLevel::Error: + log_error (category, message); + break; + + case LogLevel::Fatal: + log_fatal (category, message); + break; + + default: + case LogLevel::Unknown: + case LogLevel::Default: + log_info_nocheck (category, message); + break; + } +} + +static void +monodroid_free (void *ptr) +{ + free (ptr); +} + +static int +_monodroid_max_gref_get () +{ + return static_cast(androidSystem.get_max_gref_count ()); +} + +static int +_monodroid_gref_get () +{ + return osBridge.get_gc_gref_count (); +} + + +static void +_monodroid_gref_log (const char *message) +{ + osBridge._monodroid_gref_log (message); +} + +static int +_monodroid_gref_log_new (jobject curHandle, char curType, jobject newHandle, char newType, const char *threadName, int threadId, const char *from, int from_writable) +{ + return osBridge._monodroid_gref_log_new (curHandle, curType, newHandle, newType, threadName, threadId, from, from_writable); +} + +static void +_monodroid_gref_log_delete (jobject handle, char type, const char *threadName, int threadId, const char *from, int from_writable) +{ + osBridge._monodroid_gref_log_delete (handle, type, threadName, threadId, from, from_writable); +} + +static void +_monodroid_weak_gref_new (jobject curHandle, char curType, jobject newHandle, char newType, const char *threadName, int threadId, const char *from, int from_writable) +{ + osBridge._monodroid_weak_gref_new (curHandle, curType, newHandle, newType, threadName, threadId, from, from_writable); +} + +static void +_monodroid_weak_gref_delete (jobject handle, char type, const char *threadName, int threadId, const char *from, int from_writable) +{ + osBridge._monodroid_weak_gref_delete (handle, type, threadName, threadId, from, from_writable); +} + +static void +_monodroid_lref_log_new (int lrefc, jobject handle, char type, const char *threadName, int threadId, const char *from, int from_writable) +{ + osBridge._monodroid_lref_log_new (lrefc, handle, type, threadName, threadId, from, from_writable); +} + +static void +_monodroid_lref_log_delete (int lrefc, jobject handle, char type, const char *threadName, int threadId, const char *from, int from_writable) +{ + osBridge._monodroid_lref_log_delete (lrefc, handle, type, threadName, threadId, from, from_writable); +} + +static void +_monodroid_gc_wait_for_bridge_processing () +{ + mono_gc_wait_for_bridge_processing (); +} + +static int +_monodroid_get_android_api_level () +{ + return monodroidRuntime.get_android_api_level (); +} + +static void +monodroid_clear_gdb_wait () +{ + monodroidRuntime.set_monodroid_gdb_wait (false); +} + +static void* +_monodroid_get_identity_hash_code (JNIEnv *env, void *v) +{ + intptr_t rv = env->CallStaticIntMethod (monodroidRuntime.get_java_class_System (), monodroidRuntime.get_java_class_method_System_identityHashCode (), v); + return (void*) rv; +} + +static void* +_monodroid_timezone_get_default_id () +{ + JNIEnv *env = osBridge.ensure_jnienv (); + jmethodID getDefault = env->GetStaticMethodID (monodroidRuntime.get_java_class_TimeZone (), "getDefault", "()Ljava/util/TimeZone;"); + jmethodID getID = env->GetMethodID (monodroidRuntime.get_java_class_TimeZone (), "getID", "()Ljava/lang/String;"); + jobject d = env->CallStaticObjectMethod (monodroidRuntime.get_java_class_TimeZone (), getDefault); + jstring id = reinterpret_cast (env->CallObjectMethod (d, getID)); + const char *mutf8 = env->GetStringUTFChars (id, nullptr); + + if (mutf8 == nullptr) { + log_error (LOG_DEFAULT, "Failed to convert Java TimeZone ID to UTF8 (out of memory?)"); + env->DeleteLocalRef (id); + env->DeleteLocalRef (d); + return nullptr; + } + + char *def_id = strdup (mutf8); + + env->ReleaseStringUTFChars (id, mutf8); + env->DeleteLocalRef (id); + env->DeleteLocalRef (d); + + return def_id; +} + +static void +_monodroid_counters_dump (const char *format, va_list args) +{ + monodroidRuntime.dump_counters_v (format, args); +} + +static managed_timing_sequence* +monodroid_timing_start (const char *message) +{ + if (timing == nullptr) + return nullptr; + + managed_timing_sequence *ret = timing->get_available_sequence (); + if (message != nullptr) { + log_info (LOG_TIMING, message); + } + ret->period.mark_start (); + + return ret; +} + +static void +monodroid_timing_stop (managed_timing_sequence *sequence, const char *message) +{ + static constexpr const char DEFAULT_MESSAGE[] = "Managed Timing"; + + if (sequence == nullptr) + return; + + sequence->period.mark_end (); + Timing::info (sequence->period, message == nullptr ? DEFAULT_MESSAGE : message); + timing->release_sequence (sequence); +} + +static char** +monodroid_strsplit (const char *str, const char *delimiter, size_t max_tokens) +{ + return utils.monodroid_strsplit (str, delimiter, max_tokens); +} + +static void +monodroid_strfreev (char **str_array) +{ + utils.monodroid_strfreev (str_array); +} + +static char* +monodroid_strdup_printf (const char *format, ...) +{ + va_list args; + + va_start (args, format); + char *ret = utils.monodroid_strdup_vprintf (format, args); + va_end (args); + + return ret; +} + +static char* +monodroid_TypeManager_get_java_class_name (jclass klass) +{ + return monodroidRuntime.get_java_class_name_for_TypeManager (klass); +} + +static void +monodroid_store_package_name (const char *name) +{ + utils.monodroid_store_package_name (name); +} + +static int +monodroid_get_namespaced_system_property (const char *name, char **value) +{ + return static_cast(androidSystem.monodroid_get_system_property (name, value)); +} + +static FILE* +monodroid_fopen (const char* filename, const char* mode) +{ + return utils.monodroid_fopen (filename, mode); +} + +static int +send_uninterrupted (int fd, void *buf, int len) +{ + if (len < 0) + len = 0; + return utils.send_uninterrupted (fd, buf, static_cast(len)); +} + +static int +recv_uninterrupted (int fd, void *buf, int len) +{ + if (len < 0) + len = 0; + return static_cast(utils.recv_uninterrupted (fd, buf, static_cast(len))); +} + +static void +set_world_accessable (const char *path) +{ + utils.set_world_accessable (path); +} + +static void +create_public_directory (const char *dir) +{ + utils.create_public_directory (dir); +} + +static char* +path_combine (const char *path1, const char *path2) +{ + return utils.path_combine (path1, path2); +} + +static void* +monodroid_dylib_mono_new ([[maybe_unused]] const char *libmono_path) +{ + return nullptr; +} + +static void +monodroid_dylib_mono_free ([[maybe_unused]] void *mono_imports) +{ + // no-op +} + +/* + this function is used from JavaInterop and should be treated as public API + https://github.com/xamarin/java.interop/blob/master/src/java-interop/java-interop-gc-bridge-mono.c#L266 + + it should also accept libmono_path = nullptr parameter +*/ +static int +monodroid_dylib_mono_init (void *mono_imports, [[maybe_unused]] const char *libmono_path) +{ + if (mono_imports == nullptr) + return FALSE; + return TRUE; +} + +static void* +monodroid_get_dylib (void) +{ + return nullptr; +} + +#define PINVOKE_SYMBOL(_sym_) { #_sym_, reinterpret_cast(&_sym_) } + +MonodroidRuntime::pinvoke_api_map MonodroidRuntime::xa_pinvoke_map = { + PINVOKE_SYMBOL (create_public_directory), + PINVOKE_SYMBOL (java_interop_free), + PINVOKE_SYMBOL (java_interop_jnienv_alloc_object), + PINVOKE_SYMBOL (java_interop_jnienv_call_boolean_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_boolean_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_byte_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_byte_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_char_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_char_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_double_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_double_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_float_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_float_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_int_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_int_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_long_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_long_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_boolean_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_boolean_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_byte_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_byte_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_char_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_char_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_double_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_double_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_float_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_float_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_int_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_int_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_long_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_long_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_object_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_object_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_short_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_short_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_void_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_void_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_object_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_object_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_short_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_short_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_boolean_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_boolean_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_byte_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_byte_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_char_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_char_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_double_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_double_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_float_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_float_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_int_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_int_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_long_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_long_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_object_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_object_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_short_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_short_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_void_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_void_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_void_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_void_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_define_class), + PINVOKE_SYMBOL (java_interop_jnienv_delete_global_ref), + PINVOKE_SYMBOL (java_interop_jnienv_delete_local_ref), + PINVOKE_SYMBOL (java_interop_jnienv_delete_weak_global_ref), + PINVOKE_SYMBOL (java_interop_jnienv_ensure_local_capacity), + PINVOKE_SYMBOL (java_interop_jnienv_exception_check), + PINVOKE_SYMBOL (java_interop_jnienv_exception_clear), + PINVOKE_SYMBOL (java_interop_jnienv_exception_describe), + PINVOKE_SYMBOL (java_interop_jnienv_exception_occurred), + PINVOKE_SYMBOL (java_interop_jnienv_fatal_error), + PINVOKE_SYMBOL (java_interop_jnienv_find_class), + PINVOKE_SYMBOL (java_interop_jnienv_get_array_length), + PINVOKE_SYMBOL (java_interop_jnienv_get_boolean_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_get_boolean_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_get_boolean_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_byte_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_get_byte_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_get_byte_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_char_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_get_char_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_get_char_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_direct_buffer_address), + PINVOKE_SYMBOL (java_interop_jnienv_get_direct_buffer_capacity), + PINVOKE_SYMBOL (java_interop_jnienv_get_double_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_get_double_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_get_double_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_field_id), + PINVOKE_SYMBOL (java_interop_jnienv_get_float_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_get_float_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_get_float_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_int_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_get_int_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_get_int_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_java_vm), + PINVOKE_SYMBOL (java_interop_jnienv_get_long_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_get_long_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_get_long_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_method_id), + PINVOKE_SYMBOL (java_interop_jnienv_get_object_array_element), + PINVOKE_SYMBOL (java_interop_jnienv_get_object_class), + PINVOKE_SYMBOL (java_interop_jnienv_get_object_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_object_ref_type), + PINVOKE_SYMBOL (java_interop_jnienv_get_primitive_array_critical), + PINVOKE_SYMBOL (java_interop_jnienv_get_short_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_get_short_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_get_short_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_static_boolean_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_static_byte_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_static_char_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_static_double_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_static_field_id), + PINVOKE_SYMBOL (java_interop_jnienv_get_static_float_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_static_int_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_static_long_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_static_method_id), + PINVOKE_SYMBOL (java_interop_jnienv_get_static_object_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_static_short_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_string_chars), + PINVOKE_SYMBOL (java_interop_jnienv_get_string_length), + PINVOKE_SYMBOL (java_interop_jnienv_get_superclass), + PINVOKE_SYMBOL (java_interop_jnienv_get_version), + PINVOKE_SYMBOL (java_interop_jnienv_is_assignable_from), + PINVOKE_SYMBOL (java_interop_jnienv_is_instance_of), + PINVOKE_SYMBOL (java_interop_jnienv_is_same_object), + PINVOKE_SYMBOL (java_interop_jnienv_monitor_enter), + PINVOKE_SYMBOL (java_interop_jnienv_monitor_exit), + PINVOKE_SYMBOL (java_interop_jnienv_new_boolean_array), + PINVOKE_SYMBOL (java_interop_jnienv_new_byte_array), + PINVOKE_SYMBOL (java_interop_jnienv_new_char_array), + PINVOKE_SYMBOL (java_interop_jnienv_new_direct_byte_buffer), + PINVOKE_SYMBOL (java_interop_jnienv_new_double_array), + PINVOKE_SYMBOL (java_interop_jnienv_new_float_array), + PINVOKE_SYMBOL (java_interop_jnienv_new_global_ref), + PINVOKE_SYMBOL (java_interop_jnienv_new_int_array), + PINVOKE_SYMBOL (java_interop_jnienv_new_local_ref), + PINVOKE_SYMBOL (java_interop_jnienv_new_long_array), + PINVOKE_SYMBOL (java_interop_jnienv_new_object), + PINVOKE_SYMBOL (java_interop_jnienv_new_object_a), + PINVOKE_SYMBOL (java_interop_jnienv_new_object_array), + PINVOKE_SYMBOL (java_interop_jnienv_new_short_array), + PINVOKE_SYMBOL (java_interop_jnienv_new_string), + PINVOKE_SYMBOL (java_interop_jnienv_new_weak_global_ref), + PINVOKE_SYMBOL (java_interop_jnienv_pop_local_frame), + PINVOKE_SYMBOL (java_interop_jnienv_push_local_frame), + PINVOKE_SYMBOL (java_interop_jnienv_register_natives), + PINVOKE_SYMBOL (java_interop_jnienv_release_boolean_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_release_byte_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_release_char_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_release_double_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_release_float_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_release_int_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_release_long_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_release_primitive_array_critical), + PINVOKE_SYMBOL (java_interop_jnienv_release_short_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_release_string_chars), + PINVOKE_SYMBOL (java_interop_jnienv_set_boolean_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_set_boolean_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_byte_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_set_byte_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_char_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_set_char_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_double_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_set_double_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_float_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_set_float_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_int_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_set_int_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_long_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_set_long_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_object_array_element), + PINVOKE_SYMBOL (java_interop_jnienv_set_object_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_short_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_set_short_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_static_boolean_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_static_byte_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_static_char_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_static_double_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_static_float_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_static_int_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_static_long_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_static_object_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_static_short_field), + PINVOKE_SYMBOL (java_interop_jnienv_throw), + PINVOKE_SYMBOL (java_interop_jnienv_throw_new), + PINVOKE_SYMBOL (java_interop_jnienv_to_reflected_field), + PINVOKE_SYMBOL (java_interop_jnienv_to_reflected_method), + PINVOKE_SYMBOL (java_interop_jnienv_unregister_natives), + PINVOKE_SYMBOL (java_interop_strdup), + PINVOKE_SYMBOL (monodroid_clear_gdb_wait), + PINVOKE_SYMBOL (_monodroid_counters_dump), + PINVOKE_SYMBOL (_monodroid_detect_cpu_and_architecture), + PINVOKE_SYMBOL (monodroid_dylib_mono_free), + PINVOKE_SYMBOL (monodroid_dylib_mono_init), + PINVOKE_SYMBOL (monodroid_dylib_mono_new), + PINVOKE_SYMBOL (monodroid_embedded_assemblies_set_assemblies_prefix), + PINVOKE_SYMBOL (monodroid_fopen), + PINVOKE_SYMBOL (monodroid_free), + PINVOKE_SYMBOL (_monodroid_freeifaddrs), + PINVOKE_SYMBOL (_monodroid_gc_wait_for_bridge_processing), + PINVOKE_SYMBOL (_monodroid_get_android_api_level), + PINVOKE_SYMBOL (_monodroid_get_dns_servers), + PINVOKE_SYMBOL (monodroid_get_dylib), + PINVOKE_SYMBOL (_monodroid_get_identity_hash_code), + PINVOKE_SYMBOL (_monodroid_getifaddrs), + PINVOKE_SYMBOL (monodroid_get_log_categories), + PINVOKE_SYMBOL (monodroid_get_namespaced_system_property), + PINVOKE_SYMBOL (_monodroid_get_network_interface_supports_multicast), + PINVOKE_SYMBOL (_monodroid_get_network_interface_up_state), + PINVOKE_SYMBOL (monodroid_get_system_property), + PINVOKE_SYMBOL (_monodroid_gref_get), + PINVOKE_SYMBOL (_monodroid_gref_log), + PINVOKE_SYMBOL (_monodroid_gref_log_delete), + PINVOKE_SYMBOL (_monodroid_gref_log_new), + PINVOKE_SYMBOL (monodroid_log), + PINVOKE_SYMBOL (_monodroid_lref_log_delete), + PINVOKE_SYMBOL (_monodroid_lref_log_new), + PINVOKE_SYMBOL (_monodroid_max_gref_get), + PINVOKE_SYMBOL (monodroid_store_package_name), + PINVOKE_SYMBOL (monodroid_strdup_printf), + PINVOKE_SYMBOL (monodroid_strfreev), + PINVOKE_SYMBOL (monodroid_strsplit), + PINVOKE_SYMBOL (_monodroid_timezone_get_default_id), + PINVOKE_SYMBOL (monodroid_timing_start), + PINVOKE_SYMBOL (monodroid_timing_stop), + PINVOKE_SYMBOL (monodroid_TypeManager_get_java_class_name), + PINVOKE_SYMBOL (_monodroid_weak_gref_delete), + PINVOKE_SYMBOL (_monodroid_weak_gref_new), + PINVOKE_SYMBOL (path_combine), + PINVOKE_SYMBOL (recv_uninterrupted), + PINVOKE_SYMBOL (send_uninterrupted), + PINVOKE_SYMBOL (set_world_accessable), +}; + +MonodroidRuntime::pinvoke_library_map MonodroidRuntime::other_pinvoke_map (MonodroidRuntime::LIBRARY_MAP_INITIAL_BUCKET_COUNT); + +// `pinvoke_map_write_lock` MUST be held when calling this method +force_inline void* +MonodroidRuntime::load_library_entry (std::string const& library_name, std::string const& entrypoint_name, pinvoke_api_map_ptr api_map) +{ + // Make sure some other thread hasn't just added the entry + auto iter = api_map->find (entrypoint_name); + if (iter != api_map->end () && iter->second != nullptr) { + return iter->second; + } + + void *lib_handle = monodroid_dlopen (library_name.c_str (), MONO_DL_LOCAL, nullptr, nullptr); + if (lib_handle == nullptr) { + log_warn (LOG_ASSEMBLY, "Shared library '%s' not loaded, p/invoke '%s' may fail", library_name.c_str (), entrypoint_name.c_str ()); + return nullptr; + } + + void *entry_handle = monodroid_dlsym (lib_handle, entrypoint_name.c_str (), nullptr, nullptr); + if (entry_handle == nullptr) { + log_warn (LOG_ASSEMBLY, "Symbol '%s' not found in shared library '%s', p/invoke may fail", entrypoint_name.c_str (), library_name.c_str ()); + return nullptr; + } + + log_warn (LOG_ASSEMBLY, "Caching p/invoke entry %s @ %s", library_name.c_str (), entrypoint_name.c_str ()); + (*api_map)[entrypoint_name] = entry_handle; + return entry_handle; +} + +force_inline void* +MonodroidRuntime::fetch_or_create_pinvoke_map_entry (std::string const& library_name, std::string const& entrypoint_name, pinvoke_api_map_ptr api_map, bool need_lock) +{ + auto iter = api_map->find (entrypoint_name); + if (iter != api_map->end () && iter->second != nullptr) { + return iter->second; + } + + if (!need_lock) { + return load_library_entry (library_name, entrypoint_name, api_map); + } + + std::lock_guard lock (pinvoke_map_write_lock); + return load_library_entry (library_name, entrypoint_name, api_map); +} + +void* +MonodroidRuntime::monodroid_pinvoke_override (const char *library_name, const char *entrypoint_name) +{ + log_warn (LOG_DEFAULT, "MonodroidRuntime::monodroid_pinvoke_override (\"%s\", \"%s\")", library_name, entrypoint_name); + + timing_period total_time; + if (XA_UNLIKELY (utils.should_log (LOG_TIMING))) { + total_time.mark_start (); + } + + if (library_name == nullptr || *library_name == '\0' || entrypoint_name == nullptr || *entrypoint_name == '\0') { + return nullptr; + } + + bool is_internal; + switch (library_name[0]) { + case 'j': + is_internal = strcmp ("java-interop", library_name) == 0; + break; + + case 'x': + is_internal = strcmp ("xa-internal-api", library_name) == 0; + break; + + default: + is_internal = false; + break; + } + + if (!is_internal) { + std::string lib_name (library_name); + std::string func_name (entrypoint_name); + + auto iter = other_pinvoke_map.find (lib_name); + void *handle = nullptr; + if (iter == other_pinvoke_map.end ()) { + std::lock_guard lock (pinvoke_map_write_lock); + + pinvoke_api_map_ptr lib_map; + // Make sure some other thread hasn't just added the map + iter = other_pinvoke_map.find (lib_name); + if (iter == other_pinvoke_map.end () || iter->second == nullptr) { + lib_map = new pinvoke_api_map (1); + other_pinvoke_map[lib_name] = lib_map; + } else { + lib_map = iter->second; + } + + handle = fetch_or_create_pinvoke_map_entry (lib_name, func_name, lib_map, /* need_lock */ false); + } else { + if (XA_UNLIKELY (iter->second == nullptr)) { + log_warn (LOG_ASSEMBLY, "Internal error: null entry in p/invoke map for key '%s'", library_name); + return nullptr; // fall back to `monodroid_dlopen` + } + + handle = fetch_or_create_pinvoke_map_entry (lib_name, func_name, iter->second, /* need_lock */ true); + } + + if (XA_UNLIKELY (utils.should_log (LOG_TIMING))) { + total_time.mark_end (); + + TIMING_LOG_INFO (total_time, "p/invoke override for '%s' (foreign)", entrypoint_name); + } + + return handle; + } + + timing_period lookup_time; + if (XA_UNLIKELY (utils.should_log (LOG_TIMING))) { + lookup_time.mark_start (); + } + auto iter = xa_pinvoke_map.find (entrypoint_name); + if (iter == xa_pinvoke_map.end ()) { + // TODO: perhaps it should be fatal? + log_fatal (LOG_ASSEMBLY, "Internal p/invoke symbol '%s @ %s' not found in compile-time map.", library_name, entrypoint_name); + abort (); + return nullptr; + } + + if (XA_UNLIKELY (utils.should_log (LOG_TIMING))) { + lookup_time.mark_end (); + total_time.mark_end (); + + TIMING_LOG_INFO (lookup_time, "p/invoke cache lookup for '%s' (internal)", entrypoint_name); + TIMING_LOG_INFO (total_time, "p/invoke override for '%s' (internal)", entrypoint_name); + } + log_warn (LOG_DEFAULT, "Found %s@%s in internal p/invoke map (%p)", library_name, entrypoint_name, iter->second); + return iter->second; +} diff --git a/src/monodroid/jni/util.hh b/src/monodroid/jni/util.hh index 936a0d3380c..15b2fa02938 100644 --- a/src/monodroid/jni/util.hh +++ b/src/monodroid/jni/util.hh @@ -42,6 +42,7 @@ constexpr int FALSE = 0; #include "java-interop-util.h" #include "logger.hh" +#if !defined (NET6) #ifdef __cplusplus extern "C" { #endif // __cplusplus @@ -59,7 +60,10 @@ extern "C" { MONO_API char *path_combine (const char *path1, const char *path2); #ifdef __cplusplus } +#endif // __cplusplus +#endif // NET6 +#ifdef __cplusplus namespace xamarin::android { class Util : public BasicUtilities diff --git a/src/monodroid/monodroid.targets b/src/monodroid/monodroid.targets index 662ece0d650..9610c46361d 100644 --- a/src/monodroid/monodroid.targets +++ b/src/monodroid/monodroid.targets @@ -42,7 +42,9 @@ <_ConfigureRuntimesInputs Include="CMakeLists.txt" /> <_ConfigureRuntimesInputs Include="..\..\build-tools\scripts\Ndk.targets" /> <_ConfigureRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(IntermediateOutputPath)\%(Identity)-Debug\CMakeCache.txt')" /> + <_ConfigureRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(IntermediateOutputPath)\%(Identity)-net6-Debug\CMakeCache.txt')" /> <_ConfigureRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(IntermediateOutputPath)\%(Identity)-Release\CMakeCache.txt')" /> + <_ConfigureRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(IntermediateOutputPath)\%(Identity)-net6-Release\CMakeCache.txt')" /> <_ConfigureRuntimesOutputs Include="@(_HostRuntime->'$(IntermediateOutputPath)%(OutputDirectory)-Debug\CMakeCache.txt')" /> <_ConfigureRuntimesOutputs Include="@(_HostRuntime->'$(IntermediateOutputPath)%(OutputDirectory)-Release\CMakeCache.txt')" /> @@ -66,17 +68,27 @@ DependsOnTargets="_FindMonoDroidSources"> <_BuildAndroidRuntimesInputs Include="@(AndroidSupportedTargetJitAbi->'$(IntermediateOutputPath)\%(Identity)-Debug\CMakeCache.txt')" /> + <_BuildAndroidRuntimesInputs Include="@(AndroidSupportedTargetJitAbi->'$(IntermediateOutputPath)\%(Identity)-net6-Debug\CMakeCache.txt')" /> <_BuildAndroidRuntimesInputs Include="@(AndroidSupportedTargetJitAbi->'$(IntermediateOutputPath)\%(Identity)-Release\CMakeCache.txt')" /> + <_BuildAndroidRuntimesInputs Include="@(AndroidSupportedTargetJitAbi->'$(IntermediateOutputPath)\%(Identity)-net6-Release\CMakeCache.txt')" /> <_BuildAndroidRuntimesInputs Include="@(_MonoDroidSources)" /> <_BuildAndroidRuntimesInputs Include="..\..\build-tools\scripts\Ndk.targets" /> <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)\libmono-android.debug.so')" /> + <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)-net6\libmono-android.debug.so')" /> <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)\libmono-android-checked+ubsan.debug.so')" /> + <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)-net6\libmono-android-checked+ubsan.debug.so')" /> <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)\libmono-android-checked+asan.debug.so')" /> + <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)-net6\libmono-android-checked+asan.debug.so')" /> <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)\libmono-android.release.so')" /> + <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)-net6\libmono-android.release.so')" /> <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)\libmono-android-checked+asan.release.so')" /> + <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)-net6\libmono-android-checked+asan.release.so')" /> <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)\libmono-android-checked+ubsan.release.so')" /> + <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)-net6\libmono-android-checked+ubsan.release.so')" /> <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)\Debug\libxamarin-app.so')" /> + <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)-net6\Debug\libxamarin-app.so')" /> <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)\Release\libxamarin-app.so')" /> + <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)-net6\Release\libxamarin-app.so')" /> @@ -89,31 +101,61 @@ WorkingDirectory="$(IntermediateOutputPath)%(AndroidSupportedTargetJitAbi.Identity)-Debug" /> + + + + + + + + + + + + From bec896911328ac495fdd56b9365c9870022feaab Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Tue, 2 Mar 2021 21:59:32 -0500 Subject: [PATCH 2/2] Reformat .gitmodules --- .gitmodules | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitmodules b/.gitmodules index 8650c47f269..03f994fd0a8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -35,6 +35,10 @@ url = https://github.com/Guardsquare/proguard.git branch = master ignore = dirty +[submodule "external/robin-map"] + path = external/robin-map + url = https://github.com/Tessil/robin-map.git + branch = master [submodule "external/sqlite"] path = external/sqlite url = https://github.com/xamarin/sqlite.git @@ -43,7 +47,3 @@ path = external/xamarin-android-tools url = https://github.com/xamarin/xamarin-android-tools branch = main -[submodule "external/robin-map"] - path = external/robin-map - url = https://github.com/Tessil/robin-map.git - branch = master