How to import a crate dependency when the library name is different from the package name?

自闭症网瘾萝莉.ら 提交于 2020-05-13 05:39:06

问题


I have a crate that is imported straight off of GitHub, as per Cargo's documentation:

[dependencies]
libfoo = { git = "ssh://git@github.com/me/libfoo", branch = "dev" }

[lib]
path = "src/rust/lib.rs"
name = "myprj"
crate-type = ["cdylib"]

Running cargo build works fine here, Cargo fetches libfoo and builds it in the ~/.cargo directory. When I try to use (import) it in lib.rs:

extern crate libfoo;   //also tried foo

Cargo chokes:

error[E0463]: can't find crate for `libfoo`
 --> src/rust/lib.rs:1:1
  |
1 | extern crate libfoo;
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't find crate

Interestingly, IntelliJ's Rust plugin does find the crate when I click on it in lib.rs – it navigates to the downloaded source in ~/.cargo...

In the dependency libfoo, the lib section of the Cargo.toml file is specified as:

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

I have tried all permutations of libfoo and foo to see if Cargo is getting confused between the lib name and the package/directory name.

It also fails if I specify a local path to the dependency. (Cargo compiles the dependency but then claims not to find it when it is declared/imported in lib.rs.)

[dependencies]
libfoo = { path = "/Users/me/dev/libfoo" }

If I include a crate from git or the file system that has the same [lib] name as the [package] name, it works fine. So it appears the problem is with crates that have a have a library ([lib]) name that is different from the package ([package]) name.

If I remove the [lib] section from the dependency's Cargo.toml file, it works.

Update: if crate-type = ["cdylib"] is removed from libfoo, this works with foo imported. If that is there, I get the same error with extern crate foo;.


回答1:


Cargo is interested in package names when it comes to dependencies, while the compiler (rustc) is interested in library names when it comes to loading their metadata and linking with them.

Let's take a look again at this Cargo.toml excerpt:

[package]
name = "libfoo"

[lib]
name = "foo"

Here, the package name is libfoo and the library name is foo.

When you want to declare a dependency on libfoo in your project, you need to write the package name (libfoo) in the [dependencies] table. For example:

[dependencies]
libfoo = { git = "ssh://git@github.com/me/libfoo", branch = "dev" }

This is what you already have, and it's correct.

However, when you want to import the library in your crate, you need to write the library name in the extern crate item, i.e.

extern crate foo;

How did I figure this out? First, I wrote libfoo in both Cargo.toml and the extern crate item, as you described. When I ran cargo build, I noticed that libfoo was built successfully, indicating that Cargo correctly resolved the dependency. But I also noticed that the compiler couldn't find libfoo, as you experienced.

I then inspected the command line passed to rustc by running cargo build --verbose. This is what I saw (irrelevant parts omitted):

Running `rustc [...] --extern foo=/[path]/target/debug/deps/libfoo-5cf876c5c8ac1bfb.rlib`                                                                 

The --extern name=path argument tells rustc that the crate named name is located in path. The name here is foo, so we must write extern crate foo; in the code to reference it.



来源:https://stackoverflow.com/questions/44769922/how-to-import-a-crate-dependency-when-the-library-name-is-different-from-the-pac

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!