diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.ForceCommandLineSelfContainedToBeLocal.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.ForceCommandLineSelfContainedToBeLocal.targets
new file mode 100644
index 000000000000..9879c8211f6d
--- /dev/null
+++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.ForceCommandLineSelfContainedToBeLocal.targets
@@ -0,0 +1,6 @@
+
+
+ false
+ true
+
+
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 279717af4f5c..4824046115ea 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
@@ -70,7 +70,8 @@ Copyright (c) .NET Foundation. All rights reserved.
'$(SelfContained)' == 'true' or
'$(PublishReadyToRun)' == 'true' or
'$(PublishSingleFile)' == 'true' or
- '$(PublishAot)' == 'true'
+ '$(PublishAot)' == 'true' or
+ '$(PublishSelfContained)' == 'true'
)">true
@@ -169,6 +170,10 @@ Copyright (c) .NET Foundation. All rights reserved.
ResourceName="ImplicitRuntimeIdentifierResolutionForPublishPropertyFailed"
FormatArguments="SelfContained"/>
+
+
diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.BeforeCommon.targets b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.BeforeCommon.targets
index 2ff2c1de9993..feb73618b365 100644
--- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.BeforeCommon.targets
+++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.BeforeCommon.targets
@@ -22,7 +22,6 @@ Copyright (c) .NET Foundation. All rights reserved.
<_IsExecutable Condition="'$(OutputType)' == 'Exe' or '$(OutputType)'=='WinExe'">true
-
@@ -35,6 +34,9 @@ Copyright (c) .NET Foundation. All rights reserved.
+
+
+
diff --git a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.props b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.props
index 73a182102d13..13cda738fa8e 100644
--- a/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.props
+++ b/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.props
@@ -20,7 +20,7 @@ Copyright (c) .NET Foundation. All rights reserved.
Debug;Release
AnyCPU
- Debug
+ Debug
AnyCPU
diff --git a/src/Tests/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildASelfContainedApp.cs b/src/Tests/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildASelfContainedApp.cs
index 5e4d21f01334..845639992468 100644
--- a/src/Tests/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildASelfContainedApp.cs
+++ b/src/Tests/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildASelfContainedApp.cs
@@ -374,6 +374,34 @@ public void It_can_publish_runtime_specific_apps_with_library_dependencies_self_
publishCommand.Execute(new [] {"-property:SelfContained=true", "-property:_CommandLineDefinedSelfContained=true", $"-property:RuntimeIdentifier={rid}", "-property:_CommandLineDefinedRuntimeIdentifier=true" }).Should().Pass().And.NotHaveStdOutContaining("warning");
}
+ [Theory]
+ [InlineData("net7.0")]
+ public void It_does_not_build_SelfContained_due_to_PublishSelfContained_being_true(string targetFramework)
+ {
+ var runtimeIdentifier = EnvironmentInfo.GetCompatibleRid(targetFramework);
+ var testAsset = _testAssetsManager
+ .CopyTestAsset("HelloWorld", identifier: targetFramework)
+ .WithSource()
+ .WithTargetFramework(targetFramework)
+ .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 + "PublishSelfContained", "true"));
+ });
+
+ var buildCommand = new BuildCommand(testAsset);
+
+ buildCommand
+ .Execute("-p:SelfContained=false")
+ .Should()
+ .Pass();
+
+ var outputDirectory = buildCommand.GetOutputDirectory(targetFramework, runtimeIdentifier: runtimeIdentifier);
+ outputDirectory.Should().NotHaveFile("hostfxr.dll");
+ }
+
[Theory]
[InlineData("net7.0")]
public void It_builds_a_runnable_output_with_Prefer32Bit(string targetFramework)
diff --git a/src/Tests/dotnet-publish.Tests/GivenDotnetPublishPublishesProjects.cs b/src/Tests/dotnet-publish.Tests/GivenDotnetPublishPublishesProjects.cs
index c7f439774a27..81ccbe7049d6 100644
--- a/src/Tests/dotnet-publish.Tests/GivenDotnetPublishPublishesProjects.cs
+++ b/src/Tests/dotnet-publish.Tests/GivenDotnetPublishPublishesProjects.cs
@@ -3,7 +3,9 @@
using System;
using System.IO;
+using System.Linq;
using System.Runtime.CompilerServices;
+using System.Xml.Linq;
using FluentAssertions;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Tools;
@@ -137,6 +139,85 @@ public void ItPublishesSelfContainedWithRid(string args)
.And.HaveStdOutContaining("Hello World");
}
+ [Fact]
+ public void ItPublishesSelfContainedWithPublishSelfContainedTrue()
+ {
+ var testAppName = "MSBuildTestApp";
+ var rid = EnvironmentInfo.GetCompatibleRid();
+ var outputDirectory = PublishApp(testAppName, rid, "-p:PublishSelfContained=true");
+
+ var outputProgram = Path.Combine(outputDirectory.FullName, $"{testAppName}{Constants.ExeSuffix}");
+
+ outputDirectory.Should().HaveFiles(new[] {
+ "System.dll", // File that should only exist if self contained
+ });
+
+ new RunExeCommand(Log, outputProgram)
+ .Execute()
+ .Should().Pass()
+ .And.HaveStdOutContaining("Hello World");
+ }
+
+ [Theory]
+ [InlineData("net7.0")]
+ public void ItPublishesSelfContainedWithPublishSelfContainedProperty(string targetFramework)
+ {
+ var rid = EnvironmentInfo.GetCompatibleRid(targetFramework);
+ var testAsset = _testAssetsManager
+ .CopyTestAsset("HelloWorld", identifier: targetFramework)
+ .WithSource()
+ .WithTargetFramework(targetFramework)
+ .WithProjectChanges(project =>
+ {
+ var ns = project.Root.Name.Namespace;
+ var propertyGroup = project.Root.Elements(ns + "PropertyGroup").First();
+ propertyGroup.Add(new XElement(ns + "PublishSelfContained", "true"));
+ });
+
+ var publishCommand = new PublishCommand(testAsset);
+ var publishResult = publishCommand.Execute($"/p:RuntimeIdentifier={rid}");
+
+ publishResult.Should().Pass();
+
+ var publishDirectory = publishCommand.GetOutputDirectory(
+ targetFramework: targetFramework,
+ runtimeIdentifier: rid);
+ publishDirectory.Should().HaveFiles(new[] {
+ "HelloWorld.dll",
+ "System.dll"
+ });
+ }
+
+ [RequiresMSBuildVersionTheory("17.5.0.0")] // This needs _IsPublishing to be set in MSBuild to pass.
+ [InlineData("net7.0")]
+ public void PublishSelfContainedPropertyOverridesSelfContainProperty(string targetFramework)
+ {
+ var rid = EnvironmentInfo.GetCompatibleRid(targetFramework);
+
+ var testAsset = _testAssetsManager
+ .CopyTestAsset("HelloWorld")
+ .WithSource()
+ .WithProjectChanges(project =>
+ {
+ var ns = project.Root.Name.Namespace;
+ var propertyGroup = project.Root.Elements(ns + "PropertyGroup").First();
+ propertyGroup.Add(new XElement(ns + "PublishSelfContained", "true"));
+ });
+
+ var publishCommand = new PublishCommand(testAsset);
+ var publishResult = publishCommand.Execute( $"/p:RuntimeIdentifier={rid}", "/p:SelfContained=false");
+
+ publishResult.Should().Pass();
+
+ var publishDirectory = publishCommand.GetOutputDirectory(
+ targetFramework: targetFramework,
+ runtimeIdentifier: rid);
+ publishDirectory.Should().HaveFiles(new[] {
+ "HelloWorld.dll",
+ "System.dll" // File that should only exist if self contained
+ });
+ }
+
[Theory]
[InlineData("--sc=false")]
[InlineData("--self-contained=false")]