-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC: Add a new crate-type, rdylib #1510
Conversation
Add a new crate type accepted by the compiler, called `rdylib`, which corresponds to the behavior of `-C prefer-dynamic` plus `--crate-type dylib`.
Can you have 2 cdylibs, both linked against |
@arielb1 I believe so, yes. If we're careful to restrict the exported symbols of a dylib to only the public, no_mangle, and extern ABI functions, the in theory two independent Rust cdylibs would have disjoint sets of symbols, and they wouldn't accidentally use standard library symbols from another. I haven't tested this, however, so there may be cross-platform oddities lurking as well |
Won't the 2 separate copies of libstd fight with each other? |
Having not tested this, I'm not 100% certain, but I would expect it to work. Each dynamic library would not have any unresolved symbols to copies of libstd as they're all internally resolved. The only dependencies would be on usual system libraries (e.g. Basically what I would expect is:
With that, I don't believe that they can conflict. But again, untested! |
Seems pretty reasonable to me. |
If I understood this right, then huge 1+ from me, since I believe something like this is necessary if you want to experiment with runtime loadable crates that share dependencies and have it work right. |
Yes, definitely splitting up the two kinds of dylibs is very much needed and I am in favor of this. On Windows I know for sure that having two DLLs which have their own statically linked standard libraries should be fine with coexisting. They won't accidentally call each other's symbols. Pretty much the only thing you have to worry about is if two DLLs each keep track of some state and you pass an object specific to the state from one DLL to the other DLL. An example of this is if you have two cdylibs both with jemalloc statically linked in, and you allocate something in one DLL and then try to free it in the other. That will explode and fail horribly. As long as you avoid situations like that then everything is totally fine, on Windows anyway. Also it might be worth pointing out in the RFC how the output artifacts will be named as well as which allocators will be used by default. |
I really hope this one gets done! As I wrote here https://users.rust-lang.org/t/dynamic-linking-of-sharedlibs-with-cargo/4756 My use-case is that I will have lots of plugins written in Rust (as I write in the post) and without |
@alexcrichton think this is ready for FCP? I think so :) |
Sounds good to me! |
This RFC looks good to me. No need to stuff metadata into most dynamic libraries and having LTO available is also pretty good. |
I am very concerned that this is a really big breaking change, and one that is easily avoilable. We could alternately deprecated the |
🔔 This RFC is now entering its week-long final comment period 🔔 |
cc https://internals.rust-lang.org/t/do-you-compile-a-dylib/3342, trying to get some broader feedback on how dylibs are used |
Why is LTO disabled for rdylibs? Or perhaps I'm misunderstanding the usecase of rdylibs? But it sounds to me like a rdylib differs from an rlib in that it is linked. |
One of the primary purposes of our current implementation of LTO is to internalize all symbols, stripping what's not needed and heavily optimizing based on what's there. This means that the public API of an rdylib, in terms of symbols, isn't actually known by the compiler, so nothing can later link to that rdylib (unless it's through a C API, in which case it's just the same as a cdylib) |
So if I understand correctly you're saying you don't want to do LTO because the linker's reachability analysis doesn't understand the way Rust uses the symbols in the shared library, is that correct? It seems to me like this could be solved by having rustc generate a linker script based on the |
Not quite I believe. The way LTO works in Rust is:
As part of steps 4/5, massive swaths of code are removed. We could not internalize symbols, but that defeats one of the main purposes of LTO. LTO is also basically the antithesis of dynamic linking (you have to recompile if any dependencies change) so I'm not really sure why you'd want to do it for an rdylib? If we change or tweak how we do LTO then it may be appropriate to allow it on rdylibs in the future, but the current implementation would just flat out break rdylibs (which is why it's disabled for rdylibs today anyway). |
Please correct me if I'm wrong, but when compiling an rdylib, that is the "one giant LLVM module" and whatever the resulting code is in the rdylib end product, it will never be touched again in a future link but instead just used as is through dynamic linking. This means you're missing a huge opportunity to optimize away code that is never used, i.e. any functions that are not going to be called from outside the crate. For rdylibs, step 4 in your process would be a little different by specifying far more public symbols than you'd have in a normal binary, but it would still be possible to do LTO this way I think. |
Ah yeah so an rdylib (today's dylib crate type) isn't one large LLVM module. It's the same as an rlib, just an object file for the crate being compiled. In that sense, without LTO, we have no ability to optimize away code that isn't used beyond what we can tell the linker (which we indeed try to do). |
Tracking issue: rust-lang/rust#33132 |
@DaGenix Not really relevant to the RFC any longer, but did you ever manage to accomplish using rdylibs for use case 2 you mentioned? I'm interested, as I'm looking to do the same thing. |
@alexcrichton Would you like to change the title of this PR to use word 'cdylib' instead of 'rdylib'? |
This commit is an implementation of [RFC 1510] which adds a new crate type, `cdylib`, to the compiler. This new crate type differs from the existing `dylib` crate type in a few key ways: * No metadata is present in the final artifact * Symbol visibility rules are the same as executables, that is only reachable `extern` functions are visible symbols * LTO is allowed * All libraries are always linked statically This commit is relatively simple by just plubming the compiler with another crate type which takes different branches here and there. The only major change is an implementation of the `Linker::export_symbols` function on Unix which now actually does something. This helps restrict the public symbols from a cdylib on Unix. With this PR a "hello world" `cdylib` is 7.2K while the same `dylib` is 2.4MB, which is some nice size savings! [RFC 1510]: rust-lang/rfcs#1510 Closes rust-lang#33132
This commit is an implementation of [RFC 1510] which adds a new crate type, `cdylib`, to the compiler. This new crate type differs from the existing `dylib` crate type in a few key ways: * No metadata is present in the final artifact * Symbol visibility rules are the same as executables, that is only reachable `extern` functions are visible symbols * LTO is allowed * All libraries are always linked statically This commit is relatively simple by just plubming the compiler with another crate type which takes different branches here and there. The only major change is an implementation of the `Linker::export_symbols` function on Unix which now actually does something. This helps restrict the public symbols from a cdylib on Unix. With this PR a "hello world" `cdylib` is 7.2K while the same `dylib` is 2.4MB, which is some nice size savings! [RFC 1510]: rust-lang/rfcs#1510 Closes rust-lang#33132
rustc: Add a new crate type, cdylib This commit is an implementation of [RFC 1510] which adds a new crate type, `cdylib`, to the compiler. This new crate type differs from the existing `dylib` crate type in a few key ways: * No metadata is present in the final artifact * Symbol visibility rules are the same as executables, that is only reachable `extern` functions are visible symbols * LTO is allowed * All libraries are always linked statically This commit is relatively simple by just plubming the compiler with another crate type which takes different branches here and there. The only major change is an implementation of the `Linker::export_symbols` function on Unix which now actually does something. This helps restrict the public symbols from a cdylib on Unix. With this PR a "hello world" `cdylib` is 7.2K while the same `dylib` is 2.4MB, which is some nice size savings! [RFC 1510]: rust-lang/rfcs#1510 Closes #33132
This commit is an implementation of [RFC 1510] which adds a new crate type, `cdylib`, to the compiler. This new crate type differs from the existing `dylib` crate type in a few key ways: * No metadata is present in the final artifact * Symbol visibility rules are the same as executables, that is only reachable `extern` functions are visible symbols * LTO is allowed * All libraries are always linked statically This commit is relatively simple by just plubming the compiler with another crate type which takes different branches here and there. The only major change is an implementation of the `Linker::export_symbols` function on Unix which now actually does something. This helps restrict the public symbols from a cdylib on Unix. With this PR a "hello world" `cdylib` is 7.2K while the same `dylib` is 2.4MB, which is some nice size savings! [RFC 1510]: rust-lang/rfcs#1510 Closes rust-lang#33132
rustc: Add a new crate type, cdylib This commit is an implementation of [RFC 1510] which adds a new crate type, `cdylib`, to the compiler. This new crate type differs from the existing `dylib` crate type in a few key ways: * No metadata is present in the final artifact * Symbol visibility rules are the same as executables, that is only reachable `extern` functions are visible symbols * LTO is allowed * All libraries are always linked statically This commit is relatively simple by just plubming the compiler with another crate type which takes different branches here and there. The only major change is an implementation of the `Linker::export_symbols` function on Unix which now actually does something. This helps restrict the public symbols from a cdylib on Unix. With this PR a "hello world" `cdylib` is 7.2K while the same `dylib` is 2.4MB, which is some nice size savings! [RFC 1510]: rust-lang/rfcs#1510 Closes #33132
The rendered link is broken. Here's a fresh one: https://github.com/rust-lang/rfcs/blob/master/text/1510-cdylib.md |
Add a new crate type accepted by the compiler, called
rdylib
, whichcorresponds to the behavior of
-C prefer-dynamic
plus--crate-type dylib
.Rendered