Hello all.
Can anyone help me ?
When I do as follows:
my_project/
src/
bin/
learn_modules.rs
garden.rs
//learn_modules.rs
use std::process::ExitCode;
mod garden;
fn main() -> ExitCode {
println!("{}", garden::LOCATION);
println!("{}", garden::get_m());
return ExitCode::SUCCESS; }
//garden.rs
pub const LOCATION: &str = "Poland";
const M: &str = "garden";
pub fn get_m() -> &'static str { M }
It works 
2).
But when I do:
my_project/
src/
bin/
learn_modules.rs
modules/
garden.rs
//learn_modules.rs
use std::process::ExitCode;
mod garden;
bla bla bla ....
it complains
unresolved module, can't find module file: garden.rs, or garden/mod.rs
file not found for module garden
to create the module garden
, create file "src/bin/garden.rs" or "src/bin/garden/mod.rs"
if there is a mod garden
elsewhere in the crate already, import it with use crate::...
instead
I do not know how to handle my scenario.
Please assist.
by default, module hierachy follows the file system hierachy, i.e. a sub module corresponds to a source file in the subdirectory of the parent module. (special case: lib.rs
, main.rs
and mod.rs
logically resides one level higher than their actual file system location, e.g. foo/bar/mod.rs
is equivalent to foo/bar.rs
).
you can use the #[path="..."]
attribute to specify a source file different than the default, though I would not recommend to use this unless in very niche use cases.
so, the recommended solution is to use a lib
crate, make the garden.rs
a sub module of the lib
crate, and then import the lib
crate in your bin
crate:
// src/lib.rs
pub mod modules {
// corresponds to `src/modules/garden.rs` or `src/modules/garden/mod.rs`
pub mod garden;
}
// src/bin/learn_modules.rs
use my_project::modules::garden;
fn main() {
println!("{}", garden::LOCATION);
}
the alternative solution is to use the #[path]
attribute:
// src/bin/learn_modules.rs
#[path = "../modules/garden.rs"]
mod garden;
fn main() -> ExitCode {
println!("{}", garden::LOCATION);
}
note, when use #[path]
attribute, the module name doesn't need to match the file name, e.g., the following is valid:
#[path="../modules/garden.rs"]
mod lake;
2 Likes
You are right 
Also: best-practices-for-packages-with-a-binary-and-a-library
So I can do:
my_package/
src/
bin/
learn_modules.rs
lib.rs
lib/
garden.rs
// lib.rs
mod lib {
pub mod garden; }
pub use lib::garden; /* --- (1) --- */
//learn_modules.rs
use std::process::ExitCode;
// I do not need to
// use my_package::lib::garden;
// because of public reexport garden module inside lib module
// (see /* --- (1) --- */ above).
// Instead just need to
use my_package::garden;
fn main() -> ExitCode {
println!("{}", garden::LOCATION);
println!("{}", garden::get_m());
return ExitCode::SUCCESS; }
Although the source for a library crate in Rust "starts at" lib.rs
, you're not supposed to or expected to use a lib
namespace. Just put garden.rs
immediately under src/
and change the source of lib.rs
to pub mod garden; pub use garden;
.
you're not supposed to or expected to use a lib
namespace.
Why ? What is rationale for it ?
Can You please elaborate.
Consider the following
src/
alaka.rs
kokona.rs
lib.rs
moweqi.rs
zumua.rs
I simply can not understand which are binary crates, and which files constitute library crate, without looking inside them or to Cargo.toml.
But now I do not even need to think, it is obvious:
src/
bin/
alaka.rs
zumua.rs
lib.rs
lib/
kokona.rs
moweqi.rs
The bin
directory for multiple executables is very standard, that is true. But I would argue that with the bin
directory, lib
becomes unhelpful: you already know all your binaries are in bin
, so everything outside of it must be part of your library.
3 Likes
How about:
my_package/
Cargo.toml
src/
bin/
learn_modules.rs
lib/
lib.rs
garden.rs
# Cargo.toml
[lib]
path = "./src/lib/lib.rs"
// lib.rs
pub mod garden;
//learn_modules.rs
use std::process::ExitCode;
use my_package::garden;
fn main() -> ExitCode {
println!("{}", garden::LOCATION);
println!("{}", garden::get_m());
return ExitCode::SUCCESS; }
I wouldn't say that's necessarily idiomatic, but it's certainly a lot better. I wouldn't have any problems with it, personally.