What I was trying to do: Build a Rust wasm component (agora's agent) in a fresh external consumer repo via rules_wasm_component — a wit_library + rust_wasm_component_bindgen and bazel build //agent:agent. (agora is a brand-new repo with no prior Bazel setup.)
Tool + version: rules_wasm_component @ main (local_path_override / git_override), Bazel 9.1.1, rules_rust 0.69.0 (matching the ruleset's pinned commit).
What happened: Getting a minimal external consumer to build took four non-obvious, undocumented steps, each surfaced only as a cryptic error after a full ~20-min toolchain download:
- Root
BUILD.bazel required. Without one: rules_rust+/crate_universe/extensions.bzl ... module_ctx.path(Label("@@//:MODULE.bazel")).dirname → Unable to load package for //:MODULE.bazel: BUILD file not found. The crate_universe extension runs because the ruleset uses crate.from_cargo, so even a consumer that only builds a component needs a root package marker.
@crates hub must be imported. The generated *_bindings_wasm_base target references @crates//:wit-bindgen and @crates//:bitflags (hardcoded in rust_wasm_component_bindgen.bzl), which aren't visible to a consumer → no such package '@crates' ... No repository visible as '@crates'. Fix: use_repo(crate, "crates").
- The
crate extension requires the consumer to declare its own from_cargo tag (.from_cargo or .from_specs are required. Please update <module>) — use_repo(crate, "crates") alone is rejected.
- The
from_cargo lockfile label needs its dir to be a package — module_ctx.watch(//host:Cargo.lock) → BUILD file not found ... - host. Needs a host/BUILD.bazel with exports_files(["Cargo.toml","Cargo.lock"]).
Once all four are in place, bazel build //agent:agent succeeds and produces a valid native WASI 0.2.6 component (wasi:io@0.2.6/wasi:cli@0.2.6, exports the world). So the ruleset works — the friction is purely the undocumented external-consumer bootstrap.
Repro: new repo, MODULE.bazel with bazel_dep(rules_wasm_component) + a wit_library + rust_wasm_component_bindgen, bazel build //agent:agent. Each of the 4 errors appears in sequence.
Workaround used: Reverse-engineered the recipe from wasm-component-examples/MODULE.bazel (which shows use_repo(crate, ..., "crates")) and the rule source. Final working MODULE.bazel needs: root BUILD.bazel; crate = use_extension(...) + a crate.from_cargo(...) + use_repo(crate, "<own>", "crates"); and the lockfile dir made a package.
Impact: Slowed (significantly) — ~4 failed builds, each gated behind a long toolchain fetch, to discover an undocumented bootstrap. Suggestions: (a) a "minimal external consumer" doc/template (the 4 steps as a checklist); (b) make the @crates error message point at use_repo(crate, "crates"); (c) consider exposing wit-bindgen/bitflags deps via the ruleset itself (an alias under @rules_wasm_component//...) so consumers don't have to wire @crates; the rule already supports bitflags_dep override but @crates//:wit-bindgen looks hardcoded.
What I was trying to do: Build a Rust wasm component (
agora's agent) in a fresh external consumer repo viarules_wasm_component— awit_library+rust_wasm_component_bindgenandbazel build //agent:agent. (agorais a brand-new repo with no prior Bazel setup.)Tool + version: rules_wasm_component @ main (local_path_override / git_override), Bazel 9.1.1, rules_rust 0.69.0 (matching the ruleset's pinned commit).
What happened: Getting a minimal external consumer to build took four non-obvious, undocumented steps, each surfaced only as a cryptic error after a full ~20-min toolchain download:
BUILD.bazelrequired. Without one:rules_rust+/crate_universe/extensions.bzl ... module_ctx.path(Label("@@//:MODULE.bazel")).dirname → Unable to load package for //:MODULE.bazel: BUILD file not found. The crate_universe extension runs because the ruleset usescrate.from_cargo, so even a consumer that only builds a component needs a root package marker.@crateshub must be imported. The generated*_bindings_wasm_basetarget references@crates//:wit-bindgenand@crates//:bitflags(hardcoded inrust_wasm_component_bindgen.bzl), which aren't visible to a consumer →no such package '@crates' ... No repository visible as '@crates'. Fix:use_repo(crate, "crates").crateextension requires the consumer to declare its ownfrom_cargotag (.from_cargo or .from_specs are required. Please update <module>) —use_repo(crate, "crates")alone is rejected.from_cargolockfile label needs its dir to be a package —module_ctx.watch(//host:Cargo.lock) → BUILD file not found ... - host. Needs ahost/BUILD.bazelwithexports_files(["Cargo.toml","Cargo.lock"]).Once all four are in place,
bazel build //agent:agentsucceeds and produces a valid native WASI 0.2.6 component (wasi:io@0.2.6/wasi:cli@0.2.6, exports the world). So the ruleset works — the friction is purely the undocumented external-consumer bootstrap.Repro: new repo,
MODULE.bazelwithbazel_dep(rules_wasm_component)+ awit_library+rust_wasm_component_bindgen,bazel build //agent:agent. Each of the 4 errors appears in sequence.Workaround used: Reverse-engineered the recipe from
wasm-component-examples/MODULE.bazel(which showsuse_repo(crate, ..., "crates")) and the rule source. Final working MODULE.bazel needs: rootBUILD.bazel;crate = use_extension(...)+ acrate.from_cargo(...)+use_repo(crate, "<own>", "crates"); and the lockfile dir made a package.Impact: Slowed (significantly) — ~4 failed builds, each gated behind a long toolchain fetch, to discover an undocumented bootstrap. Suggestions: (a) a "minimal external consumer" doc/template (the 4 steps as a checklist); (b) make the
@crateserror message point atuse_repo(crate, "crates"); (c) consider exposingwit-bindgen/bitflagsdeps via the ruleset itself (an alias under@rules_wasm_component//...) so consumers don't have to wire@crates; the rule already supportsbitflags_depoverride but@crates//:wit-bindgenlooks hardcoded.