question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Support automatic transient dependency packaging for source generators

See original GitHub issue

Originally raised as part of an issue with Roslyn (dotnet/roslyn#52017), it was suggested that I raise it here to potentially get the ball rolling on this.

Basically from a user’s point of view, having private dependencies in your source generator can become unwieldy very fast when factoring in transient dependencies. For example, this is what it looks like to add System.Text.Json as a private dependency while factoring in transient dependencies.

  <ItemGroup Label="Package References">
    <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.9.0" />
    <PackageReference Include="System.Text.Json" Version="5.0.1" GeneratePathProperty="true" PrivateAssets="all" />
    <PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="5.0.0" GeneratePathProperty="true" PrivateAssets="all" />
    <PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="5.0.0" GeneratePathProperty="true" PrivateAssets="all" />
    <PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.4" GeneratePathProperty="true" PrivateAssets="all" />
    <PackageReference Include="System.Text.Encodings.Web" Version="5.0.1" GeneratePathProperty="true" PrivateAssets="all" />
    <PackageReference Include="System.Buffers" Version="4.5.1" GeneratePathProperty="true" PrivateAssets="all" />
    <PackageReference Include="System.Memory" Version="4.5.4" GeneratePathProperty="true" PrivateAssets="all" />
    <PackageReference Include="System.Numerics.Vectors" Version="4.4.0" GeneratePathProperty="true" PrivateAssets="all" />
  </ItemGroup>

  <PropertyGroup>
    <GetTargetPathDependsOn>$(GetTargetPathDependsOn);GetDependencyTargetPaths</GetTargetPathDependsOn>
  </PropertyGroup>

  <Target Name="GetDependencyTargetPaths">
    <ItemGroup>
      <TargetPathWithTargetPlatformMoniker Include="$(PKGSystem_Text_Json)\lib\netstandard2.0\*.dll" IncludeRuntimeDependency="false" />
      <TargetPathWithTargetPlatformMoniker Include="$(PKGMicrosoft_Bcl_AsyncInterfaces)\lib\netstandard2.0\*.dll" IncludeRuntimeDependency="false" />
      <TargetPathWithTargetPlatformMoniker Include="$(PKGSystem_Runtime_CompilerServices_Unsafe)\lib\netstandard2.0\*.dll" IncludeRuntimeDependency="false" />
      <TargetPathWithTargetPlatformMoniker Include="$(PKGSystem_Threading_Tasks_Extensions)\lib\netstandard2.0\*.dll" IncludeRuntimeDependency="false" />
      <TargetPathWithTargetPlatformMoniker Include="$(PKGSystem_Buffers)\lib\netstandard2.0\*.dll" IncludeRuntimeDependency="false" />
      <TargetPathWithTargetPlatformMoniker Include="$(PKGSystem_Memory)\lib\netstandard2.0\*.dll" IncludeRuntimeDependency="false" />
      <TargetPathWithTargetPlatformMoniker Include="$(PKGSystem_Numerics_Vectors)\lib\netstandard2.0\*.dll" IncludeRuntimeDependency="false" />
      <TargetPathWithTargetPlatformMoniker Include="$(PKGSystem_Text_Encodings_Web)\lib\netstandard2.0\*.dll" IncludeRuntimeDependency="false" />
    </ItemGroup>
  </Target>

Not only am I needing to be more careful about package version updates and their transient dependencies (the linked Roslyn issue came about because upgrading System.Text.Encodings.Web from 5.0.0 to 5.0.1 brought in two more dependencies for .NET Standard 2.0) but it seems like I’m doing the work the compiler/build system should be doing for me.

So far to avoid doing that, I’ve managed to hack in a semi-automated behaviour with the following:

  <ItemGroup Label="Package References">
    <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.9.0" />
    <PackageReference Include="System.Text.Json" Version="5.0.1" PrivateAssets="all" />
  </ItemGroup>

  <PropertyGroup>
    <GetTargetPathDependsOn>$(GetTargetPathDependsOn);GetDependencyTargetPaths</GetTargetPathDependsOn>
  </PropertyGroup>

  <Target Name="GetDependencyTargetPaths" AfterTargets="ResolvePackageDependenciesForBuild">
    <ItemGroup>
      <TargetPathWithTargetPlatformMoniker Include="@(ResolvedCompileFileDefinitions)" IncludeRuntimeDependency="false" />
    </ItemGroup>
  </Target>

It is not great for multiple reasons (ResolvedCompileFileDefinitions isn’t always available & includes more than the dependencies that we actually want to bundle) however this still seems like a more practical solution than manually specifying transient dependencies.

From my point of view, the ideal scenario is simply specifying PrivateAssets="all" and the build system takes care of the rest.

Issue Analytics

  • State:open
  • Created 2 years ago
  • Reactions:14
  • Comments:28 (7 by maintainers)

github_iconTop GitHub Comments

21reactions
Turnerjcommented, Aug 12, 2021

I hate to be that person but is there anyway I can help push this forward? Do I need to convince more people this is a problem or help contribute to a PR for this?

19reactions
user72356commented, Aug 28, 2021

@Turnerj I can tell you it’s a problem for me, and if you get just ONE person to comment, that means there are 100 others with the same problem but not commenting… I don’t have the bandwidth to learn the complex inner workings of Roslyn, msbuild and whatnot just to deliver a source generator. Not a wise use of my dev time. So I’m also quite supportive of a better dev experience for source generators, be it when referenced from another solution project, or when packaged in a nuget.

Read more comments on GitHub >

github_iconTop Results From Across the Web

The pain points of C# source generators: February 2022 Update
The short answer is, transient dependencies are basically just as painful for my usecase as they were originally. The issue seems to stem...
Read more >
Solving the source generator 'marker attribute' problem
In this post I describe how I solved a problem I've been wrestling with around source generators: where to put the 'marker attributes'...
Read more >
c# - How can I make a Roslyn Analyzer project a transitive ...
I have an MSBuild SDK set up so presumably consumers of my library will be able to consume the generator as an analyzer...
Read more >
Using C# Source Generators to Generate Data Transfer ...
Using C# Source Generators to generate DTOs could potentially save a lot of developer time, so in this post I am going to...
Read more >
Migrate from packages.config to PackageReference
The migrator analyzes the project's NuGet package references and attempts to categorize them into Top-level dependencies (NuGet packages that ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found