diff --git a/eng/Subsets.props b/eng/Subsets.props index 14b2d3eedab02a..549b541d80a2c0 100644 --- a/eng/Subsets.props +++ b/eng/Subsets.props @@ -163,7 +163,7 @@ clr.nativeprereqs+clr.iltools+clr.runtime+clr.native+clr.aot+clr.nativeaotlibs+clr.nativeaotruntime+clr.crossarchtools - $(AllSubsetsExpansion)+clr.paltests+clr.paltestlist+clr.hosts+clr.jit+clr.alljits+clr.alljitscommunity+clr.spmi+clr.corelib+clr.nativecorelib+clr.tools+clr.toolstests+clr.packages + $(AllSubsetsExpansion)+clr.paltests+clr.paltestlist+clr.hosts+clr.jit+clr.alljits+clr.alljitscommunity+clr.spmi+clr.corelib+clr.nativecorelib+clr.tools+clr.toolstests+clr.r2rtests+clr.packages $(AllSubsetsExpansion)+linuxdac+alpinedac $(AllSubsetsExpansion)+mono.runtime+provision.emsdk+mono.aotcross+mono.corelib+mono.manifests+mono.packages+mono.tools+mono.wasmruntime+mono.wasiruntime+mono.wasmworkload+mono.mscordbi+mono.workloads $(AllSubsetsExpansion)+tools.illink+tools.cdac+tools.illinktests+tools.cdactests+tools.cdacdumptests @@ -227,6 +227,7 @@ + @@ -508,14 +509,17 @@ Test="true" Category="clr" Condition="'$(DotNetBuildSourceOnly)' != 'true' and '$(NativeAotSupported)' == 'true'"/> - + + + + <_CDacToolsBuilt Condition="'$(_CDacToolsBuilt)' != 'true'">true diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml index 130f23b0a097d4..5dfa9e699e1aa9 100644 --- a/eng/pipelines/runtime.yml +++ b/eng/pipelines/runtime.yml @@ -223,6 +223,7 @@ extends: eq(variables['wasmDarcDependenciesChanged'], true), eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_tools_illink.containsChange'], true), eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_wasm_coreclr_runtimetests.containsChange'], true), + eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true), eq(variables['isRollingBuild'], true)) - template: /eng/pipelines/common/platform-matrix.yml @@ -882,6 +883,53 @@ 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)) + + - template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/common/global-build-job.yml + buildConfig: checked + platforms: + - linux_x64 + jobParameters: + dependsOn: + - build_browser_wasm_linux_checked_CoreCLR_ReleaseLibraries + - build_linux_arm_checked_CoreCLR_ReleaseLibraries + - build_linux_x64_checked_CoreCLR_ReleaseLibraries + timeoutInMinutes: 120 + nameSuffix: CLR_R2R_Tests + buildArgs: -s clr.r2rtests -lc Release -c $(_BuildConfig) -test /p:RequireTargetArchRuntimePack=true + enablePublishTestResults: true + testResultsFormat: 'xunit' + preBuildSteps: + - template: /eng/pipelines/common/download-artifact-step.yml + parameters: + artifactName: CoreCLR_ReleaseLibraries_BuildArtifacts_browser_wasm_linux_Checked + artifactFileName: CoreCLR_ReleaseLibraries_BuildArtifacts_browser_wasm_linux_Checked$(archiveExtension) + unpackFolder: $(Build.SourcesDirectory)/artifacts/bin + cleanUnpackFolder: false + overwriteExistingFiles: true + displayName: Download browser-wasm artifacts + - template: /eng/pipelines/common/download-artifact-step.yml + parameters: + artifactName: CoreCLR_ReleaseLibraries_BuildArtifacts_linux_arm_Checked + artifactFileName: CoreCLR_ReleaseLibraries_BuildArtifacts_linux_arm_Checked$(archiveExtension) + unpackFolder: $(Build.SourcesDirectory)/artifacts/bin + cleanUnpackFolder: false + overwriteExistingFiles: true + displayName: Download linux-arm artifacts + - template: /eng/pipelines/common/download-artifact-step.yml + parameters: + artifactName: CoreCLR_ReleaseLibraries_BuildArtifacts_linux_x64_Checked + artifactFileName: CoreCLR_ReleaseLibraries_BuildArtifacts_linux_x64_Checked$(archiveExtension) + unpackFolder: $(Build.SourcesDirectory)/artifacts/bin + cleanUnpackFolder: false + overwriteExistingFiles: true + displayName: Download linux-x64 artifacts + condition: >- + or( + eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_coreclr.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..17373e0c6f8457 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 @@ -4,14 +4,10 @@ ILCompiler.ReadyToRun.Tests $(NetCoreAppToolCurrent) enable - false true - x64;x86 - AnyCPU - linux-x64;win-x64;osx-x64 - Debug;Release;Checked true -notrait category=failing + false @@ -19,92 +15,98 @@ + + + + + + - - - 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 + $([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')) + + $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'microsoft.netcore.app.runtime.$(TargetOS)-arm')) + $([MSBuild]::NormalizeDirectory('$(ArmRuntimePackRoot)', '$(LibrariesConfiguration)', 'runtimes', '$(TargetOS)-arm', 'lib', '$(NetCoreAppCurrent)')) + $([MSBuild]::NormalizeDirectory('$(ArmRuntimePackRoot)', '$(LibrariesConfiguration)', 'runtimes', '$(TargetOS)-arm', 'native')) + $([MSBuild]::NormalizeDirectory('$(ArmRuntimePackRoot)', 'Release', 'runtimes', '$(TargetOS)-arm', 'lib', '$(NetCoreAppCurrent)')) + $([MSBuild]::NormalizeDirectory('$(ArmRuntimePackRoot)', 'Release', 'runtimes', '$(TargetOS)-arm', 'native')) - - - - - <_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) - - - $(MicrosoftNetCoreAppRefPackRefDir) - - - $(CoreCLRArtifactsPath) - - - $(TargetArchitecture) - - - $(TargetOS) - - - $(CoreCLRConfiguration) - - + + + @(Crossgen2InbuildOutputItems->WithMetadataValue('Filename', 'crossgen2')->WithMetadataValue('Extension', '$(ExeSuffix)')->'%(RootDir)%(Directory)') + + + $(MicrosoftNetCoreAppRuntimePackRidLibTfmDir) + + + $(MicrosoftNetCoreAppRuntimePackNativeDir) + + + + $(RequireTargetArchRuntimePack) + + + + $(WasmRuntimePackDir) + + + $(WasmRuntimePackNativeDir) + + + + $(ArmRuntimePackDir) + + + $(ArmRuntimePackNativeDir) + + + + + $(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 09e98fcc6a088b..1223c2f30db233 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCases/R2RTestSuites.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCases/R2RTestSuites.cs @@ -77,13 +77,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, }, ])); @@ -235,7 +232,7 @@ static void Validate(ReadyToRunReader reader) } } - [Fact] + [ConditionalFact(typeof(TestPaths), nameof(TestPaths.ArmOnHostOSSupported))] public void ArmThumbBitRelocationTargets() { var inlineableLib = new CompiledAssembly @@ -259,7 +256,7 @@ public void ArmThumbBitRelocationTargets() new CrossgenAssembly(inlineableLib) { Kind = Crossgen2InputKind.Reference }, ]) { - Options = [Crossgen2Option.TargetArchArm], + TargetRid = TargetRid.HostArm, Validate = Validate, }, ])); @@ -272,7 +269,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 @@ -286,9 +283,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..24341440e31f35 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RDriver.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RDriver.cs @@ -18,6 +18,13 @@ internal enum Crossgen2AssemblyOption CrossModuleOptimization, } +internal enum CoreLibTargetArchitecture +{ + Host, + Arm32, + Wasm +} + internal enum Crossgen2InputKind { InputAssembly, @@ -32,7 +39,6 @@ internal enum Crossgen2Option InputBubble, HotColdSplitting, Optimize, - TargetArchArm, StripILBodies, } @@ -59,7 +65,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/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..476ac89c09ce6e 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RTestCaseCompiler.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RTestCaseCompiler.cs @@ -19,26 +19,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)); } } 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..ce88a5bff97241 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,13 @@ namespace ILCompiler.ReadyToRun.Tests.TestCasesRunner; +enum TargetRid +{ + Host, + HostArm, + BrowserWasm +} + /// /// Describes an assembly compiled by Roslyn as part of a test case. /// @@ -94,6 +101,8 @@ internal sealed class CrossgenCompilation(string name, List as /// public Action? Validate { get; init; } + public TargetRid TargetRid { get; init; } = TargetRid.Host; + public string Name => name; public bool IsComposite => Options.Contains(Crossgen2Option.Composite); @@ -205,10 +214,24 @@ 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(CoreLibTargetArchitecture.Host); + List? wasmRefPaths = null; + List? armRefPaths = null; foreach(var compilation in testCase.Compilations) { + List refPaths = hostRefPaths; + if (compilation.TargetRid == TargetRid.BrowserWasm) + { + wasmRefPaths ??= BuildReferencePaths(CoreLibTargetArchitecture.Wasm); + refPaths = wasmRefPaths; + } + else if (compilation.TargetRid == TargetRid.HostArm) + { + armRefPaths ??= BuildReferencePaths(CoreLibTargetArchitecture.Arm32); + refPaths = armRefPaths; + } + string outputPath = RunCrossgenCompilation( testCase.Name, compilation, driver, compilation.FilePath, refPaths, assemblyPaths); @@ -216,7 +239,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,9 +257,11 @@ public void Run(R2RTestCase testCase) private Dictionary CompileAllAssemblies( IEnumerable assemblies) { - var compiler = new R2RTestCaseCompiler(_paths); var paths = new Dictionary(); + // Tests shouldn't require a platform-specific runtime/ref pack for Roslyn compilation + var defaultReferences = BuildReferencePaths(CoreLibTargetArchitecture.Host); + var compiler = new R2RTestCaseCompiler(defaultReferences); foreach (var asm in assemblies) { var sources = asm.SourceResourceNames @@ -252,7 +277,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 +332,14 @@ private static string RunCrossgenCompilation( foreach (var option in compilation.Options) args.Add(option.ToArg()); + 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}") + }); + // Caller-supplied raw args (for options that take values, e.g. --determinism-stress=N) args.AddRange(compilation.AdditionalArgs); @@ -335,33 +368,46 @@ 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. + /// + private List BuildReferencePaths(CoreLibTargetArchitecture coreLibArch) { - var paths = new List(); - - 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)) + List paths; + (string runtimePackDir, string runtimePackNativeDir) = coreLibArch switch { - string fallback = Path.Combine(_paths.CoreCLRArtifactsDir, "System.Private.CoreLib.dll"); - if (File.Exists(fallback)) + CoreLibTargetArchitecture.Host => (_paths.RuntimePackDir, _paths.RuntimePackNativeDir), + CoreLibTargetArchitecture.Arm32 => (_paths.ArmRuntimePackDir, _paths.ArmRuntimePackNativeDir), + CoreLibTargetArchitecture.Wasm => (_paths.WasmRuntimePackDir, _paths.WasmRuntimePackNativeDir), + _ => throw new InvalidOperationException($"Unknown CoreLibTargetArchitecture: {coreLibArch}") + }; + if (!RuntimePackPathsAreValid(runtimePackDir, runtimePackNativeDir)) + { + if (_paths.RequireTargetArchRuntimePack) { - _output.WriteLine($"[R2RTestRunner] SPCL not found at '{spcl}'; using CoreCLR artifacts fallback '{fallback}'"); - spcl = fallback; + throw new InvalidOperationException($"Required runtime pack for {coreLibArch} not found: {runtimePackDir} or {runtimePackNativeDir}"); + } + else + { + _output.WriteLine($"Warning: Required runtime pack for {coreLibArch} not found: {runtimePackDir} or {runtimePackNativeDir}. Falling back to host references."); + (runtimePackDir, runtimePackNativeDir) = (_paths.RuntimePackDir, _paths.RuntimePackNativeDir); } } - 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(runtimePackNativeDir, "System.Private.CoreLib.dll"); + Assert.True(File.Exists(coreLibPath), $"System.Private.CoreLib.dll not found: {coreLibPath}"); + Assert.True(Directory.Exists(runtimePackDir), $"Runtime pack directory not found: {runtimePackDir}"); + + paths = [ + ..Directory.GetFiles(runtimePackDir, "*.dll"), + coreLibPath + ]; return paths; + + bool RuntimePackPathsAreValid(string runtimePackDir, string runtimePackNativeDir) + { + return Directory.Exists(runtimePackDir) && File.Exists(Path.Combine(runtimePackNativeDir, "System.Private.CoreLib.dll")); + } } } 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..f6bff9fe1b2305 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,76 +28,13 @@ 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) - { - 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; - } - /// /// 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 - { - 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 +42,38 @@ 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. + /// Path to the host runtime pack managed assemblies directory. /// - public string RuntimePackDir - { - get - { - string dir = GetRequiredConfig("R2RTest.RuntimePackDir"); - return ProbeConfigFallback(dir); - } - } + public string RuntimePackDir => GetRequiredConfig("R2RTest.RuntimePackDir"); /// - /// 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 native directory. /// - public string RuntimePackNativeDir - { - get - { - string dir = GetRequiredConfig("R2RTest.RuntimePackNativeDir"); - return ProbeConfigFallback(dir); - } - } + public string RuntimePackNativeDir => GetRequiredConfig("R2RTest.RuntimePackNativeDir"); /// - /// 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 browser-wasm runtime pack managed assemblies directory. + /// When present, the wasm crossgen2 compilation references these real browser-wasm + /// framework assemblies instead of the host runtime pack. /// - 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 WasmRuntimePackDir => GetRequiredConfig("R2RTest.WasmRuntimePackDir"); /// - /// 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 native directory (contains the wasm + /// System.Private.CoreLib.dll). /// - 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; - } - } - } - } + public string WasmRuntimePackNativeDir => GetRequiredConfig("R2RTest.WasmRuntimePackNativeDir"); - return dir; - } - } + public string ArmRuntimePackDir => GetRequiredConfig("R2RTest.ArmRuntimePackDir"); + public string ArmRuntimePackNativeDir => GetRequiredConfig("R2RTest.ArmRuntimePackNativeDir"); - /// - /// Returns the target triple string for crossgen2 (e.g. "linux-x64"). - /// - public static string TargetTriple => $"{TargetOS.ToLowerInvariant()}-{TargetArchitecture.ToLowerInvariant()}"; - - /// - /// 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 RequireTargetArchRuntimePack => string.Equals( + GetRequiredConfig("R2RTest.RequireTargetArchRuntimePack"), + 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; + public static bool ArmOnHostOSSupported => RuntimeInformation.IsOSPlatform(OSPlatform.Linux); } 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..063aa3124cd217 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 @@ -14,8 +14,6 @@ NetCore.SharedFramework true true - - true