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

Tracking issue for #[link(kind)] connecting libraries on Windows #37403

Open
alexcrichton opened this Issue Oct 25, 2016 · 17 comments

Comments

Projects
None yet
9 participants
@alexcrichton
Member

alexcrichton commented Oct 25, 2016

Tracking issue for rust-lang/rfcs#1717

  • Implement -l[kind=][oldname:]libname.
  • Implement lib<->symbol association and emit dllimport for dylib symbols.
  • Implement kind="static-nobundle".

@Eh2406 Eh2406 referenced this issue Nov 4, 2016

Closed

Windows support #10

bors added a commit that referenced this issue Dec 3, 2016

Auto merge of #37973 - vadimcn:dllimport, r=alexcrichton
Implement RFC 1717

Implement the first two points from #37403.

r? @alexcrichton

bors added a commit that referenced this issue Dec 4, 2016

Auto merge of #37973 - vadimcn:dllimport, r=alexcrichton
Implement RFC 1717

Implement the first two points from #37403.

r? @alexcrichton

bors added a commit that referenced this issue Dec 6, 2016

Auto merge of #37973 - vadimcn:dllimport, r=alexcrichton
Implement RFC 1717

Implement the first two points from #37403.

r? @alexcrichton
@dgrunwald

This comment has been minimized.

Contributor

dgrunwald commented Dec 17, 2016

If I specify #[link(name="pythonXY")] on 30 extern C blocks, and then compile with rustc -l dylib=pythonXY:python27, then python27.lib is passed to the linker 30 times.

Not sure if that's actually a problem, but maybe Rust could de-duplicate the linker arguments?

@dgrunwald

This comment has been minimized.

Contributor

dgrunwald commented Dec 17, 2016

Also, is it intentional that these changes are insta-stable?

cc @vadimcn

@vadimcn

This comment has been minimized.

Contributor

vadimcn commented Dec 17, 2016

@dgrunwald: Could you coalesce those 30 extern blocks into one? You probably did it to keep extern declarations in the same file/module as the code using them, but this isn't really how we thought about extern blocks when designing Rust FFI.

The problem with de-duping is that most unix linkers resolve references using only libraries to the right on the command line. So if you know that lib1 depends on something in lib2, they must appear in that order (even if lib2 has already appeared to the left of lib1).

Our approach so far has been to simply emit libraries in the order they appear in the source, followed by the ones specified on the command line.

In order to optimize this, we'd need to provide some way of specifying library dependencies (e.g. "libraries {attached to the same extern block | within the same module | within the same source file} are guaranteed to be given to the linker in the same order"). For starters, some motivated person would need to write an RFC :)

Also, is it intentional that these changes are insta-stable?

Sort of. The changes in handling of dllimport did not create any new syntax that could be feature gated. We could still use a #[feature(...)] to toggle the new behavior, but it's a bit too subtle for my liking: There would be no error message telling the user that this is feature-gated; they'd simply get a linker error.

@dgrunwald

This comment has been minimized.

Contributor

dgrunwald commented Dec 18, 2016

