diff mbox series

[07/15] devtool: ide-sdk: reuse pseudo_rootfs_utils for SDK rootfs extraction

Message ID 20260909215337.89106-8-adrian.freihofer@siemens.com
State New
Headers show
Series devtool ide-sdk: support booting from NFS, VSCode clangd | expand

Commit Message

AdrianF Sept. 9, 2026, 9:53 p.m. UTC
From: Adrian Freihofer <adrian.freihofer@siemens.com>

RecipeImage duplicated the tar/pseudo extraction logic now available in
scripts/lib/pseudo_rootfs_utils.py (shared with runqemu-extract-sdk).
Drop the local copy in favor of the shared extract_sdk_rootfs()/
pseudo_state_dir().

extract_sdk_rootfs() now takes the pseudo invocation and environment as
parameters instead of resolving them itself via qemu-helper-native:
devtool ide-sdk keeps using the image recipe's own FAKEROOTCMD/FAKEROOTENV,
which is already guaranteed to be built as part of the image, rather than
gaining a new, otherwise unused build dependency on qemu-helper-native.
runqemu-extract-sdk resolves pseudo via pseudo_native_environment() itself
and passes it in, as it has no recipe of its own to take FAKEROOTCMD from.

Signed-off-by: Adrian Freihofer <adrian.freihofer@siemens.com>
---
 scripts/lib/devtool/ide_sdk.py | 78 +++++++---------------------------
 1 file changed, 16 insertions(+), 62 deletions(-)
diff mbox series

Patch

diff --git a/scripts/lib/devtool/ide_sdk.py b/scripts/lib/devtool/ide_sdk.py
index 2e37f20894..ba9d4adff1 100755
--- a/scripts/lib/devtool/ide_sdk.py
+++ b/scripts/lib/devtool/ide_sdk.py
@@ -27,6 +27,7 @@  from devtool.standard import get_real_srctree
 from devtool.deploy import parse_packages_arg
 from devtool.ide_plugins import BuildTool, DebuggerCrossConfig
 from oe.kernel_module import kernel_module_os_env
+from pseudo_rootfs_utils import PseudoRootfsError, extract_sdk_rootfs, pseudo_state_dir
 
 
 logger = logging.getLogger('devtool')
@@ -441,66 +442,6 @@  class RecipeImage:
         slirp_changed = self.update_qb_slirp_opt()
         return image_changed or slirp_changed
 
-    @staticmethod
-    def _tar_options(rootfs_tarball):
-        tar_extract_options = {
-            '.tar.xz': '-xJf',
-            '.tar.bz2': '-xjf',
-            '.tar.gz': '-xzf',
-            '.tar.zst': '--zstd -xf',
-            '.tar': '-xf',
-        }
-        for extension, option in tar_extract_options.items():
-            if rootfs_tarball.endswith(extension):
-                return ['--numeric-owner', *option.split()]
-        raise DevtoolError(
-            'Unable to determine sdk tarball format\n'
-            'Accepted types: .tar / .tar.gz / .tar.bz2 / .tar.xz / .tar.zst')
-
-    @staticmethod
-    def pseudo_state_dir(rootfs_dir):
-        """Return the pseudo database location associated with an extracted rootfs."""
-        return os.path.realpath(rootfs_dir) + '.pseudo_state'
-
-    def extract_sdk_rootfs(self, rootfs_tarball, rootfs_dir):
-        """Extract a rootfs tarball under pseudo and return its absolute directory."""
-        if not os.path.exists(rootfs_tarball):
-            raise DevtoolError("sdk tarball '%s' does not exist" % rootfs_tarball)
-        if not os.path.exists(self.fakerootcmd):
-            raise DevtoolError('%s does not exist' % self.fakerootcmd)
-
-        rootfs_tarball = os.path.realpath(rootfs_tarball)
-        rootfs_dir = os.path.realpath(rootfs_dir)
-        tar_options = self._tar_options(rootfs_tarball)
-        state_dir = self.pseudo_state_dir(rootfs_dir)
-
-        os.makedirs(rootfs_dir, exist_ok=True)
-        os.makedirs(state_dir, exist_ok=True)
-        Path(state_dir, 'pseudo.pid').touch()
-
-        environment = dict(os.environ)
-        for varvalue in (self.fakerootenv or '').split():
-            if '=' in varvalue:
-                key, value = varvalue.split('=', 1)
-                environment[key] = value
-        command = [self.fakerootcmd, 'tar', '-C', rootfs_dir]
-
-        environment['PSEUDO_LOCALSTATEDIR'] = state_dir
-        environment['PSEUDO_INCLUDE_PATHS'] = rootfs_dir
-        command.extend(tar_options)
-        command.append(rootfs_tarball)
-        logger.info('Extracting rootfs tarball using pseudo: %s', ' '.join(command))
-        try:
-            subprocess.run(command, env=environment, check=True)
-        except subprocess.CalledProcessError as exc:
-            raise DevtoolError('Failed to extract %s' % rootfs_tarball) from exc
-
-        if len(os.listdir(rootfs_dir)) < 4:
-            logger.warning(
-                "Only few files in %s, please double-check the extraction "
-                "worked as intended", rootfs_dir)
-        return rootfs_dir
-
     def extract_nfs_rootfs(self, nfs_export_base_dir, nfs, target):
         """Refresh the selected rootfs below nfs_export_base_dir."""
         if not self.image_link_name:
@@ -511,7 +452,7 @@  class RecipeImage:
         rootfs_tarball = os.path.join(
             self.deploy_dir_image, self.image_link_name + suffix + '.tar')
         rootfs_dir = self.nfs_rootfs_dir(nfs_export_base_dir, nfs)
-        state_dir = self.pseudo_state_dir(rootfs_dir)
+        state_dir = pseudo_state_dir(rootfs_dir)
 
         if os.path.exists(rootfs_dir):
             logger.warning(
@@ -521,7 +462,20 @@  class RecipeImage:
             if os.path.exists(stale_dir):
                 shutil.rmtree(stale_dir)
 
-        self.extract_sdk_rootfs(rootfs_tarball, rootfs_dir)
+        if not os.path.exists(self.fakerootcmd):
+            raise DevtoolError('%s does not exist' % self.fakerootcmd)
+        # Reuse the image's own pseudo instead of qemu-helper-native's, so
+        # extraction does not depend on a recipe devtool ide-sdk never builds.
+        pseudo_cmd = [self.fakerootcmd]
+        environment = dict(os.environ)
+        for varvalue in (self.fakerootenv or '').split():
+            if '=' in varvalue:
+                key, value = varvalue.split('=', 1)
+                environment[key] = value
+        try:
+            extract_sdk_rootfs(rootfs_tarball, rootfs_dir, pseudo_cmd, environment)
+        except PseudoRootfsError as exc:
+            raise DevtoolError('Unable to prepare NFS rootfs: %s' % exc) from exc
 
         logger.info('NFS rootfs extracted to %s', rootfs_dir)
         helper = self.nfs_runqemu_helper(nfs_export_base_dir, nfs)