Skip to content

Confusing link order in beta cargo #395

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

Closed
FauxFaux opened this issue Apr 13, 2019 · 3 comments
Closed

Confusing link order in beta cargo #395

FauxFaux opened this issue Apr 13, 2019 · 3 comments

Comments

@FauxFaux
Copy link

FauxFaux commented Apr 13, 2019

Rust 1.35 (currently in beta) changes the way linking order works, probably rust-lang/rust#57018.

For a my project, which uses cc to build a C wrapper for a (system) C++ library, this is now confusing. At least, it's taken me multiple hours to work out what's going on, and I thought I should write it down somewhere!

cc adds a cargo: command to static link the helper library, without me asking it to inside build.rs:
cc::Build::new().file(SRC).compile("libfoo-helper.a");

The app then links both the helper and the actual library:

#[link(name = "foo-helper", kind = "static")]
#[link(name = "foo")]
extern "C" {

This worked on rustc/cargo up until +nightly-2019-03-20, and is broken on +nightly-2019-03-21, which is 3eb4890df..82e2f3ec2. After that, you get linker errors.

Why? The reordering now means that, regardless of how you specify your #[link directives, rustc reorders the three commands such that the libraries are in the wrong order.

The simplest solution I have is to provide both libraries in the build.rs. This makes both of my #[link directives above redundant.

This doesn't feel like a bug in rustc as such, but I'm .. I'm not happy with the behaviour.

Should cc provide a hint on how to do this right? Perhaps a way to specify that a build "depends on" a dynamic library, even though this information is not needed during the compilation?
Or maybe rustc/cargo is just being unreasonable, and should be reverted?

@alexcrichton
Copy link
Member

Thanks for the report! @dcreager I do believe this is caused by #57018, so could you help take a look here?

Some local testing shows that on stable we link with:

... -lfoo-helper ... -lfoo ...

whereas on nightly we link with:

... -lfoo ... -lfoo-helper ...

which if foo-helper uses symbols from foo probably causes issues.

Now all that being said relying on the exact specifics of what rustc is doing at any one point in time isn't ever intentional but may be what's happening here. It's pretty ambiguous how we as a compiler interpret all these link annotations to specify a link line...

@dcreager
Copy link

Hey there, sorry for the delay, just saw this.

@FauxFaux To clarify, in your example, foo-helper is the C wrapper library, foo is the system C++ library, and foo-helper depends on foo, right?

My gut tells me that your suggestion to somehow tell cc about the dependency is the right one. The reason for #57018 was to fix the case where foo-helper was the thing being depended on, and so we need to move it later on in the command line to avoid a similar set of linker errors.

That said, I don't know of the best way to accomplish this. (Your workaround sidesteps the issue by outputting what cc would have produced if it knew about the dependency.)

Maybe an alternative fix in rustc where we keep both copies of -lfoo-helper, instead of keeping only one, and having to decide which of the copies was the right one to keep?

@alexcrichton
Copy link
Member

I think that this has since slipped into stable so there's probably not a huge amount we can do about this, so I'm going to close.

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

No branches or pull requests

3 participants