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> |
This will add the referenced projects dlls to the generated package. |
I think it's pretty clear what people need |
Thank you! It's wonderful to see this issue is finally being taken seriously. Here's my take on the feedback you've asked for:
I'd like to easily create a nuget package that includes dependencies from projects that I don't wish to expose as their own individual packages. So: Package1.nupkg Contains all binaries from: Project1.csproj
Makes it a lot easier to create packages that have a mixture of private dependencies (that will be self contained in the package), and public dependencies (that will be exposed as other packages). This is the largest pain point right now when creating nuget packages.
It will allow me to get rid of pointless public nuget packages that should not actually be public.
This feature is long overdue. I understand you guys haven't been working on it, as it hasn't been taken seriously, but this issue is 4 years old. It would be nice to see this work prioritised so it can be part of a release within the next year. Sooner if possible. |
FWIW, I think this is a side-effect of a (very) bad default value for IsPackable in SDK Pack. It assumes anything you don't opt out of packing, is actually a package. And therefore everything ends up creating packages, everything ends up being dependencies instead of embedded assets, etc. I'd change this to the way it works in NuGetizer: if you provide a PackageId, you're opting in to IsPackable=true. If you explicitly set it to true, also. But otherwise, nothing is packable and referencing those projects just ends up having them as embedded assets in the referencing (packable) project. Then just set a property to get the legacy behavior if you depended in any way on that (i.e. |
@JonDouglas I think the one other scenario to support is a better nuget.org UI that let's people know about private dependencies. Effectively, calculate the flow, but don't list them as public dependencies. Why throw away the good data if you have it available? Basically, for a small increase in package size, you get a wealth of useful information to build tooling around. As I've already explained, this metadata is essential for building Tools or apps that want to co-integrate with hot swappable plug-ins (runtime loaded assemblies). As far as @kzu suggestion to go off PackageId, I think as long as the tooling is there in the Project Settings dialog in Visual Studio, then that is probably an improvement. I'm not a huge fan of adding a LegacyIsPackableDefault without also adding a target date to obsolete that flag. An alternative solution is to have Visual Studio update projects if the sln version is before this change. |
Wow, a mere 48 hours before this thread enters its fifth year... |
.NET 5, 5th year... Coincidence? I don't think so =D |
@JonDouglas thank you very much for working on this. I would be so happy to see it available. |
Hello, |
https://docs.microsoft.com/en-us/dotnet/core/tools/csproj#includecontentinpack |
Thanks for a quick reply @IanKemp. I was actually hoping, that it will allow MSBuild to also include referenced project (as nuget includeReferencedProjects property). How should I approach it? What workaround is best for this? Here I found some listed |
Just posted on the mentioned StackOverflow a full repro and how it works already in NuGetizer with no changes to the project other than just adding a package reference. Just in case you need this right away and can't wait for a fix |
I feel like this is still needed. A good example might be wanting to packet project reference dependencies into a Analyzer or Source Generator Nuget package. Currently I don't think there is a way to include the assembly files directly in the package like there is for private asset Nuget package references. |
I needed to be able to produce packages (A, B) for two assemblies in the same branch where one of the packages (A) depended on another (B), but used a project reference in the solution. The way I made it work was to have a nuspec for A that had B in the dependencies section, but used a version of "SAME". The SAME value was replaced at build time with the version that was being applied to the packages and before they were packed. I posted this with a bit more info as part of at least one issue if anyone needs it. |
@HelloKitty with NuGetizer you can pull arbitrary files from arbitrary package references with: <None Include="lib\netstandard2.0\Newtonsoft.Json.dll" PackageReference="Newtonsoft.Json" /> It would be awesome if SDK pack included that capability too, since I think for non-trivial scenarios like generators, tools and even build tasks, it's quite useful. @StingyJack I'm thinking whether a |
You are correct, this will add only the referenced project dlls and not the dependencies of other NuGet packages. For example: Project B We will get NuGet package that includes ProjectA and ProjectB dlls, but without the dependency to "SomePackage". |
I think I know of a dirty hack:
<ItemGroup>
<_PackageFiles Include="[path to each project output path]\$(TargetFramework)\[project name here].dll">
<BuildAction>None</BuildAction>
<PackagePath>lib\$(TargetFramework)\</PackagePath>
</_PackageFiles>
<_PackageFiles Include="[path to each project output path]\$(TargetFramework)\[project name here].xml">
<BuildAction>None</BuildAction>
<PackagePath>lib\$(TargetFramework)\</PackagePath>
</_PackageFiles>
<!-- add reference assemblies optionally?. -->
<_PackageFiles Include="[path to each project output path]\$(TargetFramework)\ref\[project name here].dll">
<BuildAction>None</BuildAction>
<PackagePath>ref\$(TargetFramework)\</PackagePath>
</_PackageFiles>
<!-- add docs to reference assemblies too?. -->
<_PackageFiles Include="[path to each project output path]\$(TargetFramework)\[project name here].xml">
<BuildAction>None</BuildAction>
<PackagePath>ref\$(TargetFramework)\</PackagePath>
</_PackageFiles>
<!-- include pdbs and source code by somehow manually making an snupkg file using all of the above
project information ^. -->
<!-- any other build artifacts that you want to include in the AIO package like msbuild task files
to an msbuild task project you optionally want to include with the other projects so consumers
can use the task too. -->
</ItemGroup> The issue is marking the dummy csproj file as something that must not be compiled but to basically only generate an nuspec to use for packing. Another option is to possibly manually add the dependencies to each project into the dummy project, then skip step 2 to ensure each project you want embeeded into the package does not sneak into the |
Everyone is coming up with elaborate ways to avoid having to create a 15-20 line XML file (nuspec) that will do exactly as you instruct it to do. |
What everyone wants is a tidy solution where they only have to specify things in one place. The problem with going back to nuspec files is they're a second source of truth, and can diverge from how things are set up in your projects. It's not a case of avoiding having an extra 20 line file, it's a case of avoiding having a file that can become stale with no easy way of automatically detecting the problem. The nuget integration into msbuild is great, but it has some rather large holes, for what seems to be fundamental functionality. When you run into these problems, it makes the integration seem incomplete. |
@StingyJack true that. I was also searching a lot and I find creating nuspec the easiest way.
With this one, we can replace using build artifacts with nugets (in example of azure devops). |
@roofiq - the obj folder is for temporary compilation and other transient stuffs, so its a bad idea to try to use anything from an obj folder. The bin\Release folder is where you want to get the files if you are making a normal nuget. Yer also missing a target value and are probably pulling in way too many files. I'll usually use file elements like this so I can get the MyProject.DLL, MyProject.PDB, and MyProject.XML all packed up to support some debugging of the package and intellisense for VS. (make sure to set either "Full" or "Embedded" PDB for the Release configuration.) <files>
<file src="bin\Release\MyProject.*" target="net462" />
</files>
You are making it hard for yourself in a few ways. You cant deploy a nuget package from a release pipeline with the easy to use, built in tooling. Also programs are not packages. Except if you are actually making Chocolatey packages (that use the nupkg format but are still not nuget packages) and using chocolatey to install apps. I dont get the appeal of using a nuget package format and all the rules around packing it instead of an artifact (a plain zip of the published projects from the build). You probably also lose all of the artifact retention stuff that happens with a release pipeline by not using artifacts. |
@StingyJack - thanks for the long answer
Basically the point of my answer, was that we want to switch from using build artifacts to artifact feeds. So my task was to come up how we can easily pack project, that has mutliple dependencies. So to sum up, if we would simply point |
@roofiq that depends on how your build setup is, if the build is complex where you need to package like:
The crazy shit is that somehow the files to the .NET Core SDK binaries and runtimes are all packed into a single large ass package, how the f**k did they do it when we cant simply replicate that shit. This all feels like defacto b******t to me that they can do it, yet we cannot easily do the same. All I want is to provide all my projects into a single package instead of the 10+ packages they are now that I am now having issues with maintaining the shit and then trying to find time for other development work on other things as well. But like man the hell is wrong with the fact that .NET Core can do this on their packages, yet we cannot. There even lacks the documentation on how you can make your own |
@roofiq - Yes, but it is going to depend on if you are packaging assemblies or programs in this way. When you refer to build artifacts, those are usually going to be programs (Web Apps, Windows desktop apps, Web Sites, WPF, AWS Lambda, Azure Function/webjob, etc.) and sometimes other things like config files. Making these into nuget packages adds complexity because you go from a simple zipped build artifact that can be unzipped and xcopied for deploying to a nupkg (also zipped, but a container with a very specific format that you need to try to make your application fit into and then extract back out of). I'm thinking you may mean programs because the path that you were getting the files from looks like where Published apps go when you dont specify a publish path. If you had been putting your dll's by themselves into build artifacts than the answer to your question is definitely Yes, point to the bin\Release and pack/push. Just dont forget to generate and pack PDB's and XML comment files in there too (these are not required but this is far easier to do than to setup and configure symbol servers, add symbol publishing to a pipeline, then update every dev;'s visual studio instance to use the symbol server).
@AraHaan - I'm actually at a loss for understanding what you mean by "SDK", an example may help, but please open a different issue for what you need cos it doesnt seem aligned with this topic. Feel free to tag me. The large packages you see are actually metapackages and dont contain files. |
Sad we are now on .Net 5 and this is still an issue... I do not see any progress on this... |
I found something that works however it would need some edits to work for satellite assemblies too. https://github.com/Elskom/Sdk/ |
@AraHaan - those nuspec files are really, really over-worded. Rather than tangent this thread further I'm going to open an issue on the repo you linked to share some ideas with you that may reduce your maintenance pains. I'll link it here for anyone who wants to follow. |
Steps
dotnet new --type lib
two .csproj class libraries: projectA and projectB.<TargetFramework>
to<TargetFrameworks>
if you don't have #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: