From 1ec37370035fb5f2f667b3f876b4c579cf651b2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaury=20Lev=C3=A9?= Date: Thu, 29 Oct 2026 14:47:13 +0100 Subject: [PATCH 01/60] Enable staged native Bazel builds and validation Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .bazelignore | 4 + .bazelrc | 11 + .bazelversion | 1 + .github/workflows/bazel.yml | 53 ++ .gitignore | 4 + BUILD.bazel | 204 +++++ MODULE.bazel | 48 + MODULE.bazel.lock | 313 +++++++ README.md | 1 + docs/bazel.md | 192 ++++ docs/decisions/bazel-build.md | 295 +++++++ docs/dev-guide.md | 4 + eng/bazel.ps1 | 80 ++ eng/bazel/.gitignore | 1 + eng/bazel/BUILD.bazel | 29 + eng/bazel/BuildTools.cs | 183 ++++ eng/bazel/GlobalUsings.cs | 24 + eng/bazel/TestMain.cs | 41 + eng/bazel/analyzers.bzl | 67 ++ eng/bazel/analyzers.globalconfig | 3 + eng/bazel/defs.bzl | 277 ++++++ eng/bazel/extensions.bzl | 240 +++++ eng/bazel/mstest.bzl | 126 +++ eng/bazel/nuget/BUILD.bazel | 1 + eng/bazel/nuget/paket.analyzers.bzl | 104 +++ eng/bazel/nuget/paket.analyzers_extension.bzl | 11 + eng/bazel/nuget/paket.generator.bzl | 22 + eng/bazel/nuget/paket.generator_extension.bzl | 11 + eng/bazel/nuget/paket.main.bzl | 22 + eng/bazel/nuget/paket.main_extension.bzl | 11 + eng/bazel/nuget/paket.source.bzl | 70 ++ eng/bazel/nuget/paket.source_extension.bzl | 11 + eng/bazel/paket.dependencies | 60 ++ eng/bazel/paket.lock | 823 ++++++++++++++++++ eng/bazel/patches/BUILD.bazel | 11 + .../framework-reference-priority.patch | 11 + .../patches/generated-resource-names.patch | 8 + eng/bazel/patches/pdb-runfiles.patch | 6 + eng/bazel/patches/quote-csharp-sources.patch | 7 + .../patches/reference-only-analyzers.patch | 10 + eng/bazel/patches/satellite-assemblies.patch | 42 + eng/bazel/patches/short-launcher-name.patch | 6 + eng/bazel/patches/unique-analyzers.patch | 13 + eng/bazel/patches/windows-launcher.patch | 30 + eng/bazel/platform.bzl | 205 +++++ eng/bazel/server-client.bzl | 70 ++ eng/bazel/tests.bzl | 118 +++ eng/bazel/update-dependencies.ps1 | 56 ++ eng/bazel/validate.ps1 | 159 ++++ .../TestingPlatformExplorer/BUILD.bazel | 14 + .../TestingPlatformExplorer/README.md | 7 + .../BuildToolsTests.cs | 232 +++++ 52 files changed, 4352 insertions(+) create mode 100644 .bazelignore create mode 100644 .bazelrc create mode 100644 .bazelversion create mode 100644 .github/workflows/bazel.yml create mode 100644 BUILD.bazel create mode 100644 MODULE.bazel create mode 100644 MODULE.bazel.lock create mode 100644 docs/bazel.md create mode 100644 docs/decisions/bazel-build.md create mode 100644 eng/bazel.ps1 create mode 100644 eng/bazel/.gitignore create mode 100644 eng/bazel/BUILD.bazel create mode 100644 eng/bazel/BuildTools.cs create mode 100644 eng/bazel/GlobalUsings.cs create mode 100644 eng/bazel/TestMain.cs create mode 100644 eng/bazel/analyzers.bzl create mode 100644 eng/bazel/analyzers.globalconfig create mode 100644 eng/bazel/defs.bzl create mode 100644 eng/bazel/extensions.bzl create mode 100644 eng/bazel/mstest.bzl create mode 100644 eng/bazel/nuget/BUILD.bazel create mode 100644 eng/bazel/nuget/paket.analyzers.bzl create mode 100644 eng/bazel/nuget/paket.analyzers_extension.bzl create mode 100644 eng/bazel/nuget/paket.generator.bzl create mode 100644 eng/bazel/nuget/paket.generator_extension.bzl create mode 100644 eng/bazel/nuget/paket.main.bzl create mode 100644 eng/bazel/nuget/paket.main_extension.bzl create mode 100644 eng/bazel/nuget/paket.source.bzl create mode 100644 eng/bazel/nuget/paket.source_extension.bzl create mode 100644 eng/bazel/paket.dependencies create mode 100644 eng/bazel/paket.lock create mode 100644 eng/bazel/patches/BUILD.bazel create mode 100644 eng/bazel/patches/framework-reference-priority.patch create mode 100644 eng/bazel/patches/generated-resource-names.patch create mode 100644 eng/bazel/patches/pdb-runfiles.patch create mode 100644 eng/bazel/patches/quote-csharp-sources.patch create mode 100644 eng/bazel/patches/reference-only-analyzers.patch create mode 100644 eng/bazel/patches/satellite-assemblies.patch create mode 100644 eng/bazel/patches/short-launcher-name.patch create mode 100644 eng/bazel/patches/unique-analyzers.patch create mode 100644 eng/bazel/patches/windows-launcher.patch create mode 100644 eng/bazel/platform.bzl create mode 100644 eng/bazel/server-client.bzl create mode 100644 eng/bazel/tests.bzl create mode 100644 eng/bazel/update-dependencies.ps1 create mode 100644 eng/bazel/validate.ps1 create mode 100644 samples/public/TestingPlatformExamples/TestingPlatformExplorer/BUILD.bazel create mode 100644 test/UnitTests/Bazel.BuildTools.UnitTests/BuildToolsTests.cs diff --git a/.bazelignore b/.bazelignore new file mode 100644 index 0000000000..c4e2cfdb2f --- /dev/null +++ b/.bazelignore @@ -0,0 +1,4 @@ +.dotnet +.packages +artifacts +packages diff --git a/.bazelrc b/.bazelrc new file mode 100644 index 0000000000..9e29df640d --- /dev/null +++ b/.bazelrc @@ -0,0 +1,11 @@ +startup --windows_enable_symlinks +common --enable_bzlmod +common --enable_runfiles +common --incompatible_strict_action_env +build --@rules_dotnet//dotnet:target_framework=net10.0 +# Preserve SDK-style transitive ProjectReference/PackageReference compilation. +build --@rules_dotnet//dotnet/settings:strict_deps=false +build --verbose_failures +test --test_output=errors + +try-import %workspace%/.bazelrc.local diff --git a/.bazelversion b/.bazelversion new file mode 100644 index 0000000000..11f1d47dac --- /dev/null +++ b/.bazelversion @@ -0,0 +1 @@ +8.8.2 diff --git a/.github/workflows/bazel.yml b/.github/workflows/bazel.yml new file mode 100644 index 0000000000..32722ba8fa --- /dev/null +++ b/.github/workflows/bazel.yml @@ -0,0 +1,53 @@ +name: Experimental Bazel build + +on: + pull_request: + paths: + - '.bazel*' + - 'BUILD.bazel' + - 'MODULE.bazel*' + - 'eng/bazel.ps1' + - 'eng/bazel/**' + - 'eng/Versions.props' + - '.editorconfig' + - 'src/**' + - 'test/**' + - 'samples/public/mstest-runner/Simple1/**' + - 'samples/public/TestingPlatformExamples/TestingPlatformExplorer/**' + - '.github/workflows/bazel.yml' + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: bazel-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + baseline: + name: Native Bazel baseline (${{ matrix.os }}) + strategy: + fail-fast: false + matrix: + os: [windows-latest, ubuntu-latest] + runs-on: ${{ matrix.os }} + timeout-minutes: 30 + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + - name: Build, test, and validate native consumers + shell: pwsh + run: .\eng\bazel\validate.ps1 + - name: Preserve baseline evidence + if: always() + uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2 + with: + name: bazel-${{ matrix.os }} + path: artifacts/bazel-validation/ + if-no-files-found: warn + - name: Stop the worktree's Bazel server + if: always() + shell: pwsh + run: .\eng\bazel.ps1 shutdown diff --git a/.gitignore b/.gitignore index 2c13d6cc2d..dfafde2105 100644 --- a/.gitignore +++ b/.gitignore @@ -88,6 +88,10 @@ ehthumbs.db /.dotnet/ /TestAssets/ +# Bazel output symlinks/junctions and local overrides +/bazel-*/ +/.bazelrc.local + # Lean build artifacts .lake/ diff --git a/BUILD.bazel b/BUILD.bazel new file mode 100644 index 0000000000..55a923100a --- /dev/null +++ b/BUILD.bazel @@ -0,0 +1,204 @@ +load("@rules_dotnet//dotnet:defs.bzl", "csharp_binary") +load("//eng/bazel:analyzers.bzl", "analyzer_libraries") +load("//eng/bazel:defs.bzl", "testfx_binary", "testfx_test") +load("//eng/bazel:extensions.bzl", "extension_libraries") +load("//eng/bazel:mstest.bzl", "mstest_libraries") +load("//eng/bazel:platform.bzl", "platform_libraries") +load("//eng/bazel:server-client.bzl", "server_client_library") +load("//eng/bazel:tests.bzl", "unit_tests") + +package(default_visibility = ["//visibility:public"]) + +exports_files(["LICENSE"]) + +config_setting( + name = "netstandard2_0", + flag_values = {"@rules_dotnet//dotnet:target_framework": "netstandard2.0"}, +) + +platform_libraries() + +mstest_libraries() + +extension_libraries() + +analyzer_libraries() + +server_client_library() + +unit_tests() + +filegroup( + name = "managed", + srcs = [ + ":adapter", + ":ai", + ":analyzers", + ":assert_generator", + ":azdo_report", + ":azure_foundry", + ":codefixes", + ":configuration", + ":crashdump", + ":ctrf", + ":framework", + ":framework_extensions", + ":github_report", + ":globalconfigs_generator", + ":hangdump", + ":hosting", + ":hotreload", + ":html", + ":junit", + ":logging", + ":msbuild_extension", + ":mstest_generator", + ":mstest_hosting", + ":opentelemetry", + ":packaged_app", + ":platform", + ":platform_msbuild", + ":platform_services", + ":retry", + ":server_client", + ":telemetry", + ":trx", + ":trx_abstractions", + ":video", + ":vstest_bridge", + ], +) + +# Short executable labels avoid Windows' doubled runfiles batch-file paths. +# The other explorer cases intentionally demonstrate failures and skips. +csharp_binary( + name = "explorer_released", + srcs = ["//samples/public/TestingPlatformExamples/TestingPlatformExplorer:sources"], + out = "TestingPlatformExplorer", + appsetting_files = ["//samples/public/TestingPlatformExamples/TestingPlatformExplorer:TestingPlatformExplorer.testingplatformconfig.json"], + generate_documentation_file = False, + langversion = "preview", + nullable = "enable", + target_frameworks = ["net10.0"], + deps = [ + "@paket.main//microsoft.testing.extensions.trxreport", + "@paket.main//microsoft.testing.extensions.trxreport.abstractions", + "@paket.main//microsoft.testing.platform", + ], +) + +csharp_binary( + name = "explorer", + srcs = ["//samples/public/TestingPlatformExamples/TestingPlatformExplorer:sources"], + out = "TestingPlatformExplorer", + appsetting_files = ["//samples/public/TestingPlatformExamples/TestingPlatformExplorer:TestingPlatformExplorer.testingplatformconfig.json"], + generate_documentation_file = False, + langversion = "preview", + nullable = "enable", + target_frameworks = ["net10.0"], + deps = [ + ":platform", + ":trx", + ":trx_abstractions", + ], +) + +testfx_test( + name = "explorer_test", + size = "small", + args = [ + "--filter-uid", + "TestingPlatformExplorer.UnitTests.SomeTests.TestMethod1", + ], + binary = ":explorer", +) + +testfx_test( + name = "explorer_released_test", + size = "small", + args = [ + "--filter-uid", + "TestingPlatformExplorer.UnitTests.SomeTests.TestMethod1", + ], + binary = ":explorer_released", +) + +testfx_binary( + name = "simple1", + defines = ["TESTFX_REPORTS"], + generate_documentation_file = False, + linked_srcs = ["//eng/bazel:TestMain.cs"], + polyfills = False, + project = "samples/public/mstest-runner/Simple1", + deps = [ + ":adapter", + ":ctrf", + ":framework", + ":framework_extensions", + ":html", + ":junit", + ":trx", + ], +) + +testfx_test( + name = "simple1_test", + size = "small", + args = [ + "--minimum-expected-tests", + "1", + ], + binary = ":simple1", +) + +testfx_binary( + name = "framework_tests_app", + assembly_name = "Microsoft.VisualStudio.TestPlatform.TestFramework.UnitTests", + defines = ["TESTFX_INTERNAL_TESTS"], + exclude = ["test/UnitTests/TestFramework.UnitTests/Program.cs"], + generate_documentation_file = False, + linked_srcs = ["//eng/bazel:TestMain.cs"], + project = "test/UnitTests/TestFramework.UnitTests", + deps = [ + ":framework", + ":framework_extensions", + ":internal_test_framework", + ":trx", + "@paket.source//awesomeassertions", + "@paket.source//moq", + ], +) + +testfx_test( + name = "framework_tests", + size = "medium", + args = [ + "--minimum-expected-tests", + "1", + ], + binary = ":framework_tests_app", +) + +testfx_test( + name = "explorer_failure_probe", + size = "small", + args = [ + "--filter-uid", + "TestingPlatformExplorer.UnitTests.SomeTests.TestMethod2", + ], + binary = ":explorer", + tags = ["manual"], +) + +test_suite( + name = "baseline_tests", + tests = [ + ":adapter_tests", + ":build_tools_tests", + ":explorer_released_test", + ":explorer_test", + ":framework_tests", + ":platform_services_tests", + ":simple1_test", + ], +) diff --git a/MODULE.bazel b/MODULE.bazel new file mode 100644 index 0000000000..8acbb7d485 --- /dev/null +++ b/MODULE.bazel @@ -0,0 +1,48 @@ +module(name = "testfx") + +bazel_dep(name = "rules_dotnet", version = "0.22.2") +single_version_override( + module_name = "rules_dotnet", + patch_strip = 1, + patches = [ + "//eng/bazel/patches:quote-csharp-sources.patch", + "//eng/bazel/patches:generated-resource-names.patch", + "//eng/bazel/patches:short-launcher-name.patch", + "//eng/bazel/patches:reference-only-analyzers.patch", + "//eng/bazel/patches:satellite-assemblies.patch", + "//eng/bazel/patches:unique-analyzers.patch", + "//eng/bazel/patches:framework-reference-priority.patch", + "//eng/bazel/patches:pdb-runfiles.patch", + "//eng/bazel/patches:windows-launcher.patch", + ], + version = "0.22.2", +) + +dotnet = use_extension("@rules_dotnet//dotnet:extensions.bzl", "dotnet") +dotnet.toolchain(dotnet_version = "10.0.400") +use_repo(dotnet, "dotnet_toolchains") + +register_toolchains("@dotnet_toolchains//:all") + +# Bootstrap the resolver without requiring dotnet tool restore or a machine SDK. +nuget_archive = use_repo_rule("@rules_dotnet//dotnet:defs.bzl", "nuget_archive") + +nuget_archive( + name = "paket_cli", + id = "paket", + sha512 = "sha512-i6fCViUL3/f8FaHPMknsee2UL67PGMmYKKalq6qNd2k6CG4DbzFtG6bSGlAWkFRx4/92U/NRNgxEYFPSasVWsQ==", + sources = ["https://api.nuget.org/v3/index.json"], + version = "11.0.1", +) + +nuget = use_extension("//eng/bazel/nuget:paket.main_extension.bzl", "main_extension") +use_repo(nuget, "paket.main") + +source_nuget = use_extension("//eng/bazel/nuget:paket.source_extension.bzl", "source_extension") +use_repo(source_nuget, "paket.source") + +generator_nuget = use_extension("//eng/bazel/nuget:paket.generator_extension.bzl", "generator_extension") +use_repo(generator_nuget, "paket.generator") + +analyzers_nuget = use_extension("//eng/bazel/nuget:paket.analyzers_extension.bzl", "analyzers_extension") +use_repo(analyzers_nuget, "paket.analyzers") diff --git a/MODULE.bazel.lock b/MODULE.bazel.lock new file mode 100644 index 0000000000..8e3fa21873 --- /dev/null +++ b/MODULE.bazel.lock @@ -0,0 +1,313 @@ +{ + "lockFileVersion": 28, + "registryFileHashes": { + "https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497", + "https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2", + "https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589", + "https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0", + "https://bcr.bazel.build/modules/abseil-cpp/20230802.0.bcr.1/MODULE.bazel": "1c8cec495288dccd14fdae6e3f95f772c1c91857047a098fad772034264cc8cb", + "https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16", + "https://bcr.bazel.build/modules/abseil-cpp/20230802.1/MODULE.bazel": "fa92e2eb41a04df73cdabeec37107316f7e5272650f81d6cc096418fe647b915", + "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed", + "https://bcr.bazel.build/modules/abseil-cpp/20240116.1/source.json": "9be551b8d4e3ef76875c0d744b5d6a504a27e3ae67bc6b28f46415fd2d2957da", + "https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd", + "https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8", + "https://bcr.bazel.build/modules/bazel_features/1.15.0/MODULE.bazel": "d38ff6e517149dc509406aca0db3ad1efdd890a85e049585b7234d04238e2a4d", + "https://bcr.bazel.build/modules/bazel_features/1.17.0/MODULE.bazel": "039de32d21b816b47bd42c778e0454217e9c9caac4a3cf8e15c7231ee3ddee4d", + "https://bcr.bazel.build/modules/bazel_features/1.18.0/MODULE.bazel": "1be0ae2557ab3a72a57aeb31b29be347bcdc5d2b1eb1e70f39e3851a7e97041a", + "https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58", + "https://bcr.bazel.build/modules/bazel_features/1.30.0/MODULE.bazel": "a14b62d05969a293b80257e72e597c2da7f717e1e69fa8b339703ed6731bec87", + "https://bcr.bazel.build/modules/bazel_features/1.30.0/source.json": "b07e17f067fe4f69f90b03b36ef1e08fe0d1f3cac254c1241a1818773e3423bc", + "https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7", + "https://bcr.bazel.build/modules/bazel_features/1.9.0/MODULE.bazel": "885151d58d90d8d9c811eb75e3288c11f850e1d6b481a8c9f766adee4712358b", + "https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a", + "https://bcr.bazel.build/modules/bazel_lib/3.0.0/MODULE.bazel": "22b70b80ac89ad3f3772526cd9feee2fa412c2b01933fea7ed13238a448d370d", + "https://bcr.bazel.build/modules/bazel_lib/3.0.0/source.json": "895f21909c6fba01d7c17914bb6c8e135982275a1b18cdaa4e62272217ef1751", + "https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8", + "https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e", + "https://bcr.bazel.build/modules/bazel_skylib/1.2.0/MODULE.bazel": "44fe84260e454ed94ad326352a698422dbe372b21a1ac9f3eab76eb531223686", + "https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a", + "https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5", + "https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d", + "https://bcr.bazel.build/modules/bazel_skylib/1.4.2/MODULE.bazel": "3bd40978e7a1fac911d5989e6b09d8f64921865a45822d8b09e815eaa726a651", + "https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138", + "https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917", + "https://bcr.bazel.build/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d", + "https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b", + "https://bcr.bazel.build/modules/bazel_skylib/1.8.1/MODULE.bazel": "88ade7293becda963e0e3ea33e7d54d3425127e0a326e0d17da085a5f1f03ff6", + "https://bcr.bazel.build/modules/bazel_skylib/1.8.1/source.json": "7ebaefba0b03efe59cac88ed5bbc67bcf59a3eff33af937345ede2a38b2d368a", + "https://bcr.bazel.build/modules/buildozer/7.1.2/MODULE.bazel": "2e8dd40ede9c454042645fd8d8d0cd1527966aa5c919de86661e62953cd73d84", + "https://bcr.bazel.build/modules/buildozer/7.1.2/source.json": "c9028a501d2db85793a6996205c8de120944f50a0d570438fcae0457a5f9d1f8", + "https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb", + "https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4", + "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6", + "https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/source.json": "41e9e129f80d8c8bf103a7acc337b76e54fad1214ac0a7084bf24f4cd924b8b4", + "https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f", + "https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075", + "https://bcr.bazel.build/modules/jsoncpp/1.9.5/source.json": "4108ee5085dd2885a341c7fab149429db457b3169b86eb081fa245eadf69169d", + "https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902", + "https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5", + "https://bcr.bazel.build/modules/platforms/0.0.11/MODULE.bazel": "0daefc49732e227caa8bfa834d65dc52e8cc18a2faf80df25e8caea151a9413f", + "https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee", + "https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37", + "https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615", + "https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814", + "https://bcr.bazel.build/modules/platforms/0.0.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d", + "https://bcr.bazel.build/modules/platforms/1.0.0/MODULE.bazel": "f05feb42b48f1b3c225e4ccf351f367be0371411a803198ec34a389fb22aa580", + "https://bcr.bazel.build/modules/platforms/1.0.0/source.json": "f4ff1fd412e0246fd38c82328eb209130ead81d62dcd5a9e40910f867f733d96", + "https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7", + "https://bcr.bazel.build/modules/protobuf/27.0/MODULE.bazel": "7873b60be88844a0a1d8f80b9d5d20cfbd8495a689b8763e76c6372998d3f64c", + "https://bcr.bazel.build/modules/protobuf/27.1/MODULE.bazel": "703a7b614728bb06647f965264967a8ef1c39e09e8f167b3ca0bb1fd80449c0d", + "https://bcr.bazel.build/modules/protobuf/29.0-rc2/MODULE.bazel": "6241d35983510143049943fc0d57937937122baf1b287862f9dc8590fc4c37df", + "https://bcr.bazel.build/modules/protobuf/29.0/MODULE.bazel": "319dc8bf4c679ff87e71b1ccfb5a6e90a6dbc4693501d471f48662ac46d04e4e", + "https://bcr.bazel.build/modules/protobuf/29.0/source.json": "b857f93c796750eef95f0d61ee378f3420d00ee1dd38627b27193aa482f4f981", + "https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0", + "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e", + "https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/source.json": "be4789e951dd5301282729fe3d4938995dc4c1a81c2ff150afc9f1b0504c6022", + "https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206", + "https://bcr.bazel.build/modules/re2/2023-09-01/source.json": "e044ce89c2883cd957a2969a43e79f7752f9656f6b20050b62f90ede21ec6eb4", + "https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8", + "https://bcr.bazel.build/modules/rules_android/0.1.1/source.json": "e6986b41626ee10bdc864937ffb6d6bf275bb5b9c65120e6137d56e6331f089e", + "https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647", + "https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002", + "https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191", + "https://bcr.bazel.build/modules/rules_cc/0.0.14/MODULE.bazel": "5e343a3aac88b8d7af3b1b6d2093b55c347b8eefc2e7d1442f7a02dc8fea48ac", + "https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc", + "https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87", + "https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c", + "https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f", + "https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e", + "https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5", + "https://bcr.bazel.build/modules/rules_cc/0.1.1/MODULE.bazel": "2f0222a6f229f0bf44cd711dc13c858dad98c62d52bd51d8fc3a764a83125513", + "https://bcr.bazel.build/modules/rules_cc/0.1.1/source.json": "d61627377bd7dd1da4652063e368d9366fc9a73920bfa396798ad92172cf645c", + "https://bcr.bazel.build/modules/rules_dotnet/0.22.2/MODULE.bazel": "ba1ef25468b67f7bace84064ac50a8380d9140e979a09b0548e7b29918b953be", + "https://bcr.bazel.build/modules/rules_dotnet/0.22.2/source.json": "2d493ac6964cbfdd58e2b9ae9512459cecfb85d52c344e96319e1aa04143d794", + "https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6", + "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8", + "https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/source.json": "c8b1e2c717646f1702290959a3302a178fb639d987ab61d548105019f11e527e", + "https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74", + "https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86", + "https://bcr.bazel.build/modules/rules_java/6.0.0/MODULE.bazel": "8a43b7df601a7ec1af61d79345c17b31ea1fedc6711fd4abfd013ea612978e39", + "https://bcr.bazel.build/modules/rules_java/6.4.0/MODULE.bazel": "e986a9fe25aeaa84ac17ca093ef13a4637f6107375f64667a15999f77db6c8f6", + "https://bcr.bazel.build/modules/rules_java/6.5.2/MODULE.bazel": "1d440d262d0e08453fa0c4d8f699ba81609ed0e9a9a0f02cd10b3e7942e61e31", + "https://bcr.bazel.build/modules/rules_java/7.10.0/MODULE.bazel": "530c3beb3067e870561739f1144329a21c851ff771cd752a49e06e3dc9c2e71a", + "https://bcr.bazel.build/modules/rules_java/7.12.2/MODULE.bazel": "579c505165ee757a4280ef83cda0150eea193eed3bef50b1004ba88b99da6de6", + "https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab", + "https://bcr.bazel.build/modules/rules_java/7.3.2/MODULE.bazel": "50dece891cfdf1741ea230d001aa9c14398062f2b7c066470accace78e412bc2", + "https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe", + "https://bcr.bazel.build/modules/rules_java/8.14.0/MODULE.bazel": "717717ed40cc69994596a45aec6ea78135ea434b8402fb91b009b9151dd65615", + "https://bcr.bazel.build/modules/rules_java/8.14.0/source.json": "8a88c4ca9e8759da53cddc88123880565c520503321e2566b4e33d0287a3d4bc", + "https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7", + "https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909", + "https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036", + "https://bcr.bazel.build/modules/rules_jvm_external/5.3/MODULE.bazel": "bf93870767689637164657731849fb887ad086739bd5d360d90007a581d5527d", + "https://bcr.bazel.build/modules/rules_jvm_external/6.1/MODULE.bazel": "75b5fec090dbd46cf9b7d8ea08cf84a0472d92ba3585b476f44c326eda8059c4", + "https://bcr.bazel.build/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0", + "https://bcr.bazel.build/modules/rules_jvm_external/6.3/source.json": "6f5f5a5a4419ae4e37c35a5bb0a6ae657ed40b7abc5a5189111b47fcebe43197", + "https://bcr.bazel.build/modules/rules_kotlin/1.9.0/MODULE.bazel": "ef85697305025e5a61f395d4eaede272a5393cee479ace6686dba707de804d59", + "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/MODULE.bazel": "d269a01a18ee74d0335450b10f62c9ed81f2321d7958a2934e44272fe82dcef3", + "https://bcr.bazel.build/modules/rules_kotlin/1.9.6/source.json": "2faa4794364282db7c06600b7e5e34867a564ae91bda7cae7c29c64e9466b7d5", + "https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0", + "https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d", + "https://bcr.bazel.build/modules/rules_license/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c", + "https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb", + "https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc", + "https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff", + "https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a", + "https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06", + "https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7", + "https://bcr.bazel.build/modules/rules_proto/6.0.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73", + "https://bcr.bazel.build/modules/rules_proto/7.0.2/MODULE.bazel": "bf81793bd6d2ad89a37a40693e56c61b0ee30f7a7fdbaf3eabbf5f39de47dea2", + "https://bcr.bazel.build/modules/rules_proto/7.0.2/source.json": "1e5e7260ae32ef4f2b52fd1d0de8d03b606a44c91b694d2f1afb1d3b28a48ce1", + "https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f", + "https://bcr.bazel.build/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300", + "https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382", + "https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed", + "https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58", + "https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c", + "https://bcr.bazel.build/modules/rules_python/0.40.0/MODULE.bazel": "9d1a3cd88ed7d8e39583d9ffe56ae8a244f67783ae89b60caafc9f5cf318ada7", + "https://bcr.bazel.build/modules/rules_python/0.40.0/source.json": "939d4bd2e3110f27bfb360292986bb79fd8dcefb874358ccd6cdaa7bda029320", + "https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c", + "https://bcr.bazel.build/modules/rules_shell/0.4.1/MODULE.bazel": "00e501db01bbf4e3e1dd1595959092c2fadf2087b2852d3f553b5370f5633592", + "https://bcr.bazel.build/modules/rules_shell/0.5.0/MODULE.bazel": "8c8447370594d45539f66858b602b0bb2cb2d3401a4ebb9ad25830c59c0f366d", + "https://bcr.bazel.build/modules/rules_shell/0.5.0/source.json": "3038276f07cbbdd1c432d1f80a2767e34143ffbb03cfa043f017e66adbba324c", + "https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8", + "https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c", + "https://bcr.bazel.build/modules/stardoc/0.5.6/MODULE.bazel": "c43dabc564990eeab55e25ed61c07a1aadafe9ece96a4efabb3f8bf9063b71ef", + "https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c", + "https://bcr.bazel.build/modules/stardoc/0.7.1/MODULE.bazel": "3548faea4ee5dda5580f9af150e79d0f6aea934fc60c1cc50f4efdd9420759e7", + "https://bcr.bazel.build/modules/stardoc/0.7.1/source.json": "b6500ffcd7b48cd72c29bb67bcac781e12701cc0d6d55d266a652583cfcdab01", + "https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43", + "https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0", + "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/MODULE.bazel": "eec517b5bbe5492629466e11dae908d043364302283de25581e3eb944326c4ca", + "https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/source.json": "22bc55c47af97246cfc093d0acf683a7869377de362b5d1c552c2c2e16b7a806", + "https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198" + }, + "selectedYankedVersions": {}, + "moduleExtensions": { + "@@rules_dotnet+//dotnet:extensions.bzl%dotnet": { + "general": { + "bzlTransitiveDigest": "uEHkcHo+qz0mZXMqN4Q7wBRkPontx/Bonzh6vyzfwyM=", + "usagesDigest": "m36jHNMY0dPC7curUpIaXHG6VFEVahX62JfXKHe9Vow=", + "recordedInputs": [], + "generatedRepoSpecs": { + "dotnet_x86_64-apple-darwin": { + "repoRuleId": "@@rules_dotnet+//dotnet:repositories.bzl%dotnet_repositories", + "attributes": { + "platform": "x86_64-apple-darwin", + "dotnet_version": "10.0.400" + } + }, + "dotnet_aarch64-apple-darwin": { + "repoRuleId": "@@rules_dotnet+//dotnet:repositories.bzl%dotnet_repositories", + "attributes": { + "platform": "aarch64-apple-darwin", + "dotnet_version": "10.0.400" + } + }, + "dotnet_x86_64-unknown-linux-gnu": { + "repoRuleId": "@@rules_dotnet+//dotnet:repositories.bzl%dotnet_repositories", + "attributes": { + "platform": "x86_64-unknown-linux-gnu", + "dotnet_version": "10.0.400" + } + }, + "dotnet_arm64-unknown-linux-gnu": { + "repoRuleId": "@@rules_dotnet+//dotnet:repositories.bzl%dotnet_repositories", + "attributes": { + "platform": "arm64-unknown-linux-gnu", + "dotnet_version": "10.0.400" + } + }, + "dotnet_x86_64-pc-windows-msvc": { + "repoRuleId": "@@rules_dotnet+//dotnet:repositories.bzl%dotnet_repositories", + "attributes": { + "platform": "x86_64-pc-windows-msvc", + "dotnet_version": "10.0.400" + } + }, + "dotnet_arm64-pc-windows-msvc": { + "repoRuleId": "@@rules_dotnet+//dotnet:repositories.bzl%dotnet_repositories", + "attributes": { + "platform": "arm64-pc-windows-msvc", + "dotnet_version": "10.0.400" + } + }, + "dotnet_toolchains": { + "repoRuleId": "@@rules_dotnet+//dotnet/private:toolchains_repo.bzl%toolchains_repo", + "attributes": { + "user_repository_name": "dotnet" + } + }, + "dotnet_apphost_x86_64-apple-darwin": { + "repoRuleId": "@@rules_dotnet+//dotnet:repositories.bzl%dotnet_repositories", + "attributes": { + "platform": "x86_64-apple-darwin", + "dotnet_version": "10.0.201" + } + }, + "dotnet_apphost_aarch64-apple-darwin": { + "repoRuleId": "@@rules_dotnet+//dotnet:repositories.bzl%dotnet_repositories", + "attributes": { + "platform": "aarch64-apple-darwin", + "dotnet_version": "10.0.201" + } + }, + "dotnet_apphost_x86_64-unknown-linux-gnu": { + "repoRuleId": "@@rules_dotnet+//dotnet:repositories.bzl%dotnet_repositories", + "attributes": { + "platform": "x86_64-unknown-linux-gnu", + "dotnet_version": "10.0.201" + } + }, + "dotnet_apphost_arm64-unknown-linux-gnu": { + "repoRuleId": "@@rules_dotnet+//dotnet:repositories.bzl%dotnet_repositories", + "attributes": { + "platform": "arm64-unknown-linux-gnu", + "dotnet_version": "10.0.201" + } + }, + "dotnet_apphost_x86_64-pc-windows-msvc": { + "repoRuleId": "@@rules_dotnet+//dotnet:repositories.bzl%dotnet_repositories", + "attributes": { + "platform": "x86_64-pc-windows-msvc", + "dotnet_version": "10.0.201" + } + }, + "dotnet_apphost_arm64-pc-windows-msvc": { + "repoRuleId": "@@rules_dotnet+//dotnet:repositories.bzl%dotnet_repositories", + "attributes": { + "platform": "arm64-pc-windows-msvc", + "dotnet_version": "10.0.201" + } + }, + "dotnet_apphost_toolchains": { + "repoRuleId": "@@rules_dotnet+//dotnet/private:toolchains_repo.bzl%toolchains_repo", + "attributes": { + "user_repository_name": "dotnet_apphost" + } + } + } + } + }, + "@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": { + "general": { + "bzlTransitiveDigest": "03Qju4tW0vE+0RBuZGuV2A4Hx6AiSkdNahYvworx2aM=", + "usagesDigest": "QI2z8ZUR+mqtbwsf2fLqYdJAkPOHdOV+tF2yVAUgRzw=", + "recordedInputs": [ + "REPO_MAPPING:rules_kotlin+,bazel_tools bazel_tools" + ], + "generatedRepoSpecs": { + "com_github_jetbrains_kotlin_git": { + "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_compiler_git_repository", + "attributes": { + "urls": [ + "https://github.com/JetBrains/kotlin/releases/download/v1.9.23/kotlin-compiler-1.9.23.zip" + ], + "sha256": "93137d3aab9afa9b27cb06a824c2324195c6b6f6179d8a8653f440f5bd58be88" + } + }, + "com_github_jetbrains_kotlin": { + "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_capabilities_repository", + "attributes": { + "git_repository_name": "com_github_jetbrains_kotlin_git", + "compiler_version": "1.9.23" + } + }, + "com_github_google_ksp": { + "repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:ksp.bzl%ksp_compiler_plugin_repository", + "attributes": { + "urls": [ + "https://github.com/google/ksp/releases/download/1.9.23-1.0.20/artifacts.zip" + ], + "sha256": "ee0618755913ef7fd6511288a232e8fad24838b9af6ea73972a76e81053c8c2d", + "strip_version": "1.9.23-1.0.20" + } + }, + "com_github_pinterest_ktlint": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file", + "attributes": { + "sha256": "01b2e0ef893383a50dbeb13970fe7fa3be36ca3e83259e01649945b09d736985", + "urls": [ + "https://github.com/pinterest/ktlint/releases/download/1.3.0/ktlint" + ], + "executable": true + } + }, + "rules_android": { + "repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive", + "attributes": { + "sha256": "cd06d15dd8bb59926e4d65f9003bfc20f9da4b2519985c27e190cddc8b7a7806", + "strip_prefix": "rules_android-0.1.1", + "urls": [ + "https://github.com/bazelbuild/rules_android/archive/v0.1.1.zip" + ] + } + } + } + } + } + }, + "facts": {}, + "factsVersions": {} +} diff --git a/README.md b/README.md index a536947fbd..9979648618 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ We welcome any kind of contribution! - [Contributing](./CONTRIBUTING.md) guides how to best contribute - [Dev Guide](./docs/dev-guide.md) explains how to build and test +- [Experimental Bazel build](./docs/bazel.md) documents the staged native build, validation commands, and remaining MSBuild parity gaps. - [Documentation](docs/README.md) contains information about the history, context, and supported or unsupported features. It also gathers the various official documentation pages on learn.microsoft.com about MSTest. ## How to consume MSTest? diff --git a/docs/bazel.md b/docs/bazel.md new file mode 100644 index 0000000000..03638ad6b1 --- /dev/null +++ b/docs/bazel.md @@ -0,0 +1,192 @@ +# Experimental native Bazel build + +This branch provides a **staged development build, not a drop-in replacement for +the shipping MSBuild/Arcade pipeline**. Bazel compiles 35 of the 41 projects under +`src`, without running MSBuild or consuming its outputs. Existing release, +signing, packing, and acceptance workflows remain unchanged. + +## Getting started + +Install PowerShell 7.2 or newer. On Windows, use an environment that already +permits symbolic links (Developer Mode or an appropriately privileged shell). +The bootstrap does not change machine policy or install a global SDK. + +From the repository root: + +```powershell +.\eng\bazel.ps1 build //:managed +.\eng\bazel.ps1 test //:baseline_tests +.\eng\bazel\validate.ps1 +``` + +The last command also checks discovery, real TRX/HTML/JUnit/CTRF output, paths +containing spaces and `!`, failing-test exits, zero-result exits, mixed-module +failure aggregation, and the native action graph. Evidence is written under a +unique `artifacts\bazel-validation` directory. Its success is scoped to the +baseline, not the complete repository. + +The wrapper pins and verifies Bazel **8.8.2**. Bzlmod pins `rules_dotnet` +**0.22.2**, and its toolchain downloads and verifies SDK **10.0.400** +(runtime **10.0.11**). Neither the machine SDK nor the repository's +`global.json` selects this experimental compiler. + +The bootstrap supports Windows x64, Linux x64, and macOS arm64. Windows was +executed locally; the added Windows/Linux CI job is configuration, not evidence +that CI or Linux has run. Other architectures can use Bazelisk with +`.bazelversion`, subject to the rules' platform support. + +On Windows, the default output root is +`:\tfb\` to avoid batch-file path limits. +Set `TESTFX_BAZEL_OUTPUT_ROOT` to override it with another short, writable path. +It must not be shared by simultaneously running worktrees. Non-Windows hosts +default to a worktree-specific temporary directory. The executable itself lives +under `artifacts\bazel-tools`. + +Bazelisk users can invoke `bazel` directly, but must provide a suitably short +Windows output root themselves. The checked-in `.bazelrc` supplies the required +runfiles settings. + +## Targets and current scope + +| Target | Contents | +| --- | --- | +| `//:managed` | 35 source projects: MTP, its portable extensions, MSTest framework and adapter, analyzers/code fixes, generators, and the server-client validation assembly. | +| `//:explorer_released` | Existing platform explorer compiled against its released MTP 2.5.2 packages. | +| `//:explorer` | The same sample compiled against this checkout's MTP and TRX assemblies. | +| `//:simple1` | Existing `samples/public/mstest-runner/Simple1`, using the source-built MSTest runner and reporters. | +| `//:baseline_tests` | Seven test targets: the three sample smoke runs, existing framework/adapter/platform-services suites, and build-tool regression cases. | +| `//:framework_tests` | All 1,634 existing framework tests, using the existing sequential `TestContainer` engine. | +| `//:adapter_tests` | All 152 existing adapter tests, using `TestContainer`. | +| `//:platform_services_tests` | All 1,215 existing platform-services tests, using `TestContainer`. | +| `//:build_tools_tests` | Nine focused cases for RESX text/BOM preservation, XLF application/validation, and version/build-stamp generation. | +| `//:platform_tests` | Full 3,380-case MTP suite, preserving method-level parallelization. Two real Windows impersonation cases are host-blocked in local validation; this target is deliberately not part of `baseline_tests`. | + +Most native assemblies target `net10.0`. The assertion generator, MSTest +analyzers/code fixes, and MSTest source generator retain `netstandard2.0`; +the server-client validation assembly retains `net8.0`. This is **not** the +full multi-targeting matrix of their project files. + +The six source projects outside `managed` are: + +| Project | Remaining work | +| --- | --- | +| `MSTest.Analyzers.Package` | Analyzer package assembly/layout orchestration. | +| `MSTest` | Meta-package dependencies and packed assets. | +| `MSTest.Sdk` | SDK templates, package metadata, and consumer build hooks. | +| `Microsoft.Testing.Extensions.PackagedApp.MSBuild` | Exact controller/package layout and cross-TFM assets. | +| `Microsoft.Testing.Extensions.PackagedApp.Controller` | Windows-targeting packs and controller apphost deployment. | +| `TestFramework.Windows.UIAutomation` | Windows/WPF targeting and runtime validation. | + +Not yet migrated or established: the other unit-test projects, integration and +package-consuming acceptance suites, every public example, .NET 11, the complete +.NET Framework/netstandard matrix, WinRT/UWP/WinUI/WPF workloads, AOT, strong-name +identity, SourceLink/API-audit parity, official package layout/signing/publishing, +and downstream servicing. The assemblies are unsigned development outputs. + +The portable `PackagedApp` assembly is included; its Windows register/activate +flavor and real packaged-app execution are **not** implied by that compilation. +Likewise, building the server-client validation DLL does not validate the +source-only package's consumer transformation. + +### Running applications and selecting tests + +PowerShell consumes an unquoted `--` when invoking a script. Quote it when using +the wrapper: + +```powershell +.\eng\bazel.ps1 run //:explorer '--' --list-tests +.\eng\bazel.ps1 run //:explorer '--' --filter-uid TestingPlatformExplorer.UnitTests.SomeTests.TestMethod1 +.\eng\bazel.ps1 run //:framework_tests_app '--' --treenode-filter '/*/*/AssertTests/*' +.\eng\bazel.ps1 run //:platform_tests_app '--' --filter 'FullyQualifiedName~PlatformInformationTests' +``` + +Use the test host's options after the separator; Bazel's `--test_filter` is not +translated by these targets. The explorer intentionally includes failures: +selecting `TestMethod2` returns **2**, and an empty selection with +`--minimum-expected-tests 1` returns **9**. The manual +`//:explorer_failure_probe` is an intentional negative fixture used by +`validate.ps1` to verify Bazel's aggregate exit **3**. + +### Test host differences + +`eng/bazel/TestMain.cs` replaces only the selected suites' registration/entrypoint +plumbing. It keeps their test bodies and scheduling, registers the real source +runner and TRX reporter, and uses each Bazel test's undeclared-output directory. +It does not register the Arcade-only affected-test/coverage collectors or +dogfood every extension. Suites with special child-process bootstraps or extern +aliases need their own faithful migration, not this generic entrypoint. + +Local full MTP execution reported 3,378 passes and these two failures: + +- `CreateServerStream_AnUnauthorizedIdentityCannotConnect` +- `CreateServerStream_AnAppContainerConnectsOnlyWhenItsOwnPackageIsAuthorized` + +Windows returned `ERROR_BAD_IMPERSONATION_LEVEL` (**1346 / 0x542**). +The same error occurred outside Bazel's test wrapper, and a standalone +`NamedPipeServerStream`/anonymous-token probe with no TestFx or Bazel code +reproduced it. The tests and their assertions remain unchanged. A separate, +explicit selection excluding those two executed and passed the other 3,378 +cases; this is not a full-suite pass. Do not change machine security policy or +weaken the assertions to obtain a green result. + +## How the build works + +`BUILD.bazel` and `eng/bazel/*.bzl` declare the graph independently of MSBuild. +When changing a project, keep its native declaration aligned with the project +file: references, linked/excluded sources, constants, usings, resource names, +version overrides, friend assemblies, and runtime files are all significant. +Do not treat a successful C# glob as project parity. + +The native build explicitly provides: + +- Repository implicit usings and scoped `.editorconfig` diagnostics. +- SDK-compatible `NETCOREAPP` selection and transitive compilation references. + Friend-only transitive references are also declared directly where required. +- RESX accessors and binary resources, all existing XLF satellite cultures, + logical resource names, and the HTML template. +- Existing version templates, assembly/file versions, neutral-resource metadata, + the source generator's assembly-version override, and MTP's UTC build date + from Bazel's volatile build stamp. Cached artifacts retain their build stamp. +- Real Roslyn generators, analyzer release files, and the MSTest diagnostic + suppressor rather than blanket nullable-warning suppression. +- Declared runfiles/PDBs and native process exit propagation. + +NuGet resolution uses checksum-locked generated repositories, not the +machine's NuGet cache during ordinary builds. Update them explicitly: + +```powershell +# Re-resolve the declared package graph and regenerate Bazel repositories. +.\eng\bazel\update-dependencies.ps1 -Resolve + +# Regenerate from the committed lock without selecting new versions. +.\eng\bazel\update-dependencies.ps1 +``` + +The updater uses pinned Paket 11.0.1 and upstream `paket2bazel`, both launched +through the Bazel toolchain. Review and commit `paket.dependencies`, `paket.lock`, +generated `nuget/paket.*.bzl`, and `MODULE.bazel.lock` together. Do not hand-edit +generated repositories. The source graph's AI/resilience/hosting closure requires +shared 10.0.13 abstractions; these deliberate development-build convergence pins +are documented in the dependency file and do not change `Directory.Packages.props`. + +Nine small, version-scoped patches under `eng/bazel/patches` address demonstrated +gaps in the pinned rules: quoted source paths, logical resources, satellites, +short Windows launchers, Windows argument/manifest handling, PDB runfiles, +duplicate framework/package generators, canonical framework references, and a +Roslyn crash in the extra reference-only analyzer pass. Diagnostic analyzers still +run on implementation compilation. Reassess every patch on a rules upgrade; +none has been submitted upstream by this work. + +## Evidence and next migration gates + +See the maintained [research and decision record](decisions/bazel-build.md) for +experiments, exact commands, red/green evidence, and remaining limitations. +`validate.ps1` produces `validation.json`, command logs, copied TRX files, reports, +and `actions.json`. Its baseline has 3,013 passing cases across seven targets; +the action graph contains no MSBuild execution. + +Before replacing an existing shipping leg, add the missing framework/workload +toolchains and test harnesses, reproduce every NuGet/SDK layout, preserve signing +identity and audits, then run actual packed consumers and release-branch +acceptance. A successful `managed` or `baseline_tests` target does not waive +those gates. diff --git a/docs/decisions/bazel-build.md b/docs/decisions/bazel-build.md new file mode 100644 index 0000000000..70d77dab25 --- /dev/null +++ b/docs/decisions/bazel-build.md @@ -0,0 +1,295 @@ +# Bazel build: research and decisions + +## Problem and contract + +Enable and validate a native Bazel alternative for TestFx on an experimental +branch, progressing from existing public examples to source libraries and tests. +Bazel must schedule compiler actions itself; a target that shells out to +`dotnet build`, `dotnet test`, or MSBuild is not a migrated build. + +The existing Arcade/MSBuild build, package layout, CI, and release branches remain +unchanged until parity is demonstrated. This is a reversible development-build +experiment, not authorization to replace the shipping pipeline. + +The initial producer/consumer contract is: + +- Bazel owns dependency downloads, compilation, generated inputs, output + directories, test launches, and action invalidation. +- `rules_dotnet` owns the compiler/toolchain and .NET runtime launchers. + Tool versions and NuGet contents must be pinned and integrity checked. +- Public samples first consume their documented released package versions. + Source-built samples must instead consume the Bazel-built TestFx graph, not + prebuilt TestFx packages or assemblies from `artifacts/bin`. +- A passing test process returns zero. Test failures, an empty selection, and + launcher failures must remain visible as nonzero exits. Bazel aggregates + modules; one successful module must not hide a failing one. +- Existing MTP lifecycle, controller/child launch, discovery, filtering, report + generation, and cancellation semantics are not intentionally changed. +- Bazel outputs are development artifacts, not signed or published replacement + NuGets. Package/SDK/release parity requires separate shipping-layout validation. + +## Research and experiments + +### 2026-10-29: baseline and upstream contracts + +Baseline: `10847b7d879200796a35ea9888f36fdee7b9b593`, clean worktree. +No existing Bazel configuration was found. + +Sources inspected: + +- [rules_dotnet v0.22.2](https://github.com/bazel-contrib/rules_dotnet/releases/tag/v0.22.2), + its `MODULE.bazel`, `dotnet/defs.bzl`, rule implementations, and examples. + The module requires Bazel 8 or later, despite the release body's older Bazel 7 + instructions. Use Bzlmod and the actual pinned source contract. +- [Native C# test rule](https://github.com/bazel-contrib/rules_dotnet/blob/v0.22.2/dotnet/private/rules/csharp/test.bzl): + `csharp_test` executes a C# program. MTP is already executable; NUnit wrapping + and VSTest discovery are unnecessary. +- [Toolchain versions](https://github.com/bazel-contrib/rules_dotnet/blob/v0.22.2/dotnet/private/sdk/versions.bzl) + and [TFM graph](https://github.com/bazel-contrib/rules_dotnet/blob/v0.22.2/dotnet/private/common.bzl): + SDK 10.0.400 is supported with checksum-pinned downloads; modern TFMs stop at + `net10.0`. TestFx's `global.json` pins SDK 12.0.100-alpha.1.26509.101 and its + source build also includes `net11.0`. Full toolchain/TFM parity is therefore + not available from the released rules. +- [Paket integration](https://github.com/bazel-contrib/rules_dotnet/tree/v0.22.2/tools/paket2bazel): + use upstream dependency resolution/lock generation rather than inventing a + second NuGet resolver. +- Local `Directory.Build.props`, `Directory.Build.targets`, product projects, + `eng/Versions.props`, and sample defaults: implicit usings, linked sources, + generated resource accessors, version templates, source generators, friend + assemblies, and extension registration all need explicit Bazel equivalents. + Merely globbing `*.cs` is insufficient. + +The machine has no Bazel installation. A repository-scoped, checksum-pinned +bootstrap is needed; do not alter user-global SDK or tool settings. + +### 2026-10-29: bootstrap experiments + +- The checksum-verified Bazel 8.8.2 bootstrap executed successfully. +- Building upstream `paket2bazel` with the output root below this long worktree + path compiled the F# tool but failed to launch `apphost_shimmer.dll.bat`: + Windows `GetShortPathNameW` could not shorten the path sufficiently. + The bootstrap now selects a short, worktree-specific output root; + `TESTFX_BAZEL_OUTPUT_ROOT` allows an explicit supported cache location. +- The machine's temporary directory is `C:\Windows\TEMP`; Java could not resolve + its extracted security configuration there (`AccessDeniedException`). Windows + now defaults to `:\tfb\` instead of changing + system permissions. Other systems use the normal temporary directory. +- PowerShell consumes an unquoted `--` passed to a script. Commands invoking + `eng/bazel.ps1 run` must quote `'--'` to forward Bazel's separator. +- Native compilation of the existing platform explorer exposed an upstream + response-file defect: source paths such as `In-process extensions/...cs` were + split at spaces (`CS2001`). A one-line, version-scoped Bzlmod patch quotes C# + source arguments. Do not rename sample directories or copy sources elsewhere + to conceal the defect. This is build-contract evidence, not a runtime + regression-test red phase. +- Paket's default maximum-version strategy selected Application Insights 3.x + for a package that declares a 2.23 minimum. Use `strategy: min` and a committed + lock to align transitive selection with NuGet's lowest-applicable behavior. +- The compiled explorer could not resolve its runtime dependencies with + Windows manifest-only runfiles. Follow the upstream `.bazelrc` contract: + `--enable_runfiles` and `--windows_enable_symlinks`. Windows therefore needs + permission to create symbolic links (Developer Mode or an appropriately + privileged shell); the bootstrap does not change machine policy. + +### 2026-10-29: source-built platform + +The initial `bazel test //:explorer` target compiled `Microsoft.Testing.Platform`, TRX abstractions, +and TRX reporter from this checkout and passed the same existing explorer test. +The real controller launched a child that reported `Microsoft.Testing.Platform +v2.6.0-bazel`, completed one test, and exited zero. The released-package baseline +reports `v2.5.2`. No MSBuild compile/restore outputs were used. +The runnable applications and filtered smoke tests were subsequently separated +into `//:explorer` and `//:explorer_test`, so application arguments do not inherit +a fixed smoke-test filter. + +Native actions now generate RESX string accessors and binary resources, version +attributes, and existing version templates. A scoped rules patch preserves the +fully qualified manifest names of generated `.resources` files, including +hand-maintained cross-assembly resource accessors. + +The first platform compile exposed another SDK difference: upstream emits `NET` +but not `NETCOREAPP` for `net10.0`. That accidentally enabled legacy polyfills and +the netstandard JSON parser. Explicitly restore the missing symbol in the TestFx +macro; do not delete conditional sources or suppress the resulting diagnostics. +Compilation then succeeded with warnings treated as errors. + +The initial migration preserves SDK-style transitive compilation references via +`@rules_dotnet//dotnet/settings:strict_deps=false`. The first source-generator +compile with strict dependencies could not see `Microsoft.CodeAnalysis.Common` +through its declared CSharp package. This setting changes reference visibility, +not dependency ownership: the complete closure is still declared and cached by +Bazel. Tightening direct dependencies is a separate cleanup, not a prerequisite +for behavior-preserving build migration. + +Windows executable/test labels live at the workspace root: deep labels doubled +inside runfiles exceed the batch-launch path limit even with a short output root. +Source files remain in their original locations. + +### 2026-10-29: MSTest compiler boundary + +The MSTest assertion generator remains a native `netstandard2.0` analyzer. +Supply the existing `EnforceExtendedAnalyzerRules` property through a global +analyzer config, and pass the repository `.editorconfig` to preserve its scoped +experimental-API diagnostics rather than changing product sources. + +SDK 10.0.400's compiler crashed in the *extra reference-only* compilation used by +`rules_dotnet` for friend assemblies: `CSharpCompilerDiagnosticAnalyzer` reported +`Cannot enqueue data after PromiseNotToEnqueue`. Disabling compiler parallelism +was tried and still failed (AD0001); that experiment was removed. Public +builds.dotnet/ci.dot.net probes for the repository's SDK 12 pin returned 404, so +no SDK substitution was claimed. + +A version-scoped patch passes `/skipanalyzers+` only in that extra `/refonly` +action. Source generators and analyzer configuration remain supplied there. +The implementation compilation still runs all configured analyzers with +warnings as errors; it is not disabled or replaced. + +### 2026-10-29: localization, metadata, and existing-test sensitivity + +The first full framework run executed 1,634 tests: 1,632 passed and two failed +because Korean satellite resources were missing. Native XLF compilation now +builds locale assemblies and propagates them through runfiles/dependency +manifests. The same 1,634 tests then passed, with no skipped cases or changed +assertions. Preserve logical names such as `FrameworkMessages.ko.resources`; +the shipped 4.5.2 package's satellite manifests were inspected for comparison. + +Translation behavior was checked against `dotnet/xliff-tasks`' `XlfDocument`, +`XElementExtensions.GetTargetValue`, and `TranslatableDocument.Translate`: +apply targets regardless of state, and fall back to source when target is absent. +The existing localization guard passed all 364 catalogs. No RESX/XLF was edited. + +Two existing platform-services tests exposed a second real difference: the +shipped `UTA_ExecuteThrewException` resource contains CRLF, while the initial +XDocument reader normalized it to LF. A non-normalizing XML reader, with DTDs +prohibited and external resolution disabled, preserves resource text. Both +tests and all 1,215 platform-services cases now pass. Added focused LF/CRLF, +XLF, invalid-input, BOM, and metadata tests; all nine execute and pass. + +An existing adapter test also required the SDK's neutral-resource assembly +attribute. An MTP test required `Application.BuildTimeUTC`. Native metadata now +emits `NeutralResourcesLanguage("en")` and uses Bazel's volatile timestamp for +the platform's UTC date rather than inventing a date or consulting an undeclared +wall clock. All 152 adapter cases pass. + +### 2026-10-29: expanded graph and dependency experiments + +`//:managed` now compiles 35 of 41 source projects. The +[scope inventory](../bazel.md#targets-and-current-scope) identifies the six +packaging/Windows-workload projects outside this target. + +NuGet package selection required care. `strategy: min` only affects transitive +dependencies; a lower-bound experiment selected unwanted newer direct versions. +`lowest_matching: true` plus broad lower bounds caused lengthy backtracking +around the composed AI/resilience/hosting graph. The final declaration pins +direct versions, retaining repository versions where possible and converging +shared abstractions to 10.0.13 as required by that graph. A resolver abandoned +during the experiment retained its process lock; its exact owned PID was +verified and stopped, and the final bounded resolution completed in 15 seconds. +No global cache was cleared. + +Further executed failures established these scoped rules patches: + +- Both SDK and explicit System.Text.Json generators ran, generating duplicate + members. Prefer the explicit package generator when assembly names duplicate. +- Code-fix compilation received old System.* facades alongside NETStandard's + canonical references. Give the selected framework references priority. +- Long DLL-based batch launcher names overflowed Windows' doubled runfiles + paths. Use short launcher names and preserve the original source layout. +- Windows launcher argument rewriting corrupted quoted paths; forward arguments + without rewriting them and disable delayed expansion while invoking dotnet. + Actual report generation succeeds in a directory containing spaces and `!`. +- PDBs were not declared as runfiles. Carry them with the compiled assembly. + +Analyzer release files and the existing MSTest diagnostic suppressor are native +inputs. The suppressor, not a new CS8618 allowlist, handles injected TestContext +properties. Ordinary analyzer and source-generator compilation still uses its +declared Roslyn API version. + +### 2026-10-29: remaining host-specific MTP failures + +Full native MTP execution ran 3,380 cases: 3,378 passed and two real Windows +impersonation tests failed with Win32 1346 (`ERROR_BAD_IMPERSONATION_LEVEL`). +They fail outside Bazel's test wrapper too. A separate plain .NET named-pipe +and anonymous-token probe, with no TestFx or Bazel code, reproduced HRESULT +`0x80070542`. No security settings or assertions were changed. + +The explicit selection excluding those two ran and passed 3,378 cases; report +that separately from the failed full run. `baseline_tests` does not include the +full MTP target. Other suites with extern aliases, special child bootstraps, +shipping-package assumptions, or unsupported workloads remain migration work. + +## Alternatives and decision + +1. Keep MSBuild only: preserves all existing capabilities but does not answer the + request. +2. Invoke MSBuild from Bazel: easy orchestration, but retains MSBuild's graph and + ambient outputs. Rejected as a migration claim. +3. Native `rules_dotnet` targets alongside existing project files: chosen. + Start with public examples, then grow the source graph and existing tests. + Make generated inputs explicit and retain a documented supported matrix. +4. Extend the rules immediately for all TestFx workloads/TFMs: not attempted. + Only demonstrated compatibility gaps in the supported graph received scoped + patches; a complete toolchain/workload fork remains a separate decision. + +The Bazel experiment deliberately uses its own hermetic SDK 10.0.400 pin, not a +globally selected SDK and not a silent replacement of `global.json`. Initially +validate `net10.0`; only claim other TFMs after executing their build/test paths. +Windows app models, native AOT, shipping NuGet assets, .NET 11, release signing, +and Arcade services are parity gates, not implied by a green `bazel build`. + +## Validation and demonstration + +Executed on Windows x64, Bazel 8.8.2, rules_dotnet 0.22.2 at +`7e7cff30826695e814bfbe05d555db6a780a7123`, SDK 10.0.400, runtime 10.0.11. +Source baseline is `10847b7d879200796a35ea9888f36fdee7b9b593` plus this branch's +changes. Logs and reports are local evidence, not published or CI-verified. + +| Command | Result and scope | +| --- | --- | +| `.\eng\bazel.ps1 build //:managed --jobs=8` | Exit 0; 35 source projects. | +| Same build again | Exit 0; 315 action-cache hits, one internal action, 1.869 seconds in the recorded no-op run. Not a benchmark against MSBuild. | +| `.\eng\bazel\validate.ps1` | Exit 0; seven-target baseline, 3,013 passing cases, real reports, failure/zero-result/aggregation assertions, and action-graph inspection. | +| `.\eng\bazel.ps1 test //:build_tools_tests` | Exit 0; nine new cases, all passed and exported to TRX. | +| `.\eng\bazel.ps1 test //:platform_tests --nocache_test_results` | Bazel exit 3 / host exit 2; 3,380 executed, 3,378 passed, two host-specific failures, zero skipped. | +| `.\eng\bazel.ps1 run //:platform_tests_app '--' --filter 'FullyQualifiedName !~ CreateServerStream_AnUnauthorizedIdentityCannotConnect & FullyQualifiedName !~ CreateServerStream_AnAppContainerConnectsOnlyWhenItsOwnPackageIsAuthorized'` | Exit 0; 3,378 executed/passed, zero skipped; not a full-suite pass. | +| `python .github\scripts\check_localization.py` | Exit 0; 364 catalogs valid. | + +The reproducible script writes `validation.json`, logs, TRX, four actual report +formats, and `actions.json` under `artifacts/bazel-validation/`. The recorded +run `20261029-132646-a5e454f4` found 404 declared C# compiler actions and no MSBuild +execution. Product exits were 0 for success/discovery, 2 for the known failing +sample, 9 for zero work with a minimum of one, and Bazel 3 for mixed module results. +Console output plus structured reports are more useful than screenshots here; +no demonstration was fabricated or uploaded. + +### Test-value evidence + +The preserved localization red state has patch SHA-256 +`B7CC4A0E2369ED1145384D8D9C92D137E35592EA46E934EDF09FAF4C09363FA1`; +the paired green state has +`7D4B0A9F33F01F1F043FEDB894DCFB3167D2572737275A406B0E92E4468D5309`. +Both apply to the baseline above. Their patches, logs, and TRX were retained in +the session's `bazel-evidence/localization-{red,green}` storage; these are +intermediate revision-bound comparisons, not a claim that every commit was +independently compared. Later baseline runs revalidated the final behavior. + +| Requirement | Evidence | +| --- | --- | +| Localized resource behavior survives native compilation | **Executed: detected.** `GetDisplayNameArgumentsDisplayNameRefreshesLocalizedFormat` and `GetDisplayNameRefreshesLocalizedFormatWhenUICultureChanges` failed without satellites and passed with them; same assertions, 1,634 cases executed in both states. | +| Resource text and generated encoding are preserved | `Resx_PreservesTextAndEmitsBom` executes LF and CRLF cases; exact resource/source text and BOM assertions pass. Existing `ExecuteForTestThrowingExceptionShouldReturnTestResultWithFailedOutcome` and `RunTestMethodForTestThrowingExceptionShouldReturnTestResultWithFailedOutcome` failed before newline preservation and pass afterward. | +| XLF fallback and errors are explicit | `Xlf_AppliesTargetsAndPreservesMissingTargetFallback`, four `Xlf_RejectsInvalidCatalog` cases, and `Resx_RejectsNonStringDataBeforeWritingOutputs` pass. Invalid inputs produce nonzero exits without result artifacts. | +| Version and build-stamp outputs follow inputs | `Metadata_UsesVersionTemplateAndBuildStamp` passes exact source/metadata/BOM assertions. | +| Process/consumer integration is real | Existing sample tests run source-built MSTest/MTP, controller/child exits propagate, and `validate.ps1` asserts reports and mixed-result failure rather than accepting an outer success alone. | + +Paired mutation evidence for every new helper branch, complete package/source API +compatibility, all platforms, and shipping/servicing parity remain unproven. + +## Open questions + +- How much of the existing source/test graph can the released rules build without + weakening compiler diagnostics or changing product behavior? +- Which existing tests assume an MSBuild output or NuGet shipping layout? +- Which upstream changes are required for .NET 11 and Windows app-model parity? +- Release rollout/backports: none enabled. This branch owns the experiment; + replacing any supported shipping build requires an explicit later decision and + real package-consuming acceptance evidence. diff --git a/docs/dev-guide.md b/docs/dev-guide.md index e490fd76e1..ef49d51cd9 100644 --- a/docs/dev-guide.md +++ b/docs/dev-guide.md @@ -50,6 +50,10 @@ This will update your fork with the latest from `microsoft/testfx` on your machi ## Building +An [experimental native Bazel build](bazel.md) is available for the managed +development graph. It does not replace the MSBuild/Arcade shipping build or its +complete framework/workload and acceptance matrix. + The easiest and recommended solution is to build the repository with the provided scripts at the repo root. For Windows: diff --git a/eng/bazel.ps1 b/eng/bazel.ps1 new file mode 100644 index 0000000000..aa0eda7a3c --- /dev/null +++ b/eng/bazel.ps1 @@ -0,0 +1,80 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#requires -Version 7.2 + +# Quote '--' when calling this PowerShell script so PowerShell forwards the separator. +$ErrorActionPreference = 'Stop' +$root = Split-Path $PSScriptRoot -Parent +$version = (Get-Content -LiteralPath (Join-Path $root '.bazelversion') -Raw).Trim() +if ($version -ne '8.8.2') { + throw 'Update the verified Bazel bootstrap hashes when changing .bazelversion.' +} + +if (-not ($IsWindows -or $IsMacOS -or $IsLinux)) { + throw 'The Bazel bootstrap supports Windows, Linux, and macOS.' +} + +$platform = if ($IsWindows) { 'windows-x86_64.exe' } elseif ($IsMacOS) { 'darwin-arm64' } else { 'linux-x86_64' } +$architecture = [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture.ToString() +if (($IsMacOS -and $architecture -ne 'Arm64') -or (-not $IsMacOS -and $architecture -ne 'X64')) { + throw "The Bazel bootstrap does not support this OS/architecture ($architecture). Install Bazelisk and use .bazelversion." +} + +$hashes = @{ + 'windows-x86_64.exe' = '07e467a78e709a4c9b0dca13da15121b4fcd7c6a037dfb4b17c72e527d4d6785' + 'linux-x86_64' = 'bf463ba0f5f782e8fe31071bd2b821c2f6a27f03e5bb62f0879e88cbf3656e04' + 'darwin-arm64' = 'ae640432a3fdb8a08c637562895f91c7ff1f63f04b1a9d34de9e9c46162bc10b' +} +$tools = Join-Path $root 'artifacts\bazel-tools' +$executable = Join-Path $tools "bazel-$version-$platform" +if (-not (Test-Path -LiteralPath $executable)) { + New-Item -ItemType Directory -Path $tools -Force | Out-Null + $download = "$executable.$([Guid]::NewGuid().ToString('N')).download" + try { + Invoke-WebRequest "https://github.com/bazelbuild/bazel/releases/download/$version/bazel-$version-$platform" -OutFile $download + if ((Get-FileHash -LiteralPath $download -Algorithm SHA256).Hash -ne $hashes[$platform]) { + throw 'Downloaded Bazel failed SHA-256 verification.' + } + + Move-Item -LiteralPath $download -Destination $executable -Force + } + finally { + if (Test-Path -LiteralPath $download) { + Remove-Item -LiteralPath $download + } + } +} + +if ((Get-FileHash -LiteralPath $executable -Algorithm SHA256).Hash -ne $hashes[$platform]) { + throw "Bazel failed SHA-256 verification: $executable" +} + +if (-not $IsWindows) { + & chmod +x $executable + if ($LASTEXITCODE -ne 0) { + throw 'Unable to make the Bazel executable runnable.' + } +} + +Push-Location $root +try { + # Windows cannot execute long .bat paths; isolate each worktree under a short root. + $identity = [Convert]::ToHexString([System.Security.Cryptography.SHA256]::HashData([System.Text.Encoding]::UTF8.GetBytes($root))).Substring(0, 12).ToLowerInvariant() + $outputRoot = if ($env:TESTFX_BAZEL_OUTPUT_ROOT) { + $env:TESTFX_BAZEL_OUTPUT_ROOT + } + elseif ($IsWindows) { + Join-Path ([System.IO.Path]::GetPathRoot($root)) "tfb\$identity" + } + else { + Join-Path ([System.IO.Path]::GetTempPath()) "tfb-$identity" + } + & $executable "--output_user_root=$outputRoot" --max_idle_secs=120 @args + $exitCode = $LASTEXITCODE +} +finally { + Pop-Location +} + +exit $exitCode diff --git a/eng/bazel/.gitignore b/eng/bazel/.gitignore new file mode 100644 index 0000000000..ef001d3c41 --- /dev/null +++ b/eng/bazel/.gitignore @@ -0,0 +1 @@ +paket-files/ diff --git a/eng/bazel/BUILD.bazel b/eng/bazel/BUILD.bazel new file mode 100644 index 0000000000..fd0c870bc3 --- /dev/null +++ b/eng/bazel/BUILD.bazel @@ -0,0 +1,29 @@ +load("@rules_dotnet//dotnet:defs.bzl", "csharp_binary", "dotnet_tool") + +package(default_visibility = ["//visibility:public"]) + +exports_files([ + "GlobalUsings.cs", + "TestMain.cs", + "analyzers.globalconfig", +]) + +csharp_binary( + name = "build_tools", + srcs = [ + "BuildTools.cs", + "GlobalUsings.cs", + ], + generate_documentation_file = False, + nullable = "enable", + target_frameworks = ["net10.0"], + treat_warnings_as_errors = True, +) + +dotnet_tool( + name = "paket", + entrypoint = {"net10.0": "paket.dll"}, + runner = {"net10.0": "dotnet"}, + target_frameworks = ["net10.0"], + deps = "@paket_cli//:tools", +) diff --git a/eng/bazel/BuildTools.cs b/eng/bazel/BuildTools.cs new file mode 100644 index 0000000000..9f50ff3b67 --- /dev/null +++ b/eng/bazel/BuildTools.cs @@ -0,0 +1,183 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Resources; +using System.Text.Json; + +if (args.Length == 5 && args[0] == "resx") +{ + GenerateResources(args[1], args[2], args[3], args[4]); +} +else if (args.Length == 5 && args[0] == "xlf") +{ + GenerateTranslations(args[1], args[2], args[3], args[4]); +} +else if (args.Length == 11 && args[0] == "metadata") +{ + GenerateMetadata(args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9], args[10]); +} +else +{ + throw new ArgumentException("Expected resx , xlf , or metadata