From 2b259cd0536fd0678ad45dd436f01c2ff07dc341 Mon Sep 17 00:00:00 2001 From: Jonathan Pryor Date: Mon, 11 Nov 2024 14:21:15 -0500 Subject: [PATCH] [Java.Interop.BootstrapTasks] Filter out invalid JDKs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @jonpryor's developer machines are a "weird", with a macOS arm64 box containing the directories: * `$HOME/android-toolchain/jdk-17` * `$HOME/android-toolchain/jdk-17.x64` Meanwhile, `XAPrepareJdkLocations.GetXAPrepareJdks()` within dotnet/android-tools looks for all directories matching the glob `$HOME/android-toolchains/jdk*`, and thus finds both. For some reason, the JDK that `dotnet build -t:Prepare *.sln` winds up using by default is the the `jdk-17.x64` directory (😱), which cannot be loaded into an arm64 process. This results in errors from `dotnet build`: EXEC : error JM4003: jnimarshalmethod-gen: Unable to create Java VM […/dotnet/java-interop/samples/Hello-NativeAOTFromJNI/Hello-NativeAOTFromJNI.csproj] System.DllNotFoundException: Unable to load shared library '$HOME/android-toolchain/jdk-17.x64/lib/libjli.dylib' or one of its dependencies. In order to help diagnose loading problems, consider setting the DYLD_PRINT_LIBRARIES environment variable: dlopen($HOME/android-toolchain/jdk-17.x64/lib/libjli.dylib, 0x0001): tried: '$HOME/android-toolchain/jdk-17.x64/lib/libjli.dylib' (mach-o file, but is an incompatible architecture (have 'x86_64', need 'arm64e' or 'arm64')), '/System/Volumes/Preboot/Cryptexes/OS/$HOME/android-toolchain/jdk-17.x64/lib/libjli.dylib' (no such file), '$HOME/android-toolchain/jdk-17.x64/lib/libjli.dylib' (mach-o file, but is an incompatible architecture (have 'x86_64', need 'arm64e' or 'arm64')) at System.Runtime.InteropServices.NativeLibrary.Load(String libraryPath) at Java.Interop.NativeLibraryJvmLibraryHandler.LoadJvmLibrary(String path) in $HOME/Developer/src/dotnet/java-interop/src/Java.Runtime.Environment/Java.Interop/JreRuntime.cs:line 231 at Java.Interop.JreRuntime.CreateJreVM(JreRuntimeOptions builder) in $HOME/Developer/src/dotnet/java-interop/src/Java.Runtime.Environment/Java.Interop/JreRuntime.cs:line 104 at Java.Interop.JreRuntime..ctor(JreRuntimeOptions builder) in $HOME/Developer/src/dotnet/java-interop/src/Java.Runtime.Environment/Java.Interop/JreRuntime.cs:line 162 at Java.Interop.JreRuntimeOptions.CreateJreVM() in $HOME/Developer/src/dotnet/java-interop/src/Java.Runtime.Environment/Java.Interop/JreRuntime.cs:line 66 at Xamarin.Android.Tools.JniMarshalMethodGenerator.App.CreateJavaVM(String jvmDllPath) in $HOME/Developer/src/dotnet/java-interop/tools/jnimarshalmethod-gen/App.cs:line 302 … …/dotnet/java-interop/samples/Hello-NativeAOTFromJNI/Hello-NativeAOTFromJNI.targets(44,5): error MSB3073: The command ""/usr/local/share/dotnet/dotnet" "…/dotnet/java-interop/bin/Debug-net8.0//jnimarshalmethod-gen.dll" "…/dotnet/java-interop/samples/Hello-NativeAOTFromJNI/bin/Debug/Hello-NativeAOTFromJNI.dll" -v -v --keeptemp -L "…/dotnet/java-interop/samples/Hello-NativeAOTFromJNI/bin/Debug/" " exited with code 3. […/dotnet/java-interop/samples/Hello-NativeAOTFromJNI/Hello-NativeAOTFromJNI.csproj] Instead of doing the "obvious" of removing `jdk.x64` or renaming it so it doesn't match the glob `jdk*`, update `JdkInfo.GetKnownSystemJdkInfos()` and `JdkInfo.GetSupportedJdkInfos()` to filter out JDKs that cannot be loaded into the current process. This nicely filters out `jdk-17.x64`, allowing dotnet/java-interop to build successfully. --- .../Java.Interop.BootstrapTasks.csproj | 1 + .../Java.Interop.BootstrapTasks/JdkInfo.cs | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/build-tools/Java.Interop.BootstrapTasks/Java.Interop.BootstrapTasks.csproj b/build-tools/Java.Interop.BootstrapTasks/Java.Interop.BootstrapTasks.csproj index f8cd822d4..9e01bae3a 100644 --- a/build-tools/Java.Interop.BootstrapTasks/Java.Interop.BootstrapTasks.csproj +++ b/build-tools/Java.Interop.BootstrapTasks/Java.Interop.BootstrapTasks.csproj @@ -3,6 +3,7 @@ netstandard2.0 false + 11.0 diff --git a/build-tools/Java.Interop.BootstrapTasks/Java.Interop.BootstrapTasks/JdkInfo.cs b/build-tools/Java.Interop.BootstrapTasks/Java.Interop.BootstrapTasks/JdkInfo.cs index 2abf3a6a4..994084afb 100644 --- a/build-tools/Java.Interop.BootstrapTasks/Java.Interop.BootstrapTasks/JdkInfo.cs +++ b/build-tools/Java.Interop.BootstrapTasks/Java.Interop.BootstrapTasks/JdkInfo.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using System.IO; using System.Linq; +using System.Runtime.InteropServices; using System.Text; using System.Text.RegularExpressions; using System.Xml.Linq; @@ -46,6 +47,7 @@ public override bool Execute () .Where (j => maxVersion != null ? j.Version <= maxVersion : true) .Where (j => j.IncludePath.Any ()); var jdk = explicitJdks.Concat (defaultJdks) + .Where (j => JdkRunsOnHost (j)) .FirstOrDefault (); if (jdk == null) { @@ -71,6 +73,19 @@ public override bool Execute () return !Log.HasLoggedErrors; } + static bool JdkRunsOnHost (XATInfo jdk) + { + var cputype = RuntimeInformation.ProcessArchitecture; + if (jdk.ReleaseProperties.TryGetValue ("OS_ARCH", out var arch)) { + return (cputype, arch) switch { + (Architecture.Arm64, "aarch64") => true, + (Architecture.X64, "x86_64") => true, + _ => false, + }; + } + return true; + } + XATInfo[] GetJdkRoots () { XATInfo jdk = null;