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 analyzer conflicts
            var analyzerItems = GetConflictTaskItems(Analyzers, ConflictItemType.Analyzer).ToArray();

            using (var analyzerConflictScope = new ConflictResolver <ConflictItem>(packageRanks, packageOverrides, log))
            {
                analyzerConflictScope.ResolveConflicts(analyzerItems, ci => ci.FileName, HandleAnalyzerConflict);
            }

            // 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);
            AnalyzersWithoutConflicts  = RemoveConflicts(Analyzers, analyzerConflicts);
            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.

            var referenceItemSpecs = new HashSet <string>(ReferencesWithoutConflicts?.Select(r => r.ItemSpec) ?? Enumerable.Empty <string>(),
                                                          StringComparer.OrdinalIgnoreCase);

            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))
                                                    //  Don't add a reference if we already have one (especially in case the existing one has
                                                    //  metadata we want to keep, such as aliases)
                                                    .Where(simplename => !referenceItemSpecs.Contains(simplename))
                                                    .Select(r => new TaskItem(r)));
        }
Пример #2
0
        protected override void ExecuteCore()
        {
            var log              = new MSBuildLog(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));
                });
            }

            // resolve conflicts at compile time
            var referenceItems = GetConflictTaskItems(References, ConflictItemType.Reference).ToArray();

            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);
            }

            // resolve conflicts that class in output
            var runtimeConflictScope = new ConflictResolver <ConflictItem>(packageRanks, packageOverrides, log);

            runtimeConflictScope.ResolveConflicts(referenceItems,
                                                  ci => ItemUtilities.GetReferenceTargetPath(ci.OriginalItem),
                                                  HandleRuntimeConflict);

            var copyLocalItems = GetConflictTaskItems(ReferenceCopyLocalPaths, ConflictItemType.CopyLocal).ToArray();

            runtimeConflictScope.ResolveConflicts(copyLocalItems,
                                                  ci => ItemUtilities.GetTargetPath(ci.OriginalItem),
                                                  HandleRuntimeConflict);

            var 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.
            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, pi => { });
            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);
        }