Skip to content

Commit db607b0

Browse files
CopilotmarcpopMSFT
andcommitted
Add warning for --framework option on solution builds
- Added NETSDK1234 warning string in Strings.resx - Modified FrameworkOption to set _CommandLineDefinedTargetFramework property - Added _CheckForSolutionLevelTargetFramework target in Microsoft.NET.Sdk.Solution.targets - Created FrameworkOptionTests.cs with test cases for the new warning Co-authored-by: marcpopMSFT <12663534+marcpopMSFT@users.noreply.github.com>
1 parent a73be18 commit db607b0

File tree

4 files changed

+98
-2
lines changed

4 files changed

+98
-2
lines changed

src/Cli/dotnet/CommonOptions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ public static Option<string> FrameworkOption(string description) =>
175175
HelpName = CliStrings.FrameworkArgumentName
176176
}
177177
.AddCompletions(CliCompletion.TargetFrameworksFromProjectFile)
178-
.ForwardAsSingle(o => $"--property:TargetFramework={o}");
178+
.ForwardAsMany(o => [$"--property:TargetFramework={o}", "--property:_CommandLineDefinedTargetFramework=true"]);
179179

180180
public static Option<string> ArtifactsPathOption =
181181
new ForwardedOption<string>(

src/Tasks/Common/Resources/Strings.resx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1010,5 +1010,9 @@ You may need to build the project on another operating system or architecture, o
10101010
<value>NETSDK1233: Targeting .NET 10.0 or higher in Visual Studio 2022 17.14 is not supported.</value>
10111011
<comment>{StrBegins="NETSDK1233: "}</comment>
10121012
</data>
1013-
<!-- The latest message added is Net10NotCompatibleWithVS17. Please update this value with each PR to catch parallel PRs both adding a new message -->
1013+
<data name="CannotHaveSolutionLevelTargetFramework" xml:space="preserve">
1014+
<value>NETSDK1234: The "--framework" option isn't supported when building a solution. Specifying a solution-level framework results in all projects building for that framework, which can cause referenced projects to build multiple times and can lead to inconsistent builds.</value>
1015+
<comment>{StrBegins="NETSDK1234: "}{Locked="--framework"}</comment>
1016+
</data>
1017+
<!-- The latest message added is CannotHaveSolutionLevelTargetFramework. Please update this value with each PR to catch parallel PRs both adding a new message -->
10141018
</root>

src/Tasks/Microsoft.NET.Build.Extensions.Tasks/msbuildExtensions-ver/SolutionFile/ImportAfter/Microsoft.NET.Sdk.Solution.targets

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,12 @@ Copyright (c) .NET Foundation. All rights reserved.
3737

3838
</Target>
3939

40+
<Target Name="_CheckForSolutionLevelTargetFramework"
41+
BeforeTargets="Build;Publish;Clean;Store;VSTest;_MTPBuild"
42+
Condition="'$(_CommandLineDefinedTargetFramework)' == 'true'">
43+
44+
<NetSdkWarning ResourceName="CannotHaveSolutionLevelTargetFramework" />
45+
46+
</Target>
47+
4048
</Project>
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
#nullable disable
5+
6+
using System.Runtime.CompilerServices;
7+
8+
namespace dotnet.Tests;
9+
10+
public class FrameworkOptionTests : SdkTest
11+
{
12+
public FrameworkOptionTests(ITestOutputHelper log) : base(log)
13+
{
14+
}
15+
16+
[Theory]
17+
[InlineData("build", true)]
18+
[InlineData("clean", true)]
19+
[InlineData("publish", true)]
20+
[InlineData("test", true)]
21+
public void FrameworkOptionGeneratesWarningsWithSolutionFiles(string command, bool shouldWarn)
22+
{
23+
TestFrameworkWithSolution(command, useOption: true, shouldWarn: shouldWarn);
24+
}
25+
26+
[Theory]
27+
[InlineData("build")]
28+
[InlineData("clean")]
29+
[InlineData("publish")]
30+
[InlineData("test")]
31+
public void TargetFrameworkPropertyDoesNotGenerateWarningsWithSolutionFiles(string command)
32+
{
33+
TestFrameworkWithSolution(command, useOption: false, shouldWarn: false);
34+
}
35+
36+
void TestFrameworkWithSolution(string command, bool useOption, bool shouldWarn, [CallerMemberName] string callingMethod = "")
37+
{
38+
var testProject = new TestProject()
39+
{
40+
IsExe = true,
41+
TargetFrameworks = $"{ToolsetInfo.CurrentTargetFramework};net8.0"
42+
};
43+
44+
var testAsset = _testAssetsManager.CreateTestProject(testProject, callingMethod, identifier: command);
45+
46+
var slnDirectory = testAsset.TestRoot;
47+
48+
Log.WriteLine($"Test root: {slnDirectory}");
49+
50+
new DotnetNewCommand(Log)
51+
.WithVirtualHive()
52+
.WithWorkingDirectory(slnDirectory)
53+
.Execute("sln")
54+
.Should().Pass();
55+
56+
new DotnetCommand(Log)
57+
.WithWorkingDirectory(slnDirectory)
58+
.Execute("sln", "add", testProject.Name)
59+
.Should().Pass();
60+
61+
Microsoft.DotNet.Cli.Utils.CommandResult commandResult;
62+
if (useOption)
63+
{
64+
commandResult = new DotnetCommand(Log)
65+
.WithWorkingDirectory(slnDirectory)
66+
.Execute(command, "--framework", "net8.0");
67+
}
68+
else
69+
{
70+
commandResult = new DotnetCommand(Log)
71+
.WithWorkingDirectory(slnDirectory)
72+
.Execute(command, "--property:TargetFramework=net8.0");
73+
}
74+
commandResult.Should().Pass();
75+
if (shouldWarn)
76+
{
77+
commandResult.Should().HaveStdOutContaining("NETSDK1234");
78+
}
79+
else
80+
{
81+
commandResult.Should().NotHaveStdOutContaining("NETSDK1234");
82+
}
83+
}
84+
}

0 commit comments

Comments
 (0)