Re: [PATCH v2 1/2] crosvm: add recipe for ChromeOS Virtual Machine Monitor (VMM)

Bruce Ashfield <[email protected]> Mon, 22 Jun 2026 13:49:22 -0700 (PDT)
Newsgroups org.yoctoproject.lists.meta-virtualization
Message-ID <[email protected]>
Thanks for the update — the specific config.toml output and the
pointer to the rust/minijail subdir path made it easy to reproduce.
My earlier read was against an old, stale build state that masked the
real failure; once I cleansstate'd and went through a full do_compile
from scratch, the actual picture matched what you reported and I could
see what's going on.

Two things are happening:

1. cargo_common's auto-injection is the wrong tool for this case.

   cargo_common_do_patch_paths() (OE-core cargo_common.bbclass, walked
   from do_configure[postfuncs]) sees every git SRC_URI with both name=
   and destsuffix= set, and appends:

       [patch."https://github.com/google/minijail.git"]
       minijail = { path = "${UNPACKDIR}/git/third_party/minijail" }

   The path is the minijail repo root — but minijail has no top-level
   Cargo.toml; the Rust crate lives at rust/minijail/Cargo.toml. Cargo
   eagerly validates every [patch."<url>"] entry by opening the path's
   Cargo.toml to learn which crate is there, so a missing file is a
   hard error that fires before "unused patch" warnings ever get a
   chance.

   crosvm's own upstream Cargo.toml already does the right redirect:

       [patch.crates-io]
       minijail = { path = "third_party/minijail/rust/minijail" }

   bitbake's destsuffix already places the minijail repo at exactly the
   location that relative path expects, so this entry resolves to a
   real Cargo.toml and is sufficient on its own. Cleaner than rewriting
   generated state after the fact is to drop cargo_common's auto-
   injection before it ever runs — a four-line python anonymous block
   removes cargo_common_do_patch_paths from do_configure[postfuncs],
   config.toml stays clean, no sed needed.

2. minijail-sys bindgen wiring is missing from the recipe.

   On the way to validating (1), do_compile failed at:

       ../../libminijail.h:18:10: fatal error: 'stdbool.h' file not found
       thread 'main' panicked at ... third_party/minijail/
                                    rust/minijail-sys/build.rs:120:39:
       failed to generate bindings: ClangDiagnostic(...)

   minijail-sys' build.rs uses the bindgen crate (in-process libclang)
   to generate Rust FFI bindings for libminijail.h. Without clang-native
   in DEPENDS and the corresponding LIBCLANG_PATH /
   BINDGEN_EXTRA_CLANG_ARGS exports, libclang can't find its own
   resource dir, the C header parse blows up at stdbool.h, and bindings
   generation panics.

   v2 presumably builds for you because your environment provides
   clang-native and the right include paths via another route (meta-
   clang in bblayers, or a transitive dep). Adding the wiring to the
   recipe directly makes it work in a stock poky + meta-virt tree as
   well, which is what we need for the layer.

Patch below is a single diff against v2 1/2 — full `bitbake crosvm`
from cleansstate, 1448 tasks, all succeeded, 12 MB aarch64 ELF
produced on cortexa57. Feel free to fold into v3 or just take it
verbatim.

----- 8< -----

>From e244155f1a869994928ea4ec35c4b869027ee379 Mon Sep 17 00:00:00 2001
From: Bruce Ashfield <[email protected]>
Date: Mon, 22 Jun 2026 20:41:44 +0000
Subject: [PATCH] crosvm: replace cargo patch-table sed with postfunc-remove
 + add bindgen wiring

Two fixes to make the v2 recipe build on a stock OE-core + meta-virt
master tree.

