Support automatic transient dependency packaging for source generators
See original GitHub issueOriginally 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:
- Created 2 years ago
- Reactions:14
- Comments:28 (7 by maintainers)
Top GitHub Comments
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?
@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.