blob: 0b9911e3a6315669dc4204be4b175fe1eb497073 [file] [log] [blame]
Brad Bishopc342db32019-05-15 21:57:59 -04001#
Patrick Williams92b42cb2022-09-03 06:53:57 -05002# Copyright OpenEmbedded Contributors
3#
Brad Bishopc342db32019-05-15 21:57:59 -04004# SPDX-License-Identifier: GPL-2.0-only
5#
Patrick Williamsc124f4f2015-09-15 14:41:29 -05006from abc import ABCMeta, abstractmethod
7from oe.utils import execute_pre_post_process
8from oe.package_manager import *
9from oe.manifest import *
10import oe.path
Patrick Williamsc124f4f2015-09-15 14:41:29 -050011import shutil
12import os
13import subprocess
14import re
Patrick Williamsc124f4f2015-09-15 14:41:29 -050015
Patrick Williamsc0f7c042017-02-23 20:41:17 -060016class Rootfs(object, metaclass=ABCMeta):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050017 """
18 This is an abstract class. Do not instantiate this directly.
19 """
Patrick Williamsc124f4f2015-09-15 14:41:29 -050020
Brad Bishop6e60e8b2018-02-01 10:27:11 -050021 def __init__(self, d, progress_reporter=None, logcatcher=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -050022 self.d = d
23 self.pm = None
Brad Bishop6e60e8b2018-02-01 10:27:11 -050024 self.image_rootfs = self.d.getVar('IMAGE_ROOTFS')
25 self.deploydir = self.d.getVar('IMGDEPLOYDIR')
Patrick Williamsc0f7c042017-02-23 20:41:17 -060026 self.progress_reporter = progress_reporter
Brad Bishop6e60e8b2018-02-01 10:27:11 -050027 self.logcatcher = logcatcher
Patrick Williamsc124f4f2015-09-15 14:41:29 -050028
29 self.install_order = Manifest.INSTALL_ORDER
30
31 @abstractmethod
32 def _create(self):
33 pass
34
35 @abstractmethod
36 def _get_delayed_postinsts(self):
37 pass
38
39 @abstractmethod
40 def _save_postinsts(self):
41 pass
42
43 @abstractmethod
44 def _log_check(self):
45 pass
46
Patrick Williamsc0f7c042017-02-23 20:41:17 -060047 def _log_check_common(self, type, match):
48 # Ignore any lines containing log_check to avoid recursion, and ignore
49 # lines beginning with a + since sh -x may emit code which isn't
50 # actually executed, but may contain error messages
51 excludes = [ 'log_check', r'^\+' ]
52 if hasattr(self, 'log_check_expected_regexes'):
53 excludes.extend(self.log_check_expected_regexes)
Andrew Geissler4c19ea12020-10-27 13:52:24 -050054 # Insert custom log_check excludes
55 excludes += [x for x in (self.d.getVar("IMAGE_LOG_CHECK_EXCLUDES") or "").split(" ") if x]
Patrick Williamsc0f7c042017-02-23 20:41:17 -060056 excludes = [re.compile(x) for x in excludes]
57 r = re.compile(match)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050058 log_path = self.d.expand("${T}/log.do_rootfs")
Patrick Williamsc0f7c042017-02-23 20:41:17 -060059 messages = []
Patrick Williamsc124f4f2015-09-15 14:41:29 -050060 with open(log_path, 'r') as log:
61 for line in log:
Brad Bishop6e60e8b2018-02-01 10:27:11 -050062 if self.logcatcher and self.logcatcher.contains(line.rstrip()):
63 continue
Patrick Williamsc0f7c042017-02-23 20:41:17 -060064 for ee in excludes:
65 m = ee.search(line)
66 if m:
67 break
68 if m:
Patrick Williamsc124f4f2015-09-15 14:41:29 -050069 continue
70
71 m = r.search(line)
72 if m:
Patrick Williamsc0f7c042017-02-23 20:41:17 -060073 messages.append('[log_check] %s' % line)
74 if messages:
75 if len(messages) == 1:
76 msg = '1 %s message' % type
77 else:
78 msg = '%d %s messages' % (len(messages), type)
79 msg = '[log_check] %s: found %s in the logfile:\n%s' % \
Brad Bishop6e60e8b2018-02-01 10:27:11 -050080 (self.d.getVar('PN'), msg, ''.join(messages))
Patrick Williamsc0f7c042017-02-23 20:41:17 -060081 if type == 'error':
82 bb.fatal(msg)
83 else:
84 bb.warn(msg)
85
86 def _log_check_warn(self):
87 self._log_check_common('warning', '^(warn|Warn|WARNING:)')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050088
89 def _log_check_error(self):
Patrick Williamsc0f7c042017-02-23 20:41:17 -060090 self._log_check_common('error', self.log_check_regex)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050091
92 def _insert_feed_uris(self):
93 if bb.utils.contains("IMAGE_FEATURES", "package-management",
94 True, False, self.d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -050095 self.pm.insert_feeds_uris(self.d.getVar('PACKAGE_FEED_URIS') or "",
96 self.d.getVar('PACKAGE_FEED_BASE_PATHS') or "",
97 self.d.getVar('PACKAGE_FEED_ARCHS'))
98
Patrick Williamsc124f4f2015-09-15 14:41:29 -050099
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500100 """
101 The _cleanup() method should be used to clean-up stuff that we don't really
102 want to end up on target. For example, in the case of RPM, the DB locks.
103 The method is called, once, at the end of create() method.
104 """
105 @abstractmethod
106 def _cleanup(self):
107 pass
108
109 def _setup_dbg_rootfs(self, dirs):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500110 gen_debugfs = self.d.getVar('IMAGE_GEN_DEBUGFS') or '0'
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500111 if gen_debugfs != '1':
112 return
113
114 bb.note(" Renaming the original rootfs...")
115 try:
116 shutil.rmtree(self.image_rootfs + '-orig')
117 except:
118 pass
Andrew Geisslerc926e172021-05-07 16:11:35 -0500119 bb.utils.rename(self.image_rootfs, self.image_rootfs + '-orig')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500120
121 bb.note(" Creating debug rootfs...")
122 bb.utils.mkdirhier(self.image_rootfs)
123
124 bb.note(" Copying back package database...")
125 for dir in dirs:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600126 if not os.path.isdir(self.image_rootfs + '-orig' + dir):
127 continue
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500128 bb.utils.mkdirhier(self.image_rootfs + os.path.dirname(dir))
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600129 shutil.copytree(self.image_rootfs + '-orig' + dir, self.image_rootfs + dir, symlinks=True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500130
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500131 # Copy files located in /usr/lib/debug or /usr/src/debug
132 for dir in ["/usr/lib/debug", "/usr/src/debug"]:
133 src = self.image_rootfs + '-orig' + dir
Andrew Geissler82c905d2020-04-13 13:39:40 -0500134 if os.path.exists(src):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500135 dst = self.image_rootfs + dir
136 bb.utils.mkdirhier(os.path.dirname(dst))
137 shutil.copytree(src, dst)
138
139 # Copy files with suffix '.debug' or located in '.debug' dir.
Andrew Geissler82c905d2020-04-13 13:39:40 -0500140 for root, dirs, files in os.walk(self.image_rootfs + '-orig'):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500141 relative_dir = root[len(self.image_rootfs + '-orig'):]
142 for f in files:
143 if f.endswith('.debug') or '/.debug' in relative_dir:
144 bb.utils.mkdirhier(self.image_rootfs + relative_dir)
145 shutil.copy(os.path.join(root, f),
146 self.image_rootfs + relative_dir)
147
148 bb.note(" Install complementary '*-dbg' packages...")
149 self.pm.install_complementary('*-dbg')
150
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800151 if self.d.getVar('PACKAGE_DEBUG_SPLIT_STYLE') == 'debug-with-srcpkg':
152 bb.note(" Install complementary '*-src' packages...")
153 self.pm.install_complementary('*-src')
154
155 """
156 Install additional debug packages. Possibility to install additional packages,
157 which are not automatically installed as complementary package of
158 standard one, e.g. debug package of static libraries.
159 """
160 extra_debug_pkgs = self.d.getVar('IMAGE_INSTALL_DEBUGFS')
161 if extra_debug_pkgs:
162 bb.note(" Install extra debug packages...")
163 self.pm.install(extra_debug_pkgs.split(), True)
164
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500165 bb.note(" Rename debug rootfs...")
166 try:
167 shutil.rmtree(self.image_rootfs + '-dbg')
168 except:
169 pass
Andrew Geisslerc926e172021-05-07 16:11:35 -0500170 bb.utils.rename(self.image_rootfs, self.image_rootfs + '-dbg')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500171
William A. Kennington IIIac69b482021-06-02 12:28:27 -0700172 bb.note(" Restoring original rootfs...")
Andrew Geisslerc926e172021-05-07 16:11:35 -0500173 bb.utils.rename(self.image_rootfs + '-orig', self.image_rootfs)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500174
175 def _exec_shell_cmd(self, cmd):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500176 fakerootcmd = self.d.getVar('FAKEROOT')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500177 if fakerootcmd is not None:
178 exec_cmd = [fakerootcmd, cmd]
179 else:
180 exec_cmd = cmd
181
182 try:
183 subprocess.check_output(exec_cmd, stderr=subprocess.STDOUT)
184 except subprocess.CalledProcessError as e:
185 return("Command '%s' returned %d:\n%s" % (e.cmd, e.returncode, e.output))
186
187 return None
188
189 def create(self):
190 bb.note("###### Generate rootfs #######")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500191 pre_process_cmds = self.d.getVar("ROOTFS_PREPROCESS_COMMAND")
192 post_process_cmds = self.d.getVar("ROOTFS_POSTPROCESS_COMMAND")
193 rootfs_post_install_cmds = self.d.getVar('ROOTFS_POSTINSTALL_COMMAND')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500194
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500195 execute_pre_post_process(self.d, pre_process_cmds)
196
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600197 if self.progress_reporter:
198 self.progress_reporter.next_stage()
199
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500200 # call the package manager dependent create method
201 self._create()
202
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500203 sysconfdir = self.image_rootfs + self.d.getVar('sysconfdir')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500204 bb.utils.mkdirhier(sysconfdir)
205 with open(sysconfdir + "/version", "w+") as ver:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500206 ver.write(self.d.getVar('BUILDNAME') + "\n")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500207
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500208 execute_pre_post_process(self.d, rootfs_post_install_cmds)
209
Brad Bishop316dfdd2018-06-25 12:45:53 -0400210 self.pm.run_intercepts()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500211
212 execute_pre_post_process(self.d, post_process_cmds)
213
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600214 if self.progress_reporter:
215 self.progress_reporter.next_stage()
216
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500217 if bb.utils.contains("IMAGE_FEATURES", "read-only-rootfs",
Andrew Geisslerd1e89492021-02-12 15:35:20 -0600218 True, False, self.d) and \
219 not bb.utils.contains("IMAGE_FEATURES",
220 "read-only-rootfs-delayed-postinsts",
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500221 True, False, self.d):
222 delayed_postinsts = self._get_delayed_postinsts()
223 if delayed_postinsts is not None:
224 bb.fatal("The following packages could not be configured "
225 "offline and rootfs is read-only: %s" %
226 delayed_postinsts)
227
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500228 if self.d.getVar('USE_DEVFS') != "1":
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500229 self._create_devfs()
230
231 self._uninstall_unneeded()
232
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600233 if self.progress_reporter:
234 self.progress_reporter.next_stage()
235
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500236 self._insert_feed_uris()
237
238 self._run_ldconfig()
239
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500240 if self.d.getVar('USE_DEPMOD') != "0":
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500241 self._generate_kernel_module_deps()
242
243 self._cleanup()
244 self._log_check()
245
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600246 if self.progress_reporter:
247 self.progress_reporter.next_stage()
248
249
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500250 def _uninstall_unneeded(self):
Andrew Geissler95ac1b82021-03-31 14:34:31 -0500251 # Remove the run-postinsts package if no delayed postinsts are found
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500252 delayed_postinsts = self._get_delayed_postinsts()
253 if delayed_postinsts is None:
Andrew Geissler5199d832021-09-24 16:47:35 -0500254 if os.path.exists(self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/init.d/run-postinsts")) or os.path.exists(self.d.expand("${IMAGE_ROOTFS}${systemd_system_unitdir}/run-postinsts.service")):
Andrew Geissler95ac1b82021-03-31 14:34:31 -0500255 self.pm.remove(["run-postinsts"])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500256
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500257 image_rorfs = bb.utils.contains("IMAGE_FEATURES", "read-only-rootfs",
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500258 True, False, self.d)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500259 image_rorfs_force = self.d.getVar('FORCE_RO_REMOVE')
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600260
261 if image_rorfs or image_rorfs_force == "1":
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500262 # Remove components that we don't need if it's a read-only rootfs
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500263 unneeded_pkgs = self.d.getVar("ROOTFS_RO_UNNEEDED").split()
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500264 pkgs_installed = image_list_installed_packages(self.d)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500265 # Make sure update-alternatives is removed last. This is
266 # because its database has to available while uninstalling
267 # other packages, allowing alternative symlinks of packages
268 # to be uninstalled or to be managed correctly otherwise.
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500269 provider = self.d.getVar("VIRTUAL-RUNTIME_update-alternatives")
270 pkgs_to_remove = sorted([pkg for pkg in pkgs_installed if pkg in unneeded_pkgs], key=lambda x: x == provider)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500271
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500272 # update-alternatives provider is removed in its own remove()
273 # call because all package managers do not guarantee the packages
274 # are removed in the order they given in the list (which is
275 # passed to the command line). The sorting done earlier is
276 # utilized to implement the 2-stage removal.
277 if len(pkgs_to_remove) > 1:
278 self.pm.remove(pkgs_to_remove[:-1], False)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500279 if len(pkgs_to_remove) > 0:
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500280 self.pm.remove([pkgs_to_remove[-1]], False)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500281
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500282 if delayed_postinsts:
283 self._save_postinsts()
284 if image_rorfs:
285 bb.warn("There are post install scripts "
286 "in a read-only rootfs")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500287
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500288 post_uninstall_cmds = self.d.getVar("ROOTFS_POSTUNINSTALL_COMMAND")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500289 execute_pre_post_process(self.d, post_uninstall_cmds)
290
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500291 runtime_pkgmanage = bb.utils.contains("IMAGE_FEATURES", "package-management",
292 True, False, self.d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500293 if not runtime_pkgmanage:
294 # Remove the package manager data files
295 self.pm.remove_packaging_data()
296
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500297 def _run_ldconfig(self):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500298 if self.d.getVar('LDCONFIGDEPEND'):
Andrew Geissler475cb722020-07-10 16:00:51 -0500299 bb.note("Executing: ldconfig -r " + self.image_rootfs + " -c new -v -X")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500300 self._exec_shell_cmd(['ldconfig', '-r', self.image_rootfs, '-c',
Andrew Geissler475cb722020-07-10 16:00:51 -0500301 'new', '-v', '-X'])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500302
Patrick Williams213cb262021-08-07 19:21:33 -0500303 image_rorfs = bb.utils.contains("IMAGE_FEATURES", "read-only-rootfs",
304 True, False, self.d)
305 ldconfig_in_features = bb.utils.contains("DISTRO_FEATURES", "ldconfig",
306 True, False, self.d)
307 if image_rorfs or not ldconfig_in_features:
308 ldconfig_cache_dir = os.path.join(self.image_rootfs, "var/cache/ldconfig")
309 if os.path.exists(ldconfig_cache_dir):
310 bb.note("Removing ldconfig auxiliary cache...")
311 shutil.rmtree(ldconfig_cache_dir)
312
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500313 def _check_for_kernel_modules(self, modules_dir):
314 for root, dirs, files in os.walk(modules_dir, topdown=True):
315 for name in files:
Andrew Geissler78b72792022-06-14 06:47:25 -0500316 found_ko = name.endswith((".ko", ".ko.gz", ".ko.xz", ".ko.zst"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500317 if found_ko:
318 return found_ko
319 return False
320
321 def _generate_kernel_module_deps(self):
322 modules_dir = os.path.join(self.image_rootfs, 'lib', 'modules')
323 # if we don't have any modules don't bother to do the depmod
324 if not self._check_for_kernel_modules(modules_dir):
325 bb.note("No Kernel Modules found, not running depmod")
326 return
327
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500328 kernel_abi_ver_file = oe.path.join(self.d.getVar('PKGDATA_DIR'), "kernel-depmod",
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500329 'kernel-abiversion')
330 if not os.path.exists(kernel_abi_ver_file):
331 bb.fatal("No kernel-abiversion file found (%s), cannot run depmod, aborting" % kernel_abi_ver_file)
332
Andrew Geissler78b72792022-06-14 06:47:25 -0500333 with open(kernel_abi_ver_file) as f:
334 kernel_ver = f.read().strip(' \n')
335
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500336 versioned_modules_dir = os.path.join(self.image_rootfs, modules_dir, kernel_ver)
337
338 bb.utils.mkdirhier(versioned_modules_dir)
339
340 self._exec_shell_cmd(['depmodwrapper', '-a', '-b', self.image_rootfs, kernel_ver])
341
342 """
343 Create devfs:
344 * IMAGE_DEVICE_TABLE is the old name to an absolute path to a device table file
345 * IMAGE_DEVICE_TABLES is a new name for a file, or list of files, seached
346 for in the BBPATH
347 If neither are specified then the default name of files/device_table-minimal.txt
348 is searched for in the BBPATH (same as the old version.)
349 """
350 def _create_devfs(self):
351 devtable_list = []
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500352 devtable = self.d.getVar('IMAGE_DEVICE_TABLE')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500353 if devtable is not None:
354 devtable_list.append(devtable)
355 else:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500356 devtables = self.d.getVar('IMAGE_DEVICE_TABLES')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500357 if devtables is None:
358 devtables = 'files/device_table-minimal.txt'
359 for devtable in devtables.split():
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500360 devtable_list.append("%s" % bb.utils.which(self.d.getVar('BBPATH'), devtable))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500361
362 for devtable in devtable_list:
363 self._exec_shell_cmd(["makedevs", "-r",
364 self.image_rootfs, "-D", devtable])
365
366
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500367def get_class_for_type(imgtype):
Andrew Geissler6ce62a22020-11-30 19:58:47 -0600368 import importlib
369 mod = importlib.import_module('oe.package_manager.' + imgtype + '.rootfs')
370 return mod.PkgRootfs
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500371
372def variable_depends(d, manifest_dir=None):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500373 img_type = d.getVar('IMAGE_PKGTYPE')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500374 cls = get_class_for_type(img_type)
375 return cls._depends_list()
376
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500377def create_rootfs(d, manifest_dir=None, progress_reporter=None, logcatcher=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500378 env_bkp = os.environ.copy()
379
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500380 img_type = d.getVar('IMAGE_PKGTYPE')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500381
Andrew Geissler6ce62a22020-11-30 19:58:47 -0600382 cls = get_class_for_type(img_type)
383 cls(d, manifest_dir, progress_reporter, logcatcher).create()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500384 os.environ.clear()
385 os.environ.update(env_bkp)
386
387
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500388def image_list_installed_packages(d, rootfs_dir=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500389 if not rootfs_dir:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500390 rootfs_dir = d.getVar('IMAGE_ROOTFS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500391
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500392 img_type = d.getVar('IMAGE_PKGTYPE')
Andrew Geissler6ce62a22020-11-30 19:58:47 -0600393
394 import importlib
395 cls = importlib.import_module('oe.package_manager.' + img_type)
396 return cls.PMPkgsList(d, rootfs_dir).list_pkgs()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500397
398if __name__ == "__main__":
399 """
400 We should be able to run this as a standalone script, from outside bitbake
401 environment.
402 """
403 """
404 TBD
405 """