diff --git a/msbuild/Messaging/Xamarin.Messaging.Build/TaskRunner.cs b/msbuild/Messaging/Xamarin.Messaging.Build/TaskRunner.cs index 264ac4d1579..c03ff7a948d 100644 --- a/msbuild/Messaging/Xamarin.Messaging.Build/TaskRunner.cs +++ b/msbuild/Messaging/Xamarin.Messaging.Build/TaskRunner.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; @@ -10,24 +11,15 @@ namespace Xamarin.Messaging.Build { internal class TaskRunner : ITaskRunner { - ITaskSerializer serializer; - List tasks = new List (); + static readonly ITracer tracer = Tracer.Get (); + + readonly ITaskSerializer serializer; + readonly List tasks = new List (); internal TaskRunner (ITaskSerializer serializer) { this.serializer = serializer; - - var sdkRootPath = Path.Combine (MessagingContext.GetXmaPath (), "SDKs"); - var dotnetPath = Path.Combine (sdkRootPath, "dotnet", "dotnet"); - - if (File.Exists (dotnetPath)) { - Environment.SetEnvironmentVariable ("DOTNET_CUSTOM_HOME", Path.Combine (sdkRootPath, ".home")); - } else { - //In case the XMA dotnet has not been installed yet - dotnetPath = "/usr/local/share/dotnet/dotnet"; - } - - Environment.SetEnvironmentVariable ("DOTNET_HOST_PATH", dotnetPath); + SetDotNetVariables (); } internal IEnumerable Tasks => tasks.AsReadOnly (); @@ -57,5 +49,68 @@ public ExecuteTaskResult Execute (string taskName, string inputs) return result; } + + void SetDotNetVariables () + { + var xmaSdkRootPath = Path.Combine (MessagingContext.GetXmaPath (), "SDKs"); + var xmaDotNetRootPath = Path.Combine (xmaSdkRootPath, "dotnet"); + var xmaDotNetPath = default (string); + + if (IsValidDotNetInstallation (xmaDotNetRootPath)) { + //If the XMA dotnet is already installed, we use it and also declare a custom home for it (for NuGet restore and caches) + Environment.SetEnvironmentVariable ("DOTNET_CUSTOM_HOME", Path.Combine (xmaSdkRootPath, ".home")); + xmaDotNetPath = GetDotNetPath (xmaDotNetRootPath); + } else { + //In case the XMA dotnet has not been installed yet, we use the default dotnet installation + xmaDotNetPath = GetDefaultDotNetPath (); + xmaDotNetRootPath = Path.GetDirectoryName (xmaDotNetPath); + } + + var pathContent = GetPathContent (); + //We add the XMA dotnet path first so it has priority over the default dotnet installation + var newPathContent = $"{xmaDotNetRootPath}:{pathContent}"; + + //Override the PATH with the XMA dotnet in it, just in case it's used internally by dotnet + Environment.SetEnvironmentVariable ("PATH", newPathContent); + //Deprecated dotnet environment variable. We still preserve ir for backwards compatibility with other components that haven't deprecated it yet (like dotnet ILLink) + Environment.SetEnvironmentVariable ("DOTNET_HOST_PATH", xmaDotNetPath); + //Custom environment variable for internal iOS SDK usage + Environment.SetEnvironmentVariable ("DOTNET_CUSTOM_PATH", xmaDotNetPath); + + tracer.Info ($"Using dotnet: {xmaDotNetPath}"); + tracer.Info ($"Current PATH: {newPathContent}"); + } + + string GetDefaultDotNetPath () + { + var dotnetRootPath = "/usr/local/share/dotnet"; + + if (IsValidDotNetInstallation (dotnetRootPath)) { + return GetDotNetPath (dotnetRootPath); + } + + var dotnetPath = "dotnet"; + var pathContent = GetPathContent (); + var pathElements = pathContent.Split (new string [] { ":" }, StringSplitOptions.RemoveEmptyEntries); + + foreach (var pathElement in pathElements) { + try { + if (IsValidDotNetInstallation (pathElement)) { + dotnetPath = GetDotNetPath (pathElement); + break; + } + } catch { + //If we can't read a directory for any reason just skip it + } + } + + return dotnetPath; + } + + string GetPathContent () => Environment.GetEnvironmentVariable ("PATH") ?? ""; + + bool IsValidDotNetInstallation (string rootPath) => File.Exists (GetDotNetPath (rootPath)); + + string GetDotNetPath (string rootPath) => Path.Combine (rootPath, "dotnet"); } } diff --git a/msbuild/Xamarin.MacDev.Tasks/Extensions/TaskExtensions.cs b/msbuild/Xamarin.MacDev.Tasks/Extensions/TaskExtensions.cs index 9cf5682353b..0d985e5b135 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Extensions/TaskExtensions.cs +++ b/msbuild/Xamarin.MacDev.Tasks/Extensions/TaskExtensions.cs @@ -5,5 +5,22 @@ namespace Microsoft.Build.Tasks { public static class TaskExtensions { public static bool ShouldExecuteRemotely (this Task task, string sessionId) => Environment.OSVersion.Platform == PlatformID.Win32NT && !string.IsNullOrEmpty (sessionId); + + public static string GetDotNetPath (this Task task) + { + //Custom environment variable set by the XMA Build Agent + var dotnetPath = Environment.GetEnvironmentVariable ("DOTNET_CUSTOM_PATH"); + + if (string.IsNullOrEmpty (dotnetPath)) { + //Deprecated dotnet environment variable used for backwards compatibility + dotnetPath = Environment.GetEnvironmentVariable ("DOTNET_HOST_PATH"); + } + + if (string.IsNullOrEmpty (dotnetPath)) { + dotnetPath = Environment.OSVersion.Platform == PlatformID.Win32NT ? "dotnet.exe" : "dotnet"; + } + + return dotnetPath; + } } } diff --git a/msbuild/Xamarin.MacDev.Tasks/Tasks/BTouchTaskBase.cs b/msbuild/Xamarin.MacDev.Tasks/Tasks/BTouchTaskBase.cs index bfc97a58e84..55b441f26a7 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Tasks/BTouchTaskBase.cs +++ b/msbuild/Xamarin.MacDev.Tasks/Tasks/BTouchTaskBase.cs @@ -8,6 +8,7 @@ using Microsoft.Build.Framework; using Microsoft.Build.Utilities; +using Microsoft.Build.Tasks; using Xamarin.Utils; using Xamarin.Localization.MSBuild; @@ -75,26 +76,10 @@ public abstract class BTouchTaskBase : XamarinToolTask { [Required] public string ResponseFilePath { get; set; } - string DotNetPath { - get { - // Return the dotnet executable we're executing with. - var dotnet_path = Environment.GetEnvironmentVariable ("DOTNET_HOST_PATH"); - if (!string.IsNullOrEmpty (dotnet_path)) - return dotnet_path; - - if (Environment.OSVersion.Platform == PlatformID.Win32NT) { - // This might happen when building from inside VS (design-time builds, etc.) - return "dotnet.exe"; - } - - throw new InvalidOperationException ($"DOTNET_HOST_PATH is not set"); - } - } - protected override string ToolName { get { if (IsDotNet) - return Path.GetFileName (DotNetPath); + return Path.GetFileName (this.GetDotNetPath ()); return Path.GetFileNameWithoutExtension (ToolExe); } @@ -108,7 +93,7 @@ protected override string GenerateFullPathToTool () // system dotnet, which might not exist or not have the version we // need. if (IsDotNet) - return DotNetPath; + return this.GetDotNetPath (); return Path.Combine (ToolPath, ToolExe); } diff --git a/msbuild/Xamarin.MacDev.Tasks/Tasks/ComputeRemoteGeneratorPropertiesTaskBase.cs b/msbuild/Xamarin.MacDev.Tasks/Tasks/ComputeRemoteGeneratorPropertiesTaskBase.cs index 61e0c045ff0..74d8900d42a 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Tasks/ComputeRemoteGeneratorPropertiesTaskBase.cs +++ b/msbuild/Xamarin.MacDev.Tasks/Tasks/ComputeRemoteGeneratorPropertiesTaskBase.cs @@ -4,6 +4,7 @@ using System.IO; using Microsoft.Build.Framework; +using Microsoft.Build.Tasks; using Xamarin.Localization.MSBuild; using Xamarin.Utils; @@ -93,9 +94,8 @@ void ComputeProperties () var environment = default (Dictionary); if (IsDotNet) { - executable = Environment.GetEnvironmentVariable ("DOTNET_HOST_PATH"); - if (string.IsNullOrEmpty (executable)) - executable = "dotnet"; + executable = this.GetDotNetPath (); + arguments.Add ("build"); var customHome = Environment.GetEnvironmentVariable ("DOTNET_CUSTOM_HOME"); diff --git a/msbuild/Xamarin.MacDev.Tasks/Tasks/XamarinBuildTask.cs b/msbuild/Xamarin.MacDev.Tasks/Tasks/XamarinBuildTask.cs index d6c36ed3448..d5c341c77cf 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Tasks/XamarinBuildTask.cs +++ b/msbuild/Xamarin.MacDev.Tasks/Tasks/XamarinBuildTask.cs @@ -3,6 +3,7 @@ using System.IO; using System.Linq; using Microsoft.Build.Framework; +using Microsoft.Build.Tasks; using Xamarin.Localization.MSBuild; using Threading = System.Threading.Tasks; @@ -35,12 +36,7 @@ protected string ComputeValueUsingTarget (string computeValueTarget, string targ "; File.WriteAllText (projectPath, csproj); - var dotnetPath = Environment.GetEnvironmentVariable ("DOTNET_HOST_PATH"); - - if (string.IsNullOrEmpty (dotnetPath)) { - dotnetPath = "dotnet"; - } - + var dotnetPath = this.GetDotNetPath (); var environment = default (Dictionary); var customHome = Environment.GetEnvironmentVariable ("DOTNET_CUSTOM_HOME");