blob: 0e05f1f75ef1543da4408e1069fe99515a0acd8c [file] [log] [blame]
Brad Bishopc342db32019-05-15 21:57:59 -04001#
2# SPDX-License-Identifier: GPL-2.0-only
3#
Patrick Williamsc124f4f2015-09-15 14:41:29 -05004from abc import ABCMeta, abstractmethod
5from oe.utils import execute_pre_post_process
6from oe.package_manager import *
7from oe.manifest import *
8import oe.path
9import filecmp
10import shutil
11import os
12import subprocess
13import re
14
15
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)
54 excludes = [re.compile(x) for x in excludes]
55 r = re.compile(match)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050056 log_path = self.d.expand("${T}/log.do_rootfs")
Patrick Williamsc0f7c042017-02-23 20:41:17 -060057 messages = []
Patrick Williamsc124f4f2015-09-15 14:41:29 -050058 with open(log_path, 'r') as log:
59 for line in log:
Brad Bishop6e60e8b2018-02-01 10:27:11 -050060 if self.logcatcher and self.logcatcher.contains(line.rstrip()):
61 continue
Patrick Williamsc0f7c042017-02-23 20:41:17 -060062 for ee in excludes:
63 m = ee.search(line)
64 if m:
65 break
66 if m:
Patrick Williamsc124f4f2015-09-15 14:41:29 -050067 continue
68
69 m = r.search(line)
70 if m:
Patrick Williamsc0f7c042017-02-23 20:41:17 -060071 messages.append('[log_check] %s' % line)
72 if messages:
73 if len(messages) == 1:
74 msg = '1 %s message' % type
75 else:
76 msg = '%d %s messages' % (len(messages), type)
77 msg = '[log_check] %s: found %s in the logfile:\n%s' % \
Brad Bishop6e60e8b2018-02-01 10:27:11 -050078 (self.d.getVar('PN'), msg, ''.join(messages))
Patrick Williamsc0f7c042017-02-23 20:41:17 -060079 if type == 'error':
80 bb.fatal(msg)
81 else:
82 bb.warn(msg)
83
84 def _log_check_warn(self):
85 self._log_check_common('warning', '^(warn|Warn|WARNING:)')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050086
87 def _log_check_error(self):
Patrick Williamsc0f7c042017-02-23 20:41:17 -060088 self._log_check_common('error', self.log_check_regex)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050089
90 def _insert_feed_uris(self):
91 if bb.utils.contains("IMAGE_FEATURES", "package-management",
92 True, False, self.d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -050093 self.pm.insert_feeds_uris(self.d.getVar('PACKAGE_FEED_URIS') or "",
94 self.d.getVar('PACKAGE_FEED_BASE_PATHS') or "",
95 self.d.getVar('PACKAGE_FEED_ARCHS'))
96
Patrick Williamsc124f4f2015-09-15 14:41:29 -050097
Patrick Williamsc124f4f2015-09-15 14:41:29 -050098 """
99 The _cleanup() method should be used to clean-up stuff that we don't really
100 want to end up on target. For example, in the case of RPM, the DB locks.
101 The method is called, once, at the end of create() method.
102 """
103 @abstractmethod
104 def _cleanup(self):
105 pass
106
107 def _setup_dbg_rootfs(self, dirs):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500108 gen_debugfs = self.d.getVar('IMAGE_GEN_DEBUGFS') or '0'
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500109 if gen_debugfs != '1':
110 return
111
112 bb.note(" Renaming the original rootfs...")
113 try:
114 shutil.rmtree(self.image_rootfs + '-orig')
115 except:
116 pass
117 os.rename(self.image_rootfs, self.image_rootfs + '-orig')
118
119 bb.note(" Creating debug rootfs...")
120 bb.utils.mkdirhier(self.image_rootfs)
121
122 bb.note(" Copying back package database...")
123 for dir in dirs:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600124 if not os.path.isdir(self.image_rootfs + '-orig' + dir):
125 continue
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500126 bb.utils.mkdirhier(self.image_rootfs + os.path.dirname(dir))
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600127 shutil.copytree(self.image_rootfs + '-orig' + dir, self.image_rootfs + dir, symlinks=True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500128
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500129 # Copy files located in /usr/lib/debug or /usr/src/debug
130 for dir in ["/usr/lib/debug", "/usr/src/debug"]:
131 src = self.image_rootfs + '-orig' + dir
Andrew Geissler82c905d2020-04-13 13:39:40 -0500132 if os.path.exists(src):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500133 dst = self.image_rootfs + dir
134 bb.utils.mkdirhier(os.path.dirname(dst))
135 shutil.copytree(src, dst)
136
137 # Copy files with suffix '.debug' or located in '.debug' dir.
Andrew Geissler82c905d2020-04-13 13:39:40 -0500138 for root, dirs, files in os.walk(self.image_rootfs + '-orig'):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500139 relative_dir = root[len(self.image_rootfs + '-orig'):]
140 for f in files:
141 if f.endswith('.debug') or '/.debug' in relative_dir:
142 bb.utils.mkdirhier(self.image_rootfs + relative_dir)
143 shutil.copy(os.path.join(root, f),
144 self.image_rootfs + relative_dir)
145
146 bb.note(" Install complementary '*-dbg' packages...")
147 self.pm.install_complementary('*-dbg')
148
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800149 if self.d.getVar('PACKAGE_DEBUG_SPLIT_STYLE') == 'debug-with-srcpkg':
150 bb.note(" Install complementary '*-src' packages...")
151 self.pm.install_complementary('*-src')
152
153 """
154 Install additional debug packages. Possibility to install additional packages,
155 which are not automatically installed as complementary package of
156 standard one, e.g. debug package of static libraries.
157 """
158 extra_debug_pkgs = self.d.getVar('IMAGE_INSTALL_DEBUGFS')
159 if extra_debug_pkgs:
160 bb.note(" Install extra debug packages...")
161 self.pm.install(extra_debug_pkgs.split(), True)
162
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500163 bb.note(" Rename debug rootfs...")
164 try:
165 shutil.rmtree(self.image_rootfs + '-dbg')
166 except:
167 pass
168 os.rename(self.image_rootfs, self.image_rootfs + '-dbg')
169
170 bb.note(" Restoreing original rootfs...")
171 os.rename(self.image_rootfs + '-orig', self.image_rootfs)
172
173 def _exec_shell_cmd(self, cmd):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500174 fakerootcmd = self.d.getVar('FAKEROOT')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500175 if fakerootcmd is not None:
176 exec_cmd = [fakerootcmd, cmd]
177 else:
178 exec_cmd = cmd
179
180 try:
181 subprocess.check_output(exec_cmd, stderr=subprocess.STDOUT)
182 except subprocess.CalledProcessError as e:
183 return("Command '%s' returned %d:\n%s" % (e.cmd, e.returncode, e.output))
184
185 return None
186
187 def create(self):
188 bb.note("###### Generate rootfs #######")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500189 pre_process_cmds = self.d.getVar("ROOTFS_PREPROCESS_COMMAND")
190 post_process_cmds = self.d.getVar("ROOTFS_POSTPROCESS_COMMAND")
191 rootfs_post_install_cmds = self.d.getVar('ROOTFS_POSTINSTALL_COMMAND')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500192
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500193 bb.utils.mkdirhier(self.image_rootfs)
194
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600195 bb.utils.mkdirhier(self.deploydir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500196
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500197 execute_pre_post_process(self.d, pre_process_cmds)
198
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600199 if self.progress_reporter:
200 self.progress_reporter.next_stage()
201
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500202 # call the package manager dependent create method
203 self._create()
204
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500205 sysconfdir = self.image_rootfs + self.d.getVar('sysconfdir')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500206 bb.utils.mkdirhier(sysconfdir)
207 with open(sysconfdir + "/version", "w+") as ver:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500208 ver.write(self.d.getVar('BUILDNAME') + "\n")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500209
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500210 execute_pre_post_process(self.d, rootfs_post_install_cmds)
211
Brad Bishop316dfdd2018-06-25 12:45:53 -0400212 self.pm.run_intercepts()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500213
214 execute_pre_post_process(self.d, post_process_cmds)
215
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600216 if self.progress_reporter:
217 self.progress_reporter.next_stage()
218
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500219 if bb.utils.contains("IMAGE_FEATURES", "read-only-rootfs",
220 True, False, self.d):
221 delayed_postinsts = self._get_delayed_postinsts()
222 if delayed_postinsts is not None:
223 bb.fatal("The following packages could not be configured "
224 "offline and rootfs is read-only: %s" %
225 delayed_postinsts)
226
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500227 if self.d.getVar('USE_DEVFS') != "1":
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500228 self._create_devfs()
229
230 self._uninstall_unneeded()
231
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600232 if self.progress_reporter:
233 self.progress_reporter.next_stage()
234
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500235 self._insert_feed_uris()
236
237 self._run_ldconfig()
238
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500239 if self.d.getVar('USE_DEPMOD') != "0":
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500240 self._generate_kernel_module_deps()
241
242 self._cleanup()
243 self._log_check()
244
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600245 if self.progress_reporter:
246 self.progress_reporter.next_stage()
247
248
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500249 def _uninstall_unneeded(self):
250 # Remove unneeded init script symlinks
251 delayed_postinsts = self._get_delayed_postinsts()
252 if delayed_postinsts is None:
253 if os.path.exists(self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/init.d/run-postinsts")):
254 self._exec_shell_cmd(["update-rc.d", "-f", "-r",
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500255 self.d.getVar('IMAGE_ROOTFS'),
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500256 "run-postinsts", "remove"])
257
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500258 image_rorfs = bb.utils.contains("IMAGE_FEATURES", "read-only-rootfs",
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500259 True, False, self.d)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500260 image_rorfs_force = self.d.getVar('FORCE_RO_REMOVE')
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600261
262 if image_rorfs or image_rorfs_force == "1":
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500263 # Remove components that we don't need if it's a read-only rootfs
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500264 unneeded_pkgs = self.d.getVar("ROOTFS_RO_UNNEEDED").split()
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500265 pkgs_installed = image_list_installed_packages(self.d)
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500266 # Make sure update-alternatives is removed last. This is
267 # because its database has to available while uninstalling
268 # other packages, allowing alternative symlinks of packages
269 # to be uninstalled or to be managed correctly otherwise.
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500270 provider = self.d.getVar("VIRTUAL-RUNTIME_update-alternatives")
271 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 -0500272
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500273 # update-alternatives provider is removed in its own remove()
274 # call because all package managers do not guarantee the packages
275 # are removed in the order they given in the list (which is
276 # passed to the command line). The sorting done earlier is
277 # utilized to implement the 2-stage removal.
278 if len(pkgs_to_remove) > 1:
279 self.pm.remove(pkgs_to_remove[:-1], False)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500280 if len(pkgs_to_remove) > 0:
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500281 self.pm.remove([pkgs_to_remove[-1]], False)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500282
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500283 if delayed_postinsts:
284 self._save_postinsts()
285 if image_rorfs:
286 bb.warn("There are post install scripts "
287 "in a read-only rootfs")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500288
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500289 post_uninstall_cmds = self.d.getVar("ROOTFS_POSTUNINSTALL_COMMAND")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500290 execute_pre_post_process(self.d, post_uninstall_cmds)
291
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500292 runtime_pkgmanage = bb.utils.contains("IMAGE_FEATURES", "package-management",
293 True, False, self.d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500294 if not runtime_pkgmanage:
295 # Remove the package manager data files
296 self.pm.remove_packaging_data()
297
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500298 def _run_ldconfig(self):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500299 if self.d.getVar('LDCONFIGDEPEND'):
Andrew Geissler475cb722020-07-10 16:00:51 -0500300 bb.note("Executing: ldconfig -r " + self.image_rootfs + " -c new -v -X")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500301 self._exec_shell_cmd(['ldconfig', '-r', self.image_rootfs, '-c',
Andrew Geissler475cb722020-07-10 16:00:51 -0500302 'new', '-v', '-X'])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500303
304 def _check_for_kernel_modules(self, modules_dir):
305 for root, dirs, files in os.walk(modules_dir, topdown=True):
306 for name in files:
307 found_ko = name.endswith(".ko")
308 if found_ko:
309 return found_ko
310 return False
311
312 def _generate_kernel_module_deps(self):
313 modules_dir = os.path.join(self.image_rootfs, 'lib', 'modules')
314 # if we don't have any modules don't bother to do the depmod
315 if not self._check_for_kernel_modules(modules_dir):
316 bb.note("No Kernel Modules found, not running depmod")
317 return
318
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500319 kernel_abi_ver_file = oe.path.join(self.d.getVar('PKGDATA_DIR'), "kernel-depmod",
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500320 'kernel-abiversion')
321 if not os.path.exists(kernel_abi_ver_file):
322 bb.fatal("No kernel-abiversion file found (%s), cannot run depmod, aborting" % kernel_abi_ver_file)
323
324 kernel_ver = open(kernel_abi_ver_file).read().strip(' \n')
325 versioned_modules_dir = os.path.join(self.image_rootfs, modules_dir, kernel_ver)
326
327 bb.utils.mkdirhier(versioned_modules_dir)
328
329 self._exec_shell_cmd(['depmodwrapper', '-a', '-b', self.image_rootfs, kernel_ver])
330
331 """
332 Create devfs:
333 * IMAGE_DEVICE_TABLE is the old name to an absolute path to a device table file
334 * IMAGE_DEVICE_TABLES is a new name for a file, or list of files, seached
335 for in the BBPATH
336 If neither are specified then the default name of files/device_table-minimal.txt
337 is searched for in the BBPATH (same as the old version.)
338 """
339 def _create_devfs(self):
340 devtable_list = []
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500341 devtable = self.d.getVar('IMAGE_DEVICE_TABLE')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500342 if devtable is not None:
343 devtable_list.append(devtable)
344 else:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500345 devtables = self.d.getVar('IMAGE_DEVICE_TABLES')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500346 if devtables is None:
347 devtables = 'files/device_table-minimal.txt'
348 for devtable in devtables.split():
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500349 devtable_list.append("%s" % bb.utils.which(self.d.getVar('BBPATH'), devtable))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500350
351 for devtable in devtable_list:
352 self._exec_shell_cmd(["makedevs", "-r",
353 self.image_rootfs, "-D", devtable])
354
355
356class RpmRootfs(Rootfs):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500357 def __init__(self, d, manifest_dir, progress_reporter=None, logcatcher=None):
358 super(RpmRootfs, self).__init__(d, progress_reporter, logcatcher)
Brad Bishop19323692019-04-05 15:28:33 -0400359 self.log_check_regex = r'(unpacking of archive failed|Cannot find package'\
360 r'|exit 1|ERROR: |Error: |Error |ERROR '\
361 r'|Failed |Failed: |Failed$|Failed\(\d+\):)'
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500362 self.manifest = RpmManifest(d, manifest_dir)
363
364 self.pm = RpmPM(d,
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500365 d.getVar('IMAGE_ROOTFS'),
366 self.d.getVar('TARGET_VENDOR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500367 )
368
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500369 self.inc_rpm_image_gen = self.d.getVar('INC_RPM_IMAGE_GEN')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500370 if self.inc_rpm_image_gen != "1":
371 bb.utils.remove(self.image_rootfs, True)
372 else:
373 self.pm.recovery_packaging_data()
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500374 bb.utils.remove(self.d.getVar('MULTILIB_TEMP_ROOTFS'), True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500375
376 self.pm.create_configs()
377
378 '''
379 While rpm incremental image generation is enabled, it will remove the
380 unneeded pkgs by comparing the new install solution manifest and the
381 old installed manifest.
382 '''
383 def _create_incremental(self, pkgs_initial_install):
384 if self.inc_rpm_image_gen == "1":
385
386 pkgs_to_install = list()
387 for pkg_type in pkgs_initial_install:
388 pkgs_to_install += pkgs_initial_install[pkg_type]
389
390 installed_manifest = self.pm.load_old_install_solution()
391 solution_manifest = self.pm.dump_install_solution(pkgs_to_install)
392
393 pkg_to_remove = list()
394 for pkg in installed_manifest:
395 if pkg not in solution_manifest:
396 pkg_to_remove.append(pkg)
397
398 self.pm.update()
399
400 bb.note('incremental update -- upgrade packages in place ')
401 self.pm.upgrade()
402 if pkg_to_remove != []:
403 bb.note('incremental removed: %s' % ' '.join(pkg_to_remove))
404 self.pm.remove(pkg_to_remove)
405
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500406 self.pm.autoremove()
407
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500408 def _create(self):
409 pkgs_to_install = self.manifest.parse_initial_manifest()
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500410 rpm_pre_process_cmds = self.d.getVar('RPM_PREPROCESS_COMMANDS')
411 rpm_post_process_cmds = self.d.getVar('RPM_POSTPROCESS_COMMANDS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500412
413 # update PM index files
414 self.pm.write_index()
415
416 execute_pre_post_process(self.d, rpm_pre_process_cmds)
417
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600418 if self.progress_reporter:
419 self.progress_reporter.next_stage()
420
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500421 if self.inc_rpm_image_gen == "1":
422 self._create_incremental(pkgs_to_install)
423
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600424 if self.progress_reporter:
425 self.progress_reporter.next_stage()
426
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500427 self.pm.update()
428
429 pkgs = []
430 pkgs_attempt = []
431 for pkg_type in pkgs_to_install:
432 if pkg_type == Manifest.PKG_TYPE_ATTEMPT_ONLY:
433 pkgs_attempt += pkgs_to_install[pkg_type]
434 else:
435 pkgs += pkgs_to_install[pkg_type]
436
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600437 if self.progress_reporter:
438 self.progress_reporter.next_stage()
439
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500440 self.pm.install(pkgs)
441
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600442 if self.progress_reporter:
443 self.progress_reporter.next_stage()
444
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500445 self.pm.install(pkgs_attempt, True)
446
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600447 if self.progress_reporter:
448 self.progress_reporter.next_stage()
449
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500450 self.pm.install_complementary()
451
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600452 if self.progress_reporter:
453 self.progress_reporter.next_stage()
454
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500455 self._setup_dbg_rootfs(['/etc', '/var/lib/rpm', '/var/cache/dnf', '/var/lib/dnf'])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500456
457 execute_pre_post_process(self.d, rpm_post_process_cmds)
458
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500459 if self.inc_rpm_image_gen == "1":
460 self.pm.backup_packaging_data()
461
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600462 if self.progress_reporter:
463 self.progress_reporter.next_stage()
464
465
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500466 @staticmethod
467 def _depends_list():
468 return ['DEPLOY_DIR_RPM', 'INC_RPM_IMAGE_GEN', 'RPM_PREPROCESS_COMMANDS',
469 'RPM_POSTPROCESS_COMMANDS', 'RPM_PREFER_ELF_ARCH']
470
471 def _get_delayed_postinsts(self):
472 postinst_dir = self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/rpm-postinsts")
473 if os.path.isdir(postinst_dir):
474 files = os.listdir(postinst_dir)
475 for f in files:
476 bb.note('Delayed package scriptlet: %s' % f)
477 return files
478
479 return None
480
481 def _save_postinsts(self):
482 # this is just a stub. For RPM, the failed postinstalls are
483 # already saved in /etc/rpm-postinsts
484 pass
485
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500486 def _log_check(self):
487 self._log_check_warn()
488 self._log_check_error()
489
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500490 def _cleanup(self):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800491 if bb.utils.contains("IMAGE_FEATURES", "package-management", True, False, self.d):
492 self.pm._invoke_dnf(["clean", "all"])
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500493
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500494
495class DpkgOpkgRootfs(Rootfs):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500496 def __init__(self, d, progress_reporter=None, logcatcher=None):
497 super(DpkgOpkgRootfs, self).__init__(d, progress_reporter, logcatcher)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500498
499 def _get_pkgs_postinsts(self, status_file):
500 def _get_pkg_depends_list(pkg_depends):
501 pkg_depends_list = []
502 # filter version requirements like libc (>= 1.1)
503 for dep in pkg_depends.split(', '):
Brad Bishop19323692019-04-05 15:28:33 -0400504 m_dep = re.match(r"^(.*) \(.*\)$", dep)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500505 if m_dep:
506 dep = m_dep.group(1)
507 pkg_depends_list.append(dep)
508
509 return pkg_depends_list
510
511 pkgs = {}
512 pkg_name = ""
513 pkg_status_match = False
514 pkg_depends = ""
515
516 with open(status_file) as status:
517 data = status.read()
518 status.close()
519 for line in data.split('\n'):
Brad Bishop19323692019-04-05 15:28:33 -0400520 m_pkg = re.match(r"^Package: (.*)", line)
521 m_status = re.match(r"^Status:.*unpacked", line)
522 m_depends = re.match(r"^Depends: (.*)", line)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500523
Brad Bishop19323692019-04-05 15:28:33 -0400524 #Only one of m_pkg, m_status or m_depends is not None at time
525 #If m_pkg is not None, we started a new package
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500526 if m_pkg is not None:
Brad Bishop19323692019-04-05 15:28:33 -0400527 #Get Package name
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500528 pkg_name = m_pkg.group(1)
Brad Bishop19323692019-04-05 15:28:33 -0400529 #Make sure we reset other variables
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500530 pkg_status_match = False
531 pkg_depends = ""
532 elif m_status is not None:
Brad Bishop19323692019-04-05 15:28:33 -0400533 #New status matched
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500534 pkg_status_match = True
535 elif m_depends is not None:
Brad Bishop19323692019-04-05 15:28:33 -0400536 #New depends macthed
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500537 pkg_depends = m_depends.group(1)
Brad Bishop19323692019-04-05 15:28:33 -0400538 else:
539 pass
540
541 #Now check if we can process package depends and postinst
542 if "" != pkg_name and pkg_status_match:
543 pkgs[pkg_name] = _get_pkg_depends_list(pkg_depends)
544 else:
545 #Not enough information
546 pass
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500547
548 # remove package dependencies not in postinsts
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600549 pkg_names = list(pkgs.keys())
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500550 for pkg_name in pkg_names:
551 deps = pkgs[pkg_name][:]
552
553 for d in deps:
554 if d not in pkg_names:
555 pkgs[pkg_name].remove(d)
556
557 return pkgs
558
559 def _get_delayed_postinsts_common(self, status_file):
560 def _dep_resolve(graph, node, resolved, seen):
561 seen.append(node)
562
563 for edge in graph[node]:
564 if edge not in resolved:
565 if edge in seen:
566 raise RuntimeError("Packages %s and %s have " \
567 "a circular dependency in postinsts scripts." \
568 % (node, edge))
569 _dep_resolve(graph, edge, resolved, seen)
570
571 resolved.append(node)
572
573 pkg_list = []
574
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500575 pkgs = None
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500576 if not self.d.getVar('PACKAGE_INSTALL').strip():
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500577 bb.note("Building empty image")
578 else:
579 pkgs = self._get_pkgs_postinsts(status_file)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500580 if pkgs:
581 root = "__packagegroup_postinst__"
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600582 pkgs[root] = list(pkgs.keys())
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500583 _dep_resolve(pkgs, root, pkg_list, [])
584 pkg_list.remove(root)
585
586 if len(pkg_list) == 0:
587 return None
588
589 return pkg_list
590
591 def _save_postinsts_common(self, dst_postinst_dir, src_postinst_dir):
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800592 if bb.utils.contains("IMAGE_FEATURES", "package-management",
593 True, False, self.d):
594 return
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500595 num = 0
596 for p in self._get_delayed_postinsts():
597 bb.utils.mkdirhier(dst_postinst_dir)
598
599 if os.path.exists(os.path.join(src_postinst_dir, p + ".postinst")):
600 shutil.copy(os.path.join(src_postinst_dir, p + ".postinst"),
601 os.path.join(dst_postinst_dir, "%03d-%s" % (num, p)))
602
603 num += 1
604
605class DpkgRootfs(DpkgOpkgRootfs):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500606 def __init__(self, d, manifest_dir, progress_reporter=None, logcatcher=None):
607 super(DpkgRootfs, self).__init__(d, progress_reporter, logcatcher)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500608 self.log_check_regex = '^E:'
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600609 self.log_check_expected_regexes = \
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500610 [
611 "^E: Unmet dependencies."
612 ]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500613
614 bb.utils.remove(self.image_rootfs, True)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500615 bb.utils.remove(self.d.getVar('MULTILIB_TEMP_ROOTFS'), True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500616 self.manifest = DpkgManifest(d, manifest_dir)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500617 self.pm = DpkgPM(d, d.getVar('IMAGE_ROOTFS'),
618 d.getVar('PACKAGE_ARCHS'),
619 d.getVar('DPKG_ARCH'))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500620
621
622 def _create(self):
623 pkgs_to_install = self.manifest.parse_initial_manifest()
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500624 deb_pre_process_cmds = self.d.getVar('DEB_PREPROCESS_COMMANDS')
625 deb_post_process_cmds = self.d.getVar('DEB_POSTPROCESS_COMMANDS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500626
627 alt_dir = self.d.expand("${IMAGE_ROOTFS}/var/lib/dpkg/alternatives")
628 bb.utils.mkdirhier(alt_dir)
629
630 # update PM index files
631 self.pm.write_index()
632
633 execute_pre_post_process(self.d, deb_pre_process_cmds)
634
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600635 if self.progress_reporter:
636 self.progress_reporter.next_stage()
637 # Don't support incremental, so skip that
638 self.progress_reporter.next_stage()
639
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500640 self.pm.update()
641
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600642 if self.progress_reporter:
643 self.progress_reporter.next_stage()
644
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500645 for pkg_type in self.install_order:
646 if pkg_type in pkgs_to_install:
647 self.pm.install(pkgs_to_install[pkg_type],
648 [False, True][pkg_type == Manifest.PKG_TYPE_ATTEMPT_ONLY])
Brad Bishopf3fd2882019-06-21 08:06:37 -0400649 self.pm.fix_broken_dependencies()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500650
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600651 if self.progress_reporter:
652 # Don't support attemptonly, so skip that
653 self.progress_reporter.next_stage()
654 self.progress_reporter.next_stage()
655
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500656 self.pm.install_complementary()
657
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600658 if self.progress_reporter:
659 self.progress_reporter.next_stage()
660
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500661 self._setup_dbg_rootfs(['/var/lib/dpkg'])
662
663 self.pm.fix_broken_dependencies()
664
665 self.pm.mark_packages("installed")
666
667 self.pm.run_pre_post_installs()
668
669 execute_pre_post_process(self.d, deb_post_process_cmds)
670
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600671 if self.progress_reporter:
672 self.progress_reporter.next_stage()
673
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500674 @staticmethod
675 def _depends_list():
676 return ['DEPLOY_DIR_DEB', 'DEB_SDK_ARCH', 'APTCONF_TARGET', 'APT_ARGS', 'DPKG_ARCH', 'DEB_PREPROCESS_COMMANDS', 'DEB_POSTPROCESS_COMMANDS']
677
678 def _get_delayed_postinsts(self):
679 status_file = self.image_rootfs + "/var/lib/dpkg/status"
680 return self._get_delayed_postinsts_common(status_file)
681
682 def _save_postinsts(self):
683 dst_postinst_dir = self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/deb-postinsts")
684 src_postinst_dir = self.d.expand("${IMAGE_ROOTFS}/var/lib/dpkg/info")
685 return self._save_postinsts_common(dst_postinst_dir, src_postinst_dir)
686
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500687 def _log_check(self):
688 self._log_check_warn()
689 self._log_check_error()
690
691 def _cleanup(self):
692 pass
693
694
695class OpkgRootfs(DpkgOpkgRootfs):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500696 def __init__(self, d, manifest_dir, progress_reporter=None, logcatcher=None):
697 super(OpkgRootfs, self).__init__(d, progress_reporter, logcatcher)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500698 self.log_check_regex = '(exit 1|Collected errors)'
699
700 self.manifest = OpkgManifest(d, manifest_dir)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500701 self.opkg_conf = self.d.getVar("IPKGCONF_TARGET")
702 self.pkg_archs = self.d.getVar("ALL_MULTILIB_PACKAGE_ARCHS")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500703
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500704 self.inc_opkg_image_gen = self.d.getVar('INC_IPK_IMAGE_GEN') or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500705 if self._remove_old_rootfs():
706 bb.utils.remove(self.image_rootfs, True)
707 self.pm = OpkgPM(d,
708 self.image_rootfs,
709 self.opkg_conf,
710 self.pkg_archs)
711 else:
712 self.pm = OpkgPM(d,
713 self.image_rootfs,
714 self.opkg_conf,
715 self.pkg_archs)
716 self.pm.recover_packaging_data()
717
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500718 bb.utils.remove(self.d.getVar('MULTILIB_TEMP_ROOTFS'), True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500719
720 def _prelink_file(self, root_dir, filename):
721 bb.note('prelink %s in %s' % (filename, root_dir))
722 prelink_cfg = oe.path.join(root_dir,
723 self.d.expand('${sysconfdir}/prelink.conf'))
724 if not os.path.exists(prelink_cfg):
725 shutil.copy(self.d.expand('${STAGING_DIR_NATIVE}${sysconfdir_native}/prelink.conf'),
726 prelink_cfg)
727
728 cmd_prelink = self.d.expand('${STAGING_DIR_NATIVE}${sbindir_native}/prelink')
729 self._exec_shell_cmd([cmd_prelink,
730 '--root',
731 root_dir,
732 '-amR',
733 '-N',
734 '-c',
735 self.d.expand('${sysconfdir}/prelink.conf')])
736
737 '''
738 Compare two files with the same key twice to see if they are equal.
739 If they are not equal, it means they are duplicated and come from
740 different packages.
741 1st: Comapre them directly;
742 2nd: While incremental image creation is enabled, one of the
743 files could be probaly prelinked in the previous image
744 creation and the file has been changed, so we need to
745 prelink the other one and compare them.
746 '''
747 def _file_equal(self, key, f1, f2):
748
749 # Both of them are not prelinked
750 if filecmp.cmp(f1, f2):
751 return True
752
Brad Bishop19323692019-04-05 15:28:33 -0400753 if bb.data.inherits_class('image-prelink', self.d):
754 if self.image_rootfs not in f1:
755 self._prelink_file(f1.replace(key, ''), f1)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500756
Brad Bishop19323692019-04-05 15:28:33 -0400757 if self.image_rootfs not in f2:
758 self._prelink_file(f2.replace(key, ''), f2)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500759
Brad Bishop19323692019-04-05 15:28:33 -0400760 # Both of them are prelinked
761 if filecmp.cmp(f1, f2):
762 return True
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500763
764 # Not equal
765 return False
766
767 """
768 This function was reused from the old implementation.
769 See commit: "image.bbclass: Added variables for multilib support." by
770 Lianhao Lu.
771 """
772 def _multilib_sanity_test(self, dirs):
773
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500774 allow_replace = self.d.getVar("MULTILIBRE_ALLOW_REP")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500775 if allow_replace is None:
776 allow_replace = ""
777
Brad Bishop19323692019-04-05 15:28:33 -0400778 allow_rep = re.compile(re.sub(r"\|$", r"", allow_replace))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500779 error_prompt = "Multilib check error:"
780
781 files = {}
782 for dir in dirs:
783 for root, subfolders, subfiles in os.walk(dir):
784 for file in subfiles:
785 item = os.path.join(root, file)
786 key = str(os.path.join("/", os.path.relpath(item, dir)))
787
788 valid = True
789 if key in files:
790 #check whether the file is allow to replace
791 if allow_rep.match(key):
792 valid = True
793 else:
794 if os.path.exists(files[key]) and \
795 os.path.exists(item) and \
796 not self._file_equal(key, files[key], item):
797 valid = False
798 bb.fatal("%s duplicate files %s %s is not the same\n" %
799 (error_prompt, item, files[key]))
800
801 #pass the check, add to list
802 if valid:
803 files[key] = item
804
805 def _multilib_test_install(self, pkgs):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500806 ml_temp = self.d.getVar("MULTILIB_TEMP_ROOTFS")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500807 bb.utils.mkdirhier(ml_temp)
808
809 dirs = [self.image_rootfs]
810
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500811 for variant in self.d.getVar("MULTILIB_VARIANTS").split():
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500812 ml_target_rootfs = os.path.join(ml_temp, variant)
813
814 bb.utils.remove(ml_target_rootfs, True)
815
816 ml_opkg_conf = os.path.join(ml_temp,
817 variant + "-" + os.path.basename(self.opkg_conf))
818
Brad Bishop1a4b7ee2018-12-16 17:11:34 -0800819 ml_pm = OpkgPM(self.d, ml_target_rootfs, ml_opkg_conf, self.pkg_archs, prepare_index=False)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500820
821 ml_pm.update()
822 ml_pm.install(pkgs)
823
824 dirs.append(ml_target_rootfs)
825
826 self._multilib_sanity_test(dirs)
827
828 '''
829 While ipk incremental image generation is enabled, it will remove the
830 unneeded pkgs by comparing the old full manifest in previous existing
831 image and the new full manifest in the current image.
832 '''
833 def _remove_extra_packages(self, pkgs_initial_install):
834 if self.inc_opkg_image_gen == "1":
835 # Parse full manifest in previous existing image creation session
836 old_full_manifest = self.manifest.parse_full_manifest()
837
838 # Create full manifest for the current image session, the old one
839 # will be replaced by the new one.
840 self.manifest.create_full(self.pm)
841
842 # Parse full manifest in current image creation session
843 new_full_manifest = self.manifest.parse_full_manifest()
844
845 pkg_to_remove = list()
846 for pkg in old_full_manifest:
847 if pkg not in new_full_manifest:
848 pkg_to_remove.append(pkg)
849
850 if pkg_to_remove != []:
851 bb.note('decremental removed: %s' % ' '.join(pkg_to_remove))
852 self.pm.remove(pkg_to_remove)
853
854 '''
855 Compare with previous existing image creation, if some conditions
856 triggered, the previous old image should be removed.
857 The conditions include any of 'PACKAGE_EXCLUDE, NO_RECOMMENDATIONS
858 and BAD_RECOMMENDATIONS' has been changed.
859 '''
860 def _remove_old_rootfs(self):
861 if self.inc_opkg_image_gen != "1":
862 return True
863
864 vars_list_file = self.d.expand('${T}/vars_list')
865
866 old_vars_list = ""
867 if os.path.exists(vars_list_file):
868 old_vars_list = open(vars_list_file, 'r+').read()
869
870 new_vars_list = '%s:%s:%s\n' % \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500871 ((self.d.getVar('BAD_RECOMMENDATIONS') or '').strip(),
872 (self.d.getVar('NO_RECOMMENDATIONS') or '').strip(),
873 (self.d.getVar('PACKAGE_EXCLUDE') or '').strip())
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500874 open(vars_list_file, 'w+').write(new_vars_list)
875
876 if old_vars_list != new_vars_list:
877 return True
878
879 return False
880
881 def _create(self):
882 pkgs_to_install = self.manifest.parse_initial_manifest()
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500883 opkg_pre_process_cmds = self.d.getVar('OPKG_PREPROCESS_COMMANDS')
884 opkg_post_process_cmds = self.d.getVar('OPKG_POSTPROCESS_COMMANDS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500885
Brad Bishop004d4992018-10-02 23:54:45 +0200886 # update PM index files
887 self.pm.write_index()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500888
889 execute_pre_post_process(self.d, opkg_pre_process_cmds)
890
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600891 if self.progress_reporter:
892 self.progress_reporter.next_stage()
893 # Steps are a bit different in order, skip next
894 self.progress_reporter.next_stage()
895
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500896 self.pm.update()
897
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600898 if self.progress_reporter:
899 self.progress_reporter.next_stage()
900
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500901 if self.inc_opkg_image_gen == "1":
902 self._remove_extra_packages(pkgs_to_install)
903
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600904 if self.progress_reporter:
905 self.progress_reporter.next_stage()
906
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500907 for pkg_type in self.install_order:
908 if pkg_type in pkgs_to_install:
909 # For multilib, we perform a sanity test before final install
910 # If sanity test fails, it will automatically do a bb.fatal()
911 # and the installation will stop
912 if pkg_type == Manifest.PKG_TYPE_MULTILIB:
913 self._multilib_test_install(pkgs_to_install[pkg_type])
914
915 self.pm.install(pkgs_to_install[pkg_type],
916 [False, True][pkg_type == Manifest.PKG_TYPE_ATTEMPT_ONLY])
917
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600918 if self.progress_reporter:
919 self.progress_reporter.next_stage()
920
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500921 self.pm.install_complementary()
922
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600923 if self.progress_reporter:
924 self.progress_reporter.next_stage()
925
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500926 opkg_lib_dir = self.d.getVar('OPKGLIBDIR')
Brad Bishop37a0e4d2017-12-04 01:01:44 -0500927 opkg_dir = os.path.join(opkg_lib_dir, 'opkg')
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500928 self._setup_dbg_rootfs([opkg_dir])
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500929
930 execute_pre_post_process(self.d, opkg_post_process_cmds)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500931
932 if self.inc_opkg_image_gen == "1":
933 self.pm.backup_packaging_data()
934
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600935 if self.progress_reporter:
936 self.progress_reporter.next_stage()
937
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500938 @staticmethod
939 def _depends_list():
940 return ['IPKGCONF_SDK', 'IPK_FEED_URIS', 'DEPLOY_DIR_IPK', 'IPKGCONF_TARGET', 'INC_IPK_IMAGE_GEN', 'OPKG_ARGS', 'OPKGLIBDIR', 'OPKG_PREPROCESS_COMMANDS', 'OPKG_POSTPROCESS_COMMANDS', 'OPKGLIBDIR']
941
942 def _get_delayed_postinsts(self):
943 status_file = os.path.join(self.image_rootfs,
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500944 self.d.getVar('OPKGLIBDIR').strip('/'),
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500945 "opkg", "status")
946 return self._get_delayed_postinsts_common(status_file)
947
948 def _save_postinsts(self):
949 dst_postinst_dir = self.d.expand("${IMAGE_ROOTFS}${sysconfdir}/ipk-postinsts")
950 src_postinst_dir = self.d.expand("${IMAGE_ROOTFS}${OPKGLIBDIR}/opkg/info")
951 return self._save_postinsts_common(dst_postinst_dir, src_postinst_dir)
952
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500953 def _log_check(self):
954 self._log_check_warn()
955 self._log_check_error()
956
957 def _cleanup(self):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500958 self.pm.remove_lists()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500959
960def get_class_for_type(imgtype):
961 return {"rpm": RpmRootfs,
962 "ipk": OpkgRootfs,
963 "deb": DpkgRootfs}[imgtype]
964
965def variable_depends(d, manifest_dir=None):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500966 img_type = d.getVar('IMAGE_PKGTYPE')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500967 cls = get_class_for_type(img_type)
968 return cls._depends_list()
969
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500970def create_rootfs(d, manifest_dir=None, progress_reporter=None, logcatcher=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500971 env_bkp = os.environ.copy()
972
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500973 img_type = d.getVar('IMAGE_PKGTYPE')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500974 if img_type == "rpm":
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500975 RpmRootfs(d, manifest_dir, progress_reporter, logcatcher).create()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500976 elif img_type == "ipk":
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500977 OpkgRootfs(d, manifest_dir, progress_reporter, logcatcher).create()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500978 elif img_type == "deb":
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500979 DpkgRootfs(d, manifest_dir, progress_reporter, logcatcher).create()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500980
981 os.environ.clear()
982 os.environ.update(env_bkp)
983
984
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500985def image_list_installed_packages(d, rootfs_dir=None):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500986 if not rootfs_dir:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500987 rootfs_dir = d.getVar('IMAGE_ROOTFS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500988
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500989 img_type = d.getVar('IMAGE_PKGTYPE')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500990 if img_type == "rpm":
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500991 return RpmPkgsList(d, rootfs_dir).list_pkgs()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500992 elif img_type == "ipk":
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500993 return OpkgPkgsList(d, rootfs_dir, d.getVar("IPKGCONF_TARGET")).list_pkgs()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500994 elif img_type == "deb":
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500995 return DpkgPkgsList(d, rootfs_dir).list_pkgs()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500996
997if __name__ == "__main__":
998 """
999 We should be able to run this as a standalone script, from outside bitbake
1000 environment.
1001 """
1002 """
1003 TBD
1004 """