From 0c032ef8e5ad794d4425e21bb6d1dd09a0e836b4 Mon Sep 17 00:00:00 2001 From: Mauro Agnoletti Date: Thu, 20 Jul 2023 10:22:24 -0400 Subject: [PATCH 1/2] [dotnet][xma] Ensure we don't use DOTNET_ROOT and DOTNET_HOST_PATH in the Build Agent and remote tasks DOTNET_ROOT and DOTNET_HOST_PATH are being deprecated as a mechanism to store the location of dotnet. PATH will be used instead, so we should ensure that the existing code that makes usage of these variables is adapted to the new guidelines. More information: https://github.com/dotnet/roslyn/commit/f454d6960e979b6643f805f66f619650024a3f34 https://github.com/dotnet/runtime/issues/88754#issuecomment-1632957579 Additionally, to avoid confusion, we are using a dedicate DOTNET_CUSTOM_PATH variable with the path of the dotnet used by the XMA Build Agent, so it can be used internally by the tasks without mixing it with the existing dotnet variables --- .../Xamarin.Messaging.Build/TaskRunner.cs | 88 ++++++++++++++++--- .../Extensions/TaskExtensions.cs | 16 ++++ .../Tasks/BTouchTaskBase.cs | 21 +---- ...omputeRemoteGeneratorPropertiesTaskBase.cs | 6 +- .../Tasks/XamarinBuildTask.cs | 8 +- 5 files changed, 98 insertions(+), 41 deletions(-) diff --git a/msbuild/Messaging/Xamarin.Messaging.Build/TaskRunner.cs b/msbuild/Messaging/Xamarin.Messaging.Build/TaskRunner.cs index 264ac4d15790..47009288bf69 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,73 @@ 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 9cf5682353bb..9cdcca0e9f11 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Extensions/TaskExtensions.cs +++ b/msbuild/Xamarin.MacDev.Tasks/Extensions/TaskExtensions.cs @@ -5,5 +5,21 @@ 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 bfc97a58e84d..0cd8f4c33cf9 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 61e0c045ff0e..663364307d38 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 d6c36ed34481..f80483523704 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"); From b99de6ae9c252dcf2b8993380aac56baffbe72dc Mon Sep 17 00:00:00 2001 From: GitHub Actions Autoformatter Date: Wed, 26 Jul 2023 18:51:59 +0000 Subject: [PATCH 2/2] Auto-format source code --- .../Xamarin.Messaging.Build/TaskRunner.cs | 47 +++++++++---------- .../Extensions/TaskExtensions.cs | 3 +- .../Tasks/BTouchTaskBase.cs | 4 +- ...omputeRemoteGeneratorPropertiesTaskBase.cs | 2 +- .../Tasks/XamarinBuildTask.cs | 2 +- 5 files changed, 27 insertions(+), 31 deletions(-) diff --git a/msbuild/Messaging/Xamarin.Messaging.Build/TaskRunner.cs b/msbuild/Messaging/Xamarin.Messaging.Build/TaskRunner.cs index 47009288bf69..c03ff7a948d5 100644 --- a/msbuild/Messaging/Xamarin.Messaging.Build/TaskRunner.cs +++ b/msbuild/Messaging/Xamarin.Messaging.Build/TaskRunner.cs @@ -19,7 +19,7 @@ internal class TaskRunner : ITaskRunner { internal TaskRunner (ITaskSerializer serializer) { this.serializer = serializer; - SetDotNetVariables(); + SetDotNetVariables (); } internal IEnumerable Tasks => tasks.AsReadOnly (); @@ -50,23 +50,23 @@ public ExecuteTaskResult Execute (string taskName, string inputs) return result; } - void SetDotNetVariables() + void SetDotNetVariables () { var xmaSdkRootPath = Path.Combine (MessagingContext.GetXmaPath (), "SDKs"); var xmaDotNetRootPath = Path.Combine (xmaSdkRootPath, "dotnet"); - var xmaDotNetPath = default(string); + var xmaDotNetPath = default (string); - if (IsValidDotNetInstallation(xmaDotNetRootPath)) { + 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); + xmaDotNetPath = GetDotNetPath (xmaDotNetRootPath); } else { //In case the XMA dotnet has not been installed yet, we use the default dotnet installation - xmaDotNetPath = GetDefaultDotNetPath(); + xmaDotNetPath = GetDefaultDotNetPath (); xmaDotNetRootPath = Path.GetDirectoryName (xmaDotNetPath); } - var pathContent = GetPathContent(); + var pathContent = GetPathContent (); //We add the XMA dotnet path first so it has priority over the default dotnet installation var newPathContent = $"{xmaDotNetRootPath}:{pathContent}"; @@ -81,30 +81,25 @@ void SetDotNetVariables() tracer.Info ($"Current PATH: {newPathContent}"); } - string GetDefaultDotNetPath() + string GetDefaultDotNetPath () { var dotnetRootPath = "/usr/local/share/dotnet"; - if (IsValidDotNetInstallation(dotnetRootPath)) { - return GetDotNetPath(dotnetRootPath); + 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); + 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 - { + } catch { //If we can't read a directory for any reason just skip it } } @@ -112,10 +107,10 @@ string GetDefaultDotNetPath() return dotnetPath; } - string GetPathContent() => Environment.GetEnvironmentVariable("PATH") ?? ""; + string GetPathContent () => Environment.GetEnvironmentVariable ("PATH") ?? ""; - bool IsValidDotNetInstallation(string rootPath) => File.Exists (GetDotNetPath(rootPath)); + bool IsValidDotNetInstallation (string rootPath) => File.Exists (GetDotNetPath (rootPath)); - string GetDotNetPath(string rootPath) => Path.Combine (rootPath, "dotnet"); + 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 9cdcca0e9f11..0d985e5b1355 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Extensions/TaskExtensions.cs +++ b/msbuild/Xamarin.MacDev.Tasks/Extensions/TaskExtensions.cs @@ -6,7 +6,8 @@ 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) { + public static string GetDotNetPath (this Task task) + { //Custom environment variable set by the XMA Build Agent var dotnetPath = Environment.GetEnvironmentVariable ("DOTNET_CUSTOM_PATH"); diff --git a/msbuild/Xamarin.MacDev.Tasks/Tasks/BTouchTaskBase.cs b/msbuild/Xamarin.MacDev.Tasks/Tasks/BTouchTaskBase.cs index 0cd8f4c33cf9..55b441f26a70 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Tasks/BTouchTaskBase.cs +++ b/msbuild/Xamarin.MacDev.Tasks/Tasks/BTouchTaskBase.cs @@ -79,7 +79,7 @@ public abstract class BTouchTaskBase : XamarinToolTask { protected override string ToolName { get { if (IsDotNet) - return Path.GetFileName (this.GetDotNetPath()); + return Path.GetFileName (this.GetDotNetPath ()); return Path.GetFileNameWithoutExtension (ToolExe); } @@ -93,7 +93,7 @@ protected override string GenerateFullPathToTool () // system dotnet, which might not exist or not have the version we // need. if (IsDotNet) - return this.GetDotNetPath(); + 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 663364307d38..74d8900d42a0 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Tasks/ComputeRemoteGeneratorPropertiesTaskBase.cs +++ b/msbuild/Xamarin.MacDev.Tasks/Tasks/ComputeRemoteGeneratorPropertiesTaskBase.cs @@ -94,7 +94,7 @@ void ComputeProperties () var environment = default (Dictionary); if (IsDotNet) { - executable = this.GetDotNetPath(); + executable = this.GetDotNetPath (); arguments.Add ("build"); diff --git a/msbuild/Xamarin.MacDev.Tasks/Tasks/XamarinBuildTask.cs b/msbuild/Xamarin.MacDev.Tasks/Tasks/XamarinBuildTask.cs index f80483523704..d5c341c77cf9 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Tasks/XamarinBuildTask.cs +++ b/msbuild/Xamarin.MacDev.Tasks/Tasks/XamarinBuildTask.cs @@ -36,7 +36,7 @@ protected string ComputeValueUsingTarget (string computeValueTarget, string targ "; File.WriteAllText (projectPath, csproj); - var dotnetPath = this.GetDotNetPath(); + var dotnetPath = this.GetDotNetPath (); var environment = default (Dictionary); var customHome = Environment.GetEnvironmentVariable ("DOTNET_CUSTOM_HOME");