From 1c346d45c4912e16130a5e44ce92a0544447010a Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Fri, 12 Dec 2025 18:48:32 +0100 Subject: [PATCH 1/2] [msbuild] Pass the XamarinTask instance along when calling CompressionHelper.TryCompress. Pass the XamarinTask instance along when calling CompressionHelper.TryCompress, so that TryCompress can use the instance ExecuteAsync method on XamarinTask. This is required for a future change, where the instance XamarinTask.ExecuteAsync method will set the environment to use the current/correct version of Xcode. --- msbuild/Xamarin.MacDev.Tasks/Decompress.cs | 35 +++++++++++-------- .../Tasks/CreateBindingResourcePackage.cs | 2 +- .../Tasks/ResolveNativeReferences.cs | 23 ++++++------ msbuild/Xamarin.MacDev.Tasks/Tasks/Unzip.cs | 2 +- .../Xamarin.MacDev.Tasks/Tasks/XamarinTask.cs | 4 +-- msbuild/Xamarin.MacDev.Tasks/Tasks/Zip.cs | 2 +- 6 files changed, 38 insertions(+), 30 deletions(-) diff --git a/msbuild/Xamarin.MacDev.Tasks/Decompress.cs b/msbuild/Xamarin.MacDev.Tasks/Decompress.cs index fedb4d3f2027..cfedc62041f3 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Decompress.cs +++ b/msbuild/Xamarin.MacDev.Tasks/Decompress.cs @@ -100,8 +100,10 @@ static string CanonicalizeZipEntryPath (string path) /// The cancellation token (if any= /// The location on disk to the extracted resource /// True if successfully decompressed, false otherwise. - public static bool TryDecompress (TaskLoggingHelper log, string zip, string resource, string decompressionDir, List createdFiles, CancellationToken? cancellationToken, [NotNullWhen (true)] out string? decompressedResource) + public static bool TryDecompress (XamarinTask task, string zip, string resource, string decompressionDir, List createdFiles, CancellationToken? cancellationToken, [NotNullWhen (true)] out string? decompressedResource) { + var log = task.Log; + decompressedResource = Path.Combine (decompressionDir, resource); var stampFile = decompressedResource.TrimEnd ('\\', '/') + ".stamp"; @@ -118,11 +120,11 @@ public static bool TryDecompress (TaskLoggingHelper log, string zip, string reso bool rv; if (Environment.OSVersion.Platform == PlatformID.Win32NT) { - rv = TryDecompressUsingSystemIOCompression (log, zip, resource, decompressionDir, cancellationToken); + rv = TryDecompressUsingSystemIOCompression (task, zip, resource, decompressionDir, cancellationToken); } else if (!string.IsNullOrEmpty (Environment.GetEnvironmentVariable ("XAMARIN_USE_SYSTEM_IO_COMPRESSION"))) { - rv = TryDecompressUsingSystemIOCompression (log, zip, resource, decompressionDir, cancellationToken); + rv = TryDecompressUsingSystemIOCompression (task, zip, resource, decompressionDir, cancellationToken); } else { - rv = TryDecompressUsingUnzip (log, zip, resource, decompressionDir, cancellationToken); + rv = TryDecompressUsingUnzip (task, zip, resource, decompressionDir, cancellationToken); } if (rv) { @@ -145,8 +147,9 @@ public static bool TryDecompress (TaskLoggingHelper log, string zip, string reso // The dir separator character in zip files is always "/", even on Windows const char zipDirectorySeparator = '/'; - static bool TryDecompressUsingUnzip (TaskLoggingHelper log, string zip, string resource, string decompressionDir, CancellationToken? cancellationToken) + static bool TryDecompressUsingUnzip (XamarinTask task, string zip, string resource, string decompressionDir, CancellationToken? cancellationToken) { + var log = task.Log; Directory.CreateDirectory (decompressionDir); var args = new List { "-u", "-o", @@ -176,12 +179,13 @@ static bool TryDecompressUsingUnzip (TaskLoggingHelper log, string zip, string r args.Add (zipPattern); } - var rv = XamarinTask.ExecuteAsync (log, "unzip", args, cancellationToken: cancellationToken).Result; + var rv = task.ExecuteAsync ("unzip", args, cancellationToken: cancellationToken).Result; return rv.ExitCode == 0; } - static bool TryDecompressUsingSystemIOCompression (TaskLoggingHelper log, string zip, string resource, string decompressionDir, CancellationToken? cancellationToken) + static bool TryDecompressUsingSystemIOCompression (XamarinTask task, string zip, string resource, string decompressionDir, CancellationToken? cancellationToken) { + var log = task.Log; var rv = true; // canonicalize input @@ -270,8 +274,9 @@ static bool TryDecompressUsingSystemIOCompression (TaskLoggingHelper log, string /// testing the System.IO.Compression implementation locally (with the caveat that if the resources /// to compress has symlinks, it may not work). /// - public static bool TryCompress (TaskLoggingHelper log, string zip, IEnumerable resources, bool overwrite, string workingDirectory, bool maxCompression = false) + public static bool TryCompress (XamarinTask task, string zip, IEnumerable resources, bool overwrite, string workingDirectory, bool maxCompression = false) { + var log = task.Log; if (overwrite) { if (File.Exists (zip)) { log.LogMessage (MessageImportance.Low, "Replacing zip file {0} with {1}", zip, string.Join (", ", resources)); @@ -293,19 +298,20 @@ public static bool TryCompress (TaskLoggingHelper log, string zip, IEnumerable resources, string workingDirectory, bool maxCompression) + static bool TryCompressUsingZip (XamarinTask task, string zip, IEnumerable resources, string workingDirectory, bool maxCompression) { + var log = task.Log; var zipArguments = new List (); if (maxCompression) zipArguments.Add ("-9"); @@ -318,7 +324,7 @@ static bool TryCompressUsingZip (TaskLoggingHelper log, string zip, IEnumerable< var relativePath = PathUtils.AbsoluteToRelative (workingDirectory, fullPath); zipArguments.Add (relativePath); } - var rv = XamarinTask.ExecuteAsync (log, "zip", zipArguments, workingDirectory: workingDirectory).Result; + var rv = task.ExecuteAsync ("zip", zipArguments, workingDirectory: workingDirectory).Result; log.LogMessage (MessageImportance.Low, "Updated {0} with {1}: {2}", zip, string.Join (", ", resources), rv.ExitCode == 0); return rv.ExitCode == 0; } @@ -330,8 +336,9 @@ static bool TryCompressUsingZip (TaskLoggingHelper log, string zip, IEnumerable< #endif // Will always add to an existing zip file (not replace) - static bool TryCompressUsingSystemIOCompression (TaskLoggingHelper log, string zip, IEnumerable resources, string workingDirectory, bool maxCompression) + static bool TryCompressUsingSystemIOCompression (XamarinTask task, string zip, IEnumerable resources, string workingDirectory, bool maxCompression) { + var log = task.Log; var rv = true; workingDirectory = Path.GetFullPath (workingDirectory); diff --git a/msbuild/Xamarin.MacDev.Tasks/Tasks/CreateBindingResourcePackage.cs b/msbuild/Xamarin.MacDev.Tasks/Tasks/CreateBindingResourcePackage.cs index 236255778be5..048c09394d28 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Tasks/CreateBindingResourcePackage.cs +++ b/msbuild/Xamarin.MacDev.Tasks/Tasks/CreateBindingResourcePackage.cs @@ -100,7 +100,7 @@ public override bool Execute () var workingDirectory = Path.GetDirectoryName (nativeRef); if (string.IsNullOrEmpty (workingDirectory)) workingDirectory = Directory.GetCurrentDirectory (); - CompressionHelper.TryCompress (Log, zipFile, new string [] { nativeRef }, false, workingDirectory, true); + CompressionHelper.TryCompress (this, zipFile, new string [] { nativeRef }, false, workingDirectory, true); } packagedFiles.Add (zipFile); } else { diff --git a/msbuild/Xamarin.MacDev.Tasks/Tasks/ResolveNativeReferences.cs b/msbuild/Xamarin.MacDev.Tasks/Tasks/ResolveNativeReferences.cs index 3aab40aaecd7..a40e837b802b 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Tasks/ResolveNativeReferences.cs +++ b/msbuild/Xamarin.MacDev.Tasks/Tasks/ResolveNativeReferences.cs @@ -198,7 +198,7 @@ void ProcessNativeReference (ITaskItem item, string name, List native // (compressed) xcframework if (name.EndsWith (".xcframework", StringComparison.OrdinalIgnoreCase) || name.EndsWith (".xcframework.zip", StringComparison.OrdinalIgnoreCase)) { - if (!TryResolveXCFramework (Log, TargetFrameworkMoniker, SdkIsSimulator, Architectures, name, GetIntermediateDecompressionDir (item), createdFiles, cancellationToken, out var nativeLibraryPath)) + if (!TryResolveXCFramework (this, TargetFrameworkMoniker, SdkIsSimulator, Architectures, name, GetIntermediateDecompressionDir (item), createdFiles, cancellationToken, out var nativeLibraryPath)) return; var nr = new TaskItem (item); SetMetadataNativeLibrary (nr, nativeLibraryPath); @@ -208,7 +208,7 @@ void ProcessNativeReference (ITaskItem item, string name, List native // compressed framework if (name.EndsWith (".framework.zip", StringComparison.OrdinalIgnoreCase)) { - if (!CompressionHelper.TryDecompress (Log, name, Path.GetFileNameWithoutExtension (name), GetIntermediateDecompressionDir (item), createdFiles, cancellationToken, out var frameworkPath)) + if (!CompressionHelper.TryDecompress (this, name, Path.GetFileNameWithoutExtension (name), GetIntermediateDecompressionDir (item), createdFiles, cancellationToken, out var frameworkPath)) return; var nr = new TaskItem (item); nr.ItemSpec = GetActualLibrary (frameworkPath); @@ -311,14 +311,14 @@ void ProcessSidecar (ITaskItem r, string resources, List native_frame ITaskItem t = new TaskItem (r); var name = referenceNode.Attributes ["Name"].Value.Trim ('\\', '/'); if (name.EndsWith (".xcframework", StringComparison.Ordinal) || name.EndsWith (".xcframework.zip", StringComparison.Ordinal)) { - if (!TryResolveXCFramework (Log, TargetFrameworkMoniker, SdkIsSimulator, Architectures, resources, name, GetIntermediateDecompressionDir (resources), createdFiles, cancellationToken, out var nativeLibraryPath)) + if (!TryResolveXCFramework (this, TargetFrameworkMoniker, SdkIsSimulator, Architectures, resources, name, GetIntermediateDecompressionDir (resources), createdFiles, cancellationToken, out var nativeLibraryPath)) continue; SetMetadataNativeLibrary (t, nativeLibraryPath); } else if (name.EndsWith (".framework", StringComparison.Ordinal)) { string? frameworkPath; if (!isCompressed) { frameworkPath = Path.Combine (resources, name); - } else if (!CompressionHelper.TryDecompress (Log, resources, name, GetIntermediateDecompressionDir (resources), createdFiles, cancellationToken, out frameworkPath)) { + } else if (!CompressionHelper.TryDecompress (this, resources, name, GetIntermediateDecompressionDir (resources), createdFiles, cancellationToken, out frameworkPath)) { continue; } t.ItemSpec = GetActualLibrary (frameworkPath); @@ -330,7 +330,7 @@ void ProcessSidecar (ITaskItem r, string resources, List native_frame string? dylibPath; if (!isCompressed) { dylibPath = Path.Combine (resources, name); - } else if (!CompressionHelper.TryDecompress (Log, resources, name, GetIntermediateDecompressionDir (resources), createdFiles, cancellationToken, out dylibPath)) { + } else if (!CompressionHelper.TryDecompress (this, resources, name, GetIntermediateDecompressionDir (resources), createdFiles, cancellationToken, out dylibPath)) { continue; } t.ItemSpec = dylibPath; @@ -341,7 +341,7 @@ void ProcessSidecar (ITaskItem r, string resources, List native_frame string? aPath; if (!isCompressed) { aPath = Path.Combine (resources, name); - } else if (!CompressionHelper.TryDecompress (Log, resources, name, GetIntermediateDecompressionDir (resources), createdFiles, cancellationToken, out aPath)) { + } else if (!CompressionHelper.TryDecompress (this, resources, name, GetIntermediateDecompressionDir (resources), createdFiles, cancellationToken, out aPath)) { continue; } t.ItemSpec = aPath; @@ -378,7 +378,7 @@ void ProcessSidecar (ITaskItem r, string resources, List native_frame /// A full path to the resolved native library within the xcframework. If 'resourcePath' is compressed, this will point to where the native library is decompressed on disk. /// /// True if a native library was successfully found. Otherwise false, and an error will have been printed to the log. - public static bool TryResolveXCFramework (TaskLoggingHelper log, string targetFrameworkMoniker, bool isSimulator, string? architectures, string path, string intermediateDecompressionDir, List createdFiles, CancellationToken? cancellationToken, [NotNullWhen (true)] out string? nativeLibraryPath) + public static bool TryResolveXCFramework (XamarinTask task, string targetFrameworkMoniker, bool isSimulator, string? architectures, string path, string intermediateDecompressionDir, List createdFiles, CancellationToken? cancellationToken, [NotNullWhen (true)] out string? nativeLibraryPath) { string resourcePath; string xcframework; @@ -390,7 +390,7 @@ public static bool TryResolveXCFramework (TaskLoggingHelper log, string targetFr resourcePath = Path.GetDirectoryName (path); xcframework = Path.GetFileName (path); } - return TryResolveXCFramework (log, targetFrameworkMoniker, isSimulator, architectures, resourcePath, xcframework, intermediateDecompressionDir, createdFiles, cancellationToken, out nativeLibraryPath); + return TryResolveXCFramework (task, targetFrameworkMoniker, isSimulator, architectures, resourcePath, xcframework, intermediateDecompressionDir, createdFiles, cancellationToken, out nativeLibraryPath); } /// @@ -405,8 +405,9 @@ public static bool TryResolveXCFramework (TaskLoggingHelper log, string targetFr /// A full path to the resolved native library within the xcframework. If 'resourcePath' is compressed, this will point to where the native library is decompressed on disk. /// /// True if a native library was successfully found. Otherwise false, and an error will have been printed to the log. - public static bool TryResolveXCFramework (TaskLoggingHelper log, string targetFrameworkMoniker, bool isSimulator, string? architectures, string resourcePath, string xcframework, string intermediateDecompressionDir, List createdFiles, CancellationToken? cancellationToken, [NotNullWhen (true)] out string? nativeLibraryPath) + public static bool TryResolveXCFramework (XamarinTask task, string targetFrameworkMoniker, bool isSimulator, string? architectures, string resourcePath, string xcframework, string intermediateDecompressionDir, List createdFiles, CancellationToken? cancellationToken, [NotNullWhen (true)] out string? nativeLibraryPath) { + var log = task.Log; nativeLibraryPath = null; try { @@ -421,7 +422,7 @@ public static bool TryResolveXCFramework (TaskLoggingHelper log, string targetFr if (!isCompressed && CompressionHelper.IsCompressed (xcframework)) { var zipPath = Path.Combine (resourcePath, xcframework); var xcframeworkName = Path.GetFileNameWithoutExtension (xcframework); - if (!CompressionHelper.TryDecompress (log, zipPath, xcframeworkName, intermediateDecompressionDir, createdFiles, cancellationToken, out var decompressedXcframeworkPath)) + if (!CompressionHelper.TryDecompress (task, zipPath, xcframeworkName, intermediateDecompressionDir, createdFiles, cancellationToken, out var decompressedXcframeworkPath)) return false; nativeLibraryPath = Path.Combine (intermediateDecompressionDir, xcframeworkName, nativeLibraryRelativePath); @@ -434,7 +435,7 @@ public static bool TryResolveXCFramework (TaskLoggingHelper log, string targetFr } var zipResource = Path.Combine (xcframework, Path.GetDirectoryName (nativeLibraryRelativePath)); - if (!CompressionHelper.TryDecompress (log, resourcePath, zipResource, intermediateDecompressionDir, createdFiles, cancellationToken, out var decompressedPath)) + if (!CompressionHelper.TryDecompress (task, resourcePath, zipResource, intermediateDecompressionDir, createdFiles, cancellationToken, out var decompressedPath)) return false; nativeLibraryPath = Path.Combine (intermediateDecompressionDir, xcframework, nativeLibraryRelativePath); diff --git a/msbuild/Xamarin.MacDev.Tasks/Tasks/Unzip.cs b/msbuild/Xamarin.MacDev.Tasks/Tasks/Unzip.cs index 5b24af469603..5a4c4afaf1d5 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Tasks/Unzip.cs +++ b/msbuild/Xamarin.MacDev.Tasks/Tasks/Unzip.cs @@ -79,7 +79,7 @@ bool ExecuteLocally () { var createdFiles = new List (); cancellationTokenSource = new CancellationTokenSource (); - if (!CompressionHelper.TryDecompress (Log, ZipFilePath!.ItemSpec, Resource, ExtractionPath, createdFiles, cancellationTokenSource.Token, out var _)) + if (!CompressionHelper.TryDecompress (this, ZipFilePath!.ItemSpec, Resource, ExtractionPath, createdFiles, cancellationTokenSource.Token, out var _)) return false; TouchedFiles = createdFiles.Select (v => new TaskItem (v)).ToArray (); diff --git a/msbuild/Xamarin.MacDev.Tasks/Tasks/XamarinTask.cs b/msbuild/Xamarin.MacDev.Tasks/Tasks/XamarinTask.cs index 1a7ef1623ae1..b00c7fe335ab 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Tasks/XamarinTask.cs +++ b/msbuild/Xamarin.MacDev.Tasks/Tasks/XamarinTask.cs @@ -97,9 +97,9 @@ protected string GetSdkPlatform (bool isSimulator) return PlatformFrameworkHelper.GetSdkPlatform (Platform, isSimulator); } - protected System.Threading.Tasks.Task ExecuteAsync (string fileName, IList arguments, string? sdkDevPath = null, Dictionary? environment = null, bool mergeOutput = true, bool showErrorIfFailure = true, string? workingDirectory = null) + internal protected System.Threading.Tasks.Task ExecuteAsync (string fileName, IList arguments, string? sdkDevPath = null, Dictionary? environment = null, bool mergeOutput = true, bool showErrorIfFailure = true, string? workingDirectory = null, CancellationToken? cancellationToken = null) { - return ExecuteAsync (Log, fileName, arguments, sdkDevPath, environment, mergeOutput, showErrorIfFailure, workingDirectory); + return ExecuteAsync (Log, fileName, arguments, sdkDevPath, environment, mergeOutput, showErrorIfFailure, workingDirectory, cancellationToken); } static int executionCounter; diff --git a/msbuild/Xamarin.MacDev.Tasks/Tasks/Zip.cs b/msbuild/Xamarin.MacDev.Tasks/Tasks/Zip.cs index 42300770269d..42c4b199a034 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Tasks/Zip.cs +++ b/msbuild/Xamarin.MacDev.Tasks/Tasks/Zip.cs @@ -54,7 +54,7 @@ public override bool Execute () for (int i = 0; i < Sources.Length; i++) sources.Add (Sources [i].GetMetadata ("FullPath")); - if (!CompressionHelper.TryCompress (Log, zip, sources, false, workingDirectory, false)) + if (!CompressionHelper.TryCompress (this, zip, sources, false, workingDirectory, false)) return false; return !Log.HasLoggedErrors; From 0b536607e842b2df2304ad0ca50816e8679932c4 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Mon, 15 Dec 2025 09:32:05 +0100 Subject: [PATCH 2/2] Update msbuild/Xamarin.MacDev.Tasks/Decompress.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- msbuild/Xamarin.MacDev.Tasks/Decompress.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msbuild/Xamarin.MacDev.Tasks/Decompress.cs b/msbuild/Xamarin.MacDev.Tasks/Decompress.cs index cfedc62041f3..019dc2d7b8ba 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Decompress.cs +++ b/msbuild/Xamarin.MacDev.Tasks/Decompress.cs @@ -97,7 +97,7 @@ static string CanonicalizeZipEntryPath (string path) /// The zip to search in /// The relative path inside the zip to extract (may be a file or a directory). /// The location on disk to store the extracted results - /// The cancellation token (if any= + /// The cancellation token (if any) /// The location on disk to the extracted resource /// True if successfully decompressed, false otherwise. public static bool TryDecompress (XamarinTask task, string zip, string resource, string decompressionDir, List createdFiles, CancellationToken? cancellationToken, [NotNullWhen (true)] out string? decompressedResource)