Trying to add non-.NET libraries to NuGet package - c#

I have a .NET DLL that is using non-.NET DLLs. I'm trying to create a NuGet package out of this, but I don't seem to be penetrating the magic behind this. I read the NuGet reference about the <files> and <references> but that didn't really work out for me - VS kept on refusing to install the package on the grounds that "...Failed to add reference to NonNETLib1". I tried a different variant where non-.NET libs were bundled together with the .NET library in net40 folder and the nusepc file having no <files> section, but in this case even though the package installed OK, the code threw an exception in runtime, because it could not find the DLLs.
Here's the .nuspec I have:
<?xml version="1.0"?>
<package >
<metadata>
<id>PackageName</id>
<version>1.0.3</version>
<authors>me</authors>
<owners>some guys</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>description</description>
<references>
<reference file="NonNETLib1.dll" />
<reference file="NonNETLib2.dll" />
<reference file="NonNETLib3.dll" />
</references>
</metadata>
<files>
<file src="lib\NonNETLib1.dll" />
<file src="lib\NonNETLib2.dll" />
<file src="lib\NonNETLib3.dll" />
</files>
</package>
The folder structure is as follows:
[lib]
\- NonNETLib1.dll
\- NonNETLib2.dll
\- NonNETLib3.dll
\- [net40]
\- Net40Lib.dll
What am I missing here?
P.S. I know this is somewhat similar to this question, but the accepted answer to it didn't help much.

even though the package installed OK, the code threw an exception in runtime, because it could not find the DLLs
When you add a reference to a .Net DLL in your project, it's automatically copied to the output folder. But since your DLL is not .Net, you can't add a reference to it directly in the project, so it's not copied at all.
I would add a pre-build or post-build step in your project, like xcopy /y /f "$(ProjectDir)..\packages\NonNet.dll" "$(TargetDir)" but I suspect there is a better and cleaner way to do it.
In any case, it's not a nuget-related problem, but a more general Visual Studio project problem.
Update
It seems the consensus is to add the native DLL as an existing item (as a link) to the project, set it to content/copy if newer: Are there any better ways to copy a native dll to the bin folder?

There is a powershell-based toolset for packaging native code for NuGet consumption. It primarily deals with issues around integrating into native projects but it should provide the tooling you need to plug native dlls into .NET projects as well.
http://coapp.org/news/2013-04-26-Announcing-CoApp-Tools-For-NuGet.html

I had exactly the same problem and i found a good solution for me with nuget 3.3. This way only the .net-lib will be referenced to the project and the non-.Net lib is only copied to bin folder.
<references>
<reference file="Net.dll">
<references>
<files>
<file src="..\bin\NonNet.dll" target="lib/452">
<file src="..\bin\Net.dll" target="lib/452">
<files>

Related

How to inherit referenced assemblies in NuGet package

Simple question. I have a NuGet package project. This project references other class library projects (they are not NuGet Packages). I would like my NuGet package to load its references DLL's into the project installing the package. Is this possible, or do all my referenced class libraries need to be NuGet packages in order to specify them as dependencies?
TIA
When performing a nuget pack command, you can specify the option IncludeReferencedProjects.
From the docs:
Indicates that the built package should include referenced projects either as dependencies or as part of the package. If a referenced project has a corresponding .nuspec file that has the same name as the project, then that referenced project is added as a dependency. Otherwise, the referenced project is added as part of the package.
You can add your referenced dlls as files to nuspec and can set immediately source path file and target path file inside a nuget package. Next you should add references to this files in nuspec. It looks like this (I removed other metadatas):
.nuspec
<?xml version="1.0" encoding="utf-8"?>
<package>
<metadata>
...
<references>
<reference file="First.dll" />
<reference file="Second.dll" />
</references>
</metadata>
<files>
<file src="SomePath\First.dll" target="lib\First.dll" />
<file src="SomePath\Second.dll" target="lib\Second.dll" />
</files>
</package>

NuGet: package with source code that can be referenced as library

Is there any possibility to create a NuGet package containing the source code that can be referenced as library?
When I use the .nuspec for packing the created .nupkg contains the source code but cannot be referenced. I have already tried out to add a library node within the .nuspec as some suggested on SO but the resulting .nuspec does not match the standard and thus cannot be created.
When using .csproj for packing the .nupkg does only contain the .dll. It can be referenced but cannot be debugged because it does not contain any source code.
How could I achieve both? A referanceable library that contains source code.
In advance thank you for your time.
Here's a .nuspec file I use to package sources from multiple directories that get used as a library in other projects:
<?xml version="1.0"?>
<package >
<metadata>
<id>Your.Package</id>
<version>1.0.14</version>
<authors>me</authors>
<owners>me</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Class library.</description>
<releaseNotes>Initial release.</releaseNotes>
<copyright>Copyright 2017</copyright>
<tags>some tags</tags>
</metadata>
<files>
<file src="*.cs" target="content/App_Packages/<YourPackage>.Sources" />
<file src="Configuration/*.cs" target="content/App_Packages/<YourPackage>.Sources" />
</files>
</package>
Just change the "file" tags to reference the files you're trying to include.
When you're ready to create the .nupkg file, cd to the directory containing your .nuspec file and run:
nuget pack .nuspec
There's now the csproj tag EmbedAllSources. What that does is embed your source code into your NuGet package.
Usage is like this:
<EmbedAllSources>True</EmbedAllSources>
Embedding the source code will allow people to, for example, navigate to your method definitions and see the code just the way you've written it, as opposed to, not being able to navigate to definitions, at all, or rely on decompiled code.
Adding the debug symbols to the above will allow your users to put breakpoints in your code and step through it during debugging.
If that is what you want, add this to your csproj:
<DebugType>Embedded</DebugType>
<EmbedAllSources>True</EmbedAllSources>

Custom NuGet Package Install Output Window Messages

When I install my custom NuGet package it works, but the output window in VS shows messages like it tried to add the files twice and they already existed. Output is further down in this post.
I have a NuGet private repository on a server here that is working to host our gallery. Installs and uninstalls are working, even though the output window shows the messages below. I am curious about the <files> tag in the spec file and if there's a different way I need to do this. I have tried multiple ways based on the documentation. My version is up to date installed from the NuGet site.
From the site: The latest version of the nuget.exe command-line tool is always available from http://nuget.org/nuget.exe
Specifying files to include in the package
The output window shows things like this on Install-Package CustomNuGet:
The item /Plugins/CustomNuGet/CSS/custom.css already exists.
The item /Plugins/CustomNuGet/Scripts/custom.js already exists.
The item /Plugins/CustomNuGet/Views/custom.cshtml already exists.
The output window shows things like this on Uninstall-Package CustomNuGet:
The item /Plugins/CustomNuGet/CSS/custom.css could not be found in your workspace.
The item /Plugins/CustomNuGet/Scripts/custom.js could not be found in your workspace.
The item /Plugins/CustomNuGet/Views/custom.cshtml could not be found in your workspace.
I have created a custom Nuget package using the command line tools. The folder looks like this:
/CustomNuGet
CustomNuGet.nuspec
CustomNuGet.0.1.1.nupkg
/content
/lib
CustomNuGet.dll
/Plugins
/Views
custom.cshtml
/Scripts
custom.js
/CSS
custom.css
The spec file was created using: nuget spec and the package nuget pack in the root CustomeNuGet folder per the documentation. Here is the spec file:
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>CustomNuGet</id>
<version>0.1.1</version>
<authors>CustomNuGet</authors>
<owners>CustomNuGet</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>CustomNuGet</description>
<tags>CustomNuGet</tags>
<references>
<reference file="CustomNuGet.dll" />
</references>
<dependencies>
<dependency id="WebActivatorEx" version="2.0.0" />
</dependencies>
</metadata>
<files>
<file src="content\lib\CustomNuGet.dll" target="lib"/>
<file src="content\Plugins\**" target="content\Plugins" />
</files>
</package>
I didn't see any posts about this exact issue so hopefully others have had this happen and it's only a setting I missed.
This can happen if you deleted .dll reference manually instead of using uninstall-package to remove it through console. Check packages.config file, package you're trying to install is probably still listed there. You will have to delete it from that config file and save changes. After you did that, try installing package again and it should work.

NuGet: Don't include reference from package

Summary
When I package a library using NuGet and reference it in another project the referring project will pull additonal files in to the build directory.
Working Case
Project: ReferenceLibrary
Output: ReferenceLibrary.dll
Project: DerivedLibrary
Output: DerivedLibrary.dll
References: ReferenceLibrary (Copy Local = False)
Project: ConsoleApplication
Output: ConsoleApplication.exe
References: DerivedLibrary
Edit: The reference library is not copied because it is resolved at runtime. There's several versions depending on the target. The reference in derive proj. is so I can code against it.
If I build this then only DerivedLibrary.dll is copied to the ConsoleApplication build folder (i.e. bin/Release).
Non-working Case
Project: ConsoleApplication
Output: ConsoleApplication.exe
Package: DerivedLibrary.nupkg (depends on ReferenceLibrary.nupkg)
A project reference is added to DerivedLibray.dll. Both DerivedLibrary.dll and the ReferenceLibrary.dll are copied from their packages.
I can see it being copied in the MSBUILD log.
_CopyFilesMarkedCopyLocal:
Copying file from "c:\...\ReferenceLibrary.dll" to "bin\Debug\ReferenceLibrary.dll"
Even though it's not referenced in the .csproj anywhere.
I can't tell if this is a NuGet problem (due to how it unpacks things) or a Visual Studio project (how it copies referenced assemblies and encodes the requirements in other assemblies).
A possible solution I've found is to use a post build target to delete the offending references.
In the derived library add a DerivedLibrary.targets file.
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="RemoveUnwantedReferences" AfterTargets="Build">
<Message Text="Removing unwanted references"/>
<Delete Files="$(OutputPath)ReferenceLibrary.dll"/>
</Target>
</Project>
Then in the .nuspec include it
<package>
...
<files>
<file src="Targets/DerivedLibrary.targets" target="/build/DerivedLibrary.targets" />
</files>
</package>
Then when someone installs the package the post build hook will be added. When they build the files that are copied will then be deleted automatically.

