From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail1.windriver.com (mail1.windriver.com [147.11.146.13]) by mail.openembedded.org (Postfix) with ESMTP id B9ECD6E3BB for ; Wed, 5 Mar 2014 10:08:14 +0000 (UTC) Received: from ALA-HCA.corp.ad.wrs.com (ala-hca.corp.ad.wrs.com [147.11.189.40]) by mail1.windriver.com (8.14.5/8.14.5) with ESMTP id s25A8Fad016799 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=FAIL) for ; Wed, 5 Mar 2014 02:08:15 -0800 (PST) Received: from localhost.localdomain (128.224.153.21) by ALA-HCA.corp.ad.wrs.com (147.11.189.50) with Microsoft SMTP Server (TLS) id 14.3.169.1; Wed, 5 Mar 2014 02:08:15 -0800 From: Ming Liu To: Date: Wed, 5 Mar 2014 18:08:03 +0800 Message-ID: <1394014083-9969-1-git-send-email-ming.liu@windriver.com> X-Mailer: git-send-email 1.7.1 MIME-Version: 1.0 X-Originating-IP: [128.224.153.21] Subject: [PATCH] package: let dependency on a package name to be architecture specific X-BeenThere: openembedded-core@lists.openembedded.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: Patches and discussions about the oe-core layer List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 05 Mar 2014 10:08:17 -0000 Content-Type: text/plain For multilib builds that rpm is the first package backend, it would be often desireable to express that a package of compatible architecture is needed to satisfy a dependency. In most of the cases this is already handled by the automatically extracted soname dependencies, but this is not always the case: sometimes it's necessary to disable the automatic dependency generation, and then there are cases where the information cannot be automatically generated, such as: -dev package dependencies on other -dev packages or plugins are dynamically loaded via dlopen, leading to obscure build failure that a 32bit package would incorrectly satisfy the dependency for a 64bit package and similarly vice versa. The patch mainly aims to resolve this problem, the basic idea is adding a ARCH_SPECIFIC variable for packages satisfying following scenarios: * when rpm is being set as the first package backend * it's not a allarch package * it only provides libs without bins meanwhile Every satisfied package would be set with "ARCH_SPECIFIC_pkgname = 1:${TARGET_ARCH}" and it's gonna be written into pkgdata if it exists, to mark the package as architecture specific, and it will be checked during runtime_mapping_rename, all architecture specific dependencies would be expanded with a ${TARGET_ARCH} suffix, that declares a dependency on a package name architecture specific and permits differentiating between 32-bit and 64-bit versions. Off course, the user could set "ARCH_SPECIFIC_pkgname = 0" in recipes to disable this feature. Signed-off-by: Ming Liu --- meta/classes/image.bbclass | 6 +- meta/classes/package.bbclass | 78 ++++++++++++++++++++++++++------ meta/classes/populate_sdk_base.bbclass | 2 +- 3 files changed, 68 insertions(+), 18 deletions(-) diff --git a/meta/classes/image.bbclass b/meta/classes/image.bbclass index 28b68f9..670f173 100644 --- a/meta/classes/image.bbclass +++ b/meta/classes/image.bbclass @@ -225,9 +225,9 @@ do_rootfs[prefuncs] += "rootfs_process_ignore" # may have occurred. python rootfs_runtime_mapping() { pn = d.getVar('PN', True) - runtime_mapping_rename("PACKAGE_INSTALL", pn, d) - runtime_mapping_rename("PACKAGE_INSTALL_ATTEMPTONLY", pn, d) - runtime_mapping_rename("BAD_RECOMMENDATIONS", pn, d) + runtime_mapping_rename("PACKAGE_INSTALL", pn, False, d) + runtime_mapping_rename("PACKAGE_INSTALL_ATTEMPTONLY", pn, False, d) + runtime_mapping_rename("BAD_RECOMMENDATIONS", pn, False, d) } do_rootfs[prefuncs] += "rootfs_runtime_mapping" diff --git a/meta/classes/package.bbclass b/meta/classes/package.bbclass index 0018a62..3e0ca30 100644 --- a/meta/classes/package.bbclass +++ b/meta/classes/package.bbclass @@ -346,19 +346,29 @@ def copydebugsources(debugsrcdir, d): # Package data handling routines # -def get_package_mapping (pkg, basepkg, d): +def get_package_mapping (pkg, basepkg, check_arch, d): import oe.packagedata + ret = pkg data = oe.packagedata.read_subpkgdata(pkg, d) - key = "PKG_%s" % pkg + pkg_key = "PKG_%s" % pkg + arch_key = "ARCH_SPECIFIC_%s" % pkg + arch_specific = '0' - if key in data: + if pkg_key in data: # Have to avoid undoing the write_extra_pkgs(global_variants...) - if bb.data.inherits_class('allarch', d) and data[key] == basepkg: + if bb.data.inherits_class('allarch', d) and data[pkg_key] == basepkg: return pkg - return data[key] + ret = data[pkg_key] - return pkg + if arch_key in data: + arch_specific = data[arch_key] + + items = arch_specific.split(':') + if len(items) > 1 and items[0] == '1' and check_arch == True: + ret += '(' + items[1] + ')' + + return ret def get_package_additional_metadata (pkg_type, d): base_key = "PACKAGE_ADD_METADATA" @@ -371,13 +381,13 @@ def get_package_additional_metadata (pkg_type, d): metadata_fields = [field.strip() for field in oe.data.typed_value(key, d)] return "\n".join(metadata_fields).strip() -def runtime_mapping_rename (varname, pkg, d): +def runtime_mapping_rename (varname, pkg, check_arch, d): #bb.note("%s before: %s" % (varname, d.getVar(varname, True))) new_depends = {} deps = bb.utils.explode_dep_versions2(d.getVar(varname, True) or "") for depend in deps: - new_depend = get_package_mapping(depend, pkg, d) + new_depend = get_package_mapping(depend, pkg, check_arch, d) new_depends[new_depend] = deps[depend] d.setVar(varname, bb.utils.join_deps(new_depends, commasep=False)) @@ -1119,6 +1129,34 @@ python package_fixsymlinks () { d.setVar('RDEPENDS_' + pkg, bb.utils.join_deps(rdepends, commasep=False)) } +python package_check_arch () { + import glob, re + + def check_arch_specific(pkg): + bin_re = re.compile(".*/s?" + os.path.basename(d.getVar("bindir", True)) + "$") + lib_re = re.compile(".*/" + os.path.basename(d.getVar("libdir", True)) + "($|/.*$)") + has_bins = 0 + has_libs = 0 + + for file in pkgfiles[pkg]: + root = os.path.dirname(file) + if bin_re.match(root): + has_bins = 1 + if lib_re.match(root): + has_libs = 1 + + if not bb.data.inherits_class('allarch', d) and not has_bins and has_libs: + if not d.getVar('ARCH_SPECIFIC_' + pkg): + d.setVar('ARCH_SPECIFIC_' + pkg, "%s:%s" % ('1', d.getVar('TARGET_ARCH', True))) + + # Do nothing if rpm is not the first package backend + if d.getVar('PACKAGE_CLASSES', True).split()[0] != "package_rpm": + return + + for pkg in sorted((d.getVar('PACKAGES', True) or "").split()): + check_arch_specific(pkg) +} + PKGDESTWORK = "${WORKDIR}/pkgdata" python emit_pkgdata() { @@ -1184,6 +1222,16 @@ python emit_pkgdata() { pkgval = pkg d.setVar('PKG_%s' % pkg, pkg) + arch_specific = d.getVar('ARCH_SPECIFIC_%s' % pkg, True) or "" + items = arch_specific.split(':') + if len(items) > 1 and items[0] == '1': + rprovides = d.getVar('RPROVIDES_%s' % pkg, True) + if rprovides == None: + rprovides = pkg + ' (=' + d.getVar('EXTENDPKGV', True) + ')' + else: + rprovides += ' ' + pkg + ' (=' + d.getVar('EXTENDPKGV', True) + ')' + d.setVar('RPROVIDES_%s' % pkg, rprovides) + pkgdestpkg = os.path.join(pkgdest, pkg) files = {} total_size = 0 @@ -1215,6 +1263,7 @@ python emit_pkgdata() { write_if_exists(sf, pkg, 'SECTION') write_if_exists(sf, pkg, 'PKG') write_if_exists(sf, pkg, 'ALLOW_EMPTY') + write_if_exists(sf, pkg, 'ARCH_SPECIFIC') write_if_exists(sf, pkg, 'FILES') write_if_exists(sf, pkg, 'pkg_postinst') write_if_exists(sf, pkg, 'pkg_postrm') @@ -1878,6 +1927,7 @@ PACKAGESPLITFUNCS ?= " \ PACKAGEFUNCS += " \ package_fixsymlinks \ package_name_hook \ + package_check_arch \ package_do_filedeps \ package_do_shlibs \ package_do_pkgconfig \ @@ -2010,10 +2060,10 @@ def mapping_rename_hook(d): like debian.bbclass or manual PKG variable name changes """ pkg = d.getVar("PKG", True) - runtime_mapping_rename("RDEPENDS", pkg, d) - runtime_mapping_rename("RRECOMMENDS", pkg, d) - runtime_mapping_rename("RSUGGESTS", pkg, d) - runtime_mapping_rename("RPROVIDES", pkg, d) - runtime_mapping_rename("RREPLACES", pkg, d) - runtime_mapping_rename("RCONFLICTS", pkg, d) + runtime_mapping_rename("RDEPENDS", pkg, True, d) + runtime_mapping_rename("RRECOMMENDS", pkg, True, d) + runtime_mapping_rename("RSUGGESTS", pkg, True, d) + runtime_mapping_rename("RPROVIDES", pkg, True, d) + runtime_mapping_rename("RREPLACES", pkg, True, d) + runtime_mapping_rename("RCONFLICTS", pkg, True, d) diff --git a/meta/classes/populate_sdk_base.bbclass b/meta/classes/populate_sdk_base.bbclass index 235d672..3a7927a 100644 --- a/meta/classes/populate_sdk_base.bbclass +++ b/meta/classes/populate_sdk_base.bbclass @@ -54,7 +54,7 @@ fakeroot python do_populate_sdk() { from oe.manifest import create_manifest, Manifest pn = d.getVar('PN', True) - runtime_mapping_rename("TOOLCHAIN_TARGET_TASK", pn, d) + runtime_mapping_rename("TOOLCHAIN_TARGET_TASK", pn, False, d) # create target/host SDK manifests create_manifest(d, manifest_dir=d.getVar('SDK_DIR', True), -- 1.7.1