diff --git a/src/Shared/ConversionUtilities.cs b/src/Shared/ConversionUtilities.cs
index 4489d33a43b..af794b51281 100644
--- a/src/Shared/ConversionUtilities.cs
+++ b/src/Shared/ConversionUtilities.cs
@@ -108,7 +108,7 @@ internal static bool ValidBooleanTrue(string parameterValue)
/// Returns true if the string represents a valid MSBuild boolean false value,
/// such as "!on" "off" "no" "!true"
///
- private static bool ValidBooleanFalse(string parameterValue)
+ internal static bool ValidBooleanFalse(string parameterValue)
{
return String.Equals(parameterValue, "false", StringComparison.OrdinalIgnoreCase) ||
String.Equals(parameterValue, "off", StringComparison.OrdinalIgnoreCase) ||
diff --git a/src/Tasks/Microsoft.Build.Tasks.csproj b/src/Tasks/Microsoft.Build.Tasks.csproj
index 5bd98bfbe0c..6421d98c638 100644
--- a/src/Tasks/Microsoft.Build.Tasks.csproj
+++ b/src/Tasks/Microsoft.Build.Tasks.csproj
@@ -1,4 +1,4 @@
-
+
@@ -329,6 +329,7 @@
+
@@ -966,8 +967,8 @@
-
-
+
+
diff --git a/src/Tasks/Microsoft.Common.CrossTargeting.targets b/src/Tasks/Microsoft.Common.CrossTargeting.targets
index 5096427a963..af1a6b18164 100644
--- a/src/Tasks/Microsoft.Common.CrossTargeting.targets
+++ b/src/Tasks/Microsoft.Common.CrossTargeting.targets
@@ -42,9 +42,7 @@ Copyright (C) Microsoft Corporation. All rights reserved.
@(_TargetFrameworkInfo->'%(TargetPlatformMonikers)')
$(_AdditionalPropertiesFromProject)
false
-
- false
- true
+ @(_TargetFrameworkInfo->'%(IsRidAgnostic)')
false
@@ -220,4 +218,4 @@ Copyright (C) Microsoft Corporation. All rights reserved.
-
\ No newline at end of file
+
diff --git a/src/Tasks/Microsoft.Common.CurrentVersion.targets b/src/Tasks/Microsoft.Common.CurrentVersion.targets
index b73ae1e6d85..d104492de0d 100644
--- a/src/Tasks/Microsoft.Common.CurrentVersion.targets
+++ b/src/Tasks/Microsoft.Common.CurrentVersion.targets
@@ -1,4 +1,4 @@
-
+
+
+
+
+
+
+
+
+
TargetFramework=%(AnnotatedProjects.NearestTargetFramework)
@@ -1863,9 +1877,10 @@ Copyright (C) Microsoft Corporation. All rights reserved.
%(AnnotatedProjects.UndefineProperties);TargetFramework
-
-
- %(AnnotatedProjects.UndefineProperties);RuntimeIdentifier
+
+
+ %(AnnotatedProjects.UndefineProperties);RuntimeIdentifier;SelfContained
- false
- true
+ @(_TargetFrameworkInfo->'%(IsRidAgnostic)')
true
$(Platform)
@@ -1941,6 +1954,16 @@ Copyright (C) Microsoft Corporation. All rights reserved.
$(TargetPlatformMoniker)
None
$(_AdditionalTargetFrameworkInfoProperties)
+
+
+ $(IsRidAgnostic)
+ true
+ false
+
diff --git a/src/Tasks/Microsoft.Common.tasks b/src/Tasks/Microsoft.Common.tasks
index 8bcaa32b507..d91e88e9861 100644
--- a/src/Tasks/Microsoft.Common.tasks
+++ b/src/Tasks/Microsoft.Common.tasks
@@ -54,6 +54,7 @@
+
@@ -106,4 +107,4 @@
-
\ No newline at end of file
+
diff --git a/src/Tasks/PublicAPI/net/PublicAPI.Unshipped.txt b/src/Tasks/PublicAPI/net/PublicAPI.Unshipped.txt
index 68779602973..e2378ba70a3 100644
--- a/src/Tasks/PublicAPI/net/PublicAPI.Unshipped.txt
+++ b/src/Tasks/PublicAPI/net/PublicAPI.Unshipped.txt
@@ -1,2 +1,9 @@
+Microsoft.Build.Tasks.SetRidAgnosticValueForProjects
+Microsoft.Build.Tasks.SetRidAgnosticValueForProjects.Projects.get -> Microsoft.Build.Framework.ITaskItem[]
+Microsoft.Build.Tasks.SetRidAgnosticValueForProjects.Projects.set -> void
+Microsoft.Build.Tasks.SetRidAgnosticValueForProjects.SetRidAgnosticValueForProjects() -> void
+Microsoft.Build.Tasks.SetRidAgnosticValueForProjects.UpdatedProjects.get -> Microsoft.Build.Framework.ITaskItem[]
+Microsoft.Build.Tasks.SetRidAgnosticValueForProjects.UpdatedProjects.set -> void
+override Microsoft.Build.Tasks.SetRidAgnosticValueForProjects.Execute() -> bool
Microsoft.Build.Tasks.XslTransformation.PreserveWhitespace.get -> bool
-Microsoft.Build.Tasks.XslTransformation.PreserveWhitespace.set -> void
\ No newline at end of file
+Microsoft.Build.Tasks.XslTransformation.PreserveWhitespace.set -> void
diff --git a/src/Tasks/PublicAPI/netstandard/PublicAPI.Unshipped.txt b/src/Tasks/PublicAPI/netstandard/PublicAPI.Unshipped.txt
index 68779602973..176cca35d60 100644
--- a/src/Tasks/PublicAPI/netstandard/PublicAPI.Unshipped.txt
+++ b/src/Tasks/PublicAPI/netstandard/PublicAPI.Unshipped.txt
@@ -1,2 +1,9 @@
+Microsoft.Build.Tasks.SetRidAgnosticValueForProjects
+Microsoft.Build.Tasks.SetRidAgnosticValueForProjects.Projects.get -> Microsoft.Build.Framework.ITaskItem[]
+Microsoft.Build.Tasks.SetRidAgnosticValueForProjects.Projects.set -> void
+Microsoft.Build.Tasks.SetRidAgnosticValueForProjects.SetRidAgnosticValueForProjects() -> void
+Microsoft.Build.Tasks.SetRidAgnosticValueForProjects.UpdatedProjects.get -> Microsoft.Build.Framework.ITaskItem[]
+Microsoft.Build.Tasks.SetRidAgnosticValueForProjects.UpdatedProjects.set -> void
Microsoft.Build.Tasks.XslTransformation.PreserveWhitespace.get -> bool
-Microsoft.Build.Tasks.XslTransformation.PreserveWhitespace.set -> void
\ No newline at end of file
+Microsoft.Build.Tasks.XslTransformation.PreserveWhitespace.set -> void
+override Microsoft.Build.Tasks.SetRidAgnosticValueForProjects.Execute() -> bool
diff --git a/src/Tasks/SetRidAgnosticValueForProjects.cs b/src/Tasks/SetRidAgnosticValueForProjects.cs
new file mode 100644
index 00000000000..7e45e76f163
--- /dev/null
+++ b/src/Tasks/SetRidAgnosticValueForProjects.cs
@@ -0,0 +1,65 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.Build.Framework;
+using Microsoft.Build.Shared;
+using Microsoft.Build.Utilities;
+
+namespace Microsoft.Build.Tasks
+{
+ public sealed class SetRidAgnosticValueForProjects : TaskExtension
+ {
+ public ITaskItem[] Projects { get; set; } = Array.Empty();
+
+ [Output]
+ public ITaskItem[] UpdatedProjects { get; set; } = Array.Empty();
+
+ public override bool Execute()
+ {
+ UpdatedProjects = Projects
+ .Select(p =>
+ {
+ var hasSingleTargetFrameworkString = p.GetMetadata("HasSingleTargetFramework");
+ if (!ConversionUtilities.ValidBooleanFalse(hasSingleTargetFrameworkString))
+ {
+ // No change to item, it should already have a single-valued IsRidAgnostic value
+ return p;
+ }
+ var updatedItem = new TaskItem(p);
+
+ var nearestTargetFramework = p.GetMetadata("NearestTargetFramework");
+ if (string.IsNullOrEmpty(nearestTargetFramework))
+ {
+ return p;
+ }
+
+ var targetFrameworksArray = p.GetMetadata("TargetFrameworks").Split(';');
+
+ int targetFrameworkIndex = Array.IndexOf(targetFrameworksArray, nearestTargetFramework);
+ if (targetFrameworkIndex < 0)
+ {
+ return p;
+ }
+
+ var isRidAgnosticArray = p.GetMetadata("IsRidAgnostic").Split(';');
+ if (isRidAgnosticArray.Length != targetFrameworksArray.Length)
+ {
+ return p;
+ }
+
+ updatedItem.SetMetadata("IsRidAgnostic", isRidAgnosticArray[targetFrameworkIndex]);
+
+ return updatedItem;
+ })
+ .ToArray();
+
+ return true;
+ }
+ }
+}