Add support for Rust ABI dynamic libraries - #4179
Conversation
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
Adds a rule that allows building a dynamic library using the unstable Rust ABI. For easier contrast, converts the existing `rust_shared_library` rule to be a thin alias for `rust_cydylib_library`.
Updates dylib, binary, and test targets to have an additional flag for explicitly enabling the dynamic linking of the stdlib without a toolchain transition.
ead702e to
df80dac
Compare
df80dac to
9ea36c6
Compare
UebelAndre
left a comment
There was a problem hiding this comment.
I'd love @krasimirgg to take a look since I think there's some google uses of experimental_link_std_dylib. The change makes sense to me but I wonder if link_std_dylib should have more impact outside of just the allocators and codegen flag. The attribute sounds like it would directly link the dylibs but I don't think there's any wiring for that. Maybe @krasimirgg can correct me if I'm wrong
There was a problem hiding this comment.
Can you also add rust_dylib_library.bzl and rust_cdylib_library.bzl files neighboring this one with those exports?
| rust_flags.append(("-Zsplit-dwarf-out-dir=%s", dwo_outputs)) | ||
|
|
||
| if hasattr(ctx.attr, "link_std_dylib"): | ||
| link_std_dylib = toolchain._experimental_link_std_dylib or ctx.attr.link_std_dylib |
There was a problem hiding this comment.
Maybe rename these attributes on the toolchain as well?
|
Hey, I'm not an expert on dynamic linking, so please bear with me...
, you'll likely get rustc error: cannot satisfy dependencies so d only shows up once while compiling a. Example rustc commands I'm thinking about -- https://gist.github.com/krasimirgg/66c52fbebee7af4813e1e71af495bd4a. Tangent 1: On a high-level, I see a way to set up rust dynamic libraries support in a way similar to how rules_cc does dynamic libraries -- the rust_library itself has actions that produce both the rlib and the dylib, and clients pick up the appropriate dependency based on the --dynamic_mode build setting. This is composable, in particular any transitive dependencies of a dylib are automatically dylibs, avoiding the case where duplicated common dependencies render intermediate dylibs incompatible. But in a world like this, having a separate rust_dylib_library rule becomes just something almost equivalent to a rust_library. Tangent 2: The reason why I feel this is different than rust_shared_library (cdylib) is that that one is designed to act like a final artifact -- you collect all of your rust into a single such target, which acts more like a final binary; standard rust libraries cannot direclty depend on it and you just hook it up as a special dependency of the final binary. |
I would expect Bazel to bundle the
What makes the
I'm not sure it's always desirable to turn everything into dynamic libraries globally like this. Lets say you had a
I agree |
|
Thanks for thinking about this @krasimirgg ! Some thoughts:
Bazel should provide the
I feel like this is a limitation of dynamic linking with This is definitely a possible footgun though--asking for dynamic linking at some point in the chain might imply other libraries should become dynamically linked. It's not required if no dependency diamonds like this occur, though.
I think this is very cool, and could be something to build toward. In my use case, I wanted to avoid forcing every transitive dep to be unconditionally built as both an rlib and a dylib, when for many steps in that graph, only the rlib version was required (in my simpler use case, I had a deep dependencies with a dylib at the focal interface point). Instead, this lets me mark only the required targets as dylibs to save compilation time. |
Currently, there is not explicit stable Rust ABI for dynamic libraries, but Rust library may still be compiled as one. This can be useful if a large project wants to compile some core portion of its code as a shared object that can be dynamically linked against several different binaries. Bevy, for example, offers this capability as a way to allow customers of Bevy to tweak their own code without having to statically re-link the central Bevy engine code.
This PR exposes the Rust ABI dylib capabilities with a new rule,
rust_dylib_library. For clarity, it also creates arust_cylib_libraryrule, and updates methods to this name, withrust_shared_libraryjust aliasing to therust_cdylib_libraryimplementation.Building a Rust ABI dylib may cause the standard library to be linked dynamically against the generated dylib. When depended on, the dynamic standard library needs to be included to get the binary to execute. Currently,
rules_rustoffers this as a toolchain-level flag, but applying a toolchain transition at the dylib's interface imposes a new toolchain on its deps, which then forces any upstreamrlibs, for example, to recompile.To fix this, this PR exposes a
link_std_dylibattr torust_binary,rust_dylib_libraryandrust_testto allow these targets to optionally bundle themselves with the dynamically-linked stdlib.