diff --git a/src/Tasks/Common/Resources/Strings.resx b/src/Tasks/Common/Resources/Strings.resx
index d4fc63f0c196..4e7216b894e6 100644
--- a/src/Tasks/Common/Resources/Strings.resx
+++ b/src/Tasks/Common/Resources/Strings.resx
@@ -891,4 +891,8 @@ You may need to build the project on another operating system or architecture, o
NETSDK1196: The SDK does not support ahead-of-time compilation. Set the PublishAot property to false.
{StrBegin="NETSDK1196: "}
+
+ NETSDK1198: In projects with TargetFrameworks >= 8.0, RuntimeIdentifier no longer automatically gives a SelfContained app. To preserve a project's current behavior after upgrading to 8.0, consider setting SelfContained explicitly.
+ {StrBegin="NETSDK1198: "}
+
diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.RuntimeIdentifierInference.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.RuntimeIdentifierInference.targets
index 73c6643b6053..3bde13f8bf9d 100644
--- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.RuntimeIdentifierInference.targets
+++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.RuntimeIdentifierInference.targets
@@ -149,7 +149,9 @@ Copyright (c) .NET Foundation. All rights reserved.
<_SelfContainedWasSpecified Condition="'$(SelfContained)' != ''">true
- true
+
+ true
false
<_RuntimeIdentifierUsesAppHost Condition="$(RuntimeIdentifier.StartsWith('ios')) or $(RuntimeIdentifier.StartsWith('tvos')) or $(RuntimeIdentifier.StartsWith('maccatalyst')) or $(RuntimeIdentifier.StartsWith('android')) or $(RuntimeIdentifier.StartsWith('browser'))">false
<_RuntimeIdentifierUsesAppHost Condition="'$(_RuntimeIdentifierUsesAppHost)' == ''">true
@@ -222,10 +224,15 @@ Copyright (c) .NET Foundation. All rights reserved.
because we do not want the behavior to be a breaking change compared to version 3.0 -->
+ ResourceName="PublishReadyToRunRequiresVersion30" />
+ ResourceName="PublishTrimmedRequiresVersion30" />
+
+
+
+ {
+ var ns = project.Root.Name.Namespace;
+ var propertyGroup = project.Root.Elements(ns + "PropertyGroup").First();
+ propertyGroup.Add(new XElement(ns + "RuntimeIdentifier", runtimeIdentifier));
+ });
+
+ var buildCommand = new BuildCommand(testAsset);
+ buildCommand
+ .Execute()
+ .Should()
+ .Pass();
+
+ var outputDirectory = buildCommand.GetOutputDirectory(targetFramework, runtimeIdentifier: runtimeIdentifier);
+ var selfContainedExecutable = $"HelloWorld{Constants.ExeSuffix}";
+ string selfContainedExecutableFullPath = Path.Combine(outputDirectory.FullName, selfContainedExecutable);
+
+ if (targetFramework == "net7.0")
+ {
+ Assert.True(File.Exists(selfContainedExecutableFullPath));
+ }
+ else
+ {
+ Assert.False(File.Exists(selfContainedExecutableFullPath)); // RuntimeIdentifier no longer implies SelfContained for TFM >= 8
+ }
+ }
+
+ [Theory]
+ [InlineData("net7.0", true)]
+ [InlineData("net7.0", false)]
+ [InlineData("net8.0", false)]
+ public void It_does_or_doesnt_warn_based_on_SelfContained_and_TargetFramework_breaking_RID_change(string targetFramework, bool defineSelfContained)
+ {
+ var runtimeIdentifier = EnvironmentInfo.GetCompatibleRid(targetFramework);
+ var testAsset = _testAssetsManager
+ .CopyTestAsset("HelloWorld", identifier: targetFramework + defineSelfContained.ToString())
+ .WithSource()
+ .WithProjectChanges(project =>
+ {
+ var ns = project.Root.Name.Namespace;
+ var propertyGroup = project.Root.Elements(ns + "PropertyGroup").First();
+ propertyGroup.Add(new XElement(ns + "RuntimeIdentifier", runtimeIdentifier));
+ propertyGroup.Add(new XElement(ns + "SelfContained", defineSelfContained ? "true" : ""));
+ });
+
+ var buildCommand = new BuildCommand(testAsset);
+ var commandResult = buildCommand.Execute();
+
+ if (targetFramework == "net7.0" && !defineSelfContained)
+ {
+ commandResult
+ .Should()
+ .Pass()
+ .And
+ .HaveStdOutContaining(Strings.RuntimeIdentifierWillNoLongerImplySelfContained);
+ }
+ else
+ {
+ commandResult
+ .Should()
+ .Pass()
+ .And
+ .NotHaveStdOutContaining(Strings.RuntimeIdentifierWillNoLongerImplySelfContained);
+ }
+ }
+
[Fact]
public void It_does_not_build_SelfContained_due_to_PublishSelfContained_being_true()
{