Skip to content

[Build] Add experimental native Bazel desktop build foundation - #33888

Open
Justin Chu (justinchuby) wants to merge 13 commits into
mainfrom
bazel-native-build
Open

Justin Chu (justinchuby) wants to merge 13 commits into
mainfrom
bazel-native-build

Conversation

@justinchuby

@justinchuby Justin Chu (justinchuby) commented Nov 4, 2026 •

Copy link
Copy Markdown
Contributor

Description

Add an experimental source-native Bazel graph for ORT, MLAS, ONNX/protobuf, Linux CUDA, and Python, Java/JNI, Go, Node-API, and C# desktop bindings. Production targets do not invoke CMake, build.py, or foreign-build wrappers. Dependency locks, commands, supported scope, and measurements are in docs/Bazel.md.

Shared-runtime imports co-locate provider runfiles without eager provider linking. A non-LTO release profile produces package-ready binaries through the selected C++ toolchain's strip action, with platform-specific policies and opt-only linker optimizations. The standalone parity helper rejects regressions and inconclusive confidence intervals.

Validation:

  • Current foundation 621b028652: 9/9 selected native CPU targets passed on Linux, Windows, and macOS, including static/shared runtime, common/cpuinfo, Python, Java, Go, Node, and C# (completed run).
  • Windows frozen release analysis passed 66 targets with zero actions; the parity helper's 11 regression tests passed through native Bazel. Ruff, buildifier, and diff checks passed.
  • Earlier source-built H200/sm90 inference covered CUDA 12.0.1, 12.8, 13.0.2, and 13.3 with CPU fallback disabled. This is selected-toolkit/architecture coverage, not an exhaustive matrix.
  • Dependent [Build] Add native Bazel test, binding, platform, and packaging targets #33890 passed 17 Linux release/consumer targets, including real offline Rust consumers, with extracted native package members matching declared release outputs. Its CUDA 13.3 wheel built and passed installed import/eager-provider loading; installed-wheel inference remains blocked by allocated authorized GPUs. Android ARM64 source build, NDK stripping, and AAR/ELF byte-identity proof passed; installed Android inference is unverified.

Strict performance parity fails. The exact shipped Linux SDK runtime (SHA256 6f3b9425ce667ea6ba282b9d2d991b948105f59a3f7fff872585d2708d9170ea) was measured in 80 alternating paired trials on CPU3 against pinned main 98cf8961f23908912699991d69c7b9bf02490454, built with Release O3, LTO, and BinSkim-compliant flags. Paired-median candidate/baseline ratios and 95% confidence intervals:

Workload Ratio 95% CI Strict result
Add 0.92556 [0.91727, 0.93357] Pass
Conv 1.01142 [1.00622, 1.01690] Regression
MatMul 1.00082 [0.99608, 1.00528] Inconclusive

Measured size passes: stripped runtime 19,471,680 vs 23,950,912 bytes; deterministic compressed payload 7,186,446 vs 9,176,748 bytes. This is not full feature equivalence: CPU stream support differs, and full-main shipping has broader operator coverage. Earlier comparisons remain separate, including the default-Release Conv regression. Production remains O2 with existing MLAS-only frame omission; rejected optimization experiments are not included. No same-or-better performance claim is made.

#33890 adds selectable tests, Rust, Apple/mobile/web graphs, and language packages. At fa886020, Linux CI passed graph analysis, binding/package consumers, selected existing C++/managed cases, and the CPU wheel (completed run). Native Objective-C/Swift inference and the iOS framework/test-bundle build also passed on macOS. Complete macOS graph/Catalyst and Windows Maven validation still fail; targeted repairs are in progress. CI uses explicit representative targets, not bazel test //.... Training, other EPs, and full release matrices are outside this experimental scope. Replaces #33859 with a two-PR stack.

Motivation and Context

Establish a direct, dependency-aware Bazel foundation and migrate build/test and packaging surfaces in two stacked PRs.

…dings

Compile ORT, MLAS, ONNX/protobuf, CUDA, and five desktop bindings directly with Bazel. Include CPU integration tests, fallback-disabled CUDA tests, pinned dependencies, and a documented coverage matrix.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Add OS-selected runtime sources, native library artifacts, MSVC/MASM and Apple ARM64 MLAS targets, platform wheel hashes, and a desktop validation matrix. Cross-platform validation is in progress.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Two critical build issues block macOS: an Objective-C++ source in a cc_library fails analysis on both configurations, and an incompatible assembly directive prevents Intel macOS compilation.

