I have 4 files:
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();
}
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
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?
Edit: 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?
My Cargo.toml:
[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]
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.
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!
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`
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);
}
Same question, do you see anything in the Cargo.toml file about a binary or a library? No.
This package contains two things:
src/main.rs, entry point src/main.rs::main),src/lib.rs, shared code).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 refers to src/lib.rs, because we're in the context of our library here.
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.
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();
}
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();
}
Here we just declared another module (utils) and we're using it.
Cargo.toml content:
[package]
name = "hallo"
version = "0.1.0"
edition = "2018"
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"
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"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With