-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
No DisableTransitiveProjectReferences analog for package references? #11803
Comments
|
Hello again, it's been a couple weeks without any indication that this was seen, so I'm pinging again for visibility. I apologize in advance if this is a faux pas; I see that many other open issues were marked for triage and assigned, so I just wanted to try to keep this question from falling between the cracks. |
Hello, it's me again 😊. It's been another few weeks without any signs so I'm just checking in to see if anyone has seen this issue. |
Hello, it's been another month without any activity. I noticed that a pull request referenced this issue, but it appears that it was unrelated. Has anyone seen this issue? Is there somewhere else we're supposed to submit things like this? |
Just making my monthly comment to show that I am still hoping for a reply 😄. |
I've come to leave my monthly comment. I see that some other issues have been marked as "Needs Triage", so I'm still hoping this will eventually be noticed. |
Another month, another comment :). I'm still hoping to hear back on the viability of this feature request. |
It's been a little over half a year with no indication that this question has been noticed. @jaredpar, as the developer who introduced the I see that other developers are hacking around the lack of an "official" solution; for example, in this NuGet issue, @KirillOsenkov explicitly copies the DLL that the project indirectly depends on into the output folder to resolve the missing-assembly-at-runtime issue. Even if the outcome of this issue is simply "working as intended, no intent to change", I would appreciate a response :) |
One way of preventing a PackageReference from flowing to referencing projects is setting PrivateAssets=“all” on the PackageReference itself. This gives you finer grained control and I think is a suitable workaround? |
@KirillOsenkov unfortunately, using
This is better than nothing, but given how convenient |
The problem we were hitting was specific to project references and hence we limited the fix to project references. |
@jaredpar that makes sense. I was wondering if there was any specific reasoning why the ability to disable transitive package references would be explicitly unwanted. For example, I could imagine a project that is published to a NuGet package (call it "Package A"), where opting out of transitive package dependencies could mean that Package A does not declare an explicit dependency on Package B in the How would you feel about a property such as |
Nope that was not the case. Think it may help a bit to explain the context of this change. This change occurred out of need as the dotnet/roslyn repository was adopting the .NET SDK and new project file format. At the time roslyn did this we were easily the largest and most complex solution that tried to ingest the SDK. This exposed a number of bugs in the SDK, VS project system, NuGet restore, etc ... Not unexpected after all this was brand new at the time and we were stressing it harder than it had been stressed before. Up until this point we had been focusing hard on not changing the scenarios and / or features of the SDK. Instead we were focusing on getting roslyn to adapt to the SDK way of doing things. The reasoning was that part of the benefit of the SDK was having a more opinionated way of doing builds which in turn would allow us to have more aggressive defaults / features that minimized the amount of build code customers had to write. This was essentially the last bug that was holding roslyn back from adopting the SDK and merging into master. We maintained the mentality of getting roslyn to have the SDK way of doing things. After a lot of discussion though we eventually decided to add this because the case was compelling. But we wanted to implement a fix specific to the scenario and not instead reset the idea of transitive dependencies. Basically wanted to keep the principles in place as much as possible. |
That all seems very reasonable to me. Just to make sure I have understood you correctly, the reasons that
Please let me know if I have misinterpreted. Now that we are far removed from this transition, would you foresee any reasons not to introduce a property like |
Correct but a bit broader. The Roslyn solution is generally seen as a good proxy for customer solutions in size and complexity. Hence the rational is generally that if Roslyn can't adopt the SDK because of problem X then it's reasonable to expect a non-trivial amount of customers will also be unable to do so.
Generally yes but I'd word it differently. Essentially the benefit of the SDK style projects over traditional MSBuild projects is the SDK was a lot more opinionated and had a larger set of defaults based off those opinions. That in turn meant we could simplify the amount of code that was put into a project file and get to the nice minimal format we have today.
Yes for Roslyn. We took the mentality that most of the decisions we had made which differed from the SDK decisions were essentially arbitrary (and they were). Hence rather than change the SDK we flipped to match the SDK way of doing things. Note: to add context on top of context i want to emphasize that while I did do the bulk of the work to convert Roslyn to the new SDK format I work for the C# compiler team, not the SDK. Hence these views here are best read as the interpretation of a knowledgeable customer, not the product team. Possible SDK team may comment later and say "well actually". Please take their word, not mine 😄 |
Understood, I look forward to hopefully hearing from the SDK team 😜. Thank you for taking the time to explain the situation to me, I truly appreciate it. I would also like to thank you for your fine work on Roslyn! |
No concrete asks on NuGet side that I am aware of. The idea needs work, since NuGet has to consider how this would affect packages, a concern that does not exist with ProjectReferences. |
Hi @dsplaisted and @nkolev92, could you explain what impact a feature like this would have on NuGet? I am admittedly unfamiliar with how package references work under-the-hood. My naive expectation was that a The documentation for Are you considering a different mechanism? |
PrivateAssets = Transitivity flow, parents won't consume. What's |
That is the behavior that I encountered when using When I say "use", I mean whatever controls which packages are allowed to be referenced by code in a given project (barring the use of reflection or other tricks). I would like a setting like Here is a small code example. I have a project named <ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.3"/>
</ItemGroup> In public class Example
{
public static string Serialize(object value)
{
return JsonConvert.SerializeObject(value, Formatting.Indented);
}
} I have a different project named <ItemGroup>
<ProjectReference Include="..\ProjectA\ProjectA.csproj" />
</ItemGroup> In using System;
using System.Collections.Generic;
using ProjectA;
namespace ProjectB
{
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine(Example.Serialize(new Dictionary<string, string>() { ["Hello"] = "World" }));
Console.ReadLine();
}
}
} Right now, there is nothing stopping me from writing something like this in using System;
using System.Collections.Generic;
using ProjectA;
using Newtonsoft; // ProjectB transitively references Newtonsoft through ProjectA If I go back to <ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.3">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup> Now, trying to write |
That would be expected in this case because newtonsoft.json is not visible at all to ProjectB. Does |
<IncludeAssets>runtime</IncludeAssets>
<PrivateAssets>all</PrivateAssets> but that results in compile errors in
Thank you for your help @nkolev92, I really appreciate it :) |
Yes it does. The reference to the package will exist, but will be listed with exclude assets compile.
Every dependency of A would need to attach the metadata. What assets are included from a package is impacted
You can use MSBuild item Update to achieve this. I understand that it's not exactly the most discoverable behavior though.
Given that Private/Include/Exclude assets provides a lot of customizability already, I think the argument that would need to be made is that this scenario is common enough to warrant a special switch. The concern would be that having many different switches could make the behavior pretty difficult to understand. |
What does this mean from the perspective of consumers of the package? That they themselves will not have transitive access to the dependencies of the package? That would be a disadvantage; my goal isn't to change the behavior for external package consumers, but rather only for internal developers.
I think the most significant argument would be that this was a change in behavior when migrating from the old
and
it sounds like the behavior I desire (an option akin to Your suggestion to use an MSBuild item Update is interesting, but according to the documentation, My main goal is to avoid having to manually attach the <PropertyGroup>
<DisableTransitiveProjectReferences>true</DisableTransitiveProjectReferences>
<DisableTransitivePackageReferences>true</DisableTransitivePackageReferences>
</PropertyGroup> I recognize that adding additional switches like this incurs a maintenance burden, and increases the cognitive load on a reader unfamiliar with what the switches do. My counterpoint would be that there is already an existing |
They wouldn't be able to compile against it, but it will be part of their runtime.
Update should be supported in VS2017 for legacy projects as well. |
|
This means that if a project defines @rainersigwald, could you show a small example of how to use |
Commenting to show I'm still interested in a solution which does not impact assembly binding redirect generation. |
Hello again, commenting to show that I am still interested in solving this. |
I'm happy I stumbled over this issue. We are looking for exactly the same feature, since we migrated over to SDK style projects for almost two years now. Adding such a feature would help to better highlight and manage direct dependencies for a far more cleaner project structure. |
I am interested in having such possibility too. This would allow me to have cleaner dependencies tree and prevent it from accidental modifications, when projects at higher levels of hierarchy become dependent on dependencies of projects at lower levels. |
Hello, checking in to show that I am still interested in finding a solution to this. |
Hi! I'm also interested in having such possibility) We already have sdk/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.PackageDependencyResolution.targets Line 261 in 15ef8b1
sdk/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.PackageDependencyResolution.targets Line 262 in 15ef8b1
Therefore it feels natural to have |
Hello, it's been a while since I last checked in. Just commenting to show that I am still interested in finding a solution for this. |
@mdrexel Hi! I am using the following in my Directory.Build.props in the root of the solution, so I don't have to specify it for each package in each project:
|
Now it's been two years. Come on guys! This one is super important! The Now, we see that transitive nuget packages are not covered by this setting. Woah, a ticking bomb for sure. To begin with, we cannot easily see (e.g. search in DisableTransitivePackageReferences to the rescue? |
This is super important, and very difficult for developers to work around, if at all. PrivateAssets\ExcludeAssets don't cut it, when the problem is pulling in the package itself. Some nugets have critical functionality, but are way overloaded on dependencies. And those dependencies take time to download, can be unavailable on secure nuget feeds, or introduce version and target framework complications. This is the biggest issue we still have in our repo, after 3 years. |
Yeah, I'll add my vote for this setting (for what it's worth). Transitive references may work well for onion architecture, but plenty of projects don't use that (and nor should they IMHO, it's often unnecessarily complex). The default transitive reference behaviour - both for projects and for packages - is undesirable when you're specifically trying to stop projects referencing things transitively like with an n-tier architecture. A presentation layer shouldn't be able to directly reference EF stuff because the data layer references it, or ImageSharp because the BLL layer references it. |
Adding my vote as well, the lack of this is causing undue headaches in library construction and compliance. I fear if this is not implemented in .NET soon, the unbroken dependency chains will create real issues in our stack. |
Adding my vote here that this feature is necessary! .NET is much more broadly applicable than, as others have put it, the "developer-friendly" way. I know the majority use-case these days is copy-deployable apps, but industry came to depend on .NET Framework features like the GAC. We have pluggable components, not just implementations but shared contracts too. We use custom assembly resolvers. We need to be able to pull just the assets we want to support our transition to .NET 6+. I am doing my best with the tools available but it could be much easier with this feature. |
I'd prefer the fix for PackageReferences transitive behavior, but I think we're able to work around some of these issues with PackageDownload. Does this work for others? https://learn.microsoft.com/en-us/nuget/consume-packages/packagedownload-functionality |
I'm grateful you pointed this feature out. It would be more convenient to be able to disable transitive package references. However, this will solve some of my immediate problems for sure. |
This is a good start, but unfortunately not a complete replacement for What is really wanted is a full separation of: (1) Allowing/disallowing a project's code to refer at compile-time to things defined in particular projects/packages, and (2) All other analysis, artifact copying, runtime resolution, etc. of the dependency supply chain. When my team transitioned from Framework to Core, we didn't even realize transitive project references had automatically become the new default. I wondered why design/architectural regressions seemed to happen so much more easily these days, and I just chalked it up to the simplified project files being less intimidating to edit by hand and thus edited more often and more carelessly. I only discovered |
I also would be happy to get such setting, as @mdrexel requested. Meanwhile, it looks like that I've managed to exclude not needed dependency like this:
It allows to have |
This seems to be solved with CPM's Transitive Pinning. |
I checked out the Central Package Management tooling. Using the If I remove that usage of Packing However, a side effect is it also causes all projects to reference the package, even if they do not include a Packing This is definitely a lot closer to the experience I would like from a hypothetical
|
I just wish PackageDownload supported GeneratePathProperty |
Transitive pinning doesn't address the issue - I don't need to pin / override a transitive dependency, I need to exclude all dependencies. Also, to note on the GlobaclPackageReference - this is a similar strategy to excluding assets from an unwanted package in that it is a version specific solution. I want to be able to update a package without pulling any new transitive dependencies, whether I knew about them previously or not. And to the point about GeneratePathProperty for PackageDownload, this is also a good thing but different than installing the assets from a package and none of its transitive dependencies. |
I wonder why there is so few attention on this issue. If I understand the current behaviour correctly, there is no good solution to encapsulate and abstract away external packages in a larger application. We converted big parts of our application still running on .NET Framework 4.8 to SDK-style projects as a first step towards .NET 8 which seemed fine in the beginning but with the transitive dependencies
I thought we had solved the problems using But now I found that As an example, I have a project With both,
because obviously the correct assembly in When I leave out the What is the proposed way of achieving the desired encapsulation? BTW: the projects all target |
Does adding this target to project file helps? <Target Name="RemoveTransitivePackageReferences" BeforeTargets="ResolveAssemblyReferences" DependsOnTargets="ResolveLockFileReferences">
<ItemGroup>
<TransitivePackageReferenceToRemove Include="%(Reference.NuGetPackageId)" Exclude="@(PackageReference)" KeepDuplicates="False" Condition="%(Reference.NuGetSourceType) == 'Package' And %(Reference.NuGetPackageId) != ''">
<NuGetPackageId>%(Reference.NuGetPackageId)</NuGetPackageId>
</TransitivePackageReferenceToRemove>
<Reference Remove="@(TransitivePackageReferenceToRemove)" MatchOnMetadata="NuGetPackageId" Condition="%(Reference.NuGetSourceType) == 'Package'" />
<TransitivePackageReferenceToRemove Remove="@(TransitivePackageReferenceToRemove)" />
</ItemGroup>
</Target> |
Issue #1750 introduced the
<DisableTransitiveProjectReferences>
property so that an SDK-style csproj project can opt out of the new implicit transitive references feature. Originally, the proposed name for the property was<DisableImplicitTransitiveReferences>
; however, during Pull Request #1751, the name was changed toDisableTransitiveProjectReferences
to explicitly indicate that only project references would exhibit a behavior change; package references would not be impacted by setting this property.(My understanding of the meanings of these phrases is as follows:
package reference
refers to NuGet package references, whileproject reference
refers to a reference to another project in the same solution.)There doesn't seem to be a mechanism to disable the transitive reference behavior for package dependencies. This makes it so that, for example, if Project A has a project reference to Project B, and Project B has a package reference to ex. Newtonsoft.Json, Project A can utilize Newtonsoft.Json without explicitly adding a package reference to it. When
PrivateAssets
is used, Project B's dependency on Newtonsoft.Json fails at runtime when called from Project A, because Newtonsoft.Json.dll is not copied to the output directory of Project A. (I'm just using Newtonsoft.Json as an example here because it's well-known and has no external dependencies when used with recent Framework/Core/Standard TFMs - this issue applies to any NuGet package dependency.)What is the motivation for this behavior? Could an analogous property be added (named like
<DisableTransitivePackageReferences>
) so that in situations like the one described above, Project A would not be able to utilize Newtonsoft.Json without explicitly adding a package reference, but Project A could still utilize Project B (which relies on the dependency directly) without encountering runtime errors due to missing assemblies?The text was updated successfully, but these errors were encountered: