8

I have a library that relies on a source generator to work correctly. In the MyLibrary.csproj, I reference the generator like so.

<ItemGroup>
  <ProjectReference 
        Include="..\MyLibrary.Generators\MyLibrary.Generators.csproj" 
        PrivateAssets="contentfiles;build"
        ReferenceOutputAssembly="false"
        OutputItemType="analyzer"/>
</ItemGroup>

I need this analyzer reference to be transitive, i.e. projects that reference MyLibrary should get the MyLibrary.Generators analyzer transitively.

A simple reference like so does not seem to reference the analyzer, only MyLibrary

<ProjectReference Include="..\MyLibrary\MyLibrary.csproj" />

I want to stress that I am not looking for MyLibrary.Generators to be consumed as a regular assembly reference, but as a Roslyn Analyzer so my source generator can run as intended during compile time.

nalka
  • 1,894
  • 11
  • 26
chyyran
  • 2,446
  • 2
  • 21
  • 35
  • What is stopping you from adding the project reference manually? Note that if you are looking to ship the binary output from `MyLibrary.csproj`, you should do so in a nuget package, which can include the generator library. – Kris Vandermotten Mar 02 '21 at 16:24
  • I have an MSBuild SDK set up so presumably consumers of my library will be able to consume the generator as an analyzer reference that way, but I was hoping for a stronger guarantee via transitivity. – chyyran Mar 02 '21 at 19:54
  • Have you been able to find any solution to this? – abdusco Apr 09 '21 at 09:49
  • No, I haven't, unfortunately. – chyyran Apr 09 '21 at 16:22
  • I don't have an exact answer for you, but I've had some luck using the Microsoft.Build.NoTargets SDK to hand craft nuget packages for project references without causing an assembly reference. I think part of the issue you're having might be related to the ReferenceOutputAssembly="false" which may be interfering with the default pack target dependency generation. – TheXenocide May 14 '21 at 18:02
  • Did you manage to find a solution for this problem? Currently having the exact same problem and I want to avoid some trickery with nuget packages. – Christian Klemm Sep 29 '21 at 14:45
  • I have not been able to find a good solution for this. Currently I'm requiring all consumers of my framework to use a custom MSBuild SDK that references the analyzer project. See [here](https://github.com/SnowflakePowered/snowflake/blob/master/src/Snowflake.Framework.Sdk/Sdk/Sdk.props) – chyyran Sep 30 '21 at 16:31

1 Answers1

2

I have received an answer to this question on GitHub.

It is sufficient for the library project to have the following reference to the generator project:

  <ItemGroup>
    <!-- Package the generator in the analyzer directory of the nuget package -->
    <None Remove="$(OutputPath)/$(AssemblyName).Generator.dll" />
    <None Include="$(OutputPath)/$(AssemblyName).Generator.dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />
  </ItemGroup>

(I am not sure if the Remove line does anything. It might be unnecessary.)

When the library is consumed as a NuGet package, the generator is automatically included as an analyzer, i.e. the analyzer reference is transitive.

However, when the library is consumed through a project reference (such as in the library's own unit test project), we need the following:

  <ItemGroup>
    <ProjectReference Include="..\MyLibrary\MyLibrary.csproj" />
    <ProjectReference Include="..\MyLibrary.Generator\MyLibrary.Generator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
  </ItemGroup>

The examples in the original post all handle project references. From what I have gathered, a transitive project reference to an analyzer seems impossible, unfortunately.

Timo
  • 7,992
  • 4
  • 49
  • 67
  • Drawback: If the Generator project depends on other packages, they are not referenced in the resulting package. – Tom Feb 15 '23 at 16:59