当有 main.rs 和 lib.rs 时,Rust 模块会混淆 [英] Rust modules confusion when there is main.rs and lib.rs

查看:23
本文介绍了当有 main.rs 和 lib.rs 时,Rust 模块会混淆的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有 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 时,我收到一条错误消息:

When I run cargo run I get an error saying:

error[E0432]: unresolved import `crate::foo`
 --> src/bar.rs:1:5
  |
1 | use crate::foo;
  |     ^^^^^^^^^^ no `foo` in the root

有人可以向我解释如何解决这个问题吗?更广泛地说:当有 main.rslib.rs 时,模块查找如何工作?

Could someone explain to me how to fix this? A bit more broadly: how does module lookup work when there's a main.rs and a lib.rs?

mod foo 添加到 main.rs 修复了该问题.但我不明白这一点——我的印象是 lib.rs 是暴露"我所有模块的地方?为什么我还要在 main.rs 中声明模块?

Adding mod foo to main.rs fixes the issue. But I don't understand this -- I was under the impression the lib.rs was the place that "exposed" all of my modules? Why do I have to declare the module in main.rs as well?

我的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]

推荐答案

让我们从头开始.查看包布局一章://doc.rust-lang.org/cargo/index.html" rel="noreferrer">货物手册.如您所见,您的包裹可以包含很多东西:

Let's start from the beginning. Look at the Package Layout chapter in The Cargo Book. As you can see, your package can contain lot of stuff:

  • 一个二进制文件(你可以运行的东西)或多个二进制文件,
  • 单个库(共享代码),
  • 示例,
  • 基准,
  • 集成测试.

此处未列出所有可能性,仅列出二进制/库组合.

Not all of the possibilities are listed here, just the binary / library combinations.

这是一个带有单个二进制文件的包示例.入口点是src/main.rs中的main函数.

This is an example of a package with single binary. Entry point is the main function in the src/main.rs.

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!

图书馆

这是一个带有库的包示例.图书馆没有入口点,你不能运行它们.它们用于功能共享.

A library

This is an example of a package with a library. Libraries don't have entry points, you can't run them. They're used for functionality sharing.

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 文件中看到有关二进制文件或库的任何内容?不.原因是我遵循了包布局并且 cargo 知道去哪里找东西.

Do you see anything in the Cargo.toml file about a binary or a library? No. The reason is that I've followed the Package Layout and the cargo knows where to look for things.

这是一个包含二进制文件和库的包示例.

This is an example of a package with a binary and a library.

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 文件中看到有关二进制文件或库的任何内容?号

Same question, do you see anything in the Cargo.toml file about a binary or a library? No.

这个包包含两件事:

  • 一个二进制文件(根src/main.rs,入口点src/main.rs::main),
  • 一个库(根src/lib.rs,共享代码).
  • a binary (root src/main.rs, entry point src/main.rs::main),
  • a library (root src/lib.rs, shared code).

可以通过 use halo::... 从二进制文件中引用库,其中 hallo 是这个包名 (Cargo.toml> -> [package] -> name).

A library can be referenced from the binary via use hallo::... where the hallo is this package name (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,因为我们在这里处于我们库的上下文中.

crate refers to src/lib.rs, because we're in the context of our library here.

将其视为一个独立的单元,并通过use halo::...;从外部引用它.

Treat it as a standalone unit and refer to it via use hallo::...; from the outside world.

src/main.rs:

use hallo::bar::bar;

fn main() {
    bar();
}

这里我们只是使用我们的库.

Here we're just using our library.

相同的代码,但 lib.rs 被重命名为 utils.rs(foo|bar).rs 文件被移动到src/utils/ 文件夹.

Same code, but lib.rs was renamed to utils.rs and (foo|bar).rs files were moved to the src/utils/ folder.

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,但是因为我们在二进制文件的上下文中,所以路径不同.

We can use crate here as well, but because we're in the context of our binary, the path differs.

src/main.rs:

use utils::bar::bar;

mod utils;

fn main() {
    bar();
}

这里我们刚刚声明了另一个模块(utils)并且我们正在使用它.

Here we just declared another module (utils) and we're using it.

Cargo.toml 内容:

[package]
name = "hallo"
version = "0.1.0"
edition = "2018"

如果有一个 src/main.rs 文件,你基本上是这样说的:

If there's a src/main.rs file, you're basically saying this:

[package]
name = "hallo"
version = "0.1.0"
edition = "2018"

[[bin]]
name = "hallo"
src = "src/main.rs"

如果有 src/lib.rs 文件,您基本上是在说:

If there's a src/lib.rs file, you're basically saying this:

[package]
name = "hallo"
version = "0.1.0"
edition = "2018"

[lib]
name = "hallo"
path = "src/lib.rs"

如果两者都有,您基本上是在说:

If there're both of them, you're basically saying this:

[package]
name = "hallo"
version = "0.1.0"
edition = "2018"

[[bin]]
name = "hallo"
path = "src/main.rs"

[lib]
name = "hallo"
path = "src/lib.rs"

文档

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