[OE-core] [PATCH V2] package: let dependency on a package name to be architecture specific

Ming Liu ming.liu at windriver.com
Sun Mar 9 02:16:31 UTC 2014


On 03/09/2014 09:26 AM, Ming Liu wrote:
> 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:
>    * 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}" by package_check_arch function
s/TARGET_ARCH /PACKAGE_ARCH.

//Ming Liu
> added in PACKAGEFUNCS and the variable is gonna be written into pkgdata
> if it exists, to mark the package as architecture specific, and it will
> be checked during runtime_mapping_rename is executed when generating rpm
> packages, all architecture specific dependencies would be expanded with
> a ${PACKAGE_ARCH} suffix, that declares a dependency on a package name
> architecture specific and permits differentiating between 32-bit and
> 64-bit versions.
>
> The end user could set "ARCH_SPECIFIC_pkgname = 0" in recipes to disable
> this feature.
>
> Signed-off-by: Ming Liu <ming.liu at windriver.com>
> ---
>   meta/classes/image.bbclass             |    6 +-
>   meta/classes/package.bbclass           |   76 +++++++++++++++++++++++++------
>   meta/classes/package_deb.bbclass       |    2 +-
>   meta/classes/package_ipk.bbclass       |    2 +-
>   meta/classes/package_rpm.bbclass       |    2 +-
>   meta/classes/populate_sdk_base.bbclass |    2 +-
>   6 files changed, 68 insertions(+), 22 deletions(-)
>
> diff --git a/meta/classes/image.bbclass b/meta/classes/image.bbclass
> index 51d16d7..36528fd 100644
> --- a/meta/classes/image.bbclass
> +++ b/meta/classes/image.bbclass
> @@ -230,9 +230,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..1fda2f7 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,30 @@ python package_fixsymlinks () {
>           d.setVar('RDEPENDS_' + pkg, bb.utils.join_deps(rdepends, commasep=False))
>   }
>   
> +# Check architecture specific packages
> +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('PACKAGE_ARCH', True)))
> +
> +    for pkg in sorted((d.getVar('PACKAGES', True) or "").split()):
> +        check_arch_specific(pkg)
> +}
> +
>   PKGDESTWORK = "${WORKDIR}/pkgdata"
>   
>   python emit_pkgdata() {
> @@ -1184,6 +1218,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 +1259,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 +1923,7 @@ PACKAGESPLITFUNCS ?= " \
>   PACKAGEFUNCS += " \
>                   package_fixsymlinks \
>                   package_name_hook \
> +                package_check_arch \
>                   package_do_filedeps \
>                   package_do_shlibs \
>                   package_do_pkgconfig \
> @@ -2004,16 +2050,16 @@ addtask do_packagedata_setscene
>   # Helper functions for the package writing classes
>   #
>   
> -def mapping_rename_hook(d):
> +def mapping_rename_hook(check_arch, d):
>       """
>       Rewrite variables to account for package renaming in things
>       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, check_arch, d)
> +    runtime_mapping_rename("RRECOMMENDS", pkg, check_arch, d)
> +    runtime_mapping_rename("RSUGGESTS", pkg, check_arch, d)
> +    runtime_mapping_rename("RPROVIDES", pkg, check_arch, d)
> +    runtime_mapping_rename("RREPLACES", pkg, check_arch, d)
> +    runtime_mapping_rename("RCONFLICTS", pkg, check_arch, d)
>   
> diff --git a/meta/classes/package_deb.bbclass b/meta/classes/package_deb.bbclass
> index a16d57e..846f13e 100644
> --- a/meta/classes/package_deb.bbclass
> +++ b/meta/classes/package_deb.bbclass
> @@ -178,7 +178,7 @@ python do_package_deb () {
>               ctrlfile.write(unicode(custom_fields_chunk))
>               ctrlfile.write("\n")
>   
> -        mapping_rename_hook(localdata)
> +        mapping_rename_hook(False, localdata)
>   
>           def debian_cmp_remap(var):
>               # dpkg does not allow for '(' or ')' in a dependency name
> diff --git a/meta/classes/package_ipk.bbclass b/meta/classes/package_ipk.bbclass
> index aab31e5..1c88d07 100644
> --- a/meta/classes/package_ipk.bbclass
> +++ b/meta/classes/package_ipk.bbclass
> @@ -142,7 +142,7 @@ python do_package_ipk () {
>               ctrlfile.write(custom_fields_chunk)
>               ctrlfile.write("\n")
>   
> -        mapping_rename_hook(localdata)
> +        mapping_rename_hook(False, localdata)
>   
>           def debian_cmp_remap(var):
>               # In debian '>' and '<' do not mean what it appears they mean
> diff --git a/meta/classes/package_rpm.bbclass b/meta/classes/package_rpm.bbclass
> index bce5648..7c13d61 100644
> --- a/meta/classes/package_rpm.bbclass
> +++ b/meta/classes/package_rpm.bbclass
> @@ -329,7 +329,7 @@ python write_specfile () {
>           translate_vers('RCONFLICTS', localdata)
>   
>           # Map the dependencies into their final form
> -        mapping_rename_hook(localdata)
> +        mapping_rename_hook(True, localdata)
>   
>           splitrdepends    = strip_multilib_deps(localdata.getVar('RDEPENDS', True), d)
>           splitrrecommends = strip_multilib_deps(localdata.getVar('RRECOMMENDS', 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),




More information about the Openembedded-core mailing list