using System; using System.IO; using System.Linq; using System.Collections.Generic; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; using Microsoft.NET.Build.Tasks; // LockFileCache using NuGet.Frameworks; // NuGetFramework.Parse(targetframework) using NuGet.ProjectModel; // LockFileTargetLibrary namespace ILLink.Tasks { public class GetRuntimeLibraries : Task { /// <summary> /// Path to the assets file. /// </summary> [Required] public ITaskItem AssetsFilePath { get; set; } /// <summary> /// Target framework for which to get the platform /// libraries. /// </summary> [Required] public string TargetFramework { get; set; } /// <summary> /// Runtime identifier for which to get the platform /// libraries. /// </summary> [Required] public string RuntimeIdentifier { get; set; } /// <summary> /// Name of the library to consider the "platform" /// library. /// </summary> [Required] public string[] PackageNames { get; set; } [Output] public ITaskItem[] RuntimeLibraries { get; private set; } public override bool Execute() { var lockFile = new LockFileCache(BuildEngine4).GetLockFile(AssetsFilePath.ItemSpec); var lockFileTarget = lockFile.GetTarget(NuGetFramework.Parse(TargetFramework), RuntimeIdentifier); if (lockFileTarget == null) { var targetString = string.IsNullOrEmpty(RuntimeIdentifier) ? TargetFramework : $"{TargetFramework}/{RuntimeIdentifier}"; throw new Exception($"Missing target section {targetString} from assets file {AssetsFilePath}. Ensure you have restored this project previously."); } Dictionary<string, LockFileTargetLibrary> packages = new Dictionary<string, LockFileTargetLibrary>(lockFileTarget.Libraries.Count, StringComparer.OrdinalIgnoreCase); foreach (var lib in lockFileTarget.Libraries) { packages.Add(lib.Name, lib); } HashSet<string> packageNames = new HashSet<string>(PackageNames); var rootPackages = lockFileTarget.Libraries.Where(l => packageNames.Contains(l.Name)); var packageQueue = new Queue<LockFileTargetLibrary>(rootPackages); var libraries = new List<string>(); while (packageQueue.Count > 0) { var package = packageQueue.Dequeue(); foreach (var lib in package.RuntimeAssemblies) { libraries.Add(lib.ToString()); } foreach (var dep in package.Dependencies.Select(d => d.Id)) { packageQueue.Enqueue(packages[dep]); } } RuntimeLibraries = libraries.Select(l => new TaskItem(l)).ToArray(); return true; } } }