1

I'm creating an application in Rust. The problem is that I cannot import a module inside lib.rs file and I wonder how am I supposed to do that.

My folder structure looks like this:

src/
├─ lib.rs
├─ main.rs
├─ app.rs

Inside main.rs file I use mod lib to use the library's public functions. But inside lib.rs file I would like to get the public methods from app.rs file, but unlike in other files, I cannot because of a compiler error:

file not found for module `app`

help: to create the module `app`, create file "src\lib\app.rs" or "src\lib\app\mod.rs"rustc(E0583)

Strangely enough, when I move the app.rs file to newly created lib/app.rs, the compiler would like to find the file in the previous location, which is src/app.rs, nor src/lib/app.rs. It gives me a headache.

Thank you for your answers.

Cholewka
  • 775
  • 1
  • 8
  • 25
  • Having both `lib.rs` and `main.rs` in the same project has some very specific implications and is generally not advised. Here is more information on what is happening and how it can be avoided: https://stackoverflow.com/questions/57756927/rust-modules-confusion-when-there-is-main-rs-and-lib-rs – jdno Sep 04 '21 at 10:40

1 Answers1

4

Do not write mod lib;, with that name in particular. While this is technically valid code, it results in your code being compiled twice, under different configurations:

  • cargo sees lib.rs, and tells rustc to compile a library with that as the “crate root”.
    • Under this condition, mod app; looks for a sibling file and succeeds.
  • cargo sees main.rs, and tells rustc to compile a binary with that as the crate root.
    • rustc reads main.rs and sees mod lib;, so it compiles lib.rs again as a module inside of the binary.
    • Then, submodules of modules are expected to be in subdirectories, which is why it's asking for src/lib/app.rs.

If you are intending to define a library crate (which can be depended on by other packages, or your own integration tests and examples separate from main), then instead of mod lib;, just write paths referring to the library: use foo::app::some_fn_in_app_rs;, where foo is whatever name is specified in your Cargo.toml's [package] section, because that's the name of the library. The library is automatically made available to the binary.

On the other hand, if you don't have any need for a library, then you can just declare modules starting from main. In that case, don't name any of the modules lib. Any name that's not lib or main is fine.

In either case, you can always move the code around later if your needs change. The only thing that is problematic is when you name a module one of the filenames that means something specific to Cargo.

Kevin Reid
  • 37,492
  • 13
  • 80
  • 108