我有 4 个文件:
main.rs
mod bar;
fn main() {
let v = vec![1, 2, 3];
println!("Hello, world!");
}
lib.rs
pub mod foo;
pub mod bar;
foo.rs
pub fn say_foo() {
}
bar.rs
use crate::foo;
fn bar() {
foo::say_foo();
}
当我运行 cargo run
时,我收到一条错误消息:
error[E0432]: unresolved import `crate::foo`
--> src/bar.rs:1:5
|
1 | use crate::foo;
| ^^^^^^^^^^ no `foo` in the root
有人可以向我解释如何解决这个问题吗?更广泛地说:当存在 main.rs
和 lib.rs
时,模块查找如何工作?
编辑:将 mod foo
添加到 main.rs
修复了这个问题。但我不明白这一点——我的印象是 lib.rs
是“公开”我所有模块的地方?为什么我还必须在 main.rs
中声明模块?
我的 Cargo.toml
:
[package]
name = "hello-world"
version = "0.1.0"
authors = ["me@mgail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
最佳答案
让我们从头开始。看Package Layout章节 The Cargo Book .如您所见,您的包裹可能包含很多东西:
- 一个二进制文件(你可以运行的东西)或多个二进制文件,
- 单个库(共享代码),
- 示例,
- 基准,
- 集成测试。
包布局
此处并未列出所有可能性,仅列出了二进制文件/库组合。
二进制文件
这是一个包含单个二进制文件的包示例。入口点是 src/main.rs
中的 main
函数。
Cargo.toml
:
[package]
name = "hallo"
version = "0.1.0"
edition = "2018"
src/main.rs
:
fn main() {
println!("Hallo, Rust here!")
}
$ cargo run
Hallo, Rust here!
图书馆
这是一个包含库的包示例。图书馆没有入口点,你不能运行它们。它们用于功能共享。
Cargo.toml
:
[package]
name = "hallo"
version = "0.1.0"
edition = "2018"
src/lib.rs
:
pub fn foo() {
println!("Hallo, Rust library here!")
}
$ cargo run
error: a bin target must be available for `cargo run`
您在 Cargo.toml
文件中看到任何关于二进制文件或库的信息吗?不,原因是我关注了Package Layout cargo
知道去哪里找东西。
一个二进制文件和一个库
这是一个包含二进制文件和库的包示例。
Cargo.toml
:
[package]
name = "hallo"
version = "0.1.0"
edition = "2018"
src/lib.rs
:
pub const GREETING: &'static str = "Hallo, Rust library here!";
src/main.rs
:
use hallo::GREETING;
fn main() {
println!("{}", GREETING);
}
同样的问题,您在 Cargo.toml
文件中看到任何关于二进制文件或库的信息吗?没有。
这个包包含两个东西:
- 二进制文件(根
src/main.rs
,入口点src/main.rs::main
), - 一个库(root
src/lib.rs
,共享代码)。
可以通过 use hallo::...
从二进制文件中引用一个库,其中 hallo
是这个包名(Cargo.toml
-> [package]
-> name
).
你的问题
Cargo.toml
:
[package]
name = "hallo"
version = "0.1.0"
edition = "2018"
相同的包布局
库部分
src/lib.rs
:
pub mod bar;
pub mod foo;
src/foo.rs
:
pub fn say_foo() {
println!("Foo");
}
src/bar.rs
:
use crate::foo;
pub fn bar() {
foo::say_foo();
}
crate
指的是 src/lib.rs
,因为这里是我们库的上下文。
将其视为一个独立的单元,并通过 use hallo::...;
从外部世界引用它。
二进制部分
src/main.rs
:
use hallo::bar::bar;
fn main() {
bar();
}
这里我们只使用我们的库。
没有图书馆
相同的代码,但是 lib.rs
被重命名为 utils.rs
并且 (foo|bar).rs
文件被移动到src/utils/
文件夹。
src/utils.rs
:
pub mod bar;
pub mod foo;
src/utils/foo.rs
:
pub fn say_foo() {
println!("Foo");
}
src/utils/bar.rs
:
use super::foo;
// or use crate::utils::foo;
pub fn bar() {
foo::say_foo();
}
我们也可以在这里使用 crate
,但是因为我们在二进制文件的上下文中,所以路径不同。
src/main.rs
:
use utils::bar::bar;
mod utils;
fn main() {
bar();
}
这里我们刚刚声明了另一个模块 (utils
),我们正在使用它。
总结
Cargo.toml
内容:
[package]
name = "hallo"
version = "0.1.0"
edition = "2018"
如果有一个 src/main.rs
文件,你基本上是这样说的:
[package]
name = "hallo"
version = "0.1.0"
edition = "2018"
[[bin]]
name = "hallo"
src = "src/main.rs"
如果有一个 src/lib.rs
文件,你基本上是这样说的:
[package]
name = "hallo"
version = "0.1.0"
edition = "2018"
[lib]
name = "hallo"
path = "src/lib.rs"
如果两者都有,你基本上是这样说的:
[package]
name = "hallo"
version = "0.1.0"
edition = "2018"
[[bin]]
name = "hallo"
path = "src/main.rs"
[lib]
name = "hallo"
path = "src/lib.rs"
文档
关于module - 当有 main.rs 和 lib.rs 时 Rust 模块混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57756927/