diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/ResolveJdkJvmPath.cs b/src/Xamarin.Android.Build.Tasks/Tasks/ResolveJdkJvmPath.cs index f4a895f6484..8695693ca35 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/ResolveJdkJvmPath.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/ResolveJdkJvmPath.cs @@ -20,6 +20,12 @@ public class ResolveJdkJvmPath : AndroidTask [Output] public string JdkJvmPath { get; set; } + [Required] + public string MinimumSupportedJavaVersion { get; set; } + + [Required] + public string LatestSupportedJavaVersion { get; set; } + public override bool RunTask () { try { @@ -54,12 +60,10 @@ string GetJvmPath () return cached; } - JdkInfo info = null; - try { - info = new JdkInfo (JavaSdkPath); - } catch { - info = JdkInfo.GetKnownSystemJdkInfos (this.CreateTaskLogger ()).FirstOrDefault (); - } + var minVersion = Version.Parse (MinimumSupportedJavaVersion); + var maxVersion = Version.Parse (LatestSupportedJavaVersion); + + JdkInfo info = MonoAndroidHelper.GetJdkInfo (this.CreateTaskLogger (), JavaSdkPath, minVersion, maxVersion); if (info == null) return null; diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/ResolveSdksTask.cs b/src/Xamarin.Android.Build.Tasks/Tasks/ResolveSdksTask.cs index 119ac921a23..d3096519471 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/ResolveSdksTask.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/ResolveSdksTask.cs @@ -46,6 +46,12 @@ public class ResolveSdks : AndroidTask public string CommandLineToolsVersion { get; set; } + [Required] + public string MinimumSupportedJavaVersion { get; set; } + + [Required] + public string LatestSupportedJavaVersion { get; set; } + [Output] public string CommandLineToolsPath { get; set; } @@ -81,6 +87,11 @@ public override bool RunTask () MonoAndroidLibPath = MonoAndroidHelper.GetOSLibPath () + Path.DirectorySeparatorChar; AndroidBinUtilsPath = MonoAndroidBinPath + "ndk" + Path.DirectorySeparatorChar; + var minVersion = Version.Parse (MinimumSupportedJavaVersion); + var maxVersion = Version.Parse (LatestSupportedJavaVersion); + + JavaSdkPath = MonoAndroidHelper.GetJdkInfo (this.CreateTaskLogger (), JavaSdkPath, minVersion, maxVersion)?.HomePath; + MonoAndroidHelper.RefreshSupportedVersions (ReferenceAssemblyPaths); try { diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/ValidateJavaVersion.cs b/src/Xamarin.Android.Build.Tasks/Tasks/ValidateJavaVersion.cs index 96ff11c975c..7d42a5c328d 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/ValidateJavaVersion.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/ValidateJavaVersion.cs @@ -48,12 +48,12 @@ public override bool RunTask () // `java -version` will produce values such as: // java version "9.0.4" // java version "1.8.0_77" - static readonly Regex JavaVersionRegex = new Regex (@"version ""(?[\d\.]+)(_d+)?[^""]*"""); + static readonly Regex JavaVersionRegex = new Regex (@"version ""(?[\d\.]+)(_\d+)?[^""]*"""); // `javac -version` will produce values such as: // javac 9.0.4 // javac 1.8.0_77 - static readonly Regex JavacVersionRegex = new Regex (@"(?[\d\.]+)(_d+)?"); + internal static readonly Regex JavacVersionRegex = new Regex (@"(?[\d\.]+)(_\d+)?"); bool ValidateJava () { diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/ResolveSdksTaskTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/ResolveSdksTaskTests.cs index 1e3a2d05267..394d6d3f1b1 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/ResolveSdksTaskTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/ResolveSdksTaskTests.cs @@ -25,6 +25,10 @@ public class ResolveSdksTaskTests : BaseTest { new ApiInfo () { Id = "Z", Level = 127, Name = "Z", FrameworkVersion = "v108.1.99", Stable = false }, }; + // via Xamarin.Android.Common.props + const string MinimumSupportedJavaVersion = "1.6.0"; + const string LatestSupportedJavaVersion = "11.0.99"; + static object [] UseLatestAndroidSdkTestCases = new object [] { new object[] { /* buildtools */ "26.0.3", @@ -167,6 +171,8 @@ public void UseLatestAndroidSdk (string buildtools, string jdk, ApiInfo[] apis, AndroidSdkPath = androidSdkPath, AndroidNdkPath = androidNdkPath, JavaSdkPath = javaPath, + MinimumSupportedJavaVersion = MinimumSupportedJavaVersion, + LatestSupportedJavaVersion = LatestSupportedJavaVersion, ReferenceAssemblyPaths = new [] { Path.Combine (referencePath, "MonoAndroid"), }, @@ -220,6 +226,8 @@ public void ResolveSdkTiming () AndroidSdkPath = androidSdkPath, AndroidNdkPath = androidNdkPath, JavaSdkPath = javaPath, + MinimumSupportedJavaVersion = MinimumSupportedJavaVersion, + LatestSupportedJavaVersion = LatestSupportedJavaVersion, ReferenceAssemblyPaths = new [] { Path.Combine (referencePath, "MonoAndroid"), }, @@ -391,6 +399,8 @@ public void TargetFrameworkPairing (string description, ApiInfo[] androidSdk, Ap AndroidSdkPath = androidSdkPath, AndroidNdkPath = androidNdkPath, JavaSdkPath = javaPath, + MinimumSupportedJavaVersion = MinimumSupportedJavaVersion, + LatestSupportedJavaVersion = LatestSupportedJavaVersion, ReferenceAssemblyPaths = new [] { Path.Combine (referencePath, "MonoAndroid"), }, diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs index 06a56115d4a..d43df6e4b3b 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs @@ -389,48 +389,93 @@ protected string CreateFauxReferencesDirectory (string path, ApiInfo [] versions protected string CreateFauxJavaSdkDirectory (string path, string javaVersion, out string javaExe, out string javacExe) { - javaExe = IsWindows ? "Java.cmd" : "java.bash"; - javacExe = IsWindows ? "Javac.cmd" : "javac.bash"; - var jarSigner = IsWindows ? "jarsigner.exe" : "jarsigner"; + javaExe = IsWindows ? "java.cmd" : "java"; + javacExe = IsWindows ? "javac.cmd" : "javac"; + var javaPath = Path.Combine (Root, path); - var javaBinPath = Path.Combine (javaPath, "bin"); - Directory.CreateDirectory (javaBinPath); - CreateFauxJavaExe (Path.Combine (javaBinPath, javaExe), javaVersion); - CreateFauxJavacExe (Path.Combine (javaBinPath, javacExe), javaVersion); + CreateFauxJdk (javaPath, javaVersion, javaVersion, javaVersion); + var jarSigner = IsWindows ? "jarsigner.exe" : "jarsigner"; + var javaBinPath = Path.Combine (javaPath, "bin"); File.WriteAllText (Path.Combine (javaBinPath, jarSigner), ""); + return javaPath; } - void CreateFauxJavaExe (string javaExeFullPath, string version) + // https://github.com/xamarin/xamarin-android-tools/blob/683f37508b56c76c24b3287a5687743438625341/tests/Xamarin.Android.Tools.AndroidSdk-Tests/JdkInfoTests.cs#L60-L100 + void CreateFauxJdk (string dir, string releaseVersion, string releaseBuildNumber, string javaVersion) { - var sb = new StringBuilder (); - if (IsWindows) { - sb.AppendLine ("@echo off"); - sb.AppendLine ($"echo java version \"{version}\""); - sb.AppendLine ($"echo Java(TM) SE Runtime Environment (build {version}-b13)"); - sb.AppendLine ($"echo Java HotSpot(TM) 64-Bit Server VM (build 25.101-b13, mixed mode)"); - } else { - sb.AppendLine ("#!/bin/bash"); - sb.AppendLine ($"echo \"java version \\\"{version}\\\"\""); - sb.AppendLine ($"echo \"Java(TM) SE Runtime Environment (build {version}-b13)\""); - sb.AppendLine ($"echo \"Java HotSpot(TM) 64-Bit Server VM (build 25.101-b13, mixed mode)\""); - } - CreateFauxExecutable (javaExeFullPath, sb); - } - - void CreateFauxJavacExe (string javacExeFullPath, string version) + Directory.CreateDirectory (dir); + + using (var release = new StreamWriter (Path.Combine (dir, "release"))) { + release.WriteLine ($"JAVA_VERSION=\"{releaseVersion}\""); + release.WriteLine ($"BUILD_NUMBER={releaseBuildNumber}"); + release.WriteLine ($"JUST_A_KEY"); + } + + var bin = Path.Combine (dir, "bin"); + var inc = Path.Combine (dir, "include"); + var jre = Path.Combine (dir, "jre"); + var jli = Path.Combine (jre, "lib", "jli"); + + Directory.CreateDirectory (bin); + Directory.CreateDirectory (inc); + Directory.CreateDirectory (jli); + Directory.CreateDirectory (jre); + + string quote = IsWindows ? "" : "\""; + string java = IsWindows + ? $"echo java version \"{javaVersion}\"{Environment.NewLine}" + : $"echo java version '\"{javaVersion}\"'{Environment.NewLine}"; + java = java + + $"echo Property settings:{Environment.NewLine}" + + $"echo {quote} java.home = {dir}{quote}{Environment.NewLine}" + + $"echo {quote} java.vendor = Xamarin.Android Unit Tests{quote}{Environment.NewLine}" + + $"echo {quote} java.version = {javaVersion}{quote}{Environment.NewLine}" + + $"echo {quote} xamarin.multi-line = line the first{quote}{Environment.NewLine}" + + $"echo {quote} line the second{quote}{Environment.NewLine}" + + $"echo {quote} .{quote}{Environment.NewLine}"; + + string javac = + $"echo javac {javaVersion}{Environment.NewLine}"; + + CreateShellScript (Path.Combine (bin, "jar"), ""); + CreateShellScript (Path.Combine (bin, "java"), java); + CreateShellScript (Path.Combine (bin, "javac"), javac); + CreateShellScript (Path.Combine (jli, "libjli.dylib"), ""); + CreateShellScript (Path.Combine (jre, "libjvm.so"), ""); + CreateShellScript (Path.Combine (jre, "jvm.dll"), ""); + } + + // https://github.com/xamarin/xamarin-android-tools/blob/683f37508b56c76c24b3287a5687743438625341/tests/Xamarin.Android.Tools.AndroidSdk-Tests/JdkInfoTests.cs#L108-L132 + void CreateShellScript (string path, string contents) { - var sb = new StringBuilder (); - if (IsWindows) { - sb.AppendLine ("@echo off"); - sb.AppendLine ($"echo javac {version}"); - } else { - sb.AppendLine ("#!/bin/bash"); - sb.AppendLine ($"echo \"javac {version}\""); + if (IsWindows && string.Compare (Path.GetExtension (path), ".dll", true) != 0) + path += ".cmd"; + using (var script = new StreamWriter (path)) { + if (IsWindows) { + script.WriteLine ("@echo off"); + } + else { + script.WriteLine ("#!/bin/sh"); + } + script.WriteLine (contents); } - CreateFauxExecutable (javacExeFullPath, sb); + if (IsWindows) + return; + var chmod = new ProcessStartInfo { + FileName = "chmod", + Arguments = $"+x \"{path}\"", + UseShellExecute = false, + RedirectStandardInput = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + CreateNoWindow = true, + WindowStyle = ProcessWindowStyle.Hidden, + }; + var p = Process.Start (chmod); + p.WaitForExit (); } void CreateFauxExecutable (string exeFullPath, StringBuilder sb) { diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs b/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs index 2009451e793..1490bcb8ba8 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs @@ -122,6 +122,19 @@ public static void RefreshSupportedVersions (string[] referenceAssemblyPaths) } #endif // MSBUILD + public static JdkInfo GetJdkInfo (Action logger, string javaSdkPath, Version minSupportedVersion, Version maxSupportedVersion) + { + JdkInfo info = null; + try { + info = new JdkInfo (javaSdkPath); + } catch { + info = JdkInfo.GetKnownSystemJdkInfos (logger) + .Where (jdk => jdk.Version >= minSupportedVersion && jdk.Version <= maxSupportedVersion) + .FirstOrDefault (); + } + return info; + } + class SizeAndContentFileComparer : IEqualityComparer #if MSBUILD , IEqualityComparer diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Tooling.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Tooling.targets index 89f8f520550..bff4c81f9cb 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Tooling.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Tooling.targets @@ -67,6 +67,8 @@ projects. AndroidSdkPath="$(AndroidSdkDirectory)" AndroidNdkPath="$(AndroidNdkDirectory)" JavaSdkPath="$(JavaSdkDirectory)" + MinimumSupportedJavaVersion="$(MinimumSupportedJavaVersion)" + LatestSupportedJavaVersion="$(LatestSupportedJavaVersion)" ReferenceAssemblyPaths="$(_XATargetFrameworkDirectories)"> @@ -82,6 +84,8 @@ projects.