From d29392edce6bee3fb178ea6275222cc2ae69b18f Mon Sep 17 00:00:00 2001 From: Adeel Mujahid <3840695+am11@users.noreply.github.com> Date: Fri, 27 Mar 2026 12:40:14 +0000 Subject: [PATCH 1/5] Migrate remaining tools to modern commandline --- eng/build.yml | 2 +- src/AnalyzeAsm/AnalyzeAsm.csproj | 1 - src/Directory.Build.props | 15 ++ src/cijobs/CIJobsRootCommand.cs | 33 ++-- src/cijobs/Program.cs | 12 +- src/cijobs/cijobs.csproj | 3 - .../instructions-retired-explorer.csproj | 3 - src/jit-analyze/Program.cs | 7 +- src/jit-analyze/jit-analyze.csproj | 3 - src/jit-dasm-pmi/Program.cs | 7 +- src/jit-dasm-pmi/jit-dasm-pmi.csproj | 3 - src/jit-dasm/Program.cs | 7 +- src/jit-dasm/jit-dasm.csproj | 3 - .../jit-decisions-analyze.csproj | 3 - src/jit-diff/JitDiffRootCommand.cs | 149 ++++++++++++++++ src/jit-diff/jit-diff.cs | 168 ++++++++---------- src/jit-diff/jit-diff.csproj | 3 - src/jit-format/JitFormatRootCommand.cs | 65 +++++++ src/jit-format/jit-format.cs | 58 +++--- src/jit-format/jit-format.csproj | 3 - src/jit-include.props | 11 -- src/jit-rl-cse/MLCSE.csproj | 3 - src/jit-tp-analyze/Program.cs | 7 +- src/jit-tp-analyze/jit-tp-analyze.csproj | 3 - src/mutate-test/MutateTestRootCommand.cs | 32 ++-- src/mutate-test/Program.cs | 12 +- src/mutate-test/mutate-test.csproj | 3 - .../performance-explorer.csproj | 3 - src/pmi/pmi.csproj | 2 - src/superpmi/superpmicollect.csproj | 2 - src/target-framework.props | 9 - src/wasm-spmi-filter/wasm-spmi-filter.csproj | 1 - 32 files changed, 399 insertions(+), 237 deletions(-) create mode 100644 src/Directory.Build.props create mode 100644 src/jit-diff/JitDiffRootCommand.cs create mode 100644 src/jit-format/JitFormatRootCommand.cs delete mode 100644 src/jit-include.props delete mode 100644 src/target-framework.props 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 From 4c1ec85dd84e16cc4df69a5357804e203f9ac5cf Mon Sep 17 00:00:00 2001 From: Adeel Mujahid <3840695+am11@users.noreply.github.com> Date: Tue, 12 May 2026 12:43:21 +0000 Subject: [PATCH 2/5] Consolidate extended help for diff subcommand --- src/jit-diff/diff.cs | 6 +- src/jit-diff/jit-diff.cs | 133 ++++++++++++++++----------------- src/jit-format/jit-format.cs | 9 +-- src/util/CommandLineHelpers.cs | 45 +++++++++++ 4 files changed, 116 insertions(+), 77 deletions(-) diff --git a/src/jit-diff/diff.cs b/src/jit-diff/diff.cs index e9cd749c..7a671de8 100644 --- a/src/jit-diff/diff.cs +++ b/src/jit-diff/diff.cs @@ -432,14 +432,14 @@ private static int CompareFrameworkAssemblies(AssemblyInfo assemblyInfo1, Assemb { string assembly1 = assemblyInfo1.Path; - if (assembly1 == s_CoreLibAssembly) + if (assembly1 == CoreLibAssemblyName) { return -1; } string assembly2 = assemblyInfo2.Path; - if (assembly2 == s_CoreLibAssembly) + if (assembly2 == CoreLibAssemblyName) { return 1; } @@ -497,7 +497,7 @@ public static List GenerateAssemblyWorklist(Config config) if (config.CoreLib || config.DoFrameworks) { const bool recursive = false; - string searchPattern = config.DoFrameworks ? "*" : s_CoreLibAssembly; + string searchPattern = config.DoFrameworks ? "*" : CoreLibAssemblyName; List directoryAssemblyInfoList = IdentifyAssemblies(config.CoreRoot, config.CoreRoot, config, recursive, searchPattern); directoryAssemblyInfoList.Sort(CompareFrameworkAssemblies); diff --git a/src/jit-diff/jit-diff.cs b/src/jit-diff/jit-diff.cs index c395c112..a8fa8b7e 100755 --- a/src/jit-diff/jit-diff.cs +++ b/src/jit-diff/jit-diff.cs @@ -5,13 +5,10 @@ using System; using System.Collections.Generic; using System.CommandLine; -using System.CommandLine.Parsing; using System.IO; -using System.Linq; using System.Text.Json; using System.Text.Json.Nodes; using System.Text.RegularExpressions; -using System.Threading.Tasks; using System.Runtime.InteropServices; namespace ManagedCodeGen @@ -148,7 +145,7 @@ public class Config private string _platformName = null; private string _branchName = null; private bool _pmi = false; - private IReadOnlyList _assemblyList = Array.Empty(); + private IReadOnlyList _assemblyList = []; private bool _tsv; private bool _cctors; private int _count = 20; @@ -771,65 +768,11 @@ private void Validate() if (_validationError) { - DisplayUsageMessage(); + jitdiff.DisplayCommandHelp(_command); Environment.Exit(-1); } } - private void DisplayUsageMessage() - { - Console.Error.WriteLine(""); - Console.Error.WriteLine("Usage: jit-diff [options]"); - Console.Error.WriteLine("Run 'jit-diff --help' for command-specific options."); - - if (_command == Commands.Diff) - { - string[] diffExampleText = { - @"Examples:", - @"", - @" jit-diff diff --output c:\diffs --corelib --core_root c:\runtime\artifacts\tests\coreclr\windows.x64.Release\Tests\Core_Root --base c:\runtime_base\artifacts\bin\coreclr\windows.x64.Checked --diff c:\runtime\artifacts\bin\coreclr\windows.x86.Checked", - @" Generate diffs of prejitted code for System.Private.CoreLib.dll by specifying baseline and", - @" diff compiler directories explicitly.", - @"", - @" jit-diff diff --output c:\diffs --base c:\runtime_base\artifacts\bin\coreclr\windows.x64.Checked --diff", - @" If run within the c:\runtime git clone of dotnet/runtime, does the same", - @" as the prevous example, using defaults.", - @"", - @" jit-diff diff --output c:\diffs --base --base_root c:\runtime_base --diff", - @" Does the same as the prevous example, using -base_root to find the base", - @" directory (if run from c:\runtime tree).", - @"", - @" jit-diff diff --base --diff", - @" Does the same as the prevous example (if run from c:\runtime tree), but uses", - @" default c:\runtime\artifacts\diffs output directory, and `base_root` must be specified", - @" in the config.json file in the directory pointed to by the JIT_UTILS_ROOT", - @" environment variable.", - @"", - @" jit-diff diff --base --diff --pmi", - @" Does the same as the prevous example (if run from c:\runtime tree)", - @" but shows diffs for jitted code, via PMI", - @"", - @" jit-diff diff --diff", - @" Only generates asm using the diff JIT -- does not generate asm from a baseline compiler --", - @" using all computed defaults.", - @"", - @" jit-diff diff --diff --pmi --assembly test.exe", - @" Generates asm using the diff JIT, showing jitted code for all methods", - @" in the assembly test.exe", - @"", - @" jit-diff diff --diff --arch x86", - @" Generate diffs, but for x86, even if there is an x64 compiler available.", - @"", - @" jit-diff diff --diff --build Debug", - @" Generate diffs, but using a Debug build, even if there is a Checked build available." - }; - foreach (var line in diffExampleText) - { - Console.Error.WriteLine(line); - } - } - } - private void DisplayErrorMessage(string error) { Console.Error.WriteLine("error: {0}", error); @@ -976,11 +919,18 @@ public string GetToolPath(string tool, out bool found) // Extract set value for tool and see if we can find it // in the installed tools. var tools = (JsonArray)_jObj[s_configFileRootKey]["tools"]; - var path = tools.Where(x => (string)x["tag"] == tag) - .Select(x => (string)x["path"]); - // If the tag resolves to a tool return it, otherwise just return it - // as a posible path. - return path.Any() ? path.First() : tag; + foreach (JsonNode installedTool in tools) + { + if ((string)installedTool["tag"] == tag) + { + // If the tag resolves to a tool, return the resolved path. + return (string)installedTool["path"]; + } + } + + // If the tag doesn't resolve to an installed tool, return it as + // a possible path. + return tag; } found = false; @@ -1348,13 +1298,62 @@ public int ListCommand() "V8" }; - private static string s_CoreLibAssembly = "System.Private.CoreLib.dll"; + private const string CoreLibAssemblyName = "System.Private.CoreLib.dll"; + + private static RootCommand CreateRootCommand(string[] args) => + new JitDiffRootCommand(args) + .UseVersion() + .UseExtendedHelp(PrintExtendedHelp); + + internal static void DisplayCommandHelp(Commands command) + { + string[] helpArgs = command switch + { + Commands.Diff or Commands.PmiDiff => ["diff", "--help"], + Commands.List => ["list", "--help"], + Commands.Install => ["install", "--help"], + Commands.Uninstall => ["uninstall", "--help"], + _ => ["--help"] + }; + + CreateRootCommand([]).Parse(helpArgs).Invoke(); + } + + public static void PrintExtendedHelp(ParseResult parseResult) + { + if (!string.Equals(parseResult.CommandResult.Command.Name, "diff", StringComparison.OrdinalIgnoreCase)) + { + return; + } + + Console.WriteLine(""" + + Examples: + + jit-diff diff --output c:\diffs --corelib --core_root c:\runtime\artifacts\tests\coreclr\windows.x64.Release\Tests\Core_Root --base c:\runtime_base\artifacts\bin\coreclr\windows.x64.Checked --diff c:\runtime\artifacts\bin\coreclr\windows.x64.Checked + Generate corelib prejit diffs by specifying explicit baseline and diff compiler directories. + + jit-diff diff --output c:\diffs --base --base_root c:\runtime_base --diff + If run from a dotnet/runtime clone, infer the remaining paths and architecture/build defaults. + + jit-diff diff --base --diff + Same as above, but use the default output directory under artifacts\diffs. + + jit-diff diff --base --diff --pmi + Diff jitted code via PMI instead of prejitting with crossgen. + + jit-diff diff --diff --pmi --assembly test.exe + Diff all jitted methods for a specific assembly. + + jit-diff diff --diff --arch x86 + Force x86 diffs even when x64 defaults are available. + """); + } public static int Main(string[] args) { - var command = new JitDiffRootCommand(args).UseVersion(); + var command = CreateRootCommand(args); return command.Parse(args).Invoke(); } } } - diff --git a/src/jit-format/jit-format.cs b/src/jit-format/jit-format.cs index 4d7ca752..bf508d43 100644 --- a/src/jit-format/jit-format.cs +++ b/src/jit-format/jit-format.cs @@ -2,11 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -/////////////////////////////////////////////////////////////////////////////// -// -// jit-format - -// - using System; using System.Collections.Generic; using System.CommandLine; @@ -36,8 +31,8 @@ public class Config private string _build = null; private string _runtimePath = null; private string _coreclrPath = null; - private IReadOnlyList _filenames = Array.Empty(); - private IReadOnlyList _projects = Array.Empty(); + private IReadOnlyList _filenames = []; + private IReadOnlyList _projects = []; private string _srcDirectory = null; private bool _untidy = false; private bool _noformat = false; diff --git a/src/util/CommandLineHelpers.cs b/src/util/CommandLineHelpers.cs index fd1793e5..d661cb15 100644 --- a/src/util/CommandLineHelpers.cs +++ b/src/util/CommandLineHelpers.cs @@ -2,7 +2,10 @@ // 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.CommandLine; +using System.CommandLine.Help; +using System.CommandLine.Invocation; using System.CommandLine.Parsing; using System.IO; @@ -22,6 +25,48 @@ public static RootCommand UseVersion(this RootCommand command) return command; } + public static RootCommand UseExtendedHelp(this RootCommand command, Action customizer) + { + ConfigureHelp(command, customizer); + return command; + } + + private static void ConfigureHelp(Command command, Action customizer) + { + foreach (Option option in command.Options) + { + if (option is HelpOption helpOption) + { + helpOption.Action = new CustomizedHelpAction(helpOption, customizer); + break; + } + } + + foreach (Command subcommand in command.Subcommands) + { + ConfigureHelp(subcommand, customizer); + } + } + + private sealed class CustomizedHelpAction : SynchronousCommandLineAction + { + private readonly HelpAction _helpAction; + private readonly Action _customizer; + + public CustomizedHelpAction(HelpOption helpOption, Action customizer) + { + _helpAction = (HelpAction)helpOption.Action; + _customizer = customizer; + } + + public override int Invoke(ParseResult parseResult) + { + int result = _helpAction.Invoke(parseResult); + _customizer(parseResult); + return result; + } + } + #nullable enable public static string? GetResolvedPath(ArgumentResult result) => result.Tokens.Count > 0 ? Path.GetFullPath(result.Tokens[0].Value) : null; From 699d906aca6f63307f97df38582520fa685e2068 Mon Sep 17 00:00:00 2001 From: Adeel <3840695+am11@users.noreply.github.com> Date: Fri, 5 Jun 2026 02:02:28 +0300 Subject: [PATCH 3/5] Update Antigen to the same plan --- NuGet.Config | 1 - src/Antigen/Antigen/Antigen.cs | 38 ++++++---------- src/Antigen/Antigen/Antigen.csproj | 14 +----- src/Antigen/Antigen/AntigenRootCommand.cs | 37 ++++++++++++++++ src/Antigen/Antigen/Config/RunOptions.cs | 16 +++++-- .../ExecutionEngine/DynamicAssemblyLoader.cs | 2 +- .../ExecutionEngine/ExecutionEngine.csproj | 5 --- src/Antigen/ExecutionEngine/Program.cs | 19 ++++---- .../Rewriters/Statements/SyntaxRewriter.cs | 4 +- src/Antigen/Trimmer/TestTrimmer.cs | 25 +++++++---- src/Antigen/Trimmer/Trimmer.csproj | 4 +- src/Antigen/Trimmer/TrimmerRootCommand.cs | 43 +++++++++++++++++++ .../Utilities/Compilation/CompileResult.cs | 12 +++--- src/Antigen/Utilities/Compilation/Compiler.cs | 6 +-- src/Antigen/Utilities/Execution/EEDriver.cs | 4 +- src/Antigen/Utilities/Execution/EEProxy.cs | 10 +++-- .../Utilities/Execution/ExecuteResult.cs | 16 +++---- src/Antigen/Utilities/RequestResponse.cs | 6 +-- src/Antigen/Utilities/RslnUtilities.cs | 2 +- src/Antigen/Utilities/TestRunner.cs | 6 +-- src/Antigen/Utilities/Utilities.csproj | 6 +-- src/mutate-test/mutate-test.csproj | 9 ++-- src/util/CommandLineHelpers.cs | 4 +- 23 files changed, 179 insertions(+), 110 deletions(-) create mode 100644 src/Antigen/Antigen/AntigenRootCommand.cs create mode 100644 src/Antigen/Trimmer/TrimmerRootCommand.cs diff --git a/NuGet.Config b/NuGet.Config index 1c5a35f1..3f9f7ab4 100644 --- a/NuGet.Config +++ b/NuGet.Config @@ -3,7 +3,6 @@ - diff --git a/src/Antigen/Antigen/Antigen.cs b/src/Antigen/Antigen/Antigen.cs index e87a8d57..e45bdc72 100644 --- a/src/Antigen/Antigen/Antigen.cs +++ b/src/Antigen/Antigen/Antigen.cs @@ -4,7 +4,8 @@ using System.IO; using System.Threading.Tasks; using Antigen.Config; -using CommandLine; +using System.CommandLine; +using System.CommandLine.Parsing; using Utils; using System.Linq; using System.Runtime.CompilerServices; @@ -38,23 +39,27 @@ class Program static int Main(string[] args) { - return Parser.Default.ParseArguments(args).MapResult(Run, err => 1); + var command = new AntigenRootCommand(args).UseVersion(); + return command.Parse(args).Invoke(); } - private static int Run(CommandLineOptions opts) + internal static int Run(AntigenRootCommand command) { try { + ParseResult result = command.Result; PRNG.Initialize(s_runOptions.Seed); - s_runOptions.CoreRun = opts.CoreRunPath; - s_runOptions.OutputDirectory = opts.IssuesFolder; - if (opts.RunDuration > 0) + s_runOptions.CoreRun = result.GetValue(command.CoreRunPath); + s_runOptions.OutputDirectory = result.GetValue(command.IssuesFolder); + int runDuration = result.GetValue(command.RunDuration); + if (runDuration > 0) { - s_runOptions.RunDuration = opts.RunDuration; + s_runOptions.RunDuration = runDuration; } - if (opts.NumTestCases > 0) + int numTestCases = result.GetValue(command.NumTestCases); + if (numTestCases > 0) { - s_runOptions.NumTestCases = opts.NumTestCases; + s_runOptions.NumTestCases = numTestCases; } if (s_runOptions.RunDuration != -1) @@ -295,19 +300,4 @@ static void RunTest() } } } - - public class CommandLineOptions - { - [Option(shortName: 'c', longName: "CoreRun", Required = true, HelpText = "Full path to CoreRun/CoreRun.exe.")] - public string CoreRunPath { get; set; } - - [Option(shortName: 'o', longName: "IssuesFolder", Required = true, HelpText = "Full path to folder where issues will be copied.")] - public string IssuesFolder { get; set; } - - [Option(shortName: 'n', longName: "NumTestCases", Required = false, HelpText = "Number of test cases to execute. By default, 1000.")] - public int NumTestCases { get; set; } - - [Option(shortName: 'd', longName: "RunDuration", Required = false, HelpText = "Duration in minutes to run. By default until NumTestCases, but if Duration is given, will override the NumTestCases.")] - public int RunDuration { get; set; } - } } diff --git a/src/Antigen/Antigen/Antigen.csproj b/src/Antigen/Antigen/Antigen.csproj index a2aee0a9..c72d3a78 100644 --- a/src/Antigen/Antigen/Antigen.csproj +++ b/src/Antigen/Antigen/Antigen.csproj @@ -2,30 +2,20 @@ Exe - net9.0 Antigen ab71806a-3bd8-4fb1-b0e2-9450aec41a9f True - - - - + + - - false - - https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet8/nuget/v3/index.json - - - diff --git a/src/Antigen/Antigen/AntigenRootCommand.cs b/src/Antigen/Antigen/AntigenRootCommand.cs new file mode 100644 index 00000000..74b0b285 --- /dev/null +++ b/src/Antigen/Antigen/AntigenRootCommand.cs @@ -0,0 +1,37 @@ +// 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.CommandLine; +using System.CommandLine.Parsing; + +namespace Antigen +{ + internal sealed class AntigenRootCommand : RootCommand + { + public Option CoreRunPath { get; } = + new("--CoreRun", "-c") { Description = "Full path to CoreRun/CoreRun.exe.", Required = true }; + public Option IssuesFolder { get; } = + new("--IssuesFolder", "-o") { Description = "Full path to folder where issues will be copied.", Required = true }; + public Option NumTestCases { get; } = + new("--NumTestCases", "-n") { Description = "Number of test cases to execute. By default, 1000." }; + public Option RunDuration { get; } = + new("--RunDuration", "-d") { Description = "Duration in minutes to run. By default until NumTestCases, but if Duration is given, will override the NumTestCases." }; + + public ParseResult Result { get; private set; } + + public AntigenRootCommand(string[] args) : base("Antigen JIT fuzzer") + { + Options.Add(CoreRunPath); + Options.Add(IssuesFolder); + Options.Add(NumTestCases); + Options.Add(RunDuration); + + SetAction(result => + { + Result = result; + return Program.Run(this); + }); + } + } +} diff --git a/src/Antigen/Antigen/Config/RunOptions.cs b/src/Antigen/Antigen/Config/RunOptions.cs index 537bad2a..298c424d 100644 --- a/src/Antigen/Antigen/Config/RunOptions.cs +++ b/src/Antigen/Antigen/Config/RunOptions.cs @@ -4,7 +4,8 @@ using System.IO; using System.Reflection; using System.Runtime.Intrinsics; -using Newtonsoft.Json; +using System.Text.Json; +using System.Text.Json.Serialization; namespace Antigen.Config { @@ -25,7 +26,7 @@ public class RunOptions // Percent of time to execute baseline public double ExecuteBaseline; - [NonSerialized()] + [JsonIgnore] public string CoreRun = null; public List Configs; @@ -40,7 +41,16 @@ internal static RunOptions Initialize() string antiGenConfig = Path.Combine(currentDirectory, "Config", "antigen.json"); Debug.Assert(File.Exists(antiGenConfig)); - var runOption = JsonConvert.DeserializeObject(File.ReadAllText(antiGenConfig)); + JsonSerializerOptions options = new() + { + IncludeFields = true, + PropertyNameCaseInsensitive = true, + ReadCommentHandling = JsonCommentHandling.Skip, + AllowTrailingCommas = true, + NumberHandling = JsonNumberHandling.AllowReadingFromString, + }; + + var runOption = JsonSerializer.Deserialize(File.ReadAllText(antiGenConfig), options); EnvVarOptions.Initialize(runOption.BaselineEnvVars, runOption.TestEnvVars); return runOption; diff --git a/src/Antigen/ExecutionEngine/DynamicAssemblyLoader.cs b/src/Antigen/ExecutionEngine/DynamicAssemblyLoader.cs index 739ae469..f472bc51 100644 --- a/src/Antigen/ExecutionEngine/DynamicAssemblyLoader.cs +++ b/src/Antigen/ExecutionEngine/DynamicAssemblyLoader.cs @@ -21,7 +21,7 @@ public Assembly LoadFromBytes(byte[] assemblyBytes) return LoadFromStream(new MemoryStream(assemblyBytes)); } - protected override Assembly Load(AssemblyName assemblyName) + protected override Assembly? Load(AssemblyName assemblyName) { // Default implementation does nothing. return null; diff --git a/src/Antigen/ExecutionEngine/ExecutionEngine.csproj b/src/Antigen/ExecutionEngine/ExecutionEngine.csproj index 6a3b4868..a76f3d0a 100644 --- a/src/Antigen/ExecutionEngine/ExecutionEngine.csproj +++ b/src/Antigen/ExecutionEngine/ExecutionEngine.csproj @@ -2,15 +2,10 @@ Exe - net9.0 enable enable - - - - diff --git a/src/Antigen/ExecutionEngine/Program.cs b/src/Antigen/ExecutionEngine/Program.cs index 2afb3fd3..76e15dc9 100644 --- a/src/Antigen/ExecutionEngine/Program.cs +++ b/src/Antigen/ExecutionEngine/Program.cs @@ -8,8 +8,7 @@ using System.Reflection.Metadata; using System.Runtime.ExceptionServices; using System.Threading; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; +using System.Text.Json; namespace ExecutionEngine { @@ -38,7 +37,7 @@ static async Task Main(string[] args) { continue; } - Request? request = JsonConvert.DeserializeObject(lines); + Request? request = JsonSerializer.Deserialize(lines); if (request == null) { continue; @@ -61,7 +60,7 @@ static async Task Main(string[] args) response.IsJitAssert = true; } - var json = JsonConvert.SerializeObject(response); + var json = JsonSerializer.Serialize(response); Console.WriteLine(json); Console.Out.Flush(); Console.WriteLine("Done"); @@ -86,13 +85,13 @@ private static RunResult Run(byte[] assemblyBytes) { int hashCode; var assembly = s_loader.LoadFromBytes(assemblyBytes); - var methodInfo = assembly.GetType("TestClass").GetMethod("Main"); - var methodExec = methodInfo.CreateDelegate>(); + var methodInfo = assembly.GetType("TestClass")!.GetMethod("Main"); + var methodExec = methodInfo!.CreateDelegate>(); // Adopted from Jakob's Fuzzlyn int threadID = Environment.CurrentManagedThreadId; - List exceptions = null; - void FirstChanceExceptionHandler(object sender, FirstChanceExceptionEventArgs args) + List? exceptions = null; + void FirstChanceExceptionHandler(object? sender, FirstChanceExceptionEventArgs args) { if (Environment.CurrentManagedThreadId == threadID) { @@ -104,7 +103,7 @@ void FirstChanceExceptionHandler(object sender, FirstChanceExceptionEventArgs ar try { - hashCode = methodExec(null); + hashCode = methodExec(null!); } catch { @@ -123,7 +122,7 @@ void FirstChanceExceptionHandler(object sender, FirstChanceExceptionEventArgs ar // } // We are interested in the JIT assert that was hit, and not the OverflowException // thrown because value = 1 did not get to run. - Exception ex = exceptions[0]; + Exception ex = exceptions![0]; if (ex is TypeInitializationException && ex.InnerException != null) { diff --git a/src/Antigen/Trimmer/Rewriters/Statements/SyntaxRewriter.cs b/src/Antigen/Trimmer/Rewriters/Statements/SyntaxRewriter.cs index b9dcd76e..2e5fe0b5 100644 --- a/src/Antigen/Trimmer/Rewriters/Statements/SyntaxRewriter.cs +++ b/src/Antigen/Trimmer/Rewriters/Statements/SyntaxRewriter.cs @@ -44,8 +44,8 @@ public void UpdateId(int newId) public override SyntaxTrivia VisitTrivia(SyntaxTrivia trivia) { - if (trivia.Kind() == SyntaxKind.SingleLineCommentTrivia || - trivia.Kind() == SyntaxKind.MultiLineCommentTrivia) + if (trivia.IsKind(SyntaxKind.SingleLineCommentTrivia) || + trivia.IsKind(SyntaxKind.MultiLineCommentTrivia)) { return default(SyntaxTrivia); } diff --git a/src/Antigen/Trimmer/TestTrimmer.cs b/src/Antigen/Trimmer/TestTrimmer.cs index ee3db30b..2d863409 100644 --- a/src/Antigen/Trimmer/TestTrimmer.cs +++ b/src/Antigen/Trimmer/TestTrimmer.cs @@ -7,11 +7,12 @@ using Antigen.Trimmer.Rewriters; using Antigen.Trimmer.Rewriters.Expressions; using Antigen.Trimmer.Rewriters.Statements; -using CommandLine; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using System; using System.Collections.Generic; +using System.CommandLine; +using System.CommandLine.Parsing; using System.Diagnostics; using System.IO; using System.Linq; @@ -52,11 +53,23 @@ public class TestTrimmer static int Main(string[] args) { - return Parser.Default.ParseArguments(args).MapResult(Run, err => 1); + var command = new TrimmerRootCommand(args).UseVersion(); + return command.Parse(args).Invoke(); } - private static int Run(CommandLineOptions opts) + internal static int Run(TrimmerRootCommand command) { + ParseResult result = command.Result; + CommandLineOptions opts = new() + { + CoreRunPath = result.GetValue(command.CoreRunPath), + ParentPid = result.GetValue(command.ParentPid), + IssuesFolder = result.GetValue(command.IssuesFolder), + ReproFile = result.GetValue(command.ReproFile), + AltJitName = result.GetValue(command.AltJitName), + AltJitMethodName = result.GetValue(command.AltJitMethodName), + }; + int.TryParse(opts.ParentPid, out s_parentProcessId); Task monitorTask = Task.Run(() => MonitorParentProcess()); @@ -615,22 +628,16 @@ private static void MonitorParentProcess() public class CommandLineOptions { - [Option(shortName: 'c', longName: "CoreRun", Required = true, HelpText = "Path to CoreRun/CoreRun.exe.")] public string CoreRunPath { get; set; } - [Option(shortName: 'p', longName: "ParentPid", Required = false, HelpText = "Antigen process id")] public string ParentPid { get; set; } - [Option(shortName: 'o', longName: "IssuesFolder", Required = false, HelpText = "Path to folder where trimmed issue will be copied.")] public string IssuesFolder { get; set; } - [Option(shortName: 'f', longName: "ReproFile", Required = false, HelpText = "Full path of the repro file.")] public string ReproFile { get; set; } - [Option(shortName: 'j', longName: "AltJitName", Required = false, HelpText = "Name of altjit. By default, current OS/arch.")] public string AltJitName { get; set; } - [Option(shortName: 'm', longName: "AltJitMethodName", Required = false, HelpText = "Name of method for altjit. By default, current OS/arch.")] public string AltJitMethodName { get; set; } } } diff --git a/src/Antigen/Trimmer/Trimmer.csproj b/src/Antigen/Trimmer/Trimmer.csproj index 4c6a9edd..05cd19b4 100644 --- a/src/Antigen/Trimmer/Trimmer.csproj +++ b/src/Antigen/Trimmer/Trimmer.csproj @@ -2,13 +2,11 @@ Exe - net9.0 True - - + diff --git a/src/Antigen/Trimmer/TrimmerRootCommand.cs b/src/Antigen/Trimmer/TrimmerRootCommand.cs new file mode 100644 index 00000000..3508cd1f --- /dev/null +++ b/src/Antigen/Trimmer/TrimmerRootCommand.cs @@ -0,0 +1,43 @@ +// 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.CommandLine; +using System.CommandLine.Parsing; + +namespace Trimmer +{ + internal sealed class TrimmerRootCommand : RootCommand + { + public Option CoreRunPath { get; } = + new("--CoreRun", "-c") { Description = "Path to CoreRun/CoreRun.exe.", Required = true }; + public Option ParentPid { get; } = + new("--ParentPid", "-p") { Description = "Antigen process id" }; + public Option IssuesFolder { get; } = + new("--IssuesFolder", "-o") { Description = "Path to folder where trimmed issue will be copied." }; + public Option ReproFile { get; } = + new("--ReproFile", "-f") { Description = "Full path of the repro file." }; + public Option AltJitName { get; } = + new("--AltJitName", "-j") { Description = "Name of altjit. By default, current OS/arch." }; + public Option AltJitMethodName { get; } = + new("--AltJitMethodName", "-m") { Description = "Name of method for altjit. By default, current OS/arch." }; + + public ParseResult Result { get; private set; } + + public TrimmerRootCommand(string[] args) : base("Antigen test case trimmer") + { + Options.Add(CoreRunPath); + Options.Add(ParentPid); + Options.Add(IssuesFolder); + Options.Add(ReproFile); + Options.Add(AltJitName); + Options.Add(AltJitMethodName); + + SetAction(result => + { + Result = result; + return TestTrimmer.Run(this); + }); + } + } +} diff --git a/src/Antigen/Utilities/Compilation/CompileResult.cs b/src/Antigen/Utilities/Compilation/CompileResult.cs index cc5c2248..c0916160 100644 --- a/src/Antigen/Utilities/Compilation/CompileResult.cs +++ b/src/Antigen/Utilities/Compilation/CompileResult.cs @@ -19,7 +19,7 @@ public CompileResult(IEnumerable diagnostics) CompileWarnings = diagnostics.Where(diag => diag.Severity == DiagnosticSeverity.Warning); } - public CompileResult(string assemblyName, string assemblyFullPath, byte[]? debugMs, byte[]? releaseMs) + public CompileResult(string assemblyName, string? assemblyFullPath, byte[]? debugMs, byte[]? releaseMs) { AssemblyName = assemblyName; AssemblyFullPath = assemblyFullPath; @@ -32,11 +32,11 @@ public CompileResult(Exception roslynException) RoslynException = roslynException; } - public string AssemblyName { get; } - public Exception RoslynException { get; } - public IEnumerable CompileErrors { get; } - public IEnumerable CompileWarnings { get; } - public string AssemblyFullPath { get; } + public string? AssemblyName { get; } + public Exception? RoslynException { get; } + public IEnumerable? CompileErrors { get; } + public IEnumerable? CompileWarnings { get; } + public string? AssemblyFullPath { get; } public byte[]? DebugAssembly { get; } public byte[]? ReleaseAssembly { get; } } diff --git a/src/Antigen/Utilities/Compilation/Compiler.cs b/src/Antigen/Utilities/Compilation/Compiler.cs index 645e310e..ded1ce22 100644 --- a/src/Antigen/Utilities/Compilation/Compiler.cs +++ b/src/Antigen/Utilities/Compilation/Compiler.cs @@ -39,8 +39,8 @@ public class Compiler private static readonly MetadataReference[] s_references = { MetadataReference.CreateFromFile(s_corelibPath), - MetadataReference.CreateFromFile(Path.Combine(Path.GetDirectoryName(s_corelibPath), "System.Console.dll")), - MetadataReference.CreateFromFile(Path.Combine(Path.GetDirectoryName(s_corelibPath), "System.Runtime.dll")), + MetadataReference.CreateFromFile(Path.Combine(Path.GetDirectoryName(s_corelibPath)!, "System.Console.dll")), + MetadataReference.CreateFromFile(Path.Combine(Path.GetDirectoryName(s_corelibPath)!, "System.Runtime.dll")), MetadataReference.CreateFromFile(typeof(SyntaxTree).Assembly.Location), MetadataReference.CreateFromFile(typeof(CSharpSyntaxTree).Assembly.Location), }; @@ -63,7 +63,7 @@ public CompileResult Compile(SyntaxTree programTree, string assemblyName) return new CompileResult(assemblyName, null, debugBytes, releaseBytes); } - private byte[] CompileAndGetBytes(SyntaxTree programTree, string assemblyName, CSharpCompilationOptions options) + private byte[]? CompileAndGetBytes(SyntaxTree programTree, string assemblyName, CSharpCompilationOptions options) { string tag = options.OptimizationLevel == OptimizationLevel.Debug ? "Debug" : "Release"; var cc = CSharpCompilation.Create($"{assemblyName}-{tag}.exe", new SyntaxTree[] { programTree }, s_references, options); diff --git a/src/Antigen/Utilities/Execution/EEDriver.cs b/src/Antigen/Utilities/Execution/EEDriver.cs index 155d4988..4a2fb57e 100644 --- a/src/Antigen/Utilities/Execution/EEDriver.cs +++ b/src/Antigen/Utilities/Execution/EEDriver.cs @@ -97,9 +97,9 @@ private void Return(EEProxy proxy) /// /// /// - internal Response Execute(Request request) + internal Response? Execute(Request request) { - EEProxy proxy = null; + EEProxy? proxy = null; try { proxy = Get(); diff --git a/src/Antigen/Utilities/Execution/EEProxy.cs b/src/Antigen/Utilities/Execution/EEProxy.cs index c9f9fced..5083e358 100644 --- a/src/Antigen/Utilities/Execution/EEProxy.cs +++ b/src/Antigen/Utilities/Execution/EEProxy.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Runtime.InteropServices; @@ -14,7 +15,7 @@ using System.Threading.Tasks; //using Antigen.Config; using ExecutionEngine; -using Newtonsoft.Json; +using System.Text.Json; using Utils; namespace Antigen.Execution @@ -54,6 +55,7 @@ private EEProxy(string host, string executionEngine, Dictionary _testCaseExecutionCount = 0; } + [MemberNotNull(nameof(_envVars), nameof(_envVarsList))] private void SetEnvironmentVariables(ProcessStartInfo startInfo, Dictionary envVars) { envVars["DOTNET_TieredCompilation"] = "0"; @@ -96,7 +98,7 @@ public static EEProxy GetInstance(string host, string executionEngine, Dictionar public Response Execute(Request request) { - _process.StandardInput.WriteLine(JsonConvert.SerializeObject(request)); + _process.StandardInput.WriteLine(JsonSerializer.Serialize(request)); bool killed = false; using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(TimeoutInSeconds)); @@ -104,7 +106,7 @@ public Response Execute(Request request) StringBuilder responseReader = new StringBuilder(); while (true) { - string line = _process.StandardOutput.ReadLine(); + string? line = _process.StandardOutput.ReadLine(); if ((line == null) || (line == "Done")) { break; @@ -124,7 +126,7 @@ public Response Execute(Request request) try { - return JsonConvert.DeserializeObject(responseReader.ToString()); + return JsonSerializer.Deserialize(responseReader.ToString()) ?? new() { HasCrashed = true }; } catch (JsonException) { diff --git a/src/Antigen/Utilities/Execution/ExecuteResult.cs b/src/Antigen/Utilities/Execution/ExecuteResult.cs index 7655a785..174ad69a 100644 --- a/src/Antigen/Utilities/Execution/ExecuteResult.cs +++ b/src/Antigen/Utilities/Execution/ExecuteResult.cs @@ -23,18 +23,18 @@ public enum RunOutcome public struct ExecuteResult { - public string OtherErrorMessage { get; private set; } - public string AssertionMessage { get; private set; } - public string ShortAssertionText { get; private set; } + public string? OtherErrorMessage { get; private set; } + public string? AssertionMessage { get; private set; } + public string? ShortAssertionText { get; private set; } public RunOutcome Result { get; private set; } - public IReadOnlyList> EnvVars { get; private set; } + public IReadOnlyList>? EnvVars { get; private set; } public static ExecuteResult GetSuccessResult() { return new ExecuteResult(RunOutcome.Success, null); } - public static ExecuteResult GetOtherErrorResult(string errorMessage, IReadOnlyList> envVars) + public static ExecuteResult GetOtherErrorResult(string? errorMessage, IReadOnlyList>? envVars) { return new ExecuteResult(RunOutcome.OtherError, null, errorMessage, envVars); } @@ -44,14 +44,14 @@ public static ExecuteResult GetTimeoutResult() return new ExecuteResult(RunOutcome.Timeout, null); } - public static ExecuteResult GetAssertionFailureResult(string assertionMessage, IReadOnlyList> envVars) + public static ExecuteResult GetAssertionFailureResult(string assertionMessage, IReadOnlyList>? envVars) { var result = new ExecuteResult(RunOutcome.AssertionFailure, assertionMessage, null, envVars); result.ShortAssertionText = RslnUtilities.ParseAssertionError(assertionMessage); return result; } - public static ExecuteResult GetOutputMismatchResult(string outputDiff, IReadOnlyList> envVars) + public static ExecuteResult GetOutputMismatchResult(string outputDiff, IReadOnlyList>? envVars) { return new ExecuteResult(RunOutcome.OutputMismatch, null, outputDiff, envVars); } @@ -61,7 +61,7 @@ public static ExecuteResult GetCompilationError() return new ExecuteResult(RunOutcome.CompilationError, null); } - private ExecuteResult(RunOutcome result, string assertionMessage, string errorMessage = null, IReadOnlyList> envVars = null) + private ExecuteResult(RunOutcome result, string? assertionMessage, string? errorMessage = null, IReadOnlyList>? envVars = null) { Result = result; AssertionMessage = assertionMessage; diff --git a/src/Antigen/Utilities/RequestResponse.cs b/src/Antigen/Utilities/RequestResponse.cs index 598bb6be..045f13d6 100644 --- a/src/Antigen/Utilities/RequestResponse.cs +++ b/src/Antigen/Utilities/RequestResponse.cs @@ -13,8 +13,8 @@ namespace ExecutionEngine { public class Request { - public byte[] Debug { get; set; } - public byte[] Release { get; set; } + public byte[] Debug { get; set; } = []; + public byte[] Release { get; set; } = []; } public class Response @@ -26,6 +26,6 @@ public class Response public bool IsTimeout { get; set; } public bool IsJitAssert { get; set; } public bool HasCrashed { get; set; } - public IReadOnlyList> EnvironmentVariables { get; set; } + public IReadOnlyList>? EnvironmentVariables { get; set; } } } diff --git a/src/Antigen/Utilities/RslnUtilities.cs b/src/Antigen/Utilities/RslnUtilities.cs index bc4be7a8..5ce49f28 100644 --- a/src/Antigen/Utilities/RslnUtilities.cs +++ b/src/Antigen/Utilities/RslnUtilities.cs @@ -73,7 +73,7 @@ private static void FindTreeDiff(SyntaxNode expected, SyntaxNode actual) /// /// /// - public static string ParseAssertionError(string output) + public static string? ParseAssertionError(string output) { if (string.IsNullOrEmpty(output)) { diff --git a/src/Antigen/Utilities/TestRunner.cs b/src/Antigen/Utilities/TestRunner.cs index ab611f41..495dc7f1 100644 --- a/src/Antigen/Utilities/TestRunner.cs +++ b/src/Antigen/Utilities/TestRunner.cs @@ -35,7 +35,7 @@ public enum TestResult public class TestRunner { - private static TestRunner _testRunner; + private static TestRunner? _testRunner; private readonly string _coreRun; private readonly EEDriver _driver; @@ -43,8 +43,8 @@ public class TestRunner private static readonly MetadataReference[] s_references = { MetadataReference.CreateFromFile(s_corelibPath), - MetadataReference.CreateFromFile(Path.Combine(Path.GetDirectoryName(s_corelibPath), "System.Console.dll")), - MetadataReference.CreateFromFile(Path.Combine(Path.GetDirectoryName(s_corelibPath), "System.Runtime.dll")), + MetadataReference.CreateFromFile(Path.Combine(Path.GetDirectoryName(s_corelibPath)!, "System.Console.dll")), + MetadataReference.CreateFromFile(Path.Combine(Path.GetDirectoryName(s_corelibPath)!, "System.Runtime.dll")), MetadataReference.CreateFromFile(typeof(SyntaxTree).Assembly.Location), MetadataReference.CreateFromFile(typeof(CSharpSyntaxTree).Assembly.Location), }; diff --git a/src/Antigen/Utilities/Utilities.csproj b/src/Antigen/Utilities/Utilities.csproj index 74528279..7de5e0e0 100644 --- a/src/Antigen/Utilities/Utilities.csproj +++ b/src/Antigen/Utilities/Utilities.csproj @@ -1,16 +1,12 @@  - net9.0 enable enable - - - + - diff --git a/src/mutate-test/mutate-test.csproj b/src/mutate-test/mutate-test.csproj index c09eb2da..f1c92093 100644 --- a/src/mutate-test/mutate-test.csproj +++ b/src/mutate-test/mutate-test.csproj @@ -7,9 +7,12 @@ - - - + + + + + diff --git a/src/util/CommandLineHelpers.cs b/src/util/CommandLineHelpers.cs index d661cb15..0384a3da 100644 --- a/src/util/CommandLineHelpers.cs +++ b/src/util/CommandLineHelpers.cs @@ -9,7 +9,7 @@ using System.CommandLine.Parsing; using System.IO; -public static class Helpers +internal static class Helpers { public static RootCommand UseVersion(this RootCommand command) { @@ -55,7 +55,7 @@ private sealed class CustomizedHelpAction : SynchronousCommandLineAction public CustomizedHelpAction(HelpOption helpOption, Action customizer) { - _helpAction = (HelpAction)helpOption.Action; + _helpAction = (HelpAction)helpOption.Action!; _customizer = customizer; } From 468c938f47c320f24b71a9ae97be797c0cdb957f Mon Sep 17 00:00:00 2001 From: Adeel <3840695+am11@users.noreply.github.com> Date: Fri, 5 Jun 2026 02:06:26 +0300 Subject: [PATCH 4/5] Add Antigen to build.sh --- build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.sh b/build.sh index f5813c2b..e39fa05e 100755 --- a/build.sh +++ b/build.sh @@ -48,7 +48,7 @@ while getopts "hpb:" opt; do done # declare the array of projects -declare -a projects=(jit-dasm jit-diff jit-analyze jit-tp-analyze jit-format pmi jit-dasm-pmi jit-decisions-analyze performance-explorer instructions-retired-explorer) +declare -a projects=(Antigen jit-dasm jit-diff jit-analyze jit-tp-analyze jit-format pmi jit-dasm-pmi jit-decisions-analyze performance-explorer instructions-retired-explorer) # for each project either build or publish for proj in "${projects[@]}" From 0ebe2fbcb0b5a4e11cbe0c3a4c1c471fe7240cd7 Mon Sep 17 00:00:00 2001 From: Adeel <3840695+am11@users.noreply.github.com> Date: Fri, 5 Jun 2026 04:53:00 +0300 Subject: [PATCH 5/5] Update scripts --- build.cmd | 5 ++++- build.sh | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/build.cmd b/build.cmd index 02badd00..5abe72c3 100644 --- a/build.cmd +++ b/build.cmd @@ -44,7 +44,7 @@ REM Do as many builds as possible; don't stop on first failure (if any). set __ExitCode=0 REM Declare the list of projects -set projects=jit-diff jit-dasm jit-analyze jit-tp-analyze jit-format pmi jit-dasm-pmi jit-decisions-analyze performance-explorer instructions-retired-explorer +set projects=Antigen jit-diff jit-dasm jit-analyze jit-tp-analyze jit-format pmi jit-dasm-pmi jit-decisions-analyze performance-explorer instructions-retired-explorer REM Build each project for %%p in (%projects%) do ( @@ -52,6 +52,9 @@ for %%p in (%projects%) do ( REM Publish src/pmi project without single-file, so it can be executed with a custom build of the runtime/JIT if "%%p"=="pmi" ( dotnet publish -c %buildType% -o %appInstallDir% .\src\%%p + ) else if "%%p"=="Antigen" ( + REM Publish Antigen without single-file; it resolves corelib/Roslyn reference assemblies by path for compilation + dotnet publish -c %buildType% -o %appInstallDir% .\src\%%p ) else ( dotnet publish -c %buildType% -o %appInstallDir% .\src\%%p --self-contained -r:%rid% -p:PublishSingleFile=true ) diff --git a/build.sh b/build.sh index e39fa05e..19d070d6 100755 --- a/build.sh +++ b/build.sh @@ -57,6 +57,8 @@ do case "$proj" in # Publish src/pmi project without single-file, so it can be executed with a custom build of the runtime/JIT pmi) dotnet publish -c "$buildType" -o "$appInstallDir" ./src/"$proj" ;; + # Publish Antigen without single-file; it locates reference assemblies (corelib, Roslyn) by path for Roslyn compilation + Antigen) dotnet publish -c "$buildType" -o "$appInstallDir" ./src/"$proj" ;; *) dotnet publish -c "$buildType" -o "$appInstallDir" ./src/"$proj" --self-contained -r $rid -p:PublishSingleFile=true ;; esac exit_code=$?