Skip to content

Make private runtime-only dependencies on .NET Standard 2.0.#11109

Merged
JanProvaznik merged 12 commits intodotnet:mainfrom
teo-tsirpanis:ns2.0-refs
Sep 5, 2025
Merged

Make private runtime-only dependencies on .NET Standard 2.0.#11109
JanProvaznik merged 12 commits intodotnet:mainfrom
teo-tsirpanis:ns2.0-refs

Conversation

@teo-tsirpanis
Copy link
Copy Markdown
Contributor

Context

Since #6148 we produce only reference assemblies for .NET Standard 2.0, which means that several of the our NuGet packages' dependencies when targeting .NET Standard 2.0 are unused.

Changes Made

The project files for Microsoft.Build.Framework, Utilities.Core and Tasks were updated to apply PrivateAssets="all" to all package references that are not exposed in the package's public API, when targeting .NET Standard 2.0.

Testing

I ran dotnet pack on these projects and validated manually that on .NET Standard 2.0, Microsoft.Build.Framework has zero dependencies, Utilities.Core depends only on Framework, and Tasks depends only on the previous two.

Because Roslyn keeps some internal APIs in reference assemblies, these reference assemblies still reference some assemblies whose respective package is not depended upon. I manually validated with ILSpy that the types in these assemblies are used only by internal APIs.

Notes

This is going to be a (minor) source-breaking change if a .NET Standard 2.0 project uses APIs from on one of the removed packages and transitively depended on it. They will have to directly depend on them, and it's not the first time we do a change like this (#9055).

I don't think that this is a binary-breaking change because the .NET Standard 2.0 binaries are not being used at runtime.

The reference to immutable collections is surfaced to `Framework`.
This lightens the NS2.0 reference assembly.
@rainersigwald
Copy link
Copy Markdown
Member

Nice, I've been planning to do something like this (and likely even going further). Will look shortly.

@teo-tsirpanis
Copy link
Copy Markdown
Contributor Author

and likely even going further

Let me know how further this can go, happy to do it now or in a subsequent PR.

@ghost ghost assigned JanProvaznik Jul 7, 2025
@JanProvaznik
Copy link
Copy Markdown
Member

sorry for letting this be stale for such a long time. The spirit of the change is good, though it breaks CI now (not sure if it ever passed or just accumulated divergence from December). @teo-tsirpanis are you interested in finishing it?

@JanProvaznik JanProvaznik added the needs-more-info Issues that need more info to continue investigation. label Jul 10, 2025
@teo-tsirpanis
Copy link
Copy Markdown
Contributor Author

This failure is interesting:

There was a conflict between "System.Memory, Version=4.0.1.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" and "System.Memory, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51".
    "System.Memory, Version=4.0.1.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" was chosen because it was primary and "System.Memory, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" was not.
    References which depend on "System.Memory, Version=4.0.1.2, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" [D:\a\1\s\.packages\system.memory\4.5.5\lib\netstandard2.0\System.Memory.dll].
        D:\a\1\s\.packages\system.memory\4.5.5\lib\netstandard2.0\System.Memory.dll
          Project file item includes which caused reference "D:\a\1\s\.packages\system.memory\4.5.5\lib\netstandard2.0\System.Memory.dll".
            D:\a\1\s\.packages\system.memory\4.5.5\lib\netstandard2.0\System.Memory.dll
    References which depend on or have been unified to "System.Memory, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" [].
        D:\a\1\s\artifacts\bin\Microsoft.Build.Framework\Debug\netstandard2.0\Microsoft.Build.Framework.dll
          Project file item includes which caused reference "D:\a\1\s\artifacts\bin\Microsoft.Build.Framework\Debug\netstandard2.0\Microsoft.Build.Framework.dll".
            D:\a\1\s\artifacts\bin\Microsoft.Build.Framework\Debug\netstandard2.0\Microsoft.Build.Framework.dll
            D:\a\1\s\artifacts\bin\Microsoft.Build.Utilities\Debug\netstandard2.0\Microsoft.Build.Utilities.Core.dll
        D:\a\1\s\artifacts\bin\Microsoft.Build.Utilities\Debug\netstandard2.0\Microsoft.Build.Utilities.Core.dll
          Project file item includes which caused reference "D:\a\1\s\artifacts\bin\Microsoft.Build.Utilities\Debug\netstandard2.0\Microsoft.Build.Utilities.Core.dll".
            D:\a\1\s\artifacts\bin\Microsoft.Build.Utilities\Debug\netstandard2.0\Microsoft.Build.Utilities.Core.dll

Could it be because we inject references to specific versions of maintainenance packages in test projects?

@teo-tsirpanis
Copy link
Copy Markdown
Contributor Author

@JanProvaznik CI is now green.

Most failures were due to my moving of the Microsoft.CodeAnalysis.Collections dependency to Build; that package had its own Strings.resx file, which caused name clashes with Build's own Strings.resx (Framework didn't have a Strings.resx, hence no clashes).

The solution is to update MS.CA.C to a version with dotnet/roslyn#78576, but because it is a more involved change, I rolled back that commit for now, and opened #12161.

@JanProvaznik JanProvaznik removed the needs-more-info Issues that need more info to continue investigation. label Jul 17, 2025
Copilot AI review requested due to automatic review settings August 18, 2025 08:38
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR modifies three MSBuild project files to mark runtime-only dependencies as private when targeting .NET Standard 2.0, reducing transitive dependencies in reference assemblies. Since #6148 introduced reference-only assemblies for .NET Standard 2.0, many package dependencies are no longer needed at runtime.

  • Applied PrivateAssets="all" to packages not exposed in public APIs for .NET Standard 2.0 targets
  • Removed explicit package references that are now handled by the private assets pattern
  • Validated that dependency chains are simplified (Framework has zero dependencies, Utilities.Core depends only on Framework, Tasks depends only on the previous two)

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
src/Framework/Microsoft.Build.Framework.csproj Marks System.Collections.Immutable and System.Diagnostics.DiagnosticSource as private assets, removes Microsoft.Win32.Registry reference
src/Utilities/Microsoft.Build.Utilities.csproj Marks multiple dependencies as private assets including StringTools project reference and several System packages, removes System.Text.Encoding.CodePages reference
src/Tasks/Microsoft.Build.Tasks.csproj Consolidates and marks multiple dependencies as private assets, moves some package references from conditional to private assets pattern
Comments suppressed due to low confidence (1)

src/Utilities/Microsoft.Build.Utilities.csproj:35

  • The removal of System.Text.Encoding.CodePages package reference is not replaced with a private assets equivalent in the new ItemGroup below. If this package is still needed for .NET Standard 2.0, it should be included with PrivateAssets="all" in the conditional ItemGroup.
  <ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETStandard'">

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.

Copy link
Copy Markdown
Member

@rainersigwald rainersigwald left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fantastic, thank you! Sorry for the delayed merge.

@JanProvaznik JanProvaznik merged commit 0bc107d into dotnet:main Sep 5, 2025
9 checks passed
@teo-tsirpanis teo-tsirpanis deleted the ns2.0-refs branch September 5, 2025 14:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants