Skip to content
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

Linker argument order sometimes wrong. #12446

Closed
HildarTheDorf opened this issue Feb 21, 2014 · 2 comments
Closed

Linker argument order sometimes wrong. #12446

HildarTheDorf opened this issue Feb 21, 2014 · 2 comments

Comments

@HildarTheDorf
Copy link

extern crates appear in the link arguments after #[link(name="foo")] attributes in the current crate. This can cause undefined symbol issues when an rlib contains an incomplete version of the static library foo (foo.a) because it is later in the linker command line. Forcing it to be last in the commandline with -C link-args="-lfoo" works as a workaround.
`
To be fair, I'm not sure if there is ever a "perfect" ordering for linker arguments that works in every single case (other than doing it manually), but making it extern crates, then #links in the current crate seems to make more sense. Something like #[link_first()] and/or #[link_last()] would work too (forcing it to link before or after external crates respectively).

This was all on Ubuntu 13.10 x86_64, and all the libs in question were static (.rlib or .a).

@alexcrichton
Copy link
Member

Could you provide a small test case as an example? Last I tried I was unable to get a linker error when I tried things like this.

cc #11124

@HildarTheDorf
Copy link
Author

Here's an attempt:
https://github.com/HildarTheDorf/RustLinkerBug

Type make to try and build. The list of #[link(name="")] might need amending (take a look at pkg-config --static --libs glfw3 for help, or read the rustc error message). Hopefully you eventually reach the point where glfw-rs functions can't find glfw symbols (and not other errors). You can comment out the #[link(name="glfw3")] to show how many symbols in glfw it IS finding.

Fails for me on ubuntu 13.10 x64 with 6532d2f, I'll update to master and check it still fails.

Note: I have glfw3.a in my linker search path, I can't see why dropping it in ./lib/ won't work, but I haven't tried it.

EDIT: Forgot to mention that adding -C link=args=-lglfw3 to RUSTFLAGS will successfully build, with the #[link(name="glfw3")] as well. You can also drop all the #[link()] stuff and just use -C link-args="'pkg-config --static --libs glfw3'" (backticks, not ', but markdown mangles it)

alexcrichton added a commit to alexcrichton/rust that referenced this issue Feb 27, 2014
With linkers on unix systems, libraries on the right of the command line are
used to resolve symbols in those on the left of the command line. This means
that arguments must have a right-to-left dependency chain (things on the left
depend on things on the right).

This is currently done by ordering the linker arguments as

  1. Local object
  2. Local native libraries
  3. Upstream rust libraries
  4. Upstream native libraries

This commit swaps the order of 2 and 3 so upstream rust libraries have access to
local native libraries. It has been seen that some upstream crates don't specify
the library that they link to because the name varies per platform (e.g.
lua/glfw/etc).

This commit enables building these libraries by allowing the upstream rust crate
to have access to local native libraries. I believe that the failure mode for
this scheme is when an upstream rust crate depends on a symbol in an upstream
library which is then redefined in a local library. This failure mode is
incredibly uncommon, and the failure mode also varies per platform (OSX behaves
differently), so I believe that a change like this is fine to make.

Closes rust-lang#12446
alexcrichton added a commit to alexcrichton/rust that referenced this issue Sep 23, 2015
This commit swaps the order of linking local native libraries and upstream
native libraries on the linker command line. Detail of bugs this can cause can
be found in rust-lang#28595, and this change also invalidates the test case that was
added for rust-lang#12446 which is now considered a bug because the downstream dependency
would need to declare that it depends on the native library somehow.

Closes rust-lang#28595
alexcrichton added a commit to alexcrichton/rust that referenced this issue Oct 1, 2015
This commit swaps the order of linking local native libraries and upstream
native libraries on the linker command line. Detail of bugs this can cause can
be found in rust-lang#28595, and this change also invalidates the test case that was
added for rust-lang#12446 which is now considered a bug because the downstream dependency
would need to declare that it depends on the native library somehow.

Closes rust-lang#28595
bors added a commit that referenced this issue Oct 1, 2015
This commit swaps the order of linking local native libraries and upstream
native libraries on the linker command line. Detail of bugs this can cause can
be found in #28595, and this change also invalidates the test case that was
added for #12446 which is now considered a bug because the downstream dependency
would need to declare that it depends on the native library somehow.

Closes #28595
[breaking-change]
matthiaskrgr pushed a commit to matthiaskrgr/rust that referenced this issue Mar 21, 2024
use `span_lint_hir` instead of `span_lint` in more lints

Decided to grep for `check_(fn|block)` and look where `span_lint` is used, since some lints lint will then emit a lint on a statement or expression in that function, which would use the wrong lint level attributes

The `LintContext` keeps track of the last entered HIR node that had any attributes, and uses those (and its parents) for figuring out the lint level when a lint is emitted

However, this only works when we actually emit a lint at the same node as the `check_*` function we are in.
If we're in `check_fn` and we emit a lint on a statement within that function, then there is no way to allow the lint only for that one statement (if `span_lint` is used). It would only count allow attributes on the function

changelog: [`needless_return`]: [`useless_let_if_seq`]: [`mut_mut`]: [`read_zero_byte_vec`]: [`unused_io_amount`]: [`unused_peekable`]: now respects `#[allow]` attributes on the affected statement instead of only on the enclosing block or function
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants