diff --git a/eng/build.yml b/eng/build.yml index 9f7588ae..ba3779bb 100644 --- a/eng/build.yml +++ b/eng/build.yml @@ -13,7 +13,7 @@ jobs: displayName: 'Install .NET Core SDK' inputs: packageType: sdk - version: 8.x + version: 10.x installationPath: $(Agent.ToolsDirectory)/dotnet - ${{ if eq(parameters.agentOs, 'Windows_NT') }}: diff --git a/src/AnalyzeAsm/AnalyzeAsm.csproj b/src/AnalyzeAsm/AnalyzeAsm.csproj index 74954604..6a70a1ab 100644 --- a/src/AnalyzeAsm/AnalyzeAsm.csproj +++ b/src/AnalyzeAsm/AnalyzeAsm.csproj @@ -2,7 +2,6 @@ Exe - net6.0 diff --git a/src/Directory.Build.props b/src/Directory.Build.props new file mode 100644 index 00000000..0422e1b6 --- /dev/null +++ b/src/Directory.Build.props @@ -0,0 +1,15 @@ + + + + net10.0 + + + + + + + + + + + diff --git a/src/cijobs/CIJobsRootCommand.cs b/src/cijobs/CIJobsRootCommand.cs index e566a403..df9c44af 100644 --- a/src/cijobs/CIJobsRootCommand.cs +++ b/src/cijobs/CIJobsRootCommand.cs @@ -5,38 +5,37 @@ using System; using System.Collections.Generic; using System.CommandLine; -using System.CommandLine.Invocation; using System.Threading.Tasks; namespace ManagedCodeGen { - internal sealed class CIJobsRootCommand : CliRootCommand + internal sealed class CIJobsRootCommand : RootCommand { - public CliOption Server { get; } = + public Option Server { get; } = new("--server", "-s") { Description = "Url of the server. Defaults to https://ci.dot.net/" }; - public CliOption JobName { get; } = + public Option JobName { get; } = new("--job", "-j") { Description = "Name of the job." }; - public CliOption BranchName { get; } = + public Option BranchName { get; } = new("--branch", "-b") { DefaultValueFactory = _ => "master", Description = "Name of the branch." }; - public CliOption RepoName { get; } = + public Option RepoName { get; } = new("--repo", "-r") { DefaultValueFactory = _ => "dotnet_coreclr", Description = "Name of the repo (e.g. dotnet_corefx or dotnet_coreclr)." }; - public CliOption MatchPattern { get; } = + public Option MatchPattern { get; } = new("--match", "-m") { Description = "Regex pattern used to select jobs output." }; - public CliOption JobNumber { get; } = + public Option JobNumber { get; } = new("--number", "-n") { Description = "Job number." }; - public CliOption ShowLastSuccessful { get; } = + public Option ShowLastSuccessful { get; } = new("--last-successful", "-l") { Description = "Show last successful build." }; - public CliOption Commit { get; } = + public Option Commit { get; } = new("--commit", "-c") { Description = "List build at this commit." }; - public CliOption ShowArtifacts { get; } = + public Option ShowArtifacts { get; } = new("--artifacts", "-a") { Description = "Show job artifacts on server." }; - public CliOption OutputPath { get; } = + public Option OutputPath { get; } = new("--output", "-o") { Description = "The path where output will be placed." }; - public CliOption OutputRoot { get; } = + public Option OutputRoot { get; } = new("--output-root") { Description = "The root directory where output will be placed. A subdirectory named by job and build number will be created within this to store the output." }; - public CliOption Unzip { get; } = + public Option Unzip { get; } = new("--unzip", "-u") { Description = "Unzip copied artifacts" }; - public CliOption ContentPath { get; } = + public Option ContentPath { get; } = new("--ContentPath", "-p") { Description = "Relative product zip path. Default is artifact/bin/Product/*zip*/Product.zip" }; public ParseResult Result; @@ -45,7 +44,7 @@ public CIJobsRootCommand(string[] args) : base("Continuous integration build job { List errors = new(); - CliCommand listCommand = new("list", "List jobs on ci.dot.net for the repo.") + Command listCommand = new("list", "List jobs on ci.dot.net for the repo.") { Server, JobName, @@ -104,7 +103,7 @@ public CIJobsRootCommand(string[] args) : base("Continuous integration build job Subcommands.Add(listCommand); - CliCommand copyCommand = new("copy", @"Copies job artifacts from ci.dot.net. This + Command copyCommand = new("copy", @"Copies job artifacts from ci.dot.net. This command copies a zip of artifacts from a repo (defaulted to dotnet_coreclr). The default location of the zips is the Product sub-directory, though that can be changed using the diff --git a/src/cijobs/Program.cs b/src/cijobs/Program.cs index 73b01e18..24626b0e 100755 --- a/src/cijobs/Program.cs +++ b/src/cijobs/Program.cs @@ -69,13 +69,13 @@ public async Task RunAsync(string name) return await CopyAsync(cic); } - private T Get(CliOption option) => _command.Result.GetValue(option); + private T Get(Option option) => _command.Result.GetValue(option); - private static Task Main(string[] args) => - new CliConfiguration(new CIJobsRootCommand(args).UseVersion()) - { - EnableParseErrorReporting = true - }.InvokeAsync(args); + private static Task Main(string[] args) + { + var command = new CIJobsRootCommand(args).UseVersion(); + return command.Parse(args).InvokeAsync(); + } // List jobs and their details from the given project on .NETCI Jenkins instance. // List functionality: diff --git a/src/cijobs/cijobs.csproj b/src/cijobs/cijobs.csproj index 036eb0f1..87773400 100644 --- a/src/cijobs/cijobs.csproj +++ b/src/cijobs/cijobs.csproj @@ -1,8 +1,5 @@  - - - Exe diff --git a/src/instructions-retired-explorer/instructions-retired-explorer.csproj b/src/instructions-retired-explorer/instructions-retired-explorer.csproj index 4539b1d1..fc32fc7d 100644 --- a/src/instructions-retired-explorer/instructions-retired-explorer.csproj +++ b/src/instructions-retired-explorer/instructions-retired-explorer.csproj @@ -1,8 +1,5 @@  - - - Exe diff --git a/src/jit-analyze/Program.cs b/src/jit-analyze/Program.cs index 2d334f85..cc791ca9 100644 --- a/src/jit-analyze/Program.cs +++ b/src/jit-analyze/Program.cs @@ -908,8 +908,11 @@ public static Dictionary DiffInText(string diffPath, string basePat private T Get(Option option) => _command.Result.GetValue(option); - private static int Main(string[] args) => - new CommandLineConfiguration(new JitAnalyzeRootCommand(args).UseVersion()).Invoke(args); + private static int Main(string[] args) + { + var command = new JitAnalyzeRootCommand(args).UseVersion(); + return command.Parse(args).Invoke(); + } public int Run() { diff --git a/src/jit-analyze/jit-analyze.csproj b/src/jit-analyze/jit-analyze.csproj index 036eb0f1..87773400 100644 --- a/src/jit-analyze/jit-analyze.csproj +++ b/src/jit-analyze/jit-analyze.csproj @@ -1,8 +1,5 @@  - - - Exe diff --git a/src/jit-dasm-pmi/Program.cs b/src/jit-dasm-pmi/Program.cs index 16cf6c50..904bbba3 100644 --- a/src/jit-dasm-pmi/Program.cs +++ b/src/jit-dasm-pmi/Program.cs @@ -75,8 +75,11 @@ public int Run() private T Get(Option option) => _command.Result.GetValue(option); private T Get(Argument arg) => _command.Result.GetValue(arg); - private static int Main(string[] args) => - new CommandLineConfiguration(new JitDasmPmiRootCommand(args).UseVersion()).Invoke(args); + private static int Main(string[] args) + { + var command = new JitDasmPmiRootCommand(args).UseVersion(); + return command.Parse(args).Invoke(); + } public List GenerateAssemblyWorklist() { diff --git a/src/jit-dasm-pmi/jit-dasm-pmi.csproj b/src/jit-dasm-pmi/jit-dasm-pmi.csproj index 036eb0f1..87773400 100644 --- a/src/jit-dasm-pmi/jit-dasm-pmi.csproj +++ b/src/jit-dasm-pmi/jit-dasm-pmi.csproj @@ -1,8 +1,5 @@  - - - Exe diff --git a/src/jit-dasm/Program.cs b/src/jit-dasm/Program.cs index dc24baa8..77755cd1 100644 --- a/src/jit-dasm/Program.cs +++ b/src/jit-dasm/Program.cs @@ -84,8 +84,11 @@ public int Run() private T Get(Option option) => _command.Result.GetValue(option); private T Get(Argument arg) => _command.Result.GetValue(arg); - private static int Main(string[] args) => - new CommandLineConfiguration(new JitDasmRootCommand(args).UseVersion()).Invoke(args); + private static int Main(string[] args) + { + var command = new JitDasmRootCommand(args).UseVersion(); + return command.Parse(args).Invoke(); + } public List GenerateAssemblyWorklist() { diff --git a/src/jit-dasm/jit-dasm.csproj b/src/jit-dasm/jit-dasm.csproj index 036eb0f1..87773400 100644 --- a/src/jit-dasm/jit-dasm.csproj +++ b/src/jit-dasm/jit-dasm.csproj @@ -1,8 +1,5 @@  - - - Exe diff --git a/src/jit-decisions-analyze/jit-decisions-analyze.csproj b/src/jit-decisions-analyze/jit-decisions-analyze.csproj index 036eb0f1..87773400 100644 --- a/src/jit-decisions-analyze/jit-decisions-analyze.csproj +++ b/src/jit-decisions-analyze/jit-decisions-analyze.csproj @@ -1,8 +1,5 @@  - - - Exe diff --git a/src/jit-diff/JitDiffRootCommand.cs b/src/jit-diff/JitDiffRootCommand.cs new file mode 100644 index 00000000..9048517e --- /dev/null +++ b/src/jit-diff/JitDiffRootCommand.cs @@ -0,0 +1,149 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Parsing; + +namespace ManagedCodeGen +{ + internal sealed class JitDiffRootCommand : RootCommand + { + public Option BasePath { get; } = + new("--base", "-b") { Description = "The base compiler directory or tag. Will use crossgen, corerun, or clrjit from this directory.", Arity = ArgumentArity.ZeroOrOne }; + public Option DiffPath { get; } = + new("--diff", "-d") { Description = "The diff compiler directory or tag. Will use crossgen, corerun, or clrjit from this directory.", Arity = ArgumentArity.ZeroOrOne }; + public Option CrossgenExe { get; } = + new("--crossgen") { Description = "The crossgen or crossgen2 compiler exe. When this is specified, will use clrjit from the --base and --diff directories with this crossgen." }; + public Option OutputPath { get; } = + new("--output", "-o") { Description = "The output path." }; + public Option NoAnalyze { get; } = + new("--noanalyze") { Description = "Do not analyze resulting base, diff dasm directories. (By default, the directories are analyzed for diffs.)" }; + public Option Sequential { get; } = + new("--sequential", "-s") { Description = "Run sequentially; don't do parallel compiles." }; + public Option Tag { get; } = + new("--tag", "-t") { Description = "Name of root in output directory. Allows for many sets of output." }; + public Option CoreLib { get; } = + new("--corelib", "-c") { Description = "Diff System.Private.CoreLib.dll." }; + public Option Frameworks { get; } = + new("--frameworks", "-f") { Description = "Diff frameworks." }; + public Option Metric { get; } = + new("--metrics", "-m") { Description = "Comma-separated metric to use for diff computations. Available metrics: CodeSize(default), PerfScore, PrologSize, InstrCount, AllocSize, ExtraAllocBytes, DebugClauseCount, DebugVarCount" }; + public Option Benchmarks { get; } = + new("--benchmarks") { Description = "Diff core benchmarks." }; + public Option Tests { get; } = + new("--tests") { Description = "Diff all tests." }; + public Option GCInfo { get; } = + new("--gcinfo") { Description = "Add GC info to the disasm output." }; + public Option DebugInfo { get; } = + new("--debuginfo") { Description = "Add Debug info to the disasm output." }; + public Option Verbose { get; } = + new("--verbose", "-v") { Description = "Enable verbose output." }; + public Option NoDiffable { get; } = + new("--nodiffable") { Description = "Generate non-diffable asm (pointer values will be left in output)." }; + public Option CoreRoot { get; } = + new("--core_root") { Description = "Path to test CORE_ROOT." }; + public Option TestRoot { get; } = + new("--test_root") { Description = "Path to test tree. Use with --benchmarks or --tests." }; + public Option BaseRoot { get; } = + new("--base_root") { Description = "Path to root of base dotnet/runtime repo." }; + public Option DiffRoot { get; } = + new("--diff_root") { Description = "Path to root of diff dotnet/runtime repo." }; + public Option Arch { get; } = + new("--arch") { Description = "Architecture to diff (x86, x64)." }; + public Option Build { get; } = + new("--build") { Description = "Build flavor to diff (Checked, Debug)." }; + public Option AltJit { get; } = + new("--altjit") { Description = "If set, the name of the altjit to use (e.g., clrjit_win_arm64_x64.dll)." }; + public Option Pmi { get; } = + new("--pmi") { Description = "Run asm diffs via pmi." }; + public Option Cctors { get; } = + new("--cctors") { Description = "With --pmi, jit and run cctors before jitting other methods" }; + public Option> AssemblyList { get; } = + new("--assembly") { Description = "Run asm diffs on a given set of assemblies. An individual item can be an assembly or a directory tree containing assemblies." }; + public Option Tsv { get; } = + new("--tsv") { Description = "Dump analysis data to diffs.tsv in output directory." }; + public Option Tier0 { get; } = + new("--tier0") { Description = "Diff tier0 codegen where possible." }; + public Option Count { get; } = + new("--count") { Description = "Provide the count parameter to jit-analyze (default 20)." }; + + public Option JobName { get; } = + new("--job", "-j") { Description = "Name of the job." }; + public Option Number { get; } = + new("--number", "-n") { Description = "Job number." }; + public Option LastSuccessful { get; } = + new("--last_successful", "-l") { Description = "Last successful build." }; + public Option BranchName { get; } = + new("--branch", "-b") { Description = "Name of branch." }; + + public ParseResult Result { get; private set; } + public jitdiff.Commands SelectedCommand { get; private set; } + + public JitDiffRootCommand(string[] args) : base("Managed codegen diff orchestrator") + { + Command diffCommand = new("diff", "Run asm diffs via crossgen.") + { + BasePath, DiffPath, CrossgenExe, OutputPath, NoAnalyze, Sequential, Tag, CoreLib, Frameworks, Metric, + Benchmarks, Tests, GCInfo, DebugInfo, Verbose, NoDiffable, CoreRoot, TestRoot, BaseRoot, DiffRoot, + Arch, Build, AltJit, Pmi, Cctors, AssemblyList, Tsv, Tier0, Count + }; + diffCommand.SetAction(result => Execute(result, jitdiff.Commands.Diff)); + Subcommands.Add(diffCommand); + + Command listCommand = new("list", "List defaults and available tools in config.json.") + { + Verbose + }; + listCommand.SetAction(result => Execute(result, jitdiff.Commands.List)); + Subcommands.Add(listCommand); + + Command installCommand = new("install", "Install tool in config.json.") + { + JobName, Number, LastSuccessful, BranchName, Verbose + }; + installCommand.SetAction(result => Execute(result, jitdiff.Commands.Install)); + Subcommands.Add(installCommand); + + Command uninstallCommand = new("uninstall", "Uninstall tool from config.json.") + { + Tag + }; + uninstallCommand.SetAction(result => Execute(result, jitdiff.Commands.Uninstall)); + Subcommands.Add(uninstallCommand); + } + + private int Execute(ParseResult result, jitdiff.Commands command) + { + Result = result; + SelectedCommand = command; + + try + { + jitdiff.Config config = new(this); + return config.DoCommand switch + { + jitdiff.Commands.Diff => jitdiff.DiffTool.DiffCommand(config), + jitdiff.Commands.PmiDiff => jitdiff.DiffTool.DiffCommand(config), + jitdiff.Commands.List => config.ListCommand(), + jitdiff.Commands.Install => jitdiff.InstallCommand(config), + jitdiff.Commands.Uninstall => jitdiff.UninstallCommand(config), + _ => 1, + }; + } + catch (Exception e) + { + Console.ResetColor(); + Console.ForegroundColor = ConsoleColor.Red; + + Console.Error.WriteLine("Error: " + e.Message); + Console.Error.WriteLine(e.ToString()); + + Console.ResetColor(); + return 1; + } + } + } +} diff --git a/src/jit-diff/jit-diff.cs b/src/jit-diff/jit-diff.cs index 9430d637..c395c112 100755 --- a/src/jit-diff/jit-diff.cs +++ b/src/jit-diff/jit-diff.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.CommandLine; +using System.CommandLine.Parsing; using System.IO; using System.Linq; using System.Text.Json; @@ -113,7 +114,6 @@ private static string GetConfigurationArtifactDir(string platformMoniker, string public class Config { - private ArgumentSyntax _syntaxResult; private Commands _command = Commands.Diff; private bool _baseSpecified = false; // True if user specified "--base" or "--base " or "--base " private bool _diffSpecified = false; // True if user specified "--diff" or "--diff " or "--diff " @@ -158,77 +158,80 @@ public class Config private bool _noJitUtilsRoot = false; private bool _validationError = false; - public Config(string[] args) + internal Config(JitDiffRootCommand command) { - // Get configuration values from JIT_UTILS_ROOT/config.json + // Get configuration values from JIT_UTILS_ROOT/config.json. LoadFileConfig(); - _syntaxResult = ArgumentSyntax.Parse(args, syntax => + ParseResult result = command.Result; + _command = command.SelectedCommand; + + bool IsSpecified(Option option) => result.GetResult(option) != null; + T Get(Option option) => result.GetValue(option); + + if (_command == Commands.Diff) { - // Diff command section. - syntax.DefineCommand("diff", ref _command, Commands.Diff, "Run asm diffs via crossgen."); - - var baseOption = syntax.DefineOption("b|base", ref _basePath, false, - "The base compiler directory or tag. Will use crossgen, corerun, or clrjit from this directory."); - var diffOption = syntax.DefineOption("d|diff", ref _diffPath, false, - "The diff compiler directory or tag. Will use crossgen, corerun, or clrjit from this directory."); - syntax.DefineOption("crossgen", ref _crossgenExe, - "The crossgen or crossgen2 compiler exe. When this is specified, will use clrjit from the --base and " + - "--diff directories with this crossgen."); - syntax.DefineOption("o|output", ref _outputPath, "The output path."); - syntax.DefineOption("noanalyze", ref _noanalyze, "Do not analyze resulting base, diff dasm directories. (By default, the directories are analyzed for diffs.)"); - syntax.DefineOption("s|sequential", ref _sequential, "Run sequentially; don't do parallel compiles."); - syntax.DefineOption("t|tag", ref _tag, "Name of root in output directory. Allows for many sets of output."); - syntax.DefineOption("c|corelib", ref _corelib, "Diff System.Private.CoreLib.dll."); - syntax.DefineOption("f|frameworks", ref _frameworks, "Diff frameworks."); - syntax.DefineOption("m|metrics", ref _metric, false, "Comma-separated metric to use for diff computations. Available metrics: CodeSize(default), PerfScore, PrologSize, InstrCount, AllocSize, ExtraAllocBytes, DebugClauseCount, DebugVarCount"); - syntax.DefineOption("benchmarks", ref _benchmarks, "Diff core benchmarks."); - syntax.DefineOption("tests", ref _tests, "Diff all tests."); - syntax.DefineOption("gcinfo", ref _gcinfo, "Add GC info to the disasm output."); - syntax.DefineOption("debuginfo", ref _debuginfo, "Add Debug info to the disasm output."); - syntax.DefineOption("v|verbose", ref _verbose, "Enable verbose output."); - syntax.DefineOption("nodiffable", ref _noDiffable, "Generate non-diffable asm (pointer values will be left in output)."); - syntax.DefineOption("core_root", ref _platformPath, "Path to test CORE_ROOT."); - syntax.DefineOption("test_root", ref _testPath, "Path to test tree. Use with --benchmarks or --tests."); - syntax.DefineOption("base_root", ref _baseRoot, "Path to root of base dotnet/runtime repo."); - syntax.DefineOption("diff_root", ref _diffRoot, "Path to root of diff dotnet/runtime repo."); - syntax.DefineOption("arch", ref _arch, "Architecture to diff (x86, x64)."); - syntax.DefineOption("build", ref _build, "Build flavor to diff (Checked, Debug)."); - syntax.DefineOption("altjit", ref _altjit, "If set, the name of the altjit to use (e.g., clrjit_win_arm64_x64.dll)."); - var pmiOption = syntax.DefineOption("pmi", ref _pmi, "Run asm diffs via pmi."); - syntax.DefineOption("cctors", ref _cctors, "With --pmi, jit and run cctors before jitting other methods"); - syntax.DefineOptionList("assembly", ref _assemblyList, "Run asm diffs on a given set of assemblies. An individual item can be an assembly or a directory tree containing assemblies."); - syntax.DefineOption("tsv", ref _tsv, "Dump analysis data to diffs.tsv in output directory."); - syntax.DefineOption("tier0", ref _tier0, "Diff tier0 codegen where possible."); - - // used by jit-analyze - syntax.DefineOption("count", ref _count, "provide the count parameter to jit-analyze (default 20)"); - - // List command section. - syntax.DefineCommand("list", ref _command, Commands.List, - "List defaults and available tools in " + s_configFileName + "."); - syntax.DefineOption("v|verbose", ref _verbose, "Enable verbose output."); - - // Install command section. - syntax.DefineCommand("install", ref _command, Commands.Install, "Install tool in " + s_configFileName + "."); - syntax.DefineOption("j|job", ref _jobName, "Name of the job."); - syntax.DefineOption("n|number", ref _number, "Job number."); - syntax.DefineOption("l|last_successful", ref _lastSuccessful, "Last successful build."); - syntax.DefineOption("b|branch", ref _branchName, "Name of branch."); - syntax.DefineOption("v|verbose", ref _verbose, "Enable verbose output."); - - // Uninstall command section.s - syntax.DefineCommand("uninstall", ref _command, Commands.Uninstall, "Uninstall tool from " + s_configFileName + "."); - syntax.DefineOption("t|tag", ref _tag, "Name of tool tag in config file."); - - _baseSpecified = baseOption.IsSpecified; - _diffSpecified = diffOption.IsSpecified; - - if (pmiOption.IsSpecified) + _baseSpecified = IsSpecified(command.BasePath); + if (_baseSpecified) + { + _basePath = Get(command.BasePath); + } + + _diffSpecified = IsSpecified(command.DiffPath); + if (_diffSpecified) + { + _diffPath = Get(command.DiffPath); + } + + if (IsSpecified(command.CrossgenExe)) _crossgenExe = Get(command.CrossgenExe); + if (IsSpecified(command.OutputPath)) _outputPath = Get(command.OutputPath); + if (IsSpecified(command.NoAnalyze)) _noanalyze = Get(command.NoAnalyze); + if (IsSpecified(command.Sequential)) _sequential = Get(command.Sequential); + if (IsSpecified(command.Tag)) _tag = Get(command.Tag); + if (IsSpecified(command.CoreLib)) _corelib = Get(command.CoreLib); + if (IsSpecified(command.Frameworks)) _frameworks = Get(command.Frameworks); + if (IsSpecified(command.Metric)) _metric = Get(command.Metric); + if (IsSpecified(command.Benchmarks)) _benchmarks = Get(command.Benchmarks); + if (IsSpecified(command.Tests)) _tests = Get(command.Tests); + if (IsSpecified(command.GCInfo)) _gcinfo = Get(command.GCInfo); + if (IsSpecified(command.DebugInfo)) _debuginfo = Get(command.DebugInfo); + if (IsSpecified(command.Verbose)) _verbose = Get(command.Verbose); + if (IsSpecified(command.NoDiffable)) _noDiffable = Get(command.NoDiffable); + if (IsSpecified(command.CoreRoot)) _platformPath = Get(command.CoreRoot); + if (IsSpecified(command.TestRoot)) _testPath = Get(command.TestRoot); + if (IsSpecified(command.BaseRoot)) _baseRoot = Get(command.BaseRoot); + if (IsSpecified(command.DiffRoot)) _diffRoot = Get(command.DiffRoot); + if (IsSpecified(command.Arch)) _arch = Get(command.Arch); + if (IsSpecified(command.Build)) _build = Get(command.Build); + if (IsSpecified(command.AltJit)) _altjit = Get(command.AltJit); + if (IsSpecified(command.Pmi)) _pmi = Get(command.Pmi); + if (IsSpecified(command.Cctors)) _cctors = Get(command.Cctors); + if (IsSpecified(command.AssemblyList)) _assemblyList = Get(command.AssemblyList); + if (IsSpecified(command.Tsv)) _tsv = Get(command.Tsv); + if (IsSpecified(command.Tier0)) _tier0 = Get(command.Tier0); + if (IsSpecified(command.Count)) _count = Get(command.Count); + + if (_pmi) { _command = Commands.PmiDiff; } - }); + } + else if (_command == Commands.List) + { + if (IsSpecified(command.Verbose)) _verbose = Get(command.Verbose); + } + else if (_command == Commands.Install) + { + if (IsSpecified(command.JobName)) _jobName = Get(command.JobName); + if (IsSpecified(command.Number)) _number = Get(command.Number); + if (IsSpecified(command.LastSuccessful)) _lastSuccessful = Get(command.LastSuccessful); + if (IsSpecified(command.BranchName)) _branchName = Get(command.BranchName); + if (IsSpecified(command.Verbose)) _verbose = Get(command.Verbose); + } + else if (_command == Commands.Uninstall) + { + if (IsSpecified(command.Tag)) _tag = Get(command.Tag); + } SetRID(); @@ -776,7 +779,8 @@ private void Validate() private void DisplayUsageMessage() { Console.Error.WriteLine(""); - Console.Error.Write(_syntaxResult.GetHelpText(100)); + Console.Error.WriteLine("Usage: jit-diff [options]"); + Console.Error.WriteLine("Run 'jit-diff --help' for command-specific options."); if (_command == Commands.Diff) { @@ -1348,36 +1352,8 @@ public int ListCommand() public static int Main(string[] args) { - Config config = new Config(args); - int ret = 0; - - switch (config.DoCommand) - { - case Commands.Diff: - case Commands.PmiDiff: - { - ret = DiffTool.DiffCommand(config); - } - break; - case Commands.List: - { - // List command: list loaded configuration - ret = config.ListCommand(); - } - break; - case Commands.Install: - { - ret = InstallCommand(config); - } - break; - case Commands.Uninstall: - { - ret = UninstallCommand(config); - } - break; - } - - return ret; + var command = new JitDiffRootCommand(args).UseVersion(); + return command.Parse(args).Invoke(); } } } diff --git a/src/jit-diff/jit-diff.csproj b/src/jit-diff/jit-diff.csproj index 7c7b258e..87773400 100644 --- a/src/jit-diff/jit-diff.csproj +++ b/src/jit-diff/jit-diff.csproj @@ -1,14 +1,11 @@  - - Exe - diff --git a/src/jit-format/JitFormatRootCommand.cs b/src/jit-format/JitFormatRootCommand.cs new file mode 100644 index 00000000..2d3c4d3d --- /dev/null +++ b/src/jit-format/JitFormatRootCommand.cs @@ -0,0 +1,65 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Parsing; + +namespace ManagedCodeGen +{ + internal sealed class JitFormatRootCommand : RootCommand + { + public Option Arch { get; } = + new("--arch", "-a") { Description = "The architecture of the build (options: arm64, x64, x86)" }; + public Option OS { get; } = + new("--os", "-o") { Description = "The operating system of the build (options: windows, osx, linux, etc.)" }; + public Option Build { get; } = + new("--build", "-b") { Description = "The build type of the build (options: Release, Checked, Debug)" }; + public Option RuntimePath { get; } = + new("--runtime", "-r") { Description = "Full path to runtime directory" }; + public Option CompileCommands { get; } = + new("--compile-commands") { Description = "Full path to compile_commands.json" }; + public Option Verbose { get; } = + new("--verbose") { Description = "Enable verbose output." }; + public Option Untidy { get; } = + new("--untidy") { Description = "Do not run clang-tidy" }; + public Option NoFormat { get; } = + new("--noformat") { Description = "Do not run clang-format" }; + public Option Cross { get; } = + new("--cross") { Description = "If on Linux, run the configure build as a cross build." }; + public Option Fix { get; } = + new("--fix", "-f") { Description = "Fix formatting errors discovered by clang-format and clang-tidy." }; + public Option IgnoreErrors { get; } = + new("--ignore-errors", "-i") { Description = "Ignore clang-tidy errors" }; + public Option> Projects { get; } = + new("--projects") { Description = "List of build projects clang-tidy should consider (e.g. dll, standalone, protojit, etc.). Default: dll" }; + public Argument> Filenames { get; } = + new("filenames") { Description = "Optional list of files that should be formatted." }; + + public ParseResult Result { get; private set; } + + public JitFormatRootCommand(string[] args) : base("JIT formatting tool") + { + Options.Add(Arch); + Options.Add(OS); + Options.Add(Build); + Options.Add(RuntimePath); + Options.Add(CompileCommands); + Options.Add(Verbose); + Options.Add(Untidy); + Options.Add(NoFormat); + Options.Add(Cross); + Options.Add(Fix); + Options.Add(IgnoreErrors); + Options.Add(Projects); + Arguments.Add(Filenames); + + SetAction(result => + { + Result = result; + return jitformat.Execute(this); + }); + } + } +} diff --git a/src/jit-format/jit-format.cs b/src/jit-format/jit-format.cs index 104017e8..4d7ca752 100644 --- a/src/jit-format/jit-format.cs +++ b/src/jit-format/jit-format.cs @@ -10,6 +10,7 @@ using System; using System.Collections.Generic; using System.CommandLine; +using System.CommandLine.Parsing; using System.Diagnostics; using System.IO; using System.Linq; @@ -30,7 +31,6 @@ public class Config private static string s_configFileName = "config.json"; private static string s_configFileRootKey = "format"; - private ArgumentSyntax _syntaxResult; private string _arch = null; private string _os = null; private string _build = null; @@ -51,27 +51,29 @@ public class Config private JsonObject _jObj; private string _jitUtilsRoot = null; - public Config(string[] args) + internal Config(JitFormatRootCommand command) { LoadFileConfig(); - _syntaxResult = ArgumentSyntax.Parse(args, syntax => - { - syntax.DefineOption("a|arch", ref _arch, "The architecture of the build (options: arm64, x64, x86)"); - syntax.DefineOption("o|os", ref _os, "The operating system of the build (options: windows, osx, linux, etc.)"); - syntax.DefineOption("b|build", ref _build, "The build type of the build (options: Release, Checked, Debug)"); - syntax.DefineOption("r|runtime", ref _runtimePath, "Full path to runtime directory"); - syntax.DefineOption("compile-commands", ref _compileCommands, "Full path to compile_commands.json"); - syntax.DefineOption("v|verbose", ref _verbose, "Enable verbose output."); - syntax.DefineOption("untidy", ref _untidy, "Do not run clang-tidy"); - syntax.DefineOption("noformat", ref _noformat, "Do not run clang-format"); - syntax.DefineOption("cross", ref _cross, "If on Linux, run the configure build as a cross build."); - syntax.DefineOption("f|fix", ref _fix, "Fix formatting errors discovered by clang-format and clang-tidy."); - syntax.DefineOption("i|ignore-errors", ref _ignoreErrors, "Ignore clang-tidy errors"); - syntax.DefineOptionList("projects", ref _projects, "List of build projects clang-tidy should consider (e.g. dll, standalone, protojit, etc.). Default: dll"); - - syntax.DefineParameterList("filenames", ref _filenames, "Optional list of files that should be formatted."); - }); + ParseResult result = command.Result; + + bool IsSpecified(Option option) => result.GetResult(option) != null; + T Get(Option option) => result.GetValue(option); + List GetArgument(Argument> arg) => result.GetValue(arg); + + if (IsSpecified(command.Arch)) _arch = Get(command.Arch); + if (IsSpecified(command.OS)) _os = Get(command.OS); + if (IsSpecified(command.Build)) _build = Get(command.Build); + if (IsSpecified(command.RuntimePath)) _runtimePath = Get(command.RuntimePath); + if (IsSpecified(command.CompileCommands)) _compileCommands = Get(command.CompileCommands); + if (IsSpecified(command.Verbose)) _verbose = Get(command.Verbose); + if (IsSpecified(command.Untidy)) _untidy = Get(command.Untidy); + if (IsSpecified(command.NoFormat)) _noformat = Get(command.NoFormat); + if (IsSpecified(command.Cross)) _cross = Get(command.Cross); + if (IsSpecified(command.Fix)) _fix = Get(command.Fix); + if (IsSpecified(command.IgnoreErrors)) _ignoreErrors = Get(command.IgnoreErrors); + if (IsSpecified(command.Projects)) _projects = Get(command.Projects); + _filenames = GetArgument(command.Filenames); // Run validation code on parsed input to ensure we have a sensible scenario. @@ -241,7 +243,7 @@ private void validate() if (!_untidy && ((_arch == null) || (_os == null) || (_build == null))) { - _syntaxResult.ReportError("Specify --arch, --os, and --build for clang-tidy run."); + throw new Exception("Specify --arch, --os, and --build for clang-tidy run."); } if (_runtimePath == null) @@ -253,7 +255,7 @@ private void validate() _runtimePath = Utility.GetRepoRoot(_verbose); if (_runtimePath == null) { - _syntaxResult.ReportError("Specify --runtime"); + throw new Exception("Specify --runtime"); } else { @@ -265,12 +267,12 @@ private void validate() if (!Directory.Exists(_coreclrPath)) { // If _coreclrPath doesn't exist, it is an invalid path - _syntaxResult.ReportError("Invalid path to runtime directory. Specify with --runtime"); + throw new Exception("Invalid path to runtime directory. Specify with --runtime"); } else if (!File.Exists(Path.Combine(_coreclrPath, "build-runtime.cmd")) || !File.Exists(Path.Combine(_coreclrPath, "build-runtime.sh")) || !File.Exists(Path.Combine(_coreclrPath, "clr.featuredefines.props"))) { // Doesn't look like the coreclr directory. - _syntaxResult.ReportError("Invalid path to coreclr directory. Specify with --runtime"); + throw new Exception("Invalid path to coreclr directory. Specify with --runtime"); } // Check that we can find compile_commands.json on windows @@ -491,10 +493,10 @@ public CompileCommand(string dir, string cmd, string filename) } } - public static int Main(string[] args) + internal static int Execute(JitFormatRootCommand command) { // Parse and store comand line options. - var config = new Config(args); + var config = new Config(command); int returncode = 0; bool verbose = config.DoVerboseOutput; @@ -625,6 +627,12 @@ public static int Main(string[] args) return returncode; } + public static int Main(string[] args) + { + var command = new JitFormatRootCommand(args).UseVersion(); + return command.Parse(args).Invoke(); + } + // This method reads in a compile_command.json file, and writes a new json file with only the entries // commands for files found in the project specified. For example, if project is dll, it will write a // new compile_commands file (called compile_commands_dll.json) with only the entries whose directory diff --git a/src/jit-format/jit-format.csproj b/src/jit-format/jit-format.csproj index 7c7b258e..87773400 100644 --- a/src/jit-format/jit-format.csproj +++ b/src/jit-format/jit-format.csproj @@ -1,14 +1,11 @@  - - Exe - diff --git a/src/jit-include.props b/src/jit-include.props deleted file mode 100644 index e4a0fd5d..00000000 --- a/src/jit-include.props +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/src/jit-rl-cse/MLCSE.csproj b/src/jit-rl-cse/MLCSE.csproj index c5357bb9..65779695 100644 --- a/src/jit-rl-cse/MLCSE.csproj +++ b/src/jit-rl-cse/MLCSE.csproj @@ -1,8 +1,5 @@  - - - Exe enable diff --git a/src/jit-tp-analyze/Program.cs b/src/jit-tp-analyze/Program.cs index ae9acac5..2fdc5fae 100644 --- a/src/jit-tp-analyze/Program.cs +++ b/src/jit-tp-analyze/Program.cs @@ -124,8 +124,11 @@ private static double GetPercentageDiff(double baseValue, double diffValue) => private static string FormatPercentageDiff(double value, string precision = "00") => (value > 0 ? "+" : "") + value.ToString($"0.{precision}") + "%"; - private static void Main(string[] args) => - new CommandLineConfiguration(new JitTpAnalyzeRootCommand().UseVersion()).Invoke(args); + private static void Main(string[] args) + { + var command = new JitTpAnalyzeRootCommand().UseVersion(); + command.Parse(args).Invoke(); + } private struct FunctionDiff { diff --git a/src/jit-tp-analyze/jit-tp-analyze.csproj b/src/jit-tp-analyze/jit-tp-analyze.csproj index fe8dbbe8..6a70a1ab 100644 --- a/src/jit-tp-analyze/jit-tp-analyze.csproj +++ b/src/jit-tp-analyze/jit-tp-analyze.csproj @@ -1,8 +1,5 @@  - - - Exe diff --git a/src/mutate-test/MutateTestRootCommand.cs b/src/mutate-test/MutateTestRootCommand.cs index e6ed26b5..bb14301c 100644 --- a/src/mutate-test/MutateTestRootCommand.cs +++ b/src/mutate-test/MutateTestRootCommand.cs @@ -7,35 +7,35 @@ namespace MutateTest { - internal sealed class MutateTestRootCommand : CliRootCommand + internal sealed class MutateTestRootCommand : RootCommand { - public CliArgument InputFilePath { get; } = - new("input-test-case") { Description = "Input test case file or directory (for --recursive)", Arity = ArgumentArity.OneOrMore }; - public CliOption EHStress { get; } = + public Argument InputFilePath { get; } = + new("input-test-case") { Description = "Input test case file or directory (for --recursive)", Arity = ArgumentArity.ExactlyOne }; + public Option EHStress { get; } = new("--ehStress") { Description = "Add EH to methods" }; - public CliOption StructStress { get; } = + public Option StructStress { get; } = new("--structStress") { Description = "Replace locals with structs" }; - public CliOption ShowResults { get; } = + public Option ShowResults { get; } = new("--showResults") { Description = "Add EH to methods" }; - public CliOption Verbose { get; } = + public Option Verbose { get; } = new("--verbose") { Description = "Describe each transformation" }; - public CliOption Quiet { get; } = + public Option Quiet { get; } = new("--quiet") { Description = "Produce minimal output" }; - public CliOption Recursive { get; } = + public Option Recursive { get; } = new("--recursive") { Description = "Process each file recursively" }; - public CliOption Seed { get; } = + public Option Seed { get; } = new("--seed") { DefaultValueFactory = _ => 42, Description = "Random seed" }; - public CliOption StopAtFirstFailure { get; } = + public Option StopAtFirstFailure { get; } = new("--stopAtFirstFailure") { Description = "Stop each test at first failure" }; - public CliOption EmptyBlocks { get; } = + public Option EmptyBlocks { get; } = new("--emptyBlocks") { Description = "Transform empty blocks" }; - public CliOption SizeLimit { get; } = + public Option SizeLimit { get; } = new("--sizeLimit") { DefaultValueFactory = _ => 10000, Description = "Don't process programs larger than this size" }; - public CliOption TimeLimit { get; } = + public Option TimeLimit { get; } = new("--timeLimit") { DefaultValueFactory = _ => 10000, Description = "Don't stress programs where compile + run takes more than this many milliseconds" }; - public CliOption Projects { get; } = + public Option Projects { get; } = new("--projects") { Description = "Look for .csproj files instead of .cs files when doing recursive exploration" }; - public CliOption OnlyFailures { get; } = + public Option OnlyFailures { get; } = new("--onlyFailures") { Description = "Only emit output for cases that fail at runtime" }; public ParseResult Result { get; private set; } diff --git a/src/mutate-test/Program.cs b/src/mutate-test/Program.cs index 212a8ba1..6006e466 100644 --- a/src/mutate-test/Program.cs +++ b/src/mutate-test/Program.cs @@ -232,13 +232,13 @@ public Program(MutateTestRootCommand command) private static bool isFirstRun = true; - private T Get(CliOption option) => _command.Result.GetValue(option); + private T Get(Option option) => _command.Result.GetValue(option); - private static int Main(string[] args) => - new CliConfiguration(new MutateTestRootCommand(args).UseVersion()) - { - EnableParseErrorReporting = true - }.Invoke(args); + private static int Main(string[] args) + { + var command = new MutateTestRootCommand(args).UseVersion(); + return command.Parse(args).Invoke(); + } public int Run() { diff --git a/src/mutate-test/mutate-test.csproj b/src/mutate-test/mutate-test.csproj index bd600f3a..c09eb2da 100644 --- a/src/mutate-test/mutate-test.csproj +++ b/src/mutate-test/mutate-test.csproj @@ -1,10 +1,7 @@  - - Exe - net6.0 Mutate Mutate diff --git a/src/performance-explorer/performance-explorer.csproj b/src/performance-explorer/performance-explorer.csproj index 036eb0f1..87773400 100644 --- a/src/performance-explorer/performance-explorer.csproj +++ b/src/performance-explorer/performance-explorer.csproj @@ -1,8 +1,5 @@  - - - Exe diff --git a/src/pmi/pmi.csproj b/src/pmi/pmi.csproj index 344ce4c0..89ff5527 100644 --- a/src/pmi/pmi.csproj +++ b/src/pmi/pmi.csproj @@ -4,8 +4,6 @@ Exe - - diff --git a/src/superpmi/superpmicollect.csproj b/src/superpmi/superpmicollect.csproj index 95fdbc0d..52e6553d 100644 --- a/src/superpmi/superpmicollect.csproj +++ b/src/superpmi/superpmicollect.csproj @@ -4,6 +4,4 @@ Exe - - diff --git a/src/target-framework.props b/src/target-framework.props deleted file mode 100644 index c5a6fefa..00000000 --- a/src/target-framework.props +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - net8.0 - - - diff --git a/src/wasm-spmi-filter/wasm-spmi-filter.csproj b/src/wasm-spmi-filter/wasm-spmi-filter.csproj index 19d1338a..553d71b4 100644 --- a/src/wasm-spmi-filter/wasm-spmi-filter.csproj +++ b/src/wasm-spmi-filter/wasm-spmi-filter.csproj @@ -2,7 +2,6 @@ Exe - net10.0 wasm_spmi_filter enable enable