main.rs
is only used by binary targets, i.e. when you want to compile a crate to an executable program. The main.rs
file also needs to define a main
function.
lib.rs
is used by library targets, i.e. you want your crate to be imported by other code.
You can only compile one of the two targets at once, however you can have one crate which you can both compile to a binary and export as a library (by just defining both [lib]
and [[bin]]
sections in your crate's Cargo.toml
).
Depending on which target you compile to, either the main.rs
(binary) or the lib.rs
(library) file will define the crate
module in your code, which is the module that contains all other modules. But they both work the same way, as ordinary modules.
Then, as you said, you can define modules in your crate root module (crate
). You can put all modules into one file, but of course that will get cluttered quickly. that is why you can move each module into its own .rs
file, or into its own directory in the src
file. Then you just need to declare the modules in the root module:
// lib.rs
pub mod m1;
pub mod m2;
and define the modules seperately:
src
├── lib.rs
├── m1.rs
└── m2.rs
Rust will compile m1
and m2
and you can reference them in your code by crate::m1
for instance.
Now if you also have nested modules in m1
for example, you can define m1
in a directory with a mod.rs
file in it:
src
├── lib.rs
├── m1
│ ├── mod.rs
│ └── m1_1.rs
└── m2.rs
where m1/mod.rs
looks like this:
pub mod m1_1;
and m1/m1_1.rs
can contain the code that should go into module crate::m1::m1_1
.
I made all modules public here, but you can of course also declare private modules by omitting the pub
.