From 8036856ca1b606a395475d44435d7cbeb75a30f9 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Fri, 9 Nov 2018 08:40:59 -0600 Subject: [PATCH] [Xamarin.Android.Build.Tasks] locate $(JdkJvmPath) only when needed Fixes: https://github.com/xamarin/xamarin-android/issues/2409 Context: https://github.com/xamarin/xamarin-android/wiki/Build-Performance-Results When doing the latest performance comparison, I noticed the `` MSBuild task is a bit slower: * VS 15.9 80 ms ResolveSdks 7 calls * VS 16.0 p2 (master) 127 ms ResolveSdks 7 calls For `$(AndroidGenerateJniMarshalMethods)` support, we needed to locate a new `$(JdkJvmPath)` location. Since `` finds `$(JdkJvmPath)` on first build, and design-time builds, it is worth making sure this task doesn't get any slower. The initial design-time build happens on "solution create", which is one of the more important metrics the VS team measures. So I split out the logic finding `$(JdkJvmPath)` and put it in a new `` MSBuild task. Also setup a `Condition`, so it only runs if: - Not a `$(DesignTimeBuild)` - `$(AndroidGenerateJniMarshalMethods)` is enabled - `$(JdkJvmPath)` is blank This should save ~50ms on DTBs and first builds. --- .../Tasks/ResolveJdkJvmPath.cs | 71 +++++++++++++++++++ .../Tasks/ResolveSdksTask.cs | 50 ------------- .../Xamarin.Android.Build.Tasks.csproj | 1 + .../Xamarin.Android.Common.targets | 7 +- 4 files changed, 78 insertions(+), 51 deletions(-) create mode 100644 src/Xamarin.Android.Build.Tasks/Tasks/ResolveJdkJvmPath.cs diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/ResolveJdkJvmPath.cs b/src/Xamarin.Android.Build.Tasks/Tasks/ResolveJdkJvmPath.cs new file mode 100644 index 00000000000..6213e37288f --- /dev/null +++ b/src/Xamarin.Android.Build.Tasks/Tasks/ResolveJdkJvmPath.cs @@ -0,0 +1,71 @@ +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +using System; +using System.IO; +using System.Linq; +using Xamarin.Android.Tools; + +namespace Xamarin.Android.Tasks +{ + /// + /// This MSBuild task's job is to find $(JdkJvmPath) used by $(AndroidGenerateJniMarshalMethods) + /// + public class ResolveJdkJvmPath : Task + { + public string JavaSdkPath { get; set; } + + [Output] + public string JdkJvmPath { get; set; } + + public override bool Execute () + { + try { + JdkJvmPath = GetJvmPath (); + } catch (Exception e) { + Log.LogCodedError ("XA5300", $"Unable to find {nameof (JdkJvmPath)}{Environment.NewLine}{e}"); + return false; + } + + if (string.IsNullOrEmpty (JdkJvmPath)) { + Log.LogCodedError ("XA5300", $"{nameof (JdkJvmPath)} is blank"); + return false; + } + + if (!File.Exists (JdkJvmPath)) { + Log.LogCodedError ("XA5300", $"JdkJvmPath not found at {JdkJvmPath}"); + return false; + } + + return !Log.HasLoggedErrors; + } + + string GetJvmPath () + { + var key = new Tuple (nameof (ResolveJdkJvmPath), JavaSdkPath); + var cached = BuildEngine4.GetRegisteredTaskObject (key, RegisteredTaskObjectLifetime.AppDomain) as string; + if (cached != null) { + Log.LogDebugMessage ($"Using cached value for {nameof (JdkJvmPath)}: {cached}"); + + return cached; + } + + JdkInfo info = null; + try { + info = new JdkInfo (JavaSdkPath); + } catch { + info = JdkInfo.GetKnownSystemJdkInfos (this.CreateTaskLogger ()).FirstOrDefault (); + } + + if (info == null) + return null; + + var path = info.JdkJvmPath; + if (string.IsNullOrEmpty (path)) + return null; + + BuildEngine4.RegisterTaskObject (key, path, RegisteredTaskObjectLifetime.AppDomain, allowEarlyCollection: false); + + return path; + } + } +} diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/ResolveSdksTask.cs b/src/Xamarin.Android.Build.Tasks/Tasks/ResolveSdksTask.cs index 96bded448da..47affd4ea2a 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/ResolveSdksTask.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/ResolveSdksTask.cs @@ -50,9 +50,6 @@ public class ResolveSdks : Task [Output] public string JavaSdkPath { get; set; } - [Output] - public string JdkJvmPath { get; set; } - [Output] public string MonoAndroidToolsPath { get; set; } @@ -96,65 +93,18 @@ public override bool Execute () return false; } - try { - JdkJvmPath = GetJvmPath (); - } catch (Exception e) { - Log.LogCodedError ("XA5300", $"Unable to find {nameof (JdkJvmPath)}{Environment.NewLine}{e}"); - return false; - } - - if (string.IsNullOrEmpty (JdkJvmPath)) { - Log.LogCodedError ("XA5300", $"{nameof (JdkJvmPath)} is blank"); - return false; - } - - if (!File.Exists (JdkJvmPath)) { - Log.LogCodedError ("XA5300", $"JdkJvmPath not found at {JdkJvmPath}"); - return false; - } - MonoAndroidHelper.TargetFrameworkDirectories = ReferenceAssemblyPaths; Log.LogDebugMessage ($"{nameof (ResolveSdks)} Outputs:"); Log.LogDebugMessage ($" {nameof (AndroidSdkPath)}: {AndroidSdkPath}"); Log.LogDebugMessage ($" {nameof (AndroidNdkPath)}: {AndroidNdkPath}"); Log.LogDebugMessage ($" {nameof (JavaSdkPath)}: {JavaSdkPath}"); - Log.LogDebugMessage ($" {nameof (JdkJvmPath)}: {JdkJvmPath}"); Log.LogDebugMessage ($" {nameof (MonoAndroidBinPath)}: {MonoAndroidBinPath}"); Log.LogDebugMessage ($" {nameof (MonoAndroidToolsPath)}: {MonoAndroidToolsPath}"); //note: this task does not error out if it doesn't find all things. that's the job of the targets return !Log.HasLoggedErrors; } - - string GetJvmPath () - { - var key = new Tuple (nameof (ResolveSdks), JavaSdkPath); - var cached = BuildEngine4.GetRegisteredTaskObject (key, RegisteredTaskObjectLifetime.AppDomain) as string; - if (cached != null) { - Log.LogDebugMessage ($"Using cached value for {nameof (JdkJvmPath)}: {cached}"); - - return cached; - } - - Xamarin.Android.Tools.JdkInfo info = null; - try { - info = new Xamarin.Android.Tools.JdkInfo (JavaSdkPath); - } catch { - info = Xamarin.Android.Tools.JdkInfo.GetKnownSystemJdkInfos (this.CreateTaskLogger ()).FirstOrDefault (); - } - - if (info == null) - return null; - - var path = info.JdkJvmPath; - if (string.IsNullOrEmpty (path)) - return null; - - BuildEngine4.RegisterTaskObject (key, path, RegisteredTaskObjectLifetime.AppDomain, allowEarlyCollection: false); - - return path; - } } } diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj index 18761fa5376..b42f32795c3 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj @@ -142,6 +142,7 @@ + diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 56922330dbc..b584525693e 100755 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -27,6 +27,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved. + @@ -710,10 +711,14 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved. - + + +