deprecate force_all_deps_direct in favor of extra_named_deps - #4160
Merged
Conversation
… new `extra_named_deps` argument 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"]) using A = int; A 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: 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.
krasimirgg
marked this pull request as ready for review
July 22, 2026 14:07
scentini
approved these changes
Jul 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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:
While compiling the generated Rust bindings of
c, the Rust compiler needs access to the generated Rust bindings ofa, which is an indirect dependency. Historically, this was achieved via theforce_all_deps_directfeature, which has the effect of putting all direct and indirect crate dependencies as--externwhile 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:
To handle these, we provide
extra_named_depsa mechanism for extensions callingrustc_compile_actionto supply an extradepsetof 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.