-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
Reference transitive not working when app and libs has different targetFramework #2571
Comments
@joperezr @ericstj is this something you could look into? |
@yyjdelete Does your ConsoleApp5.csproj have a <PropertyGroup>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
</PropertyGroup> After that, do a |
This blog post contains more info on this problem and the resolution I provided above: https://www.hanselman.com/blog/ReferencingNETStandardAssembliesFromBothNETCoreAndNETFramework.aspx |
@joperezr It's not the case. net472 app So you get |
Can you share an binlog of your build so that we can investigate a bit more? to produce a binlog run the following command on a developer command prompt: |
@joperezr |
I see, I'm able to repro your issue. It is very weird, if I remove the condition on the ClassLibrary2.csproj |
@nkolev92 I think this is a NuGet bug, can you take a look? The issue is there is a .NET Framework app which references a .NET Standard Library, which references a library multi-targeted to .NET Standard and .NET Framework which conditionally references System.Data.SqlClient only for .NET Standard. The System.Data.SqlClient doesn't seem to be flowing through to the .NET Framework app, even though it ends up consuming the .NET Standard version of the multi-targeted library. Repro is here: https://github.com/yyjdelete/test_dotnet_indirect_dependency |
I think this is expected/by design as far as NuGet is concerned. There could in theory be 2 different edges to ClassLibrary2, that come through different target framework pivots, so for that reason, NuGet always selects the best matching for that particular project/package in an isolated fashion. |
@nkolev92 correct me if I'm wrong but if the references to ClassLibrary1 and 2 were via NuGet packages and not ProjectReferences, I believe the right dependency would be detected and would flow correctly. If so, it doesn't seem to be the correct behavior in case that was by design. |
I verified that, and it does not seem to be the case. "targets": {
".NETFramework,Version=v4.7.2": {
"ClassLibrary1/1.0.0": {
"type": "package",
"dependencies": {
"ClassLibrary2": "1.0.0"
},
"compile": {
"lib/netstandard2.0/ClassLibrary1.dll": {}
},
"runtime": {
"lib/netstandard2.0/ClassLibrary1.dll": {}
}
},
"ClassLibrary2/1.0.0": {
"type": "package",
"compile": {
"lib/net472/ClassLibrary2.dll": {}
},
"runtime": {
"lib/net472/ClassLibrary2.dll": {}
}
}
},
} Let me know if you do see something different, but I think NuGet's behavior is as expected here. |
So the problem here is that the ClassLibrary1 is relying on the transitive dependency from ClassLibrary2 to deliver SQL client. ClassLibrary2 is actually malformed to remove compile-time dependencies from a compatible target framework. A library need to consider both the API it exposes, and any packages it depends on as part of its public contract. This is the reason why we are very careful in CoreFx to choose which packages we expose to the compiler vs just reference for runtime consumption. We had a similar problem in CoreFx years back and specifically made our packaging infra catch this and promote those dependencies. Here's that commit: dotnet/buildtools@98119a0. Now the code lives in arcade and has gone through a few iterations to handle other cases but it still addresses this type of issue. NuGet could do a couple things here:
|
I've seen issues like this quite often, and there are some related asks from customers wanting to avoid taking compile time dependencies on transitively delivered libraries. Related issue: https://github.com/NuGet/Home/issues/6720|
I like this but it might raise too many warnings. Especially in the .NET Framework/.NET Standard2.0 multi targeting worlds.
NuGet doesn't spy on the assemblies today, but I'd be excited to explore what we can do here. I'll move some of this ideas to NuGet/Home and we can continue the discussion there. |
2 is effectively what we do in CoreFx to build our packages, though we use it as the source of truth for dependencies rather than a source for validation. |
@nkolev92 I'll close this issue since the questions seems to be answered. Feel free to reopen if you'd like to continue the conversation. |
Maybe two issues, and not sure where to report it(microsoft/msbuild, dotnet/sdk, dotnet/corefx, dotnet/standard; dotnet/project-system, visualstudio; etc?), so copy it from dotnet/sdk#3103.
Issue Title
Reference transitive not working when app and lib has different targetFramework, and the lib use an transitive reference from special targetFramework of an multi-targetFramework PackageReference/ProjectReference
General
Tested with dotnet-sdk : 3.0.100-preview3-010431, 2.1.504 and some other version
Run ConsoleApp5 in https://github.com/yyjdelete/test_dotnet_indirect_dependency
And see an FileNotFoundException for System.Data.SqlClient, Version=4.5.0.0(Ignore the MissingMethodException, as it's expected). The same if replace
ClassLibrary1
andClassLibrary2
with packed.nupkg
Project struct:
Expected:
The
System.Data.SqlClient
should be include in the output bins ofConsoleApp5
, if used byClassLibrary1(netstandard2.0)
.Or at least give an warning, to make people know which Reference must be added explicitly. It's almost impossibe to find all of them by hand in an project with deep reference transitive(can also be something in nupkg).
VisualStudio should show the same result of project struct as the output does, and
System.Data.SqlClient
should be include again withClassLibrary1(netstandard2.0)
if it's removed withClassLibrary2(net472)
I already know it's reasonable to reference
ClassLibrary2
withnet472
(runtime) instead ofnetstandard2.0
, so ignore theMissingMethodException
.Actual:
System.Data.SqlClient
is missing from the output, even it's used byClassLibrary1(netstandard2.0)
, and get anFileNotFoundException
when execute.The text was updated successfully, but these errors were encountered: