From 87daace271a6b571add2744f6e834b74838f6088 Mon Sep 17 00:00:00 2001 From: Parker Bibus Date: Tue, 29 Sep 2026 12:47:36 -0700 Subject: [PATCH] Set CoreCLR runtime flavor for WASM Webcil conversion Apply RuntimeFlavor after BenchmarkDotNet's UseMonoRuntime override so Webcil conversion selects the CoreCLR format. Cover R2R and non-R2R property evaluation while preserving Mono defaults. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- docs/benchmarking-workflow-dotnet-runtime.md | 5 ++ scripts/tests/test_wasm_coreclr_r2r.py | 60 +++++++++++++++++++ .../micro/MicroBenchmarks.Wasm.targets | 5 ++ 3 files changed, 70 insertions(+) diff --git a/docs/benchmarking-workflow-dotnet-runtime.md b/docs/benchmarking-workflow-dotnet-runtime.md index 8980660135b..e10416a0078 100644 --- a/docs/benchmarking-workflow-dotnet-runtime.md +++ b/docs/benchmarking-workflow-dotnet-runtime.md @@ -215,6 +215,11 @@ Essentially, add `--aotcompilermode wasm` to the `--bdn-arguments=".."`: #### Run CoreCLR WASM ReadyToRun with a nightly or VMR SDK +For CoreCLR WASM, `MicroBenchmarks.Wasm.targets` sets `RuntimeFlavor=CoreCLR` +after BenchmarkDotNet applies `UseMonoRuntime=false`. This lets the WebAssembly +SDK select the correct Webcil format, with or without ReadyToRun, while leaving +Mono configuration unchanged. + Use an exact SDK version together with a NuGet source containing the matching browser runtime/ref, WebAssembly SDK, host-specific Crossgen2, and ILLink packages, plus the complete `wasm-tools` pack closure. The source can be a diff --git a/scripts/tests/test_wasm_coreclr_r2r.py b/scripts/tests/test_wasm_coreclr_r2r.py index e59f34a4327..2ae08bcbf51 100644 --- a/scripts/tests/test_wasm_coreclr_r2r.py +++ b/scripts/tests/test_wasm_coreclr_r2r.py @@ -1,4 +1,7 @@ +import json import os +import shutil +import subprocess import sys import xml.etree.ElementTree as ET from argparse import Namespace @@ -136,6 +139,63 @@ def test_ready_to_run_validates_resolved_runtime_pack_items(): assert all("_PerformanceWasmRuntimePackName" not in condition for condition in conditions) +@pytest.mark.parametrize("ready_to_run", ["false", "true"]) +@pytest.mark.parametrize( + ("use_mono_runtime", "initial_flavor", "expected_flavor"), + [ + ("false", "", "CoreCLR"), + ("false", "Mono", "CoreCLR"), + ("true", "", ""), + ("true", "Mono", "Mono"), + ("", "", ""), + ("", "Mono", "Mono"), + ], +) +def test_wasm_runtime_flavor_after_generated_project_imports( + tmp_path, ready_to_run, use_mono_runtime, initial_flavor, expected_flavor): + dotnet_cli = shutil.which("dotnet") + if dotnet_cli is None: + pytest.skip("A .NET SDK is required for MSBuild property evaluation.") + + micro_dir = scripts_dir.parent / "src" / "benchmarks" / "micro" + project = ET.Element("Project") + properties = ET.SubElement(project, "PropertyGroup") + for name, value in { + "UseMonoRuntime": "true", + "RuntimeFlavor": initial_flavor, + "PERFLAB_WASM_READY_TO_RUN": ready_to_run, + "PublishReadyToRun": "false", + }.items(): + ET.SubElement(properties, name).text = value + + # BenchmarkDotNet overrides UseMonoRuntime after .props but before .targets. + ET.SubElement(project, "Import", Project=str(micro_dir / "MicroBenchmarks.Wasm.props")) + properties = ET.SubElement(project, "PropertyGroup") + ET.SubElement(properties, "UseMonoRuntime").text = use_mono_runtime + ET.SubElement(project, "Import", Project=str(micro_dir / "MicroBenchmarks.Wasm.targets")) + project_path = tmp_path / "GeneratedWasm.proj" + ET.ElementTree(project).write(project_path, encoding="utf-8") + + result = subprocess.run( + [ + dotnet_cli, "msbuild", str(project_path), "-nologo", + "-getProperty:UseMonoRuntime,RuntimeFlavor,PublishReadyToRun", + ], + cwd=tmp_path, + capture_output=True, + text=True, + timeout=60, + ) + + assert result.returncode == 0, result.stdout + result.stderr + evaluated = json.loads(result.stdout)["Properties"] + assert evaluated["UseMonoRuntime"] == use_mono_runtime + assert evaluated["RuntimeFlavor"] == expected_flavor + assert evaluated["PublishReadyToRun"] == ( + "true" if use_mono_runtime == "false" and ready_to_run == "true" else "false" + ) + + def test_coreclr_payload_detects_local_toolchain_package_version(tmp_path): artifact = tmp_path / "artifact" / "staging" ref_pack = artifact / "dotnet-none" / "packs" / "Microsoft.NETCore.App.Ref" / "11.0.0-rc.1.26431.109" diff --git a/src/benchmarks/micro/MicroBenchmarks.Wasm.targets b/src/benchmarks/micro/MicroBenchmarks.Wasm.targets index b6e4216cf79..e1a4340fe4c 100644 --- a/src/benchmarks/micro/MicroBenchmarks.Wasm.targets +++ b/src/benchmarks/micro/MicroBenchmarks.Wasm.targets @@ -10,6 +10,11 @@ <_WasmStrictVersionMatch>false + + + CoreCLR + + true false