in src/Tasks/Common/ConflictResolution/ResolvePackageFileConflicts.cs [55:166]
protected override void ExecuteCore()
{
var log = Log;
var packageRanks = new PackageRank(PreferredPackages);
var packageOverrides = new PackageOverrideResolver<ConflictItem>(PackageOverrides);
// Treat assemblies from FrameworkList.xml as platform assemblies that also get considered at compile time
IEnumerable<ConflictItem> compilePlatformItems = null;
if (TargetFrameworkDirectories != null && TargetFrameworkDirectories.Any())
{
var frameworkListReader = new FrameworkListReader(BuildEngine4);
compilePlatformItems = TargetFrameworkDirectories.SelectMany(tfd =>
{
return frameworkListReader.GetConflictItems(Path.Combine(tfd.ItemSpec, "RedistList", "FrameworkList.xml"), log);
}).ToArray();
}
// resolve conflicts at compile time
var referenceItems = GetConflictTaskItems(References, ConflictItemType.Reference).ToArray();
using (var compileConflictScope = new ConflictResolver<ConflictItem>(packageRanks, packageOverrides, log))
{
compileConflictScope.ResolveConflicts(referenceItems,
ci => ItemUtilities.GetReferenceFileName(ci.OriginalItem),
HandleCompileConflict);
if (compilePlatformItems != null)
{
compileConflictScope.ResolveConflicts(compilePlatformItems,
ci => ci.FileName,
HandleCompileConflict);
}
}
// Remove platform items which won a conflict with a reference but subsequently lost to something else
compilePlatformWinners.ExceptWith(allConflicts);
// resolve conflicts that clash in output
IEnumerable<ConflictItem> copyLocalItems;
IEnumerable<ConflictItem> otherRuntimeItems;
using (var runtimeConflictScope = new ConflictResolver<ConflictItem>(packageRanks, packageOverrides, log))
{
runtimeConflictScope.ResolveConflicts(referenceItems,
ci => ItemUtilities.GetReferenceTargetPath(ci.OriginalItem),
HandleRuntimeConflict);
copyLocalItems = GetConflictTaskItems(ReferenceCopyLocalPaths, ConflictItemType.CopyLocal).ToArray();
runtimeConflictScope.ResolveConflicts(copyLocalItems,
ci => ItemUtilities.GetTargetPath(ci.OriginalItem),
HandleRuntimeConflict);
otherRuntimeItems = GetConflictTaskItems(OtherRuntimeItems, ConflictItemType.Runtime).ToArray();
runtimeConflictScope.ResolveConflicts(otherRuntimeItems,
ci => ItemUtilities.GetTargetPath(ci.OriginalItem),
HandleRuntimeConflict);
}
// resolve conflicts with platform (eg: shared framework) items
// we only commit the platform items since its not a conflict if other items share the same filename.
using (var platformConflictScope = new ConflictResolver<ConflictItem>(packageRanks, packageOverrides, log))
{
var platformItems = PlatformManifests?.SelectMany(pm => PlatformManifestReader.LoadConflictItems(pm.ItemSpec, log)) ?? Enumerable.Empty<ConflictItem>();
if (compilePlatformItems != null)
{
platformItems = platformItems.Concat(compilePlatformItems);
}
platformConflictScope.ResolveConflicts(platformItems, pi => pi.FileName, (winner, loser) => { });
platformConflictScope.ResolveConflicts(referenceItems.Where(ri => !referenceConflicts.Contains(ri.OriginalItem)),
ri => ItemUtilities.GetReferenceTargetFileName(ri.OriginalItem),
HandleRuntimeConflict,
commitWinner: false);
platformConflictScope.ResolveConflicts(copyLocalItems.Where(ci => !copyLocalConflicts.Contains(ci.OriginalItem)),
ri => ri.FileName,
HandleRuntimeConflict,
commitWinner: false);
platformConflictScope.ResolveConflicts(otherRuntimeItems,
ri => ri.FileName,
HandleRuntimeConflict,
commitWinner: false);
}
ReferencesWithoutConflicts = RemoveConflicts(References, referenceConflicts);
ReferenceCopyLocalPathsWithoutConflicts = RemoveConflicts(ReferenceCopyLocalPaths, copyLocalConflicts);
Conflicts = CreateConflictTaskItems(allConflicts);
// This handles the issue described here: https://github.com/dotnet/sdk/issues/2221
// The issue is that before conflict resolution runs, references to assemblies in the framework
// that also match an assembly coming from a NuGet package are either removed (in non-SDK targets
// via the ResolveNuGetPackageAssets target in Microsoft.NuGet.targets) or transformed to refer
// to the assembly coming from the NuGet package (for SDK projects in the ResolveLockFileReferences
// task).
// In either case, there ends up being no Reference item which will resolve to the DLL in
// the reference assemblies. This is a problem if the platform item from the reference
// assemblies wins a conflict in the compile scope, as the reference to the assembly from
// the NuGet package will be removed, but there will be no reference to the Framework assembly
// passed to the compiler.
// So what we do is keep track of Platform items that win conflicts with Reference items in
// the compile scope, and explicitly add references to them here.
ReferencesWithoutConflicts = SafeConcat(ReferencesWithoutConflicts,
// The Reference item we create in this case should be without the .dll extension
// (which is added in FrameworkListReader in order to make the framework items
// correctly conflict with DLLs from NuGet packages)
compilePlatformWinners.Select(c => Path.GetFileNameWithoutExtension(c.FileName))
.Select(r => new TaskItem(r)));
}