Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 4, 2025

Using --framework on a solution build causes all projects to build for that framework, leading to referenced projects building multiple times and potential file lock contention.

Changes

  • Added NETSDK1234 warning: New warning resource in Strings.resx that fires when --framework is used on solution builds
  • Modified FrameworkOption: Updated CommonOptions.cs to forward _CommandLineDefinedTargetFramework=true property when --framework CLI option is used
  • Added MSBuild target: Created _CheckForSolutionLevelTargetFramework in Microsoft.NET.Sdk.Solution.targets to detect and warn before Build/Publish/Clean/Test targets

Behavior

# Shows warning
$ dotnet build MySolution.sln --framework net8.0
warning NETSDK1234: The "--framework" option isn't supported when building a solution...

# No warning - property set directly
$ dotnet build MySolution.sln --property:TargetFramework=net8.0

Follows the same pattern as the existing --output warning (NETSDK1194).

Original prompt

This section details on the original issue you should resolve

<issue_title>dotnet build --framework builds referenced project twice</issue_title>
<issue_description><!--
Please keep in mind that the GitHub issue tracker is not intended as a general support forum, but for reporting non-security bugs and feature requests.

If you believe you have an issue that affects the SECURITY of the platform, please do NOT create an issue and instead email your issue details to [email protected]. Your report may be eligible for our bug bounty but ONLY if it is reported through email.
For other types of questions, consider using StackOverflow.

-->

Describe the bug

dotnet build with --framework builds the same project twice in parallel, if it is referenced by a solution and a ProjectReference. Without --framework, it builds only once.

To Reproduce

Dep.sln
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30114.105
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "One", "One\One.csproj", "{6C41A8DE-5C2D-4D36-9F5E-5070A5333DC9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Two", "Two\Two.csproj", "{8DEDAFB4-3647-450C-BD9A-0D1978A0A950}"
EndProject
Global
        GlobalSection(SolutionConfigurationPlatforms) = preSolution
                Debug|Any CPU = Debug|Any CPU
                Release|Any CPU = Release|Any CPU
        EndGlobalSection
        GlobalSection(SolutionProperties) = preSolution
                HideSolutionNode = FALSE
        EndGlobalSection
        GlobalSection(ProjectConfigurationPlatforms) = postSolution
                {6C41A8DE-5C2D-4D36-9F5E-5070A5333DC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
                {6C41A8DE-5C2D-4D36-9F5E-5070A5333DC9}.Debug|Any CPU.Build.0 = Debug|Any CPU
                {6C41A8DE-5C2D-4D36-9F5E-5070A5333DC9}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {6C41A8DE-5C2D-4D36-9F5E-5070A5333DC9}.Release|Any CPU.Build.0 = Release|Any CPU
                {8DEDAFB4-3647-450C-BD9A-0D1978A0A950}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
                {8DEDAFB4-3647-450C-BD9A-0D1978A0A950}.Debug|Any CPU.Build.0 = Debug|Any CPU
                {8DEDAFB4-3647-450C-BD9A-0D1978A0A950}.Release|Any CPU.ActiveCfg = Release|Any CPU
                {8DEDAFB4-3647-450C-BD9A-0D1978A0A950}.Release|Any CPU.Build.0 = Release|Any CPU
        EndGlobalSection
EndGlobal
One/One.csproj
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.XmlSerializer.Generator" Version="6.0.0" />
  </ItemGroup>

  <ItemGroup>
    <DotNetCliToolReference Include="Microsoft.XmlSerializer.Generator" Version="6.0.0" />
  </ItemGroup>

</Project>
One/Class1.cs
namespace One
{
    [System.Xml.Serialization.XmlRoot]
    public class Class1
    {
    }
}
Two/Two.csproj
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <ProjectReference Include="..\One\One.csproj" />
  </ItemGroup>

</Project>
Log of dotnet build --framework net6.0 becoming unexpectedly parallel and attempting to access a locked file
$ dotnet build --framework net6.0
Microsoft (R) Build Engine version 17.2.0+41abc5629 for .NET
Copyright (C) Microsoft Corporation. All rights reserved.

  Determining projects to restore...
  All projects are up-to-date for restore.
  One -> C:\Projects\Dep\One\bin\Debug\net6.0\One.dll
  One -> C:\Projects\Dep\One\bin\Debug\net6.0\One.dll
  .NET Xml Serialization Generation Utility, Version 6.0.0]
  Serialization Code File Name: C:\Projects\Dep\One\obj\Debug\net6.0\One.XmlSerializers.cs.
  Generated serialization code for assembly C:\Projects\Dep\One\obj\Debug\net6.0\One.dll --> 'C:\Projects\Dep\One\obj\Debug\net6.0\One.X
  mlSerializers.cs'.
  .NET Xml Serialization Generation Utility, Version 6.0.0]
  Serialization Code File Name: C:\Projects\Dep\One\obj\Debug\net6.0\One.XmlSerializers.cs.
  Generated serialization code for assembly C:\Projects\Dep\One\obj\Debug\net6.0\One.dll --> 'C:\Projects\Dep\One\obj\Debug\net6.0\One.X
  mlSerializers.cs'.
CSC : warning CS1504: Source file 'C:\Projects\Dep\One\obj\Debug\net6.0\One.XmlSerializers.cs' could not be opened -- The process cannot
 access the file 'C:\Projects\Dep\One\obj\Debug\net6.0\One.XmlSerializers.cs' because it is being used by another ...

</details>

- Fixes dotnet/sdk#26690

<!-- START COPILOT CODING AGENT TIPS -->
---

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more [Copilot coding agent tips](https://gh.io/copilot-coding-agent-tips) in the docs.

Copilot AI and others added 2 commits November 4, 2025 21:57
- 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 <[email protected]>
Manual testing confirms the feature works correctly:
- Using --framework on solution shows NETSDK1234 warning
- Using --property:TargetFramework does not show warning
- Warning appears for build, clean, publish, and test commands

Changes:
- Added NETSDK1234 warning string in Strings.resx
- Modified FrameworkOption to set _CommandLineDefinedTargetFramework property
- Added _CheckForSolutionLevelTargetFramework target in Microsoft.NET.Sdk.Solution.targets

Co-authored-by: marcpopMSFT <[email protected]>
Copilot AI changed the title [WIP] Fix dotnet build to avoid double project builds Add warning when using --framework with solution files Nov 4, 2025
Copilot AI requested a review from marcpopMSFT November 4, 2025 22:30
Copilot finished work on behalf of marcpopMSFT November 4, 2025 22:30
@marcpopMSFT
Copy link
Member

@baronfel in the spirit of limiting new warnings, should we only spit out this warning if the TFM is net11? People are definitely going to hit it.

@baronfel
Copy link
Member

baronfel commented Nov 7, 2025

The problem (similar to the output path) is that we don't know at the solution-level that these targets run at if the projects target 11.

We probably should create a Target similar to what Restore does and have the solution gather the TFMs of the project and flag if the TFM is present.

@KalleOlaviNiemitalo
Copy link
Contributor

Does this warn when dotnet test --no-build is used with --framework on a solution? I expect it shouldn't.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants