Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/linker.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/linker/Linker/Driver.cs647
-rw-r--r--test/Mono.Linker.Tests/TestCasesRunner/LinkerDriver.cs9
2 files changed, 440 insertions, 216 deletions
diff --git a/src/linker/Linker/Driver.cs b/src/linker/Linker/Driver.cs
index e5da17786..9661cdc28 100644
--- a/src/linker/Linker/Driver.cs
+++ b/src/linker/Linker/Driver.cs
@@ -39,9 +39,11 @@ namespace Mono.Linker {
public partial class Driver {
#if FEATURE_ILLINK
+ const string resolvers = "-a|-r|-x";
static readonly string _linker = "IL Linker";
#else
- static readonly string _linker = "Mono CIL Linker";
+ const string resolvers = "-a|-i|-r|-x";
+ static readonly string _linker = "Mono IL Linker";
#endif
public static int Main (string [] args)
@@ -51,13 +53,19 @@ namespace Mono.Linker {
public static int Execute (string[] args, ILogger customLogger = null)
{
- if (args.Length == 0)
- Usage ("No parameters specified");
+ if (args.Length == 0) {
+ Console.Error.WriteLine ("No parameters specified");
+ return 1;
+ }
+
+ if (!ProcessResponseFile (args, out var arguments))
+ return 1;
try {
- Driver driver = new Driver (args);
- driver.Run (customLogger);
+ Driver driver = new Driver (arguments);
+ if (!driver.Run (customLogger))
+ return 1;
} catch {
Console.Error.WriteLine ("Fatal error in {0}", _linker);
@@ -67,17 +75,17 @@ namespace Mono.Linker {
return 0;
}
- Queue<string> _queue;
+ readonly Queue<string> arguments;
bool _needAddBypassNGenStep;
- public Driver (string [] args)
+ public Driver (Queue<string> arguments)
{
- _queue = ProcessResponseFile (args);
+ this.arguments = arguments;
}
- Queue<String> ProcessResponseFile (string [] args)
+ public static bool ProcessResponseFile (string[] args, out Queue<string> result)
{
- var result = new Queue<string> ();
+ result = new Queue<string> ();
foreach (string arg in args) {
if (arg.StartsWith ("@")) {
try {
@@ -85,13 +93,15 @@ namespace Mono.Linker {
IEnumerable<string> responseFileLines = File.ReadLines (responseFileName);
ParseResponseFileLines (responseFileLines, result);
} catch (Exception e) {
- Usage ("Cannot read response file with exception " + e.Message);
+ Console.Error.WriteLine ("Cannot read response file due to '{0}'", e.Message);
+ return false;
}
} else {
result.Enqueue (arg);
}
}
- return result;
+
+ return true;
}
public static void ParseResponseFileLines (IEnumerable<string> responseFileLines, Queue<string> result)
@@ -140,12 +150,17 @@ namespace Mono.Linker {
}
}
- bool HaveMoreTokens ()
+ static void ErrorUnrecognizedOption (string optionName)
{
- return _queue.Count > 0;
+ Console.WriteLine ($"Unrecognized command-line option: '{optionName}'");
}
- public void Run (ILogger customLogger = null)
+ static void ErrorMissingArgument (string optionName)
+ {
+ Console.WriteLine ($"Missing argument for '{optionName}' option");
+ }
+
+ public bool Run (ILogger customLogger = null)
{
Pipeline p = GetStandardPipeline ();
using (LinkContext context = GetDefaultContext (p)) {
@@ -163,34 +178,36 @@ namespace Mono.Linker {
string dependenciesFileName = null;
bool ignoreDescriptors = false;
bool removeCAS = true;
+ bool new_mvid_used = false;
+ bool deterministic_used = false;
bool resolver = false;
- while (HaveMoreTokens ()) {
- string token = GetParam ();
- if (token.Length < 2)
- Usage ("Option is too short");
-
- if (!(token [0] == '-' || token [1] == '/'))
- Usage ("Expecting an option, got instead: " + token);
+ while (arguments.Count > 0) {
+ string token = arguments.Dequeue ();
+ if (token.Length < 2) {
+ ErrorUnrecognizedOption (token);
+ return false;
+ }
+ //
+ // Handling of --value like options
+ //
if (token [0] == '-' && token [1] == '-') {
-
- if (token.Length < 3)
- Usage ("Option is too short");
-
switch (token) {
case "--skip-unresolved":
- bool ignoreUnresolved = bool.Parse (GetParam ());
- context.IgnoreUnresolved = ignoreUnresolved;
- context.Resolver.IgnoreUnresolved = ignoreUnresolved;
+ if (!GetBoolParam (token, l => context.IgnoreUnresolved = context.Resolver.IgnoreUnresolved = l))
+ return false;
+
continue;
-
+
case "--verbose":
context.LogMessages = true;
continue;
case "--dependencies-file":
- dependenciesFileName = GetParam ();
+ if (!GetStringParam (token, l => dependenciesFileName = l))
+ return false;
+
continue;
case "--dump-dependencies":
@@ -198,215 +215,279 @@ namespace Mono.Linker {
continue;
case "--reduced-tracing":
- context.EnableReducedTracing = bool.Parse (GetParam ());
+ if (!GetBoolParam (token, l => context.EnableReducedTracing = l))
+ return false;
+
continue;
case "--used-attrs-only":
- context.KeepUsedAttributeTypesOnly = bool.Parse (GetParam ());
+ if (!GetBoolParam (token, l => context.KeepUsedAttributeTypesOnly = l))
+ return false;
+
continue;
case "--strip-security":
- removeCAS = bool.Parse (GetParam ());
+ if (!GetBoolParam (token, l => removeCAS = l))
+ return false;
+
continue;
case "--strip-resources":
- context.StripResources = bool.Parse (GetParam ());
+ if (!GetBoolParam (token, l => context.StripResources = l))
+ return false;
+
continue;
case "--substitutions":
- context.AddSubstitutionFile (GetParam ());
+ if (arguments.Count < 1) {
+ ErrorMissingArgument (token);
+ return false;
+ }
+
+ if (!GetStringParam (token, l => context.AddSubstitutionFile (l)))
+ return false;
+
continue;
case "--exclude-feature":
- var name = GetParam ();
- foreach (var feature in name.Split (',')) {
- if (!excluded_features.Contains (feature))
- excluded_features.Add (feature);
+ if (arguments.Count < 1) {
+ ErrorMissingArgument (token);
+ return false;
}
+
+ if (!GetStringParam (token, l => {
+ foreach (var feature in l.Split (',')) {
+ if (!excluded_features.Contains (feature))
+ excluded_features.Add (feature);
+ }
+ }))
+ return false;
+
continue;
case "--explicit-reflection":
- context.AddReflectionAnnotations = true;
+ if (!GetBoolParam (token, l => context.AddReflectionAnnotations = l))
+ return false;
+
continue;
case "--custom-step":
- custom_steps.Add (GetParam ());
+ if (!GetStringParam (token, l => custom_steps.Add (l)))
+ return false;
+
continue;
case "--keep-facades":
- context.KeepTypeForwarderOnlyAssemblies = bool.Parse (GetParam ());
+ if (!GetBoolParam (token, l => context.KeepTypeForwarderOnlyAssemblies = l))
+ return false;
+
continue;
case "--keep-dep-attributes":
- context.KeepDependencyAttributes = bool.Parse (GetParam ());
+ if (!GetBoolParam (token, l => context.KeepDependencyAttributes = l))
+ return false;
+
continue;
case "--ignore-descriptors":
- ignoreDescriptors = bool.Parse (GetParam ());
+ if (!GetBoolParam (token, l => ignoreDescriptors = l))
+ return false;
+
continue;
case "--disable-opt":
- var opt = GetParam ().ToLower ();
- if (!disabled_optimizations.Contains (opt))
- disabled_optimizations.Add (opt);
+ if (!GetStringParam (token, l => {
+ var opt = l.ToLowerInvariant ();
+ if (!disabled_optimizations.Contains (opt))
+ disabled_optimizations.Add (opt);
+ }))
+ return false;
continue;
case "--enable-opt":
- opt = GetParam ().ToLower ();
- if (!enabled_optimizations.Contains (opt))
- enabled_optimizations.Add (opt);
+ if (!GetStringParam (token, l => {
+ var opt = l.ToLowerInvariant ();
+ if (!enabled_optimizations.Contains (opt))
+ enabled_optimizations.Add (opt);
+ }))
+ return false;
continue;
case "--new-mvid":
- if (!bool.Parse (GetParam()))
- p.RemoveStep (typeof (RegenerateGuidStep));
+ //
+ // This is not same as --deterministic which calculates MVID
+ // from stable assembly content. This option creates a new random
+ // mvid or uses mvid of the source assembly.
+ //
+ if (!GetBoolParam (token, l => {
+ if (!l)
+ p.RemoveStep (typeof (RegenerateGuidStep));
+ }))
+ return false;
+
+ new_mvid_used = true;
continue;
case "--deterministic":
- context.DeterministicOutput = true;
- p.RemoveStep (typeof (RegenerateGuidStep));
+ if (!GetBoolParam (token, l => context.DeterministicOutput = l))
+ return false;
+
+ deterministic_used = true;
continue;
case "--output-assemblylist":
- context.AssemblyListFile = GetParam ();
+ if (!GetStringParam (token, l => context.AssemblyListFile = l))
+ return false;
+
continue;
- }
- switch (token [2]) {
- case 'v':
+ case "--version":
Version ();
- break;
- case 'a':
+ return true;
+
+ case "--about":
About ();
- break;
- default:
- Usage (null);
- break;
+ return true;
}
}
- // Ensure this does not conflict with '-r' below.
- if (token == "-reference") {
- context.Resolver.AddReferenceAssembly (GetParam ());
- continue;
- }
+ if (token [0] == '-' || token [1] == '/') {
- switch (token [1]) {
- case 'd':
- DirectoryInfo info = new DirectoryInfo (GetParam ());
- context.Resolver.AddSearchDirectory (info.FullName);
- break;
- case 'o':
- context.OutputDirectory = GetParam ();
- break;
- case 'c':
- context.CoreAction = ParseAssemblyAction (GetParam ());
- break;
- case 'u':
- context.UserAction = ParseAssemblyAction (GetParam ());
- break;
- case 'p':
- AssemblyAction action = ParseAssemblyAction (GetParam ());
- context.Actions [GetParam ()] = action;
- break;
- case 't':
- context.KeepTypeForwarderOnlyAssemblies = true;
- break;
- case 'x':
- foreach (string file in GetFiles (GetParam ()))
- p.PrependStep (new ResolveFromXmlStep (new XPathDocument (file)));
- resolver = true;
- break;
- case 'r':
- case 'a':
- var rootVisibility = (token [1] == 'r')
- ? ResolveFromAssemblyStep.RootVisibility.PublicAndFamily
- : ResolveFromAssemblyStep.RootVisibility.Any;
- foreach (string file in GetFiles (GetParam ()))
- p.PrependStep (new ResolveFromAssemblyStep (file, rootVisibility));
- resolver = true;
- break;
-#if !FEATURE_ILLINK
- case 'i':
- foreach (string file in GetFiles (GetParam ()))
- p.PrependStep (new ResolveFromXApiStep (new XPathDocument (file)));
- resolver = true;
- break;
- case 'l':
- assemblies = ParseI18n (GetParam ());
- break;
-#endif
- case 'm':
- context.SetParameter (GetParam (), GetParam ());
- break;
- case 'b':
- context.LinkSymbols = bool.Parse (GetParam ());
- break;
- case 'g':
- if (!bool.Parse (GetParam ()))
- p.RemoveStep (typeof (RegenerateGuidStep));
- break;
- case 'z':
- ignoreDescriptors = !bool.Parse (GetParam ());
- break;
- case 'v':
- context.KeepMembersForDebugger = bool.Parse (GetParam ());
- break;
- default:
- Usage ("Unknown option: `" + token [1] + "'");
- break;
- }
- }
+ switch (token.Substring (1)) {
+ case "d":
+ if (!GetStringParam (token, l => {
+ DirectoryInfo info = new DirectoryInfo (l);
+ context.Resolver.AddSearchDirectory (info.FullName);
+ }))
+ return false;
- if (!resolver)
- Usage ("No resolver was created (use -x, -a or -i)");
+ continue;
+ case "o":
+ if (!GetStringParam (token, l => context.OutputDirectory = l))
+ return false;
- if (ignoreDescriptors)
- p.RemoveStep (typeof (BlacklistStep));
+ continue;
+ case "c":
+ if (!GetStringParam (token, l => context.CoreAction = ParseAssemblyAction (l)))
+ return false;
- if (dumpDependencies)
- context.Tracer.AddRecorder (new XmlDependencyRecorder (context, dependenciesFileName));
+ continue;
+ case "u":
+ if (!GetStringParam (token, l => context.UserAction = ParseAssemblyAction (l)))
+ return false;
- foreach (string custom_step in custom_steps)
- AddCustomStep (p, custom_step);
+ continue;
+ case "p":
+ if (arguments.Count < 2) {
+ ErrorMissingArgument (token);
+ return false;
+ }
- if (context.AddReflectionAnnotations)
- p.AddStepAfter (typeof (MarkStep), new ReflectionBlockedStep ());
+ AssemblyAction action = ParseAssemblyAction (arguments.Dequeue ());
+ context.Actions [arguments.Dequeue ()] = action;
+ continue;
+ case "t":
+ context.KeepTypeForwarderOnlyAssemblies = true;
+ continue;
+ case "x":
+ if (!GetStringParam (token, l => {
+ foreach (string file in GetFiles (l))
+ p.PrependStep (new ResolveFromXmlStep (new XPathDocument (file)));
+ }))
+ return false;
+
+ resolver = true;
+ continue;
+ case "r":
+ case "a":
+ if (!GetStringParam (token, l => {
+
+ var rootVisibility = (token [1] == 'r')
+ ? ResolveFromAssemblyStep.RootVisibility.PublicAndFamily
+ : ResolveFromAssemblyStep.RootVisibility.Any;
+ foreach (string file in GetFiles (l))
+ p.PrependStep (new ResolveFromAssemblyStep (file, rootVisibility));
+ }))
+ return false;
+
+ resolver = true;
+ continue;
#if !FEATURE_ILLINK
- p.AddStepAfter (typeof (LoadReferencesStep), new LoadI18nAssemblies (assemblies));
+ case "i":
+ if (!GetStringParam (token, l => {
+ foreach (string file in GetFiles (l))
+ p.PrependStep (new ResolveFromXApiStep (new XPathDocument (file)));
+ }))
+ return false;
+
+ resolver = true;
+ continue;
+ case "l":
+ if (!GetStringParam (token, l => assemblies = ParseI18n (l)))
+ return false;
- if (assemblies != I18nAssemblies.None) {
- p.AddStepAfter (typeof (PreserveDependencyLookupStep), new PreserveCalendarsStep (assemblies));
- }
+ continue;
#endif
+ case "m":
+ if (arguments.Count < 2) {
+ ErrorMissingArgument (token);
+ return false;
+ }
- if (_needAddBypassNGenStep) {
- p.AddStepAfter (typeof (SweepStep), new AddBypassNGenStep ());
- }
+ context.SetParameter (arguments.Dequeue (), arguments.Dequeue ());
+ continue;
+ case "b":
+ if (!GetBoolParam (token, l => context.LinkSymbols = l))
+ return false;
- p.AddStepBefore (typeof (MarkStep), new BodySubstituterStep ());
+ continue;
+ case "g":
+ if (!GetBoolParam (token, l => context.DeterministicOutput = !l))
+ return false;
- if (removeCAS)
- p.AddStepBefore (typeof (MarkStep), new RemoveSecurityStep ());
+ continue;
+ case "z":
+ if (!GetBoolParam (token, l => ignoreDescriptors = !l))
+ return false;
- if (excluded_features.Count > 0) {
+ continue;
+ case "v":
+ if (!GetBoolParam (token, l => context.KeepMembersForDebugger = l))
+ return false;
- p.AddStepBefore (typeof (MarkStep), new RemoveFeaturesStep () {
- FeatureCOM = excluded_features.Contains ("com"),
- FeatureETW = excluded_features.Contains ("etw"),
- FeatureSRE = excluded_features.Contains ("sre"),
- FeatureGlobalization = excluded_features.Contains ("globalization")
- });
+ continue;
+ case "?":
+ case "help":
+ Usage ();
+ return true;
- var excluded = new string [excluded_features.Count];
- excluded_features.CopyTo (excluded);
- context.ExcludedFeatures = excluded;
+ case "reference":
+ if (!GetStringParam (token, l => context.Resolver.AddReferenceAssembly (l)))
+ return false;
+
+ continue;
+ }
+ }
+
+ ErrorUnrecognizedOption (token);
+ return false;
}
- p.AddStepBefore (typeof (MarkStep), new RemoveUnreachableBlocksStep ());
+ if (!resolver) {
+ Console.WriteLine ($"No files to link were specified. Use one of '{resolvers}' options");
+ return false;
+ }
+
+ if (new_mvid_used && deterministic_used) {
+ Console.WriteLine ($"Options '--new-mvid' and '--deterministic' cannot be used at the same time");
+ return false;
+ }
+
+ if (dumpDependencies)
+ context.Tracer.AddRecorder (new XmlDependencyRecorder (context, dependenciesFileName));
if (disabled_optimizations.Count > 0) {
foreach (var item in disabled_optimizations) {
@@ -446,48 +527,145 @@ namespace Mono.Linker {
}
}
+ //
+ // Modify the default pipeline
+ //
+ if (ignoreDescriptors)
+ p.RemoveStep (typeof (BlacklistStep));
+
+ if (context.DeterministicOutput)
+ p.RemoveStep (typeof (RegenerateGuidStep));
+
+ if (context.AddReflectionAnnotations)
+ p.AddStepAfter (typeof (MarkStep), new ReflectionBlockedStep ());
+
+#if !FEATURE_ILLINK
+ p.AddStepAfter (typeof (LoadReferencesStep), new LoadI18nAssemblies (assemblies));
+
+ if (assemblies != I18nAssemblies.None) {
+ p.AddStepAfter (typeof (PreserveDependencyLookupStep), new PreserveCalendarsStep (assemblies));
+ }
+#endif
+
+ if (_needAddBypassNGenStep) {
+ p.AddStepAfter (typeof (SweepStep), new AddBypassNGenStep ());
+ }
+
+ p.AddStepBefore (typeof (MarkStep), new BodySubstituterStep ());
+
+ if (removeCAS)
+ p.AddStepBefore (typeof (MarkStep), new RemoveSecurityStep ());
+
+ if (excluded_features.Count > 0) {
+ p.AddStepBefore (typeof (MarkStep), new RemoveFeaturesStep () {
+ FeatureCOM = excluded_features.Contains ("com"),
+ FeatureETW = excluded_features.Contains ("etw"),
+ FeatureSRE = excluded_features.Contains ("sre"),
+ FeatureGlobalization = excluded_features.Contains ("globalization")
+ });
+
+ var excluded = new string [excluded_features.Count];
+ excluded_features.CopyTo (excluded);
+ context.ExcludedFeatures = excluded;
+ }
+
+ p.AddStepBefore (typeof (MarkStep), new RemoveUnreachableBlocksStep ());
+
if (context.IsOptimizationEnabled (CodeOptimizations.ClearInitLocals))
p.AddStepBefore (typeof (OutputStep), new ClearInitLocalsStep ());
+
+ //
+ // Pipeline setup with all steps enabled
+ //
+ // LoadReferencesStep
+ // BlacklistStep [optional]
+ // PreserveDependencyLookupStep
+ // TypeMapStep
+ // BodySubstituterStep [optional]
+ // RemoveSecurityStep [optional]
+ // RemoveFeaturesStep [optional]
+ // RemoveUnreachableBlocksStep [optional]
+ // MarkStep
+ // ReflectionBlockedStep [optional]
+ // SweepStep
+ // AddBypassNGenStep [optional]
+ // CodeRewriterStep
+ // CleanStep
+ // RegenerateGuidStep [optional]
+ // ClearInitLocalsStep [optional]
+ // OutputStep
+ //
+
+ foreach (string custom_step in custom_steps) {
+ if (!AddCustomStep (p, custom_step))
+ return false;
+ }
+
PreProcessPipeline (p);
try {
p.Process (context);
- }
- finally {
+ } finally {
context.Tracer.Finish ();
}
+
+ return true;
}
}
partial void PreProcessPipeline (Pipeline pipeline);
- protected static void AddCustomStep (Pipeline pipeline, string arg)
+ protected static bool AddCustomStep (Pipeline pipeline, string arg)
{
int pos = arg.IndexOf (":");
if (pos == -1) {
- pipeline.AppendStep (ResolveStep (arg));
- return;
+ var step = ResolveStep (arg);
+ if (step == null)
+ return false;
+
+ pipeline.AppendStep (step);
+ return true;
+ }
+
+ string[] parts = arg.Split (':');
+ if (parts.Length != 2) {
+ Console.WriteLine ($"Invalid value '{arg}' specified for '--custom-step' option");
+ return false;
}
- string [] parts = arg.Split (':');
- if (parts.Length != 2)
- Usage ("Step is specified as TYPE:STEP");
+ if (!parts[0].StartsWith ("-") && !parts [0].StartsWith ("+")) {
+ Console.WriteLine ($"Expected '+' or '-' to control new step insertion");
+ return false;
+ }
+
+ bool before = parts [0][0] == '-';
+ string name = parts [0].Substring (1);
- if (parts [0].IndexOf (",") > -1)
- pipeline.AddStepBefore (FindStep (pipeline, parts [1]), ResolveStep (parts [0]));
- else if (parts [1].IndexOf (",") > -1)
- pipeline.AddStepAfter (FindStep (pipeline, parts [0]), ResolveStep (parts [1]));
+ IStep target = FindStep (pipeline, name);
+ if (target == null) {
+ Console.WriteLine ($"Pipeline step '{name}' could not be found");
+ return false;
+ }
+
+ IStep newStep = ResolveStep (parts [1]);
+ if (newStep == null)
+ return false;
+
+ if (before)
+ pipeline.AddStepBefore (target, newStep);
else
- Usage ("No comma separator in TYPE or STEP");
+ pipeline.AddStepAfter (target, newStep);
+
+ return true;
}
- static Type FindStep (Pipeline pipeline, string name)
+ static IStep FindStep (Pipeline pipeline, string name)
{
foreach (IStep step in pipeline.GetSteps ()) {
Type t = step.GetType ();
if (t.Name == name)
- return t;
+ return step;
}
return null;
@@ -496,10 +674,16 @@ namespace Mono.Linker {
static IStep ResolveStep (string type)
{
Type step = Type.GetType (type, false);
- if (step == null)
- Usage (String.Format ("Step type '{0}' not found.", type));
- if (!typeof (IStep).IsAssignableFrom (step))
- Usage (String.Format ("Step type '{0}' does not implement IStep interface.", type));
+ if (step == null) {
+ Console.WriteLine ($"Custom step '{type}' could not be found");
+ return null;
+ }
+
+ if (!typeof (IStep).IsAssignableFrom (step)) {
+ Console.WriteLine ($"Custom step '{type}' is incompatible with this linker version");
+ return null;
+ }
+
return (IStep) Activator.CreateInstance (step);
}
@@ -547,33 +731,66 @@ namespace Mono.Linker {
return assemblyAction;
}
- string GetParam ()
+ bool GetBoolParam (string token, Action<bool> action)
{
- if (_queue.Count == 0)
- Usage ("Expecting a parameter");
+ if (arguments.Count == 0) {
+ action (true);
+ return true;
+ }
+
+ var arg = arguments.Peek ();
+ if (bool.TryParse (arg.ToLowerInvariant (), out bool value)) {
+ arguments.Dequeue ();
+ action (value);
+ return true;
+ }
+
+ if (arg.StartsWith ("-") || arg.StartsWith ("/")) {
+ action (true);
+ return true;
+ }
- return _queue.Dequeue ();
+ Console.WriteLine ($"Invalid argument for '{token}' option");
+ return false;
}
+ bool GetStringParam (string token, Action<string> action)
+ {
+ if (arguments.Count < 1) {
+ ErrorMissingArgument (token);
+ return false;
+ }
+
+ var arg = arguments.Dequeue ();
+ if (!string.IsNullOrEmpty (arg)) {
+ action (arg);
+ return true;
+ }
+
+ ErrorMissingArgument (token);
+ return false;
+ }
+
+
protected virtual LinkContext GetDefaultContext (Pipeline pipeline)
{
- LinkContext context = new LinkContext (pipeline);
- context.CoreAction = AssemblyAction.Skip;
- context.UserAction = AssemblyAction.Link;
- context.OutputDirectory = "output";
- context.StripResources = true;
+ LinkContext context = new LinkContext (pipeline) {
+ CoreAction = AssemblyAction.Skip,
+ UserAction = AssemblyAction.Link,
+ OutputDirectory = "output",
+ StripResources = true
+ };
return context;
}
- static void Usage (string msg)
+ static void Usage ()
{
Console.WriteLine (_linker);
- if (msg != null)
- Console.WriteLine ("Error: " + msg);
+
#if FEATURE_ILLINK
- Console.WriteLine ("illink [options] -a|-r|-x file");
+ Console.WriteLine ($"illink [options] {resolvers} file");
#else
- Console.WriteLine ("monolinker [options] -a|-i|-r|-x file");
+ Console.WriteLine ($"monolinker [options] {resolvers} file");
#endif
Console.WriteLine (" -a Link from a list of assemblies");
@@ -594,6 +811,7 @@ namespace Mono.Linker {
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 (" -help Lists all linker options");
Console.WriteLine (" @<file> Read response file for more options");
Console.WriteLine ();
@@ -610,7 +828,17 @@ namespace Mono.Linker {
Console.WriteLine ();
Console.WriteLine ("Advanced");
- Console.WriteLine (" --custom-step <name> Add a custom step to the pipeline");
+ Console.WriteLine (" --custom-step <config> Add a custom step <config> to the existing pipeline");
+ Console.WriteLine (" Step can use one of following configurations");
+ Console.WriteLine (" <type>: Add user defined type <type> as last step to the pipeline");
+ Console.WriteLine (" +<stepname:type>: Inserts step <type> before existing <stepname>");
+ Console.WriteLine (" -<stepname:type>: Add step <type> after existing step");
+ 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 (" --skip-unresolved Ignore unresolved types, methods, and assemblies. Defaults to false");
+
+ Console.WriteLine ();
+ Console.WriteLine ("Linking");
Console.WriteLine (" --deterministic Produce a deterministic output for linked assemblies");
Console.WriteLine (" --disable-opt <name> Disable one of the default optimizations");
Console.WriteLine (" beforefieldinit: Unused static fields are removed if there is no static ctor");
@@ -623,19 +851,18 @@ namespace Mono.Linker {
Console.WriteLine (" --exclude-feature <name> Any code which has a feature <name> in linked assemblies will be removed");
Console.WriteLine (" com: Support for COM Interop");
Console.WriteLine (" etw: Event Tracing for Windows");
+#if !FEATURE_ILLINK
Console.WriteLine (" remoting: .NET Remoting dependencies");
+#endif
Console.WriteLine (" sre: System.Reflection.Emit namespace");
Console.WriteLine (" globalization: Globalization data and globalization behavior");
- 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 (" --explicit-reflection Adds to members never used through reflection DisablePrivateReflection attribute. Defaults to false");
Console.WriteLine (" --keep-dep-attributes Keep attributes used for manual dependency tracking. 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 (" --substitutions <file> Configuration file with methods substitution rules");
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");
- Console.WriteLine (" --explicit-reflection Adds to members never used through reflection DisablePrivateReflection attribute. Defaults to false");
+ Console.WriteLine (" --substitutions <file> Configuration file with field or methods substitution rules");
+ Console.WriteLine (" --used-attrs-only Attribute usage is removed if the attribute type is not used. Defaults to false");
Console.WriteLine ();
Console.WriteLine ("Analyzer");
@@ -643,8 +870,6 @@ namespace Mono.Linker {
Console.WriteLine (" --dump-dependencies Dump dependencies for the linker analyzer tool");
Console.WriteLine (" --reduced-tracing Reduces dependency output related to assemblies that will not be modified");
Console.WriteLine ("");
-
- Environment.Exit (1);
}
static void Version ()
@@ -652,16 +877,12 @@ namespace Mono.Linker {
Console.WriteLine ("{0} Version {1}",
_linker,
System.Reflection.Assembly.GetExecutingAssembly ().GetName ().Version);
-
- Environment.Exit(1);
}
static void About ()
{
Console.WriteLine ("For more information, visit the project Web site");
Console.WriteLine (" http://www.mono-project.com/");
-
- Environment.Exit(1);
}
static Pipeline GetStandardPipeline ()
diff --git a/test/Mono.Linker.Tests/TestCasesRunner/LinkerDriver.cs b/test/Mono.Linker.Tests/TestCasesRunner/LinkerDriver.cs
index eb9a78a50..521094d8f 100644
--- a/test/Mono.Linker.Tests/TestCasesRunner/LinkerDriver.cs
+++ b/test/Mono.Linker.Tests/TestCasesRunner/LinkerDriver.cs
@@ -1,10 +1,12 @@
-namespace Mono.Linker.Tests.TestCasesRunner {
+using System.Collections.Generic;
+
+namespace Mono.Linker.Tests.TestCasesRunner {
public class LinkerDriver {
protected class TestDriver : Driver
{
LinkerCustomizations _customization;
- public TestDriver(string[] args, LinkerCustomizations customizations) : base(args)
+ public TestDriver(Queue<string> args, LinkerCustomizations customizations) : base(args)
{
_customization = customizations;
}
@@ -19,7 +21,8 @@
public virtual void Link (string [] args, LinkerCustomizations customizations, ILogger logger)
{
- new TestDriver (args, customizations).Run (logger);
+ Driver.ProcessResponseFile (args, out var queue);
+ new TestDriver (queue, customizations).Run (logger);
}
}
} \ No newline at end of file