176

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.

Shepmaster
  • 326,504
  • 69
  • 892
  • 1,159
RallionRl
  • 1,953
  • 2
  • 9
  • 9
  • 2
    Highly relevant: [Rust package with both a library and a binary?](http://stackoverflow.com/q/26946646/155423). – Shepmaster Apr 13 '16 at 17:18
  • In complement of [Dognert's](http://stackoverflow.com/questions/36604010/how-can-i-build-multiple-binaries-with-cargo/36604610#36604610) answer, they answer all the questions I got. Thank you a lot! – RallionRl Apr 13 '16 at 17:45

3 Answers3

234

You can specify multiple binaries using [[bin]], as mentioned here:

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

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

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.

Dogbert
  • 200,802
  • 40
  • 378
  • 386
  • I have looked at the documentation Cargo, but I can not see anything, you can specify the output to store the binary ? for example pathTo: "/some/path" I'm sorry for my English. – Angel Angel Apr 14 '16 at 11:05
  • if you think it is better to create a question about this, I can do it without any problem, it might be easier to find others with the same question ? – Angel Angel Apr 14 '16 at 11:12
  • @AngelAngel you want to customize the output path? By default it'll be stored in `target/debug/$name` where `$name` is the `name` you specify in Cargo.toml. – Dogbert Apr 14 '16 at 11:48
  • 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. – Angel Angel Apr 14 '16 at 12:01
  • @AngelAngel I think you're looking for the `cargo install` command. Try reading the output of `cargo help install`. – Dogbert Apr 14 '16 at 12:09
  • 1
    This doesn't work if one of the `[[bin]]`s uses `required-features`. For that it seems like `cargo workspace` is the only solution? – Alex Moore-Niemi Jul 14 '21 at 14:37
54

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"]
Shepmaster
  • 326,504
  • 69
  • 892
  • 1,159
UltimaWeapon
  • 2,033
  • 16
  • 19
  • 2
    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}}` – Kenny Bambridge May 03 '20 at 20:08
  • @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. – UltimaWeapon Jun 22 '20 at 14:57
  • @KennyBambridge You do have to add crates in other workspaces as dependencies in the Cargo.toml where you want to use them. – Caesar Oct 17 '20 at 10:32
  • 1
    I saw filecoin use this code structure: https://github.com/filecoin-project/rust-fil-proofs – Eric Jun 20 '21 at 06:45
  • I got it working, but I ended up referring to different Workspace docs, i.e. the one in the Rust book: https://doc.rust-lang.org/book/ch14-03-cargo-workspaces.html – rv.kvetch Feb 17 '22 at 22:55
2

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.