From 64e283750b9fa18018bfdd9dd157609e2dd4eed4 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Tue, 2 Oct 2012 11:37:07 +0100 Subject: [PATCH] classes: Update to use corrected bb.utils.explode_dep_versions2 API The bb.utils.explode_dep_versions function has issues where dependency information can be lost. The API doesn't support maintaining the correct information so this changes to use a new function which correctly handles the data. This patch also fixes various points in the code to ensure that we do not have any duplicates in things that use explode_dep_versions. A new sanity test to test the contents of the R* variables is also added. [Some changes from Mark Hatle ] (From OE-Core rev: 16a892431d0c0d03f8b561b92909cf2f11af4918) Signed-off-by: Richard Purdie --- meta/classes/insane.bbclass | 44 ++++++++++++++++++++- meta/classes/kernel.bbclass | 12 +++--- meta/classes/multilib.bbclass | 4 +- meta/classes/package.bbclass | 48 ++++++++++++----------- meta/classes/package_deb.bbclass | 21 +++++----- meta/classes/package_ipk.bbclass | 21 +++++----- meta/classes/package_rpm.bbclass | 84 ++++++++++++++++++++++------------------ 7 files changed, 142 insertions(+), 92 deletions(-) diff --git a/meta/classes/insane.bbclass b/meta/classes/insane.bbclass index b1e68b2..4f87c93 100644 --- a/meta/classes/insane.bbclass +++ b/meta/classes/insane.bbclass @@ -114,7 +114,7 @@ def package_qa_get_machine_dict(): # Currently not being used by default "desktop" WARN_QA ?= "ldflags useless-rpaths rpaths unsafe-references-in-binaries unsafe-references-in-scripts staticdev libdir" -ERROR_QA ?= "dev-so debug-deps dev-deps debug-files arch la2 pkgconfig la perms" +ERROR_QA ?= "dev-so debug-deps dev-deps debug-files arch la2 pkgconfig la perms dep-cmp" ALL_QA = "${WARN_QA} ${ERROR_QA}" @@ -646,6 +646,43 @@ def package_qa_check_rdepends(pkg, pkgdest, skip, d): return sane +def package_qa_check_deps(pkg, pkgdest, skip, d): + sane = True + + localdata = bb.data.createCopy(d) + localdata.setVar('OVERRIDES', pkg) + bb.data.update_data(localdata) + + def check_valid_deps(var): + sane = True + try: + rvar = bb.utils.explode_dep_versions2(localdata.getVar(var, True) or "") + except ValueError as e: + bb.fatal("%s_%s: %s" % (var, pkg, e)) + raise e + for dep in rvar: + for v in rvar[dep]: + if v and not v.startswith(('< ', '= ', '> ', '<= ', '>=')): + error_msg = "%s_%s is invalid: %s (%s) only comparisons <, =, >, <=, and >= are allowed" % (var, pkg, dep, v) + sane = package_qa_handle_error("dep-cmp", error_msg, d) + return sane + + sane = True + if not check_valid_deps('RDEPENDS'): + sane = False + if not check_valid_deps('RRECOMMENDS'): + sane = False + if not check_valid_deps('RSUGGESTS'): + sane = False + if not check_valid_deps('RPROVIDES'): + sane = False + if not check_valid_deps('RREPLACES'): + sane = False + if not check_valid_deps('RCONFLICTS'): + sane = False + + return sane + # The PACKAGE FUNC to scan each package python do_package_qa () { import subprocess @@ -686,6 +723,7 @@ python do_package_qa () { g = globals() walk_sane = True rdepends_sane = True + deps_sane = True for package in packages.split(): skip = (d.getVar('INSANE_SKIP_' + package, True) or "").split() if skip: @@ -709,12 +747,14 @@ python do_package_qa () { walk_sane = False if not package_qa_check_rdepends(package, pkgdest, skip, d): rdepends_sane = False + if not package_qa_check_deps(package, pkgdest, skip, d): + deps_sane = False if 'libdir' in d.getVar("ALL_QA", True).split(): package_qa_check_libdir(d) - if not walk_sane or not rdepends_sane: + if not walk_sane or not rdepends_sane or not deps_sane: bb.fatal("QA run found fatal errors. Please consider fixing them.") bb.note("DONE with PACKAGE QA") } diff --git a/meta/classes/kernel.bbclass b/meta/classes/kernel.bbclass index fdef1be..36bc3c7 100644 --- a/meta/classes/kernel.bbclass +++ b/meta/classes/kernel.bbclass @@ -429,13 +429,11 @@ python populate_packages_prepend () { old_desc = d.getVar('DESCRIPTION_' + pkg, True) or "" d.setVar('DESCRIPTION_' + pkg, old_desc + "; " + vals["description"]) - rdepends_str = d.getVar('RDEPENDS_' + pkg, True) - if rdepends_str: - rdepends = rdepends_str.split() - else: - rdepends = [] - rdepends.extend(get_dependencies(file, pattern, format)) - d.setVar('RDEPENDS_' + pkg, ' '.join(rdepends)) + rdepends = bb.utils.explode_dep_versions2(d.getVar('RDEPENDS_' + pkg, True) or "") + for dep in get_dependencies(file, pattern, format): + if not dep in rdepends: + rdepends[dep] = [] + d.setVar('RDEPENDS_' + pkg, bb.utils.join_deps(rdepends, commasep=False)) module_deps = parse_depmod() module_regex = '^(.*)\.k?o$' diff --git a/meta/classes/multilib.bbclass b/meta/classes/multilib.bbclass index f162293..eaaad5f 100644 --- a/meta/classes/multilib.bbclass +++ b/meta/classes/multilib.bbclass @@ -85,9 +85,9 @@ PACKAGEFUNCS_append = "do_package_qa_multilib" python do_package_qa_multilib() { def check_mlprefix(pkg, var, mlprefix): - values = bb.utils.explode_dep_versions(d.getVar('%s_%s' % (var, pkg), True) or d.getVar(var, True) or "") + values = bb.utils.explode_deps(d.getVar('%s_%s' % (var, pkg), True) or d.getVar(var, True) or "") candidates = [] - for i in values.keys(): + for i in values: if i.startswith('virtual/'): i = i[len('virtual/'):] if (not i.startswith('kernel-module')) and (not i.startswith(mlprefix)): diff --git a/meta/classes/package.bbclass b/meta/classes/package.bbclass index c8aafc9..a14561d 100644 --- a/meta/classes/package.bbclass +++ b/meta/classes/package.bbclass @@ -375,17 +375,13 @@ def get_package_mapping (pkg, d): def runtime_mapping_rename (varname, d): #bb.note("%s before: %s" % (varname, d.getVar(varname, True))) - new_depends = [] - deps = bb.utils.explode_dep_versions(d.getVar(varname, True) or "") + new_depends = {} + deps = bb.utils.explode_dep_versions2(d.getVar(varname, True) or "") for depend in deps: - # Have to be careful with any version component of the depend new_depend = get_package_mapping(depend, d) - if deps[depend]: - new_depends.append("%s (%s)" % (new_depend, deps[depend])) - else: - new_depends.append(new_depend) + new_depends[new_depend] = deps[depend] - d.setVar(varname, " ".join(new_depends) or None) + d.setVar(varname, bb.utils.join_deps(new_depends, commasep=False)) #bb.note("%s after: %s" % (varname, d.getVar(varname, True))) @@ -1078,7 +1074,7 @@ python populate_packages () { dangling_links[pkg].append(os.path.normpath(target)) for pkg in package_list: - rdepends = bb.utils.explode_dep_versions(d.getVar('RDEPENDS_' + pkg, True) or d.getVar('RDEPENDS', True) or "") + rdepends = bb.utils.explode_dep_versions2(d.getVar('RDEPENDS_' + pkg, True) or d.getVar('RDEPENDS', True) or "") for l in dangling_links[pkg]: found = False @@ -1091,7 +1087,7 @@ python populate_packages () { if p == pkg: break if p not in rdepends: - rdepends[p] = "" + rdepends[p] = [] break if found == False: bb.note("%s contains dangling symlink to %s" % (pkg, l)) @@ -1637,14 +1633,19 @@ def read_libdep_files(d): pkglibdeps = {} packages = d.getVar('PACKAGES', True).split() for pkg in packages: - pkglibdeps[pkg] = [] + pkglibdeps[pkg] = {} for extension in ".shlibdeps", ".pcdeps", ".clilibdeps": depsfile = d.expand("${PKGDEST}/" + pkg + extension) if os.access(depsfile, os.R_OK): fd = file(depsfile) lines = fd.readlines() fd.close() - pkglibdeps[pkg].extend([l.rstrip() for l in lines]) + for l in lines: + l.rstrip() + deps = bb.utils.explode_dep_versions2(l) + for dep in deps: + if not dep in pkglibdeps[pkg]: + pkglibdeps[pkg][dep] = deps[dep] return pkglibdeps python read_shlibdeps () { @@ -1652,9 +1653,14 @@ python read_shlibdeps () { packages = d.getVar('PACKAGES', True).split() for pkg in packages: - rdepends = bb.utils.explode_dep_versions(d.getVar('RDEPENDS_' + pkg, False) or d.getVar('RDEPENDS', False) or "") + rdepends = bb.utils.explode_dep_versions2(d.getVar('RDEPENDS_' + pkg, False) or d.getVar('RDEPENDS', False) or "") for dep in pkglibdeps[pkg]: - rdepends[dep] = "" + # Add the dep if it's not already there, or if no comparison is set + if dep not in rdepends: + rdepends[dep] = [] + for v in pkglibdeps[pkg][dep]: + if v not in rdepends[dep]: + rdepends[dep].append(v) d.setVar('RDEPENDS_' + pkg, bb.utils.join_deps(rdepends, commasep=False)) } @@ -1679,7 +1685,7 @@ python package_depchains() { def pkg_adddeprrecs(pkg, base, suffix, getname, depends, d): #bb.note('depends for %s is %s' % (base, depends)) - rreclist = bb.utils.explode_dep_versions(d.getVar('RRECOMMENDS_' + pkg, True) or d.getVar('RRECOMMENDS', True) or "") + rreclist = bb.utils.explode_dep_versions2(d.getVar('RRECOMMENDS_' + pkg, True) or d.getVar('RRECOMMENDS', True) or "") for depend in depends: if depend.find('-native') != -1 or depend.find('-cross') != -1 or depend.startswith('virtual/'): @@ -1692,7 +1698,7 @@ python package_depchains() { pkgname = getname(depend, suffix) #bb.note("Adding %s for %s" % (pkgname, depend)) if pkgname not in rreclist and pkgname != pkg: - rreclist[pkgname] = "" + rreclist[pkgname] = [] #bb.note('setting: RRECOMMENDS_%s=%s' % (pkg, ' '.join(rreclist))) d.setVar('RRECOMMENDS_%s' % pkg, bb.utils.join_deps(rreclist, commasep=False)) @@ -1700,7 +1706,7 @@ python package_depchains() { def pkg_addrrecs(pkg, base, suffix, getname, rdepends, d): #bb.note('rdepends for %s is %s' % (base, rdepends)) - rreclist = bb.utils.explode_dep_versions(d.getVar('RRECOMMENDS_' + pkg, True) or d.getVar('RRECOMMENDS', True) or "") + rreclist = bb.utils.explode_dep_versions2(d.getVar('RRECOMMENDS_' + pkg, True) or d.getVar('RRECOMMENDS', True) or "") for depend in rdepends: if depend.find('virtual-locale-') != -1: @@ -1713,13 +1719,12 @@ python package_depchains() { pkgname = getname(depend, suffix) #bb.note("Adding %s for %s" % (pkgname, depend)) if pkgname not in rreclist and pkgname != pkg: - rreclist[pkgname] = "" + rreclist[pkgname] = [] #bb.note('setting: RRECOMMENDS_%s=%s' % (pkg, ' '.join(rreclist))) d.setVar('RRECOMMENDS_%s' % pkg, bb.utils.join_deps(rreclist, commasep=False)) def add_dep(list, dep): - dep = dep.split(' (')[0].strip() if dep not in list: list.append(dep) @@ -1758,10 +1763,7 @@ python package_depchains() { if "-dbg" in pkgs: pkglibdeps = read_libdep_files(d) - pkglibdeplist = [] - for pkg in pkglibdeps: - for dep in pkglibdeps[pkg]: - add_dep(pkglibdeplist, dep) + pkglibdeplist = pkglibdeps.keys() # FIXME this should not look at PN once all task recipes inherit from task.bbclass dbgdefaultdeps = ((d.getVar('DEPCHAIN_DBGDEFAULTDEPS', True) == '1') or (d.getVar('PN', True) or '').startswith('packagegroup-')) diff --git a/meta/classes/package_deb.bbclass b/meta/classes/package_deb.bbclass index a25e5d7..d273cb0 100644 --- a/meta/classes/package_deb.bbclass +++ b/meta/classes/package_deb.bbclass @@ -341,28 +341,29 @@ python do_package_deb () { # adjust these to the '<<' and '>>' equivalents # for dep in var: - if (var[dep] or "").startswith("< "): - var[dep] = var[dep].replace("< ", "<< ") - elif (var[dep] or "").startswith("> "): - var[dep] = var[dep].replace("> ", ">> ") + for i, v in enumerate(var[dep]): + if (v or "").startswith("< "): + var[dep][i] = var[dep][i].replace("< ", "<< ") + elif (v or "").startswith("> "): + var[dep][i] = var[dep][i].replace("> ", ">> ") - rdepends = bb.utils.explode_dep_versions(localdata.getVar("RDEPENDS", True) or "") + rdepends = bb.utils.explode_dep_versions2(localdata.getVar("RDEPENDS", True) or "") debian_cmp_remap(rdepends) for dep in rdepends: if '*' in dep: del rdepends[dep] - rrecommends = bb.utils.explode_dep_versions(localdata.getVar("RRECOMMENDS", True) or "") + rrecommends = bb.utils.explode_dep_versions2(localdata.getVar("RRECOMMENDS", True) or "") debian_cmp_remap(rrecommends) for dep in rrecommends: if '*' in dep: del rrecommends[dep] - rsuggests = bb.utils.explode_dep_versions(localdata.getVar("RSUGGESTS", True) or "") + rsuggests = bb.utils.explode_dep_versions2(localdata.getVar("RSUGGESTS", True) or "") debian_cmp_remap(rsuggests) - rprovides = bb.utils.explode_dep_versions(localdata.getVar("RPROVIDES", True) or "") + rprovides = bb.utils.explode_dep_versions2(localdata.getVar("RPROVIDES", True) or "") debian_cmp_remap(rprovides) - rreplaces = bb.utils.explode_dep_versions(localdata.getVar("RREPLACES", True) or "") + rreplaces = bb.utils.explode_dep_versions2(localdata.getVar("RREPLACES", True) or "") debian_cmp_remap(rreplaces) - rconflicts = bb.utils.explode_dep_versions(localdata.getVar("RCONFLICTS", True) or "") + rconflicts = bb.utils.explode_dep_versions2(localdata.getVar("RCONFLICTS", True) or "") debian_cmp_remap(rconflicts) if rdepends: ctrlfile.write("Depends: %s\n" % unicode(bb.utils.join_deps(rdepends))) diff --git a/meta/classes/package_ipk.bbclass b/meta/classes/package_ipk.bbclass index 281ce59..019bd7c 100644 --- a/meta/classes/package_ipk.bbclass +++ b/meta/classes/package_ipk.bbclass @@ -379,22 +379,23 @@ python do_package_ipk () { # adjust these to the '<<' and '>>' equivalents # for dep in var: - if (var[dep] or "").startswith("< "): - var[dep] = var[dep].replace("< ", "<< ") - elif (var[dep] or "").startswith("> "): - var[dep] = var[dep].replace("> ", ">> ") + for i, v in enumerate(var[dep]): + if (v or "").startswith("< "): + var[dep][i] = var[dep][i].replace("< ", "<< ") + elif (v or "").startswith("> "): + var[dep][i] = var[dep][i].replace("> ", ">> ") - rdepends = bb.utils.explode_dep_versions(localdata.getVar("RDEPENDS", True) or "") + rdepends = bb.utils.explode_dep_versions2(localdata.getVar("RDEPENDS", True) or "") debian_cmp_remap(rdepends) - rrecommends = bb.utils.explode_dep_versions(localdata.getVar("RRECOMMENDS", True) or "") + rrecommends = bb.utils.explode_dep_versions2(localdata.getVar("RRECOMMENDS", True) or "") debian_cmp_remap(rrecommends) - rsuggests = bb.utils.explode_dep_versions(localdata.getVar("RSUGGESTS", True) or "") + rsuggests = bb.utils.explode_dep_versions2(localdata.getVar("RSUGGESTS", True) or "") debian_cmp_remap(rsuggests) - rprovides = bb.utils.explode_dep_versions(localdata.getVar("RPROVIDES", True) or "") + rprovides = bb.utils.explode_dep_versions2(localdata.getVar("RPROVIDES", True) or "") debian_cmp_remap(rprovides) - rreplaces = bb.utils.explode_dep_versions(localdata.getVar("RREPLACES", True) or "") + rreplaces = bb.utils.explode_dep_versions2(localdata.getVar("RREPLACES", True) or "") debian_cmp_remap(rreplaces) - rconflicts = bb.utils.explode_dep_versions(localdata.getVar("RCONFLICTS", True) or "") + rconflicts = bb.utils.explode_dep_versions2(localdata.getVar("RCONFLICTS", True) or "") debian_cmp_remap(rconflicts) if rdepends: diff --git a/meta/classes/package_rpm.bbclass b/meta/classes/package_rpm.bbclass index 49055f2..c491775 100644 --- a/meta/classes/package_rpm.bbclass +++ b/meta/classes/package_rpm.bbclass @@ -608,6 +608,13 @@ python write_specfile () { name = "".join(name.split(eext[1] + '-')) return name + def strip_multilib_deps(deps, d): + depends = bb.utils.explode_dep_versions2(deps or "") + newdeps = {} + for dep in depends: + newdeps[strip_multilib(dep, d)] = depends[dep] + return bb.utils.join_deps(newdeps) + # ml = d.getVar("MLPREFIX", True) # if ml and name and len(ml) != 0 and name.find(ml) == 0: # return ml.join(name.split(ml, 1)[1:]) @@ -630,18 +637,20 @@ python write_specfile () { def translate_vers(varname, d): depends = d.getVar(varname, True) if depends: - depends_dict = bb.utils.explode_dep_versions(depends) + depends_dict = bb.utils.explode_dep_versions2(depends) newdeps_dict = {} for dep in depends_dict: - ver = depends_dict[dep] - if dep and ver: + verlist = [] + for ver in depends_dict[dep]: if '-' in ver: subd = oe.packagedata.read_subpkgdata_dict(dep, d) if 'PKGV' in subd: pv = subd['PKGV'] reppv = pv.replace('-', '+') - ver = ver.replace(pv, reppv) - newdeps_dict[dep] = ver + verlist.append(ver.replace(pv, reppv)) + else: + verlist.append(ver) + newdeps_dict[dep] = verlist depends = bb.utils.join_deps(newdeps_dict) d.setVar(varname, depends.strip()) @@ -650,14 +659,13 @@ python write_specfile () { def print_deps(variable, tag, array, d): depends = variable if depends: - depends_dict = bb.utils.explode_dep_versions(depends) + depends_dict = bb.utils.explode_dep_versions2(depends) for dep in depends_dict: - ver = depends_dict[dep] - if dep and ver: + for ver in depends_dict[dep]: ver = ver.replace('(', '') ver = ver.replace(')', '') array.append("%s: %s %s" % (tag, dep, ver)) - else: + if not len(depends_dict[dep]): array.append("%s: %s" % (tag, dep)) def walk_files(walkpath, target, conffiles): @@ -709,7 +717,7 @@ python write_specfile () { srchomepage = d.getVar('HOMEPAGE', True) srcdescription = d.getVar('DESCRIPTION', True) or "." - srcdepends = strip_multilib(d.getVar('DEPENDS', True), d) + srcdepends = strip_multilib_deps(d.getVar('DEPENDS', True), d) srcrdepends = [] srcrrecommends = [] srcrsuggests = [] @@ -772,12 +780,12 @@ python write_specfile () { # Map the dependencies into their final form mapping_rename_hook(localdata) - splitrdepends = strip_multilib(localdata.getVar('RDEPENDS', True), d) or "" - splitrrecommends = strip_multilib(localdata.getVar('RRECOMMENDS', True), d) or "" - splitrsuggests = strip_multilib(localdata.getVar('RSUGGESTS', True), d) or "" - splitrprovides = strip_multilib(localdata.getVar('RPROVIDES', True), d) or "" - splitrreplaces = strip_multilib(localdata.getVar('RREPLACES', True), d) or "" - splitrconflicts = strip_multilib(localdata.getVar('RCONFLICTS', True), d) or "" + splitrdepends = strip_multilib_deps(localdata.getVar('RDEPENDS', True), d) + splitrrecommends = strip_multilib_deps(localdata.getVar('RRECOMMENDS', True), d) + splitrsuggests = strip_multilib_deps(localdata.getVar('RSUGGESTS', True), d) + splitrprovides = strip_multilib_deps(localdata.getVar('RPROVIDES', True), d) + splitrreplaces = strip_multilib_deps(localdata.getVar('RREPLACES', True), d) + splitrconflicts = strip_multilib_deps(localdata.getVar('RCONFLICTS', True), d) splitrobsoletes = [] # Gather special src/first package data @@ -826,16 +834,16 @@ python write_specfile () { spec_preamble_bottom.append('Group: %s' % splitsection) # Replaces == Obsoletes && Provides - if splitrreplaces and splitrreplaces.strip() != "": - for dep in splitrreplaces.split(','): - if splitrprovides: - splitrprovides = splitrprovides + ", " + dep - else: - splitrprovides = dep - if splitrobsoletes: - splitrobsoletes = splitrobsoletes + ", " + dep - else: - splitrobsoletes = dep + robsoletes = bb.utils.explode_dep_versions2(splitrobsoletes or "") + rprovides = bb.utils.explode_dep_versions2(splitrprovides or "") + rreplaces = bb.utils.explode_dep_versions2(splitrreplaces or "") + for dep in rreplaces: + if not dep in robsoletes: + robsoletes[dep] = rreplaces[dep] + if not dep in rprovides: + rprovides[dep] = rreplaces[dep] + splitrobsoletes = bb.utils.join_deps(robsoletes, commasep=False) + splitrprovides = bb.utils.join_deps(rprovides, commasep=False) print_deps(splitrdepends, "Requires", spec_preamble_bottom, d) # Suggests in RPM are like recommends in OE-core! @@ -847,7 +855,7 @@ python write_specfile () { # conflicts can not be in a provide! We will need to filter it. if splitrconflicts: - depends_dict = bb.utils.explode_dep_versions(splitrconflicts) + depends_dict = bb.utils.explode_dep_versions2(splitrconflicts) newdeps_dict = {} for dep in depends_dict: if dep not in splitrprovides: @@ -918,16 +926,16 @@ python write_specfile () { tail_source(d) # Replaces == Obsoletes && Provides - if srcrreplaces and srcrreplaces.strip() != "": - for dep in srcrreplaces.split(','): - if srcrprovides: - srcrprovides = srcrprovides + ", " + dep - else: - srcrprovides = dep - if srcrobsoletes: - srcrobsoletes = srcrobsoletes + ", " + dep - else: - srcrobsoletes = dep + robsoletes = bb.utils.explode_dep_versions2(srcrobsoletes or "") + rprovides = bb.utils.explode_dep_versions2(srcrprovides or "") + rreplaces = bb.utils.explode_dep_versions2(srcrreplaces or "") + for dep in rreplaces: + if not dep in robsoletes: + robsoletes[dep] = rreplaces[dep] + if not dep in rprovides: + rprovides[dep] = rreplaces[dep] + srcrobsoletes = bb.utils.join_deps(robsoletes, commasep=False) + srcrprovides = bb.utils.join_deps(rprovides, commasep=False) print_deps(srcdepends, "BuildRequires", spec_preamble_top, d) print_deps(srcrdepends, "Requires", spec_preamble_top, d) @@ -940,7 +948,7 @@ python write_specfile () { # conflicts can not be in a provide! We will need to filter it. if srcrconflicts: - depends_dict = bb.utils.explode_dep_versions(srcrconflicts) + depends_dict = bb.utils.explode_dep_versions2(srcrconflicts) newdeps_dict = {} for dep in depends_dict: if dep not in srcrprovides: -- 2.7.4