blob: 63ab6cf3df678ec45b5a9b2b75a49c60b312eb94 [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 \
Brad Bishop6e60e8b2018-02-01 10:27:11 -05006 gzip gawk chrpath wget cpio perl file which"
Patrick Williamsc124f4f2015-09-15 14:41:29 -05007
8def bblayers_conf_file(d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -05009 return os.path.join(d.getVar('TOPDIR'), 'conf/bblayers.conf')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050010
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
Brad Bishop6e60e8b2018-02-01 10:27:11 -050042 current_conf = d.getVar('CONF_VERSION')
43 conf_version = d.getVar('LOCALCONF_VERSION')
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050044
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
Brad Bishop6e60e8b2018-02-01 10:27:11 -050062 current_sconf = d.getVar('SCONF_VERSION')
63 sconf_version = d.getVar('SITE_CONF_VERSION')
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050064
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
Brad Bishop6e60e8b2018-02-01 10:27:11 -050083 current_lconf = int(d.getVar('LCONF_VERSION'))
84 lconf_version = int(d.getVar('LAYER_CONF_VERSION'))
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 Williamsc0f7c042017-02-23 20:41:17 -0600138 status.addresult()
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500139
140 elif current_lconf == 6 and lconf_version > 6:
141 # Handle rename of meta-yocto -> meta-poky
142 # This marks the start of separate version numbers but code is needed in OE-Core
143 # for the migration, one last time.
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500144 layers = d.getVar('BBLAYERS').split()
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500145 layers = [ os.path.basename(path) for path in layers ]
146 if 'meta-yocto' in layers:
147 found = False
148 while True:
149 index, meta_yocto_line = sanity_conf_find_line(r'.*meta-yocto[\'"\s\n]', lines)
150 if meta_yocto_line:
151 lines[index] = meta_yocto_line.replace('meta-yocto', 'meta-poky')
152 found = True
153 else:
154 break
155 if not found:
156 raise NotImplementedError(failmsg)
157 index, meta_yocto_line = sanity_conf_find_line('LCONF_VERSION.*\n', lines)
158 if meta_yocto_line:
159 lines[index] = 'POKY_BBLAYERS_CONF_VERSION = "1"\n'
160 else:
161 raise NotImplementedError(failmsg)
162 with open(bblayers_fn, "w") as f:
163 f.write(''.join(lines))
164 bb.note("Your conf/bblayers.conf has been automatically updated.")
165 return
166 current_lconf += 1
167 sanity_conf_update(bblayers_fn, lines, 'LCONF_VERSION', current_lconf)
168 bb.note("Your conf/bblayers.conf has been automatically updated.")
169 return
170
171 raise NotImplementedError(failmsg)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500172}
173
174def raise_sanity_error(msg, d, network_error=False):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500175 if d.getVar("SANITY_USE_EVENTS") == "1":
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500176 try:
177 bb.event.fire(bb.event.SanityCheckFailed(msg, network_error), d)
178 except TypeError:
179 bb.event.fire(bb.event.SanityCheckFailed(msg), d)
180 return
181
182 bb.fatal(""" OE-core's config sanity checker detected a potential misconfiguration.
183 Either fix the cause of this error or at your own risk disable the checker (see sanity.conf).
184 Following is the list of potential problems / advisories:
185
186 %s""" % msg)
187
188# Check flags associated with a tuning.
189def check_toolchain_tune_args(data, tune, multilib, errs):
190 found_errors = False
191 if check_toolchain_args_present(data, tune, multilib, errs, 'CCARGS'):
192 found_errors = True
193 if check_toolchain_args_present(data, tune, multilib, errs, 'ASARGS'):
194 found_errors = True
195 if check_toolchain_args_present(data, tune, multilib, errs, 'LDARGS'):
196 found_errors = True
197
198 return found_errors
199
200def check_toolchain_args_present(data, tune, multilib, tune_errors, which):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500201 args_set = (data.getVar("TUNE_%s" % which) or "").split()
202 args_wanted = (data.getVar("TUNEABI_REQUIRED_%s_tune-%s" % (which, tune)) or "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500203 args_missing = []
204
205 # If no args are listed/required, we are done.
206 if not args_wanted:
207 return
208 for arg in args_wanted:
209 if arg not in args_set:
210 args_missing.append(arg)
211
212 found_errors = False
213 if args_missing:
214 found_errors = True
215 tune_errors.append("TUNEABI for %s requires '%s' in TUNE_%s (%s)." %
216 (tune, ' '.join(args_missing), which, ' '.join(args_set)))
217 return found_errors
218
219# Check a single tune for validity.
220def check_toolchain_tune(data, tune, multilib):
221 tune_errors = []
222 if not tune:
223 return "No tuning found for %s multilib." % multilib
224 localdata = bb.data.createCopy(data)
225 if multilib != "default":
226 # Apply the overrides so we can look at the details.
227 overrides = localdata.getVar("OVERRIDES", False) + ":virtclass-multilib-" + multilib
228 localdata.setVar("OVERRIDES", overrides)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500229 bb.debug(2, "Sanity-checking tuning '%s' (%s) features:" % (tune, multilib))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500230 features = (localdata.getVar("TUNE_FEATURES_tune-%s" % tune) or "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500231 if not features:
232 return "Tuning '%s' has no defined features, and cannot be used." % tune
233 valid_tunes = localdata.getVarFlags('TUNEVALID') or {}
234 conflicts = localdata.getVarFlags('TUNECONFLICTS') or {}
235 # [doc] is the documentation for the variable, not a real feature
236 if 'doc' in valid_tunes:
237 del valid_tunes['doc']
238 if 'doc' in conflicts:
239 del conflicts['doc']
240 for feature in features:
241 if feature in conflicts:
242 for conflict in conflicts[feature].split():
243 if conflict in features:
244 tune_errors.append("Feature '%s' conflicts with '%s'." %
245 (feature, conflict))
246 if feature in valid_tunes:
247 bb.debug(2, " %s: %s" % (feature, valid_tunes[feature]))
248 else:
249 tune_errors.append("Feature '%s' is not defined." % feature)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500250 whitelist = localdata.getVar("TUNEABI_WHITELIST")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500251 if whitelist:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500252 tuneabi = localdata.getVar("TUNEABI_tune-%s" % tune)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500253 if not tuneabi:
254 tuneabi = tune
255 if True not in [x in whitelist.split() for x in tuneabi.split()]:
256 tune_errors.append("Tuning '%s' (%s) cannot be used with any supported tuning/ABI." %
257 (tune, tuneabi))
258 else:
259 if not check_toolchain_tune_args(localdata, tuneabi, multilib, tune_errors):
260 bb.debug(2, "Sanity check: Compiler args OK for %s." % tune)
261 if tune_errors:
262 return "Tuning '%s' has the following errors:\n" % tune + '\n'.join(tune_errors)
263
264def check_toolchain(data):
265 tune_error_set = []
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500266 deftune = data.getVar("DEFAULTTUNE")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500267 tune_errors = check_toolchain_tune(data, deftune, 'default')
268 if tune_errors:
269 tune_error_set.append(tune_errors)
270
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500271 multilibs = (data.getVar("MULTILIB_VARIANTS") or "").split()
272 global_multilibs = (data.getVar("MULTILIB_GLOBAL_VARIANTS") or "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500273
274 if multilibs:
275 seen_libs = []
276 seen_tunes = []
277 for lib in multilibs:
278 if lib in seen_libs:
279 tune_error_set.append("The multilib '%s' appears more than once." % lib)
280 else:
281 seen_libs.append(lib)
282 if not lib in global_multilibs:
283 tune_error_set.append("Multilib %s is not present in MULTILIB_GLOBAL_VARIANTS" % lib)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500284 tune = data.getVar("DEFAULTTUNE_virtclass-multilib-%s" % lib)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500285 if tune in seen_tunes:
286 tune_error_set.append("The tuning '%s' appears in more than one multilib." % tune)
287 else:
288 seen_libs.append(tune)
289 if tune == deftune:
290 tune_error_set.append("Multilib '%s' (%s) is also the default tuning." % (lib, deftune))
291 else:
292 tune_errors = check_toolchain_tune(data, tune, lib)
293 if tune_errors:
294 tune_error_set.append(tune_errors)
295 if tune_error_set:
296 return "Toolchain tunings invalid:\n" + '\n'.join(tune_error_set) + "\n"
297
298 return ""
299
300def check_conf_exists(fn, data):
301 bbpath = []
302 fn = data.expand(fn)
303 vbbpath = data.getVar("BBPATH", False)
304 if vbbpath:
305 bbpath += vbbpath.split(":")
306 for p in bbpath:
307 currname = os.path.join(data.expand(p), fn)
308 if os.access(currname, os.R_OK):
309 return True
310 return False
311
312def check_create_long_filename(filepath, pathname):
313 import string, random
314 testfile = os.path.join(filepath, ''.join(random.choice(string.ascii_letters) for x in range(200)))
315 try:
316 if not os.path.exists(filepath):
317 bb.utils.mkdirhier(filepath)
318 f = open(testfile, "w")
319 f.close()
320 os.remove(testfile)
321 except IOError as e:
322 import errno
323 err, strerror = e.args
324 if err == errno.ENAMETOOLONG:
325 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
326 else:
327 return "Failed to create a file in %s: %s.\n" % (pathname, strerror)
328 except OSError as e:
329 errno, strerror = e.args
330 return "Failed to create %s directory in which to run long name sanity check: %s.\n" % (pathname, strerror)
331 return ""
332
333def check_path_length(filepath, pathname, limit):
334 if len(filepath) > limit:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500335 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 -0500336 return ""
337
338def get_filesystem_id(path):
Brad Bishopd5ae7d92018-06-14 09:52:03 -0700339 import subprocess
340 try:
Brad Bishop19323692019-04-05 15:28:33 -0400341 return subprocess.check_output(["stat", "-f", "-c", "%t", path]).decode('utf-8').strip()
Brad Bishopd5ae7d92018-06-14 09:52:03 -0700342 except subprocess.CalledProcessError:
343 bb.warn("Can't get filesystem id of: %s" % path)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500344 return None
345
346# Check that the path isn't located on nfs.
347def check_not_nfs(path, name):
348 # The nfs' filesystem id is 6969
349 if get_filesystem_id(path) == "6969":
350 return "The %s: %s can't be located on nfs.\n" % (name, path)
351 return ""
352
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500353# Check that the path is on a case-sensitive file system
354def check_case_sensitive(path, name):
355 import tempfile
356 with tempfile.NamedTemporaryFile(prefix='TmP', dir=path) as tmp_file:
357 if os.path.exists(tmp_file.name.lower()):
358 return "The %s (%s) can't be on a case-insensitive file system.\n" % (name, path)
359 return ""
360
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500361# Check that path isn't a broken symlink
362def check_symlink(lnk, data):
363 if os.path.islink(lnk) and not os.path.exists(lnk):
364 raise_sanity_error("%s is a broken symlink." % lnk, data)
365
366def check_connectivity(d):
367 # URI's to check can be set in the CONNECTIVITY_CHECK_URIS variable
368 # using the same syntax as for SRC_URI. If the variable is not set
369 # the check is skipped
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500370 test_uris = (d.getVar('CONNECTIVITY_CHECK_URIS') or "").split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500371 retval = ""
372
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500373 bbn = d.getVar('BB_NO_NETWORK')
374 if bbn not in (None, '0', '1'):
375 return 'BB_NO_NETWORK should be "0" or "1", but it is "%s"' % bbn
376
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500377 # Only check connectivity if network enabled and the
378 # CONNECTIVITY_CHECK_URIS are set
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500379 network_enabled = not (bbn == '1')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500380 check_enabled = len(test_uris)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500381 if check_enabled and network_enabled:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500382 # Take a copy of the data store and unset MIRRORS and PREMIRRORS
383 data = bb.data.createCopy(d)
384 data.delVar('PREMIRRORS')
385 data.delVar('MIRRORS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500386 try:
387 fetcher = bb.fetch2.Fetch(test_uris, data)
388 fetcher.checkstatus()
389 except Exception as err:
390 # Allow the message to be configured so that users can be
391 # pointed to a support mechanism.
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500392 msg = data.getVar('CONNECTIVITY_CHECK_MSG') or ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500393 if len(msg) == 0:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500394 msg = "%s.\n" % err
395 msg += " Please ensure your host's network is configured correctly,\n"
396 msg += " or set BB_NO_NETWORK = \"1\" to disable network access if\n"
397 msg += " all required sources are on local disk.\n"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500398 retval = msg
399
400 return retval
401
402def check_supported_distro(sanity_data):
403 from fnmatch import fnmatch
404
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500405 tested_distros = sanity_data.getVar('SANITY_TESTED_DISTROS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500406 if not tested_distros:
407 return
408
409 try:
410 distro = oe.lsb.distro_identifier()
411 except Exception:
412 distro = None
413
414 if not distro:
415 bb.warn('Host distribution could not be determined; you may possibly experience unexpected failures. It is recommended that you use a tested distribution.')
416
417 for supported in [x.strip() for x in tested_distros.split('\\n')]:
418 if fnmatch(distro, supported):
419 return
420
421 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)
422
423# Checks we should only make if MACHINE is set correctly
424def check_sanity_validmachine(sanity_data):
425 messages = ""
426
427 # Check TUNE_ARCH is set
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500428 if sanity_data.getVar('TUNE_ARCH') == 'INVALID':
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500429 messages = messages + 'TUNE_ARCH is unset. Please ensure your MACHINE configuration includes a valid tune configuration file which will set this correctly.\n'
430
431 # Check TARGET_OS is set
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500432 if sanity_data.getVar('TARGET_OS') == 'INVALID':
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500433 messages = messages + 'Please set TARGET_OS directly, or choose a MACHINE or DISTRO that does so.\n'
434
435 # Check that we don't have duplicate entries in PACKAGE_ARCHS & that TUNE_PKGARCH is in PACKAGE_ARCHS
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500436 pkgarchs = sanity_data.getVar('PACKAGE_ARCHS')
437 tunepkg = sanity_data.getVar('TUNE_PKGARCH')
438 defaulttune = sanity_data.getVar('DEFAULTTUNE')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500439 tunefound = False
440 seen = {}
441 dups = []
442
443 for pa in pkgarchs.split():
444 if seen.get(pa, 0) == 1:
445 dups.append(pa)
446 else:
447 seen[pa] = 1
448 if pa == tunepkg:
449 tunefound = True
450
451 if len(dups):
452 messages = messages + "Error, the PACKAGE_ARCHS variable contains duplicates. The following archs are listed more than once: %s" % " ".join(dups)
453
454 if tunefound == False:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500455 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 -0500456
457 return messages
458
Brad Bishop316dfdd2018-06-25 12:45:53 -0400459# Patch before 2.7 can't handle all the features in git-style diffs. Some
460# patches may incorrectly apply, and others won't apply at all.
461def check_patch_version(sanity_data):
462 from distutils.version import LooseVersion
463 import re, subprocess
464
465 try:
Brad Bishopd5ae7d92018-06-14 09:52:03 -0700466 result = subprocess.check_output(["patch", "--version"], stderr=subprocess.STDOUT).decode('utf-8')
Brad Bishop316dfdd2018-06-25 12:45:53 -0400467 version = re.search(r"[0-9.]+", result.splitlines()[0]).group()
468 if LooseVersion(version) < LooseVersion("2.7"):
469 return "Your version of patch is older than 2.7 and has bugs which will break builds. Please install a newer version of patch.\n"
470 else:
471 return None
472 except subprocess.CalledProcessError as e:
473 return "Unable to execute patch --version, exit code %d:\n%s\n" % (e.returncode, e.output)
474
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500475# Unpatched versions of make 3.82 are known to be broken. See GNU Savannah Bug 30612.
476# Use a modified reproducer from http://savannah.gnu.org/bugs/?30612 to validate.
477def check_make_version(sanity_data):
478 from distutils.version import LooseVersion
Brad Bishopd5ae7d92018-06-14 09:52:03 -0700479 import subprocess
480
481 try:
482 result = subprocess.check_output(['make', '--version'], stderr=subprocess.STDOUT).decode('utf-8')
483 except subprocess.CalledProcessError as e:
484 return "Unable to execute make --version, exit code %d\n%s\n" % (e.returncode, e.output)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500485 version = result.split()[2]
486 if LooseVersion(version) == LooseVersion("3.82"):
487 # Construct a test file
488 f = open("makefile_test", "w")
489 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")
490 f.write("\n")
491 f.write("makefile_test_a.c:\n")
492 f.write(" touch $@\n")
493 f.write("\n")
494 f.write("makefile_test_b.c:\n")
495 f.write(" touch $@\n")
496 f.close()
497
498 # Check if make 3.82 has been patched
Brad Bishopd5ae7d92018-06-14 09:52:03 -0700499 try:
500 subprocess.check_call(['make', '-f', 'makefile_test'])
501 except subprocess.CalledProcessError as e:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500502 return "Your version of make 3.82 is broken. Please revert to 3.81 or install a patched version.\n"
Brad Bishopd5ae7d92018-06-14 09:52:03 -0700503 finally:
504 os.remove("makefile_test")
505 if os.path.exists("makefile_test_a.c"):
506 os.remove("makefile_test_a.c")
507 if os.path.exists("makefile_test_b.c"):
508 os.remove("makefile_test_b.c")
509 if os.path.exists("makefile_test.a"):
510 os.remove("makefile_test.a")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500511 return None
512
513
Brad Bishope2d5b612018-11-23 10:55:50 +1300514# Check if we're running on WSL (Windows Subsystem for Linux). Its known not to
515# work but we should tell the user that upfront.
516def check_wsl(d):
517 with open("/proc/version", "r") as f:
518 verdata = f.readlines()
519 for l in verdata:
520 if "Microsoft" in l:
521 return "OpenEmbedded doesn't work under WSL at this time, sorry"
522 return None
523
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500524# Tar version 1.24 and onwards handle overwriting symlinks correctly
525# but earlier versions do not; this needs to work properly for sstate
Brad Bishop6dbb3162019-11-25 09:41:34 -0500526# Version 1.28 is needed so opkg-build works correctly when reproducibile builds are enabled
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500527def check_tar_version(sanity_data):
528 from distutils.version import LooseVersion
Brad Bishopd5ae7d92018-06-14 09:52:03 -0700529 import subprocess
530 try:
531 result = subprocess.check_output(["tar", "--version"], stderr=subprocess.STDOUT).decode('utf-8')
532 except subprocess.CalledProcessError as e:
533 return "Unable to execute tar --version, exit code %d\n%s\n" % (e.returncode, e.output)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500534 version = result.split()[3]
535 if LooseVersion(version) < LooseVersion("1.24"):
Brad Bishop6dbb3162019-11-25 09:41:34 -0500536 return "Your version of tar is older than 1.24 and has bugs which will break builds. Please install a newer version of tar (1.28+).\n"
537 if LooseVersion(version) < LooseVersion("1.28"):
538 return "Your version of tar is older than 1.28 and does not have the support needed to enable reproducible builds. Please install a newer version of tar (you could use the projects buildtools-tarball from our last release).\n"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500539 return None
540
541# We use git parameters and functionality only found in 1.7.8 or later
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500542# The kernel tools assume git >= 1.8.3.1 (verified needed > 1.7.9.5) see #6162
543# The git fetcher also had workarounds for git < 1.7.9.2 which we've dropped
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500544def check_git_version(sanity_data):
545 from distutils.version import LooseVersion
Brad Bishopd5ae7d92018-06-14 09:52:03 -0700546 import subprocess
547 try:
548 result = subprocess.check_output(["git", "--version"], stderr=subprocess.DEVNULL).decode('utf-8')
549 except subprocess.CalledProcessError as e:
550 return "Unable to execute git --version, exit code %d\n%s\n" % (e.returncode, e.output)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500551 version = result.split()[2]
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500552 if LooseVersion(version) < LooseVersion("1.8.3.1"):
553 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 -0500554 return None
555
556# Check the required perl modules which may not be installed by default
557def check_perl_modules(sanity_data):
Brad Bishopd5ae7d92018-06-14 09:52:03 -0700558 import subprocess
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500559 ret = ""
560 modules = ( "Text::ParseWords", "Thread::Queue", "Data::Dumper" )
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500561 errresult = ''
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500562 for m in modules:
Brad Bishopd5ae7d92018-06-14 09:52:03 -0700563 try:
564 subprocess.check_output(["perl", "-e", "use %s" % m])
565 except subprocess.CalledProcessError as e:
Brad Bishopc342db32019-05-15 21:57:59 -0400566 errresult += bytes.decode(e.output)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500567 ret += "%s " % m
568 if ret:
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500569 return "Required perl module(s) not found: %s\n\n%s\n" % (ret, errresult)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500570 return None
571
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600572def sanity_check_conffiles(d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500573 funcs = d.getVar('BBLAYERS_CONF_UPDATE_FUNCS').split()
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500574 for func in funcs:
575 conffile, current_version, required_version, func = func.split(":")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500576 if check_conf_exists(conffile, d) and d.getVar(current_version) is not None and \
577 d.getVar(current_version) != d.getVar(required_version):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500578 try:
Brad Bishop08902b02019-08-20 09:16:51 -0400579 bb.build.exec_func(func, d)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500580 except NotImplementedError as e:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500581 bb.fatal(str(e))
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600582 d.setVar("BB_INVALIDCONF", True)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500583
584def sanity_handle_abichanges(status, d):
585 #
586 # Check the 'ABI' of TMPDIR
587 #
588 import subprocess
589
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500590 current_abi = d.getVar('OELAYOUT_ABI')
591 abifile = d.getVar('SANITY_ABIFILE')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500592 if os.path.exists(abifile):
593 with open(abifile, "r") as f:
594 abi = f.read().strip()
595 if not abi.isdigit():
596 with open(abifile, "w") as f:
597 f.write(current_abi)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500598 elif int(abi) <= 11 and current_abi == "12":
599 status.addresult("The layout of TMPDIR changed for Recipe Specific Sysroots.\nConversion doesn't make sense and this change will rebuild everything so please delete TMPDIR (%s).\n" % d.getVar("TMPDIR"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500600 elif (abi != current_abi):
601 # Code to convert from one ABI to another could go here if possible.
602 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))
603 else:
604 with open(abifile, "w") as f:
605 f.write(current_abi)
606
607def check_sanity_sstate_dir_change(sstate_dir, data):
608 # Sanity checks to be done when the value of SSTATE_DIR changes
609
610 # Check that SSTATE_DIR isn't on a filesystem with limited filename length (eg. eCryptFS)
611 testmsg = ""
612 if sstate_dir != "":
613 testmsg = check_create_long_filename(sstate_dir, "SSTATE_DIR")
614 # If we don't have permissions to SSTATE_DIR, suggest the user set it as an SSTATE_MIRRORS
615 try:
616 err = testmsg.split(': ')[1].strip()
617 if err == "Permission denied.":
618 testmsg = testmsg + "You could try using %s in SSTATE_MIRRORS rather than as an SSTATE_CACHE.\n" % (sstate_dir)
619 except IndexError:
620 pass
621 return testmsg
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500622
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500623def check_sanity_version_change(status, d):
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500624 # Sanity checks to be done when SANITY_VERSION or NATIVELSBSTRING changes
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500625 # In other words, these tests run once in a given build directory and then
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500626 # never again until the sanity version or host distrubution id/version changes.
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500627
Brad Bishop64c979e2019-11-04 13:55:29 -0500628 # Check the python install is complete. Examples that are often removed in
629 # minimal installations: glib-2.0-natives requries # xml.parsers.expat and icu
630 # requires distutils.sysconfig.
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500631 try:
632 import xml.parsers.expat
Brad Bishop64c979e2019-11-04 13:55:29 -0500633 import distutils.sysconfig
634 except ImportError as e:
635 status.addresult('Your Python 3 is not a full install. Please install the module %s (see the Getting Started guide for further information).\n' % e.name)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500636
637 status.addresult(check_make_version(d))
Brad Bishop316dfdd2018-06-25 12:45:53 -0400638 status.addresult(check_patch_version(d))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500639 status.addresult(check_tar_version(d))
640 status.addresult(check_git_version(d))
641 status.addresult(check_perl_modules(d))
Brad Bishope2d5b612018-11-23 10:55:50 +1300642 status.addresult(check_wsl(d))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500643
644 missing = ""
645
646 if not check_app_exists("${MAKE}", d):
647 missing = missing + "GNU make,"
648
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600649 if not check_app_exists('${BUILD_CC}', d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500650 missing = missing + "C Compiler (%s)," % d.getVar("BUILD_CC")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500651
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600652 if not check_app_exists('${BUILD_CXX}', d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500653 missing = missing + "C++ Compiler (%s)," % d.getVar("BUILD_CXX")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500654
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500655 required_utilities = d.getVar('SANITY_REQUIRED_UTILITIES')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500656
657 for util in required_utilities.split():
658 if not check_app_exists(util, d):
659 missing = missing + "%s," % util
660
661 if missing:
662 missing = missing.rstrip(',')
663 status.addresult("Please install the following missing utilities: %s\n" % missing)
664
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500665 assume_provided = d.getVar('ASSUME_PROVIDED').split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500666 # Check user doesn't have ASSUME_PROVIDED = instead of += in local.conf
667 if "diffstat-native" not in assume_provided:
668 status.addresult('Please use ASSUME_PROVIDED +=, not ASSUME_PROVIDED = in your local.conf\n')
669
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500670 # Check that TMPDIR isn't on a filesystem with limited filename length (eg. eCryptFS)
Brad Bishop64c979e2019-11-04 13:55:29 -0500671 import stat
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500672 tmpdir = d.getVar('TMPDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500673 status.addresult(check_create_long_filename(tmpdir, "TMPDIR"))
674 tmpdirmode = os.stat(tmpdir).st_mode
675 if (tmpdirmode & stat.S_ISGID):
676 status.addresult("TMPDIR is setgid, please don't build in a setgid directory")
677 if (tmpdirmode & stat.S_ISUID):
678 status.addresult("TMPDIR is setuid, please don't build in a setuid directory")
679
680 # Some third-party software apparently relies on chmod etc. being suid root (!!)
681 import stat
682 suid_check_bins = "chown chmod mknod".split()
683 for bin_cmd in suid_check_bins:
684 bin_path = bb.utils.which(os.environ["PATH"], bin_cmd)
685 if bin_path:
686 bin_stat = os.stat(bin_path)
687 if bin_stat.st_uid == 0 and bin_stat.st_mode & stat.S_ISUID:
688 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)
689
690 # Check that we can fetch from various network transports
691 netcheck = check_connectivity(d)
692 status.addresult(netcheck)
693 if netcheck:
694 status.network_error = True
695
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500696 nolibs = d.getVar('NO32LIBS')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500697 if not nolibs:
698 lib32path = '/lib'
699 if os.path.exists('/lib64') and ( os.path.islink('/lib64') or os.path.islink('/lib') ):
700 lib32path = '/lib32'
701
702 if os.path.exists('%s/libc.so.6' % lib32path) and not os.path.exists('/usr/include/gnu/stubs-32.h'):
703 status.addresult("You have a 32-bit libc, but no 32-bit headers. You must install the 32-bit libc headers.\n")
704
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500705 bbpaths = d.getVar('BBPATH').split(":")
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600706 if ("." in bbpaths or "./" in bbpaths or "" in bbpaths):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500707 status.addresult("BBPATH references the current directory, either through " \
708 "an empty entry, a './' or a '.'.\n\t This is unsafe and means your "\
709 "layer configuration is adding empty elements to BBPATH.\n\t "\
710 "Please check your layer.conf files and other BBPATH " \
711 "settings to remove the current working directory " \
712 "references.\n" \
713 "Parsed BBPATH is" + str(bbpaths));
714
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500715 oes_bb_conf = d.getVar( 'OES_BITBAKE_CONF')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500716 if not oes_bb_conf:
717 status.addresult('You are not using the OpenEmbedded version of conf/bitbake.conf. This means your environment is misconfigured, in particular check BBPATH.\n')
718
719 # The length of TMPDIR can't be longer than 410
720 status.addresult(check_path_length(tmpdir, "TMPDIR", 410))
721
722 # Check that TMPDIR isn't located on nfs
723 status.addresult(check_not_nfs(tmpdir, "TMPDIR"))
724
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500725 # Check for case-insensitive file systems (such as Linux in Docker on
726 # macOS with default HFS+ file system)
727 status.addresult(check_case_sensitive(tmpdir, "TMPDIR"))
728
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600729def sanity_check_locale(d):
730 """
731 Currently bitbake switches locale to en_US.UTF-8 so check that this locale actually exists.
732 """
733 import locale
734 try:
735 locale.setlocale(locale.LC_ALL, "en_US.UTF-8")
736 except locale.Error:
Brad Bishop316dfdd2018-06-25 12:45:53 -0400737 raise_sanity_error("Your system needs to support the en_US.UTF-8 locale.", d)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600738
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500739def check_sanity_everybuild(status, d):
740 import os, stat
741 # Sanity tests which test the users environment so need to run at each build (or are so cheap
742 # it makes sense to always run them.
743
744 if 0 == os.getuid():
745 raise_sanity_error("Do not use Bitbake as root.", d)
746
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500747 # Check the Python version, we now have a minimum of Python 3.4
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500748 import sys
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500749 if sys.hexversion < 0x03040000:
750 status.addresult('The system requires at least Python 3.4 to run. Please update your Python interpreter.\n')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500751
752 # Check the bitbake version meets minimum requirements
753 from distutils.version import LooseVersion
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500754 minversion = d.getVar('BB_MIN_VERSION')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500755 if (LooseVersion(bb.__version__) < LooseVersion(minversion)):
756 status.addresult('Bitbake version %s is required and version %s was found\n' % (minversion, bb.__version__))
757
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600758 sanity_check_locale(d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500759
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500760 paths = d.getVar('PATH').split(":")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500761 if "." in paths or "./" in paths or "" in paths:
762 status.addresult("PATH contains '.', './' or '' (empty element), which will break the build, please remove this.\nParsed PATH is " + str(paths) + "\n")
763
764 # Check that the DISTRO is valid, if set
765 # need to take into account DISTRO renaming DISTRO
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500766 distro = d.getVar('DISTRO')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500767 if distro and distro != "nodistro":
768 if not ( check_conf_exists("conf/distro/${DISTRO}.conf", d) or check_conf_exists("conf/distro/include/${DISTRO}.inc", d) ):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500769 status.addresult("DISTRO '%s' not found. Please set a valid DISTRO in your local.conf\n" % d.getVar("DISTRO"))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500770
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500771 # Check that these variables don't use tilde-expansion as we don't do that
772 for v in ("TMPDIR", "DL_DIR", "SSTATE_DIR"):
773 if d.getVar(v).startswith("~"):
774 status.addresult("%s uses ~ but Bitbake will not expand this, use an absolute path or variables." % v)
775
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500776 # Check that DL_DIR is set, exists and is writable. In theory, we should never even hit the check if DL_DIR isn't
777 # set, since so much relies on it being set.
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500778 dldir = d.getVar('DL_DIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500779 if not dldir:
780 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")
781 if os.path.exists(dldir) and not os.access(dldir, os.W_OK):
782 status.addresult("DL_DIR: %s exists but you do not appear to have write access to it. \n" % dldir)
783 check_symlink(dldir, d)
784
785 # Check that the MACHINE is valid, if it is set
786 machinevalid = True
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500787 if d.getVar('MACHINE'):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500788 if not check_conf_exists("conf/machine/${MACHINE}.conf", d):
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500789 status.addresult('MACHINE=%s is invalid. Please set a valid MACHINE in your local.conf, environment or other configuration file.\n' % (d.getVar('MACHINE')))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500790 machinevalid = False
791 else:
792 status.addresult(check_sanity_validmachine(d))
793 else:
794 status.addresult('Please set a MACHINE in your local.conf or environment\n')
795 machinevalid = False
796 if machinevalid:
797 status.addresult(check_toolchain(d))
798
799 # Check that the SDKMACHINE is valid, if it is set
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500800 if d.getVar('SDKMACHINE'):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500801 if not check_conf_exists("conf/machine-sdk/${SDKMACHINE}.conf", d):
802 status.addresult('Specified SDKMACHINE value is not valid\n')
803 elif d.getVar('SDK_ARCH', False) == "${BUILD_ARCH}":
804 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')
805
Brad Bishop64c979e2019-11-04 13:55:29 -0500806 # If SDK_VENDOR looks like "-my-sdk" then the triples are badly formed so fail early
807 sdkvendor = d.getVar("SDK_VENDOR")
808 if not (sdkvendor.startswith("-") and sdkvendor.count("-") == 1):
809 status.addresult("SDK_VENDOR should be of the form '-foosdk' with a single dash\n")
810
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500811 check_supported_distro(d)
812
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600813 omask = os.umask(0o022)
814 if omask & 0o755:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500815 status.addresult("Please use a umask which allows a+rx and u+rwx\n")
816 os.umask(omask)
817
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500818 if d.getVar('TARGET_ARCH') == "arm":
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500819 # This path is no longer user-readable in modern (very recent) Linux
820 try:
821 if os.path.exists("/proc/sys/vm/mmap_min_addr"):
822 f = open("/proc/sys/vm/mmap_min_addr", "r")
823 try:
824 if (int(f.read().strip()) > 65536):
825 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")
826 finally:
827 f.close()
828 except:
829 pass
830
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500831 oeroot = d.getVar('COREBASE')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500832 if oeroot.find('+') != -1:
833 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.")
834 if oeroot.find('@') != -1:
835 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.")
836 if oeroot.find(' ') != -1:
837 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.")
838
839 # Check the format of MIRRORS, PREMIRRORS and SSTATE_MIRRORS
840 import re
841 mirror_vars = ['MIRRORS', 'PREMIRRORS', 'SSTATE_MIRRORS']
842 protocols = ['http', 'ftp', 'file', 'https', \
843 'git', 'gitsm', 'hg', 'osc', 'p4', 'svn', \
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500844 'bzr', 'cvs', 'npm', 'sftp', 'ssh', 's3' ]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500845 for mirror_var in mirror_vars:
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500846 mirrors = (d.getVar(mirror_var) or '').replace('\\n', ' ').split()
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500847
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500848 # Split into pairs
849 if len(mirrors) % 2 != 0:
Brad Bishopd7bf8c12018-02-25 22:55:05 -0500850 bb.warn('Invalid mirror variable value for %s: %s, should contain paired members.' % (mirror_var, str(mirrors)))
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500851 continue
852 mirrors = list(zip(*[iter(mirrors)]*2))
853
854 for mirror_entry in mirrors:
855 pattern, mirror = mirror_entry
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500856
857 decoded = bb.fetch2.decodeurl(pattern)
858 try:
859 pattern_scheme = re.compile(decoded[0])
860 except re.error as exc:
861 bb.warn('Invalid scheme regex (%s) in %s; %s' % (pattern, mirror_var, mirror_entry))
862 continue
863
864 if not any(pattern_scheme.match(protocol) for protocol in protocols):
865 bb.warn('Invalid protocol (%s) in %s: %s' % (decoded[0], mirror_var, mirror_entry))
866 continue
867
868 if not any(mirror.startswith(protocol + '://') for protocol in protocols):
869 bb.warn('Invalid protocol in %s: %s' % (mirror_var, mirror_entry))
870 continue
871
872 if mirror.startswith('file://'):
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600873 import urllib
874 check_symlink(urllib.parse.urlparse(mirror).path, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500875 # SSTATE_MIRROR ends with a /PATH string
876 if mirror.endswith('/PATH'):
877 # remove /PATH$ from SSTATE_MIRROR to get a working
878 # base directory path
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600879 mirror_base = urllib.parse.urlparse(mirror[:-1*len('/PATH')]).path
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500880 check_symlink(mirror_base, d)
881
882 # Check that TMPDIR hasn't changed location since the last time we were run
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500883 tmpdir = d.getVar('TMPDIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500884 checkfile = os.path.join(tmpdir, "saved_tmpdir")
885 if os.path.exists(checkfile):
886 with open(checkfile, "r") as f:
887 saved_tmpdir = f.read().strip()
888 if (saved_tmpdir != tmpdir):
Brad Bishopd89cb5f2019-04-10 09:02:41 -0400889 status.addresult("Error, TMPDIR has changed location. You need to either move it back to %s or delete it and rebuild\n" % saved_tmpdir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500890 else:
891 bb.utils.mkdirhier(tmpdir)
892 # Remove setuid, setgid and sticky bits from TMPDIR
Patrick Williamsf1e5d692016-03-30 15:21:19 -0500893 try:
894 os.chmod(tmpdir, os.stat(tmpdir).st_mode & ~ stat.S_ISUID)
895 os.chmod(tmpdir, os.stat(tmpdir).st_mode & ~ stat.S_ISGID)
896 os.chmod(tmpdir, os.stat(tmpdir).st_mode & ~ stat.S_ISVTX)
897 except OSError as exc:
898 bb.warn("Unable to chmod TMPDIR: %s" % exc)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500899 with open(checkfile, "w") as f:
900 f.write(tmpdir)
901
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600902 # If /bin/sh is a symlink, check that it points to dash or bash
903 if os.path.islink('/bin/sh'):
904 real_sh = os.path.realpath('/bin/sh')
Brad Bishop37a0e4d2017-12-04 01:01:44 -0500905 # Due to update-alternatives, the shell name may take various
906 # forms, such as /bin/dash, bin/bash, /bin/bash.bash ...
907 if '/dash' not in real_sh and '/bash' not in real_sh:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600908 status.addresult("Error, /bin/sh links to %s, must be dash or bash\n" % real_sh)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500909
910def check_sanity(sanity_data):
911 class SanityStatus(object):
912 def __init__(self):
913 self.messages = ""
914 self.network_error = False
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500915
916 def addresult(self, message):
917 if message:
918 self.messages = self.messages + message
919
920 status = SanityStatus()
921
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500922 tmpdir = sanity_data.getVar('TMPDIR')
923 sstate_dir = sanity_data.getVar('SSTATE_DIR')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500924
925 check_symlink(sstate_dir, sanity_data)
926
927 # Check saved sanity info
928 last_sanity_version = 0
929 last_tmpdir = ""
930 last_sstate_dir = ""
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500931 last_nativelsbstr = ""
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500932 sanityverfile = sanity_data.expand("${TOPDIR}/conf/sanity_info")
933 if os.path.exists(sanityverfile):
934 with open(sanityverfile, 'r') as f:
935 for line in f:
936 if line.startswith('SANITY_VERSION'):
937 last_sanity_version = int(line.split()[1])
938 if line.startswith('TMPDIR'):
939 last_tmpdir = line.split()[1]
940 if line.startswith('SSTATE_DIR'):
941 last_sstate_dir = line.split()[1]
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500942 if line.startswith('NATIVELSBSTRING'):
943 last_nativelsbstr = line.split()[1]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500944
945 check_sanity_everybuild(status, sanity_data)
946
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500947 sanity_version = int(sanity_data.getVar('SANITY_VERSION') or 1)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500948 network_error = False
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500949 # NATIVELSBSTRING var may have been overridden with "universal", so
950 # get actual host distribution id and version
951 nativelsbstr = lsb_distro_identifier(sanity_data)
952 if last_sanity_version < sanity_version or last_nativelsbstr != nativelsbstr:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500953 check_sanity_version_change(status, sanity_data)
954 status.addresult(check_sanity_sstate_dir_change(sstate_dir, sanity_data))
955 else:
956 if last_sstate_dir != sstate_dir:
957 status.addresult(check_sanity_sstate_dir_change(sstate_dir, sanity_data))
958
959 if os.path.exists(os.path.dirname(sanityverfile)) and not status.messages:
960 with open(sanityverfile, 'w') as f:
961 f.write("SANITY_VERSION %s\n" % sanity_version)
962 f.write("TMPDIR %s\n" % tmpdir)
963 f.write("SSTATE_DIR %s\n" % sstate_dir)
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500964 f.write("NATIVELSBSTRING %s\n" % nativelsbstr)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500965
966 sanity_handle_abichanges(status, sanity_data)
967
968 if status.messages != "":
969 raise_sanity_error(sanity_data.expand(status.messages), sanity_data, status.network_error)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500970
971# Create a copy of the datastore and finalise it to ensure appends and
972# overrides are set - the datastore has yet to be finalised at ConfigParsed
973def copy_data(e):
974 sanity_data = bb.data.createCopy(e.data)
975 sanity_data.finalize()
976 return sanity_data
977
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600978addhandler config_reparse_eventhandler
979config_reparse_eventhandler[eventmask] = "bb.event.ConfigParsed"
980python config_reparse_eventhandler() {
981 sanity_check_conffiles(e.data)
982}
983
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500984addhandler check_sanity_eventhandler
985check_sanity_eventhandler[eventmask] = "bb.event.SanityCheck bb.event.NetworkTest"
986python check_sanity_eventhandler() {
987 if bb.event.getName(e) == "SanityCheck":
988 sanity_data = copy_data(e)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600989 check_sanity(sanity_data)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500990 if e.generateevents:
991 sanity_data.setVar("SANITY_USE_EVENTS", "1")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500992 bb.event.fire(bb.event.SanityCheckPassed(), e.data)
993 elif bb.event.getName(e) == "NetworkTest":
994 sanity_data = copy_data(e)
995 if e.generateevents:
996 sanity_data.setVar("SANITY_USE_EVENTS", "1")
997 bb.event.fire(bb.event.NetworkTestFailed() if check_connectivity(sanity_data) else bb.event.NetworkTestPassed(), e.data)
998
999 return
1000}