Main.rs and lib.rs at same level

Hi all,

I am new to Rust and trying to understand the Rust module system.
I am following up with chapter Rust book (building command-line app) and based on that I am building one small project.

When main.rs and lib.rs are in the same directory src/ then I can not import any module in lib.rs in a similar way I am able to do inside main.rs, lib.rs expects modules to be in the lib folder and I am not able to figure out why.

Below is the link to my project lib-use branch with lib.rs the code works properly without lib.rs, checkout master branch master branch

2 Likes

When creating a project with a lib.rs and a main.rs, you should not declare lib as a module in your main.rs file.

You should instead just call feline::start() in your main function:

fn main(){
    feline::start();
}

This is demonstrated in Listing 12-14 of the book - note that the main.rs does not declare any modules with mod, it only imports them with use (the distinction between the two is something a lot of new Rust programmers struggle with!).

The reason for this is that, in projects with both a lib.rs and a main.rs, Cargo effectively treats lib.rs as the root of your crate, and main.rs as a seperate binary that depends on your crate.

10 Likes

Yeh.. it works, Do you mind to explain what exactly happens when I write mod lib; in main.rs and call lib::start() because error appears in lib.rs at line mod internal and mod cli

I mean does writing mod lib make main.rs a root.

No, main.rs is always the root of your binary, and lib.rs is always the root of your library.

The important things to realize are:

  • These two roots are compiled seperately, and have their own entirely seperate module structure.
  • When you use the mod keyword, you are creating a module, not importing a module.
    • You almost never want to have multiple mod statements for a single file, as you'll be duplicating the content.
    • If you want to use something from an existing module or from a library, that's what the use keyword is for.

Let's walk through your example:

In lib.rs, you use mod to declare that your library has two top level modules, cli and internal. There are corresponding files in the right place in your project, so Cargo knows how to link it all up. This part is fine, and what you intended to happen!

However, when you write mod lib in your main.rs, you're not importing your library! You're actually declaring that your binary has it's own top level module, which just happens to be called lib. Cargo then sees that there is a file called lib.rs in the folder, and links that in, even though that's not what you intended. It then sees that the lib.rs file has two mod statements and treats these as submodules of the binary's lib module. The files aren't in the right place for that to work, so compilation fails.

So the root cause of your issue is that you've effectively told the compiler to create your module structure twice, once in your library and once in your binary. You really only meant to define these modules in your library, and then use them into your binary.

9 Likes

This line is so perfect, I get it now. thanks

3 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.