diff --git a/eng/Subsets.props b/eng/Subsets.props
index 337bca6fa63caf..318ffc4179c8ec 100644
--- a/eng/Subsets.props
+++ b/eng/Subsets.props
@@ -168,7 +168,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
$(AllSubsetsExpansion)+tools.illink+tools.cdac+tools.illinktests+tools.cdactests+tools.cdacdumptests
@@ -232,6 +232,7 @@
+
@@ -393,7 +394,6 @@
- <_CrossToolSubset Condition="'$(_BuildCrossComponents)' == 'true' and '$(TargetArchitecture)' != 'wasm' and $(_subset.Contains('+clr.toolstests+'))" Include="ClrAllJitsSubset=true" />
<_CrossToolSubset Condition="'$(_BuildCrossComponents)' == 'true' and '$(TargetArchitecture)' != 'wasm' and ($(_subset.Contains('+clr.tools+')) or $(_subset.Contains('+clr.nativecorelib+')) or $(_subset.Contains('+clr.crossarchtools+')))" Include="ClrJitSubset=true" />
<_CrossToolSubset Condition="'$(_BuildCrossComponents)' == 'true' and '$(TargetArchitecture)' == 'wasm' and ($(_subset.Contains('+clr.tools+')) or $(_subset.Contains('+clr.nativecorelib+')) or $(_subset.Contains('+clr.crossarchtools+')))" Include="ClrWasmJitSubset=true" />
@@ -519,14 +519,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 af2fc6e3392cf5..53dc7851765d6d 100644
--- a/eng/pipelines/runtime.yml
+++ b/eng/pipelines/runtime.yml
@@ -232,6 +232,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
@@ -951,6 +952,166 @@ 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))
+
+ # The R2R test suite compiles for one target per run: the test assembly itself always runs on
+ # the build machine, while crossgen2 and the shared framework it compiles against are staged
+ # for whatever the build targets. Each leg therefore needs only its own target's artifacts,
+ # and test cases the target cannot compile are skipped rather than failed.
+ - template: /eng/pipelines/common/platform-matrix.yml
+ parameters:
+ jobTemplate: /eng/pipelines/common/global-build-job.yml
+ buildConfig: checked
+ platforms:
+ - linux_x64
+ jobParameters:
+ dependsOn:
+ - build_linux_x64_checked_CoreCLR_ReleaseLibraries
+ timeoutInMinutes: 120
+ nameSuffix: CLR_R2R_Tests_linux_x64
+ buildArgs: -s clr.r2rtests -lc Release -c $(_BuildConfig) -test
+ enablePublishTestResults: true
+ testResultsFormat: 'xunit'
+ preBuildSteps:
+ - 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))
+
+ - template: /eng/pipelines/common/platform-matrix.yml
+ parameters:
+ jobTemplate: /eng/pipelines/common/global-build-job.yml
+ buildConfig: checked
+ platforms:
+ - linux_x64
+ variables:
+ - name: _osParameter
+ value: -os browser
+ - name: _archParameter
+ value: -arch wasm
+ jobParameters:
+ dependsOn:
+ - build_browser_wasm_linux_checked_CoreCLR_ReleaseLibraries
+ timeoutInMinutes: 120
+ nameSuffix: CLR_R2R_Tests_browser_wasm
+ buildArgs: -s clr.r2rtests -lc Release -c $(_BuildConfig) -test
+ 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
+ condition: >-
+ or(
+ eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_coreclr.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
+ variables:
+ - name: _archParameter
+ value: -arch arm
+ jobParameters:
+ dependsOn:
+ - build_linux_arm_checked_CoreCLR_ReleaseLibraries
+ timeoutInMinutes: 120
+ nameSuffix: CLR_R2R_Tests_linux_arm
+ buildArgs: -s clr.r2rtests -lc Release -c $(_BuildConfig) -test
+ enablePublishTestResults: true
+ testResultsFormat: 'xunit'
+ preBuildSteps:
+ - 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
+ condition: >-
+ or(
+ eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_coreclr.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
+ variables:
+ - name: _osParameter
+ value: -os ios
+ - name: _archParameter
+ value: -arch arm64
+ jobParameters:
+ timeoutInMinutes: 120
+ nameSuffix: CLR_R2R_Tests_ios_arm64
+ # No prebuilt artifact can supply this leg: the iOS jobs run on macOS, so their cross
+ # components are Mach-O and unusable here. The cross components are built from source
+ # instead - they target the build host (linux-x64), not iOS, so no Apple SDK is needed.
+ # libs.sfx rather than libs, because libs.native does require the Apple SDK.
+ buildArgs: -s clr.crossarchtools+clr.corelib+libs.sfx -rf CoreCLR -lc Release -c $(_BuildConfig)
+ enablePublishTestResults: true
+ testResultsFormat: 'xunit'
+ postBuildSteps:
+ # A separate invocation because clr.r2rtests is ordered ahead of libs.sfx in
+ # Subsets.props, so a single build would run the tests before their inputs exist.
+ - template: /eng/pipelines/common/templates/global-build-step.yml
+ parameters:
+ buildArgs: -s clr.r2rtests -rf CoreCLR -lc Release -c $(_BuildConfig) -test
+ displayName: Build and run R2R tests
+ condition: >-
+ or(
+ eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true),
+ eq(variables['isRollingBuild'], true))
+
+ # The only leg with a Windows host, which the two --pdb test cases require: crossgen2 writes
+ # Windows PDBs through Microsoft.DiaSymReader.Native, which is restored for Windows only.
+ - template: /eng/pipelines/common/platform-matrix.yml
+ parameters:
+ jobTemplate: /eng/pipelines/common/global-build-job.yml
+ buildConfig: checked
+ platforms:
+ - windows_x64
+ jobParameters:
+ dependsOn:
+ - build_windows_x64_checked_CoreCLR_ReleaseLibraries
+ timeoutInMinutes: 120
+ nameSuffix: CLR_R2R_Tests_windows_x64
+ buildArgs: -s clr.r2rtests -lc Release -c $(_BuildConfig) -test
+ enablePublishTestResults: true
+ testResultsFormat: 'xunit'
+ preBuildSteps:
+ - template: /eng/pipelines/common/download-artifact-step.yml
+ parameters:
+ artifactName: CoreCLR_ReleaseLibraries_BuildArtifacts_windows_x64_Checked
+ artifactFileName: CoreCLR_ReleaseLibraries_BuildArtifacts_windows_x64_Checked$(archiveExtension)
+ unpackFolder: $(Build.SourcesDirectory)/artifacts/bin
+ cleanUnpackFolder: false
+ overwriteExistingFiles: true
+ displayName: Download windows-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 9969de865e5fe9..1c77956d8bbe6b 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
@@ -1,17 +1,22 @@
+
+
+
ILCompiler.ReadyToRun.Tests
$(NetCoreAppToolCurrent)
enable
- false
- true
- x64;x86
- AnyCPU
- linux-x64;win-x64;osx-x64
- Debug;Release;Checked
- true
-notrait category=failing
+
+ AnyCPU
+ $(NETCoreSdkRuntimeIdentifier)
+ false
+
+ $(BaseOutputPath)$(Configuration)\$(CoreCLRConfiguration)_CLR\$(TargetRid)\
@@ -21,93 +26,49 @@
-
-
-
- CopyAllJitLibrariesToAotCompilerOutput=true
- Configuration=$(CoreCLRConfiguration);CopyAllJitLibrariesToAotCompilerOutput=true
+
+ Configuration=$(CoreCLRConfiguration);CopyAllJitLibrariesToAotCompilerOutput=true;TargetArchitecture=$(TargetArchitecture);TargetOS=$(TargetOS)
-
-
- <_BuildJitsCrossArch Condition="'$(CrossBuild)' == 'true' or '$(BuildArchitecture)' != '$(TargetArchitecture)' or '$(HostOS)' != '$(TargetOS)' or '$(TargetsLinuxBionic)' == 'true' 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/
-
-
-
-
-
-
+
+
+
+
+
+
+ <_SharedFrameworkAssembly Include="$(LibrariesSharedFrameworkBinArtifactsPath)*.dll" />
+ <_SharedFrameworkAssembly Include="$(CoreCLRArtifactsPath)IL/System.Private.CoreLib.dll" />
+
+
+
+
+
+
+
+
+
+
-
- $(CoreCLRArtifactsPath)/$(BuildArchitecture)/crossgen2
-
-
- $(MicrosoftNetCoreAppRuntimePackRidLibTfmDir)
-
-
- $(MicrosoftNetCoreAppRuntimePackNativeDir)
-
-
- $(MicrosoftNetCoreAppRefPackRefDir)
-
-
- $(CoreCLRArtifactsPath)
-
-
- $(TargetArchitecture)
-
-
- $(TargetOS)
-
-
- $(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 9bde75896d70a5..fc25e2a448c02a 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCases/R2RTestSuites.cs
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCases/R2RTestSuites.cs
@@ -29,7 +29,7 @@ public R2RTestSuites(ITestOutputHelper output)
_output = output;
}
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void BasicCrossModuleInlining()
{
var inlineableLib = new CompiledAssembly
@@ -62,7 +62,7 @@ static void Validate(ReadyToRunReader reader)
}
}
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsWasmTarget))]
public void WasmWebcilModule()
{
var wasmWebcilModule = new CompiledAssembly
@@ -77,13 +77,6 @@ public void WasmWebcilModule()
new(nameof(WasmWebcilModule), [new CrossgenAssembly(wasmWebcilModule)])
{
OutputFileExtension = ".wasm",
- AdditionalArgs =
- {
- "--targetarch",
- "wasm",
- "--targetos",
- "browser",
- },
Validate = Validate,
},
]));
@@ -128,7 +121,7 @@ static void Validate(ReadyToRunReader reader)
}
}
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsWasmTarget))]
public void WasmSimdModule()
{
var wasmSimdModule = new CompiledAssembly
@@ -143,13 +136,6 @@ public void WasmSimdModule()
new(nameof(WasmSimdModule), [new CrossgenAssembly(wasmSimdModule)])
{
OutputFileExtension = ".wasm",
- AdditionalArgs =
- {
- "--targetarch",
- "wasm",
- "--targetos",
- "browser",
- },
Validate = Validate,
},
]));
@@ -209,7 +195,7 @@ static WebcilImageReader.WasmFunctionInfo ResolveWasmBody(
}
}
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void RuntimeFunctionsSectionSizeExcludesSentinel()
{
var lib = new CompiledAssembly
@@ -242,7 +228,7 @@ static void Validate(ReadyToRunReader reader)
}
}
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsArmTarget))]
public void ArmThumbBitRelocationTargets()
{
var inlineableLib = new CompiledAssembly
@@ -266,7 +252,6 @@ public void ArmThumbBitRelocationTargets()
new CrossgenAssembly(inlineableLib) { Kind = Crossgen2InputKind.Reference },
])
{
- Options = [Crossgen2Option.TargetArchArm],
Validate = Validate,
},
]));
@@ -279,7 +264,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.IsArmTarget))]
public void ArmThumbBitHotColdRuntimeFunctions()
{
var hotColdSplitting = new CompiledAssembly
@@ -295,7 +280,6 @@ public void ArmThumbBitHotColdRuntimeFunctions()
{
Options =
[
- Crossgen2Option.TargetArchArm,
Crossgen2Option.Optimize,
Crossgen2Option.HotColdSplitting,
],
@@ -315,7 +299,7 @@ static void Validate(ReadyToRunReader reader)
}
}
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void TransitiveReferences()
{
var externalLib = new CompiledAssembly()
@@ -358,7 +342,7 @@ public void TransitiveReferences()
]));
}
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void AsyncCrossModuleInlining()
{
var asyncInlineableLib = new CompiledAssembly
@@ -398,7 +382,7 @@ static void Validate(ReadyToRunReader reader)
}
}
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void CompositeBasic()
{
var compositeLib = new CompiledAssembly
@@ -434,7 +418,7 @@ static void Validate(ReadyToRunReader reader)
}
}
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void CompositeManifestAssemblyMvidsAreAligned()
{
var compositeLib = new CompiledAssembly
@@ -470,9 +454,11 @@ static void Validate(ReadyToRunReader reader)
}
}
- public static bool IsWindows => System.OperatingSystem.IsWindows();
-
- [ConditionalFact(nameof(IsWindows))]
+ ///
+ /// Requires a Windows host for --pdb (see ), and a
+ /// Windows target because the padding being verified is in the composite PE image.
+ ///
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsWindowsHost), nameof(TestPaths.IsWindowsTarget))]
public void CompositeManifestAssemblyMvidsArePaddedWhenPdbPresent()
{
var compositeLib = new CompiledAssembly
@@ -522,7 +508,7 @@ static void Validate(ReadyToRunReader reader)
/// boundary. When they landed on an unaligned RVA the runtime faulted on ARM32 (which does not
/// permit unaligned multi-word loads) during coreclr_initialize; x64/arm64 tolerated it.
///
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void CompositeManifestSectionsAreAligned()
{
var compositeLib = new CompiledAssembly
@@ -561,10 +547,11 @@ static void Validate(ReadyToRunReader reader)
///
/// Complements using the same trigger as the
/// MVID-table test: --pdb emits an odd-sized debug directory section that shifts the manifest
- /// sections off a 4-byte boundary without the fix. Windows-only because it relies on Windows PDB
- /// generation.
+ /// sections off a 4-byte boundary without the fix. Requires a Windows host for --pdb
+ /// (see ), and a Windows target because the padding being
+ /// verified is in the composite PE image.
///
- [ConditionalFact(nameof(IsWindows))]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsWindowsHost), nameof(TestPaths.IsWindowsTarget))]
public void CompositeManifestSectionsArePaddedWhenPdbPresent()
{
var compositeLib = new CompiledAssembly
@@ -601,7 +588,7 @@ static void Validate(ReadyToRunReader reader)
}
}
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void RuntimeAsyncMethodEmission()
{
var runtimeAsyncMethodEmission = new CompiledAssembly
@@ -639,7 +626,7 @@ static void Validate(ReadyToRunReader reader)
/// It must also strip a non-async Task-returning method whose async variant has already been
/// compiled, since the IL is no longer needed at runtime.
///
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void RuntimeAsyncStripILBodiesPreservesTaskReturningIL()
{
var stripILBodies = new CompiledAssembly
@@ -659,7 +646,6 @@ public void RuntimeAsyncStripILBodiesPreservesTaskReturningIL()
new(nameof(RuntimeAsyncStripILBodiesPreservesTaskReturningIL), [new CrossgenAssembly(stripILBodies)])
{
Options = [Crossgen2Option.Composite, Crossgen2Option.Optimize, Crossgen2Option.StripILBodies],
- AdditionalArgs = ["--targetarch:x64"],
Validate = Validate,
},
]));
@@ -695,7 +681,7 @@ static void Validate(ReadyToRunReader reader)
}
}
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsIosArm64Target))]
public void AppleMobileStripILBodiesUsesFixedInstructionSet()
{
var stripILBodies = new CompiledAssembly
@@ -715,7 +701,6 @@ public void AppleMobileStripILBodiesUsesFixedInstructionSet()
new(nameof(AppleMobileStripILBodiesUsesFixedInstructionSet), [new CrossgenAssembly(stripILBodies)])
{
Options = [Crossgen2Option.Composite, Crossgen2Option.Optimize, Crossgen2Option.StripILBodies],
- AdditionalArgs = ["--targetos:ios", "--targetarch:arm64"],
Validate = Validate,
},
]));
@@ -744,7 +729,7 @@ static void Validate(ReadyToRunReader reader)
/// produce ContinuationLayout fixups encoding the GC ref map.
/// PR #124203: Resumption stubs for methods with suspension points.
///
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void RuntimeAsyncContinuationLayout()
{
var runtimeAsyncContinuationLayout = new CompiledAssembly
@@ -783,7 +768,7 @@ static void Validate(ReadyToRunReader reader)
/// PR #125420: [ASYNC] variant generation for devirtualizable async call patterns
/// (sealed class and interface dispatch through AsyncAwareVirtualMethodResolutionAlgorithm).
///
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void RuntimeAsyncDevirtualize()
{
var runtimeAsyncDevirtualize = new CompiledAssembly
@@ -818,7 +803,7 @@ static void Validate(ReadyToRunReader reader)
/// PR #124203: Async methods without yield points may omit resumption stubs.
/// Validates that no-yield async methods still produce [ASYNC] variants.
///
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void RuntimeAsyncNoYield()
{
var runtimeAsyncNoYield = new CompiledAssembly
@@ -855,7 +840,7 @@ static void Validate(ReadyToRunReader reader)
/// --determinism-stress), each compiled method should have exactly one
/// ResumptionStubEntryPoint fixup.
///
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void RuntimeAsyncResumptionStubFixupDedup()
{
var asm = new CompiledAssembly
@@ -898,7 +883,7 @@ static void Validate(ReadyToRunReader reader)
/// PR #121679: MutableModule async references + cross-module inlining
/// of runtime-async methods with cross-module dependency.
///
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void RuntimeAsyncCrossModule()
{
var asyncDepLib = new CompiledAssembly
@@ -957,7 +942,7 @@ static void Validate(ReadyToRunReader reader)
/// Validates that inlining info (CrossModuleInlineInfo or InliningInfo2) is
/// properly populated (CompositeBasic only validates ManifestRef).
///
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void CompositeCrossModuleInlining()
{
var inlineableLib = new CompiledAssembly
@@ -999,7 +984,7 @@ static void Validate(ReadyToRunReader reader)
/// assemblies does NOT produce a CrossModuleInlineInfo section. CrossModuleInlineInfo only records
/// inlining where the inlinee module is outside the compiled image's version bubble
///
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void CompositeDoesNotProduceCrossModuleInliningInfo()
{
var inlineableLib = new CompiledAssembly
@@ -1046,7 +1031,7 @@ static void Validate(ReadyToRunReader reader)
/// comes from an assembly outside the version bubble (passed as a Reference with
/// --opt-cross-module).
///
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void CompositeProducesCrossModuleInliningInfoForExternalReference()
{
var inlineableLib = new CompiledAssembly
@@ -1098,7 +1083,7 @@ static void Validate(ReadyToRunReader reader)
/// Composite mode with runtime-async methods in both assemblies.
/// Validates async variants exist in composite output.
///
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void CompositeAsync()
{
var asyncCompositeLib = new CompiledAssembly
@@ -1143,7 +1128,7 @@ static void Validate(ReadyToRunReader reader)
/// Verifies that, in composite mode, awaitless async candidates ARE inlined into
/// their callers.
///
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void CompositeAsyncInliningMatrix()
{
var asyncInlineCandidatesLib = new CompiledAssembly
@@ -1193,7 +1178,7 @@ static void Validate(ReadyToRunReader reader)
/// https://github.com/dotnet/runtime/pull/126904 added support for ensuring the OwningType signature modifier is emitted
/// for these methods.
///
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void CompositeAsyncGenericTypes()
{
var asyncGenericTypeLib = new CompiledAssembly
@@ -1258,7 +1243,7 @@ static void Validate(ReadyToRunReader reader)
/// captures GC refs across await points. Validates that ContinuationLayout
/// fixups correctly reference cross-module types via MutableModule tokens.
///
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void AsyncCrossModuleContinuation()
{
var asyncDepLibCont = new CompiledAssembly
@@ -1313,7 +1298,7 @@ static void Validate(ReadyToRunReader reader)
/// Two-step compilation: composite A+B, then non-composite C referencing A.
/// Exercises the multi-compilation model.
///
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void MultiStepCompositeAndNonComposite()
{
var libA = new CompiledAssembly
@@ -1378,7 +1363,7 @@ public void MultiStepCompositeAndNonComposite()
/// Composite + runtime-async + cross-module devirtualization.
/// Interface defined in AsyncInterfaceLib, call sites in CompositeAsyncDevirtMain.
///
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void CompositeAsyncDevirtualize()
{
var asyncInterfaceLib = new CompiledAssembly
@@ -1426,7 +1411,7 @@ static void Validate(ReadyToRunReader reader)
/// devirtualizes to a sealed receiver. Resolving the callee's async-variant thunk must unwrap it
/// to the underlying EcmaMethod.
///
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void CompositeAsyncDevirtNonAsyncCallee()
{
// Compiled WITHOUT runtime-async so the awaited virtuals get synthesized async-variant thunks.
@@ -1473,7 +1458,7 @@ static void Validate(ReadyToRunReader reader)
/// Composite with 3 assemblies in A→B→C transitive chain.
/// Validates manifest refs for all three and transitive inlining.
///
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void CompositeTransitive()
{
var externalLib = new CompiledAssembly
@@ -1521,7 +1506,7 @@ static void Validate(ReadyToRunReader reader)
/// Non-composite runtime-async + transitive cross-module inlining.
/// Chain: AsyncTransitiveMain → AsyncTransitiveLib → AsyncExternalLib.
///
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void AsyncCrossModuleTransitive()
{
var asyncExternalLib = new CompiledAssembly
@@ -1582,7 +1567,7 @@ static void Validate(ReadyToRunReader reader)
/// Composite + runtime-async + transitive (3 assemblies).
/// Full combination of composite, async, and transitive references.
///
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void CompositeAsyncTransitive()
{
var asyncExternalLib = new CompiledAssembly
@@ -1641,7 +1626,7 @@ static void Validate(ReadyToRunReader reader)
/// Step 1: Composite of async libs. Step 2: Non-composite consumer
/// with cross-module inlining of async methods.
///
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void MultiStepCompositeAndNonCompositeAsync()
{
var asyncDepLib = new CompiledAssembly
@@ -1712,7 +1697,7 @@ public void MultiStepCompositeAndNonCompositeAsync()
/// CrossModuleInlineInfo section, exercising the absolute-index encoding
/// (not delta-encoded) for cross-module inliner entries.
///
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void CrossModuleGenericMultiInliner()
{
var crossModuleGenericLib = new CompiledAssembly
@@ -1758,7 +1743,7 @@ static void Validate(ReadyToRunReader reader)
}
}
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void VirtualMethodGenericsNonGVM()
{
var nonGvmLib = new CompiledAssembly
@@ -1803,7 +1788,7 @@ static void Validate(ReadyToRunReader reader)
}
}
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void VirtualMethodGenericsGVM()
{
var gvmLib = new CompiledAssembly
@@ -1848,7 +1833,7 @@ static void Validate(ReadyToRunReader reader)
}
}
- [Fact]
+ [ConditionalFact(typeof(TestPaths), nameof(TestPaths.IsNotWasmTarget))]
public void VirtualMethodGenericsGenericLookup()
{
var genericLookupLib = new CompiledAssembly
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 c1da793302ad01..059f522b6d0f34 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)),
};
@@ -83,29 +81,23 @@ internal sealed class R2RDriver
{
private static readonly TimeSpan ProcessTimeout = TimeSpan.FromMinutes(2);
private readonly ITestOutputHelper _output;
- private readonly TestPaths _paths;
- public R2RDriver(ITestOutputHelper output, TestPaths paths)
+ public R2RDriver(ITestOutputHelper output)
{
_output = output;
- _paths = paths;
-
- if (!File.Exists(_paths.Crossgen2Exe))
- throw new FileNotFoundException($"crossgen2 executable not found at {_paths.Crossgen2Exe}");
}
///
- /// Runs crossgen2 with the given arguments.
+ /// Runs the crossgen2 that compiles for this build's target RID with the given arguments.
///
public R2RCompilationResult Compile(List args)
{
- var fullArgs = new List(args);
- return RunCrossgen2(fullArgs);
+ return RunCrossgen2(TestPaths.Crossgen2Exe, new List(args));
}
- private R2RCompilationResult RunCrossgen2(List crossgen2Args)
+ private R2RCompilationResult RunCrossgen2(string crossgen2Exe, List crossgen2Args)
{
- var psi = new ProcessStartInfo(_paths.Crossgen2Exe, crossgen2Args)
+ var psi = new ProcessStartInfo(crossgen2Exe, crossgen2Args)
{
RedirectStandardOutput = true,
RedirectStandardError = true,
@@ -119,7 +111,7 @@ private R2RCompilationResult RunCrossgen2(List crossgen2Args)
psi.Environment[envVar] = null;
}
- string commandLine = $"{_paths.Crossgen2Exe} {string.Join(" ", crossgen2Args)}";
+ string commandLine = $"{crossgen2Exe} {string.Join(" ", crossgen2Args)}";
_output.WriteLine($" crossgen2 command: {commandLine}");
using var process = Process.Start(psi)!;
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 68fd1d518bd545..522472920c4f1d 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RResultChecker.cs
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RResultChecker.cs
@@ -1186,11 +1186,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)
@@ -1209,10 +1213,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 f466fd20d336e7..4fdb38bc20efbf 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RTestRunner.cs
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/R2RTestRunner.cs
@@ -180,12 +180,10 @@ public void SetOutputDir(string outputDir)
internal sealed class R2RTestRunner
{
private readonly ITestOutputHelper _output;
- private readonly TestPaths _paths;
public R2RTestRunner(ITestOutputHelper output)
{
_output = output;
- _paths = new TestPaths(output);
}
///
@@ -208,19 +206,19 @@ public void Run(R2RTestCase testCase)
var assemblyPaths = CompileAllAssemblies(assembliesToCompile);
// Step 2: Run each crossgen2 compilation and validate
- var driver = new R2RDriver(_output, _paths);
- var refPaths = BuildReferencePaths();
+ var driver = new R2RDriver(_output);
+ List refPaths = BuildReferencePaths();
foreach(var compilation in testCase.Compilations)
{
string outputPath = RunCrossgenCompilation(
- testCase.Name, compilation, driver, compilation.FilePath, refPaths, assemblyPaths);
+ testCase.Name, compilation, driver, compilation.FilePath, assemblyPaths);
if (compilation.Validate is not null)
{
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);
}
}
@@ -238,9 +236,10 @@ public void Run(R2RTestCase testCase)
private Dictionary CompileAllAssemblies(
IEnumerable assemblies)
{
- var compiler = new R2RTestCaseCompiler(_paths);
var paths = new Dictionary();
+ var defaultReferences = BuildReferencePaths();
+ var compiler = new R2RTestCaseCompiler(defaultReferences);
foreach (var asm in assemblies)
{
var sources = asm.SourceResourceNames
@@ -256,7 +255,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;
@@ -275,7 +274,6 @@ private static string RunCrossgenCompilation(
CrossgenCompilation compilation,
R2RDriver driver,
string outputFile,
- List refPaths,
Dictionary assemblyPaths)
{
var args = new List();
@@ -311,11 +309,13 @@ private static string RunCrossgenCompilation(
foreach (var option in compilation.Options)
args.Add(option.ToArg());
+ args.AddRange(["--targetos", TestPaths.TargetOS, "--targetarch", TestPaths.TargetArchitecture]);
+
// Caller-supplied raw args (for options that take values, e.g. --determinism-stress=N)
args.AddRange(compilation.AdditionalArgs);
- // Global refs (runtime pack + System.Private.CoreLib)
- AddRefArgs(args, refPaths);
+ // Global refs (shared framework + System.Private.CoreLib)
+ AddRefArgs(args);
EnsureDirectoryExists(Path.GetDirectoryName(outputFile));
@@ -330,27 +330,28 @@ private static string RunCrossgenCompilation(
return outputFile;
}
- private static void AddRefArgs(List args, List refPaths)
+ ///
+ /// Adds the shared framework references for crossgen2 as a single directory wildcard.
+ ///
+ private static void AddRefArgs(List args)
{
- foreach (string refPath in refPaths)
- {
- args.Add("-r");
- args.Add(refPath);
- }
+ args.Add("-r");
+ args.Add(Path.Combine(TestPaths.LibrariesDir, "*.dll"));
}
- private List BuildReferencePaths()
+ ///
+ /// Builds the explicit reference paths used for Roslyn compilation and for resolving assemblies
+ /// when reading back an R2R image, from the shared framework IL assemblies staged for this
+ /// build's target RID. crossgen2 takes the same assemblies as a wildcard; see .
+ ///
+ private static List BuildReferencePaths()
{
- var paths = new List();
-
- paths.Add(Path.Combine(_paths.RuntimePackDir, "*.dll"));
+ string librariesDir = TestPaths.LibrariesDir;
- string spcl = _paths.SystemPrivateCoreLibPath;
- Assert.True(File.Exists(spcl),
- $"System.Private.CoreLib.dll not found at '{spcl}'. " +
- $"Searched RuntimePackNativeDir='{_paths.RuntimePackNativeDir}' and " +
- $"CoreCLRArtifactsDir='{_paths.CoreCLRArtifactsDir}'");
- paths.Add(spcl);
+ List paths = [.. Directory.GetFiles(librariesDir, "*.dll")];
+ Assert.True(
+ paths.Exists(p => Path.GetFileName(p) == "System.Private.CoreLib.dll"),
+ $"System.Private.CoreLib.dll not found in staged references: {librariesDir}");
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 f028b442cf8e86..8df61102255e4f 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/TestPaths.cs
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCasesRunner/TestPaths.cs
@@ -2,225 +2,83 @@
// 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;
-using Xunit.Abstractions;
namespace ILCompiler.ReadyToRun.Tests.TestCasesRunner;
///
-/// Provides paths to build artifacts needed by the test infrastructure.
-/// All paths come from RuntimeHostConfigurationOption items in the csproj.
+/// Provides paths to build artifacts needed by the test infrastructure, and the target and host
+/// predicates that gate test cases.
///
-internal sealed class TestPaths
+internal static class TestPaths
{
- private readonly ITestOutputHelper _output;
-
- public TestPaths(ITestOutputHelper output)
- {
- _output = output;
- }
-
private static string GetRequiredConfig(string key)
{
return AppContext.GetData(key) as string
?? 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;
+ private static string Crossgen2ExeName => RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "crossgen2.exe" : "crossgen2";
- 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;
- }
- }
+ public static string SystemPrivateCoreLibPath => Path.Combine(LibrariesDir, "System.Private.CoreLib.dll");
- return dir;
- }
+ public static string TargetOS => GetRequiredConfig("R2RTest.TargetOS");
+ public static string TargetArchitecture => GetRequiredConfig("R2RTest.TargetArchitecture");
- ///
- /// 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;
+ private static string TargetRid => $"{TargetOS}-{TargetArchitecture}";
- 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;
- }
- }
+ public static bool IsWasmTarget => TargetArchitecture == "wasm";
- return dir;
- }
+ public static bool IsNotWasmTarget => !IsWasmTarget;
- ///
- /// 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 static bool IsArmTarget => TargetArchitecture is "arm" or "armel";
- return dir;
- }
- }
+ public static bool IsWindowsTarget => TargetOS is "windows" or "win";
- private static string Crossgen2ExeName =>
- RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "crossgen2.exe" : "crossgen2";
+ public static bool IsIosArm64Target => TargetOS is "ios" && TargetArchitecture is "arm64";
- ///
- /// Path to the self-contained crossgen2 executable (from crossgen2_inbuild).
- ///
- public string Crossgen2Exe => Path.Combine(Crossgen2Dir, Crossgen2ExeName);
+ public static bool IsWindowsHost => OperatingSystem.IsWindows();
///
- /// 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 crossgen2 that compiles for this build's target.
///
- public string RuntimePackDir
+ public static string Crossgen2Exe
{
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.
- ///
- public string RuntimePackNativeDir
- {
- get
- {
- string dir = GetRequiredConfig("R2RTest.RuntimePackNativeDir");
- return ProbeConfigFallback(dir);
- }
- }
-
- ///
- /// Path to System.Private.CoreLib.dll. It lives in the runtime pack native/ dir in full builds
- /// (placed by externals.csproj BinPlace during libs.pretest), but partial builds that skip
- /// libs.pretest only have it in the CoreCLR artifacts directory.
- ///
- public string SystemPrivateCoreLibPath
- {
- get
- {
- string path = Path.Combine(RuntimePackNativeDir, "System.Private.CoreLib.dll");
- if (!File.Exists(path))
+ string exe = Path.Combine(AppContext.BaseDirectory, "crossgen2", Crossgen2ExeName);
+ if (!File.Exists(exe))
{
- string fallback = Path.Combine(CoreCLRArtifactsDir, "System.Private.CoreLib.dll");
- if (File.Exists(fallback))
- {
- _output.WriteLine($"[TestPaths] '{path}' not found; falling back to '{fallback}'");
- return fallback;
- }
+ throw new FileNotFoundException(
+ $"No crossgen2 staged for {TargetRid} at '{exe}'. Build the clr and libs subsets for " +
+ $"{TargetRid}, then rebuild this test project.");
}
- return path;
- }
- }
-
- ///
- /// 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.
- ///
- public string CoreCLRArtifactsDir
- {
- get
- {
- string dir = GetRequiredConfig("R2RTest.CoreCLRArtifactsDir");
- return ProbeDottedConfigFallback(dir);
+ return exe;
}
}
- 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;
-
///
- /// Path to the reference assembly pack (for Roslyn compilation).
- /// e.g. artifacts/bin/microsoft.netcore.app.ref/ref/net11.0/
+ /// Directory holding the shared framework IL assemblies crossgen2 compiles against.
///
- public string RefPackDir
+ public static string LibrariesDir
{
get
{
- string dir = GetRequiredConfig("R2RTest.RefPackDir");
+ string dir = Path.Combine(AppContext.BaseDirectory, "libraries");
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;
- }
- }
- }
+ throw new DirectoryNotFoundException(
+ $"No shared framework assemblies staged for {TargetRid} at '{dir}'. Build the clr and " +
+ $"libs subsets for {TargetRid}, then rebuild this test project.");
}
return dir;
}
}
- ///
- /// 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}");
-
- 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/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/WasmArgumentLayoutTests.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/WasmArgumentLayoutTests.cs
index 2629202df34758..ec327918b2f1ef 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/WasmArgumentLayoutTests.cs
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/WasmArgumentLayoutTests.cs
@@ -26,8 +26,12 @@ namespace ILCompiler.ReadyToRun.Tests;
///
/// Unit tests for the wasm argument layout crossgen2 computes. These drive the compiler's type
-/// system directly, so they need neither a wasm JIT nor a runtime to execute against.
+/// system directly, so they need neither a wasm JIT nor a runtime to execute against. They do
+/// need a wasm System.Private.CoreLib, though: the type system context they build is always a
+/// wasm one, but the corelib it reads comes from whatever the outer build targets, so on any
+/// other target they would be computing wasm layouts from the wrong assembly.
///
+[ConditionalClass(typeof(TestPaths), nameof(TestPaths.IsWasmTarget))]
public class WasmArgumentLayoutTests
{
private const string Vector128OfT = "Vector128`1";
@@ -548,7 +552,7 @@ private static MethodSignature MakeProbeSignature(ReadyToRunCompilerContext cont
///
private ReadyToRunCompilerContext CreateWasmContext()
{
- string coreLibPath = new TestPaths(_output).SystemPrivateCoreLibPath;
+ string coreLibPath = TestPaths.SystemPrivateCoreLibPath;
Assert.True(File.Exists(coreLibPath), $"System.Private.CoreLib.dll not found at '{coreLibPath}'");
InstructionSetSupport instructionSetSupport = new(default, default, TargetArchitecture.Wasm32);