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"),