bazelbuild / bazelbuild/rules_rust

Cargo features are enabled for all target triples

Open
#4,163 1 comment 0 reactions 0 assignees View on GitHub
awaiting-response crate-universe
Dominant language
Starlark
Stars
843
Forks
651
Avg merge
2d 18h
Merged PRs (30d)
15

Description

**Description**

`crate_universe` resolves Cargo features once across the whole workspace and emits a single shared target per crate, used by every target triple. So a feature enabled by _any_ workspace member is enabled for that crate on _all_ triples, and there is no way to drop a feature (or the dependencies it brings in) for a specific triple. Cargo itself resolves features per target and wouldn't do this; `crate_universe` collapses that distinction.

This breaks cross-platform workspaces where a feature is fine on one triple but not another. Concretely: one member (built for a host triple) enables the `net` feature in Tokio. The shared `tokio` target then has `net` on for `wasm32-unknown-unknown` too, pulling in `mio` and `socket2`. They don't build there — even though the Wasm member only uses `rt`/`macros`/`time` from Tokio. The Wasm build fails with

> Only features sync,macros,io-util,rt,time are supported on wasm.

**Reproduction steps**

Two Rust crates that depend on Tokio with different Cargo features. First crate:

```toml
[package]
name = "native-app"
version = "0.0.0"
edition = "2021"

[dependencies]
tokio = { version = "1", features = ["net"] }
```

Second crate:

```toml
[package]
name = "wasm-app"
version = "0.0.0"
edition = "2021"

[dependencies]
tokio = { version = "1", features = ["rt", "macros", "time"] }
```

Bazel workspace setup:

```python
crate.from_cargo(
name = "crate_index",
cargo_lockfile = "//:Cargo.lock",
manifests = ["//:Cargo.toml", "//native-app:Cargo.toml", "//wasm-app:Cargo.toml"],
supported_platform_triples = [
"x86_64-unknown-linux-gnu",
"wasm32-unknown-unknown",
],
)
```

Build file:

```python
rust_library(
name = "wasm-app",
srcs = glob(["src/**/*.rs"]),
edition = "2021",
target_compatible_with = ["@platforms//cpu:wasm32"],
deps = all_crate_deps(normal = True), # resolves to @crate_index//:tokio
)
```

Building the web app with `bazel build --platforms=@rules_rust//rust/platform:wasm32 //wasm-app:wasm-app` now because we try to compile `mio` and `socket2` for `wasm32`, which they don't support.

**Additional context**

I had Claude suggest a fix for this, coming up in a PR next.

**Impact**

I believe this makes it impossible to build our Rust business logic for Wasm.

**Bazel and rules_rust version**

- Bazel: 9.1.1
- rules_rust: 0.71.3

Contributor guide

Open the contributing guide

Research direction

Start with the crate.from_cargo configuration and all_crate_deps(normal = True) in the reproduction, then trace how Cargo features become the shared @crate_index//:tokio target. Compare that behavior with Cargo's per-target feature resolution. Done means the native and Wasm examples resolve only their target-supported Tokio features and the wasm32 build no longer attempts mio or socket2.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
build-system
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.