.netmsbuildnugetnuget-package

Include assembly from another package into my NuGet package using GeneratePathProperty


I am building a tool package which depends on another NuGet package. As it is not an usual library, it must include all dependencies into the tools\ directory. I have the following csproj (only the relevant bits are shown):

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFrameworks>netstandard2.0;netstandard2.1</TargetFrameworks>
    <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
    <DevelopmentDependency>true</DevelopmentDependency>
    <IsTool>true</IsTool>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Build.Framework" Version="16.7.0" PrivateAssets="all" />
    <PackageReference Include="Microsoft.Build.Utilities.Core" Version="16.7.0" PrivateAssets="all" />
    <PackageReference Include="System.Text.Json" Version="4.7.2" PrivateAssets="all" GeneratePathProperty="true" />
  </ItemGroup>

  <ItemGroup>
    <None Include="build\*" Pack="true" PackagePath="build\" />
    <None Include="$(PkgSystem_Text_Json)\lib\netstandard2.0\*.dll" Visible="false" Pack="true" PackagePath="tools\" />
  </ItemGroup>
</Project>

So I used GeneratePathProperty on my dependency and try to include the assembly using generated path $(PkgSystem_Text_Json). I can confirm that the path is correct by setting Visible="true" and inspecting my project. But the assembly is missing from my NuGet package. Seems that the generated path property does not exist at the moment of packaging. If I use an absolute path the assembly gets included but this solution is not portable.

How do I make generated path property work at packaging stage?


Solution

  • I got it to work locally by using

    <PropertyGroup>
      <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
    </PropertyGroup>
    
    <Target Name="_PackLocalLockFileAssemblies" AfterTargets="ResolveLockFileCopyLocalFiles">
      <ItemGroup>
        <BuildOutputInPackage Include="@(ReferenceCopyLocalPaths)" />
      </ItemGroup>
    </Target>
    

    CopyLocalLockFileAssemblies is a trick to get the PackageReference DLLs into the bin folder. The files to-be-copied get resolved into ReferenceCopyLocalPaths items in the ResolvelockFileCopyLocalFiles target. The new target takes those resolved reference paths and adds them as BuildOutputInPackage items, that the GenerateNuSpec target takes as the input.

    This also takes care of all the transitive dependencies.

    enter image description here