Crate Universe

Experimental!

Note: crate_universe is experimental, and may have breaking API changes at any time. These instructions may also change without notice.

What is it?

Crate Universe is akin to a modified version of cargo-raze that can be run as part of a Bazel build. Instead of generating BUILD files in advance with cargo-raze, the BUILD files can be created automatically at build time. It can expose crates gathered from Cargo.toml files like cargo-raze does, and also supports declaring crates directly in BUILD files, for cases where compatibility with Cargo is not required.

Workspace installation

To avoid having to build a Rust binary, pre-made releases are made available.

  1. Find the most up-to-date crate_universe release at https://github.com/bazelbuild/rules_rust/releases.
  2. Copy and paste the text into a file like crate_universe_defaults.bzl in your repo.
  3. Add something like the following to your WORKSPACE.bazel file:
load("//3rdparty/rules_rust:crate_universe_defaults.bzl", "DEFAULT_URL_TEMPLATE", "DEFAULT_SHA256_CHECKSUMS")

load("@rules_rust//crate_universe:defs.bzl", "crate", "crate_universe")

crate_universe(
    name = "crates",
    cargo_toml_files = [
        "//some_crate:Cargo.toml",
        "//some_other:Cargo.toml",
    ],
    resolver_download_url_template = DEFAULT_URL_TEMPLATE,
    resolver_sha256s = DEFAULT_SHA256_CHECKSUMS,
    # leave unset for default multi-platform support
    supported_targets = [
        "x86_64-apple-darwin",
        "x86_64-unknown-linux-gnu",
    ],
    # [package.metadata.raze.xxx] lines in Cargo.toml files are ignored;
    # the overrides need to be declared in the repo rule instead.
    overrides = {
        "example-sys": crate.override(
            extra_build_script_env_vars = {"PATH": "/usr/bin"},
        ),
    },
    # to use a lockfile, uncomment the following line,
    # create an empty file in the location, and then build
    # with REPIN=1 bazel build ...
    #lockfile = "//:crate_universe.lock",
)

load("@crates//:defs.bzl", "pinned_rust_install")

pinned_rust_install()

In the above example, two separate Cargo.toml files have been provided. Multiple Cargo.toml can be provided, and crate_universe will combine them together to ensure each crate uses a common version.

This is similar to a Cargo workspace, and can be used with an existing workspace. But some things to note:

  • the top level workspace Cargo.toml, if one exists, should not be included in cargo_toml_files, as it does not list any dependencies by itself
  • presently any existing Cargo.lock file is ignored, as crate_universe does its own resolution and locking. You can uncomment the lockfile line above to enable a separate lockfile for crate_universe; if left disabled, versions will float, like if you were to remove the Cargo.lock file each time you updated a Cargo.toml file in a Cargo workspace. Currently the lockfile is in a custom format; in the future, the Cargo.lock file may be used instead.

Build file usage

With the crates declared in the workspace, they can now be referenced in BUILD files. For example:

load("@crates//:defs.bzl", "build_crates_from", "crates_from")

cargo_build_script(
    name = "build",
    srcs = ["build.rs"],
    deps = build_crates_from("//some_crate:Cargo.toml"),
)

rust_library(
    name = "some_crate",
    srcs = [
        "lib.rs",
    ],
    deps = crates_from("//some_crate:Cargo.toml") + [":build"]
)

If you prefer, you can also list out each crate individually, eg:

load("@crates//:defs.bzl", "crate")

rust_library(
    name = "some_crate",
    srcs = [
        "lib.rs",
    ],
    deps = [crate("serde"), crate("log"), ":build"]
)

See some more examples and the documentation below for more info.

crate_universe

A rule for downloading Rust dependencies (crates).

WARNING: This rule experimental and subject to change without warning.

