Skip to content

Rebase Canva cargo-bazel changes onto rules_rust 0.75.0 (0.75.0+canva.1) - #2

Merged
ellgorrell merged 126 commits into
mainfrom
ellgorrell/0.75.0-canva.1
Oct 27, 2026
Merged

ellgorrell merged 126 commits into
mainfrom
ellgorrell/0.75.0-canva.1

Conversation

@ellgorrell

@ellgorrell ellgorrell commented Oct 27, 2026 •

Copy link
Copy Markdown

Bring in 0.75 from upstream repo

UebelAndre and others added 30 commits July 2, 2026 01:09
…4118)

For vscode users who commit `.code-workspace` or `settings.json`, this
change introduces a cross-platform compatible entrypoint for
rust-analyzer infrastructure. Note that this doesn't mean the binaries
are magically platform agnostic. It just means the two files mentioned
will be compatible on both Unix and Windows platforms if the vscode
config files are source controlled.
…ld#4117)

Location expansion happens outside the control of path mapping logic and
would produce paths with build configuration in them, breaking path
mapping's logic of replacing all build configuration with the literal
"cfg".
Adds regression testing for
bazelbuild#4117 as well as identifies
some cases where there are further incompatibilities (namely uses of
`rust_test.crate`).
toolchains_llvm
[now](bazel-contrib/toolchains_llvm@1194923)
force-includes a header via `-imacros`, which surfaced this bug.
This is bazelbuild#3168 by @durin42, with fixes for some of the pre-merge checks.

This PR adapts the original change to support path mapping when passing
`-Zsplit-dwarf-out-dir=<path>`. In order to do this, it adds to
`construct_arguments` the option to pass `(format_string, File)` as
elements in the list form of `rustc_flags`. This PR also adds tests for
the new functionality.

The new changes on top of the original PR were written with assistance
by Gemini.

---------

Co-authored-by: Augie Fackler <augie@google.com>
…build#4127)

`discover_bazel_rust_project` builds the rust-analyzer aspect over the
whole workspace and bailed on any non-zero Bazel exit. In a large
monorepo a single broken target (e.g. an unrelated, unmaintained one)
aborted the build, leaving rust-analyzer with no Bazel project model. It
then silently falls back to a Cargo workspace, which breaks proc-macro
expansion (toolchain ABI mismatch) and materializes a stray `target/`.

Pass `--keep_going` so Bazel keeps building the rest of the graph, and
treat the result as usable when the BEP still yielded crate specs:
proceed with a `log::warn` that the project may be incomplete, and only
fail when zero specs were produced. This mirrors `flycheck`'s existing
exit-code handling.

Add an end-to-end test that stands up a workspace with one good
`rust_library` and one target that fails analysis, then checks discovery
still returns a project containing the good crate. Unit tests cover the
`assess_discovery` decision.

Written with Claude, but I believe I understand what is going on.
These were not triggered before the PR was merged. I’m not sure why more
tests are run on `main` than on PRs, but maybe this could be revisited
to at least gate PRs on this kind of thing?
The --incompatible_auto_exec_groups flag requires Starlark actions to
declare whether their executable/tools come from an action toolchain.
This is not a Bazel default today, but it is exposed through strict
preset configurations and is intended to catch rules that rely on
implicit action toolchain inference.

rustfmt_aspect runs rustfmt from rules_rust's rustfmt toolchain, but the
formatting action does not declare that action toolchain. Declare the
matching rustfmt toolchain so the action's toolchain behavior is
explicit without changing its inputs or execution model.
### The bug

Since the `OUT_DIR` sanitization work (bazelbuild#4050 / bazelbuild#4011, first released in
0.71.x), `outputs_to_dep_env` redacts the producer's `out_dir` to the
generic `${out_dir}` substitution token, the same way `outputs_to_env`
does.

That redaction is only correct for `_bs.env` files, which are consumed
by the target that directly owns the build script (where
`process_wrapper`'s `--out-dir` resolves the token to the right
directory). Dep env (`DEP_*`) files, however, are consumed by
*downstream* crates' build scripts: their runner only substitutes
`${pwd}`, and their own `out_dir` points to a different directory. The
token is therefore left unresolved, or would resolve to the wrong
directory.

Real-world failure: `libssh2-sys`'s build script fails to find `zlib.h`
because `libz-sys`'s `DEP_Z_INCLUDE` contains a literal `${out_dir}`
path component. Found while upgrading `rules_rust` to 0.71.3 in
dfinity/ic (see dfinity/ic#10632, where this fix is currently carried as
a patch).

