279

I'd like to make a project with a daemon and a client, connecting through a unix socket.

A client and a daemon requires two binaries, so how do I tell Cargo to build two targets from two different sources?

To add a bit of fantasy, I'd like to have a library for the main part of the daemon, and just have a binary to wrap around it and communicate through sockets.

So, we have this kind of tree architecture:

├── Cargo.toml
├── target
|   └── debug
|       ├── daemon
│       └── client
└── src
    ├── daemon
    │   ├── bin
    │   │   └── main.rs
    │   └── lib
    │       └── lib.rs
    └── client
        └── bin
            └── main.rs

I could make one executable which manages both concerns, but that's not what I want to do, unless it's very good practice.

3

3 Answers 3

385

You can specify multiple binaries using [[bin]], as mentioned in the Cargo Book

[[bin]]
name = "daemon"
path = "src/daemon/bin/main.rs"

[[bin]]
name = "client"
path = "src/client/bin/main.rs"

You can run individual binaries with the cargo run command with the --bin <bin-name> option.

Tip: If you instead put these files in src/bin/daemon.rs and src/bin/client.rs, you'll get two executables named daemon and client as Cargo compiles all files in src/bin into executables with the same name automatically. You need to specify names and paths like in the snippet above only if you don't follow this convention.

Sign up to request clarification or add additional context in comments.

10 Comments

I just wondered if you could say where to install a copy of the binary elsewhere other than the default. A copy in $name and another copy in another path. Not that it is trivial, just curious, thanks for your time.
This doesn't work if one of the [[bin]]s uses required-features. For that it seems like cargo workspace is the only solution?
How do you specify the default binary? ie say client should be default
It is worth noting that the line 'default-run = "a"' can be added under package in Cargo.toml to specify a default to run when using the form described in this answer.
@Dogbert can these have different dependencies? I'd like to not include all deps of all bins into all bins
|
100

Another way is to use the workspace feature. This will provide more flexibility due to the fact that we can have more than one library. Example project structure:

.
├── Cargo.toml
├── cli
│   ├── Cargo.toml
│   └── src
│       └── main.rs
├── core
│   ├── Cargo.toml
│   └── src
│       └── lib.rs
├── daemon
│   ├── Cargo.toml
│   └── src
│       └── main.rs
├── gui
│   ├── Cargo.toml
│   └── src
│       └── main.rs
└── rpc
    ├── Cargo.toml
    └── src
        └── lib.rs

Contents of the root Cargo.toml:

[workspace]
members = ["cli", "core", "daemon", "gui", "rpc"]

6 Comments

I could not get this to work. I had to move the binary rust source in the src/ folder and specify another target in [[bin]]. Could you give more details about what you did to get this to work? I was getting the following error: use ::engine::RuleEngine; could not find engine in {{root}}
@KennyBambridge I have not worked on Rust for awhile. IIRC when I have created this answer I tried on my local machine and it work as intended.
@KennyBambridge You do have to add crates in other workspaces as dependencies in the Cargo.toml where you want to use them.
I saw filecoin use this code structure: github.com/filecoin-project/rust-fil-proofs
I got it working, but I ended up referring to different Workspace docs, i.e. the one in the Rust book: doc.rust-lang.org/book/ch14-03-cargo-workspaces.html
|
7

Another format could be to replicate what the Crates.io source code has done, if you have a massive project, something like:

Main Library in src, with a Bin folder with your executables. Then make calls to your main library crate from your executables.

That way you library is centralized so easier to find things as it's cached.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.