当库名与包名不同时,如何导入包依赖项?

时间:2017-06-26 23:06:40

标签: rust rust-cargo

我有一个直接从GitHub导入的箱子,按照货物的documentation

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

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

正常运行cargo build,Cargo抓取libfoo并在~/.cargo目录中构建它。当我尝试在lib.rs中使用(导入)时:

extern crate libfoo;   //also tried foo

货物窒息:

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

有趣的是,当我在lib.rs点击它时,IntelliJ的Rust插件会找到箱子 - 它导航到~/.cargo中的下载源...

在依赖项libfoo中,lib文件的Cargo.toml部分指定为:

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

我已经尝试了libfoo和foo的所有排列,看看Cargo是否在lib名称和包/目录名之间感到困惑。

如果我指定了依赖项的本地路径,它也会失败。 (Cargo编译依赖项,但声称在lib.rs中声明/导入时不会找到它。)

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

如果我从git或与[lib]名称具有相同[package]名称的文件系统中包含一个包,它可以正常工作。因此,问题似乎是包含的库([lib])名称与包([package])名称不同。

如果我从依赖项的[lib]文件中删除Cargo.toml部分,它就可以正常工作。

更新:如果从crate-type = ["cdylib"]移除了libfoo,则可以使用已导入的foo。如果那样,我在extern crate foo;时会遇到同样的错误。

1 个答案:

答案 0 :(得分:8)

当涉及到依赖关系时,Cargo对包名称感兴趣,而编译器(rustc)在加载他们的库名时感兴趣元数据并与它们链接。

让我们再看看这个Cargo.toml摘录:

[package]
name = "libfoo"

[lib]
name = "foo"

此处,包名称libfoo库名称foo

如果要在项目中声明对libfoo的依赖关系,则需要在libfoo表中编写包名称[dependencies])。例如:

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

这是你已经拥有的,这是正确的。

但是,如果要在包中导入库,则需要在extern crate项中编写库名,即

extern crate foo;

我是怎么想出来的?首先,我在libfooCargo.toml项中写了extern crate,正如您所描述的那样。当我运行cargo build时,我注意到libfoo已成功构建,表明Cargo正确解决了依赖关系。但我也注意到,编译器无法找到libfoo,正如您所经历的那样。

然后,我通过运行rustc检查了传递给cargo build --verbose的命令行。这就是我所看到的(省略了相关部分):

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

--extern name=path参数告诉rustc名为name的包位于path。这里的名称是foo,因此我们必须在代码中编写extern crate foo;来引用它。