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() {