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. 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..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,14 +124,8 @@ GetUnixCrossBuildArgumentsForDNNE" BeforeTargets="DnneBuildNativeExports"> - $([System.IO.Path]::GetDirectoryName('$(AppHostSourcePath)')) - - - - - - $([MSBuild]::NormalizePath('$(BootstrapRidGraphDir)', 'runtime.json')) + $(DotNetHostBinDir.TrimEnd('/\')) + $([System.IO.Path]::GetDirectoryName('$(AppHostSourcePath)')) diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index bff3061df6e50c..173cef6db3fd27 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -820,7 +820,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..3be09c549dda98 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..884ccfcddb0f79 100644 --- a/src/tests/build.proj +++ b/src/tests/build.proj @@ -173,8 +173,9 @@ <_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 @@ -231,6 +232,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 +274,7 @@ diff --git a/src/tests/build.sh b/src/tests/build.sh index f18f28ee740369..5ab584991f15cc 100755 --- a/src/tests/build.sh +++ b/src/tests/build.sh @@ -157,6 +157,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.") @@ -225,6 +226,10 @@ handle_arguments_local() { __UnprocessedBuildArgs+=("/p:CLRTestBuildAllTargets=allTargets") ;; + use-bootstrap|-use-bootstrap) + __UnprocessedBuildArgs+=("/p:UseBootstrap=true") + ;; + rebuild|-rebuild) __RebuildTests=1 ;;