1. do_filter_minijail_cargo_config / sed -> postfunc-remove

   cargo_common_do_patch_paths() (in OE-core's cargo_common.bbclass) walks
   SRC_URI for git entries with both name= and destsuffix= set and appends
   to ${CARGO_HOME}/config.toml:

       [patch."https://github.com/google/minijail.git"]
       minijail = { path = "${UNPACKDIR}/git/third_party/minijail" }

   The path is the minijail repo root — but minijail has no top-level
   Cargo.toml. The Rust crate lives at rust/minijail/Cargo.toml. cargo
   eagerly validates every [patch."<url>"] entry by reading the path's
   Cargo.toml to learn what crate is at that path; a missing file is a
   hard error before the "unused patch" diagnostic would ever fire.

   crosvm's own upstream Cargo.toml already supplies the correct redirect:

       [patch.crates-io]
       minijail = { path = "third_party/minijail/rust/minijail" }

   pointing at the rust/minijail subdirectory where the Cargo.toml lives.
   bitbake's destsuffix places the minijail repo at exactly the location
   that relative path expects, so this entry resolves to a real Cargo.toml
   and is sufficient on its own.

   The v2 recipe worked around this by sed'ing the cargo_common-injected
   line out of config.toml after the fact. Replace that with a python
   anonymous block that drops cargo_common_do_patch_paths from
   do_configure[postfuncs] before it ever runs — config.toml stays clean
   and there's no rewrite of generated state.

2. minijail-sys bindgen wiring

   minijail-sys's build.rs uses the bindgen crate (in-process libclang)
   to generate Rust FFI bindings for libminijail.h. Without DEPENDS on
   clang-native and the corresponding LIBCLANG_PATH /
   BINDGEN_EXTRA_CLANG_ARGS exports, bindgen fails at do_compile:

       ../../libminijail.h:18:10: fatal error: 'stdbool.h' file not found
       thread 'main' panicked at ... third_party/minijail/rust/
                                    minijail-sys/build.rs:120:39:
       failed to generate bindings: ClangDiagnostic(...)

   v2 builds for environments that already provide clang-native and the
   right include paths via another route (e.g. meta-clang in bblayers),
   but the recipe should pull in its own wiring so it works in a stock
   tree.

Verified by a full `bitbake crosvm` from cleansstate on cortexa57 against
poky/meta-virtualization master: 1448 tasks, all succeeded, 12 MB
crosvm aarch64 ELF produced, do_package_qa clean.

Signed-off-by: Bruce Ashfield <[email protected]>
---
 recipes-extended/crosvm/crosvm_0.1.0.bb | 43 ++++++++++++-------------
 1 file changed, 21 insertions(+), 22 deletions(-)

diff --git a/recipes-extended/crosvm/crosvm_0.1.0.bb b/recipes-extended/crosvm/crosvm_0.1.0.bb
index ab629c69..471d825c 100644
--- a/recipes-extended/crosvm/crosvm_0.1.0.bb
+++ b/recipes-extended/crosvm/crosvm_0.1.0.bb
@@ -28,7 +28,14 @@ SRCREV_FORMAT = "crosvm_minijail"
 # consistency, not an upstream project release.
 PV = "0.1.0+git"

-DEPENDS += "libcap wayland wayland-native protobuf-native wayland-protocols"
+DEPENDS += "libcap wayland wayland-native protobuf-native wayland-protocols clang-native"
+
+# minijail-sys' build.rs uses the bindgen crate (in-process libclang) to
+# generate Rust FFI bindings for libminijail.h. Point bindgen at the
+# clang-native libclang and pass the target sysroot so cross-compiled
+# header parsing resolves correctly.
+export LIBCLANG_PATH = "${STAGING_LIBDIR_NATIVE}"
+export BINDGEN_EXTRA_CLANG_ARGS = "--sysroot=${STAGING_DIR_HOST}"

 REQUIRED_DISTRO_FEATURES = "kvm"

@@ -36,27 +43,19 @@ COMPATIBLE_HOST = "(aarch64|x86_64).*-linux.*"

 BBCLASSEXTEND = "native"

-# cargo_common_do_patch_paths() auto-generates Cargo [patch] entries for
-# git SRC_URI items that set both "name" and "destsuffix".
-# When "subdir" is also used, cargo_common builds the path as
-# ${UNPACKDIR}/${destsuffix}/${subdir}, but BitBake unpacks as
-# ${UNPACKDIR}/${subdir}/${destsuffix}. For crosvm's minijail source, that
-# mismatch can point Cargo at a directory without Cargo.toml.
-# Remove the generated entry from ${CARGO_HOME}/config.toml; crosvm's
-# Cargo.toml already provides the correct patch path.
-do_filter_minijail_cargo_config() {
-
-    cfg="${CARGO_HOME}/config.toml"
-
-    if [ ! -f "$cfg" ]; then
-        bbwarn "Skipping missing Cargo config: $cfg"
-        exit 0
-    fi
-
-    bbnote "Processing Cargo config: $cfg"
-    sed -i '/minijail/d' "$cfg"
+# crosvm's own Cargo.toml already supplies [patch.crates-io] minijail =
+#   { path = "third_party/minijail/rust/minijail" }
+# pointing at the rust/minijail subdirectory where minijail's Cargo.toml
+# actually lives. cargo_common_do_patch_paths() would inject a competing
+# [patch."<minijail git URL>"] minijail = { path = "<unpackdir>/git/third_party/minijail" }
+# pointing at the minijail repo root, where there is no Cargo.toml — cargo
+# eagerly validates patch entries and errors out before it would even reach
+# the "unused patch" path. Disable the auto-injection; crosvm's upstream
+# table is the authoritative one.
+python () {
+    pf = (d.getVarFlag("do_configure", "postfuncs") or "").split()
+    pf = [f for f in pf if f != "cargo_common_do_patch_paths"]
+    d.setVarFlag("do_configure", "postfuncs", " ".join(pf))
 }

-addtask filter_minijail_cargo_config after do_configure before do_compile
-
 require crosvm-crates.inc
--
2.34.1

Bruce