From 2027b1c6e6f8658a460f22677be44891cfd2f200 Mon Sep 17 00:00:00 2001 From: Adeel <3840695+am11@users.noreply.github.com> Date: Thu, 7 May 2026 15:04:23 +0300 Subject: [PATCH 1/8] Enable test builds with --bootstrap --- eng/targetingpacks.targets | 2 +- src/libraries/Directory.Build.props | 4 ++++ .../tests/TestAssets/NativeExports/NativeExports.csproj | 9 +-------- src/libraries/tests.proj | 2 +- src/tests/Common/Directory.Build.targets | 2 ++ src/tests/Directory.Build.props | 4 ++++ src/tests/Directory.Build.targets | 1 + src/tests/build.proj | 6 +++--- src/tests/build.sh | 5 +++++ 9 files changed, 22 insertions(+), 13 deletions(-) diff --git a/eng/targetingpacks.targets b/eng/targetingpacks.targets index 978a6c5c89ac28..aeca52efb4c054 100644 --- a/eng/targetingpacks.targets +++ b/eng/targetingpacks.targets @@ -86,7 +86,7 @@ ExcludedRuntimeIdentifiers="android" AppHostPackNamePattern="$(LocalFrameworkOverrideName).Host.**RID**" AppHostPackVersion="$(ProductVersion)" - AppHostRuntimeIdentifiers="linux-arm;linux-arm64;linux-musl-arm64;linux-musl-x64;linux-x64;osx-x64;rhel.6-x64;tizen.4.0.0-armel;tizen.5.0.0-armel;win-arm64;win-x64;win-x86;linux-musl-arm;osx-arm64;linux-s390x;linux-bionic-arm;linux-bionic-arm64;linux-bionic-x64;linux-bionic-x86;linux-ppc64le;linux-riscv64;linux-musl-riscv64;linux-loongarch64;linux-musl-loongarch64" + AppHostRuntimeIdentifiers="linux-arm;linux-arm64;linux-musl-arm64;linux-musl-x64;linux-x64;osx-x64;rhel.6-x64;tizen.4.0.0-armel;tizen.5.0.0-armel;win-arm64;win-x64;win-x86;linux-musl-arm;osx-arm64;linux-s390x;linux-bionic-arm;linux-bionic-arm64;linux-bionic-x64;linux-bionic-x86;freebsd-x64;freebsd-arm64;openbsd-x64;openbsd-arm64;illumos-x64;solaris-x64;haiku-x64;linux-ppc64le;linux-riscv64;linux-musl-riscv64;linux-loongarch64;linux-musl-loongarch64" TargetFramework="$(NetCoreAppCurrent)" Condition="'$(UseLocalAppHostPack)' == 'true' and '@(KnownAppHostPack->AnyHaveMetadataValue('TargetFramework', '$(NetCoreAppCurrent)'))' != 'true'" /> diff --git a/src/libraries/Directory.Build.props b/src/libraries/Directory.Build.props index 95fcf08b1bafa1..55c4d486fbd14a 100644 --- a/src/libraries/Directory.Build.props +++ b/src/libraries/Directory.Build.props @@ -11,6 +11,10 @@ + + true + + $(RepositoryEngineeringDir)BeforeTargetFrameworkInference.targets $(RepositoryEngineeringDir)LicenseHeader.txt diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj index 1bf4d2d611c556..4bb45f4bf89917 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj @@ -124,14 +124,7 @@ GetUnixCrossBuildArgumentsForDNNE" BeforeTargets="DnneBuildNativeExports"> - $([System.IO.Path]::GetDirectoryName('$(AppHostSourcePath)')) - - - - - - $([MSBuild]::NormalizePath('$(BootstrapRidGraphDir)', 'runtime.json')) + $(DotNetHostBinDir) diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index c3a6d07d77d383..3a3a9f626d3ee3 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -821,7 +821,7 @@ + AdditionalProperties="%(AdditionalProperties);_IsPublishing=true;Configuration=Release;CoreCLRConfiguration=$(CoreCLRConfiguration);LibrariesConfiguration=$(LibrariesConfiguration);TasksConfiguration=$(TasksConfiguration);ToolsConfiguration=$(ToolsConfiguration);PublishDir=$(XUnitLogCheckerLibrariesOutDir);ROOTFS_DIR=$(ROOTFS_DIR);RuntimeIdentifier=$(TargetRid);UseBootstrap=$(UseBootstrap)" /> + + false diff --git a/src/tests/Directory.Build.props b/src/tests/Directory.Build.props index b6dce9ef455492..3c9c5f152e8183 100644 --- a/src/tests/Directory.Build.props +++ b/src/tests/Directory.Build.props @@ -8,6 +8,10 @@ + + true + + true diff --git a/src/tests/Directory.Build.targets b/src/tests/Directory.Build.targets index c9a5138af52d8a..a8788cfe4afcdf 100644 --- a/src/tests/Directory.Build.targets +++ b/src/tests/Directory.Build.targets @@ -517,6 +517,7 @@ + diff --git a/src/tests/build.proj b/src/tests/build.proj index e8455e5df74964..6a361422800552 100644 --- a/src/tests/build.proj +++ b/src/tests/build.proj @@ -173,8 +173,7 @@ <_RestoreProperties>MSBuildRestoreSessionId=$([System.Guid]::NewGuid());TargetOS=$(TargetOS);TargetArchitecture=$(TargetArchitecture);Configuration=$(Configuration);CrossBuild=$(CrossBuild);SetTFMForRestore=true;RuntimeIdentifier=$(RuntimeIdentifier) - <_RestoreProperties Condition="'$(UseLocalAppHostPack)' == 'true' or '$(TargetOS)' == 'browser'">$(_RestoreProperties);EnableAppHostPackDownload=false;EnableTargetingPackDownload=false;EnableRuntimePackDownload=false - <_RestoreProperties Condition="'$(TargetsAppleMobile)' == 'true'">$(_RestoreProperties);RestoreUseStaticGraphEvaluation=false + <_RestoreProperties Condition="'$(UseBootstrap)' == 'true'">$(_RestoreProperties);UseBootstrap=true @@ -231,6 +230,7 @@ $(GroupBuildCmd) "/p:PackageOS=$(PackageOS)" $(GroupBuildCmd) "/p:RuntimeFlavor=$(RuntimeFlavor)" $(GroupBuildCmd) "/p:RuntimeVariant=$(RuntimeVariant)" + $(GroupBuildCmd) "/p:UseBootstrap=true" $(GroupBuildCmd) "/p:ServerGarbageCollection=$(ServerGarbageCollection)" $(GroupBuildCmd) "/p:CLRTestBuildAllTargets=$(CLRTestBuildAllTargets)" $(GroupBuildCmd) "/p:UseCodeFlowEnforcement=$(UseCodeFlowEnforcement)" @@ -272,7 +272,7 @@ diff --git a/src/tests/build.sh b/src/tests/build.sh index a0709d7386517c..bc13c9fbc09e1a 100755 --- a/src/tests/build.sh +++ b/src/tests/build.sh @@ -151,6 +151,7 @@ usage_list+=("-nativeaot - Builds the tests for Native AOT compilation.") usage_list+=("-priority1 - Include priority=1 tests in the build.") usage_list+=("-perfmap - Emit perfmap symbol files when compiling the framework assemblies using Crossgen2.") usage_list+=("-allTargets - Build managed tests for all target platforms (including test projects in which CLRTestTargetUnsupported resolves to true).") +usage_list+=("-use-bootstrap - Use artifacts produced by the bootstrap subset for local targeting, runtime, and apphost packs.") usage_list+=("") usage_list+=("-runtests - Run tests after building them.") usage_list+=("-mono, -excludemonofailures - Build the tests for the Mono runtime honoring mono-specific issues.") @@ -218,6 +219,10 @@ handle_arguments_local() { __UnprocessedBuildArgs+=("/p:CLRTestBuildAllTargets=allTargets") ;; + use-bootstrap|-use-bootstrap) + __UnprocessedBuildArgs+=("/p:UseBootstrap=true") + ;; + rebuild|-rebuild) __RebuildTests=1 ;; From 6802573882d0f52e9fecb69efb933f89eabeb1f0 Mon Sep 17 00:00:00 2001 From: Adeel Mujahid <3840695+am11@users.noreply.github.com> Date: Thu, 7 May 2026 17:02:29 +0300 Subject: [PATCH 2/8] Trim trailing slash for windows --- .../tests/TestAssets/NativeExports/NativeExports.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj index 4bb45f4bf89917..ef5f42023f6f66 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj @@ -124,7 +124,7 @@ GetUnixCrossBuildArgumentsForDNNE" BeforeTargets="DnneBuildNativeExports"> - $(DotNetHostBinDir) + $(DotNetHostBinDir.TrimEnd('\/')) From 93488b22a599e227ad6ef04aad79fbc29760c8ef Mon Sep 17 00:00:00 2001 From: Adeel Mujahid <3840695+am11@users.noreply.github.com> Date: Thu, 7 May 2026 18:59:20 +0300 Subject: [PATCH 3/8] Add missing condition --- src/tests/Common/Directory.Build.targets | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tests/Common/Directory.Build.targets b/src/tests/Common/Directory.Build.targets index b55acf0eac33fd..c4ae15d47fb260 100644 --- a/src/tests/Common/Directory.Build.targets +++ b/src/tests/Common/Directory.Build.targets @@ -10,8 +10,8 @@ - - + + false From ca29f1620ed15fbfaee3146a7b42b1dc848429a1 Mon Sep 17 00:00:00 2001 From: Adeel Mujahid <3840695+am11@users.noreply.github.com> Date: Thu, 7 May 2026 20:54:20 +0300 Subject: [PATCH 4/8] Fix win --- .../tests/TestAssets/NativeExports/NativeExports.csproj | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj index ef5f42023f6f66..aeb3de9ecc6860 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj @@ -124,7 +124,8 @@ GetUnixCrossBuildArgumentsForDNNE" BeforeTargets="DnneBuildNativeExports"> - $(DotNetHostBinDir.TrimEnd('\/')) + $(DotNetHostBinDir.TrimEnd('/\')) + $([System.IO.Path]::GetDirectoryName('$(AppHostSourcePath)')) From 8369bdcbfd809d861fa756c67b2f9c71cc32d42a Mon Sep 17 00:00:00 2001 From: Adeel Mujahid <3840695+am11@users.noreply.github.com> Date: Thu, 7 May 2026 21:56:05 +0300 Subject: [PATCH 5/8] Add another condition --- src/tests/Directory.Build.targets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/Directory.Build.targets b/src/tests/Directory.Build.targets index a8788cfe4afcdf..3be09c549dda98 100644 --- a/src/tests/Directory.Build.targets +++ b/src/tests/Directory.Build.targets @@ -517,7 +517,7 @@ - + From cb12c3421bab8ac5231fe9eb2249266079948888 Mon Sep 17 00:00:00 2001 From: Adeel <3840695+am11@users.noreply.github.com> Date: Fri, 8 May 2026 02:05:05 +0300 Subject: [PATCH 6/8] Fix wasm --- src/tests/build.proj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tests/build.proj b/src/tests/build.proj index 6a361422800552..767c50ae78cc1b 100644 --- a/src/tests/build.proj +++ b/src/tests/build.proj @@ -173,6 +173,8 @@ <_RestoreProperties>MSBuildRestoreSessionId=$([System.Guid]::NewGuid());TargetOS=$(TargetOS);TargetArchitecture=$(TargetArchitecture);Configuration=$(Configuration);CrossBuild=$(CrossBuild);SetTFMForRestore=true;RuntimeIdentifier=$(RuntimeIdentifier) + <_RestoreProperties Condition="'$(UseLocalAppHostPack)' == 'true' or '$(TargetOS)' == 'browser'">$(_RestoreProperties);EnableAppHostPackDownload=false;EnableTargetingPackDownload=false;EnableRuntimePackDownload=false + <_RestoreProperties Condition="'$(TargetsAppleMobile)' == 'true'">$(_RestoreProperties);RestoreUseStaticGraphEvaluation=false <_RestoreProperties Condition="'$(UseBootstrap)' == 'true'">$(_RestoreProperties);UseBootstrap=true From 5749142df77eb55ea5a040ae213a787d3c56dfa5 Mon Sep 17 00:00:00 2001 From: Adeel <3840695+am11@users.noreply.github.com> Date: Fri, 8 May 2026 02:08:07 +0300 Subject: [PATCH 7/8] . --- src/tests/build.proj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/build.proj b/src/tests/build.proj index 767c50ae78cc1b..884ccfcddb0f79 100644 --- a/src/tests/build.proj +++ b/src/tests/build.proj @@ -173,7 +173,7 @@ <_RestoreProperties>MSBuildRestoreSessionId=$([System.Guid]::NewGuid());TargetOS=$(TargetOS);TargetArchitecture=$(TargetArchitecture);Configuration=$(Configuration);CrossBuild=$(CrossBuild);SetTFMForRestore=true;RuntimeIdentifier=$(RuntimeIdentifier) - <_RestoreProperties Condition="'$(UseLocalAppHostPack)' == 'true' or '$(TargetOS)' == 'browser'">$(_RestoreProperties);EnableAppHostPackDownload=false;EnableTargetingPackDownload=false;EnableRuntimePackDownload=false + <_RestoreProperties Condition="'$(TargetOS)' == 'browser'">$(_RestoreProperties);EnableAppHostPackDownload=false;EnableTargetingPackDownload=false;EnableRuntimePackDownload=false <_RestoreProperties Condition="'$(TargetsAppleMobile)' == 'true'">$(_RestoreProperties);RestoreUseStaticGraphEvaluation=false <_RestoreProperties Condition="'$(UseBootstrap)' == 'true'">$(_RestoreProperties);UseBootstrap=true From 8b2760b67b4ce17ed54143fd1d1d058fc69982ae Mon Sep 17 00:00:00 2001 From: Adeel <3840695+am11@users.noreply.github.com> Date: Fri, 8 May 2026 23:51:37 +0300 Subject: [PATCH 8/8] Update docs --- .../building/coreclr/cross-building.md | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/docs/workflow/building/coreclr/cross-building.md b/docs/workflow/building/coreclr/cross-building.md index 04b5640f7e32e6..6188026f1387a8 100644 --- a/docs/workflow/building/coreclr/cross-building.md +++ b/docs/workflow/building/coreclr/cross-building.md @@ -14,6 +14,8 @@ * [Cross-Building using Docker](#cross-building-using-docker) * [Cross-Compiling for ARM32 and ARM64 with Docker](#cross-compiling-for-arm32-and-arm64-with-docker) * [Cross-Compiling for FreeBSD with Docker](#cross-compiling-for-freebsd-with-docker) + * [Building CoreCLR with Bootstrapping](#building-coreclr-with-bootstrapping) + * [Building Tests with Bootstrapping](#building-tests-with-bootstrapping) This guide will go more in-depth on how to do cross-building across multiple operating systems and architectures. It's worth mentioning this is not an any-to-any scenario. Only the combinations explained here are possible/supported. If/When any other combinations get supported/discovered, this document will get updated accordingly. @@ -183,3 +185,100 @@ To build the bootstrap subset of the runtime repo, you can build the `bootstrap` For simplicity, a `--bootstrap` option is also provided. This option will build the `bootstrap` subset, clean up the artifacts directory, and then build the runtime repo with the `--use-bootstrap` option. This is useful for building the runtime repo with the live NativeAOT version without having to run two separate commands. The `--bootstrap` option is automatically specified when building the runtime repo for .NET Source Build, as the vast majority of Source Build scenarios use non-portable RIDs. + +### Building Tests with Bootstrapping + +For community-supported platforms where Microsoft does not publish targeting/runtime/apphost packs (e.g. FreeBSD, illumos, Haiku, linux-riscv64, linux-loongarch64, linux-ppc64le), the test builds need to consume the locally-built bootstrap artifacts instead of trying to download packs from NuGet. Both CoreCLR runtime tests and libraries tests support this via the `--use-bootstrap` flag. + +The steps below use FreeBSD ARM64 as an example. The same flow applies to any other community-supported target by swapping `--os`/`--arch` and the docker image. + +#### Building in the Container + +Start the cross-build container: + +```bash +docker run --rm -it \ + -v $(pwd):/runtime \ + -w /runtime \ + -e ROOTFS_DIR=/crossrootfs/arm64 \ + mcr.microsoft.com/dotnet-buildtools/prereqs:azurelinux-3.0-net11.0-cross-freebsd-14-arm64 \ + bash +``` + +Inside the container, set the target and build the product, then the tests: + +```bash +os=freebsd +arch=arm64 + +# Initial product build (also produces the bootstrap subset). +./build.sh clr+libs --cross --arch $arch --os $os --bootstrap + +# Subsequent rebuilds (e.g. after editing code) reuse the existing bootstrap. +./build.sh clr+libs --cross --arch $arch --os $os --use-bootstrap + +# CoreCLR runtime tests. +src/tests/build.sh -cross -$arch -$os -p:LibrariesConfiguration=Debug --use-bootstrap + +# Libraries tests (produces zipped per-library test archives under artifacts/helix/tests/). +./build.sh libs.tests --cross --arch $arch --os $os --use-bootstrap -p:ArchiveTests=true +``` + +Without `--use-bootstrap`, restore would fail with `NU1102` errors because the apphost/runtime/targeting packs for `freebsd-arm64` are not published to NuGet feeds. + +#### Running CoreCLR Runtime Tests on the Target + +From the host machine, pack and upload `artifacts/tests/coreclr/..Debug` to the target: + +```bash +tar -czf coreclr-tests-freebsd-arm64-Debug.tar.gz artifacts/tests/coreclr/freebsd.arm64.Debug +scp coreclr-tests-freebsd-arm64-Debug.tar.gz $TargetMachine:/tmp +``` + +On the target machine, extract and run a test. For example, the interpreter tests: + +```bash +ssh $TargetMachine + +mkdir coreclr-tests && cd $_ +tar -xzf /tmp/coreclr-tests-freebsd-arm64-Debug.tar.gz + +CORE_ROOT=$(pwd)/artifacts/tests/coreclr/freebsd.arm64.Debug/Tests/Core_Root \ + DOTNET_TieredCompilation=0 \ + artifacts/tests/coreclr/freebsd.arm64.Debug/JIT/Interpreter/InterpreterTester/InterpreterTester.sh +``` + +Exit code `100` means pass; any other value means fail. + +#### Running Libraries Tests on the Target + +Libraries tests need the test host (`artifacts/bin/testhost/...`) plus the per-library test archive. From the host machine: + +```bash +# Pack and upload the test host. +tar -czf testhost_net11.0-freebsd-Debug-arm64.tar.gz artifacts/bin/testhost/net11.0-freebsd-Debug-arm64 +scp testhost_net11.0-freebsd-Debug-arm64.tar.gz $TargetMachine:/tmp + +# Copy a specific test's archive (paths and names vary; this example uses System.Text.RegularExpressions). +scp artifacts/helix/tests/freebsd.AnyCPU.Debug/System.Text.RegularExpressions.Unit.Tests.zip $TargetMachine:/tmp +``` + +On the target machine: + +```bash +ssh $TargetMachine + +mkdir testhost +tar -xzf /tmp/testhost_net11.0-freebsd-Debug-arm64.tar.gz -C testhost + +mkdir regex-tests && cd $_ +unzip /tmp/System.Text.RegularExpressions.Unit.Tests.zip + +./RunTests.sh --runtime-path ~/testhost/artifacts/bin/testhost/net11.0-freebsd-Debug-arm64 +``` + +#### Notes + +* `--use-bootstrap` works on any platform; on community-supported platforms it is the only way to build the tests because the targeting/runtime/apphost packs are not published to NuGet feeds. +* If restore still fails after passing the flag, double-check that the `bootstrap` subset built successfully and produced `artifacts/bin/bootstrap/`. +* Building/packing an individual library test project (e.g. `./dotnet.sh build src/libraries/System.Formats.Nrbf/tests -p:UseBootstrap=true -p:ArchiveTests=true ...`) currently produces an unusable archive (missing `xunit.console.runtimeconfig.json` and similar). Until that is fixed, build the whole `libs.tests` subset as shown above.