From 35bdab79adf55acd9132465c68309c40671b6905 Mon Sep 17 00:00:00 2001 From: Noah Gilson Date: Fri, 16 Sep 2022 14:25:55 -0700 Subject: [PATCH] Implement publish-self-contained and add tests. --- ...eCommandLineSelfContainedToBeLocal.targets | 6 ++ ...oft.NET.RuntimeIdentifierInference.targets | 7 +- .../Microsoft.NET.Sdk.BeforeCommon.targets | 4 +- .../targets/Microsoft.NET.Sdk.props | 2 +- ...GivenThatWeWantToBuildASelfContainedApp.cs | 28 +++++++ .../GivenDotnetPublishPublishesProjects.cs | 81 +++++++++++++++++++ 6 files changed, 125 insertions(+), 3 deletions(-) create mode 100644 src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.ForceCommandLineSelfContainedToBeLocal.targets 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")]