From fa59f6d7b27a44deafed1085a781817bf8f22c87 Mon Sep 17 00:00:00 2001
From: Jackson Schuster <36744439+jtschuster@users.noreply.github.com>
Date: Sat, 18 Jul 2026 18:09:21 -0700
Subject: [PATCH 1/5] Use Wasm runtime pack for building wasm in
ILCompiler.ReadyToRun.Tests
---
eng/pipelines/runtime.yml | 45 +++++
.../ILCompiler.ReadyToRun.Tests.csproj | 51 +++++-
.../TestCases/R2RTestSuites.cs | 11 +-
.../TestCasesRunner/R2RResultChecker.cs | 18 +-
.../TestCasesRunner/R2RTestCaseCompiler.cs | 24 +--
.../TestCasesRunner/R2RTestRunner.cs | 94 +++++++---
.../TestCasesRunner/TestPaths.cs | 169 +++---------------
...rosoft.NETCore.App.Runtime.CoreCLR.sfxproj | 2 +-
8 files changed, 207 insertions(+), 207 deletions(-)
diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml
index 77ec17437b8a1e..a122b1b40d0829 100644
--- a/eng/pipelines/runtime.yml
+++ b/eng/pipelines/runtime.yml
@@ -861,9 +861,24 @@ extends:
jobParameters:
timeoutInMinutes: 120
nameSuffix: CLR_Tools_Tests
+ # Depend on the browser-wasm libraries built below so the wasm crossgen2 R2R test
+ # (ILCompiler.ReadyToRun.Tests) can compile against real browser-wasm references.
+ dependsOn:
+ - build_browser_wasm_linux_Release_CLR_Tools_Tests_WasmLibs
buildArgs: -s clr.aot+clr.iltools+clr.corelib+clr.nativecorelib+libs.sfx+clr.toolstests+tools.cdac+tools.cdactests -c $(_BuildConfig) -test
enablePublishTestResults: true
testResultsFormat: 'xunit'
+ preBuildSteps:
+ # Lay the browser-wasm libraries into artifacts/bin so TestPaths' WasmRuntimePackDir
+ # resolves and the wasm R2R test compiles against real browser-wasm references.
+ - template: /eng/pipelines/common/download-artifact-step.yml
+ parameters:
+ artifactName: CLR_Tools_Tests_WasmLibs_BuildArtifacts_browser_wasm_Release
+ artifactFileName: CLR_Tools_Tests_WasmLibs_BuildArtifacts_browser_wasm_Release$(archiveExtension)
+ unpackFolder: $(Build.SourcesDirectory)/artifacts/bin
+ cleanUnpackFolder: false
+ overwriteExistingFiles: true
+ displayName: Browser-Wasm Libraries
# We want to run AOT tests when illink changes because there's share code and tests from illink which are used by AOT
condition: >-
or(
@@ -871,6 +886,36 @@ extends:
eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_tools_illink.containsChange'], true),
eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_tools_cdac.containsChange'], true),
eq(variables['isRollingBuild'], true))
+
+ # Build the browser-wasm managed runtime pack that the CLR_Tools_Tests job uses
+ # as crossgen2 references for the wasm ReadyToRun test. Native runtime and host
+ # assets are omitted because the test only consumes managed assemblies.
+ - template: /eng/pipelines/common/platform-matrix.yml
+ parameters:
+ jobTemplate: /eng/pipelines/common/global-build-job.yml
+ buildConfig: Release
+ platforms:
+ - browser_wasm
+ jobParameters:
+ nameSuffix: CLR_Tools_Tests_WasmLibs
+ buildArgs: -s clr.corelib+libs+libs.pretest -c Release /p:IncludeStaticLibrariesInPack=false
+ timeoutInMinutes: 120
+ postBuildSteps:
+ - template: /eng/pipelines/common/upload-artifact-step.yml
+ parameters:
+ rootFolder: $(Build.SourcesDirectory)/artifacts/bin
+ includeRootFolder: false
+ archiveType: $(archiveType)
+ archiveExtension: $(archiveExtension)
+ tarCompression: $(tarCompression)
+ artifactName: CLR_Tools_Tests_WasmLibs_BuildArtifacts_$(osGroup)$(osSubgroup)_$(archType)_$(_BuildConfig)
+ displayName: Browser-Wasm Libraries
+ condition: >-
+ or(
+ eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true),
+ eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_tools_illink.containsChange'], true),
+ eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_tools_cdac.containsChange'], true),
+ eq(variables['isRollingBuild'], true))
#
# Build CrossDacs
#
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/ILCompiler.ReadyToRun.Tests.csproj b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/ILCompiler.ReadyToRun.Tests.csproj
index e3f0ab6ea0cd15..14cec02ab0230e 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/ILCompiler.ReadyToRun.Tests.csproj
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/ILCompiler.ReadyToRun.Tests.csproj
@@ -12,6 +12,12 @@
Debug;Release;Checked
true
-notrait category=failing
+ false
+ $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'microsoft.netcore.app.runtime.browser-wasm'))
+ $([MSBuild]::NormalizeDirectory('$(WasmRuntimePackRoot)', '$(LibrariesConfiguration)', 'runtimes', 'browser-wasm', 'lib', '$(NetCoreAppCurrent)'))
+ $([MSBuild]::NormalizeDirectory('$(WasmRuntimePackRoot)', '$(LibrariesConfiguration)', 'runtimes', 'browser-wasm', 'native'))
+ $([MSBuild]::NormalizeDirectory('$(WasmRuntimePackRoot)', 'Release', 'runtimes', 'browser-wasm', 'lib', '$(NetCoreAppCurrent)'))
+ $([MSBuild]::NormalizeDirectory('$(WasmRuntimePackRoot)', 'Release', 'runtimes', 'browser-wasm', 'native'))
@@ -72,6 +78,25 @@
SkipUnchangedFiles="true" />
+
+
+
+
+
+
+
+
+
+
+
@@ -81,6 +106,7 @@
+
$(CoreCLRArtifactsPath)/$(BuildArchitecture)/crossgen2
@@ -90,18 +116,25 @@
$(MicrosoftNetCoreAppRuntimePackNativeDir)
-
- $(MicrosoftNetCoreAppRefPackRefDir)
-
-
- $(CoreCLRArtifactsPath)
+
+
+
+ $(RequireWasmReferences)
-
- $(TargetArchitecture)
+
+ $(WasmRuntimePackDir)
-
- $(TargetOS)
+
+ $(WasmRuntimePackNativeDir)
+
+
$(CoreCLRConfiguration)
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCases/R2RTestSuites.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCases/R2RTestSuites.cs
index e29a57c61cccc2..8750b3551ff007 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCases/R2RTestSuites.cs
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCases/R2RTestSuites.cs
@@ -76,13 +76,10 @@ public void WasmWebcilModule()
new(nameof(WasmWebcilModule), [new CrossgenAssembly(wasmWebcilModule)])
{
OutputFileExtension = ".wasm",
- AdditionalArgs =
- {
- "--targetarch",
- "wasm",
- "--targetos",
- "browser",
- },
+ // Reference the real browser-wasm framework assemblies when they are available
+ // (e.g. the wasm tools-test job downloads them); otherwise the runner falls back
+ // to host references so this test still runs everywhere.
+ TargetRid = TargetRid.BrowserWasm,
Validate = Validate,
},
]));
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RResultChecker.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RResultChecker.cs
index 33b4ed1d743516..f7f11d6f5c5369 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RResultChecker.cs
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RResultChecker.cs
@@ -1194,11 +1194,15 @@ public static bool MethodILIsPresent(string msilFilePath, string declaringType,
///
internal sealed class SimpleAssemblyResolver : IAssemblyResolver
{
- private readonly TestPaths _paths;
+ private readonly Dictionary _assemblyPaths;
- public SimpleAssemblyResolver(TestPaths paths)
+ public SimpleAssemblyResolver(IEnumerable referencePaths)
{
- _paths = paths;
+ _assemblyPaths = new Dictionary(StringComparer.OrdinalIgnoreCase);
+ foreach (string referencePath in referencePaths)
+ {
+ _assemblyPaths[Path.GetFileNameWithoutExtension(referencePath)] = referencePath;
+ }
}
public IAssemblyMetadata? FindAssembly(MetadataReader metadataReader, AssemblyReferenceHandle assemblyReferenceHandle, string parentFile)
@@ -1217,10 +1221,12 @@ public SimpleAssemblyResolver(TestPaths paths)
string candidate = Path.Combine(dir, simpleName + ".dll");
if (!File.Exists(candidate))
- candidate = Path.Combine(_paths.RuntimePackDir, simpleName + ".dll");
+ {
+ if (!_assemblyPaths.TryGetValue(simpleName, out string? referencePath) || referencePath is null)
+ return null;
- if (!File.Exists(candidate))
- return null;
+ candidate = referencePath;
+ }
return new SimpleAssemblyMetadata(candidate);
}
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RTestCaseCompiler.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RTestCaseCompiler.cs
index 7bd12c8887fe59..cffccdf5c65b34 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RTestCaseCompiler.cs
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RTestCaseCompiler.cs
@@ -9,6 +9,7 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Emit;
+using Xunit.Abstractions;
namespace ILCompiler.ReadyToRun.Tests.TestCasesRunner;
@@ -19,26 +20,13 @@ internal sealed class R2RTestCaseCompiler
{
private readonly List _frameworkReferences;
- public R2RTestCaseCompiler(TestPaths paths)
+ public R2RTestCaseCompiler(List references)
{
_frameworkReferences = new List();
- // Add reference assemblies from the ref pack (needed for Roslyn compilation)
- string refPackDir = paths.RefPackDir;
- if (Directory.Exists(refPackDir))
+ foreach (string refPath in references)
{
- foreach (string refPath in Directory.EnumerateFiles(refPackDir, "*.dll"))
- {
- _frameworkReferences.Add(MetadataReference.CreateFromFile(refPath));
- }
- }
- else
- {
- // Fallback to runtime pack implementation assemblies
- foreach (string refPath in paths.GetFrameworkReferencePaths())
- {
- _frameworkReferences.Add(MetadataReference.CreateFromFile(refPath));
- }
+ _frameworkReferences.Add(MetadataReference.CreateFromFile(refPath));
}
}
@@ -85,7 +73,7 @@ public string CompileAssembly(
syntaxTrees,
references,
new CSharpCompilationOptions(outputKind)
- .WithOptimizationLevel(OptimizationLevel.Release)
+ .WithOptimizationLevel(OptimizationLevel.Debug)
.WithAllowUnsafe(true)
.WithNullableContextOptions(NullableContextOptions.Enable));
@@ -97,7 +85,7 @@ public string CompileAssembly(
.Where(d => d.Severity == DiagnosticSeverity.Error)
.Select(d => d.ToString());
throw new InvalidOperationException(
- $"Compilation of '{assemblyName}' failed:\n{string.Join("\n", errors)}");
+ $"Compilation of '{assemblyName}' failed:\nReferences:\n{string.Join(Environment.NewLine, compilation.References.Select(r => r.Display))}\n\n{string.Join("\n", errors)}");
}
return outputPath;
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RTestRunner.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RTestRunner.cs
index c6a2e26649671e..dc23a142c40946 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RTestRunner.cs
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RTestRunner.cs
@@ -11,6 +11,12 @@
namespace ILCompiler.ReadyToRun.Tests.TestCasesRunner;
+enum TargetRid
+{
+ Host,
+ BrowserWasm
+}
+
///
/// Describes an assembly compiled by Roslyn as part of a test case.
///
@@ -94,6 +100,16 @@ internal sealed class CrossgenCompilation(string name, List as
///
public Action? Validate { get; init; }
+ ///
+ /// When true, this compilation references the browser-wasm runtime pack (real wasm framework
+ /// assemblies and the wasm System.Private.CoreLib) if it is available, instead of the host
+ /// runtime pack. When the browser-wasm libs are not present the runner falls back to host
+ /// references so the test still runs (with a host-arch corelib). Set this on wasm compilations
+ /// (--targetarch wasm --targetos browser) so they reference target-matching libraries when run
+ /// in a job that downloads the browser-wasm libs.
+ ///
+ public TargetRid TargetRid { get; init; } = TargetRid.Host;
+
public string Name => name;
public bool IsComposite => Options.Contains(Crossgen2Option.Composite);
@@ -205,10 +221,18 @@ public void Run(R2RTestCase testCase)
// Step 2: Run each crossgen2 compilation and validate
var driver = new R2RDriver(_output, _paths);
- var refPaths = BuildReferencePaths();
+ List hostRefPaths = BuildReferencePaths(useWasmReferences: false);
+ List? wasmRefPaths = null;
foreach(var compilation in testCase.Compilations)
{
+ List refPaths = hostRefPaths;
+ if (compilation.TargetRid == TargetRid.BrowserWasm)
+ {
+ wasmRefPaths ??= BuildReferencePaths(useWasmReferences: true);
+ refPaths = wasmRefPaths;
+ }
+
string outputPath = RunCrossgenCompilation(
testCase.Name, compilation, driver, compilation.FilePath, refPaths, assemblyPaths);
@@ -216,7 +240,7 @@ public void Run(R2RTestCase testCase)
{
Assert.True(File.Exists(outputPath), $"R2R image not found: {outputPath}");
_output.WriteLine($" Validating R2R image: {outputPath}");
- var reader = new ReadyToRunReader(new SimpleAssemblyResolver(_paths), outputPath);
+ var reader = new ReadyToRunReader(new SimpleAssemblyResolver(refPaths), outputPath);
compilation.Validate(reader);
}
}
@@ -234,11 +258,13 @@ public void Run(R2RTestCase testCase)
private Dictionary CompileAllAssemblies(
IEnumerable assemblies)
{
- var compiler = new R2RTestCaseCompiler(_paths);
var paths = new Dictionary();
foreach (var asm in assemblies)
{
+ // Tests shouldn't require a platform-specific runtime/ref pack for Roslyn compilation
+ var defaultReferences = BuildReferencePaths(useWasmReferences: false);
+ var compiler = new R2RTestCaseCompiler(defaultReferences);
var sources = asm.SourceResourceNames
.Select(R2RTestCaseCompiler.ReadEmbeddedSource)
.ToList();
@@ -252,7 +278,7 @@ private Dictionary CompileAllAssemblies(
additionalReferences: asm.References.Select(r => r.FilePath).ToList(),
features: asm.Features.Count > 0 ? asm.Features : null);
paths[asm.AssemblyName] = ilPath;
- _output.WriteLine($" Roslyn compiled '{asm.AssemblyName}' -> {ilPath}");
+ _output.WriteLine($"Roslyn compiled '{asm.AssemblyName}' -> {ilPath}");
}
return paths;
@@ -307,6 +333,13 @@ private static string RunCrossgenCompilation(
foreach (var option in compilation.Options)
args.Add(option.ToArg());
+ args.AddRange(compilation.TargetRid switch
+ {
+ TargetRid.Host => [],
+ TargetRid.BrowserWasm => ["--targetos", "browser", "--targetarch", "wasm"],
+ _ => throw new InvalidOperationException($"Unknown target RID: {compilation.TargetRid}")
+ });
+
// Caller-supplied raw args (for options that take values, e.g. --determinism-stress=N)
args.AddRange(compilation.AdditionalArgs);
@@ -335,32 +368,47 @@ private static void AddRefArgs(List args, List refPaths)
}
}
- private List BuildReferencePaths()
+ ///
+ /// Runtime packs are used as references for both Roslyn compilation and crossgen2 compilation. This method builds the reference paths for both.
+ ///
+ /// Whether to try to use browser-wasm references.
+ private List BuildReferencePaths(bool useWasmReferences)
{
- var paths = new List();
+ List paths;
- paths.Add(Path.Combine(_paths.RuntimePackDir, "*.dll"));
-
- // SPCL lives in the runtime pack native/ dir in full builds (placed by
- // externals.csproj BinPlace during libs.pretest). In partial CI builds
- // that skip libs.pretest, the runtime pack layout may not exist, but the
- // CoreCLR artifacts directory always has SPCL after clr.nativecorelib.
- string spcl = Path.Combine(_paths.RuntimePackNativeDir, "System.Private.CoreLib.dll");
- if (!File.Exists(spcl))
+ if (useWasmReferences)
{
- string fallback = Path.Combine(_paths.CoreCLRArtifactsDir, "System.Private.CoreLib.dll");
- if (File.Exists(fallback))
+ string? wasmRuntimePackDir = _paths.WasmRuntimePackDir;
+ string? wasmCoreLibPath = _paths.WasmRuntimePackNativeDir is null
+ ? null
+ : Path.Combine(_paths.WasmRuntimePackNativeDir, "System.Private.CoreLib.dll");
+
+ if (wasmRuntimePackDir is not null && wasmCoreLibPath is not null && File.Exists(wasmCoreLibPath))
{
- _output.WriteLine($"[R2RTestRunner] SPCL not found at '{spcl}'; using CoreCLR artifacts fallback '{fallback}'");
- spcl = fallback;
+ _output.WriteLine($"Using browser-wasm runtime pack references from '{wasmRuntimePackDir}'");
+ paths =
+ [
+ ..Directory.GetFiles(wasmRuntimePackDir, "*.dll"),
+ wasmCoreLibPath
+ ];
+ return paths;
+ }
+ else
+ {
+ Assert.False(
+ _paths.RequireWasmReferences,
+ "Browser-wasm framework references are required, but the browser-wasm runtime pack was not found.");
+ _output.WriteLine($"Browser-wasm runtime pack references not available. Falling back to host references.");
}
}
- Assert.True(File.Exists(spcl),
- $"System.Private.CoreLib.dll not found at '{spcl}'. " +
- $"Searched RuntimePackNativeDir='{_paths.RuntimePackNativeDir}' and " +
- $"CoreCLRArtifactsDir='{_paths.CoreCLRArtifactsDir}'");
- paths.Add(spcl);
+ string coreLibPath = Path.Combine(_paths.RuntimePackNativeDir, "System.Private.CoreLib.dll");
+ Assert.True(File.Exists(coreLibPath), $"System.Private.CoreLib.dll not found: {coreLibPath}");
+
+ paths = [
+ ..Directory.GetFiles(_paths.RuntimePackDir, "*.dll"),
+ coreLibPath
+ ];
return paths;
}
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/TestPaths.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/TestPaths.cs
index be18b5ff9aeb91..eec3b189895884 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/TestPaths.cs
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/TestPaths.cs
@@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System;
-using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
@@ -29,51 +28,10 @@ private static string GetRequiredConfig(string key)
?? throw new InvalidOperationException($"Missing RuntimeHostConfigurationOption '{key}'. Was the project built with the correct properties?");
}
- ///
- /// Tries to find an existing directory by swapping the build configuration path segment
- /// (Debug, Release, Checked) in the path. Returns the first match, or the original
- /// path if no fallback exists.
- ///
- private string ProbeConfigFallback(string dir)
+ private static string? GetOptionalConfig(string key)
{
- if (Directory.Exists(dir))
- return dir;
-
- foreach (string fallbackConfig in new[] { "Release", "Checked", "Debug" })
- {
- string fallback = Regex.Replace(
- dir, @"(?<=[/\\])(Debug|Release|Checked)(?=[/\\])", fallbackConfig);
- if (fallback != dir && Directory.Exists(fallback))
- {
- _output.WriteLine($"[TestPaths] '{dir}' not found; falling back to '{fallback}'");
- return fallback;
- }
- }
-
- return dir;
- }
-
- ///
- /// Like but for paths where the configuration name
- /// is embedded in a dot-delimited segment (e.g. linux.x64.Checked).
- ///
- private string ProbeDottedConfigFallback(string dir)
- {
- if (Directory.Exists(dir))
- return dir;
-
- foreach (string fallbackConfig in new[] { "Checked", "Release", "Debug" })
- {
- string fallback = Regex.Replace(
- dir, @"\.(Debug|Release|Checked)([/\\])", $".{fallbackConfig}$2");
- if (fallback != dir && Directory.Exists(fallback))
- {
- _output.WriteLine($"[TestPaths] '{dir}' not found; falling back to '{fallback}'");
- return fallback;
- }
- }
-
- return dir;
+ string? value = AppContext.GetData(key) as string;
+ return string.IsNullOrEmpty(value) ? null : value;
}
///
@@ -81,24 +39,9 @@ private string ProbeDottedConfigFallback(string dir)
/// e.g. artifacts/bin/coreclr/linux.x64.Checked/x64/crossgen2/
/// Falls back to Checked or Release if the configured path doesn't exist.
///
- public string Crossgen2Dir
- {
- get
- {
- string dir = GetRequiredConfig("R2RTest.Crossgen2Dir");
- if (!File.Exists(Path.Combine(dir, Crossgen2ExeName)))
- {
- string fallback = ProbeDottedConfigFallback(dir);
- if (File.Exists(Path.Combine(fallback, Crossgen2ExeName)))
- return fallback;
- }
+ public string Crossgen2Dir => GetRequiredConfig("R2RTest.Crossgen2Dir");
- return dir;
- }
- }
-
- private static string Crossgen2ExeName =>
- RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "crossgen2.exe" : "crossgen2";
+ private static string Crossgen2ExeName => RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "crossgen2.exe" : "crossgen2";
///
/// Path to the self-contained crossgen2 executable (from crossgen2_inbuild).
@@ -106,97 +49,37 @@ public string Crossgen2Dir
public string Crossgen2Exe => Path.Combine(Crossgen2Dir, Crossgen2ExeName);
///
- /// Path to the runtime pack managed assemblies directory.
- /// e.g. artifacts/bin/microsoft.netcore.app.runtime.linux-x64/Release/runtimes/linux-x64/lib/net11.0/
- /// Falls back to a different build configuration if the path doesn't exist.
- ///
- public string RuntimePackDir
- {
- get
- {
- string dir = GetRequiredConfig("R2RTest.RuntimePackDir");
- return ProbeConfigFallback(dir);
- }
- }
-
- ///
- /// Path to the runtime pack native directory (contains System.Private.CoreLib.dll and native runtime).
- /// e.g. artifacts/bin/microsoft.netcore.app.runtime.linux-x64/Release/runtimes/linux-x64/native/
- /// Falls back to a different build configuration if the path doesn't exist.
+ /// Path to the host runtime pack managed assemblies directory.
///
- public string RuntimePackNativeDir
- {
- get
- {
- string dir = GetRequiredConfig("R2RTest.RuntimePackNativeDir");
- return ProbeConfigFallback(dir);
- }
- }
+ public string RuntimePackDir => GetRequiredConfig("R2RTest.RuntimePackDir");
///
- /// Path to the CoreCLR artifacts directory (contains native bits like corerun).
- /// e.g. artifacts/bin/coreclr/linux.x64.Checked/
- /// Falls back to Checked or Release if the configured path doesn't exist.
+ /// Path to the host runtime pack native directory.
///
- public string CoreCLRArtifactsDir
- {
- get
- {
- string dir = GetRequiredConfig("R2RTest.CoreCLRArtifactsDir");
- return ProbeDottedConfigFallback(dir);
- }
- }
-
- public static string TargetArchitecture => GetRequiredConfig("R2RTest.TargetArchitecture");
- public static string TargetOS => GetRequiredConfig("R2RTest.TargetOS");
- public static string CoreCLRConfiguration => GetRequiredConfig("R2RTest.CoreCLRConfiguration");
- public static bool IsReleaseCoreCLR => string.Equals(CoreCLRConfiguration, "Release", StringComparison.OrdinalIgnoreCase);
- public static bool IsNotReleaseCoreCLR => !IsReleaseCoreCLR;
+ public string RuntimePackNativeDir => GetRequiredConfig("R2RTest.RuntimePackNativeDir");
///
- /// Path to the reference assembly pack (for Roslyn compilation).
- /// e.g. artifacts/bin/microsoft.netcore.app.ref/ref/net11.0/
+ /// Path to the browser-wasm runtime pack managed assemblies directory, or null when the
+ /// browser-wasm runtime pack has not been built/downloaded (e.g. in the default linux-x64 tools
+ /// test job). When present, the wasm crossgen2 compilation references these real browser-wasm
+ /// framework assemblies instead of the host runtime pack.
+ /// e.g. artifacts/bin/microsoft.netcore.app.runtime.browser-wasm/Release/runtimes/browser-wasm/lib/net11.0/
///
- public string RefPackDir
- {
- get
- {
- string dir = GetRequiredConfig("R2RTest.RefPackDir");
- if (!Directory.Exists(dir))
- {
- // Try the artifacts/bin/ref/net* fallback
- string artifactsBin = Path.GetFullPath(Path.Combine(CoreCLRArtifactsDir, "..", ".."));
- string refDir = Path.Combine(artifactsBin, "ref");
- if (Directory.Exists(refDir))
- {
- foreach (string subDir in Directory.GetDirectories(refDir, "net*"))
- {
- if (File.Exists(Path.Combine(subDir, "System.Runtime.dll")))
- {
- _output.WriteLine($"[TestPaths] '{dir}' not found; falling back to '{subDir}'");
- return subDir;
- }
- }
- }
- }
-
- return dir;
- }
- }
+ public string? WasmRuntimePackDir => GetOptionalConfig("R2RTest.WasmRuntimePackDir");
///
- /// Returns the target triple string for crossgen2 (e.g. "linux-x64").
+ /// Path to the browser-wasm runtime pack native directory (contains the wasm
+ /// System.Private.CoreLib.dll), or null when not available.
+ /// e.g. artifacts/bin/microsoft.netcore.app.runtime.browser-wasm/Release/runtimes/browser-wasm/native/
///
- public static string TargetTriple => $"{TargetOS.ToLowerInvariant()}-{TargetArchitecture.ToLowerInvariant()}";
+ public string? WasmRuntimePackNativeDir => GetOptionalConfig("R2RTest.WasmRuntimePackNativeDir");
- ///
- /// Returns all framework reference assembly paths (*.dll in the runtime pack).
- ///
- public IEnumerable GetFrameworkReferencePaths()
- {
- if (!Directory.Exists(RuntimePackDir))
- throw new DirectoryNotFoundException($"Runtime pack directory not found: {RuntimePackDir}");
+ public bool RequireWasmReferences => string.Equals(
+ GetOptionalConfig("R2RTest.RequireWasmReferences"),
+ bool.TrueString,
+ StringComparison.OrdinalIgnoreCase);
- return Directory.EnumerateFiles(RuntimePackDir, "*.dll");
- }
+ public static string CoreCLRConfiguration => GetRequiredConfig("R2RTest.CoreCLRConfiguration");
+ public static bool IsReleaseCoreCLR => string.Equals(CoreCLRConfiguration, "Release", StringComparison.OrdinalIgnoreCase);
+ public static bool IsNotReleaseCoreCLR => !IsReleaseCoreCLR;
}
diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.CoreCLR.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.CoreCLR.sfxproj
index 45a5d877f608a9..61dcef292c508d 100644
--- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.CoreCLR.sfxproj
+++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Runtime.CoreCLR.sfxproj
@@ -15,7 +15,7 @@
true
true
- true
+ true
From 4f17299b5e9f48777b19a709e259fcdb663a3175 Mon Sep 17 00:00:00 2001
From: Jackson Schuster <36744439+jtschuster@users.noreply.github.com>
Date: Sat, 18 Jul 2026 18:11:37 -0700
Subject: [PATCH 2/5] Clean up ILCompiler.ReadyToRun.Tests.csproj
- Use CopyAllJitLibrariesToAotCompilerOutput=true instead of copying ourselves.
- Set crossgenDir based on crossgen2_inbuild.csproj output items
- Reorder properties and items to keep related items close to each other
---
.../ILCompiler.ReadyToRun.Tests.csproj | 139 +++++++-----------
1 file changed, 55 insertions(+), 84 deletions(-)
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/ILCompiler.ReadyToRun.Tests.csproj b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/ILCompiler.ReadyToRun.Tests.csproj
index 14cec02ab0230e..9c2ff4fdf2e558 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/ILCompiler.ReadyToRun.Tests.csproj
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/ILCompiler.ReadyToRun.Tests.csproj
@@ -13,11 +13,6 @@
true
-notrait category=failing
false
- $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'microsoft.netcore.app.runtime.browser-wasm'))
- $([MSBuild]::NormalizeDirectory('$(WasmRuntimePackRoot)', '$(LibrariesConfiguration)', 'runtimes', 'browser-wasm', 'lib', '$(NetCoreAppCurrent)'))
- $([MSBuild]::NormalizeDirectory('$(WasmRuntimePackRoot)', '$(LibrariesConfiguration)', 'runtimes', 'browser-wasm', 'native'))
- $([MSBuild]::NormalizeDirectory('$(WasmRuntimePackRoot)', 'Release', 'runtimes', 'browser-wasm', 'lib', '$(NetCoreAppCurrent)'))
- $([MSBuild]::NormalizeDirectory('$(WasmRuntimePackRoot)', 'Release', 'runtimes', 'browser-wasm', 'native'))
@@ -25,57 +20,33 @@
+
+
+
+
+
+
-
-
- CopyAllJitLibrariesToAotCompilerOutput=true
- Configuration=$(CoreCLRConfiguration);CopyAllJitLibrariesToAotCompilerOutput=true
+
+ Configuration=$(CoreCLRConfiguration);CopyAllJitLibrariesToAotCompilerOutput=true
-
-
- <_BuildJitsCrossArch Condition="'$(CrossBuild)' == 'true' or '$(BuildArchitecture)' != '$(TargetArchitecture)' or '$(HostOS)' != '$(TargetOS)' or '$(EnableNativeSanitizers)' != ''">true
- <_BuildJitsProperties>ClrAllJitsSubset=true;ClrWasmJitSubset=true;Configuration=$(CoreCLRConfiguration)
- <_BuildJitsProperties Condition="!$([MSBuild]::IsOsPlatform(Windows))">$(_BuildJitsProperties);Ninja=true
- <_BuildJitsProperties Condition="'$(_BuildJitsCrossArch)' == 'true'">$(_BuildJitsProperties);HostArchitecture=$(BuildArchitecture);HostCrossOS=$(HostOS);CrossBuild=false;BuildSubdirectory=$(BuildArchitecture);CMakeArgs=$(CMakeArgs) -DCLR_CROSS_COMPONENTS_BUILD=1;PgoInstrument=false;NoPgoOptimize=true
-
-
+
+
+ <_BuildJitsCrossArch Condition="'$(CrossBuild)' == 'true' or '$(BuildArchitecture)' != '$(TargetArchitecture)' or '$(HostOS)' != '$(TargetOS)' or '$(EnableNativeSanitizers)' != ''">true
+ <_BuildJitsProperties>ClrAllJitsSubset=true;ClrWasmJitSubset=true;Configuration=$(CoreCLRConfiguration)
+ <_BuildJitsProperties Condition="!$([MSBuild]::IsOsPlatform(Windows))">$(_BuildJitsProperties);Ninja=true
+ <_BuildJitsProperties Condition="'$(_BuildJitsCrossArch)' == 'true'">$(_BuildJitsProperties);HostArchitecture=$(BuildArchitecture);HostCrossOS=$(HostOS);CrossBuild=false;BuildSubdirectory=$(BuildArchitecture);CMakeArgs=$(CMakeArgs) -DCLR_CROSS_COMPONENTS_BUILD=1;PgoInstrument=false;NoPgoOptimize=true
+
-
-
- <_WasmJitCrossHostArchSubdir Condition="'$(_BuildJitsCrossArch)' == 'true'">$(BuildArchitecture)/
- <_WasmJitFileName>$(HostLibPrefix)clrjit_universal_wasm_$(BuildArchitecture)$(HostLibSuffix)
- <_WasmJitSourcePath>$(CoreCLRArtifactsPath)$(_WasmJitCrossHostArchSubdir)$(_WasmJitFileName)
- <_Crossgen2InbuildPublishDir>$(CoreCLRArtifactsPath)$(BuildArchitecture)/crossgen2/
-
-
+
-
-
-
-
-
+
+
-
-
-
-
- $(CoreCLRArtifactsPath)/$(BuildArchitecture)/crossgen2
-
-
- $(MicrosoftNetCoreAppRuntimePackRidLibTfmDir)
-
-
- $(MicrosoftNetCoreAppRuntimePackNativeDir)
-
+
+ $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'microsoft.netcore.app.runtime.browser-wasm'))
+ $([MSBuild]::NormalizeDirectory('$(WasmRuntimePackRoot)', '$(LibrariesConfiguration)', 'runtimes', 'browser-wasm', 'lib', '$(NetCoreAppCurrent)'))
+ $([MSBuild]::NormalizeDirectory('$(WasmRuntimePackRoot)', '$(LibrariesConfiguration)', 'runtimes', 'browser-wasm', 'native'))
+ $([MSBuild]::NormalizeDirectory('$(WasmRuntimePackRoot)', 'Release', 'runtimes', 'browser-wasm', 'lib', '$(NetCoreAppCurrent)'))
+ $([MSBuild]::NormalizeDirectory('$(WasmRuntimePackRoot)', 'Release', 'runtimes', 'browser-wasm', 'native'))
+
-
-
- $(RequireWasmReferences)
-
-
- $(WasmRuntimePackDir)
-
-
- $(WasmRuntimePackNativeDir)
-
+
+
+ @(Crossgen2InbuildOutputItems->WithMetadataValue('Filename', 'crossgen2')->WithMetadataValue('Extension', '$(ExeSuffix)')->'%(RootDir)%(Directory)')
+
+
+ $(MicrosoftNetCoreAppRuntimePackRidLibTfmDir)
+
+
+ $(MicrosoftNetCoreAppRuntimePackNativeDir)
+
-
-
- $(CoreCLRConfiguration)
-
-
+
+ $(RequireWasmReferences)
+
+
+ $(WasmRuntimePackDir)
+
+
+ $(WasmRuntimePackNativeDir)
+
+
+
+
+ $(CoreCLRConfiguration)
+
+
+
+
From 898d14be4ef04bcfb6b9b49966d39551e763451f Mon Sep 17 00:00:00 2001
From: Jackson Schuster <36744439+jtschuster@users.noreply.github.com>
Date: Sat, 18 Jul 2026 18:32:00 -0700
Subject: [PATCH 3/5] Cleanup
---
.../TestCases/R2RTestSuites.cs | 13 +++++++++----
.../TestCasesRunner/R2RDriver.cs | 2 --
.../TestCasesRunner/R2RTestCaseCompiler.cs | 3 +--
.../TestCasesRunner/R2RTestRunner.cs | 10 ++--------
.../TestCasesRunner/TestPaths.cs | 1 +
5 files changed, 13 insertions(+), 16 deletions(-)
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCases/R2RTestSuites.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCases/R2RTestSuites.cs
index 8750b3551ff007..4c92350b7fe581 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCases/R2RTestSuites.cs
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCases/R2RTestSuites.cs
@@ -150,7 +150,12 @@ static void Validate(ReadyToRunReader reader)
}
}
- [Fact]
+ // Note: The arm tests compile for an arm32 target, but they are compiled with the host Corelib. If there are
+ // load-bearing dependencies in the arm32 corelib (that aren't present in the host corelib) that crossgen2 requires,
+ // these tests may fail. Wasm tests are similar, but since it doesn't require a special cross-build setup, they use
+ // a wasm corelib in CI. arm32 tests could be similarly set up, but it hasn't been done yet.
+
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.ArmOnHostOSSupported))]
public void ArmThumbBitRelocationTargets()
{
var inlineableLib = new CompiledAssembly
@@ -174,7 +179,7 @@ public void ArmThumbBitRelocationTargets()
new CrossgenAssembly(inlineableLib) { Kind = Crossgen2InputKind.Reference },
])
{
- Options = [Crossgen2Option.TargetArchArm],
+ TargetRid = TargetRid.HostArm,
Validate = Validate,
},
]));
@@ -187,7 +192,7 @@ static void Validate(ReadyToRunReader reader)
}
// JitStressProcedureSplitting is only available in Debug/Checked JIT builds.
- [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotReleaseCoreCLR))]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotReleaseCoreCLR), nameof(TestPaths.ArmOnHostOSSupported))]
public void ArmThumbBitHotColdRuntimeFunctions()
{
var hotColdSplitting = new CompiledAssembly
@@ -201,9 +206,9 @@ public void ArmThumbBitHotColdRuntimeFunctions()
[
new(nameof(ArmThumbBitHotColdRuntimeFunctions), [new CrossgenAssembly(hotColdSplitting)])
{
+ TargetRid = TargetRid.HostArm,
Options =
[
- Crossgen2Option.TargetArchArm,
Crossgen2Option.Optimize,
Crossgen2Option.HotColdSplitting,
],
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RDriver.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RDriver.cs
index a359f7bfa45d05..c598f917dc0787 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RDriver.cs
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RDriver.cs
@@ -32,7 +32,6 @@ internal enum Crossgen2Option
InputBubble,
HotColdSplitting,
Optimize,
- TargetArchArm,
StripILBodies,
}
@@ -59,7 +58,6 @@ internal static class Crossgen2OptionsExtensions
Crossgen2Option.InputBubble => $"--input-bubble",
Crossgen2Option.HotColdSplitting => $"--hot-cold-splitting",
Crossgen2Option.Optimize => $"--optimize",
- Crossgen2Option.TargetArchArm => $"--targetarch:arm",
Crossgen2Option.StripILBodies => $"--strip-il-bodies",
_ => throw new ArgumentOutOfRangeException(nameof(kind)),
};
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RTestCaseCompiler.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RTestCaseCompiler.cs
index cffccdf5c65b34..816801c96cdc6c 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RTestCaseCompiler.cs
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RTestCaseCompiler.cs
@@ -9,7 +9,6 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Emit;
-using Xunit.Abstractions;
namespace ILCompiler.ReadyToRun.Tests.TestCasesRunner;
@@ -85,7 +84,7 @@ public string CompileAssembly(
.Where(d => d.Severity == DiagnosticSeverity.Error)
.Select(d => d.ToString());
throw new InvalidOperationException(
- $"Compilation of '{assemblyName}' failed:\nReferences:\n{string.Join(Environment.NewLine, compilation.References.Select(r => r.Display))}\n\n{string.Join("\n", errors)}");
+ $"Compilation of '{assemblyName}' failed:\n{string.Join("\n", errors)}");
}
return outputPath;
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RTestRunner.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RTestRunner.cs
index dc23a142c40946..769cdad89c2773 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RTestRunner.cs
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RTestRunner.cs
@@ -14,6 +14,7 @@ namespace ILCompiler.ReadyToRun.Tests.TestCasesRunner;
enum TargetRid
{
Host,
+ HostArm,
BrowserWasm
}
@@ -100,14 +101,6 @@ internal sealed class CrossgenCompilation(string name, List as
///
public Action? Validate { get; init; }
- ///
- /// When true, this compilation references the browser-wasm runtime pack (real wasm framework
- /// assemblies and the wasm System.Private.CoreLib) if it is available, instead of the host
- /// runtime pack. When the browser-wasm libs are not present the runner falls back to host
- /// references so the test still runs (with a host-arch corelib). Set this on wasm compilations
- /// (--targetarch wasm --targetos browser) so they reference target-matching libraries when run
- /// in a job that downloads the browser-wasm libs.
- ///
public TargetRid TargetRid { get; init; } = TargetRid.Host;
public string Name => name;
@@ -336,6 +329,7 @@ private static string RunCrossgenCompilation(
args.AddRange(compilation.TargetRid switch
{
TargetRid.Host => [],
+ TargetRid.HostArm => ["--targetarch", "arm"],
TargetRid.BrowserWasm => ["--targetos", "browser", "--targetarch", "wasm"],
_ => throw new InvalidOperationException($"Unknown target RID: {compilation.TargetRid}")
});
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/TestPaths.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/TestPaths.cs
index eec3b189895884..4947a4604dd50a 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/TestPaths.cs
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/TestPaths.cs
@@ -82,4 +82,5 @@ private static string GetRequiredConfig(string key)
public static string CoreCLRConfiguration => GetRequiredConfig("R2RTest.CoreCLRConfiguration");
public static bool IsReleaseCoreCLR => string.Equals(CoreCLRConfiguration, "Release", StringComparison.OrdinalIgnoreCase);
public static bool IsNotReleaseCoreCLR => !IsReleaseCoreCLR;
+ public static bool ArmOnHostOSSupported => RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
}
From 08fc40a5d8fcf5bda8f392f8ea00e1f0c25b7295 Mon Sep 17 00:00:00 2001
From: Jackson Schuster <36744439+jtschuster@users.noreply.github.com>
Date: Mon, 20 Jul 2026 09:07:50 -0700
Subject: [PATCH 4/5] Address copilot feedback
---
.../ILCompiler.ReadyToRun.Tests.csproj | 18 ++++++++++--------
.../TestCasesRunner/R2RTestRunner.cs | 6 +++---
.../TestCasesRunner/TestPaths.cs | 1 -
3 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/ILCompiler.ReadyToRun.Tests.csproj b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/ILCompiler.ReadyToRun.Tests.csproj
index 9c2ff4fdf2e558..7d99e13fac1471 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/ILCompiler.ReadyToRun.Tests.csproj
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/ILCompiler.ReadyToRun.Tests.csproj
@@ -34,8 +34,18 @@
+
+ $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'microsoft.netcore.app.runtime.browser-wasm'))
+ $([MSBuild]::NormalizeDirectory('$(WasmRuntimePackRoot)', '$(LibrariesConfiguration)', 'runtimes', 'browser-wasm', 'lib', '$(NetCoreAppCurrent)'))
+ $([MSBuild]::NormalizeDirectory('$(WasmRuntimePackRoot)', '$(LibrariesConfiguration)', 'runtimes', 'browser-wasm', 'native'))
+ $([MSBuild]::NormalizeDirectory('$(WasmRuntimePackRoot)', 'Release', 'runtimes', 'browser-wasm', 'lib', '$(NetCoreAppCurrent)'))
+ $([MSBuild]::NormalizeDirectory('$(WasmRuntimePackRoot)', 'Release', 'runtimes', 'browser-wasm', 'native'))
+
+
+
@@ -74,14 +84,6 @@
BeforeTargets="GenerateBuildRuntimeConfigurationFiles"
Condition="'$(DesignTimeBuild)' != 'true'">
-
- $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'microsoft.netcore.app.runtime.browser-wasm'))
- $([MSBuild]::NormalizeDirectory('$(WasmRuntimePackRoot)', '$(LibrariesConfiguration)', 'runtimes', 'browser-wasm', 'lib', '$(NetCoreAppCurrent)'))
- $([MSBuild]::NormalizeDirectory('$(WasmRuntimePackRoot)', '$(LibrariesConfiguration)', 'runtimes', 'browser-wasm', 'native'))
- $([MSBuild]::NormalizeDirectory('$(WasmRuntimePackRoot)', 'Release', 'runtimes', 'browser-wasm', 'lib', '$(NetCoreAppCurrent)'))
- $([MSBuild]::NormalizeDirectory('$(WasmRuntimePackRoot)', 'Release', 'runtimes', 'browser-wasm', 'native'))
-
-
@(Crossgen2InbuildOutputItems->WithMetadataValue('Filename', 'crossgen2')->WithMetadataValue('Extension', '$(ExeSuffix)')->'%(RootDir)%(Directory)')
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RTestRunner.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RTestRunner.cs
index 769cdad89c2773..850bf53ffc0750 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RTestRunner.cs
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RTestRunner.cs
@@ -253,11 +253,11 @@ private Dictionary CompileAllAssemblies(
{
var paths = new Dictionary();
+ // Tests shouldn't require a platform-specific runtime/ref pack for Roslyn compilation
+ var defaultReferences = BuildReferencePaths(useWasmReferences: false);
+ var compiler = new R2RTestCaseCompiler(defaultReferences);
foreach (var asm in assemblies)
{
- // Tests shouldn't require a platform-specific runtime/ref pack for Roslyn compilation
- var defaultReferences = BuildReferencePaths(useWasmReferences: false);
- var compiler = new R2RTestCaseCompiler(defaultReferences);
var sources = asm.SourceResourceNames
.Select(R2RTestCaseCompiler.ReadEmbeddedSource)
.ToList();
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/TestPaths.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/TestPaths.cs
index 4947a4604dd50a..71661567fe2daf 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/TestPaths.cs
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/TestPaths.cs
@@ -37,7 +37,6 @@ private static string GetRequiredConfig(string key)
///
/// Path to the crossgen2 output directory (contains the self-contained crossgen2 executable and clrjit).
/// e.g. artifacts/bin/coreclr/linux.x64.Checked/x64/crossgen2/
- /// Falls back to Checked or Release if the configured path doesn't exist.
///
public string Crossgen2Dir => GetRequiredConfig("R2RTest.Crossgen2Dir");
From 7e40733b9c8cd0c7f00e32825e438411df6cda41 Mon Sep 17 00:00:00 2001
From: Jackson Schuster <36744439+jtschuster@users.noreply.github.com>
Date: Mon, 20 Jul 2026 14:05:33 -0700
Subject: [PATCH 5/5] Check runtime pack dir exists before enumerating
---
.../TestCasesRunner/R2RTestRunner.cs | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RTestRunner.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RTestRunner.cs
index 850bf53ffc0750..e8c1704bd3fd58 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RTestRunner.cs
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RTestRunner.cs
@@ -365,7 +365,7 @@ private static void AddRefArgs(List args, List refPaths)
///
/// Runtime packs are used as references for both Roslyn compilation and crossgen2 compilation. This method builds the reference paths for both.
///
- /// Whether to try to use browser-wasm references.
+ /// Whether to try to use browser-wasm references. The host references are used as a fallback if browser-wasm references are not available.
private List BuildReferencePaths(bool useWasmReferences)
{
List paths;
@@ -377,7 +377,8 @@ private List BuildReferencePaths(bool useWasmReferences)
? null
: Path.Combine(_paths.WasmRuntimePackNativeDir, "System.Private.CoreLib.dll");
- if (wasmRuntimePackDir is not null && wasmCoreLibPath is not null && File.Exists(wasmCoreLibPath))
+ if (wasmRuntimePackDir is not null && wasmCoreLibPath is not null
+ && File.Exists(wasmCoreLibPath) && Directory.Exists(wasmRuntimePackDir))
{
_output.WriteLine($"Using browser-wasm runtime pack references from '{wasmRuntimePackDir}'");
paths =
@@ -398,6 +399,7 @@ private List BuildReferencePaths(bool useWasmReferences)
string coreLibPath = Path.Combine(_paths.RuntimePackNativeDir, "System.Private.CoreLib.dll");
Assert.True(File.Exists(coreLibPath), $"System.Private.CoreLib.dll not found: {coreLibPath}");
+ Assert.True(Directory.Exists(_paths.RuntimePackDir), $"Runtime pack directory not found: {_paths.RuntimePackDir}");
paths = [
..Directory.GetFiles(_paths.RuntimePackDir, "*.dll"),