-
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
Linking modifiers for native libraries #2951
Conversation
cc @retep998 |
text/0000-native-link-modifiers.md
Outdated
undefined symbols at the point at which it is specified on the command line, | ||
making it similar to static libraries in this regard. | ||
|
||
This modifier translates to `--as-needed` for `ld`-like linkers. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should add a sentence describing what this does for link.exe
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will add (there's no MSVC equivalent, so it's ignored).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
Notes from a Darwin (macOS/iOS/etc.) perspective: Darwin uses ld64, which shares the basic syntax of a Unix linker but doesn't support these GNU ld options. Instead it has these equivalents:
Frameworks are Darwin-specific and are literally identical to dylibs but with a different naming scheme and separate search paths.
It should be compatible with the same modifiers as regular dylibs on Darwin. |
@comex |
Without |
[guide-level-explanation]: #guide-level-explanation | ||
|
||
This is an advanced feature not expected to be used commonly, | ||
see the reference-level explanation if you know that you need some of these modifiers. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I generally distinguish between guide and reference level for usage and implementation level, although I understand why you didn't bother here. It's not that big of a deal, but I just figured I'd mention this here in case people viewing get ideas. :p
on some future edition boundary, and hopefully unblocking its stabilization. | ||
|
||
The generic syntax provides a way to add more such modifiers in the future | ||
without introducing new linking kinds. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMHO this section doesn't really provide that powerful of a motivation. If you've run into needing these issues before, it seems obvious, but I've personally never had to do any special linking despite having done a lot of work in C before. I feel like examples may be helpful, even if they're contrived.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The GitHub issues linked from this PR provide some examples, I'll try to move them into the RFC.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
|
||
The modifiers are boolean and applied only to the single library specified with `name`. \ | ||
`+` means enable, `-` means disable, multiple options can be separated by commas, | ||
the last boolean value specified for the given modifier wins. \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason to do this instead of erroring if multiple are specified?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To mirror target features mostly, there it's needed to override features on command line (rust-lang/rust#56527) so that -C target-feature=+keep,+change -C target-feature=-change
becomes -C target-feature=+keep,+change,-change
and becomes -C target-feature=+keep,-change
.
(With linking modifiers it can also be used in theory, to override modifiers from attributes on command line, like
#[link(name = "mylib", modifiers = "+keep,+change")]
+ -l:-change=mylib:mylib
which becomes -l:+keep,-change=mylib
.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible to have a deny-by-default lint in code, then? Command line switches make perfect sense, but if someone includes multiple in the code it's almost certainly a mistake.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even if the multiple specifier case doesn't make sense, it's still very hard to write it accidentally, so making a new lint for it doesn't pull its weight. (There are plenty opportunities to write some unnatural code that doesn't make any sense but is not linted.)
I guess it's easier to make it a hard error then.
[RFC 1717](https://github.com/rust-lang/rfcs/pull/1717). | ||
|
||
The default for this modifier is currently `+bundle`, | ||
but it could be changed later on some future edition boundary. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the whole point of editions is that you can link together code for multiple editions at once, wouldn't that not be a good idea?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this change would break anything implicitly?
When a crate with #[link]
attributes migrates from edition 202X to edition 202X+3 it will need to either add the modifier or change its build and/or distribution strategy. Both such such changes should be ok when a crate does edition bump.
is now added automatically. \ | ||
If your DLL doesn't have the `.dll` suffix, it can be specified with `+verbatim`. | ||
|
||
### `whole-archive` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like this name is a bit weird, because really it seems to be talking more about LTO. When reading "whole archive" my first thought is "why wouldn't the whole library be linked?"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logic behind both whole-archive
and as-needed
is to simply mirror the corresponding linker options.
Generally, if someone wants the "whole-archive" linking, then they probably want it to have the same name "whole-archive" for searchability.
On the other hand, if someone doesn't know what "whole-archive" means, then they probably don't need this option.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm personally viewing this from the perspective of someone looking at existing code to understand how it works. Documentation will include the options that they translate to for searchability, but I'm not sure someone would need to search for this in code itself.
|
||
The default for this modifier is `-whole-archive`. | ||
|
||
### `as-needed` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, a bit fuzzy on the name here. Seems to be more of a statement about LTO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
||
For `ld`-like linkers `rustc` will use the `-l:filename` syntax (note the colon) | ||
when passing the library, so the linker won't add any prefixes or suffixes as well. \ | ||
See [`-l namespec`](https://sourceware.org/binutils/docs/ld/Options.html) in `ld` documentation | ||
for more details. | ||
for more details. \ | ||
For linkers not supporting any verbatim modifiers (e.g. `link.exe` or `ld64`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
link.exe
is inherently verbatim, and it is Rust itself which adds any prefix/suffix. That is a significant difference compared to ld64
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not entirely, link.exe
will add .obj
to files without extensions.
Also, the paragraph above talks about prefixes/suffixes added by rustc itself.
My idea here was "rustc passes what you passed to the linker without changes and the linker does what it wants with this input", not sure how to word this better.
One more request for |
We ended up adopting a similar plan in the form of a compiler-team major change proposal, rust-lang/compiler-team#356, so I'm going to close this RFC PR. =) |
@nikomatsakis UPD: Tracking issue - rust-lang/rust#81490. |
…trochenkov Implement RFC 2951: Native link modifiers A first attempt at implementing rust-lang/rfcs#2951 / rust-lang/compiler-team#356. Tracking Issue: rust-lang#81490 Introduces feature flags for the general syntax (`native_link_modifiers`) and each modifier (`native_link_modifiers_{as_needed,bundle,verbatim,whole_archive}`). r? `@petrochenkov`
…trochenkov Implement RFC 2951: Native link modifiers A first attempt at implementing rust-lang/rfcs#2951 / rust-lang/compiler-team#356. Tracking Issue: rust-lang#81490 Introduces feature flags for the general syntax (`native_link_modifiers`) and each modifier (`native_link_modifiers_{as_needed,bundle,verbatim,whole_archive}`). r? `@petrochenkov`
Provide some generic syntax (similar to target features) for linking modifiers used for native libraries.
Provide some specific modifiers to control bundling behavior, whole-archive and the library name mangling.