summaryrefslogtreecommitdiffstats
path: root/meta/classes
diff options
context:
space:
mode:
authorRichard Purdie <richard.purdie@linuxfoundation.org>2013-06-21 17:45:33 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2013-06-24 15:41:33 +0100
commit87da29080429f1793845978901f5160701648c21 (patch)
tree47c3bc665f8c37ea31bcf0ba67f710c6ed99f0fe /meta/classes
parenta355f13f73cb5a3fbd61435a8ee06967c3c86498 (diff)
downloadpoky-87da29080429f1793845978901f5160701648c21.tar.gz
sanity.bbclass: Various improvements
I started trying to make some changes in sanity.bbclass and couldn't stand the current code. This patch splits out the one big function into a number of smaller units and adds a status class which handles queuing of messages and issues like network errors and whether a reparse is required. It also cleans up some syntax and obsolete code. The other fundamental change is the tests are split into ones which run once and those which run at every build. This was always the way the class was intended to work but that got lost somewhere along the way. This patch fixes that. Its still far from perfect but it is hopefully an improvement and sets the scene for other improvements to be built on top of this. (From OE-Core rev: 4e6de6d5f0454024eec2ec775a938c5dab70610c) Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/classes')
-rw-r--r--meta/classes/sanity.bbclass511
1 files changed, 257 insertions, 254 deletions
diff --git a/meta/classes/sanity.bbclass b/meta/classes/sanity.bbclass
index e62000cc16..622bb41856 100644
--- a/meta/classes/sanity.bbclass
+++ b/meta/classes/sanity.bbclass
@@ -158,7 +158,7 @@ def check_toolchain(data):
158 if tune_errors: 158 if tune_errors:
159 tune_error_set.append(tune_errors) 159 tune_error_set.append(tune_errors)
160 if tune_error_set: 160 if tune_error_set:
161 return "Toolchain tunings invalid:\n" + '\n'.join(tune_error_set) 161 return "Toolchain tunings invalid:\n" + '\n'.join(tune_error_set) + "\n"
162 162
163 return "" 163 return ""
164 164
@@ -174,36 +174,6 @@ def check_conf_exists(fn, data):
174 return True 174 return True
175 return False 175 return False
176 176
177def check_sanity_sstate_dir_change(sstate_dir, data):
178 # Sanity checks to be done when the value of SSTATE_DIR changes
179
180 # Check that SSTATE_DIR isn't on a filesystem with limited filename length (eg. eCryptFS)
181 testmsg = ""
182 if sstate_dir != "":
183 testmsg = check_create_long_filename(sstate_dir, "SSTATE_DIR")
184 # If we don't have permissions to SSTATE_DIR, suggest the user set it as an SSTATE_MIRRORS
185 try:
186 err = testmsg.split(': ')[1].strip()
187 if err == "Permission denied.":
188 testmsg = testmsg + "You could try using %s in SSTATE_MIRRORS rather than as an SSTATE_CACHE.\n" % (sstate_dir)
189 except IndexError:
190 pass
191 return testmsg
192
193def check_sanity_tmpdir_change(tmpdir, data):
194 # Sanity checks to be done when the value of TMPDIR changes
195
196 # Check that TMPDIR isn't on a filesystem with limited filename length (eg. eCryptFS)
197 testmsg = check_create_long_filename(tmpdir, "TMPDIR")
198 # Check that we can fetch from various network transports
199 errmsg = check_connectivity(data)
200 testmsg = testmsg + check_connectivity(data)
201 return testmsg, errmsg != ""
202
203def check_sanity_version_change(data):
204 # Sanity checks to be done when SANITY_VERSION changes
205 return ""
206
207def check_create_long_filename(filepath, pathname): 177def check_create_long_filename(filepath, pathname):
208 testfile = os.path.join(filepath, ''.join([`num`[-1] for num in xrange(1,200)])) 178 testfile = os.path.join(filepath, ''.join([`num`[-1] for num in xrange(1,200)]))
209 try: 179 try:
@@ -338,226 +308,323 @@ def check_gcc_march(sanity_data):
338 308
339# Tar version 1.24 and onwards handle overwriting symlinks correctly 309# Tar version 1.24 and onwards handle overwriting symlinks correctly
340# but earlier versions do not; this needs to work properly for sstate 310# but earlier versions do not; this needs to work properly for sstate
341def check_tar_version(sanity_data, loosever): 311def check_tar_version(sanity_data):
312 from distutils.version import LooseVersion
342 status, result = oe.utils.getstatusoutput("tar --version") 313 status, result = oe.utils.getstatusoutput("tar --version")
343 if status != 0: 314 if status != 0:
344 return "Unable to execute tar --version, exit code %s\n" % status 315 return "Unable to execute tar --version, exit code %s\n" % status
345 version = result.split()[3] 316 version = result.split()[3]
346 if loosever(version) < loosever("1.24"): 317 if LooseVersion(version) < LooseVersion("1.24"):
347 return "Your version of tar is older than 1.24 and has bugs which will break builds. Please install a newer version of tar.\n" 318 return "Your version of tar is older than 1.24 and has bugs which will break builds. Please install a newer version of tar.\n"
348 return None 319 return None
349 320
350# We use git parameters and functionality only found in 1.7.5 or later 321# We use git parameters and functionality only found in 1.7.5 or later
351def check_git_version(sanity_data, loosever): 322def check_git_version(sanity_data):
323 from distutils.version import LooseVersion
352 status, result = oe.utils.getstatusoutput("git --version 2> /dev/null") 324 status, result = oe.utils.getstatusoutput("git --version 2> /dev/null")
353 if status != 0: 325 if status != 0:
354 return "Unable to execute git --version, exit code %s\n" % status 326 return "Unable to execute git --version, exit code %s\n" % status
355 version = result.split()[2] 327 version = result.split()[2]
356 if loosever(version) < loosever("1.7.5"): 328 if LooseVersion(version) < LooseVersion("1.7.5"):
357 return "Your version of git is older than 1.7.5 and has bugs which will break builds. Please install a newer version of git.\n" 329 return "Your version of git is older than 1.7.5 and has bugs which will break builds. Please install a newer version of git.\n"
358 return None 330 return None
359 331
360 332
361def check_sanity(sanity_data): 333def sanity_check_conffiles(status, d):
362 import subprocess
363
364 reparse = False
365 try:
366 from distutils.version import LooseVersion
367 except ImportError:
368 def LooseVersion(v):
369 print("WARNING: sanity.bbclass can't compare versions without python-distutils")
370 return 1
371
372 if 0 == os.getuid():
373 raise_sanity_error("Do not use Bitbake as root.", sanity_data)
374
375 messages = ""
376
377 # Check the Python version, we now have a minimum of Python 2.7.3
378 import sys
379 if sys.hexversion < 0x020703F0:
380 messages = messages + 'The system requires at least Python 2.7.3 to run. Please update your Python interpreter.\n'
381 # Check the python install is complete. glib-2.0-natives requries
382 # xml.parsers.expat
383 try:
384 import xml.parsers.expat
385 except ImportError:
386 messages = messages + 'Your python is not a full install. Please install the module xml.parsers.expat (python-xml on openSUSE and SUSE Linux).\n'
387
388 # Check the bitbake version meets minimum requirements
389 minversion = sanity_data.getVar('BB_MIN_VERSION', True)
390 if (LooseVersion(bb.__version__) < LooseVersion(minversion)):
391 messages = messages + 'Bitbake version %s is required and version %s was found\n' % (minversion, bb.__version__)
392
393 # Check that the MACHINE is valid, if it is set
394 machinevalid = True
395 if sanity_data.getVar('MACHINE', True):
396 if not check_conf_exists("conf/machine/${MACHINE}.conf", sanity_data):
397 messages = messages + 'Please set a valid MACHINE in your local.conf or environment\n'
398 machinevalid = False
399 else:
400 messages = messages + check_sanity_validmachine(sanity_data)
401 else:
402 messages = messages + 'Please set a MACHINE in your local.conf or environment\n'
403 machinevalid = False
404
405 tarmsg = check_tar_version(sanity_data, LooseVersion)
406 if tarmsg:
407 messages = messages + tarmsg
408
409 gitmsg = check_git_version(sanity_data, LooseVersion)
410 if gitmsg:
411 messages = messages + gitmsg
412
413
414 # Check we are using a valid local.conf 334 # Check we are using a valid local.conf
415 current_conf = sanity_data.getVar('CONF_VERSION', True) 335 current_conf = d.getVar('CONF_VERSION', True)
416 conf_version = sanity_data.getVar('LOCALCONF_VERSION', True) 336 conf_version = d.getVar('LOCALCONF_VERSION', True)
417 337
418 if current_conf != conf_version: 338 if current_conf != conf_version:
419 messages = messages + "Your version of local.conf was generated from an older/newer version of local.conf.sample and there have been updates made to this file. Please compare the two files and merge any changes before continuing.\nMatching the version numbers will remove this message.\n\"meld conf/local.conf ${COREBASE}/meta*/conf/local.conf.sample\" is a good way to visualise the changes.\n" 339 status.addresult("Your version of local.conf was generated from an older/newer version of local.conf.sample and there have been updates made to this file. Please compare the two files and merge any changes before continuing.\nMatching the version numbers will remove this message.\n\"meld conf/local.conf ${COREBASE}/meta*/conf/local.conf.sample\" is a good way to visualise the changes.\n")
420 340
421 # Check bblayers.conf is valid 341 # Check bblayers.conf is valid
422 current_lconf = sanity_data.getVar('LCONF_VERSION', True) 342 current_lconf = d.getVar('LCONF_VERSION', True)
423 lconf_version = sanity_data.getVar('LAYER_CONF_VERSION', True) 343 lconf_version = d.getVar('LAYER_CONF_VERSION', True)
424 if current_lconf != lconf_version: 344 if current_lconf != lconf_version:
425 funcs = sanity_data.getVar('BBLAYERS_CONF_UPDATE_FUNCS', True).split() 345 funcs = d.getVar('BBLAYERS_CONF_UPDATE_FUNCS', True).split()
426 for func in funcs: 346 for func in funcs:
427 success = True 347 success = True
428 try: 348 try:
429 bb.build.exec_func(func, sanity_data) 349 bb.build.exec_func(func, d)
430 except Exception: 350 except Exception:
431 success = False 351 success = False
432 if success: 352 if success:
433 bb.note("Your conf/bblayers.conf has been automatically updated.") 353 bb.note("Your conf/bblayers.conf has been automatically updated.")
434 reparse = True 354 status.reparse = True
435 break 355 break
436 if not reparse: 356 if not status.reparse:
437 messages = messages + "Your version of bblayers.conf was generated from an older/newer version of bblayers.conf.sample and there have been updates made to this file. Please compare the two files and merge any changes before continuing.\nMatching the version numbers will remove this message.\n\"meld conf/bblayers.conf ${COREBASE}/meta*/conf/bblayers.conf.sample\" is a good way to visualise the changes.\n" 357 status.addresult("Your version of bblayers.conf was generated from an older/newer version of bblayers.conf.sample and there have been updates made to this file. Please compare the two files and merge any changes before continuing.\nMatching the version numbers will remove this message.\n\"meld conf/bblayers.conf ${COREBASE}/meta*/conf/bblayers.conf.sample\" is a good way to visualise the changes.\n")
438 358
439 # If we have a site.conf, check it's valid 359 # If we have a site.conf, check it's valid
440 if check_conf_exists("conf/site.conf", sanity_data): 360 if check_conf_exists("conf/site.conf", d):
441 current_sconf = sanity_data.getVar('SCONF_VERSION', True) 361 current_sconf = d.getVar('SCONF_VERSION', True)
442 sconf_version = sanity_data.getVar('SITE_CONF_VERSION', True) 362 sconf_version = d.getVar('SITE_CONF_VERSION', True)
443 if current_sconf != sconf_version: 363 if current_sconf != sconf_version:
444 messages = messages + "Your version of site.conf was generated from an older version of site.conf.sample and there have been updates made to this file. Please compare the two files and merge any changes before continuing.\nMatching the version numbers will remove this message.\n\"meld conf/site.conf ${COREBASE}/meta*/conf/site.conf.sample\" is a good way to visualise the changes.\n" 364 status.addresult("Your version of site.conf was generated from an older version of site.conf.sample and there have been updates made to this file. Please compare the two files and merge any changes before continuing.\nMatching the version numbers will remove this message.\n\"meld conf/site.conf ${COREBASE}/meta*/conf/site.conf.sample\" is a good way to visualise the changes.\n")
445 365
446 assume_provided = sanity_data.getVar('ASSUME_PROVIDED', True).split()
447 # Check user doesn't have ASSUME_PROVIDED = instead of += in local.conf
448 if "diffstat-native" not in assume_provided:
449 messages = messages + 'Please use ASSUME_PROVIDED +=, not ASSUME_PROVIDED = in your local.conf\n'
450 366
451 # Check that DL_DIR is set, exists and is writable. In theory, we should never even hit the check if DL_DIR isn't 367def sanity_handle_abichanges(status, d):
452 # set, since so much relies on it being set. 368 #
453 dldir = sanity_data.getVar('DL_DIR', True) 369 # Check the 'ABI' of TMPDIR
454 if not dldir: 370 #
455 messages = messages + "DL_DIR is not set. Your environment is misconfigured, check that DL_DIR is set, and if the directory exists, that it is writable. \n" 371 current_abi = d.getVar('OELAYOUT_ABI', True)
456 if os.path.exists(dldir) and not os.access(dldir, os.W_OK): 372 abifile = d.getVar('SANITY_ABIFILE', True)
457 messages = messages + "DL_DIR: %s exists but you do not appear to have write access to it. \n" % dldir 373 if os.path.exists(abifile):
458 374 with open(abifile, "r") as f:
459 # Check that the DISTRO is valid, if set 375 abi = f.read().strip()
460 # need to take into account DISTRO renaming DISTRO 376 if not abi.isdigit():
461 distro = sanity_data.getVar('DISTRO', True) 377 with open(abifile, "w") as f:
462 if distro: 378 f.write(current_abi)
463 if not ( check_conf_exists("conf/distro/${DISTRO}.conf", sanity_data) or check_conf_exists("conf/distro/include/${DISTRO}.inc", sanity_data) ): 379 elif abi == "2" and current_abi == "3":
464 messages = messages + "DISTRO '%s' not found. Please set a valid DISTRO in your local.conf\n" % sanity_data.getVar("DISTRO", True ) 380 bb.note("Converting staging from layout version 2 to layout version 3")
381 subprocess.call(d.expand("mv ${TMPDIR}/staging ${TMPDIR}/sysroots"), shell=True)
382 subprocess.call(d.expand("ln -s sysroots ${TMPDIR}/staging"), shell=True)
383 subprocess.call(d.expand("cd ${TMPDIR}/stamps; for i in */*do_populate_staging; do new=`echo $i | sed -e 's/do_populate_staging/do_populate_sysroot/'`; mv $i $new; done"), shell=True)
384 with open(abifile, "w") as f:
385 f.write(current_abi)
386 elif abi == "3" and current_abi == "4":
387 bb.note("Converting staging layout from version 3 to layout version 4")
388 if os.path.exists(d.expand("${STAGING_DIR_NATIVE}${bindir_native}/${MULTIMACH_HOST_SYS}")):
389 subprocess.call(d.expand("mv ${STAGING_DIR_NATIVE}${bindir_native}/${MULTIMACH_HOST_SYS} ${STAGING_BINDIR_CROSS}"), shell=True)
390 subprocess.call(d.expand("ln -s ${STAGING_BINDIR_CROSS} ${STAGING_DIR_NATIVE}${bindir_native}/${MULTIMACH_HOST_SYS}"), shell=True)
391 with open(abifile, "w") as f:
392 f.write(current_abi)
393 elif abi == "4":
394 status.addresult("Staging layout has changed. The cross directory has been deprecated and cross packages are now built under the native sysroot.\nThis requires a rebuild.\n")
395 elif abi == "5" and current_abi == "6":
396 bb.note("Converting staging layout from version 5 to layout version 6")
397 subprocess.call(d.expand("mv ${TMPDIR}/pstagelogs ${SSTATE_MANIFESTS}"), shell=True)
398 with open(abifile, "w") as f:
399 f.write(current_abi)
400 elif abi == "7" and current_abi == "8":
401 status.addresult("Your configuration is using stamp files including the sstate hash but your build directory was built with stamp files that do not include this.\nTo continue, either rebuild or switch back to the OEBasic signature handler with BB_SIGNATURE_HANDLER = 'OEBasic'.\n")
402 elif (abi != current_abi and current_abi == "9"):
403 status.addresult("The layout of the TMPDIR STAMPS directory has changed. Please clean out TMPDIR and rebuild (sstate will be still be valid and reused)\n")
404 elif (abi != current_abi):
405 # Code to convert from one ABI to another could go here if possible.
406 status.addresult("Error, TMPDIR has changed its layout version number (%s to %s) and you need to either rebuild, revert or adjust it at your own risk.\n" % (abi, current_abi))
407 else:
408 with open(abifile, "w") as f:
409 f.write(current_abi)
410
411def check_sanity_sstate_dir_change(sstate_dir, data):
412 # Sanity checks to be done when the value of SSTATE_DIR changes
413
414 # Check that SSTATE_DIR isn't on a filesystem with limited filename length (eg. eCryptFS)
415 testmsg = ""
416 if sstate_dir != "":
417 testmsg = check_create_long_filename(sstate_dir, "SSTATE_DIR")
418 # If we don't have permissions to SSTATE_DIR, suggest the user set it as an SSTATE_MIRRORS
419 try:
420 err = testmsg.split(': ')[1].strip()
421 if err == "Permission denied.":
422 testmsg = testmsg + "You could try using %s in SSTATE_MIRRORS rather than as an SSTATE_CACHE.\n" % (sstate_dir)
423 except IndexError:
424 pass
425 return testmsg
426
427def check_sanity_version_change(status, d):
428 # Sanity checks to be done when SANITY_VERSION changes
429 # In other words, these tests run once in a given build directory and then
430 # never again until the sanity version changes.
431
432 # Check the python install is complete. glib-2.0-natives requries
433 # xml.parsers.expat
434 try:
435 import xml.parsers.expat
436 except ImportError:
437 status.addresult('Your python is not a full install. Please install the module xml.parsers.expat (python-xml on openSUSE and SUSE Linux).\n')
438
439 status.addresult(check_tar_version(d))
440 status.addresult(check_git_version(d))
465 441
466 missing = "" 442 missing = ""
467 443
468 if not check_app_exists("${MAKE}", sanity_data): 444 if not check_app_exists("${MAKE}", d):
469 missing = missing + "GNU make," 445 missing = missing + "GNU make,"
470 446
471 if not check_app_exists('${BUILD_PREFIX}gcc', sanity_data): 447 if not check_app_exists('${BUILD_PREFIX}gcc', d):
472 missing = missing + "C Compiler (%sgcc)," % sanity_data.getVar("BUILD_PREFIX", True) 448 missing = missing + "C Compiler (%sgcc)," % d.getVar("BUILD_PREFIX", True)
449
450 if not check_app_exists('${BUILD_PREFIX}g++', d):
451 missing = missing + "C++ Compiler (%sg++)," % d.getVar("BUILD_PREFIX", True)
452
453 required_utilities = d.getVar('SANITY_REQUIRED_UTILITIES', True)
454
455 for util in required_utilities.split():
456 if not check_app_exists(util, d):
457 missing = missing + "%s," % util
473 458
474 if not check_app_exists('${BUILD_PREFIX}g++', sanity_data): 459 if missing:
475 missing = missing + "C++ Compiler (%sg++)," % sanity_data.getVar("BUILD_PREFIX", True) 460 missing = missing.rstrip(',')
461 status.addresult("Please install the following missing utilities: %s\n" % missing)
476 462
477 required_utilities = sanity_data.getVar('SANITY_REQUIRED_UTILITIES', True) 463 assume_provided = d.getVar('ASSUME_PROVIDED', True).split()
464 # Check user doesn't have ASSUME_PROVIDED = instead of += in local.conf
465 if "diffstat-native" not in assume_provided:
466 status.addresult('Please use ASSUME_PROVIDED +=, not ASSUME_PROVIDED = in your local.conf\n')
478 467
479 if "qemu-native" in assume_provided: 468 if "qemu-native" in assume_provided:
480 if not check_app_exists("qemu-arm", sanity_data): 469 if not check_app_exists("qemu-arm", d):
481 messages = messages + "qemu-native was in ASSUME_PROVIDED but the QEMU binaries (qemu-arm) can't be found in PATH" 470 status.addresult("qemu-native was in ASSUME_PROVIDED but the QEMU binaries (qemu-arm) can't be found in PATH")
482 471
483 if check_gcc_march(sanity_data): 472 if check_gcc_march(d):
484 messages = messages + "Your gcc version is older than 4.5, please add the following param to local.conf\n \ 473 status.addresult("Your gcc version is older than 4.5, please add the following param to local.conf\n \
485 BUILD_CFLAGS_append = \" -march=native\"\n" 474 BUILD_CFLAGS_append = \" -march=native\"\n")
486 475
487 paths = sanity_data.getVar('PATH', True).split(":") 476 # Check that TMPDIR isn't on a filesystem with limited filename length (eg. eCryptFS)
488 if "." in paths or "" in paths: 477 tmpdir = d.getVar('TMPDIR', True)
489 messages = messages + "PATH contains '.' or '' (empty element), which will break the build, please remove this.\n" 478 status.addresult(check_create_long_filename(tmpdir, "TMPDIR"))
490 messages = messages + "Parsed PATH is " + str(paths) + "\n" 479
491 480 # Check that we can fetch from various network transports
492 bbpaths = sanity_data.getVar('BBPATH', True).split(":") 481 netcheck = check_connectivity(d)
493 if ("." in bbpaths or "" in bbpaths) and not reparse: 482 status.addresult(netcheck)
494 # TODO: change the following message to fatal when all BBPATH issues 483 if netcheck:
495 # are fixed 484 status.network_error = True
496 bb.warn("BBPATH references the current directory, either through " \ 485
486 nolibs = d.getVar('NO32LIBS', True)
487 if not nolibs:
488 lib32path = '/lib'
489 if os.path.exists('/lib64') and ( os.path.islink('/lib64') or os.path.islink('/lib') ):
490 lib32path = '/lib32'
491
492 if os.path.exists('%s/libc.so.6' % lib32path) and not os.path.exists('/usr/include/gnu/stubs-32.h'):
493 status.addresult("You have a 32-bit libc, but no 32-bit headers. You must install the 32-bit libc headers.\n")
494
495 bbpaths = d.getVar('BBPATH', True).split(":")
496 if ("." in bbpaths or "" in bbpaths) and not status.reparse:
497 status.addresult("BBPATH references the current directory, either through " \
497 "an empty entry, or a '.'.\n\t This is unsafe and means your "\ 498 "an empty entry, or a '.'.\n\t This is unsafe and means your "\
498 "layer configuration is adding empty elements to BBPATH.\n\t "\ 499 "layer configuration is adding empty elements to BBPATH.\n\t "\
499 "Please check your layer.conf files and other BBPATH " \ 500 "Please check your layer.conf files and other BBPATH " \
500 "settings to remove the current working directory " \ 501 "settings to remove the current working directory " \
501 "references."); 502 "references.\n" \
502 bb.warn("Parsed BBPATH is" + str(bbpaths)); 503 "Parsed BBPATH is" + str(bbpaths));
503 504
504 if sanity_data.getVar('TARGET_ARCH', True) == "arm": 505 oes_bb_conf = d.getVar( 'OES_BITBAKE_CONF', True)
506 if not oes_bb_conf:
507 status.addresult('You do not include the OpenEmbedded version of conf/bitbake.conf. This means your environment is misconfigured, in particular check BBPATH.\n')
508
509 # The length of tmpdir can't be longer than 410
510 status.addresult(check_path_length(tmpdir, "TMPDIR", 410))
511
512def check_sanity_everybuild(status, d):
513 # Sanity tests which test the users environment so need to run at each build (or are so cheap
514 # it makes sense to always run them.
515
516 if 0 == os.getuid():
517 raise_sanity_error("Do not use Bitbake as root.", d)
518
519 # Check the Python version, we now have a minimum of Python 2.7.3
520 import sys
521 if sys.hexversion < 0x020703F0:
522 status.addresult('The system requires at least Python 2.7.3 to run. Please update your Python interpreter.\n')
523
524 # Check the bitbake version meets minimum requirements
525 from distutils.version import LooseVersion
526 minversion = d.getVar('BB_MIN_VERSION', True)
527 if (LooseVersion(bb.__version__) < LooseVersion(minversion)):
528 status.addresult('Bitbake version %s is required and version %s was found\n' % (minversion, bb.__version__))
529
530 sanity_check_conffiles(status, d)
531
532 paths = d.getVar('PATH', True).split(":")
533 if "." in paths or "" in paths:
534 status.addresult("PATH contains '.' or '' (empty element), which will break the build, please remove this.\nParsed PATH is " + str(paths) + "\n")
535
536 # Check that the DISTRO is valid, if set
537 # need to take into account DISTRO renaming DISTRO
538 distro = d.getVar('DISTRO', True)
539 if distro:
540 if not ( check_conf_exists("conf/distro/${DISTRO}.conf", d) or check_conf_exists("conf/distro/include/${DISTRO}.inc", d) ):
541 status.addresult("DISTRO '%s' not found. Please set a valid DISTRO in your local.conf\n" % d.getVar("DISTRO", True))
542
543 # Check that DL_DIR is set, exists and is writable. In theory, we should never even hit the check if DL_DIR isn't
544 # set, since so much relies on it being set.
545 dldir = d.getVar('DL_DIR', True)
546 if not dldir:
547 status.addresult("DL_DIR is not set. Your environment is misconfigured, check that DL_DIR is set, and if the directory exists, that it is writable. \n")
548 if os.path.exists(dldir) and not os.access(dldir, os.W_OK):
549 status.addresult("DL_DIR: %s exists but you do not appear to have write access to it. \n" % dldir)
550
551 # Check that the MACHINE is valid, if it is set
552 machinevalid = True
553 if d.getVar('MACHINE', True):
554 if not check_conf_exists("conf/machine/${MACHINE}.conf", d):
555 status.addresult('Please set a valid MACHINE in your local.conf or environment\n')
556 machinevalid = False
557 else:
558 status.addresult(check_sanity_validmachine(d))
559 else:
560 status.addresult('Please set a MACHINE in your local.conf or environment\n')
561 machinevalid = False
562 if machinevalid:
563 status.addresult(check_toolchain(d))
564
565 check_supported_distro(d)
566
567 # Check if DISPLAY is set if IMAGETEST is set
568 if d.getVar( 'IMAGETEST', True ) == 'qemu':
569 display = d.getVar("BB_ORIGENV", False).getVar("DISPLAY", True)
570 if not display:
571 status.addresult('qemuimagetest needs a X desktop to start qemu, please set DISPLAY correctly (e.g. DISPLAY=:1.0)\n')
572
573 omask = os.umask(022)
574 if omask & 0755:
575 status.addresult("Please use a umask which allows a+rx and u+rwx\n")
576 os.umask(omask)
577
578 if d.getVar('TARGET_ARCH', True) == "arm":
505 # This path is no longer user-readable in modern (very recent) Linux 579 # This path is no longer user-readable in modern (very recent) Linux
506 try: 580 try:
507 if os.path.exists("/proc/sys/vm/mmap_min_addr"): 581 if os.path.exists("/proc/sys/vm/mmap_min_addr"):
508 f = open("/proc/sys/vm/mmap_min_addr", "r") 582 f = open("/proc/sys/vm/mmap_min_addr", "r")
509 try: 583 try:
510 if (int(f.read().strip()) > 65536): 584 if (int(f.read().strip()) > 65536):
511 messages = messages + "/proc/sys/vm/mmap_min_addr is not <= 65536. This will cause problems with qemu so please fix the value (as root).\n\nTo fix this in later reboots, set vm.mmap_min_addr = 65536 in /etc/sysctl.conf.\n" 585 status.addresult("/proc/sys/vm/mmap_min_addr is not <= 65536. This will cause problems with qemu so please fix the value (as root).\n\nTo fix this in later reboots, set vm.mmap_min_addr = 65536 in /etc/sysctl.conf.\n")
512 finally: 586 finally:
513 f.close() 587 f.close()
514 except: 588 except:
515 pass 589 pass
516 590
517 for util in required_utilities.split(): 591 oeroot = d.getVar('COREBASE')
518 if not check_app_exists( util, sanity_data ): 592 if oeroot.find ('+') != -1:
519 missing = missing + "%s," % util 593 status.addresult("Error, you have an invalid character (+) in your COREBASE directory path. Please move the installation to a directory which doesn't include a +.")
520 594 elif oeroot.find (' ') != -1:
521 if missing != "": 595 status.addresult("Error, you have a space in your COREBASE directory path. Please move the installation to a directory which doesn't include a space.")
522 missing = missing.rstrip(',')
523 messages = messages + "Please install the following missing utilities: %s\n" % missing
524
525 check_supported_distro(sanity_data)
526 if machinevalid:
527 toolchain_msg = check_toolchain(sanity_data)
528 if toolchain_msg != "":
529 messages = messages + toolchain_msg + '\n'
530 596
531 # Check if DISPLAY is set if IMAGETEST is set 597 # Check that TMPDIR hasn't changed location since the last time we were run
532 if sanity_data.getVar( 'IMAGETEST', True ) == 'qemu': 598 tmpdir = d.getVar('TMPDIR', True)
533 display = sanity_data.getVar("BB_ORIGENV", False).getVar("DISPLAY", True) 599 checkfile = os.path.join(tmpdir, "saved_tmpdir")
534 if not display: 600 if os.path.exists(checkfile):
535 messages = messages + 'qemuimagetest needs a X desktop to start qemu, please set DISPLAY correctly (e.g. DISPLAY=:1.0)\n' 601 with open(checkfile, "r") as f:
602 saved_tmpdir = f.read().strip()
603 if (saved_tmpdir != tmpdir):
604 status.addresult("Error, TMPDIR has changed location. You need to either move it back to %s or rebuild\n" % saved_tmpdir)
605 else:
606 bb.utils.mkdirhier(tmpdir)
607 with open(checkfile, "w") as f:
608 f.write(tmpdir)
536 609
537 omask = os.umask(022) 610def check_sanity(sanity_data):
538 if omask & 0755: 611 import subprocess
539 messages = messages + "Please use a umask which allows a+rx and u+rwx\n"
540 os.umask(omask)
541 612
542 oes_bb_conf = sanity_data.getVar( 'OES_BITBAKE_CONF', True) 613 class SanityStatus(object):
543 if not oes_bb_conf: 614 def __init__(self):
544 messages = messages + 'You do not include the OpenEmbedded version of conf/bitbake.conf. This means your environment is misconfigured, in particular check BBPATH.\n' 615 self.messages = ""
616 self.network_error = False
617 self.reparse = False
545 618
546 nolibs = sanity_data.getVar('NO32LIBS', True) 619 def addresult(self, message):
547 if not nolibs: 620 if message:
548 lib32path = '/lib' 621 self.messages = self.messages + message
549 if os.path.exists('/lib64') and ( os.path.islink('/lib64') or os.path.islink('/lib') ):
550 lib32path = '/lib32'
551 622
552 if os.path.exists('%s/libc.so.6' % lib32path) and not os.path.exists('/usr/include/gnu/stubs-32.h'): 623 status = SanityStatus()
553 messages = messages + "You have a 32-bit libc, but no 32-bit headers. You must install the 32-bit libc headers.\n"
554 624
555 tmpdir = sanity_data.getVar('TMPDIR', True) 625 tmpdir = sanity_data.getVar('TMPDIR', True)
556 sstate_dir = sanity_data.getVar('SSTATE_DIR', True) 626 sstate_dir = sanity_data.getVar('SSTATE_DIR', True)
557 627
558 # The length of tmpdir can't be longer than 410
559 messages = messages + check_path_length(tmpdir, "TMPDIR", 410)
560
561 # Check saved sanity info 628 # Check saved sanity info
562 last_sanity_version = 0 629 last_sanity_version = 0
563 last_tmpdir = "" 630 last_tmpdir = ""
@@ -572,92 +639,28 @@ def check_sanity(sanity_data):
572 last_tmpdir = line.split()[1] 639 last_tmpdir = line.split()[1]
573 if line.startswith('SSTATE_DIR'): 640 if line.startswith('SSTATE_DIR'):
574 last_sstate_dir = line.split()[1] 641 last_sstate_dir = line.split()[1]
642
643 check_sanity_everybuild(status, sanity_data)
575 644
576 sanity_version = int(sanity_data.getVar('SANITY_VERSION', True) or 1) 645 sanity_version = int(sanity_data.getVar('SANITY_VERSION', True) or 1)
577 network_error = False 646 network_error = False
578 if last_sanity_version < sanity_version: 647 if last_sanity_version < sanity_version:
579 messages = messages + check_sanity_version_change(sanity_data) 648 check_sanity_version_change(status, sanity_data)
580 err, network_error = check_sanity_tmpdir_change(tmpdir, sanity_data) 649 status.addresult(check_sanity_sstate_dir_change(sstate_dir, sanity_data))
581 messages = messages + err
582 messages = messages + check_sanity_sstate_dir_change(sstate_dir, sanity_data)
583 else: 650 else:
584 if last_tmpdir != tmpdir:
585 err, network_error = check_sanity_tmpdir_change(tmpdir, sanity_data)
586 messages = messages + err
587 if last_sstate_dir != sstate_dir: 651 if last_sstate_dir != sstate_dir:
588 messages = messages + check_sanity_sstate_dir_change(sstate_dir, sanity_data) 652 status.addresult(check_sanity_sstate_dir_change(sstate_dir, sanity_data))
589 if os.path.exists("conf") and not messages: 653 if os.path.exists("conf") and not status.messages:
590 with open(sanityverfile, 'w') as f: 654 with open(sanityverfile, 'w') as f:
591 f.write("SANITY_VERSION %s\n" % sanity_version) 655 f.write("SANITY_VERSION %s\n" % sanity_version)
592 f.write("TMPDIR %s\n" % tmpdir) 656 f.write("TMPDIR %s\n" % tmpdir)
593 f.write("SSTATE_DIR %s\n" % sstate_dir) 657 f.write("SSTATE_DIR %s\n" % sstate_dir)
594 658
595 # 659 sanity_handle_abichanges(status, sanity_data)
596 # Check that TMPDIR hasn't changed location since the last time we were run
597 #
598 checkfile = os.path.join(tmpdir, "saved_tmpdir")
599 if os.path.exists(checkfile):
600 with open(checkfile, "r") as f:
601 saved_tmpdir = f.read().strip()
602 if (saved_tmpdir != tmpdir):
603 messages = messages + "Error, TMPDIR has changed location. You need to either move it back to %s or rebuild\n" % saved_tmpdir
604 else:
605 bb.utils.mkdirhier(tmpdir)
606 with open(checkfile, "w") as f:
607 f.write(tmpdir)
608
609 #
610 # Check the 'ABI' of TMPDIR
611 #
612 current_abi = sanity_data.getVar('OELAYOUT_ABI', True)
613 abifile = sanity_data.getVar('SANITY_ABIFILE', True)
614 if os.path.exists(abifile):
615 with open(abifile, "r") as f:
616 abi = f.read().strip()
617 if not abi.isdigit():
618 with open(abifile, "w") as f:
619 f.write(current_abi)
620 elif abi == "2" and current_abi == "3":
621 bb.note("Converting staging from layout version 2 to layout version 3")
622 subprocess.call(sanity_data.expand("mv ${TMPDIR}/staging ${TMPDIR}/sysroots"), shell=True)
623 subprocess.call(sanity_data.expand("ln -s sysroots ${TMPDIR}/staging"), shell=True)
624 subprocess.call(sanity_data.expand("cd ${TMPDIR}/stamps; for i in */*do_populate_staging; do new=`echo $i | sed -e 's/do_populate_staging/do_populate_sysroot/'`; mv $i $new; done"), shell=True)
625 with open(abifile, "w") as f:
626 f.write(current_abi)
627 elif abi == "3" and current_abi == "4":
628 bb.note("Converting staging layout from version 3 to layout version 4")
629 if os.path.exists(sanity_data.expand("${STAGING_DIR_NATIVE}${bindir_native}/${MULTIMACH_HOST_SYS}")):
630 subprocess.call(sanity_data.expand("mv ${STAGING_DIR_NATIVE}${bindir_native}/${MULTIMACH_HOST_SYS} ${STAGING_BINDIR_CROSS}"), shell=True)
631 subprocess.call(sanity_data.expand("ln -s ${STAGING_BINDIR_CROSS} ${STAGING_DIR_NATIVE}${bindir_native}/${MULTIMACH_HOST_SYS}"), shell=True)
632 with open(abifile, "w") as f:
633 f.write(current_abi)
634 elif abi == "4":
635 messages = messages + "Staging layout has changed. The cross directory has been deprecated and cross packages are now built under the native sysroot.\nThis requires a rebuild.\n"
636 elif abi == "5" and current_abi == "6":
637 bb.note("Converting staging layout from version 5 to layout version 6")
638 subprocess.call(sanity_data.expand("mv ${TMPDIR}/pstagelogs ${SSTATE_MANIFESTS}"), shell=True)
639 with open(abifile, "w") as f:
640 f.write(current_abi)
641 elif abi == "7" and current_abi == "8":
642 messages = messages + "Your configuration is using stamp files including the sstate hash but your build directory was built with stamp files that do not include this.\nTo continue, either rebuild or switch back to the OEBasic signature handler with BB_SIGNATURE_HANDLER = 'OEBasic'.\n"
643 elif (abi != current_abi and current_abi == "9"):
644 messages = messages + "The layout of the TMPDIR STAMPS directory has changed. Please clean out TMPDIR and rebuild (sstate will be still be valid and reused)\n"
645 elif (abi != current_abi):
646 # Code to convert from one ABI to another could go here if possible.
647 messages = messages + "Error, TMPDIR has changed its layout version number (%s to %s) and you need to either rebuild, revert or adjust it at your own risk.\n" % (abi, current_abi)
648 else:
649 with open(abifile, "w") as f:
650 f.write(current_abi)
651
652 oeroot = sanity_data.getVar('COREBASE')
653 if oeroot.find ('+') != -1:
654 messages = messages + "Error, you have an invalid character (+) in your COREBASE directory path. Please move the installation to a directory which doesn't include a +."
655 elif oeroot.find (' ') != -1:
656 messages = messages + "Error, you have a space in your COREBASE directory path. Please move the installation to a directory which doesn't include a space."
657 660
658 if messages != "": 661 if status.messages != "":
659 raise_sanity_error(sanity_data.expand(messages), sanity_data, network_error) 662 raise_sanity_error(sanity_data.expand(status.messages), sanity_data, status.network_error)
660 return reparse 663 return status.reparse
661 664
662# Create a copy of the datastore and finalise it to ensure appends and 665# Create a copy of the datastore and finalise it to ensure appends and
663# overrides are set - the datastore has yet to be finalised at ConfigParsed 666# overrides are set - the datastore has yet to be finalised at ConfigParsed