python3-sys is structured in the same way as the python headers: one .rs file per .h file; with the declarations within the file in the same order as in the .h file.
Because the Python headers have lots of macros (which I manually translate into constants or #[inline] fns), I frequently close the extern "C" block, define the macro functions/constants, and then re-open the extern "C" block. This approach means that python3-sys has 95 #[link(name="pythonXY")] extern "C" blocks in total.

When a new Python version is released, I diff the new Python headers against the old headers and apply the same changes to the Rust code (using #[cfg] attributes for new functions). This would be much more difficult if I had to keep everything in a single extern block.

@retep998

This comment has been minimized.

Member

retep998 commented Dec 18, 2016

@dgrunwald A similar situation will occur for me in winapi = "0.3". Preserving duplicates isn't strictly necessary everywhere. link.exe and lld in particular aren't dumb the way unix linkers are, so we can trivially deduplicate libraries for the msvc linker without breaking anything, and eventually when we switch to LLD for all the other targets we can deduplicate libraries everywhere. Until then though, we need some sort of solution.

@dgrunwald

This comment has been minimized.

Contributor

dgrunwald commented Dec 18, 2016

The current logic seems to be: if both #[link(X)] and -l X:Y is specified, ignore the position of the -l X:Y command-line argument and use all the #[link] positions instead.

What if we just did this the other way around: if both are specified, ignore the #[link] positions and use the single -l X:Y position instead.

@vadimcn

This comment has been minimized.

Contributor

vadimcn commented Dec 18, 2016

In any case, this is not a new issue and has nothing to do with dllimport annotations. Let's continue this discussion in #38460.

bors added a commit that referenced this issue Feb 4, 2017

Auto merge of #38426 - vadimcn:nobundle, r=alexcrichton
Implement kind="static-nobundle" (RFC 1717)

This implements the "static-nobundle" library kind (last item from #37403).

Rustc handles "static-nobundle" libs very similarly to dylibs, except that on Windows, uses of their symbols do not get marked with "dllimport".  Which is the whole point of this feature.

@brson brson added the B-unstable label Mar 1, 2017

@steveklabnik steveklabnik added T-tools and removed A-tools labels Mar 24, 2017

@Mark-Simulacrum Mark-Simulacrum added T-dev-tools and removed T-tools labels May 24, 2017

@retep998

This comment has been minimized.

Member

retep998 commented Sep 12, 2017

Would it be possible to get some focus on bikeshedding the name of kind=static-nobundle and perhaps stabilizing it?

@cramertj

This comment has been minimized.

Member

cramertj commented Jan 17, 2018

Are there any remaining issues blocking stabilization here? @retep998 I see you have thoughts about the name of kind=static-nobundle. Does anyone else have opinions on this?

@retep998

This comment has been minimized.

Member

retep998 commented May 19, 2018

The only idea I have is to rename static to static-bundle and deprecate static with a warning that you may actually want static-nobundle.

@vadimcn

This comment has been minimized.

Contributor

vadimcn commented May 20, 2018

Maybe staticref, as in "a reference to a static library"?
I could also see cstaticlib standing for "using C's static linkage model".

IMO, the current use staticain't too bad: after all, in C world, there's no analogues of "linking static library to a static library", so we may as well define it the way we like.

@vadimcn

This comment has been minimized.

Contributor

vadimcn commented May 20, 2018

... another option might be latestatIc, for "late-bound static library".

@retep998

This comment has been minimized.

Member

retep998 commented May 20, 2018

IMO, the current use staticain't too bad: after all, in C world, there's no analogues of "linking static library to a static library", so we may as well define it the way we like.

In the (Microsoft) C world there absolutely is. #pragma comment(lib, "foo.lib") in a library will ensure that foo.lib is linked whenever that library is linked, and works identically to our current kinds dylib and static-nobundle. static is the odd one out with weird bundling behavior which keeps tripping up people who wonder why static is unable to find the static libraries installed on their system.

@vadimcn

This comment has been minimized.

Contributor

vadimcn commented May 21, 2018

I am not sure that MSVC's #pragma comment lib is a pinnacle of intuitive design either. For all other linking artifacts, "static" means "include it in the output", so bundling into .rlibs does make some amount sense as well. Not to mention that the world does not end with MSVC...

In any case, it's too late now to change what static means in Rust. What's the next best one?

@Neurrone

This comment has been minimized.

Neurrone commented Sep 1, 2018

Hoping this gets fixed before the 2018 edition, as it is extremely confusing behaviour. Just wasted over an hour trying to understand why it wouldn't find static .libs when I've specified all paths correctly.

@retep998

This comment has been minimized.

Member

retep998 commented Sep 19, 2018

Someone on IRC was getting hit by #26003 and static-nobundle would have avoided that issue and solved their problem. Because it isn't stable they instead had to do workarounds by linking to it with kind=dylib and putting the symbols in a separate extern block so they wouldn't get dllimport'd.

Does anyone have any examples of actual legitimate use cases where static is required and static-nobundle won't work?

@vadimcn

This comment has been minimized.

Contributor

vadimcn commented Sep 20, 2018

@retep998: Maybe you could submit a stabilization RFC for "static-nobundle"? (probably renamed to something prettier)
I've been meaning to do that, but $work keeps me busy and I keep forgetting. :(

It's probably too late for changing the way static works, and anyway, the current implementation doesn't seem totally unreasonable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment