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

Use correct target path for runtimeTargets items when resolving conflicts #1565

Merged
merged 11 commits into from
Sep 14, 2017

Conversation

dsplaisted
Copy link
Member

@dsplaisted dsplaisted commented Sep 6, 2017

Fixes #1510

EDIT: Also fixes #1465 now

@nguerrera @ericstj @eerhardt for review

@dsplaisted
Copy link
Member Author

@dotnet-bot test Windows_NT_FullFramework Debug

@nguerrera
Copy link
Contributor

We should fix related #1465 at the same time. We set "Destination Sub Path" too late there. We should be setting it when resolving "all copy local items".

(Aside: it's unfortunate that we use an item list called "all copy local items" for purposes other than copying things locally now.)

I think we can get the correct sub path from the joined file definition locale rather than the path convention we use now.

@@ -32,10 +32,14 @@ Copyright (c) .NET Foundation. All rights reserved.


<!-- Also include RuntimeTarget items, which aren't included in AllCopyLocalItems, but need to be considered
for conflict resolution -->
for conflict resolution. Set DestinationSubPath for these items so that conflict resolution will consider
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we need some sort of condition on this for frameworks that don't understand RuntimeTarget items, or did you have you decided that you're adding the RuntimeTarget concept to desktop?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This just tries to match the path that will come out of PublishAssembliesResolver here when doing conflict resolution. If you have a package that assumes that native assets under runtimes/ will be loaded when used in an AnyCPU .NET Framework app, then those assets will be placed in the runtimes/ subfolders when the app is published and will fail to load at runtime. This doesn't change that.

If you publish for a specific RID, then the items will be runtime items instead of runtimeTargets items and will get copied directly to your output folder, and conflict resolution will use the right path. For example, under the .NETCoreApp,Version=v2.0 target in an assets file:

"System.Diagnostics.TraceSource/4.0.0": {
  "type": "package",
  "dependencies": {
    "Microsoft.NETCore.Platforms": "1.0.1",
    "System.Collections": "4.0.11",
    "System.Diagnostics.Debug": "4.0.11",
    "System.Globalization": "4.0.11",
    "System.Resources.ResourceManager": "4.0.1",
    "System.Runtime": "4.1.0",
    "System.Runtime.Extensions": "4.1.0",
    "System.Threading": "4.0.11",
    "runtime.native.System": "4.0.0"
  },
  "compile": {
    "ref/netstandard1.3/System.Diagnostics.TraceSource.dll": {}
  },
  "runtimeTargets": {
    "runtimes/unix/lib/netstandard1.3/System.Diagnostics.TraceSource.dll": {
      "assetType": "runtime",
      "rid": "unix"
    },
    "runtimes/win/lib/netstandard1.3/System.Diagnostics.TraceSource.dll": {
      "assetType": "runtime",
      "rid": "win"
    }
  }
},

While for the .NETCoreApp,Version=v2.0/win10-x64 target, it looks like this:

"System.Diagnostics.TraceSource/4.0.0": {
  "type": "package",
  "dependencies": {
    "Microsoft.NETCore.Platforms": "1.0.1",
    "System.Collections": "4.0.11",
    "System.Diagnostics.Debug": "4.0.11",
    "System.Globalization": "4.0.11",
    "System.Resources.ResourceManager": "4.0.1",
    "System.Runtime": "4.1.0",
    "System.Runtime.Extensions": "4.1.0",
    "System.Threading": "4.0.11",
    "runtime.native.System": "4.0.0"
  },
  "compile": {
    "ref/netstandard1.3/System.Diagnostics.TraceSource.dll": {}
  },
  "runtime": {
    "runtimes/win/lib/netstandard1.3/System.Diagnostics.TraceSource.dll": {}
  }
},

Copy link
Member

@ericstj ericstj Sep 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand, I'm talking about the desktop case where runtimeTargets are meaningless since nothing knows how to load them. If you'd like you can treat that separately but make sure we have an issue on it.

@dsplaisted
Copy link
Member Author

@nguerrera @ericstj @eerhardt I've also added a fix for #1465 to this now, at @nguerrera's suggestion

@dsplaisted
Copy link
Member Author

@dotnet-bot test this please

@dsplaisted dsplaisted force-pushed the 1510-conflict-resolution branch 2 times, most recently from feee7a8 to 38f6751 Compare September 11, 2017 21:46
@dsplaisted
Copy link
Member Author

@dotnet-bot test OSX10.12 Release

@sbomer
Copy link
Member

sbomer commented Sep 12, 2017

Just stumbled across this PR because I was looking into a related issue where the trimming logic doesn't handle resource dlls. I'm wondering: would it make sense to use DestinationSubPath instead of DestinationSubDirectory for satellite assemblies? This would seem more consistent to me, and would require less of a special case for satellite assemblies in GetTargetPath.

@dsplaisted
Copy link
Member Author

@sbomer DestinationSubDirectory is what MSBuild uses when copying CopyLocal files to the output path: https://github.com/Microsoft/msbuild/blob/9ed9a33898750567e1ac653174038e542158cf02/src/Tasks/Microsoft.Common.CurrentVersion.targets#L4236

The SDK uses DestinationSubPath for some things, perhaps it should have used the same name. :-\

@sbomer
Copy link
Member

sbomer commented Sep 13, 2017

@dsplaisted That's a bit unfortunate. Thanks for the explanation!

@wli3
Copy link

wli3 commented Sep 13, 2017

26m13.112s on my machine

@dsplaisted dsplaisted changed the base branch from release/2.0.0 to release/2.0-vs September 14, 2017 19:05
@dsplaisted
Copy link
Member Author

Customer scenario

Use System.Security.Cryptography.Algorithms in project targeting .NET Framework and AnyCPU. (The fix applies to a lot of scenarios involving conflict resolution. For some of those, the impact is only spurious conflict messages in the build log. The scenario with System.Security.Cryptography.Algorithms, however, is an example of a case that leads to a runtime failure.)

Bugs this fixes

#1510 and #1465

Workarounds, if any

A workaround for one of the scenarios was to add the following:

  <Target Name="WorkaroundConflictResolution" AfterTargets="_ComputeActiveTFMFileDependencies"
          Condition="'$(PlatformTarget)' == 'AnyCPU' And '$(TargetFrameworkIdentifier)' == '.NETFramework'">
    <ItemGroup>
      <_ActiveTFMFileDependencies Remove="@(_ActiveTFMFileDependencies->WithMetadataValue('FileGroup', 'RuntimeTarget'))" />
    </ItemGroup>
  </Target>

For other scenarios, other workarounds may be necessary.

Risk

Low - changes are targeted to consider extra information during conflict resolution

Performance impact

Low

Root cause analysis

One of the inputs to conflict resolution is the path that a file would be published to. We're not actually publishing so we are essentially duplicating part of that logic for conflict resolution. The "duplicated" logic didn't take into account some cases where the target path would be in a subfolder of the output.

How was the bug found?

Customer and internal reports

@MattGertz for approval

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants