Create nuget package for a solution with multiple projects - c#

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.

Related

Nuget package creation - Class library that targets .NET framework 4.6.1 can not target correct framework

I created a class library that targets .net framework 4.6.1 (so pretty much a blank canvas, with a single method to return a string, just for testing purposes). I want to make this into a nuget package. I'm following this article https://learn.microsoft.com/en-us/nuget/quickstart/create-and-publish-a-package-using-visual-studio-net-framework , but when I get to "nuget pack" I get the following warning:
"WARNING: NU5128: Some target frameworks declared in the dependencies group of the nuspec and the lib/ref folder do not have exact matches in the other location. Consult the list of actions below:
- Add a dependency group for .NETFramework4.6.1 to the nuspec"
I tried adding the dependency group to the .nuspec file:
<?xml version="1.0"?>
<package>
<metadata>
<id>$id$</id>
<version>$version$</version>
<title>$title$</title>
<authors>Author</authors>
<owners>$author$</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>H</description>
<copyright>Copyright 2019</copyright>
<tags>blah</tags>
<dependencies>
<group targetFramework=".NETFramework4.6.1" />
</dependencies>
</metadata>
</package>
and I also tried:
<?xml version="1.0"?>
<package>
<metadata>
<id>$id$</id>
<version>$version$</version>
<title>$title$</title>
<authors>Author</authors>
<owners>$author$</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>H</description>
<copyright>Copyright 2019</copyright>
<tags>blah</tags>
<dependencies>
<group targetFramework="net461" />
</dependencies>
</metadata>
</package>
I still get same error.
I tried using older versions of nuget, where the warning message isn't shown, but the same problem persists (If I try to add via the package manager, it says it has no dependencies).
WARNING: NU5128: Some target frameworks declared in the dependencies
group of the nuspec and the lib/ref folder do not have exact matches
in the other location. Consult the list of actions below.
This is an open issue in Github/Nuget, see #8713. I can reproduce same issue in my VS2017 with Nuget V5.3, and this issue goes away if I use Nuget V5.2 or earlier. For this situation, I'm afraid you have to use earlier versions of Nuget.exe until the team releases the fix.
If I try to add via the package manager, it says it has no
dependencies
1.If it displays no package dependencies though your package project depends on some nuget packages, please check if you're using packageReference to manage nuget in your current project. For now, nuget pack command doesn't work well for .net framework projects with packageReference or new SDK format projects.
You can check details from Leo's answer to resolve this issue.
2.If the no dependencies you mean is that when one project consumes your package, it doesn't display which framework your project targets like this:
(We can see your package depends on Newtonsoft.Json but we can't find which framework it targets(net461).)
For this, we need to use command like nuget pack xx.nuspec to add the dependencies+group into package when packing. Then we can see both targets framework and dependent packages like this:
Hope all above helps and if I misunderstand anything, feel free to correct me :)

Visual Studio Nuget Manager reports "unsupported" for the .NETStandard2.0 section of a custom Nuget

We have a .NetStandard2.0 project which is meant to be packaged into a nuget following the technique explained here:
https://stackoverflow.com/a/45004898/863651
with a nuspec file which looks like so:
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<!-- https://stackoverflow.com/a/45004898/863651 we had to resort to employing a seperate nuspec -->
<!-- file because thats the canonical way to include more than one dlls into the resulting nuget -->
<metadata>
<id>$id$</id>
<tags>$tags$</tags>
<owners>$owners$</owners>
<version>$version$</version>
<authors>$authors$</authors>
<description>$description$</description>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<dependencies>
<group targetFramework=".NETFramework4.5">
</group>
<group targetFramework=".NETStandard2.0">
<dependency id="Newtonsoft.Json" version="12.0.1" exclude="Build,Analyzers" />
</group>
</dependencies>
<frameworkAssemblies>
<frameworkAssembly assemblyName="System" targetFramework=".NETFramework4.5" />
<frameworkAssembly assemblyName="Microsoft.CSharp" targetFramework=".NETFramework4.5" />
</frameworkAssemblies>
</metadata>
<files>
<file src="bin\$config$\netstandard2.0\*.dll;bin\$config$\netstandard2.0\*.pdb;" target="lib\netstandard2.0\" />
</files>
</package>
As you can see there is a section targeting .NetStandard2.0. The nuget package is generated by our build server using the following msbuild scriptlet:
<MSBuild Projects="C:\path\to\foo.csproj" Targets="Clean;foo;" Properties="SkipRestoringNugetPackages=true;Configuration=Release;Platform=AnyCPU;" ToolsVersion="15.0" />
The resulting nuget package is getting pushed into a nuget server with the following specs:
NuGet.Server v2.10.3.0
When reviewing the package through Visual Studio 2017 Nuget Package Manager of a .Net4.8 project the following is displayed on the sidebar:
Why does it say "Unsupported" for the .NetStandard2.0 section? Other packages don't display something like that and I can't find see any typos in the xml of the nuspec.
I've just found your issue could be related to the version of Nuget.Server package since you don't use nuget pack command. With same nuget package, when I use Nuget.server 2.10.3, it displays unsupported, After I update the Nuget.server to 3.4.1, all works well now. Let me know if it helps:)
I made a package locally, when I try to consume it in VS all works well.
After I deploy same package to nuget server 2.10.3, it displays unsupported!
So if the issue occurs when you try to fetch the package from the server after you deploy to it. I think it's because the Nuget.Server package you use is too old! Updating the Nuget.Server package can help resolve this issue.

dotnet pack command along with nuspec file not including project's DLL

I have a .NET Standard 2.0 project called ProjectName.Logging with a ProjectName.Logging.nuspec file.
This file file is referenced in the .csproj of my project
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
<NuspecFile>ProjectName.Logging.nuspec</NuspecFile>
</PropertyGroup>
Here is my .nuspec
<?xml version="1.0"?>
<package >
<metadata>
<id>ProjectName.Logging</id>
<version>1.2.1</version>
<authors>Jérôme MEVEL</authors>
<description>Just a logging component</description>
<dependencies>
<dependency id="Dapper" version="1.50.5" />
<dependency id="Another.Project" version="1.1.1" />
<dependency id="Microsoft.Extensions.DependencyInjection" version="2.1.1" />
<dependency id="Microsoft.Extensions.Logging" version="2.1.1" />
<dependency id="Microsoft.Extensions.Logging.Abstractions" version="2.1.1" />
<dependency id="NLog" version="4.5.8" />
<dependency id="NLog.Extensions.Logging" version="1.2.1" />
<dependency id="NLog.Web.AspNetCore" version="4.6.0" />
<dependency id="System.Data.SqlClient" version="4.5.1" />
</dependencies>
</metadata>
<files>
<file src="bin\Release\netstandard2.0\ProjectName.Logging.dll" target="lib/netstandard2.0/ESHCloud.Logging.dll" />
<file src="ProjectName.Logging.targets" target="build/ProjectName.Logging.targets" />
<file src="NLog/Nlog.config" target="content/Nlog.config" />
</files>
</package>
As you can see I manually include the ProjectName.Logging.dll file and I even have to include Release because the usage of the MsBuild variable $(Configuration) doesn't work in my .nuspec file.
I pack the project by executing this command in my project's directory
dotnet pack --output C:/Nuget --force
and if I remove the <files> element from my .nuspec when I run the dotnet pack command, my generated Nuget package is completely empty.
On the other hand if I run the dotnet pack command without a .nuspec file, absolutely everything in my project is included in the Nuget package.
So what's the deal with the dotnet pack command? I don't understand what am I doing wrong.
How to include my project's DLL in the Nuget package without having to specify the configuration (Debug or Release)?
One last thing: I don't want to use the nuget pack command.
I played enough with Nuget on our VSTS servers (recently renamed Azure DevOps) and I don't have full control over these build servers (my manager has but he seems too busy to care about it).
So to sum up, nuget pack is not an option for me. I want to use dotnet pack along with a .nuspec file.
Thank you
To add your DLL without specifying the configuration use a glob pattern:
<file src="runtimes\**" target="runtimes/"/>
If you use nuget.exe you could use a replacement token:
<file src="bin\$configuration$\netstandard2.0\*.dll" target="lib\netstandard2.0\"/>
If you really need to use the nuspec file you're better off using nuget.exe. If you don't want to use nuget.exe drop the nuspec. I've done a fair amount of work with dotnet and nupkgs the last few weeks and mixing nuspec with project files is fiddly.
You can put the majority of the nupkg meta-data directly in the csproj:
<PropertyGroup>
<PackageId>Subor.nng.NETCore</PackageId>
<PackageVersion>0.0.2</PackageVersion>
<Authors>Subor</Authors>
...
</PropertyGroup>
This is the recommended approach when using the dotnet CLI. Likewise for msbuild with the PackageReference format.
Here's an example of a project I've been working on. dotnet pack builds a package bin/Debug/ and dotnet pack --configuration Release builds this nuget.org package.
Everything in the project should not get copied into the nupkg. In Visual Studio check the Properties of the files and make sure everything isn't flagged as "Content", etc.. Also check the project files to see if files are getting added that shouldn't be. Look for (miss-)use of <PackagePath> and <IsPackable>.
Without knowing the particulars of your project, I'll mention trying some of the arguments to dotnet pack.

nuget package not installing dependencies

I've created a nuget package which has 2 dependencies.
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata>
<id>ConsoleApp2</id>
<version>1.0.0</version>
<title>ConsoleApp2</title>
<authors>XX</authors>
<owners>XX</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Description</description>
<copyright>Copyright © 2018</copyright>
<dependencies>
<dependency id="AutoMapper" version="6.2.2" />
<dependency id="NHibernate" version="4.0.4.4000" />
</dependencies>
</metadata>
</package>
I would like install this nuget package to other project but it is't download and install AutoMapper or NHibernate and i don't have any reference.
from csproj
To create nuget package I'm using nuget.exe version 4.6.2 but other version also don't work.
However if I use method with app.config and package.config it's works well, but I need use first method.
from package.config:
nuget package not installing dependencies
Probably you have select the Ignore Dependencies for Dependency behavior in the options Install and Update options on the nuget package manager UI. To check it, please extend the options button:
If yes, please set it to the default value Lowest.

Trying to add non-.NET libraries to NuGet package

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>

Categories