-
Notifications
You must be signed in to change notification settings - Fork 253
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for source generators that add non BCL code #10746
Comments
I suspect the answers will be "this is by design" or "it can't be |
The way I work around this is to have the This means all analyzers that list packages under the Because the |
@AraHaan I've explored the suggestion of adding a package reference in a package's .props for very different reasons and it's not stable last I checked. The .props does not exist on the first restore for the consuming project, and there is no loop to restore over and over until the set of package references stabilizes. It's necessary for a clean build with no prior restores (and an empty NuGet package cache) to restore correctly and compile and run the first time. |
I share @jnm2's concern. The only supported way for one nuget package to bring in another is via nuspec dependency. A PackageReference item added by an msbuild import file brought in by another package does not work in a single-phase restore that our tools assume today. |
Hey all, It's definitely a tricky situation, let me provide some information: DevelopmentDependency
@jnm2 You were right on point. Things work as designed, but not ideal in the context of source generators as per the current guidelines. Development dependency as a concept in PackageReference is mixed with the regular project graph. Dev dependencies are relatively pain free as long as the packages are self contained. I think the documentation in https://github.com/dotnet/roslyn/blob/main/docs/features/source-generators.cookbook.md#use-functionality-from-nuget-packages might need some updating, as it doesn't necessarily prevent customers from running into the scenario described here. I don't think introducing another knob for controlling the metadata is the right solution, as it's been suggested. I personally think dev dependencies should be self contained and not have dependencies, and apply the same reasoning to the source generators themselves. Alternatively, development dependencies could be their own item, and not interfere with the PackageReference/compile graph. cc @chsienki as I imagine you are the source gen owner from roslyn side. |
Another thing that I wanted to add is that development dependencies affecting runtime is not without issues. |
@nkolev92 To clarify: this is not a runtime dependency for the development dependency tool itself to load as it runs, but for its consuming project to load as it runs. |
Yep, I think similar idea applies. If you want to depend on a certain package, you should include it explicitly, not through something that is a development dependency. |
To add another data point: I've got a library which generates implementations for user-defined interfaces at runtime, using S.R.E, when the user calls e.g. I currently have to have the source generator check whether the user is referencing my library,and what version of it they're referencing, and raise an error diagnostic if necessary saying "please install version XYZ of this library", and also spam this information over the Nuget packet description, and documentation. This works, but it's not a great user experience. |
We want the app to "just work" after installing the source generator. If I want to add functionality to my project, and I add a package to do this, if the package opts into "disappearing" itself as a dependency because downstream users do not need it, why should that prevent that same package from leaving behind dependencies on other packages that are needed by downstream users? Another code generation library I own that I am planning to migrate to Roslyn Source Generators (ImmutableObjectGraph) is exactly in the use case @canton7 describes: it provides its own runtime library as well as generated code that uses it. But all this doesn't address one of my fundamental questions: if removing the IncludeAssets metadata from the PackageReference makes the whole thing work as we intend (which is true), what in VS gaining by explicitly setting the metadata and omitting |
I misunderstood the part that the generated code would depend on an API from a package.
I'll try to cover the multiple parts that went into the original design:
The development dependencies feature breaks down the moment there's a dependency for that package, whether it brings compile or other assets is not particularly relevant. It makes generating the dependency graph significantly more difficult because it would potentially require re-walking if a package id has been used as both a development dependency and not a development dependency. If I'm understanding it correctly, the concerns for source generators seem slightly different in that, these now transitively included packages would need to flow to the parent of the consuming project at runtime, so changing the metadata on the generator packagereference wouldn't be sufficient. Maybe a concept of related packages/package groups is appropriate here? |
What does this mean? A package self-identifies as a development dependency -- it is not designated as one by the one referencing it. So how could the same package appear as one and not as one in the same dependency graph?
Sure, if you're only thinking about the content of the package itself (excluding its respective dependencies). But then, if that made sense, the dev dependency package wouldn't include any content for the
If you're asking for a concrete example, here's one: Today, this compiles fine, since it includes the System.Memory reference to the compiler: <PackageReference Include="Microsoft.Windows.CsWin32" Version="0.1.422-beta">
<PrivateAssets>all</PrivateAssets>
</PackageReference> But unfortunately the packed result omits the System.Memory package dependency. And of course as the issue description describes, the IDE like to add this metadata when the reference is added: <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> And this breaks even the compilation. So what we want (in this concrete example) is a way for System.Memory to survive as a dependency even without the dev dependency intermediary, and for |
Perhaps the way of using source generator packages should change, Perhaps something like this could work for source generators then: <SourceGeneratorReference Include="SourceGeneratorName" Version="Version" /> And then any dependencies of them are then automatically marked as runtime dependencies, note the fact that |
Tagging in @jmarolf as he's been experimenting with some potential solutions to this problem. Unfortunately analyzers and NuGet have never played particularly well together and this has been really exacerbated with the addition of source generators. It's not really a conscious decision, but just an outcome of the two teams working at very different levels in the stack and there being impedance mismatches across those levels. I suspect we need some 'joined up thinking' from both teams to really solve this rather than just patching holes as they come up. |
I agree. There are some pending designs for analyzers that may extend to source generators. |
compile
Fody/Equals#356 |
To clarify: Fody weaver packages include a library which provides code that is needed to configure the desired weaving. The references to the library are then removed by Fody during its processing. These packages can't set I know it's a very specific use case, but ideally we'd like to have a way to tell NuGet to only add |
I think this is a good solution - any updates on this topic? |
In VS 16.9.3 (or as new as 16.10 Preview 3, 31206.385.main)...
Span<byte>
somewhere in a .cs fileExpected
No compilation errors.
Actual
Span<byte>
produces a compiler error because System.Memory.dll is not a reference that is passed to the compiler.The nuget package reference was added with:
Note the
IncludeAssets
metadata is missing thecompile
value. Adding it manually (or removing theIncludeAssets
metadata altogether) fixes the problem.Note that the nuspec for Microsoft.Windows.CsWin32 includes the System.Memory dependency with
include="all"
:Note also that our nuspec sets:
The net effect we want is that Microsoft.Windows.CsWin32 itself not be a package dependency expressed in the consuming project's own package, but we do want
System.Memory
to be expressed.As originally reported at microsoft/CsWin32#242
The text was updated successfully, but these errors were encountered: