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

mar*_*hon 3 rust rust-cargo

根据Cargo的文档,我有一个直接从GitHub导入的箱子:

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

[lib]
path = "src/rust/lib.rs"
name = "myprj"
crate-type = ["cdylib"]
Run Code Online (Sandbox Code Playgroud)

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

extern crate libfoo;   //also tried foo
Run Code Online (Sandbox Code Playgroud)

货物扼流圈:

error[E0463]: can't find crate for `libfoo`
 --> src/rust/lib.rs:1:1
  |
1 | extern crate libfoo;
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't find crate
Run Code Online (Sandbox Code Playgroud)

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

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

[package]
name = "libfoo"
[lib]
name = "foo"
crate-type = ["cdylib"]
Run Code Online (Sandbox Code Playgroud)

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

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

[dependencies]
libfoo = { path = "/Users/me/dev/libfoo" }
Run Code Online (Sandbox Code Playgroud)

如果我从git或与[lib]名称同名的文件系统中包含一个包[package],它可以正常工作.所以看来问题是crates的library([lib])名称与package([package])名称不同.

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

更新:如果crate-type = ["cdylib"]删除libfoo,则适用于foo导入.如果那样,我得到同样的错误extern crate foo;.

Fra*_*gné 8

当涉及到依赖关系时,Cargo对包名称感兴趣,而在加载元数据和链接它们时,compiler(rustc)对库名称感兴趣.

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

[package]
name = "libfoo"

[lib]
name = "foo"
Run Code Online (Sandbox Code Playgroud)

这里,包名libfoo,库名foo.

如果要libfoo在项目中声明依赖项,则需要在表中编写包名称(libfoo)[dependencies].例如:

[dependencies]
libfoo = { git = "ssh://git@github.com/me/libfoo", branch = "dev" }
Run Code Online (Sandbox Code Playgroud)

这就是你已经拥有的,这是正确的.

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

extern crate foo;
Run Code Online (Sandbox Code Playgroud)

我怎么知道这个?首先,正如你所描述的那样,我libfoo在两个Cargo.tomlextern crate项目中都写过.当我跑步时cargo build,我注意到它libfoo已成功构建,表明Cargo正确解决了依赖关系.但我也注意到编译器无法找到libfoo,正如您所经历的那样.

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

Running `rustc [...] --extern foo=/[path]/target/debug/deps/libfoo-5cf876c5c8ac1bfb.rlib`                                                                 
Run Code Online (Sandbox Code Playgroud)

--extern name=path参数告诉rustc名字的箱子name位于path.这里的名字是foo,所以我们必须extern crate foo;在代码中写入引用它.

  • 我认为这是完全正常的.`cdylib`代表一个提供C接口的库,而不是Rust接口.`cdylib`不包含在其上使用`extern crate`所必需的元数据,因此Cargo甚至不会将`--extern`传递给`rustc`以获取此类依赖项.如果你想要一个C接口*和*一个Rust接口,请使用`crate-type = ["cdylib","lib"]`而不是(或者`crate-type = ["cdylib","dylib"]`如果你想要的话动态库).如果你只需要一个Rust接口,省略`crate-type`. (2认同)