- Add handling of "-?" and no command line arguments.
- Print out default values for --targetos and --targetarch
- Describe behavior of response files
- Describe the behavior of the -- switch
- Describe in much greater detail the valid values for the --instruction-set switch
Fix #47486
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
private readonly List<Argument> _options = new List<Argument>();
private readonly List<Argument> _parameters = new List<Argument>();
+ private readonly List<string> _extraHelpParagraphs = new List<string>();
+
private ArgumentParser _parser;
private ArgumentCommand _definedCommand;
private ArgumentCommand _activeCommand;
{
return HelpTextGenerator.Generate(this, maxWidth);
}
+
+ public IReadOnlyList<string> ExtraHelpParagraphs
+ {
+ set
+ {
+ _extraHelpParagraphs.Clear();
+ _extraHelpParagraphs.AddRange(value);
+ }
+ get
+ {
+ return _extraHelpParagraphs.ToArray();
+ }
+ }
}
}
public string ApplicationName;
public IEnumerable<string> SyntaxElements;
public IReadOnlyList<HelpRow> Rows;
+ public IReadOnlyList<string> ExtraParagraphs;
}
private struct HelpRow
sb.WriteRows(page.Rows, maxWidth);
sb.AppendLine();
+
+ if (page.ExtraParagraphs != null)
+ {
+ foreach (string text in page.ExtraParagraphs)
+ {
+ var words = SplitWords(text);
+ sb.WriteWordWrapped(words, 0, maxWidth);
+ }
+ }
}
private static void WriteUsage(this StringBuilder sb, string applicationName, IEnumerable<string> syntaxElements, int maxWidth)
{
ApplicationName = argumentSyntax.ApplicationName,
SyntaxElements = GetGlobalSyntax(),
- Rows = GetCommandRows(argumentSyntax).ToArray()
+ Rows = GetCommandRows(argumentSyntax).ToArray(),
+ ExtraParagraphs = argumentSyntax.ExtraHelpParagraphs
};
}
{
ApplicationName = argumentSyntax.ApplicationName,
SyntaxElements = GetCommandSyntax(argumentSyntax, command),
- Rows = GetArgumentRows(argumentSyntax, command).ToArray()
+ Rows = GetArgumentRows(argumentSyntax, command).ToArray(),
+ ExtraParagraphs = argumentSyntax.ExtraHelpParagraphs
};
}
using System.Collections.Generic;
using System.IO;
using System.Reflection;
+using System.Text;
using Internal.CommandLine;
+using Internal.TypeSystem;
namespace ILCompiler
{
Parallelism = Environment.ProcessorCount;
SingleMethodGenericArg = null;
+ bool forceHelp = false;
+ if (args.Length == 0)
+ {
+ forceHelp = true;
+ }
+
+ foreach (string arg in args)
+ {
+ if (arg == "-?")
+ forceHelp = true;
+ }
+
+ if (forceHelp)
+ {
+ args = new string[] {"--help"};
+ }
+
ArgumentSyntax argSyntax = ArgumentSyntax.Parse(args, syntax =>
{
syntax.ApplicationName = typeof(Program).Assembly.GetName().Name.ToString();
if (Help)
{
+ List<string> extraHelp = new List<string>();
+ extraHelp.Add(SR.OptionPassingHelp);
+ extraHelp.Add("");
+ extraHelp.Add(SR.DashDashHelp);
+ extraHelp.Add("");
+
+ string[] ValidArchitectures = new string[] {"arm", "armel", "arm64", "x86", "x64"};
+ string[] ValidOS = new string[] {"windows", "linux", "osx"};
+ TargetOS defaultOs;
+ TargetArchitecture defaultArch;
+ Program.ComputeDefaultOptions(out defaultOs, out defaultArch);
+
+ extraHelp.Add(String.Format(SR.SwitchWithDefaultHelp, "--targetos", String.Join("', '", ValidOS), defaultOs.ToString().ToLowerInvariant()));
+
+ extraHelp.Add("");
+
+ extraHelp.Add(String.Format(SR.SwitchWithDefaultHelp, "--targetarch", String.Join("', '", ValidArchitectures), defaultArch.ToString().ToLowerInvariant()));
+
+ extraHelp.Add("");
+
+ extraHelp.Add(SR.InstructionSetHelp);
+ foreach (string arch in ValidArchitectures)
+ {
+ StringBuilder archString = new StringBuilder();
+
+ archString.Append(arch);
+ archString.Append(": ");
+
+ TargetArchitecture targetArch = Program.GetTargetArchitectureFromArg(arch, out _);
+ bool first = true;
+ foreach (var instructionSet in Internal.JitInterface.InstructionSetFlags.ArchitectureToValidInstructionSets(targetArch))
+ {
+ // Only instruction sets with are specifiable should be printed to the help text
+ if (instructionSet.Specifiable)
+ {
+ if (first)
+ {
+ first = false;
+ }
+ else
+ {
+ archString.Append(", ");
+ }
+ archString.Append(instructionSet.Name);
+ }
+ }
+
+ extraHelp.Add(archString.ToString());
+ }
+
+ argSyntax.ExtraHelpParagraphs = extraHelp;
+
HelpText = argSyntax.GetHelpText();
}
}
{
}
- private void InitializeDefaultOptions()
+ public static void ComputeDefaultOptions(out TargetOS os, out TargetArchitecture arch)
{
- // We could offer this as a command line option, but then we also need to
- // load a different RyuJIT, so this is a future nice to have...
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
- _targetOS = TargetOS.Windows;
+ os = TargetOS.Windows;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
- _targetOS = TargetOS.Linux;
+ os = TargetOS.Linux;
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
- _targetOS = TargetOS.OSX;
+ os = TargetOS.OSX;
else
throw new NotImplementedException();
switch (RuntimeInformation.ProcessArchitecture)
{
case Architecture.X86:
- _targetArchitecture = TargetArchitecture.X86;
+ arch = TargetArchitecture.X86;
break;
case Architecture.X64:
- _targetArchitecture = TargetArchitecture.X64;
+ arch = TargetArchitecture.X64;
break;
case Architecture.Arm:
- _targetArchitecture = TargetArchitecture.ARM;
+ arch = TargetArchitecture.ARM;
break;
case Architecture.Arm64:
- _targetArchitecture = TargetArchitecture.ARM64;
+ arch = TargetArchitecture.ARM64;
break;
default:
throw new NotImplementedException();
}
+
+ }
+
+ private void InitializeDefaultOptions()
+ {
+ ComputeDefaultOptions(out _targetOS, out _targetArchitecture);
}
private void ProcessCommandLine(string[] args)
}
+ public static TargetArchitecture GetTargetArchitectureFromArg(string archArg, out bool armelAbi)
+ {
+ armelAbi = false;
+ if (archArg.Equals("x86", StringComparison.OrdinalIgnoreCase))
+ return TargetArchitecture.X86;
+ else if (archArg.Equals("x64", StringComparison.OrdinalIgnoreCase))
+ return TargetArchitecture.X64;
+ else if (archArg.Equals("arm", StringComparison.OrdinalIgnoreCase))
+ return TargetArchitecture.ARM;
+ else if (archArg.Equals("armel", StringComparison.OrdinalIgnoreCase))
+ {
+ armelAbi = true;
+ return TargetArchitecture.ARM;
+ }
+ else if (archArg.Equals("arm64", StringComparison.OrdinalIgnoreCase))
+ return TargetArchitecture.ARM64;
+ else
+ throw new CommandLineException(SR.TargetArchitectureUnsupported);
+ }
+
private void ConfigureTarget()
{
//
//
if (_commandLineOptions.TargetArch != null)
{
- if (_commandLineOptions.TargetArch.Equals("x86", StringComparison.OrdinalIgnoreCase))
- _targetArchitecture = TargetArchitecture.X86;
- else if (_commandLineOptions.TargetArch.Equals("x64", StringComparison.OrdinalIgnoreCase))
- _targetArchitecture = TargetArchitecture.X64;
- else if (_commandLineOptions.TargetArch.Equals("arm", StringComparison.OrdinalIgnoreCase))
- _targetArchitecture = TargetArchitecture.ARM;
- else if (_commandLineOptions.TargetArch.Equals("armel", StringComparison.OrdinalIgnoreCase))
- {
- _targetArchitecture = TargetArchitecture.ARM;
- _armelAbi = true;
- }
- else if (_commandLineOptions.TargetArch.Equals("arm64", StringComparison.OrdinalIgnoreCase))
- _targetArchitecture = TargetArchitecture.ARM64;
- else
- throw new CommandLineException(SR.TargetArchitectureUnsupported);
+ _targetArchitecture = GetTargetArchitectureFromArg(_commandLineOptions.TargetArch, out _armelAbi);
}
if (_commandLineOptions.TargetOS != null)
{
<data name="PerfMapFormatVersionOption" xml:space="preserve">
<value>Explicitly request a particular PerfMap format version</value>
</data>
-</root>
\ No newline at end of file
+ <data name="OptionPassingHelp" xml:space="preserve">
+ <value>Options may be passed on the command line, or via response file. On the command line switch values may be specified by passing the option followed by a space followed by the value of the option, or by specifying a : between option and switch value. A response file is specified by passing the @ symbol before the response file name. In a response file all options must be specified on their own lines, and only the : syntax for switches is supported.</value>
+ </data>
+ <data name="DashDashHelp" xml:space="preserve">
+ <value>Use the '--' option to disambiguate between input files that have begin with -- and options. After a '--' option, all arguments are considered to be input files. If no input files begin with '--' then this option is not necessary.</value>
+ </data>
+ <data name="SwitchWithDefaultHelp" xml:space="preserve">
+ <value>Valid switches for {0} are: '{1}'. The default value is '{2}'.</value>
+ </data>
+ <data name="InstructionSetHelp" xml:space="preserve">
+ <value>The allowable values for the --instruction-set option are described in the table below. Each architecture has a different set of valid instruction sets, and multiple instruction sets may be specified by separating the instructions sets by a ','. For example 'avx2,bmi,lzcnt'</value>
+ </data>
+</root>