Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions docs/build-apps/build-items.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,42 @@ ms.date: 09/19/2024
Build items control how .NET for iOS, Mac Catalyst, macOS, and tvOS
application or library projects are built.

## PartialAppManifest

`PartialAppManifest` can be used to add additional partial app manifests that
will be merged with the main app manifest (Info.plist).

Any values in the partial app manifests will override values in the main app
manifest unless the `Overwrite` metadata is set to `false`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be "Overwrite attribute" instead of metadata?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


If the same value is specified in multiple partial app manifests, it's
undetermined which one will be the one used.

```xml
<ItemGroup>
<PartialAppManifest Include="my-partial-manifest.plist" Overwrite="false" />
</ItemGroup>
```

If the developer needs to execute a target to compute what to add to the
`PartialAppManifest` item group, it's possible to make sure this target is
executed before the `PartialAppManifest` items are procesed by adding it to
the `CollectAppManifestsDependsOn` property:

```xml
<PropertyGroup>
<CollectAppManifestsDependsOn>
AddPartialAppManifests;
$(CollectAppManifestsDependsOn);
</CollectAppManifestsDependsOn>
</PropertyGroup>
<Target Name="AddPartialAppManifests">
<ItemGroup>
<PartialAppManifest Include="MyPartialAppManifest.plist" />
</ItemGroup>
</Target>
```

## XcodeProject

`<XcodeProject>` can be used to build and consume the outputs
Expand Down
9 changes: 6 additions & 3 deletions msbuild/Xamarin.MacDev.Tasks/Tasks/CompileAppManifest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -393,15 +393,17 @@ protected void SetValue (PDictionary dict, string key, string value)
dict [key] = value;
}

public static void MergePartialPlistDictionary (PDictionary plist, PDictionary partial)
public static void MergePartialPlistDictionary (PDictionary plist, PDictionary partial, bool overwrite)
{
foreach (var property in partial) {
var key = property.Key!;
if (plist.ContainsKey (key)) {
if (!overwrite)
continue;
var value = plist [key];

if (value is PDictionary && property.Value is PDictionary) {
MergePartialPlistDictionary ((PDictionary) value, (PDictionary) property.Value);
MergePartialPlistDictionary ((PDictionary) value, (PDictionary) property.Value, overwrite);
} else {
plist [key] = property.Value.Clone ();
}
Expand All @@ -418,6 +420,7 @@ public static void MergePartialPLists (Task task, PDictionary plist, IEnumerable

foreach (var template in partialLists) {
PDictionary partial;
var overwrite = !string.Equals (template.GetMetadata ("Overwrite"), "false", StringComparison.OrdinalIgnoreCase);

try {
partial = PDictionary.FromFile (template.ItemSpec)!;
Expand All @@ -426,7 +429,7 @@ public static void MergePartialPLists (Task task, PDictionary plist, IEnumerable
continue;
}

MergePartialPlistDictionary (plist, partial);
MergePartialPlistDictionary (plist, partial, overwrite);
}
}

Expand Down
2 changes: 1 addition & 1 deletion msbuild/Xamarin.Shared/Xamarin.Shared.targets
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ Copyright (C) 2018 Microsoft. All rights reserved.
property to run targets that add to the `PartialAppManifest` item group before we process them.
* Some MSBuild properties can also add values.

The precedence is: MSBuild properties can be overridden by the Info.plist, which can be overridden by a partial plist.
The precedence is: MSBuild properties can be overridden by the Info.plist, which can be overridden by a partial plist (a partial plist can also specify the "Overwrite=false" metadata to not overwrite any existing entries).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same


2. In the `CompileAppManifest` target we get all the inputs from above, and compute a temporary app manifest, which is written to a temporary output file.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,36 @@ public void MultipleMinimumOSVersions ()
Assert.AreEqual ("13.0", plist.GetMinimumOSVersion (), "MinimumOSVersion");
}

[Test]
[TestCase (false, "14.0")]
[TestCase (true, "13.0")]
public void MultipleMinimumOSVersions_Overwrite (bool overwrite, string expectedMinimumOSVersion)
{
var dir = Cache.CreateTemporaryDirectory ();
var task = CreateTask (dir);

var mainPath = Path.Combine (dir, "Info.plist");
var main = new PDictionary ();
main.SetMinimumOSVersion ("14.0");
main.Save (mainPath);

var partialPath = Path.Combine (dir, "PartialAppManifest.plist");
var partial = new PDictionary ();
partial.SetMinimumOSVersion ("13.0");
partial.Save (partialPath);

task.AppManifest = new TaskItem (mainPath);
var partialAppManifest = new TaskItem (partialPath);
partialAppManifest.SetMetadata ("Overwrite", overwrite ? "true" : "false");
task.PartialAppManifests = new [] { partialAppManifest };
task.SupportedOSPlatformVersion = "14.0";

ExecuteTask (task);

var plist = PDictionary.FromFile (task.CompiledAppManifest!.ItemSpec)!;
Assert.AreEqual (expectedMinimumOSVersion, plist.GetMinimumOSVersion (), "MinimumOSVersion");
}

[Test]
public void ErrorWithMismatchedInfoPlistMinimumOSVersion ()
{
Expand Down