diff mbox series

[v2,10/18] devtool: ide-sdk: add Cargo build task

Message ID 20261109-devtool-ide-sdk-cargo-v2-10-d56134000561@savoirfairelinux.com
State New
Headers show
Series devtool: ide-sdk: add support for Rust recipes | expand

Commit Message

Enguerrand de Ribaucourt Nov. 9, 2026, 1:44 p.m. UTC
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>

---
Changes in v2:
- Use the rustc problem matcher for Cargo build diagnostics.
---
 meta/lib/oeqa/selftest/cases/devtool.py     | 38 +++++++++++++++++++++++++++++
 scripts/lib/devtool/ide_plugins/ide_code.py | 25 +++++++++++++++++++
 2 files changed, 63 insertions(+)
diff mbox series

Patch

diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py
index ee055c218a..ef13eaa09a 100644
--- a/meta/lib/oeqa/selftest/cases/devtool.py
+++ b/meta/lib/oeqa/selftest/cases/devtool.py
@@ -4363,6 +4363,44 @@  class DevtoolIdeSdkRustTests(DevtoolIdeSdkTests):
         self.assertNotIn('rust-analyzer.cargo.extraEnv', settings)
         self.assertIn('rust-lang.rust-analyzer', extensions['recommendations'])
 
+    def test_code_cargo_build_task(self):
+        recipe_name = "cargo-example"
+        self._check_workspace()
+        self._write_bb_config()
+        tempdir = self._devtool_ide_sdk_recipe(recipe_name, "Cargo.toml", None)
+        runCmd('devtool ide-sdk %s oe-selftest-image --ide=code '
+               '--target root@localhost --no-host-check' % recipe_name,
+               output_log=self._cmd_logger)
+
+        with open(os.path.join(tempdir, '.vscode', 'tasks.json')) as tasks_file:
+            tasks = json.load(tasks_file)['tasks']
+        build_task = next(task for task in tasks
+                          if task['label'].startswith('cargo build '))
+        cargo_config = os.path.join(
+            self.workspacedir, 'ide-sdk', recipe_name, 'cargo-config.toml')
+        self.assertEqual(build_task['command'], get_bb_var('CARGO', recipe_name))
+        self.assertEqual(
+            build_task['args'][:3], ['--config', cargo_config, 'build'])
+        self.assertIn('--features', build_task['args'])
+        self.assertIn('ide-sdk-selftest', build_task['args'])
+        self.assertEqual(set(build_task['options']['env']), {'PATH'})
+        self.assertEqual(build_task['problemMatcher'], '$rustc')
+
+        build_env = os.environ.copy()
+        build_env.update(build_task['options']['env'])
+        result = subprocess.run(
+            [build_task['command']] + build_task['args'],
+            cwd=build_task['options']['cwd'], env=build_env,
+            stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
+            universal_newlines=True)
+        self.assertEqual(result.returncode, 0, result.stdout)
+
+        install_task = next(
+            task for task in tasks
+            if task['label'].startswith('install && deploy-target '))
+        self.assertEqual(install_task['dependsOn'], [build_task['label']])
+
+
 class DevtoolIdeSdkKernelTests(DevtoolIdeSdkTests):
 
     @OETestTag("runqemu")
diff --git a/scripts/lib/devtool/ide_plugins/ide_code.py b/scripts/lib/devtool/ide_plugins/ide_code.py
index 5d35be4f52..cb54948ce1 100644
--- a/scripts/lib/devtool/ide_plugins/ide_code.py
+++ b/scripts/lib/devtool/ide_plugins/ide_code.py
@@ -8,6 +8,7 @@ 
 import json
 import logging
 import os
+import shlex
 import shutil
 from devtool.ide_plugins import BuildTool, IdeBase, GdbCrossConfig, DebuggerServerModes, LldbServerConfig, get_devtool_deploy_opts, resolve_deploy_target
 
@@ -832,6 +833,28 @@  class IdeVSCode(IdeBase):
         IdeBase.update_json_file(
             self.dot_code_dir(modified_recipe), tasks_file, tasks_dict)
 
+    def vscode_tasks_cargo(self, args, image_recipe, modified_recipe):
+        build_task_name = "cargo build %s" % modified_recipe.recipe_id_pretty
+        cargo_config = modified_recipe.cargo_config_path
+        build_task = {
+            "label": build_task_name,
+            "type": "shell",
+            "command": modified_recipe.cargo,
+            "args": ["--config", cargo_config, "build"] +
+                     shlex.split(modified_recipe.cargo_build_flags) +
+                     shlex.split(modified_recipe.cargo_packageconfig_confargs),
+            "options": {
+                "cwd": modified_recipe.real_srctree,
+                "env": {"PATH": modified_recipe.path},
+            },
+            "group": {
+                "kind": "build",
+                "isDefault": True
+            },
+            "problemMatcher": "$rustc"
+        }
+        self.vscode_tasks_binary(args, image_recipe, modified_recipe, build_task)
+
     def vscode_tasks_fallback(self, args, image_recipe, modified_recipe):
         oe_init_dir = modified_recipe.oe_init_dir
         oe_init = ". %s %s > /dev/null && " % (modified_recipe.oe_init_build_env, modified_recipe.topdir)
@@ -970,6 +993,8 @@  class IdeVSCode(IdeBase):
             self.vscode_tasks_binary(args, image_recipe, modified_recipe)
         elif modified_recipe.build_tool == BuildTool.KERNEL_MODULE:
             self.vscode_tasks_kernel_module(args, image_recipe, modified_recipe)
+        elif modified_recipe.build_tool == BuildTool.CARGO:
+            self.vscode_tasks_cargo(args, image_recipe, modified_recipe)
         else:
             self.vscode_tasks_fallback(args, image_recipe, modified_recipe)