外部工具
Cargo 的目标之一是与第三方工具(如 IDE 和其他构建系统)简单集成。为了简化集成,Cargo 提供了几种工具
-
cargo metadata
命令,以 JSON 格式输出包结构和依赖项信息, -
--message-format
标志,输出有关特定构建的信息,以及 -
对自定义子命令的支持。
有关包结构的信息
您可以使用 cargo metadata
命令获取有关包结构和依赖项的信息。有关输出格式的详细信息,请参阅 cargo metadata
文档。
该格式是稳定的并进行版本控制。调用 cargo metadata
时,您应该显式传递 --format-version
标志,以避免向前不兼容的风险。
如果您使用的是 Rust,则可以使用 cargo_metadata 包来解析输出。
JSON 消息
传递 --message-format=json
时,Cargo 将在构建期间输出以下信息
-
编译器错误和警告,
-
生成的工件,
-
构建脚本的结果(例如,原生依赖项)。
输出以每行一个 JSON 对象的格式发送到标准输出。reason
字段区分不同类型的消息。package_id
字段是用于引用包的唯一标识符,并且作为许多命令的 --package
参数。语法规则可以在 包 ID 规范 章节中找到。
--message-format
选项还可以采用其他格式值,这些值会改变 JSON 消息的计算和呈现方式。有关更多详细信息,请参阅 构建命令文档 中对 --message-format
选项的描述。
如果您使用的是 Rust,则可以使用 cargo_metadata 包来解析这些消息。
编译器消息
“compiler-message”消息包含来自编译器的输出,例如警告和错误。有关 rustc
消息格式的详细信息,请参阅 rustc JSON 章节,该格式嵌入在以下结构中
{
/* The "reason" indicates the kind of message. */
"reason": "compiler-message",
/* The Package ID, a unique identifier for referring to the package. */
"package_id": "file:///path/to/my-package#0.1.0",
/* Absolute path to the package manifest. */
"manifest_path": "/path/to/my-package/Cargo.toml",
/* The Cargo target (lib, bin, example, etc.) that generated the message. */
"target": {
/* Array of target kinds.
- lib targets list the `crate-type` values from the
manifest such as "lib", "rlib", "dylib",
"proc-macro", etc. (default ["lib"])
- binary is ["bin"]
- example is ["example"]
- integration test is ["test"]
- benchmark is ["bench"]
- build script is ["custom-build"]
*/
"kind": [
"lib"
],
/* Array of crate types.
- lib and example libraries list the `crate-type` values
from the manifest such as "lib", "rlib", "dylib",
"proc-macro", etc. (default ["lib"])
- all other target kinds are ["bin"]
*/
"crate_types": [
"lib"
],
/* The name of the target. */
"name": "my-package",
/* Absolute path to the root source file of the target. */
"src_path": "/path/to/my-package/src/lib.rs",
/* The Rust edition of the target.
Defaults to the package edition.
*/
"edition": "2018",
/* Array of required features.
This property is not included if no required features are set.
*/
"required-features": ["feat1"],
/* Whether the target should be documented by `cargo doc`. */
"doc": true,
/* Whether or not this target has doc tests enabled, and
the target is compatible with doc testing.
*/
"doctest": true
/* Whether or not this target should be built and run with `--test`
*/
"test": true
},
/* The message emitted by the compiler.
See https://doc.rust-lang.net.cn/rustc/json.html for details.
*/
"message": {
/* ... */
}
}
工件消息
对于每个编译步骤,都会发出带有以下结构的“compiler-artifact”消息
{
/* The "reason" indicates the kind of message. */
"reason": "compiler-artifact",
/* The Package ID, a unique identifier for referring to the package. */
"package_id": "file:///path/to/my-package#0.1.0",
/* Absolute path to the package manifest. */
"manifest_path": "/path/to/my-package/Cargo.toml",
/* The Cargo target (lib, bin, example, etc.) that generated the artifacts.
See the definition above for `compiler-message` for details.
*/
"target": {
"kind": [
"lib"
],
"crate_types": [
"lib"
],
"name": "my-package",
"src_path": "/path/to/my-package/src/lib.rs",
"edition": "2018",
"doc": true,
"doctest": true,
"test": true
},
/* The profile indicates which compiler settings were used. */
"profile": {
/* The optimization level. */
"opt_level": "0",
/* The debug level, an integer of 0, 1, or 2, or a string
"line-directives-only" or "line-tables-only". If `null`, it implies
rustc's default of 0.
*/
"debuginfo": 2,
/* Whether or not debug assertions are enabled. */
"debug_assertions": true,
/* Whether or not overflow checks are enabled. */
"overflow_checks": true,
/* Whether or not the `--test` flag is used. */
"test": false
},
/* Array of features enabled. */
"features": ["feat1", "feat2"],
/* Array of files generated by this step. */
"filenames": [
"/path/to/my-package/target/debug/libmy_package.rlib",
"/path/to/my-package/target/debug/deps/libmy_package-be9f3faac0a26ef0.rmeta"
],
/* A string of the path to the executable that was created, or null if
this step did not generate an executable.
*/
"executable": null,
/* Whether or not this step was actually executed.
When `true`, this means that the pre-existing artifacts were
up-to-date, and `rustc` was not executed. When `false`, this means that
`rustc` was run to generate the artifacts.
*/
"fresh": true
}
构建脚本输出
“build-script-executed”消息包含构建脚本的解析输出。请注意,即使未运行构建脚本,也会发出此消息;它将显示先前缓存的值。有关构建脚本输出的更多详细信息,请参见 关于构建脚本的章节。
{
/* The "reason" indicates the kind of message. */
"reason": "build-script-executed",
/* The Package ID, a unique identifier for referring to the package. */
"package_id": "file:///path/to/my-package#0.1.0",
/* Array of libraries to link, as indicated by the `cargo::rustc-link-lib`
instruction. Note that this may include a "KIND=" prefix in the string
where KIND is the library kind.
*/
"linked_libs": ["foo", "static=bar"],
/* Array of paths to include in the library search path, as indicated by
the `cargo::rustc-link-search` instruction. Note that this may include a
"KIND=" prefix in the string where KIND is the library kind.
*/
"linked_paths": ["/some/path", "native=/another/path"],
/* Array of cfg values to enable, as indicated by the `cargo::rustc-cfg`
instruction.
*/
"cfgs": ["cfg1", "cfg2=\"string\""],
/* Array of [KEY, VALUE] arrays of environment variables to set, as
indicated by the `cargo::rustc-env` instruction.
*/
"env": [
["SOME_KEY", "some value"],
["ANOTHER_KEY", "another value"]
],
/* An absolute path which is used as a value of `OUT_DIR` environmental
variable when compiling current package.
*/
"out_dir": "/some/path/in/target/dir"
}
构建完成
“build-finished”消息在构建结束时发出。
{
/* The "reason" indicates the kind of message. */
"reason": "build-finished",
/* Whether or not the build finished successfully. */
"success": true,
}
此消息有助于工具了解何时停止读取 JSON 消息。诸如 cargo test
或 cargo run
之类的命令可以在构建完成后产生额外的输出。此消息让工具知道 Cargo 将不会产生额外的 JSON 消息,但之后可能会生成其他输出(例如由 cargo run
执行的程序生成的输出)。
注意:对于测试,实验性的仅限 nightly 版本的 JSON 输出支持,因此如果启用了该功能,则在“build-finished”消息之后可能会开始接收其他特定于测试的 JSON 消息。
自定义子命令
Cargo 旨在通过新的子命令进行扩展,而无需修改 Cargo 本身。这是通过将形式为 cargo (?<command>[^ ]+)
的 cargo 调用转换为对外部工具 cargo-${command}
的调用来实现的。外部工具必须存在于用户的 $PATH
目录之一中。
**注意**:默认情况下,Cargo 优先考虑
$CARGO_HOME/bin
中的外部工具,而不是$PATH
。用户可以通过将$CARGO_HOME/bin
添加到$PATH
来覆盖此优先级。
当 Cargo 调用自定义子命令时,子命令的第一个参数将像往常一样是自定义子命令的文件名。第二个参数将是子命令名称本身。例如,调用 cargo-${command}
时,第二个参数将是 ${command}
。命令行上的任何其他参数都将不加更改地转发。
Cargo 还可以使用 cargo help ${command}
显示自定义子命令的帮助输出。如果子命令的第三个参数是 --help
,Cargo 假定该子命令将打印帮助消息。因此,cargo help ${command}
将调用 cargo-${command} ${command} --help
。
自定义子命令可以使用 CARGO
环境变量回调 Cargo。或者,它可以链接到 cargo
包作为库,但是这种方法有缺点
- Cargo 作为库是不稳定的:API 可能会在没有弃用警告的情况下更改
- 链接的 Cargo 库的版本可能与 Cargo 二进制文件不同
相反,鼓励使用 CLI 接口来驱动 Cargo。cargo metadata
命令可用于获取有关当前项目的信息(cargo_metadata
包为此命令提供了 Rust 接口)。