### The fix

Only substitute the exec root in dep env files and keep the real
`out_dir` path. That path is valid for consumers: the producer's
`out_dir` is a declared input of downstream build script actions.

### Tests

* Unit test
`out_dir_in_dep_env_value_is_not_redacted_to_substitution_token` in
`cargo/private/cargo_build_script_runner/lib.rs`.
* End-to-end regression test `//cargo/tests/dep_env:build_read_out_dir`
mirroring the libz-sys → libssh2-sys scenario: a producer build script
advertises `cargo:include=$OUT_DIR/include` and the consumer build
script asserts `DEP_Z_INCLUDE` points at an existing directory. Fails
without the fix, passes with it.

---

Assisted-by: GitHub Copilot
The rewrite of the Rust Analyzer auto-discovery pipeline (see bazelbuild#4075)
introduced a bug for users who use
`--experimental_convenience_symlinks=ignore` (i.e. have no bazel-out
symlink in their workspace).

`parse_output_group_paths` documentation suggests that output paths are
always absolute


https://github.com/bazelbuild/rules_rust/blob/dedf05304354aace6a76ae78030a9d69c74e37d4/tools/rust_analyzer/bep.rs#L107-L110

but that is not true for BEP events that trigger the fallback
reconstruction path


https://github.com/bazelbuild/rules_rust/blob/dedf05304354aace6a76ae78030a9d69c74e37d4/tools/rust_analyzer/bep.rs#L241-L243

This PR detects those cases and anchors those paths to the execution
root, making them also absolute.
The change aims to cleanly handle merging rust-analyzer settings into
existing vscode config files that are `jsonc` vs valid `json`.
…4140)

Written by AI, reviewed by human.

Fixes bazelbuild#4139.

## Summary

`consolidate_crate_specs` prefers proc-macro dylib paths that look like
exec outputs. The previous marker matched paths with `-opt-exec-`, but
Bazel can also emit exec paths like `bazel-out/k8-opt-exec/bin/...`.

This updates the marker to match both forms and adds a regression test
for the unsuffixed `k8-opt-exec/bin` path shape.

## Testing

```sh
bazel test --cache_test_results=no //tools/rust_analyzer:gen_rust_project_lib_test
```
This allows the remote repo contents cache to cache the result of these
Implements bazelbuild#4143 and also
fixes a memory leak from multiple rust-analyzer processes for different
rust-analyzer-workspaces.

