Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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>
like image 231
David Christopher Reynolds Avatar asked Oct 16 '22 07:10

David Christopher Reynolds


1 Answers

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

like image 109
zivkan Avatar answered Oct 31 '22 00:10

zivkan