1*4882a593Smuzhiyun# 2*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0-only 3*4882a593Smuzhiyun# 4*4882a593Smuzhiyunfrom abc import ABCMeta, abstractmethod 5*4882a593Smuzhiyunfrom oe.utils import execute_pre_post_process 6*4882a593Smuzhiyunfrom oe.package_manager import * 7*4882a593Smuzhiyunfrom oe.manifest import * 8*4882a593Smuzhiyunimport oe.path 9*4882a593Smuzhiyunimport shutil 10*4882a593Smuzhiyunimport os 11*4882a593Smuzhiyunimport subprocess 12*4882a593Smuzhiyunimport re 13*4882a593Smuzhiyun 14*4882a593Smuzhiyunclass Rootfs(object, metaclass=ABCMeta): 15*4882a593Smuzhiyun """ 16*4882a593Smuzhiyun This is an abstract class. Do not instantiate this directly. 17*4882a593Smuzhiyun """ 18*4882a593Smuzhiyun 19*4882a593Smuzhiyun def __init__(self, d, progress_reporter=None, logcatcher=None): 20*4882a593Smuzhiyun self.d = d 21*4882a593Smuzhiyun self.pm = None 22*4882a593Smuzhiyun self.image_rootfs = self.d.getVar('IMAGE_ROOTFS') 23*4882a593Smuzhiyun self.deploydir = self.d.getVar('IMGDEPLOYDIR') 24*4882a593Smuzhiyun self.progress_reporter = progress_reporter 25*4882a593Smuzhiyun self.logcatcher = logcatcher 26*4882a593Smuzhiyun 27*4882a593Smuzhiyun self.install_order = Manifest.INSTALL_ORDER 28*4882a593Smuzhiyun 29*4882a593Smuzhiyun @abstractmethod 30*4882a593Smuzhiyun def _create(self): 31*4882a593Smuzhiyun pass 32*4882a593Smuzhiyun 33*4882a593Smuzhiyun @abstractmethod 34*4882a593Smuzhiyun def _get_delayed_postinsts(self): 35*4882a593Smuzhiyun pass 36*4882a593Smuzhiyun 37*4882a593Smuzhiyun @abstractmethod 38*4882a593Smuzhiyun def _save_postinsts(self): 39*4882a593Smuzhiyun pass 40*4882a593Smuzhiyun 41*4882a593Smuzhiyun @abstractmethod 42*4882a593Smuzhiyun def _log_check(self): 43*4882a593Smuzhiyun pass 44*4882a593Smuzhiyun 45*4882a593Smuzhiyun def _log_check_common(self, type, match): 46*4882a593Smuzhiyun # Ignore any lines containing log_check to avoid recursion, and ignore 47*4882a593Smuzhiyun # lines beginning with a + since sh -x may emit code which isn't 48*4882a593Smuzhiyun # actually executed, but may contain error messages 49*4882a593Smuzhiyun excludes = [ 'log_check', r'^\+' ] 50*4882a593Smuzhiyun if hasattr(self, 'log_check_expected_regexes'): 51*4882a593Smuzhiyun excludes.extend(self.log_check_expected_regexes) 52*4882a593Smuzhiyun # Insert custom log_check excludes 53*4882a593Smuzhiyun excludes += [x for x in (self.d.getVar("IMAGE_LOG_CHECK_EXCLUDES") or "").split(" ") if x] 54*4882a593Smuzhiyun excludes = [re.compile(x) for x in excludes] 55*4882a593Smuzhiyun r = re.compile(match) 56*4882a593Smuzhiyun log_path = self.d.expand("${T}/log.do_rootfs") 57*4882a593Smuzhiyun messages = [] 58*4882a593Smuzhiyun with open(log_path, 'r') as log: 59*4882a593Smuzhiyun for line in log: 60*4882a593Smuzhiyun if self.logcatcher and self.logcatcher.contains(line.rstrip()): 61*4882a593Smuzhiyun continue 62*4882a593Smuzhiyun for ee in excludes: 63*4882a593Smuzhiyun m = ee.search(line) 64*4882a593Smuzhiyun if m: 65*4882a593Smuzhiyun break 66*4882a593Smuzhiyun if m: 67*4882a593Smuzhiyun continue 68*4882a593Smuzhiyun 69*4882a593Smuzhiyun m = r.search(line) 70*4882a593Smuzhiyun if m: 71*4882a593Smuzhiyun messages.append('[log_check] %s' % line) 72*4882a593Smuzhiyun if messages: 73*4882a593Smuzhiyun if len(messages) == 1: 74*4882a593Smuzhiyun msg = '1 %s message' % type 75*4882a593Smuzhiyun else: 76*4882a593Smuzhiyun msg = '%d %s messages' % (len(messages), type) 77*4882a593Smuzhiyun msg = '[log_check] %s: found %s in the logfile:\n%s' % \ 78*4882a593Smuzhiyun (self.d.getVar('PN'), msg, ''.join(messages)) 79*4882a593Smuzhiyun if type == 'error': 80*4882a593Smuzhiyun bb.fatal(msg) 81*4882a593Smuzhiyun else: 82*4882a593Smuzhiyun bb.warn(msg) 83*4882a593Smuzhiyun 84*4882a593Smuzhiyun def _log_check_warn(self): 85*4882a593Smuzhiyun self._log_check_common('warning', '^(warn|Warn|WARNING:)') 86*4882a593Smuzhiyun 87*4882a593Smuzhiyun def _log_check_error(self): 88*4882a593Smuzhiyun self._log_check_common('error', self.log_check_regex) 89*4882a593Smuzhiyun 90*4882a593Smuzhiyun def _insert_feed_uris(self): 91*4882a593Smuzhiyun if bb.utils.contains("IMAGE_FEATURES", "package-management", 92*4882a593Smuzhiyun True, False, self.d): 93*4882a593Smuzhiyun self.pm.insert_feeds_uris(self.d.getVar('PACKAGE_FEED_URIS') or "", 94*4882a593Smuzhiyun self.d.getVar('PACKAGE_FEED_BASE_PATHS') or "", 95*4882a593Smuzhiyun self.d.getVar('PACKAGE_FEED_ARCHS')) 96*4882a593Smuzhiyun 97*4882a593Smuzhiyun 98*4882a593Smuzhiyun """ 99*4882a593Smuzhiyun The _cleanup() method should be used to clean-up stuff that we don't really 100*4882a593Smuzhiyun want to end up on target. For example, in the case of RPM, the DB locks. 101*4882a593Smuzhiyun The method is called, once, at the end of create() method. 102*4882a593Smuzhiyun """ 103*4882a593Smuzhiyun @abstractmethod 104*4882a593Smuzhiyun def _cleanup(self): 105*4882a593Smuzhiyun pass 106*4882a593Smuzhiyun 107*4882a593Smuzhiyun def _setup_dbg_rootfs(self, dirs): 108*4882a593Smuzhiyun gen_debugfs = self.d.getVar('IMAGE_GEN_DEBUGFS') or '0' 109*4882a593Smuzhiyun if gen_debugfs != '1': 110*4882a593Smuzhiyun return 111*4882a593Smuzhiyun 112*4882a593Smuzhiyun bb.note(" Renaming the original rootfs...") 113*4882a593Smuzhiyun try: 114*4882a593Smuzhiyun shutil.rmtree(self.image_rootfs + '-orig') 115*4882a593Smuzhiyun except: 116*4882a593Smuzhiyun pass 117*4882a593Smuzhiyun bb.utils.rename(self.image_rootfs, self.image_rootfs + '-orig') 118*4882a593Smuzhiyun 119*4882a593Smuzhiyun bb.note(" Creating debug rootfs...") 120*4882a593Smuzhiyun bb.utils.mkdirhier(self.image_rootfs) 121*4882a593Smuzhiyun 122*4882a593Smuzhiyun bb.note(" Copying back package database...") 123*4882a593Smuzhiyun for dir in dirs: 124*4882a593Smuzhiyun if not os.path.isdir(self.image_rootfs + '-orig' + dir): 125*4882a593Smuzhiyun continue 126*4882a593Smuzhiyun bb.utils.mkdirhier(self.image_rootfs + os.path.dirname(dir)) 127*4882a593Smuzhiyun shutil.copytree(self.image_rootfs + '-orig' + dir, self.image_rootfs + dir, symlinks=True) 128*4882a593Smuzhiyun 129*4882a593Smuzhiyun # Copy files located in /usr/lib/debug or /usr/src/debug 130*4882a593Smuzhiyun for dir in ["/usr/lib/debug", "/usr/src/debug"]: 131*4882a593Smuzhiyun src = self.image_rootfs + '-orig' + dir 132*4882a593Smuzhiyun if os.path.exists(src): 133*4882a593Smuzhiyun dst = self.image_rootfs + dir 134*4882a593Smuzhiyun bb.utils.mkdirhier(os.path.dirname(dst)) 135*4882a593Smuzhiyun shutil.copytree(src, dst) 136*4882a593Smuzhiyun 137*4882a593Smuzhiyun # Copy files with suffix '.debug' or located in '.debug' dir. 138*4882a593Smuzhiyun for root, dirs, files in os.walk(self.image_rootfs + '-orig'): 139*4882a593Smuzhiyun relative_dir = root[len(self.image_rootfs + '-orig'):] 140*4882a593Smuzhiyun for f in files: 141*4882a593Smuzhiyun if f.endswith('.debug') or '/.debug' in relative_dir: 142*4882a593Smuzhiyun bb.utils.mkdirhier(self.image_rootfs + relative_dir) 143*4882a593Smuzhiyun shutil.copy(os.path.join(root, f), 144*4882a593Smuzhiyun self.image_rootfs + relative_dir) 145*4882a593Smuzhiyun 146*4882a593Smuzhiyun bb.note(" Install complementary '*-dbg' packages...") 147*4882a593Smuzhiyun self.pm.install_complementary('*-dbg') 148*4882a593Smuzhiyun 149*4882a593Smuzhiyun if self.d.getVar('PACKAGE_DEBUG_SPLIT_STYLE') == 'debug-with-srcpkg': 150*4882a593Smuzhiyun bb.note(" Install complementary '*-src' packages...") 151*4882a593Smuzhiyun self.pm.install_complementary('*-src') 152*4882a593Smuzhiyun 153*4882a593Smuzhiyun """ 154*4882a593Smuzhiyun Install additional debug packages. Possibility to install additional packages, 155*4882a593Smuzhiyun which are not automatically installed as complementary package of 156*4882a593Smuzhiyun standard one, e.g. debug package of static libraries. 157*4882a593Smuzhiyun """ 158*4882a593Smuzhiyun extra_debug_pkgs = self.d.getVar('IMAGE_INSTALL_DEBUGFS') 159*4882a593Smuzhiyun if extra_debug_pkgs: 160*4882a593Smuzhiyun bb.note(" Install extra debug packages...") 161*4882a593Smuzhiyun self.pm.install(extra_debug_pkgs.split(), True) 162*4882a593Smuzhiyun 163*4882a593Smuzhiyun bb.note(" Rename debug rootfs...") 164*4882a593Smuzhiyun try: 165*4882a593Smuzhiyun shutil.rmtree(self.image_rootfs + '-dbg') 166*4882a593Smuzhiyun except: 167*4882a593Smuzhiyun pass 168*4882a593Smuzhiyun bb.utils.rename(self.image_rootfs, self.image_rootfs + '-dbg') 169*4882a593Smuzhiyun 170*4882a593Smuzhiyun bb.note(" Restoring original rootfs...") 171*4882a593Smuzhiyun bb.utils.rename(self.image_rootfs + '-orig', self.image_rootfs) 172*4882a593Smuzhiyun 173*4882a593Smuzhiyun def _exec_shell_cmd(self, cmd): 174*4882a593Smuzhiyun fakerootcmd = self.d.getVar('FAKEROOT') 175*4882a593Smuzhiyun if fakerootcmd is not None: 176*4882a593Smuzhiyun exec_cmd = [fakerootcmd, cmd] 177*4882a593Smuzhiyun else: 178*4882a593Smuzhiyun exec_cmd = cmd 179*4882a593Smuzhiyun 180*4882a593Smuzhiyun try: 181*4882a593Smuzhiyun subprocess.check_output(exec_cmd, stderr=subprocess.STDOUT) 182*4882a593Smuzhiyun except subprocess.CalledProcessError as e: 183*4882a593Smuzhiyun return("Command '%s' returned %d:\n%s" % (e.cmd, e.returncode, e.output)) 184*4882a593Smuzhiyun 185*4882a593Smuzhiyun return None 186*4882a593Smuzhiyun 187*4882a593Smuzhiyun def create(self): 188*4882a593Smuzhiyun bb.note("###### Generate rootfs #######") 189*4882a593Smuzhiyun pre_process_cmds = self.d.getVar("ROOTFS_PREPROCESS_COMMAND") 190*4882a593Smuzhiyun post_process_cmds = self.d.getVar("ROOTFS_POSTPROCESS_COMMAND") 191*4882a593Smuzhiyun rootfs_post_install_cmds = self.d.getVar('ROOTFS_POSTINSTALL_COMMAND') 192*4882a593Smuzhiyun 193*4882a593Smuzhiyun execute_pre_post_process(self.d, pre_process_cmds) 194*4882a593Smuzhiyun 195*4882a593Smuzhiyun if self.progress_reporter: 196*4882a593Smuzhiyun self.progress_reporter.next_stage() 197*4882a593Smuzhiyun 198*4882a593Smuzhiyun # call the package manager dependent create method 199*4882a593Smuzhiyun self._create() 200*4882a593Smuzhiyun 201*4882a593Smuzhiyun sysconfdir = self.image_rootfs + self.d.getVar('sysconfdir') 202*4882a593Smuzhiyun bb.utils.mkdirhier(sysconfdir) 203*4882a593Smuzhiyun with open(sysconfdir + "/version", "w+") as ver: 204*4882a593Smuzhiyun ver.write(self.d.getVar('BUILDNAME') + "\n") 205*4882a593Smuzhiyun 206*4882a593Smuzhiyun execute_pre_post_process(self.d, rootfs_post_install_cmds) 207*4882a593Smuzhiyun 208*4882a593Smuzhiyun self.pm.run_intercepts() 209*4882a593Smuzhiyun 210*4882a593Smuzhiyun execute_pre_post_process(self.d, post_process_cmds) 211*4882a593Smuzhiyun 212*4882a593Smuzhiyun if self.progress_reporter: 213*4882a593Smuzhiyun self.progress_reporter.next_stage() 214*4882a593Smuzhiyun 215*4882a593Smuzhiyun if bb.utils.contains("IMAGE_FEATURES", "read-only-rootfs", 216*4882a593Smuzhiyun True, False, self.d) and \ 217*4882a593Smuzhiyun not bb.utils.contains("IMAGE_FEATURES", 218*4882a593Smuzhiyun "read-only-rootfs-delayed-postinsts", 219*4882a593Smuzhiyun True, False, self.d): 220*4882a593Smuzhiyun delayed_postinsts = self._get_delayed_postinsts() 221*4882a593Smuzhiyun if delayed_postinsts is not None: 222*4882a593Smuzhiyun bb.fatal("The following packages could not be configured " 223*4882a593Smuzhiyun "offline and rootfs is read-only: %s" % 224*4882a593Smuzhiyun delayed_postinsts) 225*4882a593Smuzhiyun 226*4882a593Smuzhiyun if self.d.getVar('USE_DEVFS') != "1": 227*4882a593Smuzhiyun self._create_devfs() 228*4882a593Smuzhiyun 229*4882a593Smuzhiyun self._uninstall_unneeded() 230*4882a593Smuzhiyun 231*4882a593Smuzhiyun if self.progress_reporter: 232*4882a593Smuzhiyun self.progress_reporter.next_stage() 233*4882a593Smuzhiyun 234*4882a593Smuzhiyun self._insert_feed_uris() 235*4882a593Smuzhiyun 236*4882a593Smuzhiyun self._run_ldconfig() 237*4882a593Smuzhiyun 238*4882a593Smuzhiyun if self.d.getVar('USE_DEPMOD') != "0": 239*4882a593Smuzhiyun self._generate_kernel_module_deps() 240*4882a593Smuzhiyun 241*4882a593Smuzhiyun self._cleanup() 242*4882a593Smuzhiyun self._log_check() 243*4882a593Smuzhiyun 244*4882a593Smuzhiyun if self.progress_reporter: 245*4882a593Smuzhiyun self.progress_reporter.next_stage() 246*4882a593Smuzhiyun 247*4882a593Smuzhiyun 248*4882a593Smuzhiyun def _uninstall_unneeded(self): 249*4882a593Smuzhiyun # Remove the run-postinsts package if no delayed postinsts are found 250*4882a593Smuzhiyun delayed_postinsts = self._get_delayed_postinsts() 251*4882a593Smuzhiyun if delayed_postinsts is None: 252*4882a593Smuzhiyun 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")): 253*4882a593Smuzhiyun self.pm.remove(["run-postinsts"]) 254*4882a593Smuzhiyun 255*4882a593Smuzhiyun image_rorfs = bb.utils.contains("IMAGE_FEATURES", "read-only-rootfs", 256*4882a593Smuzhiyun True, False, self.d) 257*4882a593Smuzhiyun image_rorfs_force = self.d.getVar('FORCE_RO_REMOVE') 258*4882a593Smuzhiyun 259*4882a593Smuzhiyun if image_rorfs or image_rorfs_force == "1": 260*4882a593Smuzhiyun # Remove components that we don't need if it's a read-only rootfs 261*4882a593Smuzhiyun unneeded_pkgs = self.d.getVar("ROOTFS_RO_UNNEEDED").split() 262*4882a593Smuzhiyun pkgs_installed = image_list_installed_packages(self.d) 263*4882a593Smuzhiyun # Make sure update-alternatives is removed last. This is 264*4882a593Smuzhiyun # because its database has to available while uninstalling 265*4882a593Smuzhiyun # other packages, allowing alternative symlinks of packages 266*4882a593Smuzhiyun # to be uninstalled or to be managed correctly otherwise. 267*4882a593Smuzhiyun provider = self.d.getVar("VIRTUAL-RUNTIME_update-alternatives") 268*4882a593Smuzhiyun pkgs_to_remove = sorted([pkg for pkg in pkgs_installed if pkg in unneeded_pkgs], key=lambda x: x == provider) 269*4882a593Smuzhiyun 270*4882a593Smuzhiyun # update-alternatives provider is removed in its own remove() 271*4882a593Smuzhiyun # call because all package managers do not guarantee the packages 272*4882a593Smuzhiyun # are removed in the order they given in the list (which is 273*4882a593Smuzhiyun # passed to the command line). The sorting done earlier is 274*4882a593Smuzhiyun # utilized to implement the 2-stage removal. 275*4882a593Smuzhiyun if len(pkgs_to_remove) > 1: 276*4882a593Smuzhiyun self.pm.remove(pkgs_to_remove[:-1], False) 277*4882a593Smuzhiyun if len(pkgs_to_remove) > 0: 278*4882a593Smuzhiyun self.pm.remove([pkgs_to_remove[-1]], False) 279*4882a593Smuzhiyun 280*4882a593Smuzhiyun if delayed_postinsts: 281*4882a593Smuzhiyun self._save_postinsts() 282*4882a593Smuzhiyun if image_rorfs: 283*4882a593Smuzhiyun bb.warn("There are post install scripts " 284*4882a593Smuzhiyun "in a read-only rootfs") 285*4882a593Smuzhiyun 286*4882a593Smuzhiyun post_uninstall_cmds = self.d.getVar("ROOTFS_POSTUNINSTALL_COMMAND") 287*4882a593Smuzhiyun execute_pre_post_process(self.d, post_uninstall_cmds) 288*4882a593Smuzhiyun 289*4882a593Smuzhiyun runtime_pkgmanage = bb.utils.contains("IMAGE_FEATURES", "package-management", 290*4882a593Smuzhiyun True, False, self.d) 291*4882a593Smuzhiyun if not runtime_pkgmanage: 292*4882a593Smuzhiyun # Remove the package manager data files 293*4882a593Smuzhiyun self.pm.remove_packaging_data() 294*4882a593Smuzhiyun 295*4882a593Smuzhiyun def _run_ldconfig(self): 296*4882a593Smuzhiyun if self.d.getVar('LDCONFIGDEPEND'): 297*4882a593Smuzhiyun bb.note("Executing: ldconfig -r " + self.image_rootfs + " -c new -v -X") 298*4882a593Smuzhiyun self._exec_shell_cmd(['ldconfig', '-r', self.image_rootfs, '-c', 299*4882a593Smuzhiyun 'new', '-v', '-X']) 300*4882a593Smuzhiyun 301*4882a593Smuzhiyun image_rorfs = bb.utils.contains("IMAGE_FEATURES", "read-only-rootfs", 302*4882a593Smuzhiyun True, False, self.d) 303*4882a593Smuzhiyun ldconfig_in_features = bb.utils.contains("DISTRO_FEATURES", "ldconfig", 304*4882a593Smuzhiyun True, False, self.d) 305*4882a593Smuzhiyun if image_rorfs or not ldconfig_in_features: 306*4882a593Smuzhiyun ldconfig_cache_dir = os.path.join(self.image_rootfs, "var/cache/ldconfig") 307*4882a593Smuzhiyun if os.path.exists(ldconfig_cache_dir): 308*4882a593Smuzhiyun bb.note("Removing ldconfig auxiliary cache...") 309*4882a593Smuzhiyun shutil.rmtree(ldconfig_cache_dir) 310*4882a593Smuzhiyun 311*4882a593Smuzhiyun def _check_for_kernel_modules(self, modules_dir): 312*4882a593Smuzhiyun for root, dirs, files in os.walk(modules_dir, topdown=True): 313*4882a593Smuzhiyun for name in files: 314*4882a593Smuzhiyun found_ko = name.endswith((".ko", ".ko.gz", ".ko.xz", ".ko.zst")) 315*4882a593Smuzhiyun if found_ko: 316*4882a593Smuzhiyun return found_ko 317*4882a593Smuzhiyun return False 318*4882a593Smuzhiyun 319*4882a593Smuzhiyun def _generate_kernel_module_deps(self): 320*4882a593Smuzhiyun modules_dir = os.path.join(self.image_rootfs, 'lib', 'modules') 321*4882a593Smuzhiyun # if we don't have any modules don't bother to do the depmod 322*4882a593Smuzhiyun if not self._check_for_kernel_modules(modules_dir): 323*4882a593Smuzhiyun bb.note("No Kernel Modules found, not running depmod") 324*4882a593Smuzhiyun return 325*4882a593Smuzhiyun 326*4882a593Smuzhiyun kernel_abi_ver_file = oe.path.join(self.d.getVar('PKGDATA_DIR'), "kernel-depmod", 327*4882a593Smuzhiyun 'kernel-abiversion') 328*4882a593Smuzhiyun if not os.path.exists(kernel_abi_ver_file): 329*4882a593Smuzhiyun bb.fatal("No kernel-abiversion file found (%s), cannot run depmod, aborting" % kernel_abi_ver_file) 330*4882a593Smuzhiyun 331*4882a593Smuzhiyun with open(kernel_abi_ver_file) as f: 332*4882a593Smuzhiyun kernel_ver = f.read().strip(' \n') 333*4882a593Smuzhiyun 334*4882a593Smuzhiyun versioned_modules_dir = os.path.join(self.image_rootfs, modules_dir, kernel_ver) 335*4882a593Smuzhiyun 336*4882a593Smuzhiyun bb.utils.mkdirhier(versioned_modules_dir) 337*4882a593Smuzhiyun 338*4882a593Smuzhiyun self._exec_shell_cmd(['depmodwrapper', '-a', '-b', self.image_rootfs, kernel_ver]) 339*4882a593Smuzhiyun 340*4882a593Smuzhiyun """ 341*4882a593Smuzhiyun Create devfs: 342*4882a593Smuzhiyun * IMAGE_DEVICE_TABLE is the old name to an absolute path to a device table file 343*4882a593Smuzhiyun * IMAGE_DEVICE_TABLES is a new name for a file, or list of files, seached 344*4882a593Smuzhiyun for in the BBPATH 345*4882a593Smuzhiyun If neither are specified then the default name of files/device_table-minimal.txt 346*4882a593Smuzhiyun is searched for in the BBPATH (same as the old version.) 347*4882a593Smuzhiyun """ 348*4882a593Smuzhiyun def _create_devfs(self): 349*4882a593Smuzhiyun devtable_list = [] 350*4882a593Smuzhiyun devtable = self.d.getVar('IMAGE_DEVICE_TABLE') 351*4882a593Smuzhiyun if devtable is not None: 352*4882a593Smuzhiyun devtable_list.append(devtable) 353*4882a593Smuzhiyun else: 354*4882a593Smuzhiyun devtables = self.d.getVar('IMAGE_DEVICE_TABLES') 355*4882a593Smuzhiyun if devtables is None: 356*4882a593Smuzhiyun devtables = 'files/device_table-minimal.txt' 357*4882a593Smuzhiyun for devtable in devtables.split(): 358*4882a593Smuzhiyun devtable_list.append("%s" % bb.utils.which(self.d.getVar('BBPATH'), devtable)) 359*4882a593Smuzhiyun 360*4882a593Smuzhiyun for devtable in devtable_list: 361*4882a593Smuzhiyun self._exec_shell_cmd(["makedevs", "-r", 362*4882a593Smuzhiyun self.image_rootfs, "-D", devtable]) 363*4882a593Smuzhiyun 364*4882a593Smuzhiyun 365*4882a593Smuzhiyundef get_class_for_type(imgtype): 366*4882a593Smuzhiyun import importlib 367*4882a593Smuzhiyun mod = importlib.import_module('oe.package_manager.' + imgtype + '.rootfs') 368*4882a593Smuzhiyun return mod.PkgRootfs 369*4882a593Smuzhiyun 370*4882a593Smuzhiyundef variable_depends(d, manifest_dir=None): 371*4882a593Smuzhiyun img_type = d.getVar('IMAGE_PKGTYPE') 372*4882a593Smuzhiyun cls = get_class_for_type(img_type) 373*4882a593Smuzhiyun return cls._depends_list() 374*4882a593Smuzhiyun 375*4882a593Smuzhiyundef create_rootfs(d, manifest_dir=None, progress_reporter=None, logcatcher=None): 376*4882a593Smuzhiyun env_bkp = os.environ.copy() 377*4882a593Smuzhiyun 378*4882a593Smuzhiyun img_type = d.getVar('IMAGE_PKGTYPE') 379*4882a593Smuzhiyun 380*4882a593Smuzhiyun cls = get_class_for_type(img_type) 381*4882a593Smuzhiyun cls(d, manifest_dir, progress_reporter, logcatcher).create() 382*4882a593Smuzhiyun os.environ.clear() 383*4882a593Smuzhiyun os.environ.update(env_bkp) 384*4882a593Smuzhiyun 385*4882a593Smuzhiyun 386*4882a593Smuzhiyundef image_list_installed_packages(d, rootfs_dir=None): 387*4882a593Smuzhiyun # Theres no rootfs for baremetal images 388*4882a593Smuzhiyun if bb.data.inherits_class('baremetal-image', d): 389*4882a593Smuzhiyun return "" 390*4882a593Smuzhiyun 391*4882a593Smuzhiyun if not rootfs_dir: 392*4882a593Smuzhiyun rootfs_dir = d.getVar('IMAGE_ROOTFS') 393*4882a593Smuzhiyun 394*4882a593Smuzhiyun img_type = d.getVar('IMAGE_PKGTYPE') 395*4882a593Smuzhiyun 396*4882a593Smuzhiyun import importlib 397*4882a593Smuzhiyun cls = importlib.import_module('oe.package_manager.' + img_type) 398*4882a593Smuzhiyun return cls.PMPkgsList(d, rootfs_dir).list_pkgs() 399*4882a593Smuzhiyun 400*4882a593Smuzhiyunif __name__ == "__main__": 401*4882a593Smuzhiyun """ 402*4882a593Smuzhiyun We should be able to run this as a standalone script, from outside bitbake 403*4882a593Smuzhiyun environment. 404*4882a593Smuzhiyun """ 405*4882a593Smuzhiyun """ 406*4882a593Smuzhiyun TBD 407*4882a593Smuzhiyun """ 408