-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Unable to add native .dll reference to source generator project #54899
Comments
Also hitting this one (had opened #63396 though it was a dupe of this). I'm trying to update my generator in ComputeSharp to remove IO (following the conversation in #63290), and I'm currently with the following structure in my NuGet: My generator then will P/Invoke I really want to stop doing IO from the generator, and I do need to bundle those .dll-s this way to do that 🥲 @chsienki if it helps, when you start working on this feel free to ping me on Discord or Teams if you wanted another test scenario to validate the changes. I'd love to help and to try out a preview build of the toolset to double check a fix for this does resolve all issues both when going through NuGet and locally when using a project reference (I'm using both) 🙂 |
Sharing some more findings while testing Sergio0694/ComputeSharp#349. I believe there's two different issues related to supporting this scenario (ie. analyzers that depend on native libs bundled with the analyzer .dll), depending on how one is referencing the analyzer in question. Specifically:
To be clear, issue (1) is the most important one to solve, as that'd impact consumers of the library. Issue (2) can be worked around locally as it's mostly just encountered when working locally and setting up test projects and whatnot, though it'd be nice if that scenario also "just worked" out of the box, as one would normally expect items marked as Hope this helps! 😄 cc. @RikkiGibson |
Let me blow your mind: embed the native dlls in your assembly yourself, and write them out to disk during DLL startup. If you only use run-time binding ( This is of course bordering on the ridiculous, but you're likely to get farther than waiting for the root cause of this to be fixed :( |
My mind was not blown, as that's exactly what I've been doing for months already. But the whole point is that scenario is completely unsupported: source generators shouldn't do any IO. Not to mention it makes the setup unnecessarily complicated and ends up creating a lot of garbage in temporary folders for all the copied .dll-s. |
Jokes aside, my biggest problem with this issue (my issue, and the first on your list) is that if the build system did literally nothing, it would all just work. The problem only occurs because it's trying to load every dll as a managed assembly and it crashes on native ones, but if it just ignored load problems with native assemblies, everything else would work as is: the native dlls would still be copied alongside the managed ones and be ready for function binding. |
What does "it's" refer to here? Roslyn, or something else? |
Roslyn, yes. If it just ignored native PEs, then all would be fine 🙂 |
Do you know where roslyn is loading the native dlls? can you hook the point where that happens somehow and show the stack that is doing htat? |
@CyrusNajmabadi Msbuild targets pass all dlls in the analyzer package to the compiler as /analyzer command line params. AnalyzerAssemblyLoader then loads all these dlls. The loader could definitely check whether the dll is managed and ignore native. |
Yeah, I'd assume the issue is originating here: roslyn/src/Compilers/Core/Portable/DiagnosticAnalyzer/AnalyzerFileReference.cs Lines 451 to 469 in dd04453
Where the loader just tried to get the |
Missing tomas' explanation. |
ickkkkkkkkkk. it feels like this is on msbuild. Having us try to infer that it is passing bad stuff to us and undo it seems like the wrong way to handle things. CAn we not come up with a way for them to do things differently here? |
Do you know who we should ping from the MSBuild team about this? With its behavior currently being this, and leading Roslyn to just fail to load analyzers entirely, we're a bit in a bad spot now as the only way to make it work at all currently is to manually embed and unpack libraries at runtime, which goes directly against #63290 and is explicitly unsupported 😅 |
We are supposed to receive all the analyzer dependencies in the command line. This is important for determinism (@jaredpar in case he has an FAQ handy for this :P). We could consider using another flag instead of /analyzer to give them to the compiler but it's not hugely important IMO. we just have to account, one way or another, for the possibility that an analyzer dependency is native. |
Doing random IO would be a problem, as it would represent machine state not encoded into your inputs. Using IO to effectively just load data you are shipping is likely less of a problem. |
Is reporting errors for assemblies that have incorrect CorFlags set more important for Roslyn analyzer ecosystem than simplifying loading native analyzer dependencies? Why do we care about bad IL rewriters producing bad analyzer assemblies? Seems like super edge case. |
I agree it's an edge case. The claims being made are this is "it won't break anything". I'm pushing back on that notion. Every change has a consequence, ignoring them doesn't benefit the discussion. |
It seems like we should be able to distinguish this doesn't have managed metadata from this has malformed managed metadata, and continue to give an error on the latter if we think that has value. |
@CyrusNajmabadi Sure, and in fact that's what we're currently doing, but it's still not ideal because (1) it adds extra complexity, (2) once the new analyzers for banned APIs go online, we'll also get warnings on all those IO APIs we'll have to disable, (2) it adds overhead, and (3) it leaves a lot of garbage in temp folders for consumers 🥲 |
Picking this up now that 17.4 is mostly done, have we reached a conclusion on what the correct approach (if any) should be used to solve this issue? To recap, @RikkiGibson's proposal makes sense to me:
That would completely solve the issue while also preserving existing behavior in other cases, in case that was desired 🙂 |
Just wanted to mention that now that |
Um, any progress on this? There are real scenarios where native dependencies might be required for source generators, I believe the merit is proven. |
I think the recommended approach is to package up your native dependencies as resources in your dll. You can then extract those bits and load them on demand. |
I'm not sure it's possible in my case, because the dependency's static constructor throws, so it's implicitly called. Any pointers or samples I could take a look at? |
I'm doing this in ComputeSharp, for reference. @CyrusNajmabadi worth noting that while this works, it still produces a bunch of warnings from Roslyn, as you necessarily need to use some banned IO APIs. It'd be nice to be able to just bundle libs right in the analyzer folder, so we'd no longer need to suppress those warnings (and also, no more hassle of extracting the libs manually). |
Thanks @Sergio0694, I'll take a look. <ItemGroup>
<EmbeddedResource Include="..\..\libs\x64\dxcompiler.dll" Link="ComputeSharp\Libraries\x64\dxcompiler.dll" />
<EmbeddedResource Include="..\..\libs\x64\dxil.dll" Link="ComputeSharp\Libraries\x64\dxil.dll" />
<EmbeddedResource Include="..\..\libs\arm64\dxcompiler.dll" Link="ComputeSharp\Libraries\arm64\dxcompiler.dll" />
<EmbeddedResource Include="..\..\libs\arm64\dxil.dll" Link="ComputeSharp\Libraries\arm64\dxil.dll" />
</ItemGroup> and DxcLibraryLoader, I assume. |
There has been some discussion on letting them deploy as we do for normal DLLs and then differentiating native / managed by checking for the right metadata headers. That would solve the deployment bit but there are still some questions around how we'd manage them in the actual application. Keep in mind that there is not a single way that analyzers are loaded into the compiler: there are at least half a dozen depending on the host. Have to work through the details for all of those before taking on wrok.
Just because an issue has merit doesn't mean we're guaranteed to do the work. Every issue we fix is another issue that we don't fix. This has to be weighed against all of the other work that we're doing and not doing. |
Thanks @jaredpar. I wasn't trying to imply the work was free at all. I understand this is a small niche of a small niche, but there wasn't any activity on this issue, and I was wondering if it was even considered. Thanks for the insight. |
Version Used: VS 17.0.0 Preview 2.0
Steps to Reproduce:
You can find the full source code at https://github.com/myblindy/GrimBuilding/tree/efcore (the
efcore
branch).I understand that source generators can't automatically harvest dependencies from nuget packages and you have to use a clunky work-around to get it to work, and I have done so. This is my source generator project:
Since there isn't even transitive support, I added every nested
Microsoft.Data.Sqlite
package one by one, generated its property and referenced it usingTargetPathWithTargetPlatformMoniker
. It all works until I get to the nativee_sqlite3.dll
, if I useTargetPathWithTargetPlatformMoniker
with it, it tries to reference it as a managed library, and it fails as expected:So given that the path is found, is there a different tag I can use to make the main project copy the
e_sqlite3.dll
file so the analyzer can use it?The text was updated successfully, but these errors were encountered: