Nuget nuspec specify private dependency - nuget

Essentially this.
I have a NuGet package that has a dependency, it gets installed alongside the package.
However, NuGet adds both the package and recursive dependency package as a reference.
MsBuild has the <private> tag to distinguish one type of dependency from the other, has NuGet been changed in the last 5 years to support this?
I can't find any hints that it does.
Tx

If you are using the PackageReference format of referencing NuGet packages (instead of packages.config), it allows to control the assets consumed by the project and forwarded to dependencies per referenced package. This also allows to sepcify that all assets of the package are "private" which causes the reference to not be added to the packed nupkg:
<ItemGroup>
<PackageReference Include="My.BuildTimeOnly.Dependency"
Version="1.2.3"
PrivateAssets="all" />
</ItemGroup>

Related

Is there an official NuGet single-string package identifier?

For a dependency management system, I'm looking to see if there is an official single-string format identifying NuGet packages, which combines package name and version. I couldn't find any information on this, the official documentation always separating the package name from the version.
I am thinking for example of what is done for Maven, npm or pip:
Maven: groupId:artifactId:version
npm: <name>#<version>
pip: name==version
Thanks
No, there isn't anything like this in the NuGet world. The used package identifier strings mostly depend on the usage and tool, e. g.:
Package Manager → Install-Package My.Package -Version 19.5.3
.NET CLI → dotnet add package My.Package --version 19.5.3
packages.config → <package id="My.Package" version="19.5.3" />
<PackageReference> → <PackageReference Include="My.Package" Version="19.5.3" />

VSIX - Include PackageReference output groups

Currently we reference another project in the following way in order to include it completely in the VSIX package.
<ProjectReference Include="....csproj">
<Project>{8da36305-5468-465a-bf37-d87936b776d2}</Project>
<Name>ProjectName</Name>
<VSIXSubPath>SubDirectory</VSIXSubPath>
<IncludeOutputGroupsInVSIX>BuiltProjectOutputGroup%3bBuiltProjectOutputGroupDependencies%3bGetCopyToOutputDirectoryItems%3bSatelliteDllsProjectOutputGroup%3bDocumentationProjectOutputGroup%3b</IncludeOutputGroupsInVSIX>
<IncludeOutputGroupsInVSIXLocalOnly>DebugSymbolsProjectOutputGroup%3b</IncludeOutputGroupsInVSIXLocalOnly>
</ProjectReference>
This was working perfectly, until we have converted our 'old' Nuget references to the new PackageReference format. What we see is that the output files of the package references are not included in the VSIX package anymore. Is there an additional output group that we can include to solve this?
Can be solved by adding "ReferenceCopyLocalPathsOutputGroup" to IncludeOutputGroupsInVSIX.
Found it here: https://github.com/dotnet/msbuild/issues/3069
<ProjectReference Include="....csproj">
<Project>{8da36305-5468-465a-bf37-d87936b776d2}</Project>
<Name>ProjectName</Name>
<VSIXSubPath>SubDirectory</VSIXSubPath>
<IncludeOutputGroupsInVSIX>BuiltProjectOutputGroup%3bBuiltProjectOutputGroupDependencies%3bGetCopyToOutputDirectoryItems%3bSatelliteDllsProjectOutputGroup%3bDocumentationProjectOutputGroup%3bReferenceCopyLocalPathsOutputGroup%3b</IncludeOutputGroupsInVSIX>
<IncludeOutputGroupsInVSIXLocalOnly>DebugSymbolsProjectOutputGroup%3b</IncludeOutputGroupsInVSIXLocalOnly>
</ProjectReference>

NuGet: Two packages with targets files lead to incorrectly copied DLLs

