How to build a “private” copy of std for crate?


I'm playing around with Microsoft's com-rs crate. I have the following setup:

  • COM implementation library - a cdylib containing COM classes that can be registered.
  • COM client - a binary app that makes use of the COM classes.
  • COM interfaces library - a common library between the first two containing definitions of GUIDs and COM interfaces.

To maximize reuse, the COM interfaces library is built into a dylib that is used by both the implementation library and the client. The downside of this solution is that all three depend on std.dll, which is almost 3 MB in size (after stripping).

Now, I realize that Rust doesn't have a stable ABI and for the sake of this sample I assume the three are always being built and redistributed together.

My question is: is there a way to build Rust's std library as a dylib together with these three crates, so it only contains parts of std that are being used? So, basically, is there a way to build a private copy of std?

I might be able to achieve this with Xargo maybe (any advice here is also much appreciated :sweat_smile:) , but I also wonder if there is a way to do so with current or nightly Cargo?


Yes, Xargo allows rebuilding std. There are instructions available here for building std from the rust-src component. Coincidentally, the linked instructions provide details for using link-time optimization to remove the unused parts of std from your binary via dead code elimination. This only works if std is statically linked, as the linker will be unable to tell which exports are actually unused in a dynamically linked library.

In general, rust interfaces cannot be safely used across dylib boundaries, only extern C functions with all #[repr(C)] types.You can end up with bad behavior even on the same version of rust, from things like different optimization choices for struct layout or different allocators (or different instances of the same allocator). Plus, I don't believe Rust supports any sort of generic interfaces for dylib binaries.

Just from this information, I don't believe there is any way to link all of std as a dylib. The rust interface just can't be expressed as a dylib interface.

If you're only using limited parts of std, might I suggest making each user a #[no_std] application, and making a new interface (either #[repr(C)] or using abi_stable) between your crates and a dylib which calls into std?

If you're using a lot of std though, or generic parts, I don't think it's at all feasible. @parasyte's suggestion of building a custom std with more removal of unused parts might be the best way to trim down size.

@daboross Thank you for the explanation!

If what you're describing is the actual state of things, then I don't get the use of [dylib] crate type and -C prefer-dynamic compiler flag. The former allows one to build a Rust dynamic library (as opposed to cdylib), and the latter links all the dependencies including std dynamically.

@parasyte Thanks for the link, I'll try this out! I was wondering though is it ever going to be included in the stable Cargo code?

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.