Excluding the library being built from nuget package in .NET Standard
Asked Answered
B

2

9

Bear with me - this is an unusual scenario. I have 4 projects in my solution. The top most project references the 3 other projects. None of the 3 other projects reference each other. So the architecture is like this:

enter image description here

Now, when I build project A I want it to produce a nuget package containing projects B, C and D but not project A. As this is in .NET standard I can configure the packages tab of project A to produce a nuget package automatically when it builds by checking the 'Generate NuGet package on build option.' Then, I can get it to include B, C and D by making the following changes to A's csproj file:

<ItemGroup>
    <ProjectReference Include="..\B.csproj">
      <PrivateAssets>all</PrivateAssets>
    </ProjectReference>
    <ProjectReference Include="..\C.csproj">
      <PrivateAssets>all</PrivateAssets>
    </ProjectReference>
    <ProjectReference Include="..\D.csproj">
      <PrivateAssets>all</PrivateAssets>
    </ProjectReference>
  </ItemGroup>

  <PropertyGroup>
    <TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage</TargetsForTfmSpecificBuildOutput>
    <Version>1.0.0-beta</Version>
    <PackageId>A</PackageId>
    <Company></Company>
    <Product>A</Product>
    <Description></Description>
    <Authors></Authors>
    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
  </PropertyGroup>

  <Target Name="CopyProjectReferencesToPackage" DependsOnTargets="ResolveReferences">
    <ItemGroup>
      <BuildOutputInPackage    Include="@(ReferenceCopyLocalPaths-&gt;WithMetadataValue('ReferenceSourceTarget', 'ProjectReference')-&gt;WithMetadataValue('PrivateAssets', 'all'))" />
    </ItemGroup>
  </Target>

Ideally I would like to add a line to remove A.dll from the nuget package. Is this possible? A is a wrapper project which consuming code will never need to use. It is not possible for B, C and D to reference each other.

UPDATE This is how I solved it (thanks @tom redfern)

I created a nuspec file manually:

<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
  <metadata>
    <id>A</id>
    <version>1.0.0-beta</version>
    <authors>Foo</authors>
    <owners>Bar</owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>A package</description>
    <dependencies>
      <group targetFramework=".NETStandard2.0">    
      </group>
    </dependencies>
  </metadata>
  <files>
    <file src="bin\Release\netstandard2.0\B.dll" target="lib\netstandard2.0\B.dll" />
    <file src="bin\Release\netstandard2.0\C.dll" target="lib\netstandard2.0\C.dll" />
    <file src="bin\Release\netstandard2.0\D.dll" target="lib\netstandard2.0\D.dll" />
  </files>
</package>

Then in my .csproj file for A I put the following to automatically pack it after a build:

 <Target Name="__PackNuGetPackage" AfterTargets="Build">
    <Exec Command="$(NugetPackage)nuget.exe pack &quot;A.nuspec&quot;" />
  </Target>
Borough answered 13/1, 2020 at 14:17 Comment(2)
So you want to exclude the library being packaged....from being packaged?Patronizing
Yes! Like I said its an unusual scenario.Borough
P
1

You can achieve this by using a nuspec file. Use nuspec when you need absolute control over the nuget pack process. A simple nuspec file:

<package >
  <metadata>
    <id>MyPackage</id>
    <version>1.0</version>
    <authors>Something</authors>
    <owners>Something</owners>
    <description>Somthing</description>
    <copyright></copyright>
    <dependencies>
       <!-- any nuget package dependencies -->
       <dependency id="AnotherPackage" version="2019.2.4.1" />
    </dependencies>
  </metadata>
  <files>
    <!-- this is where you can have complete control over which assemblies get added to your package. You can add them individually pr using wildcards. -->
    <file src="..\obj\**\*.dll" target="lib" />
  </files>
</package>

When you have created your .nuspec file, add it into your solution, and then make your "Nuget Pack" build step read the nuspec file rather than the project file.

Patronizing answered 14/1, 2020 at 15:37 Comment(0)
C
5

Using patented(1) elite(2) debugging skills, we can figure out if it's possible without manually creating and maintaining a nuspec file.

First, let's start with NuGet's docs on creating a package with the dotnet CLI. It says "msbuild -t:pack is functionality equivalent to dotnet pack". So, first hint, it's just running MSBuild targets.

So, run dotnet msbuild my.csproj -pp:pp.txt. This "pre-processes" (evaluates all MSBuild import statements and writes the result into a single file) the csproj (just a standard MSBuild file). We then search for the pack target, and scroll up until we find the filename of the file that was imported. We see it's NuGet.Build.Tasks.Pack.targets, and since NuGet is open source on GitHub, I can point you to the source.

Searching NuGet.Build.Tasks.Pack.targets for Condition, to see what extensibility options the NuGet team has provided, I see <IncludeBuildOutput Condition="'$(IncludeBuildOutput)'==''">true</IncludeBuildOutput>. So, settings <IncludeBuildOutput Condition="'$(IncludeBuildOutput)'==''">false</IncludeBuildOutput> in your csproj, might work.

(1) not patented

(2) standard, but since people don't modify MSBuild files anywhere near as often as C#, the skills and tools aren't as well known

Costrel answered 14/1, 2020 at 16:47 Comment(1)
Thanks for the suggestion - I tried setting IncludeBuildOutput to false but it won't let me pack a project without any items in it - not surprising really.Borough
P
1

You can achieve this by using a nuspec file. Use nuspec when you need absolute control over the nuget pack process. A simple nuspec file:

<package >
  <metadata>
    <id>MyPackage</id>
    <version>1.0</version>
    <authors>Something</authors>
    <owners>Something</owners>
    <description>Somthing</description>
    <copyright></copyright>
    <dependencies>
       <!-- any nuget package dependencies -->
       <dependency id="AnotherPackage" version="2019.2.4.1" />
    </dependencies>
  </metadata>
  <files>
    <!-- this is where you can have complete control over which assemblies get added to your package. You can add them individually pr using wildcards. -->
    <file src="..\obj\**\*.dll" target="lib" />
  </files>
</package>

When you have created your .nuspec file, add it into your solution, and then make your "Nuget Pack" build step read the nuspec file rather than the project file.

Patronizing answered 14/1, 2020 at 15:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.