NativeLink
Contribute

Develop with Bazel

Build, test, and run NativeLink with Bazel, the same dev loop CI uses.

The Bazel-based dev loop is the one our CI runs. Use this if you want the most reproducible setup or if your editor integration prefers Bazel.

Prerequisites

  • Bazelisk, which reads .bazelversion and fetches the right Bazel for you. CI runs 9.1.1 and also checks 8.7.0.
  • A C++ toolchain (clang or gcc) for native dependencies.
  • On macOS: XCode command-line tools.
  • On Linux, inside the Nix shell, the LRE toolchains link with mold; outside it Bazel uses whatever the host toolchain provides.

First build

git clone https://github.com/TraceMachina/nativelink
cd nativelink
bazel test //...

The first bazel test will take 10-20 minutes as it builds the toolchain and dependencies. Subsequent builds finish in seconds.

Hooking up your own cache

.bazelrc already defines --config=self_test (remote cache at grpc://127.0.0.1:50051) and --config=self_execute (remote executor at grpc://127.0.0.1:50052) for a NativeLink running locally. For any other endpoint, put the flags in user.bazelrc at the repository root, which .bazelrc pulls in with try-import and git ignores:

build --remote_cache=grpc://localhost:50051
build --remote_executor=grpc://localhost:50051

With a NativeLink cluster running, subsequent builds will hit the cache for any action your team has already produced.

Common commands

# Run all tests.
bazel test //...

# Run one crate's tests/ directory.
bazel test //nativelink-store:integration

# Run the in-file `mod tests` suites, or the doc examples.
bazel test //:unit_tests
bazel test doctests

# Build the server binary. The binary is defined in the root BUILD.bazel,
# so its label is `//:nativelink`; there is no `//nativelink` package.
bazel build //:nativelink

# Run the built binary against a config.
bazel run //:nativelink -- /path/to/config.json5

# Format Rust code. The formatting config uses nightly-only options, so
# stable `cargo fmt` produces different output than CI expects.
bazel run --config=rustfmt @rules_rust//:rustfmt

See the testing guide for what unit_test and integration actually mean in this repository; they do not mean what the names suggest.

Editor integration

For rust-analyzer:

bazel run @rules_rust//tools/rust_analyzer:gen_rust_project

This generates a rust-project.json that VS Code / Helix / your editor of choice will pick up.

Common pitfalls

  • LRE flags are missing: .bazelrc pulls in lre.bazelrc, nativelink.bazelrc, nixos.bazelrc and darwin.bazelrc with try-import, and the Nix dev shell is what generates them. Without nix develop they do not exist, and the try- means Bazel says nothing about it. See Develop with Nix.
  • Slow first build with no cache: expected. Subsequent builds reuse Bazel's local cache; pointing at a remote NativeLink cluster makes a fresh clone fast for everyone.
  • A new source file builds with Cargo and fails under Bazel: Bazel enumerates srcs rather than globbing. Add the file to the crate's BUILD.bazel, alphabetically.

FAQ

On this page