I have created two NuGet packages that contain Native Libraries. The first one has two subfolders (amd64 and x86) the second one includes the DLL flat under the build directory. The NativeLibraries of the the first package are supposed to be copied into subfolders of the OutputPath. The only DLL in the second package should be copied flat under the OutputPath. I used the following stackoverflow entry as a guide for creating the package: https://stackoverflow.com/a/30316946/4496150
The first NuGet package folder structure looks like this (amd64 and x86 subfolder under build):
build
amd64
DLL1.dll
DLL2.dll
x86
DLL1.dll
DLL2.dll
packagename.targets
First targets file:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<NativeLibs Include="$(MSBuildThisFileDirectory)**\*.dll" />
<None Include="#(NativeLibs)">
<Link>%(RecursiveDir)%(FileName)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
Please notice $(MSBuildThisFileDirectory)** as NativeLibs Include and %(RecursiveDir) as part of Link attribute.
The second NuGet package structure looks like this (no subfolders under build):
build
DLL1.dll
packagename.targets
Second targets file:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<NativeLibs Include="$(MSBuildThisFileDirectory)\*.dll" />
<None Include="#(NativeLibs)">
<Link>%(FileName)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
Please notice $(MSBuildThisFileDirectory) (without **) as NativeLibs Include and missing %(RecursiveDir) in Link attribute.
If you reference both packages, the DLLs from the first package are additionally copied flat into the output folder, which is not desired. I suspect this is because the second include step also reads the DLLs from the first package, but then does not use %(RecursiveDir).
A workaround is to also include in the second package both.
and NativeLibs Include="$(MSBuildThisFileDirectory)***.dll" /> exactly as in the first package.
However, I would prefer to understand why the second package ensures that the DLLs from the first are copied flat.
If I read https://learn.microsoft.com/de-de/visualstudio/msbuild/msbuild-reserved-and-well-known-properties?view=vs-2019 correctly, $(MSBuildThisFileDirectory) points to the folder in my NuGet cache where the targets file of the NuGet package is located. So actually everything would be correct. But still (probably) wrong DLLs are copied.
Edit
I added the following snippet in both targets files to get some output:
<Target Name="OutputPackage1NativeLibs" BeforeTargets="Build">
<Message Text="Package1 %(NativeLibs.Identity)" Importance="high"/>
</Target>
For the seconds targets file I changed the target name to OutputPackage2NativeLibs and started the text Output with Packag2.
When I clean my NuGet Package Cache and rebuild the solution everything is fine. But after the third or forth rebuild operation the DLLs of the first package are copied flat under the Output path and I get the following output:
Package1 C:\Users\USERNAME\.nuget\packages\PACKAGENAME1\1.2.3.4\build\amd64\DLL1.dll
Package1 C:\Users\USERNAME\.nuget\packages\PACKAGENAME1\1.2.3.4\build\amd64\DLL2.dll
Package1 C:\Users\USERNAME\.nuget\packages\PACKAGENAME1\1.2.3.4\build\x86\DLL1.dll
Package1 C:\Users\USERNAME\.nuget\packages\PACKAGENAME1\1.2.3.4\build\x86\DLL2.dll
Package1 C:\Users\USERNAME\.nuget\packages\PACKAGENAME2\1.0.0.0\build\DLL1.dll
Package2 C:\Users\USERNAME\.nuget\packages\PACKAGENAME1\1.2.3.4\build\amd64\DLL1.dll
Package2 C:\Users\USERNAME\.nuget\packages\PACKAGENAME1\1.2.3.4\build\amd64\DLL2.dll
Package2 C:\Users\USERNAME\.nuget\packages\PACKAGENAME1\1.2.3.4\build\x86\DLL1.dll
Package2 C:\Users\USERNAME\.nuget\packages\PACKAGENAME1\1.2.3.4\build\x86\DLL2.dll
Package2 C:\Users\USERNAME\.nuget\packages\PACKAGENAME2\1.0.0.0\build\DLL1.dll
So NativeLibs are added from the other NuGet package apparently after the third or fourth rebuild.
I think you are using Packages.config nuget package format with non-sdk net framework projects. If so, that could be explained.
For packages.config nuget management format, it imports the target files directly under csproj file. In my side, I created two nuget packages called flat 1.0.0 and faltt 1.0.0 nuget packages.
You can check my csproj file:
If so, the first import targets file flat.targets file is the same as your first nuget package's targets file:
It includes the x86 and amd64 folder files into output folder\x86 and output folder\amd64 folder, that is right as we excepted.
However, under pakckages.config, since the two targets file are in the same csproj file, they can access each other(they have the same life cycle in the same CSProj), when msbuild reads faltt.targets file after flat.targets file, also you did not change NativeLibs item for the second targets file, itself has the file:
C:\Users\xxx\source\repos\flat\packages\flat.1.0.0\build\amd64\Dll1.dll
C:\Users\xxx\source\repos\flat\packages\flat.1.0.0\build\amd64\Dll2.dll
C:\Users\xxx\source\repos\flat\packages\flat.1.0.0\build\x86\Dll1.dll
C:\Users\xxx\source\repos\flat\packages\flat.1.0.0\build\x86\Dll1.dll
When reads the flatt.targets file, it also includes C:\Users\xxx\source\repos\flat\packages\flatt.1.0.0\build\x86\Dll1.dll,
So it has five files under NativeLibs item.
And then it executes <Link>%(FileName)%(Extension)</Link>, the first nuget package's dlls will be executed under the second nuget packages's node, output to the output root folder.
Because of the special nature of Packages.config import targets files, they are interlaced.
You should note that
Under PackageReference nuget management format, the import targets files are stored under obj\xxx.csproj.nuget.g.targets file, like this:
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)flatt\1.0.0\build\flatt.targets" Condition="Exists('$(NuGetPackageRoot)flatt\1.0.0\build\flatt.targets')" />
<Import Project="$(NuGetPackageRoot)flat\1.0.0\build\flat.targets" Condition="Exists('$(NuGetPackageRoot)flat\1.0.0\build\flat.targets')" />
</ImportGroup>
Since the content is not in csproj file and the particularity of the file xxx.csproj.nuget.g.targets, it will read the targets files in each nuget package separately. Each file is a separate life cycle, so it does not Will affect each other. This is also one of the advantages of the latest PackagesReference nuget management format.
Sorry for not telling you at the beginning that I was using packagesReference and I didn't notice packages.config.
So if you want to get the right behavior to separate them, try the two approaches:
1) do not change the two nuget packages, right-click on the packages.config file of the main project which installs the two nuget packages-->click Migrate packages.config to PackageReference option
After that, click Rebuild option to get that.
2) modify the nuget packages--> change the NativeLibs item's name to another for the second nuget package targets file:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<NativeLibs1 Include="$(MSBuildThisFileDirectory)*.dll" />
<None Include="#(NativeLibs1)">
<Link>%(FileName)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
When re-pack your project, uninstall them first, delete all cache files under C:\Users\xxx\.nuget\packages. And then re-install the packages again.

