From e8ec3751e9845f93bb4d85bbe74d2ce533b784a0 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 264ac4d1579..47009288bf6 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 9cf5682353b..9cdcca0e9f1 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 bfc97a58e84..0cd8f4c33cf 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..663364307d3 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..f8048352370 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 2ce362add18ffb5ef9fd06f5acdc28f7b0aec957 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 47009288bf6..c03ff7a948d 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 9cdcca0e9f1..0d985e5b135 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 0cd8f4c33cf..55b441f26a7 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 663364307d3..74d8900d42a 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 f8048352370..d5c341c77cf 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");