$ cargo install --path ~/cargo-gnaw
$ cargo gnaw --manifest-path ~/fuchsia/third_party/rust_crates/Cargo.toml -o ~/fuchsia/third_party/rust_crates/BUILD.gn
Cargo GNaw operates on vendored crates to convert them into GN rules. The resulting BUILD.gn file is expected to be vendored with the crates and provides targets for the GN build system to reference.
All top-level crates are given an easy to use GN alias group that references the version exposed in the Cargo.toml. Direct dependencies of the root crate can be “lifted” to the top-level by skipping the default root crate.
[package] name = "simple" version = "1.0.25" authors = ["Benjamin Brittain <bwb@google.com>"] edition = "2018" [dependencies]
converts to:
group("simple") { deps = [":simple-1-0-25"] } rust_library("simple-1-0-25") { crate_name = "simple" crate_root = "//tools/cargo-gnaw/src/tests/simple/src/lib.rs" output_name = "simple-9ac42213326ac72d" deps = [] rustenv = [] rustflags = ["--cap-lints=allow", "--edition=2018", "-Cmetadata=9ac42213326ac72d", "-Cextra-filename=-9ac42213326ac72d"] }
GNaw intentionally does not handle build.rs scripts at compilation time. Any evaluation of a build.rs script is done when the crate is vendored. The resulting configuration which is usually produced by the build.rs script is put into a section in the source Cargo.toml. Simple build.rs scripts (ones that only depend upon Rust's std
library) evaluate and automatically provide the author with the expected configuration.
The difference between a “package”, “target”, and a “crate” is useful knowledge when working with GNaw:
(Paraphrased from https://doc.rust-lang.org/cargo/reference/cargo-targets.html)
Many Cargo packages only contain a single library target that produces a single library crate. Because of this (and because of the catchiness of the term) “crate” is often used imprecisely to refer to any of those three items depending on the context. However, when packages contain multiple targets, like one or more binaries alongside the library, it becomes important to distinguish between these terms.
Some targets, including but not limited to those that use build.rs scripts, require additional configuration that can be specified in the Cargo.toml file. This configuration is consumed by GNaw, not Cargo, and used when generating GN targets.
Basic configuration for a package's library target is specified as gn.package.<PackageName>.<ExactVersion>
. This configuration will be applied to the GN library target unconditionally (for all platforms) and can include the following arrays:
configs
- native GN configdeps
- native GN dependencyenv_vars
- environment variables, usually used for pretending to be Cargorustflags
- flags to pass through to rustc[gn.package.anyhow."1.0.25"] rustflags = [ "--cfg=backtrace" ]
Configuration can also be applied to only specific platforms, for example only when building for Fuchsia or only when building for a specific host platform.
Platforms are specified in the Rust cfg format (e.g. cfg(unix)
). The same four configuration fields (configs
, deps
, env_vars
, rustflags
) documented above are supported.
[gn.package.foo."1.2.3".platform."cfg(target_os = \"fuchsia\")"] configs = [ "//some:fuchsia_specific_config" ]
GNaw also supports generating GN executable targets for Cargo binary targets. GNaw must be told to generate such targets; none are generated by default.
Platform-independent or -dependent configuration can be specified as well, similar to above. The same four configuration fields (configs
, deps
, env_vars
, rustflags
) documented above are supported.
In the example below, my-gn-name
will become both the name of the group target to depend upon and the executable's output_name, so usages can assume output_name == target_name (and must since get_target_outputs only works within the same file).
This example generates a group target named my-gn-name
and an executable target that produces my-gn-name
from the binary my-cargo-target
target inside package my-cargo-package
version 1.2.3. Also, when building for Unix this example applies an extra GN config.
[gn.package.my-cargo-package."1.2.3".binary.my-cargo-target] output_name = "my-gn-name" rustflags = [ "--cfg=feature" ] [gn.package.my-cargo-package."1.2.3".binary.my-cargo-target.platform."cfg(unix)"] configs = [ "//some:unix_specific_config" ]