Skip to content

Commit

Permalink
Fix restore in Traversal when TargetFrameworks property is set (#197)
Browse files Browse the repository at this point in the history
A breaking change in the .NET SDK now uses TargetFrameworks differently leading to restore errors when Traversal projects set it accidentally.

Traversal projects do not support multi-targeting by design, so this change just sets TargetFrameworks to empty to ensure that NuGet does not try to restore using multiple frameworks.

Fixes #196
  • Loading branch information
jeffkl authored Aug 25, 2020
1 parent 0ba2860 commit 1f14aec
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 48 deletions.
118 changes: 71 additions & 47 deletions src/Traversal.UnitTests/TraversalTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Shouldly;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnitTest.Common;
using Xunit;
Expand All @@ -17,6 +18,53 @@ namespace Microsoft.Build.Traversal.UnitTests
{
public class TraversalTests : MSBuildSdkTestBase
{
[Theory]
[InlineData(null)]
[InlineData("Build")]
[InlineData("Rebuild")]
public void CollectsProjectReferenceBuildTargetOutputs(string target)
{
string[] projects = new[]
{
GetSkeletonCSProjWithTargetOutputs("A"),
GetSkeletonCSProjWithTargetOutputs("B")
}.Select(i => i.FullPath).ToArray();

var subTraversalProject = ProjectCreator
.Templates
.TraversalProject(projects, path: GetTempFile("dirs.proj"))
.Save();

ProjectCreator
.Create(path: GetTempFile("root.proj"))
.Target("BuildTraversalProject")
.Task(
"MSBuild",
parameters: new Dictionary<string, string>
{
["Projects"] = subTraversalProject.FullPath,
["Targets"] = target
})
.TaskOutputItem("TargetOutputs", "CollectedOutputs")
.TaskMessage("%(CollectedOutputs.Identity)", MessageImportance.High)
.Save()
.TryBuild("BuildTraversalProject", out bool result, out BuildOutput buildOutput);

buildOutput.Messages.High.Count.ShouldBe(2, customMessage: () => buildOutput.GetConsoleLog());
buildOutput.Messages.High.ShouldContain("A.dll", customMessage: () => buildOutput.GetConsoleLog());
buildOutput.Messages.High.ShouldContain("B.dll", customMessage: () => buildOutput.GetConsoleLog());

ProjectCreator GetSkeletonCSProjWithTargetOutputs(string projectName)
{
return ProjectCreator.Templates.SdkCsproj(path: GetTempFile($"{projectName}.csproj"), sdk: string.Empty)
.Target("Build", returns: "@(TestReturnItem)")
.TargetItemGroup()
.TargetItemInclude("TestReturnItem", "$(MSBuildThisFileName).dll")
.Target("Clean")
.Save();
}
}

[Theory]
[InlineData("dirs.proj")]
[InlineData("Dirs.proj")]
Expand Down Expand Up @@ -181,6 +229,29 @@ public void StaticGraphProjectReferenceTargetsAreSetForEachTraversalTarget(strin
: target);
}

[Fact]
public void TargetFrameworksDoesNotBreakRestore()
{
string[] projects = new[]
{
ProjectCreator.Templates.SdkCsproj(
path: Path.Combine(TestRootPath, "ProjectA", "ProjectA.csproj"),
targetFramework: "net46")
.Save(),
}.Select(i => i.FullPath).ToArray();

ProjectCreator
.Templates
.TraversalProject(
projects,
path: GetTempFile("dirs.proj"),
customAction: creator => creator.Property("TargetFrameworks", "net45;net46"))
.Save()
.TryBuild("Restore", out bool result, out BuildOutput buildOutput);

result.ShouldBeTrue(customMessage: () => buildOutput.GetConsoleLog());
}

[Theory]
[InlineData("Property1=Value1", null, "Property1=Value1")]
[InlineData("Property1=Value1", "Property2=Value2", "Property1=Value1;Property2=Value2")]
Expand Down Expand Up @@ -302,52 +373,5 @@ public void WorksWhenConfigurationSpecified(string configuration)

result.ShouldBeTrue(customMessage: () => buildOutput.GetConsoleLog());
}

[Theory]
[InlineData(null)]
[InlineData("Build")]
[InlineData("Rebuild")]
public void CollectsProjectReferenceBuildTargetOutputs(string target)
{
string[] projects = new[]
{
GetSkeletonCSProjWithTargetOutputs("A"),
GetSkeletonCSProjWithTargetOutputs("B")
}.Select(i => i.FullPath).ToArray();

var subTraversalProject = ProjectCreator
.Templates
.TraversalProject(projects, path: GetTempFile("dirs.proj"))
.Save();

ProjectCreator
.Create(path: GetTempFile("root.proj"))
.Target("BuildTraversalProject")
.Task(
"MSBuild",
parameters: new Dictionary<string, string>
{
["Projects"] = subTraversalProject.FullPath,
["Targets"] = target
})
.TaskOutputItem("TargetOutputs", "CollectedOutputs")
.TaskMessage("%(CollectedOutputs.Identity)", MessageImportance.High)
.Save()
.TryBuild("BuildTraversalProject", out bool result, out BuildOutput buildOutput);

buildOutput.Messages.High.Count.ShouldBe(2, customMessage: () => buildOutput.GetConsoleLog());
buildOutput.Messages.High.ShouldContain("A.dll", customMessage: () => buildOutput.GetConsoleLog());
buildOutput.Messages.High.ShouldContain("B.dll", customMessage: () => buildOutput.GetConsoleLog());

ProjectCreator GetSkeletonCSProjWithTargetOutputs(string projectName)
{
return ProjectCreator.Templates.SdkCsproj(path: GetTempFile($"{projectName}.csproj"), sdk: string.Empty)
.Target("Build", returns: "@(TestReturnItem)")
.TargetItemGroup()
.TargetItemInclude("TestReturnItem", "$(MSBuildThisFileName).dll")
.Target("Clean")
.Save();
}
}
}
}
9 changes: 9 additions & 0 deletions src/Traversal/Sdk/Sdk.targets
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@
<OutputPath Condition=" '$(Configuration)' != '' And '$(Platform)' != '' ">bin\$(Configuration)\$(Platform)\</OutputPath>
</PropertyGroup>

<!--
TargetFrameworks is used to convey that a project targets multiple frameworks. Traversal does not support multi-targeting
but having this property set to a value can confuse NuGet leading to errors. Setting the property to empty fixes an issue
where a user unknowningly sets it, breaking restore. See also: https://github.com/microsoft/MSBuildSdks/issues/196
-->
<PropertyGroup>
<TargetFrameworks></TargetFrameworks>
</PropertyGroup>

<Import Project="$(MSBuildToolsPath)\Microsoft.Common.targets" Condition=" Exists('$(MSBuildToolsPath)\Microsoft.Common.targets') " />

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion src/Traversal/version.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"inherit": true,
"version": "2.0"
"version": "2.1"
}

0 comments on commit 1f14aec

Please sign in to comment.