Environment Variables:

  • REPIN: Re-pin the lockfile if set (useful for repinning deps from multiple rulesets).
  • RULES_RUST_REPIN: Re-pin the lockfile if set (useful for only repinning Rust deps).
  • RULES_RUST_CRATE_UNIVERSE_RESOLVER_URL_OVERRIDE: Override URL to use to download resolver binary
    • for local paths use a file:// URL.
  • RULES_RUST_CRATE_UNIVERSE_RESOLVER_URL_OVERRIDE_SHA256: An optional sha256 value for the binary at the override url location.

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this repository.Namerequired
cargo_toml_filesA list of Cargo manifests (Cargo.toml files).List of labelsoptional[]
crate_registry_templateA template for where to download crates from for the default crate registry. This must contain {version} and {crate} templates.Stringoptionalhttps://crates.io/api/v1/crates/{crate}/{version}/download
iso_dateThe iso_date of cargo binary the resolver should use. Note: This can only be set if version is beta or nightlyStringoptional""
lockfileThe path to a file which stores pinned information about the generated dependency graph. this target must be a file and will be updated by the repository rule when the REPIN environment variable is set. If this is not set, dependencies will be re-resolved more often, setting this allows caching resolves, but will error if the cache is stale.LabeloptionalNone
overridesMapping of crate name to specification overrides. See crate.override for more details.Dictionary: String -> Stringoptional{}
packagesA list of crate specifications. See crate.spec for more details.List of stringsoptional[]
repo_mappingA dictionary from local repository name to global repository name. This allows controls over workspace dependency resolution for dependencies of this repository.<p>For example, an entry “@foo”: “@bar” declares that, for any time this repository depends on @foo (such as a dependency on @foo//some:target, it should actually resolve that dependency within globally-declared @bar (@bar//some:target).Dictionary: String -> Stringrequired
resolverThe label of a crate_universe resolver. Resolvers can be built using cargo_bootstrap_repository but if possible, it's recommended to stick with downloading a resoler via resolver_download_url_template.LabeloptionalNone
resolver_download_url_templateURL template from which to download the resolver binary. {host_triple} and {extension} will be filled in according to the host platform.Stringoptional“{host_triple}{extension}”
resolver_sha256sDictionary of host_triple -> sha256 for resolver binary.Dictionary: String -> Stringoptional{“aarch64-apple-darwin”: “{aarch64-apple-darwin--sha256}”, “aarch64-unknown-linux-gnu”: “{aarch64-unknown-linux-gnu--sha256}”, “x86_64-apple-darwin”: “{x86_64-apple-darwin--sha256}”, “x86_64-pc-windows-gnu”: “{x86_64-pc-windows-gnu--sha256}”, “x86_64-unknown-linux-gnu”: “{x86_64-unknown-linux-gnu--sha256}”}
rust_toolchain_repository_templateThe template to use for finding the host rust_toolchain repository. {version} (eg. ‘1.53.0’), {triple} (eg. ‘x86_64-unknown-linux-gnu’), {system} (eg. ‘darwin’), and {arch} (eg. ‘aarch64’) will be replaced in the string if present.Stringoptional“rust_{system}_{arch}”
sha256sThe sha256 checksum of the desired rust artifactsDictionary: String -> Stringoptional{}
supported_targetsA list of supported platform triples to consider when resoliving dependencies.List of stringsoptional[“aarch64-apple-darwin”, “aarch64-unknown-linux-gnu”, “x86_64-apple-darwin”, “x86_64-pc-windows-msvc”, “x86_64-unknown-freebsd”, “x86_64-unknown-linux-gnu”]
versionThe version of cargo the resolver should useStringoptional“1.54.0”

crate.spec

A simple crate definition for use in the crate_universe rule.

WARNING: This rule experimental and subject to change without warning.

Example:

load("@rules_rust//crate_universe:defs.bzl", "crate_universe", "crate")

crate_universe(
    name = "spec_example",
    packages = [
        crate.spec(
            name = "lazy_static",
            semver = "=1.4",
        ),
    ],
)

PARAMETERS

NameDescriptionDefault Value
nameThe name of the crate as it would appear in a crate registry.none
semverThe desired version (semver) of the cratenone
featuresA list of desired features.None

crate.override

A map of overrides for a particular crate

WARNING: This rule experimental and subject to change without warning.

Example:

load("@rules_rust//crate_universe:defs.bzl", "crate_universe", "crate")

crate_universe(
    name = "override_example",
    # [...]
    overrides = {
        "tokio": crate.override(
            extra_rustc_env_vars = {
                "MY_ENV_VAR": "MY_ENV_VALUE",
            },
            extra_build_script_env_vars = {
                "MY_BUILD_SCRIPT_ENV_VAR": "MY_ENV_VALUE",
            },
            extra_bazel_deps = {
                # Extra dependencies are per target. They are additive.
                "cfg(unix)": ["@somerepo//:foo"],  # cfg() predicate.
                "x86_64-apple-darwin": ["@somerepo//:bar"],  # Specific triple.
                "cfg(all())": ["@somerepo//:baz"],  # Applies to all targets ("regular dependency").
            },
            extra_build_script_bazel_deps = {
                # Extra dependencies are per target. They are additive.
                "cfg(unix)": ["@buildscriptdep//:foo"],
                "x86_64-apple-darwin": ["@buildscriptdep//:bar"],
                "cfg(all())": ["@buildscriptdep//:baz"],
            },
            extra_bazel_data_deps = {
                # ...
            },
            extra_build_script_bazel_data_deps = {
                # ...
            },
        ),
    },
)

PARAMETERS

NameDescriptionDefault Value
extra_bazel_data_depsTargets to add to the data attribute of the generated target (eg: rust_library.data).None
extra_bazel_depsTargets to add to the deps attribute of the generated target (eg: rust_library.deps).None
extra_build_script_bazel_data_depsTargets to add to the data attribute of the generated cargo_build_script target.None
extra_build_script_bazel_depsTargets to add to the deps attribute of the generated cargo_build_script target.None
extra_build_script_env_varsEnvironment variables to add to the build_script_env attribute of the generated cargo_build_script target.None
extra_rustc_env_varsEnvironment variables to add to the rustc_env attribute for the generated target (eg: rust_library.rustc_env).None
features_to_removeA list of features to remove from a generated target.[]