@@ -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()
@@ -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:
@@ -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:
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(-)