public override bool Execute() { if (null == FrameworkListsPath) { Log.LogError("FrameworkListsPath argument must be specified"); return(false); } if (String.IsNullOrEmpty(AssemblyName)) { Log.LogError("AssemblyName argument must be specified"); return(false); } if (!Directory.Exists(FrameworkListsPath)) { Log.LogError("FrameworkListsPath '{0}' does not exist", FrameworkListsPath); return(false); } Log.LogMessage(LogImportance.Low, "Determining inbox frameworks for {0}, {1}", AssemblyName, AssemblyVersion); InboxFrameworks = Frameworks.GetInboxFrameworksList(FrameworkListsPath, AssemblyName, AssemblyVersion, Log); return(!Log.HasLoggedErrors); }
private IEnumerable <ITaskItem> CopyDependencies(IEnumerable <Dependency> dependencies, NuGetFramework targetFramework) { foreach (var dependency in dependencies) { if (!Frameworks.IsInbox(FrameworkListsPath, targetFramework, dependency.Id, dependency.Version)) { var copiedDepenedency = new TaskItem(dependency.OriginalItem); copiedDepenedency.SetMetadata(TargetFrameworkMetadataName, targetFramework.GetShortFolderName()); yield return(copiedDepenedency); } } }
public override bool Execute() { if (References == null || References.Length == 0) { return(true); } Dictionary <string, ITaskItem> packageReferences = new Dictionary <string, ITaskItem>(); Dictionary <string, ITaskItem> assemblyReferences = new Dictionary <string, ITaskItem>(); bool referencesMscorlib = false; NuGetFramework targetFx = NuGetFramework.Parse(TargetFramework); bool isOobFramework = targetFx.Equals(FrameworkConstants.CommonFrameworks.NetCore50) || targetFx.Framework == FrameworkConstants.FrameworkIdentifiers.UAP; foreach (var reference in References) { string referenceName = reference.ItemSpec; referencesMscorlib |= referenceName.Equals("mscorlib"); string referenceVersion = reference.GetMetadata("Version"); reference.SetMetadata("TargetFramework", TargetFramework); if (!string.IsNullOrEmpty(TargetFramework) && !isOobFramework && Frameworks.IsInbox(FrameworkListsPath, TargetFramework, referenceName, referenceVersion)) { AddReference(assemblyReferences, reference); } else { AddReference(packageReferences, reference); } } if (referencesMscorlib) { // only add framework references for mscorlib-based assemblies. FrameworkReferences = assemblyReferences.Values.ToArray(); } if (packageReferences.Count == 0) { var emptyItem = new TaskItem("_._"); emptyItem.SetMetadata("TargetFramework", TargetFramework); packageReferences.Add(emptyItem.ItemSpec, emptyItem); } PackageReferences = packageReferences.Values.ToArray(); return(true); }
public override bool Execute() { List <ITaskItem> promotedDependencies = new List <ITaskItem>(); var implementationFxs = Dependencies.Select(d => d.GetMetadata("TargetFramework")).Distinct(); var actualDependencies = Dependencies.Where(d => d.ItemSpec != "_._").Select(d => new Dependency(d)).ToArray(); var referenceSets = actualDependencies.Where(d => d.IsReference).GroupBy(d => d.TargetFramework).ToDictionary(g => NuGetFramework.Parse(g.Key), g => g.ToArray()); var candidateFxs = referenceSets.Keys.ToArray(); if (candidateFxs.Length != 0) { foreach (var implementationFx in implementationFxs) { NuGetFramework fx = NuGetFramework.Parse(implementationFx); if (referenceSets.ContainsKey(fx)) { // if this implementation assembly fx has a matching reference fx skip promotion continue; } var nearestReferenceFx = FrameworkUtilities.GetNearest(fx, candidateFxs); if (nearestReferenceFx == null) { // This should never happen and indicates a bug in the package. If a package contains references, // all implementations should have an applicable reference assembly. Log.LogError($"Could not find applicable reference assembly for implementation framework {implementationFx} from reference frameworks {string.Join(", ", referenceSets.Keys)}"); } foreach (var reference in referenceSets[nearestReferenceFx]) { var promotedDependency = new TaskItem(reference.OriginalItem); promotedDependency.SetMetadata(TargetFrameworkMetadataName, implementationFx); if (!Frameworks.IsInbox(FrameworkListsPath, implementationFx, reference.Id, reference.Version)) { promotedDependencies.Add(promotedDependency); } } } } PromotedDependencies = promotedDependencies.ToArray(); return(!Log.HasLoggedErrors); }
public override bool Execute() { var minNETStandard = Frameworks.Select(fx => NuGetFramework.Parse(fx.ItemSpec)) .Where(fx => fx.Framework == FrameworkConstants.FrameworkIdentifiers.NetStandard) .OrderBy(fx => fx.Version) .FirstOrDefault(); if (minNETStandard == null) { minNETStandard = FrameworkConstants.CommonFrameworks.NetStandard10; Log.LogMessage($"Could not find any NETStandard frameworks, defaulting to {minNETStandard}."); } MinimumNETStandard = minNETStandard.ToString(); return(!Log.HasLoggedErrors); }
/* Given a set of available frameworks ("InboxOnTargetFrameworks"), and a list of desired frameworks, * reduce the set of frameworks to the minimum set of frameworks which is compatible (preferring inbox frameworks. */ public override bool Execute() { if (null == Dependencies) { Log.LogError("Dependencies argument must be specified"); return(false); } if (null == FrameworkListsPath) { Log.LogError("FrameworkListsPath argument must be specified"); return(false); } // Retrieve the list of generation dependency group TFM's var dependencyGroups = Dependencies.GroupBy(d => d.GetMetadata("TargetFramework")).Select(dg => new { Framework = NuGetFramework.Parse(dg.Key), Dependencies = dg.ToArray() }); List <ITaskItem> addedDependencies = new List <ITaskItem>(); // Exclude any non-portable frameworks that already have specific dependency groups. var frameworksToExclude = dependencyGroups.Select(dg => dg.Framework).Where(fx => !FrameworkUtilities.IsGenerationMoniker(fx)); // Prepare a resolver for evaluating if candidate frameworks are actually supported by the package PackageItem[] packageItems = Files.Select(f => new PackageItem(f)).ToArray(); var packagePaths = packageItems.Select(pi => pi.TargetPath); var targetFrameworksWithPlaceHolders = packageItems.Where(pi => NuGetAssetResolver.IsPlaceholder(pi.TargetPath)).Select(pi => pi.TargetFramework); NuGetAssetResolver resolver = new NuGetAssetResolver(null, packagePaths); foreach (var portableDependencyGroup in dependencyGroups.Where(dg => FrameworkUtilities.IsGenerationMoniker(dg.Framework))) { // Determine inbox frameworks for this generation that don't already have explicit groups HashSet <NuGetFramework> inboxFrameworksList = new HashSet <NuGetFramework>( Frameworks.GetAlllInboxFrameworks(FrameworkListsPath) .Where(fx => !fx.IsPCL) .Where(fx => Generations.DetermineGenerationForFramework(fx, UseNetPlatform) >= portableDependencyGroup.Framework.Version && !frameworksToExclude.Any(exFx => exFx.Framework == fx.Framework && exFx.Version <= fx.Version))); // Check for assets which have a ref, but not a lib asset. If we have any of these, then they are actually not supported frameworks // and we should not include them. inboxFrameworksList.RemoveWhere(inboxFx => !IsSupported(inboxFx, resolver)); // Only add the lowest version for a particular inbox framework. EG if both net45 and net46 are supported by this generation, // only add net45 inboxFrameworksList.RemoveWhere(fx => inboxFrameworksList.Any(otherFx => (otherFx.Framework.Equals(fx.Framework)) && (otherFx.Version < fx.Version))); // Create dependency items for each inbox framework. foreach (var framework in inboxFrameworksList) { bool addedDependencyToFramework = false; foreach (ITaskItem dependency in portableDependencyGroup.Dependencies) { string version = GetVersion(dependency); if (!Frameworks.IsInbox(FrameworkListsPath, framework, dependency.ItemSpec, version)) { addedDependencyToFramework = true; AddDependency(addedDependencies, new TaskItem(dependency), framework, portableDependencyGroup.Framework); } } if (!addedDependencyToFramework) { AddDependency(addedDependencies, new TaskItem("_._"), framework, portableDependencyGroup.Framework); } } } // Collapse frameworks // For any dependency with a targetframework, if there is another target framework which is compatible and older, remove this dependency. // Get all Dependencies which are not in a portable dependency group so that we can collapse the frameworks. If we include // the portable frameworks, then we'll end up collapsing to those. List <NuGetFramework> allDependencyGroups = new List <NuGetFramework>(); allDependencyGroups.AddRange(Dependencies.Select(d => NuGetFramework.Parse(d.GetMetadata("TargetFramework"))).Where(a => !allDependencyGroups.Contains(a) && !FrameworkUtilities.IsGenerationMoniker(a) && !FrameworkUtilities.IsPortableMoniker(a))); allDependencyGroups.AddRange(addedDependencies.Select(d => NuGetFramework.Parse(d.GetMetadata("TargetFramework"))).Where(a => !allDependencyGroups.Contains(a) && !FrameworkUtilities.IsGenerationMoniker(a) && !FrameworkUtilities.IsPortableMoniker(a))); List <NuGetFramework> collapsedDependencyGroups = FrameworkUtilities.ReduceDownwards(allDependencyGroups).ToList <NuGetFramework>(); // Get the list of dependency groups that we collapsed down so that we can add them back if they contained different dependencies than what is present in the collapsed group. /* TODO: Look into NuGet's sorting algorithm, they may have a bug (fixed in this line). They were not including version in the sort. * See ReduceCore in https://github.com/NuGet/NuGet.Client/blob/23ea68b91a439fcfd7f94bcd01bcdee2e8adae92/src/NuGet.Core/NuGet.Frameworks/FrameworkReducer.cs */ IEnumerable <NuGetFramework> removedDependencyGroups = allDependencyGroups.Where(d => !collapsedDependencyGroups.Contains(d))?.OrderBy(f => f.Framework, StringComparer.OrdinalIgnoreCase).ThenBy(f => f.Version); foreach (NuGetFramework removedDependencyGroup in removedDependencyGroups) { // always recalculate collapsedDependencyGroups in case we added an item in a previous iteration. Dependency groups are sorted, so this should be additive and we shouldn't need to restart the collapse / add back cycle var nearest = FrameworkUtilities.GetNearest(removedDependencyGroup, collapsedDependencyGroups.ToArray()); // gather the dependencies for this dependency group and the calculated "nearest" dependency group var nearestDependencies = addedDependencies.Where(d => nearest.Equals(NuGetFramework.Parse(d.GetMetadata("TargetFramework")))).OrderBy(f => f.ToString()); var currentDependencies = addedDependencies.Where(d => removedDependencyGroup.Equals(NuGetFramework.Parse(d.GetMetadata("TargetFramework")))).OrderBy(f => f.ToString()); // The nearest dependency group's dependencies are different than this dependency group's dependencies if (nearestDependencies.Count() != currentDependencies.Count()) { // ignore if dependency is a placeholder if (currentDependencies.Count() > 0) { if (!NuGetAssetResolver.IsPlaceholder(currentDependencies.First().ToString())) { collapsedDependencyGroups.Add(removedDependencyGroup); } } else { collapsedDependencyGroups.Add(removedDependencyGroup); } } // identical dependency count between current and nearest, and the count is > 0 else if (nearestDependencies.Count() > 0) { if (!currentDependencies.SequenceEqual(nearestDependencies, new DependencyITaskItemComparer())) { collapsedDependencyGroups.Add(removedDependencyGroup); } } } List <ITaskItem> collapsedDependencies = new List <ITaskItem>(); foreach (ITaskItem dependency in addedDependencies) { if (collapsedDependencyGroups.Contains(NuGetFramework.Parse(dependency.GetMetadata("TargetFramework")))) { collapsedDependencies.Add(dependency); } } TrimmedDependencies = collapsedDependencies.ToArray(); return(!Log.HasLoggedErrors); }
/* Given a set of available frameworks ("InboxOnTargetFrameworks"), and a list of desired frameworks, * reduce the set of frameworks to the minimum set of frameworks which is compatible (preferring inbox frameworks. */ public override bool Execute() { if (null == Dependencies) { Log.LogError("Dependencies argument must be specified"); return(false); } if (null == FrameworkListsPath) { Log.LogError("FrameworkListsPath argument must be specified"); return(false); } // Retrieve the list of generation dependency group TFM's Dictionary <string, IEnumerable <ITaskItem> > portableDependencyGroups = new Dictionary <string, IEnumerable <ITaskItem> >(); foreach (ITaskItem dependency in Dependencies) { string framework = dependency.GetMetadata("TargetFramework"); if (framework != null && FrameworkUtilities.IsGenerationMoniker(framework) && !portableDependencyGroups.ContainsKey(framework)) { portableDependencyGroups.Add(framework, Dependencies.Where(d => d.GetMetadata("TargetFramework") == framework)); } } List <ITaskItem> addedDependencies = new List <ITaskItem>(); List <string> placeHolderFrameworks = new List <string>(); var frameworksToExclude = TrimFrameworks?.Select(fx => NuGetFramework.Parse(fx))?.ToArray() ?? new NuGetFramework[0]; // Prepare a resolver for evaluating if candidate frameworks are actually supported by the package PackageItem[] packageItems = Files.Select(f => new PackageItem(f)).ToArray(); var packagePaths = packageItems.Select(pi => pi.TargetPath); var targetFrameworksWithPlaceHolders = packageItems.Where(pi => NuGetAssetResolver.IsPlaceholder(pi.TargetPath)).Select(pi => pi.TargetFramework); NuGetAssetResolver resolver = new NuGetAssetResolver(null, packagePaths); foreach (string portableDependency in portableDependencyGroups.Keys) { NuGetFramework portableDependencyFramework = NuGetFramework.Parse(portableDependency); // Determine inbox frameworks for this generations dependencies as a whole HashSet <NuGetFramework> inboxFrameworksList = new HashSet <NuGetFramework>(); foreach (NuGetFramework inboxFramework in Frameworks.GetAlllInboxFrameworks(FrameworkListsPath)) { if (Generations.DetermineGenerationForFramework(inboxFramework, UseNetPlatform) >= portableDependencyFramework.Version && !frameworksToExclude.Contains(inboxFramework)) { inboxFrameworksList.Add(inboxFramework); } } // Only add the lowest version for a particular inbox framework. EG if both net45 and net46 are supported by this generation, // only add net45 inboxFrameworksList.RemoveWhere(fx => inboxFrameworksList.Any(otherFx => (otherFx.Framework.Equals(fx.Framework)) && (otherFx.Version < fx.Version))); // Check for assets which have a ref, but not a lib asset. If we have any of these, then they are actually not supported frameworks // and we should not include them. inboxFrameworksList.RemoveWhere(inboxFx => !IsSupported(inboxFx, resolver)); // Remove the frameworks which have placeholders. inboxFrameworksList.RemoveWhere(fx => targetFrameworksWithPlaceHolders.Any(tfx => tfx != null && fx.DotNetFrameworkName == tfx.DotNetFrameworkName)); // Create dependency items for each inbox framework. foreach (string framework in inboxFrameworksList.Select(fx => fx.GetShortFolderName())) { bool addedDependencyToFramework = false; foreach (ITaskItem dependency in portableDependencyGroups[portableDependency]) { // If we don't have the AssemblyVersion metadata (4 part version string), fall back and use Version (3 part version string) string version = dependency.GetMetadata("AssemblyVersion"); if (string.IsNullOrEmpty(version)) { version = dependency.GetMetadata("Version"); int prereleaseIndex = version.IndexOf('-'); if (prereleaseIndex != -1) { version = version.Substring(0, prereleaseIndex); } } if (!Frameworks.IsInbox(FrameworkListsPath, framework, dependency.ItemSpec, version)) { addedDependencyToFramework = true; TaskItem dependencyItem = new TaskItem(dependency); dependencyItem.SetMetadata("TargetFramework", framework); // "Generation" is not required metadata, we just include it because it can be useful for debugging. dependencyItem.SetMetadata("Generation", portableDependency); addedDependencies.Add(dependencyItem); } } if (!addedDependencyToFramework) { TaskItem dependencyItem = new TaskItem("_._"); dependencyItem.SetMetadata("TargetFramework", framework); // "Generation" is not required metadata, we just include it because it can be useful for debugging. dependencyItem.SetMetadata("Generation", portableDependency); addedDependencies.Add(dependencyItem); placeHolderFrameworks.Add(framework); } } } // Collapse frameworks // For any dependency with a targetframework, if there is another target framework which is compatible and older, remove this dependency. // Get all Dependencies which are not in a portable dependency group so that we can collapse the frameworks. If we include // the portable frameworks, then we'll end up collapsing to those. List <NuGetFramework> allDependencyGroups = new List <NuGetFramework>(); allDependencyGroups.AddRange(Dependencies.Select(d => NuGetFramework.Parse(d.GetMetadata("TargetFramework"))).Where(a => !allDependencyGroups.Contains(a) && !FrameworkUtilities.IsGenerationMoniker(a) && !FrameworkUtilities.IsPortableMoniker(a))); allDependencyGroups.AddRange(addedDependencies.Select(d => NuGetFramework.Parse(d.GetMetadata("TargetFramework"))).Where(a => !allDependencyGroups.Contains(a) && !FrameworkUtilities.IsGenerationMoniker(a) && !FrameworkUtilities.IsPortableMoniker(a))); List <NuGetFramework> collapsedDependencyGroups = FrameworkUtilities.ReduceDownwards(allDependencyGroups).ToList <NuGetFramework>(); // Get the list of dependency groups that we collapsed down so that we can add them back if they contained different dependencies than what is present in the collapsed group. /* TODO: Look into NuGet's sorting algorithm, they may have a bug (fixed in this line). They were not including version in the sort. * See ReduceCore in https://github.com/NuGet/NuGet.Client/blob/23ea68b91a439fcfd7f94bcd01bcdee2e8adae92/src/NuGet.Core/NuGet.Frameworks/FrameworkReducer.cs */ IEnumerable <NuGetFramework> removedDependencyGroups = allDependencyGroups.Where(d => !collapsedDependencyGroups.Contains(d))?.OrderBy(f => f.Framework, StringComparer.OrdinalIgnoreCase).ThenBy(f => f.Version); foreach (NuGetFramework removedDependencyGroup in removedDependencyGroups) { // always recalculate collapsedDependencyGroups in case we added an item in a previous iteration. Dependency groups are sorted, so this should be additive and we shouldn't need to restart the collapse / add back cycle var nearest = FrameworkUtilities.GetNearest(removedDependencyGroup, collapsedDependencyGroups.ToArray()); // gather the dependencies for this dependency group and the calculated "nearest" dependency group var nearestDependencies = addedDependencies.Where(d => nearest.Equals(NuGetFramework.Parse(d.GetMetadata("TargetFramework")))).OrderBy(f => f.ToString()); var currentDependencies = addedDependencies.Where(d => removedDependencyGroup.Equals(NuGetFramework.Parse(d.GetMetadata("TargetFramework")))).OrderBy(f => f.ToString()); // The nearest dependency group's dependencies are different than this dependency group's dependencies if (nearestDependencies.Count() != currentDependencies.Count()) { // ignore if dependency is a placeholder if (currentDependencies.Count() > 0) { if (!NuGetAssetResolver.IsPlaceholder(currentDependencies.First().ToString())) { collapsedDependencyGroups.Add(removedDependencyGroup); } } else { collapsedDependencyGroups.Add(removedDependencyGroup); } } // identical dependency count between current and nearest, and the count is > 0 else if (nearestDependencies.Count() > 0) { if (!currentDependencies.SequenceEqual(nearestDependencies, new DependencyITaskItemComparer())) { collapsedDependencyGroups.Add(removedDependencyGroup); } } } List <ITaskItem> collapsedDependencies = new List <ITaskItem>(); foreach (ITaskItem dependency in addedDependencies) { if (collapsedDependencyGroups.Contains(NuGetFramework.Parse(dependency.GetMetadata("TargetFramework")))) { collapsedDependencies.Add(dependency); } } TrimmedDependencies = collapsedDependencies.ToArray(); return(!Log.HasLoggedErrors); }
public override bool Execute() { var frameworks = Frameworks.NullAsEmpty().ToDictionary( i => NuGetFramework.Parse(i.ItemSpec), i => { var rids = i.GetMetadata("RuntimeIds"); return(String.IsNullOrEmpty(rids) ? new HashSet <string>() : new HashSet <string>(rids.Split(';'))); }, NuGetFramework.Comparer); var layoutFiles = new List <ITaskItem>(); foreach (var packageReportFile in PackageReports) { var packageReport = PackageReport.Load(packageReportFile); foreach (var targetInfo in packageReport.Targets) { var targetName = targetInfo.Key; var target = targetInfo.Value; var targetParts = targetName.Split('/'); var fx = NuGetFramework.Parse(targetParts[0]); string rid = null; if (targetParts.Length > 1) { rid = targetParts[1]; } if (frameworks.Count != 0) { HashSet <string> rids = null; if (!frameworks.TryGetValue(fx, out rids)) { Log.LogMessage(LogImportance.Low, $"Skipping {fx} since it is not in {nameof(Frameworks)}"); continue; } if (rid != null && rids.Count > 0 && !rids.Contains(rid)) { Log.LogMessage(LogImportance.Low, $"Skipping {fx}/{rid} since it is not in {nameof(Frameworks)}"); continue; } } if (!packageReport.SupportedFrameworks.ContainsKey(fx.ToString())) { Log.LogMessage(LogImportance.Low, $"Skipping {fx} since it is not supported"); continue; } var fxFolder = fx.GetShortFolderName(); if (rid == null) { // only consider compile assets for RID-less target layoutFiles.AddRange(CreateLayoutFiles(target.CompileAssets, $"ref\\{fxFolder}", "Compile")); } layoutFiles.AddRange(CreateLayoutFiles(target.RuntimeAssets, $"runtimes\\{rid}\\lib\\{fxFolder}", "Runtime")); layoutFiles.AddRange(CreateLayoutFiles(target.NativeAssets, $"runtimes\\{rid}\\native", "Native")); } } LayoutFiles = layoutFiles.ToArray(); return(!Log.HasLoggedErrors); }