rules_dx is a Bazel developer platform with one dx CLI for
build, test, lint, typecheck, format, generate, audit, and release tasks.
Language toolchains come from Bazel. No separate installs.
Bazel via Bazelisk is required. In an empty directory, create three files.
.bazelversion:
9.3.1
MODULE.bazel:
bazel_dep(name = "rules_dx", version = "<release>")BUILD.bazel:
# Empty on purpose: rules_rust crate_universe needs a root package.Then:
bazel run @rules_dx//:dx -- init --apply
tools/dx test //...After that, run dx through the launcher:
tools/dx --help
tools/dx build //...On a fresh clone, run tools/dx first. Any dx command writes the gitignored .dx/bazelrc layers that plain bazel reads.
Behind a proxy or a company CA? See Corporate proxy and custom CA.
In your module, @rules_dx//:dx runs the dx binary for the target
platform, checked against the sha256 in cli/prebuilt/pins.bzl.
A release pins binaries for linux x86_64, linux aarch64, macos aarch64,
windows x86_64 and windows aarch64. A version with no
pinned sha256 builds dx from source, with the Rust and C toolchains
dx init sets up. Once some binary is pinned, platforms with no release
binary fail the build. To pick a binary yourself, add this to your root
MODULE.bazel:
dx_prebuilt = use_extension("@rules_dx//cli/prebuilt:extension.bzl", "dx_prebuilt")
dx_prebuilt.asset(name = "dx-linux-x86_64", url = "https://...", sha256 = "...")Or build dx from source with dx_prebuilt.from_source(). That needs Rust
and C toolchains. Only the root module's tags count.
The Gazelle binary behind dx generate works the same way. Each release
ships a pure-Go dx-gazelle-<os>-<cpu> per platform, pinned in
GAZELLE_SHA256 under the same DX_VERSION, so the first dx generate
fetches no Go SDK. It builds from source instead when rules_dx is the root
module, when no gazelle binary is pinned, or when a module other than
rules_dx adds a dx_gazelle.language, because the release binary holds only
the languages rules_dx registers. The root module can override it:
dx_gazelle = use_extension("@rules_dx//gazelle/dispatch:extension.bzl", "dx_gazelle")
dx_gazelle.asset(name = "dx-gazelle-linux-x86_64", url = "https://...", sha256 = "...")or build it with dx_gazelle.from_source(), which needs a Go toolchain.
A global dx shim for PATH is built from //cli/shim. It runs the version in
.dx/pins without Bazel. See
Global Shim.
- Microsoft
cl.exe(--//cc:compiler=msvc): the Visual Studio Build Tools come from the hermetic@dx_msvcrepo, not an installed Visual Studio. The download needs the Visual Studio Build Tools license, accepted withdx_licenses.accept(ids = ["visual-studio-build-tools"]). See the support matrix. - GCC (
--//cc:compiler=gcc): GCC 16.2.0 onlinux_x86_64andlinux_arm64, with no install.
tutorial, docs index, Bazel for dx users, adopting rules_dx in an existing Bazel repo, adopting rules_dx without Bazel experience, command reference, examples, CI, support matrix, and the docs site.
You get:
- One
dxCLI instead of per-language scripts. - Pinned toolchains, so nobody installs tools per machine.
- Lint, format, and typecheck locally and in CI.
- Security and license audits with
dx securityanddx license; see audit and update. - A CI workflow from
dx init --apply; see init. - It replaces hand-picked rule-set versions, a Makefile or shell wrapper around Bazel, and CI config per language.
It costs:
- Bazel and its learning curve: BUILD files and
MODULE.bazel. - The files
dx initwrites: launcher, editor, devcontainer, CI and agent files; see init. - Following the pinned rule and tool versions. You move when you run
dx upgrade.
See Contributing for the current workflow.
rules_dx is licensed under Apache-2.0.