VSTS Automated Build NuGet Packager/Publisher

My package builds successfully and is uploaded to the Packages feed in VSTS however I can't seem to figure out how to edit the Description and Author of the package so that my set values show in the Package feed.
From what I read I put my content in the NuGet Packager under additional build properties and when I look at the log file I see this:
...NuGet.exe pack "...csproj" -OutputDirectory "..." -Properties Configuration=release;Description="My Description";Authors="Me";Owners="My Company"
From the documentation I believe I did this right(but clearly I did not). It does seem a bit confusing as to what goes in "Additional build properties" vs NuGet Arguments.
Again my goal is get the Description and Author that I set to be viewable from the NuGet Package Manager within Visual Studio.
You could create a package according to the .nuspec file.
Steps:
Generate .nuspec file for your project (command: nugget spec).
For example: (Include author and description token)
<?xml version="1.0"?>
<package >
<metadata>
<id>CommLib1</id>
<version>1.0.0.6</version>
<title>CommLib1</title>
<authors>$author$</authors>
<owners>$author$</owners>
<licenseUrl>http://LICENSE_URL_HERE_OR_DELETE_THIS_LINE</licenseUrl>
<projectUrl>http://PROJECT_URL_HERE_OR_DELETE_THIS_LINE</projectUrl>
<iconUrl>http://ICON_URL_HERE_OR_DELETE_THIS_LINE</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>$description$</description>
<releaseNotes>Summary of changes made in this release of the package.</releaseNotes>
<copyright>Copyright 2016</copyright>
<tags>Tag1 Tag2</tags>
</metadata>
</package>
Include this file to source control
Specify Nuget Arguments (token in step 1) of Nuget Packager build step
Update1:
In general, you just need to update AssemblyInfo.cs file of your project (Author=>AssemblyCompany; Description=>AssemblyDescription; Version=>AssemblyVersion), it creates package according to this data unless it can't retrieve metadata from your assembly (I have a project has this issue).
So, steps:
Make sure nuget could retrieve necessary metadata by creating package through nuget.exe command directly in your local/build machine (nuget pack [XX].csproj)
Create a build definition (1. Visual Studio Build 2. Nuget Packager with default value 3. Nuget Publisher)
If it's building the package then there are no problems with your NuGet Packager build step. Two things need to change though.
In order to specify properties like you are doing there MUST be a tokenized *.nuspec file in the same directory as the solution file with the same name and of course the *.nuspec file needs to be checked in to VSTS/TFS.
The token name for description can't be Description.
For more details on the *.nuspec file please see the solution here:
Nuget.exe pack WARNING: Description was not specified. Using 'Description'

Deploying PostSharp into a Source Repository with NuGet Package Restore

Is it possible to Deploy PostSharp into a Source Repository in conjunction with NuGet Package Restore?
I can get this working by committing the postsharp package, but that negates somewhat the value of the Package Restore feature.
Here’s what I did.
I was trying to set up postshap like so: Deploying post sharp into a source repo
I have set up nugget to use without commiting like so: Using NuGet Without Committing Packages to Source Control
I see this in my csproj
<Import Project="..\packages\PostSharp.2.1.6.13\tools\PostSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
(I re-ordered them to no avail)
And my build server (CC.net) reports the following errors:
D:\wwwroot\www.snip.co.nz\http\www.snip.co.nz.csproj (714,3):
errorMSB4019: The imported project "D:\wwwroot\www.snip.co.nz\packages\PostSharp.2.1.6.13\tools\PostSharp.targets" was not found. Confirm that the path in the <Import> declaration is correct, and that the file exists on disk.
CacheAttribute.cs (8,7):
errorCS0246: The type or namespace name 'PostSharp' could not be found (are you missing a using directive or an assembly reference?)
…etc…
You currently (v2.1.6.13) have to fix the csproj to support Package Restore,
within the Import target element add the condition shown here:
<Import Project="..\packages\PostSharp.2.1.6.13\tools\PostSharp.targets"
Condition="Exists('..\packages\PostSharp.2.1.6.13\tools\PostSharp.targets')" />