From 1bd01c06f7eb201f602538a5154c865c25fde635 Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Mon, 13 May 2019 16:43:40 -0700 Subject: [PATCH 1/9] Resolve assemblies from specific paths This introduces a command-line option, "--ref ", which makes it possible to give the linker full assembly paths to resolve. LinkTask now uses "--ref" instead of "-d", to prevent the directory resolution behavior from finding dependencies next to inputs. Now it takes an explicit list of inputs, which will be the only files it resolves. When passing along full paths to each file, the command-line becomes substantially longer. To prevent hitting command length limits, arguments are now passed via a response file (using ToolTask's GenerateResponseFileCommands). --- src/ILLink.Tasks/LinkTask.cs | 76 ++++++++----------- .../Linker/DirectoryAssemblyResolver.cs | 28 ++++++- src/linker/Linker/Driver.cs | 5 ++ 3 files changed, 64 insertions(+), 45 deletions(-) diff --git a/src/ILLink.Tasks/LinkTask.cs b/src/ILLink.Tasks/LinkTask.cs index f4b6943972ca..572961b94a20 100644 --- a/src/ILLink.Tasks/LinkTask.cs +++ b/src/ILLink.Tasks/LinkTask.cs @@ -12,12 +12,7 @@ public class ILLink : ToolTask { /// /// 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. + /// input to the linker. /// Each path can also have an "action" metadata, /// which will set the illink action to take for /// that assembly. @@ -88,14 +83,12 @@ private string DotNetPath get { if (!String.IsNullOrEmpty (_dotnetPath)) - { return _dotnetPath; - } + _dotnetPath = Environment.GetEnvironmentVariable (DotNetHostPathEnvironmentName); if (String.IsNullOrEmpty (_dotnetPath)) - { throw new InvalidOperationException ($"{DotNetHostPathEnvironmentName} is not set"); - } + return _dotnetPath; } } @@ -112,9 +105,8 @@ private string DotNetPath public string ILLinkPath { get { if (!String.IsNullOrEmpty (_illinkPath)) - { return _illinkPath; - } + var taskDirectory = Path.GetDirectoryName (Assembly.GetExecutingAssembly ().Location); // The linker always runs on .NET Core, even when using desktop MSBuild to host ILLink.Tasks. _illinkPath = Path.Combine (Path.GetDirectoryName (taskDirectory), "netcoreapp2.0", "illink.dll"); @@ -132,30 +124,31 @@ protected override string GenerateCommandLineCommands () { var args = new StringBuilder (); args.Append (Quote (ILLinkPath)); + return args.ToString (); + } + + protected override string GenerateResponseFileCommands () + { + var args = new StringBuilder (); if (RootDescriptorFiles != null) { - foreach (var rootFile in RootDescriptorFiles) { + foreach (var rootFile in RootDescriptorFiles) args.Append (" -x ").Append (Quote (rootFile.ItemSpec)); - } } - foreach (var assemblyItem in RootAssemblyNames) { + foreach (var assemblyItem in RootAssemblyNames) args.Append (" -a ").Append (Quote (assemblyItem.ItemSpec)); - } - HashSet directories = new HashSet (StringComparer.OrdinalIgnoreCase); HashSet assemblyNames = new HashSet (StringComparer.OrdinalIgnoreCase); foreach (var assembly in AssemblyPaths) { var assemblyPath = assembly.ItemSpec; var assemblyName = Path.GetFileNameWithoutExtension (assemblyPath); - assemblyNames.Add (assemblyName); + // If there are multiple paths with the same assembly name, only use the first one. + if (!assemblyNames.Add (assemblyName)) + continue; - var dir = Path.GetDirectoryName (assemblyPath); - if (!directories.Contains (dir)) { - directories.Add (dir); - args.Append (" -d ").Append (Quote (dir)); - } + args.Append (" --ref ").Append (Quote (assemblyPath)); string action = assembly.GetMetadata ("action"); if ((action != null) && (action.Length > 0)) { @@ -165,30 +158,27 @@ protected override string GenerateCommandLineCommands () } } - foreach (var assembly in ReferenceAssemblyPaths) { - var assemblyPath = assembly.ItemSpec; - var assemblyName = Path.GetFileNameWithoutExtension (assemblyPath); + if (ReferenceAssemblyPaths != null) { + foreach (var assembly in ReferenceAssemblyPaths) { + var assemblyPath = assembly.ItemSpec; + var assemblyName = Path.GetFileNameWithoutExtension (assemblyPath); - // Don't process references for which we already have - // implementation assemblies. - if (assemblyNames.Contains (assemblyName)) - continue; + // Don't process references for which we already have + // implementation assemblies. + if (assemblyNames.Contains (assemblyName)) + continue; - var dir = Path.GetDirectoryName (assemblyPath); - if (!directories.Contains (dir)) { - directories.Add (dir); - args.Append (" -d ").Append (Quote (dir)); - } + args.Append (" --ref ").Append (Quote (assemblyPath)); - // Treat reference assemblies as "skip". Ideally we - // would not even look at the IL, but only use them to - // resolve surface area. - args.Append (" -p skip ").Append (Quote (assemblyName)); + // Treat reference assemblies as "skip". Ideally we + // would not even look at the IL, but only use them to + // resolve surface area. + args.Append (" -p skip ").Append (Quote (assemblyName)); + } } - if (OutputDirectory != null) { + if (OutputDirectory != null) args.Append (" -out ").Append (Quote (OutputDirectory.ItemSpec)); - } if (ClearInitLocals) { args.Append (" -s "); @@ -200,15 +190,13 @@ protected override string GenerateCommandLineCommands () } } - if (ExtraArgs != null) { + if (ExtraArgs != null) args.Append (" ").Append (ExtraArgs); - } if (DumpDependencies) args.Append (" --dump-dependencies"); return args.ToString (); } - } } diff --git a/src/linker/Linker/DirectoryAssemblyResolver.cs b/src/linker/Linker/DirectoryAssemblyResolver.cs index 416dab71b546..ca470942d691 100644 --- a/src/linker/Linker/DirectoryAssemblyResolver.cs +++ b/src/linker/Linker/DirectoryAssemblyResolver.cs @@ -11,12 +11,18 @@ namespace Mono.Linker { public abstract class DirectoryAssemblyResolver : IAssemblyResolver { readonly Collection directories; + readonly Collection assemblyPaths; public void AddSearchDirectory (string directory) { directories.Add (directory); } + public void AddAssemblyPath (string assemblyPath) + { + assemblyPaths.Add (assemblyPath); + } + public void RemoveSearchDirectory (string directory) { directories.Remove (directory); @@ -30,6 +36,7 @@ public void RemoveSearchDirectory (string directory) protected DirectoryAssemblyResolver () { directories = new Collection (2) { "." }; + assemblyPaths = new Collection (10) { }; } AssemblyDefinition GetAssembly (string file, ReaderParameters parameters) @@ -52,13 +59,32 @@ public virtual AssemblyDefinition Resolve (AssemblyNameReference name, ReaderPar if (parameters == null) parameters = new ReaderParameters (); - var assembly = SearchDirectory (name, directories, parameters); + var assembly = SearchAssemblyPaths (name, assemblyPaths, parameters); + if (assembly != null) + return assembly; + + assembly = SearchDirectory (name, directories, parameters); if (assembly != null) return assembly; throw new AssemblyResolutionException (name); } + AssemblyDefinition SearchAssemblyPaths (AssemblyNameReference name, IEnumerable assemblyPaths, ReaderParameters parameters) + { + foreach (var assemblyPath in assemblyPaths) { + if (Path.GetFileName (assemblyPath) != name.Name + ".dll") + continue; + try { + return GetAssembly (assemblyPath, parameters); + } catch (System.BadImageFormatException) { + continue; + } + } + + return null; + } + AssemblyDefinition SearchDirectory (AssemblyNameReference name, IEnumerable directories, ReaderParameters parameters) { var extensions = new [] { ".dll", ".exe" }; diff --git a/src/linker/Linker/Driver.cs b/src/linker/Linker/Driver.cs index a23bd7c404c5..042735ade525 100644 --- a/src/linker/Linker/Driver.cs +++ b/src/linker/Linker/Driver.cs @@ -240,6 +240,10 @@ public void Run (ILogger customLogger = null) disabled_optimizations.Add (opt); continue; + + case "--ref": + context.Resolver.AddAssemblyPath (GetParam ()); + continue; } switch (token [2]) { @@ -504,6 +508,7 @@ static void Usage (string msg) Console.WriteLine (" -r Link from a list of assemblies using roots visible outside of the assembly"); Console.WriteLine (" -x Link from XML descriptor"); Console.WriteLine (" -d Specify additional directories to search in for references"); + Console.WriteLine (" --ref Specify additional assemblies to use as references"); Console.WriteLine (" -b Update debug symbols for each linked module. Defaults to false"); Console.WriteLine (" -v Keep members and types used by debugger. Defaults to false"); Console.WriteLine (" -l , List of i18n assemblies to copy to the output directory. Defaults to 'all'"); From 2074abcb3c17a7ccd411d04a8e6fd8ee263e748e Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Mon, 13 May 2019 18:23:55 -0700 Subject: [PATCH 2/9] Move path resolution logic to child assembly resolver class This is necessary for the '--ref' argument to work with the mono build of the linker. Due to the design of cecil's BaseAssemblyResolver, there is a small amount of duplication. --- src/linker/Linker/AssemblyResolver.cs | 56 ++++++++++++++++++- .../Linker/DirectoryAssemblyResolver.cs | 32 +---------- 2 files changed, 58 insertions(+), 30 deletions(-) diff --git a/src/linker/Linker/AssemblyResolver.cs b/src/linker/Linker/AssemblyResolver.cs index 72ac6e2923c6..1393acec0a9a 100644 --- a/src/linker/Linker/AssemblyResolver.cs +++ b/src/linker/Linker/AssemblyResolver.cs @@ -30,6 +30,7 @@ using System.Collections.Generic; using System.IO; using Mono.Cecil; +using Mono.Collections.Generic; namespace Mono.Linker { @@ -43,6 +44,8 @@ public class AssemblyResolver : BaseAssemblyResolver { HashSet _unresolvedAssemblies; bool _ignoreUnresolved; LinkContext _context; + readonly Collection _assemblyPaths; + public IDictionary AssemblyCache { get { return _assemblies; } @@ -56,6 +59,7 @@ public AssemblyResolver () public AssemblyResolver (Dictionary assembly_cache) { _assemblies = assembly_cache; + _assemblyPaths = new Collection (10) { }; } public bool IgnoreUnresolved { @@ -68,12 +72,57 @@ public AssemblyResolver (Dictionary assembly_cache) set { _context = value; } } +#if !FEATURE_ILLINK + // The base class's definition of GetAssembly is visible when using DirectoryAssemblyResolver. + AssemblyDefinition GetAssembly (string file, ReaderParameters parameters) + { + if (parameters.AssemblyResolver == null) + parameters.AssemblyResolver = this; + + return ModuleDefinition.ReadModule (file, parameters).Assembly; + } +#endif + + private AssemblyDefinition ResolveWithPaths (AssemblyNameReference name, ReaderParameters parameters) + { + // Validate arguments, similarly to how the base class does it. + if (name == null) + throw new ArgumentNullException ("name"); + if (parameters == null) + throw new ArgumentNullException ("parameters"); + + AssemblyDefinition asm = null; + + // Try the new resolution behavior. This can't live in the cecil-owned base class. + asm = SearchAssemblyPaths (name, _assemblyPaths, parameters); + if (asm != null) + return asm; + + // Fall back to the base class resolution logic + return base.Resolve (name, parameters); + } + + private AssemblyDefinition SearchAssemblyPaths (AssemblyNameReference name, IEnumerable assemblyPaths, ReaderParameters parameters) + { + foreach (var assemblyPath in assemblyPaths) { + if (Path.GetFileName (assemblyPath) != name.Name + ".dll") + continue; + try { + return GetAssembly (assemblyPath, parameters); + } catch (System.BadImageFormatException) { + continue; + } + } + + return null; + } + public override AssemblyDefinition Resolve (AssemblyNameReference name, ReaderParameters parameters) { AssemblyDefinition asm = null; if (!_assemblies.TryGetValue (name.Name, out asm) && (_unresolvedAssemblies == null || !_unresolvedAssemblies.Contains (name.Name))) { try { - asm = base.Resolve (name, parameters); + asm = ResolveWithPaths (name, parameters); _assemblies [name.Name] = asm; } catch (AssemblyResolutionException) { if (!_ignoreUnresolved) @@ -96,6 +145,11 @@ public virtual AssemblyDefinition CacheAssembly (AssemblyDefinition assembly) return assembly; } + public void AddAssemblyPath (string assemblyPath) + { + _assemblyPaths.Add (assemblyPath); + } + protected override void Dispose (bool disposing) { foreach (var asm in _assemblies.Values) { diff --git a/src/linker/Linker/DirectoryAssemblyResolver.cs b/src/linker/Linker/DirectoryAssemblyResolver.cs index ca470942d691..e3aa534a40d2 100644 --- a/src/linker/Linker/DirectoryAssemblyResolver.cs +++ b/src/linker/Linker/DirectoryAssemblyResolver.cs @@ -11,18 +11,12 @@ namespace Mono.Linker { public abstract class DirectoryAssemblyResolver : IAssemblyResolver { readonly Collection directories; - readonly Collection assemblyPaths; public void AddSearchDirectory (string directory) { directories.Add (directory); } - public void AddAssemblyPath (string assemblyPath) - { - assemblyPaths.Add (assemblyPath); - } - public void RemoveSearchDirectory (string directory) { directories.Remove (directory); @@ -36,10 +30,9 @@ public void RemoveSearchDirectory (string directory) protected DirectoryAssemblyResolver () { directories = new Collection (2) { "." }; - assemblyPaths = new Collection (10) { }; } - AssemblyDefinition GetAssembly (string file, ReaderParameters parameters) + protected AssemblyDefinition GetAssembly (string file, ReaderParameters parameters) { if (parameters.AssemblyResolver == null) parameters.AssemblyResolver = this; @@ -57,34 +50,15 @@ public virtual AssemblyDefinition Resolve (AssemblyNameReference name, ReaderPar if (name == null) throw new ArgumentNullException ("name"); if (parameters == null) - parameters = new ReaderParameters (); + throw new ArgumentNullException ("parameters"); - var assembly = SearchAssemblyPaths (name, assemblyPaths, parameters); - if (assembly != null) - return assembly; - - assembly = SearchDirectory (name, directories, parameters); + var assembly = SearchDirectory (name, directories, parameters); if (assembly != null) return assembly; throw new AssemblyResolutionException (name); } - AssemblyDefinition SearchAssemblyPaths (AssemblyNameReference name, IEnumerable assemblyPaths, ReaderParameters parameters) - { - foreach (var assemblyPath in assemblyPaths) { - if (Path.GetFileName (assemblyPath) != name.Name + ".dll") - continue; - try { - return GetAssembly (assemblyPath, parameters); - } catch (System.BadImageFormatException) { - continue; - } - } - - return null; - } - AssemblyDefinition SearchDirectory (AssemblyNameReference name, IEnumerable directories, ReaderParameters parameters) { var extensions = new [] { ".dll", ".exe" }; From 4ab145e60877dafd3d9f0ca09e4dfdac6a65eb97 Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Wed, 15 May 2019 18:00:32 -0700 Subject: [PATCH 3/9] Place response file arguments on separate lines --- src/ILLink.Tasks/LinkTask.cs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/ILLink.Tasks/LinkTask.cs b/src/ILLink.Tasks/LinkTask.cs index 572961b94a20..cb78f370009a 100644 --- a/src/ILLink.Tasks/LinkTask.cs +++ b/src/ILLink.Tasks/LinkTask.cs @@ -133,11 +133,11 @@ protected override string GenerateResponseFileCommands () if (RootDescriptorFiles != null) { foreach (var rootFile in RootDescriptorFiles) - args.Append (" -x ").Append (Quote (rootFile.ItemSpec)); + args.Append ("-x ").AppendLine (Quote (rootFile.ItemSpec)); } foreach (var assemblyItem in RootAssemblyNames) - args.Append (" -a ").Append (Quote (assemblyItem.ItemSpec)); + args.Append ("-a ").AppendLine (Quote (assemblyItem.ItemSpec)); HashSet assemblyNames = new HashSet (StringComparer.OrdinalIgnoreCase); foreach (var assembly in AssemblyPaths) { @@ -148,13 +148,13 @@ protected override string GenerateResponseFileCommands () if (!assemblyNames.Add (assemblyName)) continue; - args.Append (" --ref ").Append (Quote (assemblyPath)); + args.Append ("--ref ").AppendLine (Quote (assemblyPath)); string action = assembly.GetMetadata ("action"); if ((action != null) && (action.Length > 0)) { - args.Append (" -p "); + args.Append ("-p "); args.Append (action); - args.Append (" ").Append (Quote (assemblyName)); + args.Append (" ").AppendLine (Quote (assemblyName)); } } @@ -168,33 +168,33 @@ protected override string GenerateResponseFileCommands () if (assemblyNames.Contains (assemblyName)) continue; - args.Append (" --ref ").Append (Quote (assemblyPath)); + args.Append ("--ref ").AppendLine (Quote (assemblyPath)); // Treat reference assemblies as "skip". Ideally we // would not even look at the IL, but only use them to // resolve surface area. - args.Append (" -p skip ").Append (Quote (assemblyName)); + args.Append ("-p skip ").AppendLine (Quote (assemblyName)); } } if (OutputDirectory != null) - args.Append (" -out ").Append (Quote (OutputDirectory.ItemSpec)); + args.Append ("-out ").AppendLine (Quote (OutputDirectory.ItemSpec)); if (ClearInitLocals) { - args.Append (" -s "); + args.Append ("-s "); // Version of ILLink.CustomSteps is passed as a workaround for msbuild issue #3016 - args.Append ("LLink.CustomSteps.ClearInitLocalsStep,ILLink.CustomSteps,Version=0.0.0.0:OutputStep"); + args.AppendLine ("ILLink.CustomSteps.ClearInitLocalsStep,ILLink.CustomSteps,Version=0.0.0.0:OutputStep"); if ((ClearInitLocalsAssemblies != null) && (ClearInitLocalsAssemblies.Length > 0)) { - args.Append (" -m ClearInitLocalsAssemblies "); - args.Append (ClearInitLocalsAssemblies); + args.Append ("-m ClearInitLocalsAssemblies "); + args.AppendLine (ClearInitLocalsAssemblies); } } if (ExtraArgs != null) - args.Append (" ").Append (ExtraArgs); + args.AppendLine (ExtraArgs); if (DumpDependencies) - args.Append (" --dump-dependencies"); + args.AppendLine ("--dump-dependencies"); return args.ToString (); } From b7d75048e103e0410749d6377d374b85513d588a Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Thu, 23 May 2019 09:35:24 -0700 Subject: [PATCH 4/9] Move SearchAssemblyPaths call directly into Resolve --- src/linker/Linker/AssemblyResolver.cs | 33 +++++++++++---------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/src/linker/Linker/AssemblyResolver.cs b/src/linker/Linker/AssemblyResolver.cs index 1393acec0a9a..ec218e4cf220 100644 --- a/src/linker/Linker/AssemblyResolver.cs +++ b/src/linker/Linker/AssemblyResolver.cs @@ -83,25 +83,6 @@ AssemblyDefinition GetAssembly (string file, ReaderParameters parameters) } #endif - private AssemblyDefinition ResolveWithPaths (AssemblyNameReference name, ReaderParameters parameters) - { - // Validate arguments, similarly to how the base class does it. - if (name == null) - throw new ArgumentNullException ("name"); - if (parameters == null) - throw new ArgumentNullException ("parameters"); - - AssemblyDefinition asm = null; - - // Try the new resolution behavior. This can't live in the cecil-owned base class. - asm = SearchAssemblyPaths (name, _assemblyPaths, parameters); - if (asm != null) - return asm; - - // Fall back to the base class resolution logic - return base.Resolve (name, parameters); - } - private AssemblyDefinition SearchAssemblyPaths (AssemblyNameReference name, IEnumerable assemblyPaths, ReaderParameters parameters) { foreach (var assemblyPath in assemblyPaths) { @@ -122,7 +103,19 @@ public override AssemblyDefinition Resolve (AssemblyNameReference name, ReaderPa AssemblyDefinition asm = null; if (!_assemblies.TryGetValue (name.Name, out asm) && (_unresolvedAssemblies == null || !_unresolvedAssemblies.Contains (name.Name))) { try { - asm = ResolveWithPaths (name, parameters); + // Validate arguments, similarly to how the base class does it. + if (name == null) + throw new ArgumentNullException ("name"); + if (parameters == null) + throw new ArgumentNullException ("parameters"); + + // Try the new resolution behavior. This can't live in the cecil-owned base class. + asm = SearchAssemblyPaths (name, _assemblyPaths, parameters); + + // Fall back to the base class resolution logic + if (asm == null) + asm = base.Resolve (name, parameters); + _assemblies [name.Name] = asm; } catch (AssemblyResolutionException) { if (!_ignoreUnresolved) From 9dd49f366f3aca63428418528065d17cd48df057 Mon Sep 17 00:00:00 2001 From: Sven Boemer Date: Thu, 23 May 2019 12:35:46 -0700 Subject: [PATCH 5/9] Update names for clarity and other PR feedback --ref -> --reference SearchAssemblyPaths -> ResolveFromReferences AddAssemblyPath -> AddReferenceAssembly _assemblyPaths -> _references Also: - move parameter checking to beginning of Resolve () - remove unnecessary "System." - move computed string out of loop --- src/linker/Linker/AssemblyResolver.cs | 33 ++++++++++++++------------- src/linker/Linker/Driver.cs | 6 ++--- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/linker/Linker/AssemblyResolver.cs b/src/linker/Linker/AssemblyResolver.cs index ec218e4cf220..9f458ee33680 100644 --- a/src/linker/Linker/AssemblyResolver.cs +++ b/src/linker/Linker/AssemblyResolver.cs @@ -44,7 +44,7 @@ public class AssemblyResolver : BaseAssemblyResolver { HashSet _unresolvedAssemblies; bool _ignoreUnresolved; LinkContext _context; - readonly Collection _assemblyPaths; + readonly Collection _references; public IDictionary AssemblyCache { @@ -59,7 +59,7 @@ public AssemblyResolver () public AssemblyResolver (Dictionary assembly_cache) { _assemblies = assembly_cache; - _assemblyPaths = new Collection (10) { }; + _references = new Collection () { }; } public bool IgnoreUnresolved { @@ -83,14 +83,15 @@ AssemblyDefinition GetAssembly (string file, ReaderParameters parameters) } #endif - private AssemblyDefinition SearchAssemblyPaths (AssemblyNameReference name, IEnumerable assemblyPaths, ReaderParameters parameters) + private AssemblyDefinition ResolveFromReferences (AssemblyNameReference name, Collection references, ReaderParameters parameters) { - foreach (var assemblyPath in assemblyPaths) { - if (Path.GetFileName (assemblyPath) != name.Name + ".dll") + var fileName = name.Name + ".dll"; + foreach (var reference in references) { + if (Path.GetFileName (reference) != fileName) continue; try { - return GetAssembly (assemblyPath, parameters); - } catch (System.BadImageFormatException) { + return GetAssembly (reference, parameters); + } catch (BadImageFormatException) { continue; } } @@ -100,17 +101,17 @@ private AssemblyDefinition SearchAssemblyPaths (AssemblyNameReference name, IEnu public override AssemblyDefinition Resolve (AssemblyNameReference name, ReaderParameters parameters) { + // Validate arguments, similarly to how the base class does it. + if (name == null) + throw new ArgumentNullException ("name"); + if (parameters == null) + throw new ArgumentNullException ("parameters"); + AssemblyDefinition asm = null; if (!_assemblies.TryGetValue (name.Name, out asm) && (_unresolvedAssemblies == null || !_unresolvedAssemblies.Contains (name.Name))) { try { - // Validate arguments, similarly to how the base class does it. - if (name == null) - throw new ArgumentNullException ("name"); - if (parameters == null) - throw new ArgumentNullException ("parameters"); - // Try the new resolution behavior. This can't live in the cecil-owned base class. - asm = SearchAssemblyPaths (name, _assemblyPaths, parameters); + asm = ResolveFromReferences (name, _references, parameters); // Fall back to the base class resolution logic if (asm == null) @@ -138,9 +139,9 @@ public virtual AssemblyDefinition CacheAssembly (AssemblyDefinition assembly) return assembly; } - public void AddAssemblyPath (string assemblyPath) + public void AddReferenceAssembly (string referencePath) { - _assemblyPaths.Add (assemblyPath); + _references.Add (referencePath); } protected override void Dispose (bool disposing) diff --git a/src/linker/Linker/Driver.cs b/src/linker/Linker/Driver.cs index 042735ade525..5d430c6b7adb 100644 --- a/src/linker/Linker/Driver.cs +++ b/src/linker/Linker/Driver.cs @@ -241,8 +241,8 @@ public void Run (ILogger customLogger = null) continue; - case "--ref": - context.Resolver.AddAssemblyPath (GetParam ()); + case "--reference": + context.Resolver.AddReferenceAssembly (GetParam ()); continue; } @@ -508,7 +508,7 @@ static void Usage (string msg) Console.WriteLine (" -r Link from a list of assemblies using roots visible outside of the assembly"); Console.WriteLine (" -x Link from XML descriptor"); Console.WriteLine (" -d Specify additional directories to search in for references"); - Console.WriteLine (" --ref Specify additional assemblies to use as references"); + Console.WriteLine (" --reference Specify additional assemblies to use as references"); Console.WriteLine (" -b Update debug symbols for each linked module. Defaults to false"); Console.WriteLine (" -v Keep members and types used by debugger. Defaults to false"); Console.WriteLine (" -l , List of i18n assemblies to copy to the output directory. Defaults to 'all'"); From cd9c2f20a9810a44562035ad441c4829edd42e6f Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Fri, 24 May 2019 10:10:59 +0200 Subject: [PATCH 6/9] Update Driver.cs --- src/linker/Linker/Driver.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/linker/Linker/Driver.cs b/src/linker/Linker/Driver.cs index 5d430c6b7adb..469328136504 100644 --- a/src/linker/Linker/Driver.cs +++ b/src/linker/Linker/Driver.cs @@ -508,16 +508,15 @@ static void Usage (string msg) Console.WriteLine (" -r Link from a list of assemblies using roots visible outside of the assembly"); Console.WriteLine (" -x Link from XML descriptor"); Console.WriteLine (" -d Specify additional directories to search in for references"); - Console.WriteLine (" --reference Specify additional assemblies to use as references"); + Console.WriteLine (" -reference Specify additional assemblies to use as references"); Console.WriteLine (" -b Update debug symbols for each linked module. Defaults to false"); Console.WriteLine (" -v Keep members and types used by debugger. Defaults to false"); Console.WriteLine (" -l , List of i18n assemblies to copy to the output directory. Defaults to 'all'"); Console.WriteLine (" Valid names are 'none', 'all', 'cjk', 'mideast', 'other', 'rare', 'west'"); + Console.WriteLine (" -out Specify the output directory. Defaults to 'output'"); Console.WriteLine (" --about About the {0}", _linker); Console.WriteLine (" --verbose Log messages indicating progress and warnings"); Console.WriteLine (" --version Print the version number of the {0}", _linker); - Console.WriteLine (" --skip-unresolved Ignore unresolved types, methods, and assemblies. Defaults to false"); - Console.WriteLine (" -out Specify the output directory. Defaults to 'output'"); Console.WriteLine (); Console.WriteLine ("Actions"); @@ -547,6 +546,7 @@ static void Usage (string msg) Console.WriteLine (" --ignore-descriptors Skips reading embedded descriptors (short -z). Defaults to false"); Console.WriteLine (" --keep-facades Keep assemblies with type-forwarders (short -t). Defaults to false"); Console.WriteLine (" --new-mvid Generate a new guid for each linked assembly (short -g). Defaults to true"); + Console.WriteLine (" --skip-unresolved Ignore unresolved types, methods, and assemblies. Defaults to false"); Console.WriteLine (" --strip-resources Remove XML descriptor resources for linked assemblies. Defaults to true"); Console.WriteLine (" --strip-security Remove metadata and code related to Code Access Security. Defaults to true"); Console.WriteLine (" --used-attrs-only Any attribute is removed if the attribute type is not used. Defaults to false"); From a757cd3ddd9bf838f81dd747eed16b00b5a92cea Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Fri, 24 May 2019 10:11:39 +0200 Subject: [PATCH 7/9] Update Driver.cs --- src/linker/Linker/Driver.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/linker/Linker/Driver.cs b/src/linker/Linker/Driver.cs index 469328136504..d769c660ae8f 100644 --- a/src/linker/Linker/Driver.cs +++ b/src/linker/Linker/Driver.cs @@ -241,7 +241,7 @@ public void Run (ILogger customLogger = null) continue; - case "--reference": + case "-reference": context.Resolver.AddReferenceAssembly (GetParam ()); continue; } From 36f9c2cce410c3ccbd4eb8fffceff0ba3033f38c Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Fri, 24 May 2019 10:14:22 +0200 Subject: [PATCH 8/9] Update AssemblyResolver.cs --- src/linker/Linker/AssemblyResolver.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/linker/Linker/AssemblyResolver.cs b/src/linker/Linker/AssemblyResolver.cs index 9f458ee33680..5a4299bae9f3 100644 --- a/src/linker/Linker/AssemblyResolver.cs +++ b/src/linker/Linker/AssemblyResolver.cs @@ -83,7 +83,7 @@ AssemblyDefinition GetAssembly (string file, ReaderParameters parameters) } #endif - private AssemblyDefinition ResolveFromReferences (AssemblyNameReference name, Collection references, ReaderParameters parameters) + AssemblyDefinition ResolveFromReferences (AssemblyNameReference name, Collection references, ReaderParameters parameters) { var fileName = name.Name + ".dll"; foreach (var reference in references) { @@ -110,7 +110,7 @@ public override AssemblyDefinition Resolve (AssemblyNameReference name, ReaderPa AssemblyDefinition asm = null; if (!_assemblies.TryGetValue (name.Name, out asm) && (_unresolvedAssemblies == null || !_unresolvedAssemblies.Contains (name.Name))) { try { - // Try the new resolution behavior. This can't live in the cecil-owned base class. + // Any full path explicit reference takes precedence over other look up logic asm = ResolveFromReferences (name, _references, parameters); // Fall back to the base class resolution logic From a0c7c636d1eb1175de6a7535c39797b2f7a89757 Mon Sep 17 00:00:00 2001 From: Marek Safar Date: Fri, 24 May 2019 10:15:08 +0200 Subject: [PATCH 9/9] Update LinkTask.cs --- src/ILLink.Tasks/LinkTask.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ILLink.Tasks/LinkTask.cs b/src/ILLink.Tasks/LinkTask.cs index cb78f370009a..b9f69a376070 100644 --- a/src/ILLink.Tasks/LinkTask.cs +++ b/src/ILLink.Tasks/LinkTask.cs @@ -168,7 +168,7 @@ protected override string GenerateResponseFileCommands () if (assemblyNames.Contains (assemblyName)) continue; - args.Append ("--ref ").AppendLine (Quote (assemblyPath)); + args.Append ("-reference ").AppendLine (Quote (assemblyPath)); // Treat reference assemblies as "skip". Ideally we // would not even look at the IL, but only use them to