aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKoen Kooi <koen.kooi@linaro.org>2016-02-18 12:00:19 +0100
committerKoen Kooi <koen.kooi@linaro.org>2016-02-18 12:01:06 +0100
commit021a8d66e620073de282381b57f6e048e60e8af5 (patch)
tree262c505fda77130a0b0f224f8edbeca8514af8b2
parentd7b87f5d93d59c86e8058c41dabefd0fc2ca2ae7 (diff)
meta-ilp32: sync insane.bbclass with OE-core
Change-Id: I87d5d1018832f9a248cf9a163a1d7925a7a9cc65 Signed-off-by: Koen Kooi <koen.kooi@linaro.org>
-rw-r--r--meta-ilp32/classes/insane.bbclass361
1 files changed, 251 insertions, 110 deletions
diff --git a/meta-ilp32/classes/insane.bbclass b/meta-ilp32/classes/insane.bbclass
index ab8896c4..cb0029c7 100644
--- a/meta-ilp32/classes/insane.bbclass
+++ b/meta-ilp32/classes/insane.bbclass
@@ -11,6 +11,7 @@
# -Check if packages contains .debug directories or .so files
# where they should be in -dev or -dbg
# -Check if config.log contains traces to broken autoconf tests
+# -Check invalid characters (non-utf8) on some package metadata
# -Ensure that binaries in base_[bindir|sbindir|libdir] do not link
# into exec_prefix
# -Check that scripts in base_[bindir|sbindir|libdir] do not reference
@@ -30,16 +31,22 @@ WARN_QA ?= "ldflags useless-rpaths rpaths staticdev libdir xorg-driver-abi \
textrel already-stripped incompatible-license files-invalid \
installed-vs-shipped compile-host-path install-host-path \
pn-overrides infodir build-deps file-rdeps \
+ unknown-configure-option symlink-to-sysroot multilib \
+ invalid-packageconfig host-user-contaminated \
"
ERROR_QA ?= "dev-so debug-deps dev-deps debug-files arch pkgconfig la \
perms dep-cmp pkgvarcheck perm-config perm-line perm-link \
split-strip packages-list pkgv-undefined var-undefined \
- version-going-backwards \
+ version-going-backwards expanded-d invalid-chars \
+ license-checksum dev-elf \
"
+FAKEROOT_QA = "host-user-contaminated"
+FAKEROOT_QA[doc] = "QA tests which need to run under fakeroot. If any \
+enabled tests are listed here, the do_package_qa task will run under fakeroot."
ALL_QA = "${WARN_QA} ${ERROR_QA}"
-UNKNOWN_CONFIGURE_WHITELIST ?= "--enable-nls --disable-nls --disable-silent-rules --disable-dependency-tracking --with-libtool-sysroot"
+UNKNOWN_CONFIGURE_WHITELIST ?= "--enable-nls --disable-nls --disable-silent-rules --disable-dependency-tracking --with-libtool-sysroot --disable-static"
#
# dictionary for elf headers
@@ -52,6 +59,14 @@ def package_qa_get_machine_dict():
"darwin9" : {
"arm" : (40, 0, 0, True, 32),
},
+ "eabi" : {
+ "arm" : (40, 0, 0, True, 32),
+ },
+ "elf" : {
+ "i586" : (3, 0, 0, True, 32),
+ "x86_64": (62, 0, 0, True, 64),
+ "epiphany": (4643, 0, 0, True, 32),
+ },
"linux" : {
"aarch64" : (183, 0, 0, True, 64),
"aarch64_be" :(183, 0, 0, False, 64),
@@ -72,10 +87,12 @@ def package_qa_get_machine_dict():
"mipsel": ( 8, 0, 0, True, 32),
"mips64": ( 8, 0, 0, False, 64),
"mips64el": ( 8, 0, 0, True, 64),
+ "nios2": (113, 0, 0, True, 32),
"s390": (22, 0, 0, False, 32),
"sh4": (42, 0, 0, True, 32),
"sparc": ( 2, 0, 0, False, 32),
"microblaze": (189, 0, 0, False, 32),
+ "microblazeeb":(189, 0, 0, False, 32),
"microblazeel":(189, 0, 0, True, 32),
},
"linux-uclibc" : {
@@ -96,6 +113,8 @@ def package_qa_get_machine_dict():
},
"linux-musl" : {
+ "aarch64" : (183, 0, 0, True, 64),
+ "aarch64_be" :(183, 0, 0, False, 64),
"arm" : ( 40, 97, 0, True, 32),
"armeb": ( 40, 97, 0, False, 32),
"powerpc": ( 20, 0, 0, False, 32),
@@ -108,6 +127,9 @@ def package_qa_get_machine_dict():
"mipsel": ( 8, 0, 0, True, 32),
"mips64": ( 8, 0, 0, False, 64),
"mips64el": ( 8, 0, 0, True, 64),
+ "microblaze": (189, 0, 0, False, 32),
+ "microblazeeb":(189, 0, 0, False, 32),
+ "microblazeel":(189, 0, 0, True, 32),
},
"uclinux-uclibc" : {
"bfin": ( 106, 0, 0, True, 32),
@@ -152,7 +174,7 @@ def package_qa_get_machine_dict():
def package_qa_clean_path(path,d):
""" Remove the common prefix from the path. In this case it is the TMPDIR"""
- return path.replace(d.getVar('TMPDIR',True),"")
+ return path.replace(d.getVar("TMPDIR", True) + "/", "")
def package_qa_write_error(type, error, d):
logfile = d.getVar('QA_LOGFILE', True)
@@ -174,6 +196,12 @@ def package_qa_handle_error(error_class, error_msg, d):
bb.note("QA Issue: %s [%s]" % (error_msg, error_class))
return True
+def package_qa_add_message(messages, section, new_msg):
+ if section not in messages:
+ messages[section] = new_msg
+ else:
+ messages[section] = messages[section] + "\n" + new_msg
+
QAPATHTEST[libexec] = "package_qa_check_libexec"
def package_qa_check_libexec(path,name, d, elf, messages):
@@ -183,7 +211,7 @@ def package_qa_check_libexec(path,name, d, elf, messages):
return True
if 'libexec' in path.split(os.path.sep):
- messages["libexec"] = "%s: %s is using libexec please relocate to %s" % (name, package_qa_clean_path(path, d), libexec)
+ package_qa_add_message(messages, "libexec", "%s: %s is using libexec please relocate to %s" % (name, package_qa_clean_path(path, d), libexec))
return False
return True
@@ -211,7 +239,7 @@ def package_qa_check_rpath(file,name, d, elf, messages):
rpath = m.group(1)
for dir in bad_dirs:
if dir in rpath:
- messages["rpaths"] = "package %s contains bad RPATH %s in file %s" % (name, rpath, file)
+ package_qa_add_message(messages, "rpaths", "package %s contains bad RPATH %s in file %s" % (name, rpath, file))
QAPATHTEST[useless-rpaths] = "package_qa_check_useless_rpaths"
def package_qa_check_useless_rpaths(file, name, d, elf, messages):
@@ -241,7 +269,7 @@ def package_qa_check_useless_rpaths(file, name, d, elf, messages):
if rpath_eq(rpath, libdir) or rpath_eq(rpath, base_libdir):
# The dynamic linker searches both these places anyway. There is no point in
# looking there again.
- messages["useless-rpaths"] = "%s: %s contains probably-redundant RPATH %s" % (name, package_qa_clean_path(file, d), rpath)
+ package_qa_add_message(messages, "useless-rpaths", "%s: %s contains probably-redundant RPATH %s" % (name, package_qa_clean_path(file, d), rpath))
QAPATHTEST[dev-so] = "package_qa_check_dev"
def package_qa_check_dev(path, name, d, elf, messages):
@@ -250,8 +278,19 @@ def package_qa_check_dev(path, name, d, elf, messages):
"""
if not name.endswith("-dev") and not name.endswith("-dbg") and not name.endswith("-ptest") and not name.startswith("nativesdk-") and path.endswith(".so") and os.path.islink(path):
- messages["dev-so"] = "non -dev/-dbg/-nativesdk package contains symlink .so: %s path '%s'" % \
- (name, package_qa_clean_path(path,d))
+ package_qa_add_message(messages, "dev-so", "non -dev/-dbg/nativesdk- package contains symlink .so: %s path '%s'" % \
+ (name, package_qa_clean_path(path,d)))
+
+QAPATHTEST[dev-elf] = "package_qa_check_dev_elf"
+def package_qa_check_dev_elf(path, name, d, elf, messages):
+ """
+ Check that -dev doesn't contain real shared libraries. The test has to
+ check that the file is not a link and is an ELF object as some recipes
+ install link-time .so files that are linker scripts.
+ """
+ if name.endswith("-dev") and path.endswith(".so") and not os.path.islink(path) and elf:
+ package_qa_add_message(messages, "dev-elf", "-dev package contains non-symlink .so: %s path '%s'" % \
+ (name, package_qa_clean_path(path,d)))
QAPATHTEST[staticdev] = "package_qa_check_staticdev"
def package_qa_check_staticdev(path, name, d, elf, messages):
@@ -263,8 +302,8 @@ def package_qa_check_staticdev(path, name, d, elf, messages):
"""
if not name.endswith("-pic") and not name.endswith("-staticdev") and not name.endswith("-ptest") and path.endswith(".a") and not path.endswith("_nonshared.a"):
- messages["staticdev"] = "non -staticdev package contains static .a library: %s path '%s'" % \
- (name, package_qa_clean_path(path,d))
+ package_qa_add_message(messages, "staticdev", "non -staticdev package contains static .a library: %s path '%s'" % \
+ (name, package_qa_clean_path(path,d)))
def package_qa_check_libdir(d):
"""
@@ -277,6 +316,7 @@ def package_qa_check_libdir(d):
pkgdest = d.getVar('PKGDEST', True)
base_libdir = d.getVar("base_libdir",True) + os.sep
libdir = d.getVar("libdir", True) + os.sep
+ libexecdir = d.getVar("libexecdir", True) + os.sep
exec_prefix = d.getVar("exec_prefix", True) + os.sep
messages = []
@@ -292,6 +332,9 @@ def package_qa_check_libdir(d):
if 'libdir' in (d.getVar('INSANE_SKIP_' + package, True) or "").split():
bb.note("Package %s skipping libdir QA test" % (package))
skippackages.append(package)
+ elif d.getVar('PACKAGE_DEBUG_SPLIT_STYLE', True) == 'debug-file-directory' and package.endswith("-dbg"):
+ bb.note("Package %s skipping libdir QA test for PACKAGE_DEBUG_SPLIT_STYLE equals debug-file-directory" % (package))
+ skippackages.append(package)
for package in skippackages:
dirs.remove(package)
for file in files:
@@ -304,7 +347,7 @@ def package_qa_check_libdir(d):
if base_libdir not in rel_path:
messages.append("%s: found library in wrong location: %s" % (package, rel_path))
if exec_re.match(rel_path):
- if libdir not in rel_path:
+ if libdir not in rel_path and libexecdir not in rel_path:
messages.append("%s: found library in wrong location: %s" % (package, rel_path))
if messages:
@@ -318,8 +361,8 @@ def package_qa_check_dbg(path, name, d, elf, messages):
if not "-dbg" in name and not "-ptest" in name:
if '.debug' in path.split(os.path.sep):
- messages["debug-files"] = "non debug package contains .debug directory: %s path %s" % \
- (name, package_qa_clean_path(path,d))
+ messages("debug-files", "non debug package contains .debug directory: %s path %s" % \
+ (name, package_qa_clean_path(path,d)))
QAPATHTEST[perms] = "package_qa_check_perm"
def package_qa_check_perm(path,name,d, elf, messages):
@@ -448,6 +491,11 @@ def package_qa_check_arch(path,name,d, elf, messages):
provides = d.getVar('PROVIDES', True)
bpn = d.getVar('BPN', True)
+ if target_arch == "allarch":
+ pn = d.getVar('PN', True)
+ package_qa_add_message(messages, "arch", pn + ": Recipe inherits the allarch class, but has packaged architecture-specific binaries")
+ return
+
# FIXME: Cross package confuse this check, so just skip them
for s in ['cross', 'nativesdk', 'cross-canadian']:
if bb.data.inherits_class(s, d):
@@ -465,15 +513,15 @@ def package_qa_check_arch(path,name,d, elf, messages):
# Check the architecture and endiannes of the binary
if not ((machine == elf.machine()) or \
((("virtual/kernel" in provides) or bb.data.inherits_class("module", d) ) and (target_os == "linux-gnux32" or target_os == "linux-gnun32"))):
- messages["arch"] = "Architecture did not match (%d to %d) on %s" % \
- (machine, elf.machine(), package_qa_clean_path(path,d))
+ package_qa_add_message(messages, "arch", "Architecture did not match (%d to %d) on %s" % \
+ (machine, elf.machine(), package_qa_clean_path(path,d)))
elif not ((bits == elf.abiSize()) or \
((("virtual/kernel" in provides) or bb.data.inherits_class("module", d) ) and (target_os == "linux-gnux32" or target_os == "linux-gnun32"))):
- messages["arch"] = "Bit size did not match (%d to %d) %s on %s" % \
- (bits, elf.abiSize(), bpn, package_qa_clean_path(path,d))
+ package_qa_add_message(messages, "arch", "Bit size did not match (%d to %d) %s on %s" % \
+ (bits, elf.abiSize(), bpn, package_qa_clean_path(path,d)))
elif not littleendian == elf.isLittleEndian():
- messages["arch"] = "Endiannes did not match (%d to %d) on %s" % \
- (littleendian, elf.isLittleEndian(), package_qa_clean_path(path,d))
+ package_qa_add_message(messages, "arch", "Endiannes did not match (%d to %d) on %s" % \
+ (littleendian, elf.isLittleEndian(), package_qa_clean_path(path,d)))
QAPATHTEST[desktop] = "package_qa_check_desktop"
def package_qa_check_desktop(path, name, d, elf, messages):
@@ -485,7 +533,7 @@ def package_qa_check_desktop(path, name, d, elf, messages):
output = os.popen("%s %s" % (desktop_file_validate, path))
# This only produces output on errors
for l in output:
- messages["desktop"] = "Desktop file issue: " + l.strip()
+ package_qa_add_message(messages, "desktop", "Desktop file issue: " + l.strip())
QAPATHTEST[textrel] = "package_qa_textrel"
def package_qa_textrel(path, name, d, elf, messages):
@@ -509,7 +557,7 @@ def package_qa_textrel(path, name, d, elf, messages):
sane = False
if not sane:
- messages["textrel"] = "ELF binary '%s' has relocations in .text" % path
+ package_qa_add_message(messages, "textrel", "ELF binary '%s' has relocations in .text" % path)
QAPATHTEST[ldflags] = "package_qa_hash_style"
def package_qa_hash_style(path, name, d, elf, messages):
@@ -544,7 +592,7 @@ def package_qa_hash_style(path, name, d, elf, messages):
sane = True
if has_syms and not sane:
- messages["ldflags"] = "No GNU_HASH in the elf binary: '%s'" % path
+ package_qa_add_message(messages, "ldflags", "No GNU_HASH in the elf binary: '%s'" % path)
QAPATHTEST[buildpaths] = "package_qa_check_buildpaths"
@@ -560,11 +608,15 @@ def package_qa_check_buildpaths(path, name, d, elf, messages):
if os.path.islink(path):
return
+ # Ignore ipk and deb's CONTROL dir
+ if path.find(name + "/CONTROL/") != -1 or path.find(name + "/DEBIAN/") != -1:
+ return
+
tmpdir = d.getVar('TMPDIR', True)
with open(path) as f:
file_content = f.read()
if tmpdir in file_content:
- messages["buildpaths"] = "File %s in package contained reference to tmpdir" % package_qa_clean_path(path,d)
+ package_qa_add_message(messages, "buildpaths", "File %s in package contained reference to tmpdir" % package_qa_clean_path(path,d))
QAPATHTEST[xorg-driver-abi] = "package_qa_check_xorg_driver_abi"
@@ -583,7 +635,7 @@ def package_qa_check_xorg_driver_abi(path, name, d, elf, messages):
for rdep in bb.utils.explode_deps(d.getVar('RDEPENDS_' + name, True) or ""):
if rdep.startswith("%sxorg-abi-" % mlprefix):
return
- messages["xorg-driver-abi"] = "Package %s contains Xorg driver (%s) but no xorg-abi- dependencies" % (name, os.path.basename(path))
+ package_qa_add_message(messages, "xorg-driver-abi", "Package %s contains Xorg driver (%s) but no xorg-abi- dependencies" % (name, os.path.basename(path)))
QAPATHTEST[infodir] = "package_qa_check_infodir"
def package_qa_check_infodir(path, name, d, elf, messages):
@@ -593,7 +645,7 @@ def package_qa_check_infodir(path, name, d, elf, messages):
infodir = d.expand("${infodir}/dir")
if infodir in path:
- messages["infodir"] = "The /usr/share/info/dir file is not meant to be shipped in a particular package."
+ package_qa_add_message(messages, "infodir", "The /usr/share/info/dir file is not meant to be shipped in a particular package.")
QAPATHTEST[symlink-to-sysroot] = "package_qa_check_symlink_to_sysroot"
def package_qa_check_symlink_to_sysroot(path, name, d, elf, messages):
@@ -606,7 +658,7 @@ def package_qa_check_symlink_to_sysroot(path, name, d, elf, messages):
tmpdir = d.getVar('TMPDIR', True)
if target.startswith(tmpdir):
trimmed = path.replace(os.path.join (d.getVar("PKGDEST", True), name), "")
- messages["symlink-to-sysroot"] = "Symlink %s in %s points to TMPDIR" % (trimmed, name)
+ package_qa_add_message(messages, "symlink-to-sysroot", "Symlink %s in %s points to TMPDIR" % (trimmed, name))
def package_qa_check_license(workdir, d):
"""
@@ -620,11 +672,11 @@ def package_qa_check_license(workdir, d):
pn = d.getVar('PN', True)
if lic == "CLOSED":
- return True
+ return
if not lic_files:
- bb.error(pn + ": Recipe file does not have license file information (LIC_FILES_CHKSUM)")
- return False
+ package_qa_handle_error("license-checksum", pn + ": Recipe file does not have license file information (LIC_FILES_CHKSUM)", d)
+ return
srcdir = d.getVar('S', True)
@@ -632,10 +684,12 @@ def package_qa_check_license(workdir, d):
try:
(type, host, path, user, pswd, parm) = bb.fetch.decodeurl(url)
except bb.fetch.MalformedUrl:
- raise bb.build.FuncFailed( pn + ": LIC_FILES_CHKSUM contains an invalid URL: " + url)
+ package_qa_handle_error("license-checksum", pn + ": LIC_FILES_CHKSUM contains an invalid URL: " + url, d)
+ continue
srclicfile = os.path.join(srcdir, path)
if not os.path.isfile(srclicfile):
- raise bb.build.FuncFailed( pn + ": LIC_FILES_CHKSUM points to an invalid file: " + srclicfile)
+ package_qa_handle_error("license-checksum", pn + ": LIC_FILES_CHKSUM points to an invalid file: " + srclicfile, d)
+ continue
recipemd5 = parm.get('md5', '')
beginline, endline = 0, 0
@@ -670,8 +724,8 @@ def package_qa_check_license(workdir, d):
bb.note (pn + ": md5 checksum matched for ", url)
else:
if recipemd5:
- bb.error(pn + ": md5 data is not matching for ", url)
- bb.error(pn + ": The new md5 checksum is ", md5chksum)
+ msg = pn + ": The LIC_FILES_CHKSUM does not match for " + url
+ msg = msg + "\n" + pn + ": The new md5 checksum is " + md5chksum
if beginline:
if endline:
srcfiledesc = "%s (lines %d through to %d)" % (srclicfile, beginline, endline)
@@ -681,29 +735,26 @@ def package_qa_check_license(workdir, d):
srcfiledesc = "%s (ending on line %d)" % (srclicfile, endline)
else:
srcfiledesc = srclicfile
- bb.error(pn + ": Check if the license information has changed in %s to verify that the LICENSE value \"%s\" remains valid" % (srcfiledesc, lic))
- else:
- bb.error(pn + ": md5 checksum is not specified for ", url)
- bb.error(pn + ": The md5 checksum is ", md5chksum)
- sane = False
+ msg = msg + "\n" + pn + ": Check if the license information has changed in %s to verify that the LICENSE value \"%s\" remains valid" % (srcfiledesc, lic)
- return sane
+ else:
+ msg = pn + ": LIC_FILES_CHKSUM is not specified for " + url
+ msg = msg + "\n" + pn + ": The md5 checksum is " + md5chksum
+ package_qa_handle_error("license-checksum", msg, d)
def package_qa_check_staged(path,d):
"""
- Check staged la and pc files for sanity
- -e.g. installed being false
+ Check staged la and pc files for common problems like references to the work
+ directory.
- As this is run after every stage we should be able
- to find the one responsible for the errors easily even
- if we look at every .pc and .la file
+ As this is run after every stage we should be able to find the one
+ responsible for the errors easily even if we look at every .pc and .la file.
"""
sane = True
tmpdir = d.getVar('TMPDIR', True)
workdir = os.path.join(tmpdir, "work")
- installed = "installed=yes"
if bb.data.inherits_class("native", d) or bb.data.inherits_class("cross", d):
pkgconfigcheck = workdir
else:
@@ -731,7 +782,7 @@ def package_qa_check_staged(path,d):
return sane
# Walk over all files in a directory and call func
-def package_qa_walk(path, warnfuncs, errorfuncs, skip, package, d):
+def package_qa_walk(warnfuncs, errorfuncs, skip, package, d):
import oe.qa
#if this will throw an exception, then fix the dict above
@@ -744,7 +795,9 @@ def package_qa_walk(path, warnfuncs, errorfuncs, skip, package, d):
elf = oe.qa.ELFFile(path)
try:
elf.open()
- except:
+ except (IOError, ValueError):
+ # IOError can happen if the packaging control files disappear,
+ # ValueError means the file isn't an ELF.
elf = None
for func in warnfuncs:
func(path, package, d, elf, warnings)
@@ -756,15 +809,12 @@ def package_qa_walk(path, warnfuncs, errorfuncs, skip, package, d):
for e in errors:
package_qa_handle_error(e, errors[e], d)
- return len(errors) == 0
-
def package_qa_check_rdepends(pkg, pkgdest, skip, taskdeps, packages, d):
# Don't do this check for kernel/module recipes, there aren't too many debug/development
# packages and you can get false positives e.g. on kernel-module-lirc-dev
if bb.data.inherits_class("kernel", d) or bb.data.inherits_class("module-base", d):
- return True
+ return
- sane = True
if not "-dbg" in pkg and not "packagegroup-" in pkg and not "-image" in pkg:
localdata = bb.data.createCopy(d)
localdata.setVar('OVERRIDES', pkg)
@@ -778,10 +828,10 @@ def package_qa_check_rdepends(pkg, pkgdest, skip, taskdeps, packages, d):
for rdepend in rdepends:
if "-dbg" in rdepend and "debug-deps" not in skip:
error_msg = "%s rdepends on %s" % (pkg,rdepend)
- sane = package_qa_handle_error("debug-deps", error_msg, d)
+ package_qa_handle_error("debug-deps", error_msg, d)
if (not "-dev" in pkg and not "-staticdev" in pkg) and rdepend.endswith("-dev") and "dev-deps" not in skip:
error_msg = "%s rdepends on %s" % (pkg, rdepend)
- sane = package_qa_handle_error("dev-deps", error_msg, d)
+ package_qa_handle_error("dev-deps", error_msg, d)
if rdepend not in packages:
rdep_data = oe.packagedata.read_subpkgdata(rdepend, d)
if rdep_data and 'PN' in rdep_data and rdep_data['PN'] in taskdeps:
@@ -799,20 +849,21 @@ def package_qa_check_rdepends(pkg, pkgdest, skip, taskdeps, packages, d):
if rdep_data and 'PN' in rdep_data and rdep_data['PN'] in taskdeps:
continue
error_msg = "%s rdepends on %s, but it isn't a build dependency?" % (pkg, rdepend)
- sane = package_qa_handle_error("build-deps", error_msg, d)
+ package_qa_handle_error("build-deps", error_msg, d)
if "file-rdeps" not in skip:
ignored_file_rdeps = set(['/bin/sh', '/usr/bin/env', 'rtld(GNU_HASH)'])
if bb.data.inherits_class('nativesdk', d):
ignored_file_rdeps |= set(['/bin/bash', '/usr/bin/perl'])
# For Saving the FILERDEPENDS
- filerdepends = set()
+ filerdepends = {}
rdep_data = oe.packagedata.read_subpkgdata(pkg, d)
for key in rdep_data:
if key.startswith("FILERDEPENDS_"):
for subkey in rdep_data[key].split():
- filerdepends.add(subkey)
- filerdepends -= ignored_file_rdeps
+ if subkey not in ignored_file_rdeps:
+ # We already know it starts with FILERDEPENDS_
+ filerdepends[subkey] = key[13:]
if filerdepends:
next = rdepends
@@ -844,44 +895,36 @@ def package_qa_check_rdepends(pkg, pkgdest, skip, taskdeps, packages, d):
# case there is a RDEPENDS_pkg = "python" in the recipe.
for py in [ d.getVar('MLPREFIX', True) + "python", "python" ]:
if py in done:
- filerdepends.discard("/usr/bin/python")
+ filerdepends.pop("/usr/bin/python",None)
done.remove(py)
for rdep in done:
# For Saving the FILERPROVIDES, RPROVIDES and FILES_INFO
- rdep_rprovides = set()
rdep_data = oe.packagedata.read_subpkgdata(rdep, d)
for key in rdep_data:
if key.startswith("FILERPROVIDES_") or key.startswith("RPROVIDES_"):
for subkey in rdep_data[key].split():
- rdep_rprovides.add(subkey)
+ filerdepends.pop(subkey,None)
# Add the files list to the rprovides
if key == "FILES_INFO":
# Use eval() to make it as a dict
for subkey in eval(rdep_data[key]):
- rdep_rprovides.add(subkey)
- filerdepends -= rdep_rprovides
+ filerdepends.pop(subkey,None)
if not filerdepends:
# Break if all the file rdepends are met
break
- else:
- # Clear it for the next loop
- rdep_rprovides.clear()
if filerdepends:
- error_msg = "%s requires %s, but no providers in its RDEPENDS" % \
- (pkg, ', '.join(str(e) for e in filerdepends))
- sane = package_qa_handle_error("file-rdeps", error_msg, d)
-
- return sane
+ for key in filerdepends:
+ error_msg = "%s contained in package %s requires %s, but no providers found in its RDEPENDS" % \
+ (filerdepends[key],pkg, key)
+ package_qa_handle_error("file-rdeps", error_msg, d)
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:
@@ -890,25 +933,95 @@ def package_qa_check_deps(pkg, pkgdest, skip, d):
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
+ package_qa_handle_error("dep-cmp", error_msg, d)
- 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
+ check_valid_deps('RDEPENDS')
+ check_valid_deps('RRECOMMENDS')
+ check_valid_deps('RSUGGESTS')
+ check_valid_deps('RPROVIDES')
+ check_valid_deps('RREPLACES')
+ check_valid_deps('RCONFLICTS')
+
+QAPATHTEST[expanded-d] = "package_qa_check_expanded_d"
+def package_qa_check_expanded_d(path,name,d,elf,messages):
+ """
+ Check for the expanded D (${D}) value in pkg_* and FILES
+ variables, warn the user to use it correctly.
+ """
+ sane = True
+ expanded_d = d.getVar('D',True)
+
+ # Get packages for current recipe and iterate
+ packages = d.getVar('PACKAGES', True).split(" ")
+ for pak in packages:
+ # Go through all variables and check if expanded D is found, warn the user accordingly
+ for var in 'FILES','pkg_preinst', 'pkg_postinst', 'pkg_prerm', 'pkg_postrm':
+ bbvar = d.getVar(var + "_" + pak, False)
+ if bbvar:
+ # Bitbake expands ${D} within bbvar during the previous step, so we check for its expanded value
+ if expanded_d in bbvar:
+ if var == 'FILES':
+ package_qa_add_message(messages, "expanded-d", "FILES in %s recipe should not contain the ${D} variable as it references the local build directory not the target filesystem, best solution is to remove the ${D} reference" % pak)
+ sane = False
+ else:
+ package_qa_add_message(messages, "expanded-d", "%s in %s recipe contains ${D}, it should be replaced by $D instead" % (var, pak))
+ sane = False
return sane
+def package_qa_check_encoding(keys, encode, d):
+ def check_encoding(key,enc):
+ sane = True
+ value = d.getVar(key, True)
+ if value:
+ try:
+ s = unicode(value, enc)
+ except UnicodeDecodeError as e:
+ error_msg = "%s has non %s characters" % (key,enc)
+ sane = False
+ package_qa_handle_error("invalid-chars", error_msg, d)
+ return sane
+
+ for key in keys:
+ sane = check_encoding(key, encode)
+ if not sane:
+ break
+
+HOST_USER_UID := "${@os.getuid()}"
+HOST_USER_GID := "${@os.getgid()}"
+
+QAPATHTEST[host-user-contaminated] = "package_qa_check_host_user"
+def package_qa_check_host_user(path, name, d, elf, messages):
+ """Check for paths outside of /home which are owned by the user running bitbake."""
+
+ if not os.path.lexists(path):
+ return
+
+ dest = d.getVar('PKGDEST', True)
+ pn = d.getVar('PN', True)
+ home = os.path.join(dest, 'home')
+ if path == home or path.startswith(home + os.sep):
+ return
+
+ try:
+ stat = os.lstat(path)
+ except OSError as exc:
+ import errno
+ if exc.errno != errno.ENOENT:
+ raise
+ else:
+ rootfs_path = path[len(dest):]
+ check_uid = int(d.getVar('HOST_USER_UID', True))
+ if stat.st_uid == check_uid:
+ package_qa_add_message(messages, "host-user-contaminated", "%s: %s is owned by uid %d, which is the same as the user running bitbake. This may be due to host contamination" % (pn, rootfs_path, check_uid))
+ return False
+
+ check_gid = int(d.getVar('HOST_USER_GID', True))
+ if stat.st_gid == check_gid:
+ package_qa_add_message(messages, "host-user-contaminated", "%s: %s is owned by gid %d, which is the same as the user running bitbake. This may be due to host contamination" % (pn, rootfs_path, check_gid))
+ return False
+ return True
+
# The PACKAGE FUNC to scan each package
python do_package_qa () {
import subprocess
@@ -918,6 +1031,9 @@ python do_package_qa () {
bb.build.exec_func("read_subpackage_metadata", d)
+ # Check non UTF-8 characters on recipe's metadata
+ package_qa_check_encoding(['DESCRIPTION', 'SUMMARY', 'LICENSE', 'SECTION'], 'utf-8', d)
+
logdir = d.getVar('T', True)
pkg = d.getVar('PN', True)
@@ -943,12 +1059,12 @@ python do_package_qa () {
# Scan the packages...
pkgdest = d.getVar('PKGDEST', True)
- packages = d.getVar('PACKAGES', True)
+ packages = set((d.getVar('PACKAGES', True) or '').split())
cpath = oe.cachedpath.CachedPath()
global pkgfiles
pkgfiles = {}
- for pkg in (packages or "").split():
+ for pkg in packages:
pkgfiles[pkg] = []
for walkroot, dirs, files in cpath.walk(pkgdest + "/" + pkg):
for file in files:
@@ -969,10 +1085,7 @@ python do_package_qa () {
taskdeps.add(taskdepdata[dep][0])
g = globals()
- walk_sane = True
- rdepends_sane = True
- deps_sane = True
- for package in packages.split():
+ for package in packages:
skip = (d.getVar('INSANE_SKIP_' + package, True) or "").split()
if skip:
bb.note("Package %s skipping QA tests: %s" % (package, str(skip)))
@@ -993,26 +1106,24 @@ python do_package_qa () {
# Check package name
if not pkgname_pattern.match(package):
package_qa_handle_error("pkgname",
- "%s doesn't match the [a-z0-9.+-]+ regex\n" % package, d)
+ "%s doesn't match the [a-z0-9.+-]+ regex" % package, d)
path = "%s/%s" % (pkgdest, package)
- if not package_qa_walk(path, warnchecks, errorchecks, skip, package, d):
- walk_sane = False
- if not package_qa_check_rdepends(package, pkgdest, skip, taskdeps, packages, d):
- rdepends_sane = False
- if not package_qa_check_deps(package, pkgdest, skip, d):
- deps_sane = False
+ package_qa_walk(warnchecks, errorchecks, skip, package, d)
+ package_qa_check_rdepends(package, pkgdest, skip, taskdeps, packages, d)
+ package_qa_check_deps(package, pkgdest, skip, d)
if 'libdir' in d.getVar("ALL_QA", True).split():
package_qa_check_libdir(d)
qa_sane = d.getVar("QA_SANE", True)
- if not walk_sane or not rdepends_sane or not deps_sane or not qa_sane:
+ if not qa_sane:
bb.fatal("QA run found fatal errors. Please consider fixing them.")
bb.note("DONE with PACKAGE QA")
}
+do_package_qa[vardepsexclude] = "BB_TASKDEPDATA"
do_package_qa[rdeptask] = "do_packagedata"
addtask do_package_qa after do_packagedata do_package before do_build
@@ -1027,7 +1138,7 @@ addtask do_package_qa_setscene
python do_qa_staging() {
bb.note("QA checking staging")
- if not package_qa_check_staged(d.expand('${SYSROOT_DESTDIR}${STAGING_LIBDIR}'), d):
+ if not package_qa_check_staged(d.expand('${SYSROOT_DESTDIR}${libdir}'), d):
bb.fatal("QA staging was broken by the package built above")
}
@@ -1047,7 +1158,7 @@ python do_qa_configure() {
if "config.log" in files:
if subprocess.call(statement, shell=True) == 0:
bb.fatal("""This autoconf log indicates errors, it looked at host include and/or library paths while determining system capabilities.
-Rerun configure task after fixing this. The path was '%s'""" % root)
+Rerun configure task after fixing this.""")
if "configure.ac" in files:
configs.append(os.path.join(root,"configure.ac"))
@@ -1079,8 +1190,7 @@ Missing inherit gettext?""" % (gt, config))
# Check license variables
###########################################################################
- if not package_qa_check_license(workdir, d):
- bb.fatal("Licensing Error: LIC_FILES_CHKSUM does not match, please fix")
+ package_qa_check_license(workdir, d)
###########################################################################
# Check unrecognised configure options (with a white list)
@@ -1102,7 +1212,30 @@ Missing inherit gettext?""" % (gt, config))
package_qa_handle_error("unknown-configure-option", error_msg, d)
except subprocess.CalledProcessError:
pass
+
+ # Check invalid PACKAGECONFIG
+ pkgconfig = (d.getVar("PACKAGECONFIG", True) or "").split()
+ if pkgconfig:
+ pkgconfigflags = d.getVarFlags("PACKAGECONFIG") or {}
+ for pconfig in pkgconfig:
+ if pconfig not in pkgconfigflags:
+ pn = d.getVar('PN', True)
+ error_msg = "%s: invalid PACKAGECONFIG: %s" % (pn, pconfig)
+ package_qa_handle_error("invalid-packageconfig", error_msg, d)
+
+ qa_sane = d.getVar("QA_SANE", True)
+ if not qa_sane:
+ bb.fatal("Fatal QA errors found, failing task.")
}
+
+python do_qa_unpack() {
+ bb.note("Checking has ${S} been created")
+
+ s_dir = d.getVar('S', True)
+ if not os.path.exists(s_dir):
+ bb.warn('%s: the directory %s (%s) pointed to by the S variable doesn\'t exist - please set S within the recipe to point to where the source has been unpacked to' % (d.getVar('PN', True), d.getVar('S', False), s_dir))
+}
+
# The Staging Func, to check all staging
#addtask qa_staging after do_populate_sysroot before do_build
do_populate_sysroot[postfuncs] += "do_qa_staging "
@@ -1112,10 +1245,13 @@ do_populate_sysroot[postfuncs] += "do_qa_staging "
#addtask qa_configure after do_configure before do_compile
do_configure[postfuncs] += "do_qa_configure "
+# Check does S exist.
+do_unpack[postfuncs] += "do_qa_unpack"
+
python () {
tests = d.getVar('ALL_QA', True).split()
if "desktop" in tests:
- d.appendVar("PACKAGE_DEPENDS", "desktop-file-utils-native")
+ d.appendVar("PACKAGE_DEPENDS", " desktop-file-utils-native")
###########################################################################
# Check various variables
@@ -1134,9 +1270,6 @@ python () {
msg += "%s\n" % extrapaths
bb.warn(msg)
- if d.getVar('do_stage', True) is not None:
- bb.fatal("Legacy staging found for %s as it has a do_stage function. This will need conversion to a do_install or often simply removal to work with OE-core" % d.getVar("FILE", True))
-
overrides = d.getVar('OVERRIDES', True).split(':')
pn = d.getVar('PN', True)
if pn in overrides:
@@ -1148,10 +1281,18 @@ python () {
for dep in (d.getVar('QADEPENDS', True) or "").split():
d.appendVarFlag('do_package_qa', 'depends', " %s:do_populate_sysroot" % dep)
for var in 'RDEPENDS', 'RRECOMMENDS', 'RSUGGESTS', 'RCONFLICTS', 'RPROVIDES', 'RREPLACES', 'FILES', 'pkg_preinst', 'pkg_postinst', 'pkg_prerm', 'pkg_postrm', 'ALLOW_EMPTY':
- if d.getVar(var):
+ if d.getVar(var, False):
issues.append(var)
+
+ fakeroot_tests = d.getVar('FAKEROOT_QA', True).split()
+ if set(tests) & set(fakeroot_tests):
+ d.setVarFlag('do_package_qa', 'fakeroot', '1')
+ d.appendVarFlag('do_package_qa', 'depends', ' virtual/fakeroot-native:do_populate_sysroot')
else:
d.setVarFlag('do_package_qa', 'rdeptask', '')
for i in issues:
package_qa_handle_error("pkgvarcheck", "%s: Variable %s is set as not being package specific, please fix this." % (d.getVar("FILE", True), i), d)
+ qa_sane = d.getVar("QA_SANE", True)
+ if not qa_sane:
+ bb.fatal("Fatal QA errors found, failing task.")
}