From a9c21ef79170d08b6d4542dcd36ca92a41a5f5e5 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Fri, 29 Jan 2021 17:37:37 +0100 Subject: [PATCH] [dotnet] Add support for some of the single-project MSBuild properties. (#10545) * [tests] Add test case for single-project properties in .NET. * [msbuild] Add support for the single-project ApplicationId MSBuild property. * [msbuild] Add support for the single-project ApplicationTitle, ApplicationVersion and AppleShortVersion MSBuild properties. * [dotnet] Enable the single-project MSBuild properties by default. * [dotnet] Add a short doc about single project properties. * [tests] Fix the GeneratePlistTaskTests.BundleIdentifier test according to bundle identifier changes. This test asserts that the CFBundleIdentifier value in the Info.plist isn't overwritten, and does so by calling the CompileAppManifest task, giving it a different value for the bundle identifier than what's in the Info.plist. The behavior change is that now we do things in the following manner: DetectSigningIdentityTask will read the Info.plist, compute a bundle identifier (which will be the value from the Info.plist if it's there), and returns it to the MSBuild code. Eventually that value will be passed to the CompileAppManifestTask, which will write it to the Info.plist. However, this test doesn't run the DetectSigningIdentityTask, which means that the initial value for the bundle identifier doesn't come from the Info.plist. --- dotnet/SingleProject.md | 27 +++++++++++++++ dotnet/targets/Xamarin.Shared.Sdk.targets | 3 ++ .../Tasks/CompileAppManifestTaskBase.cs | 34 +++++++++++++++++-- .../Tasks/DetectSigningIdentityTaskBase.cs | 14 ++++++-- msbuild/Xamarin.Shared/Xamarin.Shared.targets | 6 ++++ .../Tasks/CompileAppManifestTaskCore.cs | 1 - tests/dotnet/MySingleView/Info.plist | 4 --- tests/dotnet/MySingleView/MySingleView.csproj | 4 +++ tests/dotnet/UnitTests/DotNetUnitTests.csproj | 3 ++ tests/dotnet/UnitTests/ProjectTest.cs | 10 +++++- .../GeneratePlistTaskTests_Core.cs | 2 +- 11 files changed, 97 insertions(+), 11 deletions(-) create mode 100644 dotnet/SingleProject.md diff --git a/dotnet/SingleProject.md b/dotnet/SingleProject.md new file mode 100644 index 0000000000..bee82c1f83 --- /dev/null +++ b/dotnet/SingleProject.md @@ -0,0 +1,27 @@ +# .NET "Single Project" + +In order to improve the cross-platform experience between Android and our +Apple platforms, there are certain properties that can be set in the project +file that will be added to the app in a platform-specific way. + +More a more detailed description see this document: [OneDotNetSingleProject.md][1] + +For our Apple platforms this means we're mapping the following MSBuild +properties to Info.plist keys (this mapping will only take place if the +Info.plist in the project doesn't already contain entries for these keys): + +| MSBuild Property | Info.plist key | Notes | +| --------------------|----------------------------|-------------------------------------------| +| ApplicationId | CFBundleIdentifier | | +| ApplicationTitle | CFBundleDisplayName | | +| ApplicationVersion | CFBundleVersion | | +| AppleShortVersion | CFBundleShortVersionString | Defaults to ApplicationVersion when blank | + +This is only enabled if the `GenerateApplicationManifest` is set to `true` +(which is the default for `.NET 6`, and not for "legacy" +Xamarin.iOS/Xamarin.Mac) + +Ref: [Issue #10473][2] + +[1]: https://github.com/xamarin/xamarin-android/blob/40cedfa89c2660479fcb5e2482d2463fbcad1d04/Documentation/guides/OneDotNetSingleProject.md +[2]: https://github.com/xamarin/xamarin-macios/issues/10473 diff --git a/dotnet/targets/Xamarin.Shared.Sdk.targets b/dotnet/targets/Xamarin.Shared.Sdk.targets index 9be00f9f7b..6f2923dfae 100644 --- a/dotnet/targets/Xamarin.Shared.Sdk.targets +++ b/dotnet/targets/Xamarin.Shared.Sdk.targets @@ -9,6 +9,9 @@ <_XamarinTaskAssembly Condition="'$(_PlatformName)' != 'macOS'">$(_XamarinSdkRootDirectory)\tools\msbuild\iOS\Xamarin.iOS.Tasks.dll <_XamarinTaskAssembly Condition="'$(_PlatformName)' == 'macOS'">$(_XamarinSdkRootDirectory)\tools\msbuild\macOS\Xamarin.Mac.Tasks.dll + + + true diff --git a/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/CompileAppManifestTaskBase.cs b/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/CompileAppManifestTaskBase.cs index bc4b1bb7bc..d7b17abd61 100644 --- a/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/CompileAppManifestTaskBase.cs +++ b/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/CompileAppManifestTaskBase.cs @@ -13,6 +13,15 @@ namespace Xamarin.MacDev.Tasks { #region Inputs + // Single-project property that maps to CFBundleShortVersionString for Apple platforms + public string AppleShortVersion { get; set; } + + // Single-project property that maps to CFBundleDisplayName for Apple platforms + public string ApplicationTitle { get; set; } + + // Single-project property that maps to CFBundleVersion for Apple platforms + public string ApplicationVersion { get; set; } + [Required] public string AppBundleName { get; set; } @@ -36,6 +45,9 @@ namespace Xamarin.MacDev.Tasks [Required] public string DefaultSdkVersion { get; set; } + // Single-project property that determines whether other single-project properties should have any effect + public bool GenerateApplicationManifest { get; set; } + [Required] public bool IsAppExtension { get; set; } @@ -88,14 +100,32 @@ namespace Xamarin.MacDev.Tasks return false; } - plist.SetIfNotPresent (ManifestKeys.CFBundleIdentifier, BundleIdentifier); + plist.SetCFBundleIdentifier (BundleIdentifier); // no ifs and buts, we've computed the final bundle identifier (BundleIdentifier) in DetectSigningIdentityTask. plist.SetIfNotPresent (ManifestKeys.CFBundleInfoDictionaryVersion, "6.0"); plist.SetIfNotPresent (ManifestKeys.CFBundlePackageType, IsAppExtension ? "XPC!" : "APPL"); plist.SetIfNotPresent (ManifestKeys.CFBundleSignature, "????"); - plist.SetIfNotPresent (ManifestKeys.CFBundleVersion, "1.0"); plist.SetIfNotPresent (ManifestKeys.CFBundleExecutable, AssemblyName); plist.SetIfNotPresent (ManifestKeys.CFBundleName, AppBundleName); + if (GenerateApplicationManifest && !string.IsNullOrEmpty (ApplicationTitle)) + plist.SetIfNotPresent (ManifestKeys.CFBundleDisplayName, ApplicationTitle); + + string defaultBundleVersion = "1.0"; + if (GenerateApplicationManifest && !string.IsNullOrEmpty (ApplicationVersion)) + defaultBundleVersion = ApplicationVersion; + plist.SetIfNotPresent (ManifestKeys.CFBundleVersion, defaultBundleVersion); + + string defaultBundleShortVersion = null; + if (GenerateApplicationManifest) { + if (!string.IsNullOrEmpty (AppleShortVersion)) + defaultBundleShortVersion = AppleShortVersion; + else if (!string.IsNullOrEmpty (ApplicationVersion)) + defaultBundleShortVersion = ApplicationVersion; + } + if (string.IsNullOrEmpty (defaultBundleShortVersion)) + defaultBundleShortVersion = plist.GetCFBundleVersion (); + plist.SetIfNotPresent (ManifestKeys.CFBundleShortVersionString, defaultBundleShortVersion); + if (!Compile (plist)) return false; diff --git a/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/DetectSigningIdentityTaskBase.cs b/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/DetectSigningIdentityTaskBase.cs index aaa153df29..516fd200d9 100644 --- a/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/DetectSigningIdentityTaskBase.cs +++ b/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/DetectSigningIdentityTaskBase.cs @@ -105,6 +105,12 @@ namespace Xamarin.MacDev.Tasks [Required] public string AppManifest { get; set; } + // Single-project property that maps to CFBundleIdentifier for Apple platforms + public string ApplicationId { get; set; } + + // Single-project property that determines whether other single-project properties should have any effect + public bool GenerateApplicationManifest { get; set; } + public string Keychain { get; set; } public string SigningKey { get; set; } @@ -518,8 +524,12 @@ namespace Xamarin.MacDev.Tasks identity.BundleId = plist.GetCFBundleIdentifier (); if (string.IsNullOrEmpty (identity.BundleId)) { - Log.LogError (null, null, null, AppManifest, 0, 0, 0, 0, MSBStrings.E0139, AppManifest); - return false; + if (GenerateApplicationManifest && !string.IsNullOrEmpty (ApplicationId)) { + identity.BundleId = ApplicationId; + } else { + Log.LogError (null, null, null, AppManifest, 0, 0, 0, 0, MSBStrings.E0139, AppManifest); + return false; + } } DetectedBundleId = identity.BundleId; DetectedAppId = DetectedBundleId; // default value that can be changed below diff --git a/msbuild/Xamarin.Shared/Xamarin.Shared.targets b/msbuild/Xamarin.Shared/Xamarin.Shared.targets index 5ae4886c1f..71141066d7 100644 --- a/msbuild/Xamarin.Shared/Xamarin.Shared.targets +++ b/msbuild/Xamarin.Shared/Xamarin.Shared.targets @@ -231,6 +231,9 @@ Copyright (C) 2018 Microsoft. All rights reserved. MinimumOSVersion 7.0 - CFBundleDisplayName - ApplicationName - CFBundleIdentifier - com.xamarin.mysingleview XSAppIconAssets Resources/Images.xcassets/AppIcons.appiconset XSLaunchImageAssets diff --git a/tests/dotnet/MySingleView/MySingleView.csproj b/tests/dotnet/MySingleView/MySingleView.csproj index 5da1813d4d..4051594c83 100644 --- a/tests/dotnet/MySingleView/MySingleView.csproj +++ b/tests/dotnet/MySingleView/MySingleView.csproj @@ -4,5 +4,9 @@ net6.0-ios ios-x64 Exe + + MySingleTitle + com.xamarin.mysingletitle + 3.14 diff --git a/tests/dotnet/UnitTests/DotNetUnitTests.csproj b/tests/dotnet/UnitTests/DotNetUnitTests.csproj index 119b1fd227..15846460fd 100644 --- a/tests/dotnet/UnitTests/DotNetUnitTests.csproj +++ b/tests/dotnet/UnitTests/DotNetUnitTests.csproj @@ -43,6 +43,9 @@ external\BinLog.cs + + external\PListObject.cs + diff --git a/tests/dotnet/UnitTests/ProjectTest.cs b/tests/dotnet/UnitTests/ProjectTest.cs index 6d6ec73aa7..9d01663551 100644 --- a/tests/dotnet/UnitTests/ProjectTest.cs +++ b/tests/dotnet/UnitTests/ProjectTest.cs @@ -9,6 +9,7 @@ using NUnit.Framework; using Xamarin.Utils; using Xamarin.Tests; +using Xamarin.MacDev; namespace Xamarin.Tests { [TestFixture] @@ -55,7 +56,14 @@ namespace Xamarin.Tests { Clean (project_path); var result = DotNet.AssertBuild (project_path, verbosity); AssertThatLinkerExecuted (result); - AssertAppContents (platform, Path.Combine (Path.GetDirectoryName (project_path), "bin", "Debug", "net6.0-ios", "ios-x64", "MySingleView.app")); + var appPath = Path.Combine (Path.GetDirectoryName (project_path), "bin", "Debug", "net6.0-ios", "ios-x64", "MySingleView.app"); + AssertAppContents (platform, appPath); + var infoPlistPath = Path.Combine (appPath, "Info.plist"); + var infoPlist = PDictionary.FromFile (infoPlistPath); + Assert.AreEqual ("com.xamarin.mysingletitle", infoPlist.GetString ("CFBundleIdentifier").Value, "CFBundleIdentifier"); + Assert.AreEqual ("MySingleTitle", infoPlist.GetString ("CFBundleDisplayName").Value, "CFBundleDisplayName"); + Assert.AreEqual ("3.14", infoPlist.GetString ("CFBundleVersion").Value, "CFBundleVersion"); + Assert.AreEqual ("3.14", infoPlist.GetString ("CFBundleShortVersionString").Value, "CFBundleShortVersionString"); } [Test] diff --git a/tests/msbuild/Xamarin.MacDev.Tasks.Tests/TaskTests/GeneratePlistTaskTests/GeneratePlistTaskTests_Core.cs b/tests/msbuild/Xamarin.MacDev.Tasks.Tests/TaskTests/GeneratePlistTaskTests/GeneratePlistTaskTests_Core.cs index e7295cfbf6..14665b88a7 100644 --- a/tests/msbuild/Xamarin.MacDev.Tasks.Tests/TaskTests/GeneratePlistTaskTests/GeneratePlistTaskTests_Core.cs +++ b/tests/msbuild/Xamarin.MacDev.Tasks.Tests/TaskTests/GeneratePlistTaskTests/GeneratePlistTaskTests_Core.cs @@ -128,7 +128,7 @@ namespace Xamarin.iOS.Tasks public virtual void BundleIdentifier () { Assert.That (CompiledPlist.ContainsKey (ManifestKeys.CFBundleIdentifier), "#1"); - Assert.AreEqual (CompiledPlist.Get (ManifestKeys.CFBundleIdentifier).Value, identifier, "#2"); + Assert.AreEqual (CompiledPlist.Get (ManifestKeys.CFBundleIdentifier).Value, bundleIdentifier, "#2"); } [Test]