This is the last version on the 1.8.x branch. The build system will be updated to the 1.9.x branch in a later commit.tags/v1.9.13
@@ -117,6 +117,7 @@ WAFLIB_STRIP_EXTRAS=" | |||
run_py_script | |||
run_r_script | |||
sas | |||
satellite_assembly | |||
scala | |||
slow_qt4 | |||
smart_continue | |||
@@ -133,4 +134,5 @@ WAFLIB_STRIP_EXTRAS=" | |||
valadoc | |||
why | |||
win32_opts | |||
wix | |||
" |
@@ -1,6 +1,6 @@ | |||
#!/usr/bin/env python | |||
# encoding: ISO8859-1 | |||
# Thomas Nagy, 2005-2015 | |||
# Thomas Nagy, 2005-2016 | |||
""" | |||
Redistribution and use in source and binary forms, with or without | |||
@@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. | |||
import os, sys, inspect | |||
VERSION="1.8.17" | |||
VERSION="1.8.22" | |||
REVISION="x" | |||
GIT="x" | |||
INSTALL="x" | |||
@@ -335,6 +335,12 @@ class ConfigSet(object): | |||
tbl[x] = copy.deepcopy(tbl[x]) | |||
self.undo_stack = self.undo_stack + [orig] | |||
def commit(self): | |||
""" | |||
Commits transactional changes. See :py:meth:`ConfigSet.stash` | |||
""" | |||
self.undo_stack.pop(-1) | |||
def revert(self): | |||
""" | |||
Reverts the object to a previous state. See :py:meth:`ConfigSet.stash` | |||
@@ -1,6 +1,6 @@ | |||
#!/usr/bin/env python | |||
# encoding: utf-8 | |||
# Thomas Nagy, 2010 (ita) | |||
# Thomas Nagy, 2010-2016 (ita) | |||
""" | |||
Classes and functions required for waf commands | |||
@@ -11,13 +11,13 @@ from waflib import Utils, Errors, Logs | |||
import waflib.Node | |||
# the following 3 constants are updated on each new release (do not touch) | |||
HEXVERSION=0x1081100 | |||
HEXVERSION=0x1081600 | |||
"""Constant updated on new releases""" | |||
WAFVERSION="1.8.17" | |||
WAFVERSION="1.8.22" | |||
"""Constant updated on new releases""" | |||
WAFREVISION="cd7579a727d1b390bf9cbf111c1b20e811370bc0" | |||
WAFREVISION="17d4d4faa52c454eb3580e482df69b2a80e19fa7" | |||
"""Git revision when the waf version is updated""" | |||
ABI = 98 | |||
@@ -352,7 +352,7 @@ class Context(ctx): | |||
if 'input' in kw: | |||
if kw['input']: | |||
wargs['input'] = kw['input'] | |||
kw['stdin'] = Utils.subprocess.PIPE | |||
kw['stdin'] = subprocess.PIPE | |||
del kw['input'] | |||
try: | |||
@@ -432,7 +432,7 @@ class Context(ctx): | |||
if 'input' in kw: | |||
if kw['input']: | |||
wargs['input'] = kw['input'] | |||
kw['stdin'] = Utils.subprocess.PIPE | |||
kw['stdin'] = subprocess.PIPE | |||
del kw['input'] | |||
try: | |||
@@ -169,7 +169,7 @@ class log_handler(logging.StreamHandler): | |||
else: | |||
stream.write(fs % msg) | |||
except UnicodeError: | |||
stream.write((fs % msg).encode("UTF-8")) | |||
stream.write((fs % msg).encode('utf-8')) | |||
else: | |||
logging.StreamHandler.emit(self, record) | |||
@@ -200,8 +200,9 @@ class formatter(logging.Formatter): | |||
c2 = getattr(rec, 'c2', colors.NORMAL) | |||
msg = '%s%s%s' % (c1, msg, c2) | |||
else: | |||
msg = msg.replace('\r', '\n') | |||
msg = re.sub(r'\x1B\[(K|.*?(m|h|l))', '', msg) | |||
# remove single \r that make long lines in text files | |||
# and other terminal commands | |||
msg = re.sub(r'\r(?!\n)|\x1B\[(K|.*?(m|h|l))', '', msg) | |||
if rec.levelno >= logging.INFO: # ?? | |||
return msg | |||
@@ -76,7 +76,11 @@ def waf_entry_point(current_directory, version, wafdir): | |||
# at the same time, store the first wscript file seen | |||
cur = current_directory | |||
while cur and not Context.top_dir: | |||
lst = os.listdir(cur) | |||
try: | |||
lst = os.listdir(cur) | |||
except OSError: | |||
lst = [] | |||
Logs.error('Directory %r is unreadable!' % cur) | |||
if Options.lockfile in lst: | |||
env = ConfigSet.ConfigSet() | |||
try: | |||
@@ -193,7 +197,7 @@ def set_main_module(file_path): | |||
name = obj.__name__ | |||
if not name in Context.g_module.__dict__: | |||
setattr(Context.g_module, name, obj) | |||
for k in (update, dist, distclean, distcheck, update): | |||
for k in (update, dist, distclean, distcheck): | |||
set_def(k) | |||
# add dummy init and shutdown functions if they're not defined | |||
if not 'init' in Context.g_module.__dict__: | |||
@@ -614,13 +618,19 @@ def autoconfigure(execute_method): | |||
do_config = h != env.hash | |||
if do_config: | |||
Options.commands.insert(0, self.cmd) | |||
Options.commands.insert(0, 'configure') | |||
cmd = env['config_cmd'] or 'configure' | |||
if Configure.autoconfig == 'clobber': | |||
tmp = Options.options.__dict__ | |||
Options.options.__dict__ = env.options | |||
return | |||
return execute_method(self) | |||
try: | |||
run_command(cmd) | |||
finally: | |||
Options.options.__dict__ = tmp | |||
else: | |||
run_command(cmd) | |||
run_command(self.cmd) | |||
else: | |||
return execute_method(self) | |||
return execute | |||
Build.BuildContext.execute = autoconfigure(Build.BuildContext.execute) | |||
@@ -950,6 +950,7 @@ def funex(c): | |||
exec(c, dc) | |||
return dc['f'] | |||
re_novar = re.compile(r"^(SRC|TGT)\W+.*?$") | |||
reg_act = re.compile(r"(?P<backslash>\\)|(?P<dollar>\$\$)|(?P<subst>\$\{(?P<var>\w+)(?P<code>.*?)\})", re.M) | |||
def compile_fun_shell(line): | |||
""" | |||
@@ -979,25 +980,31 @@ def compile_fun_shell(line): | |||
else: app('" ".join([a.path_from(cwdx) for a in tsk.outputs])') | |||
elif meth: | |||
if meth.startswith(':'): | |||
if var not in dvars: | |||
dvars.append(var) | |||
m = meth[1:] | |||
if m == 'SRC': | |||
m = '[a.path_from(cwdx) for a in tsk.inputs]' | |||
elif m == 'TGT': | |||
m = '[a.path_from(cwdx) for a in tsk.outputs]' | |||
elif re_novar.match(m): | |||
m = '[tsk.inputs%s]' % m[3:] | |||
elif re_novar.match(m): | |||
m = '[tsk.outputs%s]' % m[3:] | |||
elif m[:3] not in ('tsk', 'gen', 'bld'): | |||
dvars.extend([var, meth[1:]]) | |||
dvars.append(meth[1:]) | |||
m = '%r' % m | |||
app('" ".join(tsk.colon(%r, %s))' % (var, m)) | |||
else: | |||
app('%s%s' % (var, meth)) | |||
else: | |||
if not var in dvars: dvars.append(var) | |||
if var not in dvars: | |||
dvars.append(var) | |||
app("p('%s')" % var) | |||
if parm: parm = "%% (%s) " % (',\n\t\t'.join(parm)) | |||
else: parm = '' | |||
c = COMPILE_TEMPLATE_SHELL % (line, parm) | |||
Logs.debug('action: %s' % c.strip().splitlines()) | |||
return (funex(c), dvars) | |||
@@ -1034,20 +1041,27 @@ def compile_fun_noshell(line): | |||
else: app("lst.extend([a.path_from(cwdx) for a in tsk.outputs])") | |||
elif meth: | |||
if meth.startswith(':'): | |||
if not var in dvars: | |||
dvars.append(var) | |||
m = meth[1:] | |||
if m == 'SRC': | |||
m = '[a.path_from(cwdx) for a in tsk.inputs]' | |||
elif m == 'TGT': | |||
m = '[a.path_from(cwdx) for a in tsk.outputs]' | |||
elif re_novar.match(m): | |||
m = '[tsk.inputs%s]' % m[3:] | |||
elif re_novar.match(m): | |||
m = '[tsk.outputs%s]' % m[3:] | |||
elif m[:3] not in ('tsk', 'gen', 'bld'): | |||
dvars.extend([var, m]) | |||
dvars.append(m) | |||
m = '%r' % m | |||
app('lst.extend(tsk.colon(%r, %s))' % (var, m)) | |||
else: | |||
app('lst.extend(gen.to_list(%s%s))' % (var, meth)) | |||
else: | |||
app('lst.extend(to_list(env[%r]))' % var) | |||
if not var in dvars: dvars.append(var) | |||
if not var in dvars: | |||
dvars.append(var) | |||
if extr: | |||
if params[-1]: | |||
@@ -216,7 +216,8 @@ class task_gen(object): | |||
tmp.append(x) | |||
if prec: | |||
raise Errors.WafError('Cycle detected in the method execution %r' % prec) | |||
txt = '\n'.join(['- %s after %s' % (k, repr(v)) for k, v in prec.items()]) | |||
raise Errors.WafError('Cycle detected in the method execution\n%s' % txt) | |||
out.reverse() | |||
self.meths = out | |||
@@ -100,6 +100,7 @@ MACRO_TO_DEST_CPU = { | |||
'__s390x__' : 's390x', | |||
'__s390__' : 's390', | |||
'__sh__' : 'sh', | |||
'__xtensa__' : 'xtensa', | |||
} | |||
@conf | |||
@@ -167,7 +168,12 @@ def parse_flags(self, line, uselib_store, env=None, force_static=False, posix=No | |||
elif x.startswith('/LIBPATH:'): | |||
prefix = (force_static or static) and 'STLIBPATH_' or 'LIBPATH_' | |||
appu(prefix + uselib, [x.replace('/LIBPATH:', '')]) | |||
elif x == '-pthread' or x.startswith('+') or x.startswith('-std'): | |||
elif x.startswith('-std='): | |||
if '++' in x: | |||
app('CXXFLAGS_' + uselib, [x]) | |||
else: | |||
app('CFLAGS_' + uselib, [x]) | |||
elif x == '-pthread' or x.startswith('+'): | |||
app('CFLAGS_' + uselib, [x]) | |||
app('CXXFLAGS_' + uselib, [x]) | |||
app('LINKFLAGS_' + uselib, [x]) | |||
@@ -342,13 +348,13 @@ def exec_cfg(self, kw): | |||
# retrieving variables of a module | |||
if 'variables' in kw: | |||
v = kw.get('env', self.env) | |||
v_env = kw.get('env', self.env) | |||
uselib = kw.get('uselib_store', kw['package'].upper()) | |||
vars = Utils.to_list(kw['variables']) | |||
for v in vars: | |||
val = self.cmd_and_log(lst + ['--variable=' + v], env=env).strip() | |||
var = '%s_%s' % (uselib, v) | |||
v[var] = val | |||
v_env[var] = val | |||
if not 'okmsg' in kw: | |||
kw['okmsg'] = 'yes' | |||
return | |||
@@ -635,13 +641,15 @@ def post_check(self, *k, **kw): | |||
if 'define_name' in kw: | |||
# TODO simplify! | |||
comment = kw.get('comment', '') | |||
define_name = kw['define_name'] | |||
if 'header_name' in kw or 'function_name' in kw or 'type_name' in kw or 'fragment' in kw: | |||
if kw['execute'] and kw.get('define_ret', None) and isinstance(is_success, str): | |||
self.define(kw['define_name'], is_success, quote=kw.get('quote', 1)) | |||
self.define(define_name, is_success, quote=kw.get('quote', 1), comment=comment) | |||
else: | |||
self.define_cond(kw['define_name'], is_success) | |||
self.define_cond(define_name, is_success, comment=comment) | |||
else: | |||
self.define_cond(kw['define_name'], is_success) | |||
self.define_cond(define_name, is_success, comment=comment) | |||
# consistency with check_cfg | |||
if kw.get('global_define', None): | |||
@@ -757,7 +765,20 @@ def check_cc(self, *k, **kw): | |||
return self.check(*k, **kw) | |||
@conf | |||
def define(self, key, val, quote=True): | |||
def set_define_comment(self, key, comment): | |||
# comments that appear in get_config_header | |||
coms = self.env.DEFINE_COMMENTS | |||
if not coms: | |||
coms = self.env.DEFINE_COMMENTS = {} | |||
coms[key] = comment or '' | |||
@conf | |||
def get_define_comment(self, key): | |||
coms = self.env.DEFINE_COMMENTS or {} | |||
return coms.get(key, '') | |||
@conf | |||
def define(self, key, val, quote=True, comment=''): | |||
""" | |||
Store a single define and its state into conf.env.DEFINES. If the value is True, False or None it is cast to 1 or 0. | |||
@@ -791,9 +812,10 @@ def define(self, key, val, quote=True): | |||
self.env.append_value('DEFINES', app) | |||
self.env.append_unique(DEFKEYS, key) | |||
self.set_define_comment(key, comment) | |||
@conf | |||
def undefine(self, key): | |||
def undefine(self, key, comment=''): | |||
""" | |||
Remove a define from conf.env.DEFINES | |||
@@ -806,9 +828,10 @@ def undefine(self, key): | |||
lst = [x for x in self.env['DEFINES'] if not x.startswith(ban)] | |||
self.env['DEFINES'] = lst | |||
self.env.append_unique(DEFKEYS, key) | |||
self.set_define_comment(key, comment) | |||
@conf | |||
def define_cond(self, key, val): | |||
def define_cond(self, key, val, comment=''): | |||
""" | |||
Conditionally define a name:: | |||
@@ -826,9 +849,9 @@ def define_cond(self, key, val): | |||
assert key and isinstance(key, str) | |||
if val: | |||
self.define(key, 1) | |||
self.define(key, 1, comment=comment) | |||
else: | |||
self.undefine(key) | |||
self.undefine(key, comment=comment) | |||
@conf | |||
def is_defined(self, key): | |||
@@ -958,10 +981,13 @@ def get_config_header(self, defines=True, headers=False, define_prefix=''): | |||
tbl[a] = b | |||
for k in self.env[DEFKEYS]: | |||
caption = self.get_define_comment(k) | |||
if caption: | |||
caption = ' /* %s */' % caption | |||
try: | |||
txt = '#define %s%s %s' % (define_prefix, k, tbl[k]) | |||
txt = '#define %s%s %s%s' % (define_prefix, k, tbl[k], caption) | |||
except KeyError: | |||
txt = '/* #undef %s%s */' % (define_prefix, k) | |||
txt = '/* #undef %s%s */%s' % (define_prefix, k, caption) | |||
lst.append(txt) | |||
return "\n".join(lst) | |||
@@ -1129,7 +1155,10 @@ def get_suncc_version(conf, cc): | |||
version = (out or err) | |||
version = version.splitlines()[0] | |||
version_re = re.compile(r'cc:\s+sun\s+(c\+\+|c)\s+(?P<major>\d*)\.(?P<minor>\d*)', re.I).search | |||
# cc: Sun C 5.10 SunOS_i386 2009/06/03 | |||
# cc: Studio 12.5 Sun C++ 5.14 SunOS_sparc Beta 2015/11/17 | |||
# cc: WorkShop Compilers 5.0 98/12/15 C 5.0 | |||
version_re = re.compile(r'cc: (studio.*?|\s+)?(sun\s+(c\+\+|c)|(WorkShop\s+Compilers))?\s+(?P<major>\d*)\.(?P<minor>\d*)', re.I).search | |||
match = version_re(version) | |||
if match: | |||
k = match.groupdict() | |||
@@ -735,7 +735,7 @@ def tokenize_private(s): | |||
if v: | |||
if name == IDENT: | |||
try: | |||
g_optrans[v]; | |||
g_optrans[v] | |||
name = OP | |||
except KeyError: | |||
# c++ specific | |||
@@ -127,18 +127,23 @@ class utest(Task.Task): | |||
testcmd = getattr(self.generator, 'ut_cmd', False) or getattr(Options.options, 'testcmd', False) | |||
if testcmd: | |||
self.ut_exec = (testcmd % self.ut_exec[0]).split(' ') | |||
self.ut_exec = (testcmd % " ".join(self.ut_exec)).split(' ') | |||
proc = Utils.subprocess.Popen(self.ut_exec, cwd=cwd, env=self.get_test_env(), stderr=Utils.subprocess.PIPE, stdout=Utils.subprocess.PIPE) | |||
(stdout, stderr) = proc.communicate() | |||
tup = (filename, proc.returncode, stdout, stderr) | |||
self.waf_unit_test_results = tup = (filename, proc.returncode, stdout, stderr) | |||
testlock.acquire() | |||
try: | |||
return self.generator.add_test_results(tup) | |||
finally: | |||
testlock.release() | |||
def post_run(self): | |||
super(utest, self).post_run() | |||
if getattr(Options.options, 'clear_failed_tests', False) and self.waf_unit_test_results[1]: | |||
self.generator.bld.task_sigs[self.uid()] = None | |||
def summary(bld): | |||
""" | |||
Display an execution summary:: | |||
@@ -194,6 +199,7 @@ def options(opt): | |||
""" | |||
opt.add_option('--notests', action='store_true', default=False, help='Exec no unit tests', dest='no_tests') | |||
opt.add_option('--alltests', action='store_true', default=False, help='Exec all unit tests', dest='all_tests') | |||
opt.add_option('--clear-failed', action='store_true', default=False, help='Force failed unit tests to run again next time', dest='clear_failed_tests') | |||
opt.add_option('--testcmd', action='store', default=False, | |||
help = 'Run the unit tests using the test-cmd string' | |||
' example "--test-cmd="valgrind --error-exitcode=1' | |||
@@ -213,7 +213,7 @@ class PBXProject(XCodeNode): | |||
XCodeNode.__init__(self) | |||
self.buildConfigurationList = XCConfigurationList([XCBuildConfiguration('waf', {})]) | |||
self.compatibilityVersion = version[0] | |||
self.hasScannedForEncodings = 1; | |||
self.hasScannedForEncodings = 1 | |||
self.mainGroup = PBXGroup(name) | |||
self.projectRoot = "" | |||
self.projectDirPath = "" | |||
@@ -417,7 +417,7 @@ class PBXProject(XCodeNode): | |||
self.buildConfigurationList = XCConfigurationList(configurations) | |||
self.compatibilityVersion = version[0] | |||
self.hasScannedForEncodings = 1; | |||
self.hasScannedForEncodings = 1 | |||
self.mainGroup = PBXGroup(name) | |||
self.projectRoot = "" | |||
self.projectDirPath = "" | |||