From: AdrianF <adrian.freihofer@siemens.com>
To: openembedded-core@lists.openembedded.org
Cc: Adrian Freihofer <adrian.freihofer@siemens.com>
Subject: [PATCH 05/15] oe-selftest: devtool ide-sdk: test NFS debug rootfs
Date: Wed, 9 Sep 2026 23:53:05 +0200 [thread overview]
Message-ID: <20260909215337.89106-6-adrian.freihofer@siemens.com> (raw)
In-Reply-To: <20260909215337.89106-1-adrian.freihofer@siemens.com>
From: Adrian Freihofer <adrian.freihofer@siemens.com>
Exercise --nfs=rootfs-dbg with a real image build and verify the
extracted rootfs, pseudo state, runqemu helper, image bbappend and the
generated VS Code debug paths. Two further tests boot that rootfs over
NFS with runqemu, once with tap and once with slirp networking, re-run
ide-sdk against the actual target address and drive a full remote GDB
debug session.
Booting from NFS also exposed that the gdbserver pid file written by the
start script can become readable over the next SSH connection only a
moment later, so poll for it instead of reading it once.
Signed-off-by: Adrian Freihofer <adrian.freihofer@siemens.com>
---
meta/lib/oeqa/selftest/cases/devtool.py | 120 ++++++++++++++++++++++++
1 file changed, 120 insertions(+)
diff --git a/meta/lib/oeqa/selftest/cases/devtool.py b/meta/lib/oeqa/selftest/cases/devtool.py
index 8bfdd15552..38eb9b3905 100644
--- a/meta/lib/oeqa/selftest/cases/devtool.py
+++ b/meta/lib/oeqa/selftest/cases/devtool.py
@@ -3627,8 +3627,17 @@ class DevtoolIdeSdkGccTests(DevtoolIdeSdkTests):
r = runCmd(gdbserver_script, output_log=self._cmd_logger)
self.assertEqual(r.status, 0)
+ # The start script waits for gdbserver's port before returning, but on
+ # an NFS-root target (--nfs=rootfs-dbg) the pid file it wrote has been
+ # observed to become readable over the next SSH connection only a
+ # moment later, so poll for it.
pid_file = '/tmp/gdbserver_1234_usr-bin-%s_multi/gdbserver.pid' % example_exe
status, output = qemu.run('cat %s' % pid_file)
+ for _ in range(10):
+ if status == 0:
+ break
+ time.sleep(1)
+ status, output = qemu.run('cat %s' % pid_file)
self.assertEqual(status, 0)
gdbserver_pid = output.strip()
self.assertRegex(gdbserver_pid, r'^\d+$')
@@ -4068,6 +4077,117 @@ class DevtoolIdeSdkGccTests(DevtoolIdeSdkTests):
self.assertEqual(r.status, 0)
debug_check_func(r.output, DevtoolIdeSdkTests.MAGIC_STRING_ORIG)
+ def test_devtool_ide_sdk_code_nfs_debug_rootfs(self):
+ """Verify ide-sdk extracts an NFS debug rootfs for VS Code debugging."""
+ recipe_name = "cmake-example"
+ build_file = "CMakeLists.txt"
+ testimage = "oe-selftest-image"
+
+ self._check_workspace()
+ self._write_bb_config()
+ tempdir = self._devtool_ide_sdk_recipe(
+ recipe_name, build_file, testimage)
+ runCmd('devtool ide-sdk %s %s -c --ide=code --nfs=rootfs-dbg' %
+ (recipe_name, testimage), output_log=self._cmd_logger)
+
+ nfs_rootfs = os.path.join(
+ self.workspacedir, 'nfs-exports', testimage, 'rootfs-dbg')
+ self.assertExists(nfs_rootfs)
+ self.assertExists(nfs_rootfs + '.pseudo_state')
+ self.assertExists(os.path.join(nfs_rootfs, 'usr', 'bin', recipe_name))
+ runqemu_helper = os.path.join(
+ self.workspacedir, 'nfs-exports', testimage,
+ 'runqemu-rootfs-dbg')
+ self.assertExists(runqemu_helper)
+ self.assertTrue(os.access(runqemu_helper, os.X_OK))
+ with open(runqemu_helper) as helper_file:
+ helper = helper_file.read()
+ self.assertIn('exec runqemu ', helper)
+ self.assertIn(nfs_rootfs, helper)
+
+ bbappend = os.path.join(
+ self.workspacedir, 'appends', testimage + '.bbappend')
+ with open(bbappend) as append_file:
+ self.assertRegex(
+ append_file.read(),
+ r'IMAGE_FSTYPES_DEBUGFS(?::append)? = " ?tar"')
+
+ with open(os.path.join(tempdir, '.vscode', 'launch.json')) as launch_file:
+ launch_configurations = json.load(launch_file)['configurations']
+ for configuration in launch_configurations:
+ self.assertIn(
+ nfs_rootfs, configuration['additionalSOLibSearchPath'])
+ self.assertEqual(
+ os.path.join(nfs_rootfs, 'usr', 'src', 'debug'),
+ configuration['sourceFileMap']['/usr/src/debug'])
+
+ def _test_devtool_ide_sdk_nfs_debug_rootfs_qemu(self, slirp=False):
+ """Boot the extracted NFS debug rootfs and exercise remote GDB."""
+ recipe_name = "cmake-example"
+ build_file = "CMakeLists.txt"
+ testimage = "oe-selftest-image"
+
+ self._check_workspace()
+ self._write_bb_config()
+ if not slirp:
+ self._check_runqemu_prerequisites()
+
+ tempdir = self._devtool_ide_sdk_recipe(
+ recipe_name, build_file, testimage)
+ runCmd('devtool ide-sdk %s %s -c --ide=none --nfs=rootfs-dbg' %
+ (recipe_name, testimage),
+ output_log=self._cmd_logger)
+
+ nfs_rootfs = os.path.join(
+ self.workspacedir, 'nfs-exports', testimage, 'rootfs-dbg')
+ runqemu_helper = os.path.join(
+ self.workspacedir, 'nfs-exports', testimage,
+ 'runqemu-rootfs-dbg')
+ self.assertExists(nfs_rootfs)
+ self.assertExists(runqemu_helper)
+
+ launch_cmd = '%s nographic' % shlex.quote(runqemu_helper)
+ runqemuparams = ''
+ if slirp:
+ launch_cmd += ' slirp'
+ # QemuTarget uses this only to select its localhost SSH endpoint;
+ # launch_cmd supplies the actual runqemu option.
+ runqemuparams = 'slirp'
+
+ with runqemu(testimage, runqemuparams=runqemuparams,
+ launch_cmd=launch_cmd) as qemu:
+ status, output = qemu.run(
+ "awk '$2 == \"/\" {print $3}' /proc/mounts")
+ self.assertEqual(status, 0)
+ self.assertEqual(output.strip(), 'nfs')
+
+ # Re-run with the real QEMU target address, instead of 192.168.7.2 IP.
+ # --skip-bitbake also skips the rootfs extraction, which would
+ # otherwise wipe the directory the target has mounted right now.
+ if slirp:
+ self.assertIsNotNone(qemu.port, 'No SSH port for the slirp target')
+ target_options = '-t root@%s -P %s ' % (qemu.ip, qemu.port)
+ else:
+ target_options = '-t root@%s -c ' % qemu.ip
+ runCmd('devtool ide-sdk %s %s %s--skip-bitbake --ide=none --nfs=rootfs-dbg' %
+ (recipe_name, testimage, target_options),
+ output_log=self._cmd_logger)
+
+ self._gdb_cross()
+ compile_cmd = self._verify_cmake_preset(tempdir)
+ self._devtool_ide_sdk_qemu(
+ tempdir, qemu, recipe_name, recipe_name, compile_cmd)
+
+ @OETestTag("runqemu")
+ def test_devtool_ide_sdk_none_nfs_qemu(self):
+ """Verify remote GDB debugging through an NFS-root QEMU target."""
+ self._test_devtool_ide_sdk_nfs_debug_rootfs_qemu()
+
+ @OETestTag("runqemu")
+ def test_devtool_ide_sdk_none_nfs_qemu_slirp(self):
+ """Verify remote GDB debugging through an NFS-root slirp target."""
+ self._test_devtool_ide_sdk_nfs_debug_rootfs_qemu(slirp=True)
+
@OETestTag("runqemu")
def test_devtool_ide_sdk_code_cmake(self):
"""Verify a cmake recipe works with ide=code mode"""
--
2.55.0
next prev parent reply other threads:[~2026-09-09 21:53 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-09 21:53 [PATCH 00/15] devtool ide-sdk: support booting from NFS, VSCode clangd AdrianF
2026-09-09 21:53 ` [PATCH 01/15] devtool: deploy: split ssh deployment into a separate function AdrianF
2026-09-09 21:53 ` [PATCH 02/15] devtool: deploy: allow deploying directly into a local rootfs directory AdrianF
2026-09-09 21:53 ` [PATCH 03/15] oe-selftest: devtool deploy-target: test deploying into a local rootfs path AdrianF
2026-09-09 21:53 ` [PATCH 04/15] devtool: ide-sdk: support NFS rootfs AdrianF
2026-09-09 21:53 ` AdrianF [this message]
2026-09-09 21:53 ` [PATCH 06/15] runqemu-extract-sdk: refactor in Python AdrianF
2026-09-10 17:45 ` [OE-core] " Richard Purdie
2026-09-09 21:53 ` [PATCH 07/15] devtool: ide-sdk: reuse pseudo_rootfs_utils for SDK rootfs extraction AdrianF
2026-09-09 21:53 ` [PATCH 08/15] cpp-example: update formatting and code style AdrianF
2026-09-09 21:53 ` [PATCH 09/15] cpp-example: fix clang-tidy warnings AdrianF
2026-09-09 21:53 ` [PATCH 10/15] devtool: ide-sdk: add clangd support for VSCode IntelliSense AdrianF
2026-09-09 21:53 ` [PATCH 11/15] devtool: ide-sdk: support clangd for non-clang toolchain recipes AdrianF
2026-09-09 21:53 ` [PATCH 12/15] devtool: ide-sdk: format C/C++ with clangd when .clang-format is present AdrianF
2026-09-09 21:53 ` [PATCH 13/15] devtool: ide-sdk: support LLDB ATTACH mode AdrianF
2026-09-09 21:53 ` [PATCH 14/15] devtool: ide-sdk: pin BBPATH in generated do_install script AdrianF
2026-09-09 21:53 ` [PATCH 15/15] buildstats: close proc/disk log files via weakref.finalize safety net AdrianF
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=20260909215337.89106-6-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