using System; using System.Collections.Generic; using System.Diagnostics; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; using System.Text; using System.IO; using System.Linq; namespace ILLink.Tasks { public class ILLink : Task { /// /// Paths to the assembly files that should be considered as /// input to the linker. Currently the linker will /// additionally be able to resolve any assemblies in the /// same directory as an assembly in AssemblyPaths, but this /// behavior should not be relied upon. Instead, work under /// the assumption that only the AssemblyPaths given will be /// resolved. /// [Required] public ITaskItem[] AssemblyPaths { get; set; } /// /// The names of the assemblies to root. This should contain /// assembly names without an extension, not file names or /// paths. Exactly which parts of the assemblies get rooted /// is subject to change. Currently these get passed to /// illink with "-a", which roots the entry point for /// executables, and everything for libraries. To control /// the linker more explicitly, either pass descriptor /// files, or pass extra arguments for illink. /// [Required] public ITaskItem[] RootAssemblyNames { get; set; } /// /// The directory in which to place linked assemblies. /// [Required] public ITaskItem OutputDirectory { get; set; } /// /// A list of XML root descriptor files specifying linker /// roots at a granular level. See the mono/linker /// documentation for details about the format. /// public ITaskItem[] RootDescriptorFiles { get; set; } /// /// Extra arguments to pass to illink, delimited by spaces. /// public string ExtraArgs { get; set; } public override bool Execute() { string[] args = GenerateCommandLineCommands(); var argsString = String.Join(" ", args); Log.LogMessageFromText($"illink {argsString}", MessageImportance.Normal); int ret = Mono.Linker.Driver.Main(args); return ret == 0; } private string[] GenerateCommandLineCommands() { var args = new List(); if (RootDescriptorFiles != null) { foreach (var rootFile in RootDescriptorFiles) { args.Add("-x"); args.Add(rootFile.ItemSpec); } } foreach (var assemblyItem in RootAssemblyNames) { args.Add("-a"); args.Add(assemblyItem.ItemSpec); } var assemblyDirs = AssemblyPaths.Select(p => Path.GetDirectoryName(p.ItemSpec)) .GroupBy(d => d).Select(ds => ds.First()); foreach (var dir in assemblyDirs) { args.Add("-d"); args.Add(dir); } if (OutputDirectory != null) { args.Add("-out"); args.Add(OutputDirectory.ItemSpec); } if (ExtraArgs != null) { args.AddRange(ExtraArgs.Split(' ')); } return args.ToArray(); } } }