Skip to content
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

Transitive dependency items not attached for all target frameworks when multi-targeting #6832

Closed
drewnoakes opened this issue Jan 13, 2021 · 7 comments · Fixed by NuGet/NuGet.Client#5507
Assignees
Labels
Feature-Dependency-Node "Dependencies" node in Solution Explorer that display project, binary & package references Regression Regressions from a previous (typically public) build or release. Triage-Approved Reviewed and prioritized
Milestone

Comments

@drewnoakes
Copy link
Member

Following the merge of PR #6712 (which fixed several bugs) we see some package and project reference nodes not having their children populated for multi-targeting projects. That PR changed the representation of the target we store on these items, which is now no longer understood by the code that attaches these children.

We are no longer parsing the TargetFramework dimension to produce a sanitised version for external consumption. Internally this works well enough as an opaque identifier, however it breaks when we communicate that information externally, in this case to the code in NuGet.Client that populates descendents of package and project references.

The fix is likely to capture whatever property values we need information from the ConfiguredProject and pass that throughout the system in our TargetFramework class. There are some rough edges here that will make this challenging and require careful thought.

@drewnoakes drewnoakes added Bug Regression Regressions from a previous (typically public) build or release. Feature-Dependency-Node "Dependencies" node in Solution Explorer that display project, binary & package references labels Jan 13, 2021
@drewnoakes drewnoakes self-assigned this Jan 13, 2021
@jjmew jjmew added this to the 16.10 milestone Jan 29, 2021
@jjmew jjmew added the Triage-Approved Reviewed and prioritized label Jan 29, 2021
@drewnoakes drewnoakes modified the milestones: 16.10, 16.11 May 11, 2021
@drewnoakes drewnoakes modified the milestones: 16.11, 17.x Oct 6, 2021
@drewnoakes drewnoakes changed the title Failing to attach children to package/project references of multi-targeting projects Transitive dependency items not attached for all target frameworks when multi-targeting May 10, 2023
@drewnoakes
Copy link
Member Author

When a project is multi-targeting, the code in NuGet.Client that attaches transitive dependency information to dependency nodes must determine which target each item belongs to.

This doesn't work correctly for certain target framework kinds today.

Given:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFrameworks>net472;net481;netcoreapp3.1;netstandard2.1;net5.0;net6.0;net7.0</TargetFrameworks>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="MetadataExtractor" Version="2.8.0" />
  </ItemGroup>

</Project>

We see:

image

Only net5.0, net6.0 and net7.0 have children attached. The others are not expandable, indicating attachments failed.

The reason for this is inconsistent treatment of the target identifier in the project.assets.json file:

image

These are two different kinds of values, which makes this mapping difficult. Perhaps we need to store both the alias and the TFM on the target node, so the NuGet code can try and find either. Or NuGet could settle on a single identifier in this file. Or something else.

The JSON file does have, under project.restore:

image

So perhaps it could map these back, however they appear in a different order, and I can't see any other way in the data model to do that mapping such that we have only a single kind of identifier.

@drewnoakes
Copy link
Member Author

TODO investigate any relationship to NuGetTargetMoniker.

@drewnoakes
Copy link
Member Author

Another scenario to test:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFrameworks>net35;net35-client</TargetFrameworks>
  </PropertyGroup>

  <PropertyGroup Condition="'$(TargetFramework)' == 'net35-client'">
    <TargetFrameworkIdentifier>.NETFramework</TargetFrameworkIdentifier>
    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
    <TargetFrameworkProfile>Client</TargetFrameworkProfile>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="MetadataExtractor" Version="2.8.0" Condition="'$(TargetFramework)' == 'net35-client'" />
  </ItemGroup>

</Project>

image

image

@drewnoakes
Copy link
Member Author

Another case of this is specifying net6.0-windows in the project file, and the assets file using net6.0-windows7.0 instead.

@zivkan
Copy link
Member

zivkan commented Nov 16, 2023

@drewnoakes assuming the assets file was parsed with NuGet.ProjectModel (and therfore LockFileFormat.Read), you can find the TFM "alias" under assetsFile.PackageSpec.TargetFrameworks[]. This list contains objects of type TargetFrameworkInformation where you can use string TargetAlias to match the TargetFramework from the project, then use NuGetFramework FrameworkName to get the parsed framework object. Then, you use that to match == assetsFile.Targets[x].TargetFramework (and you might also want to check string.IsNullOrEmpty(target.RuntimeIdentifier), but I think the no RID target should always be first.

Note that API might change when NuGet/Home#5154 is implemented

If you're not parsing with NuGet.ProjectModel, look at json path $/project/frameworks[]/targetAlias. This will definitely change when the feature is implemented

drewnoakes added a commit to NuGet/NuGet.Client that referenced this issue Nov 17, 2023
…projects

Fixes dotnet/project-system#6832

The "target name" used in the project model can take different forms. For example, both `net8.0` and `.NETFramework,Version=v4.8.1` are valid values. The dependencies tree uses the "target alias" for its target nodes, in multi-target projects. This is because two different aliases can resolve to the same TFM, for example, yet attached items may differ.

This change digs the alias out of the lock file and uses that value throughout. It also renames a property and fixes the documentation on it so as to avoid confusion.
@drewnoakes
Copy link
Member Author

Thanks @zivkan. That was really helpful. I filed NuGet/NuGet.Client#5507 which fixes this issue.

Note that API might change when NuGet/Home#5154 is implemented

That's fine, as the code is in the NuGet.Client solution so will be included in any refactoring there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature-Dependency-Node "Dependencies" node in Solution Explorer that display project, binary & package references Regression Regressions from a previous (typically public) build or release. Triage-Approved Reviewed and prioritized
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants