<Uri>https://github.com/dotnet/llvm-project</Uri>
<Sha>f17917e8d6a2e3ba069cddeab873554706d502a5</Sha>
</Dependency>
+ <Dependency Name="System.CommandLine" Version="2.0.0-beta3.22151.2">
+ <Uri>https://github.com/dotnet/command-line-api</Uri>
+ <Sha>021ec68a4cb510c2cc125c6ebb78b9cfd4e3847a</Sha>
+ </Dependency>
</ProductDependencies>
<ToolsetDependencies>
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="7.0.0-beta.22166.1">
<optimizationPGOCoreCLRVersion>1.0.0-prerelease.22121.2</optimizationPGOCoreCLRVersion>
<!-- Not auto-updated. -->
<MicrosoftDiaSymReaderNativeVersion>16.9.0-beta1.21055.5</MicrosoftDiaSymReaderNativeVersion>
- <SystemCommandLineVersion>2.0.0-beta1.20253.1</SystemCommandLineVersion>
+ <SystemCommandLineVersion>2.0.0-beta3.22114.1</SystemCommandLineVersion>
<TraceEventVersion>2.0.65</TraceEventVersion>
- <CommandLineParserVersion>2.2.0</CommandLineParserVersion>
<NETStandardLibraryRefVersion>2.1.0</NETStandardLibraryRefVersion>
<NetStandardLibraryVersion>2.0.3</NetStandardLibraryVersion>
<MicrosoftDiagnosticsToolsRuntimeClientVersion>1.0.4-preview6.19326.1</MicrosoftDiagnosticsToolsRuntimeClientVersion>
using System;
using System.Collections.Generic;
using System.CommandLine;
+using System.CommandLine.Builder;
using System.CommandLine.Invocation;
+using System.CommandLine.Parsing;
using System.IO;
using System.Linq;
using System.Reflection;
return patternList;
}
- public class Options
- {
- public string[] InputFilePath { get; set; }
- public string[] Reference { get; set; }
- public string SystemModule { get; set; }
- public bool SanityChecks { get; set; }
- public string[] Include { get; set; }
- public FileInfo IncludeFile { get; set; }
- public string[] Exclude { get; set; }
- public FileInfo ExcludeFile { get; set; }
- public string[] IgnoreError { get; set; }
- public FileInfo IgnoreErrorFile { get; set; }
- public bool Statistics { get; set; }
- public bool Verbose { get; set; }
- public bool Tokens { get; set; }
- }
-
- public static RootCommand RootCommand()
- {
- RootCommand command = new RootCommand();
- command.AddArgument(new Argument<string[]>("input-file-path", "Input file(s)") { Arity = new ArgumentArity(1, Int32.MaxValue) });
- command.AddOption(new Option<string[]>(new[] { "--reference", "-r" }, "Reference metadata from the specified assembly"));
- command.AddOption(new Option<string>(new[] { "--system-module", "-s" }, "System module name (default: mscorlib)"));
- command.AddOption(new Option<bool>(new[] { "--sanity-checks", "-c" }, "Check for valid constructs that are likely mistakes"));
- command.AddOption(new Option<string[]>(new[] { "--include", "-i" }, "Use only methods/types/namespaces, which match the given regular expression(s)"));
- command.AddOption(new Option<FileInfo>(new[] { "--include-file" }, "Same as --include, but the regular expression(s) are declared line by line in the specified file.").ExistingOnly());
- command.AddOption(new Option<string[]>(new[] { "--exclude", "-e" }, "Skip methods/types/namespaces, which match the given regular expression(s)"));
- command.AddOption(new Option<FileInfo>(new[] { "--exclude-file" }, "Same as --exclude, but the regular expression(s) are declared line by line in the specified file.").ExistingOnly());
- command.AddOption(new Option<string[]>(new[] { "--ignore-error", "-g" }, "Ignore errors, which match the given regular expression(s)"));
- command.AddOption(new Option<FileInfo>(new[] { "--ignore-error-file" }, "Same as --ignore-error, but the regular expression(s) are declared line by line in the specified file.").ExistingOnly());
- command.AddOption(new Option<bool>(new[] { "--statistics" }, "Print verification statistics"));
- command.AddOption(new Option<bool>(new[] { "--verbose", "-v" }, "Verbose output"));
- command.AddOption(new Option<bool>(new[] { "--tokens", "-t" }, "Include metadata tokens in error messages"));
- return command;
- }
-
private Program(Options options)
{
_options = options;
return null;
}
- private static int Run(Options options)
+ //
+ // Command line parsing
+ //
+
+ private class ILVerifyRootCommand : RootCommand
{
- try
- {
- return new Program(options).Run();
- }
- catch (CommandLineException e)
- {
- Console.WriteLine("Error: " + e.Message);
- return 1;
- }
- catch (Exception e)
+ public Argument<string[]> InputFilePath { get; } =
+ new("input-file-path", "Input file(s)") { Arity = ArgumentArity.OneOrMore };
+ public Option<string[]> Reference { get; } =
+ new(new[] { "--reference", "-r" }, "Reference metadata from the specified assembly");
+ public Option<string> SystemModule { get; } =
+ new(new[] { "--system-module", "-s" }, "System module name (default: mscorlib)");
+ public Option<bool> SanityChecks { get; } =
+ new(new[] { "--sanity-checks", "-c" }, "Check for valid constructs that are likely mistakes");
+ public Option<string[]> Include { get; } =
+ new(new[] { "--include", "-i" }, "Use only methods/types/namespaces, which match the given regular expression(s)");
+ public Option<FileInfo> IncludeFile { get; } =
+ new Option<FileInfo>(new[] { "--include-file" }, "Same as --include, but the regular expression(s) are declared line by line in the specified file.").ExistingOnly();
+ public Option<string[]> Exclude { get; } =
+ new(new[] { "--exclude", "-e" }, "Skip methods/types/namespaces, which match the given regular expression(s)");
+ public Option<FileInfo> ExcludeFile { get; } =
+ new Option<FileInfo>(new[] { "--exclude-file" }, "Same as --exclude, but the regular expression(s) are declared line by line in the specified file.").ExistingOnly();
+ public Option<string[]> IgnoreError { get; } =
+ new(new[] { "--ignore-error", "-g" }, "Ignore errors, which match the given regular expression(s)");
+ public Option<FileInfo> IgnoreErrorFile { get; } =
+ new Option<FileInfo>(new[] { "--ignore-error-file" }, "Same as --ignore-error, but the regular expression(s) are declared line by line in the specified file.").ExistingOnly();
+ public Option<bool> Statistics { get; } =
+ new(new[] { "--statistics" }, "Print verification statistics");
+ public Option<bool> Verbose { get; } =
+ new(new[] { "--verbose", "-v" }, "Verbose output");
+ public Option<bool> Tokens { get; } =
+ new(new[] { "--tokens", "-t" }, "Include metadata tokens in error messages");
+
+ public ILVerifyRootCommand()
+ : base("Tool for verifying MSIL code based on ECMA-335.")
{
- Console.WriteLine("Error: " + e.ToString());
- return 1;
+ AddArgument(InputFilePath);
+ AddOption(Reference);
+ AddOption(SystemModule);
+ AddOption(SanityChecks);
+ AddOption(Include);
+ AddOption(IncludeFile);
+ AddOption(Exclude);
+ AddOption(ExcludeFile);
+ AddOption(IgnoreError);
+ AddOption(IgnoreErrorFile);
+ AddOption(Statistics);
+ AddOption(Verbose);
+ AddOption(Tokens);
+
+ this.SetHandler<InvocationContext>((InvocationContext context) =>
+ {
+ try
+ {
+ context.ExitCode = new Program(new Options(this, context.ParseResult)).Run();
+ }
+ catch (Exception e)
+ {
+ Console.ResetColor();
+ Console.ForegroundColor = ConsoleColor.Red;
+
+ // Omit the stacktrace from the error (different from the default System.CommandLine exception handler)
+ Console.Error.WriteLine("Error: " + e.Message);
+
+ Console.ResetColor();
+
+ context.ExitCode = 1;
+ }
+ });
}
}
- private static async Task<int> Main(string[] args)
+ private class Options
{
- var command = RootCommand();
- command.Handler = CommandHandler.Create<Options>(Run);
- return await command.InvokeAsync(args);
+ public Options(ILVerifyRootCommand cmd, ParseResult res)
+ {
+ InputFilePath = res.GetValueForArgument(cmd.InputFilePath);
+ Reference = res.GetValueForOption(cmd.Reference);
+ SystemModule = res.GetValueForOption(cmd.SystemModule);
+ SanityChecks = res.GetValueForOption(cmd.SanityChecks);
+ Include = res.GetValueForOption(cmd.Include);
+ IncludeFile = res.GetValueForOption(cmd.IncludeFile);
+ Exclude = res.GetValueForOption(cmd.Exclude);
+ ExcludeFile = res.GetValueForOption(cmd.ExcludeFile);
+ IgnoreError = res.GetValueForOption(cmd.IgnoreError);
+ IgnoreErrorFile = res.GetValueForOption(cmd.IgnoreErrorFile);
+ Statistics = res.GetValueForOption(cmd.Statistics);
+ Verbose = res.GetValueForOption(cmd.Verbose);
+ Tokens = res.GetValueForOption(cmd.Tokens);
+ }
+
+ public string[] InputFilePath { get; }
+ public string[] Reference { get; }
+ public string SystemModule { get; }
+ public bool SanityChecks { get; }
+ public string[] Include { get; }
+ public FileInfo IncludeFile { get; }
+ public string[] Exclude { get; }
+ public FileInfo ExcludeFile { get; }
+ public string[] IgnoreError { get; }
+ public FileInfo IgnoreErrorFile { get; }
+ public bool Statistics { get; }
+ public bool Verbose { get; }
+ public bool Tokens { get; }
}
+
+ private static int Main(string[] args) =>
+ new CommandLineBuilder(new ILVerifyRootCommand())
+ .UseVersionOption()
+ .UseHelp()
+ .UseParseErrorReporting()
+ .Build()
+ .Invoke(args);
}
}
// The .NET Foundation licenses this file to you under the MIT license.
using System.CommandLine;
+using System.CommandLine.Invocation;
+using System.CommandLine.Parsing;
using System.IO;
namespace R2RDump
{
- internal static class CommandLineOptions
+ public class R2RDumpRootCommand : RootCommand
{
- public static RootCommand RootCommand()
+ public Option<FileInfo[]> In { get; } =
+ new(new[] { "--in", "-i" }, "Input file(s) to dump. Expects them to by ReadyToRun images");
+ public Option<FileInfo> Out { get; } =
+ new(new[] { "--out", "-o" }, "Output file path. Dumps everything to the specified file except for help message and exception messages");
+ public Option<bool> Raw { get; } =
+ new(new[] { "--raw" }, "Dump the raw bytes of each section or runtime function");
+ public Option<bool> Header { get; } =
+ new(new[] { "--header" }, "Dump R2R header");
+ public Option<bool> Disasm { get; } =
+ new(new[] { "--disasm", "-d" }, "Show disassembly of methods or runtime functions");
+ public Option<bool> Naked { get; } =
+ new(new[] { "--naked" }, "Naked dump suppresses most compilation details like placement addresses");
+ public Option<bool> HideOffsets { get; } =
+ new(new[] { "--hide-offsets", "--ho" }, "Hide offsets in naked disassembly");
+
+ public Option<string[]> Query { get; } =
+ new(new[] { "--query", "-q" }, "Query method by exact name, signature, row ID or token");
+ public Option<string[]> Keyword { get; } =
+ new(new[] { "--keyword", "-k" }, "Search method by keyword");
+ public Option<string[]> RuntimeFunction { get; } =
+ new(new[] { "--runtimefunction", "-f" }, "Get one runtime function by id or relative virtual address");
+ public Option<string[]> Section { get; } =
+ new(new[] { "--section", "-s" }, "Get section by keyword");
+
+ public Option<bool> Unwind { get; } =
+ new(new[] { "--unwind" }, "Dump unwindInfo");
+ public Option<bool> GC { get; } =
+ new(new[] { "--gc" }, "Dump gcInfo and slot table");
+ public Option<bool> Pgo { get; } =
+ new(new[] { "--pgo" }, "Dump embedded pgo instrumentation data");
+ public Option<bool> SectionContents { get; } =
+ new(new[] { "--sectionContents", "--sc" }, "Dump section contents");
+ public Option<bool> EntryPoints { get; } =
+ new(new[] { "--entrypoints", "-e" }, "Dump list of method / instance entrypoints in the R2R file");
+ public Option<bool> Normalize { get; } =
+ new(new[] { "--normalize", "-n" }, "Normalize dump by sorting the various tables and methods (default = unsorted i.e. file order)");
+ public Option<bool> HideTransitions { get; } =
+ new(new[] { "--hide-transitions", "--ht" }, "Don't include GC transitions in disassembly output");
+ public Option<bool> Verbose { get; } =
+ new(new[] { "--verbose", "-v" }, "Dump disassembly, unwindInfo, gcInfo and sectionContents");
+ public Option<bool> Diff { get; } =
+ new(new[] { "--diff" }, "Compare two R2R images");
+ public Option<bool> DiffHideSameDisasm { get; } =
+ new(new[] { "--diff-hide-same-disasm" }, "In matching method diff dump, hide functions with identical disassembly");
+
+ public Option<bool> CreatePDB { get; } =
+ new(new[] { "--create-pdb" }, "Create PDB");
+ public Option<string> PdbPath { get; } =
+ new(new[] { "--pdb-path" }, "PDB output path for --create-pdb");
+
+ public Option<bool> CreatePerfmap { get; } =
+ new(new[] { "--create-perfmap" }, "Create PerfMap");
+ public Option<string> PerfmapPath { get; } =
+ new(new[] { "--perfmap-path" }, "PerfMap output path for --create-perfmap");
+ public Option<int> PerfmapFormatVersion { get; } =
+ new(new[] { "--perfmap-format-version" }, () => ILCompiler.Diagnostics.PerfMapWriter.CurrentFormatVersion, "PerfMap format version for --create-perfmap");
+
+ public Option<FileInfo[]> Reference { get; } =
+ new(new[] { "--reference", "-r" }, "Explicit reference assembly files");
+ public Option<DirectoryInfo[]> ReferencePath { get; } =
+ new(new[] { "--referencePath", "--rp" }, "Search paths for reference assemblies");
+
+ public Option<bool> SignatureBinary { get; } =
+ new(new[] { "--signatureBinary", "--sb" }, "Append signature binary to its textual representation");
+ public Option<bool> InlineSignatureBinary { get; } =
+ new(new[] { "--inlineSignatureBinary", "--isb" }, "Embed binary signature into its textual representation");
+
+ public R2RDumpRootCommand()
+ : base("Parses and outputs the contents of a ReadyToRun image")
{
- RootCommand command = new RootCommand();
- command.AddOption(new Option<FileInfo[]>(new[] { "--in", "-i" }, "Input file(s) to dump. Expects them to by ReadyToRun images"));
- command.AddOption(new Option<FileInfo>(new[] { "--out", "-o" }, "Output file path. Dumps everything to the specified file except for help message and exception messages"));
- command.AddOption(new Option<bool>(new[] { "--raw" }, "Dump the raw bytes of each section or runtime function"));
- command.AddOption(new Option<bool>(new[] { "--header" }, "Dump R2R header"));
- command.AddOption(new Option<bool>(new[] { "--disasm", "-d" }, "Show disassembly of methods or runtime functions"));
- command.AddOption(new Option<bool>(new[] { "--naked" }, "Naked dump suppresses most compilation details like placement addresses"));
- command.AddOption(new Option<bool>(new[] { "--hide-offsets", "--ho" }, "Hide offsets in naked disassembly"));
- command.AddOption(new Option<string[]>(new[] { "--query", "-q" }, "Query method by exact name, signature, row ID or token"));
- command.AddOption(new Option<string[]>(new[] { "--keyword", "-k" }, "Search method by keyword"));
- command.AddOption(new Option<string[]>(new[] { "--runtimefunction", "-f" }, "Get one runtime function by id or relative virtual address"));
- command.AddOption(new Option<string[]>(new[] { "--section", "-s" }, "Get section by keyword"));
- command.AddOption(new Option<bool>(new[] { "--unwind" }, "Dump unwindInfo"));
- command.AddOption(new Option<bool>(new[] { "--gc" }, "Dump gcInfo and slot table"));
- command.AddOption(new Option<bool>(new[] { "--pgo" }, "Dump embedded pgo instrumentation data"));
- command.AddOption(new Option<bool>(new[] { "--sectionContents", "--sc" }, "Dump section contents"));
- command.AddOption(new Option<bool>(new[] { "--entrypoints", "-e" }, "Dump list of method / instance entrypoints in the R2R file"));
- command.AddOption(new Option<bool>(new[] { "--normalize", "-n" }, "Normalize dump by sorting the various tables and methods (default = unsorted i.e. file order)"));
- command.AddOption(new Option<bool>(new[] { "--hide-transitions", "--ht" }, "Don't include GC transitions in disassembly output"));
- command.AddOption(new Option<bool>(new[] { "--verbose", "-v" }, "Dump disassembly, unwindInfo, gcInfo and sectionContents"));
- command.AddOption(new Option<bool>(new[] { "--diff" }, "Compare two R2R images"));
- command.AddOption(new Option<bool>(new[] { "--diff-hide-same-disasm" }, "In matching method diff dump, hide functions with identical disassembly"));
- command.AddOption(new Option<FileInfo[]>(new[] { "--reference", "-r" }, "Explicit reference assembly files"));
- command.AddOption(new Option<DirectoryInfo[]>(new[] { "--referencePath", "--rp" }, "Search paths for reference assemblies"));
- command.AddOption(new Option<bool>(new[] { "--inlineSignatureBinary", "--isb" }, "Embed binary signature into its textual representation"));
- command.AddOption(new Option<bool>(new[] { "--signatureBinary", "--sb" }, "Append signature binary to its textual representation"));
- command.AddOption(new Option<bool>(new[] { "--create-pdb" }, "Create PDB"));
- command.AddOption(new Option<string>(new[] { "--pdb-path" }, "PDB output path for --create-pdb"));
- command.AddOption(new Option<bool>(new[] { "--create-perfmap" }, "Create PerfMap"));
- command.AddOption(new Option<string>(new[] { "--perfmap-path" }, "PerfMap output path for --create-perfmap"));
- command.AddOption(new Option<int>(new[] { "--perfmap-format-version" }, "PerfMap format version for --create-perfmap"));
- return command;
+ AddOption(In);
+ AddOption(Out);
+ AddOption(Raw);
+ AddOption(Header);
+ AddOption(Disasm);
+ AddOption(Naked);
+ AddOption(HideOffsets);
+
+ AddOption(Query);
+ AddOption(Keyword);
+ AddOption(RuntimeFunction);
+ AddOption(Section);
+
+ AddOption(Unwind);
+ AddOption(GC);
+ AddOption(Pgo);
+ AddOption(SectionContents);
+ AddOption(EntryPoints);
+ AddOption(Normalize);
+ AddOption(HideTransitions);
+ AddOption(Verbose);
+ AddOption(Diff);
+ AddOption(DiffHideSameDisasm);
+
+ AddOption(CreatePDB);
+ AddOption(PdbPath);
+
+ AddOption(CreatePerfmap);
+ AddOption(PerfmapPath);
+ AddOption(PerfmapFormatVersion);
+
+ AddOption(Reference);
+ AddOption(ReferencePath);
+
+ AddOption(SignatureBinary);
+ AddOption(InlineSignatureBinary);
+
+ this.SetHandler<InvocationContext>((InvocationContext context) =>
+ context.ExitCode = new R2RDump(new DumpOptions(this, context.ParseResult)).Run());
+ }
+ }
+
+ public partial class DumpOptions
+ {
+ public FileInfo[] In { get; }
+ public FileInfo Out { get; }
+ public bool Raw { get; }
+ public bool Header { get; }
+ public bool Disasm { get; }
+ public bool Naked { get; }
+ public bool HideOffsets { get; }
+
+ public string[] Query { get; }
+ public string[] Keyword { get; }
+ public string[] RuntimeFunction { get; }
+ public string[] Section { get; }
+
+ public bool Unwind { get; }
+ public bool GC { get; }
+ public bool Pgo { get; }
+ public bool SectionContents { get; }
+ public bool EntryPoints { get; }
+ public bool Normalize { get; }
+ public bool HideTransitions { get; }
+ public bool Verbose { get; }
+ public bool Diff { get; }
+ public bool DiffHideSameDisasm { get; }
+
+ public bool CreatePDB { get; }
+ public string PdbPath { get; }
+
+ public bool CreatePerfmap { get; }
+ public string PerfmapPath { get; }
+ public int PerfmapFormatVersion { get; }
+
+ public FileInfo[] Reference { get; }
+ public DirectoryInfo[] ReferencePath { get; }
+
+ public bool SignatureBinary { get; }
+ public bool InlineSignatureBinary { get; }
+
+ public DumpOptions(R2RDumpRootCommand cmd, ParseResult res)
+ {
+ In = res.GetValueForOption(cmd.In);
+ Out = res.GetValueForOption(cmd.Out);
+ Raw = res.GetValueForOption(cmd.Raw);
+ Header = res.GetValueForOption(cmd.Header);
+ Disasm = res.GetValueForOption(cmd.Disasm);
+ Naked = res.GetValueForOption(cmd.Naked);
+ HideOffsets = res.GetValueForOption(cmd.HideOffsets);
+
+ Query = res.GetValueForOption(cmd.Query);
+ Keyword = res.GetValueForOption(cmd.Keyword);
+ RuntimeFunction = res.GetValueForOption(cmd.RuntimeFunction);
+ Section = res.GetValueForOption(cmd.Section);
+
+ Unwind = res.GetValueForOption(cmd.Unwind);
+ GC = res.GetValueForOption(cmd.GC);
+ Pgo = res.GetValueForOption(cmd.Pgo);
+ SectionContents = res.GetValueForOption(cmd.SectionContents);
+ EntryPoints = res.GetValueForOption(cmd.EntryPoints);
+ Normalize = res.GetValueForOption(cmd.Normalize);
+ HideTransitions = res.GetValueForOption(cmd.HideTransitions);
+ Verbose = res.GetValueForOption(cmd.Verbose);
+ Diff = res.GetValueForOption(cmd.Diff);
+ DiffHideSameDisasm = res.GetValueForOption(cmd.DiffHideSameDisasm);
+
+ CreatePDB = res.GetValueForOption(cmd.CreatePDB);
+ PdbPath = res.GetValueForOption(cmd.PdbPath);
+
+ CreatePerfmap = res.GetValueForOption(cmd.CreatePerfmap);
+ PerfmapPath = res.GetValueForOption(cmd.PerfmapPath);
+ PerfmapFormatVersion = res.GetValueForOption(cmd.PerfmapFormatVersion);
+
+ Reference = res.GetValueForOption(cmd.Reference);
+ ReferencePath = res.GetValueForOption(cmd.ReferencePath);
+
+ SignatureBinary = res.GetValueForOption(cmd.SignatureBinary);
+ InlineSignatureBinary = res.GetValueForOption(cmd.InlineSignatureBinary);
+
+ if (Verbose)
+ {
+ Disasm = true;
+ Unwind = true;
+ GC = true;
+ Pgo = true;
+ SectionContents = true;
+ }
}
}
}
using System.Collections.Generic;
using System.Collections.Immutable;
using System.CommandLine;
+using System.CommandLine.Builder;
using System.CommandLine.Invocation;
+using System.CommandLine.Parsing;
using System.IO;
using System.Linq;
using System.Reflection.Metadata;
namespace R2RDump
{
- public class DumpOptions : IAssemblyResolver
+ public partial class DumpOptions : IAssemblyResolver
{
- public FileInfo[] In { get; set; }
- public FileInfo Out { get; set; }
- public bool Raw { get; set; }
- public bool Header { get; set; }
- public bool Disasm { get; set; }
- public bool Naked { get; set; }
- public bool HideOffsets { get; set; }
-
- public string[] Query { get; set; }
- public string[] Keyword { get; set; }
- public string[] RuntimeFunction { get; set; }
- public string[] Section { get; set; }
-
- public bool Unwind { get; set; }
- public bool GC { get; set; }
- public bool Pgo { get; set; }
- public bool SectionContents { get; set; }
- public bool EntryPoints { get; set; }
- public bool Normalize { get; set; }
- public bool HideTransitions { get; set; }
- public bool Verbose { get; set; }
- public bool Diff { get; set; }
- public bool DiffHideSameDisasm { get; set; }
- public bool IgnoreSensitive { get; set; }
-
- public bool CreatePDB { get; set; }
- public string PdbPath { get; set; }
-
- public bool CreatePerfmap { get; set; }
- public string PerfmapPath { get; set; }
- public int PerfmapFormatVersion { get; set; }
-
-
- public FileInfo[] Reference { get; set; }
- public DirectoryInfo[] ReferencePath { get; set; }
-
- public bool SignatureBinary { get; set; }
- public bool InlineSignatureBinary { get; set; }
-
private SignatureFormattingOptions signatureFormattingOptions;
- public DumpOptions()
- {
- PerfmapFormatVersion = PerfMapWriter.CurrentFormatVersion;
- }
-
/// <summary>
/// Probing extensions to use when looking up assemblies under reference paths.
/// </summary>
public Disassembler Disassembler => _disassembler;
}
- class R2RDump
+ public class R2RDump
{
private readonly DumpOptions _options;
private readonly Dictionary<ReadyToRunSectionType, bool> _selectedSections = new Dictionary<ReadyToRunSectionType, bool>();
private readonly TextWriter _writer;
private Dumper _dumper;
- private R2RDump(DumpOptions options)
+ public R2RDump(DumpOptions options)
{
_options = options;
_encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: false);
- if (_options.Verbose)
- {
- _options.Disasm = true;
- _options.Unwind = true;
- _options.GC = true;
- _options.Pgo = true;
- _options.SectionContents = true;
- }
-
if (_options.Out != null)
{
_writer = new StreamWriter(_options.Out.FullName, append: false, _encoding);
return null;
}
- private int Run()
+ public int Run()
{
Disassembler disassembler = null;
return 0;
}
- public static async Task<int> Main(string[] args)
- {
- var command = CommandLineOptions.RootCommand();
- command.Handler = CommandHandler.Create<DumpOptions>((DumpOptions options) => new R2RDump(options).Run());
- return await command.InvokeAsync(args);
- }
+ //
+ // Command line parsing
+ //
+
+ public static int Main(string[] args) =>
+ new CommandLineBuilder(new R2RDumpRootCommand())
+ .UseHelp()
+ .UseParseErrorReporting()
+ .Build()
+ .Invoke(args);
}
}
namespace R2RTest
{
- public class BuildOptions
+ public partial class BuildOptions
{
- public DirectoryInfo InputDirectory { get; set; }
- public DirectoryInfo OutputDirectory { get; set; }
- public DirectoryInfo CoreRootDirectory { get; set; }
- public FileInfo Crossgen2Path { get; set; }
- public bool VerifyTypeAndFieldLayout { get; set; }
- public string TargetArch { get; set; }
- public bool Exe { get; set; }
- public bool NoJit { get; set; }
- public bool NoCrossgen2 { get; set; }
- public bool NoExe { get; set; }
- public bool NoEtw { get; set; }
- public bool NoCleanup { get; set; }
- public bool Map { get; set; }
- public bool Pdb { get; set; }
-
- public bool Perfmap { get; set; }
- public int PerfmapFormatVersion { get; set; } = 1;
- public FileInfo PackageList { get; set; }
- public int DegreeOfParallelism { get; set; }
- public bool Sequential { get; set; }
- public int Iterations { get; set; } = 1;
- public bool Framework { get; set; }
- public bool UseFramework { get; set; }
- public bool Release { get; set; }
- public bool LargeBubble { get; set; }
- public bool Composite { get; set; }
- public int Crossgen2Parallelism { get; set; }
- public FileInfo Crossgen2JitPath { get; set; }
- public int CompilationTimeoutMinutes { get; set; }
- public int ExecutionTimeoutMinutes { get; set; }
- public DirectoryInfo[] ReferencePath { get; set; }
- public FileInfo[] IssuesPath { get; set; }
- public FileInfo R2RDumpPath { get; set; }
- public FileInfo CrossgenResponseFile { get; set; }
- public DirectoryInfo[] RewriteOldPath { get; set; }
- public DirectoryInfo[] RewriteNewPath { get; set; }
- public DirectoryInfo AspNetPath { get; set; }
- public bool MeasurePerf { get; set; }
- public string InputFileSearchString { get; set; }
public string ConfigurationSuffix => (Release ? "-ret.out" : "-chk.out");
- public string GCStress { get; set; }
- public FileInfo[] MibcPath { get; set; }
+
public string DotNetCli
{
get
using System.CommandLine;
using System.CommandLine.Builder;
using System.CommandLine.Invocation;
+using System.CommandLine.Parsing;
using System.IO;
namespace R2RTest
{
- internal static class CommandLineOptions
+ public class R2RTestRootCommand : RootCommand
{
- public static CommandLineBuilder Build()
+ void CreateCommand(string name, string description, Option[] options, Func<BuildOptions, int> action)
{
- var parser = new CommandLineBuilder()
- .AddCommand(CompileFolder())
- .AddCommand(CompileSubtree())
- .AddCommand(CompileFramework())
- .AddCommand(CompileNugetPackages())
- .AddCommand(CompileSerp());
-
- return parser;
-
- Command CreateCommand(string name, string description, Option[] options, Func<BuildOptions, int> action)
- {
- Command command = new Command(name, description);
- foreach (var option in GetCommonOptions())
- command.AddOption(option);
- foreach (var option in options)
- command.AddOption(option);
- command.Handler = CommandHandler.Create<BuildOptions>(action);
- return command;
- }
-
- Option[] GetCommonOptions() => new[] { CoreRootDirectory(), DotNetCli() };
-
- Command CompileFolder() =>
- CreateCommand("compile-directory", "Compile all assemblies in directory",
- new Option[]
- {
- InputDirectory(),
- OutputDirectory(),
- Crossgen2Path(),
- TargetArch(),
- VerifyTypeAndFieldLayout(),
- NoJit(),
- NoCrossgen2(),
- Exe(),
- NoExe(),
- NoEtw(),
- NoCleanup(),
- Map(),
- Pdb(),
- Perfmap(),
- PerfmapFormatVersion(),
- DegreeOfParallelism(),
- Sequential(),
- Iterations(),
- Framework(),
- UseFramework(),
- Release(),
- LargeBubble(),
- Composite(),
- Crossgen2Parallelism(),
- Crossgen2JitPath(),
- ReferencePath(),
- IssuesPath(),
- CompilationTimeoutMinutes(),
- ExecutionTimeoutMinutes(),
- R2RDumpPath(),
- MeasurePerf(),
- InputFileSearchString(),
- MibcPath(),
- },
- CompileDirectoryCommand.CompileDirectory);
-
- Command CompileSubtree() =>
- CreateCommand("compile-subtree", "Build each directory in a given subtree containing any managed assemblies as a separate app",
- new Option[]
- {
- InputDirectory(),
- OutputDirectory(),
- Crossgen2Path(),
- TargetArch(),
- VerifyTypeAndFieldLayout(),
- NoJit(),
- NoCrossgen2(),
- Exe(),
- NoExe(),
- NoEtw(),
- NoCleanup(),
- Map(),
- Pdb(),
- Perfmap(),
- PerfmapFormatVersion(),
- DegreeOfParallelism(),
- Sequential(),
- Iterations(),
- Framework(),
- UseFramework(),
- Release(),
- LargeBubble(),
- Composite(),
- Crossgen2Parallelism(),
- Crossgen2JitPath(),
- ReferencePath(),
- IssuesPath(),
- CompilationTimeoutMinutes(),
- ExecutionTimeoutMinutes(),
- R2RDumpPath(),
- GCStress(),
- MibcPath(),
- },
- CompileSubtreeCommand.CompileSubtree);
-
- Command CompileFramework() =>
- CreateCommand("compile-framework", "Compile managed framework assemblies in Core_Root",
- new Option[]
- {
- Crossgen2Path(),
- TargetArch(),
- VerifyTypeAndFieldLayout(),
- NoCrossgen2(),
- NoCleanup(),
- Map(),
- Pdb(),
- Perfmap(),
- PerfmapFormatVersion(),
- Crossgen2Parallelism(),
- Crossgen2JitPath(),
- DegreeOfParallelism(),
- Sequential(),
- Iterations(),
- Release(),
- LargeBubble(),
- Composite(),
- ReferencePath(),
- IssuesPath(),
- CompilationTimeoutMinutes(),
- R2RDumpPath(),
- MeasurePerf(),
- InputFileSearchString(),
- OutputDirectory(),
- MibcPath(),
- },
- CompileFrameworkCommand.CompileFramework);
-
- Command CompileNugetPackages() =>
- CreateCommand("compile-nuget", "Restore a list of Nuget packages into an empty console app, publish, and optimize with Crossgen / CPAOT",
- new Option[]
- {
- R2RDumpPath(),
- InputDirectory(),
- OutputDirectory(),
- PackageList(),
- NoCleanup(),
- Map(),
- Pdb(),
- Perfmap(),
- PerfmapFormatVersion(),
- DegreeOfParallelism(),
- CompilationTimeoutMinutes(),
- ExecutionTimeoutMinutes(),
- MibcPath(),
- },
- CompileNugetCommand.CompileNuget);
-
- Command CompileSerp() =>
- CreateCommand("compile-serp", "Compile existing application",
- new Option[]
- {
- InputDirectory(),
- DegreeOfParallelism(),
- AspNetPath(),
- Composite(),
- Map(),
- Pdb(),
- Perfmap(),
- PerfmapFormatVersion(),
- CompilationTimeoutMinutes(),
- Crossgen2Path(),
- MibcPath(),
- },
- options =>
- {
- var compileSerp = new CompileSerpCommand(options);
- return compileSerp.CompileSerpAssemblies();
- });
-
- // Todo: Input / Output directories should be required arguments to the command when they're made available to handlers
- // https://github.com/dotnet/command-line-api/issues/297
- Option InputDirectory() =>
- new Option<DirectoryInfo>(new[] { "--input-directory", "-in" }, "Folder containing assemblies to optimize").ExistingOnly();
-
- Option OutputDirectory() =>
- new Option<DirectoryInfo>(new[] { "--output-directory", "-out" }, "Folder to emit compiled assemblies").LegalFilePathsOnly();
-
- Option CoreRootDirectory() =>
- new Option<DirectoryInfo>(new[] { "--core-root-directory", "-cr" }, "Location of the CoreCLR CORE_ROOT folder")
+ Command command = new Command(name, description);
+ foreach (var option in GetCommonOptions())
+ command.AddOption(option);
+ foreach (var option in options)
+ command.AddOption(option);
+ command.SetHandler<InvocationContext>((InvocationContext context) =>
+ context.ExitCode = action(new BuildOptions(this, context.ParseResult)));
+ AddCommand(command);
+ }
+
+ Option[] GetCommonOptions() => new Option[] { CoreRootDirectory, DotNetCli };
+
+ R2RTestRootCommand()
+ {
+ CreateCommand("compile-directory", "Compile all assemblies in directory",
+ new Option[]
+ {
+ InputDirectory,
+ OutputDirectory,
+ Crossgen2Path,
+ TargetArch,
+ VerifyTypeAndFieldLayout,
+ NoJit,
+ NoCrossgen2,
+ Exe,
+ NoExe,
+ NoEtw,
+ NoCleanup,
+ Map,
+ Pdb,
+ Perfmap,
+ PerfmapFormatVersion,
+ DegreeOfParallelism,
+ Sequential,
+ Iterations,
+ Framework,
+ UseFramework,
+ Release,
+ LargeBubble,
+ Composite,
+ Crossgen2Parallelism,
+ Crossgen2JitPath,
+ ReferencePath,
+ IssuesPath,
+ CompilationTimeoutMinutes,
+ ExecutionTimeoutMinutes,
+ R2RDumpPath,
+ MeasurePerf,
+ InputFileSearchString,
+ MibcPath,
+ },
+ CompileDirectoryCommand.CompileDirectory);
+
+ CreateCommand("compile-subtree", "Build each directory in a given subtree containing any managed assemblies as a separate app",
+ new Option[]
+ {
+ InputDirectory,
+ OutputDirectory,
+ Crossgen2Path,
+ TargetArch,
+ VerifyTypeAndFieldLayout,
+ NoJit,
+ NoCrossgen2,
+ Exe,
+ NoExe,
+ NoEtw,
+ NoCleanup,
+ Map,
+ Pdb,
+ Perfmap,
+ PerfmapFormatVersion,
+ DegreeOfParallelism,
+ Sequential,
+ Iterations,
+ Framework,
+ UseFramework,
+ Release,
+ LargeBubble,
+ Composite,
+ Crossgen2Parallelism,
+ Crossgen2JitPath,
+ ReferencePath,
+ IssuesPath,
+ CompilationTimeoutMinutes,
+ ExecutionTimeoutMinutes,
+ R2RDumpPath,
+ GCStress,
+ MibcPath,
+ },
+ CompileSubtreeCommand.CompileSubtree);
+
+ CreateCommand("compile-framework", "Compile managed framework assemblies in Core_Root",
+ new Option[]
{
- Required = true
- }.ExistingOnly();
+ Crossgen2Path,
+ TargetArch,
+ VerifyTypeAndFieldLayout,
+ NoCrossgen2,
+ NoCleanup,
+ Map,
+ Pdb,
+ Perfmap,
+ PerfmapFormatVersion,
+ Crossgen2Parallelism,
+ Crossgen2JitPath,
+ DegreeOfParallelism,
+ Sequential,
+ Iterations,
+ Release,
+ LargeBubble,
+ Composite,
+ ReferencePath,
+ IssuesPath,
+ CompilationTimeoutMinutes,
+ R2RDumpPath,
+ MeasurePerf,
+ InputFileSearchString,
+ OutputDirectory,
+ MibcPath,
+ },
+ CompileFrameworkCommand.CompileFramework);
+
+ CreateCommand("compile-nuget", "Restore a list of Nuget packages into an empty console app, publish, and optimize with Crossgen / CPAOT",
+ new Option[]
+ {
+ R2RDumpPath,
+ InputDirectory,
+ OutputDirectory,
+ PackageList,
+ NoCleanup,
+ Map,
+ Pdb,
+ Perfmap,
+ PerfmapFormatVersion,
+ DegreeOfParallelism,
+ CompilationTimeoutMinutes,
+ ExecutionTimeoutMinutes,
+ MibcPath,
+ },
+ CompileNugetCommand.CompileNuget);
+
+ CreateCommand("compile-serp", "Compile existing application",
+ new Option[]
+ {
+ InputDirectory,
+ DegreeOfParallelism,
+ AspNetPath,
+ Composite,
+ Map,
+ Pdb,
+ Perfmap,
+ PerfmapFormatVersion,
+ CompilationTimeoutMinutes,
+ Crossgen2Path,
+ MibcPath,
+ },
+ options =>
+ {
+ var compileSerp = new CompileSerpCommand(options);
+ return compileSerp.CompileSerpAssemblies();
+ });
+ }
+
+ // Todo: Input / Output directories should be required arguments to the command when they're made available to handlers
+ // https://github.com/dotnet/command-line-api/issues/297
+ public Option<DirectoryInfo> InputDirectory { get; } =
+ new Option<DirectoryInfo>(new[] { "--input-directory", "-in" }, "Folder containing assemblies to optimize").ExistingOnly();
- Option ReferencePath() =>
- new Option<DirectoryInfo[]>(new[] { "--reference-path", "-r" }, "Folder containing assemblies to reference during compilation")
- { Argument = new Argument<DirectoryInfo[]>() { Arity = ArgumentArity.ZeroOrMore }.ExistingOnly() };
+ public Option<DirectoryInfo> OutputDirectory { get; } =
+ new Option<DirectoryInfo>(new[] { "--output-directory", "-out" }, "Folder to emit compiled assemblies").LegalFilePathsOnly();
- Option MibcPath() =>
- new Option<FileInfo[]>(new[] { "--mibc-path", "-m" }, "Mibc files to use in compilation")
- { Argument = new Argument<FileInfo[]>() { Arity = ArgumentArity.ZeroOrMore }.ExistingOnly() };
+ public Option<DirectoryInfo> CoreRootDirectory { get; } =
+ new Option<DirectoryInfo>(new[] { "--core-root-directory", "-cr" }, "Location of the CoreCLR CORE_ROOT folder")
+ { Arity = ArgumentArity.ExactlyOne }.ExistingOnly();
- Option Crossgen2Path() =>
- new Option<FileInfo>(new[] { "--crossgen2-path", "-c2p" }, "Explicit Crossgen2 path (useful for cross-targeting)").ExistingOnly();
+ public Option<DirectoryInfo[]> ReferencePath { get; } =
+ new Option<DirectoryInfo[]>(new[] { "--reference-path", "-r" }, "Folder containing assemblies to reference during compilation")
+ { Arity = ArgumentArity.ZeroOrMore }.ExistingOnly();
- Option VerifyTypeAndFieldLayout() =>
- new Option<bool>(new[] { "--verify-type-and-field-layout" }, "Verify that struct type layout and field offsets match between compile time and runtime. Use only for diagnostic purposes.");
+ public Option<FileInfo[]> MibcPath { get; } =
+ new Option<FileInfo[]>(new[] { "--mibc-path", "-m" }, "Mibc files to use in compilation")
+ { Arity = ArgumentArity.ZeroOrMore }.ExistingOnly();
- Option NoJit() =>
- new Option<bool>(new[] { "--nojit" }, "Don't run tests in JITted mode");
+ public Option<FileInfo> Crossgen2Path { get; } =
+ new Option<FileInfo>(new[] { "--crossgen2-path", "-c2p" }, "Explicit Crossgen2 path (useful for cross-targeting)").ExistingOnly();
- Option NoCrossgen2() =>
- new Option<bool>(new[] { "--nocrossgen2" }, "Don't run tests in Crossgen2 mode");
+ public Option<bool> VerifyTypeAndFieldLayout { get; } =
+ new(new[] { "--verify-type-and-field-layout" }, "Verify that struct type layout and field offsets match between compile time and runtime. Use only for diagnostic purposes.");
- Option Exe() =>
- new Option<bool>(new[] { "--exe" }, "Don't compile tests, just execute them");
+ public Option<bool> NoJit { get; } =
+ new(new[] { "--nojit" }, "Don't run tests in JITted mode");
- Option NoExe() =>
- new Option<bool>(new[] { "--noexe" }, "Compilation-only mode (don't execute the built apps)");
+ public Option<bool> NoCrossgen2 { get; } =
+ new(new[] { "--nocrossgen2" }, "Don't run tests in Crossgen2 mode");
- Option NoEtw() =>
- new Option<bool>(new[] { "--noetw" }, "Don't capture jitted methods using ETW");
+ public Option<bool> Exe { get; } =
+ new(new[] { "--exe" }, "Don't compile tests, just execute them");
- Option NoCleanup() =>
- new Option<bool>(new[] { "--nocleanup" }, "Don't clean up compilation artifacts after test runs");
+ public Option<bool> NoExe { get; } =
+ new(new[] { "--noexe" }, "Compilation-only mode (don't execute the built apps)");
- Option Map() =>
- new Option<bool>(new[] { "--map" }, "Generate a map file (Crossgen2)");
+ public Option<bool> NoEtw { get; } =
+ new(new[] { "--noetw" }, "Don't capture jitted methods using ETW");
- Option Pdb() =>
- new Option<bool>(new[] { "--pdb" }, "Generate PDB symbol information (Crossgen2 / Windows only)");
+ public Option<bool> NoCleanup { get; } =
+ new(new[] { "--nocleanup" }, "Don't clean up compilation artifacts after test runs");
- Option Perfmap() =>
- new Option<bool>(new[] { "--perfmap" }, "Generate perfmap symbol information");
+ public Option<bool> Map { get; } =
+ new(new[] { "--map" }, "Generate a map file (Crossgen2)");
- Option PerfmapFormatVersion() =>
- new Option<int>(new[] { "--perfmap-format-version" }, "Perfmap format version to generate");
+ public Option<bool> Pdb { get; } =
+ new(new[] { "--pdb" }, "Generate PDB symbol information (Crossgen2 / Windows only)");
- Option DegreeOfParallelism() =>
- new Option<int>(new[] { "--degree-of-parallelism", "-dop" }, "Override default compilation / execution DOP (default = logical processor count)");
+ public Option<bool> Perfmap { get; } =
+ new(new[] { "--perfmap" }, "Generate perfmap symbol information");
- Option Sequential() =>
- new Option<bool>(new[] { "--sequential" }, "Run tests sequentially");
+ public Option<int> PerfmapFormatVersion { get; } =
+ new(new[] { "--perfmap-format-version" }, () => 1, "Perfmap format version to generate");
- Option Iterations() =>
- new Option<int>(new[] { "--iterations" }, "Number of iterations for each test execution");
+ public Option<int> DegreeOfParallelism { get; } =
+ new(new[] { "--degree-of-parallelism", "-dop" }, "Override default compilation / execution DOP (default = logical processor count)");
- Option Framework() =>
- new Option<bool>(new[] { "--framework" }, "Precompile and use native framework");
+ public Option<bool> Sequential { get; } =
+ new(new[] { "--sequential" }, "Run tests sequentially");
- Option UseFramework() =>
- new Option<bool>(new[] { "--use-framework" }, "Use native framework (don't precompile, assume previously compiled)");
+ public Option<int> Iterations { get; } =
+ new(new[] { "--iterations" }, () => 1, "Number of iterations for each test execution");
- Option Release() =>
- new Option<bool>(new[] { "--release" }, "Build the tests in release mode");
+ public Option<bool> Framework { get; } =
+ new(new[] { "--framework" }, "Precompile and use native framework");
- Option LargeBubble() =>
- new Option<bool>(new[] { "--large-bubble" }, "Assume all input files as part of one version bubble");
+ public Option<bool> UseFramework { get; } =
+ new(new[] { "--use-framework" }, "Use native framework (don't precompile, assume previously compiled)");
- Option Composite() =>
- new Option<bool>(new[] { "--composite" }, "Compile tests in composite R2R mode");
+ public Option<bool> Release { get; } =
+ new(new[] { "--release" }, "Build the tests in release mode");
- Option Crossgen2Parallelism() =>
- new Option<int>(new[] { "--crossgen2-parallelism" }, "Max number of threads to use in Crossgen2 (default = logical processor count)");
-
- Option Crossgen2JitPath() =>
- new Option<FileInfo>(new[] { "--crossgen2-jitpath" }, "Jit path to use for crossgen2");
+ public Option<bool> LargeBubble { get; } =
+ new(new[] { "--large-bubble" }, "Assume all input files as part of one version bubble");
- Option IssuesPath() =>
- new Option<FileInfo[]>(new[] { "--issues-path", "-ip" }, "Path to issues.targets")
- { Argument = new Argument<FileInfo[]>() { Arity = ArgumentArity.ZeroOrMore } };
+ public Option<bool> Composite { get; } =
+ new(new[] { "--composite" }, "Compile tests in composite R2R mode");
- Option CompilationTimeoutMinutes() =>
- new Option<int>(new[] { "--compilation-timeout-minutes", "-ct" }, "Compilation timeout (minutes)");
+ public Option<int> Crossgen2Parallelism { get; } =
+ new(new[] { "--crossgen2-parallelism" }, "Max number of threads to use in Crossgen2 (default = logical processor count)");
- Option ExecutionTimeoutMinutes() =>
- new Option<int>(new[] { "--execution-timeout-minutes", "-et" }, "Execution timeout (minutes)");
+ public Option<FileInfo> Crossgen2JitPath { get; } =
+ new(new[] { "--crossgen2-jitpath" }, "Jit path to use for crossgen2");
- Option R2RDumpPath() =>
- new Option<FileInfo>(new[] { "--r2r-dump-path" }, "Path to R2RDump.exe/dll").ExistingOnly();
+ public Option<FileInfo[]> IssuesPath { get; } =
+ new Option<FileInfo[]>(new[] { "--issues-path", "-ip" }, "Path to issues.targets")
+ { Arity = ArgumentArity.ZeroOrMore };
- Option MeasurePerf() =>
- new Option<bool>(new[] { "--measure-perf" }, "Print out compilation time");
+ public Option<int> CompilationTimeoutMinutes { get; } =
+ new(new[] { "--compilation-timeout-minutes", "-ct" }, "Compilation timeout (minutes)");
- Option InputFileSearchString() =>
- new Option<string>(new[] { "--input-file-search-string", "-input-file" }, "Search string for input files in the input directory");
+ public Option<int> ExecutionTimeoutMinutes { get; } =
+ new(new[] { "--execution-timeout-minutes", "-et" }, "Execution timeout (minutes)");
- Option GCStress() =>
- new Option<string>(new[] { "--gcstress" }, "Run tests with the specified GC stress level enabled (the argument value is in hex)");
+ public Option<FileInfo> R2RDumpPath { get; } =
+ new Option<FileInfo>(new[] { "--r2r-dump-path" }, "Path to R2RDump.exe/dll").ExistingOnly();
- Option DotNetCli() =>
- new Option<string>(new [] { "--dotnet-cli", "-cli" }, "For dev box testing, point at .NET 5 dotnet.exe or <repo>/dotnet.cmd.");
+ public Option<bool> MeasurePerf { get; } =
+ new(new[] { "--measure-perf" }, "Print out compilation time");
- Option TargetArch() =>
- new Option<string>(new[] { "--target-arch" }, "Target architecture for crossgen2");
+ public Option<string> InputFileSearchString { get; } =
+ new(new[] { "--input-file-search-string", "-input-file" }, "Search string for input files in the input directory");
- //
- // compile-nuget specific options
- //
- Option PackageList() =>
- new Option<FileInfo>(new[] { "--package-list", "-pl" }, "Text file containing a package name on each line").ExistingOnly();
+ public Option<string> GCStress { get; } =
+ new(new[] { "--gcstress" }, "Run tests with the specified GC stress level enabled (the argument value is in hex)");
- //
- // compile-serp specific options
- //
- Option AspNetPath() =>
- new Option<DirectoryInfo>(new[] { "--asp-net-path", "-asp" }, "Path to SERP's ASP.NET Core folder").ExistingOnly();
+ public Option<string> DotNetCli { get; } =
+ new(new [] { "--dotnet-cli", "-cli" }, "For dev box testing, point at .NET 5 dotnet.exe or <repo>/dotnet.cmd.");
+
+ public Option<string> TargetArch { get; } =
+ new(new[] { "--target-arch" }, "Target architecture for crossgen2");
+
+ //
+ // compile-nuget specific options
+ //
+ public Option<FileInfo> PackageList { get; } =
+ new Option<FileInfo>(new[] { "--package-list", "-pl" }, "Text file containing a package name on each line").ExistingOnly();
+
+ //
+ // compile-serp specific options
+ //
+ public Option<DirectoryInfo> AspNetPath { get; } =
+ new Option<DirectoryInfo>(new[] { "--asp-net-path", "-asp" }, "Path to SERP's ASP.NET Core folder").ExistingOnly();
+
+ static int Main(string[] args)
+ {
+ return new CommandLineBuilder(new R2RTestRootCommand())
+ .UseHelp()
+ .UseParseErrorReporting()
+ .Build()
+ .Invoke(args);
}
}
+
+ public partial class BuildOptions
+ {
+ public BuildOptions(R2RTestRootCommand cmd, ParseResult res)
+ {
+ InputDirectory = res.GetValueForOption(cmd.InputDirectory);
+ OutputDirectory = res.GetValueForOption(cmd.OutputDirectory);
+ CoreRootDirectory = res.GetValueForOption(cmd.CoreRootDirectory);
+ Crossgen2Path = res.GetValueForOption(cmd.Crossgen2Path);
+ VerifyTypeAndFieldLayout = res.GetValueForOption(cmd.VerifyTypeAndFieldLayout);
+ TargetArch = res.GetValueForOption(cmd.TargetArch);
+ Exe = res.GetValueForOption(cmd.Exe);
+ NoJit = res.GetValueForOption(cmd.NoJit);
+ NoCrossgen2 = res.GetValueForOption(cmd.NoCrossgen2);
+ NoExe = res.GetValueForOption(cmd.NoExe);
+ NoEtw = res.GetValueForOption(cmd.NoEtw);
+ NoCleanup = res.GetValueForOption(cmd.NoCleanup);
+ Map = res.GetValueForOption(cmd.Map);
+ Pdb = res.GetValueForOption(cmd.Pdb);
+
+ Perfmap = res.GetValueForOption(cmd.Perfmap);
+ PerfmapFormatVersion = res.GetValueForOption(cmd.PerfmapFormatVersion);
+ PackageList = res.GetValueForOption(cmd.PackageList);
+ DegreeOfParallelism = res.GetValueForOption(cmd.DegreeOfParallelism);
+ Sequential = res.GetValueForOption(cmd.Sequential);
+ Iterations = res.GetValueForOption(cmd.Iterations);
+ Framework = res.GetValueForOption(cmd.Framework);
+ UseFramework = res.GetValueForOption(cmd.UseFramework);
+ Release = res.GetValueForOption(cmd.Release);
+ LargeBubble = res.GetValueForOption(cmd.LargeBubble);
+ Composite = res.GetValueForOption(cmd.Composite);
+ Crossgen2Parallelism = res.GetValueForOption(cmd.Crossgen2Parallelism);
+ Crossgen2JitPath = res.GetValueForOption(cmd.Crossgen2JitPath);
+ CompilationTimeoutMinutes = res.GetValueForOption(cmd.CompilationTimeoutMinutes);
+ ExecutionTimeoutMinutes = res.GetValueForOption(cmd.ExecutionTimeoutMinutes);
+ ReferencePath = res.GetValueForOption(cmd.ReferencePath);
+ IssuesPath = res.GetValueForOption(cmd.IssuesPath);
+ R2RDumpPath = res.GetValueForOption(cmd.R2RDumpPath);
+ AspNetPath = res.GetValueForOption(cmd.AspNetPath);
+ MeasurePerf = res.GetValueForOption(cmd.MeasurePerf);
+ InputFileSearchString = res.GetValueForOption(cmd.InputFileSearchString);
+ GCStress = res.GetValueForOption(cmd.GCStress);
+ MibcPath = res.GetValueForOption(cmd.MibcPath);
+ }
+
+ public DirectoryInfo InputDirectory { get; set; }
+ public DirectoryInfo OutputDirectory { get; set; }
+ public DirectoryInfo CoreRootDirectory { get; }
+ public FileInfo Crossgen2Path { get; }
+ public bool VerifyTypeAndFieldLayout { get; }
+ public string TargetArch { get; }
+ public bool Exe { get; }
+ public bool NoJit { get; set; }
+ public bool NoCrossgen2 { get; }
+ public bool NoExe { get; set; }
+ public bool NoEtw { get; set; }
+ public bool NoCleanup { get; }
+ public bool Map { get; }
+ public bool Pdb { get; }
+
+ public bool Perfmap { get; }
+ public int PerfmapFormatVersion { get; }
+ public FileInfo PackageList { get; }
+ public int DegreeOfParallelism { get; set; }
+ public bool Sequential { get; }
+ public int Iterations { get; }
+ public bool Framework { get; set; }
+ public bool UseFramework { get; }
+ public bool Release { get; set; }
+ public bool LargeBubble { get; }
+ public bool Composite { get; }
+ public int Crossgen2Parallelism { get; }
+ public FileInfo Crossgen2JitPath { get; }
+ public int CompilationTimeoutMinutes { get; }
+ public int ExecutionTimeoutMinutes { get; }
+ public DirectoryInfo[] ReferencePath { get; }
+ public FileInfo[] IssuesPath { get; }
+ public FileInfo R2RDumpPath { get; }
+ public DirectoryInfo AspNetPath { get; }
+ public bool MeasurePerf { get; }
+ public string InputFileSearchString { get; }
+ public string GCStress { get; }
+ public FileInfo[] MibcPath { get; }
+ }
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-using System.CommandLine;
-using System.CommandLine.Builder;
-using System.CommandLine.Parsing;
-using System.Threading.Tasks;
-
-namespace R2RTest
-{
- class Program
- {
- static async Task<int> Main(string[] args)
- {
- var parser = CommandLineOptions.Build().UseDefaults().Build();
-
- return await parser.InvokeAsync(args);
- }
- }
-}