Zorthgo
Zorthgo

Reputation: 2977

Including referenced project DLLs in nuget package [.Net Core RC3 *.csproj file]

I have a solution with two projects in it. First project is called Library1, which references project two called Referencelibrary. I am trying to embed the DLLs for ReferenceLibrary inside Library1's nuget package so that I don't have to publish 2 separate nuget packages. I've been able to embed ReferenceLibrary's DLL into the nuget package (so it seems) by adding the entries below into my csproj file:

  <ItemGroup>
    <ProjectReference Include="..\ReferenceLibrary\ReferenceLibrary.csproj">
        <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
        <IncludeAssets>ReferenceLibrary.dll</IncludeAssets>
        <IncludeAssets>ReferenceLibrary.pdp</IncludeAssets>
    </ProjectReference>
  </ItemGroup>

But when I import the nuget package and try to run my test app, I get the following exception:

Exception Screenshot I assumed that the DLLs had been embedded because prior to adding the "IncludeAssets" to the csproj, I wasn't able to import the nuget package because it was trying to reference the ReferenceLibrary nuget package. But after adding those entries, it allowed me to import it. But now it bombs at run-time. Any help would be greatly appreciated. Thanks!

;)

Upvotes: 42

Views: 27816

Answers (5)

BlackGad
BlackGad

Reputation: 81

Some extended version of Neo answer. Additionally instruct MSBuild to pack all pdb symbols to chosen symbols format. (built in pdb or snupkg)

<PropertyGroup>
    <TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage</TargetsForTfmSpecificBuildOutput>
    <TargetsForTfmSpecificDebugSymbolsInPackage>$(TargetsForTfmSpecificDebugSymbolsInPackage);CopyProjectReferencesSymbolsToPackage</TargetsForTfmSpecificDebugSymbolsInPackage>
</PropertyGroup>
<Target Name="CopyProjectReferencesToPackage" DependsOnTargets="ResolveReferences">
    <ItemGroup>
        <BuildOutputInPackage Include="@(ReferenceCopyLocalPaths->WithMetadataValue('ReferenceSourceTarget', 'ProjectReference'))" />
    </ItemGroup>
</Target>
<Target Name="CopyProjectReferencesSymbolsToPackage" DependsOnTargets="ResolveReferences">
    <ItemGroup>
        <SupposedSymbolFiles Include="@(ReferenceCopyLocalPaths->'%(RootDir)%(Directory)%(Filename).pdb')"/>
        <TfmSpecificDebugSymbolsFile Include="@(SupposedSymbolFiles)" Condition="Exists('%(Identity)')">
            <TargetFramework>$(TargetFramework)</TargetFramework>
        </TfmSpecificDebugSymbolsFile>
    </ItemGroup>
</Target>

Upvotes: 1

Neo
Neo

Reputation: 4497

There is now a more up-to-date workaround described here. Simply add the TargetsForTfmSpecificBuildOutput and Target nodes to your .csproj file as shown below.

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage</TargetsForTfmSpecificBuildOutput>
  </PropertyGroup>
  <Target Name="CopyProjectReferencesToPackage" DependsOnTargets="ResolveReferences">
    <ItemGroup>
      <BuildOutputInPackage Include="@(ReferenceCopyLocalPaths->WithMetadataValue('ReferenceSourceTarget', 'ProjectReference'))" />
    </ItemGroup>
  </Target>
</Project>

Official documentation for this extension point in the pack target can be found here.

You might also then want to add the attribute PrivateAssets="All" to the ProjectReference element to suppress that project from appearing as a NuGet dependency in the generated package, e.g.:

<ProjectReference Include="MyNonNugetDependentProject.csproj" PrivateAssets="All" />

Upvotes: 40

tobster
tobster

Reputation: 196

For placing DLLs within a folder of my choice I used the other customization point as described at Microsoft.

So I ended up with the following:

<PropertyGroup>
  <IncludeBuildOutput>false</IncludeBuildOutput> <!-- omit the package creating library itself -->
  <PackProject>true</PackProject>
  <TargetsForTfmSpecificContentInPackage>$(TargetsForTfmSpecificContentInPackage);CreatePackNupkg</TargetsForTfmSpecificContentInPackage>
</PropertyGroup>

<Target Name="CreatePackNupkg">
  <ItemGroup>
    <TfmSpecificPackageFile Include="$(OutputPath)\<whatever>.*.dll">
      <PackagePath>folder/subfolder</PackagePath>
    </TfmSpecificPackageFile>
  </ItemGroup>    
</Target>

The NuGet.Pack package is created the same way (have a look).

Upvotes: 4

David Burg
David Burg

Reputation: 1163

This appears to be a known limitation with the built-in NuGet packaging for core projects in Visual Studio 2017 and is discussed here:

https://github.com/NuGet/Home/issues/3891

In that discussion thread there is a hack that worked for me:

https://github.com/NuGet/Home/issues/3891#issuecomment-309792369

<ItemGroup>
  <_PackageFiles Include="$(OutputPath)\ReferencedProjectDll.dll">
    <BuildAction>None</BuildAction>
    <PackagePath>lib\net45\</PackagePath>
  </_PackageFiles>
</ItemGroup>

Note that you need to change the assembly name AND you might need to also change the package path to match the version of .NET Framework you are using. Above example is for 4.5 but you might be on the more current 4.6.

Upvotes: 10

Leo Liu
Leo Liu

Reputation: 76680

We could not include referenced project DLLs with three or above projects.

For example, the ReferenceLibrary.dll will be added to References for Library1 when project Library1 reference to project ReferenceLibrary. But only the Library1.dll will be add to the References of test app project when you reference project Library1 to project test app. The referenced project DLLs “Referencelibrary” will be omitted . See Flexible Project-to-Project References for more detail.

If you want to embed the DLLs for ReferenceLibrary inside Library1's nuget package and reference it to the test app project, you can add the ReferenceLibrary project reference to test app project after add the reference project Library1 or set ReferenceLibrary.dll as a dependence of Library1 project, you can add the below entries into Library1.csproj, then package the Library1 and install this package to test app via NuGet:

  <ItemGroup>
    <Reference Include="ReferenceLibrary, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\packages\ReferenceLibrary.1.0.0\lib\net461\ReferenceLibrary.dll</HintPath>
      <Private>True</Private>
    </Reference>
  </ItemGroup>

Update:

If we want to embed the DLLs for ReferenceLibrary inside Library1's nuget package, we should make sure the ReferenceLibrary.dll include in the Library1 package, No matter how we embed the DLLS. So you can add ReferenceLibrary.dll to the Library1.nuspec as file when we pack the Library1 package and set target to the lib folder. Below is my Library1.nuspec:

<?xml version="1.0"?>
<package >
  <metadata>
    <id>Library1</id>
    <version>1.0.0</version>
    <authors>xxxx</authors>
    <owners>xxxx</owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Package description</description>
    <releaseNotes>Summary of changes made in this release of the package.</releaseNotes>
    <copyright>Copyright 2017</copyright>
    <tags>Test</tags>
  </metadata>
     <files>
        <file src="..\Library1\bin\Debug\Referencelibrary.dll" target="\lib\net461" />
        <file src="..\Library1\bin\Debug\Library1.dll" target="\lib\net461" />
     </files>
</package>

Note that: You also need include the Library1.dll in the Library1.nuspec.

Upvotes: 2

Related Questions