2 open issues
What changed in this PR

Adds an experimental native Bazel foundation alongside the existing build system, enabling incremental migration of ONNX Runtime and desktop bindings without invoking CMake or build wrappers. macOS targets are included but remain unverified.

Changes:

  • Defines native runtime, MLAS, ONNX/protobuf, and optional Linux CUDA targets.
  • Adds five desktop binding targets, inference smoke tests, and desktop CI.
  • Pins dependencies, enforces frozen module locks, and documents coverage and limitations.
File Description
tools/​bazel/​RuntimeSmokeTest.java Tests Java/JNI Add inference.
tools/​bazel/​RuntimeSmokeTest.cs Tests C# Add inference.
tools/​bazel/​runtime_smoke_test.cc Tests CPU/CUDA Add, MatMul, and Conv inference.
tools/​bazel/​python_smoke_test.py Tests native Python extension inference.
tools/​bazel/​node_smoke_test.cjs Tests Node-API inference.
onnxruntime/​core/​session/​environment.cc Copies provider factories using reserve and iteration.
MODULE.bazel.lock Records resolved module and extension state.
MODULE.bazel Declares dependencies and language toolchains.
docs/​Bazel.md Documents usage, validation, and migration limits.
cmake/​vcpkg-ports/​abseil/​absl_cuda13_member_template.patch Adds Git diff headers to the reused patch.
BUILD.bazel Defines runtime libraries and C++ tests.
bazel/​requirements.txt Pins NumPy for Python targets.
bazel/​python.lds Limits Python extension symbol exports.
bazel/​platforms.bzl Defines platform-specific shared-library helpers.
bazel/​onnxruntime.lds Controls runtime symbol exports.
bazel/​onnx.BUILD.bazel Builds ONNX and generated protobuf sources.
bazel/​mlas.bzl Defines architecture-specific MLAS kernel targets.
bazel/​mingw.BUILD.bazel Configures the Windows cgo compiler.
bazel/​local_sdk.bzl Exposes local cuDNN SDK headers.
bazel/​jni_headers.bzl Extracts generated JNI headers.
bazel/​headers_only.bzl Separates compilation requirements from linking.
bazel/​go_desktop.bzl Isolates Windows cgo configuration and wraps tests.
bazel/​dependencies.bzl Declares checksum-pinned source archives.
bazel/​cuda.bzl Defines CUDA kernels and shared providers.
bazel/​cuda_provider.lds Restricts CUDA provider exports.
bazel/​BUILD.bazel Declares platform settings and CUDA opt-in.
bazel/​bindings.bzl Defines desktop bindings and their tests.
bazel/​abseil-includes.patch Exposes Abseil include paths.
.gitignore Ignores Bazel workspace links.
.github/​workflows/​bazel_native.yml Adds a four-host desktop CI matrix.
.bazelversion Pins the Bazel version.
.bazelrc Sets frozen locks and platform build options.
.bazelignore Excludes generated and dependency directories.

Review effort: Balanced

Comment thread BUILD.bazel Outdated
"onnxruntime/core/platform/posix/stacktrace.cc",
],
}) + select({
"//bazel:macos": ["onnxruntime/core/platform/apple/logging/apple_log_sink.mm"],
Comment thread bazel/mlas.bzl
Comment on lines +96 to +99
"//conditions:default": native.glob([
_LIB + "x86_64/*Sse2.S",
_LIB + "x86_64/cvtfp16a.S",
]),
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@edgchen1

Copy link
Copy Markdown
Contributor

just curious about the motivation for this. would we have to maintain two build systems (this and CMake)?

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Measure native Bazel against a controlled CMake baseline and close the observed convolution gap without changing debug or other platforms.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
import json
import stat
import tempfile
import unittest
@justinchuby

Copy link
Copy Markdown
Contributor Author

just curious about the motivation for this. would we have to maintain two build systems (this and CMake)?

This is an experiment to streamline the build experience and to make it more efficient. For downstream usage, yes, we would have to maintain two build systems. The hypothesis is that once this is setup, AIs will be able to keep them in sync.

That said we still need to be more clear on how the bazel system will make our workflow different. Suggestions welcome

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants