Organizing code in binary crates
Within a binary crate, here's the organization that's recommended.
my-app/src/command.rs
:
#![allow(unused)] fn main() { //! Contains command parsers and logic. use clap::Parser; #[derive(Debug, Parser)] pub struct MyApp { // Options, subcommands etc #[clap(short, long, default_value_t)] my_arg: usize, } impl MyApp { pub fn exec(self) -> color_eyre::Result<()> { println!("The value of my-arg is {}", self.my_arg); Ok(()) } } }
my-app/src/lib.rs
:
#![allow(unused)] fn main() { //! Help text for my-app. //! //! Can contain information about what the binary does, command-line options, //! configuration, etc. mod command; // ... other modules // This is the only export from the crate. It is marked hidden and // is not part of the public API. #[doc(hidden)] pub use command::MyApp; }
my-app/src/bin/my-app.rs
:
use clap::Parser; use my_app::MyApp; fn main() -> color_eyre::Result<()> { color_eyre::install()?; let my_app = MyApp::parse(); my_app.exec() }
Notes:
- Most of the logic is within
command.rs
.- In general, you should keep lib.rs as minimal as possible, unless your entire library fits in it. That's
because all methods and fields in
lib.rs
are visible to the entire library---code in the top-level module cannot be marked private to the rest of the module.
- In general, you should keep lib.rs as minimal as possible, unless your entire library fits in it. That's
because all methods and fields in
- There's a
lib.rs
separate from themy-app.rs
that containsmain
.- There are several advantages to having a
lib.rs
. In particular,rustdoc
doesn't use standard privacy rules if building documentation frommain.rs
, so private modules are visible in the public documentation.
- There are several advantages to having a
- Only the top-level
MyApp
is exported.- The top-level
MyApp
is allmain.rs
should generally need to care about.
- The top-level
MyApp
is marked#[doc(hidden)]
.- The details of
MyApp
are only meant to be seen bymain
. The library is not part of the public API. Only the command-line interface is.
- The details of
src/bin/my-app.rs
instead ofsrc/main.rs
.- While
src/main.rs
works just as well,src/bin
makes it harder to accidentally import library code withmod
statements.
- While