* [PATCH 00/20] devtool: ide-sdk: add support for Rust recipes
@ 2026-10-26 8:55 Enguerrand de Ribaucourt
2026-10-26 8:55 ` [PATCH 01/20] cargo-example: add minimal selftest fixture Enguerrand de Ribaucourt
` (20 more replies)
0 siblings, 21 replies; 31+ messages in thread
From: Enguerrand de Ribaucourt @ 2026-10-26 8:55 UTC (permalink / raw)
To: openembedded-core; +Cc: Adrian Freihofer, Enguerrand de Ribaucourt
Hello, this series introduces support for Rust ide-sdk VS Code configuration
against the Yocto cross-compilation toolchain:
- editor symbol resolution and linting
- build task
- deploy task
- debuging
It introduces a cargo-example recipe, on the model we have for cmake or meson.
The generated configurations can be portable to standalone SDK installations,
by manually updating the paths.
I reproduced the selftest coverage that is expected from other recipe classes,
including configuration analysis up to actual debuging symbol resolution.
I largely used AI generation to write this stack. After many iterations, I am
finally happy with the code and commit history quality of this series.
I also have a documentation commit at the ready for the manual if this gets
aproved.
Any feedback is appreciated. Hope this will help lots of Rust developers
working with Yocto distros :).
Cheers,
Enguerrand de Ribaucourt
Signed-off-by: Enguerrand de Ribaucourt <enguerrand.de-ribaucourt@savoirfairelinux.com>
---
Enguerrand de Ribaucourt (20):
cargo-example: add minimal selftest fixture
devtool: ide-sdk: capture Cargo cross environment
devtool: ide-sdk: export recipe Cargo configuration
devtool: ide-sdk: recommend Rust Analyzer for Cargo
devtool: ide-sdk: configure Rust Analyzer for Cargo
devtool: ide-sdk: share IntelliSense architecture mapping
devtool: ide-sdk: configure Cargo C++ IntelliSense
devtool: ide-sdk: generalize binary install task name
devtool: ide-sdk: extract install task definition
devtool: ide-sdk: order install after optional build task
devtool: ide-sdk: add Cargo build task
devtool: ide-sdk: enforce LLDB for Cargo
devtool: ide-sdk: parse Rust debug path remaps
devtool: ide-sdk: remap Cargo sources for BitBake builds
devtool: ide-sdk: map Cargo workspace sources for LLDB
devtool: ide-sdk: map libstd-rs sources to Rust SDK
oeqa/selftest: share source breakpoint lookup
oeqa/selftest: run IDE tasks with configured environment
oeqa/selftest: debug Cargo example over QEMU slirp
oeqa/selftest: verify Cargo rebuild and redeploy
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 +
meta/lib/oeqa/selftest/cases/devtool.py | 310 +++++++++++++++++++--
scripts/lib/devtool/ide_plugins/__init__.py | 1 +
scripts/lib/devtool/ide_plugins/ide_code.py | 125 +++++++--
scripts/lib/devtool/ide_sdk.py | 247 ++++++++++++++--
9 files changed, 673 insertions(+), 69 deletions(-)
---
base-commit: 39b27e524f3c092e5018cbed23ddf1829390ae65
change-id: 20261022-devtool-ide-sdk-cargo-d003158ae2f1
Best regards,
--
Enguerrand de Ribaucourt <enguerrand.de-ribaucourt@savoirfairelinux.com>
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PATCH 01/20] cargo-example: add minimal selftest fixture
2026-10-26 8:55 [PATCH 00/20] devtool: ide-sdk: add support for Rust recipes Enguerrand de Ribaucourt
@ 2026-10-26 8:55 ` Enguerrand de Ribaucourt
2026-10-26 8:55 ` [PATCH 02/20] devtool: ide-sdk: capture Cargo cross environment Enguerrand de Ribaucourt
` (19 subsequent siblings)
20 siblings, 0 replies; 31+ messages in thread
From: Enguerrand de Ribaucourt @ 2026-10-26 8:55 UTC (permalink / raw)
To: openembedded-core; +Cc: Adrian Freihofer, Enguerrand de Ribaucourt
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 <enguerrand.de-ribaucourt@savoirfairelinux.com>
---
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));
+}
--
2.53.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 02/20] devtool: ide-sdk: capture Cargo cross environment
2026-10-26 8:55 [PATCH 00/20] devtool: ide-sdk: add support for Rust recipes Enguerrand de Ribaucourt
2026-10-26 8:55 ` [PATCH 01/20] cargo-example: add minimal selftest fixture Enguerrand de Ribaucourt
@ 2026-10-26 8:55 ` Enguerrand de Ribaucourt
2026-10-26 8:55 ` [PATCH 03/20] devtool: ide-sdk: export recipe Cargo configuration Enguerrand de Ribaucourt
` (18 subsequent siblings)
20 siblings, 0 replies; 31+ messages in thread
From: Enguerrand de Ribaucourt @ 2026-10-26 8:55 UTC (permalink / raw)
To: openembedded-core; +Cc: Adrian Freihofer, Enguerrand de Ribaucourt
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 generated
Cargo config matches OE's system-library behavior.
AI-Generated: Uses GitHub Copilot
Signed-off-by: Enguerrand de Ribaucourt <enguerrand.de-ribaucourt@savoirfairelinux.com>
---
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
--
2.53.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 03/20] devtool: ide-sdk: export recipe Cargo configuration
2026-10-26 8:55 [PATCH 00/20] devtool: ide-sdk: add support for Rust recipes Enguerrand de Ribaucourt
2026-10-26 8:55 ` [PATCH 01/20] cargo-example: add minimal selftest fixture Enguerrand de Ribaucourt
2026-10-26 8:55 ` [PATCH 02/20] devtool: ide-sdk: capture Cargo cross environment Enguerrand de Ribaucourt
@ 2026-10-26 8:55 ` Enguerrand de Ribaucourt
2026-10-28 22:40 ` [OE-core] " adrian.freihofer
2026-10-26 8:55 ` [PATCH 04/20] devtool: ide-sdk: recommend Rust Analyzer for Cargo Enguerrand de Ribaucourt
` (17 subsequent siblings)
20 siblings, 1 reply; 31+ messages in thread
From: Enguerrand de Ribaucourt @ 2026-10-26 8:55 UTC (permalink / raw)
To: openembedded-core; +Cc: Adrian Freihofer, Enguerrand de Ribaucourt
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.
Update managed TOML table entries in place to preserve unrelated content.
tomllib and tomli only parse TOML; using a writer would add a dependency.
AI-Generated: Uses GitHub Copilot
Signed-off-by: Enguerrand de Ribaucourt <enguerrand.de-ribaucourt@savoirfairelinux.com>
---
scripts/lib/devtool/ide_sdk.py | 84 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 84 insertions(+)
diff --git a/scripts/lib/devtool/ide_sdk.py b/scripts/lib/devtool/ide_sdk.py
index e686dbcff8..21229f5970 100755
--- a/scripts/lib/devtool/ide_sdk.py
+++ b/scripts/lib/devtool/ide_sdk.py
@@ -36,6 +36,34 @@ logger = logging.getLogger('devtool')
ide_plugins = {}
+def set_toml_table_values(content, table, values):
+ """Update one TOML table while preserving unrelated configuration text."""
+ lines = content.splitlines()
+ header = '[%s]' % table
+ try:
+ start = next(i for i, line in enumerate(lines)
+ if line.strip() == header)
+ except StopIteration:
+ if lines and lines[-1].strip():
+ lines.append('')
+ lines.append(header)
+ start = len(lines) - 1
+
+ end = next((i for i in range(start + 1, len(lines))
+ if lines[i].lstrip().startswith('[')
+ and lines[i].rstrip().endswith(']')), len(lines))
+ for key, value in values.items():
+ entry = '%s = %s' % (key, value)
+ for i in range(start + 1, end):
+ if '=' in lines[i] and lines[i].split('=', 1)[0].strip() == key:
+ lines[i] = entry
+ break
+ else:
+ lines.insert(end, entry)
+ end += 1
+ return '\n'.join(lines).rstrip() + '\n'
+
+
class DevtoolIdeMode(Enum):
"""Different modes are supported by the ide-sdk plugin.
@@ -1122,6 +1150,62 @@ 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:
+ original = config_file.read()
+ except FileNotFoundError as exc:
+ raise DevtoolError(
+ 'Cargo config not found at %s; build the recipe first' % source_config) from exc
+
+ content = (
+ '# Generated by devtool ide-sdk for the active build environment.\n'
+ '\n'
+ + original)
+ content = set_toml_table_values(content, 'build', {
+ 'target': json.dumps(self.cargo_target),
+ })
+ content = set_toml_table_values(content, 'target.%s' % self.cargo_target, {
+ 'linker': json.dumps(self.cargo_linker),
+ 'rustflags': json.dumps(shlex.split(self.cargo_rustflags)),
+ })
+ 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',
+ )
+ env_values = {}
+ for name in env_names:
+ value = self.cargo_env.get(name)
+ if value is not None:
+ env_values[name] = '{ value = %s, force = true }' % json.dumps(str(value))
+ content = set_toml_table_values(content, 'env', env_values)
+
+ 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
--
2.53.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 04/20] devtool: ide-sdk: recommend Rust Analyzer for Cargo
2026-10-26 8:55 [PATCH 00/20] devtool: ide-sdk: add support for Rust recipes Enguerrand de Ribaucourt
` (2 preceding siblings ...)
2026-10-26 8:55 ` [PATCH 03/20] devtool: ide-sdk: export recipe Cargo configuration Enguerrand de Ribaucourt
@ 2026-10-26 8:55 ` Enguerrand de Ribaucourt
2026-10-28 22:48 ` [OE-core] " adrian.freihofer
2026-10-26 8:55 ` [PATCH 05/20] devtool: ide-sdk: configure " Enguerrand de Ribaucourt
` (16 subsequent siblings)
20 siblings, 1 reply; 31+ messages in thread
From: Enguerrand de Ribaucourt @ 2026-10-26 8:55 UTC (permalink / raw)
To: openembedded-core; +Cc: Adrian Freihofer, Enguerrand de Ribaucourt
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 <enguerrand.de-ribaucourt@savoirfairelinux.com>
---
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 265f2147a4..941f54e36b 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
--
2.53.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 05/20] devtool: ide-sdk: configure Rust Analyzer for Cargo
2026-10-26 8:55 [PATCH 00/20] devtool: ide-sdk: add support for Rust recipes Enguerrand de Ribaucourt
` (3 preceding siblings ...)
2026-10-26 8:55 ` [PATCH 04/20] devtool: ide-sdk: recommend Rust Analyzer for Cargo Enguerrand de Ribaucourt
@ 2026-10-26 8:55 ` Enguerrand de Ribaucourt
2026-10-26 8:55 ` [PATCH 06/20] devtool: ide-sdk: share IntelliSense architecture mapping Enguerrand de Ribaucourt
` (15 subsequent siblings)
20 siblings, 0 replies; 31+ messages in thread
From: Enguerrand de Ribaucourt @ 2026-10-26 8:55 UTC (permalink / raw)
To: openembedded-core; +Cc: Adrian Freihofer, Enguerrand de Ribaucourt
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 <enguerrand.de-ribaucourt@savoirfairelinux.com>
---
meta/lib/oeqa/selftest/cases/devtool.py | 12 +++++++++++-
scripts/lib/devtool/ide_plugins/ide_code.py | 11 +++++++++++
2 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py
index 941f54e36b..d1e15d0180 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..85f286335f 100644
--- a/scripts/lib/devtool/ide_plugins/ide_code.py
+++ b/scripts/lib/devtool/ide_plugins/ide_code.py
@@ -228,6 +228,16 @@ class IdeVSCode(IdeBase):
}
]
+ def __vscode_settings_cargo(self, settings_dict, modified_recipe):
+ if modified_recipe.build_tool is not BuildTool.CARGO:
+ return
+ cargo_config = modified_recipe.update_cargo_config()
+ 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"] = cargo_config
+
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 +304,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)
--
2.53.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 06/20] devtool: ide-sdk: share IntelliSense architecture mapping
2026-10-26 8:55 [PATCH 00/20] devtool: ide-sdk: add support for Rust recipes Enguerrand de Ribaucourt
` (4 preceding siblings ...)
2026-10-26 8:55 ` [PATCH 05/20] devtool: ide-sdk: configure " Enguerrand de Ribaucourt
@ 2026-10-26 8:55 ` Enguerrand de Ribaucourt
2026-10-26 8:55 ` [PATCH 07/20] devtool: ide-sdk: configure Cargo C++ IntelliSense Enguerrand de Ribaucourt
` (14 subsequent siblings)
20 siblings, 0 replies; 31+ messages in thread
From: Enguerrand de Ribaucourt @ 2026-10-26 8:55 UTC (permalink / raw)
To: openembedded-core; +Cc: Adrian Freihofer, Enguerrand de Ribaucourt
Move the target architecture map out of the Meson branch so Cargo C/C++
IntelliSense for FFI and build-script code can reuse the same mapping instead
of duplicating it.
AI-Generated: Uses GitHub Copilot
Signed-off-by: Enguerrand de Ribaucourt <enguerrand.de-ribaucourt@savoirfairelinux.com>
---
scripts/lib/devtool/ide_plugins/ide_code.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/scripts/lib/devtool/ide_plugins/ide_code.py b/scripts/lib/devtool/ide_plugins/ide_code.py
index 85f286335f..95ef472ed4 100644
--- a/scripts/lib/devtool/ide_plugins/ide_code.py
+++ b/scripts/lib/devtool/ide_plugins/ide_code.py
@@ -352,16 +352,16 @@ class IdeVSCode(IdeBase):
properties_dict = {
"name": modified_recipe.recipe_id_pretty,
}
+ arch_map = {
+ 'aarch64': 'arm64', 'x86_64': 'x64', 'arm': 'arm',
+ 'i686': 'x86', 'i586': 'x86', 'riscv64': 'x64', 'riscv32': 'x86',
+ }
if modified_recipe.build_tool is BuildTool.CMAKE:
properties_dict["configurationProvider"] = "ms-vscode.cmake-tools"
elif modified_recipe.build_tool is BuildTool.MESON:
# configurationProvider = "mesonbuild.mesonbuild" does not work because
# the cross-compiler is not in PATH and omits the sysroot by default.
compiler_type = 'clang' if modified_recipe.toolchain == 'clang' else 'gcc'
- arch_map = {
- 'aarch64': 'arm64', 'x86_64': 'x64', 'arm': 'arm',
- 'i686': 'x86', 'i586': 'x86', 'riscv64': 'x64', 'riscv32': 'x86',
- }
intelli_arch = arch_map.get(modified_recipe.target_arch, 'x64')
properties_dict["compilerPath"] = os.path.join(
modified_recipe.staging_bindir_toolchain,
--
2.53.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 07/20] devtool: ide-sdk: configure Cargo C++ IntelliSense
2026-10-26 8:55 [PATCH 00/20] devtool: ide-sdk: add support for Rust recipes Enguerrand de Ribaucourt
` (5 preceding siblings ...)
2026-10-26 8:55 ` [PATCH 06/20] devtool: ide-sdk: share IntelliSense architecture mapping Enguerrand de Ribaucourt
@ 2026-10-26 8:55 ` Enguerrand de Ribaucourt
2026-10-28 22:59 ` [OE-core] " adrian.freihofer
2026-10-26 8:55 ` [PATCH 08/20] devtool: ide-sdk: generalize binary install task name Enguerrand de Ribaucourt
` (13 subsequent siblings)
20 siblings, 1 reply; 31+ messages in thread
From: Enguerrand de Ribaucourt @ 2026-10-26 8:55 UTC (permalink / raw)
To: openembedded-core; +Cc: Adrian Freihofer, Enguerrand de Ribaucourt
Recommend cpptools for Cargo's native C/C++ code and configure its cross
compiler, sysroot, and include path. Reuse the shared architecture mapping
so IntelliSense matches the recipe environment. The selftest checks the
generated compiler and sysroot settings.
AI-Generated: Uses GitHub Copilot
Signed-off-by: Enguerrand de Ribaucourt <enguerrand.de-ribaucourt@savoirfairelinux.com>
---
meta/lib/oeqa/selftest/cases/devtool.py | 27 ++++++++++++++++++++++++++
scripts/lib/devtool/ide_plugins/ide_code.py | 30 ++++++++++++++++++++---------
2 files changed, 48 insertions(+), 9 deletions(-)
diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py
index d1e15d0180..990a3060aa 100644
--- a/meta/lib/oeqa/selftest/cases/devtool.py
+++ b/meta/lib/oeqa/selftest/cases/devtool.py
@@ -4353,15 +4353,42 @@ class DevtoolIdeSdkRustTests(DevtoolIdeSdkTests):
settings = json.load(settings_file)
with open(os.path.join(tempdir, '.vscode', 'extensions.json')) as extensions_file:
extensions = json.load(extensions_file)
+ with open(os.path.join(tempdir, '.vscode', 'c_cpp_properties.json')) as properties_file:
+ properties = json.load(properties_file)['configurations'][0]
+ recipe_sysroot = os.path.realpath(get_bb_var('RECIPE_SYSROOT', 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')
+ with open(cargo_config) as cargo_config_file:
+ cargo_config_text = cargo_config_file.read()
+ cargo_class_env = {
+ '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',
+ }
+ for name, value in cargo_class_env.items():
+ self.assertIn(
+ '%s = { value = "%s", force = true }' % (name, value),
+ cargo_config_text)
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.assertEqual(
+ properties['compilerPath'],
+ shlex.split(get_bb_var('RUST_TARGET_CXX', recipe_name))[0])
+ self.assertEqual(
+ properties['compilerArgs'], ['--sysroot=' + recipe_sysroot])
+ self.assertIn(os.path.join(recipe_sysroot, 'usr', 'include'),
+ properties['includePath'])
self.assertIn('rust-lang.rust-analyzer', extensions['recommendations'])
+ self.assertIn('ms-vscode.cpptools', 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 95ef472ed4..fcd2e5b5fe 100644
--- a/scripts/lib/devtool/ide_plugins/ide_code.py
+++ b/scripts/lib/devtool/ide_plugins/ide_code.py
@@ -9,6 +9,7 @@ import json
import logging
import os
import shutil
+import shlex
from devtool.ide_plugins import BuildTool, IdeBase, GdbCrossConfig, DebuggerServerModes, LldbServerConfig, get_devtool_deploy_opts, resolve_deploy_target
logger = logging.getLogger('devtool')
@@ -315,7 +316,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",
+ "ms-vscode.cpptools",
+ ]
# 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
@@ -358,18 +362,26 @@ class IdeVSCode(IdeBase):
}
if modified_recipe.build_tool is BuildTool.CMAKE:
properties_dict["configurationProvider"] = "ms-vscode.cmake-tools"
- elif modified_recipe.build_tool is BuildTool.MESON:
- # configurationProvider = "mesonbuild.mesonbuild" does not work because
- # the cross-compiler is not in PATH and omits the sysroot by default.
+ elif modified_recipe.build_tool in (BuildTool.MESON, BuildTool.CARGO):
compiler_type = 'clang' if modified_recipe.toolchain == 'clang' else 'gcc'
intelli_arch = arch_map.get(modified_recipe.target_arch, 'x64')
- properties_dict["compilerPath"] = os.path.join(
- modified_recipe.staging_bindir_toolchain,
- modified_recipe.cxx.split()[0])
+ if modified_recipe.build_tool is BuildTool.MESON:
+ # configurationProvider = "mesonbuild.mesonbuild" does not work
+ # because the cross-compiler is not in PATH and omits the sysroot.
+ properties_dict["compilerPath"] = os.path.join(
+ modified_recipe.staging_bindir_toolchain,
+ modified_recipe.cxx.split()[0])
+ properties_dict["compileCommands"] = os.path.join(
+ modified_recipe.b, 'compile_commands.json')
+ else:
+ properties_dict["compilerPath"] = shlex.split(
+ modified_recipe.cargo_env['CXX'])[0]
+ properties_dict["includePath"] = [
+ "${workspaceFolder}/**",
+ os.path.join(modified_recipe.recipe_sysroot, "usr", "include")
+ ]
properties_dict["compilerArgs"] = [
"--sysroot=" + modified_recipe.recipe_sysroot]
- properties_dict["compileCommands"] = os.path.join(
- modified_recipe.b, 'compile_commands.json')
properties_dict["intelliSenseMode"] = "linux-%s-%s" % (compiler_type, intelli_arch)
elif modified_recipe.build_tool is BuildTool.KERNEL_MODULE:
# Using e.g. configurationProvider = "ms-vscode.makefile-tools" was not successful
--
2.53.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 08/20] devtool: ide-sdk: generalize binary install task name
2026-10-26 8:55 [PATCH 00/20] devtool: ide-sdk: add support for Rust recipes Enguerrand de Ribaucourt
` (6 preceding siblings ...)
2026-10-26 8:55 ` [PATCH 07/20] devtool: ide-sdk: configure Cargo C++ IntelliSense Enguerrand de Ribaucourt
@ 2026-10-26 8:55 ` Enguerrand de Ribaucourt
2026-10-26 8:55 ` [PATCH 09/20] devtool: ide-sdk: extract install task definition Enguerrand de Ribaucourt
` (12 subsequent siblings)
20 siblings, 0 replies; 31+ messages in thread
From: Enguerrand de Ribaucourt @ 2026-10-26 8:55 UTC (permalink / raw)
To: openembedded-core; +Cc: Adrian Freihofer, Enguerrand de Ribaucourt
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 <enguerrand.de-ribaucourt@savoirfairelinux.com>
---
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 fcd2e5b5fe..53cebe71a8 100644
--- a/scripts/lib/devtool/ide_plugins/ide_code.py
+++ b/scripts/lib/devtool/ide_plugins/ide_code.py
@@ -674,7 +674,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)]
@@ -976,7 +976,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:
--
2.53.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 09/20] devtool: ide-sdk: extract install task definition
2026-10-26 8:55 [PATCH 00/20] devtool: ide-sdk: add support for Rust recipes Enguerrand de Ribaucourt
` (7 preceding siblings ...)
2026-10-26 8:55 ` [PATCH 08/20] devtool: ide-sdk: generalize binary install task name Enguerrand de Ribaucourt
@ 2026-10-26 8:55 ` Enguerrand de Ribaucourt
2026-10-26 8:55 ` [PATCH 10/20] devtool: ide-sdk: order install after optional build task Enguerrand de Ribaucourt
` (11 subsequent siblings)
20 siblings, 0 replies; 31+ messages in thread
From: Enguerrand de Ribaucourt @ 2026-10-26 8:55 UTC (permalink / raw)
To: openembedded-core; +Cc: Adrian Freihofer, Enguerrand de Ribaucourt
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 <enguerrand.de-ribaucourt@savoirfairelinux.com>
---
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 53cebe71a8..b5ff344e8a 100644
--- a/scripts/lib/devtool/ide_plugins/ide_code.py
+++ b/scripts/lib/devtool/ide_plugins/ide_code.py
@@ -682,17 +682,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:
--
2.53.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 10/20] devtool: ide-sdk: order install after optional build task
2026-10-26 8:55 [PATCH 00/20] devtool: ide-sdk: add support for Rust recipes Enguerrand de Ribaucourt
` (8 preceding siblings ...)
2026-10-26 8:55 ` [PATCH 09/20] devtool: ide-sdk: extract install task definition Enguerrand de Ribaucourt
@ 2026-10-26 8:55 ` Enguerrand de Ribaucourt
2026-10-28 23:01 ` [OE-core] " adrian.freihofer
2026-10-26 8:55 ` [PATCH 11/20] devtool: ide-sdk: add Cargo " Enguerrand de Ribaucourt
` (10 subsequent siblings)
20 siblings, 1 reply; 31+ messages in thread
From: Enguerrand de Ribaucourt @ 2026-10-26 8:55 UTC (permalink / raw)
To: openembedded-core; +Cc: Adrian Freihofer, Enguerrand de Ribaucourt
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 <enguerrand.de-ribaucourt@savoirfairelinux.com>
---
scripts/lib/devtool/ide_plugins/ide_code.py | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/scripts/lib/devtool/ide_plugins/ide_code.py b/scripts/lib/devtool/ide_plugins/ide_code.py
index b5ff344e8a..80314bfb89 100644
--- a/scripts/lib/devtool/ide_plugins/ide_code.py
+++ b/scripts/lib/devtool/ide_plugins/ide_code.py
@@ -674,7 +674,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)]
@@ -689,9 +689,21 @@ class IdeVSCode(IdeBase):
"args": deploy_args,
"problemMatcher": []
}
+ tasks = [build_task] if build_task else []
+ install_task = {
+ "label": install_task_name,
+ "type": "shell",
+ "command": run_install_deploy,
+ "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:
--
2.53.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 11/20] devtool: ide-sdk: add Cargo build task
2026-10-26 8:55 [PATCH 00/20] devtool: ide-sdk: add support for Rust recipes Enguerrand de Ribaucourt
` (9 preceding siblings ...)
2026-10-26 8:55 ` [PATCH 10/20] devtool: ide-sdk: order install after optional build task Enguerrand de Ribaucourt
@ 2026-10-26 8:55 ` Enguerrand de Ribaucourt
2026-10-28 23:04 ` [OE-core] " adrian.freihofer
2026-10-26 8:55 ` [PATCH 12/20] devtool: ide-sdk: enforce LLDB for Cargo Enguerrand de Ribaucourt
` (9 subsequent siblings)
20 siblings, 1 reply; 31+ messages in thread
From: Enguerrand de Ribaucourt @ 2026-10-26 8:55 UTC (permalink / raw)
To: openembedded-core; +Cc: Adrian Freihofer, Enguerrand de Ribaucourt
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 <enguerrand.de-ribaucourt@savoirfairelinux.com>
---
meta/lib/oeqa/selftest/cases/devtool.py | 37 +++++++++++++++++++++++++++++
scripts/lib/devtool/ide_plugins/ide_code.py | 25 +++++++++++++++++++
2 files changed, 62 insertions(+)
diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py
index 990a3060aa..bd0bfb06ec 100644
--- a/meta/lib/oeqa/selftest/cases/devtool.py
+++ b/meta/lib/oeqa/selftest/cases/devtool.py
@@ -4390,6 +4390,43 @@ class DevtoolIdeSdkRustTests(DevtoolIdeSdkTests):
self.assertIn('rust-lang.rust-analyzer', extensions['recommendations'])
self.assertIn('ms-vscode.cpptools', 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'})
+
+ 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 80314bfb89..089016c639 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
import shlex
from devtool.ide_plugins import BuildTool, IdeBase, GdbCrossConfig, DebuggerServerModes, LldbServerConfig, get_devtool_deploy_opts, resolve_deploy_target
@@ -852,6 +853,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": []
+ }
+ 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)
@@ -990,6 +1013,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)
--
2.53.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 12/20] devtool: ide-sdk: enforce LLDB for Cargo
2026-10-26 8:55 [PATCH 00/20] devtool: ide-sdk: add support for Rust recipes Enguerrand de Ribaucourt
` (10 preceding siblings ...)
2026-10-26 8:55 ` [PATCH 11/20] devtool: ide-sdk: add Cargo " Enguerrand de Ribaucourt
@ 2026-10-26 8:55 ` Enguerrand de Ribaucourt
2026-10-28 23:08 ` [OE-core] " adrian.freihofer
2026-10-26 8:55 ` [PATCH 13/20] devtool: ide-sdk: parse Rust debug path remaps Enguerrand de Ribaucourt
` (8 subsequent siblings)
20 siblings, 1 reply; 31+ messages in thread
From: Enguerrand de Ribaucourt @ 2026-10-26 8:55 UTC (permalink / raw)
To: openembedded-core; +Cc: Adrian Freihofer, Enguerrand de Ribaucourt
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 <enguerrand.de-ribaucourt@savoirfairelinux.com>
---
meta/lib/oeqa/selftest/cases/devtool.py | 22 ++++++++++++++++++
scripts/lib/devtool/ide_plugins/ide_code.py | 3 ++-
scripts/lib/devtool/ide_sdk.py | 35 ++++++++++++++++++-----------
3 files changed, 46 insertions(+), 14 deletions(-)
diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py
index bd0bfb06ec..38bd3301cf 100644
--- a/meta/lib/oeqa/selftest/cases/devtool.py
+++ b/meta/lib/oeqa/selftest/cases/devtool.py
@@ -4390,6 +4390,28 @@ class DevtoolIdeSdkRustTests(DevtoolIdeSdkTests):
self.assertIn('rust-lang.rust-analyzer', extensions['recommendations'])
self.assertIn('ms-vscode.cpptools', extensions['recommendations'])
+ def test_code_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 '
+ '--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')
+ 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 089016c639..e18c6a703d 100644
--- a/scripts/lib/devtool/ide_plugins/ide_code.py
+++ b/scripts/lib/devtool/ide_plugins/ide_code.py
@@ -320,6 +320,7 @@ class IdeVSCode(IdeBase):
recommendations += [
"rust-lang.rust-analyzer",
"ms-vscode.cpptools",
+ "vadimcn.vscode-lldb"
]
# clangd (matched to the recipe's real cross compiler via
# compile_commands.json) replaces cpptools as the IntelliSense provider
@@ -1023,7 +1024,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_sdk.py b/scripts/lib/devtool/ide_sdk.py
index 21229f5970..44429e80b0 100755
--- a/scripts/lib/devtool/ide_sdk.py
+++ b/scripts/lib/devtool/ide_sdk.py
@@ -433,11 +433,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
@@ -1150,6 +1150,14 @@ 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.
+ 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')
@@ -2032,20 +2040,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:
--
2.53.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 13/20] devtool: ide-sdk: parse Rust debug path remaps
2026-10-26 8:55 [PATCH 00/20] devtool: ide-sdk: add support for Rust recipes Enguerrand de Ribaucourt
` (11 preceding siblings ...)
2026-10-26 8:55 ` [PATCH 12/20] devtool: ide-sdk: enforce LLDB for Cargo Enguerrand de Ribaucourt
@ 2026-10-26 8:55 ` Enguerrand de Ribaucourt
2026-10-28 23:16 ` [OE-core] " adrian.freihofer
2026-10-26 8:55 ` [PATCH 14/20] devtool: ide-sdk: remap Cargo sources for BitBake builds Enguerrand de Ribaucourt
` (7 subsequent siblings)
20 siblings, 1 reply; 31+ messages in thread
From: Enguerrand de Ribaucourt @ 2026-10-26 8:55 UTC (permalink / raw)
To: openembedded-core; +Cc: Adrian Freihofer, Enguerrand de Ribaucourt
Use Cargo RUSTFLAGS to populate reverse debug mappings and recognize Rust
--remap-path-prefix alongside the existing GCC prefix-map options. The
following LLDB source-map change depends on these normalized mappings.
AI-Generated: Uses GitHub Copilot
Signed-off-by: Enguerrand de Ribaucourt <enguerrand.de-ribaucourt@savoirfairelinux.com>
---
scripts/lib/devtool/ide_sdk.py | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/scripts/lib/devtool/ide_sdk.py b/scripts/lib/devtool/ide_sdk.py
index 44429e80b0..f22a98cedf 100755
--- a/scripts/lib/devtool/ide_sdk.py
+++ b/scripts/lib/devtool/ide_sdk.py
@@ -1140,6 +1140,9 @@ class RecipeModified:
if self.build_tool is BuildTool.KERNEL_MODULE:
self.reverse_debug_prefix_map = self._init_reverse_debug_prefix_map(
self.kernel_cc)
+ elif self.build_tool is BuildTool.CARGO:
+ self.reverse_debug_prefix_map = self._init_reverse_debug_prefix_map(
+ self.cargo_rustflags)
else:
self.reverse_debug_prefix_map = self._init_reverse_debug_prefix_map(
recipe_d.getVar('DEBUG_PREFIX_MAP'))
@@ -1292,15 +1295,20 @@ class RecipeModified:
return ':'.join(self.solib_search_path(image))
def _init_reverse_debug_prefix_map(self, debug_prefix_map):
- """Parses GCC map options and returns a mapping of target to host paths.
+ """Parses compiler map options and returns a mapping of target to host paths.
- This function scans a string containing GCC options such as -fdebug-prefix-map,
+ This function scans a string containing compiler options such as -fdebug-prefix-map,
-fmacro-prefix-map, and -ffile-prefix-map (in both '--option value' and '--option=value'
forms), extracting all mappings from target paths (used in debug info) to host source
paths. If multiple mappings for the same target path are found, the most suitable
host path is selected (preferring 'sources' over 'build' directories).
"""
- prefixes = ("-fdebug-prefix-map", "-fmacro-prefix-map", "-ffile-prefix-map")
+ prefixes = (
+ "-fdebug-prefix-map",
+ "-fmacro-prefix-map",
+ "-ffile-prefix-map",
+ "--remap-path-prefix",
+ )
all_mappings = {}
args = shlex.split(debug_prefix_map)
i = 0
--
2.53.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 14/20] devtool: ide-sdk: remap Cargo sources for BitBake builds
2026-10-26 8:55 [PATCH 00/20] devtool: ide-sdk: add support for Rust recipes Enguerrand de Ribaucourt
` (12 preceding siblings ...)
2026-10-26 8:55 ` [PATCH 13/20] devtool: ide-sdk: parse Rust debug path remaps Enguerrand de Ribaucourt
@ 2026-10-26 8:55 ` Enguerrand de Ribaucourt
2026-10-28 23:28 ` [OE-core] " adrian.freihofer
2026-10-26 8:55 ` [PATCH 15/20] devtool: ide-sdk: map Cargo workspace sources for LLDB Enguerrand de Ribaucourt
` (6 subsequent siblings)
20 siblings, 1 reply; 31+ messages in thread
From: Enguerrand de Ribaucourt @ 2026-10-26 8:55 UTC (permalink / raw)
To: openembedded-core; +Cc: Adrian Freihofer, Enguerrand de Ribaucourt
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
Signed-off-by: Enguerrand de Ribaucourt <enguerrand.de-ribaucourt@savoirfairelinux.com>
---
scripts/lib/devtool/ide_sdk.py | 38 ++++++++++++++++++++++++++++----------
1 file changed, 28 insertions(+), 10 deletions(-)
diff --git a/scripts/lib/devtool/ide_sdk.py b/scripts/lib/devtool/ide_sdk.py
index f22a98cedf..9fd95f0a63 100755
--- a/scripts/lib/devtool/ide_sdk.py
+++ b/scripts/lib/devtool/ide_sdk.py
@@ -823,6 +823,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
@@ -943,13 +944,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 IDE dependencies and Cargo debug path remaps."""
wants_clang_native = (
self.build_tool.is_c_cpp
and self.ide_sdk_intellisense == 'clangd'
@@ -962,28 +964,44 @@ 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:
+ # Managed sections were stripped before parsing, so compare against
+ # what BitBake parsed rather than the saved pre-strip contents.
+ if new_content == parsed_content:
return False
appends_dir = os.path.dirname(self.bbappend)
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):
--
2.53.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 15/20] devtool: ide-sdk: map Cargo workspace sources for LLDB
2026-10-26 8:55 [PATCH 00/20] devtool: ide-sdk: add support for Rust recipes Enguerrand de Ribaucourt
` (13 preceding siblings ...)
2026-10-26 8:55 ` [PATCH 14/20] devtool: ide-sdk: remap Cargo sources for BitBake builds Enguerrand de Ribaucourt
@ 2026-10-26 8:55 ` Enguerrand de Ribaucourt
2026-10-26 8:55 ` [PATCH 16/20] devtool: ide-sdk: map libstd-rs sources to Rust SDK Enguerrand de Ribaucourt
` (5 subsequent siblings)
20 siblings, 0 replies; 31+ messages in thread
From: Enguerrand de Ribaucourt @ 2026-10-26 8:55 UTC (permalink / raw)
To: openembedded-core; +Cc: Adrian Freihofer, Enguerrand de Ribaucourt
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 <enguerrand.de-ribaucourt@savoirfairelinux.com>
---
meta/lib/oeqa/selftest/cases/devtool.py | 3 +++
scripts/lib/devtool/ide_plugins/ide_code.py | 13 ++++++++++---
2 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py
index 38bd3301cf..ca76597bbe 100644
--- a/meta/lib/oeqa/selftest/cases/devtool.py
+++ b/meta/lib/oeqa/selftest/cases/devtool.py
@@ -4408,6 +4408,9 @@ class DevtoolIdeSdkRustTests(DevtoolIdeSdkTests):
self.assertIn('vadimcn.vscode-lldb', extensions['recommendations'])
self.assertEqual(launch['type'], 'lldb')
+ 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])
diff --git a/scripts/lib/devtool/ide_plugins/ide_code.py b/scripts/lib/devtool/ide_plugins/ide_code.py
index e18c6a703d..596586ee9e 100644
--- a/scripts/lib/devtool/ide_plugins/ide_code.py
+++ b/scripts/lib/devtool/ide_plugins/ide_code.py
@@ -566,15 +566,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. '
--
2.53.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 16/20] devtool: ide-sdk: map libstd-rs sources to Rust SDK
2026-10-26 8:55 [PATCH 00/20] devtool: ide-sdk: add support for Rust recipes Enguerrand de Ribaucourt
` (14 preceding siblings ...)
2026-10-26 8:55 ` [PATCH 15/20] devtool: ide-sdk: map Cargo workspace sources for LLDB Enguerrand de Ribaucourt
@ 2026-10-26 8:55 ` Enguerrand de Ribaucourt
2026-10-28 23:23 ` [OE-core] " adrian.freihofer
2026-10-26 8:55 ` [PATCH 17/20] oeqa/selftest: share source breakpoint lookup Enguerrand de Ribaucourt
` (4 subsequent siblings)
20 siblings, 1 reply; 31+ messages in thread
From: Enguerrand de Ribaucourt @ 2026-10-26 8:55 UTC (permalink / raw)
To: openembedded-core; +Cc: Adrian Freihofer, Enguerrand de Ribaucourt
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 <enguerrand.de-ribaucourt@savoirfairelinux.com>
---
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 596586ee9e..623a54ddc6 100644
--- a/scripts/lib/devtool/ide_plugins/ide_code.py
+++ b/scripts/lib/devtool/ide_plugins/ide_code.py
@@ -568,6 +568,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 9fd95f0a63..b6ac02e367 100755
--- a/scripts/lib/devtool/ide_sdk.py
+++ b/scripts/lib/devtool/ide_sdk.py
@@ -915,6 +915,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
@@ -1134,6 +1135,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(
+ self.recipe_sysroot_native, self.libdir.lstrip('/'),
+ '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
--
2.53.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 17/20] oeqa/selftest: share source breakpoint lookup
2026-10-26 8:55 [PATCH 00/20] devtool: ide-sdk: add support for Rust recipes Enguerrand de Ribaucourt
` (15 preceding siblings ...)
2026-10-26 8:55 ` [PATCH 16/20] devtool: ide-sdk: map libstd-rs sources to Rust SDK Enguerrand de Ribaucourt
@ 2026-10-26 8:55 ` Enguerrand de Ribaucourt
2026-10-26 8:55 ` [PATCH 18/20] oeqa/selftest: run IDE tasks with configured environment Enguerrand de Ribaucourt
` (3 subsequent siblings)
20 siblings, 0 replies; 31+ messages in thread
From: Enguerrand de Ribaucourt @ 2026-10-26 8:55 UTC (permalink / raw)
To: openembedded-core; +Cc: Adrian Freihofer, Enguerrand de Ribaucourt
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 <enguerrand.de-ribaucourt@savoirfairelinux.com>
---
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 ca76597bbe..99e6531877 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
@@ -4876,20 +4890,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
--
2.53.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 18/20] oeqa/selftest: run IDE tasks with configured environment
2026-10-26 8:55 [PATCH 00/20] devtool: ide-sdk: add support for Rust recipes Enguerrand de Ribaucourt
` (16 preceding siblings ...)
2026-10-26 8:55 ` [PATCH 17/20] oeqa/selftest: share source breakpoint lookup Enguerrand de Ribaucourt
@ 2026-10-26 8:55 ` Enguerrand de Ribaucourt
2026-10-26 8:55 ` [PATCH 19/20] oeqa/selftest: debug Cargo example over QEMU slirp Enguerrand de Ribaucourt
` (2 subsequent siblings)
20 siblings, 0 replies; 31+ messages in thread
From: Enguerrand de Ribaucourt @ 2026-10-26 8:55 UTC (permalink / raw)
To: openembedded-core; +Cc: Adrian Freihofer, Enguerrand de Ribaucourt
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 <enguerrand.de-ribaucourt@savoirfairelinux.com>
---
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 99e6531877..114536fc16 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."""
--
2.53.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 19/20] oeqa/selftest: debug Cargo example over QEMU slirp
2026-10-26 8:55 [PATCH 00/20] devtool: ide-sdk: add support for Rust recipes Enguerrand de Ribaucourt
` (17 preceding siblings ...)
2026-10-26 8:55 ` [PATCH 18/20] oeqa/selftest: run IDE tasks with configured environment Enguerrand de Ribaucourt
@ 2026-10-26 8:55 ` Enguerrand de Ribaucourt
2026-10-26 8:55 ` [PATCH 20/20] oeqa/selftest: verify Cargo rebuild and redeploy Enguerrand de Ribaucourt
2026-10-28 23:30 ` [OE-core] [PATCH 00/20] devtool: ide-sdk: add support for Rust recipes adrian.freihofer
20 siblings, 0 replies; 31+ messages in thread
From: Enguerrand de Ribaucourt @ 2026-10-26 8:55 UTC (permalink / raw)
To: openembedded-core; +Cc: Adrian Freihofer, Enguerrand de Ribaucourt
Exercise Cargo deploy and CodeLLDB launch against oe-selftest-image over
slirp. Verify source breakpoints, Rust and runtime backtrace frames, and
that BitBake's 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 <enguerrand.de-ribaucourt@savoirfairelinux.com>
---
meta/lib/oeqa/selftest/cases/devtool.py | 127 ++++++++++++++++++++++++++++++++
1 file changed, 127 insertions(+)
diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py
index 114536fc16..87dc8a1ee5 100644
--- a/meta/lib/oeqa/selftest/cases/devtool.py
+++ b/meta/lib/oeqa/selftest/cases/devtool.py
@@ -4472,6 +4472,133 @@ 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')
+ runCmd(
+ 'devtool ide-sdk %s %s %s --skip-bitbake --ide=code%s' % (
+ recipe_name, testimage,
+ '-t root@%s -P %s --no-host-check' % (qemu.ip, qemu.port),
+ port_opts),
+ output_log=self._cmd_logger)
+ rustflags = shlex.split(get_bb_var('RUSTFLAGS', recipe_name))
+ self.assertIn(
+ source_remap, rustflags,
+ 'Repeated ide-sdk runs must preserve the Cargo source remap')
+ 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('RECIPE_SYSROOT_NATIVE', 'cargo-example'),
+ 'usr', 'lib', '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):
--
2.53.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* [PATCH 20/20] oeqa/selftest: verify Cargo rebuild and redeploy
2026-10-26 8:55 [PATCH 00/20] devtool: ide-sdk: add support for Rust recipes Enguerrand de Ribaucourt
` (18 preceding siblings ...)
2026-10-26 8:55 ` [PATCH 19/20] oeqa/selftest: debug Cargo example over QEMU slirp Enguerrand de Ribaucourt
@ 2026-10-26 8:55 ` Enguerrand de Ribaucourt
2026-10-28 23:30 ` [OE-core] [PATCH 00/20] devtool: ide-sdk: add support for Rust recipes adrian.freihofer
20 siblings, 0 replies; 31+ messages in thread
From: Enguerrand de Ribaucourt @ 2026-10-26 8:55 UTC (permalink / raw)
To: openembedded-core; +Cc: Adrian Freihofer, Enguerrand de Ribaucourt
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 <enguerrand.de-ribaucourt@savoirfairelinux.com>
---
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 87dc8a1ee5..b9adb624c4 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
@@ -4511,6 +4520,28 @@ class DevtoolIdeSdkRustTests(DevtoolIdeSdkTests):
'Repeated ide-sdk runs must preserve the Cargo source remap')
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]
--
2.53.0
^ permalink raw reply related [flat|nested] 31+ messages in thread
* Re: [OE-core] [PATCH 03/20] devtool: ide-sdk: export recipe Cargo configuration
2026-10-26 8:55 ` [PATCH 03/20] devtool: ide-sdk: export recipe Cargo configuration Enguerrand de Ribaucourt
@ 2026-10-28 22:40 ` adrian.freihofer
0 siblings, 0 replies; 31+ messages in thread
From: adrian.freihofer @ 2026-10-28 22:40 UTC (permalink / raw)
To: enguerrand.de-ribaucourt, openembedded-core; +Cc: Adrian Freihofer
There are probably two issues with set_toml_table_values() which should
be fixed.
Multi-line values
The helper only replaces the first line of an existing key. If
config.toml already has a multi-line value, e.g. rustflags = [\n "-
C",\n "link-arg=-lfoo",\n], the key line is replaced with the new
single-line value but the continuation lines ("-C", "link-arg=-lfoo",
]) are left behind, which is invalid TOML.
It also doesn't recognise a header written as [ build ]. It appends a
second [build] table instead of updating the existing one.
Trailing comments
New keys are inserted at the end of a table, and the end is found by
searching for the next [ line.
Blank and comment lines before that next header are treated as part of
the table. In the generated cargo-config.toml, the # BUILD_SYS comment
(which describes the next table) ends up above the injected rustflags.
Please insert new keys after the last key/value line of the table
instead.
A tomllib.loads() check of the generated file in a selftest would also
be cheap.
Thank you,
Adrian
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [OE-core] [PATCH 04/20] devtool: ide-sdk: recommend Rust Analyzer for Cargo
2026-10-26 8:55 ` [PATCH 04/20] devtool: ide-sdk: recommend Rust Analyzer for Cargo Enguerrand de Ribaucourt
@ 2026-10-28 22:48 ` adrian.freihofer
0 siblings, 0 replies; 31+ messages in thread
From: adrian.freihofer @ 2026-10-28 22:48 UTC (permalink / raw)
To: enguerrand.de-ribaucourt, openembedded-core; +Cc: Adrian Freihofer
It also recommends ms-vscode.cpptools. That is only justified by the
C++ IntelliSense patch (7/20). For a pure-Rust crate, cpptools isn't
needed (see my reply to 7/20). Maybe it should be removed at least for
now.
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [OE-core] [PATCH 07/20] devtool: ide-sdk: configure Cargo C++ IntelliSense
2026-10-26 8:55 ` [PATCH 07/20] devtool: ide-sdk: configure Cargo C++ IntelliSense Enguerrand de Ribaucourt
@ 2026-10-28 22:59 ` adrian.freihofer
0 siblings, 0 replies; 31+ messages in thread
From: adrian.freihofer @ 2026-10-28 22:59 UTC (permalink / raw)
To: enguerrand.de-ribaucourt, openembedded-core; +Cc: Adrian Freihofer
The crate in the example has no C or C++ code, yet but a
c_cpp_properties.json is generated. cpptools starts as soon as the file
exists, and ${workspaceFolder}/** recursively reaches the whole workdir
through the oe-workdir link, plus rootfs-dbg/usr/src/debug/**
(including kernel sources).
Why is this needed at all? I'm not very rusty. But I would assume that
with Yocto C/C++ libraries linked by Rust binaries should go into
separate packages rather than building the C/C++ code bundled. That
would then mean that ide-sdk would generate either a Cargo or a C/C++
configuration for the IDE without a need for mixed setups.
If there is a need for bundled C/C++ setups this should probably come
with test coverage and therefore also with a example using this
features.
Regards,
Adrian
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [OE-core] [PATCH 10/20] devtool: ide-sdk: order install after optional build task
2026-10-26 8:55 ` [PATCH 10/20] devtool: ide-sdk: order install after optional build task Enguerrand de Ribaucourt
@ 2026-10-28 23:01 ` adrian.freihofer
0 siblings, 0 replies; 31+ messages in thread
From: adrian.freihofer @ 2026-10-28 23:01 UTC (permalink / raw)
To: enguerrand.de-ribaucourt, openembedded-core; +Cc: Adrian Freihofer
On Mon, 2026-10-26 at 09:55 +0100, Enguerrand de Ribaucourt via
lists.openembedded.org wrote:
> 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
> <enguerrand.de-ribaucourt@savoirfairelinux.com>
> ---
> scripts/lib/devtool/ide_plugins/ide_code.py | 16 ++++++++++++++--
> 1 file changed, 14 insertions(+), 2 deletions(-)
>
> diff --git a/scripts/lib/devtool/ide_plugins/ide_code.py
> b/scripts/lib/devtool/ide_plugins/ide_code.py
> index b5ff344e8a..80314bfb89 100644
> --- a/scripts/lib/devtool/ide_plugins/ide_code.py
> +++ b/scripts/lib/devtool/ide_plugins/ide_code.py
> @@ -674,7 +674,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)]
> @@ -689,9 +689,21 @@ class IdeVSCode(IdeBase):
> "args": deploy_args,
> "problemMatcher": []
> }
> + tasks = [build_task] if build_task else []
> + install_task = {
This is now set twice.
Regards,
Adrian
> + "label": install_task_name,
> + "type": "shell",
> + "command": run_install_deploy,
> + "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:
>
>
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#248648):
> https://lists.openembedded.org/g/openembedded-core/message/248648
> Mute This Topic: https://lists.openembedded.org/mt/121938791/4454582
> Group Owner: openembedded-core+owner@lists.openembedded.org
> Unsubscribe:
> https://lists.openembedded.org/g/openembedded-core/unsub [
> adrian.freihofer@gmail.com]
> -=-=-=-=-=-=-=-=-=-=-=-
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [OE-core] [PATCH 11/20] devtool: ide-sdk: add Cargo build task
2026-10-26 8:55 ` [PATCH 11/20] devtool: ide-sdk: add Cargo " Enguerrand de Ribaucourt
@ 2026-10-28 23:04 ` adrian.freihofer
0 siblings, 0 replies; 31+ messages in thread
From: adrian.freihofer @ 2026-10-28 23:04 UTC (permalink / raw)
To: enguerrand.de-ribaucourt, openembedded-core; +Cc: Adrian Freihofer
On Mon, 2026-10-26 at 09:55 +0100, Enguerrand de Ribaucourt via
lists.openembedded.org wrote:
> 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
> <enguerrand.de-ribaucourt@savoirfairelinux.com>
> ---
> meta/lib/oeqa/selftest/cases/devtool.py | 37
> +++++++++++++++++++++++++++++
> scripts/lib/devtool/ide_plugins/ide_code.py | 25 +++++++++++++++++++
> 2 files changed, 62 insertions(+)
>
> diff --git a/meta/lib/oeqa/selftest/cases/devtool.py
> b/meta/lib/oeqa/selftest/cases/devtool.py
> index 990a3060aa..bd0bfb06ec 100644
> --- a/meta/lib/oeqa/selftest/cases/devtool.py
> +++ b/meta/lib/oeqa/selftest/cases/devtool.py
> @@ -4390,6 +4390,43 @@ class
> DevtoolIdeSdkRustTests(DevtoolIdeSdkTests):
> self.assertIn('rust-lang.rust-analyzer',
> extensions['recommendations'])
> self.assertIn('ms-vscode.cpptools',
> 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'})
> +
> + 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 80314bfb89..089016c639 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
> import shlex
Duplicate.
> from devtool.ide_plugins import BuildTool, IdeBase, GdbCrossConfig,
> DebuggerServerModes, LldbServerConfig, get_devtool_deploy_opts,
> resolve_deploy_target
> @@ -852,6 +853,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": []
Problem matcher. The build task has "problemMatcher": [], so compiler
errors never reach the Problems panel. Should this be "$rustc" ?
Regards,
Adrian
> + }
> + 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)
> @@ -990,6 +1013,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)
>
>
>
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#248649):
> https://lists.openembedded.org/g/openembedded-core/message/248649
> Mute This Topic: https://lists.openembedded.org/mt/121938792/4454582
> Group Owner: openembedded-core+owner@lists.openembedded.org
> Unsubscribe:
> https://lists.openembedded.org/g/openembedded-core/unsub [
> adrian.freihofer@gmail.com]
> -=-=-=-=-=-=-=-=-=-=-=-
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [OE-core] [PATCH 12/20] devtool: ide-sdk: enforce LLDB for Cargo
2026-10-26 8:55 ` [PATCH 12/20] devtool: ide-sdk: enforce LLDB for Cargo Enguerrand de Ribaucourt
@ 2026-10-28 23:08 ` adrian.freihofer
0 siblings, 0 replies; 31+ messages in thread
From: adrian.freihofer @ 2026-10-28 23:08 UTC (permalink / raw)
To: enguerrand.de-ribaucourt, openembedded-core; +Cc: Adrian Freihofer
Hi,
This is a blocking issue. uses_lldb is wired into ide_sdk.py (debugger
selection, wants_lldb_server) and ide_code.py, but not into
ide_plugins/ide_none.py. ide_none.setup_modified_recipe() still checks
toolchain == 'clang'.
With --ide=none or --ide=all on a Cargo recipe, the image gets lldb-
server and RecipeLldbNative, but GdbCrossConfigNone generates gdbserver
scripts for a gdbserver that isn't on the target. Please use
modified_recipe.uses_lldb there.
No test can catch this today, since all Cargo tests use --ide=code
only. Please add a Cargo --ide=code --ide=none test without QEMU,
asserting the generated debugger configuration and install script, as
the C++ _test_code_and_none_qemu does.
Also, the comment citing the VS Code Rust docs is good. Please add one
sentence on why cppdbg/GDB can't resolve Rust breakpoints.
Best regards
Adrian
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [OE-core] [PATCH 13/20] devtool: ide-sdk: parse Rust debug path remaps
2026-10-26 8:55 ` [PATCH 13/20] devtool: ide-sdk: parse Rust debug path remaps Enguerrand de Ribaucourt
@ 2026-10-28 23:16 ` adrian.freihofer
0 siblings, 0 replies; 31+ messages in thread
From: adrian.freihofer @ 2026-10-28 23:16 UTC (permalink / raw)
To: enguerrand.de-ribaucourt, openembedded-core; +Cc: Adrian Freihofer
On Mon, 2026-10-26 at 09:55 +0100, Enguerrand de Ribaucourt via
lists.openembedded.org wrote:
> Use Cargo RUSTFLAGS to populate reverse debug mappings and recognize
> Rust
> --remap-path-prefix alongside the existing GCC prefix-map options.
> The
> following LLDB source-map change depends on these normalized
> mappings.
>
> AI-Generated: Uses GitHub Copilot
> Signed-off-by: Enguerrand de Ribaucourt
> <enguerrand.de-ribaucourt@savoirfairelinux.com>
> ---
> scripts/lib/devtool/ide_sdk.py | 14 +++++++++++---
> 1 file changed, 11 insertions(+), 3 deletions(-)
>
> diff --git a/scripts/lib/devtool/ide_sdk.py
> b/scripts/lib/devtool/ide_sdk.py
> index 44429e80b0..f22a98cedf 100755
> --- a/scripts/lib/devtool/ide_sdk.py
> +++ b/scripts/lib/devtool/ide_sdk.py
> @@ -1140,6 +1140,9 @@ class RecipeModified:
> if self.build_tool is BuildTool.KERNEL_MODULE:
> self.reverse_debug_prefix_map =
> self._init_reverse_debug_prefix_map(
> self.kernel_cc)
> + elif self.build_tool is BuildTool.CARGO:
> + self.reverse_debug_prefix_map =
> self._init_reverse_debug_prefix_map(
> + self.cargo_rustflags)
> else:
> self.reverse_debug_prefix_map =
> self._init_reverse_debug_prefix_map(
> recipe_d.getVar('DEBUG_PREFIX_MAP'))
> @@ -1292,15 +1295,20 @@ class RecipeModified:
> return ':'.join(self.solib_search_path(image))
>
> def _init_reverse_debug_prefix_map(self, debug_prefix_map):
> - """Parses GCC map options and returns a mapping of target to
> host paths.
> + """Parses compiler map options and returns a mapping of
> target to host paths.
>
> - This function scans a string containing GCC options such as
> -fdebug-prefix-map,
> + This function scans a string containing compiler options
> such as -fdebug-prefix-map,
> -fmacro-prefix-map, and -ffile-prefix-map (in both '--option
> value' and '--option=value'
> forms), extracting all mappings from target paths (used in
> debug info) to host source
> paths. If multiple mappings for the same target path are
> found, the most suitable
> host path is selected (preferring 'sources' over 'build'
> directories).
> """
> - prefixes = ("-fdebug-prefix-map", "-fmacro-prefix-map", "-
> ffile-prefix-map")
> + prefixes = (
> + "-fdebug-prefix-map",
> + "-fmacro-prefix-map",
> + "-ffile-prefix-map",
> + "--remap-path-prefix",
mapping.split('=', 1) splits --remap-path-prefix mappings on the first
=, but rustc splits on the last. It only matters for paths containing
=; .
Regards,
Adrian
> + )
> all_mappings = {}
> args = shlex.split(debug_prefix_map)
> i = 0
>
>
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#248650):
> https://lists.openembedded.org/g/openembedded-core/message/248650
> Mute This Topic: https://lists.openembedded.org/mt/121938793/4454582
> Group Owner: openembedded-core+owner@lists.openembedded.org
> Unsubscribe:
> https://lists.openembedded.org/g/openembedded-core/unsub [
> adrian.freihofer@gmail.com]
> -=-=-=-=-=-=-=-=-=-=-=-
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [OE-core] [PATCH 16/20] devtool: ide-sdk: map libstd-rs sources to Rust SDK
2026-10-26 8:55 ` [PATCH 16/20] devtool: ide-sdk: map libstd-rs sources to Rust SDK Enguerrand de Ribaucourt
@ 2026-10-28 23:23 ` adrian.freihofer
0 siblings, 0 replies; 31+ messages in thread
From: adrian.freihofer @ 2026-10-28 23:23 UTC (permalink / raw)
To: enguerrand.de-ribaucourt, openembedded-core; +Cc: Adrian Freihofer
On Mon, 2026-10-26 at 09:55 +0100, Enguerrand de Ribaucourt via
lists.openembedded.org wrote:
> 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
> <enguerrand.de-ribaucourt@savoirfairelinux.com>
> ---
> 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 596586ee9e..623a54ddc6 100644
> --- a/scripts/lib/devtool/ide_plugins/ide_code.py
> +++ b/scripts/lib/devtool/ide_plugins/ide_code.py
> @@ -568,6 +568,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 9fd95f0a63..b6ac02e367 100755
> --- a/scripts/lib/devtool/ide_sdk.py
> +++ b/scripts/lib/devtool/ide_sdk.py
> @@ -915,6 +915,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
> @@ -1134,6 +1135,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(
> + self.recipe_sysroot_native,
> self.libdir.lstrip('/'),
The native rustlib path is built with self.libdir (the target libdir).
On multilib (/usr/lib64) it doesn't match the rust-native sysroot.
Please use the native libdir (STAGING_LIBDIR_NATIVE). The selftest
hard-codes usr/lib and so doesn't catch this.
Regards,
Adrian
> + '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
>
>
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#248654):
> https://lists.openembedded.org/g/openembedded-core/message/248654
> Mute This Topic: https://lists.openembedded.org/mt/121938797/4454582
> Group Owner: openembedded-core+owner@lists.openembedded.org
> Unsubscribe:
> https://lists.openembedded.org/g/openembedded-core/unsub [
> adrian.freihofer@gmail.com]
> -=-=-=-=-=-=-=-=-=-=-=-
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [OE-core] [PATCH 14/20] devtool: ide-sdk: remap Cargo sources for BitBake builds
2026-10-26 8:55 ` [PATCH 14/20] devtool: ide-sdk: remap Cargo sources for BitBake builds Enguerrand de Ribaucourt
@ 2026-10-28 23:28 ` adrian.freihofer
0 siblings, 0 replies; 31+ messages in thread
From: adrian.freihofer @ 2026-10-28 23:28 UTC (permalink / raw)
To: enguerrand.de-ribaucourt, openembedded-core; +Cc: Adrian Freihofer
On Mon, 2026-10-26 at 09:55 +0100, Enguerrand de Ribaucourt via
lists.openembedded.org wrote:
> 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
> Signed-off-by: Enguerrand de Ribaucourt
> <enguerrand.de-ribaucourt@savoirfairelinux.com>
> ---
> scripts/lib/devtool/ide_sdk.py | 38 ++++++++++++++++++++++++++++----
> ------
> 1 file changed, 28 insertions(+), 10 deletions(-)
>
> diff --git a/scripts/lib/devtool/ide_sdk.py
> b/scripts/lib/devtool/ide_sdk.py
> index f22a98cedf..9fd95f0a63 100755
> --- a/scripts/lib/devtool/ide_sdk.py
> +++ b/scripts/lib/devtool/ide_sdk.py
> @@ -823,6 +823,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
> @@ -943,13 +944,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 IDE dependencies and Cargo debug path
> remaps."""
> wants_clang_native = (
> self.build_tool.is_c_cpp
> and self.ide_sdk_intellisense == 'clangd'
> @@ -962,28 +964,44 @@ 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:
> + # Managed sections were stripped before parsing, so compare
> against
> + # what BitBake parsed rather than the saved pre-strip
> contents.
> + if new_content == parsed_content:
> return False
>
> appends_dir = os.path.dirname(self.bbappend)
> 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
update_bbappend() compares new_content == parsed_content, but
new_content is parsed_content plus the new section, so they never
match. The function now always returns True when it generates a
section. Every run rewrites the bbappend and forces a reparse, and this
regresses existing clangd users, who got False when nothing changed.
Regards,
Adrian
>
> def initialize(self, config, workspace, tinfoil):
>
>
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#248652):
> https://lists.openembedded.org/g/openembedded-core/message/248652
> Mute This Topic: https://lists.openembedded.org/mt/121938795/4454582
> Group Owner: openembedded-core+owner@lists.openembedded.org
> Unsubscribe:
> https://lists.openembedded.org/g/openembedded-core/unsub [
> adrian.freihofer@gmail.com]
> -=-=-=-=-=-=-=-=-=-=-=-
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: [OE-core] [PATCH 00/20] devtool: ide-sdk: add support for Rust recipes
2026-10-26 8:55 [PATCH 00/20] devtool: ide-sdk: add support for Rust recipes Enguerrand de Ribaucourt
` (19 preceding siblings ...)
2026-10-26 8:55 ` [PATCH 20/20] oeqa/selftest: verify Cargo rebuild and redeploy Enguerrand de Ribaucourt
@ 2026-10-28 23:30 ` adrian.freihofer
20 siblings, 0 replies; 31+ messages in thread
From: adrian.freihofer @ 2026-10-28 23:30 UTC (permalink / raw)
To: enguerrand.de-ribaucourt, openembedded-core; +Cc: Adrian Freihofer
Hi Enguerrand
Thanks for the series. The structure follows the existing CMake/Meson
support well. The QEMU test shows the whole build → deploy → debug →
rebuild cycle working. That's already very nice.
Three issues should be fixed before merge. Each is in a reply to the
matching patch:
12/20: ide_none is not updated for LLDB.
14/20: update_bbappend() always reports a change.
16/20: the native rustlib path is built from the target libdir.
Smaller points are in the other replies. Some of them I confirmed by
inspecting the generated .vscode files from a real run.
Also, we should consider to start without C/C++ support mixed into Rust
configurations.
Test coverage is thinner than for C/C++. Cargo has one QEMU scenario
(slirp, --ide=code only). There is no --ide=none, NFS, tap or shared-
sysroots coverage, and no recipe with dependencies. We can add this
later.
Best regards
Adrian
^ permalink raw reply [flat|nested] 31+ messages in thread
end of thread, other threads:[~2026-10-28 23:30 UTC | newest]
Thread overview: 31+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-26 8:55 [PATCH 00/20] devtool: ide-sdk: add support for Rust recipes Enguerrand de Ribaucourt
2026-10-26 8:55 ` [PATCH 01/20] cargo-example: add minimal selftest fixture Enguerrand de Ribaucourt
2026-10-26 8:55 ` [PATCH 02/20] devtool: ide-sdk: capture Cargo cross environment Enguerrand de Ribaucourt
2026-10-26 8:55 ` [PATCH 03/20] devtool: ide-sdk: export recipe Cargo configuration Enguerrand de Ribaucourt
2026-10-28 22:40 ` [OE-core] " adrian.freihofer
2026-10-26 8:55 ` [PATCH 04/20] devtool: ide-sdk: recommend Rust Analyzer for Cargo Enguerrand de Ribaucourt
2026-10-28 22:48 ` [OE-core] " adrian.freihofer
2026-10-26 8:55 ` [PATCH 05/20] devtool: ide-sdk: configure " Enguerrand de Ribaucourt
2026-10-26 8:55 ` [PATCH 06/20] devtool: ide-sdk: share IntelliSense architecture mapping Enguerrand de Ribaucourt
2026-10-26 8:55 ` [PATCH 07/20] devtool: ide-sdk: configure Cargo C++ IntelliSense Enguerrand de Ribaucourt
2026-10-28 22:59 ` [OE-core] " adrian.freihofer
2026-10-26 8:55 ` [PATCH 08/20] devtool: ide-sdk: generalize binary install task name Enguerrand de Ribaucourt
2026-10-26 8:55 ` [PATCH 09/20] devtool: ide-sdk: extract install task definition Enguerrand de Ribaucourt
2026-10-26 8:55 ` [PATCH 10/20] devtool: ide-sdk: order install after optional build task Enguerrand de Ribaucourt
2026-10-28 23:01 ` [OE-core] " adrian.freihofer
2026-10-26 8:55 ` [PATCH 11/20] devtool: ide-sdk: add Cargo " Enguerrand de Ribaucourt
2026-10-28 23:04 ` [OE-core] " adrian.freihofer
2026-10-26 8:55 ` [PATCH 12/20] devtool: ide-sdk: enforce LLDB for Cargo Enguerrand de Ribaucourt
2026-10-28 23:08 ` [OE-core] " adrian.freihofer
2026-10-26 8:55 ` [PATCH 13/20] devtool: ide-sdk: parse Rust debug path remaps Enguerrand de Ribaucourt
2026-10-28 23:16 ` [OE-core] " adrian.freihofer
2026-10-26 8:55 ` [PATCH 14/20] devtool: ide-sdk: remap Cargo sources for BitBake builds Enguerrand de Ribaucourt
2026-10-28 23:28 ` [OE-core] " adrian.freihofer
2026-10-26 8:55 ` [PATCH 15/20] devtool: ide-sdk: map Cargo workspace sources for LLDB Enguerrand de Ribaucourt
2026-10-26 8:55 ` [PATCH 16/20] devtool: ide-sdk: map libstd-rs sources to Rust SDK Enguerrand de Ribaucourt
2026-10-28 23:23 ` [OE-core] " adrian.freihofer
2026-10-26 8:55 ` [PATCH 17/20] oeqa/selftest: share source breakpoint lookup Enguerrand de Ribaucourt
2026-10-26 8:55 ` [PATCH 18/20] oeqa/selftest: run IDE tasks with configured environment Enguerrand de Ribaucourt
2026-10-26 8:55 ` [PATCH 19/20] oeqa/selftest: debug Cargo example over QEMU slirp Enguerrand de Ribaucourt
2026-10-26 8:55 ` [PATCH 20/20] oeqa/selftest: verify Cargo rebuild and redeploy Enguerrand de Ribaucourt
2026-10-28 23:30 ` [OE-core] [PATCH 00/20] devtool: ide-sdk: add support for Rust recipes adrian.freihofer
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox