Nuget packages with both debug and release - visual-studio

In our work we have one team that develops libraries and other teams that develop projects using those libraries.
The libraries team has much more experience than the projects one.
We created this environment here:
All the libraries are in nuget packages, in a nuget server, in azure devops.
We have source link in Azure devops.
But when we deploy the libraries, we have to choose between debug or release, and we have the pros and cons of each.
My ideal nuget package would have both debug and release, and would select the same as the project running it.
this way I would have better debugging for the projects team, and maximum performance on the releases.
I talked with https://twitter.com/rrelyea and he gave some ideas, but they seem to complicated for the other teams to implement, or complex do manage.
Like 2 nuget servers, one for debug, and one for release, and configure those different ones on the machines and on the build server.
Or 2 nuget packages, with .debug and .release on the name of the package, and configure the project to load a diffent one on each mode.
The real problem is that I need a guarantee that all the packages have the same id and version on both servers.
Isn't there a more automatic way to pack the packages?
Simple if it's debug use the debug, if it's the release use the release.
By the way, how much performance difference is between debug and release in this case?

Isn't there a more automatic way to pack the packages?
Actually, nuget package does not have a mechanism to let a project to reference the debug output files or release output files based on the configuration of the main project.
And when you pack a project, it does not have a function to include the Debug or Release output files at the same time and then let the main project-------when using Debug, reference the Debug content of the nuget, when using Release, reference the Release content of the nuget.
So far, nuget is not yet so flexible, and it can't do the functions you mentioned above.
=====================
As a suggestion, you should create two nuget packages(Debug or Release) of the project and then manually install the corresponding package as required.
You can create a net standard library project, and add these in xxx.csproj file:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace>PackageName</RootNamespace>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<PackageId>PackageName_Debug</PackageId> //name the nuget package which contains Debug key name
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<PackageId>PackageName_Release</PackageId> //name the nuget package which contains Debug key name
</PropertyGroup>
<PropertyGroup>
<Version>1.0.0</Version>
<Authors>your_name</Authors>
<Company>your_company</Company>
</PropertyGroup>
<ItemGroup Condition="'$(Configuration)'=='Debug'">
<None Include="$(ProjectDir)$(OutputPath)$(AssemblyName).pdb" Pack="true" PackagePath="lib\$(TargetFramework)"></None>
<Compile Update="Class1.cs" Pack="true" PackagePath="Resource">
</Compile>
...// add any source files
</ItemGroup>
</Project>
And you can switch the Configuration to Debug or Release to build your project to generate the nupkg file under output folder.
Note:
1) To generate a debug nuget package, you should contains the pdb file and source files into the nuget package and then you can debug it in the main project. There is a similar issue which contains the detailed steps about it.
2) You can define the package_id directly in the new sdk format project. And you should add Debug or Release to distinguish between them.
More info about packing new sdk format project, you can refer to this document.
==============================
In addition, if you still want the initial feature(contain Debug or Release in the same package), you could suggest a feature on our User Voice Forum and I hope the Team will consider you idea carefully and give a satisfactory reply.

Maybe... just add .pdb files from debug folder to Lib using Nuget Explorer

Related

How do you get NuGet package restore to work on locally deployed packages stored in VSIX targeting Visual Studio 2019?

I am aware there are multiple questions on this topic already, but they all seem outdated. To clarify, I am using the "new" VSIX manifest format, and trying to follow the official instructions here: https://learn.microsoft.com/en-us/nuget/visual-studio-extensibility/visual-studio-templates
I have one project template and a couple of item templates that go with it. They all depend on deploying a NuGet package that should come bundled locally with the VSIX. I have examined the resulting VSIX file and all the files seem to be in the right place:
The project template has the required XML for declaring which packages to install:
<WizardExtension>
<Assembly>NuGet.VisualStudio.Interop, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</Assembly>
<FullClassName>NuGet.VisualStudio.TemplateWizard</FullClassName>
</WizardExtension>
<WizardData>
<packages repository="extension" repositoryId="VsixID.etc.etc">
<package id="Rx-Linq" version="2.2.5" />
</packages>
</WizardData>
The repositoryID matches the ID attribute in the .vsixmanifest file.
There is an individual Asset entry for each package, with the form:
<Asset Type="Rx-Linq.2.2.5.nupkg" d:Source="File" Path="Packages\Rx-Linq.2.2.5.nupkg" d:VsixSubPath="Packages" />
I have removed all packages.config and all the package references from the .csproj file installed by the VSIX (and even from the VSIX project itself just for good measure).
I have inspected the output VSIX and there is indeed a Packages folder in the VSIX containing all the .nupkg files. This folder is indeed unpacked and copied into the Visual Studio Extensions folder.
Despite all this, when I create a new project with the template, VS displays an error message saying: Failed to restore package from C:\users\<pathtoextensions>\Packages.
The thing is, the .nupkg files are actually present in the exact folder that the error message refers to.
I have been searching this for days and I can't seem to find any reference to best practices that actually work. It seems like these VSIX manifests are geared towards the legacy packages.config way of doing things, and there are discussions about how to extend them to use PackageReference instead.
Can anyone give any advice at all at how we are supposed to proceed going forward? Are packages not supposed to be deployed with the VSIX anymore? Are we supposed to just fill in the project with PackageReference entries and just let the user resolve them manually?
I feel like I am missing something fundamental here and any insight would be extremely valuable.
Update: I have also opened an issue on the NuGet github repository, as this is clearly a problem with the PackageRestore feature when restoring packages stored in a VSIX installer. Everything else mentioned in this question is working as intended and expected, except the package restore.
How do you actually include NuGet packages in Visual Studio Project
Templates VSIX targeting Visual Studio 2019?
Actually, there is no way to specify in a VS project template project that nuget packages can be used both using packages.config and PackageReference. Only two project templates of nuget management types can be created separately.
I have an easy way and since you have some issues with PackageReference format, you can try this funtion:
PackageReference
1) add these reference node in projecttemplate.csporj file:
<ItemGroup>
<PackageReference Include="Rx-Linq">
<Version>2.2.5</Version>
</PackageReference>
</ItemGroup>
2) When you create a project by this project template, please check these two options and VS will automatically read xxx.csproj and then recover the corresponding nuget package based on the information in it during build process.
Note: also make sure that the nuget url is checked and can be access under Package Source.
packages.config
In additon, for packages.config, you can just create a file named packages.config and then add your nuget info into it:
1)
2) add these into projecttemplate.csproj file:
<ItemGroup>
<Content Include="packages.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<Reference Include="Rx-Linq, Version=2.2.5, Culture=neutral, PublicKeyToken=eb42632606e9261f, processorArchitecture=MSIL">
<HintPath>..\packages\Rx-Linq.2.2.5\lib\net472\xxxxxxx.dll</HintPath>
</Reference>
</ItemGroup>
Note: if this nuget package has dependencies, you should also add them(above steps) into packages.config and xxxx.csproj file. This funcution is a little more complicated than yours but it works. So, I recommend that you use PackageReference format.
More info you can refer to this similar issue.

Installing SQLite NuGet Package installs the package but the reference is not available. VS2019 Community

I"m writing a c# application using SQLite and I need the the SQLite Reference. Using NuGet I locate the package and the output window shows a successful install.
Looking at the packages config file in the solution explorer it shows the version installed.
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="SQLite" version="3.13.0" targetFramework="net472" />
</packages>
However under the project References in the Solution explorer SQLite is not there.
I have watched tutorials online where the same process is done on other machines and all is ok, all of the references pop up after NuGet finishes the installation.
I'm using VS2019 and from what I understand there were some changes on how NuGet operates, however I had VS2015 and VS2017 Community and had the same issues. I'm really at a standing point as I have no idea how to get the reference to show up so I can access it in my program.
SQLite has no Assembly reference so adding it there is not an option.
I have seen posts about a NuGet config file and Package Config File as well as the possibility of the package being installed outside of the Solution Folder but I don't know where. I have looked in the output location of the solution and none of the references are located in the debug folder anywhere.
I feel the Dll's are being installed outside of the solution folder but I don't know where and how to get Visual Studio to get them to the proper location or reference there existing location correctly.
Rebuild and Restore NuGet Packages provide no solution.
Any help would be greatly appreciated.
Installing SQLite NuGet Package installs the package but the reference
is not available. VS2019 Community
I assume you have installed sqlite version 3.13.0 nuget package.If so, it is the behavior of this nuget package. This package is very special in that it is a transactional SQL database engine that implements self-contained, serverless, zero-configuration.
In simple terms, it is a configuration function package that operates on related data when the project is running, rather than a package that provides a reference class library for the project.
Let me explain it in more detail:
This is the content of the nuget package sqlite version 3.13.0
Note that each folder provides specific functionality for the installation project.
And the function of the lib folder is to add its content(xxxx.dlls) as reference to a new project. In a word, Only the Dlls in lib folder can be recognized by nuget and added into Reference.
You can refer to this link for more detailed info about the function of the folders.
Second, there is a file called SQLite.props in the Build folder. The file will do some configuration to your project during build process.
In it, you can see these files:
<Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\win7-x64\native\*">
<Link>x64\%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Visible>False</Visible>
</Content>
</ItemGroup>
<ItemGroup Condition=" (Exists('packages.config') Or Exists('packages.$(MSBuildProjectName).config')) And '$(Platform)' == 'x86'">
<Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\win7-x86\native\*">
<Link>%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Visible>False</Visible>
</Content>
</ItemGroup>
<ItemGroup Condition=" (Exists('packages.config') Or Exists('packages.$(MSBuildProjectName).config')) And '$(Platform)' == 'x64'">
<Content Include="$(MSBuildThisFileDirectory)..\..\runtimes\win7-x64\native\*">
<Link>%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Visible>False</Visible>
</Content>
So when you build your project, the SQLite.props file will be executed and they will provide services during build or at the runtime.
All of these indicates it is a package for specific execution functions rather than a nuget package for adding reference libraries to the project.
Suggestion
As a suggestion, you could install System.Data.SQLite in your project. And this nuget package provides the dlls which you want in Reference.
Hope it could help you.

Building NuGet packages from Visual Studio

I'm trying to share an internal company assembly via NuGet packages and a private source. This assembly targets .NET Framework 4.6.1. I want these NuGet packages to pack automatically from Visual Studio during the release build. I see I can add <GeneratePackageOnBuild>true</GeneratePackageOnBuild> to .csproj. I'm not sure if this is a .NET Standard-specific property but it seems to partially work. However, when I build, I get
error MSB4044: The "GetPackOutputItemsTask" task was not given a value for the required parameter "PackageOutputPath".
I've been trying to learn how to pass this parameter from within Visual Studio but I don't see a lot of documentation on parameters except when calling it from the command line manually. Is there an easy way to do this from within Visual Studio? Am I going about this wrong?
Edit: This is using a .NET Framework class library. I can run the pack command from the command line giving it the required parameters with /p:PackageOutputPath="path\here". It seems this might have been designed for .NET Core and Standard projects and Visual Studio might not handle packing .NET Framework projects.
To enable on-build packing in a "non SDK" project, using old .NET framework (eg:. 4.5.1) and visual studio 2019 without using custom Target. you need to do the following step:
add a first PropertyGroup tag on the csproj
add minimal tags Authors and PackageOutputPath
check that the same PropertyGroup has GeneratePackageOnBuild
Now the variables will be passed to the internally triggered msbuild -t:Pack command.
Here an example of working configuration, please make sure this will be the first <PropertyGroup> of the .csproj:
<PropertyGroup>
<Title>packageid</Title>
<Description>your description</Description>
<Version>1.1.1</Version>
<ReleaseNotes>New package system</ReleaseNotes>
<Authors>authors</Authors>
<Owners>owners</Owners>
<Copyright>your copyrights</Copyright>
<PackageOutputPath>bin\Package</PackageOutputPath>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
If you are looking for the references, here:
how to create a nuget package with msbuild
all possible tags to set on the csproj on the first PropertyGroup
Am I going about this wrong?
This GeneratePackageOnBuild property is not something for .net framework projects. Create a new .net Standard or .net Core class library project, right-click the project you'll see a Pack command(not available for .net framework).
If we click the button, VS will pack that assembly into a nuget package. And if someone doesn't want to click that button every time manually, go Project=>Properties=>Package we can see the Generate Nuget Packages on build checkbox. Enable it, and then the nuget package will be created after every build.
Actually, enabling that checkbox in VS will add statement <GeneratePackageOnBuild>true</GeneratePackageOnBuild> to xx.csproj, but the Pack button or Package tab in Project=>Properties are not available for .net framework projects.
So I'm afraid the answer is negative, you should't use that property for .net framework projects.(I tested the property in VS2017 and VS2019, it all just did nothing, can't reproduce the partial work mentioned in your question)
Is there an easy way to do this from within Visual Studio?
You need to use nuget pack command to do that as Lex Li says. And to do this in VS automatically, you can consider configuring that command in Post-Build-Event or using custom after-build target to run that command.
Since you want these NuGet packages to pack automatically from Visual Studio during the release build. You can try adding this script into your xx.csproj file:
<Target Name="CustomPack" AfterTargets="build" Condition="'$(Configuration)'=='Release'">
<Message Text="Custom Pack command starts ..." Importance="high"/>
<Exec Command="nuget pack $(MSBuildProjectFile) -Properties Configuration=Release"/>
</Target>
To run this script successfully, you need to download the nuget.exe and add the path of it to Environment Variables. Or use the full path like "C:\SomePath\Nuget.exe" pack ...
If the build in release mode succeeds, you'll see a xx.nupkg file in project folder.
In addition:
1.For more details about nuget pack command please see this document.
2.And don't forget to create a xx.nuspec file in project folder to avoid encountering warnings like NU5115(xxx was not specified). Similar issue see here.
I have a unique situation of needing to Register for Com Interop for and older application but also needing to pack for use in other internal applications and development in our company. I actually got this to work for a .NET Framework project from Visual Studio. Manually adding GeneratePackageOnBuild did attempt to make a package for me in VS2017. I was also able to add other .NET Core project properties such as <Authors>,<Description>, etc. I haven't tried VS2019 yet so maybe that is more restricted but I hope not.
The issue is VS2017 doesn't feed the pack target the output parameter (in this type of project). So then I tried to call pack in the After Build events but that causes a recursive loop because packing also attempts to build (dotnet and nuget both seem to call the msbuild pack target which calls a build). I then found an option -p:NoBuild=true for msbuild that allows me to call the pack target without msbuild actually building the project. Therefore I added the following command to <PostBuildEvent> and it works.
"$(MSBuildBinPath)\msbuild" -t:Pack "$(ProjectPath)" -p:PackageOutputPath="$(SolutionDir)..\packages" -p:NoBuild=true
Edit: I eventually used the following in my csproj. Calling nuget directly worked better because I had a nuspec file that was not getting merged or fully used when calling MSBuild directly.
<Target Name="CustomPack" AfterTargets="Build" Condition="'$(Configuration)'=='Release'">
<Message Text="Custom Pack command starts ..." Importance="high" />
<Exec Command=""nuget" pack "$(ProjectPath)" -OutputDirectory "$(ProjectDir)..\..\packages" -Prop Configuration=Release" />
</Target>
Add this to your proj file to use the pack target on .net framework projects.
<PackageReference Include="NuGet.Build.Tasks.Pack" Version="6.4.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
if you want to run from command line then use this:
msbuild -t:restore

Project reference VS NuGet

How should I reference to another project A from project B in the same solution?
What do I gain and what do I lose if I:
Add the reference to project A as a project reference.
Install the NuGet package of project A in project B.
Things that would bother me are build dependencies, versioning..?
Or does this totally destroy the purpose of a solution?
Project reference VS NuGet
Project reference or NuGet is a very common problem in our development process, we need to choose which one to use based on our actual situation.
For example, if the referenced project A is modified frequently during the development process, we recommend to use Project reference. Because if you use nuget, you have to rebuild the referenced project, recreate the nuget package, reinstall that nuget package to the project B, even you have to publish it to the server. This will bring a lot of unnecessary work and we often forget to update our nuget package after we modify the referenced project A. If you use the project reference, you will not have these problems. The modified referenced project A will be update automatically before we build the project B.
On the other hand, when we share our referenced project A out of solution, or share that project to others, nuget will be a better choice. It has more portability.
So the project reference will be recommended when you reference to another project A from project B in the same solution, the nuget is more appropriate when share the reference project out of solution or share project to others.
Besides, there is a Visual Studio extension NuGet Reference Switcher, which which automatically switches NuGet assembly references to project references and vice-versa.
Hope this helps.
With the first approach, you gain in simplicity, since you don't need to generate a new version of the ProjectA nuget package, every change you make in it (i.e. ProjectA.nupkg).
However, with the second approach, you gain in portability, since you can easily share the same nuget package with other projects / solutions.
Personally, I create nuget packages only for projects whose goal is to share with other solutions. (E.g. libs and frameworks).
Hope this helps you decide!
Nowadays with the new csproj format the you can use both at the same time (if you have both projects in the same solution).
In your example, you could reference project A from project B as a project reference. Then, if you want to release project A as a NuGet package you just need to add the following tag to it's csproj inside a PropertyGroup:
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
The plot twist: If you want to release project B as a NuGet Package too just add the GeneratePackageOnBuild target - MSBuild will set projectA.nupkg as a dependency in projectB.nupkg.
This way you can work internally with your projects while at the same time release them as packages to third parties or other teams.
You could use both: project references during development (faster), and package references during production.
In your .csproj project file:
<ItemGroup Condition="'$(Configuration)'=='Debug'">
<ProjectReference Include="../../../Library1/Library1.csproj" />
<ProjectReference Include="../../../Library2/Library2.csproj" />
</ItemGroup>
<ItemGroup Condition="'$(Configuration)'!='Debug'">
<PackageReference Include="Library1" Version="1.0.0" />
<PackageReference Include="Library2" Version="1.0.0" />
</ItemGroup>
In development: project compiled in debug mode, so the project reference will be used.
In production (CI server, docker container): project compiled in release mode, so the package reference will be used.

Reference nuget package project from another nuget package project in same solution

I am creating couple of .NET Standard 1.6 libraries that I want to publish as Nuget packages. They share a common libary that is a 3rd project in the same solution as the first two. The shared library has no value by itself, but I am assuming that if I want people to use both of these two libaries in the same project I should publish the shared library as a Nuget package as well. If I don't I am worried about multiple copies of the same shared library "colliding" or not properly warning when there are version mismatch issues.
Am I correct that the shared library needs to be a Nuget package as well? Is there a way to reference the shared library as Nuget package, but use is as if it was a project reference when developing / debugging the 2 main libraries in this solution? If I had to publish to Nuget.org and wait for the package be propagate through the Nuget.org system before using a changed version in a debug session that is REALLY going to slow down development. Note that these are .NET Standard projects. I found How to reference related projects in the same solution when Nuget packages are the required output but that doesn't seem to work with .NET Standard (getting errors during pack) and I am also not sure if .NET Standard not using nuspec files anymore also would cause a problem.
I am also not sure if .NET Standard not using nuspec files anymore also would cause a problem.
The .NET Standard still using .nuspec files, and using old school nuget pack and a .nuspec will resolve this issue.
As per document dotnet pack:
NuGet dependencies of the packed project are added to the .nuspec
file, so they're properly resolved when the package is installed.
Project-to-project references aren't packaged inside the project.
Currently, you must have a package per project if you have
project-to-project dependencies.
So, to include project-to-project references in NuGet packages, you need manually maintain a .nuspec file and add dependencies. You can refer to the Create .NET Standard packages with Visual Studio 2015 for detail info.
Besides, dasMulli has provided a simpler way to do this by involving adding and hooking up a custom target :
<Project>
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);IncludeP2PAssets</TargetsForTfmSpecificBuildOutput>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\testprivatelib\testprivatelib.csproj" PrivateAssets="All" />
</ItemGroup>
<Target Name="IncludeP2PAssets">
<ItemGroup>
<BuildOutputInPackage Include="$(OutputPath)\testprivatelib.dll" />
</ItemGroup>
</Target>
</Project>
The source code comes from: "donet pack" is not including project references

Resources