Rust modules confusion when there is main.rs and lib.rs
我有4个文件:
1 2 3 4 5 6 | mod bar; fn main() { let v = vec![1, 2, 3]; println!("Hello, world!"); } |
1 2 | pub mod foo; pub mod bar; |
1 2 3 | pub fn say_foo() { } |
1 2 3 4 5 | use crate::foo; fn bar() { foo::say_foo(); } |
运行
1 2 3 4 5 | error[E0432]: unresolved import `crate::foo` --> src/bar.rs:1:5 | 1 | use crate::foo; | ^^^^^^^^^^ no `foo` in the root |
有人可以向我解释如何解决此问题吗?更广泛地说:当存在
编辑:将
我的
1 2 3 4 5 6 7 8 9 | [package] name ="hello-world" version ="0.1.0" authors = ["[email protected]>"] edition ="2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] |
让我们从头开始。查看《货运手册》中的"包装布局"一章。如您所见,您的包中可能包含很多东西:
- 一个二进制文件(可以运行的文件)或多个二进制文件,
- 单个库(共享代码),
- 例子),
- 基准,
- 集成测试。
包装布局
此处未列出所有可能性,仅列出了二进制文件/库组合。
二进制文件
这是带有单个二进制文件的软件包的示例。入口点是
1 2 3 4 | [package] name ="hallo" version ="0.1.0" edition ="2018" |
1 2 3 | fn main() { println!("Hallo, Rust here!") } |
1 2 | $ cargo run Hallo, Rust here! |
图书馆
这是带有库的软件包的示例。图书馆没有入口点,您不能运行它们。它们用于功能共享。
1 2 3 4 | [package] name ="hallo" version ="0.1.0" edition ="2018" |
1 2 3 | pub fn foo() { println!("Hallo, Rust library here!") } |
1 2 | $ cargo run error: a bin target must be available for `cargo run` |
您是否在
二进制文件和库
这是带有二进制文件和库的软件包的示例。
1 2 3 4 | [package] name ="hallo" version ="0.1.0" edition ="2018" |
1 | pub const GREETING: &'static str ="Hallo, Rust library here!"; |
1 2 3 4 5 | use hallo::GREETING; fn main() { println!("{}", GREETING); } |
相同的问题,您是否在
此程序包包含两件事:
-
二进制文件(根
src/main.rs ,入口点src/main.rs::main ), -
库(根
src/lib.rs ,共享代码)。
可通过
你的问题
1 2 3 4 | [package] name ="hallo" version ="0.1.0" edition ="2018" |
相同的包装布局
库部分
1 2 | pub mod bar; pub mod foo; |
1 2 3 | pub fn say_foo() { println!("Foo"); } |
1 2 3 4 5 | use crate::foo; pub fn bar() { foo::say_foo(); } |
将其作为独立的单元进行处理,并通过
二进制部分
1 2 3 4 5 | use hallo::bar::bar; fn main() { bar(); } |
这里我们只是在使用我们的库。
没有图书馆
相同的代码,但是
1 2 | pub mod bar; pub mod foo; |
1 2 3 | pub fn say_foo() { println!("Foo"); } |
1 2 3 4 5 6 | use super::foo; // or use crate::utils::foo; pub fn bar() { foo::say_foo(); } |
我们也可以在这里使用
1 2 3 4 5 6 7 | use utils::bar::bar; mod utils; fn main() { bar(); } |
在这里,我们刚刚声明了另一个模块(
概要
1 2 3 4 | [package] name ="hallo" version ="0.1.0" edition ="2018" |
如果有
1 2 3 4 5 6 7 8 | [package] name ="hallo" version ="0.1.0" edition ="2018" [[bin]] name ="hallo" src ="src/main.rs" |
如果有
1 2 3 4 5 6 7 8 | [package] name ="hallo" version ="0.1.0" edition ="2018" [lib] name ="hallo" path ="src/lib.rs" |
如果两者都存在,基本上就是这样说:
1 2 3 4 5 6 7 8 9 10 11 12 | [package] name ="hallo" version ="0.1.0" edition ="2018" [[bin]] name ="hallo" path ="src/main.rs" [lib] name ="hallo" path ="src/lib.rs" |
文献资料
- 包装布局
- 清单格式
- 使用软件包,板条箱和模块管理不断增长的项目
简而言之,Rust官方书上写着:
If a package contains
src/main.rs andsrc/lib.rs , it has two crates: a library and a binary, both with the same name as the package.
此外,Rust参考说明:
crate resolves the path relative to the current crate
因此,您的项目中实际上有两个包装箱,
现在在代码示例中,如果要编译内容,则必须从
将其删除后,则因为在
1 2 | pub mod foo; pub mod bar; |
还有一件事,如果您想从
的项目中
1 2 3 4 | use hello_world::foo; fn main() { foo::say_foo(); } |
是将
但是,导入行为似乎没有其他效果。即如果在
当您使用
但是,导入库时,入口点是
在这种情况下,通常的工作流程是使二进制文件像库周围的薄包装纸一样-在某些极端情况下,
的东西
1 2 3 4 | use library; fn main() { library::main(); } |
和整个逻辑(以及所有项目结构)进入库箱。原因之一就是您遇到的问题:是否将此具体模块导入包装中的每个板条箱中可能引起混淆。