2
0
mirror of https://gitlab.com/ita1024/waf.git synced 2024-11-11 12:49:06 +01:00
waf/waflib/Tools/errcheck.py

224 lines
7.1 KiB
Python
Raw Normal View History

2011-09-10 11:13:51 +02:00
#! /usr/bin/env python
# encoding: utf-8
# Thomas Nagy, 2011 (ita)
"""
2016-06-26 11:59:27 +02:00
Common mistakes highlighting.
2011-09-10 11:13:51 +02:00
2016-06-26 11:59:27 +02:00
There is a performance impact, so this tool is only loaded when running ``waf -v``
2011-09-10 11:13:51 +02:00
"""
typos = {
'feature':'features',
'sources':'source',
'targets':'target',
'include':'includes',
'export_include':'export_includes',
'define':'defines',
'importpath':'includes',
'installpath':'install_path',
'iscopy':'is_copy',
2011-09-10 11:13:51 +02:00
}
meths_typos = ['__call__', 'program', 'shlib', 'stlib', 'objects']
import sys
2011-09-10 11:13:51 +02:00
from waflib import Logs, Build, Node, Task, TaskGen, ConfigSet, Errors, Utils
2016-06-25 21:30:32 +02:00
from waflib.Tools import ccroot
2011-09-10 11:13:51 +02:00
def check_same_targets(self):
mp = Utils.defaultdict(list)
uids = {}
def check_task(tsk):
if not isinstance(tsk, Task.Task):
return
if hasattr(tsk, 'no_errcheck_out'):
return
2011-09-10 11:13:51 +02:00
for node in tsk.outputs:
mp[node].append(tsk)
try:
uids[tsk.uid()].append(tsk)
2012-02-11 14:49:27 +01:00
except KeyError:
2011-09-10 11:13:51 +02:00
uids[tsk.uid()] = [tsk]
for g in self.groups:
for tg in g:
try:
for tsk in tg.tasks:
check_task(tsk)
except AttributeError:
# raised if not a task generator, which should be uncommon
check_task(tg)
dupe = False
for (k, v) in mp.items():
if len(v) > 1:
dupe = True
2012-07-20 20:16:25 +02:00
msg = '* Node %r is created more than once%s. The task generators are:' % (k, Logs.verbose == 1 and " (full message on 'waf -v -v')" or "")
2011-09-10 11:13:51 +02:00
Logs.error(msg)
for x in v:
if Logs.verbose > 1:
Logs.error(' %d. %r', 1 + v.index(x), x.generator)
2011-09-10 11:13:51 +02:00
else:
Logs.error(' %d. %r in %r', 1 + v.index(x), x.generator.name, getattr(x.generator, 'path', None))
Logs.error('If you think that this is an error, set no_errcheck_out on the task instance')
2011-09-10 11:13:51 +02:00
if not dupe:
for (k, v) in uids.items():
if len(v) > 1:
2015-06-21 22:43:19 +02:00
Logs.error('* Several tasks use the same identifier. Please check the information on\n https://waf.io/apidocs/Task.html?highlight=uid#waflib.Task.Task.uid')
2011-09-10 11:13:51 +02:00
for tsk in v:
Logs.error(' - object %r (%r) defined in %r', tsk.__class__.__name__, tsk, tsk.generator)
2011-09-10 11:13:51 +02:00
def check_invalid_constraints(self):
2016-09-02 20:20:43 +02:00
feat = set()
2011-09-10 11:13:51 +02:00
for x in list(TaskGen.feats.values()):
feat.union(set(x))
for (x, y) in TaskGen.task_gen.prec.items():
feat.add(x)
feat.union(set(y))
2016-09-02 20:20:43 +02:00
ext = set()
2011-09-10 11:13:51 +02:00
for x in TaskGen.task_gen.mappings.values():
ext.add(x.__name__)
invalid = ext & feat
if invalid:
Logs.error('The methods %r have invalid annotations: @extension <-> @feature/@before_method/@after_method', list(invalid))
2011-09-10 11:13:51 +02:00
# the build scripts have been read, so we can check for invalid after/before attributes on task classes
for cls in list(Task.classes.values()):
if sys.hexversion > 0x3000000 and issubclass(cls, Task.Task) and isinstance(cls.hcode, str):
raise Errors.WafError('Class %r has hcode value %r of type <str>, expecting <bytes> (use Utils.h_cmd() ?)' % (cls, cls.hcode))
2011-09-10 11:13:51 +02:00
for x in ('before', 'after'):
for y in Utils.to_list(getattr(cls, x, [])):
2016-04-19 22:00:21 +02:00
if not Task.classes.get(y):
Logs.error('Erroneous order constraint %r=%r on task class %r', x, y, cls.__name__)
if getattr(cls, 'rule', None):
Logs.error('Erroneous attribute "rule" on task class %r (rename to "run_str")', cls.__name__)
2011-09-10 11:13:51 +02:00
def replace(m):
"""
2016-06-26 11:59:27 +02:00
Replaces existing BuildContext methods to verify parameter names,
for example ``bld(source=)`` has no ending *s*
2011-09-10 11:13:51 +02:00
"""
oldcall = getattr(Build.BuildContext, m)
def call(self, *k, **kw):
ret = oldcall(self, *k, **kw)
for x in typos:
if x in kw:
if x == 'iscopy' and 'subst' in getattr(self, 'features', ''):
continue
Logs.error('Fix the typo %r -> %r on %r', x, typos[x], ret)
2011-09-10 11:13:51 +02:00
return ret
setattr(Build.BuildContext, m, call)
def enhance_lib():
"""
2016-06-26 11:59:27 +02:00
Modifies existing classes and methods to enable error verification
2011-09-10 11:13:51 +02:00
"""
for m in meths_typos:
replace(m)
# catch '..' in ant_glob patterns
def ant_glob(self, *k, **kw):
if k:
2016-06-26 11:59:27 +02:00
lst = Utils.to_list(k[0])
2011-09-10 11:13:51 +02:00
for pat in lst:
if '..' in pat.split('/'):
Logs.error("In ant_glob pattern %r: '..' means 'two dots', not 'parent directory'", k[0])
if kw.get('remove', True):
try:
if self.is_child_of(self.ctx.bldnode) and not kw.get('quiet', False):
Logs.error('Using ant_glob on the build folder (%r) is dangerous (quiet=True to disable this warning)', self)
except AttributeError:
pass
return self.old_ant_glob(*k, **kw)
Node.Node.old_ant_glob = Node.Node.ant_glob
2011-09-10 11:13:51 +02:00
Node.Node.ant_glob = ant_glob
# catch conflicting ext_in/ext_out/before/after declarations
old = Task.is_before
def is_before(t1, t2):
ret = old(t1, t2)
if ret and old(t2, t1):
Logs.error('Contradictory order constraints in classes %r %r', t1, t2)
2011-09-10 11:13:51 +02:00
return ret
Task.is_before = is_before
# check for bld(feature='cshlib') where no 'c' is given - this can be either a mistake or on purpose
# so we only issue a warning
def check_err_features(self):
lst = self.to_list(self.features)
if 'shlib' in lst:
Logs.error('feature shlib -> cshlib, dshlib or cxxshlib')
for x in ('c', 'cxx', 'd', 'fc'):
if not x in lst and lst and lst[0] in [x+y for y in ('program', 'shlib', 'stlib')]:
Logs.error('%r features is probably missing %r', self, x)
2011-09-10 11:13:51 +02:00
TaskGen.feature('*')(check_err_features)
# check for erroneous order constraints
def check_err_order(self):
if not hasattr(self, 'rule') and not 'subst' in Utils.to_list(self.features):
2011-09-10 11:13:51 +02:00
for x in ('before', 'after', 'ext_in', 'ext_out'):
if hasattr(self, x):
Logs.warn('Erroneous order constraint %r on non-rule based task generator %r', x, self)
2011-09-10 11:13:51 +02:00
else:
for x in ('before', 'after'):
for y in self.to_list(getattr(self, x, [])):
if not Task.classes.get(y, None):
Logs.error('Erroneous order constraint %s=%r on %r (no such class)', x, y, self)
2011-09-10 11:13:51 +02:00
TaskGen.feature('*')(check_err_order)
# check for @extension used with @feature/@before_method/@after_method
def check_compile(self):
check_invalid_constraints(self)
try:
ret = self.orig_compile()
finally:
check_same_targets(self)
return ret
Build.BuildContext.orig_compile = Build.BuildContext.compile
Build.BuildContext.compile = check_compile
# check for invalid build groups #914
def use_rec(self, name, **kw):
try:
y = self.bld.get_tgen_by_name(name)
except Errors.WafError:
pass
else:
idx = self.bld.get_group_idx(self)
odx = self.bld.get_group_idx(y)
if odx > idx:
msg = "Invalid 'use' across build groups:"
if Logs.verbose > 1:
msg += '\n target %r\n uses:\n %r' % (self, y)
else:
msg += " %r uses %r (try 'waf -v -v' for the full error)" % (self.name, name)
raise Errors.WafError(msg)
self.orig_use_rec(name, **kw)
TaskGen.task_gen.orig_use_rec = TaskGen.task_gen.use_rec
TaskGen.task_gen.use_rec = use_rec
# check for env.append
2016-06-26 11:59:27 +02:00
def _getattr(self, name, default=None):
2011-09-10 11:13:51 +02:00
if name == 'append' or name == 'add':
raise Errors.WafError('env.append and env.add do not exist: use env.append_value/env.append_unique')
elif name == 'prepend':
raise Errors.WafError('env.prepend does not exist: use env.prepend_value')
if name in self.__slots__:
return object.__getattr__(self, name, default)
else:
return self[name]
2016-06-26 11:59:27 +02:00
ConfigSet.ConfigSet.__getattr__ = _getattr
2011-09-10 11:13:51 +02:00
def options(opt):
"""
2016-06-26 11:59:27 +02:00
Error verification can be enabled by default (not just on ``waf -v``) by adding to the user script options
2011-09-10 11:13:51 +02:00
"""
enhance_lib()