I do this with cargo workspaces. You can have the shared functionality in a library with optional features, and then each binary has its own cargo manifest and uses the main library as a dependency.
Individual binaries in one package can also have a required-features setting. However, to my knowledge you have to explicitly enable them. (I.e. cargo run --bin=name doesn't enable the features automatically, but rather spits out a compilation error telling you to enable them). Individual crates in a workspace is more powerful.