-
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 an alias
attribute to #[link] and -l
#1296
Conversation
Add a new `alias` attribute to `#[link]` and the `-l` flag which indicates that the linkage will happen through another annotation to inform how a library is linked. This is then leverage to inform the compiler about dllimport and dllexport with respect to native libraries on the MSVC platform.
I will continue to feel uneasy about any proposal that makes the question of whether to apply |
The Does As I understand it, the |
Anyway, why is dllexport not emitted for naked |
@arielb1 |
Relevant discussions are on internals and in this issue. |
Can you be more specific in what you think needs expanding or better explaining? For example your question seems addressed via this text in the RFC:
followed by
Which is to say, yes, with your example Can you also elaborate more as to why you would like aliases under crate attributes as well as a new flag on the command line? This proposes modifying the existing flags and attributes for two reasons:
Applying dllexport or dllimport is somewhat nonstandard in the sense that you've got to go out of your way to do so, so in my mind it makes sense that if the author did not go out of their way to annotate with More technically, however, with a bare extern block the compiler has no current way of knowing where the symbol comes from, so it doesn't know whether it's being included statically or linked dynamically. This can indeed work, even on MSVC, in some situations, but in others it won't. An alternative would be to require all extern blocks annotated with some |
Actually, |
I'd be ok with tweaking the CLI syntax, but one of the main aspects of this is to ensure that each |
#![crate_type="rlib"]
#![cfg_attr(win32, lib_alias(name="foo-static", lib="gnu32-foo", linkage="static", bundle="false"))]
#![cfg_attr(linux, lib_alias(name="foo-static", lib="foo", linkage="static", bundle="false"))]
#[link(name="foo-static")] extern "C" {
fn foo_create() -> *const Foo;
} |
Ah yeah I considered doing something like that for a bit, but preferred to not use existing forms as it seems ambiguous in that location how "foo-static" is actually linked. As a reader of the code it looks like the library is linked dynamically (as no By having a new form it explicitly signals "this is linked somewhere else" which serves as a flag to readers that the linkage must happen elsewhere, and it's also an assertion that the linkage will happen elsewhere to succeed (e.g. if you forget for some platform to specify |
So use |
It's certainly true that we've got quite a bit of leeway in terms of attributes we can add here, I'm not sure if I'd actually expect the attribute form to be used that often to introduce aliases, I expect that they'll almost always come from the command line. If that's the case this could even remove the ability to introduce a separately named alias via the attribute and only allow those to be added on the command line to start out with. |
I prefer command-line attributes to have equivalent crate attributes, for these who invoke rustc manually. |
I will support this RFC as soon as it is demonstrated that it handles the second situation described here. |
🔔 This RFC is now entering its week-long final comment period 🔔 |
I want to make sure that bindgen can understand the model and make rustc generate dllimport/dllexport correctly. @alexcrichton says it should be able to do this. |
OK, I've been banging my head against this RFC and this discussion thread all morning and I'm coming up for air. I'd like to ask for some clarification, because I'm somewhat confused about precisely what scenarios are under discussion. It seems to me that the overall summary here is that @retep998 feels that there are various scenarios in Windows linking which are not covered by Rust's current model. I think that is likely true, but it is really hard for me to be sure, because most of the comments I see are pretty abstract -- I think it'd be helpful to outline these scenarios in terms of actual use cases and libraries. @retep998 can you take the scenarios you summarized in this post here and make a concrete example where each of them arises? Or at least scenario #2, the one you seem most concerned about? Sorry if you've already done this and I didn't find it, in that case maybe you can just point me at it. And please explain it to me like I am an ignorant fool -- I, like many of us, I suspect, do my best to ignore linking at all times except when I am forced to pay attention. :) Also, in that post you seem to imply that I am concerned that if we adopt a method that is too narrow now, we may find that we have to extend it in ungainly ways later. As @retep998 wrote,
It seems to me that basically most of these features and abilities exist for a reason, and we will sooner or later wind up with someone who really wants to use them. But it is ALSO true that the vast majority of people are like me, and just want to work in a cross-platform fashion and pretend the linker doesn't exist, so I hope we can find a design that accommodates both. |
OK, I just wanted to drill into one other thing a bit more. The scenario that you are describing here, and which you later summarized as example #2, is (iiuc) as follows:
This is where I get a bit confused. If the code is not compiled into the DLL, it seems to me it must be dynamically linked. And in that case, it seems like we must tell the EXE that we need them to dynamically link this dependency. So perhaps I am confused? Or perhaps my mental model of how linking works is too simplistic? You then go on to say:
I do not understand what this "re-exported" means. It sounds to me like you ARE bundling the code of I am guessing you have a very specific scenario in mind -- e.g., perhaps your crate that re-exports windows APIs? Can you spell it out a bit more so I understand? |
The problem is not bundling the |
@nikomatsakis |
Yes, so it seems like bundling the .lib into the .rlib is the wrong thing to do. It seems like the rlib wants to specify "kind=dylib", so that it defers the work to the crate producing a DLL.
OK so can we drill in on this a bit more. Let's ignore the search path thing for a second and just pretend that rustc knew about the system search paths. Let's ignore Rust too for a second. Can you just tell me what setup you would do in C++ and how it would work? What I keep hearing seems a bit confusing to me. That is, it seems like you want:
This seems like what Rust calls So where am I going wrong? (Or is the only reason we don't want static linking because it requires rustc to know about search paths of which it is currently ignorant?) |
OK, so, now that I understand this RFC a bit better, I have a few questions: How I understand it is that writing I find the name "alias" here a bit confusing. I feel like what you are doing is making a kind of "abstract library" -- I wonder if we could use specify this a bit differently. I was thinking perhaps we could modify the
@alexcrichton @brson does that make sense? What do you think? |
I think this is correct. That is, I think this RFC doesn't really change anything fundamental about our linking model. In that sense, it seems harmless to accept -- a strict improvement on today, without much backwards compat hazard to be afraid of -- but clearly doesn't address all possible linking scenarios (though I gather it DOES let us handle a good bit more than we do today, particularly on Windows). I think what I was personally a bit confused about was the role of |
to keep this updated, I intend to tweak this RFC with |
Removing from FCP until I have a chance to update this. |
@alexcrichton: The thread about MSVC runtime linkage jogged my memory about this RFC. Is attribute syntax the only outstanding issue here? |
@vadimcn yeah I don't think my "hopefully soon" panned out. But yes the intention was to update with @nikomatsakis's suggestion of @vadimcn would you be interested in helping to update this RFC and resubmit it? |
Sorry if I have misunderstood, I'm out of my depth but enthusiastic. Does the new Also am I correct that this RFC will help with dgrunwald/rust-cpython#10 (comment) ? |
@Eh2406 This is for specifying the kinds of libraries that you are linking in, not the type of the artifact that will be produced from your crate. But yes, this RFC has the potential to fix that issue. |
Thanks for the explanation! |
Sorry for late jumping into this thread. Didn't have the time to read it all back in December...
I disagree with this statement. What prevents a.dll from re-exporting symbols from b.dll?
In the worst case we could generate a stub function like this: // a.rs
mod b {
#[link(name="b", kind="dylib")]
extern "C" {
pub fn foo();
}
}
// now foo exists in a.dll !
pub fn foo() {
b::foo()
} However, we can do better than that because Windows directly supports dll import forwarding (sorry, couldn't find this info on MSDN proper). We may need to fix the compiler to actually do that, but I do not see any conceptual difficulties. @alexcrichton: Yeah, I'll try to get this moving again, hopefully soon 😀 |
@nikomatsakis, @alexcrichton: After thinking some more about this... Seems to me that it's going to be confusing whether we add alias="..." or kind="abstract"+link_name="...". Do we actually need aliases? Can we simply use the library name to refer to it? Something like this:
|
I'm saying the functions/statics provided from |
As long as the override can be specified via a cargo build script, then this scheme seems fine to me. |
@vadimcn that sounds reasonable to me! I agree that somehow in the source connecting an "abstract name" to a "real name" probably isn't worth it. |
Do we have any real use cases for overriding native library's "kind" from the command line? |
@vadimcn not that I know of, the command line bits here were intended for libraries whose name may not always be known when the source code is written, but at compile time a build script can discover the name (e.g. via pkg-config). The build script could the connect that name (unknown at source-writing time) to the name written down in the source. Overriding the actual kind of the library though (static vs dynamic) was never intended. |
@alexcrichton: In that case I don't see a reason to preserve library's identity. All the compiler really needs to know is whether the library is dynamically linked. |
@vadimcn yeah that's another possibility, but it doesn't account for the case where linkage can change at compile time. For example Cargo is sometimes statically linked to libcurl (what we ship) but it's dynamically linked to libcurl if you just run |
Okay, sounds like we need a new compiler (not linker) flag just to specify library linkage on Windows. Yuck. |
Depends kinda on what you're doing. We're not applying dllimport correctly today anyway, so it's really rare you'll actually get yourself into a situation where you need to apply these tags. (at least that's the theory) It may be handle-able with #[cfg], and Windows libraries don't change names that much, so we could cut back on functionality perhaps. |
I am fine with not having an "abstract" kind, but it does seem like then sometimes you will be specifying a kind (e.g., dylib) that is kind of a "dummy" value, since you always expect it to be "overridden" by cargo, right? |
@nikomatsakis yeah we may not be entirely able to remove "abstract" as function declarations in an |
Hey, y'all! (I've decided to dump all the |
@vadimcn looks great to me! |
Closing in favor of #1717 |
Add a new
alias
attribute to#[link]
and the-l
flag which indicates thatthe linkage will happen through another annotation to inform how a library is
linked. This is then leverage to inform the compiler about dllimport and
dllexport with respect to native libraries on the MSVC platform.
Rendered