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
Issue with External nugets used directly via #addin directive #373
Comments
#addin
directive
👍 |
@jrnail23 you're absolutely correct, this is a known issue I've haven't had time to get around to fix yet. Initially we'd like to pick correct DLL based on framework preferably without adding dependencies. Nuget targets are a bit messy but should be doable to get something so we can compare running framework against highest avail matching that. |
@devlead, It seems like that |
I took a look at this a while back but only got as far as taking the parsing of the line into own class (see commit above).
Hence my attacking the argument parsing. Looks like you guys are heading towards an automatic way of getting this. |
Ah, so I got back into this and kept going and now have something that works (see PR). Not sure it will be what you were after. Happy to take feedback... or if you want to use some of the code in a different manner be my guest :) |
@marcosnz, IMHO, getting that -prerelease switch is key to making this thing more usable. In particular, this is very valuable when developing and testing our own add-ins, as it allows us to follow semantic versioning in development (using prerelease SemVer suffixes for works-in-progress). I think the I'd personally prefer locating the appropriate package at runtime, based on the currently targeted framework, as described above. That being said, it's just an idea I had, and it's obviously wide-open for debate. |
I'm going to be contrarian here and say that cake should take a dependency on NuGet. We already take a soft dependency on it, it's the defacto package manager for C#, and it's basically the defacto package manager for delivering Cake addins as well. We need Cake itself to be smart enough to reason about how to install packages, and where to grab references from. Half done solutions where we're piping arguments to nuget aren't good enough. |
@RichiCoder1, I tend to agree with you, with one caveat -- which version of NuGet.Core (assuming that's the lib you're talking about) do you take a dependency on? |
Cake already have a dependency on NuGet.Core. The core library should not have one. We could define a contract in Cake.Core that wraps functionality around NuGet.Core and implement the contract in Cake. |
Agreed and that is the fallback if none is selected in my PR. However, the package I am targeting is MSBuild.Extension.Tasks. It has a structure like I am running from on .net 4.5. Trying to find that I need tools\net40 would be tricky for cake but trivial for me. Hence my switch (now named -VersionFolder). Having said all that, I tend to agree that taking a dependency on NuGet may be the right way to go but can think of 2 things to consider:
Also, my PR is a (fully backwards compatible) working solution which means I can target the package I want in the manner I want (and greatly eases the friction of an addin I have written). So I would ask that it is considered for inclusion for now until a "proper" solution is created. |
@jrnail23 We should target the version that makes the most sense when interoping with Nuget feeds. If we really want the ability to potentially target a newer (or older) nuget, we could make the resolution library external and then have Cake import it so you can swap out your own. Use the interface that @patriksvensson mentioned and MEF and barring any major changes you're good. It basically needs to do two things: Install this package to this folder with this info (version, prerelease, etc...), and tell me what dlls I can/should reference for that package. |
@RichiCoder1, sounds like good ol' fashioned Dependency Inversion principle, via Separated Interface Pattern, FTW! 😄 |
I did some experimenting with using external nuget packages through the
#addin
directive, and I found that it only works when there is only a single dll file for each dll name in the referenced nupkg file.Before I get into detail here, I should say that I assume what I'm trying to do here isn't really what the developer of Cake's
#addin
directive intended when writing it (there's really no documentation that I could find to explain the intended usage for the various ways to reference such dependencies).I'm sure my initial explanation was about as clear as mud, so here's an example:
Let's say I want to use Polly in my Cake script, so I do this:
Ok, so I run that, and it works.
However, if I want to use Polly as an addin like this (because I don't want to have to specify the path to Polly.dll for various reasons -- among them being that I might like to specify the tools directory at runtime), I'm out of luck:
Results in this:
Okay, so apparently if I want to (and I don't really want to), I can use Polly-Signed instead to resolve this, although when I did, I got this:
Since I never really wanted to use Polly-Signed anyway, let's ignore this -- I just wanted to include that for your info.
As you can see from the output above, the Polly nupkg has the following file structure:
Cake's AddInDirectiveProcessor recursively finds all DLLs (not named Cake.Core.dll) under
/Addins/Polly/
and loads them all, regardless of name or target version, causing the above error (Error: error CS1704: An assembly with the same simple name 'Polly' has already been imported.
).So that seems to be the heart of the issue -- that Cake doesn't use a particular target version to load assemblies from nuget. Further research suggested that because it's being added outside the context of Visual Studio, we don't have the context to decide which version is appropriate, but I managed to figure out how this can be remedied.
In NuGet.Core, there's a
NuGet.VersionUtility
class that can be used to match those target-version-specific folder names to the current runtime framework version, like this:Of course the downside of this is that it would require taking a dependency on NuGet.Core (unless simply duplicating NuGet's implementation of
GetShortFrameworkName()
is preferable).So.... any thoughts? Am I barking up the wrong tree entirely?
The text was updated successfully, but these errors were encountered: