Skip to content

Publish postprocessing logic doesn't account for conflicts #39107

Open
@sbomer

Description

@sbomer

The Publish logic that computes the assemblies to postprocess misses assemblies which were picked by conflict resolution during publish. This results for example in illink not getting a chance to process such assemblies.

To Reproduce

Add a reference to Microsoft.Diagnostics.Tracing.TraceEvent version 3.0.2:

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

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net9.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <SelfContained>true</SelfContained>
    <!-- <PublishTrimmed>true</PublishTrimmed> -->
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="3.0.2" />
  </ItemGroup>

</Project>

dotnet publish -v:d. Note that the output has:

Encountered conflict between 'CopyLocal:/home/svbomer/.nuget/packages/microsoft.diagnostics.tracing.traceevent/3.0.2/lib/netstandard2.0/Dia2Lib.dll' and 'CopyLocal:/home/svbomer/.nuget/packages/microsoft.diagnostics.tracing.traceevent/3.0.2/lib/netstandard1.6/Dia2Lib.dll'. Choosing 'CopyLocal:/home/svbomer/.nuget/packages/microsoft.diagnostics.tracing.traceevent/3.0.2/lib/netstandard1.6/Dia2Lib.dll' arbitrarily as both items are copy-local and have equal file and assembly versions.

There is a conflict between the netstandard1.6 and netstandard2.0 versions of Dia2Lib.dll, and the conflict resolution picks one and continues.

Now uncomment the <PublishTrimmed> setting in the project file and publish again. Notice that the illink.dll invocation in the log does not pass Dia2Lib.dll.

Further technical details

I see that RuntimeCopyLocalItems has a netstandard2.0 version of Dia2Lib, but ResolvedFileToPublish has a netstandard1.6 version, so the two don't unify in the logic which computes the set of assemblies to postprocess:

<JoinItems Left="@(_ManagedRuntimeAssembly)" Right="@(ResolvedFileToPublish)" RightMetadata="*">
<Output TaskParameter="JoinResult" ItemName="_AssemblyToPostprocessOnPublish" />
</JoinItems>

_AssemblyToPostprocessOnPublish doesn't contain Dia2Lib.

Compare this to the Publish conflict resolution logic:

<ResolveOverlappingItemGroupConflicts ItemGroup1="@(_ResolvedCopyLocalPublishAssets->Distinct())"
ItemGroup2="@(ResolvedFileToPublish->Distinct())"
PreferredPackages="$(PackageConflictPreferredPackages)">
<Output TaskParameter="RemovedItemGroup1" ItemName="_ResolvedCopyLocalPublishAssetsRemoved" />
<Output TaskParameter="RemovedItemGroup2" ItemName="ResolvedFileToPublishRemoved" />
</ResolveOverlappingItemGroupConflicts>

This compares ResolvedFileToPublish with _ResolvedCopyLocalPublishAssets (which is populated earlier from RuntimeCopyLocalItems), and chooses one to include in the output.

I think the root cause is this discrepancy between the filtering in these two places. Seems like the logic that computes assemblies to postprocess should operate on the previously filtered set, without doing its own different filtering.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions