[msbuild] Save/restore all the NativeReference metadata.

* Save all the NativeReference metadata in binding resource packages.
* Copy all the NativeReference metadata to new items when resolving native references.

This makes it possible to set custom metadata on NativeReferences, and have that
metadata show up when it's needed, which might not be in the same project (for instance
if the native reference is in a binding project, we might want the custom metadata
when we load the native references from the binding project's resource package -
another case is when app extensions have native references, we might want any custom
metadata in the main executable project to know how to handle certain types of native
references).

Also sort the metadata we write to binding resource packages, so that the output
is stable. This required updating the corresponding tests.
This commit is contained in:
Rolf Bjarne Kvinge 2022-02-24 18:55:04 +01:00
Родитель 6e6c82b40e
Коммит 6c30c3ab22
4 изменённых файлов: 39 добавлений и 44 удалений

Просмотреть файл

@ -1,3 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace Microsoft.Build.Framework {
public static class ITaskItemExtensions {
const string FrameworkFileMetadataKey = "FrameworkFile";
@ -15,5 +19,14 @@ namespace Microsoft.Build.Framework {
return;
self.SetMetadata (metadata, value);
}
public static Dictionary<string, string> CloneCustomMetadataToDictionary (this ITaskItem item)
{
var custom = item.CloneCustomMetadata ();
var rv = new Dictionary<string, string> (custom.Count, StringComparer.OrdinalIgnoreCase);
foreach (DictionaryEntry entry in custom)
rv [(string) entry.Key] = (string) entry.Value;
return rv;
}
}
}

Просмотреть файл

@ -1,4 +1,5 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@ -112,9 +113,15 @@ namespace Xamarin.MacDev.Tasks {
writer.WriteStartElement ("NativeReference");
writer.WriteAttributeString ("Name", Path.GetFileName (nativeRef.ItemSpec));
foreach (string attribute in NativeReferenceAttributeNames) {
writer.WriteStartElement (attribute);
writer.WriteString (nativeRef.GetMetadata (attribute));
var customMetadata = nativeRef.CloneCustomMetadataToDictionary ();
var allKeys = customMetadata.Keys.Union (NativeReferenceAttributeNames, StringComparer.OrdinalIgnoreCase);
foreach (var key in allKeys.OrderBy (v => v)) {
writer.WriteStartElement (key);
if (customMetadata.TryGetValue (key, out var value)) {
writer.WriteString (value);
} else {
writer.WriteString (string.Empty);
}
writer.WriteEndElement ();
}

Просмотреть файл

@ -77,38 +77,13 @@ namespace Xamarin.MacDev.Tasks {
if (resolved == null)
return false;
var t = new TaskItem (resolved);
// add metadata from the original item
nr.CopyMetadataTo (t);
t.SetMetadata ("Kind", "Framework");
t.SetMetadata ("Name", resolved);
// add some metadata from the original item
var addToAppBundle = nr.GetMetadata ("AddToAppBundle");
if (!string.IsNullOrEmpty (addToAppBundle))
t.SetMetadata ("AddToAppBundle", addToAppBundle);
var frameworks = nr.GetMetadata("Frameworks");
if (!string.IsNullOrEmpty(frameworks))
t.SetMetadata("Frameworks", frameworks);
var weakFrameworks = nr.GetMetadata("WeakFrameworks");
if (!string.IsNullOrEmpty(weakFrameworks))
t.SetMetadata("WeakFrameworks", weakFrameworks);
var smartLink = nr.GetMetadata("SmartLink");
if (!string.IsNullOrEmpty(smartLink))
t.SetMetadata("SmartLink", smartLink);
var forceLoad = nr.GetMetadata("ForceLoad");
if (!string.IsNullOrEmpty(forceLoad))
t.SetMetadata("ForceLoad", forceLoad);
var linkerFlags = nr.GetMetadata("LinkerFlags");
if (!string.IsNullOrEmpty(linkerFlags))
t.SetMetadata("LinkerFlags", linkerFlags);
var isCxx = nr.GetMetadata("IsCxx");
if (!string.IsNullOrEmpty(isCxx))
t.SetMetadata("IsCxx", isCxx);
native_frameworks.Add (t);
break;
case ".framework":

Просмотреть файл

@ -117,34 +117,34 @@ namespace Xamarin.MacDev.Tasks {
var manifest = @"<BindingAssembly>
<NativeReference Name=""A.txt"">
<Kind></Kind>
<ForceLoad></ForceLoad>
<SmartLink></SmartLink>
<Frameworks></Frameworks>
<WeakFrameworks></WeakFrameworks>
<IsCxx></IsCxx>
<Kind></Kind>
<LinkerFlags></LinkerFlags>
<NeedsGccExceptionHandling></NeedsGccExceptionHandling>
<IsCxx></IsCxx>
<SmartLink></SmartLink>
<WeakFrameworks></WeakFrameworks>
</NativeReference>
<NativeReference Name=""B.txt"">
<Kind></Kind>
<ForceLoad></ForceLoad>
<SmartLink></SmartLink>
<Frameworks></Frameworks>
<WeakFrameworks></WeakFrameworks>
<IsCxx></IsCxx>
<Kind></Kind>
<LinkerFlags></LinkerFlags>
<NeedsGccExceptionHandling></NeedsGccExceptionHandling>
<IsCxx></IsCxx>
<SmartLink></SmartLink>
<WeakFrameworks></WeakFrameworks>
</NativeReference>
<NativeReference Name=""C.framework"">
<Kind></Kind>
<ForceLoad></ForceLoad>
<SmartLink></SmartLink>
<Frameworks></Frameworks>
<WeakFrameworks></WeakFrameworks>
<IsCxx></IsCxx>
<Kind></Kind>
<LinkerFlags></LinkerFlags>
<NeedsGccExceptionHandling></NeedsGccExceptionHandling>
<IsCxx></IsCxx>
<SmartLink></SmartLink>
<WeakFrameworks></WeakFrameworks>
</NativeReference>
</BindingAssembly>";
Assert.AreEqual (manifest, File.ReadAllText (Path.Combine (directory, "manifest")), "Manifest");