如何使用Cargo构建多个二进制文件?

241

我想用一个 daemon 和一个 client项目,并通过Unix套接字进行连接。

一个 client和一个daemon需要两个二进制文件,那么如何告诉Cargo从两个不同的源构建两个目标?

为了增加一点幻想,我希望为daemon的主要部分添加一个library ,并只有一个二进制包装器通过套接字进行通信。

因此,我们拥有这种树形结构:

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

我可以制作一个可执行文件来管理这两个问题,但这不是我想做的,除非这是非常好的实践。


4
非常相关:同时包含库和可执行文件的Rust包? - Shepmaster
在补充Dognert的回答中,他们回答了我所有的问题。非常感谢! - RallionRl
这似乎是相关问题:https://github.com/rust-lang/cargo/issues/8294 - Bryan Larsen
3个回答

333

您可以使用[[bin]]指定多个二进制文件,如此处所述:

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

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

提示:如果您将这些文件放在src/bin/daemon.rssrc/bin/client.rs中,Cargo会自动将src/bin中的所有文件编译成相同名称的可执行文件daemonclient。只有当您不遵循此约定时,才需要像上面片段中那样指定名称和路径。


@AngelAngel,你想自定义输出路径吗?默认情况下,它将存储在 target/debug/$name 中,其中 $name 是您在 Cargo.toml 中指定的 name - Dogbert
我只是想知道您是否可以告诉我在默认位置以外的其他地方安装二进制文件的方法。例如,在 $name 中安装一份副本,另外在另一个路径中安装一份副本。虽然这并不容易,但我只是好奇。感谢您的时间。 - Angel Angel
@AngelAngel 我认为你正在寻找 cargo install 命令。尝试阅读 cargo help install 的输出。 - Dogbert
1
如果其中一个 [[bin]] 使用了 required-features,那么这种方法就行不通了。看起来只有使用 cargo workspace 才是唯一的解决方案? - Alex Moore-Niemi
值得注意的是,在Cargo.toml文件中的package下可以添加一行'default-run = "a"',以指定在使用本答案描述的形式时要运行的默认程序。 - Cameron
显示剩余5条评论

81

另一种方法是使用工作区特性。这将提供更大的灵活性,因为我们可以拥有多个库。示例项目结构:

.
├── 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

根目录下的 Cargo.toml 文件内容:

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

3
我无法使它工作。我不得不将二进制rust源文件移动到src/文件夹中,并在[[bin]]中指定另一个目标。您能否详细说明一下您是如何解决这个问题的?我遇到了以下错误:use ::engine::RuleEngine; could not find engine in {{root}} - Kenny Bambridge
@KennyBambridge,我有一段时间没有使用Rust了。如果我没记错的话,在我创建这个答案时,我尝试在我的本地机器上运行它,结果它按预期工作。 - UltimaWeapon
@KennyBambridge 在其他工作区中,您必须将箱子添加为Cargo.toml中要使用它们的依赖项。 - Caesar
1
我看到Filecoin使用了这个代码结构:https://github.com/filecoin-project/rust-fil-proofs - Eric
我已经让它工作了,但最终我参考了不同的 Workspace 文档,即 Rust 书中的文档:https://doc.rust-lang.org/book/ch14-03-cargo-workspaces.html - rv.kvetch
这是一个这种方法的示例:https://github.com/JohnScience/two-bins-wp-example然而,功能统一可能会引起麻烦。 - undefined

3
另一种格式可以复制 Crates.io源代码所做的内容,如果您有一个庞大的项目,可以像这样做:
在src中设置主库,并在Bin文件夹中设置可执行文件。 然后从您的可执行文件中调用主库crate。
这样,您的库就可以集中管理,更容易找到并缓存。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接