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

poor error messages when depending on a |crate-type = ["staticlib"]| crate #3169

Closed
froydnj opened this issue Oct 6, 2016 · 13 comments
Closed
Labels
A-diagnostics Area: Error and warning messages generated by Cargo itself. E-easy Experience: Easy

Comments

@froydnj
Copy link
Contributor

froydnj commented Oct 6, 2016

I have a library, gkrust-gtest, that depends on another library, gkrust. When gkrust's crate-type is set to ["staticlib"] in Cargo.toml, I get the following output:

       Fresh mp4parse-gtest v0.1.0 (file:///home/froydnj/src/gecko-dev.git/dom/media/gtest)
       Fresh byteorder v0.5.3
       Fresh nsstring v0.1.0 (file:///home/froydnj/src/gecko-dev.git/xpcom/rust/nsstring)
       Fresh mp4parse v0.5.1 (file:///home/froydnj/src/gecko-dev.git/media/libstagefright/binding/mp4parse)
       Fresh nsstring-gtest v0.1.0 (file:///home/froydnj/src/gecko-dev.git/xpcom/rust/nsstring/gtest)
       Fresh mp4parse_capi v0.5.1 (file:///home/froydnj/src/gecko-dev.git/media/libstagefright/binding/mp4parse_capi)
       Fresh gkrust v0.1.0 (file:///home/froydnj/src/gecko-dev.git/toolkit/library/rust)
   Compiling gkrust-gtest v0.1.0 (file:///home/froydnj/src/gecko-dev.git/toolkit/library/gtest/rust)
     Running `/usr/local/bin/rustc /home/froydnj/src/gecko-dev.git/toolkit/library/gtest/rust/lib.rs --crate-name gkrust_gtest --crate-type staticlib -C opt-level=1 -C panic=abort -C codegen-units=1 -C debug-assertions=on -C metadata=c6d79253ac32483b --out-dir /opt/build/froydnj/build-rust-mc/toolkit/library/gtest/rust/./x86_64-unknown-linux-gnu/debug/deps --emit=dep-info,link --target x86_64-unknown-linux-gnu -L dependency=/opt/build/froydnj/build-rust-mc/toolkit/library/gtest/rust/./x86_64-unknown-linux-gnu/debug/deps --extern mp4parse_gtest=/opt/build/froydnj/build-rust-mc/toolkit/library/gtest/rust/./x86_64-unknown-linux-gnu/debug/deps/libmp4parse_gtest.rlib --extern nsstring_gtest=/opt/build/froydnj/build-rust-mc/toolkit/library/gtest/rust/./x86_64-unknown-linux-gnu/debug/deps/libnsstring_gtest.rlib -C debuginfo=1`
error[E0463]: can't find crate for `gkrust`
 --> /home/froydnj/src/gecko-dev.git/toolkit/library/gtest/rust/lib.rs:5:1
  |
5 | extern crate gkrust;
  | ^^^^^^^^^^^^^^^^^^^^

This error is most puzzling, as gkrust's Cargo.toml is where one would expect, etc. If you look at the deps folder, you can even see a libgkrust.a file:

toolkit/library/gtest/rust/x86_64-unknown-linux-gnu/debug/deps:
total 8664
-rw-r--r-- 1 froydnj froydnj  274976 Oct  5 22:39 libbyteorder-3f87aa5c5a324af1.rlib
-rw-r--r-- 1 froydnj froydnj 5857872 Oct  6 17:46 libgkrust.a
-rw-r--r-- 1 froydnj froydnj  982010 Oct  5 22:39 libmp4parse_capi.rlib
-rw-r--r-- 1 froydnj froydnj    5968 Oct  5 22:39 libmp4parse_gtest.rlib
-rw-r--r-- 1 froydnj froydnj 1194406 Oct  5 22:39 libmp4parse.rlib
-rw-r--r-- 1 froydnj froydnj  118874 Oct  5 22:39 libnsstring_gtest.rlib
-rw-r--r-- 1 froydnj froydnj  369538 Oct  5 22:39 libnsstring.rlib

The error from rustc is misleading. Notice that the rustc invocation doesn't include an --extern for gkrust. The real problem here is that Cargo isn't telling the user upfront, "hey, you can't link to a staticlib library like that, you need to do something different."

Listing rlib as a crate-type solves the problem, but it would be most excellent if Cargo detected the configuration problem first, rather than leaving rustc to do a poor job of diagnosing the issue.

@alexcrichton alexcrichton added the A-diagnostics Area: Error and warning messages generated by Cargo itself. label Oct 6, 2016
@alexcrichton
Copy link
Member

Right now Cargo filters out non-linkable targets, for example a staticlib, because the compiler can't actually use that for --extern.

We should definitely have an error there if there aren't actually any linkable targets, as it it's basically guaranteed to fail!

I'm going to tag this as an E-easy bug, as I think all that needs to happen is to return an error there if we didn't actually link anything. If anyone needs any help tackling this though just let me know!

@alexcrichton alexcrichton added the E-easy Experience: Easy label Oct 6, 2016
froydnj added a commit to froydnj/cargo that referenced this issue Oct 6, 2016
@froydnj
Copy link
Contributor Author

froydnj commented Oct 6, 2016

Right now Cargo filters out non-linkable targets, for example a staticlib, because the compiler can't actually use that for --extern.

OK, so I took a crack at fixing this, basically returning an error if !unit.target.linkable()--though there's this peculiar interaction with unit.profile.doc which I can't figure out. Which does the right thing for my homegrown testcase, but then I can't use the newly-built cargo to build cargo itself, getting errors like:

error: Crate build_script_build cannot be linked into ws2_32

You can see the current effort at froydnj/cargo@3b6c255. I suspect this is some sort of interaction with things that we aren't actually building, so we'd need something a little finer-grained than linkable() there?

@alexcrichton
Copy link
Member

@froydnj oh we don't want to return an error if any target is not linkable, only if all targets are not linkable. Some dependencies are build scripts (we don't link those) while other dependencies are staticlibs (we also don't link those). If a dependency is an rlib or a dylib though (we link those) then this should be fine.

@froydnj
Copy link
Contributor Author

froydnj commented Oct 6, 2016

we don't want to return an error if any target is not linkable, only if all targets are not linkable.

Oh, duh. I had actually implemented that behavior in link_to before I figured out that was the wrong place to be putting the logic; I carried the logic over, but not the correct gathering of the logic. Thanks for pointing that out, I'll fix things up.

@froydnj
Copy link
Contributor Author

froydnj commented Oct 7, 2016

Actually, I don't think that's quite right, either. In the example given to start this bug, gkrust depends on three things: mp4parse_gtest, nsstring_gtest, and gkrust. The first two certainly are linkable: we have rlibs for them. But the last one is not linkable, because it's a staticlib. So "all" is not the right condition to apply, because we have some linkable things. But "any" isn't right either, as you point out--though in the original example, we're not linking staticlibs and that's part of the problem!

@alexcrichton
Copy link
Member

Oh I thought the problem Gecko was having was that gkrust_test did want to link to gkrust? That is, it currently only creates a staticlib but the "bug fix" was to also produce an rlib?

@froydnj
Copy link
Contributor Author

froydnj commented Oct 7, 2016

Yes, we really did want to link gkrust. One could fix the original problem by setting |crate-type = ["staticlib", "rlib"]|.

@alexcrichton
Copy link
Member

In that state though I figured it was invalid when gkrust_test said it'd like to link to gkrust when gkrust only created a staticlib, because Cargo didn't actually link anything (causing this weird error)

@froydnj
Copy link
Contributor Author

froydnj commented Oct 7, 2016

In that state though I figured it was invalid when gkrust_test said it'd like to link to gkrust when gkrust only created a staticlib, because Cargo didn't actually link anything (causing this weird error)

What is "that state"? I don't understand this comment.

@alexcrichton
Copy link
Member

@froydnj oh sorry for being a little belated to get back to you!

The state there I was referring to was where gkrust_test declared that it would like to link to gkrust, which was in fact invalid because gkrust produced no linkable artifacts. That is, the check I'd imagine is that if all targets are not linkable there's no way for that package to be a dependency of anything, so we should be emitting a hard error there instead of waiting for the compiler to spit out something random.

@lukaslueg
Copy link
Contributor

Is this still open? Building against a staticlib-crate seems to work just fine and the docs say

The available options are dylib, rlib, staticlib, cdylib, and proc-macro. You should only use this option in a project. Cargo will always compile packages (dependencies) based on the requirements of the project that includes them.

@alexcrichton
Copy link
Member

@lukaslueg I think so, for example of you have foo depend on bar (with extern crate bar) and then bar is compiled as a staticlib I think you'll get a bad error message?

@lukaslueg
Copy link
Contributor

Indeed it does. I have a test in place that didn't actually extern crate so there was no error. This raises the question where we want to detect the situation: At the latest in cargo_rustc/mod.rs::build_deps_args() if not any of cx.dep_targets() is linkable(). Or could it be detected during resolve somehow? Since we might just want to generate docs, build_deps_args() is the right place ?!

Besides, the docs I mentioned above leave room for improvement as the language used suggests a level of certainty that isn't founded.

bors added a commit that referenced this issue Dec 12, 2017
Bail out when trying to link to a library that is not linkable.

There are more subtleties here than expected, as we can have situations where it is actually Ok to have no linkable targets: Build scripts are a common case, yet benchmark tests started to also fail. I have to say I'm not convinced if the situation "not one target is linkable, yet at least one target is a library (and therefor at least something should be linked)" is actually correct. All tests pass, however, including the one that checks for #3169
@bors bors closed this as completed in 554f333 Dec 12, 2017
@weihanglo weihanglo modified the milestone: 1.24.0 Mar 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Error and warning messages generated by Cargo itself. E-easy Experience: Easy
Projects
None yet
Development

No branches or pull requests

4 participants