ruststructuredirectory-structurerust-crates

Why should/shoudn't I use lib.rs in binary crates?


When I search the internet for design examples how to structure my code, I frequently find setups with main.rs only containing the main function and usages of lib, while lib.rs contains all the actual code and mods.

There are also cases where there is just main.rs without lib.rs, but I found enough main+lib examples that I never really thought about this point and just always created a lib.rs for binary crates. Now I stumbled upon the issue that I was refactoring my code, but many of my functions and structs are pub* and I don't get unused-warnings for them because of that.

I see the point of using main+lib when I want to build a library and add a binary to try if it is working. I also see the point of it when I have multiple binaries that share same lib code. However, most of these examples contained just one lib and one main and were meant to be executables. So, both points don't apply.

Is it a best practice to usually create lib.rs in binary crates? What are the pros and cons?


*many functions are pub: I am aware that in this setup I should only expose things that are necessary for the main (or for public API), but my main was too large. Hence the refactoring. Also, I could search and replace all pub with pub(crate), then make everything pub again what the new main really needs and now I would get unused warnings for everything else again. But this is an active step I need to remember to do every now and then, while the compiler would remind me automatically.


Solution

  • The most important distinction between having a lib.rs + main.rs, rather than just main.rs, is that in the former case, you are producing two targets, a library, and an executable, whereas in the latter you just have an executable. So, basically, the question is why would you move part of your code into a library rather than have it all in an executable.

    Here is a list of reasons I could think of. Note that I can't think of a single reason not to do so, except if you are writing a super small application, and none of these reasons outweigh the cost of having one additional file.

    My personal feeling about this is that I don't have the same mindset when writing an executable, or a library, and I tend to accumulate less technical debt when writing a library, because it forces me to think about all possible use cases of the interface I offer, which is more general than that of the executable. Hence, I usually write better code if it's a library.