From 1b1807479a6a7bebd38d4111a033d159722db562 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Fri, 11 Mar 2022 11:56:57 +0100 Subject: [PATCH 1/8] [msbuild] Move ITaskItemExtensions to Xamarin.MacDev.Task.Core. So that it's available for code in Xamarin.MacDev.Tasks.Core. --- .../Extensions/ITaskItemExtensions.cs | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename msbuild/{Xamarin.MacDev.Tasks => Xamarin.MacDev.Tasks.Core}/Extensions/ITaskItemExtensions.cs (100%) diff --git a/msbuild/Xamarin.MacDev.Tasks/Extensions/ITaskItemExtensions.cs b/msbuild/Xamarin.MacDev.Tasks.Core/Extensions/ITaskItemExtensions.cs similarity index 100% rename from msbuild/Xamarin.MacDev.Tasks/Extensions/ITaskItemExtensions.cs rename to msbuild/Xamarin.MacDev.Tasks.Core/Extensions/ITaskItemExtensions.cs From 5934522ba8fd10f441ad997af909b8d621b42f22 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Fri, 11 Mar 2022 11:53:13 +0100 Subject: [PATCH 2/8] [msbuild] Begone old code signing logic. I'm removing the old logic first, because the new logic is so different that a diff just complicates understanding what's happening (there's not much value in comparing textually what's changed when it's pretty much a complete rewrite). --- msbuild/Xamarin.Shared/Xamarin.Shared.targets | 297 ------------------ 1 file changed, 297 deletions(-) diff --git a/msbuild/Xamarin.Shared/Xamarin.Shared.targets b/msbuild/Xamarin.Shared/Xamarin.Shared.targets index b5836493e6..a1f5ab1f89 100644 --- a/msbuild/Xamarin.Shared/Xamarin.Shared.targets +++ b/msbuild/Xamarin.Shared/Xamarin.Shared.targets @@ -1789,80 +1789,6 @@ Copyright (C) 2018 Microsoft. All rights reserved. - - <_CodesignNativeLibrariesDependsOn> - $(_CodesignNativeLibrariesDependsOn); - _DetectSigningIdentity; - _CompileToNative; - _PlaceAppExtensions; - - - - - - - - <_CodesignDisableTimestamp>False - <_CodesignDisableTimestamp Condition="'$(_SdkIsSimulator)' == 'true' Or '$(_BundlerDebug)' == 'true'">True - <_LibraryCodeSigningKey>$(_CodeSigningKey) - <_LibraryCodeSigningKey Condition="'$(_LibraryCodeSigningKey)' == ''">- - - - - <_CodesignNativeLibrary Include="$(_AppContentsPath)\**\*.dylib" /> - <_CodesignNativeLibrary Include="$(_AppResourcesPath)\**\*.metallib" /> - - - <_CodesignNativeLibrary - Include="$(_AppBundlePath)\**\*.dylib;$(_AppBundlePath)\**\*.metallib" - Exclude="$(_AppBundlePath)\Watch\**;$(_AppExtensionRoot)\PlugIns\**" - /> - - - - <_CodesignItems Include="@(_CodesignNativeLibrary)"> - $(_CodesignAllocate) - $(IsAppExtension) - $(_CodesignDisableTimestamp) - - $(CodesignExtraArgs) - $(CodesignKeychain) - - $(_LibraryCodeSigningKey) - $(DeviceSpecificIntermediateOutputPath)codesign\ - - $(UseHardenedRuntime) - - - - - - - - - - - - <_CollectFrameworksDependsOn> $(_CollectFrameworksDependsOn); @@ -1889,229 +1815,6 @@ Copyright (C) 2018 Microsoft. All rights reserved. - - - - <_CodesignDisableTimestamp>False - <_CodesignDisableTimestamp Condition="'$(_SdkIsSimulator)' == 'true' Or '$(_BundlerDebug)' == 'true'">True - <_FrameworkCodeSigningKey>$(_CodeSigningKey) - <_FrameworkCodeSigningKey Condition="'$(_FrameworkCodeSigningKey)' == ''">- - - - - <_CodesignItems Include="@(_Frameworks)"> - $(_CodesignAllocate) - - $(_CodesignDisableTimestamp) - - $(CodesignExtraArgs) - $(CodesignKeychain) - - $(_FrameworkCodeSigningKey) - - $(UseHardenedRuntime) - - - - - - - - - - - - - - <_CodesignAppExtensionsLibraryPath>$(_AppPlugInsPath)%(_AppExtensionCodesignProperties.Identity)\ - - - - <_CodesignAppExtensionsLibrary - Include="$(_CodesignAppExtensionsLibraryPath)**\*.dylib;$(_CodesignAppExtensionsLibraryPath)**\*.metallib" - Exclude="$(_CodesignAppExtensionsLibraryPath)Watch\**;$(_CodesignAppExtensionsLibraryPath)$(_AppPlugInsRelativePath)\**" - > - - - - - <_CodesignItems Include="@(_CodesignAppExtensionsLibrary)" Condition="'%(_AppExtensionCodesignProperties.LibrarySigningKey)' != ''"> - %(_AppExtensionCodesignProperties.CodesignAllocate) - - %(_AppExtensionCodesignProperties.DisableTimestamp) - - %(_AppExtensionCodesignProperties.ExtraArgs) - %(_AppExtensionCodesignProperties.Keychain) - - %(_AppExtensionCodesignProperties.LibrarySigningKey) - $(DeviceSpecificIntermediateOutputPath)codesign\PlugIns\%(_AppExtensionCodesignProperties.Identity) - - - - - - - <_CodesignItems Include="$(_AppPlugInsPath)%(_AppExtensionCodesignProperties.Identity)" Condition="'%(_AppExtensionCodesignProperties.SigningKey)' != ''"> - %(_AppExtensionCodesignProperties.CodesignAllocate) - - %(_AppExtensionCodesignProperties.DisableTimestamp) - %(_AppExtensionCodesignProperties.Entitlements) - %(_AppExtensionCodesignProperties.ExtraArgs) - %(_AppExtensionCodesignProperties.Keychain) - %(_AppExtensionCodesignProperties.ResourceRules) - %(_AppExtensionCodesignProperties.SigningKey) - - - - - - - - - - - <_CompiledEntitlementsFullPath> - <_ResourceRulesFullPath> - - - - - - - - - - - - - - - - - - - - - <_AppBundleFileName>$([System.IO.Path]::GetFileName('$(AppBundleDir)')) - <_NativeExecutableFileName>$([System.IO.Path]::GetFileName('$(_NativeExecutable)')) - - <_CodesignDisableTimestamp>False - <_CodesignDisableTimestamp Condition="'$(_SdkIsSimulator)' == 'true' Or '$(_BundlerDebug)' == 'true'">True - - <_CodesignAppExtensionInputs>@(_AppExtensionBundleFiles);$(_EntitlementsFullPath) - - <_LibrarySigningKey>$(_CodeSigningKey) - <_LibrarySigningKey Condition="'$(_LibrarySigningKey)' == ''">- - - - - <_AppExtensionCodesignPropertiesToWrite Include="$(_AppBundleFileName)"> - $(_CodesignAppExtensionInputs) - $(_NativeExecutableFileName) - $(_CodesignAllocate) - $(_CodesignDisableTimestamp) - $(_CompiledEntitlementsFullPath) - $(_ResourceRulesFullPath) - $(CodesignKeychain) - $(_LibrarySigningKey) - $(_CodeSigningKey) - $(CodesignExtraArgs) - - - - - - - - - <_CodesignAppBundleInputs Include="$(_AppBundlePath)**\*.*" Exclude="$(_AppCodeSignaturePath)_CodeSignature\CodeResources" /> - - - - <_CodesignDisableTimestamp>False - <_CodesignDisableTimestamp Condition="'$(_SdkIsSimulator)' == 'true' Or '$(_BundlerDebug)' == 'true'">True - - <_AppBundleCodesignEntitlements Condition="'$(_PlatformName)' == 'macOS'">$(IntermediateOutputPath)Entitlements.xcent - <_AppBundleCodesignEntitlements Condition="'$(_PlatformName)' != 'macOS'">$(_CompiledCodesignEntitlements) - - <_CodesignAppBundleCondition Condition="'$(_PlatformName)' == 'macOS' And '$(_RequireCodeSigning)'">true - <_CodesignAppBundleCondition Condition="'$(_PlatformName)' != 'macOS' And ('$(_CanOutputAppBundle)' == 'true' And '$(_CodeSigningKey)' != '') And ('$(IsAppExtension)' == 'false' Or '@(_ResolvedAppExtensionReferences)' != '')">true - - - - <_CodesignItems Include="$(AppBundleDir)"> - $(_CodesignAllocate) - $(AppBundleDir).dSYM\Contents\Info.plist - $(IsAppExtension) - $(_CodesignDisableTimestamp) - $(_AppBundleCodesignEntitlements) - $(CodesignExtraArgs) - $(CodesignKeychain) - $(_PreparedResourceRules) - $(_CodeSigningKey) - $(_AppCodeSignaturePath)_CodeSignature\CodeResources - - $(UseHardenedRuntime) - $(UseHardenedRuntime) - - - - - - - <_CodesignItems> - $([System.String]::new('%(Identity)').Substring($([MSBuild]::Add($([System.String]::new('%(Identity)').LastIndexOf('.app/')),5)))) - - - <_CodesignItems Condition="'%(_CodesignItems.CodesignStampPath)' == ''"> - $(DeviceSpecificIntermediateOutputPath)codesign\ - true - - - - - - <_CodesignItems Condition="'%(_CodesignItems.CodesignStampFile)' == ''"> - %(_CodesignItems.CodesignStampPath)\%(_CodesignItems.CodesignRelativeAppBundlePath) - %(_CodesignItems.CodesignStampPath)\%(_CodesignItems.CodesignRelativeAppBundlePath)\.directory-stamp - - - - - - - - - - - - <_ComputeLinkModeDependsOn> From 3d055426771d53cd9817c7d3c7482fa9c74f8402 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Fri, 11 Feb 2022 13:55:22 +0100 Subject: [PATCH 3/8] [msbuild] Rework code signing. The main theme here is that code signing will be done in the outermost executable project, not in any app extension projects or watch projects, nor during the RID-specific build of a .NET universal app. This makes codesigning easier to reason about and other affected logic (such as strip/dsymutil) easier to handle, in particular for .NET universal apps. Another benefit is that the differences between the iOS and macOS code bases have been eliminated. The first step is to collect all the information we need from the targets files. Every app bundle (be it app extension, watch app or main app) will add its own output app bundle (.app/.appex) to the _CodesignBundle item group. Then every app bundle will load this informarion from referenced app bundles, and finally store this information on disk (in the 'codesign-bundle.items' file). This means that in the end the main app bundle will have a list of all contained app bundles in the app (recursively), in the _CodesignBundle item group. Separately we keep a list of other items that need signing, in the _CodesignItems item group, and we do the same store/load logic for every contained/contained app bundle (in the 'codesign.items' file, so a the end the main app bundle will have a list of all the _CodesignItems for all contained app bundles (recursively). The previous steps occur in the _CollectCodesigningData and _StoreCodesigningData targets. The next step is to use the new ComputeCodesignItems task to compute everything we need to know for code signing. This task takes over the responsibility for listing all the *.dylib and *.metallib files, and the *.framework directories in the app bundles, that need signing (which was previously done in the targets file). This logic is significantly easier to write, debug and test in C# than MSBuild. In addition the ComputeCodesignItems also figures out a stamp file path we use to determine if something needs (re-)signing. Previously .framework directories did not have a stamp location, so they'd always end up resigned in a rebuild, while now we'll automatically skip signing *.framework directories unless something changed in them. I've also tried to comment everything thorougly, for the next poor soul having to deal with any bugs, as well has adding a comprehensive test for the new task. Behavioral differences: * We were always signing *.dylib files for macOS. We're now doing the same thing for all platforms. * We're now always signing *.framework directories for all platforms (like we do for *.dylib files), since frameworks are pretty much like dylibs anyways. --- .../Extensions/ITaskItemExtensions.cs | 7 + .../Tasks/ComputeCodesignItemsTaskBase.cs | 205 ++++++++ .../Tasks/ComputeCodesignItems.cs | 20 + msbuild/Xamarin.Shared/Xamarin.Shared.targets | 284 ++++++++++- .../Xamarin.iOS.Common.targets | 6 + .../ComputeCodesignItemsTaskTests.cs | 475 ++++++++++++++++++ tools/common/PathUtils.cs | 14 + 7 files changed, 1001 insertions(+), 10 deletions(-) create mode 100644 msbuild/Xamarin.MacDev.Tasks.Core/Tasks/ComputeCodesignItemsTaskBase.cs create mode 100644 msbuild/Xamarin.MacDev.Tasks/Tasks/ComputeCodesignItems.cs create mode 100644 tests/msbuild/Xamarin.MacDev.Tasks.Tests/TaskTests/ComputeCodesignItemsTaskTests.cs diff --git a/msbuild/Xamarin.MacDev.Tasks.Core/Extensions/ITaskItemExtensions.cs b/msbuild/Xamarin.MacDev.Tasks.Core/Extensions/ITaskItemExtensions.cs index 5f298aeda4..aece426504 100644 --- a/msbuild/Xamarin.MacDev.Tasks.Core/Extensions/ITaskItemExtensions.cs +++ b/msbuild/Xamarin.MacDev.Tasks.Core/Extensions/ITaskItemExtensions.cs @@ -8,5 +8,12 @@ namespace Microsoft.Build.Framework { item.GetMetadata ("ResolvedFrom") == "{TargetFrameworkDirectory}" || item.GetMetadata ("ResolvedFrom") == "ImplicitlyExpandDesignTimeFacades"; } + + public static void SetMetadataIfNotSet (this ITaskItem self, string metadata, string value) + { + if (!string.IsNullOrEmpty (self.GetMetadata (metadata))) + return; + self.SetMetadata (metadata, value); + } } } diff --git a/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/ComputeCodesignItemsTaskBase.cs b/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/ComputeCodesignItemsTaskBase.cs new file mode 100644 index 0000000000..c09d342a39 --- /dev/null +++ b/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/ComputeCodesignItemsTaskBase.cs @@ -0,0 +1,205 @@ +using System; +using System.IO; +using System.Collections.Generic; + +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +using Xamarin.Localization.MSBuild; +using Xamarin.Utils; + +#nullable enable + +namespace Xamarin.MacDev.Tasks { + // + // This task is responsible for computing everything we need to know for code + // signing. + // + // For each app bundle to be signed, a few more items to be code signed: + // + // * All *.dylib and *.metallib files + // * All *.framework directories + // + // In both cases we iterate over what we find in the app bundle instead of + // relying on what the msbuild tasks built and copied in the app bundle, + // because customer logic might have added additional frameworks, and those + // need to be signed too. + // + // This task will also figure out a stamp file path we use to determine if + // something needs (re-)signing. + // + public abstract class ComputeCodesignItemsTaskBase : XamarinTask { + + [Required] + public string AppBundleDir { get; set; } = string.Empty; + + [Required] + public ITaskItem [] CodesignBundle { get; set; } = Array.Empty (); + + [Required] + public ITaskItem [] CodesignItems { get; set; } = Array.Empty (); + + [Required] + public string CodesignStampPath { get; set; } = string.Empty; + + [Output] + public ITaskItem[] OutputCodesignItems { get; set; } = Array.Empty (); + + public override bool Execute () + { + var output = new List (); + + // Make sure AppBundleDir has a trailing slash + var appBundlePath = PathUtils.EnsureTrailingSlash (Path.GetFullPath (AppBundleDir)); + + // Add the app bundles themselves + foreach (var bundle in CodesignBundle) { + // An app bundle is signed if either 'RequireCodeSigning' is true + // or a 'CodesignSigningKey' has been provided. + var requireCodeSigning = bundle.GetMetadata ("RequireCodeSigning"); + var codesignSigningKey = bundle.GetMetadata ("CodesignSigningKey"); + if (!string.Equals (requireCodeSigning, "true") && string.IsNullOrEmpty (codesignSigningKey)) + continue; + + // Create a new item for the app bundle, and copy any metadata over. + var bundlePath = Path.Combine (Path.GetDirectoryName (AppBundleDir), bundle.ItemSpec); + var item = new TaskItem (bundlePath); + bundle.CopyMetadataTo (item); + + // Compute the stamp file to use + item.SetMetadataIfNotSet ("CodesignStampFile", Path.Combine (bundlePath, CodeSignatureRelativePath, "_CodeSignature", "CodeResources")); + + // Get any additional stamp files we must touch when the item is signed. + var additionalStampFiles = new List (); + // We must touch the dSYM directory's Info.plist, to ensure that we don't end up running dsymutil again after codesigning in the next build + var dSYMUtilStampFile = Path.Combine (Path.GetDirectoryName (AppBundleDir), Path.GetFileName (item.ItemSpec) + ".dSYM", "Contents", "Info.plist"); + additionalStampFiles.Add (dSYMUtilStampFile); + // Set the CodesignAdditionalFilesToTouch metadata (merge with any existing values) + if (additionalStampFiles.Count > 0) { + additionalStampFiles.AddRange (item.GetMetadata ("CodesignAdditionalFilesToTouch").Split (',')); + additionalStampFiles.RemoveAll (v => string.IsNullOrEmpty (v)); + item.SetMetadata ("CodesignAdditionalFilesToTouch", string.Join (";", additionalStampFiles)); + } + + output.Add (item); + } + + // Find all: + // - *.dylib and *.metallib files + // - *.framework directories + foreach (var bundle in CodesignBundle) { + var bundlePath = Path.Combine (Path.GetDirectoryName (Path.GetDirectoryName (appBundlePath)), bundle.ItemSpec); + var filesToSign = FindFilesToSign (bundlePath); + foreach (var lib in filesToSign) { + var relativeLib = Path.Combine (AppBundleDir, lib.Substring (appBundlePath.Length)); + var item = new TaskItem (relativeLib); + bundle.CopyMetadataTo (item); + + // These items must not use the entitlements for the app + item.RemoveMetadata ("CodesignEntitlements"); + + // These files are a bit special, because they're always signed. This is done + // by setting the signing key to '-' if it's not set. + item.SetMetadataIfNotSet ("CodesignSigningKey", "-"); + + // Set the stamp file even if already set (because any existing values would be copied from + // the bundle, which would be the wrong stamp file, so it must be overridden) + if (Directory.Exists (relativeLib)) { + item.SetMetadata ("CodesignStampFile", Path.Combine (CodesignStampPath, relativeLib, ".stampfile")); + } else { + item.SetMetadata ("CodesignStampFile", Path.Combine (CodesignStampPath, relativeLib)); + } + + output.Add (item); + } + } + + // Add all additional items + foreach (var item in CodesignItems) { + // Set the stamp file if not already set. + item.SetMetadataIfNotSet ("CodesignStampFile", Path.Combine (CodesignStampPath, item.ItemSpec)); + + output.Add (item); + } + + OutputCodesignItems = output.ToArray (); + + return !Log.HasLoggedErrors; + } + + string CodeSignatureRelativePath { + get { + switch (Platform) { + case ApplePlatform.iOS: + case ApplePlatform.TVOS: + case ApplePlatform.WatchOS: + return string.Empty; + case ApplePlatform.MacOSX: + case ApplePlatform.MacCatalyst: + return "Contents"; + default: + throw new InvalidOperationException (string.Format (MSBStrings.InvalidPlatform, Platform)); + } + } + } + + IEnumerable FindFilesToSign (string appPath) + { + var rv = new List (); + + // Canonicalize the app path, so string comparisons work later on + appPath = PathUtils.ResolveSymbolicLinks (Path.GetFullPath (appPath)); + + // Make sure path ends with trailing slash to ease logic + appPath = PathUtils.EnsureTrailingSlash (appPath); + + string dylibDirectory; + string metallibDirectory; + string frameworksDirectory; + switch (Platform) { + case ApplePlatform.iOS: + case ApplePlatform.TVOS: + case ApplePlatform.WatchOS: + dylibDirectory = appPath; + metallibDirectory = appPath; + frameworksDirectory = Path.Combine (appPath, "Frameworks"); + break; + case ApplePlatform.MacOSX: + case ApplePlatform.MacCatalyst: + dylibDirectory = Path.Combine (appPath, "Contents"); + metallibDirectory = Path.Combine (appPath, "Contents", "Resources"); + frameworksDirectory = Path.Combine (appPath, "Contents", "Frameworks"); + break; + default: + throw new InvalidOperationException (string.Format (MSBStrings.InvalidPlatform, Platform)); + } + + dylibDirectory = PathUtils.EnsureTrailingSlash (dylibDirectory); + metallibDirectory = PathUtils.EnsureTrailingSlash (metallibDirectory); + + foreach (var entry in Directory.EnumerateFileSystemEntries (appPath, "*", SearchOption.AllDirectories)) { + var relativePath = entry.Substring (appPath.Length); + // Don't recurse into the PlugIns directory, that's already handled for any app bundle inside the PlugIns directory + if (relativePath.StartsWith ("PlugIns" + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase)) + continue; + // Don't recurse into the Watch directory, for the same reason + if (relativePath.StartsWith ("Watch" + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase)) + continue; + + if (entry.EndsWith (".dylib", StringComparison.OrdinalIgnoreCase) && entry.StartsWith (dylibDirectory, StringComparison.OrdinalIgnoreCase)) { + // We find *.dylibs in any subdirectory + rv.Add (entry); + } else if (entry.EndsWith (".metallib", StringComparison.OrdinalIgnoreCase) && entry.StartsWith (metallibDirectory, StringComparison.OrdinalIgnoreCase)) { + // We find *.metallib in any subdirectory + rv.Add (entry); + } else if (entry.EndsWith (".framework", StringComparison.OrdinalIgnoreCase) && string.Equals (Path.GetDirectoryName (entry), frameworksDirectory, StringComparison.OrdinalIgnoreCase)) { + // We only find *.frameworks inside the Frameworks subdirectory, not recursively + // (not quite sure if this is the right thing to do, but it's what we've been doing so far). + rv.Add (entry); + } + } + + return rv; + } + } +} diff --git a/msbuild/Xamarin.MacDev.Tasks/Tasks/ComputeCodesignItems.cs b/msbuild/Xamarin.MacDev.Tasks/Tasks/ComputeCodesignItems.cs new file mode 100644 index 0000000000..f64211f4ce --- /dev/null +++ b/msbuild/Xamarin.MacDev.Tasks/Tasks/ComputeCodesignItems.cs @@ -0,0 +1,20 @@ +using Microsoft.Build.Framework; +using Xamarin.Messaging.Build.Client; + +namespace Xamarin.MacDev.Tasks { + public class ComputeCodesignItems : ComputeCodesignItemsTaskBase, ICancelableTask { + public override bool Execute () + { + if (ShouldExecuteRemotely ()) + return new TaskRunner (SessionId, BuildEngine4).RunAsync (this).Result; + + return base.Execute (); + } + + public void Cancel () + { + if (ShouldExecuteRemotely ()) + BuildConnection.CancelAsync (SessionId, BuildEngine4).Wait (); + } + } +} diff --git a/msbuild/Xamarin.Shared/Xamarin.Shared.targets b/msbuild/Xamarin.Shared/Xamarin.Shared.targets index a1f5ab1f89..4cfddd6a9b 100644 --- a/msbuild/Xamarin.Shared/Xamarin.Shared.targets +++ b/msbuild/Xamarin.Shared/Xamarin.Shared.targets @@ -87,6 +87,7 @@ Copyright (C) 2018 Microsoft. All rights reserved. + @@ -374,7 +375,8 @@ Copyright (C) 2018 Microsoft. All rights reserved. <_IpaPackageFile Include="$(DeviceSpecificOutputPath)*.ipa" /> - + + @@ -1754,17 +1756,21 @@ Copyright (C) 2018 Microsoft. All rights reserved. + <_CollectCodesigningDataDependsOn> + $(_CollectCodesigningData); + _PlaceAppExtensions; + + <_CollectCodesigningDataDependsOn Condition="'$(_PlatformName)' != 'macOS'"> + $(_CollectCodesigningData); + _ResolveWatchAppReferences; + + <_CodesignAppBundleDependsOn> $(_CodesignAppBundleDependsOn); _CleanAppBundleRootDirectory; _EmbedProvisionProfile; - _CodesignNativeLibraries; - _CollectFrameworks; - _CodesignFrameworks; - _ReadAppExtensionCodesignProperties; - _CodesignAppExtensions; - _PrepareCodesignAppExtension; - _CalculateCodesignAppBundleInputs; + _CollectCodesigningData; + _StoreCodesigningData; @@ -1789,6 +1795,263 @@ Copyright (C) 2018 Microsoft. All rights reserved. + + + + + + + + + + + + + + + + + <_CodesignBundle Include="@(_CodesignAppExtensionBundle->'$(_AppBundleName)$(AppBundleExtension)/$(_AppPlugInsRelativePath)/%(Identity)')" /> + + + + + + + <_CodesignItems Include="@(_CodesignAppExtensionItem->'$(_AppBundleName)$(AppBundleExtension)/$(_AppPlugInsRelativePath)/%(Identity)')" /> + + + + + + + + <_CodesignBundle Include="@(_CodesignWatchBundle->'$(_AppBundleName)$(AppBundleExtension)/Watch/%(Identity)')" /> + + + + + + + <_CodesignItems Include="@(_CodesignWatchItem->'$(_AppBundleName)$(AppBundleExtension)/Watch/%(Identity)')" /> + + + + + <_CodesignBundle Include="$(_AppBundleName)$(AppBundleExtension)"> + $(_CodesignAllocate) + false + true + $(_CompiledCodesignEntitlements) + $(CodesignExtraArgs) + $(CodesignKeychain) + $(_PreparedResourceRules) + $(_CodeSigningKey) + $(UseHardenedRuntime) + $(UseHardenedRuntime) + $(_RequireCodeSigning) + $(MSBuildProjectDirectory) + + + + <_CodesignItems> + $(MSBuildProjectDirectory) + + + + + + <_CodesignAppBundleCondition Condition="'$(_CodesignAppBundleCondition)' == '' And '$(IsAppExtension)' != 'true' And '$(IsWatchApp)' != 'true' And '$(_CanOutputAppBundle)' == 'true'">true + <_CodesignAppBundleCondition Condition="'$(_CodesignAppBundleCondition)' == ''">false + + + + + + + + + + + + + + + + + + + + + + + + + <_ComputeLinkModeDependsOn> + $(_ComputeLinkModeDependsOn); + _DetectSdkLocations; + + + + + <_LinkMode Condition="'$(_LinkMode)' == '' And '$(_PlatformName)' == 'macOS'">$(LinkMode) + <_LinkMode Condition="'$(_LinkMode)' == '' And '$(_PlatformName)' != 'macOS'">$(MtouchLink) + <_LinkMode Condition="'$(_LinkMode)' == ''">$(_DefaultLinkMode) + <_LinkMode Condition="'$(_LinkMode)' == '' And '$(_PlatformName)' == 'macOS'">None + <_LinkMode Condition="'$(_LinkMode)' == '' And '$(_PlatformName)' != 'macOS'">SdkOnly + + + <_CollectFrameworksDependsOn> $(_CollectFrameworksDependsOn); @@ -2266,8 +2529,9 @@ Copyright (C) 2018 Microsoft. All rights reserved. - $(DeviceSpecificOutputPath)$(_AppBundleName)$(AppBundleExtension) - $(ArchivePath)\Products\Applications\$(_AppBundleName)$(AppBundleExtension) + <_AppContainerDir Condition="'$(IsAppDistribution)' != 'true'">$(DeviceSpecificOutputPath) + <_AppContainerDir Condition="'$(IsAppDistribution)' == 'true'">$(ArchivePath)\Products\Applications\ + $(_AppContainerDir)$(_AppBundleName)$(AppBundleExtension) <_AppBundlePath>$(AppBundleDir)\ diff --git a/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.targets b/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.targets index d98519476d..00fe21c7ed 100644 --- a/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.targets +++ b/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.targets @@ -523,6 +523,12 @@ Copyright (C) 2013-2016 Xamarin. All rights reserved. + + (); + var codesignBundle = new List (); + + string codeSignatureSubdirectory = string.Empty; + switch (platform) { + case ApplePlatform.MacCatalyst: + case ApplePlatform.MacOSX: + codeSignatureSubdirectory = "Contents/"; + break; + } + + var bundleAppMetadata = new Dictionary { + { "CodesignDisableTimestamp", "true" }, + { "CodesignEntitlements" , "CompiledEntitlements.plist" }, + { "CodesignExtraArgs", "bundle-app-extra-args" }, + { "CodesignKeychain", "bundle-app-keychain" }, + { "CodesignResourceRules", "bundle-app-resource-rules" }, + { "CodesignSigningKey", "bundle-app-signing-key" }, + { "CodesignStampFile", "bundle-app-stamp-file" }, + { "CodesignUseHardenedRuntime", "bundle-app-use-hardened-runtime" }, + { "CodesignUseSecureTimestamp", "bundle-app-use-secure-timestamp" }, + { "RequireCodeSigning", "true" }, + }; + var bundleAppMetadataNativeLibraries = new Dictionary (bundleAppMetadata); + bundleAppMetadataNativeLibraries.Remove ("CodesignEntitlements"); + + var p1Metadata = new Dictionary { + { "CodesignDisableTimestamp", "true" }, + { "CodesignEntitlements" , "p1.appex-entitlements" }, + { "CodesignExtraArgs", "p1.appex-extra-args" }, + { "CodesignKeychain", "p1.appex-keychain" }, + { "CodesignResourceRules", "p1.appex-resource-rules" }, + { "CodesignSigningKey", "" }, // empty code signing key + { "CodesignStampFile", "" }, // empty stamp file + { "CodesignUseHardenedRuntime", "p1.appex-use-hardened-runtime" }, + { "CodesignUseSecureTimestamp", "p1.appex-use-secure-timestamp" }, + { "RequireCodeSigning", "false" }, // don't require code signing + }; + var p1MetadataNativeLibraries = new Dictionary (p1Metadata); + p1MetadataNativeLibraries ["CodesignSigningKey"] = "-"; + p1MetadataNativeLibraries ["CodesignStampFile"] = "_CodeSignature/CodeResources"; + p1MetadataNativeLibraries.Remove ("CodesignEntitlements"); + + var p2Metadata = new Dictionary { + { "CodesignDisableTimestamp", "true" }, + { "CodesignEntitlements" , "p2.appex-entitlements" }, + { "RequireCodeSigning", "true" }, + { "CodesignExtraArgs", "p2.appex-extra-args" }, + { "CodesignKeychain", "p2.appex-keychain" }, + { "CodesignResourceRules", "p2.appex-resource-rules" }, + { "CodesignSigningKey", "p2.appex-signing-key" }, + { "CodesignStampFile", "" }, // empty stamp file + { "CodesignUseHardenedRuntime", "p2.appex-use-hardened-runtime" }, + { "CodesignUseSecureTimestamp", "p2.appex-use-secure-timestamp" }, + }; + var p2MetadataNativeLibraries = new Dictionary (p2Metadata); + p2MetadataNativeLibraries ["CodesignStampFile"] = "_CodeSignature/CodeResources"; + p2MetadataNativeLibraries.Remove ("CodesignEntitlements"); + + var p3Metadata = new Dictionary { + { "CodesignDisableTimestamp", "true" }, + { "CodesignEntitlements" , "p3.appex-entitlements" }, + { "RequireCodeSigning", "true" }, + { "CodesignExtraArgs", "p3.appex-extra-args" }, + { "CodesignKeychain", "p3.appex-keychain" }, + { "CodesignResourceRules", "p3.appex-resource-rules" }, + { "CodesignSigningKey", "p3.appex-signing-key" }, + { "CodesignStampFile", "" }, // empty stamp file + { "CodesignUseHardenedRuntime", "p3.appex-use-hardened-runtime" }, + { "CodesignUseSecureTimestamp", "p3.appex-use-secure-timestamp" }, + }; + var p3MetadataNativeLibraries = new Dictionary (p3Metadata); + p3MetadataNativeLibraries ["CodesignStampFile"] = "_CodeSignature/CodeResources"; + p3MetadataNativeLibraries.Remove ("CodesignEntitlements"); + + var w1Metadata = new Dictionary { + { "CodesignDisableTimestamp", "true" }, + { "CodesignEntitlements" , "CompiledEntitlements.plist" }, + { "RequireCodeSigning", "true" }, + { "CodesignExtraArgs", "bundle-app-extra-args" }, + { "CodesignKeychain", "bundle-app-keychain" }, + { "CodesignResourceRules", "bundle-app-resource-rules" }, + { "CodesignSigningKey", "bundle-app-signing-key" }, + { "CodesignStampFile", "" }, // empty stamp file + { "CodesignUseHardenedRuntime", "bundle-app-use-hardened-runtime" }, + { "CodesignUseSecureTimestamp", "bundle-app-use-secure-timestamp" }, + }; + var w1MetadataNativeLibraries = new Dictionary (w1Metadata); + w1MetadataNativeLibraries.Remove ("CodesignEntitlements"); + + var wp1Metadata = new Dictionary { + { "CodesignDisableTimestamp", "true" }, + { "CodesignEntitlements" , "wp1.appex-entitlements" }, + { "RequireCodeSigning", "true" }, + { "CodesignExtraArgs", "wp1.appex-extra-args" }, + { "CodesignKeychain", "wp1.appex-keychain" }, + { "CodesignResourceRules", "wp1.appex-resource-rules" }, + { "CodesignSigningKey", "" }, // empty code signing key + { "CodesignStampFile", "" }, // empty stamp file + { "CodesignUseHardenedRuntime", "wp1.appex-use-hardened-runtime" }, + { "CodesignUseSecureTimestamp", "wp1.appex-use-secure-timestamp" }, + }; + var wp1MetadataNativeLibraries = new Dictionary (wp1Metadata); + wp1MetadataNativeLibraries ["CodesignSigningKey"] = "-"; + wp1MetadataNativeLibraries ["CodesignStampFile"] = "_CodeSignature/CodeResources"; + wp1MetadataNativeLibraries.Remove ("CodesignEntitlements"); + + var wp2Metadata = new Dictionary { + { "CodesignDisableTimestamp", "true" }, + { "CodesignEntitlements" , "wp2.appex-entitlements" }, + { "RequireCodeSigning", "true" }, + { "CodesignExtraArgs", "wp2.appex-extra-args" }, + { "CodesignKeychain", "wp2.appex-keychain" }, + { "CodesignResourceRules", "wp2.appex-resource-rules" }, + { "CodesignSigningKey", "wp2.appex-signing-key" }, + { "CodesignStampFile", "" }, // empty stamp file + { "CodesignUseHardenedRuntime", "wp2.appex-use-hardened-runtime" }, + { "CodesignUseSecureTimestamp", "wp2.appex-use-secure-timestamp" }, + }; + var wp2MetadataNativeLibraries = new Dictionary (wp2Metadata); + wp2MetadataNativeLibraries ["CodesignStampFile"] = "_CodeSignature/CodeResources"; + wp2MetadataNativeLibraries.Remove ("CodesignEntitlements"); + + var wp3Metadata = new Dictionary { + { "CodesignDisableTimestamp", "true" }, + { "CodesignEntitlements" , "wp3.appex-entitlements" }, + { "RequireCodeSigning", "true" }, + { "CodesignExtraArgs", "wp3.appex-extra-args" }, + { "CodesignKeychain", "wp3.appex-keychain" }, + { "CodesignResourceRules", "wp3.appex-resource-rules" }, + { "CodesignSigningKey", "wp3.appex-signing-key" }, + { "CodesignStampFile", "" }, // empty stamp file + { "CodesignUseHardenedRuntime", "wp3.appex-use-hardened-runtime" }, + { "CodesignUseSecureTimestamp", "wp3.appex-use-secure-timestamp" }, + }; + var wp3MetadataNativeLibraries = new Dictionary (wp3Metadata); + wp3MetadataNativeLibraries ["CodesignStampFile"] = "_CodeSignature/CodeResources"; + wp3MetadataNativeLibraries.Remove ("CodesignEntitlements"); + + var createDumpMetadata = new Dictionary { + { "CodesignDisableTimestamp", "true" }, + { "CodesignEntitlements" , "createdump-entitlements" }, + { "RequireCodeSigning", "true" }, + { "CodesignExtraArgs", "createdump-extra-args" }, + { "CodesignKeychain", "createdump-keychain" }, + { "CodesignResourceRules", "createdump-resource-rules" }, + { "CodesignSigningKey", "createdump-signing-key" }, + { "CodesignStampFile", "createdump-stamp-file" }, + { "CodesignUseHardenedRuntime", "createdump-use-hardened-runtime" }, + { "CodesignUseSecureTimestamp", "createdump-use-secure-timestamp" }, + }; + + codesignItems = new List { + new TaskItem ("Bundle.app/Contents/MonoBundle/createdump", createDumpMetadata), + }; + + codesignBundle = new List { + new TaskItem ("Bundle.app", bundleAppMetadata), + new TaskItem ("Bundle.app/PlugIns/P1.appex", p1Metadata), + new TaskItem ("Bundle.app/PlugIns/P1.appex/PlugIns/P2.appex", p2Metadata), + new TaskItem ("Bundle.app/PlugIns/P1.appex/PlugIns/P2.appex/PlugIns/P3.appex", p3Metadata), + new TaskItem ("Bundle.app/Watch/W1.app", w1Metadata), + new TaskItem ("Bundle.app/Watch/W1.app/PlugIns/WP1.appex", wp1Metadata), + new TaskItem ("Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex", wp2Metadata), + new TaskItem ("Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/PlugIns/WP3.appex", wp3Metadata), + }; + + var infos = new CodesignInfo [] { + new CodesignInfo ("Bundle.app", Platforms.All, bundleAppMetadata.Set ("CodesignAdditionalFilesToTouch", "Bundle.app.dSYM/Contents/Info.plist")), + new CodesignInfo ("Bundle.app/a.dylib", Platforms.Mobile, bundleAppMetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/a.dylib")), + new CodesignInfo ("Bundle.app/Contents/b.dylib", Platforms.All, bundleAppMetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Contents/b.dylib")), + new CodesignInfo ("Bundle.app/Contents/MonoBundle/c.dylib", Platforms.All, bundleAppMetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Contents/MonoBundle/c.dylib")), + new CodesignInfo ("Bundle.app/Contents/MonoBundle/SubDir/d.dylib", Platforms.All, bundleAppMetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Contents/MonoBundle/SubDir/d.dylib")), + new CodesignInfo ("Bundle.app/M1.metallib", Platforms.Mobile, bundleAppMetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/M1.metallib")), + new CodesignInfo ("Bundle.app/Resources/M2.metallib", Platforms.Mobile, bundleAppMetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Resources/M2.metallib")), + new CodesignInfo ("Bundle.app/Contents/Resources/M3.metallib", Platforms.All, bundleAppMetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Contents/Resources/M3.metallib")), + new CodesignInfo ("Bundle.app/Contents/Resources/SubDir/M4.metallib", Platforms.All, bundleAppMetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Contents/Resources/SubDir/M4.metallib")), + new CodesignInfo ( + "Bundle.app/PlugIns/P1.appex", + Platforms.None, + p1Metadata. + Set ("CodesignStampFile", $"Bundle.app/PlugIns/P1.appex/PlugIns/P2.appex/{codeSignatureSubdirectory}_CodeSignature/CodeResources") + ), + new CodesignInfo ("Bundle.app/PlugIns/P1.appex/P1a.dylib", Platforms.Mobile, p1MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/PlugIns/P1.appex/P1a.dylib")), + new CodesignInfo ("Bundle.app/PlugIns/P1.appex/Contents/P1b.dylib", Platforms.All, p1MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/PlugIns/P1.appex/Contents/P1b.dylib")), + new CodesignInfo ("Bundle.app/PlugIns/P1.appex/Contents/MonoBundle/P1c.dylib", Platforms.All, p1MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/PlugIns/P1.appex/Contents/MonoBundle/P1c.dylib")), + new CodesignInfo ("Bundle.app/PlugIns/P1.appex/Contents/MonoBundle/SubDir/P1d.dylib", Platforms.All, p1MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/PlugIns/P1.appex/Contents/MonoBundle/SubDir/P1d.dylib")), + new CodesignInfo ("Bundle.app/PlugIns/P1.appex/PM1.metallib", Platforms.Mobile, p1MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/PlugIns/P1.appex/PM1.metallib")), + new CodesignInfo ("Bundle.app/PlugIns/P1.appex/Resources/PM2.metallib", Platforms.Mobile, p1MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/PlugIns/P1.appex/Resources/PM2.metallib")), + new CodesignInfo ("Bundle.app/PlugIns/P1.appex/Contents/Resources/PM3.metallib", Platforms.All, p1MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/PlugIns/P1.appex/Contents/Resources/PM3.metallib")), + new CodesignInfo ("Bundle.app/PlugIns/P1.appex/Contents/Resources/SubDir/PM4.metallib", Platforms.All, p1MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/PlugIns/P1.appex/Contents/Resources/SubDir/PM4.metallib")), + new CodesignInfo ( + "Bundle.app/PlugIns/P1.appex/plugins/P2.appex", + Platforms.All, + p2Metadata. + Set ("CodesignStampFile", $"Bundle.app/PlugIns/P1.appex/PlugIns/P2.appex/{codeSignatureSubdirectory}_CodeSignature/CodeResources"). + Set ("CodesignAdditionalFilesToTouch", "P2.appex.dSYM/Contents/Info.plist") + ), + new CodesignInfo ("Bundle.app/PlugIns/P1.appex/plugins/P2.appex/P2a.dylib", Platforms.Mobile, p2MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/PlugIns/P1.appex/plugins/P2.appex/P2a.dylib")), + new CodesignInfo ("Bundle.app/PlugIns/P1.appex/plugins/P2.appex/Contents/P2b.dylib", Platforms.All, p2MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/PlugIns/P1.appex/plugins/P2.appex/Contents/P2b.dylib")), + new CodesignInfo ("Bundle.app/PlugIns/P1.appex/plugins/P2.appex/Contents/MonoBundle/P2c.dylib", Platforms.All, p2MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/PlugIns/P1.appex/plugins/P2.appex/Contents/MonoBundle/P2c.dylib")), + new CodesignInfo ("Bundle.app/PlugIns/P1.appex/plugins/P2.appex/Contents/MonoBundle/SubDir/P2d.dylib", Platforms.All, p2MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/PlugIns/P1.appex/plugins/P2.appex/Contents/MonoBundle/SubDir/P2d.dylib")), + new CodesignInfo ("Bundle.app/PlugIns/P1.appex/plugins/P2.appex/P2M1.metallib", Platforms.Mobile, p2MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/PlugIns/P1.appex/plugins/P2.appex/P2M1.metallib")), + new CodesignInfo ("Bundle.app/PlugIns/P1.appex/plugins/P2.appex/Resources/P2M2.metallib", Platforms.Mobile, p2MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/PlugIns/P1.appex/plugins/P2.appex/Resources/P2M2.metallib")), + new CodesignInfo ("Bundle.app/PlugIns/P1.appex/plugins/P2.appex/Contents/Resources/P2M3.metallib", Platforms.All, p2MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/PlugIns/P1.appex/plugins/P2.appex/Contents/Resources/P2M3.metallib")), + new CodesignInfo ("Bundle.app/PlugIns/P1.appex/plugins/P2.appex/Contents/Resources/SubDir/P2M4.metallib", Platforms.All, p2MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/PlugIns/P1.appex/plugins/P2.appex/Contents/Resources/SubDir/P2M4.metallib")), + new CodesignInfo ( + "Bundle.app/PlugIns/P1.appex/plugins/P2.appex/PlugIns/P3.appex", + Platforms.All, + p3Metadata. + Set ("CodesignStampFile", $"Bundle.app/PlugIns/P1.appex/PlugIns/P2.appex/PlugIns/P3.appex/{codeSignatureSubdirectory}_CodeSignature/CodeResources"). + Set ("CodesignAdditionalFilesToTouch", "P3.appex.dSYM/Contents/Info.plist") + ), + new CodesignInfo ("Bundle.app/PlugIns/P1.appex/plugins/P2.appex/PlugIns/P3.appex/P3a.dylib", Platforms.Mobile, p3MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/PlugIns/P1.appex/plugins/P2.appex/PlugIns/P3.appex/P3a.dylib")), + new CodesignInfo ("Bundle.app/PlugIns/P1.appex/plugins/P2.appex/PlugIns/P3.appex/Contents/P3b.dylib", Platforms.All, p3MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/PlugIns/P1.appex/plugins/P2.appex/PlugIns/P3.appex/Contents/P3b.dylib")), + new CodesignInfo ("Bundle.app/PlugIns/P1.appex/plugins/P2.appex/PlugIns/P3.appex/Contents/MonoBundle/P3c.dylib", Platforms.All, p3MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/PlugIns/P1.appex/plugins/P2.appex/PlugIns/P3.appex/Contents/MonoBundle/P3c.dylib")), + new CodesignInfo ("Bundle.app/PlugIns/P1.appex/plugins/P2.appex/PlugIns/P3.appex/Contents/MonoBundle/SubDir/P3d.dylib", Platforms.All, p3MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/PlugIns/P1.appex/plugins/P2.appex/PlugIns/P3.appex/Contents/MonoBundle/SubDir/P3d.dylib")), + new CodesignInfo ("Bundle.app/PlugIns/P1.appex/plugins/P2.appex/PlugIns/P3.appex/P3M1.metallib", Platforms.Mobile, p3MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/PlugIns/P1.appex/plugins/P2.appex/PlugIns/P3.appex/P3M1.metallib")), + new CodesignInfo ("Bundle.app/PlugIns/P1.appex/plugins/P2.appex/PlugIns/P3.appex/Resources/P3M2.metallib", Platforms.Mobile, p3MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/PlugIns/P1.appex/plugins/P2.appex/PlugIns/P3.appex/Resources/P3M2.metallib")), + new CodesignInfo ("Bundle.app/PlugIns/P1.appex/plugins/P2.appex/PlugIns/P3.appex/Contents/Resources/P3M3.metallib", Platforms.All, p3MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/PlugIns/P1.appex/plugins/P2.appex/PlugIns/P3.appex/Contents/Resources/P3M3.metallib")), + new CodesignInfo ("Bundle.app/PlugIns/P1.appex/plugins/P2.appex/PlugIns/P3.appex/Contents/Resources/SubDir/P3M4.metallib", Platforms.All, p3MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/PlugIns/P1.appex/plugins/P2.appex/PlugIns/P3.appex/Contents/Resources/SubDir/P3M4.metallib")), + new CodesignInfo ( + "Bundle.app/Watch/W1.app", + Platforms.All, + w1Metadata. + Set ("CodesignStampFile", $"Bundle.app/Watch/W1.app/{codeSignatureSubdirectory}_CodeSignature/CodeResources"). + Set ("CodesignAdditionalFilesToTouch", "W1.app.dSYM/Contents/Info.plist") + ), + new CodesignInfo ("Bundle.app/Watch/W1.app/Contents/b.dylib", Platforms.All, w1MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Watch/W1.app/Contents/b.dylib")), + new CodesignInfo ("Bundle.app/Watch/W1.app/Contents/MonoBundle/c.dylib", Platforms.All, w1MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Watch/W1.app/Contents/MonoBundle/c.dylib")), + new CodesignInfo ("Bundle.app/Watch/W1.app/Contents/MonoBundle/SubDir/d.dylib", Platforms.All, w1MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Watch/W1.app/Contents/MonoBundle/SubDir/d.dylib")), + new CodesignInfo ("Bundle.app/Watch/W1.app/W1M1.metallib", Platforms.Mobile, w1MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Watch/W1.app/W1M1.metallib")), + new CodesignInfo ("Bundle.app/Watch/W1.app/Resources/W1M2.metallib", Platforms.Mobile, w1MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Watch/W1.app/Resources/W1M2.metallib")), + new CodesignInfo ("Bundle.app/Watch/W1.app/Contents/Resources/W1M3.metallib", Platforms.All, w1MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Watch/W1.app/Contents/Resources/W1M3.metallib")), + new CodesignInfo ("Bundle.app/Watch/W1.app/Contents/Resources/SubDir/W1M4.metallib", Platforms.All, w1MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Watch/W1.app/Contents/Resources/SubDir/W1M4.metallib")), + new CodesignInfo ( + "Bundle.app/Watch/W1.app/PlugIns/WP1.appex", + Platforms.All, + wp1Metadata. + Set ("CodesignStampFile", $"Bundle.app/Watch/W1.app/PlugIns/WP1.appex/{codeSignatureSubdirectory}_CodeSignature/CodeResources"). + Set ("CodesignAdditionalFilesToTouch", "WP1.appex.dSYM/Contents/Info.plist") + ), + new CodesignInfo ("Bundle.app/Watch/W1.app/PlugIns/WP1.appex/W1a.dylib", Platforms.Mobile, wp1MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Watch/W1.app/PlugIns/WP1.appex/W1a.dylib")), + new CodesignInfo ("Bundle.app/Watch/W1.app/PlugIns/WP1.appex/Contents/W1b.dylib", Platforms.All, wp1MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Watch/W1.app/PlugIns/WP1.appex/Contents/W1b.dylib")), + new CodesignInfo ("Bundle.app/Watch/W1.app/PlugIns/WP1.appex/Contents/MonoBundle/W1c.dylib", Platforms.All, wp1MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Watch/W1.app/PlugIns/WP1.appex/Contents/MonoBundle/W1c.dylib")), + new CodesignInfo ("Bundle.app/Watch/W1.app/PlugIns/WP1.appex/Contents/MonoBundle/SubDir/W1d.dylib", Platforms.All, wp1MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Watch/W1.app/PlugIns/WP1.appex/Contents/MonoBundle/SubDir/W1d.dylib")), + new CodesignInfo ("Bundle.app/Watch/W1.app/PlugIns/WP1.appex/W1M1.metallib", Platforms.Mobile, wp1MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Watch/W1.app/PlugIns/WP1.appex/W1M1.metallib")), + new CodesignInfo ("Bundle.app/Watch/W1.app/PlugIns/WP1.appex/Resources/W1M2.metallib", Platforms.Mobile, wp1MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Watch/W1.app/PlugIns/WP1.appex/Resources/W1M2.metallib")), + new CodesignInfo ("Bundle.app/Watch/W1.app/PlugIns/WP1.appex/Contents/Resources/W1M3.metallib", Platforms.All, wp1MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Watch/W1.app/PlugIns/WP1.appex/Contents/Resources/W1M3.metallib")), + new CodesignInfo ("Bundle.app/Watch/W1.app/PlugIns/WP1.appex/Contents/Resources/SubDir/W1M4.metallib", Platforms.All, wp1MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Watch/W1.app/PlugIns/WP1.appex/Contents/Resources/SubDir/W1M4.metallib")), + new CodesignInfo ( + "Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex", + Platforms.All, + wp2Metadata. + Set ("CodesignStampFile", $"Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/{codeSignatureSubdirectory}_CodeSignature/CodeResources"). + Set ("CodesignAdditionalFilesToTouch", "WP2.appex.dSYM/Contents/Info.plist") + ), + new CodesignInfo ("Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/W2a.dylib", Platforms.Mobile, wp2MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/W2a.dylib")), + new CodesignInfo ("Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/Contents/W2b.dylib", Platforms.All, wp2MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/Contents/W2b.dylib")), + new CodesignInfo ("Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/Contents/MonoBundle/W2c.dylib", Platforms.All, wp2MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/Contents/MonoBundle/W2c.dylib")), + new CodesignInfo ("Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/Contents/MonoBundle/SubDir/W2c.dylib", Platforms.All, wp2MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/Contents/MonoBundle/SubDir/W2c.dylib")), + new CodesignInfo ("Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/W2M1.metallib", Platforms.Mobile, wp2MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/W2M1.metallib")), + new CodesignInfo ("Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/Resources/W2M2.metallib", Platforms.Mobile, wp2MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/Resources/W2M2.metallib")), + new CodesignInfo ("Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/Contents/Resources/W2M3.metallib", Platforms.All, wp2MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/Contents/Resources/W2M3.metallib")), + new CodesignInfo ("Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/Contents/Resources/SubDir/W2M4.metallib", Platforms.All, wp2MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/Contents/Resources/SubDir/W2M4.metallib")), + new CodesignInfo ( + "Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/PlugIns/WP3.appex", + Platforms.All, + wp3Metadata. + Set ("CodesignStampFile", $"Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/PlugIns/WP3.appex/{codeSignatureSubdirectory}_CodeSignature/CodeResources"). + Set ("CodesignAdditionalFilesToTouch", "WP3.appex.dSYM/Contents/Info.plist") + ), + new CodesignInfo ("Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/PlugIns/WP3.appex/W3a.dylib", Platforms.Mobile, wp3MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/PlugIns/WP3.appex/W3a.dylib")), + new CodesignInfo ("Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/PlugIns/WP3.appex/Contents/W3b.dylib", Platforms.All, wp3MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/PlugIns/WP3.appex/Contents/W3b.dylib")), + new CodesignInfo ("Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/PlugIns/WP3.appex/Contents/MonoBundle/W3c.dylib", Platforms.All, wp3MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/PlugIns/WP3.appex/Contents/MonoBundle/W3c.dylib")), + new CodesignInfo ("Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/PlugIns/WP3.appex/Contents/MonoBundle/SubDir/W3c.dylib", Platforms.All, wp3MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/PlugIns/WP3.appex/Contents/MonoBundle/SubDir/W3c.dylib")), + new CodesignInfo ("Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/PlugIns/WP3.appex/W3M1.metallib", Platforms.Mobile, wp3MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/PlugIns/WP3.appex/W3M1.metallib")), + new CodesignInfo ("Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/PlugIns/WP3.appex/Resources/W3M2.metallib", Platforms.Mobile, wp3MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/PlugIns/WP3.appex/Resources/W3M2.metallib")), + new CodesignInfo ("Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/PlugIns/WP3.appex/Contents/Resources/W3M3.metallib", Platforms.All, wp3MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/PlugIns/WP3.appex/Contents/Resources/W3M3.metallib")), + new CodesignInfo ("Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/PlugIns/WP3.appex/Contents/Resources/SubDir/W3M4.metallib", Platforms.All, wp3MetadataNativeLibraries.Set ("CodesignStampFile", "codesign-stamp-path/Bundle.app/Watch/W1.app/PlugIns/WP1.appex/PlugIns/WP2.appex/PlugIns/WP3.appex/Contents/Resources/SubDir/W3M4.metallib")), + + new CodesignInfo ("Bundle.app/Contents/MonoBundle/createdump", Platforms.All, createDumpMetadata), + }; + + var allFiles = infos.Select (v => v.ItemSpec).ToArray (); + Touch (tmpdir, allFiles); + + var task = CreateTask (); + task.AppBundleDir = "Bundle.app"; + task.CodesignBundle = codesignBundle.ToArray (); + task.CodesignItems = codesignItems.ToArray (); + task.CodesignStampPath = "codesign-stamp-path/"; + task.TargetFrameworkMoniker = TargetFramework.GetTargetFramework (platform, isDotNet).ToString (); + Assert.IsTrue (task.Execute (), "Execute"); + + var outputCodesignItems = task.OutputCodesignItems; + Assert.That (outputCodesignItems.Select (v => v.ItemSpec), Is.Unique, "Uniqueness"); + + var failures = new List (); + var itemsFound = new List (); + foreach (var info in infos) { + var item = outputCodesignItems.SingleOrDefault (v => string.Equals (v.ItemSpec, info.ItemSpec, StringComparison.OrdinalIgnoreCase)); + info.CodesignItem = item; + if (IsPlatform (info.SignedOn, platform)) { + if (item is null) { + failures.Add ($"Expected '{info.ItemSpec}' to be signed."); + continue; + } + } else { + if (item is not null) { + failures.Add ($"Did not expect '{info.ItemSpec}' to be signed."); + continue; + } + } + + if (item is null) + continue; + itemsFound.Add (item); + + foreach (var kvp in info.Metadata) { + var metadata = item.GetMetadata (kvp.Key); + if (metadata == string.Empty && kvp.Value != string.Empty) { + failures.Add ($"Item '{info.ItemSpec}': Expected metadata '{kvp.Key}' not found (with value '{kvp.Value}')."); + } else if (!string.Equals (metadata, kvp.Value)) { + failures.Add ($"Item '{info.ItemSpec}': Expected value '{kvp.Value}' for metadata '{kvp.Key}', but got '{metadata}' instead.\nExpected: {kvp.Value}\nActual: {metadata}"); + } + } + + var customMetadata = item.CopyCustomMetadata (); + var unexpectedMetadata = customMetadata.Keys.ToHashSet (); + unexpectedMetadata.ExceptWith (info.Metadata.Keys); + unexpectedMetadata.Remove ("OriginalItemSpec"); + foreach (var unexpected in unexpectedMetadata) { + if (string.IsNullOrEmpty (customMetadata [unexpected])) + continue; + failures.Add ($"Item '{info.ItemSpec}': Unexpected metadata '{unexpected}' with value '{customMetadata [unexpected]}'."); + } + } + + var itemsNotFound = outputCodesignItems.Where (v => !itemsFound.Contains (v)).ToArray (); + foreach (var itemNotFound in itemsNotFound) { + failures.Add ($"Did not expect '{itemNotFound.ItemSpec}' to be signed."); + } + + if (failures.Count > 0) { + Console.WriteLine ($"{failures.Count} failures"); + foreach (var f in failures) + Console.WriteLine (f); + Console.WriteLine ($"{failures.Count} failures"); + } + Assert.That (failures, Is.Empty, "Failures"); + } finally { + Environment.CurrentDirectory = currentDir; + } + } + + bool IsPlatform (Platforms platforms, ApplePlatform platform) + { + switch (platform) { + case ApplePlatform.iOS: + return (platforms & Platforms.iOS) == Platforms.iOS; + case ApplePlatform.TVOS: + return (platforms & Platforms.tvOS) == Platforms.tvOS; + case ApplePlatform.MacOSX: + return (platforms & Platforms.macOS) == Platforms.macOS; + case ApplePlatform.WatchOS: + return (platforms & Platforms.watchOS) == Platforms.watchOS; + case ApplePlatform.MacCatalyst: + return (platforms & Platforms.MacCatalyst) == Platforms.MacCatalyst; + default: + throw new NotImplementedException (); + } + } + + void Touch (string root, params string [] files) + { + foreach (var f in files) { + var file = Path.Combine (root, f); + if (file.EndsWith (".appex", StringComparison.OrdinalIgnoreCase) || file.EndsWith (".app", StringComparison.OrdinalIgnoreCase)) { + Directory.CreateDirectory (f); + } else { + Directory.CreateDirectory (Path.GetDirectoryName (file)); + File.WriteAllText (file, string.Empty); + } + } + } + + class CodesignInfo { + public string ItemSpec; + public Platforms SignedOn; + public Dictionary Metadata; + public ITaskItem? CodesignItem; + + public CodesignInfo (string item, Platforms signedOn, Dictionary? metadata = null) + { + ItemSpec = item; + SignedOn = signedOn; + Metadata = metadata ?? new Dictionary (); + } + } + + // As opposed to ApplePlatform, this enum is a bitfield, and can represent multiple platforms in a single value. + [Flags] + enum Platforms { + None = 0, + iOS = 1, + tvOS = 2, + watchOS = 4, + macOS = 8, + MacCatalyst = 16, + Mobile = iOS | tvOS | watchOS, + Desktop = macOS | MacCatalyst, + All = Mobile | Desktop, + } + + } + + public static class Dictionary_Extensions { + public static Dictionary Set (this Dictionary self, string key, string value) + { + var rv = new Dictionary (self); + rv [key] = value; + return rv; + } + } + + public static class ITaskItem_Extensions { + public static Dictionary CopyCustomMetadata (this ITaskItem self) + { + var rv = new Dictionary (); + foreach (DictionaryEntry de in self.CloneCustomMetadata ()) { + rv [(string) de.Key] = (string) de.Value; + } + return rv; + } + } +} + diff --git a/tools/common/PathUtils.cs b/tools/common/PathUtils.cs index fca8291981..0523c2fadd 100644 --- a/tools/common/PathUtils.cs +++ b/tools/common/PathUtils.cs @@ -17,6 +17,20 @@ namespace Xamarin.Utils return (((uint) c - 'a') <= ((uint) 'z' - 'a')) ? (char) (c - 0x20) : c; } + public static string EnsureTrailingSlash (this string path) + { + if (path is null) + return null; + + if (path.Length == 0) + return Path.DirectorySeparatorChar.ToString (); + + if (path [path.Length - 1] != Path.DirectorySeparatorChar) + path += Path.DirectorySeparatorChar; + + return path; + } + [DllImport ("/usr/lib/libc.dylib")] static extern IntPtr realpath (string path, IntPtr buffer); From 536402184dc68024dcd6af703394c98b44fb9180 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Fri, 11 Feb 2022 13:55:22 +0100 Subject: [PATCH 4/8] [msbuild] Resolve the CodesignEntitlements and CodesignResourceRules properties. The CodesignEntitlements and CodesignResourceRules properties can be relative paths, and they might be coming from a referenced project. This means that if they're relative paths, we must resolve them to a full path using the project that defined them (which is specified using the 'SourceProjectPath' metadata). --- .../Tasks/CodesignTaskBase.cs | 38 ++++++++++++++++++- .../Tasks/XamarinTask.cs | 10 ++++- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/CodesignTaskBase.cs b/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/CodesignTaskBase.cs index 687d7df9be..8f7133b2ac 100644 --- a/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/CodesignTaskBase.cs +++ b/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/CodesignTaskBase.cs @@ -154,6 +154,40 @@ namespace Xamarin.MacDev.Tasks return string.Equals (metadataValue, "true", StringComparison.OrdinalIgnoreCase); } + string ResolvePath (ITaskItem item, string path) + { + if (string.IsNullOrEmpty (path)) + return path; + + path = PathUtils.ConvertToMacPath (path); + if (Path.IsPathRooted (path)) + return path; + + var sourceProjectPath = GetNonEmptyStringOrFallback (item, "SourceProjectPath", null); + if (sourceProjectPath is null) + return path; + + return Path.Combine (sourceProjectPath, path); + } + + string GetCodesignResourceRules (ITaskItem item) + { + var rv = GetNonEmptyStringOrFallback (item, "CodesignResourceRules", out var foundInMetadata, ResourceRules); + // The ResourceRules value is a path, and as such it might be a relative path from a different project, in which case we have to resolve it accordingly. + if (foundInMetadata) + rv = ResolvePath (item, rv); + return rv; + } + + string GetCodesignEntitlements (ITaskItem item) + { + var rv = GetNonEmptyStringOrFallback (item, "CodesignEntitlements", out var foundInMetadata, ResourceRules); + // The ResourceRules value is a path, and as such it might be a relative path from a different project, in which case we have to resolve it accordingly. + if (foundInMetadata) + rv = ResolvePath (item, rv); + return rv; + } + IList GenerateCommandLineArguments (ITaskItem item) { var args = new List (); @@ -163,8 +197,8 @@ namespace Xamarin.MacDev.Tasks var disableTimestamp = ParseBoolean (item, "CodesignDisableTimestamp", DisableTimestamp); var signingKey = GetNonEmptyStringOrFallback (item, "CodesignSigningKey", SigningKey, "SigningKey", required: true); var keychain = GetNonEmptyStringOrFallback (item, "CodesignKeychain", Keychain); - var resourceRules = GetNonEmptyStringOrFallback (item, "CodesignResourceRules", ResourceRules); - var entitlements = GetNonEmptyStringOrFallback (item, "CodesignEntitlements", Entitlements); + var resourceRules = GetCodesignResourceRules (item); + var entitlements = GetCodesignEntitlements (item); var extraArgs = GetNonEmptyStringOrFallback (item, "CodesignExtraArgs", ExtraArgs); args.Add ("-v"); diff --git a/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/XamarinTask.cs b/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/XamarinTask.cs index ed33271439..4e2dd11426 100644 --- a/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/XamarinTask.cs +++ b/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/XamarinTask.cs @@ -154,12 +154,20 @@ namespace Xamarin.MacDev.Tasks { } protected string GetNonEmptyStringOrFallback (ITaskItem item, string metadataName, string fallbackValue, string fallbackName = null, bool required = false) + { + return GetNonEmptyStringOrFallback (item, metadataName, out var _, fallbackValue, fallbackName, required); + } + + protected string GetNonEmptyStringOrFallback (ITaskItem item, string metadataName, out bool foundInMetadata, string fallbackValue, string fallbackName = null, bool required = false) { var metadataValue = item.GetMetadata (metadataName); - if (!string.IsNullOrEmpty (metadataValue)) + if (!string.IsNullOrEmpty (metadataValue)) { + foundInMetadata = true; return metadataValue; + } if (required && string.IsNullOrEmpty (fallbackValue)) Log.LogError (MSBStrings.E7085 /* The "{0}" task was not given a value for the required parameter "{1}", nor was there a "{2}" metadata on the resource {3}. */, GetType ().Name, fallbackName ?? metadataName, metadataName, item.ItemSpec); + foundInMetadata = false; return fallbackValue; } } From 5ec43ff963ddb8fb391362dfb71507825ed63ba5 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Fri, 11 Feb 2022 13:55:22 +0100 Subject: [PATCH 5/8] [msbuild] Execute _CompileEntitlements target on macOS under same conditions as for other platforms. The CompileEntitlements task already handles each platform as it should. This way we have fewer differences in the code between platforms. --- msbuild/Xamarin.Shared/Xamarin.Shared.targets | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/msbuild/Xamarin.Shared/Xamarin.Shared.targets b/msbuild/Xamarin.Shared/Xamarin.Shared.targets index 4cfddd6a9b..baf19a6756 100644 --- a/msbuild/Xamarin.Shared/Xamarin.Shared.targets +++ b/msbuild/Xamarin.Shared/Xamarin.Shared.targets @@ -616,7 +616,7 @@ Copyright (C) 2018 Microsoft. All rights reserved. - + From 71482a975436300579651e8d5248c560122756b2 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Wed, 16 Mar 2022 16:23:23 +0100 Subject: [PATCH 6/8] [msbuild] Resolve the path to the entitlements to a full path. This way the property works when exposed to containing projects as well. --- msbuild/Xamarin.Shared/Xamarin.Shared.targets | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/msbuild/Xamarin.Shared/Xamarin.Shared.targets b/msbuild/Xamarin.Shared/Xamarin.Shared.targets index baf19a6756..9805f3c65c 100644 --- a/msbuild/Xamarin.Shared/Xamarin.Shared.targets +++ b/msbuild/Xamarin.Shared/Xamarin.Shared.targets @@ -643,6 +643,16 @@ Copyright (C) 2018 Microsoft. All rights reserved. + + + + + + + + From 2057fa3041b0bfb612e9f7ba91b9f07d9a1bb9cb Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Thu, 17 Mar 2022 07:57:55 +0100 Subject: [PATCH 7/8] [msbuild] Remove code that got duplicated in a rebase. --- msbuild/Xamarin.Shared/Xamarin.Shared.targets | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/msbuild/Xamarin.Shared/Xamarin.Shared.targets b/msbuild/Xamarin.Shared/Xamarin.Shared.targets index 9805f3c65c..d4975b30c1 100644 --- a/msbuild/Xamarin.Shared/Xamarin.Shared.targets +++ b/msbuild/Xamarin.Shared/Xamarin.Shared.targets @@ -2045,31 +2045,6 @@ Copyright (C) 2018 Microsoft. All rights reserved. - - - <_ComputeLinkModeDependsOn> - $(_ComputeLinkModeDependsOn); - _DetectSdkLocations; - - - - - <_LinkMode Condition="'$(_LinkMode)' == '' And '$(_PlatformName)' == 'macOS'">$(LinkMode) - <_LinkMode Condition="'$(_LinkMode)' == '' And '$(_PlatformName)' != 'macOS'">$(MtouchLink) - <_LinkMode Condition="'$(_LinkMode)' == ''">$(_DefaultLinkMode) - <_LinkMode Condition="'$(_LinkMode)' == '' And '$(_PlatformName)' == 'macOS'">None - <_LinkMode Condition="'$(_LinkMode)' == '' And '$(_PlatformName)' != 'macOS'">SdkOnly - - - - - <_CollectFrameworksDependsOn> - $(_CollectFrameworksDependsOn); - _DetectSigningIdentity; - _CompileToNative; - - - <_FrameworksDirectory Condition="'$(_FrameworksDirectory)' == '' And ('$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS' Or '$(_PlatformName)' == 'watchOS')">$(_AppBundlePath)/Frameworks From 5d36a7ed4a7058317cba84e244f6ae4a5ee3de7d Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Thu, 17 Mar 2022 16:19:00 +0100 Subject: [PATCH 8/8] [msbuild] Make the ComputeCodesignItems task not copy anything between macOS and Windows. The ComputeCodesignItems does not touch any files, and all the input files should already exist on the mac, so there's no need to copy files back and forth. --- .../Tasks/ComputeCodesignItems.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/msbuild/Xamarin.MacDev.Tasks/Tasks/ComputeCodesignItems.cs b/msbuild/Xamarin.MacDev.Tasks/Tasks/ComputeCodesignItems.cs index f64211f4ce..924a92b65c 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Tasks/ComputeCodesignItems.cs +++ b/msbuild/Xamarin.MacDev.Tasks/Tasks/ComputeCodesignItems.cs @@ -1,8 +1,12 @@ +using System.Collections.Generic; +using System.Linq; + using Microsoft.Build.Framework; + using Xamarin.Messaging.Build.Client; namespace Xamarin.MacDev.Tasks { - public class ComputeCodesignItems : ComputeCodesignItemsTaskBase, ICancelableTask { + public class ComputeCodesignItems : ComputeCodesignItemsTaskBase, ITaskCallback, ICancelableTask { public override bool Execute () { if (ShouldExecuteRemotely ()) @@ -11,6 +15,14 @@ namespace Xamarin.MacDev.Tasks { return base.Execute (); } + public IEnumerable GetAdditionalItemsToBeCopied () => Enumerable.Empty (); + + // This task does not create or modify any files, and it should only + // deal with files that are already on the mac, so no need to copy any + // files either way. + public bool ShouldCopyToBuildServer (ITaskItem item) => false; + public bool ShouldCreateOutputFile (ITaskItem item) => false; + public void Cancel () { if (ShouldExecuteRemotely ())