From fcc09483cbef48cbec2c99e5708f6d9d84fab7a5 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Mon, 20 Nov 2023 09:42:51 +0100 Subject: [PATCH 1/2] [msbuild] Several updates to the ScnTool task. * Enable nullability and fix the resulting issues. * Convert to XamarinTask (instead of XaxmarinToolTask): this allows us to run multiple 'scntool' invocations in parallel. * Use 'xcrun' to call 'scntool' instead of computing the path. --- .../Tasks/ScnToolTaskBase.cs | 145 +++++++----------- msbuild/Xamarin.Shared/Xamarin.Shared.targets | 62 +++++--- 2 files changed, 94 insertions(+), 113 deletions(-) diff --git a/msbuild/Xamarin.MacDev.Tasks/Tasks/ScnToolTaskBase.cs b/msbuild/Xamarin.MacDev.Tasks/Tasks/ScnToolTaskBase.cs index f9ae8e617cc2..7d49b81dfe51 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Tasks/ScnToolTaskBase.cs +++ b/msbuild/Xamarin.MacDev.Tasks/Tasks/ScnToolTaskBase.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Generic; using System.IO; +using System.Threading.Tasks; using Microsoft.Build.Utilities; using Microsoft.Build.Framework; @@ -7,123 +9,66 @@ using Xamarin.Messaging.Build.Client; using Xamarin.Utils; -// Disable until we get around to enable + fix any issues. -#nullable disable - namespace Xamarin.MacDev.Tasks { - public class ScnTool : XamarinToolTask { - string sdkDevPath; - + public class ScnTool : XamarinTask { #region Inputs [Required] - public string IntermediateOutputPath { get; set; } + public string IntermediateOutputPath { get; set; } = string.Empty; [Required] - public string InputScene { get; set; } + public ITaskItem [] ColladaAssets { get; set; } = Array.Empty (); + + [Required] + public string DeviceSpecificIntermediateOutputPath { get; set; } = string.Empty; public bool IsWatchApp { get; set; } [Required] - public string OutputScene { get; set; } + public string ProjectDir { get; set; } = string.Empty; [Required] - public string SdkPlatform { get; set; } + public string ResourcePrefix { get; set; } = string.Empty; [Required] - public string SdkRoot { get; set; } + public string SdkPlatform { get; set; } = string.Empty; [Required] - public string SdkVersion { get; set; } + public string SdkRoot { get; set; } = string.Empty; [Required] - public string SdkDevPath { - get { return sdkDevPath; } - set { - sdkDevPath = value; + public string SdkVersion { get; set; } = string.Empty; - SetEnvironmentVariable ("DEVELOPER_DIR", sdkDevPath); - } - } + [Required] + public string SdkDevPath { get; set; } = string.Empty; #endregion - string DevicePlatformBinDir { - get { return Path.Combine (SdkDevPath, "usr", "bin"); } - } - - protected virtual string OperatingSystem { - get { - return PlatformFrameworkHelper.GetOperatingSystem (TargetFrameworkMoniker); - } - } - - protected override string ToolName { - get { return "scntool"; } - } - - void SetEnvironmentVariable (string variableName, string value) - { - var envVariables = EnvironmentVariables; - var index = -1; - - if (envVariables is null) { - envVariables = new string [1]; - index = 0; - } else { - for (int i = 0; i < envVariables.Length; i++) { - if (envVariables [i].StartsWith (variableName + "=", StringComparison.Ordinal)) { - index = i; - break; - } - } - - if (index < 0) { - Array.Resize (ref envVariables, envVariables.Length + 1); - index = envVariables.Length - 1; - } - } - - envVariables [index] = string.Format ("{0}={1}", variableName, value); - - EnvironmentVariables = envVariables; - } - - protected override string GenerateFullPathToTool () - { - if (!string.IsNullOrEmpty (ToolPath)) - return Path.Combine (ToolPath, ToolExe); - - var path = Path.Combine (DevicePlatformBinDir, ToolExe); - - return File.Exists (path) ? path : ToolExe; - } + #region Outputs + [Output] + public ITaskItem [] BundleResources { get; set; } = Array.Empty (); + #endregion - protected override string GenerateCommandLineCommands () + IList GenerateCommandLineCommands (string inputScene, string outputScene) { - var args = new CommandLineArgumentBuilder (); + var args = new List (); + args.Add ("scntool"); args.Add ("--compress"); - args.AddQuoted (InputScene); + args.Add (inputScene); args.Add ("-o"); - args.AddQuoted (OutputScene); - args.AddQuotedFormat ("--sdk-root={0}", SdkRoot); - args.AddQuotedFormat ("--target-build-dir={0}", IntermediateOutputPath); + args.Add (outputScene); + args.Add ($"--sdk-root={SdkRoot}"); + args.Add ($"--target-build-dir={IntermediateOutputPath}"); if (AppleSdkSettings.XcodeVersion.Major >= 13) { // I'm not sure which Xcode version these options are available in, but it's at least Xcode 13+ - args.AddQuotedFormat ("--target-version={0}", SdkVersion); - args.AddQuotedFormat ("--target-platform={0}", PlatformUtils.GetTargetPlatform (SdkPlatform, IsWatchApp)); + args.Add ($"--target-version={SdkVersion}"); + args.Add ($"--target-platform={PlatformUtils.GetTargetPlatform (SdkPlatform, IsWatchApp)}"); } else { - args.AddQuotedFormat ("--target-version-{0}={1}", OperatingSystem, SdkVersion); + args.Add ($"--target-version-{PlatformFrameworkHelper.GetOperatingSystem (TargetFrameworkMoniker)}={SdkVersion}"); } - return args.ToString (); - } - - protected override void LogEventsFromTextOutput (string singleLine, MessageImportance messageImportance) - { - // TODO: do proper parsing of error messages and such - Log.LogMessage (messageImportance, "{0}", singleLine); + return args; } public override bool Execute () @@ -131,17 +76,37 @@ public override bool Execute () if (ShouldExecuteRemotely ()) return new TaskRunner (SessionId, BuildEngine4).RunAsync (this).Result; - Directory.CreateDirectory (Path.GetDirectoryName (OutputScene)); + var prefixes = BundleResource.SplitResourcePrefixes (ResourcePrefix); + var listOfArguments = new List<(IList Arguments, ITaskItem Input)> (); + var bundleResources = new List (); + foreach (var asset in ColladaAssets) { + var inputScene = asset.ItemSpec; + var outputScene = Path.Combine (DeviceSpecificIntermediateOutputPath, asset.GetMetadata ("LogicalName")); + var args = GenerateCommandLineCommands (inputScene, outputScene); + listOfArguments.Add (new (args, asset)); + + Directory.CreateDirectory (Path.GetDirectoryName (outputScene)); + + var bundleResource = new TaskItem (outputScene); + asset.CopyMetadataTo (bundleResource); + bundleResource.SetMetadata ("Optimize", "false"); + bundleResource.SetMetadata ("LogicalName", BundleResource.GetLogicalName (ProjectDir, prefixes, asset, !string.IsNullOrEmpty (SessionId))); + bundleResources.Add (bundleResource); + } + + Parallel.ForEach (listOfArguments, (arg) => { + ExecuteAsync ("xcrun", arg.Arguments, sdkDevPath: SdkDevPath).Wait (); + }); - return base.Execute (); + BundleResources = bundleResources.ToArray (); + + return !Log.HasLoggedErrors; } - public override void Cancel () + public void Cancel () { if (ShouldExecuteRemotely ()) BuildConnection.CancelAsync (BuildEngine4).Wait (); - - base.Execute (); } } } diff --git a/msbuild/Xamarin.Shared/Xamarin.Shared.targets b/msbuild/Xamarin.Shared/Xamarin.Shared.targets index 5dece87a4b85..a1d3b6c01e89 100644 --- a/msbuild/Xamarin.Shared/Xamarin.Shared.targets +++ b/msbuild/Xamarin.Shared/Xamarin.Shared.targets @@ -1021,9 +1021,11 @@ Copyright (C) 2018 Microsoft. All rights reserved. + $(CompileColladaAssetsDependsOn); _RemoveProcessedColladaAssets; - _CollectColladaAssets; - _CoreCompileColladaAssets + _BeforeCoreCompileColladaAssets; + _ReadCoreCompileColladaAssets; + _CoreCompileColladaAssets; @@ -1042,46 +1044,57 @@ Copyright (C) 2018 Microsoft. All rights reserved. - - - - + + + + + + + + + + + + + ColladaAssets="@(Collada)" + > + + + - - - - + - + + @@ -1137,6 +1150,9 @@ Copyright (C) 2018 Microsoft. All rights reserved. <_TextureAtlasCache>$(DeviceSpecificIntermediateOutputPath)atlas\_BundleResourceWithLogicalName.items + + <_ColladaCache>$(DeviceSpecificIntermediateOutputPath)collada\_BundleResourceWithLogicalName.items + <_ProcessedBundleResourcesPath Condition="'$(_ProcessedBundleResourcesPath)' == ''">$(DeviceSpecificIntermediateOutputPath)\_ProcessedBundleResourcesPath.items <_ProcessedContentPath Condition="'$(_ProcessedContentPath)' == ''">$(DeviceSpecificIntermediateOutputPath)\_ProcessedContentPath.items From 350bf1f44c2db1ff53711737b4fc65ca569ed53c Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Fri, 2 Feb 2024 19:10:20 +0100 Subject: [PATCH 2/2] Fix output path. --- msbuild/Xamarin.MacDev.Tasks/Tasks/ScnToolTaskBase.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/msbuild/Xamarin.MacDev.Tasks/Tasks/ScnToolTaskBase.cs b/msbuild/Xamarin.MacDev.Tasks/Tasks/ScnToolTaskBase.cs index 7d49b81dfe51..0220c6ec39e4 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Tasks/ScnToolTaskBase.cs +++ b/msbuild/Xamarin.MacDev.Tasks/Tasks/ScnToolTaskBase.cs @@ -81,7 +81,8 @@ public override bool Execute () var bundleResources = new List (); foreach (var asset in ColladaAssets) { var inputScene = asset.ItemSpec; - var outputScene = Path.Combine (DeviceSpecificIntermediateOutputPath, asset.GetMetadata ("LogicalName")); + var logicalName = BundleResource.GetLogicalName (ProjectDir, prefixes, asset, !string.IsNullOrEmpty (SessionId)); + var outputScene = Path.Combine (DeviceSpecificIntermediateOutputPath, logicalName); var args = GenerateCommandLineCommands (inputScene, outputScene); listOfArguments.Add (new (args, asset)); @@ -90,7 +91,7 @@ public override bool Execute () var bundleResource = new TaskItem (outputScene); asset.CopyMetadataTo (bundleResource); bundleResource.SetMetadata ("Optimize", "false"); - bundleResource.SetMetadata ("LogicalName", BundleResource.GetLogicalName (ProjectDir, prefixes, asset, !string.IsNullOrEmpty (SessionId))); + bundleResource.SetMetadata ("LogicalName", logicalName); bundleResources.Add (bundleResource); }