From 6f9a8ebbbdcd60aed71b39a11838d121edc26044 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Fri, 20 Aug 2021 09:54:59 +0200 Subject: [PATCH] [msbuild] Rename the GetMinimumOSVersion task to ReadAppManifest and make it read more properties from the app manifest. (#12485) * Read CFBundleDisplayName and CFBundleVersion and use them in the _CompileITunesMetadata task. * Read numerous other app manifest values and pass them to the ACTool and IBTool tasks. This makes it possible to not parse the Info.plist in these tasks, which will become more complicated in the future, when we might either not have an Info.plist, or have many partial ones. Also enable nullability. --- dotnet/targets/Xamarin.Shared.Sdk.targets | 2 +- .../Tasks/ACToolTaskBase.cs | 43 ++++------ .../Tasks/GetMinimumOSVersionTaskBase.cs | 51 ----------- .../Tasks/ReadAppManifestTaskBase.cs | 86 +++++++++++++++++++ .../Tasks/XcodeCompilerToolTask.cs | 63 ++++++-------- ...MinimumOSVersion.cs => ReadAppManifest.cs} | 2 +- msbuild/Xamarin.Shared/Xamarin.Shared.targets | 65 ++++++++++---- .../Tasks/CompileITunesMetadataTaskBase.cs | 26 +++--- .../Xamarin.iOS.Common.targets | 8 +- .../TaskTests/IBToolTaskTests.cs | 1 - 10 files changed, 190 insertions(+), 157 deletions(-) delete mode 100644 msbuild/Xamarin.MacDev.Tasks.Core/Tasks/GetMinimumOSVersionTaskBase.cs create mode 100644 msbuild/Xamarin.MacDev.Tasks.Core/Tasks/ReadAppManifestTaskBase.cs rename msbuild/Xamarin.MacDev.Tasks/Tasks/{GetMinimumOSVersion.cs => ReadAppManifest.cs} (80%) diff --git a/dotnet/targets/Xamarin.Shared.Sdk.targets b/dotnet/targets/Xamarin.Shared.Sdk.targets index 6264e1992e..5d5933cb0d 100644 --- a/dotnet/targets/Xamarin.Shared.Sdk.targets +++ b/dotnet/targets/Xamarin.Shared.Sdk.targets @@ -882,7 +882,7 @@ diff --git a/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/ACToolTaskBase.cs b/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/ACToolTaskBase.cs index 8196acc6b7..74d6712151 100644 --- a/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/ACToolTaskBase.cs +++ b/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/ACToolTaskBase.cs @@ -53,31 +53,20 @@ namespace Xamarin.MacDev.Tasks get { return "actool"; } } - static bool IsMessagesExtension (PDictionary plist) - { - PDictionary extension; - PString id; - - if (!plist.TryGetValue ("NSExtension", out extension)) - return false; - - if (!extension.TryGetValue ("NSExtensionPointIdentifier", out id)) - return false; - - return id.Value == "com.apple.message-payload-provider"; + bool IsMessagesExtension { + get { + return NSExtensionPointIdentifier == "com.apple.message-payload-provider"; + } } protected override void AppendCommandLineArguments (IDictionary environment, CommandLineArgumentBuilder args, ITaskItem[] items) { - var plist = GetAppManifest (); - PString value = null; - var assetDirs = new HashSet (items.Select (x => BundleResource.GetVirtualProjectPath (ProjectDir, x, !string.IsNullOrEmpty (SessionId)))); - if (plist?.TryGetValue (ManifestKeys.XSAppIconAssets, out value) == true && !string.IsNullOrEmpty (value.Value)) { - int index = value.Value.IndexOf (".xcassets" + Path.DirectorySeparatorChar, StringComparison.Ordinal); + if (!string.IsNullOrEmpty (XSAppIconAssets)) { + int index = XSAppIconAssets.IndexOf (".xcassets" + Path.DirectorySeparatorChar, StringComparison.Ordinal); string assetDir = null; - var rpath = value.Value; + var rpath = XSAppIconAssets; if (index != -1) assetDir = rpath.Substring (0, index + ".xcassets".Length); @@ -95,15 +84,15 @@ namespace Xamarin.MacDev.Tasks args.Add ("--app-icon"); args.AddQuoted (assetName); - if (IsMessagesExtension (plist)) + if (IsMessagesExtension) args.Add ("--product-type com.apple.product-type.app-extension.messages"); } } - if (plist?.TryGetValue (ManifestKeys.XSLaunchImageAssets, out value) == true && !string.IsNullOrEmpty (value.Value)) { - int index = value.Value.IndexOf (".xcassets" + Path.DirectorySeparatorChar, StringComparison.Ordinal); + if (!string.IsNullOrEmpty (XSLaunchImageAssets)) { + int index = XSLaunchImageAssets.IndexOf (".xcassets" + Path.DirectorySeparatorChar, StringComparison.Ordinal); string assetDir = null; - var rpath = value.Value; + var rpath = XSLaunchImageAssets; if (index != -1) assetDir = rpath.Substring (0, index + ".xcassets".Length); @@ -123,8 +112,8 @@ namespace Xamarin.MacDev.Tasks } } - if (plist?.TryGetValue (ManifestKeys.CLKComplicationGroup, out value) == true && !string.IsNullOrEmpty (value.Value)) - args.Add ("--complication", value); + if (!string.IsNullOrEmpty (CLKComplicationGroup)) + args.Add ("--complication", CLKComplicationGroup); if (OptimizePNGs) args.Add ("--compress-pngs"); @@ -150,10 +139,8 @@ namespace Xamarin.MacDev.Tasks args.Add ("uikit"); } - if (plist != null) { - foreach (var targetDevice in GetTargetDevices ()) - args.Add ("--target-device", targetDevice); - } + foreach (var targetDevice in GetTargetDevices ()) + args.Add ("--target-device", targetDevice); args.Add ("--minimum-deployment-target", MinimumOSVersion); diff --git a/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/GetMinimumOSVersionTaskBase.cs b/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/GetMinimumOSVersionTaskBase.cs deleted file mode 100644 index c3772d4889..0000000000 --- a/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/GetMinimumOSVersionTaskBase.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; - -using Microsoft.Build.Framework; - -using Xamarin.Localization.MSBuild; -using Xamarin.Utils; - -namespace Xamarin.MacDev.Tasks { - public abstract class GetMinimumOSVersionTaskBase : XamarinTask { - public ITaskItem AppManifest { get; set; } - - [Required] - public string SdkVersion { get; set; } - - [Output] - public string MinimumOSVersion { get; set; } - - public override bool Execute () - { - PDictionary plist = null; - - if (!string.IsNullOrEmpty (AppManifest?.ItemSpec)) { - try { - plist = PDictionary.FromFile (AppManifest.ItemSpec); - } catch (Exception ex) { - Log.LogError (null, null, null, AppManifest.ItemSpec, 0, 0, 0, 0, MSBStrings.E0010, AppManifest.ItemSpec, ex.Message); - return false; - } - } - - var minimumOSVersionInManifest = plist?.Get (PlatformFrameworkHelper.GetMinimumOSVersionKey (Platform))?.Value; - if (string.IsNullOrEmpty (minimumOSVersionInManifest)) { - MinimumOSVersion = SdkVersion; - } else if (!IAppleSdkVersion_Extensions.TryParse (minimumOSVersionInManifest, out var _)) { - Log.LogError (null, null, null, AppManifest.ItemSpec, 0, 0, 0, 0, MSBStrings.E0011, minimumOSVersionInManifest); - return false; - } else { - MinimumOSVersion = minimumOSVersionInManifest; - } - - if (Platform == ApplePlatform.MacCatalyst) { - // Convert the min macOS version to the min iOS version, which the rest of our tooling expects. - if (!MacCatalystSupport.TryGetiOSVersion (Sdks.GetAppleSdk (Platform).GetSdkPath (SdkVersion, false), MinimumOSVersion, out var convertedVersion)) - Log.LogError (MSBStrings.E0187, MinimumOSVersion); - MinimumOSVersion = convertedVersion; - } - - return true; - } - } -} diff --git a/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/ReadAppManifestTaskBase.cs b/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/ReadAppManifestTaskBase.cs new file mode 100644 index 0000000000..0ad7628769 --- /dev/null +++ b/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/ReadAppManifestTaskBase.cs @@ -0,0 +1,86 @@ +#nullable enable + +using System; + +using Microsoft.Build.Framework; + +using Xamarin.Localization.MSBuild; +using Xamarin.Utils; + +namespace Xamarin.MacDev.Tasks { + public abstract class ReadAppManifestTaskBase : XamarinTask { + public ITaskItem? AppManifest { get; set; } + + [Required] + public string? SdkVersion { get; set; } + + [Output] + public string? CLKComplicationGroup { get; set; } + + [Output] + public string? CFBundleDisplayName { get; set; } + + [Output] + public string? CFBundleVersion { get; set; } + + [Output] + public string? MinimumOSVersion { get; set; } + + [Output] + public string? NSExtensionPointIdentifier { get; set; } + + [Output] + public string? UIDeviceFamily { get; set; } + + [Output] + public bool WKWatchKitApp { get; set; } + + [Output] + public string? XSAppIconAssets { get; set; } + + [Output] + public string? XSLaunchImageAssets { get; set; } + + public override bool Execute () + { + PDictionary? plist = null; + + if (!string.IsNullOrEmpty (AppManifest?.ItemSpec)) { + try { + plist = PDictionary.FromFile (AppManifest!.ItemSpec); + } catch (Exception ex) { + Log.LogError (null, null, null, AppManifest!.ItemSpec, 0, 0, 0, 0, MSBStrings.E0010, AppManifest.ItemSpec, ex.Message); + return false; + } + } + + var minimumOSVersionInManifest = plist?.Get (PlatformFrameworkHelper.GetMinimumOSVersionKey (Platform))?.Value; + if (string.IsNullOrEmpty (minimumOSVersionInManifest)) { + MinimumOSVersion = SdkVersion; + } else if (!IAppleSdkVersion_Extensions.TryParse (minimumOSVersionInManifest, out var _)) { + Log.LogError (null, null, null, AppManifest?.ItemSpec, 0, 0, 0, 0, MSBStrings.E0011, minimumOSVersionInManifest); + return false; + } else { + MinimumOSVersion = minimumOSVersionInManifest; + } + + if (Platform == ApplePlatform.MacCatalyst) { + // Convert the min macOS version to the min iOS version, which the rest of our tooling expects. + if (!MacCatalystSupport.TryGetiOSVersion (Sdks.GetAppleSdk (Platform).GetSdkPath (SdkVersion, false), MinimumOSVersion, out var convertedVersion)) + Log.LogError (MSBStrings.E0187, MinimumOSVersion); + MinimumOSVersion = convertedVersion; + } + + CFBundleDisplayName = plist?.GetCFBundleDisplayName (); + CFBundleVersion = plist?.GetCFBundleVersion (); + CLKComplicationGroup = plist?.Get (ManifestKeys.CLKComplicationGroup)?.Value; + NSExtensionPointIdentifier = plist?.GetNSExtensionPointIdentifier (); + UIDeviceFamily = plist?.GetUIDeviceFamily ().ToString (); + WKWatchKitApp = plist?.GetWKWatchKitApp () == true; + XSAppIconAssets = plist?.Get (ManifestKeys.XSAppIconAssets)?.Value; + XSLaunchImageAssets = plist?.Get (ManifestKeys.XSLaunchImageAssets)?.Value; + + return true; + } + } +} diff --git a/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/XcodeCompilerToolTask.cs b/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/XcodeCompilerToolTask.cs index e2de7df381..308ea0a2d4 100644 --- a/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/XcodeCompilerToolTask.cs +++ b/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/XcodeCompilerToolTask.cs @@ -26,8 +26,6 @@ namespace Xamarin.MacDev.Tasks #region Inputs - public ITaskItem AppManifest { get; set; } - public string BundleIdentifier { get; set; } [Required] @@ -77,22 +75,28 @@ namespace Xamarin.MacDev.Tasks #endregion - bool loadedAppManifest; - protected PDictionary GetAppManifest () - { - if (!loadedAppManifest) { - if (AppManifest != null) { - try { - plist = PDictionary.FromFile (AppManifest.ItemSpec); - } catch (Exception ex) { - Log.LogError (null, null, null, AppManifest.ItemSpec, 0, 0, 0, 0, "{0}", ex.Message); - return null; - } - } - loadedAppManifest = true; - } + #region Inputs from the app manifest - return plist; + public string CLKComplicationGroup { get; set; } + + public string NSExtensionPointIdentifier { get; set; } + + public string UIDeviceFamily { get; set; } + + public bool WKWatchKitApp { get; set; } + + public string XSAppIconAssets { get; set; } + + public string XSLaunchImageAssets { get; set; } + + #endregion + + public IPhoneDeviceType ParsedUIDeviceFamily { + get { + if (!string.IsNullOrEmpty (UIDeviceFamily)) + return (IPhoneDeviceType) Enum.Parse (typeof (IPhoneDeviceType), UIDeviceFamily); + return IPhoneDeviceType.NotSet; + } } protected abstract string DefaultBinDir { @@ -118,30 +122,15 @@ namespace Xamarin.MacDev.Tasks get { return false; } } - protected static bool IsWatchExtension (PDictionary plist) - { - PDictionary extension; - PString id; - - if (plist == null) - return false; - - if (!plist.TryGetValue ("NSExtension", out extension)) - return false; - - if (!extension.TryGetValue ("NSExtensionPointIdentifier", out id)) - return false; - - return id.Value == "com.apple.watchkit"; + protected bool IsWatchExtension { + get { + return NSExtensionPointIdentifier == "com.apple.watchkit"; + } } protected IEnumerable GetTargetDevices () { - var plist = GetAppManifest (); - var devices = plist?.GetUIDeviceFamily () ?? IPhoneDeviceType.NotSet; - var watch = plist?.GetWKWatchKitApp () == true; - var watchExtension = IsWatchExtension (plist); - return GetTargetDevices (devices, watch, watchExtension); + return GetTargetDevices (ParsedUIDeviceFamily, WKWatchKitApp, IsWatchExtension); } IEnumerable GetTargetDevices (IPhoneDeviceType devices, bool watch, bool watchExtension) diff --git a/msbuild/Xamarin.MacDev.Tasks/Tasks/GetMinimumOSVersion.cs b/msbuild/Xamarin.MacDev.Tasks/Tasks/ReadAppManifest.cs similarity index 80% rename from msbuild/Xamarin.MacDev.Tasks/Tasks/GetMinimumOSVersion.cs rename to msbuild/Xamarin.MacDev.Tasks/Tasks/ReadAppManifest.cs index 7a4557e5b2..902285d027 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Tasks/GetMinimumOSVersion.cs +++ b/msbuild/Xamarin.MacDev.Tasks/Tasks/ReadAppManifest.cs @@ -2,7 +2,7 @@ using Xamarin.Messaging.Build.Client; namespace Xamarin.MacDev.Tasks { - public class GetMinimumOSVersion : GetMinimumOSVersionTaskBase + public class ReadAppManifest : ReadAppManifestTaskBase { public override bool Execute () { diff --git a/msbuild/Xamarin.Shared/Xamarin.Shared.targets b/msbuild/Xamarin.Shared/Xamarin.Shared.targets index 82851aed59..42800aabb5 100644 --- a/msbuild/Xamarin.Shared/Xamarin.Shared.targets +++ b/msbuild/Xamarin.Shared/Xamarin.Shared.targets @@ -110,7 +110,6 @@ Copyright (C) 2018 Microsoft. All rights reserved. - @@ -118,6 +117,7 @@ Copyright (C) 2018 Microsoft. All rights reserved. + @@ -274,7 +274,7 @@ Copyright (C) 2018 Microsoft. All rights reserved. <_CompileAppManifestDependsOn> $(_CompileAppManifestDependsOn); _DetectSdkLocations; - _GetMinimumOSVersion; + _ReadAppManifest; _GenerateBundleName; _DetectSigningIdentity; _ComputeTargetFrameworkMoniker; @@ -319,6 +319,35 @@ Copyright (C) 2018 Microsoft. All rights reserved. + + <_ReadAppManifestDependsOn> + $(_ReadAppManifestDependsOn); + _DetectAppManifest; + _DetectSdkLocations; + _ComputeTargetFrameworkMoniker; + + + + + + + + + + + + + + + + + <_CompileEntitlementsDependsOn> $(_CompileEntitlementsDependsOn); @@ -382,7 +411,7 @@ Copyright (C) 2018 Microsoft. All rights reserved. <_CoreCompileInterfaceDefinitionsDependsOn> _BeforeCoreCompileInterfaceDefinitions; - _GetMinimumOSVersion; + _ReadAppManifest; _DetectSigningIdentity; _ComputeTargetFrameworkMoniker; @@ -398,12 +427,13 @@ Copyright (C) 2018 Microsoft. All rights reserved. Condition="'$(IsMacEnabled)' == 'true'" ToolExe="$(IBToolExe)" ToolPath="$(IBToolPath)" - AppManifest="$(_AppManifest)" BundleIdentifier="$(_BundleIdentifier)" + CLKComplicationGroup="$(_CLKComplicationGroup)" EnableOnDemandResources="$(EnableOnDemandResources)" InterfaceDefinitions="@(InterfaceDefinition)" IntermediateOutputPath="$(DeviceSpecificIntermediateOutputPath)" MinimumOSVersion="$(_MinimumOSVersion)" + NSExtensionPointIdentifier="$(_NSExtensionPointIdentifier)" IsWatchApp="$(IsWatchApp)" IsWatch2App="$(IsWatch2App)" ProjectDir="$(MSBuildProjectDirectory)" @@ -415,6 +445,10 @@ Copyright (C) 2018 Microsoft. All rights reserved. SdkPlatform="$(_SdkPlatform)" SdkVersion="$(_SdkVersion)" TargetFrameworkMoniker="$(_ComputedTargetFrameworkMoniker)" + UIDeviceFamily="$(_UIDeviceFamily)" + WKWatchKitApp="$(_WKWatchKitApp)" + XSAppIconAssets="$(_XSAppIconAssets)" + XSLaunchImageAssets="$(_XSLaunchImageAssets)" > @@ -458,20 +492,21 @@ Copyright (C) 2018 Microsoft. All rights reserved. + DependsOnTargets="_DetectAppManifest;_ReadAppManifest;_DetectSdkLocations;_BeforeCoreCompileImageAssets;_DetectSigningIdentity;_ComputeTargetFrameworkMoniker"> @@ -751,7 +790,7 @@ Copyright (C) 2018 Microsoft. All rights reserved. - + - - - - - - diff --git a/tests/msbuild/Xamarin.MacDev.Tasks.Tests/TaskTests/IBToolTaskTests.cs b/tests/msbuild/Xamarin.MacDev.Tasks.Tests/TaskTests/IBToolTaskTests.cs index e2fb7803d9..79d58aa6ce 100644 --- a/tests/msbuild/Xamarin.MacDev.Tasks.Tests/TaskTests/IBToolTaskTests.cs +++ b/tests/msbuild/Xamarin.MacDev.Tasks.Tests/TaskTests/IBToolTaskTests.cs @@ -47,7 +47,6 @@ namespace Xamarin.iOS.Tasks interfaceDefinitions.Add (new TaskItem (item)); var task = CreateTask (); - task.AppManifest = new TaskItem (Path.Combine (projectDir, "Info.plist")); task.InterfaceDefinitions = interfaceDefinitions.ToArray (); task.IntermediateOutputPath = intermediateOutputPath; task.MinimumOSVersion = PDictionary.FromFile (Path.Combine (projectDir, "Info.plist")).GetMinimumOSVersion ();