closes bazelbuild#4143
…n. (bazelbuild#4135)

This allows callers of rustc_compile_action to override the default
flags.

The motivating example for making this change was some path remapping
done by Crubit
(https://github.com/google/crubit/blob/685a46aabbdf6552803c5bd77da6628008d0d245/rs_bindings_from_cc/bazel_support/compile_rust.bzl#L100).
PR bazelbuild#4106 added another `--remap-path-prefix` flag after the code that
adds `rust_flags` to the rustc invocation, and the new remapping took
precedence.
Changes:
- Add `rust_clippy_test` for having a test target that runs clippy on a
list of targets
- Add a `transitive` bool to `rustfmt_test` that aggregates
`rustfmt_aspect` outputs from deps of `targets`. This behavior also
applies to the new `rust_clippy_test`
Crates with generated inputs have their source files and compile data
staged under bazel-out so rustc can resolve modules from one root. The
compile action still points `CARGO_MANIFEST_DIR` at the source package,
which is absent from the sandbox and breaks proc macros that read files
relative to the manifest.

Assisted-by: GPT-5.6 Sol
This change updates `rustfmt_test` and `rust_clippy_test` to behave more
consistently with the aspect output groups by ensuring transitive
targets in the transitioned configuration get added to `//...`
invocations.
Allows specifying `root_path` when the crate root (`srcs` entrypoint) is
a directory artifact (`TreeArtifact`). This enables rules_rust targets
(`rust_library`, `rust_binary`, `rust_test`, etc.) to consume directory
artifacts produced by upstream rules and correctly construct the path to
the crate root (`lib.rs` / `main.rs`).

We use something like this internally to build standard libraries from
sources distributed as .zip source archives: a custom rule extracts the
contents into a generated directory artifact, which then the rust rules
can consume as sources.

This may be helpful to achieve the request from
bazelbuild#3757, where the user is
trying to consume a directory of generated sources.

* Adds `root_path` attribute to `_COMMON_ATTRS` and `CrateInfo`
provider.
* Updates `rustc_compile_action` argument construction (`rustc.bzl`) to
join `crate_info.root.path` with `root_path` when
`crate_info.root.is_directory` is true.
* Adds a unit and build test case under `test/root_path/` using a custom
rule that packages its `srcs` as a directory artifact (`TreeArtifact`)
and compiles a `rust_library` and `rust_test` from it.

I have taken special care in the rustc argument construction to ensure
it is compatible with the new [bazel path remapping
guidelines](bazelbuild/bazel#22658).

While here, added a few checks in the rules for combinations of `srcs`,
`crate` and `crate_root` attributes that don't make sense and would
cause compilation to fail later anyways.
There seemed to be a confusion around `CrateInfo.output` being optional
within the rustdoc rules that leads to a `NoneType` error when using
rustdoc on a generated crate root:
```
external/rules_rust+/rust/private/rustc.bzl:1090:38: Traceback (most recent call last):
File "external/rules_rust+/rust/private/rustc.bzl", line 2883, column 16, in _get_dirname
    return file.dirname
Error: 'NoneType' value has no field or method 'dirname'
```

This change adds a proper output to satisfy the the current `CrateInfo`
interface.
…ild#4160)

This is intended to give better control and more flexibility for
extensions like Crubit, which automatically generates rust bindings for
C++ code. The bindings generator uses an aspect to crawl over a
dependency graph of cc_libraries, plugs itself as a tool similar to a
C++ compiler, parses the header files and generates the corresponding
Rust bindings.
Due to the C++ compilation model, it's possible that a header file in a
library uses a C++ symbol that is only defined in a header file owned by
an indirect dependency of a c++ library. For example:

```
rust_library(name = "a", hdrs = ["a.h"])
rust_library(name = "b", hdrs = ["b.h"], deps = ["a"]) 
rust_library(name = "c", hdrs = ["c.h"], deps = ["b"])

# c.h
using C = int;
# a.h
C f();
```

While compiling the generated Rust bindings of `c`, the Rust compiler
needs access to the generated Rust bindings of `a`, which is an indirect
dependency. Historically, this was achieved via the
`force_all_deps_direct` feature, which has the effect of putting all
direct and indirect crate dependencies as `--extern` while compiling the
bindings for a c++ target. This is imprecise and suffers from crate name
collisions.

It is imprecise, because if any cc_library happens to depend on a rust
library as an implementation detail, that rust library does not need to
be made available via `--extern`.

It suffers from crate name collisions, because by default the crate
names of generated bindings are derived from the name of the label of
the c++ library. In a build graph where where two c++ libraries from
different packages share the same name, there is a naming collision when
client bindings are compiled:
```
# the generated bindings of both //p:a and //q:a produce a crate named a.
cc_library(name = "client", deps = ["//p:a", "//q:a"])
```
To handle these, we provide `extra_named_deps` a mechanism for
extensions calling `rustc_compile_action` to supply an extra `depset` of
named dependencies. The Crubit aspect can then compute appropriate names
for the generated bindings of dependencies. For this to work at scale,
we supply this as a depset to be computed recursively by the aspect
crawling the dependency graph, avoiding quadratic blaze analysis time
overhead.

The supplied test is a mock of the type of code pattern possible in this
context -- a chain of 3 rust libraries, where the top-level one refers
to its indirect dependency via a custom crate name.
This change introduces `use_cc_toolchain` to `cargo_build_script` which
can be used to control whether or not a `cc_toolchain` is explicitly
withheld from `CargoBuildScript` actions. Additionally a global flag
`--@rules_rust//cargo/settings:use_cc_toolchain` can be used to control
the default of any build script that has not either explicitly set
`use_cc_toolchain = 1` (always include cc toolchains) or
`use_cc_toolchain = 0` (always exclude cc toolchains).

closes bazelbuild#3680
closes bazelbuild#3679

Co-authored-by: Krasimir Georgiev <krasimir@google.com>
This change determines whether to use `pic_static_library` or
`static_library` in `cc_common.create_library_to_link` based on the
`should_use_pic` helper. It also updates the unit tests to expect only
one of the libraries depending on the configuration.

Co-authored-by: UebelAndre <github@uebelandre.com>
chouquette and others added 16 commits October 16, 2026 09:37
`dlltool_path_from_linker_path` derives `dlltool` from the
cc_toolchain's linker path, which assumes a MinGW binutils layout.
Toolchains that name it differently (`llvm-dlltool` in hermetic-llvm) or
don't ship it next to the linker can't build non-MSVC Windows targets.

This adds an optional `dlltool` attribute to `rust_toolchain`, also
exposed on the `rust.toolchain` and `rust.repository_set` extension
tags. When set, it's passed with `--codegen=dlltool=` and added to the
Rustc action inputs. When unset, the current behavior is kept.

Fixes bazelbuild#4315
…rary (bazelbuild#4251)

Split of from bazelbuild#4249

---------

Co-authored-by: Fabrice <schaubfabrice@gmail.com>
Co-authored-by: Krasimir Georgiev <krasimir@google.com>
This aligns with the naming convention of `cc_toolchain_alias`. The
change should be backward compatible.
Exports `rust_lto_flag` from `//rust:defs.bzl`, next to the other flag
rules, so that custom toolchains can set the public `lto` attribute of
`rust_toolchain` without loading `//rust/private:lto.bzl`. Also fixes
the doc string of the `lto` attribute and adds a toolchain test that
uses a custom `rust_lto_flag`. `RustLtoInfo` stays private.

Fixes bazelbuild#4337
…uild#4341)

On Windows, Python toolchains such as python-build-standalone expose the
Python import library (`libs/python3*.lib`) through
`cc_import(interface_library = ..., system_provided = True)`.
`pyo3_toolchain` only collected `dynamic_library` and `static_library`
from `py_cc_toolchain.libs`, so analysis failed with `Failed to find
python libraries for linking`. This also collects `interface_library`;
`.lib` is already a preferred extension, so it sets
`PYO3_CROSS_LIB_DIR`.
link_deps passed to pyo3_extension should only reach
rust_shared_library, not py_pyo3_library.
This fixes compatibility with toolchains that don't ship a libresolv
(e.g hermetic_cc_toolchain from Uber). rules_rust currently forces
'-lresolv' for a rust stdlib that hasn't needed it for several years.
For context, see rust-lang/rust#102766 and
bazelbuild#2611 .
This change adds a stand-alone toolchain for Cargo. This change aims to
help reduce the size of `rust_toolchain` by removing components not
needed by core `@rules_rust//rust/...`.
Rules which consult a C++ toolchain declared the type as
`@bazel_tools//tools/cpp:toolchain_type` while looking it up through
rules_cc's `find_cc_toolchain`. Declare it through rules_cc too: rule
definitions take `use_cc_toolchain()` from
`@rules_cc//cc:find_cc_toolchain.bzl`, so the type they require is
whatever rules_cc resolves, and plain label sites (test and example
`toolchain()` declarations, string `toolchains` lists) name
`@rules_cc//cc:toolchain_type`.
The fork's versions carry a `+canva.N` suffix in version.bzl, which the
typos pre-commit hook rewrites to "canvas" and fails the Formatting
workflow on every push. Teach it the word.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@ellgorrell
ellgorrell force-pushed the ellgorrell/0.75.0-canva.1 branch from a19cc70 to 11b5963 Compare October 27, 2026 01:28
ellgorrell and others added 2 commits October 27, 2026 12:33
This fork only exists to publish prebuilt cargo-bazel binaries for
Canva/canva. It must never push a `+canva` version to the Bazel Central
Registry, and without BCR_PUBLISH_TOKEN the job failed on every release
anyway, leaving the run red after the tag and release had already been
created. Skip it with `if: false` so release runs are green and the
upstream workflow file otherwise stays untouched for the next rebase.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…eam rules_rust 0.75.0

Brings main from upstream 0.71.2 (+ the Canva commits as released from
jesses-canva/rules_rust as 0.71.2+canva.3) to upstream 0.75.0 with the same
Canva commits replayed on top. The merge takes the rebased side's tree
wholesale; the only overlap is the generated crate_universe vendoring, which
was regenerated against 0.75.0 rather than merged by hand.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@ellgorrell
ellgorrell force-pushed the ellgorrell/0.75.0-canva.1 branch from 11b5963 to d8a0408 Compare October 27, 2026 01:33
@ellgorrell
ellgorrell marked this pull request as ready for review October 27, 2026 02:37
@cursor

cursor Bot commented Oct 27, 2026

Copy link
Copy Markdown

This PR is too large for Bugbot to review. It changes 41,031 lines and 3,729,049 characters. Split the change into smaller pull requests to get a review.

@ellgorrell
ellgorrell merged commit b06a850 into main Oct 27, 2026
15 checks passed
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.