From 309d553425bd91aef3eb10655e2eb7ee292c1f0e Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Fri, 23 Jan 2026 00:34:24 +0100 Subject: [PATCH] [msbuild] Add support for ACToolPath, IBToolPath and TextureAtlasPath. Add support for ACToolPath, IBToolPath and TextureAtlasPath to specify the location of the corresponding executables. And if not specified, then locate these executables using `xcrun`. Also make these process invocations cancellable. --- docs/building-apps/build-properties.md | 18 +++++++ msbuild/Xamarin.MacDev.Tasks/Tasks/ACTool.cs | 12 +---- msbuild/Xamarin.MacDev.Tasks/Tasks/IBTool.cs | 12 +---- .../Tasks/TextureAtlas.cs | 14 +---- .../Tasks/XcodeCompilerToolTask.cs | 54 +++++++++---------- .../Xamarin.MacDev.Tasks/Tasks/XcodeTool.cs | 54 ++++++------------- msbuild/Xamarin.Shared/Xamarin.Shared.targets | 3 -- 7 files changed, 64 insertions(+), 103 deletions(-) diff --git a/docs/building-apps/build-properties.md b/docs/building-apps/build-properties.md index 6ead612bd047..95bc5a672c49 100644 --- a/docs/building-apps/build-properties.md +++ b/docs/building-apps/build-properties.md @@ -17,6 +17,12 @@ The full path to the `altool` tool. The default behavior is to use `xcrun altool`. +## ACToolPath + +The full path to the `actool` tool. + +The default behavior is to use `xcrun actool`. + ## AppBundleResourcePrefix The directory where resources are stored (this prefix will be removed when copying resources to the app bundle). @@ -517,6 +523,12 @@ Default: true Where the generated source from the generator are saved. +## IBToolPath + +The full path to the `ibtool` tool. + +The default behavior is to use `xcrun ibtool`. + ## IncludeAllAppIcons Set the `IncludeAllAppIcons` property to true to automatically include all app @@ -1261,6 +1273,12 @@ It's also possible to use a platform-specific property: * [macOSMinimumVersion](#macosminimumversion) * [MacCatalystMinimumVersion](#maccatalystminimumversion) +## TextureAtlasPath + +The full path to the `TextureAtlas` tool. + +The default behavior is to use `xcrun TextureAtlas`. + ## TrimMode Specifies the trimming granularity. diff --git a/msbuild/Xamarin.MacDev.Tasks/Tasks/ACTool.cs b/msbuild/Xamarin.MacDev.Tasks/Tasks/ACTool.cs index eb09d5ad18dd..38d87d918f9f 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Tasks/ACTool.cs +++ b/msbuild/Xamarin.MacDev.Tasks/Tasks/ACTool.cs @@ -12,7 +12,7 @@ using Xamarin.Utils; namespace Xamarin.MacDev.Tasks { - public class ACTool : XcodeCompilerToolTask, ICancelableTask { + public class ACTool : XcodeCompilerToolTask { string? outputSpecs; string? partialAppManifestPath; @@ -58,10 +58,6 @@ public class ACTool : XcodeCompilerToolTask, ICancelableTask { HashSet brandAssetsInAssets = new (); // tvOS HashSet imageStacksInAssets = new (); // tvOS - protected override string DefaultBinDir { - get { return DeveloperRootBinDir; } - } - protected override string ToolName { get { return "actool"; } } @@ -544,12 +540,6 @@ public override bool Execute () return !Log.HasLoggedErrors; } - - public void Cancel () - { - if (ShouldExecuteRemotely ()) - BuildConnection.CancelAsync (BuildEngine4).Wait (); - } } class AssetInfo { diff --git a/msbuild/Xamarin.MacDev.Tasks/Tasks/IBTool.cs b/msbuild/Xamarin.MacDev.Tasks/Tasks/IBTool.cs index f71e3ab3a680..d8e349b2cdcf 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Tasks/IBTool.cs +++ b/msbuild/Xamarin.MacDev.Tasks/Tasks/IBTool.cs @@ -11,7 +11,7 @@ using Xamarin.Utils; namespace Xamarin.MacDev.Tasks { - public class IBTool : XcodeCompilerToolTask, ICancelableTask { + public class IBTool : XcodeCompilerToolTask { static readonly string [] WatchAppExtensions = { "-glance.plist", "-notification.plist" }; #region Inputs @@ -30,10 +30,6 @@ public class IBTool : XcodeCompilerToolTask, ICancelableTask { #endregion - protected override string DefaultBinDir { - get { return DeveloperRootBinDir; } - } - protected override string ToolName { get { return "ibtool"; } } @@ -459,11 +455,5 @@ public override bool Execute () return !Log.HasLoggedErrors; } - - public void Cancel () - { - if (ShouldExecuteRemotely ()) - BuildConnection.CancelAsync (BuildEngine4).Wait (); - } } } diff --git a/msbuild/Xamarin.MacDev.Tasks/Tasks/TextureAtlas.cs b/msbuild/Xamarin.MacDev.Tasks/Tasks/TextureAtlas.cs index b2240c760e42..81d5bc9b9885 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Tasks/TextureAtlas.cs +++ b/msbuild/Xamarin.MacDev.Tasks/Tasks/TextureAtlas.cs @@ -11,7 +11,7 @@ #nullable enable namespace Xamarin.MacDev.Tasks { - public class TextureAtlas : XcodeToolTaskBase, ICancelableTask { + public class TextureAtlas : XcodeToolTaskBase { readonly Dictionary Items)> atlases = new (); #region Inputs @@ -20,15 +20,11 @@ public class TextureAtlas : XcodeToolTaskBase, ICancelableTask { #endregion - protected override string DefaultBinDir { - get { return DeveloperRootBinDir; } - } - protected override string ToolName { get { return "TextureAtlas"; } } - protected override void AppendCommandLineArguments (IDictionary environment, List args, ITaskItem input, ITaskItem output) + protected override void AppendCommandLineArguments (List args, ITaskItem input, ITaskItem output) { args.Add (input.GetMetadata ("FullPath")); args.Add (Path.GetDirectoryName (output.GetMetadata ("FullPath"))!); @@ -117,11 +113,5 @@ public override bool Execute () return base.Execute (); } - - public void Cancel () - { - if (ShouldExecuteRemotely ()) - BuildConnection.CancelAsync (BuildEngine4).Wait (); - } } } diff --git a/msbuild/Xamarin.MacDev.Tasks/Tasks/XcodeCompilerToolTask.cs b/msbuild/Xamarin.MacDev.Tasks/Tasks/XcodeCompilerToolTask.cs index 870289df97f0..e86af43215b6 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Tasks/XcodeCompilerToolTask.cs +++ b/msbuild/Xamarin.MacDev.Tasks/Tasks/XcodeCompilerToolTask.cs @@ -13,14 +13,16 @@ using Xamarin.Localization.MSBuild; using Xamarin.MacDev; +using Xamarin.Messaging.Build.Client; using Xamarin.Utils; #nullable enable namespace Xamarin.MacDev.Tasks { - public abstract class XcodeCompilerToolTask : XamarinTask, IHasProjectDir, IHasResourcePrefix { + public abstract class XcodeCompilerToolTask : XamarinTask, IHasProjectDir, IHasResourcePrefix, ICancelableTask { + CancellationTokenSource cancellationTokenSource = new (); + protected bool Link { get; set; } - string? toolExe; #region Inputs @@ -44,11 +46,6 @@ public abstract class XcodeCompilerToolTask : XamarinTask, IHasProjectDir, IHasR [Required] public string SdkVersion { get; set; } = string.Empty; - public string ToolExe { - get { return toolExe ?? ToolName; } - set { toolExe = value; } - } - public string ToolPath { get; set; } = string.Empty; #endregion @@ -87,14 +84,6 @@ public IPhoneDeviceType ParsedUIDeviceFamily { } } - protected abstract string DefaultBinDir { - get; - } - - protected string DeveloperRootBinDir { - get { return Path.Combine (GetSdkDevPath (), "usr", "bin"); } - } - protected abstract string ToolName { get; } protected virtual bool UseCompilationDirectory { @@ -170,18 +159,6 @@ protected int Compile (ITaskItem [] items, string output, ITaskItem manifest) var environment = new Dictionary (); var args = new List (); - // workaround for ibtool[d] bug / asserts if Intel version is loaded - string tool; - if (IsTranslated ()) { - // we force the Intel (translated) msbuild process to launch ibtool as "Apple" - tool = "arch"; - args.Add ("-arch"); - args.Add ("arm64e"); - args.Add ("/usr/bin/xcrun"); - } else { - tool = "/usr/bin/xcrun"; - } - args.Add (ToolName); args.Add ("--errors"); args.Add ("--warnings"); args.Add ("--notices"); @@ -202,11 +179,21 @@ protected int Compile (ITaskItem [] items, string output, ITaskItem manifest) foreach (var item in items) args.Add (item.GetMetadata ("FullPath")); - // don't bother executing the tool if we've already looged errors. + var executable = GetExecutable (args, ToolName, ToolPath); + // workaround for ibtool[d] bug / asserts if Intel version is loaded + if (IsTranslated ()) { + // we force the Intel (translated) msbuild process to launch ibtool as "Apple" + args.Insert (0, "-arch"); + args.Insert (1, "arm64e"); + args.Insert (2, executable); + executable = "arch"; + } + + // don't bother executing the tool if we've already logged errors. if (Log.HasLoggedErrors) return 1; - var rv = ExecuteAsync (tool, args, environment: environment).Result; + var rv = ExecuteAsync (executable, args, environment: environment, cancellationToken: cancellationTokenSource.Token).Result; var exitCode = rv.ExitCode; var messages = rv.Output.StandardOutput; File.WriteAllText (manifest.ItemSpec, messages); @@ -310,5 +297,14 @@ protected void LogWarningsAndErrors (PDictionary plist, ITaskItem file) } } } + + public void Cancel () + { + if (ShouldExecuteRemotely ()) { + BuildConnection.CancelAsync (BuildEngine4).Wait (); + } else { + cancellationTokenSource?.Cancel (); + } + } } } diff --git a/msbuild/Xamarin.MacDev.Tasks/Tasks/XcodeTool.cs b/msbuild/Xamarin.MacDev.Tasks/Tasks/XcodeTool.cs index cadc14ee1419..24fc65d689a9 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Tasks/XcodeTool.cs +++ b/msbuild/Xamarin.MacDev.Tasks/Tasks/XcodeTool.cs @@ -3,18 +3,20 @@ using System.Diagnostics; using System.ComponentModel; using System.Collections.Generic; +using System.Threading; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; using Xamarin.Localization.MSBuild; using Xamarin.MacDev; +using Xamarin.Messaging.Build.Client; #nullable enable namespace Xamarin.MacDev.Tasks { - public abstract class XcodeToolTaskBase : XamarinTask, IHasProjectDir, IHasResourcePrefix { - string? toolExe; + public abstract class XcodeToolTaskBase : XamarinTask, IHasProjectDir, IHasResourcePrefix, ICancelableTask { + CancellationTokenSource cancellationTokenSource = new (); #region Inputs @@ -27,11 +29,6 @@ public abstract class XcodeToolTaskBase : XamarinTask, IHasProjectDir, IHasResou [Required] public string ResourcePrefix { get; set; } = string.Empty; - public string ToolExe { - get { return toolExe ?? ToolName; } - set { toolExe = value; } - } - public string ToolPath { get; set; } = string.Empty; #endregion @@ -43,27 +40,11 @@ public string ToolExe { #endregion - protected abstract string DefaultBinDir { - get; - } - - protected string DeveloperRootBinDir { - get { return Path.Combine (GetSdkDevPath (), "usr", "bin"); } - } - - protected string DevicePlatformBinDir { - get { return Path.Combine (GetSdkDevPath (), "Platforms", "iPhoneOS.platform", "Developer", "usr", "bin"); } - } - - protected string SimulatorPlatformBinDir { - get { return Path.Combine (GetSdkDevPath (), "Platforms", "iPhoneSimulator.platform", "Developer", "usr", "bin"); } - } - protected abstract string ToolName { get; } protected abstract IEnumerable EnumerateInputs (); - protected abstract void AppendCommandLineArguments (IDictionary environment, List args, ITaskItem input, ITaskItem output); + protected abstract void AppendCommandLineArguments (List args, ITaskItem input, ITaskItem output); protected virtual string GetBundleRelativeOutputPath (ITaskItem input) { @@ -83,24 +64,14 @@ protected virtual bool NeedsBuilding (ITaskItem input, ITaskItem output) return !File.Exists (dest) || File.GetLastWriteTimeUtc (src) > File.GetLastWriteTimeUtc (dest); } - string GetFullPathToTool () - { - if (!string.IsNullOrEmpty (ToolPath)) - return Path.Combine (ToolPath, ToolExe); - - var path = Path.Combine (DefaultBinDir, ToolExe); - - return File.Exists (path) ? path : ToolExe; - } - int ExecuteTool (ITaskItem input, ITaskItem output) { - var environment = new Dictionary (); var args = new List (); - AppendCommandLineArguments (environment, args, input, output); + AppendCommandLineArguments (args, input, output); - var rv = ExecuteAsync (GetFullPathToTool (), args, environment: environment).Result; + var executable = GetExecutable (args, ToolName, ToolPath); + var rv = ExecuteAsync (executable, args, cancellationToken: cancellationTokenSource.Token).Result; return rv.ExitCode; } @@ -142,5 +113,14 @@ public override bool Execute () return !Log.HasLoggedErrors; } + + public void Cancel () + { + if (ShouldExecuteRemotely ()) { + BuildConnection.CancelAsync (BuildEngine4).Wait (); + } else { + cancellationTokenSource?.Cancel (); + } + } } } diff --git a/msbuild/Xamarin.Shared/Xamarin.Shared.targets b/msbuild/Xamarin.Shared/Xamarin.Shared.targets index 66a7012475cf..64301f9460bc 100644 --- a/msbuild/Xamarin.Shared/Xamarin.Shared.targets +++ b/msbuild/Xamarin.Shared/Xamarin.Shared.targets @@ -893,7 +893,6 @@ Copyright (C) 2018 Microsoft. All rights reserved.