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

Cargo uses different linker for some dependencies #4741

Closed
BatmanAoD opened this issue Nov 22, 2017 · 20 comments
Closed

Cargo uses different linker for some dependencies #4741

BatmanAoD opened this issue Nov 22, 2017 · 20 comments

Comments

@BatmanAoD
Copy link
Member

BatmanAoD commented Nov 22, 2017

Description

It appears that I can't cross-compile some dependencies, because Cargo attempts to use cc as the linker for these packages despite my specification of a target-specific linker. None of my installed linkers are called simply cc, so this of course fails.

The specific packages I've encountered problems with so far are:

  • error-chain (fails compiling backtrace_sys)
  • serde_derive
  • zmq (fails compiling zmq-sys)

I looked at the Cargo.toml for serde_derive and also ripgrep'd the source for instances of cc and found nothing; since this is happening with multiple packages and I don't know why it would ever make sense to revert to some kind of generic linker when cross-compiling, I believe this is an issue with Cargo. (Not necessarily a bug; I fully realize that I could simply be doing something wrong!)

My setup

I'm on a Debian system and have installed the linker arm-linux-gnueabihf-gcc-7.

My ~/.cargo/config:

[target.armv7-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc-7"

To trigger the bug, I put this in my Cargo.toml for a simple "hello world" app:

[dependencies]
error-chain = "0.11"

I then built with:

cargo build --target=armv7-unknown-linux-gnueabihf

My cargo version

cargo 0.21.0 (5b4b8b2ae 2017-08-12)
@BatmanAoD
Copy link
Member Author

Additionally, the linker arguments seem to be inappropriate. They include -m64.

@alexcrichton
Copy link
Member

When cross-compiling dependencies are compiled differently as some are needed for build scripts (on the host) and others are needed for the target. Can you gist the full error message you're seeing?

@BatmanAoD
Copy link
Member Author

Oops, sorry, I attached the error for a native build previously. Here's the output:

capture.txt

@BatmanAoD
Copy link
Member Author

Okay, it seems that apt may have misconfigured my cross-compiler installation. After re-running apt-get install gcc-6-arm-linux-gnueabihf, the example with serde_derive compiles correctly.

I'm now getting an error that seems specific to configure (which I think is used with make?), from zmq-sys (from zmq) and backtrace-sys (from error-chain). It seems to be looking for arm-linux-gnueabihf-gcc when the actual executable is named arm-linux-gnueabihf-gcc-6. I can work around this by adding a symlink with the appropriate name.

So, this no longer seems like a Cargo issue but something related to apt/dpkg and configure. It's odd to me that configure got the wrong executable name; should I report this as an issue on backtrace-rs?

@alexcrichton
Copy link
Member

The error in the gist you sent was a missing cc executable which means that you may not be specifying the correct linker for the final executable or you're missing a native linker for assembling plugins. It also sounds like you were discovering local configuration issues?

@BatmanAoD
Copy link
Member Author

@alexcrichton Sorry, I would completely ignore the gist. Uninstalling my Debian gcc-7 cross-compiling packages and installing gcc-6 ones (which match the system native gcc version) seemed to fix that issue. I'm not sure why Cargo ever went looking for a compiler with the generic name cc, but it does seem to be related to having a strange Debian configuration. (Granted, I don't think I did anything too strange to get into this bad state, so it may be worth investigating, but I don't know that much about apt/dpkg so I can't say it wasn't user error, and I highly doubt it has much at all to do with Cargo.)

Anyway, yes, after getting a working gcc-6 cross-compiler, I still got the strange issue where Cargo was able to configure most packages but some packages using configure scripts tried to use the wrong compiler name. I can attach a config.log tomorrow, but I thought maybe that would be more appropriate as a new issue on a separate project.

@alexcrichton
Copy link
Member

Note that compiler/linker selection isn't always automatic and can sometimes require some amount of configuration. For example rustc will link with cc by default unless otherwise specified which is typically done through something like target.$target.linker in .cargo/config. Additionally build scripts typically tend to use cc by default unless otherwise configured. Most build scripts tend to use crates like cc (confusing names eh?) which reads a bunch of environment variables and tries to have "good defaults" as well though.

The bug in configuration could be anywhere there along the chain unfortunately :(

@BatmanAoD
Copy link
Member Author

I showed my target.$target.linker option in .cargo/config in the top-level post. The strange thing to me, which I think might be a bug in something Cargo-related, is that at one point I was getting an error that indicated an attempt to link using arm-linux-gnueabihf-gcc (which didn't exist) rather than arm-linux-gnueabihf-gcc-6. I resolved this by simply making a symlink ~/bin/arm-linux-gnueabihf-gcc pointing at $(which arm-linux-gnueabihf-gcc-6).

@alexcrichton
Copy link
Member

I think that may have been through the cc crate? That crate tries to do "smart" selection where it can and has different defaults than rustc (but it's only used to compile C code)

@BatmanAoD
Copy link
Member Author

@alexcrichton Makes sense. Any idea why cc wouldn't use the same linker Cargo is using?

I'd like to see if I can verify that indeed this is a cc issue, then close this issue in favor of one on cc. Does cc have a frontend I can use to try to reproduce the issue on the command-line? It looks like cargo install cc installs something called gcc-shim, but it doesn't appear to provide a helpstring.

Failing that, do you think cc-env.rs provides the necessary tools to create a unit test for this case, and if so, do you think you could briefly explain how I'd need to go about doing that? Alternatively, do you have another approach you'd recommend?

@alexcrichton
Copy link
Member

@BatmanAoD oh they're just different systems. Cargo actually isn't doing anything and it's rustc-the-compiler and cc-the-crate. They're just different so they have different defaults right now.

Can you gist the current error message? If it's in a build script it's cc and if not it's probably rustc.

@BatmanAoD
Copy link
Member Author

BatmanAoD commented Dec 6, 2017

Sorry, what I mean is, why wouldn't cargo export the name of the specified linker as an environment variable so that when cc (the crate) goes through its toolchain-detection, it can ensure that the same linker is used as Cargo is using?

Here's the error in the console:
cc_err.txt

..and here's config.log:
config.log

Note line 72:

/home/kjstrand/.cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-sys-0.1.16/src/libbacktrace/configure: line 3001: arm-linux-gnueabihf-gcc: command not found

@alexcrichton
Copy link
Member

OK that error is from the cc crate which means it's using the wrong C compiler most likely. It looks like none of the various CC env vars are set to the cc crate is using the default, which presumably isn't present on your system.

@BatmanAoD
Copy link
Member Author

Correct. Since I'm feeding Cargo a target triple and a specific linker to use, why isn't Cargo passing this information on to cc-rs using the environment variables?

@alexcrichton
Copy link
Member

I think this is just rust-lang/cc-rs#82?

Cargo doesn't currently set anything for cc to pick up, it's sort of cc's job to go find this info right now.

@BatmanAoD
Copy link
Member Author

@alexcrichton Yes! I hadn't seen that issue.

I'm not sure I entirely understand the rational for not just making Cargo communicate the proper toolchain to cc, although I do see the merit in your point (in a different cc issue) that cc requires a full C toolchain while Cargo configuration only specifies the linker.

Perhaps if the user specifies a linker that actually is a full C compiler, then Cargo should export the associated environment variables?

As for this particular failure of cc to detect the toolchain, the problem was the "-6" appended to the end of each executable name in the toolchain. Since I got the toolchain from a stable Debian package, this seems like a case cc can and should handle; shall I open a new issue for that, at least?

@alexcrichton
Copy link
Member

I'm not sure I entirely understand the rational for not just making Cargo communicate the proper toolchain to cc

Oh it's just a thing to design and implement. It's also got a lot of options of how it's implemented. Consequently, it requires a fairly nontrivial effort to do, so it just hasn't been done! There's of course no reason Cargo couldn't do this, it's just that no one's gotten around to it yet.

Also yeah seems plausible for cc to handle this by default!

@BatmanAoD
Copy link
Member Author

@alexcrichton Okay; some of the comments from those issues made me think that maybe you were opposed to having communication (direct or indirect) from Cargo to cc-rs.

@alexcrichton
Copy link
Member

Ah no sorry, was just trying to clarify what was going on!

@alexcrichton
Copy link
Member

I believe Cargo here is working correctly, so I'm going to close this in favor of rust-lang/cc-rs#82

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

2 participants