Description
The Android (32) workload currently ships four runtime packs, one for each Android architecture:
Microsoft.Android.Runtime.32.android-arm
Microsoft.Android.Runtime.32.android-arm64
Microsoft.Android.Runtime.32.android-x86
Microsoft.Android.Runtime.32.android-x64
In order to reduce our installation footprint we have a desire to introduce a new runtime pack for managed assemblies that are not architecture specific, but are still only intended to be used with the parent android
RID. Right now these managed assemblies are duplicated in all four packs mentioned above. Ideally, we would move the non-architecture specific assemblies into a new pack:
Microsoft.Android.Runtime.32.android
I tried to get this to work by adding a second RuntimePackNamePatterns
value to the KnownFrameworkReference
we declare:
<KnownFrameworkReference
Include="Microsoft.Android"
TargetFramework="net6.0"
RuntimeFrameworkName="Microsoft.Android"
LatestRuntimeFrameworkVersion="**FromWorkload**"
TargetingPackName="Microsoft.Android.Ref.32"
TargetingPackVersion="**FromWorkload**"
- RuntimePackNamePatterns="Microsoft.Android.Runtime.32.**RID**"
+ RuntimePackNamePatterns="Microsoft.Android.Runtime.32.android;Microsoft.Android.Runtime.32.**RID**"
RuntimePackRuntimeIdentifiers="android-arm;android-arm64;android-x86;android-x64"
Profile="Android"
/>
The ProcessFrameworkReferences
task handles this approach, but the ResolveFrameworkReferences task breaks as it only allows for a 1:1 relationship between runtime pack and framework reference:
Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(326,5): error MSB4018: System.ArgumentException: An item with the same key has already been added. Key: Microsoft.Android
I'm wondering how risky or big of a breaking change it would be to change the RuntimePack*
metadata on ResolvedFrameworkReferences
, and do something like this instead:
--- a/src/Tasks/Microsoft.NET.Build.Tasks/ResolveFrameworkReferences.cs
+++ b/src/Tasks/Microsoft.NET.Build.Tasks/ResolveFrameworkReferences.cs
@@ -26,7 +26,6 @@ protected override void ExecuteCore()
}
var resolvedTargetingPacks = ResolvedTargetingPacks.ToDictionary(tp => tp.ItemSpec, StringComparer.OrdinalIgnoreCase);
- var resolvedRuntimePacks = ResolvedRuntimePacks.ToDictionary(rp => rp.GetMetadata(MetadataKeys.FrameworkName), StringComparer.OrdinalIgnoreCase);
var resolvedFrameworkReferences = new List<TaskItem>(FrameworkReferences.Length);
@@ -48,12 +47,11 @@ protected override void ExecuteCore()
resolvedFrameworkReference.SetMetadata("TargetingPackVersion", targetingPack.GetMetadata(MetadataKeys.NuGetPackageVersion));
resolvedFrameworkReference.SetMetadata("Profile", targetingPack.GetMetadata("Profile"));
- ITaskItem runtimePack;
- if (resolvedRuntimePacks.TryGetValue(frameworkReference.ItemSpec, out runtimePack))
- {
- resolvedFrameworkReference.SetMetadata("RuntimePackPath", runtimePack.GetMetadata(MetadataKeys.PackageDirectory));
- resolvedFrameworkReference.SetMetadata("RuntimePackName", runtimePack.GetMetadata(MetadataKeys.NuGetPackageId));
- resolvedFrameworkReference.SetMetadata("RuntimePackVersion", runtimePack.GetMetadata(MetadataKeys.NuGetPackageVersion));
+ var matchingPacks = ResolvedRuntimePacks.Where(rp => rp.GetMetadata(MetadataKeys.FrameworkName).Equals(frameworkReference.ItemSpec, StringComparison.OrdinalIgnoreCase));
+ if (matchingPacks.Any()) {
+ resolvedFrameworkReference.SetMetadata("RuntimePackPath", string.Join (";", matchingPacks.Select (mp => mp.GetMetadata(MetadataKeys.PackageDirectory))));
+ resolvedFrameworkReference.SetMetadata("RuntimePackName", string.Join (";", matchingPacks.Select (mp => mp.GetMetadata(MetadataKeys.NuGetPackageId))));
+ resolvedFrameworkReference.SetMetadata("RuntimePackVersion", string.Join (";", matchingPacks.Select (mp => mp.GetMetadata(MetadataKeys.NuGetPackageVersion))));
}
resolvedFrameworkReferences.Add(resolvedFrameworkReference);
We may also want to update the metadata names, but that might cause more breakage. These changes would produce ;
separated RuntimePack*
metadata values, for example:
RuntimePackName = Microsoft.Android.Runtime.32.android;Microsoft.Android.Runtime.32.android-x64
These changes to ResolveFrameworkReferences
appear to work as needed for the Android use case. I've also got something working on the workload side by introducing a new FrameworkReference
for Android, but I am not convinced that this FrameworkReference
addition is the most sane or desirable approach.
Maybe there are other approaches that would support a "generic RID" runtime pack that I am not considering?