blob: 77813e41bcf03d0761be1a071b2b849bb1708403 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001#
2# Sanity check the users setup for common misconfigurations
3#
4
5SANITY_REQUIRED_UTILITIES ?= "patch diffstat makeinfo git bzip2 tar \
Patrick Williamsf1e5d692016-03-30 15:21:19 -05006 gzip gawk chrpath wget cpio perl file"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05007
8def bblayers_conf_file(d):
9 return os.path.join(d.getVar('TOPDIR', True), 'conf/bblayers.conf')
10
11def sanity_conf_read(fn):
12 with open(fn, 'r') as f:
13 lines = f.readlines()
14 return lines
15
16def sanity_conf_find_line(pattern, lines):
17 import re
18 return next(((index, line)
19 for index, line in enumerate(lines)
20 if re.search(pattern, line)), (None, None))
21
22def sanity_conf_update(fn, lines, version_var_name, new_version):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050023 index, line = sanity_conf_find_line(r"^%s" % version_var_name, lines)
Patrick Williamsc124f4f2015-09-15 14:41:29 -050024 lines[index] = '%s = "%d"\n' % (version_var_name, new_version)
25 with open(fn, "w") as f:
26 f.write(''.join(lines))
27
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050028# Functions added to this variable MUST throw a NotImplementedError exception unless
29# they successfully changed the config version in the config file. Exceptions
30# are used since exec_func doesn't handle return values.
31BBLAYERS_CONF_UPDATE_FUNCS += " \
32 conf/bblayers.conf:LCONF_VERSION:LAYER_CONF_VERSION:oecore_update_bblayers \
33 conf/local.conf:CONF_VERSION:LOCALCONF_VERSION:oecore_update_localconf \
34 conf/site.conf:SCONF_VERSION:SITE_CONF_VERSION:oecore_update_siteconf \
35"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050036
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050037SANITY_DIFF_TOOL ?= "meld"
38
39SANITY_LOCALCONF_SAMPLE ?= "${COREBASE}/meta*/conf/local.conf.sample"
40python oecore_update_localconf() {
41 # Check we are using a valid local.conf
42 current_conf = d.getVar('CONF_VERSION', True)
43 conf_version = d.getVar('LOCALCONF_VERSION', True)
44
45 failmsg = """Your version of local.conf was generated from an older/newer version of
46local.conf.sample and there have been updates made to this file. Please compare the two
47files and merge any changes before continuing.
48
49Matching the version numbers will remove this message.
50
51\"${SANITY_DIFF_TOOL} conf/local.conf ${SANITY_LOCALCONF_SAMPLE}\"
52
53is a good way to visualise the changes."""
54 failmsg = d.expand(failmsg)
55
56 raise NotImplementedError(failmsg)
57}
58
59SANITY_SITECONF_SAMPLE ?= "${COREBASE}/meta*/conf/site.conf.sample"
60python oecore_update_siteconf() {
61 # If we have a site.conf, check it's valid
62 current_sconf = d.getVar('SCONF_VERSION', True)
63 sconf_version = d.getVar('SITE_CONF_VERSION', True)
64
65 failmsg = """Your version of site.conf was generated from an older version of
66site.conf.sample and there have been updates made to this file. Please compare the two
67files and merge any changes before continuing.
68
69Matching the version numbers will remove this message.
70
71\"${SANITY_DIFF_TOOL} conf/site.conf ${SANITY_SITECONF_SAMPLE}\"
72
73is a good way to visualise the changes."""
74 failmsg = d.expand(failmsg)
75
76 raise NotImplementedError(failmsg)
77}
78
79SANITY_BBLAYERCONF_SAMPLE ?= "${COREBASE}/meta*/conf/bblayers.conf.sample"
Patrick Williamsc124f4f2015-09-15 14:41:29 -050080python oecore_update_bblayers() {
81 # bblayers.conf is out of date, so see if we can resolve that
82
83 current_lconf = int(d.getVar('LCONF_VERSION', True))
Patrick Williamsc124f4f2015-09-15 14:41:29 -050084 lconf_version = int(d.getVar('LAYER_CONF_VERSION', True))
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050085
86 failmsg = """Your version of bblayers.conf has the wrong LCONF_VERSION (has ${LCONF_VERSION}, expecting ${LAYER_CONF_VERSION}).
87Please compare your file against bblayers.conf.sample and merge any changes before continuing.
88"${SANITY_DIFF_TOOL} conf/bblayers.conf ${SANITY_BBLAYERCONF_SAMPLE}"
89
90is a good way to visualise the changes."""
91 failmsg = d.expand(failmsg)
92
93 if not current_lconf:
94 raise NotImplementedError(failmsg)
95
Patrick Williamsc124f4f2015-09-15 14:41:29 -050096 lines = []
97
98 if current_lconf < 4:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050099 raise NotImplementedError(failmsg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500100
101 bblayers_fn = bblayers_conf_file(d)
102 lines = sanity_conf_read(bblayers_fn)
103
104 if current_lconf == 4 and lconf_version > 4:
105 topdir_var = '$' + '{TOPDIR}'
106 index, bbpath_line = sanity_conf_find_line('BBPATH', lines)
107 if bbpath_line:
108 start = bbpath_line.find('"')
109 if start != -1 and (len(bbpath_line) != (start + 1)):
110 if bbpath_line[start + 1] == '"':
111 lines[index] = (bbpath_line[:start + 1] +
112 topdir_var + bbpath_line[start + 1:])
113 else:
114 if not topdir_var in bbpath_line:
115 lines[index] = (bbpath_line[:start + 1] +
116 topdir_var + ':' + bbpath_line[start + 1:])
117 else:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500118 raise NotImplementedError(failmsg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500119 else:
120 index, bbfiles_line = sanity_conf_find_line('BBFILES', lines)
121 if bbfiles_line:
122 lines.insert(index, 'BBPATH = "' + topdir_var + '"\n')
123 else:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500124 raise NotImplementedError(failmsg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500125
126 current_lconf += 1
127 sanity_conf_update(bblayers_fn, lines, 'LCONF_VERSION', current_lconf)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500128 bb.note("Your conf/bblayers.conf has been automatically updated.")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500129 return
130
131 elif current_lconf == 5 and lconf_version > 5:
132 # Null update, to avoid issues with people switching between poky and other distros
133 current_lconf = 6
134 sanity_conf_update(bblayers_fn, lines, 'LCONF_VERSION', current_lconf)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500135 bb.note("Your conf/bblayers.conf has been automatically updated.")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500136 return
137
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500138 if not status.reparse:
139 status.addresult()
140
141 elif current_lconf == 6 and lconf_version > 6:
142 # Handle rename of meta-yocto -> meta-poky
143 # This marks the start of separate version numbers but code is needed in OE-Core
144 # for the migration, one last time.
145 layers = d.getVar('BBLAYERS', True).split()
146 layers = [ os.path.basename(path) for path in layers ]
147 if 'meta-yocto' in layers:
148 found = False
149 while True:
150 index, meta_yocto_line = sanity_conf_find_line(r'.*meta-yocto[\'"\s\n]', lines)
151 if meta_yocto_line:
152 lines[index] = meta_yocto_line.replace('meta-yocto', 'meta-poky')
153 found = True
154 else:
155 break
156 if not found:
157 raise NotImplementedError(failmsg)
158 index, meta_yocto_line = sanity_conf_find_line('LCONF_VERSION.*\n', lines)
159 if meta_yocto_line:
160 lines[index] = 'POKY_BBLAYERS_CONF_VERSION = "1"\n'
161 else:
162 raise NotImplementedError(failmsg)
163 with open(bblayers_fn, "w") as f:
164 f.write(''.join(lines))
165 bb.note("Your conf/bblayers.conf has been automatically updated.")
166 return
167 current_lconf += 1
168 sanity_conf_update(bblayers_fn, lines, 'LCONF_VERSION', current_lconf)
169 bb.note("Your conf/bblayers.conf has been automatically updated.")
170 return
171
172 raise NotImplementedError(failmsg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500173}
174
175def raise_sanity_error(msg, d, network_error=False):
176 if d.getVar("SANITY_USE_EVENTS", True) == "1":
177 try:
178 bb.event.fire(bb.event.SanityCheckFailed(msg, network_error), d)
179 except TypeError:
180 bb.event.fire(bb.event.SanityCheckFailed(msg), d)
181 return
182
183 bb.fatal(""" OE-core's config sanity checker detected a potential misconfiguration.
184 Either fix the cause of this error or at your own risk disable the checker (see sanity.conf).
185 Following is the list of potential problems / advisories:
186
187 %s""" % msg)
188
189# Check flags associated with a tuning.
190def check_toolchain_tune_args(data, tune, multilib, errs):
191 found_errors = False
192 if check_toolchain_args_present(data, tune, multilib, errs, 'CCARGS'):
193 found_errors = True
194 if check_toolchain_args_present(data, tune, multilib, errs, 'ASARGS'):
195 found_errors = True
196 if check_toolchain_args_present(data, tune, multilib, errs, 'LDARGS'):
197 found_errors = True
198
199 return found_errors
200
201def check_toolchain_args_present(data, tune, multilib, tune_errors, which):
202 args_set = (data.getVar("TUNE_%s" % which, True) or "").split()
203 args_wanted = (data.getVar("TUNEABI_REQUIRED_%s_tune-%s" % (which, tune), True) or "").split()
204 args_missing = []
205
206 # If no args are listed/required, we are done.
207 if not args_wanted:
208 return
209 for arg in args_wanted:
210 if arg not in args_set:
211 args_missing.append(arg)
212
213 found_errors = False
214 if args_missing:
215 found_errors = True
216 tune_errors.append("TUNEABI for %s requires '%s' in TUNE_%s (%s)." %
217 (tune, ' '.join(args_missing), which, ' '.join(args_set)))
218 return found_errors
219
220# Check a single tune for validity.
221def check_toolchain_tune(data, tune, multilib):
222 tune_errors = []
223 if not tune:
224 return "No tuning found for %s multilib." % multilib
225 localdata = bb.data.createCopy(data)
226 if multilib != "default":
227 # Apply the overrides so we can look at the details.
228 overrides = localdata.getVar("OVERRIDES", False) + ":virtclass-multilib-" + multilib
229 localdata.setVar("OVERRIDES", overrides)
230 bb.data.update_data(localdata)
231 bb.debug(2, "Sanity-checking tuning '%s' (%s) features:" % (tune, multilib))
232 features = (localdata.getVar("TUNE_FEATURES_tune-%s" % tune, True) or "").split()
233 if not features:
234 return "Tuning '%s' has no defined features, and cannot be used." % tune
235 valid_tunes = localdata.getVarFlags('TUNEVALID') or {}
236 conflicts = localdata.getVarFlags('TUNECONFLICTS') or {}
237 # [doc] is the documentation for the variable, not a real feature
238 if 'doc' in valid_tunes:
239 del valid_tunes['doc']
240 if 'doc' in conflicts:
241 del conflicts['doc']
242 for feature in features:
243 if feature in conflicts:
244 for conflict in conflicts[feature].split():
245 if conflict in features:
246 tune_errors.append("Feature '%s' conflicts with '%s'." %
247 (feature, conflict))
248 if feature in valid_tunes:
249 bb.debug(2, " %s: %s" % (feature, valid_tunes[feature]))
250 else:
251 tune_errors.append("Feature '%s' is not defined." % feature)
252 whitelist = localdata.getVar("TUNEABI_WHITELIST", True)
253 if whitelist:
254 tuneabi = localdata.getVar("TUNEABI_tune-%s" % tune, True)
255 if not tuneabi:
256 tuneabi = tune
257 if True not in [x in whitelist.split() for x in tuneabi.split()]:
258 tune_errors.append("Tuning '%s' (%s) cannot be used with any supported tuning/ABI." %
259 (tune, tuneabi))
260 else:
261 if not check_toolchain_tune_args(localdata, tuneabi, multilib, tune_errors):
262 bb.debug(2, "Sanity check: Compiler args OK for %s." % tune)
263 if tune_errors:
264 return "Tuning '%s' has the following errors:\n" % tune + '\n'.join(tune_errors)
265
266def check_toolchain(data):
267 tune_error_set = []
268 deftune = data.getVar("DEFAULTTUNE", True)
269 tune_errors = check_toolchain_tune(data, deftune, 'default')
270 if tune_errors:
271 tune_error_set.append(tune_errors)
272
273 multilibs = (data.getVar("MULTILIB_VARIANTS", True) or "").split()
274 global_multilibs = (data.getVar("MULTILIB_GLOBAL_VARIANTS", True) or "").split()
275
276 if multilibs:
277 seen_libs = []
278 seen_tunes = []
279 for lib in multilibs:
280 if lib in seen_libs:
281 tune_error_set.append("The multilib '%s' appears more than once." % lib)
282 else:
283 seen_libs.append(lib)
284 if not lib in global_multilibs:
285 tune_error_set.append("Multilib %s is not present in MULTILIB_GLOBAL_VARIANTS" % lib)
286 tune = data.getVar("DEFAULTTUNE_virtclass-multilib-%s" % lib, True)
287 if tune in seen_tunes:
288 tune_error_set.append("The tuning '%s' appears in more than one multilib." % tune)
289 else:
290 seen_libs.append(tune)
291 if tune == deftune:
292 tune_error_set.append("Multilib '%s' (%s) is also the default tuning." % (lib, deftune))
293 else:
294 tune_errors = check_toolchain_tune(data, tune, lib)
295 if tune_errors:
296 tune_error_set.append(tune_errors)
297 if tune_error_set:
298 return "Toolchain tunings invalid:\n" + '\n'.join(tune_error_set) + "\n"
299
300 return ""
301
302def check_conf_exists(fn, data):
303 bbpath = []
304 fn = data.expand(fn)
305 vbbpath = data.getVar("BBPATH", False)
306 if vbbpath:
307 bbpath += vbbpath.split(":")
308 for p in bbpath:
309 currname = os.path.join(data.expand(p), fn)
310 if os.access(currname, os.R_OK):
311 return True
312 return False
313
314def check_create_long_filename(filepath, pathname):
315 import string, random
316 testfile = os.path.join(filepath, ''.join(random.choice(string.ascii_letters) for x in range(200)))
317 try:
318 if not os.path.exists(filepath):
319 bb.utils.mkdirhier(filepath)
320 f = open(testfile, "w")
321 f.close()
322 os.remove(testfile)
323 except IOError as e:
324 import errno
325 err, strerror = e.args
326 if err == errno.ENAMETOOLONG:
327 return "Failed to create a file with a long name in %s. Please use a filesystem that does not unreasonably limit filename length.\n" % pathname
328 else:
329 return "Failed to create a file in %s: %s.\n" % (pathname, strerror)
330 except OSError as e:
331 errno, strerror = e.args
332 return "Failed to create %s directory in which to run long name sanity check: %s.\n" % (pathname, strerror)
333 return ""
334
335def check_path_length(filepath, pathname, limit):
336 if len(filepath) > limit:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500337 return "The length of %s is longer than %s, this would cause unexpected errors, please use a shorter path.\n" % (pathname, limit)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500338 return ""
339
340def get_filesystem_id(path):
341 status, result = oe.utils.getstatusoutput("stat -f -c '%s' %s" % ("%t", path))
342 if status == 0:
343 return result
344 else:
345 bb.warn("Can't get the filesystem id of: %s" % path)
346 return None
347
348# Check that the path isn't located on nfs.
349def check_not_nfs(path, name):
350 # The nfs' filesystem id is 6969
351 if get_filesystem_id(path) == "6969":
352 return "The %s: %s can't be located on nfs.\n" % (name, path)
353 return ""
354
355# Check that path isn't a broken symlink
356def check_symlink(lnk, data):
357 if os.path.islink(lnk) and not os.path.exists(lnk):
358 raise_sanity_error("%s is a broken symlink." % lnk, data)
359
360def check_connectivity(d):
361 # URI's to check can be set in the CONNECTIVITY_CHECK_URIS variable
362 # using the same syntax as for SRC_URI. If the variable is not set
363 # the check is skipped
364 test_uris = (d.getVar('CONNECTIVITY_CHECK_URIS', True) or "").split()
365 retval = ""
366
367 # Only check connectivity if network enabled and the
368 # CONNECTIVITY_CHECK_URIS are set
369 network_enabled = not d.getVar('BB_NO_NETWORK', True)
370 check_enabled = len(test_uris)
371 # Take a copy of the data store and unset MIRRORS and PREMIRRORS
372 data = bb.data.createCopy(d)
373 data.delVar('PREMIRRORS')
374 data.delVar('MIRRORS')
375 if check_enabled and network_enabled:
376 try:
377 fetcher = bb.fetch2.Fetch(test_uris, data)
378 fetcher.checkstatus()
379 except Exception as err:
380 # Allow the message to be configured so that users can be
381 # pointed to a support mechanism.
382 msg = data.getVar('CONNECTIVITY_CHECK_MSG', True) or ""
383 if len(msg) == 0:
384 msg = "%s. Please ensure your network is configured correctly.\n" % err
385 retval = msg
386
387 return retval
388
389def check_supported_distro(sanity_data):
390 from fnmatch import fnmatch
391
392 tested_distros = sanity_data.getVar('SANITY_TESTED_DISTROS', True)
393 if not tested_distros:
394 return
395
396 try:
397 distro = oe.lsb.distro_identifier()
398 except Exception:
399 distro = None
400
401 if not distro:
402 bb.warn('Host distribution could not be determined; you may possibly experience unexpected failures. It is recommended that you use a tested distribution.')
403
404 for supported in [x.strip() for x in tested_distros.split('\\n')]:
405 if fnmatch(distro, supported):
406 return
407
408 bb.warn('Host distribution "%s" has not been validated with this version of the build system; you may possibly experience unexpected failures. It is recommended that you use a tested distribution.' % distro)
409
410# Checks we should only make if MACHINE is set correctly
411def check_sanity_validmachine(sanity_data):
412 messages = ""
413
414 # Check TUNE_ARCH is set
415 if sanity_data.getVar('TUNE_ARCH', True) == 'INVALID':
416 messages = messages + 'TUNE_ARCH is unset. Please ensure your MACHINE configuration includes a valid tune configuration file which will set this correctly.\n'
417
418 # Check TARGET_OS is set
419 if sanity_data.getVar('TARGET_OS', True) == 'INVALID':
420 messages = messages + 'Please set TARGET_OS directly, or choose a MACHINE or DISTRO that does so.\n'
421
422 # Check that we don't have duplicate entries in PACKAGE_ARCHS & that TUNE_PKGARCH is in PACKAGE_ARCHS
423 pkgarchs = sanity_data.getVar('PACKAGE_ARCHS', True)
424 tunepkg = sanity_data.getVar('TUNE_PKGARCH', True)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500425 defaulttune = sanity_data.getVar('DEFAULTTUNE', True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500426 tunefound = False
427 seen = {}
428 dups = []
429
430 for pa in pkgarchs.split():
431 if seen.get(pa, 0) == 1:
432 dups.append(pa)
433 else:
434 seen[pa] = 1
435 if pa == tunepkg:
436 tunefound = True
437
438 if len(dups):
439 messages = messages + "Error, the PACKAGE_ARCHS variable contains duplicates. The following archs are listed more than once: %s" % " ".join(dups)
440
441 if tunefound == False:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500442 messages = messages + "Error, the PACKAGE_ARCHS variable (%s) for DEFAULTTUNE (%s) does not contain TUNE_PKGARCH (%s)." % (pkgarchs, defaulttune, tunepkg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500443
444 return messages
445
446# Checks if necessary to add option march to host gcc
447def check_gcc_march(sanity_data):
448 result = True
449 message = ""
450
451 # Check if -march not in BUILD_CFLAGS
452 if sanity_data.getVar("BUILD_CFLAGS",True).find("-march") < 0:
453 result = False
454
455 # Construct a test file
456 f = open("gcc_test.c", "w")
457 f.write("int main (){ volatile int atomic = 2; __sync_bool_compare_and_swap (&atomic, 2, 3); return 0; }\n")
458 f.close()
459
460 # Check if GCC could work without march
461 if not result:
462 status,res = oe.utils.getstatusoutput("${BUILD_PREFIX}gcc gcc_test.c -o gcc_test")
463 if status == 0:
464 result = True;
465
466 if not result:
467 status,res = oe.utils.getstatusoutput("${BUILD_PREFIX}gcc -march=native gcc_test.c -o gcc_test")
468 if status == 0:
469 message = "BUILD_CFLAGS_append = \" -march=native\""
470 result = True;
471
472 if not result:
473 build_arch = sanity_data.getVar('BUILD_ARCH', True)
474 status,res = oe.utils.getstatusoutput("${BUILD_PREFIX}gcc -march=%s gcc_test.c -o gcc_test" % build_arch)
475 if status == 0:
476 message = "BUILD_CFLAGS_append = \" -march=%s\"" % build_arch
477 result = True;
478
479 os.remove("gcc_test.c")
480 if os.path.exists("gcc_test"):
481 os.remove("gcc_test")
482
483 return (result, message)
484
485# Unpatched versions of make 3.82 are known to be broken. See GNU Savannah Bug 30612.
486# Use a modified reproducer from http://savannah.gnu.org/bugs/?30612 to validate.
487def check_make_version(sanity_data):
488 from distutils.version import LooseVersion
489 status, result = oe.utils.getstatusoutput("make --version")
490 if status != 0:
491 return "Unable to execute make --version, exit code %s\n" % status
492 version = result.split()[2]
493 if LooseVersion(version) == LooseVersion("3.82"):
494 # Construct a test file
495 f = open("makefile_test", "w")
496 f.write("makefile_test.a: makefile_test_a.c makefile_test_b.c makefile_test.a( makefile_test_a.c makefile_test_b.c)\n")
497 f.write("\n")
498 f.write("makefile_test_a.c:\n")
499 f.write(" touch $@\n")
500 f.write("\n")
501 f.write("makefile_test_b.c:\n")
502 f.write(" touch $@\n")
503 f.close()
504
505 # Check if make 3.82 has been patched
506 status,result = oe.utils.getstatusoutput("make -f makefile_test")
507
508 os.remove("makefile_test")
509 if os.path.exists("makefile_test_a.c"):
510 os.remove("makefile_test_a.c")
511 if os.path.exists("makefile_test_b.c"):
512 os.remove("makefile_test_b.c")
513 if os.path.exists("makefile_test.a"):
514 os.remove("makefile_test.a")
515
516 if status != 0:
517 return "Your version of make 3.82 is broken. Please revert to 3.81 or install a patched version.\n"
518 return None
519
520
521# Tar version 1.24 and onwards handle overwriting symlinks correctly
522# but earlier versions do not; this needs to work properly for sstate
523def check_tar_version(sanity_data):
524 from distutils.version import LooseVersion
525 status, result = oe.utils.getstatusoutput("tar --version")
526 if status != 0:
527 return "Unable to execute tar --version, exit code %s\n" % status
528 version = result.split()[3]
529 if LooseVersion(version) < LooseVersion("1.24"):
530 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"
531 return None
532
533# We use git parameters and functionality only found in 1.7.8 or later
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500534# The kernel tools assume git >= 1.8.3.1 (verified needed > 1.7.9.5) see #6162
535# The git fetcher also had workarounds for git < 1.7.9.2 which we've dropped
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500536def check_git_version(sanity_data):
537 from distutils.version import LooseVersion
538 status, result = oe.utils.getstatusoutput("git --version 2> /dev/null")
539 if status != 0:
540 return "Unable to execute git --version, exit code %s\n" % status
541 version = result.split()[2]
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500542 if LooseVersion(version) < LooseVersion("1.8.3.1"):
543 return "Your version of git is older than 1.8.3.1 and has bugs which will break builds. Please install a newer version of git.\n"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500544 return None
545
546# Check the required perl modules which may not be installed by default
547def check_perl_modules(sanity_data):
548 ret = ""
549 modules = ( "Text::ParseWords", "Thread::Queue", "Data::Dumper" )
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500550 errresult = ''
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500551 for m in modules:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500552 status, result = oe.utils.getstatusoutput("perl -e 'use %s'" % m)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500553 if status != 0:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500554 errresult += result
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500555 ret += "%s " % m
556 if ret:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500557 return "Required perl module(s) not found: %s\n\n%s\n" % (ret, errresult)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500558 return None
559
560def sanity_check_conffiles(status, d):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500561 funcs = d.getVar('BBLAYERS_CONF_UPDATE_FUNCS', True).split()
562 for func in funcs:
563 conffile, current_version, required_version, func = func.split(":")
564 if check_conf_exists(conffile, d) and d.getVar(current_version, True) is not None and \
565 d.getVar(current_version, True) != d.getVar(required_version, True):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500566 success = True
567 try:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500568 bb.build.exec_func(func, d, pythonexception=True)
569 except NotImplementedError as e:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500570 success = False
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500571 status.addresult(str(e))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500572 if success:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500573 status.reparse = True
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500574
575def sanity_handle_abichanges(status, d):
576 #
577 # Check the 'ABI' of TMPDIR
578 #
579 import subprocess
580
581 current_abi = d.getVar('OELAYOUT_ABI', True)
582 abifile = d.getVar('SANITY_ABIFILE', True)
583 if os.path.exists(abifile):
584 with open(abifile, "r") as f:
585 abi = f.read().strip()
586 if not abi.isdigit():
587 with open(abifile, "w") as f:
588 f.write(current_abi)
589 elif abi == "2" and current_abi == "3":
590 bb.note("Converting staging from layout version 2 to layout version 3")
591 subprocess.call(d.expand("mv ${TMPDIR}/staging ${TMPDIR}/sysroots"), shell=True)
592 subprocess.call(d.expand("ln -s sysroots ${TMPDIR}/staging"), shell=True)
593 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)
594 with open(abifile, "w") as f:
595 f.write(current_abi)
596 elif abi == "3" and current_abi == "4":
597 bb.note("Converting staging layout from version 3 to layout version 4")
598 if os.path.exists(d.expand("${STAGING_DIR_NATIVE}${bindir_native}/${MULTIMACH_HOST_SYS}")):
599 subprocess.call(d.expand("mv ${STAGING_DIR_NATIVE}${bindir_native}/${MULTIMACH_HOST_SYS} ${STAGING_BINDIR_CROSS}"), shell=True)
600 subprocess.call(d.expand("ln -s ${STAGING_BINDIR_CROSS} ${STAGING_DIR_NATIVE}${bindir_native}/${MULTIMACH_HOST_SYS}"), shell=True)
601 with open(abifile, "w") as f:
602 f.write(current_abi)
603 elif abi == "4":
604 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")
605 elif abi == "5" and current_abi == "6":
606 bb.note("Converting staging layout from version 5 to layout version 6")
607 subprocess.call(d.expand("mv ${TMPDIR}/pstagelogs ${SSTATE_MANIFESTS}"), shell=True)
608 with open(abifile, "w") as f:
609 f.write(current_abi)
610 elif abi == "7" and current_abi == "8":
611 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")
612 elif (abi != current_abi and current_abi == "9"):
613 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")
614 elif (abi != current_abi and current_abi == "10" and (abi == "8" or abi == "9")):
615 bb.note("Converting staging layout from version 8/9 to layout version 10")
616 cmd = d.expand("grep -r -l sysroot-providers/virtual_kernel ${SSTATE_MANIFESTS}")
617 ret, result = oe.utils.getstatusoutput(cmd)
618 result = result.split()
619 for f in result:
620 bb.note("Uninstalling manifest file %s" % f)
621 sstate_clean_manifest(f, d)
622 with open(abifile, "w") as f:
623 f.write(current_abi)
624 elif abi == "10" and current_abi == "11":
625 bb.note("Converting staging layout from version 10 to layout version 11")
626 # Files in xf86-video-modesetting moved to xserver-xorg and bitbake can't currently handle that:
627 subprocess.call(d.expand("rm ${TMPDIR}/sysroots/*/usr/lib/xorg/modules/drivers/modesetting_drv.so ${TMPDIR}/sysroots/*/pkgdata/runtime/xf86-video-modesetting* ${TMPDIR}/sysroots/*/pkgdata/runtime-reverse/xf86-video-modesetting* ${TMPDIR}/sysroots/*/pkgdata/shlibs2/xf86-video-modesetting*"), shell=True)
628 with open(abifile, "w") as f:
629 f.write(current_abi)
630 elif (abi != current_abi):
631 # Code to convert from one ABI to another could go here if possible.
632 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))
633 else:
634 with open(abifile, "w") as f:
635 f.write(current_abi)
636
637def check_sanity_sstate_dir_change(sstate_dir, data):
638 # Sanity checks to be done when the value of SSTATE_DIR changes
639
640 # Check that SSTATE_DIR isn't on a filesystem with limited filename length (eg. eCryptFS)
641 testmsg = ""
642 if sstate_dir != "":
643 testmsg = check_create_long_filename(sstate_dir, "SSTATE_DIR")
644 # If we don't have permissions to SSTATE_DIR, suggest the user set it as an SSTATE_MIRRORS
645 try:
646 err = testmsg.split(': ')[1].strip()
647 if err == "Permission denied.":
648 testmsg = testmsg + "You could try using %s in SSTATE_MIRRORS rather than as an SSTATE_CACHE.\n" % (sstate_dir)
649 except IndexError:
650 pass
651 return testmsg
652
653def check_sanity_version_change(status, d):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500654 # Sanity checks to be done when SANITY_VERSION or NATIVELSBSTRING changes
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500655 # In other words, these tests run once in a given build directory and then
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500656 # never again until the sanity version or host distrubution id/version changes.
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500657
658 # Check the python install is complete. glib-2.0-natives requries
659 # xml.parsers.expat
660 try:
661 import xml.parsers.expat
662 except ImportError:
663 status.addresult('Your python is not a full install. Please install the module xml.parsers.expat (python-xml on openSUSE and SUSE Linux).\n')
664 import stat
665
666 status.addresult(check_make_version(d))
667 status.addresult(check_tar_version(d))
668 status.addresult(check_git_version(d))
669 status.addresult(check_perl_modules(d))
670
671 missing = ""
672
673 if not check_app_exists("${MAKE}", d):
674 missing = missing + "GNU make,"
675
676 if not check_app_exists('${BUILD_PREFIX}gcc', d):
677 missing = missing + "C Compiler (%sgcc)," % d.getVar("BUILD_PREFIX", True)
678
679 if not check_app_exists('${BUILD_PREFIX}g++', d):
680 missing = missing + "C++ Compiler (%sg++)," % d.getVar("BUILD_PREFIX", True)
681
682 required_utilities = d.getVar('SANITY_REQUIRED_UTILITIES', True)
683
684 for util in required_utilities.split():
685 if not check_app_exists(util, d):
686 missing = missing + "%s," % util
687
688 if missing:
689 missing = missing.rstrip(',')
690 status.addresult("Please install the following missing utilities: %s\n" % missing)
691
692 assume_provided = d.getVar('ASSUME_PROVIDED', True).split()
693 # Check user doesn't have ASSUME_PROVIDED = instead of += in local.conf
694 if "diffstat-native" not in assume_provided:
695 status.addresult('Please use ASSUME_PROVIDED +=, not ASSUME_PROVIDED = in your local.conf\n')
696
697 if "qemu-native" in assume_provided:
698 if not check_app_exists("qemu-arm", d):
699 status.addresult("qemu-native was in ASSUME_PROVIDED but the QEMU binaries (qemu-arm) can't be found in PATH")
700
701 if "libsdl-native" in assume_provided:
702 if not check_app_exists("sdl-config", d):
703 status.addresult("libsdl-native is set to be ASSUME_PROVIDED but sdl-config can't be found in PATH. Please either install it, or configure qemu not to require sdl.")
704
705 (result, message) = check_gcc_march(d)
706 if result and message:
707 status.addresult("Your gcc version is older than 4.5, please add the following param to local.conf\n \
708 %s\n" % message)
709 if not result:
710 status.addresult("Your gcc version is older than 4.5 or is not working properly. Please verify you can build")
711 status.addresult(" and link something that uses atomic operations, such as: \n")
712 status.addresult(" __sync_bool_compare_and_swap (&atomic, 2, 3);\n")
713
714 # Check that TMPDIR isn't on a filesystem with limited filename length (eg. eCryptFS)
715 tmpdir = d.getVar('TMPDIR', True)
716 status.addresult(check_create_long_filename(tmpdir, "TMPDIR"))
717 tmpdirmode = os.stat(tmpdir).st_mode
718 if (tmpdirmode & stat.S_ISGID):
719 status.addresult("TMPDIR is setgid, please don't build in a setgid directory")
720 if (tmpdirmode & stat.S_ISUID):
721 status.addresult("TMPDIR is setuid, please don't build in a setuid directory")
722
723 # Some third-party software apparently relies on chmod etc. being suid root (!!)
724 import stat
725 suid_check_bins = "chown chmod mknod".split()
726 for bin_cmd in suid_check_bins:
727 bin_path = bb.utils.which(os.environ["PATH"], bin_cmd)
728 if bin_path:
729 bin_stat = os.stat(bin_path)
730 if bin_stat.st_uid == 0 and bin_stat.st_mode & stat.S_ISUID:
731 status.addresult('%s has the setuid bit set. This interferes with pseudo and may cause other issues that break the build process.\n' % bin_path)
732
733 # Check that we can fetch from various network transports
734 netcheck = check_connectivity(d)
735 status.addresult(netcheck)
736 if netcheck:
737 status.network_error = True
738
739 nolibs = d.getVar('NO32LIBS', True)
740 if not nolibs:
741 lib32path = '/lib'
742 if os.path.exists('/lib64') and ( os.path.islink('/lib64') or os.path.islink('/lib') ):
743 lib32path = '/lib32'
744
745 if os.path.exists('%s/libc.so.6' % lib32path) and not os.path.exists('/usr/include/gnu/stubs-32.h'):
746 status.addresult("You have a 32-bit libc, but no 32-bit headers. You must install the 32-bit libc headers.\n")
747
748 bbpaths = d.getVar('BBPATH', True).split(":")
749 if ("." in bbpaths or "./" in bbpaths or "" in bbpaths) and not status.reparse:
750 status.addresult("BBPATH references the current directory, either through " \
751 "an empty entry, a './' or a '.'.\n\t This is unsafe and means your "\
752 "layer configuration is adding empty elements to BBPATH.\n\t "\
753 "Please check your layer.conf files and other BBPATH " \
754 "settings to remove the current working directory " \
755 "references.\n" \
756 "Parsed BBPATH is" + str(bbpaths));
757
758 oes_bb_conf = d.getVar( 'OES_BITBAKE_CONF', True)
759 if not oes_bb_conf:
760 status.addresult('You are not using the OpenEmbedded version of conf/bitbake.conf. This means your environment is misconfigured, in particular check BBPATH.\n')
761
762 # The length of TMPDIR can't be longer than 410
763 status.addresult(check_path_length(tmpdir, "TMPDIR", 410))
764
765 # Check that TMPDIR isn't located on nfs
766 status.addresult(check_not_nfs(tmpdir, "TMPDIR"))
767
768def check_sanity_everybuild(status, d):
769 import os, stat
770 # Sanity tests which test the users environment so need to run at each build (or are so cheap
771 # it makes sense to always run them.
772
773 if 0 == os.getuid():
774 raise_sanity_error("Do not use Bitbake as root.", d)
775
776 # Check the Python version, we now have a minimum of Python 2.7.3
777 import sys
778 if sys.hexversion < 0x020703F0:
779 status.addresult('The system requires at least Python 2.7.3 to run. Please update your Python interpreter.\n')
780
781 # Check the bitbake version meets minimum requirements
782 from distutils.version import LooseVersion
783 minversion = d.getVar('BB_MIN_VERSION', True)
784 if (LooseVersion(bb.__version__) < LooseVersion(minversion)):
785 status.addresult('Bitbake version %s is required and version %s was found\n' % (minversion, bb.__version__))
786
787 sanity_check_conffiles(status, d)
788
789 paths = d.getVar('PATH', True).split(":")
790 if "." in paths or "./" in paths or "" in paths:
791 status.addresult("PATH contains '.', './' or '' (empty element), which will break the build, please remove this.\nParsed PATH is " + str(paths) + "\n")
792
793 # Check that the DISTRO is valid, if set
794 # need to take into account DISTRO renaming DISTRO
795 distro = d.getVar('DISTRO', True)
796 if distro and distro != "nodistro":
797 if not ( check_conf_exists("conf/distro/${DISTRO}.conf", d) or check_conf_exists("conf/distro/include/${DISTRO}.inc", d) ):
798 status.addresult("DISTRO '%s' not found. Please set a valid DISTRO in your local.conf\n" % d.getVar("DISTRO", True))
799
800 # Check that DL_DIR is set, exists and is writable. In theory, we should never even hit the check if DL_DIR isn't
801 # set, since so much relies on it being set.
802 dldir = d.getVar('DL_DIR', True)
803 if not dldir:
804 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")
805 if os.path.exists(dldir) and not os.access(dldir, os.W_OK):
806 status.addresult("DL_DIR: %s exists but you do not appear to have write access to it. \n" % dldir)
807 check_symlink(dldir, d)
808
809 # Check that the MACHINE is valid, if it is set
810 machinevalid = True
811 if d.getVar('MACHINE', True):
812 if not check_conf_exists("conf/machine/${MACHINE}.conf", d):
813 status.addresult('Please set a valid MACHINE in your local.conf or environment\n')
814 machinevalid = False
815 else:
816 status.addresult(check_sanity_validmachine(d))
817 else:
818 status.addresult('Please set a MACHINE in your local.conf or environment\n')
819 machinevalid = False
820 if machinevalid:
821 status.addresult(check_toolchain(d))
822
823 # Check that the SDKMACHINE is valid, if it is set
824 if d.getVar('SDKMACHINE', True):
825 if not check_conf_exists("conf/machine-sdk/${SDKMACHINE}.conf", d):
826 status.addresult('Specified SDKMACHINE value is not valid\n')
827 elif d.getVar('SDK_ARCH', False) == "${BUILD_ARCH}":
828 status.addresult('SDKMACHINE is set, but SDK_ARCH has not been changed as a result - SDKMACHINE may have been set too late (e.g. in the distro configuration)\n')
829
830 check_supported_distro(d)
831
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500832 omask = os.umask(022)
833 if omask & 0755:
834 status.addresult("Please use a umask which allows a+rx and u+rwx\n")
835 os.umask(omask)
836
837 if d.getVar('TARGET_ARCH', True) == "arm":
838 # This path is no longer user-readable in modern (very recent) Linux
839 try:
840 if os.path.exists("/proc/sys/vm/mmap_min_addr"):
841 f = open("/proc/sys/vm/mmap_min_addr", "r")
842 try:
843 if (int(f.read().strip()) > 65536):
844 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")
845 finally:
846 f.close()
847 except:
848 pass
849
850 oeroot = d.getVar('COREBASE', True)
851 if oeroot.find('+') != -1:
852 status.addresult("Error, you have an invalid character (+) in your COREBASE directory path. Please move the installation to a directory which doesn't include any + characters.")
853 if oeroot.find('@') != -1:
854 status.addresult("Error, you have an invalid character (@) in your COREBASE directory path. Please move the installation to a directory which doesn't include any @ characters.")
855 if oeroot.find(' ') != -1:
856 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 since autotools doesn't support this.")
857
858 # Check the format of MIRRORS, PREMIRRORS and SSTATE_MIRRORS
859 import re
860 mirror_vars = ['MIRRORS', 'PREMIRRORS', 'SSTATE_MIRRORS']
861 protocols = ['http', 'ftp', 'file', 'https', \
862 'git', 'gitsm', 'hg', 'osc', 'p4', 'svn', \
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500863 'bzr', 'cvs', 'npm', 'sftp', 'ssh']
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500864 for mirror_var in mirror_vars:
865 mirrors = (d.getVar(mirror_var, True) or '').replace('\\n', '\n').split('\n')
866 for mirror_entry in mirrors:
867 mirror_entry = mirror_entry.strip()
868 if not mirror_entry:
869 # ignore blank lines
870 continue
871
872 try:
873 pattern, mirror = mirror_entry.split()
874 except ValueError:
875 bb.warn('Invalid %s: %s, should be 2 members.' % (mirror_var, mirror_entry.strip()))
876 continue
877
878 decoded = bb.fetch2.decodeurl(pattern)
879 try:
880 pattern_scheme = re.compile(decoded[0])
881 except re.error as exc:
882 bb.warn('Invalid scheme regex (%s) in %s; %s' % (pattern, mirror_var, mirror_entry))
883 continue
884
885 if not any(pattern_scheme.match(protocol) for protocol in protocols):
886 bb.warn('Invalid protocol (%s) in %s: %s' % (decoded[0], mirror_var, mirror_entry))
887 continue
888
889 if not any(mirror.startswith(protocol + '://') for protocol in protocols):
890 bb.warn('Invalid protocol in %s: %s' % (mirror_var, mirror_entry))
891 continue
892
893 if mirror.startswith('file://'):
894 import urlparse
895 check_symlink(urlparse.urlparse(mirror).path, d)
896 # SSTATE_MIRROR ends with a /PATH string
897 if mirror.endswith('/PATH'):
898 # remove /PATH$ from SSTATE_MIRROR to get a working
899 # base directory path
900 mirror_base = urlparse.urlparse(mirror[:-1*len('/PATH')]).path
901 check_symlink(mirror_base, d)
902
903 # Check that TMPDIR hasn't changed location since the last time we were run
904 tmpdir = d.getVar('TMPDIR', True)
905 checkfile = os.path.join(tmpdir, "saved_tmpdir")
906 if os.path.exists(checkfile):
907 with open(checkfile, "r") as f:
908 saved_tmpdir = f.read().strip()
909 if (saved_tmpdir != tmpdir):
910 status.addresult("Error, TMPDIR has changed location. You need to either move it back to %s or rebuild\n" % saved_tmpdir)
911 else:
912 bb.utils.mkdirhier(tmpdir)
913 # Remove setuid, setgid and sticky bits from TMPDIR
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500914 try:
915 os.chmod(tmpdir, os.stat(tmpdir).st_mode & ~ stat.S_ISUID)
916 os.chmod(tmpdir, os.stat(tmpdir).st_mode & ~ stat.S_ISGID)
917 os.chmod(tmpdir, os.stat(tmpdir).st_mode & ~ stat.S_ISVTX)
918 except OSError as exc:
919 bb.warn("Unable to chmod TMPDIR: %s" % exc)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500920 with open(checkfile, "w") as f:
921 f.write(tmpdir)
922
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500923 # Check /bin/sh links to dash or bash
924 real_sh = os.path.realpath('/bin/sh')
925 if not real_sh.endswith('/dash') and not real_sh.endswith('/bash'):
926 status.addresult("Error, /bin/sh links to %s, must be dash or bash\n" % real_sh)
927
928def check_sanity(sanity_data):
929 class SanityStatus(object):
930 def __init__(self):
931 self.messages = ""
932 self.network_error = False
933 self.reparse = False
934
935 def addresult(self, message):
936 if message:
937 self.messages = self.messages + message
938
939 status = SanityStatus()
940
941 tmpdir = sanity_data.getVar('TMPDIR', True)
942 sstate_dir = sanity_data.getVar('SSTATE_DIR', True)
943
944 check_symlink(sstate_dir, sanity_data)
945
946 # Check saved sanity info
947 last_sanity_version = 0
948 last_tmpdir = ""
949 last_sstate_dir = ""
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500950 last_nativelsbstr = ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500951 sanityverfile = sanity_data.expand("${TOPDIR}/conf/sanity_info")
952 if os.path.exists(sanityverfile):
953 with open(sanityverfile, 'r') as f:
954 for line in f:
955 if line.startswith('SANITY_VERSION'):
956 last_sanity_version = int(line.split()[1])
957 if line.startswith('TMPDIR'):
958 last_tmpdir = line.split()[1]
959 if line.startswith('SSTATE_DIR'):
960 last_sstate_dir = line.split()[1]
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500961 if line.startswith('NATIVELSBSTRING'):
962 last_nativelsbstr = line.split()[1]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500963
964 check_sanity_everybuild(status, sanity_data)
965
966 sanity_version = int(sanity_data.getVar('SANITY_VERSION', True) or 1)
967 network_error = False
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500968 # NATIVELSBSTRING var may have been overridden with "universal", so
969 # get actual host distribution id and version
970 nativelsbstr = lsb_distro_identifier(sanity_data)
971 if last_sanity_version < sanity_version or last_nativelsbstr != nativelsbstr:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500972 check_sanity_version_change(status, sanity_data)
973 status.addresult(check_sanity_sstate_dir_change(sstate_dir, sanity_data))
974 else:
975 if last_sstate_dir != sstate_dir:
976 status.addresult(check_sanity_sstate_dir_change(sstate_dir, sanity_data))
977
978 if os.path.exists(os.path.dirname(sanityverfile)) and not status.messages:
979 with open(sanityverfile, 'w') as f:
980 f.write("SANITY_VERSION %s\n" % sanity_version)
981 f.write("TMPDIR %s\n" % tmpdir)
982 f.write("SSTATE_DIR %s\n" % sstate_dir)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500983 f.write("NATIVELSBSTRING %s\n" % nativelsbstr)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500984
985 sanity_handle_abichanges(status, sanity_data)
986
987 if status.messages != "":
988 raise_sanity_error(sanity_data.expand(status.messages), sanity_data, status.network_error)
989 return status.reparse
990
991# Create a copy of the datastore and finalise it to ensure appends and
992# overrides are set - the datastore has yet to be finalised at ConfigParsed
993def copy_data(e):
994 sanity_data = bb.data.createCopy(e.data)
995 sanity_data.finalize()
996 return sanity_data
997
998addhandler check_sanity_eventhandler
999check_sanity_eventhandler[eventmask] = "bb.event.SanityCheck bb.event.NetworkTest"
1000python check_sanity_eventhandler() {
1001 if bb.event.getName(e) == "SanityCheck":
1002 sanity_data = copy_data(e)
1003 if e.generateevents:
1004 sanity_data.setVar("SANITY_USE_EVENTS", "1")
1005 reparse = check_sanity(sanity_data)
1006 e.data.setVar("BB_INVALIDCONF", reparse)
1007 bb.event.fire(bb.event.SanityCheckPassed(), e.data)
1008 elif bb.event.getName(e) == "NetworkTest":
1009 sanity_data = copy_data(e)
1010 if e.generateevents:
1011 sanity_data.setVar("SANITY_USE_EVENTS", "1")
1012 bb.event.fire(bb.event.NetworkTestFailed() if check_connectivity(sanity_data) else bb.event.NetworkTestPassed(), e.data)
1013
1014 return
1015}