summaryrefslogtreecommitdiffstats
path: root/meta/classes/insane.bbclass
diff options
context:
space:
mode:
Diffstat (limited to 'meta/classes/insane.bbclass')
-rw-r--r--meta/classes/insane.bbclass183
1 files changed, 92 insertions, 91 deletions
diff --git a/meta/classes/insane.bbclass b/meta/classes/insane.bbclass
index 9bb999324b..2ef5527dac 100644
--- a/meta/classes/insane.bbclass
+++ b/meta/classes/insane.bbclass
@@ -8,28 +8,25 @@
8# -Check the RUNTIME path for the $TMPDIR 8# -Check the RUNTIME path for the $TMPDIR
9# -Check if .la files wrongly point to workdir 9# -Check if .la files wrongly point to workdir
10# -Check if .pc files wrongly point to workdir 10# -Check if .pc files wrongly point to workdir
11# -Check if packages contains .debug directories or .so files where they should be in -dev or -dbg 11# -Check if packages contains .debug directories or .so files
12# where they should be in -dev or -dbg
12# -Check if config.log contains traces to broken autoconf tests 13# -Check if config.log contains traces to broken autoconf tests
13#
14 14
15 15
16# 16#
17# We need to have the scanelf utility as soon as 17# We need to have the scanelf utility as soon as
18# possible and this is contained within the pax-utils-native 18# possible and this is contained within the pax-utils-native.
19# The package.bbclass can help us here.
19# 20#
20
21
22# We play a special package function
23inherit package 21inherit package
24PACKAGE_DEPENDS += "pax-utils-native desktop-file-utils-native" 22PACKAGE_DEPENDS += "pax-utils-native desktop-file-utils-native"
25#PACKAGE_DEPENDS += chrpath-native"
26PACKAGEFUNCS += " do_package_qa " 23PACKAGEFUNCS += " do_package_qa "
27 24
28 25
29# 26#
30# dictionary for elf headers 27# dictionary for elf headers
31# 28#
32# feel free to add and correct. 29# feel free to add and correct.
33# 30#
34# TARGET_OS TARGET_ARCH MACHINE, OSABI, ABIVERSION, Little Endian, 32bit? 31# TARGET_OS TARGET_ARCH MACHINE, OSABI, ABIVERSION, Little Endian, 32bit?
35def package_qa_get_machine_dict(): 32def package_qa_get_machine_dict():
@@ -57,8 +54,12 @@ def package_qa_get_machine_dict():
57 "arm" : ( 40, 97, 0, True, True), 54 "arm" : ( 40, 97, 0, True, True),
58 "armeb": ( 40, 97, 0, False, True), 55 "armeb": ( 40, 97, 0, False, True),
59 "powerpc": ( 20, 0, 0, False, True), 56 "powerpc": ( 20, 0, 0, False, True),
57 "i386": ( 3, 0, 0, True, True),
58 "i486": ( 3, 0, 0, True, True),
59 "i586": ( 3, 0, 0, True, True),
60 "i686": ( 3, 0, 0, True, True),
60 "mipsel": ( 8, 0, 0, True, True), 61 "mipsel": ( 8, 0, 0, True, True),
61 "avr32": (6317, 0, 0, False, True), 62 "avr32": (6317, 0, 0, False, True),
62 }, 63 },
63 "uclinux-uclibc" : { 64 "uclinux-uclibc" : {
64 "bfin": ( 106, 0, 0, True, True), 65 "bfin": ( 106, 0, 0, True, True),
@@ -71,7 +72,7 @@ def package_qa_get_machine_dict():
71 "arm" : (40, 0, 0, True, True), 72 "arm" : (40, 0, 0, True, True),
72 "armeb" : (40, 0, 0, False, True), 73 "armeb" : (40, 0, 0, False, True),
73 }, 74 },
74 75
75 } 76 }
76 77
77# factory for a class, embedded in a method 78# factory for a class, embedded in a method
@@ -98,11 +99,10 @@ def package_qa_get_elf(path, bits32):
98 ELFDATA2LSB = 1 99 ELFDATA2LSB = 1
99 ELFDATA2MSB = 2 100 ELFDATA2MSB = 2
100 101
101 def my_assert(expectation, result): 102 def my_assert(self, expectation, result):
102 if not expectation == result: 103 if not expectation == result:
103 #print "'%x','%x'" % (ord(expectation), ord(result)) 104 #print "'%x','%x' %s" % (ord(expectation), ord(result), self.name)
104 raise Exception("This does not work as expected") 105 raise Exception("This does not work as expected")
105 my_assert = staticmethod(my_assert)
106 106
107 def __init__(self, name): 107 def __init__(self, name):
108 self.name = name 108 self.name = name
@@ -111,16 +111,16 @@ def package_qa_get_elf(path, bits32):
111 self.file = file(self.name, "r") 111 self.file = file(self.name, "r")
112 self.data = self.file.read(ELFFile.EI_NIDENT+4) 112 self.data = self.file.read(ELFFile.EI_NIDENT+4)
113 113
114 ELFFile.my_assert(len(self.data), ELFFile.EI_NIDENT+4) 114 self.my_assert(len(self.data), ELFFile.EI_NIDENT+4)
115 ELFFile.my_assert(self.data[0], chr(0x7f) ) 115 self.my_assert(self.data[0], chr(0x7f) )
116 ELFFile.my_assert(self.data[1], 'E') 116 self.my_assert(self.data[1], 'E')
117 ELFFile.my_assert(self.data[2], 'L') 117 self.my_assert(self.data[2], 'L')
118 ELFFile.my_assert(self.data[3], 'F') 118 self.my_assert(self.data[3], 'F')
119 if bits32 : 119 if bits32 :
120 ELFFile.my_assert(self.data[ELFFile.EI_CLASS], chr(ELFFile.ELFCLASS32)) # only 32 bits 120 self.my_assert(self.data[ELFFile.EI_CLASS], chr(ELFFile.ELFCLASS32))
121 else: 121 else:
122 ELFFile.my_assert(self.data[ELFFile.EI_CLASS], chr(ELFFile.ELFCLASS64)) # only 64 bits 122 self.my_assert(self.data[ELFFile.EI_CLASS], chr(ELFFile.ELFCLASS64))
123 ELFFile.my_assert(self.data[ELFFile.EI_VERSION], chr(ELFFile.EV_CURRENT) ) 123 self.my_assert(self.data[ELFFile.EI_VERSION], chr(ELFFile.EV_CURRENT) )
124 124
125 self.sex = self.data[ELFFile.EI_DATA] 125 self.sex = self.data[ELFFile.EI_DATA]
126 if self.sex == chr(ELFFile.ELFDATANONE): 126 if self.sex == chr(ELFFile.ELFDATANONE):
@@ -156,8 +156,6 @@ def package_qa_get_elf(path, bits32):
156 return ELFFile(path) 156 return ELFFile(path)
157 157
158 158
159#
160#
161# Known Error classes 159# Known Error classes
162# 0 - non dev contains .so 160# 0 - non dev contains .so
163# 1 - package contains a dangerous RPATH 161# 1 - package contains a dangerous RPATH
@@ -166,10 +164,11 @@ def package_qa_get_elf(path, bits32):
166# 4 - wrong architecture 164# 4 - wrong architecture
167# 5 - .la contains installed=yes or reference to the workdir 165# 5 - .la contains installed=yes or reference to the workdir
168# 6 - .pc contains reference to /usr/include or workdir 166# 6 - .pc contains reference to /usr/include or workdir
169# 167# 7 - the desktop file is not valid
170# 168# 8 - .la contains reference to the workdir
171 169
172def package_qa_clean_path(path,d): 170def package_qa_clean_path(path,d):
171 """ Remove the common prefix from the path. In this case it is the TMPDIR"""
173 import bb 172 import bb
174 return path.replace(bb.data.getVar('TMPDIR',d,True),"") 173 return path.replace(bb.data.getVar('TMPDIR',d,True),"")
175 174
@@ -179,14 +178,15 @@ def package_qa_make_fatal_error(error_class, name, path,d):
179 178
180 TODO: Load a whitelist of known errors 179 TODO: Load a whitelist of known errors
181 """ 180 """
182 if error_class == 0: 181 return not error_class in [0, 5, 7, 8]
183 return False
184 else:
185 return True
186 182
187def package_qa_write_error(error_class, name, path, d): 183def package_qa_write_error(error_class, name, path, d):
184 """
185 Log the error
186 """
188 import bb, os 187 import bb, os
189 if not bb.data.getVar('QA_LOG', d): 188 if not bb.data.getVar('QA_LOG', d):
189 bb.note("a QA error occured but will not be logged because QA_LOG is not set")
190 return 190 return
191 191
192 ERROR_NAMES =[ 192 ERROR_NAMES =[
@@ -197,44 +197,45 @@ def package_qa_write_error(error_class, name, path, d):
197 "wrong architecture", 197 "wrong architecture",
198 "evil hides inside the .la", 198 "evil hides inside the .la",
199 "evil hides inside the .pc", 199 "evil hides inside the .pc",
200 "the desktop file is not valid",
201 ".la contains reference to the workdir",
200 ] 202 ]
201 203
202
203 log_path = os.path.join( bb.data.getVar('T', d, True), "log.qa_package" ) 204 log_path = os.path.join( bb.data.getVar('T', d, True), "log.qa_package" )
204 f = file( log_path, "a+") 205 f = file( log_path, "a+")
205 print >> f, "%s, %s, %s" % (ERROR_NAMES[error_class], name, package_qa_clean_path(path,d)) 206 print >> f, "%s, %s, %s" % \
207 (ERROR_NAMES[error_class], name, package_qa_clean_path(path,d))
206 f.close() 208 f.close()
207 209
210def package_qa_handle_error(error_class, error_msg, name, path, d):
211 import bb
212 bb.error("QA Issue: %s" % error_msg)
213 package_qa_write_error(error_class, name, path, d)
214 return not package_qa_make_fatal_error(error_class, name, path, d)
208 215
209def package_qa_check_rpath(file,name,d): 216def package_qa_check_rpath(file,name,d):
210 """ 217 """
211 Check for dangerous RPATHs 218 Check for dangerous RPATHs
212 """ 219 """
213 import bb, os 220 import bb, os
221 sane = True
214 scanelf = os.path.join(bb.data.getVar('STAGING_BINDIR_NATIVE',d,True),'scanelf') 222 scanelf = os.path.join(bb.data.getVar('STAGING_BINDIR_NATIVE',d,True),'scanelf')
215 #chrpath = os.path.join(bb.data.getVar('STAGING_BINDIR_NATIVE',d,True),'chrpath')
216 bad_dir = bb.data.getVar('TMPDIR', d, True) + "/work" 223 bad_dir = bb.data.getVar('TMPDIR', d, True) + "/work"
217 bad_dir_test = bb.data.getVar('TMPDIR', d, True) 224 bad_dir_test = bb.data.getVar('TMPDIR', d, True)
218 if not os.path.exists(scanelf): 225 if not os.path.exists(scanelf):
219 bb.fatal("Can not check RPATH, scanelf (part of pax-utils-native) not found") 226 bb.fatal("Can not check RPATH, scanelf (part of pax-utils-native) not found")
220 #if not os.path.exists(chrpath): 227
221 # bb.fatal("Can not fix RPATH, chrpath (part of chrpath-native) not found")
222 if not bad_dir in bb.data.getVar('WORKDIR', d, True): 228 if not bad_dir in bb.data.getVar('WORKDIR', d, True):
223 bb.fatal("This class assumed that WORKDIR is ${TMPDIR}/work... Not doing any check") 229 bb.fatal("This class assumed that WORKDIR is ${TMPDIR}/work... Not doing any check")
224 230
225 #bb.note("%s -B -F%%r#F %s" % (scanelf,file))
226 output = os.popen("%s -B -F%%r#F '%s'" % (scanelf,file)) 231 output = os.popen("%s -B -F%%r#F '%s'" % (scanelf,file))
227 txt = output.readline().split() 232 txt = output.readline().split()
228 #bb.note("???%s???" % bad_dir_test)
229 for line in txt: 233 for line in txt:
230 #bb.note("===%s===" % line)
231 if bad_dir in line: 234 if bad_dir in line:
232 package_qa_write_error( 1, name, file, d) 235 error_msg = "package %s contains bad RPATH %s in file %s" % (name, line, file)
233 bb.error("QA Issue package %s contains bad RPATH %s in file %s" % (name, line, file)) 236 sane = package_qa_handle_error(1, error_msg, name, file, d)
234 #bb.note("Fixing RPATH for you in %s" % file) 237
235 #os.popen("%s -r /lib %s" % (chrpath,file)) 238 return sane
236 #return False
237 return True
238 239
239def package_qa_check_devdbg(path, name,d): 240def package_qa_check_devdbg(path, name,d):
240 """ 241 """
@@ -247,17 +248,15 @@ def package_qa_check_devdbg(path, name,d):
247 248
248 if not "-dev" in name: 249 if not "-dev" in name:
249 if path[-3:] == ".so" and os.path.islink(path): 250 if path[-3:] == ".so" and os.path.islink(path):
250 package_qa_write_error( 0, name, path, d ) 251 error_msg = "non -dev package contains symlink .so: %s path '%s'" % \
251 bb.error("QA Issue: non -dev package contains symlink .so: %s path '%s'" % (name, package_qa_clean_path(path,d))) 252 (name, package_qa_clean_path(path,d))
252 if package_qa_make_fatal_error( 0, name, path, d ): 253 sane = package_qa_handle_error(0, error_msg, name, path, d)
253 sane = False
254 254
255 if not "-dbg" in name: 255 if not "-dbg" in name:
256 if '.debug' in path: 256 if '.debug' in path:
257 package_qa_write_error( 3, name, path, d ) 257 error_msg = "non debug package contains .debug directory: %s path %s" % \
258 bb.error("QA Issue: non debug package contains .debug directory: %s path %s" % (name, package_qa_clean_path(path,d))) 258 (name, package_qa_clean_path(path,d))
259 if package_qa_make_fatal_error( 3, name, path, d ): 259 sane = package_qa_handle_error(3, error_msg, name, path, d)
260 sane = False
261 260
262 return sane 261 return sane
263 262
@@ -273,9 +272,10 @@ def package_qa_check_arch(path,name,d):
273 Check if archs are compatible 272 Check if archs are compatible
274 """ 273 """
275 import bb, os 274 import bb, os
275 sane = True
276 target_os = bb.data.getVar('TARGET_OS', d, True) 276 target_os = bb.data.getVar('TARGET_OS', d, True)
277 target_arch = bb.data.getVar('TARGET_ARCH', d, True) 277 target_arch = bb.data.getVar('TARGET_ARCH', d, True)
278 278
279 # FIXME: Cross package confuse this check, so just skip them 279 # FIXME: Cross package confuse this check, so just skip them
280 if bb.data.inherits_class('cross', d) or bb.data.inherits_class('sdk', d): 280 if bb.data.inherits_class('cross', d) or bb.data.inherits_class('sdk', d):
281 return True 281 return True
@@ -286,29 +286,24 @@ def package_qa_check_arch(path,name,d):
286 return True 286 return True
287 287
288 #if this will throw an exception, then fix the dict above 288 #if this will throw an exception, then fix the dict above
289 (machine, osabi, abiversion, littleendian, bits32) = package_qa_get_machine_dict()[target_os][target_arch] 289 (machine, osabi, abiversion, littleendian, bits32) \
290 = package_qa_get_machine_dict()[target_os][target_arch]
290 elf = package_qa_get_elf(path, bits32) 291 elf = package_qa_get_elf(path, bits32)
291 try: 292 try:
292 elf.open() 293 elf.open()
293 except: 294 except:
294 # just for debbugging to check the parser, remove once convinced...
295 return True 295 return True
296 296
297 # Check the architecture and endiannes of the binary
297 if not machine == elf.machine(): 298 if not machine == elf.machine():
298 bb.error("Architecture did not match (%d to %d) on %s" %(machine, elf.machine(), package_qa_clean_path(path,d))) 299 error_msg = "Architecture did not match (%d to %d) on %s" % \
299 return not package_qa_make_fatal_error( 4, name, path, d ) 300 (machine, elf.machine(), package_qa_clean_path(path,d))
301 sane = package_qa_handle_error(4, error_msg, name, path, d)
300 elif not littleendian == elf.isLittleEndian(): 302 elif not littleendian == elf.isLittleEndian():
301 bb.error("Endiannes did not match (%d to %d) on %s" % (littleendian, elf.isLittleEndian(), package_qa_clean_path(path,d))) 303 error_msg = "Endiannes did not match (%d to %d) on %s" % \
302 return not package_qa_make_fatal_error( 4, name, path, d ) 304 (littleendian, elf.isLittleEndian(), package_qa_clean_path(path,d))
303 305 sane = package_qa_handle_error(4, error_msg, name, path, d)
304 return True
305 306
306def package_qa_check_pcla(path,name,d):
307 """
308 .pc and .la files should not point to the WORKDIR
309 """
310 sane = True
311 # TODO
312 return sane 307 return sane
313 308
314def package_qa_check_desktop(path, name, d): 309def package_qa_check_desktop(path, name, d):
@@ -316,12 +311,14 @@ def package_qa_check_desktop(path, name, d):
316 Run all desktop files through desktop-file-validate. 311 Run all desktop files through desktop-file-validate.
317 """ 312 """
318 import bb, os 313 import bb, os
314 sane = True
319 if path.endswith(".desktop"): 315 if path.endswith(".desktop"):
320 output = os.popen("desktop-file-validate %s" % path) 316 output = os.popen("desktop-file-validate %s" % path)
321 # This only produces output on errors 317 # This only produces output on errors
322 for l in output: 318 for l in output:
323 bb.error(l.strip()) 319 sane = package_qa_handle_error(7, l.strip(), name, path, d)
324 return True 320
321 return sane
325 322
326def package_qa_check_staged(path,d): 323def package_qa_check_staged(path,d):
327 """ 324 """
@@ -335,12 +332,14 @@ def package_qa_check_staged(path,d):
335 import os, bb 332 import os, bb
336 333
337 sane = True 334 sane = True
338 workdir = os.path.join(bb.data.getVar('TMPDIR', d, True), "work") 335 tmpdir = bb.data.getVar('TMPDIR', d, True)
336 workdir = os.path.join(tmpdir, "work")
339 337
340 if bb.data.inherits_class("native", d): 338 installed = "installed=yes"
341 installed = "installed=no" 339 if bb.data.inherits_class("native", d) or bb.data.inherits_class("cross", d):
340 pkgconfigcheck = workdir
342 else: 341 else:
343 installed = "installed=yes" 342 pkgconfigcheck = tmpdir
344 343
345 # find all .la and .pc files 344 # find all .la and .pc files
346 # read the content 345 # read the content
@@ -350,20 +349,19 @@ def package_qa_check_staged(path,d):
350 path = os.path.join(root,file) 349 path = os.path.join(root,file)
351 if file[-2:] == "la": 350 if file[-2:] == "la":
352 file_content = open(path).read() 351 file_content = open(path).read()
353 if installed in file_content: 352 # Don't check installed status for native/cross packages
354 bb.error("QA issue: %s failed sanity test (installed)" % file ) 353 if not bb.data.inherits_class("native", d) and not bb.data.inherits_class("cross", d):
355 if package_qa_make_fatal_error( 5, "staging", path, d): 354 if installed in file_content:
356 sane = True 355 error_msg = "%s failed sanity test (installed) in path %s" % (file,root)
356 sane = package_qa_handle_error(5, error_msg, "staging", path, d)
357 if workdir in file_content: 357 if workdir in file_content:
358 bb.error("QA issue: %s failed sanity test (reference to workdir)" % file ) 358 error_msg = "%s failed sanity test (workdir) in path %s" % (file,root)
359 if package_qa_make_fatal_error( 5, "staging", path, d): 359 sane = package_qa_handle_error(8, error_msg, "staging", path, d)
360 sane = True
361 elif file[-2:] == "pc": 360 elif file[-2:] == "pc":
362 file_content = open(path).read() 361 file_content = open(path).read()
363 if workdir in file_content: 362 if pkgconfigcheck in file_content:
364 bb.error("QA issue: %s failed sanity test (reference to workdir)" % file ) 363 error_msg = "%s failed sanity test (tmpdir) in path %s" % (file,root)
365 if package_qa_make_fatal_error( 6, "staging", path, d): 364 sane = package_qa_handle_error(6, error_msg, "staging", path, d)
366 sane = False
367 365
368 return sane 366 return sane
369 367
@@ -381,7 +379,6 @@ def package_qa_walk(path, funcs, package,d):
381 379
382 return sane 380 return sane
383 381
384
385def package_qa_check_rdepends(pkg, workdir, d): 382def package_qa_check_rdepends(pkg, workdir, d):
386 import bb 383 import bb
387 sane = True 384 sane = True
@@ -413,10 +410,8 @@ def package_qa_check_rdepends(pkg, workdir, d):
413 # Now do the sanity check!!! 410 # Now do the sanity check!!!
414 for rdepend in rdepends: 411 for rdepend in rdepends:
415 if "-dbg" in rdepend: 412 if "-dbg" in rdepend:
416 package_qa_write_error( 2, pkgname, rdepend, d ) 413 error_msg = "%s rdepends on %s" % (pkgname,rdepend)
417 bb.error("QA issue: %s rdepends on %s" % (pkgname,rdepend)) 414 sane = package_qa_handle_error(2, error_msg, pkgname, rdepend, d)
418 if package_qa_make_fatal_error( 2, pkgname, rdepend, d ):
419 sane = False
420 415
421 return sane 416 return sane
422 417
@@ -430,6 +425,9 @@ python do_package_qa () {
430 if not packages: 425 if not packages:
431 return 426 return
432 427
428 checks = [package_qa_check_rpath, package_qa_check_devdbg,
429 package_qa_check_perm, package_qa_check_arch,
430 package_qa_check_desktop]
433 walk_sane = True 431 walk_sane = True
434 rdepends_sane = True 432 rdepends_sane = True
435 for package in packages.split(): 433 for package in packages.split():
@@ -439,7 +437,7 @@ python do_package_qa () {
439 437
440 bb.note("Checking Package: %s" % package) 438 bb.note("Checking Package: %s" % package)
441 path = "%s/install/%s" % (workdir, package) 439 path = "%s/install/%s" % (workdir, package)
442 if not package_qa_walk(path, [package_qa_check_rpath, package_qa_check_devdbg, package_qa_check_perm, package_qa_check_arch, package_qa_check_desktop], package, d): 440 if not package_qa_walk(path, checks, package, d):
443 walk_sane = False 441 walk_sane = False
444 if not package_qa_check_rdepends(package, workdir, d): 442 if not package_qa_check_rdepends(package, workdir, d):
445 rdepends_sane = False 443 rdepends_sane = False
@@ -465,7 +463,10 @@ python do_qa_configure() {
465 bb.note("Checking sanity of the config.log file") 463 bb.note("Checking sanity of the config.log file")
466 import os 464 import os
467 for root, dirs, files in os.walk(bb.data.getVar('WORKDIR', d, True)): 465 for root, dirs, files in os.walk(bb.data.getVar('WORKDIR', d, True)):
466 statement = "grep 'CROSS COMPILE Badness:' %s > /dev/null" % \
467 os.path.join(root,"config.log")
468 if "config.log" in files: 468 if "config.log" in files:
469 if os.system("grep 'CROSS COMPILE Badness:' %s > /dev/null" % (os.path.join(root,"config.log"))) == 0: 469 if os.system(statement) == 0:
470 bb.fatal("This autoconf log indicates errors, it looked at host includes. Rerun configure task after fixing this. Path was '%s'" % root) 470 bb.fatal("""This autoconf log indicates errors, it looked at host includes.
471Rerun configure task after fixing this. The path was '%s'""" % root)
471} 472}