From 9c2abfc696561f796909e84a8b37f5ebef25c8bb Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Fri, 20 Feb 2026 14:32:26 +0100 Subject: [PATCH 1/4] Use WASM sdk for coreclr and allow running with nodeJS. --- .../ConsoleArguments/CommandLineOptions.cs | 2 +- .../Environments/Runtimes/WasmRuntime.cs | 2 +- src/BenchmarkDotNet/Templates/WasmCsProj.txt | 2 +- .../Templates/benchmark-main.mjs | 5 +++- .../Toolchains/MonoWasm/WasmGenerator.cs | 23 ++++++++++++++++--- 5 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/BenchmarkDotNet/ConsoleArguments/CommandLineOptions.cs b/src/BenchmarkDotNet/ConsoleArguments/CommandLineOptions.cs index 259b2c7bdc..90d8187c96 100644 --- a/src/BenchmarkDotNet/ConsoleArguments/CommandLineOptions.cs +++ b/src/BenchmarkDotNet/ConsoleArguments/CommandLineOptions.cs @@ -204,7 +204,7 @@ public bool UseDisassemblyDiagnoser [Option("wasmEngine", Required = false, HelpText = "Full path to a java script engine used to run the benchmarks, used by Wasm toolchain.")] public FileInfo? WasmJavascriptEngine { get; set; } - [Option("wasmArgs", Required = false, Default = "--expose_wasm", HelpText = "Arguments for the javascript engine used by Wasm toolchain.")] + [Option("wasmArgs", Required = false, Default = "", HelpText = "Arguments for the javascript engine used by Wasm toolchain.")] public string? WasmJavaScriptEngineArguments { get; set; } [Option("customRuntimePack", Required = false, HelpText = "Path to a custom runtime pack. Only used for wasm/MonoAotLLVM currently.")] diff --git a/src/BenchmarkDotNet/Environments/Runtimes/WasmRuntime.cs b/src/BenchmarkDotNet/Environments/Runtimes/WasmRuntime.cs index 0c148c0352..6c95f7fbe9 100644 --- a/src/BenchmarkDotNet/Environments/Runtimes/WasmRuntime.cs +++ b/src/BenchmarkDotNet/Environments/Runtimes/WasmRuntime.cs @@ -30,7 +30,7 @@ public class WasmRuntime : Runtime, IEquatable /// creates new instance of WasmRuntime /// /// Full path to a java script engine used to run the benchmarks. "v8" by default - /// Arguments for the javascript engine. "--expose_wasm" by default + /// Arguments for the javascript engine. Empty by default. /// moniker, default: "net5.0" /// default: "Wasm" /// Specifies whether AOT or Interpreter (default) project should be generated. diff --git a/src/BenchmarkDotNet/Templates/WasmCsProj.txt b/src/BenchmarkDotNet/Templates/WasmCsProj.txt index bf35251428..3daf85e070 100644 --- a/src/BenchmarkDotNet/Templates/WasmCsProj.txt +++ b/src/BenchmarkDotNet/Templates/WasmCsProj.txt @@ -8,7 +8,7 @@ - +$CORECLR_OVERRIDES$ Exe Release diff --git a/src/BenchmarkDotNet/Templates/benchmark-main.mjs b/src/BenchmarkDotNet/Templates/benchmark-main.mjs index c9f705d547..cd11444db6 100644 --- a/src/BenchmarkDotNet/Templates/benchmark-main.mjs +++ b/src/BenchmarkDotNet/Templates/benchmark-main.mjs @@ -3,7 +3,10 @@ import { dotnet } from './_framework/dotnet.js' +// Get command line arguments: Node.js uses process.argv, v8 uses arguments/scriptArgs +const args = typeof process !== 'undefined' ? process.argv.slice(2) : (typeof arguments !== 'undefined' ? [...arguments] : (typeof scriptArgs !== 'undefined' ? scriptArgs : [])); + await dotnet .withDiagnosticTracing(false) - .withApplicationArguments(...arguments) + .withApplicationArguments(...args) .run() diff --git a/src/BenchmarkDotNet/Toolchains/MonoWasm/WasmGenerator.cs b/src/BenchmarkDotNet/Toolchains/MonoWasm/WasmGenerator.cs index b42aef9e4b..7823e42888 100644 --- a/src/BenchmarkDotNet/Toolchains/MonoWasm/WasmGenerator.cs +++ b/src/BenchmarkDotNet/Toolchains/MonoWasm/WasmGenerator.cs @@ -46,8 +46,22 @@ protected void GenerateProjectFile(BuildPartition buildPartition, ArtifactsPaths var xmlDoc = new XmlDocument(); xmlDoc.Load(projectFile.FullName); var (customProperties, _) = GetSettingsThatNeedToBeCopied(xmlDoc, projectFile); - // Microsoft.NET.Sdk.WebAssembly auto-defaults UseMonoRuntime=true. - string sdkName = runtime.IsMonoRuntime ? "Microsoft.NET.Sdk.WebAssembly" : "Microsoft.NET.Sdk"; + string sdkName = "Microsoft.NET.Sdk.WebAssembly"; + + // For CoreCLR WASM: + // - UseMonoRuntime=false: resolves CoreCLR runtime pack instead of Mono + // - WasmBuildNative=false: avoids requiring wasm-tools workload + // - WasmEnableWebcil=false: CoreCLR doesn't support webcil format + string coreclrOverrides = runtime.IsMonoRuntime + ? string.Empty + : @" + + + false + false + false + +"; string content = new StringBuilder(ResourceHelper.LoadTemplate("WasmCsProj.txt")) .Replace("$PLATFORM$", buildPartition.Platform.ToConfig()) @@ -60,14 +74,17 @@ protected void GenerateProjectFile(BuildPartition buildPartition, ArtifactsPaths .Replace("$SDKNAME$", sdkName) .Replace("$WASMDATADIR$", runtime.WasmDataDir) .Replace("$TARGET$", CustomRuntimePack.IsNotBlank() ? "PublishWithCustomRuntimePack" : "Publish") + .Replace("$CORECLR_OVERRIDES$", coreclrOverrides) .ToString(); File.WriteAllText(artifactsPaths.ProjectFilePath, content); // Place benchmark-main.mjs in wwwroot/ next to the generated csproj. + // Use CoreCLR-specific template that imports from parent directory (no _framework/) string projectWwwroot = Path.Combine(Path.GetDirectoryName(artifactsPaths.ProjectFilePath)!, "wwwroot"); Directory.CreateDirectory(projectWwwroot); - File.WriteAllText(Path.Combine(projectWwwroot, MainJS), ResourceHelper.LoadTemplate(MainJS)); + string templateName = runtime.IsMonoRuntime ? MainJS : "benchmark-main-coreclr.mjs"; + File.WriteAllText(Path.Combine(projectWwwroot, MainJS), ResourceHelper.LoadTemplate(templateName)); GatherReferences(buildPartition, artifactsPaths, logger); } From fd47555a9e24c46206e14ab6b934e7f5c07024f5 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Fri, 20 Feb 2026 14:41:36 +0100 Subject: [PATCH 2/4] Cleanup. --- src/BenchmarkDotNet/Toolchains/MonoWasm/WasmGenerator.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/BenchmarkDotNet/Toolchains/MonoWasm/WasmGenerator.cs b/src/BenchmarkDotNet/Toolchains/MonoWasm/WasmGenerator.cs index 7823e42888..9bd1835fe6 100644 --- a/src/BenchmarkDotNet/Toolchains/MonoWasm/WasmGenerator.cs +++ b/src/BenchmarkDotNet/Toolchains/MonoWasm/WasmGenerator.cs @@ -80,11 +80,9 @@ protected void GenerateProjectFile(BuildPartition buildPartition, ArtifactsPaths File.WriteAllText(artifactsPaths.ProjectFilePath, content); // Place benchmark-main.mjs in wwwroot/ next to the generated csproj. - // Use CoreCLR-specific template that imports from parent directory (no _framework/) string projectWwwroot = Path.Combine(Path.GetDirectoryName(artifactsPaths.ProjectFilePath)!, "wwwroot"); Directory.CreateDirectory(projectWwwroot); - string templateName = runtime.IsMonoRuntime ? MainJS : "benchmark-main-coreclr.mjs"; - File.WriteAllText(Path.Combine(projectWwwroot, MainJS), ResourceHelper.LoadTemplate(templateName)); + File.WriteAllText(Path.Combine(projectWwwroot, MainJS), ResourceHelper.LoadTemplate(MainJS)); GatherReferences(buildPartition, artifactsPaths, logger); } From 12e3cb22512e99720e12f50198848d0cb60d1820 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Fri, 20 Feb 2026 16:16:11 +0100 Subject: [PATCH 3/4] Revert transition to nodeJS - v8 newer than 10.8 works fine. --- src/BenchmarkDotNet/ConsoleArguments/CommandLineOptions.cs | 2 +- src/BenchmarkDotNet/Environments/Runtimes/WasmRuntime.cs | 2 +- src/BenchmarkDotNet/Templates/benchmark-main.mjs | 5 +---- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/BenchmarkDotNet/ConsoleArguments/CommandLineOptions.cs b/src/BenchmarkDotNet/ConsoleArguments/CommandLineOptions.cs index 90d8187c96..259b2c7bdc 100644 --- a/src/BenchmarkDotNet/ConsoleArguments/CommandLineOptions.cs +++ b/src/BenchmarkDotNet/ConsoleArguments/CommandLineOptions.cs @@ -204,7 +204,7 @@ public bool UseDisassemblyDiagnoser [Option("wasmEngine", Required = false, HelpText = "Full path to a java script engine used to run the benchmarks, used by Wasm toolchain.")] public FileInfo? WasmJavascriptEngine { get; set; } - [Option("wasmArgs", Required = false, Default = "", HelpText = "Arguments for the javascript engine used by Wasm toolchain.")] + [Option("wasmArgs", Required = false, Default = "--expose_wasm", HelpText = "Arguments for the javascript engine used by Wasm toolchain.")] public string? WasmJavaScriptEngineArguments { get; set; } [Option("customRuntimePack", Required = false, HelpText = "Path to a custom runtime pack. Only used for wasm/MonoAotLLVM currently.")] diff --git a/src/BenchmarkDotNet/Environments/Runtimes/WasmRuntime.cs b/src/BenchmarkDotNet/Environments/Runtimes/WasmRuntime.cs index 6c95f7fbe9..0c148c0352 100644 --- a/src/BenchmarkDotNet/Environments/Runtimes/WasmRuntime.cs +++ b/src/BenchmarkDotNet/Environments/Runtimes/WasmRuntime.cs @@ -30,7 +30,7 @@ public class WasmRuntime : Runtime, IEquatable /// creates new instance of WasmRuntime /// /// Full path to a java script engine used to run the benchmarks. "v8" by default - /// Arguments for the javascript engine. Empty by default. + /// Arguments for the javascript engine. "--expose_wasm" by default /// moniker, default: "net5.0" /// default: "Wasm" /// Specifies whether AOT or Interpreter (default) project should be generated. diff --git a/src/BenchmarkDotNet/Templates/benchmark-main.mjs b/src/BenchmarkDotNet/Templates/benchmark-main.mjs index cd11444db6..c9f705d547 100644 --- a/src/BenchmarkDotNet/Templates/benchmark-main.mjs +++ b/src/BenchmarkDotNet/Templates/benchmark-main.mjs @@ -3,10 +3,7 @@ import { dotnet } from './_framework/dotnet.js' -// Get command line arguments: Node.js uses process.argv, v8 uses arguments/scriptArgs -const args = typeof process !== 'undefined' ? process.argv.slice(2) : (typeof arguments !== 'undefined' ? [...arguments] : (typeof scriptArgs !== 'undefined' ? scriptArgs : [])); - await dotnet .withDiagnosticTracing(false) - .withApplicationArguments(...args) + .withApplicationArguments(...arguments) .run() From 89a81353669d65ffdcb49fe6cca2672d8461250e Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Fri, 20 Feb 2026 16:16:46 +0100 Subject: [PATCH 4/4] Fix version. --- src/BenchmarkDotNet/Portability/RuntimeInformation.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/BenchmarkDotNet/Portability/RuntimeInformation.cs b/src/BenchmarkDotNet/Portability/RuntimeInformation.cs index bd0b62d0e8..565905bebd 100644 --- a/src/BenchmarkDotNet/Portability/RuntimeInformation.cs +++ b/src/BenchmarkDotNet/Portability/RuntimeInformation.cs @@ -102,7 +102,8 @@ internal static string GetRuntimeVersion() } } - return $".NET Core (Mono) {versionString}"; + string runtimeName = IsMono ? "Mono" : "CoreCLR"; + return $".NET Core ({runtimeName}) {versionString}"; } else if (IsOldMono) {