flycheck / flycheck-rust

Better Rust/Cargo support for Flycheck
GNU General Public License v3.0
121 stars 19 forks source link

Flycheck fails with a cdylib crate type #54

Closed Dushistov closed 7 years ago

Dushistov commented 7 years ago

Suspicious state from syntax checker rust-cargo: Flycheck checker rust-cargo returned non-zero exit code 1, but its output contained no errors: error: Unknown flag: '--cdylib'

Usage: cargo rustc [options] [--] [...]

Try installing a more recent version of rust-cargo, and please open a bug report if the issue persists in the latest release. Thanks!

Dushistov commented 7 years ago

With other crates flycheck-rust works fine, but with this crate with crate-type = ["cdylib"] in Cargo.toml it reports this strange error.

evgeniy@localhost ~ $ rustc --version
rustc 1.17.0-nightly (ccce2c6eb 2017-03-27)
evgeniy@localhost ~ $ cargo --version
cargo 0.19.0-nightly (c995e9eb5 2017-03-17)
fmdkdd commented 7 years ago

When you use rust-cargo, we pass the crate type to cargo rustc (see the code) for the build target type (lib, bin, example, bench, or test).

The cdylib is for plain rustc, no? I have no experience with building cdylib crates; if you can tell me how you build your project with cargo, we can see how to instruct Flycheck to do the correct thing :)

Dushistov commented 7 years ago

The cdylib is for plain rustc, no?

No, it is supported by cargo since rustc 1.11 or so.

To reproduce my issue you need:

cd /tmp/
cargo new --lib foo

after that add such lines into Cargo.toml:

[lib]
name = "foo"
crate-type = ["cdylib"]

after that open foo/src/lib.rs in emacs

if you can tell me how you build your project with cargo

to build project I use cargo build

If I ran cargo build -v -v then cargo reports that it invoke rustc in such way:

$ cargo build -v -v
   Compiling foo v0.1.0 (file:///tmp/foo)
     Running `rustc --crate-name foo src/lib.rs --crate-type cdylib --emit=dep-info,link -C debuginfo=2 -C metadata=1dca6d3bd3489032 -C extra-filename=-1dca6d3bd3489032 --out-dir /tmp/foo/target/debug/deps -L dependency=/tmp/foo/target/debug/deps`
fmdkdd commented 7 years ago

Thanks for the steps; I can indeed reproduce.

So the issue is that flycheck-rust uses cargo metadata to figure out what target to build when calling cargo rustc. Here, cargo metadata returns:

$ cargo metadata --no-deps
...
 "targets": [
        {
          "kind": [
            "cdylib"
          ],
          "name": "foo",
          "src_path": "/tmp/foo/src/lib.rs"
        }
      ],
...

And flycheck-rust tries to pass cdylib as target to cargo rustc, but cargo rustc understands only lib, bin, example, bench, test. In fact, cargo rustc --lib -v - v shows that cdylib is still passed to rustc:

$ cargo rustc --lib -v - v
   Compiling foo v0.1.0 (file:///tmp/foo)
     Running `rustc --crate-name foo src/lib.rs --crate-type cdylib --emit=dep-info,link -C debuginfo=2 -C metadata=1dca6d3bd3489032 -C extra-filename=-1dca6d3bd3489032 --out-dir /tmp/foo/target/debug/deps -L dependency=/tmp/foo/target/debug/deps`

I don't know what a cdylib is, but would it be correct to assume that a cdylib for rustc corresponds to a lib target for cargo?

In any case, you can work around this by setting flycheck-rust-crate-type manually to "lib" using a dir-locals.el file.

Dushistov commented 7 years ago

I don't know what a cdylib is, but would it be correct to assume that a cdylib for rustc corresponds to a lib target for cargo?

cdylib force cargo to build shared libraries that possible to use outside of rust world. For example .so on linux and .dll on windows. So if divide world into two parts lib and bin, then it is lib.

So the issue is that flycheck-rust uses cargo metadata to figure out what target to build when calling cargo rustc

Why so complex? I thought that flycheck just run cargo check and parse it's output.

fmdkdd commented 7 years ago

Thanks for the crash course :) I'll have to dive deeper to see if the cdylib => lib assumption is correct.

Why so complex? I thought that flycheck just run cargo check and parse it's output.

Calling cargo rustc provides us with more flexibility (see #51). But even if we did use cargo check, when you have multiple targets in your project (think one lib and one or more bin), you want to know which target to build depending on the file your are visiting in Emacs to avoid compiling unnecessary targets.

fmdkdd commented 7 years ago

The way I understand the docs, it seems that specifying the crate-type option in a [lib] is just a way to tell rustc which library type to build. But you are still building a library, so it seems to me that when cargo metadata gives us a dylib, cdylib, rlib, staticlib, proc-macro, it means that the build target is lib.

I'll make a patch.

fmdkdd commented 7 years ago

@Dushistov Does the new version work for you?

Dushistov commented 7 years ago

@fmdkdd Yes, thanks.

fmdkdd commented 7 years ago

@Dushistov Great! Thanks for the report :)