ChatGPT解决这个技术问题 Extra ChatGPT

How can I build multiple binaries with Cargo?

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.

In complement of Dognert's answer, they answer all the questions I got. Thank you a lot!

D
Dogbert

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.


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.
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 ?
@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.
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?
S
Shepmaster

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"]

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
R
Robust Systems 8472-1488

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.