From fc469e51475b5272b4047d4713eb99529193ac8a Mon Sep 17 00:00:00 2001 From: Robert Yang Date: Tue, 15 Sep 2015 19:04:11 -0700 Subject: package_manager.py: make rpm install mutilib pkgs corectly When configure multilib, "bitbake -c populate_sdk" should install all arch toolchains (for example, 32 and 64bit), but rpm not handle the multilib requires correctly, for example: lib32-packagegroup-core-standalone-sdk-target requires lib32-libc6, rpm may pull in libc6 rather than lib32-libc6, there are the similar issue when: IMAGE_INSTALL_append += "lib32-packagegroup-foo foo" Use bitbake to expand the RDEPENDS will fix the problem since bitbake knows mlprefix and handle it well, but rpm doesn't. This patch only affects when: IMAGE_INSTALL = "lib32-foo foo" Doesn't affect: IMAGE_INSTALL = "lib32-foo1 lib32-foo2" Or: IMAGE_INSTALL = "foo1 foo2" [YOCTO #8089] Signed-off-by: Robert Yang Signed-off-by: Richard Purdie --- meta/lib/oe/package_manager.py | 83 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 2 deletions(-) diff --git a/meta/lib/oe/package_manager.py b/meta/lib/oe/package_manager.py index 292ed44461..c51e88be58 100644 --- a/meta/lib/oe/package_manager.py +++ b/meta/lib/oe/package_manager.py @@ -605,12 +605,12 @@ class PackageManager(object): cmd.extend(['-x', exclude]) try: bb.note("Installing complementary packages ...") + bb.note('Running %s' % cmd) complementary_pkgs = subprocess.check_output(cmd, stderr=subprocess.STDOUT) except subprocess.CalledProcessError as e: bb.fatal("Could not compute complementary packages list. Command " "'%s' returned %d:\n%s" % (' '.join(cmd), e.returncode, e.output)) - self.install(complementary_pkgs.split(), attempt_only=True) def deploy_dir_lock(self): @@ -1050,6 +1050,35 @@ class RpmPM(PackageManager): def update(self): self._invoke_smart('update rpmsys') + def get_rdepends_recursively(self, pkgs): + # pkgs will be changed during the loop, so use [:] to make a copy. + for pkg in pkgs[:]: + sub_data = oe.packagedata.read_subpkgdata(pkg, self.d) + sub_rdep = sub_data.get("RDEPENDS_" + pkg) + if not sub_rdep: + continue + done = bb.utils.explode_dep_versions2(sub_rdep).keys() + next = done + # Find all the rdepends on dependency chain + while next: + new = [] + for sub_pkg in next: + sub_data = oe.packagedata.read_subpkgdata(sub_pkg, self.d) + sub_pkg_rdep = sub_data.get("RDEPENDS_" + sub_pkg) + if not sub_pkg_rdep: + continue + for p in bb.utils.explode_dep_versions2(sub_pkg_rdep): + # Already handled, skip it. + if p in done or p in pkgs: + continue + # It's a new dep + if oe.packagedata.has_subpkgdata(p, self.d): + done.append(p) + new.append(p) + next = new + pkgs.extend(done) + return pkgs + ''' Install pkgs with smart, the pkg name is oe format ''' @@ -1059,8 +1088,58 @@ class RpmPM(PackageManager): bb.note("There are no packages to install") return bb.note("Installing the following packages: %s" % ' '.join(pkgs)) + if not attempt_only: + # Pull in multilib requires since rpm may not pull in them + # correctly, for example, + # lib32-packagegroup-core-standalone-sdk-target requires + # lib32-libc6, but rpm may pull in libc6 rather than lib32-libc6 + # since it doesn't know mlprefix (lib32-), bitbake knows it and + # can handle it well, find out the RDEPENDS on the chain will + # fix the problem. Both do_rootfs and do_populate_sdk have this + # issue. + # The attempt_only packages don't need this since they are + # based on the installed ones. + # + # Separate pkgs into two lists, one is multilib, the other one + # is non-multilib. + ml_pkgs = [] + non_ml_pkgs = pkgs[:] + for pkg in pkgs: + for mlib in (self.d.getVar("MULTILIB_VARIANTS", True) or "").split(): + if pkg.startswith(mlib + '-'): + ml_pkgs.append(pkg) + non_ml_pkgs.remove(pkg) + + if len(ml_pkgs) > 0 and len(non_ml_pkgs) > 0: + # Found both foo and lib-foo + ml_pkgs = self.get_rdepends_recursively(ml_pkgs) + non_ml_pkgs = self.get_rdepends_recursively(non_ml_pkgs) + # Longer list makes smart slower, so only keep the pkgs + # which have the same BPN, and smart can handle others + # correctly. + pkgs_new = [] + for pkg in non_ml_pkgs: + for mlib in (self.d.getVar("MULTILIB_VARIANTS", True) or "").split(): + mlib_pkg = mlib + "-" + pkg + if mlib_pkg in ml_pkgs: + pkgs_new.append(pkg) + pkgs_new.append(mlib_pkg) + for pkg in pkgs: + if pkg not in pkgs_new: + pkgs_new.append(pkg) + pkgs = pkgs_new + new_depends = {} + deps = bb.utils.explode_dep_versions2(" ".join(pkgs)) + for depend in deps: + data = oe.packagedata.read_subpkgdata(depend, self.d) + key = "PKG_%s" % depend + if key in data: + new_depend = data[key] + else: + new_depend = depend + new_depends[new_depend] = deps[depend] + pkgs = bb.utils.join_deps(new_depends, commasep=True).split(', ') pkgs = self._pkg_translate_oe_to_smart(pkgs, attempt_only) - if not attempt_only: bb.note('to be installed: %s' % ' '.join(pkgs)) cmd = "%s %s install -y %s" % \ -- cgit 1.2.3-korg