I am building a Roslyn Code Generator and one of the constraints of these analyser-style projects is that they must include all their dependencies in the package; there can be no NuGet dependencies on the package.
My generator project has a dependency on another project, and that project has a dependency on a NuGet package.
Generator.csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>10.0</LangVersion>
<IsRoslynComponent>true</IsRoslynComponent>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Syntax\Sytnax.csproj" />
</ItemGroup>
</Project>
Syntax.csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>10.0</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Text.Json" Version="7.0.3" />
</ItemGroup>
There is also a simple test project to consume and run the code generator:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference
Include="..\Generator\Generator.csproj"
OutputItemType="Analyzer"
ReferenceOutputAssembly="false" />
</ItemGroup>
</Project>
What needs to happen is the Syntax.dll
output from the Syntax project and the System.Text.Json.dll
from its package reference and any of the package's dependencies all need to be copied into the output for the project and included in the package's libraries. Additionally, when the project reference in the test project is resolved, it needs to be to a location that contains all the dependencies for the analyzer.
The default behaviour for library projects which produce NuGet packages is to only produce the built assembly in the project's output. When building a console application or a web application, all dependencies find their way into the output folder. What I would like is to achieve this effect, but for a library project.
I have had success marking the Generator's reference to the Syntax project with PrivateAssets="all"
and including the following target in the TargetsForTfmSpecificBuildOutput
property:
<Target Name="CopyProjectReferencesToPackage" DependsOnTargets="BuildOnlySettings;ResolveReferences">
<ItemGroup>
<BuildOutputInPackage Include="@(ReferenceCopyLocalPaths->WithMetadataValue('ReferenceSourceTarget', 'ProjectReference')->WithMetadataValue('PrivateAssets', 'All'))" />
</ItemGroup>
</Target>
Unfortunately this only solves the direct dependency and does not deal with the transient package references.