NuGet / Home

Repo for NuGet Client issues
Other
1.49k stars 250 forks source link

Transitively include targets and content files from referenced packages #9474

Open MikeRosoft opened 4 years ago

MikeRosoft commented 4 years ago

Scenario: I have a solution with many projects, which we want to publish as NuGet packages. (In addition, we want to be able to debug them in Visual Studio.) The projects reference each other, and also reference other NuGet packages, e.g. to bring unmanaged libraries to project output.

By default, when I reference a NuGet package, its build targets and content files are brought to the first referencing project, but not to the projects that reference it. The same happens if I reference a package indirectly (project X references package A, package A references package B, package B has build targets and/or content files).

But this also causes the build target to be excluded by the package generated by dotnet pack / msbuild /t:Pack. The generated package has the following dependency declarations: <dependency id="PackageName" version="PackageVersion" exclude="Build,Analyzers" /> So the the package built from the project will ignore the build targets of the referenced package - if I reference this package in another project, they won't be executed (the files won't be brought to the project output).

Option 1: Set PrivateAssets. This is a problem, because I have to set this for every package and project reference in the solution, and there can be perhaps a hundred of them. In addition, this changes the behavior during the build, causing them to be executed in every referencing project. (As above, I only want the target to be executed once during build, and also I want it to be executed once if the generated package is referenced by another project.)

Option 2: Use buildTransitive. This requires me to modify every package in question, which may not be under my control. In addition, what will happen if another project references my project? Will this cause the transitive target to be executed again by the referencing project? (Again, this is behavior which I don't want.)

Option 3: Hook to some MsBuild target and modify the generated nuspec file before packing. I didn't succeed with that. If I run msbuild /t:Pack, then if I execute my target before GenerateNuspec, the nuspec file doesn't exist yet; if I run it after GenerateNuspec, it is too late because it has already been packed into the package. (In addition - as far as I know - there is no property containing the location of the nuspec file.) If I run msbuild /t:GenerateNuspec;Pack, it doesn't pack anything.

What other options are there? I want to preserve the default behavior of Visual Studio when building (to not bring the imported targets to referencing projects, and to instead depend on the copying of the output directory), but I also want to preserve the default behavior of NuGet (do not generate the exclude declarations to modify the default behavior; or, alternately, to perform arbitrary modification of the generated nuspec file and remove them before packing).

See related issues: https://github.com/dotnet/sdk/issues/1266 , https://github.com/NuGet/Home/issues/3697 , https://github.com/NuGet/Home/issues/6388 .

emamontov commented 4 years ago

Same issue here...

We have thousands(!!!) of native/mixed/managed nuget packages that are using only "*.targets" files for reference and content injection, which works same for any project type(csproj,vcxproj...). There are several reasons why we use custom targets:

  1. It supports mix environment, where C#, C++ and C++/CLI reference each other like they are of the same type
  2. It supports debug and release versions to put in the same nuget (Yeah! Development environment require debug too!)
  3. It created before PackageReference and VS2017 were exists at all.
  4. After 5 years, original nuget still does not support the #1 and #2

Now, some teams are moving to the new Pack method, and this issue makes it very annoying. It actually breaks the community's "default expected" behavior, while migrating from VS2015 environment to VS2017+

Thieum commented 3 years ago

Here is a repro project I put together when describing the issue to @terrajobst in https://twitter.com/terrajobst/status/1376570583001931778?s=20 :

https://github.com/Thieum/PackageRefTargetsLost

MichaelKetting commented 2 years ago

I've git this issue, too. An update would be appriciated.

msedi commented 1 year ago

We are having similar issues with many packages and need to add .targets to each packagem but we only want to have the content files in the output executable and not in the built reference assembly output.