0

I'm developing a library. For internal development experiments I need a bunch of binary command line entry points that I can execute. I'm using a standard project layout like described in this answer under "Flexible".

What I'd like to achieve: Certain functionality in my command line tools is similar, and I'd like to move that out into its own module. Ideally I'd like to introduce a cli_common.rs module containing some helper functions here in the package structure:

.
├── Cargo.toml
└── src
    ├── bin
    │   ├── cli_common.rs
    │   ├── run_foo.rs (uses cli_common)
    │   └── run_bar.rs (uses cli_common)
    ├── lib.rs
    └── <various-lib-related-sub-modules>

This doesn't seem to be possible, because the compiler expects every module under bin to have a main function.

This suggest that I have to move the functionality of cli_common.rs into the library itself. This doesn't feel great, because it mixes "peripheral" logic with "core" logic, and I'd like to avoid having this functionality as part of the public interface of the library.

Is there a trick to have such a cli_commons.rs without having to move it into the library?

bluenote10
  • 23,414
  • 14
  • 122
  • 178

1 Answers1

0

I found a solution based on this answer.

For simple cases, an extra crate can be avoided by moving the cli_common.rs somewhere, where the compiler doesn't expect a main. In my example I modified the structure for instance to:

.
├── Cargo.toml
└── src
    ├── bin
    │   ├── cli_common.rs
    │   │   └── cli_common.rs
    │   ├── run_foo.rs
    │   └── run_bar.rs
    ├── lib.rs
    └── <various-lib-related-sub-modules>

Within run_foo.rs and run_bar.rs, I can now use mod combined with a #[path] attribute:

#[path="cli_common/cli_common.rs"]
mod cli_common;

For more complex scenarios, going for a separate crate may be preferred.

bluenote10
  • 23,414
  • 14
  • 122
  • 178