-
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
Extended linking kinds #1489
Extended linking kinds #1489
Conversation
Signed-off-by: Peter Atashian <[email protected]>
Signed-off-by: Peter Atashian <[email protected]>
text/0000-unkind-static-libraries.md
Outdated
# Motivation | ||
[motivation]: #motivation | ||
|
||
There is currently no way to properly link a static library by passing it to the linker instead of bundling it with rustc. `kind=dynamic` doesn't work because it thinks the library is a dynamic library resulting in issues such as passing the library on to later linker invocations beyond the first immediate linker invocation and also on Windows, once dllimport is actually supported correctly, `kind=dynamic` would cause dllimport to be emitted for all the symbols which is incorrect for static libraries. `kind=static` doesn't work because instead of passing the library to the linker, rustc bundles it, which results in rustc not looking in the standard library paths for the library. |
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 am very sympathetic to the aims of this RFC -- and I think I am persuaded that there is something missing in the current model, though I have to try to bring the details back into cache -- but I'd appreciate it you could edit it to maintain a more objective tone. I find phrases like "no way to properly link" or describing things as "weird" distracting, since they imply value judgements, which complicates the issue.
I'd rather see something like:
"The current set of linker options do not allow static linking to be handled by the linker. The current link=static
causes rustc to bundle up the executables and kind=dynamic
uses dynamic linking. However, on windows, a common configuration is to do blah blah blah."
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.
One other thing: this RFC is a golden opportunity to lay out the subtleties involved here (and there are many, it seems). It'd be really valuable to have a good exposition of the windows linking model and where Rust is falling short.
Signed-off-by: Peter Atashian <[email protected]>
I'm considering extending this RFC to also add cc @DanielKeep @cybergeek94 |
@retep998 At that point, wouldn't All that having been said: being able to link in resources and object files without having to use the |
I'd kinda prefer |
Just a bit of clarification on how resource files get passed in.
So this means for msvc you'd use |
the I am less convinced by the utility of |
@nrc We could make it so that with both gnu and msvc you'd pass your |
This sentence seems to be the key motivation, but I don't understand it: " What is the difference between "passing it along to the linker" and not doing that? Surely the code is linked either way right? |
@brson The linker has a set of paths that it looks in for libraries. rustc does not know what those paths are. Suppose I have a static library located in one of those folders that the linker normally looks in for libraries. If I use |
Thanks for the explanation. As an alternative proposal, what if we taught rustc about the pre-defined linker paths? The separation between the linker and compiler in rustc is artificial, a historical accident. If it worked the way we wished the linker would be integrated into rustc and rustc would know whatever the linker knows. With the actual state of the world where linkers are ancient monoliths, adding this knowledge to rustc would not be simple, but there's probably a way. |
When bundling another library into a Rust .rlib instead of passing it to the linker, there are other issues as well. For example if that library was compiled with LTCG, passing it to the linker will work fine, but if rustc bundles it into the .rlib the LTCG data is ruined. rust-lang/rust#26003 Actually, how about we try coming up with arguments for when
Can anyone think of any other reasons? |
text/0000-unkind-static-libraries.md
Outdated
[alternatives]: #alternatives | ||
|
||
* Don't do this and make me very sad. | ||
* Change the behavior of `kind=static`. Remove the bundling aspect and simply make it provide the knowledge to rustc that the symbols are static instead of dynamic. Since Cargo ensures the non-Rust static library will hang around until link time anyway, this would not really break anything for most people. Only a few people would be broken by this and it would be fairly easy to fix. Has the advantage of not adding another `kind`. |
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 much prefer this alternative. We generally make no guarantees about independent uses of anything other than executables, cdylib
s and staticlib
s, the last of which requires the user to make note of the library list Cargo outputs.
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 am in favor of this alternative as well.
I updated the RFC to add |
Note that for resource files, the user cannot simply use |
Ping @rust-lang/tools, this RFC seems to've stalled. Can someone summarize the current state of play and try to make progress? |
|
Ok cool if we don't want support for arbitrary object files then focusing on just resource files sounds good to me. I wonder though if could perhaps go for a bit more of an ergonomic inclusion, as well as lifting some requirements? I could imagine, for example:
|
Allowing resource files to be generated by a build script would be desirable, so anything that prevents that from working probably wouldn't be a good idea.
A library may wish to bring along a resource file to provide some things that it needs. For example a UI library may want to define some resources so that it can use them. So resource files from a library definitely seems like a worthwhile use case to support.
We don't necessarily have to compile the resource file immediately, saving it somewhere and later compiling it right before passing it to the linker is fine. However what we cannot do is put the compiled resource file in a library and pass that library to the linker, because the linker will fail to recognize the compiled resource file in the library. |
Ok so it seems to be like we may not want to use Perhaps something like: #[windows_resource = "foo.rc"]
extern {} // ?? That way if you want to include a file relative to a source file you can do so. If you want to generate it via a build script then you can do so and include that via I kinda like the idea of not running I'm not really sure where or how to precisely specify the inclusion of a resource file, though. We could maybe slap it on a module or something like that, but it seems like almost a hack no matter how we slice it unfortunately. |
@alexcrichton Oh, there might actually be an issue with storing resource files to compile them later, because when resource files are compiled they pull in other files around them, like icons and manifests and stuff. If you store the rc then those other files won't be around when you need them. So you'll have to compile the resource file on the spot and then somehow keep track of or store the compiled |
What are your thoughts on how resource files are declared? I feel like |
I personally don't care too much about what the syntax for declaring resource files is. If someone proposes a better syntax that others agree on, then I'll gladly update the RFC. |
Ok well in that case my proposal is: #[windows_resource = "foo.rc"]
extern {} The This also differentiates itself as a windows-specific extension (like |
But why does it need an extern block? Why not as a crate attribute? |
@alexcrichton What would be the recommended way to link a resource file that is generated using a build script using your attribute? |
I kinda agree with @retep998: linking in an object file (not necessarily resources) is just something you sometimes need to do when building for a custom target. |
@Boscop with a crate attribute it's difficult to include something dynamically generated, such as (to answer @retep998's question as well) with an extern block you can generate @vadimcn just to clarify, but you're pushing back on the trimming down of this RFC from object files to just resource files? If so, can you clarify why archives wouldn't work? (e.g. why raw object files must be used) |
Having to generate a rust file in order to link to a generated resource file seems rather convoluted. I'd rather have a rustc flag to link in a resource file and cargo would support some sort of |
@alexcrichton: I liked the part about linking object files in general, not just outputs from windres/cvtres. On more than one occasion during my hacking I had wished I could pass objects directly to Rust compiler, like I can do with GCC. It would also let us deal with resources, so we'd be killing two birds with one stone :) |
Agreed, being able to just link to object files would be nice. Maybe rustc could look through |
I would also be ok with linking arbitrary object files with logic that looks like:
I don't feel that it's strictly necessary, but I'm comfortable with those semantics and if we want to go back to arbitrary object files that'd be ok. |
Unfortunately, this is wrong! Due to the overriding nature of object files in the msvc toolchain, msvc actually provides a set of object files to override certain behavior. If you want to link to one of those object files, the linker must be able to link to those object files, and expecting the rlib to adequately inform rustc of where those object files is just not going to work.
Due to the above, this step won't work, unless there are major changes to how rustc searches for libraries. |
Discussed at the @rust-lang/tools triage a few days ago, the conclusion we reached were:
Does that make sense? How does that sound to you @retep998? |
So what happens if I want to link a system object file, like one of the object files provided by VC++? |
IMO, the single namespace for native libs (due to using lookup paths) is already a problem. Having to deal with a single namespace for objects (again, due to the proposed use of lookup paths) doesn't seem like a good idea if it's not a problem to specify full paths. |
@alexcrichton Well, if rustc were responsible for finding the object files and not the linker, I'd be screwed. This is the same thing that happened with |
Ok, do you have a proposal to fix that problem? |
The problem is that
|
Could you elaborate on the motivation for system object files? Could that perhaps get punted to a future RFC? Could you also elaborate what your first option would look like? E.g. the specifics of lookup. |
I'm going to close this RFC for the time being, to keep our queue clean, as it's waiting on follow up from its author, @retep998. Please feel free to reopen if/when you're ready to pick this topic back up. |
This RFC proposes adding a kind for object files which are passed directly to the linker.
Please bikeshed vigorously on the name of the
kind
.rendered