No matching package named 'clap' found while building with Yocto – why does cargo build can’t find the crate?

I have a Rust binary that depends on the clap and nix crates.
My Cargo.toml looks like this:

[package]
name = "argumentParser"
version = "0.1.0"
edition = "2024"

[dependencies]
clap    = { version = "4.6.1", features = ["derive"] }
nix     = { version = "0.31.3", features = ["ioctl"] }

When Yocto scarthgap runs cargo build --release I get the following error:

error: no matching package named `clap` found
location searched: registry `crates-io`
required by package `argumentParser v0.1.0 (/mnt/data/poky/build/tmp/work/... )`

The question is why Cargo cannot locate the clap crate and how to make Yocto’s Rust target able to fetch it.

I don't think clap is actually the problem here

for example,if I create a regular rust project with:

[dependencies]
clap = { version = "4.6.1", features = ["derive"] }
nix = { version = "0.31.3", features = ["ioctl"] }

and run:

cargo build --release

on my local machine, Cargo downloads everything from crates.io and builds without any issues

what makes me think this is Yocto-related is the error:

error: no matching package named `clap` found
location searched: registry `crates-io`

I've seen similar errors when Cargo is running in an offline or controlled Yocto environment and BitBake hasn't fetched the crates beforehand.

In that case, the issue isn't that clap doesn't exist, but that Yocto doesn't know where to get it (or one of its transitive dependencies).

A few things I'd check:

Does the project include a Cargo.lock?
Does the recipe inherit cargo?
Are the crate dependencies being imported through crate://, cargo-bitbake, or update_crates?
Is Cargo being forced to build offline?

Could you share the bb recipe? my guess is that the problem is somewhere in the yocto recipe rather than in the Cargo.toml

Project don't include Cargo.lock
I doubt that something forces cargo to be offline
Here is the recipe

SRC_URI = " \
    file://Cargo.toml \
    file://src/main.rs \
"
S = "${WORKDIR}"

inherit cargo

do_install() {
    install -d ${D}${bindir}
    install   -m 0755 ${B}/target/${CARGO_TARGET_SUBDIR}/mcp2515-test-application ${D}${bindir}/${PN}
}
CARGO_BUILD_FLAGS = "--release"
FILES:${PN} = "${bindir}/${PN}"
do_compile[network] = "1"
do_prepare_recipe_sysroot[network] = "1"
DEPENDS += "cargo-native"

Ah, I think I see the issue now
Your recipe is only providing:

SRC_URI = " \
    file://Cargo.toml \
    file://src/main.rs \
"

so Yocto only knows about those two files. It has no information about clap, nix, or any of their dependencies.

One thing that stands out is that the project doesn't have a Cargo.lock. In my experience, that's usually the first thing I'd fix when building rust projects with yocto.

I'd try generating one locally:

cargo generate-lockfile

or simply:

cargo build

and then include it in SRC_URI:

SRC_URI = " \
    file://Cargo.toml \
    file://Cargo.lock \
    file://src/main.rs \
"

At the moment Yocto has no lockfile and no crate metadata, so it doesn't really know what it needs to fetchh
could you try adding a Cargo.lock first and see if the error changes? That would help narrow down whether this is just a dependency-fetching issue or something else in the recipe

I have some experience with rust in yocto, so let's go through the checklist:

  • You use yocto scarthgap. You need to update to release 5.0.18, as there recently was a patch that fixed an API rate limiting issue on crates.io.
  • To be built with yocto, your project should really have a Cargo.lock. It makes it a lot easier to use the next suggestion:
  • Yocto automatically adds the --offline flag to cargo, as Yocto manages the downloads using its own fetcher. For the downloads to work, best also use the cargo-update-recipe-crates class. See its documentation here 5 Classes — The Yocto Project ® 5.0-tip documentation
  • At last: If you are not using the rust-mixin https://git.yoctoproject.org/meta-lts-mixins/log/?h=scarthgap/rust, scarthgap is still on Rust version 1.75, which may be not supported anymore by some newer crates.

Is it using very old Rust maybe? Clap may be invisible to Rust/Cargo older than 1.60 due to registry index format changes.

that's a good catch i hadn't thought about the Cargo version, but an old registry implementation could definitely cause symptoms like this.

I did the following

  • Updated to yocto release 5.0.18
  • Generated cargo lockfile
  • Updated my rust version to 1.86.0 by adding the following in local.conf
RUST_VERSION = "1.86.0"
PREFERRED_VERSION_rust = "1.86.0"
PREFERRED_VERSION_rust-cross = "1.86.0"
PREFERRED_VERSION_rust-native    = "1.86.0"
PREFERRED_VERSION_rust-llvm    = "1.86.0"
PREFERRED_VERSION_rust-llvm-native    = "1.86.0"
PREFERRED_VERSION_rust-cross-canadian    = "1.86.0"
PREFERRED_VERSION_rust-tools-cross-canadian    = "1.86.0"
PREFERRED_VERSION_rust-crosssdk    = "1.86.0"
  • Used cargo-update-recipe-crates class

I am getting a new error

