-
Notifications
You must be signed in to change notification settings - Fork 258
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature : Allow project reference DLLs to be added to the parent nupkg for pack target like IncludeReferencedProjects in nuget.exe #3891
Comments
Please check spec on wiki for planned behavior |
Spec: https://github.com/NuGet/Home/wiki/Adding-nuget-pack-as-a-msbuild-target This doesn't work: <TreatAsPackageReference>false</TreatAsPackageReference> The output .nuspec still has projectB as a package reference and only one file: projectA.dll under lib. |
This is a non-trivial feature that hasn't been implemented for RC yet. Supporting this will require potentially walking the entire project closure to determine all projects that need to be merged into the package, or reading the assets file and matching the project closure with both the project reference flags and the pack flags found in the project (since it can be set either way). This is also impacted by build outputs not flowing transitively to parent projects yet. |
Plan of action:
This has repercussions on:
|
@rohit21agrawal, I partially got through consuming the assets file from in the pack task: This also has some progress on getting the output DLLs of child projects (using This branch is pretty rough so let me know if I can clarify. |
As per @rrelyea : #3893 (comment) "We don't plan to enable this in dotnet pack / msbuild /t:pack in 4.0 timeframe. |
moving to future as this is post-rtm work. |
building a nupkg from multiple projects seems like a major feature to be missing :/ |
@gulbanana thanks for the feedback. this is something that is not planned for the 4.0 RTM release, but this is something we will definitely address in a future release. |
@kzu 's nugetizer 3000 does this? |
Hi guys, Just out of curiosity - are there any plans to proceed on this one? Currently, I need to use the dirty workaround that is MSBuild internals specifics: <ItemGroup>
<_PackageFiles Include="$(OutputPath)\ReferencedProjectDll.dll">
<BuildAction>None</BuildAction>
<PackagePath>lib\net45\</PackagePath>
</_PackageFiles>
</ItemGroup> |
There's the |
@ViktorHofer thanks for you answer, but unfortunatelly this didn't help, inspecting the nuspec file, with the Here is a set of commands to quickly setup this locally, if you maybe would like to try it out: dotnet new sln --name solution
dotnet new console --name PackagedApp
dotnet sln add .\PackagedApp
dotnet new classlib --name ReferencedLibrary
dotnet sln add ReferencedLibrary
dotnet new console --name ConsumingApp
dotnet sln add ConsumingApp Now edit PackagedApp.csproj: <Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\ReferencedLibrary\ReferencedLibrary.csproj" PrivateAssets="All"/>
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);IncludeProjectReferenceDlls</TargetsForTfmSpecificBuildOutput>
</PropertyGroup>
<Target Name="IncludeProjectReferenceDlls" DependsOnTargets="BuildOnlySettings;ResolveReferences">
<ItemGroup>
<BuildOutputInPackage Include="@(ReferenceCopyLocalPaths->WithMetadataValue('ReferenceSourceTarget', 'ProjectReference')->WithMetadataValue('PrivateAssets', 'All'))"/>
</ItemGroup>
</Target>
</Project> dotnet pack .\PackagedApp
dotnet nuget add source . -n TempSource
dotnet nuget push .\PackagedApp\bin\Release\PackagedApp.1.0.0.nupkg --source TempSource
dotnet add .\ConsumingApp package PackagedApp --version 1.0.0 At this point if you go into the ConsumingApp I would like that the defaul Class1 is not visible, but currently it is. Cleanup: |
Ok so my The issue is that the "private" class library is put into the "lib" folder in the package and NuGet by default passes all assemblies from the lib folder to the compiler as a reference. I think you could work around this by only putting your "PackagedApp" assembly into the "ref" folder. If you define a ref folder in addition to the lib folder, the assemblies from the former will be passed to the compiler and the assemblies from the latter will be made available at run time. You can include the assembly into the ref folder via this item:
This needs to be put in a target that is added to the |
@ViktorHofer thanks for you answer once again, but I still coudn't make it work I have tried: <Target Name="IncludeProjectReferenceDlls" DependsOnTargets="BuildOnlySettings;ResolveReferences">
<ItemGroup>
<BuildOutputInPackage Include="@(ReferenceCopyLocalPaths->WithMetadataValue('ReferenceSourceTarget', 'ProjectReference')->WithMetadataValue('PrivateAssets', 'All'))"/>
<TfmSpecificPackageFile Include="@(ReferenceCopyLocalPaths->WithMetadataValue('ReferenceSourceTarget', 'ProjectReference')->WithMetadataValue('PrivateAssets', 'All'))" PackagePath="ref\$(TargetFramework)\"/>
</ItemGroup>
</Target> <Target Name="IncludeProjectReferenceDlls" DependsOnTargets="BuildOnlySettings;ResolveReferences">
<ItemGroup>
<TfmSpecificPackageFile Include="@(ReferenceCopyLocalPaths->WithMetadataValue('ReferenceSourceTarget', 'ProjectReference')->WithMetadataValue('PrivateAssets', 'All'))" PackagePath="ref\$(TargetFramework)\"/>
</ItemGroup>
</Target> Thanks to your suggestion I have also found this msdn reference, but even with a nuspec file a coudn't make it to work: <?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
<metadata>
<id>PackagedApp</id>
<version>1.0.0</version>
<authors>PackagedApp</authors>
<description>Package Description</description>
<repository type="git"/>
<dependencies>
<group targetFramework="net8.0"/>
</dependencies>
<references>
<group targetFramework="net8.0">
<reference file="ReferencedLibrary.dll"/>
</group>
</references>
</metadata>
<files>
<file src="bin\Release\net8.0\PackagedApp.dll" target="lib\net8.0\PackagedApp.dll"/>
<file src="bin\Release\net8.0\ReferencedLibrary.dll" target="ref\net8.0\ReferencedLibrary.dll"/>
<file src="bin\Release\net8.0\ReferencedLibrary.dll" target="lib\net8.0\ReferencedLibrary.dll"/>
</files>
</package> Did you maybe manage to make this work? Maybe I will just give up, and make the reference projects nuget packages ... |
I missed a few thing. Update your PackagedApp.csproj to the following: <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);IncludeProjectReferenceDlls</TargetsForTfmSpecificBuildOutput>
<NoWarn>$(NoWarn);NU5131</NoWarn>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\ReferencedLibrary\ReferencedLibrary.csproj" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
<!-- Add a ref folder to the package which only exposes the library so that the referenced class library doesn't get exposed. -->
<None Include="$(TargetPath)" PackagePath="ref/$(TargetFramework)" Pack="true" Condition="'$(TargetFramework)' != ''" />
</ItemGroup>
<Target Name="IncludeProjectReferenceDlls" DependsOnTargets="BuildOnlySettings;ResolveReferences">
<ItemGroup>
<BuildOutputInPackage Include="@(ReferenceCopyLocalPaths->WithMetadataValue('ReferenceSourceTarget', 'ProjectReference')->WithMetadataValue('PrivateAssets', 'All'))"
TargetPath="%(ReferenceCopyLocalPaths.DestinationSubDirectory)" />
</ItemGroup>
</Target>
</Project> |
@ViktorHofer Great this now finally works, thank you very much. If you agree and find it valuable a would like to make a pull request to the docs and include what you have provided at the bottem where there already is the exact same example, but the missing part is how to do this with the |
It work incorrect if dll has translated resources |
I'm using the approach recommended in the latest comments and it seems to work. However, I'm seeing a bunch of build warnings (NU5131) because the "ref" folders is missing files. You can see that the "Abstractions" lib is not present in the ref folder. However the files are present in the nupkg. Is it ok to ignore NU5131 (as suggested above)? Build output ( Warning Build succeeded. "./KernelMemory.sln" (default target) (1:2) -> "./clients/dotnet/WebClient/WebClient.csproj" (default target) (6:8) -> (GenerateNuspec target) -> /usr/local/share/dotnet/sdk/8.0.201/Sdks/NuGet.Build.Tasks.Pack/build/NuGet.Build.Tasks.Pack.targets(221,5): warning NU5131: - Add Microsoft.KernelMemory.WebClient.dll to the net8.0 reference group in the nuspec [./clients/dotnet/WebClient/WebClient.csproj] /usr/local/share/dotnet/sdk/8.0.201/Sdks/NuGet.Build.Tasks.Pack/build/NuGet.Build.Tasks.Pack.targets(221,5): warning NU5131: [./clients/dotnet/WebClient/WebClient.csproj] |
The suggested approach about using
The last step fails with |
@ViktorHofer , I have the same issue as @dluc with |
@ViktorHofer Thanks for the great example. There was one issue I had when including a nuget package, which contained resources for internationalization. For those, the DLLs are not just included in the <Target Name="IncludeProjectReferenceDlls" DependsOnTargets="BuildOnlySettings;ResolveReferences">
<ItemGroup>
<BuildOutputInPackage
Include="@(ReferenceCopyLocalPaths->WithMetadataValue('ReferenceSourceTarget', 'ProjectReference')->WithMetadataValue('PrivateAssets', 'All'))"
TargetPath="%(ReferenceCopyLocalPaths.DestinationSubDirectory)" />
</ItemGroup>
</Target> |
@prezaei @dluc @ViktorHofer I was able to work around the "NETSDK1085" error when using
I assume this doesn't cause any side effects as I'm just packing after the build is already done separately. Reading the pack log it says,
Finding that target in the mentioned .targets file has this,
Although that github 7801 issue mentioned in the todo was closed 5 years ago this todo still exists--maybe for other reasons, or it was just forgotten? Anyways, because I pass in |
I've tried the solution that @ViktorHofer laid out for @DomenPigeon. Using @DomenPigeon's example, the DLL for ReferencedLibrary is included in the nupkg for PackagedApp, however when I try and add the PackagedApp package to ConsumingApp project I get an error complaining that a package for ReferencedLibrary cannot be found. Has anyone encountered this before? The only difference in my code vs the example is PackagedApp is another classlib. |
Regarding #3891 (comment), can one say that these included DLLs are supposed to be only runtime dependencies (i.e. can one add |
@serj1980 you are right, thanks for pointing that out. I just updated my answer above which now works with satellite assemblies as well: <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);IncludeProjectReferenceDlls</TargetsForTfmSpecificBuildOutput>
<NoWarn>$(NoWarn);NU5131</NoWarn>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\ReferencedLibrary\ReferencedLibrary.csproj" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
<!-- Add a ref folder to the package which only exposes the library so that the referenced class library doesn't get exposed. -->
<None Include="$(TargetPath)" PackagePath="ref/$(TargetFramework)" Pack="true" Condition="'$(TargetFramework)' != ''" />
</ItemGroup>
<Target Name="IncludeProjectReferenceDlls" DependsOnTargets="BuildOnlySettings;ResolveReferences">
<ItemGroup>
<BuildOutputInPackage Include="@(ReferenceCopyLocalPaths->WithMetadataValue('ReferenceSourceTarget', 'ProjectReference')->WithMetadataValue('PrivateAssets', 'All'))"
TargetPath="%(ReferenceCopyLocalPaths.DestinationSubDirectory)" />
</ItemGroup>
</Target>
</Project>
@dluc yes that's fine to suppress. There isn't a way to put a reference assembly into a package and make the nuspec list it as a reference item. There's a tracking issue for that: #8684 |
For those looking for a working example, see the Microsoft.ML package. It contains a suite of assemblies such as "Microsoft.ML.KMeansClustering.dll". Look at these files:
|
I think the microsoft/CsWin32 repository will be helpful. |
I've gotten the setup that @ViktorHofer and @DomenPigeon have described setup and its works (thank you!). However one thing I have noticed is that if multiple frameworks are specified using |
@nathanmascitelli I managed to do it using this as reference: |
Here's the updated version that work with multiple TargetFrameworks as well: <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>net9.0;net8.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);IncludeProjectReferenceDlls</TargetsForTfmSpecificBuildOutput>
<TargetsForTfmSpecificContentInPackage>$(TargetsForTfmSpecificContentInPackage);IncludeReferenceAssemblies</TargetsForTfmSpecificContentInPackage>
<NoWarn>$(NoWarn);NU5131</NoWarn>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\ReferencedLibrary\ReferencedLibrary.csproj" PrivateAssets="all" />
</ItemGroup>
<Target Name="IncludeProjectReferenceDlls" DependsOnTargets="BuildOnlySettings;ResolveReferences">
<ItemGroup>
<BuildOutputInPackage Include="@(ReferenceCopyLocalPaths->WithMetadataValue('ReferenceSourceTarget', 'ProjectReference')->WithMetadataValue('PrivateAssets', 'all'))"
TargetPath="%(ReferenceCopyLocalPaths.DestinationSubDirectory)" />
</ItemGroup>
</Target>
<!-- Add a ref folder to the package which only exposes the library so that the referenced class library doesn't get exposed. -->
<Target Name="IncludeReferenceAssemblies">
<ItemGroup>
<TfmSpecificPackageFile Include="$(TargetPath)" PackagePath="ref/$(TargetFramework)" />
</ItemGroup>
</Target>
</Project>
Hehe, that's my code copied from dotnet/runtime ;) I would not recommend using that here if not strictly necessary. |
@antonioacg @ViktorHofer thank you both! Works like a charm. |
Steps
dotnet new --type lib
two .csproj class libraries: projectA and projectB.<TargetFramework>
to<TargetFrameworks>
if you don't have dotnet pack fails with project references and <TargetFramework> #3865.ProjectReference
to projectB.<Type>project</Type>
to the<ProjectReference>
.dotnet pack
projectAExpected
projectB.dll should be in the .nupkg along with projectA.dll
Actual
projectB is still a package reference, not a DLL included in the package.
Environment
Tried latest dev's pack target.
dotnet --info
UPDATE: Please see workaround posted as comment to see how to add ProjectReferences as DLLs in the package dynamically.
The text was updated successfully, but these errors were encountered: