From patchwork Mon Nov 9 13:44:18 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Enguerrand de Ribaucourt X-Patchwork-Id: 103507 Received: from mail.savoirfairelinux.com (mail.savoirfairelinux.com [208.88.110.44]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.6068.1794231915957764798 for ; Mon, 09 Nov 2026 05:45:16 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@savoirfairelinux.com header.s=DFC430D2-D198-11EC-948E-34200CB392D2 header.b=iobreePs; spf=pass (domain: savoirfairelinux.com, ip: 208.88.110.44, mailfrom: enguerrand.de-ribaucourt@savoirfairelinux.com) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id A79DF3D8182D; Mon, 9 Nov 2026 08:45:14 -0500 (EST) Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10032) with ESMTP id 5X6HOSSophhh; Mon, 9 Nov 2026 08:45:13 -0500 (EST) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 510993D80F35; Mon, 9 Nov 2026 08:45:13 -0500 (EST) DKIM-Filter: OpenDKIM Filter v2.10.3 mail.savoirfairelinux.com 510993D80F35 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=savoirfairelinux.com; s=DFC430D2-D198-11EC-948E-34200CB392D2; t=1794231913; bh=PK+35z7NuDY6/Hc6QVCzbAzBh2WYdnTziMjtFpSGdmY=; h=From:Date:MIME-Version:Message-Id:To; b=iobreePsaN+IsRj3WKDkJMkuPCHqKDzjmaVxBvnsRalkKtaAjexU5vgpp9iwLWpPL eYaFu0En5IBrkGvMhZDjUZwrgAObKD4lZvj+MbRmskaNdxvufk7DrPdCUaxTGFnKZT wk2AsPnMLGbfUoFqFiaUqXghWh+FNrVIBbtTQI9F9giadLaBC+tLRWElwVw3+eoLcw P1v4zO667VRpd3c1JYicdaUAeTnjPsYdndsBeRy5FJbRmwZJFkbBHnmCMwBrXzwKbJ jyOUmQRFJ+aUVJ7GVfxClhImUFvUSwjf5KdsHTQt8a6RhQwOMBWJo6KG9FF45wNvQ5 Kppd3LT1TnFvw== X-Virus-Scanned: amavis at mail.savoirfairelinux.com Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10026) with ESMTP id 1hHneJxsnkpS; Mon, 9 Nov 2026 08:45:13 -0500 (EST) Received: from isabelle.rennes.sfl (80-15-101-118.ftth.fr.orangecustomers.net [80.15.101.118]) by mail.savoirfairelinux.com (Postfix) with ESMTPSA id C74643D8176B; Mon, 9 Nov 2026 08:45:12 -0500 (EST) From: Enguerrand de Ribaucourt Date: Mon, 09 Nov 2026 14:44:18 +0100 Subject: [PATCH v2 01/18] cargo-example: add minimal selftest fixture MIME-Version: 1.0 Message-Id: <20261109-devtool-ide-sdk-cargo-v2-1-d56134000561@savoirfairelinux.com> References: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> In-Reply-To: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer , Enguerrand de Ribaucourt X-Mailer: b4 0.16.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Mon, 09 Nov 2026 13:45:21 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/249828 Add a minimal Cargo recipe to demonstrate the ide-sdk configuration for Rust in the selftests. AI-Generated: Uses GitHub Copilot Signed-off-by: Enguerrand de Ribaucourt --- meta-selftest/recipes-test/rust/cargo-example.bb | 15 +++++++++++++++ .../recipes-test/rust/cargo-example/Cargo.lock | 5 +++++ .../recipes-test/rust/cargo-example/Cargo.toml | 8 ++++++++ .../recipes-test/rust/cargo-example/build.rs | 20 ++++++++++++++++++++ .../recipes-test/rust/cargo-example/src/main.rs | 11 +++++++++++ 5 files changed, 59 insertions(+) diff --git a/meta-selftest/recipes-test/rust/cargo-example.bb b/meta-selftest/recipes-test/rust/cargo-example.bb new file mode 100644 index 0000000000..cca56d8d81 --- /dev/null +++ b/meta-selftest/recipes-test/rust/cargo-example.bb @@ -0,0 +1,15 @@ +SUMMARY = "Minimal Cargo application for devtool ide-sdk selftests" +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" + +SRC_URI = "file://Cargo.toml \ + file://Cargo.lock \ + file://build.rs \ + file://src/main.rs \ + " + +S = "${UNPACKDIR}" + +inherit cargo + +CARGO_BUILD_FLAGS:append = " --features ide-sdk-selftest" diff --git a/meta-selftest/recipes-test/rust/cargo-example/Cargo.lock b/meta-selftest/recipes-test/rust/cargo-example/Cargo.lock new file mode 100644 index 0000000000..27cb8ffd40 --- /dev/null +++ b/meta-selftest/recipes-test/rust/cargo-example/Cargo.lock @@ -0,0 +1,5 @@ +version = 3 + +[[package]] +name = "cargo-example" +version = "0.1.0" diff --git a/meta-selftest/recipes-test/rust/cargo-example/Cargo.toml b/meta-selftest/recipes-test/rust/cargo-example/Cargo.toml new file mode 100644 index 0000000000..e8a2e1dde4 --- /dev/null +++ b/meta-selftest/recipes-test/rust/cargo-example/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "cargo-example" +version = "0.1.0" +edition = "2021" + +[features] +# Used only to verify that ide-sdk forwards recipe Cargo features to its task. +ide-sdk-selftest = [] diff --git a/meta-selftest/recipes-test/rust/cargo-example/build.rs b/meta-selftest/recipes-test/rust/cargo-example/build.rs new file mode 100644 index 0000000000..f0733b3d38 --- /dev/null +++ b/meta-selftest/recipes-test/rust/cargo-example/build.rs @@ -0,0 +1,20 @@ +use std::env; + +// Fail the selftest build if Cargo does not receive BitBake's cross environment. +fn main() { + let target_cc = env::var("CC").expect("Cargo config should set target CC"); + assert!(target_cc.ends_with("/target-rust-cc"), "unexpected CC: {target_cc}"); + + let host_cc = env::var("HOST_CC").expect("Cargo config should set host CC"); + assert!(host_cc.ends_with("/build-rust-cc"), "unexpected HOST_CC: {host_cc}"); + + assert!( + env::var_os("RUST_TARGET_PATH").is_some(), + "Cargo config should set the OE Rust target path", + ); + assert_eq!( + env::var("PKG_CONFIG_ALLOW_CROSS").as_deref(), + Ok("1"), + "Cargo config should allow cross pkg-config", + ); +} diff --git a/meta-selftest/recipes-test/rust/cargo-example/src/main.rs b/meta-selftest/recipes-test/rust/cargo-example/src/main.rs new file mode 100644 index 0000000000..7066010f51 --- /dev/null +++ b/meta-selftest/recipes-test/rust/cargo-example/src/main.rs @@ -0,0 +1,11 @@ +fn fibonacci(n: u32) -> u32 { + match n { + 0 => 0, + 1 => 1, + _ => fibonacci(n - 1) + fibonacci(n - 2), + } +} + +fn main() { + println!("fibonacci={}", fibonacci(4)); +} From patchwork Mon Nov 9 13:44:19 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Enguerrand de Ribaucourt X-Patchwork-Id: 103502 Received: from mail.savoirfairelinux.com (mail.savoirfairelinux.com [208.88.110.44]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.6190.1794231916180754002 for ; Mon, 09 Nov 2026 05:45:16 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@savoirfairelinux.com header.s=DFC430D2-D198-11EC-948E-34200CB392D2 header.b=GEnxRg5q; spf=pass (domain: savoirfairelinux.com, ip: 208.88.110.44, mailfrom: enguerrand.de-ribaucourt@savoirfairelinux.com) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 37B1D3D818F4; Mon, 9 Nov 2026 08:45:15 -0500 (EST) Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10032) with ESMTP id bytq-E14sF1s; Mon, 9 Nov 2026 08:45:14 -0500 (EST) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id DF8733D8176B; Mon, 9 Nov 2026 08:45:13 -0500 (EST) DKIM-Filter: OpenDKIM Filter v2.10.3 mail.savoirfairelinux.com DF8733D8176B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=savoirfairelinux.com; s=DFC430D2-D198-11EC-948E-34200CB392D2; t=1794231913; bh=wI78uxHd1pMbYbJcXjonsVp2w/BTllkH4Wqbys6og3c=; h=From:Date:MIME-Version:Message-Id:To; b=GEnxRg5qzIcslKhzyKWfc/YadHvudXt8Cqkc5x5jQYbJxIJarIuKZhwzpkCE65SXF 2SXdkkBQAU68BE0gSCjMBMiPia1SupdE2mmel4JvFTXqbiaF/mhAmc+fOv331xsDnK 7f0FKD+RQGBmT43BzVwEpeu8JaTjyLInoaP/NJBX9wLMh7R3b1N7MiCoEAyCw3N6cg EA8yDY69EulHD94gCrR6OXoHrrlVCCbM5ns7WoEexOECIRkpSDnLkyAY2GEuc9yIVC 4F46zhLvXUa33BNDovJkOQTGt10+xGJ8WtD/m0L7w3QLjD1Hrwhu+RNHAPHHj+UyZy ZwfRS5Ahep7Ww== X-Virus-Scanned: amavis at mail.savoirfairelinux.com Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10026) with ESMTP id 8ZcRlXxUi7bi; Mon, 9 Nov 2026 08:45:13 -0500 (EST) Received: from isabelle.rennes.sfl (80-15-101-118.ftth.fr.orangecustomers.net [80.15.101.118]) by mail.savoirfairelinux.com (Postfix) with ESMTPSA id 60B643D81838; Mon, 9 Nov 2026 08:45:13 -0500 (EST) From: Enguerrand de Ribaucourt Date: Mon, 09 Nov 2026 14:44:19 +0100 Subject: [PATCH v2 02/18] devtool: ide-sdk: capture Cargo cross environment MIME-Version: 1.0 Message-Id: <20261109-devtool-ide-sdk-cargo-v2-2-d56134000561@savoirfairelinux.com> References: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> In-Reply-To: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer , Enguerrand de Ribaucourt X-Mailer: b4 0.16.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Mon, 09 Nov 2026 13:45:20 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/249827 Capture Cargo target and host compiler settings, recipe Cargo state, and package configuration to generate IDE settings. Rust source paths use Cargo RUSTFLAGS and TARGET_DBGSRC_DIR because Rust does not use compiler DEBUG_PREFIX_MAP. Mirror the -sys and pkg-config exports from cargo_common.bbclass so Cargo config matches OE's system-library behavior. AI-Generated: Uses GitHub Copilot Signed-off-by: Enguerrand de Ribaucourt --- scripts/lib/devtool/ide_plugins/__init__.py | 1 + scripts/lib/devtool/ide_sdk.py | 57 +++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/scripts/lib/devtool/ide_plugins/__init__.py b/scripts/lib/devtool/ide_plugins/__init__.py index 7841bc37b9..10fcde471f 100644 --- a/scripts/lib/devtool/ide_plugins/__init__.py +++ b/scripts/lib/devtool/ide_plugins/__init__.py @@ -33,6 +33,7 @@ class BuildTool(Enum): UNDEFINED = auto() CMAKE = auto() MESON = auto() + CARGO = auto() KERNEL_MODULE = auto() @property diff --git a/scripts/lib/devtool/ide_sdk.py b/scripts/lib/devtool/ide_sdk.py index 9faf041957..e686dbcff8 100755 --- a/scripts/lib/devtool/ide_sdk.py +++ b/scripts/lib/devtool/ide_sdk.py @@ -877,6 +877,15 @@ class RecipeModified: self.extra_oemake = None self.kernel_cc = None self.staging_kernel_dir = None + # Cargo application + self.cargo = None + self.cargo_target = None + self.cargo_linker = None + self.cargo_home = None + self.cargo_build_flags = None + self.cargo_packageconfig_confargs = None + self.cargo_rustflags = None + self.cargo_env = None # Populated after bitbake built all the recipes self._installed_binaries = None @@ -1032,6 +1041,54 @@ class RecipeModified: self.extra_oemeson = recipe_d.getVar('EXTRA_OEMESON') self.meson_cross_file = recipe_d.getVar('MESON_CROSS_FILE') self.build_tool = BuildTool.MESON + elif bb.data.inherits_class('cargo', recipe_d): + self.cargo = recipe_d.getVar('CARGO') or 'cargo' + self.cargo_target = recipe_d.getVar('RUST_HOST_SYS') + self.cargo_linker = recipe_d.getVar('CARGO_RUST_TARGET_CCLD') + self.cargo_home = recipe_d.getVar('CARGO_HOME') + self.cargo_build_flags = recipe_d.getVar('CARGO_BUILD_FLAGS') or '' + self.cargo_packageconfig_confargs = recipe_d.getVar( + 'PACKAGECONFIG_CONFARGS') or '' + self.cargo_rustflags = recipe_d.getVar('RUSTFLAGS') or '' + # Rust DWARF paths need remapping to the target debug-source path + # so LLDB can resolve files after the source tree is relocated. + target_dbgsrc_dir = recipe_d.getVar('TARGET_DBGSRC_DIR') + if target_dbgsrc_dir: + source_map = '--remap-path-prefix=%s=%s' % ( + self.real_srctree, target_dbgsrc_dir) + self.cargo_rustflags = '%s %s' % ( + self.cargo_rustflags, shlex.quote(source_map)) + # This environment feeds the generated Cargo config and the C/C++ + # IntelliSense settings; build tasks themselves only need PATH. + self.cargo_env = self.exported_vars.copy() + self.cargo_env.update({ + 'CC': recipe_d.getVar('RUST_TARGET_CC'), + 'CXX': recipe_d.getVar('RUST_TARGET_CXX'), + 'CFLAGS': recipe_d.getVar('CFLAGS'), + 'CXXFLAGS': recipe_d.getVar('CXXFLAGS'), + 'AR': recipe_d.getVar('AR'), + 'TARGET_CC': recipe_d.getVar('RUST_TARGET_CC'), + 'TARGET_CXX': recipe_d.getVar('RUST_TARGET_CXX'), + 'TARGET_CFLAGS': recipe_d.getVar('CFLAGS'), + 'TARGET_CXXFLAGS': recipe_d.getVar('CXXFLAGS'), + 'TARGET_AR': recipe_d.getVar('AR'), + 'HOST_CC': recipe_d.getVar('RUST_BUILD_CC'), + 'HOST_CXX': recipe_d.getVar('RUST_BUILD_CXX'), + 'HOST_CFLAGS': recipe_d.getVar('BUILD_CFLAGS'), + 'HOST_CXXFLAGS': recipe_d.getVar('BUILD_CXXFLAGS'), + 'HOST_AR': recipe_d.getVar('BUILD_AR'), + # Match cargo_common.bbclass so Cargo -sys crates use OE's + # staged libraries through pkg-config instead of vendoring. + 'LIBGIT2_NO_VENDOR': '1', + 'LIBSSH2_SYS_USE_PKG_CONFIG': '1', + 'LIBSQLITE3_SYS_USE_PKG_CONFIG': '1', + 'OPENSSL_NO_VENDOR': '1', + 'PKG_CONFIG_ALLOW_CROSS': '1', + 'PKG_CONFIG_ALL_DYNAMIC': '1', + 'SYSTEM_DEPS_BUILD_INTERNAL': 'never', + 'ZSTD_SYS_USE_PKG_CONFIG': '1', + }) + self.build_tool = BuildTool.CARGO elif bb.data.inherits_class('module', recipe_d): self.build_tool = BuildTool.KERNEL_MODULE self.wants_gdbserver = False From patchwork Mon Nov 9 13:44:20 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Enguerrand de Ribaucourt X-Patchwork-Id: 103509 Received: from mail.savoirfairelinux.com (mail.savoirfairelinux.com [208.88.110.44]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.6070.1794231917356673281 for ; Mon, 09 Nov 2026 05:45:17 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@savoirfairelinux.com header.s=DFC430D2-D198-11EC-948E-34200CB392D2 header.b=sPFJarJc; spf=pass (domain: savoirfairelinux.com, ip: 208.88.110.44, mailfrom: enguerrand.de-ribaucourt@savoirfairelinux.com) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 65DAD3D818F1; Mon, 9 Nov 2026 08:45:16 -0500 (EST) Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10032) with ESMTP id 1GcET_s4anHG; Mon, 9 Nov 2026 08:45:14 -0500 (EST) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 7D0863D81838; Mon, 9 Nov 2026 08:45:14 -0500 (EST) DKIM-Filter: OpenDKIM Filter v2.10.3 mail.savoirfairelinux.com 7D0863D81838 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=savoirfairelinux.com; s=DFC430D2-D198-11EC-948E-34200CB392D2; t=1794231914; bh=3u8yMDt24SsZiL0sasZJpdoNgWmoG+iAl3YU+JMOF+o=; h=From:Date:MIME-Version:Message-Id:To; b=sPFJarJc6yTeBzpGySeRF3PthtdUiOyBKF3CbkBUyl6+o3A1Wl6ai4/42/7tuliUA f928ExkUurTCWDj/Y8kpIE0Q2Jb+2b7RjlWc1xGmg89I6J7juZqdXU+slrS0IiUd4s bm2ud6zPI5CgFJ4Qo1D33BzKXJE3Eg+bwkvsll2ndpp7fs9j5tpU4ztJWiKlutSSSO 0GUsMVbtyC3XIVqyIf67Cw4OSZuXM5uPcztDADEl/8zGZ8pGUUmUiIGt9LfCgIfL+k UGrn1naaNbcKlnEmFqDMmGiAP8gLylZcrkCn841+sedU0v2oLFHNTRze1PB5YU7Xx6 clzIbDThXELLw== X-Virus-Scanned: amavis at mail.savoirfairelinux.com Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10026) with ESMTP id SKVT_NFuSs39; Mon, 9 Nov 2026 08:45:14 -0500 (EST) Received: from isabelle.rennes.sfl (80-15-101-118.ftth.fr.orangecustomers.net [80.15.101.118]) by mail.savoirfairelinux.com (Postfix) with ESMTPSA id EE3793D81892; Mon, 9 Nov 2026 08:45:13 -0500 (EST) From: Enguerrand de Ribaucourt Date: Mon, 09 Nov 2026 14:44:20 +0100 Subject: [PATCH v2 03/18] devtool: ide-sdk: export recipe Cargo configuration MIME-Version: 1.0 Message-Id: <20261109-devtool-ide-sdk-cargo-v2-3-d56134000561@savoirfairelinux.com> References: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> In-Reply-To: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer , Enguerrand de Ribaucourt X-Mailer: b4 0.16.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Mon, 09 Nov 2026 13:45:21 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/249831 Export recipe Cargo config to the devtool workspace so Cargo and rust-analyzer reuse target, linker, rustflags, and dependency settings instead of duplicating them in settings.json and tasks.json. Other IDE integrations can reuse the generated config too. The original input is generated by cargo_common.bbclass. Updating it in-place would require a Python TOML writer dependency, so regenerate it with a bounded writer helper. AI-Generated: Uses GitHub Copilot Signed-off-by: Enguerrand de Ribaucourt --- Changes in v2: - Replace in-place Cargo config updates with a helper that rewrites the full file. - Generate Cargo config for all IDE modes. --- scripts/lib/devtool/ide_sdk.py | 102 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/scripts/lib/devtool/ide_sdk.py b/scripts/lib/devtool/ide_sdk.py index e686dbcff8..98e39703e7 100755 --- a/scripts/lib/devtool/ide_sdk.py +++ b/scripts/lib/devtool/ide_sdk.py @@ -22,6 +22,7 @@ from pathlib import Path import scriptutils import bb +from bb._vendor import tomli from devtool import exec_build_env_command, setup_tinfoil, check_workspace_recipe, DevtoolError, parse_recipe from devtool.standard import get_real_srctree from devtool.deploy import parse_packages_arg @@ -787,6 +788,41 @@ class ExecutableBinary: return None +def _toml_dumps(config): + """Serialize TOML values and tables.""" + def format_value(value): + if isinstance(value, str): + return json.dumps(value) + if isinstance(value, bool): + return str(value).lower() + if isinstance(value, (int, float)): + return repr(value) + if isinstance(value, list): + return '[%s]' % ', '.join(format_value(item) for item in value) + if isinstance(value, dict): + return '{ %s }' % ', '.join( + '%s = %s' % (json.dumps(key), format_value(item)) + for key, item in value.items()) + raise TypeError('Unsupported TOML value: %s' % type(value).__name__) + + lines = [] + + def write_table(table, path=()): + if path: + if lines: + lines.append('') + lines.append('[%s]' % '.'.join(json.dumps(key) for key in path)) + for key, value in table.items(): + if not isinstance(value, dict): + lines.append('%s = %s' % (json.dumps(key), format_value(value))) + for key, value in table.items(): + if isinstance(value, dict): + write_table(value, path + (key,)) + + write_table(config) + return '\n'.join(lines) + ('\n' if lines else '') + + class RecipeModified: """Handling of recipes in the workspace created by devtool modify""" OE_INIT_BUILD_ENV = 'oe-init-build-env' @@ -1122,6 +1158,70 @@ class RecipeModified: self.recipe_id = self.bpn + "-" + self.package_arch self.recipe_id_pretty = self.bpn + ": " + self.package_arch + @property + def cargo_config_path(self): + return os.path.join(self.ide_sdk_dir, 'cargo-config.toml') + + def update_cargo_config(self): + """Export the recipe Cargo config to the devtool workspace.""" + source_config = os.path.join(self.cargo_home, 'config.toml') + try: + with open(source_config, 'r') as config_file: + cargo_config = tomli.loads(config_file.read()) + except FileNotFoundError as exc: + raise DevtoolError( + 'Cargo config not found at %s; build the recipe first' % source_config) from exc + + if 'build' not in cargo_config: + cargo_config['build'] = {} + cargo_config['build']['target'] = self.cargo_target + + if 'target' not in cargo_config: + cargo_config['target'] = {} + target_config = cargo_config['target'] + if self.cargo_target not in target_config: + target_config[self.cargo_target] = {} + target_config = target_config[self.cargo_target] + target_config['linker'] = self.cargo_linker + target_config['rustflags'] = shlex.split(self.cargo_rustflags) + + if 'env' not in cargo_config: + cargo_config['env'] = {} + env_config = cargo_config['env'] + env_names = ( + 'CC', 'CXX', 'CFLAGS', 'CXXFLAGS', 'AR', + 'TARGET_CC', 'TARGET_CXX', 'TARGET_CFLAGS', 'TARGET_CXXFLAGS', 'TARGET_AR', + 'HOST_CC', 'HOST_CXX', 'HOST_CFLAGS', 'HOST_CXXFLAGS', 'HOST_AR', + 'RUST_TARGET_PATH', 'RUST_BACKTRACE', 'SOURCE_DATE_EPOCH', + 'PKG_CONFIG', 'PKG_CONFIG_FOR_BUILD', 'PKG_CONFIG_FOR_TARGET', + 'PKG_CONFIG_SYSROOT_DIR', 'PKG_CONFIG_PATH', 'PKG_CONFIG_LIBDIR', + 'LIBGIT2_NO_VENDOR', 'LIBSSH2_SYS_USE_PKG_CONFIG', + 'LIBSQLITE3_SYS_USE_PKG_CONFIG', 'OPENSSL_NO_VENDOR', + 'PKG_CONFIG_ALLOW_CROSS', 'PKG_CONFIG_ALL_DYNAMIC', + 'SYSTEM_DEPS_BUILD_INTERNAL', 'ZSTD_SYS_USE_PKG_CONFIG', + ) + for name in env_names: + value = self.cargo_env.get(name) + if value is not None: + env_config[name] = {'value': str(value), 'force': True} + + content = ( + '# Generated by devtool ide-sdk for the active build environment.\n' + '\n' + + _toml_dumps(cargo_config)) + + config_path = self.cargo_config_path + os.makedirs(os.path.dirname(config_path), exist_ok=True) + try: + with open(config_path, 'r') as config_file: + current = config_file.read() + except FileNotFoundError: + current = None + if current != content: + with open(config_path, 'w') as config_file: + config_file.write(content) + return config_path + @staticmethod def is_valid_shell_variable(var): """Skip strange shell variables like systemd @@ -2019,6 +2119,8 @@ def ide_setup(args, config, basepath, workspace): image.extract_nfs_rootfs(nfs_export_base_dir, args.nfs, args.target) if DevtoolIdeMode.modified in modes: for recipe_modified in recipes_modified: + if recipe_modified.build_tool is BuildTool.CARGO: + recipe_modified.update_cargo_config() if recipe_modified.build_tool is BuildTool.CMAKE: recipe_modified.cmake_preset() if recipe_modified.build_tool is BuildTool.MESON: From patchwork Mon Nov 9 13:44:21 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Enguerrand de Ribaucourt X-Patchwork-Id: 103508 Received: from mail.savoirfairelinux.com (mail.savoirfairelinux.com [208.88.110.44]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.6069.1794231917223012450 for ; Mon, 09 Nov 2026 05:45:17 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@savoirfairelinux.com header.s=DFC430D2-D198-11EC-948E-34200CB392D2 header.b=m0PwVNHc; spf=pass (domain: savoirfairelinux.com, ip: 208.88.110.44, mailfrom: enguerrand.de-ribaucourt@savoirfairelinux.com) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 3FA5A3D818F9; Mon, 9 Nov 2026 08:45:16 -0500 (EST) Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10032) with ESMTP id 8k5z8NPfVqO5; Mon, 9 Nov 2026 08:45:15 -0500 (EST) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 262C53D81892; Mon, 9 Nov 2026 08:45:15 -0500 (EST) DKIM-Filter: OpenDKIM Filter v2.10.3 mail.savoirfairelinux.com 262C53D81892 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=savoirfairelinux.com; s=DFC430D2-D198-11EC-948E-34200CB392D2; t=1794231915; bh=B13kUIrUvQDimnqARUVsnNYd6tsy5hTK1xIxggVl5Aw=; h=From:Date:MIME-Version:Message-Id:To; b=m0PwVNHcoMgABB9ftfKv8fmWfQHVcDncoeHPaaXxgK4oPayA82omREYymc12EQFPj QN/VQNJBczSjOaS1zBssmExas/bvjOVWpULSU6kvwNuyPfPeQEbXpwKjxnlZpVYqWh wW0UeCBSpjn3RoeR/yHc5k67d21SRvmYwmjBGx28R8jsAp18Eo/DB34D/yONmUKjCv WV+zqJVrgJ3BoJA83udiFKQ4Qo0s13ollluA3vVBECiNVuz4JWLili5KZeEbBBT8j5 UxcTvOfqUk4KaZWbHVU4I+93e/DOlyNKph/mNG7kD9wRa4NB6SPIyqovt5VNakElFD VUrisXsPKSdeA== X-Virus-Scanned: amavis at mail.savoirfairelinux.com Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10026) with ESMTP id 7_kHgTTgKO1k; Mon, 9 Nov 2026 08:45:14 -0500 (EST) Received: from isabelle.rennes.sfl (80-15-101-118.ftth.fr.orangecustomers.net [80.15.101.118]) by mail.savoirfairelinux.com (Postfix) with ESMTPSA id 880EF3D818F1; Mon, 9 Nov 2026 08:45:14 -0500 (EST) From: Enguerrand de Ribaucourt Date: Mon, 09 Nov 2026 14:44:21 +0100 Subject: [PATCH v2 04/18] oeqa/selftest: verify Cargo config serialization MIME-Version: 1.0 Message-Id: <20261109-devtool-ide-sdk-cargo-v2-4-d56134000561@savoirfairelinux.com> References: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> In-Reply-To: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer , Enguerrand de Ribaucourt X-Mailer: b4 0.16.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Mon, 09 Nov 2026 13:45:21 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/249830 Parse the config exported by devtool and round-trip the TOML writer's supported tables and values. AI-Generated: Uses GitHub Copilot Signed-off-by: Enguerrand de Ribaucourt --- Changes in v2: - Commit added to verify the generated Cargo config. --- meta/lib/oeqa/selftest/cases/devtool.py | 63 +++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py index 265f2147a4..cab49b4c02 100644 --- a/meta/lib/oeqa/selftest/cases/devtool.py +++ b/meta/lib/oeqa/selftest/cases/devtool.py @@ -5242,3 +5242,66 @@ class DevtoolIdeSdkMiscTests(DevtoolIdeSdkTests): with open(modified_config_file) as modified_config: modified_config_new = modified_config.read() self.assertEqual(modified_config_str, modified_config_new) + + +class DevtoolIdeSdkCargoConfigTests(DevtoolIdeSdkTests): + + def test_cargo_toml_serialization(self): + import importlib + import sys + + from bb._vendor import tomli + + config = { + 'paths': ['/work/crate', '/work/quoted "crate"\\dir'], + 'source': {'bitbake': {'directory': '/downloads/cargo'}}, + 'patch': { + 'https://example.com/repo': { + 'example': {'path': '/work/patched-crate'} + } + }, + 'env': { + 'CC': {'value': '/tool/cc --flag="quoted"\\path', 'force': True} + }, + 'target': { + 'x86_64-poky-linux': { + 'linker': '/tool/ld', + 'rustflags': ['--sysroot', '/sysroot path'], + } + }, + 'term': {'progress': {'when': 'always', 'width': 80}}, + } + + scripts_lib = os.path.join(get_bb_var('COREBASE'), 'scripts', 'lib') + sys.path.insert(0, scripts_lib) + oeqa_devtool = sys.modules.pop('devtool') + try: + ide_sdk = importlib.import_module('devtool.ide_sdk') + self.assertEqual(tomli.loads(ide_sdk._toml_dumps(config)), config) + finally: + for name in tuple(sys.modules): + if name == 'devtool' or name.startswith('devtool.'): + del sys.modules[name] + sys.modules['devtool'] = oeqa_devtool + sys.path.remove(scripts_lib) + + def test_cargo_config_is_generated_and_valid(self): + from bb._vendor import tomli + + recipe_name = 'cargo-example' + self._check_workspace() + self._write_bb_config() + self._devtool_ide_sdk_recipe(recipe_name, 'Cargo.toml', None) + runCmd('devtool ide-sdk %s oe-selftest-image --ide=code' % recipe_name, + output_log=self._cmd_logger) + + cargo_config = os.path.join( + self.workspacedir, 'ide-sdk', recipe_name, 'cargo-config.toml') + self.assertExists(cargo_config, 'Cargo config was not generated') + with open(cargo_config) as cargo_config_file: + config = tomli.loads(cargo_config_file.read()) + rust_target = get_bb_var('RUST_HOST_SYS', recipe_name) + self.assertEqual(config['build']['target'], rust_target) + self.assertEqual( + config['target'][rust_target]['linker'], + get_bb_var('CARGO_RUST_TARGET_CCLD', recipe_name)) From patchwork Mon Nov 9 13:44:22 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Enguerrand de Ribaucourt X-Patchwork-Id: 103510 Received: from mail.savoirfairelinux.com (mail.savoirfairelinux.com [208.88.110.44]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.6191.1794231918037246001 for ; Mon, 09 Nov 2026 05:45:18 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@savoirfairelinux.com header.s=DFC430D2-D198-11EC-948E-34200CB392D2 header.b=NrWwxWHO; spf=pass (domain: savoirfairelinux.com, ip: 208.88.110.44, mailfrom: enguerrand.de-ribaucourt@savoirfairelinux.com) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id AA5D93D81838; Mon, 9 Nov 2026 08:45:16 -0500 (EST) Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10032) with ESMTP id IvSzK59mV24w; Mon, 9 Nov 2026 08:45:15 -0500 (EST) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id A7BD53D8176B; Mon, 9 Nov 2026 08:45:15 -0500 (EST) DKIM-Filter: OpenDKIM Filter v2.10.3 mail.savoirfairelinux.com A7BD53D8176B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=savoirfairelinux.com; s=DFC430D2-D198-11EC-948E-34200CB392D2; t=1794231915; bh=6ai6xwDvj57On1WiS+GLTQWqwdkYEs5vV0nWnJcZjeM=; h=From:Date:MIME-Version:Message-Id:To; b=NrWwxWHOUKNmbQlB1ljv4eaiZi9O39boZB/e9QROytoonAzQaVH7+ChFOFaU++9j/ sdMqnz/qg+QMuPmdNf7Y55ThUlBzNBx0p5nVBmML1Tq+eRatFSSwHCJVeUOGWCH65k dA7VdnsILeXH9rL3BFWZAQw/nJxWPEqARR50y6oXFMluHYE+xUfiOJus2rkJaw96nZ mpXZ29L8YkhRJuDEGSGrigaqAIAHntlCT5M35m1AzAa2mg/51dP8P6H9cHIUMbBySy qDMXs32do+yLg30UP5yyJ+FamtwSFwQyZrmP+em3QJ8d+1f3dD2Xpr48EtOyaBqyOt Ku+WwamgyjipQ== X-Virus-Scanned: amavis at mail.savoirfairelinux.com Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10026) with ESMTP id bHRNMiRl40vr; Mon, 9 Nov 2026 08:45:15 -0500 (EST) Received: from isabelle.rennes.sfl (80-15-101-118.ftth.fr.orangecustomers.net [80.15.101.118]) by mail.savoirfairelinux.com (Postfix) with ESMTPSA id 21F923D80F35; Mon, 9 Nov 2026 08:45:15 -0500 (EST) From: Enguerrand de Ribaucourt Date: Mon, 09 Nov 2026 14:44:22 +0100 Subject: [PATCH v2 05/18] devtool: ide-sdk: recommend Rust Analyzer for Cargo MIME-Version: 1.0 Message-Id: <20261109-devtool-ide-sdk-cargo-v2-5-d56134000561@savoirfairelinux.com> References: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> In-Reply-To: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer , Enguerrand de Ribaucourt X-Mailer: b4 0.16.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Mon, 09 Nov 2026 13:45:21 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/249832 Recommend rust-analyzer for Cargo recipes and verify the extension appears in the generated VS Code recommendations file. AI-Generated: Uses GitHub Copilot Signed-off-by: Enguerrand de Ribaucourt --- meta/lib/oeqa/selftest/cases/devtool.py | 14 ++++++++++++++ scripts/lib/devtool/ide_plugins/ide_code.py | 2 ++ 2 files changed, 16 insertions(+) diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py index cab49b4c02..8e90dba7d0 100644 --- a/meta/lib/oeqa/selftest/cases/devtool.py +++ b/meta/lib/oeqa/selftest/cases/devtool.py @@ -4339,6 +4339,20 @@ class DevtoolIdeSdkGccTests(DevtoolIdeSdkTests): self._test_code_and_none_qemu(slirp=True) +class DevtoolIdeSdkRustTests(DevtoolIdeSdkTests): + + def test_code_cargo_rust_analyzer_recommendation(self): + recipe_name = "cargo-example" + self._check_workspace() + self._write_bb_config() + tempdir = self._devtool_ide_sdk_recipe(recipe_name, "Cargo.toml", None) + runCmd('devtool ide-sdk %s oe-selftest-image --ide=code' % recipe_name, + output_log=self._cmd_logger) + + with open(os.path.join(tempdir, '.vscode', 'extensions.json')) as extensions_file: + extensions = json.load(extensions_file) + self.assertIn('rust-lang.rust-analyzer', extensions['recommendations']) + class DevtoolIdeSdkKernelTests(DevtoolIdeSdkTests): @OETestTag("runqemu") diff --git a/scripts/lib/devtool/ide_plugins/ide_code.py b/scripts/lib/devtool/ide_plugins/ide_code.py index 081dc08657..cf7f81293c 100644 --- a/scripts/lib/devtool/ide_plugins/ide_code.py +++ b/scripts/lib/devtool/ide_plugins/ide_code.py @@ -303,6 +303,8 @@ class IdeVSCode(IdeBase): def vscode_extensions(self, modified_recipe): recommendations = [] + if modified_recipe.build_tool is BuildTool.CARGO: + recommendations.append("rust-lang.rust-analyzer") # clangd (matched to the recipe's real cross compiler via # compile_commands.json) replaces cpptools as the IntelliSense provider # when selected via IDE_SDK_INTELLISENSE (defaults to clangd for the From patchwork Mon Nov 9 13:44:23 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Enguerrand de Ribaucourt X-Patchwork-Id: 103503 Received: from mail.savoirfairelinux.com (mail.savoirfairelinux.com [208.88.110.44]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.6192.1794231918384421816 for ; Mon, 09 Nov 2026 05:45:18 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@savoirfairelinux.com header.s=DFC430D2-D198-11EC-948E-34200CB392D2 header.b=HhFHpWC2; spf=pass (domain: savoirfairelinux.com, ip: 208.88.110.44, mailfrom: enguerrand.de-ribaucourt@savoirfairelinux.com) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 77C093D818F4; Mon, 9 Nov 2026 08:45:17 -0500 (EST) Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10032) with ESMTP id wUUc2urG3NLT; Mon, 9 Nov 2026 08:45:16 -0500 (EST) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 3BAF53D80F35; Mon, 9 Nov 2026 08:45:16 -0500 (EST) DKIM-Filter: OpenDKIM Filter v2.10.3 mail.savoirfairelinux.com 3BAF53D80F35 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=savoirfairelinux.com; s=DFC430D2-D198-11EC-948E-34200CB392D2; t=1794231916; bh=L0/j2Xl+/2j7NR9SG0qTBmIgwztozTRm23pNrpfa1GA=; h=From:Date:MIME-Version:Message-Id:To; b=HhFHpWC2DK5dN68aTOw8UhMtOimwu+8GZUkw9Akl4EVYXano0yY167UbdYlXBViT6 Q0I4m6Od017E63WWzeG6XnYKs0jYZHG/30EKOTJZW5pfejY8Q0MumS7q2B6ZuTGcu/ qZEwmx6SUDlke7xhuviDfaa9Pf5mkj5Iak3Xl8btG5FMrPqj4MOxE7EcJhbQ5RtT5+ Frsol2a2snp6sJ1zE0K7XCnE4x6MK1VQQJnHI8xzDENHEM78lHC93CaZUs95fEd2LY ElSGMSW1276jYz3I5TIlPLhTA7NiWR0FDKbcvAxSSqgauNBDMEAXAEgq4I9LP6rMJ/ R/SjilZ85vy1A== X-Virus-Scanned: amavis at mail.savoirfairelinux.com Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10026) with ESMTP id wmJMJG0matPb; Mon, 9 Nov 2026 08:45:16 -0500 (EST) Received: from isabelle.rennes.sfl (80-15-101-118.ftth.fr.orangecustomers.net [80.15.101.118]) by mail.savoirfairelinux.com (Postfix) with ESMTPSA id B0E913D818F1; Mon, 9 Nov 2026 08:45:15 -0500 (EST) From: Enguerrand de Ribaucourt Date: Mon, 09 Nov 2026 14:44:23 +0100 Subject: [PATCH v2 06/18] devtool: ide-sdk: configure Rust Analyzer for Cargo MIME-Version: 1.0 Message-Id: <20261109-devtool-ide-sdk-cargo-v2-6-d56134000561@savoirfairelinux.com> References: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> In-Reply-To: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer , Enguerrand de Ribaucourt X-Mailer: b4 0.16.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Mon, 09 Nov 2026 13:45:20 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/249833 Point Rust Analyzer at the generated Cargo config and target, while keeping its process environment limited to the recipe PATH. Verify the workspace config path and target in the Cargo selftest. AI-Generated: Uses GitHub Copilot Signed-off-by: Enguerrand de Ribaucourt --- Changes in v2: - Use the Cargo config path generated during common recipe setup. --- meta/lib/oeqa/selftest/cases/devtool.py | 12 +++++++++++- scripts/lib/devtool/ide_plugins/ide_code.py | 10 ++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py index 8e90dba7d0..ee055c218a 100644 --- a/meta/lib/oeqa/selftest/cases/devtool.py +++ b/meta/lib/oeqa/selftest/cases/devtool.py @@ -4341,7 +4341,7 @@ class DevtoolIdeSdkGccTests(DevtoolIdeSdkTests): class DevtoolIdeSdkRustTests(DevtoolIdeSdkTests): - def test_code_cargo_rust_analyzer_recommendation(self): + def test_code_cargo_rust_analyzer_configuration(self): recipe_name = "cargo-example" self._check_workspace() self._write_bb_config() @@ -4349,8 +4349,18 @@ class DevtoolIdeSdkRustTests(DevtoolIdeSdkTests): runCmd('devtool ide-sdk %s oe-selftest-image --ide=code' % recipe_name, output_log=self._cmd_logger) + with open(os.path.join(tempdir, '.vscode', 'settings.json')) as settings_file: + settings = json.load(settings_file) with open(os.path.join(tempdir, '.vscode', 'extensions.json')) as extensions_file: extensions = json.load(extensions_file) + cargo_config = os.path.join( + self.workspacedir, 'ide-sdk', recipe_name, 'cargo-config.toml') + self.assertExists(cargo_config, 'Cargo config was not generated') + self.assertEqual(settings['rust-analyzer.cargo.configPath'], cargo_config) + self.assertEqual( + settings['rust-analyzer.cargo.target'], + get_bb_var('RUST_HOST_SYS', recipe_name)) + self.assertNotIn('rust-analyzer.cargo.extraEnv', settings) self.assertIn('rust-lang.rust-analyzer', extensions['recommendations']) class DevtoolIdeSdkKernelTests(DevtoolIdeSdkTests): diff --git a/scripts/lib/devtool/ide_plugins/ide_code.py b/scripts/lib/devtool/ide_plugins/ide_code.py index cf7f81293c..3cb3a486a2 100644 --- a/scripts/lib/devtool/ide_plugins/ide_code.py +++ b/scripts/lib/devtool/ide_plugins/ide_code.py @@ -228,6 +228,15 @@ class IdeVSCode(IdeBase): } ] + def __vscode_settings_cargo(self, settings_dict, modified_recipe): + if modified_recipe.build_tool is not BuildTool.CARGO: + return + settings_dict["rust-analyzer.server.extraEnv"] = { + "PATH": modified_recipe.path + } + settings_dict["rust-analyzer.cargo.target"] = modified_recipe.cargo_target + settings_dict["rust-analyzer.cargo.configPath"] = modified_recipe.cargo_config_path + def __vscode_settings_clangd(self, settings_dict, modified_recipe): if not (modified_recipe.ide_sdk_intellisense == 'clangd' and modified_recipe.build_tool.is_c_cpp): return @@ -294,6 +303,7 @@ class IdeVSCode(IdeBase): self.__vscode_settings_cmake(settings_dict, modified_recipe) self.__vscode_settings_meson(settings_dict, modified_recipe) self.__vscode_settings_kernel_module(settings_dict, modified_recipe) + self.__vscode_settings_cargo(settings_dict, modified_recipe) self.__vscode_settings_clangd(settings_dict, modified_recipe) self.__vscode_settings_format(settings_dict, modified_recipe) From patchwork Mon Nov 9 13:44:24 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Enguerrand de Ribaucourt X-Patchwork-Id: 103504 Received: from mail.savoirfairelinux.com (mail.savoirfairelinux.com [208.88.110.44]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.6071.1794231918530308727 for ; Mon, 09 Nov 2026 05:45:18 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@savoirfairelinux.com header.s=DFC430D2-D198-11EC-948E-34200CB392D2 header.b=mmdzeA9Y; spf=pass (domain: savoirfairelinux.com, ip: 208.88.110.44, mailfrom: enguerrand.de-ribaucourt@savoirfairelinux.com) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 9F1623D80F35; Mon, 9 Nov 2026 08:45:17 -0500 (EST) Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10032) with ESMTP id u2hjCopsoTvP; Mon, 9 Nov 2026 08:45:16 -0500 (EST) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id CBD113D8176B; Mon, 9 Nov 2026 08:45:16 -0500 (EST) DKIM-Filter: OpenDKIM Filter v2.10.3 mail.savoirfairelinux.com CBD113D8176B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=savoirfairelinux.com; s=DFC430D2-D198-11EC-948E-34200CB392D2; t=1794231916; bh=ybs4iB9sbv0CPzwELY2XDtqVUj4Mdz2hX/fmxtsJ3mA=; h=From:Date:MIME-Version:Message-Id:To; b=mmdzeA9YeZTzg4ZrwM94vh1GfJgKOkGjcigAUJ4iAglTe+4wa3F/PNXekVI1850GB Z1Oo6wgzFQXcN1yI6tML0I51+2ICdl/juKYnV0l2p2r/Apf8XtuNTUKq8CEDUe1824 HTIqo7Dr/naUw6D54M0lM9FMJnM0/hjTTMaAxcGiONmd0T88UFOhC552/d+W5B/IAh vL2D6wjboFdDfy/Wv0K8FozPrLJuOMZHLLAXTkIa2nWCqpkeF8y0P/tgbYgzx4SQQ9 /zc0d0gg7878QNfnAlDO72e24R6MQvJupfRgw0fnR1gyfSmpDWRtSVcICo8sgDtR7s yOZ7tTrnvK16w== X-Virus-Scanned: amavis at mail.savoirfairelinux.com Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10026) with ESMTP id eMQADSEoFd3L; Mon, 9 Nov 2026 08:45:16 -0500 (EST) Received: from isabelle.rennes.sfl (80-15-101-118.ftth.fr.orangecustomers.net [80.15.101.118]) by mail.savoirfairelinux.com (Postfix) with ESMTPSA id 4AC463D81892; Mon, 9 Nov 2026 08:45:16 -0500 (EST) From: Enguerrand de Ribaucourt Date: Mon, 09 Nov 2026 14:44:24 +0100 Subject: [PATCH v2 07/18] devtool: ide-sdk: generalize binary install task name MIME-Version: 1.0 Message-Id: <20261109-devtool-ide-sdk-cargo-v2-7-d56134000561@savoirfairelinux.com> References: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> In-Reply-To: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer , Enguerrand de Ribaucourt X-Mailer: b4 0.16.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Mon, 09 Nov 2026 13:45:20 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/249834 Rename the C++-specific generator to describe its install/deploy behavior. The upcoming Cargo task builds outside BitBake and will reuse this helper to install and deploy the resulting recipe artifacts. AI-Generated: Uses GitHub Copilot Signed-off-by: Enguerrand de Ribaucourt --- scripts/lib/devtool/ide_plugins/ide_code.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/lib/devtool/ide_plugins/ide_code.py b/scripts/lib/devtool/ide_plugins/ide_code.py index 3cb3a486a2..9ee403f506 100644 --- a/scripts/lib/devtool/ide_plugins/ide_code.py +++ b/scripts/lib/devtool/ide_plugins/ide_code.py @@ -661,7 +661,7 @@ class IdeVSCode(IdeBase): IdeBase.update_json_file( self.dot_code_dir(modified_recipe), launch_file, launch_dict) - def vscode_tasks_cpp(self, args, image_recipe, modified_recipe): + def vscode_tasks_binary(self, args, image_recipe, modified_recipe): run_install_deploy = modified_recipe.gen_install_deploy_script(args, image_recipe.nfs_deploy_dir) install_task_name = "install && deploy-target %s" % modified_recipe.recipe_id_pretty deploy_args = ["--target", resolve_deploy_target(args, image_recipe.nfs_deploy_dir)] @@ -963,7 +963,7 @@ class IdeVSCode(IdeBase): def vscode_tasks(self, args, image_recipe, modified_recipe): if modified_recipe.build_tool.is_c_cpp: - self.vscode_tasks_cpp(args, image_recipe, modified_recipe) + self.vscode_tasks_binary(args, image_recipe, modified_recipe) elif modified_recipe.build_tool == BuildTool.KERNEL_MODULE: self.vscode_tasks_kernel_module(args, image_recipe, modified_recipe) else: From patchwork Mon Nov 9 13:44:25 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Enguerrand de Ribaucourt X-Patchwork-Id: 103505 Received: from mail.savoirfairelinux.com (mail.savoirfairelinux.com [208.88.110.44]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.6193.1794231919162663062 for ; Mon, 09 Nov 2026 05:45:19 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@savoirfairelinux.com header.s=DFC430D2-D198-11EC-948E-34200CB392D2 header.b=hgx4EWtG; spf=pass (domain: savoirfairelinux.com, ip: 208.88.110.44, mailfrom: enguerrand.de-ribaucourt@savoirfairelinux.com) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 43B9C3D818F1; Mon, 9 Nov 2026 08:45:18 -0500 (EST) Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10032) with ESMTP id 6Wc3DC6aD--G; Mon, 9 Nov 2026 08:45:17 -0500 (EST) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 63DF03D81892; Mon, 9 Nov 2026 08:45:17 -0500 (EST) DKIM-Filter: OpenDKIM Filter v2.10.3 mail.savoirfairelinux.com 63DF03D81892 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=savoirfairelinux.com; s=DFC430D2-D198-11EC-948E-34200CB392D2; t=1794231917; bh=ve+tP6XfxLxAdZawjPv73T8g7p0gCjUNATn/XNsuNU0=; h=From:Date:MIME-Version:Message-Id:To; b=hgx4EWtGJYXE8uHR2H0s1CQdfLlpvej2DBpVkiF9KytYfVCWl7gplqrsmSWjCsv9o 3MiR7iu27fKEYlGff4LTZICJP6PoF7+9nnFHW8jvqbIYjmaD3vICLdfctV7PY30U6Q voB3lgGjRsEYTwWdy6xs3lvxnOTnmkYGPrUMd0VFX6KSAAtgLYtB3I7MEtEo5SQlmA xPX1oaMAtIqBSkJEI405wBsVj7kXvfwDwbsjqr352hqOehwh39odcOlvtj0udPmeBd xlxHzFoJDi9Llp5vZXkeBBuxsrmrhGjCeKFtI67V0jwug6JbeW6orHV3QvkwxWm8tD aK+DOBG+E0t4g== X-Virus-Scanned: amavis at mail.savoirfairelinux.com Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10026) with ESMTP id vthtN0GgLXIF; Mon, 9 Nov 2026 08:45:17 -0500 (EST) Received: from isabelle.rennes.sfl (80-15-101-118.ftth.fr.orangecustomers.net [80.15.101.118]) by mail.savoirfairelinux.com (Postfix) with ESMTPSA id DC3E53D818FC; Mon, 9 Nov 2026 08:45:16 -0500 (EST) From: Enguerrand de Ribaucourt Date: Mon, 09 Nov 2026 14:44:25 +0100 Subject: [PATCH v2 08/18] devtool: ide-sdk: extract install task definition MIME-Version: 1.0 Message-Id: <20261109-devtool-ide-sdk-cargo-v2-8-d56134000561@savoirfairelinux.com> References: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> In-Reply-To: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer , Enguerrand de Ribaucourt X-Mailer: b4 0.16.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Mon, 09 Nov 2026 13:45:20 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/249835 Extract the install/deploy task object before adding optional dependencies. This preserves existing task output and provides a shared insertion point for Cargo build/deploy ordering. AI-Generated: Uses GitHub Copilot Signed-off-by: Enguerrand de Ribaucourt --- scripts/lib/devtool/ide_plugins/ide_code.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/scripts/lib/devtool/ide_plugins/ide_code.py b/scripts/lib/devtool/ide_plugins/ide_code.py index 9ee403f506..491e74f764 100644 --- a/scripts/lib/devtool/ide_plugins/ide_code.py +++ b/scripts/lib/devtool/ide_plugins/ide_code.py @@ -669,17 +669,16 @@ class IdeVSCode(IdeBase): deploy_args += ["--port", args.port] for package in args.package or []: deploy_args += ["--package", package] + install_task = { + "label": install_task_name, + "type": "shell", + "command": run_install_deploy, + "args": deploy_args, + "problemMatcher": [] + } tasks_dict = { "version": "2.0.0", - "tasks": [ - { - "label": install_task_name, - "type": "shell", - "command": run_install_deploy, - "args": deploy_args, - "problemMatcher": [] - } - ] + "tasks": [install_task] } for cross_debug_config in self.cross_debug_configs: if cross_debug_config.modified_recipe is not modified_recipe: From patchwork Mon Nov 9 13:44:26 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Enguerrand de Ribaucourt X-Patchwork-Id: 103506 Received: from mail.savoirfairelinux.com (mail.savoirfairelinux.com [208.88.110.44]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.6072.1794231919766389743 for ; Mon, 09 Nov 2026 05:45:19 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@savoirfairelinux.com header.s=DFC430D2-D198-11EC-948E-34200CB392D2 header.b=WD/ul8ql; spf=pass (domain: savoirfairelinux.com, ip: 208.88.110.44, mailfrom: enguerrand.de-ribaucourt@savoirfairelinux.com) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id D6FDA3D818FB; Mon, 9 Nov 2026 08:45:18 -0500 (EST) Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10032) with ESMTP id Ga2AW1jOg9MW; Mon, 9 Nov 2026 08:45:18 -0500 (EST) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id F2DCB3D8176B; Mon, 9 Nov 2026 08:45:17 -0500 (EST) DKIM-Filter: OpenDKIM Filter v2.10.3 mail.savoirfairelinux.com F2DCB3D8176B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=savoirfairelinux.com; s=DFC430D2-D198-11EC-948E-34200CB392D2; t=1794231918; bh=ggrICKcqJpwvEvdCEqbIQ188VgfvuF93H5tzfpK++ZI=; h=From:Date:MIME-Version:Message-Id:To; b=WD/ul8qlsV0KhPmYYsOvl/nITY+v5rMMSw8WEuD5ANvJEJ4kRfFpUpBM2cPsOCVBi AWnDjxKuhpXNKLO9QcWRWLJsvAcl+T4aw9tmCMbdbEEWTHW1jsA5O8faURpe9kvBT3 GVt5QjBv1aP5DlmQdBgk0FYSR0vnk5UJ13qsD8yrtpXgc6O4iznikX8TxLid49saHH 5SN/z10I44FJajI0TOoN1W/r3WLspXkKYz49ea+mRUrT0DHMV+HfQDSd+VBwv5zH2+ jkRYupBD+0U4uI40EkvChYYmVtuwO5IM5dMLEVVaMiuzELF475bLpV0oQH2gIS5IYk 5V0BpP0dVE7Xg== X-Virus-Scanned: amavis at mail.savoirfairelinux.com Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10026) with ESMTP id VUg4GAK3UqY6; Mon, 9 Nov 2026 08:45:17 -0500 (EST) Received: from isabelle.rennes.sfl (80-15-101-118.ftth.fr.orangecustomers.net [80.15.101.118]) by mail.savoirfairelinux.com (Postfix) with ESMTPSA id 750223D818F3; Mon, 9 Nov 2026 08:45:17 -0500 (EST) From: Enguerrand de Ribaucourt Date: Mon, 09 Nov 2026 14:44:26 +0100 Subject: [PATCH v2 09/18] devtool: ide-sdk: order install after optional build task MIME-Version: 1.0 Message-Id: <20261109-devtool-ide-sdk-cargo-v2-9-d56134000561@savoirfairelinux.com> References: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> In-Reply-To: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer , Enguerrand de Ribaucourt X-Mailer: b4 0.16.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Mon, 09 Nov 2026 13:45:20 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/249836 Let binary task generation optionally insert a build task and make install/deploy depend on it. Cargo builds outside BitBake, so this ordering ensures its artifacts exist before do_install and deploy-target run. AI-Generated: Uses GitHub Copilot Signed-off-by: Enguerrand de Ribaucourt --- Changes in v2: - Fix install-task duplication while adding build-before-install ordering. --- scripts/lib/devtool/ide_plugins/ide_code.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/scripts/lib/devtool/ide_plugins/ide_code.py b/scripts/lib/devtool/ide_plugins/ide_code.py index 491e74f764..5d35be4f52 100644 --- a/scripts/lib/devtool/ide_plugins/ide_code.py +++ b/scripts/lib/devtool/ide_plugins/ide_code.py @@ -661,7 +661,7 @@ class IdeVSCode(IdeBase): IdeBase.update_json_file( self.dot_code_dir(modified_recipe), launch_file, launch_dict) - def vscode_tasks_binary(self, args, image_recipe, modified_recipe): + def vscode_tasks_binary(self, args, image_recipe, modified_recipe, build_task=None): run_install_deploy = modified_recipe.gen_install_deploy_script(args, image_recipe.nfs_deploy_dir) install_task_name = "install && deploy-target %s" % modified_recipe.recipe_id_pretty deploy_args = ["--target", resolve_deploy_target(args, image_recipe.nfs_deploy_dir)] @@ -669,6 +669,7 @@ class IdeVSCode(IdeBase): deploy_args += ["--port", args.port] for package in args.package or []: deploy_args += ["--package", package] + tasks = [build_task] if build_task else [] install_task = { "label": install_task_name, "type": "shell", @@ -676,9 +677,13 @@ class IdeVSCode(IdeBase): "args": deploy_args, "problemMatcher": [] } + if build_task: + install_task["dependsOn"] = [build_task["label"]] + install_task["dependsOrder"] = "sequence" + tasks.append(install_task) tasks_dict = { "version": "2.0.0", - "tasks": [install_task] + "tasks": tasks } for cross_debug_config in self.cross_debug_configs: if cross_debug_config.modified_recipe is not modified_recipe: From patchwork Mon Nov 9 13:44:27 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Enguerrand de Ribaucourt X-Patchwork-Id: 103511 Received: from mail.savoirfairelinux.com (mail.savoirfairelinux.com [208.88.110.44]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.6073.1794231920870953585 for ; Mon, 09 Nov 2026 05:45:21 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@savoirfairelinux.com header.s=DFC430D2-D198-11EC-948E-34200CB392D2 header.b=YAFMWRfG; spf=pass (domain: savoirfairelinux.com, ip: 208.88.110.44, mailfrom: enguerrand.de-ribaucourt@savoirfairelinux.com) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id F1C9C3D818F4; Mon, 9 Nov 2026 08:45:19 -0500 (EST) Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10032) with ESMTP id PVQWd0n2fZyG; Mon, 9 Nov 2026 08:45:18 -0500 (EST) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 8F9213D8182D; Mon, 9 Nov 2026 08:45:18 -0500 (EST) DKIM-Filter: OpenDKIM Filter v2.10.3 mail.savoirfairelinux.com 8F9213D8182D DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=savoirfairelinux.com; s=DFC430D2-D198-11EC-948E-34200CB392D2; t=1794231918; bh=95lPpieJfcewwPvyTS3MuZ7vdKV/OxxKwNkzLHT/rNI=; h=From:Date:MIME-Version:Message-Id:To; b=YAFMWRfGeHrx65Ezkt7lt5O/DKgs5Yyg5Q0Z1oeXGcXf4j0jyWkLieziWALckQP00 Mj4/CbaDf+nWrF0OVUuNege14DZ2yPTv0C4bnlW1/CBBT2aHbO0TDleXBubeRqpSQ+ U216biQF6O5yQfJ/M6OPBOPVPUbK8GEo7SkvBdbOMb0xFVge/dc2svFWutD3GyOMKP ujqlG6U+1C1FUMdo3citaawMO94FIXA/CZTEawFM+ri4t8xdZTduMolTXtRtVDn4Vm I/eaQjRi+QvfTO5iyTogRogpwSIlsz+mhEcVfu45Q87A+lfDhT9D+Ld7WqIOM69WMl rV6VE7B279HsQ== X-Virus-Scanned: amavis at mail.savoirfairelinux.com Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10026) with ESMTP id hm_ujEmM6D7H; Mon, 9 Nov 2026 08:45:18 -0500 (EST) Received: from isabelle.rennes.sfl (80-15-101-118.ftth.fr.orangecustomers.net [80.15.101.118]) by mail.savoirfairelinux.com (Postfix) with ESMTPSA id 0E7613D818FB; Mon, 9 Nov 2026 08:45:17 -0500 (EST) From: Enguerrand de Ribaucourt Date: Mon, 09 Nov 2026 14:44:27 +0100 Subject: [PATCH v2 10/18] devtool: ide-sdk: add Cargo build task MIME-Version: 1.0 Message-Id: <20261109-devtool-ide-sdk-cargo-v2-10-d56134000561@savoirfairelinux.com> References: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> In-Reply-To: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer , Enguerrand de Ribaucourt X-Mailer: b4 0.16.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Mon, 09 Nov 2026 13:45:21 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/249837 Generate a Cargo build task that uses the exported recipe config and build flags. Run it in the recipe source tree with only the SDK PATH so Cargo uses the cross environment captured for the recipe. AI-Generated: Uses GitHub Copilot Signed-off-by: Enguerrand de Ribaucourt --- Changes in v2: - Use the rustc problem matcher for Cargo build diagnostics. --- meta/lib/oeqa/selftest/cases/devtool.py | 38 +++++++++++++++++++++++++++++ scripts/lib/devtool/ide_plugins/ide_code.py | 25 +++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py index ee055c218a..ef13eaa09a 100644 --- a/meta/lib/oeqa/selftest/cases/devtool.py +++ b/meta/lib/oeqa/selftest/cases/devtool.py @@ -4363,6 +4363,44 @@ class DevtoolIdeSdkRustTests(DevtoolIdeSdkTests): self.assertNotIn('rust-analyzer.cargo.extraEnv', settings) self.assertIn('rust-lang.rust-analyzer', extensions['recommendations']) + def test_code_cargo_build_task(self): + recipe_name = "cargo-example" + self._check_workspace() + self._write_bb_config() + tempdir = self._devtool_ide_sdk_recipe(recipe_name, "Cargo.toml", None) + runCmd('devtool ide-sdk %s oe-selftest-image --ide=code ' + '--target root@localhost --no-host-check' % recipe_name, + output_log=self._cmd_logger) + + with open(os.path.join(tempdir, '.vscode', 'tasks.json')) as tasks_file: + tasks = json.load(tasks_file)['tasks'] + build_task = next(task for task in tasks + if task['label'].startswith('cargo build ')) + cargo_config = os.path.join( + self.workspacedir, 'ide-sdk', recipe_name, 'cargo-config.toml') + self.assertEqual(build_task['command'], get_bb_var('CARGO', recipe_name)) + self.assertEqual( + build_task['args'][:3], ['--config', cargo_config, 'build']) + self.assertIn('--features', build_task['args']) + self.assertIn('ide-sdk-selftest', build_task['args']) + self.assertEqual(set(build_task['options']['env']), {'PATH'}) + self.assertEqual(build_task['problemMatcher'], '$rustc') + + build_env = os.environ.copy() + build_env.update(build_task['options']['env']) + result = subprocess.run( + [build_task['command']] + build_task['args'], + cwd=build_task['options']['cwd'], env=build_env, + stdout=subprocess.PIPE, stderr=subprocess.STDOUT, + universal_newlines=True) + self.assertEqual(result.returncode, 0, result.stdout) + + install_task = next( + task for task in tasks + if task['label'].startswith('install && deploy-target ')) + self.assertEqual(install_task['dependsOn'], [build_task['label']]) + + class DevtoolIdeSdkKernelTests(DevtoolIdeSdkTests): @OETestTag("runqemu") diff --git a/scripts/lib/devtool/ide_plugins/ide_code.py b/scripts/lib/devtool/ide_plugins/ide_code.py index 5d35be4f52..cb54948ce1 100644 --- a/scripts/lib/devtool/ide_plugins/ide_code.py +++ b/scripts/lib/devtool/ide_plugins/ide_code.py @@ -8,6 +8,7 @@ import json import logging import os +import shlex import shutil from devtool.ide_plugins import BuildTool, IdeBase, GdbCrossConfig, DebuggerServerModes, LldbServerConfig, get_devtool_deploy_opts, resolve_deploy_target @@ -832,6 +833,28 @@ class IdeVSCode(IdeBase): IdeBase.update_json_file( self.dot_code_dir(modified_recipe), tasks_file, tasks_dict) + def vscode_tasks_cargo(self, args, image_recipe, modified_recipe): + build_task_name = "cargo build %s" % modified_recipe.recipe_id_pretty + cargo_config = modified_recipe.cargo_config_path + build_task = { + "label": build_task_name, + "type": "shell", + "command": modified_recipe.cargo, + "args": ["--config", cargo_config, "build"] + + shlex.split(modified_recipe.cargo_build_flags) + + shlex.split(modified_recipe.cargo_packageconfig_confargs), + "options": { + "cwd": modified_recipe.real_srctree, + "env": {"PATH": modified_recipe.path}, + }, + "group": { + "kind": "build", + "isDefault": True + }, + "problemMatcher": "$rustc" + } + self.vscode_tasks_binary(args, image_recipe, modified_recipe, build_task) + def vscode_tasks_fallback(self, args, image_recipe, modified_recipe): oe_init_dir = modified_recipe.oe_init_dir oe_init = ". %s %s > /dev/null && " % (modified_recipe.oe_init_build_env, modified_recipe.topdir) @@ -970,6 +993,8 @@ class IdeVSCode(IdeBase): self.vscode_tasks_binary(args, image_recipe, modified_recipe) elif modified_recipe.build_tool == BuildTool.KERNEL_MODULE: self.vscode_tasks_kernel_module(args, image_recipe, modified_recipe) + elif modified_recipe.build_tool == BuildTool.CARGO: + self.vscode_tasks_cargo(args, image_recipe, modified_recipe) else: self.vscode_tasks_fallback(args, image_recipe, modified_recipe) From patchwork Mon Nov 9 13:44:28 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Enguerrand de Ribaucourt X-Patchwork-Id: 103512 Received: from mail.savoirfairelinux.com (mail.savoirfairelinux.com [208.88.110.44]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.6195.1794231922105908864 for ; Mon, 09 Nov 2026 05:45:22 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@savoirfairelinux.com header.s=DFC430D2-D198-11EC-948E-34200CB392D2 header.b=PB3EDCqX; spf=pass (domain: savoirfairelinux.com, ip: 208.88.110.44, mailfrom: enguerrand.de-ribaucourt@savoirfairelinux.com) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 39A493D818F1; Mon, 9 Nov 2026 08:45:21 -0500 (EST) Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10032) with ESMTP id JpsBJqaZXm2e; Mon, 9 Nov 2026 08:45:19 -0500 (EST) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 29B5B3D8176B; Mon, 9 Nov 2026 08:45:19 -0500 (EST) DKIM-Filter: OpenDKIM Filter v2.10.3 mail.savoirfairelinux.com 29B5B3D8176B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=savoirfairelinux.com; s=DFC430D2-D198-11EC-948E-34200CB392D2; t=1794231919; bh=YMNWfkvU6mN8rFoxBgDxgdJ5jCwjbaLv6flmzW0CHL8=; h=From:Date:MIME-Version:Message-Id:To; b=PB3EDCqXYGcwA5Uyo0BZQAj8vMvVINSlU4zFgzwF6ONGo+wpLzt1HxwTnziHwqwkn JGqcLVQbhERwPref0d5Hu+Y8KDRY2BSyNlKkEVTXHO1vc2YAHRlqgmBRACLojtHQcI dukOoj3cBVY/0iN94SY5sRqTDL8WN/xovnNWU+q+0x3Wneb9fLNxfcowWG+HzIw1D6 OWmBJCF8Qr0S3vZGoip3wKg4E8cpvcKkaK0WVluLGT8erNnTERWAiCCYo7W3iMYHTb 1QxO5XvPUe5YpQrUwNk0ShWgB6+uhlFrE21G0GZ3ONkbYiTWONA2JEZVORHDLd3Xwu UMxdjl2qlOIcw== X-Virus-Scanned: amavis at mail.savoirfairelinux.com Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10026) with ESMTP id 5_GFrKgIri4P; Mon, 9 Nov 2026 08:45:19 -0500 (EST) Received: from isabelle.rennes.sfl (80-15-101-118.ftth.fr.orangecustomers.net [80.15.101.118]) by mail.savoirfairelinux.com (Postfix) with ESMTPSA id 9C93C3D81892; Mon, 9 Nov 2026 08:45:18 -0500 (EST) From: Enguerrand de Ribaucourt Date: Mon, 09 Nov 2026 14:44:28 +0100 Subject: [PATCH v2 11/18] devtool: ide-sdk: enforce LLDB for Cargo MIME-Version: 1.0 Message-Id: <20261109-devtool-ide-sdk-cargo-v2-11-d56134000561@savoirfairelinux.com> References: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> In-Reply-To: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer , Enguerrand de Ribaucourt X-Mailer: b4 0.16.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Mon, 09 Nov 2026 13:45:31 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/249838 Route Cargo debugging through CodeLLDB and lldb-server because GDB/cppdbg does not resolve Rust function breakpoints in the VS Code Rust workflow. Cargo debugging always uses LLDB, regardless of the recipe C/C++ toolchain. Key shared debugger instances by backend rather than TOOLCHAIN so Rust recipes use the correct server while ordinary GCC recipes retain GDB. Cargo C++ IntelliSense still uses the recipe compiler. This follows VS Code's recommended Rust workflow: https://code.visualstudio.com/docs/languages/rust#_debugging AI-Generated: Uses GitHub Copilot Signed-off-by: Enguerrand de Ribaucourt --- Changes in v2: - Cover LLDB configuration when using --ide=none. - Explain GDB's Rust function breakpoint limitations. --- meta/lib/oeqa/selftest/cases/devtool.py | 35 +++++++++++++++++++++++++++ scripts/lib/devtool/ide_plugins/ide_code.py | 7 ++++-- scripts/lib/devtool/ide_plugins/ide_none.py | 4 ++-- scripts/lib/devtool/ide_sdk.py | 37 +++++++++++++++++++---------- 4 files changed, 66 insertions(+), 17 deletions(-) diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py index ef13eaa09a..3b80d6a4a8 100644 --- a/meta/lib/oeqa/selftest/cases/devtool.py +++ b/meta/lib/oeqa/selftest/cases/devtool.py @@ -4363,6 +4363,41 @@ class DevtoolIdeSdkRustTests(DevtoolIdeSdkTests): self.assertNotIn('rust-analyzer.cargo.extraEnv', settings) self.assertIn('rust-lang.rust-analyzer', extensions['recommendations']) + def test_cargo_lldb_configuration(self): + recipe_name = "cargo-example" + self._check_workspace() + self._write_bb_config() + tempdir = self._devtool_ide_sdk_recipe(recipe_name, "Cargo.toml", None) + runCmd('devtool ide-sdk %s oe-selftest-image --ide=code --ide=none ' + '--target root@localhost --no-host-check' % recipe_name, + output_log=self._cmd_logger) + + with open(os.path.join(tempdir, '.vscode', 'extensions.json')) as extensions_file: + extensions = json.load(extensions_file) + with open(os.path.join(tempdir, '.vscode', 'launch.json')) as launch_file: + launch = json.load(launch_file)['configurations'][0] + with open(os.path.join(tempdir, '.vscode', 'tasks.json')) as tasks_file: + tasks = json.load(tasks_file)['tasks'] + + self.assertIn('vadimcn.vscode-lldb', extensions['recommendations']) + self.assertEqual(launch['type'], 'lldb') + + scripts_dir = self._workspace_scripts_dir(recipe_name) + scripts = os.listdir(scripts_dir) + self.assertTrue(any(name.startswith('lldb_server_') for name in scripts)) + self.assertFalse(any(name.startswith('gdbserver_') for name in scripts)) + self._verify_install_script_code(tempdir, recipe_name) + cargo_config = os.path.join( + self.workspacedir, 'ide-sdk', recipe_name, 'cargo-config.toml') + self.assertExists( + cargo_config, 'Cargo config was not generated for --ide=none') + target_dbgsrc_dir = get_bb_var('TARGET_DBGSRC_DIR', recipe_name) + self.assertEqual( + launch['sourceMap'][target_dbgsrc_dir], os.path.realpath(tempdir)) + server_task = next( + task for task in tasks if task['label'] == launch['preLaunchTask']) + self.assertIn('lldb-server platform --server', server_task['args'][-1]) + def test_code_cargo_build_task(self): recipe_name = "cargo-example" self._check_workspace() diff --git a/scripts/lib/devtool/ide_plugins/ide_code.py b/scripts/lib/devtool/ide_plugins/ide_code.py index cb54948ce1..a7bb3221e0 100644 --- a/scripts/lib/devtool/ide_plugins/ide_code.py +++ b/scripts/lib/devtool/ide_plugins/ide_code.py @@ -315,7 +315,10 @@ class IdeVSCode(IdeBase): def vscode_extensions(self, modified_recipe): recommendations = [] if modified_recipe.build_tool is BuildTool.CARGO: - recommendations.append("rust-lang.rust-analyzer") + recommendations += [ + "rust-lang.rust-analyzer", + "vadimcn.vscode-lldb" + ] # clangd (matched to the recipe's real cross compiler via # compile_commands.json) replaces cpptools as the IntelliSense provider # when selected via IDE_SDK_INTELLISENSE (defaults to clangd for the @@ -1003,7 +1006,7 @@ class IdeVSCode(IdeBase): self.vscode_extensions(modified_recipe) self.vscode_c_cpp_properties(modified_recipe, image_recipe) if args.target: - if modified_recipe.toolchain == 'clang': + if modified_recipe.uses_lldb: self.initialize_cross_debug_configs( image_recipe, modified_recipe, LldbServerConfigVSCode) else: diff --git a/scripts/lib/devtool/ide_plugins/ide_none.py b/scripts/lib/devtool/ide_plugins/ide_none.py index eba576bfdb..d2f66ade8d 100644 --- a/scripts/lib/devtool/ide_plugins/ide_none.py +++ b/scripts/lib/devtool/ide_plugins/ide_none.py @@ -306,13 +306,13 @@ class IdeNone(IdeBase): - Execute the do_install task - Execute devtool deploy-target - - Generate a gdbinit file per executable + - Generate debugger configuration for each executable - Generate the oe-scripts sym-link """ script_path = modified_recipe.gen_install_deploy_script(args, image_recipe.nfs_deploy_dir) logger.info("Created: %s" % script_path) - if modified_recipe.toolchain == 'clang': + if modified_recipe.uses_lldb: self.initialize_cross_debug_configs( image_recipe, modified_recipe, LldbServerConfigNone) else: diff --git a/scripts/lib/devtool/ide_sdk.py b/scripts/lib/devtool/ide_sdk.py index 98e39703e7..0ce2a7780e 100755 --- a/scripts/lib/devtool/ide_sdk.py +++ b/scripts/lib/devtool/ide_sdk.py @@ -406,11 +406,11 @@ class RecipeImage: resulting bbappend content actually differs from what was on disk when initialize() ran, False if it is left exactly as it was. """ - wants_gdbserver = any( - r.wants_gdbserver and r.toolchain != 'clang' - for r in recipes_modified) wants_lldb_server = any( - r.wants_gdbserver and r.toolchain == 'clang' + r.wants_gdbserver and r.uses_lldb + for r in recipes_modified) + wants_gdbserver = any( + r.wants_gdbserver and not r.uses_lldb for r in recipes_modified) # Only add what the base configuration (e.g. local.conf) does not @@ -1158,6 +1158,16 @@ class RecipeModified: self.recipe_id = self.bpn + "-" + self.package_arch self.recipe_id_pretty = self.bpn + ": " + self.package_arch + @property + def uses_lldb(self): + # VS Code's Rust debugging guide recommends CodeLLDB: + # https://code.visualstudio.com/docs/languages/rust#_debugging + # ide-sdk supports Rust debugging only through CodeLLDB; cppdbg/GDB + # does not resolve Rust function breakpoints from the VS Code UI because + # GDB does not fully understand Rust's LLVM-generated function layout + # and name mangling. + return self.toolchain == 'clang' or self.build_tool is BuildTool.CARGO + @property def cargo_config_path(self): return os.path.join(self.ide_sdk_dir, 'cargo-config.toml') @@ -2048,20 +2058,21 @@ def ide_setup(args, config, basepath, workspace): bootstrap_tasks += recipe_modified.bootstrap_tasks recipes_modified.append(recipe_modified) - # Key by (arch, toolchain) so recipes with different toolchains - # targeting the same arch each get the right debugger. + # Key by (arch, debugger) so recipes sharing an architecture + # but using different debugger backends each get the right one. + debugger = 'lldb' if recipe_modified.uses_lldb else 'gdb' debugger_key = (recipe_modified.target_arch, - recipe_modified.toolchain or '') + debugger) if debugger_key not in debuggers: target_device = TargetDevice(args) - if recipe_modified.toolchain == 'clang': - debugger = RecipeLldbNative(args, target_device) + if recipe_modified.uses_lldb: + debugger_config = RecipeLldbNative(args, target_device) else: - debugger = RecipeGdbCross( + debugger_config = RecipeGdbCross( args, recipe_modified.target_arch, target_device) - debugger.initialize(config, workspace, tinfoil) - bootstrap_tasks += debugger.bootstrap_tasks - debuggers[debugger_key] = debugger + debugger_config.initialize(config, workspace, tinfoil) + bootstrap_tasks += debugger_config.bootstrap_tasks + debuggers[debugger_key] = debugger_config recipe_modified.debugger_cross = debuggers[debugger_key] finally: From patchwork Mon Nov 9 13:44:29 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Enguerrand de Ribaucourt X-Patchwork-Id: 103515 Received: from mail.savoirfairelinux.com (mail.savoirfairelinux.com [208.88.110.44]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.6074.1794231922196809365 for ; Mon, 09 Nov 2026 05:45:22 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@savoirfairelinux.com header.s=DFC430D2-D198-11EC-948E-34200CB392D2 header.b=UCC5hUlH; spf=pass (domain: savoirfairelinux.com, ip: 208.88.110.44, mailfrom: enguerrand.de-ribaucourt@savoirfairelinux.com) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 4CEB13D8176B; Mon, 9 Nov 2026 08:45:21 -0500 (EST) Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10032) with ESMTP id DvbqVrQqfGnF; Mon, 9 Nov 2026 08:45:20 -0500 (EST) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id E94593D818F3; Mon, 9 Nov 2026 08:45:19 -0500 (EST) DKIM-Filter: OpenDKIM Filter v2.10.3 mail.savoirfairelinux.com E94593D818F3 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=savoirfairelinux.com; s=DFC430D2-D198-11EC-948E-34200CB392D2; t=1794231920; bh=TJbL/Ug0+0fZ8oQ5yp5cr/FU1qS8tHB2OChIVDVKqQg=; h=From:Date:MIME-Version:Message-Id:To; b=UCC5hUlH6qbS369AWMaBedWa4EqXAmN8AW1sR/8osRybvpfYygajTsLwkJbW/lhvW C6tWy4SQlEj+0Uk7JhGsK7o0fNP1jQVR7Zo97mQQuT5X3GkvxMaXNP0G/FIOT8Agw5 WsyYTkboir7UjHHOWPVmapj974XL833YiYI4OCSp7yPUTBP9NvAO7XQE/cOXPublYv oi4MI9ks+i/36+H6wtPSIVz+maml/hfhnnprj97gXJg/A+OctByWmgOIruJyKnlKJM YuUfiVhKjueJQ+oHYQk2Hjv5l8g5kGsmqokcsjq6zuAqXOwmjRVGenDxPqXT1yVP5Q H4Lac6JgAJVcg== X-Virus-Scanned: amavis at mail.savoirfairelinux.com Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10026) with ESMTP id l15F38LbneYF; Mon, 9 Nov 2026 08:45:19 -0500 (EST) Received: from isabelle.rennes.sfl (80-15-101-118.ftth.fr.orangecustomers.net [80.15.101.118]) by mail.savoirfairelinux.com (Postfix) with ESMTPSA id 36AA93D818FC; Mon, 9 Nov 2026 08:45:19 -0500 (EST) From: Enguerrand de Ribaucourt Date: Mon, 09 Nov 2026 14:44:29 +0100 Subject: [PATCH v2 12/18] devtool: ide-sdk: remap Cargo sources for BitBake builds MIME-Version: 1.0 Message-Id: <20261109-devtool-ide-sdk-cargo-v2-12-d56134000561@savoirfairelinux.com> References: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> In-Reply-To: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer , Enguerrand de Ribaucourt X-Mailer: b4 0.16.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Mon, 09 Nov 2026 13:45:32 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/249839 With devtool modify, Cargo sources can live outside WORKDIR, so the standard Rust remaps leave the workspace path in DWARF and package QA rejects the debug package. Append a workspace-specific remap to RUST_DEBUG_REMAP in a managed bbappend section so repeated ide-sdk runs restore and reparse it. AI-Generated: Uses GitHub Copilot --- Changes in v2: - Revert bbappend comparison after stripping managed sections to avoid reparse when the ide-sdk section is not modified. I think there is a pre-existing bug with that logic however. An ide-sdk re-run leaves the stripped bbappend for clang and cargo classes. As a consequence, I simplified the Qemu selftest to no longer run ide-sdk twice. --- scripts/lib/devtool/ide_sdk.py | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/scripts/lib/devtool/ide_sdk.py b/scripts/lib/devtool/ide_sdk.py index 0ce2a7780e..5096297b32 100755 --- a/scripts/lib/devtool/ide_sdk.py +++ b/scripts/lib/devtool/ide_sdk.py @@ -831,6 +831,7 @@ class RecipeModified: VALID_BASH_ENV_NAME_CHARS = re.compile(r"^[a-zA-Z0-9_]*$") MARKER = '# devtool ide-sdk: clangd toolchain support' + CARGO_REMAP_MARKER = '# devtool ide-sdk: Cargo source debug remap' # PROVIDES of recipes that are deployed via do_deploy (e.g. to # DEPLOY_DIR_IMAGE) rather than installed into the rootfs, so adding them @@ -951,13 +952,14 @@ class RecipeModified: content = f.read() originals[name] = content stripped = cls._strip_marker_section(content, cls.MARKER) + stripped = cls._strip_marker_section(stripped, cls.CARGO_REMAP_MARKER) if stripped != content: with open(bbappend, 'w') as f: f.write(stripped) return originals def update_bbappend(self): - """Add DEPENDS on clang-native when clangd is used as only the IntelliSense engine""" + """Add workspace-only clang dependencies or Cargo debug path remaps.""" wants_clang_native = ( self.build_tool.is_c_cpp and self.ide_sdk_intellisense == 'clangd' @@ -970,17 +972,27 @@ class RecipeModified: else: parsed_content = '' - if not wants_clang_native: + new_sections = [] + if wants_clang_native: + new_sections.append( + self.MARKER + '\nDEPENDS:append = " clang-native"\n') + if self.build_tool is BuildTool.CARGO: + new_sections.append( + self.CARGO_REMAP_MARKER + + '\nRUST_DEBUG_REMAP:append = " ' + '--remap-path-prefix=${S}=${TARGET_DBGSRC_DIR}"\n') + + if not new_sections: if self.MARKER in original_content: logger.info( "Removed clangd toolchain support from %s: no longer needed", self.bbappend) return False - new_section = self.MARKER + '\nDEPENDS:append = " clang-native"\n' new_content = parsed_content - if new_content and not new_content.endswith('\n'): - new_content += '\n' - new_content += new_section + for section in new_sections: + if new_content and not new_content.endswith('\n'): + new_content += '\n' + new_content += section if new_content == original_content: return False @@ -989,9 +1001,13 @@ class RecipeModified: os.makedirs(appends_dir, exist_ok=True) with open(self.bbappend, 'w') as f: f.write(new_content) - logger.info( - "Updated %s: added DEPENDS on clang-native, needed to stage clangd " - "for IDE_SDK_INTELLISENSE=\"clangd\"", self.bbappend) + if wants_clang_native: + logger.info( + "Updated %s: added DEPENDS on clang-native, needed to stage clangd " + "for IDE_SDK_INTELLISENSE=\"clangd\"", self.bbappend) + if self.build_tool is BuildTool.CARGO: + logger.info( + "Updated %s: remapped Cargo external sources for debug info", self.bbappend) return True def initialize(self, config, workspace, tinfoil): From patchwork Mon Nov 9 13:44:30 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Enguerrand de Ribaucourt X-Patchwork-Id: 103516 Received: from mail.savoirfairelinux.com (mail.savoirfairelinux.com [208.88.110.44]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.6196.1794231922310880885 for ; Mon, 09 Nov 2026 05:45:22 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@savoirfairelinux.com header.s=DFC430D2-D198-11EC-948E-34200CB392D2 header.b=Wv+IyXPr; spf=pass (domain: savoirfairelinux.com, ip: 208.88.110.44, mailfrom: enguerrand.de-ribaucourt@savoirfairelinux.com) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 6AA543D818F3; Mon, 9 Nov 2026 08:45:21 -0500 (EST) Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10032) with ESMTP id 71eu6rzYzGez; Mon, 9 Nov 2026 08:45:20 -0500 (EST) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 55B0B3D81838; Mon, 9 Nov 2026 08:45:20 -0500 (EST) DKIM-Filter: OpenDKIM Filter v2.10.3 mail.savoirfairelinux.com 55B0B3D81838 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=savoirfairelinux.com; s=DFC430D2-D198-11EC-948E-34200CB392D2; t=1794231920; bh=KIS9f9X68D0vi+H/3CLUb4m4fLV1kbGpgWsJYgmrFoQ=; h=From:Date:MIME-Version:Message-Id:To; b=Wv+IyXPrvMGZUTZViL/EcJhrkjDm6csl33DqwyOfFF9W/aRFRejIzKRl0MxjxuUKu OxpEREKlaudtoB47fmOPcrEt4wTF9tB678bg20o/PBRXeuaKcOSwQISzu23ZyXI6Ia j4p7Bmcjo+k2Ql/Vcd8YFGtH6oLSsoI4w9THnUBhtpGJgZddrgoJl1guyInQNfmYbd rLduPa4pZ1830MxZ3/e9UbZo+BjvNu+YdqZVj5LTZ0rGCJrR8LP9GqhnbM2nkYUUHT BOkxEF3aHKUDlH6AFdT/wtxwR2MMeK9t0SwiFjgVltXX5B1wS+7yGSHO7s5Ii13mdL 037U9XnT2+46Q== X-Virus-Scanned: amavis at mail.savoirfairelinux.com Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10026) with ESMTP id RCWLNJzQ8sno; Mon, 9 Nov 2026 08:45:20 -0500 (EST) Received: from isabelle.rennes.sfl (80-15-101-118.ftth.fr.orangecustomers.net [80.15.101.118]) by mail.savoirfairelinux.com (Postfix) with ESMTPSA id C4AEA3D81892; Mon, 9 Nov 2026 08:45:19 -0500 (EST) From: Enguerrand de Ribaucourt Date: Mon, 09 Nov 2026 14:44:30 +0100 Subject: [PATCH v2 13/18] devtool: ide-sdk: map Cargo workspace sources for LLDB MIME-Version: 1.0 Message-Id: <20261109-devtool-ide-sdk-cargo-v2-13-d56134000561@savoirfairelinux.com> References: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> In-Reply-To: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer , Enguerrand de Ribaucourt X-Mailer: b4 0.16.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Mon, 09 Nov 2026 13:45:32 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/249840 Cargo debug info remaps the modified source tree to TARGET_DBGSRC_DIR. Include this reverse map in CodeLLDB launch configs even when rootfs-dbg is disabled. Use the Cargo workspace as its source root while preserving the existing rootfs-debug mappings for other recipes. AI-Generated: Uses GitHub Copilot Signed-off-by: Enguerrand de Ribaucourt --- Changes in v2: - Move source-map verification to the LLDB configuration test. --- scripts/lib/devtool/ide_plugins/ide_code.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/scripts/lib/devtool/ide_plugins/ide_code.py b/scripts/lib/devtool/ide_plugins/ide_code.py index a7bb3221e0..6312988db1 100644 --- a/scripts/lib/devtool/ide_plugins/ide_code.py +++ b/scripts/lib/devtool/ide_plugins/ide_code.py @@ -555,15 +555,22 @@ class IdeVSCode(IdeBase): source_map = { "/usr/include": os.path.join(modified_recipe.recipe_sysroot, "usr", "include") } - if lldb_config.image_recipe.rootfs_dbg: + rootfs_dbg = lldb_config.image_recipe.rootfs_dbg + is_cargo = modified_recipe.build_tool is BuildTool.CARGO + if is_cargo or rootfs_dbg: + source_root = ( + modified_recipe.real_srctree + if is_cargo else "${workspaceFolder}") # Map build-time paths back to the workspace source tree. for target_path, host_path in modified_recipe.reverse_debug_prefix_map.items(): if host_path.startswith(modified_recipe.real_srctree): source_map[target_path] = ( - "${workspaceFolder}" + source_root + host_path[len(modified_recipe.real_srctree):]) - else: + elif rootfs_dbg: source_map[target_path] = host_path + + if rootfs_dbg: if "/usr/src/debug" in source_map: logger.error( 'Key "/usr/src/debug" already exists in source_map. ' From patchwork Mon Nov 9 13:44:31 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Enguerrand de Ribaucourt X-Patchwork-Id: 103517 Received: from mail.savoirfairelinux.com (mail.savoirfairelinux.com [208.88.110.44]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.6075.1794231923125722542 for ; Mon, 09 Nov 2026 05:45:23 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@savoirfairelinux.com header.s=DFC430D2-D198-11EC-948E-34200CB392D2 header.b=dD+5ja1V; spf=pass (domain: savoirfairelinux.com, ip: 208.88.110.44, mailfrom: enguerrand.de-ribaucourt@savoirfairelinux.com) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 3CA2D3D818FC; Mon, 9 Nov 2026 08:45:22 -0500 (EST) Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10032) with ESMTP id jZ2XAnm9SgNq; Mon, 9 Nov 2026 08:45:21 -0500 (EST) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 00BAE3D81892; Mon, 9 Nov 2026 08:45:21 -0500 (EST) DKIM-Filter: OpenDKIM Filter v2.10.3 mail.savoirfairelinux.com 00BAE3D81892 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=savoirfairelinux.com; s=DFC430D2-D198-11EC-948E-34200CB392D2; t=1794231921; bh=Pwz251FBEtuAAPOlH9+UQFsLFFLpRWsYu/cZHm0cxRM=; h=From:Date:MIME-Version:Message-Id:To; b=dD+5ja1VFZXJPJ9INFAXkgwDHK1RExbhETBYKXucN3uwkk9tsBOViP/5TLVhb39n+ JPRkmMHal70frwodd6H/rd28wT/Iro/eaEU+Mn4E8kvLgry4havhc3yMcGm5BjunaA jgUbzymmBDTFEm5Qayd9c+D/LaUMeSkztOKAU6wXZgR/9mIssOIJRC0QrNNs709LyJ /TiaxfgAdR1bHtVMbleB3c/vF8kwPiyjstRpY7AvXYgRHoHzl6ZKLTsy9gT3WN6aJo xnbdfx990I+eNC2xw9jj2uS+xVrv63O2OAp8UK7yQPtN+TOphwq+k/dExcAz/1QhMp bYv/EDHlWwV8A== X-Virus-Scanned: amavis at mail.savoirfairelinux.com Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10026) with ESMTP id g8OrO_nI2Vge; Mon, 9 Nov 2026 08:45:20 -0500 (EST) Received: from isabelle.rennes.sfl (80-15-101-118.ftth.fr.orangecustomers.net [80.15.101.118]) by mail.savoirfairelinux.com (Postfix) with ESMTPSA id 5F18A3D818F1; Mon, 9 Nov 2026 08:45:20 -0500 (EST) From: Enguerrand de Ribaucourt Date: Mon, 09 Nov 2026 14:44:31 +0100 Subject: [PATCH v2 14/18] devtool: ide-sdk: map libstd-rs sources to Rust SDK MIME-Version: 1.0 Message-Id: <20261109-devtool-ide-sdk-cargo-v2-14-d56134000561@savoirfairelinux.com> References: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> In-Reply-To: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer , Enguerrand de Ribaucourt X-Mailer: b4 0.16.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Mon, 09 Nov 2026 13:45:32 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/249841 libstd-rs DWARF paths use a source prefix under work-shared, while rust-native stages the standard-library sources in the recipe native sysroot. Derive the target prefix from BitBake metadata and map it to the SDK source tree so LLDB runtime frames resolve without host Rust sources. AI-Generated: Uses GitHub Copilot Signed-off-by: Enguerrand de Ribaucourt --- Changes in v2: - Use STAGING_LIBDIR_NATIVE for multilib-correct Rust source paths. --- scripts/lib/devtool/ide_plugins/ide_code.py | 2 ++ scripts/lib/devtool/ide_sdk.py | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/scripts/lib/devtool/ide_plugins/ide_code.py b/scripts/lib/devtool/ide_plugins/ide_code.py index 6312988db1..8d5a0710fa 100644 --- a/scripts/lib/devtool/ide_plugins/ide_code.py +++ b/scripts/lib/devtool/ide_plugins/ide_code.py @@ -557,6 +557,8 @@ class IdeVSCode(IdeBase): } rootfs_dbg = lldb_config.image_recipe.rootfs_dbg is_cargo = modified_recipe.build_tool is BuildTool.CARGO + if is_cargo: + source_map.update(modified_recipe.cargo_std_source_map) if is_cargo or rootfs_dbg: source_root = ( modified_recipe.real_srctree diff --git a/scripts/lib/devtool/ide_sdk.py b/scripts/lib/devtool/ide_sdk.py index 5096297b32..17209a8bde 100755 --- a/scripts/lib/devtool/ide_sdk.py +++ b/scripts/lib/devtool/ide_sdk.py @@ -923,6 +923,7 @@ class RecipeModified: self.cargo_packageconfig_confargs = None self.cargo_rustflags = None self.cargo_env = None + self.cargo_std_source_map = {} # Populated after bitbake built all the recipes self._installed_binaries = None @@ -1140,6 +1141,24 @@ class RecipeModified: 'SYSTEM_DEPS_BUILD_INTERNAL': 'never', 'ZSTD_SYS_USE_PKG_CONFIG': '1', }) + # libstd-rs DWARF paths map to sources staged by rust-native. + libstd_recipe_d = parse_recipe( + config, tinfoil, 'libstd-rs', appends=True, + filter_workspace=False) + if libstd_recipe_d: + libstd_rustsrc = libstd_recipe_d.getVar('RUSTSRC') + target_dbgsrc_dir = libstd_recipe_d.getVar('TARGET_DBGSRC_DIR') + libstd_tmpdir = libstd_recipe_d.getVar('TMPDIR') + if libstd_rustsrc and target_dbgsrc_dir and libstd_tmpdir: + shared_source_dir = os.path.join(libstd_tmpdir, 'work-shared') + target_source_root = os.path.join( + target_dbgsrc_dir, + os.path.relpath(libstd_rustsrc, shared_source_dir), + 'library') + sdk_source_root = os.path.join( + recipe_d.getVar('STAGING_LIBDIR_NATIVE'), + 'rustlib', 'src', 'rust', 'library') + self.cargo_std_source_map[target_source_root] = sdk_source_root self.build_tool = BuildTool.CARGO elif bb.data.inherits_class('module', recipe_d): self.build_tool = BuildTool.KERNEL_MODULE From patchwork Mon Nov 9 13:44:32 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Enguerrand de Ribaucourt X-Patchwork-Id: 103518 Received: from mail.savoirfairelinux.com (mail.savoirfairelinux.com [208.88.110.44]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.6197.1794231923590750331 for ; Mon, 09 Nov 2026 05:45:23 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@savoirfairelinux.com header.s=DFC430D2-D198-11EC-948E-34200CB392D2 header.b=u5zhGJrR; spf=pass (domain: savoirfairelinux.com, ip: 208.88.110.44, mailfrom: enguerrand.de-ribaucourt@savoirfairelinux.com) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id AEAD33D818F9; Mon, 9 Nov 2026 08:45:22 -0500 (EST) Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10032) with ESMTP id zYJZ-xdxwcmN; Mon, 9 Nov 2026 08:45:21 -0500 (EST) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id AC42E3D80F35; Mon, 9 Nov 2026 08:45:21 -0500 (EST) DKIM-Filter: OpenDKIM Filter v2.10.3 mail.savoirfairelinux.com AC42E3D80F35 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=savoirfairelinux.com; s=DFC430D2-D198-11EC-948E-34200CB392D2; t=1794231921; bh=wLnXzdNitA2vxndp/qoR1rZuR4DEoMybexn+RauOHUE=; h=From:Date:MIME-Version:Message-Id:To; b=u5zhGJrRDs7AyrcxU2noGq5bq5uDtu+aaRzWfXEcwLHfR3Q79E1Fkn6lQMuIYNwXl cLejLA+wGZ86y50Qk0btWyYnS7C5b14Y9RfD5TT0gDRRRZRbtlURF/C24uCm7MYeA+ 8ty8WpTHsatB3sXBWz1s7F2zycJlIoSG4Fl+BBlpvaJMgeqCKkQwtk53QLD5D1EHrH g/G68WcxxSrS17fx3Cws/eabHZHEdNrr8/cNVNIDZfO0jidACcmHU6rXL6KY7BYG2h vPZ/bPMIJgg01luhgKBof4rBUQEuA1l7hGCeMkjVoRI5DnLLztG5EyLNvLCmAIP/En W3w3QpolIGPnQ== X-Virus-Scanned: amavis at mail.savoirfairelinux.com Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10026) with ESMTP id MWqLjBpU6out; Mon, 9 Nov 2026 08:45:21 -0500 (EST) Received: from isabelle.rennes.sfl (80-15-101-118.ftth.fr.orangecustomers.net [80.15.101.118]) by mail.savoirfairelinux.com (Postfix) with ESMTPSA id EC5DB3D8182D; Mon, 9 Nov 2026 08:45:20 -0500 (EST) From: Enguerrand de Ribaucourt Date: Mon, 09 Nov 2026 14:44:32 +0100 Subject: [PATCH v2 15/18] oeqa/selftest: share source breakpoint lookup MIME-Version: 1.0 Message-Id: <20261109-devtool-ide-sdk-cargo-v2-15-d56134000561@savoirfairelinux.com> References: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> In-Reply-To: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer , Enguerrand de Ribaucourt X-Mailer: b4 0.16.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Mon, 09 Nov 2026 13:45:32 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/249842 Move the stable source-line helper to the common ide-sdk test base so the Rust CodeLLDB integration can reuse it. Preserve the rationale for using marker-based lines instead of brittle hard-coded numbers. AI-Generated: Uses GitHub Copilot Signed-off-by: Enguerrand de Ribaucourt --- meta/lib/oeqa/selftest/cases/devtool.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py index 3b80d6a4a8..f0bfa5ce27 100644 --- a/meta/lib/oeqa/selftest/cases/devtool.py +++ b/meta/lib/oeqa/selftest/cases/devtool.py @@ -3133,6 +3133,20 @@ class DevtoolIdeSdkTests(DevtoolBase): def _sources_workdir_dir(self, src_dir): return os.path.realpath(os.path.join(src_dir, 'oe-workdir')) + def _find_source_break_line(self, tempdir, source_file, marker): + """Find the 1-based line number of `marker` in tempdir/source_file + + Used to set a source-level (file:line) breakpoint at a stable, + self-documenting location instead of hard-coding a line number that + would silently go stale whenever the example source changes. + """ + source_path = os.path.join(tempdir, source_file) + with open(source_path) as f: + for lineno, line in enumerate(f, start=1): + if marker in line: + return lineno + self.fail("Could not find marker %r in %s" % (marker, source_path)) + def _find_multi_script_port(self, recipe_name, script_prefix, example_exe): """Discover the port assigned to a generated 'multi' mode debug-server script (gdbserver_*/lldb_server_*), since each --ide plugin allocates @@ -4860,20 +4874,6 @@ class DevtoolIdeSdkClangTests(DevtoolIdeSdkTests): self.assertTrue(task, f"Configuration '{config_name}' preLaunchTask should not be empty") - def _find_source_break_line(self, tempdir, source_file, marker): - """Find the 1-based line number of `marker` in tempdir/source_file - - Used to set a source-level (file:line) breakpoint at a stable, - self-documenting location instead of hard-coding a line number that - would silently go stale whenever the example source changes. - """ - source_path = os.path.join(tempdir, source_file) - with open(source_path) as f: - for lineno, line in enumerate(f, start=1): - if marker in line: - return lineno - self.fail("Could not find marker %r in %s" % (marker, source_path)) - def _lldb_debug_cpp_example_batch_commands(self, tempdir): """Get a list of lldb --batch '-o' commands to debug the cpp-example-lib example From patchwork Mon Nov 9 13:44:33 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Enguerrand de Ribaucourt X-Patchwork-Id: 103519 Received: from mail.savoirfairelinux.com (mail.savoirfairelinux.com [208.88.110.44]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.6076.1794231923991731249 for ; Mon, 09 Nov 2026 05:45:24 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@savoirfairelinux.com header.s=DFC430D2-D198-11EC-948E-34200CB392D2 header.b=V62odj1H; spf=pass (domain: savoirfairelinux.com, ip: 208.88.110.44, mailfrom: enguerrand.de-ribaucourt@savoirfairelinux.com) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 1C0E63D8182D; Mon, 9 Nov 2026 08:45:23 -0500 (EST) Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10032) with ESMTP id CMM85TaRMK5a; Mon, 9 Nov 2026 08:45:22 -0500 (EST) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 3B7493D818F4; Mon, 9 Nov 2026 08:45:22 -0500 (EST) DKIM-Filter: OpenDKIM Filter v2.10.3 mail.savoirfairelinux.com 3B7493D818F4 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=savoirfairelinux.com; s=DFC430D2-D198-11EC-948E-34200CB392D2; t=1794231922; bh=Brm56ZBdRKDiuJ+rNTRyUTVDEWpeCtfABTMl+Q6BO8c=; h=From:Date:MIME-Version:Message-Id:To; b=V62odj1H3iQLtQaEsJXLKwm6Y92s5JwfEl11ZpJRHWAk3Zesc497uQpztSe8XFGDD g+BrlNDJ9jLUKB9qpdTgFigDmzz26ZMXT/1yzzOwXeSXXYNHjPcZGVTplWfidyPr7m 2aTuGg5WU5Yz/E5VYbtCog98P/eGM8SsQsOcRuY5xFySB+AEZoxCmg5nasBq3qh7HP /22kKJnD1DEhAk9rrkaYrigdMafyXET4Qyt60/D5Qyk+CuVVTcW7w9uDfvHyS/mpj7 Gl/nnm8F8H33tamsK0Miz/L9zrp0surO3UmiEyn27bqIgxVzJ+ueXKR+g2RCrkVKh/ TesGv/ceOFC2g== X-Virus-Scanned: amavis at mail.savoirfairelinux.com Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10026) with ESMTP id uUOqBZasPGgz; Mon, 9 Nov 2026 08:45:21 -0500 (EST) Received: from isabelle.rennes.sfl (80-15-101-118.ftth.fr.orangecustomers.net [80.15.101.118]) by mail.savoirfairelinux.com (Postfix) with ESMTPSA id 878F53D81838; Mon, 9 Nov 2026 08:45:21 -0500 (EST) From: Enguerrand de Ribaucourt Date: Mon, 09 Nov 2026 14:44:33 +0100 Subject: [PATCH v2 16/18] oeqa/selftest: run IDE tasks with configured environment MIME-Version: 1.0 Message-Id: <20261109-devtool-ide-sdk-cargo-v2-16-d56134000561@savoirfairelinux.com> References: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> In-Reply-To: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer , Enguerrand de Ribaucourt X-Mailer: b4 0.16.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Mon, 09 Nov 2026 13:45:32 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/249843 Apply each generated shell task's options.env and return its runCmd results. Cargo build tasks intentionally keep only the SDK PATH, and the following rebuild integration test needs both to execute and inspect that task. AI-Generated: Uses GitHub Copilot Signed-off-by: Enguerrand de Ribaucourt --- meta/lib/oeqa/selftest/cases/devtool.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py index f0bfa5ce27..f23e1a7f95 100644 --- a/meta/lib/oeqa/selftest/cases/devtool.py +++ b/meta/lib/oeqa/selftest/cases/devtool.py @@ -3485,6 +3485,7 @@ class DevtoolIdeSdkTests(DevtoolBase): self.assertIn(task_label, task_by_label, "Task '%s' not found in tasks.json" % task_label) + task_results = [] ran = set() def run_task(label, execute_task): @@ -3509,14 +3510,20 @@ class DevtoolIdeSdkTests(DevtoolBase): args = [args] task_cmd = [command] + [str(arg) for arg in args] - task_cwd = task.get('options', {}).get('cwd', tempdir) + task_options = task.get('options', {}) + task_cwd = task_options.get('cwd', tempdir) if isinstance(task_cwd, str): task_cwd = task_cwd.replace('${workspaceFolder}', tempdir) - runCmd(task_cmd, cwd=task_cwd, output_log=self._cmd_logger) + task_env = os.environ.copy() + task_env.update(task_options.get('env', {})) + task_results.append(runCmd( + task_cmd, cwd=task_cwd, env=task_env, + output_log=self._cmd_logger)) ran.add(label) run_task(task_label, run_main_task) + return task_results def _ide_sdk_package_opts(self): """Extra `devtool ide-sdk --package` options. Override to scope packages.""" From patchwork Mon Nov 9 13:44:34 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Enguerrand de Ribaucourt X-Patchwork-Id: 103513 Received: from mail.savoirfairelinux.com (mail.savoirfairelinux.com [208.88.110.44]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.6079.1794231925100266687 for ; Mon, 09 Nov 2026 05:45:25 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@savoirfairelinux.com header.s=DFC430D2-D198-11EC-948E-34200CB392D2 header.b=BVH07v9v; spf=pass (domain: savoirfairelinux.com, ip: 208.88.110.44, mailfrom: enguerrand.de-ribaucourt@savoirfairelinux.com) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 367D53D81892; Mon, 9 Nov 2026 08:45:24 -0500 (EST) Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10032) with ESMTP id DWy1TkACVqTv; Mon, 9 Nov 2026 08:45:22 -0500 (EST) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id A08533D8176B; Mon, 9 Nov 2026 08:45:22 -0500 (EST) DKIM-Filter: OpenDKIM Filter v2.10.3 mail.savoirfairelinux.com A08533D8176B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=savoirfairelinux.com; s=DFC430D2-D198-11EC-948E-34200CB392D2; t=1794231922; bh=40sDrF9NuAkV+vk09pT7+oe3Hp1Go9jiXVdEIfSxG0I=; h=From:Date:MIME-Version:Message-Id:To; b=BVH07v9vrrw9tuI6nKtHSmQU4DQjXArEO0Dx95a0HO1jfIwryPbsSfCGbqDGQ+ZN6 MAUnwlnm2O32IH6vBUBUn4/yJ1diOjXy5/TcItUMInMZVPyI9lonH8U25edYbAJJ/O tOiBtWhu11Rz7VOZ6E7PBOW856EV1vtNvtmkYiozl71SBVjPUpcCYjPPYlpvpcwEVP 65ncDgmfby95ak7eNfRrr/51+9Mirg0ZjJcNfwRthL1bmXQXIrfKNVZRwRcUOrjvmd htPAkuhSOEhBi57BKWCDd9fpKw914tx+7O3FIQEe4Eq69KWr73XgzmMDPEyNPzlmEh 9dFVwRll6DPEQ== X-Virus-Scanned: amavis at mail.savoirfairelinux.com Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10026) with ESMTP id yTP_M0-mMVEj; Mon, 9 Nov 2026 08:45:22 -0500 (EST) Received: from isabelle.rennes.sfl (80-15-101-118.ftth.fr.orangecustomers.net [80.15.101.118]) by mail.savoirfairelinux.com (Postfix) with ESMTPSA id 20C393D8182D; Mon, 9 Nov 2026 08:45:22 -0500 (EST) From: Enguerrand de Ribaucourt Date: Mon, 09 Nov 2026 14:44:34 +0100 Subject: [PATCH v2 17/18] oeqa/selftest: debug Cargo example over QEMU slirp MIME-Version: 1.0 Message-Id: <20261109-devtool-ide-sdk-cargo-v2-17-d56134000561@savoirfairelinux.com> References: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> In-Reply-To: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer , Enguerrand de Ribaucourt X-Mailer: b4 0.16.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Mon, 09 Nov 2026 13:45:31 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/249844 Exercise Cargo deploy and CodeLLDB launch against oe-selftest-image over slirp. Verify source breakpoints, Rust and runtime backtrace frames, and that the BitBake RUST_DEBUG_REMAP includes the devtool external source tree so package QA does not reject host paths in DWARF. AI-Generated: Uses GitHub Copilot Signed-off-by: Enguerrand de Ribaucourt --- Changes in v2: - Use STAGING_LIBDIR_NATIVE to locate Rust standard-library sources in the SDK. - Remove the second ide-sdk invocation and repeated-remap assertion while retaining the QEMU debugging and rebuild coverage. --- meta/lib/oeqa/selftest/cases/devtool.py | 117 ++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py index f23e1a7f95..0128d37d83 100644 --- a/meta/lib/oeqa/selftest/cases/devtool.py +++ b/meta/lib/oeqa/selftest/cases/devtool.py @@ -4456,6 +4456,123 @@ class DevtoolIdeSdkRustTests(DevtoolIdeSdkTests): if task['label'].startswith('install && deploy-target ')) self.assertEqual(install_task['dependsOn'], [build_task['label']]) + @OETestTag("runqemu") + def test_code_cargo_qemu_slirp(self): + recipe_name = 'cargo-example' + testimage = 'oe-selftest-image' + self._check_workspace() + self._write_bb_config() + tempdir = self._devtool_ide_sdk_recipe( + recipe_name, 'Cargo.toml', testimage) + port_start = self._reserve_slirp_port_block() + port_opts = ' -G %d' % port_start + runCmd( + 'devtool ide-sdk %s %s --ide=code --target root@localhost ' + '--port 2222 --no-host-check%s' % ( + recipe_name, testimage, port_opts), + output_log=self._cmd_logger) + source_remap = '--remap-path-prefix=%s=%s' % ( + os.path.realpath(tempdir), + get_bb_var('TARGET_DBGSRC_DIR', recipe_name)) + rustflags = shlex.split(get_bb_var('RUSTFLAGS', recipe_name)) + self.assertIn( + source_remap, rustflags, + 'Cargo BitBake builds must remap the external source tree for DWARF') + self._verify_slirp_bbappend(testimage) + + with runqemu( + testimage, runqemuparams='nographic slirp snapshot') as qemu: + self.assertIsNotNone(qemu.port, 'No SSH port for the slirp target') + self._verify_rust_lldb_debugging(tempdir, expected_input=4) + + def _verify_rust_lldb_debugging(self, tempdir, expected_input): + with open(os.path.join(tempdir, '.vscode', 'launch.json')) as launch_file: + launch = json.load(launch_file)['configurations'][0] + with open(os.path.join(tempdir, '.vscode', 'tasks.json')) as tasks_file: + tasks = json.load(tasks_file)['tasks'] + + self.assertEqual(launch['type'], 'lldb') + target_dbgsrc_dir = get_bb_var('TARGET_DBGSRC_DIR', 'cargo-example') + self.assertEqual( + launch['sourceMap'][target_dbgsrc_dir], os.path.realpath(tempdir)) + self._run_vscode_task_with_dependencies( + tempdir, launch['preLaunchTask'], run_main_task=False) + server_task = next( + task for task in tasks if task['label'] == launch['preLaunchTask']) + self.assertEqual(server_task['command'], 'ssh') + ssh_args = [server_task['command']] + server_task['args'] + if ssh_args[-1].startswith('"') and ssh_args[-1].endswith('"'): + ssh_args[-1] = ssh_args[-1][1:-1].replace('\\$', '$') + runCmd(ssh_args, output_log=self._cmd_logger) + + source_line = self._find_source_break_line( + tempdir, 'src/main.rs', ' match n {') + println_line = self._find_source_break_line( + tempdir, 'src/main.rs', 'println!') + lldb_batch = [ + os.path.join( + get_bb_var('RECIPE_SYSROOT_NATIVE', 'lldb-native'), + 'usr', 'bin', 'lldb'), + '--batch', + ] + for command in launch['initCommands'] + launch['targetCreateCommands']: + lldb_batch += ['-o', command] + source_map_args = [] + for source, destination in launch.get('sourceMap', {}).items(): + source_map_args += [source, destination] + if source_map_args: + lldb_batch += [ + '-o', 'settings set target.source-map %s' % + ' '.join(source_map_args)] + lldb_batch += [ + '-o', 'breakpoint set --file main.rs --line %d' % source_line, + '-o', 'breakpoint set --file main.rs --line %d' % println_line, + '-o', 'breakpoint disable 2', + '-o', 'breakpoint list', + '-o', 'run', + '-o', 'frame variable n', + '-o', 'thread backtrace', + '-o', 'breakpoint disable 1', + '-o', 'breakpoint enable 2', + '-o', 'continue', + '-o', 'frame info', + '-o', 'frame select 1', + '-o', 'frame info', + '-o', 'frame select 3', + '-o', "image lookup -v -r -n 'std::rt::lang_start.*'", + '-o', 'thread backtrace', + '-o', 'exit', + ] + result = runCmd(lldb_batch, timeout=60, output_log=self._cmd_logger) + self.assertNotIn('(pending)', result.output) + self.assertIn('cargo_example::fibonacci', result.output) + self.assertIn('cargo_example::main', result.output) + self.assertIn('std::rt::lang_start', result.output) + self.assertIn('__libc_start', result.output) + self.assertRegex(result.output, r'n\s*=\s*%d' % expected_input) + libstd_rustsrc = get_bb_var('RUSTSRC', 'libstd-rs') + libstd_work_shared = os.path.join( + get_bb_var('TMPDIR', 'libstd-rs'), 'work-shared') + rust_std_target_root = os.path.join( + get_bb_var('TARGET_DBGSRC_DIR', 'libstd-rs'), + os.path.relpath(libstd_rustsrc, libstd_work_shared), + 'library') + rust_std_sdk_root = os.path.join( + get_bb_var('STAGING_LIBDIR_NATIVE', 'cargo-example'), + 'rustlib', 'src', 'rust', 'library') + rust_std_source = os.path.join( + rust_std_target_root, 'std', 'src', 'rt.rs') + self.assertEqual( + launch['sourceMap'][rust_std_target_root], rust_std_sdk_root) + self.assertIn( + rust_std_source, result.output, + 'Rust runtime backtrace did not resolve to the SDK debug path:\n%s' % + result.output) + self.assertNotIn(libstd_rustsrc, result.output) + self.assertTrue( + os.path.isfile(os.path.join(rust_std_sdk_root, 'std', 'src', 'rt.rs')), + 'Rust standard-library source is missing from the recipe SDK sysroot') + class DevtoolIdeSdkKernelTests(DevtoolIdeSdkTests): From patchwork Mon Nov 9 13:44:35 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Enguerrand de Ribaucourt X-Patchwork-Id: 103514 Received: from mail.savoirfairelinux.com (mail.savoirfairelinux.com [208.88.110.44]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.6199.1794231925343675182 for ; Mon, 09 Nov 2026 05:45:25 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@savoirfairelinux.com header.s=DFC430D2-D198-11EC-948E-34200CB392D2 header.b=iLcqSrbI; spf=pass (domain: savoirfairelinux.com, ip: 208.88.110.44, mailfrom: enguerrand.de-ribaucourt@savoirfairelinux.com) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 72E153D8176B; Mon, 9 Nov 2026 08:45:24 -0500 (EST) Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10032) with ESMTP id Jwh8AzjLB_Gb; Mon, 9 Nov 2026 08:45:23 -0500 (EST) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 682C63D81838; Mon, 9 Nov 2026 08:45:23 -0500 (EST) DKIM-Filter: OpenDKIM Filter v2.10.3 mail.savoirfairelinux.com 682C63D81838 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=savoirfairelinux.com; s=DFC430D2-D198-11EC-948E-34200CB392D2; t=1794231923; bh=fUw/aP++f+syKwl+31QMkC9oA3gcNdnoeXcEna27yzA=; h=From:Date:MIME-Version:Message-Id:To; b=iLcqSrbIZJWk966P/Z4IVNZ8fU4ewlkxSWWqq11LbfQgr7u6Wd4JRcxpmQ8P4U930 UjcKwcAhdAZXvFTARbN8p24Tr27rwsC0Jr4J26HYm9177j14pVznISCA8SG+OFRwdS lCvHFtLvK1Xn+cFgj5o4XbIeg4wo1jTKsH7Dq/smcdHNZBErI8mDLKYl0EjhTv4cn4 MZ+HeDQzTl7wHqLNLAvHnPP+GUSsWGMcy6Soy87yvJ0iNwgRQXGfX0OzWGBTZFUZCZ 9WbgN89e3ohJAbQIppWaxfeR4I8jHvlDct3Y6s7QY2VzOzLmVaVTaWqZHHCIR4/qGH ZYMf+YI1BhlnQ== X-Virus-Scanned: amavis at mail.savoirfairelinux.com Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavis, port 10026) with ESMTP id VajSjwILUvRF; Mon, 9 Nov 2026 08:45:23 -0500 (EST) Received: from isabelle.rennes.sfl (80-15-101-118.ftth.fr.orangecustomers.net [80.15.101.118]) by mail.savoirfairelinux.com (Postfix) with ESMTPSA id AE2503D81892; Mon, 9 Nov 2026 08:45:22 -0500 (EST) From: Enguerrand de Ribaucourt Date: Mon, 09 Nov 2026 14:44:35 +0100 Subject: [PATCH v2 18/18] oeqa/selftest: verify Cargo rebuild and redeploy MIME-Version: 1.0 Message-Id: <20261109-devtool-ide-sdk-cargo-v2-18-d56134000561@savoirfairelinux.com> References: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> In-Reply-To: <20261109-devtool-ide-sdk-cargo-v2-0-d56134000561@savoirfairelinux.com> To: openembedded-core@lists.openembedded.org Cc: Adrian Freihofer , Enguerrand de Ribaucourt X-Mailer: b4 0.16.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by lin-tor-korg-lkml-alma10-1 with HTTPS for ; Mon, 09 Nov 2026 13:45:31 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/249845 After a source edit, run the ordered Cargo build/install/deploy tasks and verify the changed Fibonacci result. Use a helper to shift source lines so the breakpoint location can change without hard-coded line numbers; reuse the shared LLDB runner for both debug sessions. AI-Generated: Uses GitHub Copilot Signed-off-by: Enguerrand de Ribaucourt --- meta/lib/oeqa/selftest/cases/devtool.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py index 0128d37d83..c54f13de5a 100644 --- a/meta/lib/oeqa/selftest/cases/devtool.py +++ b/meta/lib/oeqa/selftest/cases/devtool.py @@ -3147,6 +3147,15 @@ class DevtoolIdeSdkTests(DevtoolBase): return lineno self.fail("Could not find marker %r in %s" % (marker, source_path)) + def _insert_source_line_shift(self, source_path, marker, line_count): + with open(source_path) as source_handle: + source = source_handle.read() + self.assertEqual(source.count(marker), 1) + inserted_lines = ''.join( + ' // line shift %d\n' % index for index in range(line_count)) + with open(source_path, 'w') as source_handle: + source_handle.write(source.replace(marker, inserted_lines + marker, 1)) + def _find_multi_script_port(self, recipe_name, script_prefix, example_exe): """Discover the port assigned to a generated 'multi' mode debug-server script (gdbserver_*/lldb_server_*), since each --ide plugin allocates @@ -4485,6 +4494,28 @@ class DevtoolIdeSdkRustTests(DevtoolIdeSdkTests): self.assertIsNotNone(qemu.port, 'No SSH port for the slirp target') self._verify_rust_lldb_debugging(tempdir, expected_input=4) + main_rs = os.path.join(tempdir, 'src', 'main.rs') + self._insert_source_line_shift(main_rs, ' match n {', 4) + with open(main_rs) as source_file: + shifted_source = source_file.read() + self.assertEqual(shifted_source.count('fibonacci(4)'), 1) + with open(main_rs, 'w') as source_file: + source_file.write( + shifted_source.replace('fibonacci(4)', 'fibonacci(5)', 1)) + + with open(os.path.join(tempdir, '.vscode', 'tasks.json')) as tasks_file: + tasks = json.load(tasks_file)['tasks'] + install_task = next( + task for task in tasks + if task['label'].startswith('install && deploy-target ')) + task_results = self._run_vscode_task_with_dependencies( + tempdir, install_task['label']) + self.assertTrue( + any('Compiling cargo-example' in result.output + for result in task_results), + 'Cargo build task did not recompile the modified Rust source') + self._verify_rust_lldb_debugging(tempdir, expected_input=5) + def _verify_rust_lldb_debugging(self, tempdir, expected_input): with open(os.path.join(tempdir, '.vscode', 'launch.json')) as launch_file: launch = json.load(launch_file)['configurations'][0]