@@ -36,6 +36,9 @@ IMAGE_FEATURES ?= ""
IMAGE_FEATURES[type] = "list"
IMAGE_FEATURES[validitems] += "debug-tweaks read-only-rootfs read-only-rootfs-delayed-postinsts stateless-rootfs empty-root-password allow-empty-password allow-root-login post-install-logging overlayfs-etc"
+# Generate snapshot of the package database?
+IMAGE_GEN_PKGDBFS ?= "0"
+
# Generate companion debugfs?
IMAGE_GEN_DEBUGFS ?= "0"
@@ -125,7 +128,7 @@ def rootfs_variables(d):
'IMAGE_ROOTFS_MAXSIZE','IMAGE_NAME','IMAGE_LINK_NAME','IMAGE_MANIFEST','DEPLOY_DIR_IMAGE','IMAGE_FSTYPES','IMAGE_INSTALL_COMPLEMENTARY','IMAGE_LINGUAS', 'IMAGE_LINGUAS_COMPLEMENTARY', 'IMAGE_LOCALES_ARCHIVE',
'MULTILIBRE_ALLOW_REP','MULTILIB_TEMP_ROOTFS','MULTILIB_VARIANTS','MULTILIBS','ALL_MULTILIB_PACKAGE_ARCHS','MULTILIB_GLOBAL_VARIANTS','BAD_RECOMMENDATIONS','NO_RECOMMENDATIONS',
'PACKAGE_ARCHS','PACKAGE_CLASSES','TARGET_VENDOR','TARGET_ARCH','TARGET_OS','OVERRIDES','BBEXTENDVARIANT','FEED_DEPLOYDIR_BASE_URI','INTERCEPT_DIR','USE_DEVFS',
- 'CONVERSIONTYPES', 'IMAGE_GEN_DEBUGFS', 'ROOTFS_RO_UNNEEDED', 'IMGDEPLOYDIR', 'PACKAGE_EXCLUDE_COMPLEMENTARY', 'REPRODUCIBLE_TIMESTAMP_ROOTFS', 'IMAGE_INSTALL_DEBUGFS']
+ 'CONVERSIONTYPES', 'IMAGE_GEN_PKGDBFS', 'IMAGE_GEN_DEBUGFS', 'ROOTFS_RO_UNNEEDED', 'IMGDEPLOYDIR', 'PACKAGE_EXCLUDE_COMPLEMENTARY', 'REPRODUCIBLE_TIMESTAMP_ROOTFS', 'IMAGE_INSTALL_DEBUGFS']
variables.extend(rootfs_command_variables(d))
variables.extend(variable_depends(d))
return " ".join(variables)
@@ -330,6 +333,19 @@ python do_image_qa_setscene () {
}
addtask do_image_qa_setscene
+def setup_pkgdbfs_variables(d):
+ d.appendVar('IMAGE_ROOTFS', '-pkgdb')
+ if d.getVar('IMAGE_LINK_NAME'):
+ d.appendVar('IMAGE_LINK_NAME', '-pkgdb')
+ d.appendVar('IMAGE_NAME','-pkgdb')
+ pkgdbfs_image_fstypes = d.getVar('IMAGE_FSTYPES_PKGDBFS')
+ if pkgdbfs_image_fstypes:
+ d.setVar('IMAGE_FSTYPES', pkgdbfs_image_fstypes)
+
+python setup_pkgdbfs () {
+ setup_pkgdbfs_variables(d)
+}
+
def setup_debugfs_variables(d):
d.appendVar('IMAGE_ROOTFS', '-dbg')
if d.getVar('IMAGE_LINK_NAME'):
@@ -374,6 +390,11 @@ python () {
alltypes = d.getVar('IMAGE_FSTYPES').split()
typedeps = {}
+ if d.getVar('IMAGE_GEN_PKGDBFS') == "1":
+ pkgdbfs_fstypes = d.getVar('IMAGE_FSTYPES_PKGDBFS').split()
+ for t in pkgdbfs_fstypes:
+ alltypes.append("pkgdbfs_" + t)
+
if d.getVar('IMAGE_GEN_DEBUGFS') == "1":
debugfs_fstypes = d.getVar('IMAGE_FSTYPES_DEBUGFS').split()
for t in debugfs_fstypes:
@@ -386,6 +407,10 @@ python () {
basetypes[baset]= []
if t not in basetypes[baset]:
basetypes[baset].append(t)
+ pkgdb = ""
+ if t.startswith("pkgdbfs_"):
+ t = t[8:]
+ pkgdb = "pkgdbfs_"
debug = ""
if t.startswith("debugfs_"):
t = t[8:]
@@ -394,6 +419,13 @@ python () {
vardeps.add('IMAGE_TYPEDEP:' + t)
if baset not in typedeps:
typedeps[baset] = set()
+ deps = [pkgdb + dep for dep in deps]
+ for dep in deps:
+ if dep not in alltypes:
+ alltypes.append(dep)
+ _add_type(dep)
+ basedep = _image_base_type(dep)
+ typedeps[baset].add(basedep)
deps = [debug + dep for dep in deps]
for dep in deps:
if dep not in alltypes:
@@ -412,6 +444,7 @@ python () {
maskedtypes = (d.getVar('IMAGE_TYPES_MASKED') or "").split()
maskedtypes = [dbg + t for t in maskedtypes for dbg in ("", "debugfs_")]
+ maskedtypes = [pkgdb + t for t in maskedtypes for pkgdb in ("", "pkgdbfs_")]
for t in basetypes:
vardeps = set()
@@ -423,6 +456,11 @@ python () {
continue
localdata = bb.data.createCopy(d)
+ pkgdb = ""
+ if t.startswith("pkgdbfs_"):
+ setup_pkgdbfs_variables(localdata)
+ pkgdb = "setup_pkgdbfs "
+ realt = t[8:]
debug = ""
if t.startswith("debugfs_"):
setup_debugfs_variables(localdata)
@@ -461,6 +499,8 @@ python () {
for ctype in sorted(ctypes):
if bt.endswith("." + ctype):
type = bt[0:-len(ctype) - 1]
+ if type.startswith("pkgdbfs_"):
+ type = type[8:]
if type.startswith("debugfs_"):
type = type[8:]
# Create input image first.
@@ -501,7 +541,7 @@ python () {
d.setVarFlag(task, 'func', '1')
d.setVarFlag(task, 'fakeroot', '1')
- d.appendVarFlag(task, 'prefuncs', ' ' + debug + ' set_image_size')
+ d.appendVarFlag(task, 'prefuncs', ' ' + debug + pkgdb + ' set_image_size')
d.prependVarFlag(task, 'postfuncs', 'create_symlinks ')
d.appendVarFlag(task, 'subimages', ' ' + ' '.join(subimages))
d.appendVarFlag(task, 'vardeps', ' ' + ' '.join(vardeps))
@@ -19,6 +19,7 @@ def imagetypes_getdepends(d):
fstypes = set((d.getVar('IMAGE_FSTYPES') or "").split())
fstypes |= set((d.getVar('IMAGE_FSTYPES_DEBUGFS') or "").split())
+ fstypes |= set((d.getVar('IMAGE_FSTYPES_PKGDBFS') or "").split())
deprecated = set()
deps = set()
@@ -830,6 +830,7 @@ require conf/sanity.conf
DL_DIR ?= "${TOPDIR}/downloads"
SSTATE_DIR ?= "${TOPDIR}/sstate-cache"
IMAGE_FSTYPES ?= "tar.gz"
+IMAGE_FSTYPES_PKGDBFS ?= "tar.gz"
IMAGE_FSTYPES_DEBUGFS ?= "tar.gz"
INITRAMFS_FSTYPES ?= "cpio.gz"
@@ -176,6 +176,7 @@ class PkgRootfs(DpkgOpkgRootfs):
if self.progress_reporter:
self.progress_reporter.next_stage()
+ self._setup_pkg_db_rootfs(['/var/lib/dpkg'])
self._setup_dbg_rootfs(['/var/lib/dpkg'])
self.pm.fix_broken_dependencies()
@@ -317,6 +317,7 @@ class PkgRootfs(DpkgOpkgRootfs):
opkg_lib_dir = self.d.getVar('OPKGLIBDIR')
opkg_dir = os.path.join(opkg_lib_dir, 'opkg')
+ self._setup_pkg_db_rootfs([opkg_dir])
self._setup_dbg_rootfs([opkg_dir])
execute_pre_post_process(self.d, opkg_post_process_cmds)
@@ -108,6 +108,7 @@ class PkgRootfs(Rootfs):
if self.progress_reporter:
self.progress_reporter.next_stage()
+ self._setup_pkg_db_rootfs(['/etc/rpm', '/etc/rpmrc', '/etc/dnf', '/var/lib/rpm', '/var/cache/dnf', '/var/lib/dnf'])
self._setup_dbg_rootfs(['/etc/rpm', '/etc/rpmrc', '/etc/dnf', '/var/lib/rpm', '/var/cache/dnf', '/var/lib/dnf'])
execute_pre_post_process(self.d, rpm_post_process_cmds)
@@ -104,6 +104,41 @@ class Rootfs(object, metaclass=ABCMeta):
def _cleanup(self):
pass
+ def _setup_pkg_db_rootfs(self, package_paths):
+ gen_pkg_db_fs = self.d.getVar('IMAGE_GEN_PKGDBFS') or '0'
+ if gen_pkg_db_fs != '1':
+ return
+
+ bb.note(" Renaming the original rootfs...")
+ try:
+ shutil.rmtree(self.image_rootfs + '-orig')
+ except:
+ pass
+ bb.utils.rename(self.image_rootfs, self.image_rootfs + '-orig')
+
+ bb.note(" Creating pkg-db rootfs...")
+ bb.utils.mkdirhier(self.image_rootfs)
+
+ bb.note(" Copying back package database...")
+ for path in package_paths:
+ bb.utils.mkdirhier(self.image_rootfs + os.path.dirname(path))
+ if os.path.isdir(self.image_rootfs + '-orig' + path):
+ shutil.copytree(self.image_rootfs + '-orig' + path, self.image_rootfs + path, symlinks=True)
+ elif os.path.isfile(self.image_rootfs + '-orig' + path):
+ shutil.copyfile(self.image_rootfs + '-orig' + path, self.image_rootfs + path)
+
+ ####
+
+ bb.note(" Rename pkg-db rootfs...")
+ try:
+ shutil.rmtree(self.image_rootfs + '-pkgdb')
+ except:
+ pass
+ bb.utils.rename(self.image_rootfs, self.image_rootfs + '-pkgdb')
+
+ bb.note(" Restoring original rootfs...")
+ bb.utils.rename(self.image_rootfs + '-orig', self.image_rootfs)
+
def _setup_dbg_rootfs(self, package_paths):
gen_debugfs = self.d.getVar('IMAGE_GEN_DEBUGFS') or '0'
if gen_debugfs != '1':
archive the package database after the rootfs has been put together as *rootfs-pkdbfs.tar.gz, and put it into the deploy folder. This creates a snapshot of the package mangers state at the point in time when all dependencies have been resolved and installed; which can be used by "follow up" images to be built upon. Signed-off-by: Johannes Schneider <johannes.schneider@leica-geosystems.com> --- meta/classes/image.bbclass | 44 +++++++++++++++++++++-- meta/classes/image_types.bbclass | 1 + meta/conf/bitbake.conf | 1 + meta/lib/oe/package_manager/deb/rootfs.py | 1 + meta/lib/oe/package_manager/ipk/rootfs.py | 1 + meta/lib/oe/package_manager/rpm/rootfs.py | 1 + meta/lib/oe/rootfs.py | 35 ++++++++++++++++++ 7 files changed, 82 insertions(+), 2 deletions(-)