DEBUG: Executing shell function do_compile
COMPILE rust-native build --stage 2
Building bootstrap
running: /mnt/data/poky/build/tmp/work/x86_64-linux/rust-native/1.86.0/rust-snapshot/bin/cargo build --manifest-path /mnt/data/poky/build/tmp/work/x86_64-linux/rust-native/1.86.0/rustc-1.86.0-src/src/bootstrap/Cargo.toml -Zroot-dir=/mnt/data/poky/build/tmp/work/x86_64-linux/rust-native/1.86.0/rustc-1.86.0-src --verbose --frozen
warning: `/mnt/data/poky/build/tmp/work/x86_64-linux/rust-native/1.86.0/cargo_home/config` is deprecated in favor of `config.toml`
note: if you need to support cargo 1.38 or earlier, you can symlink `config` to `config.toml`
warning: `/mnt/data/poky/build/tmp/work/x86_64-linux/rust-native/1.86.0/cargo_home/config` is deprecated in favor of `config.toml`
note: if you need to support cargo 1.38 or earlier, you can symlink `config` to `config.toml`
warning: `/mnt/data/poky/build/tmp/work/x86_64-linux/rust-native/1.86.0/cargo_home/config` is deprecated in favor of `config.toml`
note: if you need to support cargo 1.38 or earlier, you can symlink `config` to `config.toml`
warning: `/mnt/data/poky/build/tmp/work/x86_64-linux/rust-native/1.86.0/cargo_home/config` is deprecated in favor of `config.toml`
note: if you need to support cargo 1.38 or earlier, you can symlink `config` to `config.toml`
error: could not load Cargo configuration

Caused by:
  could not parse TOML configuration in `/mnt/data/poky/build/tmp/work/x86_64-linux/rust-native/1.86.0/cargo_home/config`

Caused by:
  TOML parse error at line 26, column 1
     |
  26 | [target.x86_64-unknown-linux-gnu]
     | ^
  invalid table header
  duplicate key `x86_64-unknown-linux-gnu` in table `target`
Traceback (most recent call last):
  File "/mnt/data/poky/build/tmp/work/x86_64-linux/rust-native/1.86.0/rustc-1.86.0-src/src/bootstrap/bootstrap.py", line 1359, in <module>
    main()
  File "/mnt/data/poky/build/tmp/work/x86_64-linux/rust-native/1.86.0/rustc-1.86.0-src/src/bootstrap/bootstrap.py", line 1339, in main
    bootstrap(args)
  File "/mnt/data/poky/build/tmp/work/x86_64-linux/rust-native/1.86.0/rustc-1.86.0-src/src/bootstrap/bootstrap.py", line 1306, in bootstrap
    build.build_bootstrap()
  File "/mnt/data/poky/build/tmp/work/x86_64-linux/rust-native/1.86.0/rustc-1.86.0-src/src/bootstrap/bootstrap.py", line 1010, in build_bootstrap
    run(args, env=env, verbose=self.verbose, cwd=self.rust_root)
  File "/mnt/data/poky/build/tmp/work/x86_64-linux/rust-native/1.86.0/rustc-1.86.0-src/src/bootstrap/bootstrap.py", line 236, in run
    raise RuntimeError(err)
RuntimeError: failed to run: /mnt/data/poky/build/tmp/work/x86_64-linux/rust-native/1.86.0/rust-snapshot/bin/cargo build --manifest-path /mnt/data/poky/build/tmp/work/x86_64-linux/rust-native/1.86.0/rustc-1.86.0-src/src/bootstrap/Cargo.toml -Zroot-dir=/mnt/data/poky/build/tmp/work/x86_64-linux/rust-native/1.86.0/rustc-1.86.0-src --verbose --frozen
WARNING: exit code 1 from a shell command.

My Host machine is x86_64, but my target machine is Raspberry Pi

You should not manually set the rust version in Yocto, it will break the bootstrap process as happened here. Please use the meta-lts-mixin for rust I linked earlier if you want to use a newer version.

Btw: Where did you get this list of variables to change the Rust version from?

I got variables by checking available recipes

Thanks for the suggestions. They worked successfully. I followed your recommendations and eventually arrived at the following final approach:

Steps Performed

  • Updated the Yocto branch to the latest Scarthgap revision
git pull origin scarthgap
  • Added the following meta-lts-mixins layer:
git clone -b scarthgap/rust https://git.yoctoproject.org/meta-lts-mixins
  • Generated a Cargo lockfile from the Rust project directory
cargo generate-lockfile
  • Updated the crate dependencies
bitbake -c update_crates rustapp
  • Included the generated ${BPN}-crates.inc file in the recipe
require ${BPN}-crates.inc

Final Recipe

require ${BPN}-crates.inc
SRC_URI += " \
    file://Cargo.toml \
    file://Cargo.lock \
    file://src/main.rs \
"
S = "${WORKDIR}"

inherit cargo cargo-update-recipe-crates

do_install() {
    install -d ${D}${bindir}
    install -m 0755 ${B}/target/${CARGO_TARGET_SUBDIR}/rustapp ${D}${bindir}/${PN}
}

FILES:${PN} = "${bindir}/${PN}"
DEPENDS += "cargo-native"