Create nuget package for a solution with multiple projects

We are currently building a solution with several projects.
We have something like this:
- Common
- Logging
- Logging.NLog
- Threading
So Logging.NLog is dependant on Logging, Logging on Common...etc.
When we pack Logging.NLog I would like nuget to discover the Loggin and Common dependecies.
At the moment, I created a package with Common, then in Logging I installed the package Common with
install-package Common
But whenever I do a modification to Common, I have to update the package and they are created by our continous integration systeme (Hudson), so it is pretty annoying when we are developing.
I would like to simply have a Project Reference (Add References -> Project...) and the nuget discover the depencies anyway.
Is there a way to achieve it?
There is a planned feature targeting this exact scenario.
This is how it will apparently look like:
> nuget.exe pack proj.csproj -IncludeReferencedProjects
It has apparently been implemented mere days ago, but there are bugs still being ironed out.
The feature, as it currently stands, allows:
packaging several projects' artifacts into a single nuget package (by walking project references recursively),
OR
creating nuget package references to those projects's associated packages, if the referenced projects have accompanying .nuspec files.
The feature request dates back all the way to 1.5, but it kept slipping. Recently though, it gathered enough mass (requests) to be scheduled for release in Nuget 2.3.
The release plan pegs version 2.3 for "End of April, 2013" so stay tuned.
(Presently, the latest Nuget version is 2.2.1).
There is currently no way to do exactly what you ask, but the following will help you streamline your updates.
It sounds like you need to add nuspec files to your solution. Something like the following three files. Note the dependencies in the second two. These refer to the same dll version as common through [$version$]. This means that when you run the following command, it updates all three because the square brackets on the dependencies require a specific version of the dependent packages.
PM> update-package common
In Hudson, you will need to execute these nuspec files using nuget pack command (see Nuget command reference) and include the resulting packages in your artifacts, AND deploy them to your local nuget server. I will leave that over to you.
The other thing you would need to do is ensure that all of your assemblies get the same version for the same build. Again, Hudson can take care of this or you could use a common AssemblyInfo file.
Common.nuspec
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<version>$version$</version>
<authors>Charles Ouellet</authors>
<owners />
<iconUrl>http://domain/Content/images/LOGO_32x32.png</iconUrl>
<id>Common</id>
<title>Common</title>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>full description here</description>
</metadata>
<files>
<file src="..\Common\bin\Release\Common.dll" target="lib\net40" />
<file src="..\Common\bin\Release\Common.pdb" target="lib\net40" />
</files>
</package>
Logging.nuspec
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<version>$version$</version>
<authors>Charles Ouellet</authors>
<owners />
<iconUrl>http://domain/Content/images/LOGO_32x32.png</iconUrl>
<id>Logging</id>
<title>Logging</title>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>full description here</description>
<dependencies>
<dependency id="Common" version="[$version$]" />
</dependencies>
</metadata>
<files>
<file src="..\Logging\bin\Release\Logging.dll" target="lib\net40" />
<file src="..\Logging\bin\Release\Logging.pdb" target="lib\net40" />
</files>
</package>
Logging.NLog
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<version>$version$</version>
<authors>Charles Ouellet</authors>
<owners />
<iconUrl>http://domain/Content/images/LOGO_32x32.png</iconUrl>
<id>Logging.NLog</id>
<title>Logging.NLog</title>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>full description here</description>
<dependencies>
<dependency id="Logging" version="[$version$]" />
</dependencies>
</metadata>
<files>
<file src="..\Logging.NLog\bin\Release\Logging.NLog.dll" target="lib\net40" />
<file src="..\Logging.NLog\bin\Release\Logging.NLog.pdb" target="lib\net40" />
</files>
</package>
I think Charles means he wants NuGet to automatically resolve project references into package dependencies if said referenced projects also are used to construct NuGet packages, right?
Example:
Logging is set up to generate a NuGet package
Logging.Nlog is set up to generate a NuGet package
Logging.Nlog has a project reference to Logging.
The generated Logging.Nlog package should get a dependency on the generated Logging package.
This is something I had been looking for myself as well, but sadly I found that it is currently not supported. There is a work item on it, scheduled for NuGet 1.7, but there isn't even a design on how to handle this yet.
This thread has a good suggestion: NuGet and multiple solutions
Basically, break out the common components to their own Solution, with their own release lifecycle.
I managed this achieve it like this:
<ProjectReference Include="MyProject2.csproj" PrivateAssets="All" />
Add PrivateAssets="All" in MyProject.csproj for each project.

Categories