From: AdrianF <adrian.freihofer@siemens.com>
To: openembedded-core@lists.openembedded.org
Cc: Adrian Freihofer <adrian.freihofer@siemens.com>
Subject: [PATCH v2 14/14] oe-selftest: devtool ide-sdk: add test for ide=none LLDB/clang support
Date: Tue, 4 Aug 2026 13:59:38 +0200 [thread overview]
Message-ID: <20260804120034.378787-15-adrian.freihofer@siemens.com> (raw)
In-Reply-To: <20260804120034.378787-1-adrian.freihofer@siemens.com>
From: Adrian Freihofer <adrian.freihofer@siemens.com>
Add test_devtool_ide_sdk_none_cmake_clang to DevtoolIdeSdkTests to
exercise the new LldbServerConfigNone code path in ide_none.py.
The test uses the cmake-example-clang recipe (TOOLCHAIN = "clang") and
runs devtool ide-sdk with --ide=none. It verifies:
- lldb_server_<port>_<binary>_multi script is generated
- lldbinit/lldbinit_<port>_<binary> init file is generated
- lldb_<port>_<binary> wrapper script is generated
- No gdbserver_* script is generated for a clang recipe
- The install_and_deploy script exists
- The oe-scripts symlink inside the source tree is valid
- lldb-server can be started on the target via the generated script
- The pid file written by the start script references the live process
- An lldb --batch session using the generated wrapper reaches main and
can evaluate CppExample::test_string at the breakpoint
- lldb-server stops cleanly via the generated stop script
A new helper _lldb_none_debugging_multi is added alongside the
existing _gdb_cross_debugging_multi, following the same structure.
Signed-off-by: Adrian Freihofer <adrian.freihofer@siemens.com>
---
meta/lib/oeqa/selftest/cases/devtool.py | 192 ++++++++++++++++++++++++
1 file changed, 192 insertions(+)
diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py
index e9b8f38449..7145755fed 100644
--- a/meta/lib/oeqa/selftest/cases/devtool.py
+++ b/meta/lib/oeqa/selftest/cases/devtool.py
@@ -4378,6 +4378,198 @@ class DevtoolIdeSdkTests(DevtoolBase):
lambda magic_string: self._lldb_server_debugging_once(
tempdir, qemu, magic_string))
+ def _lldb_none_debugging_multi(self, tempdir, qemu, recipe_name, example_exe, magic_string):
+ """Verify lldb-server scripts generated by ide=none work end-to-end.
+
+ Mirrors _gdb_cross_debugging_multi but for the LLDB/clang path:
+ - uses the generated lldb_server_* start/stop script
+ - uses the generated lldb_* wrapper script with lldb --batch
+
+ Covers the executable, the library and a header-only inline function
+ (see _lldb_debug_cpp_example_batch_commands), since a single call-site
+ breakpoint would not exercise (and thus not catch a regression in) the
+ lldbinit source map / debug-file-search-paths setup for the library's
+ own debug info specifically.
+ """
+ sshargs = '-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no'
+ scripts_dir = self._workspace_scripts_dir(recipe_name)
+ binary_pretty = 'usr-bin-' + example_exe
+ lldb_server_script = os.path.join(
+ scripts_dir, 'lldb_server_1234_%s_multi' % binary_pretty)
+ lldb_script = os.path.join(scripts_dir, 'lldb_1234_%s' % binary_pretty)
+
+ self.assertExists(lldb_server_script)
+ self.assertExists(lldb_script)
+
+ # Start lldb-server (script exits once the port is ready)
+ r = runCmd(lldb_server_script, output_log=self._cmd_logger)
+ self.assertEqual(r.status, 0)
+
+ # Verify lldb-server is running on the target
+ r = runCmd('ssh %s root@%s ps' % (sshargs, qemu.ip),
+ output_log=self._cmd_logger)
+ self.assertEqual(r.status, 0)
+ self.assertIn('lldb-server', r.output)
+
+ # Verify the pid file points at the running lldb-server process
+ pid_file = '/tmp/lldb_server_1234_%s_multi/lldb_server.pid' % binary_pretty
+ test_cmd = "'cat /proc/$(cat %s)/cmdline'" % pid_file
+ r = runCmd('ssh %s root@%s %s' % (sshargs, qemu.ip, test_cmd),
+ output_log=self._cmd_logger)
+ self.assertEqual(r.status, 0)
+ self.assertIn('lldb-server', r.output)
+
+ # Run an lldb batch session covering the executable, library and
+ # header breakpoints, then continue to completion
+ lldb_batch_args = self._lldb_debug_cpp_example_batch_commands(tempdir)
+ r = runCmd([lldb_script, '--batch'] + lldb_batch_args,
+ output_log=self._cmd_logger)
+ self.logger.debug("lldb batch output: %s", r.output)
+ self.assertEqual(r.status, 0)
+ self._lldb_debug_cpp_example_check(r.output, magic_string)
+
+ # Stop lldb-server
+ r = runCmd(lldb_server_script + ' stop', output_log=self._cmd_logger)
+ self.assertEqual(r.status, 0)
+
+ # Verify lldb-server is no longer running
+ r = runCmd('ssh %s root@%s ps' % (sshargs, qemu.ip),
+ output_log=self._cmd_logger)
+ self.assertEqual(r.status, 0)
+ self.assertNotIn('lldb-server', r.output)
+
+ @OETestTag("runqemu")
+ def test_devtool_ide_sdk_none_cmake_clang(self):
+ """Verify ide=none generates correct LLDB scripts for a clang cmake recipe.
+
+ Uses cmake-example-clang (TOOLCHAIN = "clang") which is built with the
+ clang toolchain. devtool ide-sdk with --ide=none should produce:
+ - lldb_server_<port>_<binary>_multi (start/stop script)
+ - lldbinit/lldbinit_<port>_<binary> (platform connect + source maps)
+ - lldb_<port>_<binary> (lldb wrapper)
+
+ The test verifies that lldb-server can be started via the generated
+ script, and that a basic lldb --batch debugging session reaches main.
+ """
+ recipe_name = 'cmake-example-clang'
+ example_exe = 'cmake-example-clang'
+ build_file = 'CMakeLists.txt'
+ testimage = 'oe-selftest-image'
+
+ self._check_workspace()
+ self._write_bb_config([recipe_name], extra_packages=['lldb-server'])
+ self._check_runqemu_prerequisites()
+ bitbake(testimage)
+ with runqemu(testimage, runqemuparams='nographic') as qemu:
+ tempdir = self._devtool_ide_sdk_recipe(recipe_name, build_file, testimage)
+ bitbake_sdk_cmd = 'devtool ide-sdk %s %s -t root@%s -c --ide=none' % (
+ recipe_name, testimage, qemu.ip)
+ runCmd(bitbake_sdk_cmd, output_log=self._cmd_logger)
+
+ # Verify cmake preset still works (build system unchanged)
+ compile_cmd = self._verify_cmake_preset(tempdir)
+
+ # Verify install && deploy script exists
+ # (_verify_install_script_code opens .vscode/tasks.json which is not
+ # generated for ide=none; check the script path directly instead)
+ recipe_id, _ = self._get_recipe_ids(recipe_name)
+ scripts_dir = self._workspace_scripts_dir(recipe_name)
+ self.assertExists(os.path.join(
+ scripts_dir, 'install_and_deploy_' + recipe_id))
+
+ # Verify LLDB scripts were generated (not GDB scripts)
+ binary_pretty = 'usr-bin-' + example_exe
+ self.assertExists(os.path.join(
+ scripts_dir, 'lldb_server_1234_%s_multi' % binary_pretty))
+ self.assertExists(os.path.join(
+ scripts_dir, 'lldbinit', 'lldbinit_1234_%s' % binary_pretty))
+ self.assertExists(os.path.join(
+ scripts_dir, 'lldb_1234_%s' % binary_pretty))
+ # No GDB scripts should have been generated for a clang recipe
+ self.assertFalse(os.path.exists(os.path.join(
+ scripts_dir, 'gdbserver_1234_%s_multi' % binary_pretty)),
+ 'gdbserver script should not be generated for clang recipe')
+
+ # Verify the oe-scripts sym-link is valid
+ self.assertEqual(self._workspace_scripts_dir(recipe_name),
+ self._sources_scripts_dir(tempdir))
+
+ # Verify end-to-end lldb debugging, before and after a code
+ # change/recompile/redeploy cycle (see _lldb_cross_debugging_multi)
+ self._lldb_cross_debugging_multi(
+ tempdir, recipe_name, compile_cmd,
+ lambda magic_string: self._lldb_none_debugging_multi(
+ tempdir, qemu, recipe_name, example_exe, magic_string))
+
+ @OETestTag("runqemu")
+ def test_devtool_ide_sdk_none_meson_clang(self):
+ """Verify ide=none generates correct LLDB scripts for a clang meson recipe.
+
+ This is the meson/ninja counterpart of test_devtool_ide_sdk_none_cmake_clang.
+ It is required in addition to the cmake/clang test because meson/ninja
+ (unlike cmake here) invoke the compiler with source paths relative to
+ the build directory, which is what previously caused source-level
+ breakpoints to be left unresolved (pending) for devtool workspaces due
+ to -fdebug-prefix-map/-ffile-prefix-map underflow; see
+ _lldb_none_debugging_multi.
+
+ Uses meson-example-clang (TOOLCHAIN = "clang").
+ """
+ recipe_name = 'meson-example-clang'
+ example_exe = 'mesonex-clang'
+ build_file = 'meson.build'
+ testimage = 'oe-selftest-image'
+
+ self._check_workspace()
+ self._write_bb_config([recipe_name], extra_packages=['lldb-server'])
+ self._check_runqemu_prerequisites()
+
+ # Build image with debug settings (lldb-server for clang) before starting QEMU
+ tempdir = self._devtool_ide_sdk_recipe(recipe_name, build_file, testimage)
+ runCmd('devtool ide-sdk %s %s -c --ide=none' % (recipe_name, testimage),
+ output_log=self._cmd_logger)
+
+ with runqemu(testimage, runqemuparams='nographic') as qemu:
+ # Re-run with actual QEMU IP; image is already built
+ bitbake_sdk_cmd = 'devtool ide-sdk %s %s -t root@%s -c --skip-bitbake --ide=none' % (
+ recipe_name, testimage, qemu.ip)
+ runCmd(bitbake_sdk_cmd, output_log=self._cmd_logger)
+
+ # Verify the meson build system still works (unchanged by clang/lldb support)
+ compile_cmd = self._verify_meson_build(tempdir, recipe_name)
+
+ # Verify install && deploy script exists
+ # (_verify_install_script_code opens .vscode/tasks.json which is not
+ # generated for ide=none; check the script path directly instead)
+ recipe_id, _ = self._get_recipe_ids(recipe_name)
+ scripts_dir = self._workspace_scripts_dir(recipe_name)
+ self.assertExists(os.path.join(
+ scripts_dir, 'install_and_deploy_' + recipe_id))
+
+ # Verify LLDB scripts were generated (not GDB scripts)
+ binary_pretty = 'usr-bin-' + example_exe
+ self.assertExists(os.path.join(
+ scripts_dir, 'lldb_server_1234_%s_multi' % binary_pretty))
+ self.assertExists(os.path.join(
+ scripts_dir, 'lldbinit', 'lldbinit_1234_%s' % binary_pretty))
+ self.assertExists(os.path.join(
+ scripts_dir, 'lldb_1234_%s' % binary_pretty))
+ # No GDB scripts should have been generated for a clang recipe
+ self.assertFalse(os.path.exists(os.path.join(
+ scripts_dir, 'gdbserver_1234_%s_multi' % binary_pretty)),
+ 'gdbserver script should not be generated for clang recipe')
+
+ # Verify the oe-scripts sym-link is valid
+ self.assertEqual(self._workspace_scripts_dir(recipe_name),
+ self._sources_scripts_dir(tempdir))
+
+ # Verify end-to-end lldb debugging, before and after a code
+ # change/recompile/redeploy cycle (see _lldb_cross_debugging_multi)
+ self._lldb_cross_debugging_multi(
+ tempdir, recipe_name, compile_cmd,
+ lambda magic_string: self._lldb_none_debugging_multi(
+ tempdir, qemu, recipe_name, example_exe, magic_string))
+
def test_devtool_ide_sdk_plugins(self):
"""Test that devtool ide-sdk can use plugins from other layers."""
--
2.55.0
prev parent reply other threads:[~2026-08-04 12:00 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-04 11:59 [PATCH v2 00/14] devtool ide-sdk: clang and lldb support AdrianF
2026-08-04 11:59 ` [PATCH v2 01/14] oe-selftest: devtool: use stat for reading user/group names in ide-sdk tests AdrianF
2026-08-04 11:59 ` [PATCH v2 02/14] devtool: ide-sdk: fix duplicate -p flag in _target_ssh_args AdrianF
2026-08-04 11:59 ` [PATCH v2 03/14] devtool: ide-sdk: fix $@ overwritten by set in install_and_deploy script AdrianF
2026-08-04 11:59 ` [PATCH v2 04/14] devtool: ide-sdk: fix meson compile_commands.json AdrianF
2026-08-04 11:59 ` [PATCH v2 05/14] devtool: deploy-target: fix run strip under pseudo AdrianF
2026-08-04 11:59 ` [PATCH v2 06/14] oe-selftest: devtool ide-sdk: cover breakpoints in exe, header and library AdrianF
2026-08-04 11:59 ` [PATCH v2 07/14] oe-selftest: devtool ide-sdk: add real debug coverage for meson+code AdrianF
2026-08-04 11:59 ` [PATCH v2 08/14] devtool: ide-sdk debugger back-end abstraction AdrianF
2026-08-04 11:59 ` [PATCH v2 09/14] devtool: ide-sdk: wait for gdbserver port before returning AdrianF
2026-08-04 11:59 ` [PATCH v2 10/14] devtool: ide-sdk add LLDB support for clang toolchain AdrianF
2026-08-04 11:59 ` [PATCH v2 11/14] devtool: ide-sdk: add LLDB support for ide=none (clang toolchain) AdrianF
2026-08-04 11:59 ` [PATCH v2 12/14] meta-selftest: refactor cpp examples into .inc files and add clang variants AdrianF
2026-08-04 11:59 ` [PATCH v2 13/14] oe-selftest: devtool ide-sdk: add clang/LLDB test AdrianF
2026-08-07 15:11 ` [OE-core] " Mathieu Dubois-Briand
2026-08-07 15:17 ` Freihofer, Adrian
2026-08-07 15:44 ` Mathieu Dubois-Briand
2026-08-09 9:46 ` adrian.freihofer
2026-08-04 11:59 ` AdrianF [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260804120034.378787-15-adrian.freihofer@siemens.com \
--to=adrian.freihofer@siemens.com \
--cc=openembedded-core@lists.openembedded.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox