diff options
author | Alexander Bokovoy <ab@samba.org> | 2018-01-31 11:48:43 +0200 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2018-09-05 06:37:22 +0200 |
commit | 4e65b33c1d40bb2c243f775f388056aed31d8671 (patch) | |
tree | 5a41b6ddef7ce1c0b6a93bcc16ef89da10f080e8 /third_party/waf/waflib/Tools | |
parent | faef27506977db01cc4619140a71652463914378 (diff) | |
download | samba-4e65b33c1d40bb2c243f775f388056aed31d8671.tar.gz |
third_party:waf: update to upstream 2.0.4 release
Update third_party/waf/ to 2.0.4 to bring us closer to Python 3
This change requires a number of changes in buildtools/ too.
Signed-off-by: Alexander Bokovoy <ab@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Diffstat (limited to 'third_party/waf/waflib/Tools')
62 files changed, 767 insertions, 1353 deletions
diff --git a/third_party/waf/waflib/Tools/__init__.py b/third_party/waf/waflib/Tools/__init__.py index 8766ecb7da1..94cf66f799b 100644 --- a/third_party/waf/waflib/Tools/__init__.py +++ b/third_party/waf/waflib/Tools/__init__.py @@ -4,4 +4,4 @@ #!/usr/bin/env python # encoding: utf-8 -# Thomas Nagy, 2005-2016 (ita) +# Thomas Nagy, 2005-2018 (ita) diff --git a/third_party/waf/waflib/Tools/ar.py b/third_party/waf/waflib/Tools/ar.py index 2ee1a0851bb..bf5220d41c0 100644 --- a/third_party/waf/waflib/Tools/ar.py +++ b/third_party/waf/waflib/Tools/ar.py @@ -4,7 +4,7 @@ #!/usr/bin/env python # encoding: utf-8 -# Thomas Nagy, 2006-2016 (ita) +# Thomas Nagy, 2006-2018 (ita) # Ralf Habacker, 2006 (rh) """ @@ -25,3 +25,4 @@ def configure(conf): conf.add_os_flags('ARFLAGS') if not conf.env.ARFLAGS: conf.env.ARFLAGS = ['rcs'] + diff --git a/third_party/waf/waflib/Tools/asm.py b/third_party/waf/waflib/Tools/asm.py index f14a725fb12..46fa614d9d3 100644 --- a/third_party/waf/waflib/Tools/asm.py +++ b/third_party/waf/waflib/Tools/asm.py @@ -4,7 +4,7 @@ #!/usr/bin/env python # encoding: utf-8 -# Thomas Nagy, 2008-2016 (ita) +# Thomas Nagy, 2008-2018 (ita) """ Assembly support, used by tools such as gas and nasm diff --git a/third_party/waf/waflib/Tools/bison.py b/third_party/waf/waflib/Tools/bison.py index 5b455836886..771d39e7abf 100644 --- a/third_party/waf/waflib/Tools/bison.py +++ b/third_party/waf/waflib/Tools/bison.py @@ -5,7 +5,7 @@ #!/usr/bin/env python # encoding: utf-8 # John O'Meara, 2006 -# Thomas Nagy 2009-2016 (ita) +# Thomas Nagy 2009-2018 (ita) """ The **bison** program is a code generator which creates C or C++ files. @@ -50,3 +50,4 @@ def configure(conf): """ conf.find_program('bison', var='BISON') conf.env.BISONFLAGS = ['-d'] + diff --git a/third_party/waf/waflib/Tools/c.py b/third_party/waf/waflib/Tools/c.py index f54fd10c11e..0b998a3b0ee 100644 --- a/third_party/waf/waflib/Tools/c.py +++ b/third_party/waf/waflib/Tools/c.py @@ -4,7 +4,7 @@ #!/usr/bin/env python # encoding: utf-8 -# Thomas Nagy, 2006-2016 (ita) +# Thomas Nagy, 2006-2018 (ita) "Base for c programs/libraries" @@ -40,3 +40,4 @@ class cshlib(cprogram): class cstlib(stlink_task): "Links object files into a c static libraries" pass # do not remove + diff --git a/third_party/waf/waflib/Tools/c_aliases.py b/third_party/waf/waflib/Tools/c_aliases.py index 6fa8c68ed77..d9c050b46f8 100644 --- a/third_party/waf/waflib/Tools/c_aliases.py +++ b/third_party/waf/waflib/Tools/c_aliases.py @@ -145,3 +145,4 @@ def objects(bld, *k, **kw): """ set_features(kw, 'objects') return bld(*k, **kw) + diff --git a/third_party/waf/waflib/Tools/c_config.py b/third_party/waf/waflib/Tools/c_config.py index b6156004895..db8197db14b 100644 --- a/third_party/waf/waflib/Tools/c_config.py +++ b/third_party/waf/waflib/Tools/c_config.py @@ -4,7 +4,7 @@ #!/usr/bin/env python # encoding: utf-8 -# Thomas Nagy, 2005-2016 (ita) +# Thomas Nagy, 2005-2018 (ita) """ C/C++/D configuration helpers @@ -23,32 +23,6 @@ WAF_CONFIG_H = 'config.h' DEFKEYS = 'define_key' INCKEYS = 'include_key' -cfg_ver = { - 'atleast-version': '>=', - 'exact-version': '==', - 'max-version': '<=', -} - -SNIP_FUNCTION = ''' -int main(int argc, char **argv) { - void (*p)(); - (void)argc; (void)argv; - p=(void(*)())(%s); - return !p; -} -''' -"""Code template for checking for functions""" - -SNIP_TYPE = ''' -int main(int argc, char **argv) { - (void)argc; (void)argv; - if ((%(type_name)s *) 0) return 0; - if (sizeof (%(type_name)s)) return 0; - return 1; -} -''' -"""Code template for checking for types""" - SNIP_EMPTY_PROGRAM = ''' int main(int argc, char **argv) { (void)argc; (void)argv; @@ -56,15 +30,6 @@ int main(int argc, char **argv) { } ''' -SNIP_FIELD = ''' -int main(int argc, char **argv) { - char *off; - (void)argc; (void)argv; - off = (char*) &((%(type_name)s*)0)->%(field_name)s; - return (size_t) off < sizeof(%(type_name)s); -} -''' - MACRO_TO_DESTOS = { '__linux__' : 'linux', '__GNU__' : 'gnu', # hurd @@ -205,7 +170,8 @@ def parse_flags(self, line, uselib_store, env=None, force_static=False, posix=No static = False elif x.startswith('-Wl') or x in ('-rdynamic', '-pie'): app('LINKFLAGS', x) - elif x.startswith(('-m', '-f', '-dynamic', '-O')): + elif x.startswith(('-m', '-f', '-dynamic', '-O', '-g')): + # Adding the -W option breaks python builds on Openindiana app('CFLAGS', x) app('CXXFLAGS', x) elif x.startswith('-bundle'): @@ -243,55 +209,42 @@ def validate_cfg(self, kw): self.find_program('pkg-config', var='PKGCONFIG') kw['path'] = self.env.PKGCONFIG - # pkg-config version - if 'atleast_pkgconfig_version' in kw: - if not 'msg' in kw: + # verify that exactly one action is requested + s = ('atleast_pkgconfig_version' in kw) + ('modversion' in kw) + ('package' in kw) + if s != 1: + raise ValueError('exactly one of atleast_pkgconfig_version, modversion and package must be set') + if not 'msg' in kw: + if 'atleast_pkgconfig_version' in kw: kw['msg'] = 'Checking for pkg-config version >= %r' % kw['atleast_pkgconfig_version'] - return + elif 'modversion' in kw: + kw['msg'] = 'Checking for %r version' % kw['modversion'] + else: + kw['msg'] = 'Checking for %r' %(kw['package']) - if not 'okmsg' in kw: + # let the modversion check set the okmsg to the detected version + if not 'okmsg' in kw and not 'modversion' in kw: kw['okmsg'] = 'yes' if not 'errmsg' in kw: kw['errmsg'] = 'not found' - if 'modversion' in kw: - if not 'msg' in kw: - kw['msg'] = 'Checking for %r version' % kw['modversion'] + # pkg-config version + if 'atleast_pkgconfig_version' in kw: + pass + elif 'modversion' in kw: if not 'uselib_store' in kw: kw['uselib_store'] = kw['modversion'] if not 'define_name' in kw: kw['define_name'] = '%s_VERSION' % Utils.quote_define_name(kw['uselib_store']) - return - - if not 'package' in kw: - raise ValueError('a package name is required') - - if not 'uselib_store' in kw: - kw['uselib_store'] = kw['package'].upper() - - if not 'define_name' in kw: - kw['define_name'] = self.have_define(kw['uselib_store']) - - if not 'msg' in kw: - kw['msg'] = 'Checking for %r' % (kw['package'] or kw['path']) - - for x in cfg_ver: - # Gotcha: only one predicate is allowed at a time - # TODO remove in waf 2.0 - y = x.replace('-', '_') - if y in kw: - package = kw['package'] - if Logs.verbose: - Logs.warn('Passing %r to conf.check_cfg() is obsolete, pass parameters directly, eg:', y) - Logs.warn(" conf.check_cfg(package='%s', args=['--libs', '--cflags', '%s >= 1.6'])", package, package) - if not 'msg' in kw: - kw['msg'] = 'Checking for %r %s %s' % (package, cfg_ver[x], kw[y]) - break + else: + if not 'uselib_store' in kw: + kw['uselib_store'] = Utils.to_list(kw['package'])[0].upper() + if not 'define_name' in kw: + kw['define_name'] = self.have_define(kw['uselib_store']) @conf def exec_cfg(self, kw): """ - Executes ``pkg-config`` or other ``-config`` applications to colect configuration flags: + Executes ``pkg-config`` or other ``-config`` applications to collect configuration flags: * if atleast_pkgconfig_version is given, check that pkg-config has the version n and return * if modversion is given, then return the module version @@ -335,23 +288,13 @@ def exec_cfg(self, kw): if 'atleast_pkgconfig_version' in kw: cmd = path + ['--atleast-pkgconfig-version=%s' % kw['atleast_pkgconfig_version']] self.cmd_and_log(cmd, env=env) - if not 'okmsg' in kw: - kw['okmsg'] = 'yes' return - for x in cfg_ver: - # TODO remove in waf 2.0 - y = x.replace('-', '_') - if y in kw: - self.cmd_and_log(path + ['--%s=%s' % (x, kw[y]), kw['package']], env=env) - if not 'okmsg' in kw: - kw['okmsg'] = 'yes' - define_it() - break - # single version for a module if 'modversion' in kw: version = self.cmd_and_log(path + ['--modversion', kw['modversion']], env=env).strip() + if not 'okmsg' in kw: + kw['okmsg'] = version self.define(kw['define_name'], version) return version @@ -381,14 +324,10 @@ def exec_cfg(self, kw): val = self.cmd_and_log(lst + ['--variable=' + v], env=env).strip() var = '%s_%s' % (kw['uselib_store'], v) v_env[var] = val - if not 'okmsg' in kw: - kw['okmsg'] = 'yes' return # so we assume the command-line will output flags to be parsed afterwards ret = self.cmd_and_log(lst, env=env) - if not 'okmsg' in kw: - kw['okmsg'] = 'yes' define_it() self.parse_flags(ret, kw['uselib_store'], kw.get('env', self.env), force_static=static, posix=kw.get('posix')) @@ -405,8 +344,6 @@ def check_cfg(self, *k, **kw): def configure(conf): conf.load('compiler_c') conf.check_cfg(package='glib-2.0', args='--libs --cflags') - conf.check_cfg(package='glib-2.0', uselib_store='GLIB', atleast_version='2.10.0', - args='--cflags --libs') conf.check_cfg(package='pango') conf.check_cfg(package='pango', uselib_store='MYPANGO', args=['--cflags', '--libs']) conf.check_cfg(package='pango', @@ -419,11 +356,6 @@ def check_cfg(self, *k, **kw): conf.check_cfg(package='gtk+-2.0', variables=['includedir', 'prefix'], uselib_store='FOO') print(conf.env.FOO_includedir) """ - if k: - lst = k[0].split() - kw['package'] = lst[0] - kw['args'] = ' '.join(lst[1:]) - self.validate_cfg(kw) if 'msg' in kw: self.start_msg(kw['msg'], **kw) @@ -490,6 +422,9 @@ def validate_c(self, kw): :param auto_add_header_name: if header_name was set, add the headers in env.INCKEYS so the next tests will include these headers :type auto_add_header_name: bool """ + for x in ('type_name', 'field_name', 'function_name'): + if x in kw: + Logs.warn('Invalid argument %r in test' % x) if not 'build_fun' in kw: kw['build_fun'] = build_fun @@ -510,7 +445,7 @@ def validate_c(self, kw): if not 'compile_mode' in kw: kw['compile_mode'] = 'c' - if 'cxx' in Utils.to_list(kw.get('features',[])) or kw.get('compiler', '') == 'cxx': + if 'cxx' in Utils.to_list(kw.get('features', [])) or kw.get('compiler') == 'cxx': kw['compile_mode'] = 'cxx' if not 'type' in kw: @@ -533,50 +468,19 @@ def validate_c(self, kw): return ''.join(['#include <%s>\n' % x for x in dct]) return '' - #OSX if 'framework_name' in kw: + # OSX, not sure this is used anywhere fwkname = kw['framework_name'] if not 'uselib_store' in kw: kw['uselib_store'] = fwkname.upper() - if not kw.get('no_header', False): - if not 'header_name' in kw: - kw['header_name'] = [] + if not kw.get('no_header'): fwk = '%s/%s.h' % (fwkname, fwkname) if kw.get('remove_dot_h'): fwk = fwk[:-2] - kw['header_name'] = Utils.to_list(kw['header_name']) + [fwk] - + val = kw.get('header_name', []) + kw['header_name'] = Utils.to_list(val) + [fwk] kw['msg'] = 'Checking for framework %s' % fwkname kw['framework'] = fwkname - #kw['frameworkpath'] = set it yourself - - if 'function_name' in kw: - fu = kw['function_name'] - if not 'msg' in kw: - kw['msg'] = 'Checking for function %s' % fu - kw['code'] = to_header(kw) + SNIP_FUNCTION % fu - if not 'uselib_store' in kw: - kw['uselib_store'] = fu.upper() - if not 'define_name' in kw: - kw['define_name'] = self.have_define(fu) - - elif 'type_name' in kw: - tu = kw['type_name'] - if not 'header_name' in kw: - kw['header_name'] = 'stdint.h' - if 'field_name' in kw: - field = kw['field_name'] - kw['code'] = to_header(kw) + SNIP_FIELD % {'type_name' : tu, 'field_name' : field} - if not 'msg' in kw: - kw['msg'] = 'Checking for field %s in %s' % (field, tu) - if not 'define_name' in kw: - kw['define_name'] = self.have_define((tu + '_' + field).upper()) - else: - kw['code'] = to_header(kw) + SNIP_TYPE % {'type_name' : tu} - if not 'msg' in kw: - kw['msg'] = 'Checking for type %s' % tu - if not 'define_name' in kw: - kw['define_name'] = self.have_define(tu.upper()) elif 'header_name' in kw: if not 'msg' in kw: @@ -639,11 +543,12 @@ def validate_c(self, kw): kw['code'] = '\n'.join(['#include <%s>' % x for x in self.env[INCKEYS]]) + '\n' + kw['code'] # in case defines lead to very long command-lines - if kw.get('merge_config_header', False) or env.merge_config_header: + if kw.get('merge_config_header') or env.merge_config_header: kw['code'] = '%s\n\n%s' % (self.get_config_header(), kw['code']) env.DEFINES = [] # modify the copy - if not kw.get('success'): kw['success'] = None + if not kw.get('success'): + kw['success'] = None if 'define_name' in kw: self.undefine(kw['define_name']) @@ -659,7 +564,7 @@ def post_check(self, *k, **kw): is_success = 0 if kw['execute']: if kw['success'] is not None: - if kw.get('define_ret', False): + if kw.get('define_ret'): is_success = kw['success'] else: is_success = (kw['success'] == 0) @@ -667,7 +572,6 @@ def post_check(self, *k, **kw): is_success = (kw['success'] == 0) if kw.get('define_name'): - # TODO this is still way too complicated comment = kw.get('comment', '') define_name = kw['define_name'] if kw['execute'] and kw.get('define_ret') and isinstance(is_success, str): @@ -698,7 +602,7 @@ def post_check(self, *k, **kw): self.env[define_name] = int(is_success) if 'header_name' in kw: - if kw.get('auto_add_header_name', False): + if kw.get('auto_add_header_name'): self.env.append_value(INCKEYS, Utils.to_list(kw['header_name'])) if is_success and 'uselib_store' in kw: @@ -986,7 +890,8 @@ def write_config_header(self, configfile='', guard='', top=False, defines=True, :type define_prefix: string :param define_prefix: prefix all the defines in the file with a particular prefix """ - if not configfile: configfile = WAF_CONFIG_H + if not configfile: + configfile = WAF_CONFIG_H waf_guard = guard or 'W_%s_WAF' % Utils.quote_define_name(configfile) node = top and self.bldnode or self.path.get_bld() @@ -1110,8 +1015,8 @@ def get_cc_version(conf, cc, gcc=False, icc=False, clang=False): cmd = cc + ['-dM', '-E', '-'] env = conf.env.env or None try: - out, err = conf.cmd_and_log(cmd, output=0, input='\n', env=env) - except Exception: + out, err = conf.cmd_and_log(cmd, output=0, input='\n'.encode(), env=env) + except Errors.WafError: conf.fatal('Could not determine the compiler version %r' % cmd) if gcc: @@ -1159,6 +1064,8 @@ def get_cc_version(conf, cc, gcc=False, icc=False, clang=False): conf.env.DEST_BINFMT = 'elf' elif isD('__WINNT__') or isD('__CYGWIN__') or isD('_WIN32'): conf.env.DEST_BINFMT = 'pe' + if not conf.env.IMPLIBDIR: + conf.env.IMPLIBDIR = conf.env.LIBDIR # for .lib or .dll.a files conf.env.LIBDIR = conf.env.BINDIR elif isD('__APPLE__'): conf.env.DEST_BINFMT = 'mac-o' @@ -1218,7 +1125,7 @@ def get_suncc_version(conf, cc): cmd = cc + ['-V'] try: out, err = conf.cmd_and_log(cmd, output=0) - except Errors.WafError ,e: + except Errors.WafError as e: # Older versions of the compiler exit with non-zero status when reporting their version if not (hasattr(e, 'returncode') and hasattr(e, 'stdout') and hasattr(e, 'stderr')): conf.fatal('Could not find suncc %r' % cmd) @@ -1252,14 +1159,14 @@ def add_as_needed(self): # ============ parallel configuration -class cfgtask(Task.TaskBase): +class cfgtask(Task.Task): """ A task that executes build configuration tests (calls conf.check) Make sure to use locks if concurrent access to the same conf.env data is necessary. """ def __init__(self, *k, **kw): - Task.TaskBase.__init__(self, *k, **kw) + Task.Task.__init__(self, *k, **kw) self.run_after = set() def display(self): @@ -1274,6 +1181,9 @@ class cfgtask(Task.TaskBase): def uid(self): return Utils.SIG_NIL + def signature(self): + return Utils.SIG_NIL + def run(self): conf = self.conf bld = Build.BuildContext(top_dir=conf.srcnode.abspath(), out_dir=conf.bldnode.abspath()) @@ -1301,7 +1211,7 @@ class cfgtask(Task.TaskBase): return 1 def process(self): - Task.TaskBase.process(self) + Task.Task.process(self) if 'msg' in self.args: with self.generator.bld.multicheck_lock: self.conf.start_msg(self.args['msg']) @@ -1357,11 +1267,12 @@ def multicheck(self, *k, **kw): bld = par() bld.keep = kw.get('run_all_tests', True) + bld.imp_sigs = {} tasks = [] id_to_task = {} for dct in k: - x = Task.classes['cfgtask'](bld=bld) + x = Task.classes['cfgtask'](bld=bld, env=None) tasks.append(x) x.args = dct x.bld = bld @@ -1424,3 +1335,22 @@ def multicheck(self, *k, **kw): if x.hasrun != Task.SUCCESS: if x.args.get('mandatory', True): self.fatal(kw.get('fatalmsg') or 'One of the tests has failed, read config.log for more information') + +@conf +def check_gcc_o_space(self, mode='c'): + if int(self.env.CC_VERSION[0]) > 4: + # this is for old compilers + return + self.env.stash() + if mode == 'c': + self.env.CCLNK_TGT_F = ['-o', ''] + elif mode == 'cxx': + self.env.CXXLNK_TGT_F = ['-o', ''] + features = '%s %sshlib' % (mode, mode) + try: + self.check(msg='Checking if the -o link must be split from arguments', fragment=SNIP_EMPTY_PROGRAM, features=features) + except self.errors.ConfigurationError: + self.env.revert() + else: + self.env.commit() + diff --git a/third_party/waf/waflib/Tools/c_osx.py b/third_party/waf/waflib/Tools/c_osx.py index c575de28b99..bafcda19684 100644 --- a/third_party/waf/waflib/Tools/c_osx.py +++ b/third_party/waf/waflib/Tools/c_osx.py @@ -4,7 +4,7 @@ #!/usr/bin/env python # encoding: utf-8 -# Thomas Nagy 2008-2016 (ita) +# Thomas Nagy 2008-2018 (ita) """ MacOSX related tools @@ -194,3 +194,4 @@ class macplist(Task.Task): context = getattr(self, 'context', {}) txt = txt.format(**context) self.outputs[0].write(txt) + diff --git a/third_party/waf/waflib/Tools/c_preproc.py b/third_party/waf/waflib/Tools/c_preproc.py index 3d1208d2cf1..1a8b9137644 100644 --- a/third_party/waf/waflib/Tools/c_preproc.py +++ b/third_party/waf/waflib/Tools/c_preproc.py @@ -4,7 +4,7 @@ #!/usr/bin/env python # encoding: utf-8 -# Thomas Nagy, 2006-2016 (ita) +# Thomas Nagy, 2006-2018 (ita) """ C/C++ preprocessor for finding dependencies @@ -48,15 +48,15 @@ recursion_limit = 150 go_absolute = False "Set to True to track headers on files in /usr/include, else absolute paths are ignored (but it becomes very slow)" -standard_includes = ['/usr/include'] +standard_includes = ['/usr/local/include', '/usr/include'] if Utils.is_win32: standard_includes = [] use_trigraphs = 0 """Apply trigraph rules (False by default)""" +# obsolete, do not use strict_quotes = 0 -"""Reserve the "#include <>" quotes for system includes (do not search for those includes). False by default.""" g_optrans = { 'not':'!', @@ -159,22 +159,6 @@ for x, syms in enumerate(ops): for u in syms.split(): prec[u] = x -def trimquotes(s): - """ - Remove the single quotes around an expression:: - - trimquotes("'test'") == "test" - - :param s: expression to transform - :type s: string - :rtype: string - """ - # TODO remove in waf 2.0 - if not s: return '' - s = s.rstrip() - if s[0] == "'" and s[-1] == "'": return s[1:-1] - return s - def reduce_nums(val_1, val_2, val_op): """ Apply arithmetic rules to compute a result @@ -190,32 +174,56 @@ def reduce_nums(val_1, val_2, val_op): #print val_1, val_2, val_op # now perform the operation, make certain a and b are numeric - try: a = 0 + val_1 - except TypeError: a = int(val_1) - try: b = 0 + val_2 - except TypeError: b = int(val_2) + try: + a = 0 + val_1 + except TypeError: + a = int(val_1) + try: + b = 0 + val_2 + except TypeError: + b = int(val_2) d = val_op - if d == '%': c = a%b - elif d=='+': c = a+b - elif d=='-': c = a-b - elif d=='*': c = a*b - elif d=='/': c = a/b - elif d=='^': c = a^b - elif d=='==': c = int(a == b) - elif d=='|' or d == 'bitor': c = a|b - elif d=='||' or d == 'or' : c = int(a or b) - elif d=='&' or d == 'bitand': c = a&b - elif d=='&&' or d == 'and': c = int(a and b) - elif d=='!=' or d == 'not_eq': c = int(a != b) - elif d=='^' or d == 'xor': c = int(a^b) - elif d=='<=': c = int(a <= b) - elif d=='<': c = int(a < b) - elif d=='>': c = int(a > b) - elif d=='>=': c = int(a >= b) - elif d=='<<': c = a<<b - elif d=='>>': c = a>>b - else: c = 0 + if d == '%': + c = a % b + elif d=='+': + c = a + b + elif d=='-': + c = a - b + elif d=='*': + c = a * b + elif d=='/': + c = a / b + elif d=='^': + c = a ^ b + elif d=='==': + c = int(a == b) + elif d=='|' or d == 'bitor': + c = a | b + elif d=='||' or d == 'or' : + c = int(a or b) + elif d=='&' or d == 'bitand': + c = a & b + elif d=='&&' or d == 'and': + c = int(a and b) + elif d=='!=' or d == 'not_eq': + c = int(a != b) + elif d=='^' or d == 'xor': + c = int(a^b) + elif d=='<=': + c = int(a <= b) + elif d=='<': + c = int(a < b) + elif d=='>': + c = int(a > b) + elif d=='>=': + c = int(a >= b) + elif d=='<<': + c = a << b + elif d=='>>': + c = a >> b + else: + c = 0 return c def get_num(lst): @@ -227,7 +235,8 @@ def get_num(lst): :return: a pair containing the number and the rest of the list :rtype: tuple(value, list) """ - if not lst: raise PreprocError('empty list for get_num') + if not lst: + raise PreprocError('empty list for get_num') (p, v) = lst[0] if p == OP: if v == '(': @@ -283,7 +292,8 @@ def get_term(lst): :rtype: value, list """ - if not lst: raise PreprocError('empty list for get_term') + if not lst: + raise PreprocError('empty list for get_term') num, lst = get_num(lst) if not lst: return (num, []) @@ -466,18 +476,22 @@ def reduce_tokens(lst, defs, ban=[]): one_param.append((p2, v2)) count_paren += 1 elif v2 == ')': - if one_param: args.append(one_param) + if one_param: + args.append(one_param) break elif v2 == ',': - if not one_param: raise PreprocError('empty param in funcall %r' % v) + if not one_param: + raise PreprocError('empty param in funcall %r' % v) args.append(one_param) one_param = [] else: one_param.append((p2, v2)) else: one_param.append((p2, v2)) - if v2 == '(': count_paren += 1 - elif v2 == ')': count_paren -= 1 + if v2 == '(': + count_paren += 1 + elif v2 == ')': + count_paren -= 1 else: raise PreprocError('malformed macro') @@ -514,7 +528,6 @@ def reduce_tokens(lst, defs, ban=[]): accu.append((p2, v2)) accu.extend(toks) elif to_add[j+1][0] == IDENT and to_add[j+1][1] == '__VA_ARGS__': - # TODO not sure # first collect the tokens va_toks = [] st = len(macro_def[0]) @@ -522,7 +535,8 @@ def reduce_tokens(lst, defs, ban=[]): for x in args[pt-st+1:]: va_toks.extend(x) va_toks.append((OP, ',')) - if va_toks: va_toks.pop() # extra comma + if va_toks: + va_toks.pop() # extra comma if len(accu)>1: (p3, v3) = accu[-1] (p4, v4) = accu[-2] @@ -570,7 +584,8 @@ def eval_macro(lst, defs): :rtype: int """ reduce_tokens(lst, defs, []) - if not lst: raise PreprocError('missing tokens to evaluate') + if not lst: + raise PreprocError('missing tokens to evaluate') if lst: p, v = lst[0] @@ -597,7 +612,8 @@ def extract_macro(txt): p, name = t[0] p, v = t[1] - if p != OP: raise PreprocError('expected (') + if p != OP: + raise PreprocError('expected (') i = 1 pindex = 0 @@ -700,16 +716,20 @@ def parse_char(txt): return ord(txt) c = txt[1] if c == 'x': - if len(txt) == 4 and txt[3] in string.hexdigits: return int(txt[2:], 16) + if len(txt) == 4 and txt[3] in string.hexdigits: + return int(txt[2:], 16) return int(txt[2:], 16) elif c.isdigit(): - if c == '0' and len(txt)==2: return 0 + if c == '0' and len(txt)==2: + return 0 for i in 3, 2, 1: if len(txt) > i and txt[1:1+i].isdigit(): return (1+i, int(txt[1:1+i], 8)) else: - try: return chr_esc[c] - except KeyError: raise PreprocError('could not parse char literal %r' % txt) + try: + return chr_esc[c] + except KeyError: + raise PreprocError('could not parse char literal %r' % txt) def tokenize(s): """ @@ -730,28 +750,32 @@ def tokenize_private(s): v = m(name) if v: if name == IDENT: - try: - g_optrans[v] + if v in g_optrans: name = OP - except KeyError: - # c++ specific - if v.lower() == "true": - v = 1 - name = NUM - elif v.lower() == "false": - v = 0 - name = NUM + elif v.lower() == "true": + v = 1 + name = NUM + elif v.lower() == "false": + v = 0 + name = NUM elif name == NUM: - if m('oct'): v = int(v, 8) - elif m('hex'): v = int(m('hex'), 16) - elif m('n0'): v = m('n0') + if m('oct'): + v = int(v, 8) + elif m('hex'): + v = int(m('hex'), 16) + elif m('n0'): + v = m('n0') else: v = m('char') - if v: v = parse_char(v) - else: v = m('n2') or m('n4') + if v: + v = parse_char(v) + else: + v = m('n2') or m('n4') elif name == OP: - if v == '%:': v = '#' - elif v == '%:%:': v = '##' + if v == '%:': + v = '#' + elif v == '%:%:': + v = '##' elif name == STR: # remove the quotes around the string v = v[1:-1] @@ -807,6 +831,9 @@ class c_parser(object): self.ban_includes = set() """Includes that must not be read (#pragma once)""" + self.listed = set() + """Include nodes/names already listed to avoid duplicates in self.nodes/self.names""" + def cached_find_resource(self, node, filename): """ Find a file from the input directory @@ -821,7 +848,6 @@ class c_parser(object): try: cache = node.ctx.preproc_cache_node except AttributeError: - global FILE_CACHE_SIZE cache = node.ctx.preproc_cache_node = Utils.lru_cache(FILE_CACHE_SIZE) key = (node, filename) @@ -839,7 +865,7 @@ class c_parser(object): cache[key] = ret return ret - def tryfind(self, filename): + def tryfind(self, filename, kind='"', env=None): """ Try to obtain a node from the filename based from the include paths. Will add the node found to :py:attr:`waflib.Tools.c_preproc.c_parser.nodes` or the file name to @@ -853,26 +879,37 @@ class c_parser(object): """ if filename.endswith('.moc'): # we could let the qt4 module use a subclass, but then the function "scan" below must be duplicated - # in the qt4 and in the qt5 classes. So we have two lines here and it is sufficient. TODO waf 1.9 + # in the qt4 and in the qt5 classes. So we have two lines here and it is sufficient. self.names.append(filename) return None self.curfile = filename - # for msvc it should be a for loop over the whole stack - found = self.cached_find_resource(self.currentnode_stack[-1], filename) + found = None + if kind == '"': + if env.MSVC_VERSION: + for n in reversed(self.currentnode_stack): + found = self.cached_find_resource(n, filename) + if found: + break + else: + found = self.cached_find_resource(self.currentnode_stack[-1], filename) - for n in self.nodepaths: - if found: - break - found = self.cached_find_resource(n, filename) + if not found: + for n in self.nodepaths: + found = self.cached_find_resource(n, filename) + if found: + break + listed = self.listed if found and not found in self.ban_includes: - # TODO duplicates do not increase the no-op build times too much, but they may be worth removing - self.nodes.append(found) + if found not in listed: + listed.add(found) + self.nodes.append(found) self.addlines(found) else: - if not filename in self.names: + if filename not in listed: + listed.add(filename) self.names.append(filename) return found @@ -887,7 +924,8 @@ class c_parser(object): # return a list of tuples : keyword, line code = node.read() if use_trigraphs: - for (a, b) in trig_def: code = code.split(a).join(b) + for (a, b) in trig_def: + code = code.split(a).join(b) code = re_nl.sub('', code) code = re_cpp.sub(repl, code) return re_lines.findall(code) @@ -896,7 +934,6 @@ class c_parser(object): try: cache = node.ctx.preproc_cache_lines except AttributeError: - global LINE_CACHE_SIZE cache = node.ctx.preproc_cache_lines = Utils.lru_cache(LINE_CACHE_SIZE) try: return cache[node] @@ -929,8 +966,7 @@ class c_parser(object): raise PreprocError('could not read the file %r' % node) except Exception: if Logs.verbose > 0: - Logs.error('parsing %r failed', node) - traceback.print_exc() + Logs.error('parsing %r failed %s', node, traceback.format_exc()) else: self.lines.extend(lines) @@ -963,8 +999,6 @@ class c_parser(object): continue try: - ve = Logs.verbose - if ve: Logs.debug('preproc: line is %s - %s state is %s', token, line, self.state) state = self.state # make certain we define the state if we are about to enter in an if block @@ -980,23 +1014,27 @@ class c_parser(object): if token == 'if': ret = eval_macro(tokenize(line), self.defs) - if ret: state[-1] = accepted - else: state[-1] = ignored + if ret: + state[-1] = accepted + else: + state[-1] = ignored elif token == 'ifdef': m = re_mac.match(line) - if m and m.group() in self.defs: state[-1] = accepted - else: state[-1] = ignored + if m and m.group() in self.defs: + state[-1] = accepted + else: + state[-1] = ignored elif token == 'ifndef': m = re_mac.match(line) - if m and m.group() in self.defs: state[-1] = ignored - else: state[-1] = accepted + if m and m.group() in self.defs: + state[-1] = ignored + else: + state[-1] = accepted elif token == 'include' or token == 'import': (kind, inc) = extract_include(line, self.defs) - if ve: Logs.debug('preproc: include found %s (%s) ', inc, kind) - if kind == '"' or not strict_quotes: - self.current_file = self.tryfind(inc) - if token == 'import': - self.ban_includes.add(self.current_file) + self.current_file = self.tryfind(inc, kind, env) + if token == 'import': + self.ban_includes.add(self.current_file) elif token == 'elif': if state[-1] == accepted: state[-1] = skipped @@ -1004,8 +1042,10 @@ class c_parser(object): if eval_macro(tokenize(line), self.defs): state[-1] = accepted elif token == 'else': - if state[-1] == accepted: state[-1] = skipped - elif state[-1] == ignored: state[-1] = accepted + if state[-1] == accepted: + state[-1] = skipped + elif state[-1] == ignored: + state[-1] = accepted elif token == 'define': try: self.defs[self.define_name(line)] = line @@ -1019,9 +1059,9 @@ class c_parser(object): elif token == 'pragma': if re_pragma_once.match(line.lower()): self.ban_includes.add(self.current_file) - except Exception ,e: + except Exception as e: if Logs.verbose: - Logs.debug('preproc: line parsing failed (%s): %s %s', e, line, Utils.ex_stack()) + Logs.debug('preproc: line parsing failed (%s): %s %s', e, line, traceback.format_exc()) def define_name(self, line): """ @@ -1040,9 +1080,6 @@ def scan(task): This function is bound as a task method on :py:class:`waflib.Tools.c.c` and :py:class:`waflib.Tools.cxx.cxx` for example """ - - global go_absolute - try: incn = task.generator.includes_nodes except AttributeError: diff --git a/third_party/waf/waflib/Tools/c_tests.py b/third_party/waf/waflib/Tools/c_tests.py index d4b8469e3db..c3620192498 100644 --- a/third_party/waf/waflib/Tools/c_tests.py +++ b/third_party/waf/waflib/Tools/c_tests.py @@ -4,7 +4,7 @@ #!/usr/bin/env python # encoding: utf-8 -# Thomas Nagy, 2016 (ita) +# Thomas Nagy, 2016-2018 (ita) """ Various configuration tests. @@ -203,7 +203,7 @@ class grep_for_endianness(Task.Task): """ color = 'PINK' def run(self): - txt = self.inputs[0].read(flags='rb').decode('iso8859-1') + txt = self.inputs[0].read(flags='rb').decode('latin-1') if txt.find('LiTTleEnDian') > -1: self.generator.tmp.append('little') elif txt.find('BIGenDianSyS') > -1: @@ -230,3 +230,4 @@ def check_endianness(self): self.check(fragment=ENDIAN_FRAGMENT, features='c grep_for_endianness', msg='Checking for endianness', define='ENDIANNESS', tmp=tmp, okmsg=check_msg) return tmp[0] + diff --git a/third_party/waf/waflib/Tools/ccroot.py b/third_party/waf/waflib/Tools/ccroot.py index 506bd12445b..6a425fd8f4d 100644 --- a/third_party/waf/waflib/Tools/ccroot.py +++ b/third_party/waf/waflib/Tools/ccroot.py @@ -4,7 +4,7 @@ #!/usr/bin/env python # encoding: utf-8 -# Thomas Nagy, 2005-2016 (ita) +# Thomas Nagy, 2005-2018 (ita) """ Classes and methods shared by tools providing support for C-like language such @@ -135,6 +135,9 @@ class link_task(Task.Task): """ color = 'YELLOW' + weight = 3 + """Try to process link tasks as early as possible""" + inst_to = None """Default installation path for the link task outputs, or None to disable""" @@ -231,8 +234,10 @@ class stlink_task(link_task): def rm_tgt(cls): old = cls.run def wrap(self): - try: os.remove(self.outputs[0].abspath()) - except OSError: pass + try: + os.remove(self.outputs[0].abspath()) + except OSError: + pass return old(self) setattr(cls, 'run', wrap) rm_tgt(stlink_task) @@ -272,7 +277,7 @@ def apply_link(self): try: inst_to = self.install_path except AttributeError: - inst_to = self.link_task.__class__.inst_to + inst_to = self.link_task.inst_to if inst_to: # install a copy of the node list we have at this moment (implib not added) self.install_task = self.add_install_files( @@ -395,7 +400,8 @@ def process_use(self): self.add_objects_from_tgen(y) if getattr(y, 'export_includes', None): - self.includes.extend(y.to_incnodes(y.export_includes)) + # self.includes may come from a global variable #2035 + self.includes = self.includes + y.to_incnodes(y.export_includes) if getattr(y, 'export_defines', None): self.env.append_value('DEFINES', self.to_list(y.export_defines)) @@ -597,7 +603,7 @@ def apply_vnum(self): self.create_task('vnum', node, outs) if getattr(self, 'install_task', None): - self.install_task.hasrun = Task.SKIP_ME + self.install_task.hasrun = Task.SKIPPED path = self.install_task.install_to if self.env.DEST_OS == 'openbsd': libname = self.link_task.outputs[0].name @@ -617,7 +623,7 @@ def apply_vnum(self): try: inst_to = self.install_path except AttributeError: - inst_to = self.link_task.__class__.inst_to + inst_to = self.link_task.inst_to if inst_to: p = Utils.subst_vars(inst_to, self.env) path = os.path.join(p, name2) @@ -770,3 +776,4 @@ def set_full_paths_hpux(self): else: lst.append(os.path.normpath(os.path.join(base, x))) self.env[var] = lst + diff --git a/third_party/waf/waflib/Tools/clangxx.py b/third_party/waf/waflib/Tools/clangxx.py index 628d3dccb8f..cec3311e41c 100644 --- a/third_party/waf/waflib/Tools/clangxx.py +++ b/third_party/waf/waflib/Tools/clangxx.py @@ -4,7 +4,7 @@ #!/usr/bin/env python # encoding: utf-8 -# Thomas Nagy 2009-2016 (ita) +# Thomas Nagy 2009-2018 (ita) """ Detect the Clang++ C++ compiler @@ -31,3 +31,4 @@ def configure(conf): conf.cxx_load_tools() conf.cxx_add_flags() conf.link_add_flags() + diff --git a/third_party/waf/waflib/Tools/compiler_c.py b/third_party/waf/waflib/Tools/compiler_c.py index 92e9c054499..2bc55bf518f 100644 --- a/third_party/waf/waflib/Tools/compiler_c.py +++ b/third_party/waf/waflib/Tools/compiler_c.py @@ -81,7 +81,7 @@ def configure(conf): conf.start_msg('Checking for %r (C compiler)' % compiler) try: conf.load(compiler) - except conf.errors.ConfigurationError ,e: + except conf.errors.ConfigurationError as e: conf.env.revert() conf.end_msg(False) debug('compiler_c: %r', e) @@ -111,3 +111,4 @@ def options(opt): for x in test_for_compiler.split(): opt.load('%s' % x) + diff --git a/third_party/waf/waflib/Tools/compiler_cxx.py b/third_party/waf/waflib/Tools/compiler_cxx.py index 14e9fc0d6d3..fb5b874d679 100644 --- a/third_party/waf/waflib/Tools/compiler_cxx.py +++ b/third_party/waf/waflib/Tools/compiler_cxx.py @@ -82,7 +82,7 @@ def configure(conf): conf.start_msg('Checking for %r (C++ compiler)' % compiler) try: conf.load(compiler) - except conf.errors.ConfigurationError ,e: + except conf.errors.ConfigurationError as e: conf.env.revert() conf.end_msg(False) debug('compiler_cxx: %r', e) @@ -112,3 +112,4 @@ def options(opt): for x in test_for_compiler.split(): opt.load('%s' % x) + diff --git a/third_party/waf/waflib/Tools/compiler_d.py b/third_party/waf/waflib/Tools/compiler_d.py index 690d1469896..6146d7b2cae 100644 --- a/third_party/waf/waflib/Tools/compiler_d.py +++ b/third_party/waf/waflib/Tools/compiler_d.py @@ -5,7 +5,7 @@ #!/usr/bin/env python # encoding: utf-8 # Carlos Rafael Giani, 2007 (dv) -# Thomas Nagy, 2016 (ita) +# Thomas Nagy, 2016-2018 (ita) """ Try to detect a D compiler from the list of supported compilers:: @@ -58,7 +58,7 @@ def configure(conf): conf.start_msg('Checking for %r (D compiler)' % compiler) try: conf.load(compiler) - except conf.errors.ConfigurationError ,e: + except conf.errors.ConfigurationError as e: conf.env.revert() conf.end_msg(False) Logs.debug('compiler_d: %r', e) @@ -86,3 +86,4 @@ def options(opt): for x in test_for_compiler.split(): opt.load('%s' % x) + diff --git a/third_party/waf/waflib/Tools/compiler_fc.py b/third_party/waf/waflib/Tools/compiler_fc.py index 8625e04d2c8..0def0180444 100644 --- a/third_party/waf/waflib/Tools/compiler_fc.py +++ b/third_party/waf/waflib/Tools/compiler_fc.py @@ -44,7 +44,7 @@ def configure(conf): conf.start_msg('Checking for %r (Fortran compiler)' % compiler) try: conf.load(compiler) - except conf.errors.ConfigurationError ,e: + except conf.errors.ConfigurationError as e: conf.env.revert() conf.end_msg(False) Logs.debug('compiler_fortran: %r', e) @@ -74,3 +74,4 @@ def options(opt): for x in test_for_compiler.split(): opt.load('%s' % x) + diff --git a/third_party/waf/waflib/Tools/cs.py b/third_party/waf/waflib/Tools/cs.py index 0ac0ac31732..b23b77f91f2 100644 --- a/third_party/waf/waflib/Tools/cs.py +++ b/third_party/waf/waflib/Tools/cs.py @@ -4,7 +4,7 @@ #!/usr/bin/env python # encoding: utf-8 -# Thomas Nagy, 2006-2016 (ita) +# Thomas Nagy, 2006-2018 (ita) """ C# support. A simple example:: @@ -107,10 +107,10 @@ def debug_cs(self): else: out = node.change_ext('.pdb') self.cs_task.outputs.append(out) - try: - self.install_task.source.append(out) - except AttributeError: - pass + + if getattr(self, 'install_task', None): + self.pdb_install_task = self.add_install_files( + install_to=self.install_task.install_to, install_from=out) if csdebug == 'pdbonly': val = ['/debug+', '/debug:pdbonly'] @@ -120,6 +120,29 @@ def debug_cs(self): val = ['/debug-'] self.env.append_value('CSFLAGS', val) +@feature('cs') +@after_method('debug_cs') +def doc_cs(self): + """ + The C# targets may create .xml documentation files:: + + def build(bld): + bld(features='cs', source='My.cs', bintype='library', gen='my.dll', csdoc=True) + # csdoc is a boolean value + """ + csdoc = getattr(self, 'csdoc', self.env.CSDOC) + if not csdoc: + return + + node = self.cs_task.outputs[0] + out = node.change_ext('.xml') + self.cs_task.outputs.append(out) + + if getattr(self, 'install_task', None): + self.doc_install_task = self.add_install_files( + install_to=self.install_task.install_to, install_from=out) + + self.env.append_value('CSFLAGS', '/doc:%s' % out.abspath()) class mcs(Task.Task): """ @@ -128,10 +151,16 @@ class mcs(Task.Task): color = 'YELLOW' run_str = '${MCS} ${CSTYPE} ${CSFLAGS} ${ASS_ST:ASSEMBLIES} ${RES_ST:RESOURCES} ${OUT} ${SRC}' - def exec_command(self, cmd, **kw): - if '/noconfig' in cmd: - raise ValueError('/noconfig is not allowed when using response files, check your flags!') - return super(self.__class__, self).exec_command(cmd, **kw) + def split_argfile(self, cmd): + inline = [cmd[0]] + infile = [] + for x in cmd[1:]: + # csc doesn't want /noconfig in @file + if x.lower() == '/noconfig': + inline.append(x) + else: + infile.append(self.quote_flag(x)) + return (inline, infile) def configure(conf): """ @@ -183,3 +212,4 @@ def read_csshlib(self, name, paths=[]): :rtype: :py:class:`waflib.TaskGen.task_gen` """ return self(name=name, features='fake_lib', lib_paths=paths, lib_type='csshlib') + diff --git a/third_party/waf/waflib/Tools/cxx.py b/third_party/waf/waflib/Tools/cxx.py index 2ebcdfcf646..e6964e9cdeb 100644 --- a/third_party/waf/waflib/Tools/cxx.py +++ b/third_party/waf/waflib/Tools/cxx.py @@ -4,7 +4,7 @@ #!/usr/bin/env python # encoding: utf-8 -# Thomas Nagy, 2005-2016 (ita) +# Thomas Nagy, 2005-2018 (ita) "Base for c++ programs and libraries" @@ -41,3 +41,4 @@ class cxxshlib(cxxprogram): class cxxstlib(stlink_task): "Links object files into c++ static libraries" pass # do not remove + diff --git a/third_party/waf/waflib/Tools/d.py b/third_party/waf/waflib/Tools/d.py index c493b820d1d..f4337146e0b 100644 --- a/third_party/waf/waflib/Tools/d.py +++ b/third_party/waf/waflib/Tools/d.py @@ -5,7 +5,7 @@ #!/usr/bin/env python # encoding: utf-8 # Carlos Rafael Giani, 2007 (dv) -# Thomas Nagy, 2007-2016 (ita) +# Thomas Nagy, 2007-2018 (ita) from waflib import Utils, Task, Errors from waflib.TaskGen import taskgen_method, feature, extension @@ -98,3 +98,4 @@ def process_header(self): if not node: raise Errors.WafError('file %r not found on d obj' % i[0]) self.create_task('d_header', node, node.change_ext('.di')) + diff --git a/third_party/waf/waflib/Tools/d_config.py b/third_party/waf/waflib/Tools/d_config.py index 2586733a49f..207f3c75b71 100644 --- a/third_party/waf/waflib/Tools/d_config.py +++ b/third_party/waf/waflib/Tools/d_config.py @@ -4,7 +4,7 @@ #!/usr/bin/env python # encoding: utf-8 -# Thomas Nagy, 2016 (ita) +# Thomas Nagy, 2016-2018 (ita) from waflib import Utils from waflib.Configure import conf @@ -65,3 +65,4 @@ def check_dlibrary(self, execute=True): ret = self.check_cc(features='d dprogram', fragment=DLIB, compile_filename='test.d', execute=execute, define_ret=True) if execute: self.env.DLIBRARY = ret.strip() + diff --git a/third_party/waf/waflib/Tools/d_scan.py b/third_party/waf/waflib/Tools/d_scan.py index f5cec7e6d98..4b9b148d381 100644 --- a/third_party/waf/waflib/Tools/d_scan.py +++ b/third_party/waf/waflib/Tools/d_scan.py @@ -4,7 +4,7 @@ #!/usr/bin/env python # encoding: utf-8 -# Thomas Nagy, 2016 (ita) +# Thomas Nagy, 2016-2018 (ita) """ Provide a scanner for finding dependencies on d files @@ -33,7 +33,8 @@ def filter_comments(filename): i += 1 while i < max: c = txt[i] - if c == delim: break + if c == delim: + break elif c == '\\': # skip the character following backslash i += 1 i += 1 @@ -42,7 +43,8 @@ def filter_comments(filename): elif c == '/': # try to replace a comment with whitespace buf.append(txt[begin:i]) i += 1 - if i == max: break + if i == max: + break c = txt[i] if c == '+': # eat nesting /+ +/ comment i += 1 @@ -56,7 +58,8 @@ def filter_comments(filename): c = None elif prev == '+' and c == '/': nesting -= 1 - if nesting == 0: break + if nesting == 0: + break c = None i += 1 elif c == '*': # eat /* */ comment @@ -65,7 +68,8 @@ def filter_comments(filename): while i < max: prev = c c = txt[i] - if prev == '*' and c == '/': break + if prev == '*' and c == '/': + break i += 1 elif c == '/': # eat // comment i += 1 @@ -192,7 +196,8 @@ class d_parser(object): names = self.get_strings(code) # obtain the import strings for x in names: # optimization - if x in self.allnames: continue + if x in self.allnames: + continue self.allnames.append(x) # for each name, see if it is like a node or not @@ -207,3 +212,4 @@ def scan(self): nodes = gruik.nodes names = gruik.names return (nodes, names) + diff --git a/third_party/waf/waflib/Tools/dbus.py b/third_party/waf/waflib/Tools/dbus.py index b6951b4ebc4..801ad1fa5c6 100644 --- a/third_party/waf/waflib/Tools/dbus.py +++ b/third_party/waf/waflib/Tools/dbus.py @@ -71,3 +71,4 @@ def configure(conf): Detects the program dbus-binding-tool and sets ``conf.env.DBUS_BINDING_TOOL`` """ conf.find_program('dbus-binding-tool', var='DBUS_BINDING_TOOL') + diff --git a/third_party/waf/waflib/Tools/dmd.py b/third_party/waf/waflib/Tools/dmd.py index ef620153101..07d7d59cf2c 100644 --- a/third_party/waf/waflib/Tools/dmd.py +++ b/third_party/waf/waflib/Tools/dmd.py @@ -5,7 +5,7 @@ #!/usr/bin/env python # encoding: utf-8 # Carlos Rafael Giani, 2007 (dv) -# Thomas Nagy, 2008-2016 (ita) +# Thomas Nagy, 2008-2018 (ita) import sys from waflib.Tools import ar, d @@ -81,3 +81,4 @@ def configure(conf): if str(conf.env.D).find('ldc') > -1: conf.common_flags_ldc() + diff --git a/third_party/waf/waflib/Tools/errcheck.py b/third_party/waf/waflib/Tools/errcheck.py index 83a3a5bdb88..e50fe607761 100644 --- a/third_party/waf/waflib/Tools/errcheck.py +++ b/third_party/waf/waflib/Tools/errcheck.py @@ -22,6 +22,7 @@ typos = { 'importpath':'includes', 'installpath':'install_path', 'iscopy':'is_copy', +'uses':'use', } meths_typos = ['__call__', 'program', 'shlib', 'stlib', 'objects'] @@ -73,8 +74,11 @@ def check_same_targets(self): for (k, v) in uids.items(): if len(v) > 1: 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') + tg_details = tsk.generator.name + if Logs.verbose > 2: + tg_details = tsk.generator for tsk in v: - Logs.error(' - object %r (%r) defined in %r', tsk.__class__.__name__, tsk, tsk.generator) + Logs.error(' - object %r (%r) defined in %r', tsk.__class__.__name__, tsk, tg_details) def check_invalid_constraints(self): feat = set() @@ -135,16 +139,23 @@ def enhance_lib(): Logs.error("In ant_glob pattern %r: '..' means 'two dots', not 'parent directory'", k[0]) if '.' in sp: Logs.error("In ant_glob pattern %r: '.' means 'one dot', not 'current 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 Node.Node.ant_glob = ant_glob + # catch ant_glob on build folders + def ant_iter(self, accept=None, maxdepth=25, pats=[], dir=False, src=True, remove=True, quiet=False): + if remove: + try: + if self.is_child_of(self.ctx.bldnode) and not quiet: + quiet = True + Logs.error('Calling ant_glob on build folders (%r) is dangerous: add quiet=True / remove=False', self) + except AttributeError: + pass + return self.old_ant_iter(accept, maxdepth, pats, dir, src, remove, quiet) + Node.Node.old_ant_iter = Node.Node.ant_iter + Node.Node.ant_iter = ant_iter + # catch conflicting ext_in/ext_out/before/after declarations old = Task.is_before def is_before(t1, t2): @@ -174,7 +185,7 @@ def enhance_lib(): else: for x in ('before', 'after'): for y in self.to_list(getattr(self, x, [])): - if not Task.classes.get(y, None): + if not Task.classes.get(y): Logs.error('Erroneous order constraint %s=%r on %r (no such class)', x, y, self) TaskGen.feature('*')(check_err_order) @@ -216,7 +227,7 @@ def enhance_lib(): 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) + return super(ConfigSet.ConfigSet, self).__getattr__(name, default) else: return self[name] ConfigSet.ConfigSet.__getattr__ = _getattr @@ -227,3 +238,4 @@ def options(opt): Error verification can be enabled by default (not just on ``waf -v``) by adding to the user script options """ enhance_lib() + diff --git a/third_party/waf/waflib/Tools/fc.py b/third_party/waf/waflib/Tools/fc.py index 5a98ce538ed..92bb2eb60a6 100644 --- a/third_party/waf/waflib/Tools/fc.py +++ b/third_party/waf/waflib/Tools/fc.py @@ -5,13 +5,13 @@ #! /usr/bin/env python # encoding: utf-8 # DC 2008 -# Thomas Nagy 2016 (ita) +# Thomas Nagy 2016-2018 (ita) """ Fortran support """ -from waflib import Utils, Task +from waflib import Utils, Task, Errors from waflib.Tools import ccroot, fc_config, fc_scan from waflib.TaskGen import extension from waflib.Configure import conf @@ -50,7 +50,7 @@ def get_fortran_tasks(tsk): class fc(Task.Task): """ - Fortran tasks can only run when all fortran tasks in the current group are ready to be executed + Fortran tasks can only run when all fortran tasks in a current task group are ready to be executed This may cause a deadlock if some fortran task is waiting for something that cannot happen (circular dependency) Should this ever happen, set the 'nomod=True' on those tasks instances to break the loop """ @@ -89,12 +89,11 @@ class fc(Task.Task): ret = tsk.runnable_status() if ret == Task.ASK_LATER: # we have to wait for one of the other fortran tasks to be ready - # this may deadlock if there are dependencies between the fortran tasks + # this may deadlock if there are dependencies between fortran tasks # but this should not happen (we are setting them here!) for x in lst: x.mod_fortran_done = None - # TODO sort the list of tasks in bld.producer.outstanding to put all fortran tasks at the end return Task.ASK_LATER ins = Utils.defaultdict(set) @@ -108,7 +107,7 @@ class fc(Task.Task): name = bld.modfile(x.replace('MOD@', '')) node = bld.srcnode.find_or_declare(name) tsk.set_outputs(node) - outs[id(node)].add(tsk) + outs[node].add(tsk) # the .mod files to use for tsk in lst: @@ -120,7 +119,7 @@ class fc(Task.Task): if node and node not in tsk.outputs: if not node in bld.node_deps[key]: bld.node_deps[key].append(node) - ins[id(node)].add(tsk) + ins[node].add(tsk) # if the intersection matches, set the order for k in ins.keys(): @@ -182,10 +181,11 @@ class fcprogram_test(fcprogram): kw['output'] = 0 try: (bld.out, bld.err) = bld.cmd_and_log(cmd, **kw) - except Exception: + except Errors.WafError: return -1 if bld.out: bld.to_log('out: %s\n' % bld.out) if bld.err: bld.to_log('err: %s\n' % bld.err) + diff --git a/third_party/waf/waflib/Tools/fc_config.py b/third_party/waf/waflib/Tools/fc_config.py index 76a17a140d8..69928abc940 100644 --- a/third_party/waf/waflib/Tools/fc_config.py +++ b/third_party/waf/waflib/Tools/fc_config.py @@ -5,7 +5,7 @@ #! /usr/bin/env python # encoding: utf-8 # DC 2008 -# Thomas Nagy 2016 (ita) +# Thomas Nagy 2016-2018 (ita) """ Fortran configuration helpers @@ -121,7 +121,7 @@ def fortran_modifier_win32(conf): v.fcprogram_PATTERN = v.fcprogram_test_PATTERN = '%s.exe' v.fcshlib_PATTERN = '%s.dll' - v.implib_PATTERN = 'lib%s.dll.a' + v.implib_PATTERN = '%s.dll.a' v.IMPLIB_ST = '-Wl,--out-implib,%s' v.FCFLAGS_fcshlib = [] @@ -343,10 +343,10 @@ def getoutput(conf, cmd, stdin=False): else: env = dict(os.environ) env['LANG'] = 'C' - input = stdin and '\n' or None + input = stdin and '\n'.encode() or None try: out, err = conf.cmd_and_log(cmd, env=env, output=0, input=input) - except Errors.WafError ,e: + except Errors.WafError as e: # An WafError might indicate an error code during the command # execution, in this case we still obtain the stderr and stdout, # which we can use to find the version string. @@ -460,7 +460,7 @@ def detect_openmp(self): """ Detects openmp flags and sets the OPENMP ``FCFLAGS``/``LINKFLAGS`` """ - for x in ('-qopenmp', '-fopenmp','-openmp','-mp','-xopenmp','-omp','-qsmp=omp'): + for x in ('-fopenmp','-openmp','-mp','-xopenmp','-omp','-qsmp=omp'): try: self.check_fc( msg = 'Checking for OpenMP flag %s' % x, @@ -475,3 +475,18 @@ def detect_openmp(self): break else: self.fatal('Could not find OpenMP') + +@conf +def check_gfortran_o_space(self): + if self.env.FC_NAME != 'GFORTRAN' or int(self.env.FC_VERSION[0]) > 4: + # This is for old compilers and only for gfortran. + # No idea how other implementations handle this. Be safe and bail out. + return + self.env.stash() + self.env.FCLNK_TGT_F = ['-o', ''] + try: + self.check_fc(msg='Checking if the -o link must be split from arguments', fragment=FC_FRAGMENT, features='fc fcshlib') + except self.errors.ConfigurationError: + self.env.revert() + else: + self.env.commit() diff --git a/third_party/waf/waflib/Tools/fc_scan.py b/third_party/waf/waflib/Tools/fc_scan.py index 5e4412609e7..e8c6eda9624 100644 --- a/third_party/waf/waflib/Tools/fc_scan.py +++ b/third_party/waf/waflib/Tools/fc_scan.py @@ -5,7 +5,7 @@ #! /usr/bin/env python # encoding: utf-8 # DC 2008 -# Thomas Nagy 2016 (ita) +# Thomas Nagy 2016-2018 (ita) import re @@ -115,3 +115,4 @@ class fortran_parser(object): if not found: if not filename in self.names: self.names.append(filename) + diff --git a/third_party/waf/waflib/Tools/flex.py b/third_party/waf/waflib/Tools/flex.py index 1a115d3cbd7..11191af3447 100644 --- a/third_party/waf/waflib/Tools/flex.py +++ b/third_party/waf/waflib/Tools/flex.py @@ -5,7 +5,7 @@ #!/usr/bin/env python # encoding: utf-8 # John O'Meara, 2006 -# Thomas Nagy, 2006-2016 (ita) +# Thomas Nagy, 2006-2018 (ita) """ The **flex** program is a code generator which creates C or C++ files. @@ -26,7 +26,8 @@ def flexfun(tsk): bld = tsk.generator.bld wd = bld.variant_dir def to_list(xx): - if isinstance(xx, str): return [xx] + if isinstance(xx, str): + return [xx] return xx tsk.last_cmd = lst = [] lst.extend(to_list(env.FLEX)) @@ -62,3 +63,4 @@ def configure(conf): if re.search (r"\\msys\\[0-9.]+\\bin\\flex.exe$", conf.env.FLEX[0]): # this is the flex shipped with MSYS conf.env.FLEX_MSYS = True + diff --git a/third_party/waf/waflib/Tools/g95.py b/third_party/waf/waflib/Tools/g95.py index 33e7dfc79e2..95db89bbb04 100644 --- a/third_party/waf/waflib/Tools/g95.py +++ b/third_party/waf/waflib/Tools/g95.py @@ -5,7 +5,7 @@ #! /usr/bin/env python # encoding: utf-8 # KWS 2010 -# Thomas Nagy 2016 (ita) +# Thomas Nagy 2016-2018 (ita) import re from waflib import Utils @@ -67,3 +67,4 @@ def configure(conf): conf.fc_add_flags() conf.g95_flags() conf.g95_modifier_platform() + diff --git a/third_party/waf/waflib/Tools/gas.py b/third_party/waf/waflib/Tools/gas.py index f1b648e60fc..c3862b82714 100644 --- a/third_party/waf/waflib/Tools/gas.py +++ b/third_party/waf/waflib/Tools/gas.py @@ -4,7 +4,7 @@ #!/usr/bin/env python # encoding: utf-8 -# Thomas Nagy, 2008-2016 (ita) +# Thomas Nagy, 2008-2018 (ita) "Detect as/gas/gcc for compiling assembly files" diff --git a/third_party/waf/waflib/Tools/gcc.py b/third_party/waf/waflib/Tools/gcc.py index 78f286716f3..60183ceeae0 100644 --- a/third_party/waf/waflib/Tools/gcc.py +++ b/third_party/waf/waflib/Tools/gcc.py @@ -4,7 +4,7 @@ #!/usr/bin/env python # encoding: utf-8 -# Thomas Nagy, 2006-2016 (ita) +# Thomas Nagy, 2006-2018 (ita) # Ralf Habacker, 2006 (rh) # Yinon Ehrlich, 2009 @@ -72,7 +72,7 @@ def gcc_modifier_win32(conf): v.cprogram_PATTERN = '%s.exe' v.cshlib_PATTERN = '%s.dll' - v.implib_PATTERN = 'lib%s.dll.a' + v.implib_PATTERN = '%s.dll.a' v.IMPLIB_ST = '-Wl,--out-implib,%s' v.CFLAGS_cshlib = [] @@ -156,3 +156,5 @@ def configure(conf): conf.cc_load_tools() conf.cc_add_flags() conf.link_add_flags() + conf.check_gcc_o_space() + diff --git a/third_party/waf/waflib/Tools/gdc.py b/third_party/waf/waflib/Tools/gdc.py index a9d1d20b868..8d378c512c8 100644 --- a/third_party/waf/waflib/Tools/gdc.py +++ b/third_party/waf/waflib/Tools/gdc.py @@ -56,3 +56,4 @@ def configure(conf): conf.load('d') conf.common_flags_gdc() conf.d_platform_flags() + diff --git a/third_party/waf/waflib/Tools/gfortran.py b/third_party/waf/waflib/Tools/gfortran.py index 09eeee8b83c..12cff7106d2 100644 --- a/third_party/waf/waflib/Tools/gfortran.py +++ b/third_party/waf/waflib/Tools/gfortran.py @@ -5,7 +5,7 @@ #! /usr/bin/env python # encoding: utf-8 # DC 2008 -# Thomas Nagy 2016 (ita) +# Thomas Nagy 2016-2018 (ita) import re from waflib import Utils @@ -54,8 +54,10 @@ def get_gfortran_version(conf, fc): version_re = re.compile(r"GNU\s*Fortran", re.I).search cmd = fc + ['--version'] out, err = fc_config.getoutput(conf, cmd, stdin=False) - if out: match = version_re(out) - else: match = version_re(err) + if out: + match = version_re(out) + else: + match = version_re(err) if not match: conf.fatal('Could not determine the compiler type') @@ -92,3 +94,4 @@ def configure(conf): conf.fc_add_flags() conf.gfortran_flags() conf.gfortran_modifier_platform() + conf.check_gfortran_o_space() diff --git a/third_party/waf/waflib/Tools/glib2.py b/third_party/waf/waflib/Tools/glib2.py index 18d6f04f59f..6891ac8cadb 100644 --- a/third_party/waf/waflib/Tools/glib2.py +++ b/third_party/waf/waflib/Tools/glib2.py @@ -4,7 +4,7 @@ #! /usr/bin/env python # encoding: utf-8 -# Thomas Nagy, 2006-2016 (ita) +# Thomas Nagy, 2006-2018 (ita) """ Support for GLib2 tools: @@ -74,7 +74,8 @@ class glib_genmarshal(Task.Task): ) ret = bld.exec_command(cmd1) - if ret: return ret + if ret: + return ret #print self.outputs[1].abspath() c = '''#include "%s"\n''' % self.outputs[0].name @@ -247,7 +248,7 @@ def add_settings_enums(self, namespace, filename_list): raise Errors.WafError("Tried to add gsettings enums to %r more than once" % self.name) self.settings_enum_namespace = namespace - if type(filename_list) != 'list': + if not isinstance(filename_list, list): filename_list = [filename_list] self.settings_enum_files = filename_list @@ -455,7 +456,6 @@ def find_glib_compile_schemas(conf): def getstr(varname): return getattr(Options.options, varname, getattr(conf.env,varname, '')) - # TODO make this dependent on the gnu_dirs tool? gsettingsschemadir = getstr('GSETTINGSSCHEMADIR') if not gsettingsschemadir: datadir = getstr('DATADIR') @@ -490,3 +490,4 @@ def options(opt): """ gr = opt.add_option_group('Installation directories') gr.add_option('--gsettingsschemadir', help='GSettings schema location [DATADIR/glib-2.0/schemas]', default='', dest='GSETTINGSSCHEMADIR') + diff --git a/third_party/waf/waflib/Tools/gnu_dirs.py b/third_party/waf/waflib/Tools/gnu_dirs.py index d5b26f79ba1..b9735b8cf38 100644 --- a/third_party/waf/waflib/Tools/gnu_dirs.py +++ b/third_party/waf/waflib/Tools/gnu_dirs.py @@ -132,3 +132,4 @@ def options(opt): str_default = default str_help = '%s [%s]' % (help, re.sub(r'\$\{([^}]+)\}', r'\1', str_default)) dirs_options.add_option(option_name, help=str_help, default='', dest=name.upper()) + diff --git a/third_party/waf/waflib/Tools/gxx.py b/third_party/waf/waflib/Tools/gxx.py index 9a068c699c3..69c7aa2172a 100644 --- a/third_party/waf/waflib/Tools/gxx.py +++ b/third_party/waf/waflib/Tools/gxx.py @@ -4,7 +4,7 @@ #!/usr/bin/env python # encoding: utf-8 -# Thomas Nagy, 2006-2016 (ita) +# Thomas Nagy, 2006-2018 (ita) # Ralf Habacker, 2006 (rh) # Yinon Ehrlich, 2009 @@ -72,7 +72,7 @@ def gxx_modifier_win32(conf): v.cxxprogram_PATTERN = '%s.exe' v.cxxshlib_PATTERN = '%s.dll' - v.implib_PATTERN = 'lib%s.dll.a' + v.implib_PATTERN = '%s.dll.a' v.IMPLIB_ST = '-Wl,--out-implib,%s' v.CXXFLAGS_cxxshlib = [] @@ -157,3 +157,5 @@ def configure(conf): conf.cxx_load_tools() conf.cxx_add_flags() conf.link_add_flags() + conf.check_gcc_o_space('cxx') + diff --git a/third_party/waf/waflib/Tools/icc.py b/third_party/waf/waflib/Tools/icc.py index 744af9c5bf8..eede6035143 100644 --- a/third_party/waf/waflib/Tools/icc.py +++ b/third_party/waf/waflib/Tools/icc.py @@ -5,7 +5,7 @@ #!/usr/bin/env python # encoding: utf-8 # Stian Selnes 2008 -# Thomas Nagy 2009-2016 (ita) +# Thomas Nagy 2009-2018 (ita) """ Detects the Intel C compiler diff --git a/third_party/waf/waflib/Tools/icpc.py b/third_party/waf/waflib/Tools/icpc.py index c8a627865b6..226e8292379 100644 --- a/third_party/waf/waflib/Tools/icpc.py +++ b/third_party/waf/waflib/Tools/icpc.py @@ -4,7 +4,7 @@ #!/usr/bin/env python # encoding: utf-8 -# Thomas Nagy 2009-2016 (ita) +# Thomas Nagy 2009-2018 (ita) """ Detects the Intel C++ compiler @@ -31,3 +31,4 @@ def configure(conf): conf.cxx_load_tools() conf.cxx_add_flags() conf.link_add_flags() + diff --git a/third_party/waf/waflib/Tools/ifort.py b/third_party/waf/waflib/Tools/ifort.py index 636d863fee2..3d0f83f0732 100644 --- a/third_party/waf/waflib/Tools/ifort.py +++ b/third_party/waf/waflib/Tools/ifort.py @@ -5,9 +5,9 @@ #! /usr/bin/env python # encoding: utf-8 # DC 2008 -# Thomas Nagy 2016 (ita) +# Thomas Nagy 2016-2018 (ita) -import os, re +import os, re, traceback from waflib import Utils, Logs, Errors from waflib.Tools import fc, fc_config, fc_scan, ar, ccroot from waflib.Configure import conf @@ -80,7 +80,7 @@ def configure(conf): Detects the Intel Fortran compilers """ if Utils.is_win32: - compiler, version, path, includes, libdirs, arch = conf.detect_ifort(True) + compiler, version, path, includes, libdirs, arch = conf.detect_ifort() v = conf.env v.DEST_CPU = arch v.PATH = path @@ -89,8 +89,7 @@ def configure(conf): v.MSVC_COMPILER = compiler try: v.MSVC_VERSION = float(version) - except Exception: - raise + except ValueError: v.MSVC_VERSION = float(version[:-3]) conf.find_ifort_win32() @@ -115,32 +114,34 @@ def gather_ifort_versions(conf, versions): version_pattern = re.compile('^...?.?\....?.?') try: all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Intel\\Compilers\\Fortran') - except WindowsError: + except OSError: try: all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Intel\\Compilers\\Fortran') - except WindowsError: + except OSError: return index = 0 while 1: try: version = Utils.winreg.EnumKey(all_versions, index) - except WindowsError: + except OSError: break index += 1 if not version_pattern.match(version): continue targets = {} for target,arch in all_ifort_platforms: - if target=='intel64': targetDir='EM64T_NATIVE' - else: targetDir=target + if target=='intel64': + targetDir='EM64T_NATIVE' + else: + targetDir=target try: Utils.winreg.OpenKey(all_versions,version+'\\'+targetDir) icl_version=Utils.winreg.OpenKey(all_versions,version) path,type=Utils.winreg.QueryValueEx(icl_version,'ProductDir') - except WindowsError: + except OSError: pass else: - batch_file=os.path.join(path,'bin','iclvars.bat') + batch_file=os.path.join(path,'bin','ifortvars.bat') if os.path.isfile(batch_file): targets[target] = target_compiler(conf, 'intel', arch, version, target, batch_file) @@ -148,10 +149,10 @@ def gather_ifort_versions(conf, versions): try: icl_version = Utils.winreg.OpenKey(all_versions, version+'\\'+target) path,type = Utils.winreg.QueryValueEx(icl_version,'ProductDir') - except WindowsError: + except OSError: continue else: - batch_file=os.path.join(path,'bin','iclvars.bat') + batch_file=os.path.join(path,'bin','ifortvars.bat') if os.path.isfile(batch_file): targets[target] = target_compiler(conf, 'intel', arch, version, target, batch_file) major = version[0:2] @@ -235,11 +236,11 @@ echo LIB=%%LIB%%;%%LIBPATH%% try: conf.cmd_and_log(fc + ['/help'], env=env) except UnicodeError: - st = Utils.ex_stack() + st = traceback.format_exc() if conf.logger: conf.logger.error(st) conf.fatal('ifort: Unicode error - check the code page?') - except Exception ,e: + except Exception as e: Logs.debug('ifort: get_ifort_version: %r %r %r -> failure %s', compiler, version, target, str(e)) conf.fatal('ifort: cannot run the compiler in get_ifort_version (run with -v to display errors)') else: @@ -281,7 +282,7 @@ class target_compiler(object): return self.is_done = True try: - vs = self.conf.get_msvc_version(self.compiler, self.version, self.bat_target, self.bat) + vs = self.conf.get_ifort_version_win32(self.compiler, self.version, self.bat_target, self.bat) except Errors.ConfigurationError: self.is_valid = False return @@ -338,7 +339,8 @@ def find_ifort_win32(conf): # before setting anything, check if the compiler is really intel fortran env = dict(conf.environ) - if path: env.update(PATH = ';'.join(path)) + if path: + env.update(PATH = ';'.join(path)) if not conf.cmd_and_log(fc + ['/nologo', '/help'], env=env): conf.fatal('not intel fortran compiler could not be identified') @@ -412,3 +414,4 @@ def apply_manifest_ifort(self): man_node = out_node.parent.find_or_declare(out_node.name + '.manifest') self.link_task.outputs.append(man_node) self.env.DO_MANIFEST = True + diff --git a/third_party/waf/waflib/Tools/intltool.py b/third_party/waf/waflib/Tools/intltool.py index 22ea3ff8954..960c3963cb7 100644 --- a/third_party/waf/waflib/Tools/intltool.py +++ b/third_party/waf/waflib/Tools/intltool.py @@ -4,7 +4,7 @@ #!/usr/bin/env python # encoding: utf-8 -# Thomas Nagy, 2006-2016 (ita) +# Thomas Nagy, 2006-2018 (ita) """ Support for translation tools such as msgfmt and intltool @@ -31,6 +31,8 @@ Usage:: Usage of the :py:mod:`waflib.Tools.gnu_dirs` is recommended, but not obligatory. """ +from __future__ import with_statement + import os, re from waflib import Context, Task, Utils, Logs import waflib.Tools.ccroot @@ -90,8 +92,10 @@ def apply_intltool_in_f(self): :param install_path: installation path :type install_path: string """ - try: self.meths.remove('process_source') - except ValueError: pass + try: + self.meths.remove('process_source') + except ValueError: + pass self.ensure_localedir() @@ -145,8 +149,10 @@ def apply_intltool_po(self): The file LINGUAS must be present in the directory pointed by *podir* and list the translation files to process. """ - try: self.meths.remove('process_source') - except ValueError: pass + try: + self.meths.remove('process_source') + except ValueError: + pass self.ensure_localedir() @@ -157,13 +163,12 @@ def apply_intltool_po(self): linguas = self.path.find_node(os.path.join(podir, 'LINGUAS')) if linguas: # scan LINGUAS file for locales to process - file = open(linguas.abspath()) - langs = [] - for line in file.readlines(): - # ignore lines containing comments - if not line.startswith('#'): - langs += line.split() - file.close() + with open(linguas.abspath()) as f: + langs = [] + for line in f.readlines(): + # ignore lines containing comments + if not line.startswith('#'): + langs += line.split() re_linguas = re.compile('[-a-zA-Z_@.]+') for lang in langs: # Make sure that we only process lines which contain locales @@ -227,3 +232,4 @@ def configure(conf): conf.find_intltool_merge() if conf.env.CC or conf.env.CXX: conf.check(header_name='locale.h') + diff --git a/third_party/waf/waflib/Tools/irixcc.py b/third_party/waf/waflib/Tools/irixcc.py index 413261e2a14..ed5c49ff6e0 100644 --- a/third_party/waf/waflib/Tools/irixcc.py +++ b/third_party/waf/waflib/Tools/irixcc.py @@ -10,6 +10,7 @@ Compiler definition for irix/MIPSpro cc compiler """ +from waflib import Errors from waflib.Tools import ccroot, ar from waflib.Configure import conf @@ -28,7 +29,7 @@ def find_irixcc(conf): try: conf.cmd_and_log(cc + ['-version']) - except Exception: + except Errors.WafError: conf.fatal('%r -version could not be executed' % cc) v.CC = cc @@ -66,3 +67,4 @@ def configure(conf): conf.cc_load_tools() conf.cc_add_flags() conf.link_add_flags() + diff --git a/third_party/waf/waflib/Tools/javaw.py b/third_party/waf/waflib/Tools/javaw.py index 1e56d4891cd..3a2f3a7af58 100644 --- a/third_party/waf/waflib/Tools/javaw.py +++ b/third_party/waf/waflib/Tools/javaw.py @@ -4,7 +4,7 @@ #!/usr/bin/env python # encoding: utf-8 -# Thomas Nagy, 2006-2016 (ita) +# Thomas Nagy, 2006-2018 (ita) """ Java support @@ -96,6 +96,7 @@ def apply_java(self): if not y: self.bld.fatal('Could not find the folder %s from %s' % (x, self.path)) tmp.append(y) + tsk.srcdir = tmp if getattr(self, 'compat', None): @@ -111,6 +112,7 @@ def apply_java(self): tsk.env.append_value('JAVACFLAGS', ['-sourcepath', names]) @feature('javac') +@before_method('propagate_uselib_vars') @after_method('apply_java') def use_javac_files(self): """ @@ -141,7 +143,8 @@ def set_classpath(self): """ Sets the CLASSPATH value on the *javac* task previously created. """ - self.env.append_value('CLASSPATH', getattr(self, 'classpath', [])) + if getattr(self, 'classpath', None): + self.env.append_unique('CLASSPATH', getattr(self, 'classpath', [])) for x in self.tasks: x.env.CLASSPATH = os.pathsep.join(self.env.CLASSPATH) + os.pathsep @@ -169,9 +172,11 @@ def jar_files(self): if manifest: jarcreate = getattr(self, 'jarcreate', 'cfm') if not isinstance(manifest,Node.Node): - node = self.path.find_or_declare(manifest) + node = self.path.find_resource(manifest) else: node = manifest + if not node: + self.bld.fatal('invalid manifest file %r for %r' % (manifest, self)) tsk.dep_nodes.append(node) jaropts.insert(0, node.abspath()) else: @@ -243,7 +248,6 @@ class jar_create(JTask): if not t.hasrun: return Task.ASK_LATER if not self.inputs: - global JAR_RE try: self.inputs = [x for x in self.basedir.ant_glob(JAR_RE, remove=False) if id(x) != id(self.outputs[0])] except Exception: @@ -276,10 +280,10 @@ class javac(JTask): return Task.ASK_LATER if not self.inputs: - global SOURCE_RE self.inputs = [] for x in self.srcdir: - self.inputs.extend(x.ant_glob(SOURCE_RE, remove=False)) + if x.exists(): + self.inputs.extend(x.ant_glob(SOURCE_RE, remove=False)) return super(javac, self).runnable_status() def post_run(self): @@ -461,3 +465,4 @@ def check_jni_headers(conf): break else: conf.fatal('could not find lib jvm in %r (see config.log)' % libDirs) + diff --git a/third_party/waf/waflib/Tools/kde4.py b/third_party/waf/waflib/Tools/kde4.py deleted file mode 100644 index f39f24ad023..00000000000 --- a/third_party/waf/waflib/Tools/kde4.py +++ /dev/null @@ -1,93 +0,0 @@ -#! /usr/bin/env python -# encoding: utf-8 -# WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file - -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2006-2010 (ita) - -""" -Support for the KDE4 libraries and msgfmt -""" - -import os, re -from waflib import Task, Utils -from waflib.TaskGen import feature - -@feature('msgfmt') -def apply_msgfmt(self): - """ - Process all languages to create .mo files and to install them:: - - def build(bld): - bld(features='msgfmt', langs='es de fr', appname='myapp', install_path='${KDE4_LOCALE_INSTALL_DIR}') - """ - for lang in self.to_list(self.langs): - node = self.path.find_resource(lang+'.po') - task = self.create_task('msgfmt', node, node.change_ext('.mo')) - - langname = lang.split('/') - langname = langname[-1] - - inst = getattr(self, 'install_path', '${KDE4_LOCALE_INSTALL_DIR}') - - self.bld.install_as( - inst + os.sep + langname + os.sep + 'LC_MESSAGES' + os.sep + getattr(self, 'appname', 'set_your_appname') + '.mo', - task.outputs[0], - chmod = getattr(self, 'chmod', Utils.O644)) - -class msgfmt(Task.Task): - """ - Transform .po files into .mo files - """ - color = 'BLUE' - run_str = '${MSGFMT} ${SRC} -o ${TGT}' - -def configure(self): - """ - Detect kde4-config and set various variables for the *use* system:: - - def options(opt): - opt.load('compiler_cxx kde4') - def configure(conf): - conf.load('compiler_cxx kde4') - def build(bld): - bld.program(source='main.c', target='app', use='KDECORE KIO KHTML') - """ - kdeconfig = self.find_program('kde4-config') - prefix = self.cmd_and_log(kdeconfig + ['--prefix']).strip() - fname = '%s/share/apps/cmake/modules/KDELibsDependencies.cmake' % prefix - try: os.stat(fname) - except OSError: - fname = '%s/share/kde4/apps/cmake/modules/KDELibsDependencies.cmake' % prefix - try: os.stat(fname) - except OSError: self.fatal('could not open %s' % fname) - - try: - txt = Utils.readf(fname) - except EnvironmentError: - self.fatal('could not read %s' % fname) - - txt = txt.replace('\\\n', '\n') - fu = re.compile('#(.*)\n') - txt = fu.sub('', txt) - - setregexp = re.compile('([sS][eE][tT]\s*\()\s*([^\s]+)\s+\"([^"]+)\"\)') - found = setregexp.findall(txt) - - for (_, key, val) in found: - #print key, val - self.env[key] = val - - # well well, i could just write an interpreter for cmake files - self.env['LIB_KDECORE']= ['kdecore'] - self.env['LIB_KDEUI'] = ['kdeui'] - self.env['LIB_KIO'] = ['kio'] - self.env['LIB_KHTML'] = ['khtml'] - self.env['LIB_KPARTS'] = ['kparts'] - - self.env['LIBPATH_KDECORE'] = [os.path.join(self.env.KDE4_LIB_INSTALL_DIR, 'kde4', 'devel'), self.env.KDE4_LIB_INSTALL_DIR] - self.env['INCLUDES_KDECORE'] = [self.env['KDE4_INCLUDE_INSTALL_DIR']] - self.env.append_value('INCLUDES_KDECORE', [self.env['KDE4_INCLUDE_INSTALL_DIR']+ os.sep + 'KDE']) - - self.find_program('msgfmt', var='MSGFMT') diff --git a/third_party/waf/waflib/Tools/ldc2.py b/third_party/waf/waflib/Tools/ldc2.py index 80a09fd355d..3d719de781c 100644 --- a/third_party/waf/waflib/Tools/ldc2.py +++ b/third_party/waf/waflib/Tools/ldc2.py @@ -57,3 +57,4 @@ def configure(conf): conf.load('d') conf.common_flags_ldc2() conf.d_platform_flags() + diff --git a/third_party/waf/waflib/Tools/lua.py b/third_party/waf/waflib/Tools/lua.py index f864970e47c..9c6a234447a 100644 --- a/third_party/waf/waflib/Tools/lua.py +++ b/third_party/waf/waflib/Tools/lua.py @@ -5,7 +5,7 @@ #!/usr/bin/env python # encoding: utf-8 # Sebastian Schlingmann, 2008 -# Thomas Nagy, 2008-2016 (ita) +# Thomas Nagy, 2008-2018 (ita) """ Lua support. @@ -39,3 +39,4 @@ def configure(conf): Detect the luac compiler and set *conf.env.LUAC* """ conf.find_program('luac', var='LUAC') + diff --git a/third_party/waf/waflib/Tools/md5_tstamp.py b/third_party/waf/waflib/Tools/md5_tstamp.py index 48434279eb7..f17b1223f4e 100644 --- a/third_party/waf/waflib/Tools/md5_tstamp.py +++ b/third_party/waf/waflib/Tools/md5_tstamp.py @@ -29,15 +29,15 @@ def h_file(self): if filename in cache and cache[filename][0] == st.st_mtime: return cache[filename][1] - global STRONGEST if STRONGEST: ret = Utils.h_file(filename) else: if stat.S_ISDIR(st[stat.ST_MODE]): raise IOError('Not a file') - ret = Utils.md5(str((st.st_mtime, st.st_size))).digest() + ret = Utils.md5(str((st.st_mtime, st.st_size)).encode()).digest() cache[filename] = (st.st_mtime, ret) return ret h_file.__doc__ = Node.Node.h_file.__doc__ Node.Node.h_file = h_file + diff --git a/third_party/waf/waflib/Tools/msvc.py b/third_party/waf/waflib/Tools/msvc.py index 7cc2fef17a2..9ee7eadcdbe 100644 --- a/third_party/waf/waflib/Tools/msvc.py +++ b/third_party/waf/waflib/Tools/msvc.py @@ -42,7 +42,7 @@ Supported platforms: ia64, x64, x86, x86_amd64, x86_ia64, x86_arm, amd64_x86, am Compilers supported: -* msvc => Visual Studio, versions 6.0 (VC 98, VC .NET 2002) to 12.0 (Visual Studio 2013) +* msvc => Visual Studio, versions 6.0 (VC 98, VC .NET 2002) to 15 (Visual Studio 2017) * wsdk => Windows SDK, versions 6.0, 6.1, 7.0, 7.1, 8.0 * icl => Intel compiler, versions 9, 10, 11, 13 * winphone => Visual Studio to target Windows Phone 8 native (version 8.0 for now) @@ -56,7 +56,7 @@ cmd.exe /C "chcp 1252 & set PYTHONUNBUFFERED=true && set && waf configure" Setting PYTHONUNBUFFERED gives the unbuffered output. """ -import os, sys, re +import os, sys, re, traceback from waflib import Utils, Logs, Options, Errors from waflib.TaskGen import after_method, feature @@ -117,7 +117,7 @@ def setup_msvc(conf, versiondict): platforms=Utils.to_list(conf.env.MSVC_TARGETS) or [i for i,j in all_msvc_platforms+all_icl_platforms+all_wince_platforms] desired_versions = getattr(Options.options, 'msvc_version', '').split(',') if desired_versions == ['']: - desired_versions = conf.env.MSVC_VERSIONS or list(versiondict.keys()) + desired_versions = conf.env.MSVC_VERSIONS or list(reversed(sorted(versiondict.keys()))) # Override lazy detection by evaluating after the fact. lazy_detect = getattr(Options.options, 'msvc_lazy', True) @@ -134,15 +134,23 @@ def setup_msvc(conf, versiondict): conf.env.MSVC_INSTALLED_VERSIONS = versiondict for version in desired_versions: + Logs.debug('msvc: detecting %r - %r', version, desired_versions) try: targets = versiondict[version] except KeyError: continue + + seen = set() for arch in platforms: + if arch in seen: + continue + else: + seen.add(arch) try: cfg = targets[arch] except KeyError: continue + cfg.evaluate() if cfg.is_valid: compiler,revision = version.rsplit(' ', 1) @@ -209,11 +217,11 @@ echo LIB=%%LIB%%;%%LIBPATH%% try: conf.cmd_and_log(cxx + ['/help'], env=env) except UnicodeError: - st = Utils.ex_stack() + st = traceback.format_exc() if conf.logger: conf.logger.error(st) conf.fatal('msvc: Unicode error - check the code page?') - except Exception ,e: + except Exception as e: Logs.debug('msvc: get_msvc_version: %r %r %r -> failure %s', compiler, version, target, str(e)) conf.fatal('msvc: cannot run the compiler in get_msvc_version (run with -v to display errors)') else: @@ -223,42 +231,6 @@ echo LIB=%%LIB%%;%%LIBPATH%% return (MSVC_PATH, MSVC_INCDIR, MSVC_LIBDIR) -@conf -def gather_wsdk_versions(conf, versions): - """ - Use winreg to add the msvc versions to the input list - - :param versions: list to modify - :type versions: list - """ - version_pattern = re.compile('^v..?.?\...?.?') - try: - all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Microsoft\\Microsoft SDKs\\Windows') - except WindowsError: - try: - all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows') - except WindowsError: - return - index = 0 - while 1: - try: - version = Utils.winreg.EnumKey(all_versions, index) - except WindowsError: - break - index += 1 - if not version_pattern.match(version): - continue - try: - msvc_version = Utils.winreg.OpenKey(all_versions, version) - path,type = Utils.winreg.QueryValueEx(msvc_version,'InstallationFolder') - except WindowsError: - continue - if path and os.path.isfile(os.path.join(path, 'bin', 'SetEnv.cmd')): - targets = {} - for target,arch in all_msvc_platforms: - targets[target] = target_compiler(conf, 'wsdk', arch, version, '/'+target, os.path.join(path, 'bin', 'SetEnv.cmd')) - versions['wsdk ' + version[1:]] = targets - def gather_wince_supported_platforms(): """ Checks SmartPhones SDKs @@ -269,10 +241,10 @@ def gather_wince_supported_platforms(): supported_wince_platforms = [] try: ce_sdk = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Microsoft\\Windows CE Tools\\SDKs') - except WindowsError: + except OSError: try: ce_sdk = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Windows CE Tools\\SDKs') - except WindowsError: + except OSError: ce_sdk = '' if not ce_sdk: return supported_wince_platforms @@ -282,15 +254,15 @@ def gather_wince_supported_platforms(): try: sdk_device = Utils.winreg.EnumKey(ce_sdk, index) sdk = Utils.winreg.OpenKey(ce_sdk, sdk_device) - except WindowsError: + except OSError: break index += 1 try: path,type = Utils.winreg.QueryValueEx(sdk, 'SDKRootDir') - except WindowsError: + except OSError: try: path,type = Utils.winreg.QueryValueEx(sdk,'SDKInformation') - except WindowsError: + except OSError: continue path,xml = os.path.split(path) path = str(path) @@ -313,18 +285,18 @@ def gather_msvc_detected_versions(): prefix = 'SOFTWARE\\Wow6432node\\Microsoft\\' + vcver try: all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, prefix) - except WindowsError: + except OSError: prefix = 'SOFTWARE\\Microsoft\\' + vcver try: all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, prefix) - except WindowsError: + except OSError: continue index = 0 while 1: try: version = Utils.winreg.EnumKey(all_versions, index) - except WindowsError: + except OSError: break index += 1 match = version_pattern.match(version) @@ -352,7 +324,6 @@ class target_compiler(object): :param version: compiler version number :param bat_target: ? :param bat: path to the batch file to run - :param callback: optional function to take the realized environment variables tup and map it (e.g. to combine other constant paths) """ self.conf = ctx self.name = None @@ -381,10 +352,46 @@ class target_compiler(object): (self.bindirs, self.incdirs, self.libdirs) = vs def __str__(self): - return str((self.bindirs, self.incdirs, self.libdirs)) + return str((self.compiler, self.cpu, self.version, self.bat_target, self.bat)) def __repr__(self): - return repr((self.bindirs, self.incdirs, self.libdirs)) + return repr((self.compiler, self.cpu, self.version, self.bat_target, self.bat)) + +@conf +def gather_wsdk_versions(conf, versions): + """ + Use winreg to add the msvc versions to the input list + + :param versions: list to modify + :type versions: list + """ + version_pattern = re.compile('^v..?.?\...?.?') + try: + all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Microsoft\\Microsoft SDKs\\Windows') + except OSError: + try: + all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows') + except OSError: + return + index = 0 + while 1: + try: + version = Utils.winreg.EnumKey(all_versions, index) + except OSError: + break + index += 1 + if not version_pattern.match(version): + continue + try: + msvc_version = Utils.winreg.OpenKey(all_versions, version) + path,type = Utils.winreg.QueryValueEx(msvc_version,'InstallationFolder') + except OSError: + continue + if path and os.path.isfile(os.path.join(path, 'bin', 'SetEnv.cmd')): + targets = {} + for target,arch in all_msvc_platforms: + targets[target] = target_compiler(conf, 'wsdk', arch, version, '/'+target, os.path.join(path, 'bin', 'SetEnv.cmd')) + versions['wsdk ' + version[1:]] = targets @conf def gather_msvc_targets(conf, versions, version, vc_path): @@ -402,7 +409,7 @@ def gather_msvc_targets(conf, versions, version, vc_path): elif os.path.isfile(os.path.join(vc_path, 'Bin', 'vcvars32.bat')): targets['x86'] = target_compiler(conf, 'msvc', 'x86', version, '', os.path.join(vc_path, 'Bin', 'vcvars32.bat')) if targets: - versions['msvc ' + version] = targets + versions['msvc %s' % version] = targets @conf def gather_wince_targets(conf, versions, version, vc_path, vsvars, supported_platforms): @@ -419,6 +426,7 @@ def gather_wince_targets(conf, versions, version, vc_path, vsvars, supported_pla incdirs = [os.path.join(winCEpath, 'include'), os.path.join(winCEpath, 'atlmfc', 'include'), include] libdirs = [os.path.join(winCEpath, 'lib', platform), os.path.join(winCEpath, 'atlmfc', 'lib', platform), lib] def combine_common(obj, compiler_env): + # TODO this is likely broken, remove in waf 2.1 (common_bindirs,_1,_2) = compiler_env return (bindirs + common_bindirs, incdirs, libdirs) targets[platform] = target_compiler(conf, 'msvc', platform, version, 'x86', vsvars, combine_common) @@ -435,20 +443,52 @@ def gather_winphone_targets(conf, versions, version, vc_path, vsvars): versions['winphone ' + version] = targets @conf +def gather_vswhere_versions(conf, versions): + try: + import json + except ImportError: + Logs.error('Visual Studio 2017 detection requires Python 2.6') + return + + prg_path = os.environ.get('ProgramFiles(x86)', os.environ.get('ProgramFiles', 'C:\\Program Files (x86)')) + + vswhere = os.path.join(prg_path, 'Microsoft Visual Studio', 'Installer', 'vswhere.exe') + args = [vswhere, '-products', '*', '-legacy', '-format', 'json'] + try: + txt = conf.cmd_and_log(args) + except Errors.WafError as e: + Logs.debug('msvc: vswhere.exe failed %s', e) + return + + if sys.version_info[0] < 3: + try: + txt = txt.decode(sys.stdout.encoding or 'cp1252') + except UnicodeError: + txt = txt.decode('utf-8', 'replace') + arr = json.loads(txt) + arr.sort(key=lambda x: x['installationVersion']) + for entry in arr: + ver = entry['installationVersion'] + ver = str('.'.join(ver.split('.')[:2])) + path = str(os.path.abspath(entry['installationPath'])) + if os.path.exists(path) and ('msvc %s' % ver) not in versions: + conf.gather_msvc_targets(versions, ver, path) + +@conf def gather_msvc_versions(conf, versions): vc_paths = [] for (v,version,reg) in gather_msvc_detected_versions(): try: try: msvc_version = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, reg + "\\Setup\\VC") - except WindowsError: + except OSError: msvc_version = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, reg + "\\Setup\\Microsoft Visual C++") path,type = Utils.winreg.QueryValueEx(msvc_version, 'ProductDir') - except WindowsError: + except OSError: try: msvc_version = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\Wow6432node\\Microsoft\\VisualStudio\\SxS\\VS7") path,type = Utils.winreg.QueryValueEx(msvc_version, version) - except WindowsError: + except OSError: continue else: vc_paths.append((version, os.path.abspath(str(path)))) @@ -488,29 +528,31 @@ def gather_icl_versions(conf, versions): version_pattern = re.compile('^...?.?\....?.?') try: all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Intel\\Compilers\\C++') - except WindowsError: + except OSError: try: all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Intel\\Compilers\\C++') - except WindowsError: + except OSError: return index = 0 while 1: try: version = Utils.winreg.EnumKey(all_versions, index) - except WindowsError: + except OSError: break index += 1 if not version_pattern.match(version): continue targets = {} for target,arch in all_icl_platforms: - if target=='intel64': targetDir='EM64T_NATIVE' - else: targetDir=target + if target=='intel64': + targetDir='EM64T_NATIVE' + else: + targetDir=target try: Utils.winreg.OpenKey(all_versions,version+'\\'+targetDir) icl_version=Utils.winreg.OpenKey(all_versions,version) path,type=Utils.winreg.QueryValueEx(icl_version,'ProductDir') - except WindowsError: + except OSError: pass else: batch_file=os.path.join(path,'bin','iclvars.bat') @@ -520,7 +562,7 @@ def gather_icl_versions(conf, versions): try: icl_version = Utils.winreg.OpenKey(all_versions, version+'\\'+target) path,type = Utils.winreg.QueryValueEx(icl_version,'ProductDir') - except WindowsError: + except OSError: continue else: batch_file=os.path.join(path,'bin','iclvars.bat') @@ -540,28 +582,30 @@ def gather_intel_composer_versions(conf, versions): version_pattern = re.compile('^...?.?\...?.?.?') try: all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Intel\\Suites') - except WindowsError: + except OSError: try: all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Intel\\Suites') - except WindowsError: + except OSError: return index = 0 while 1: try: version = Utils.winreg.EnumKey(all_versions, index) - except WindowsError: + except OSError: break index += 1 if not version_pattern.match(version): continue targets = {} for target,arch in all_icl_platforms: - if target=='intel64': targetDir='EM64T_NATIVE' - else: targetDir=target + if target=='intel64': + targetDir='EM64T_NATIVE' + else: + targetDir=target try: try: defaults = Utils.winreg.OpenKey(all_versions,version+'\\Defaults\\C++\\'+targetDir) - except WindowsError: + except OSError: if targetDir == 'EM64T_NATIVE': defaults = Utils.winreg.OpenKey(all_versions,version+'\\Defaults\\C++\\EM64T') else: @@ -570,7 +614,7 @@ def gather_intel_composer_versions(conf, versions): Utils.winreg.OpenKey(all_versions,version+'\\'+uid+'\\C++\\'+targetDir) icl_version=Utils.winreg.OpenKey(all_versions,version+'\\'+uid+'\\C++') path,type=Utils.winreg.QueryValueEx(icl_version,'ProductDir') - except WindowsError: + except OSError: pass else: batch_file=os.path.join(path,'bin','iclvars.bat') @@ -611,6 +655,7 @@ def get_msvc_versions(self): self.gather_intel_composer_versions(dct) self.gather_wsdk_versions(dct) self.gather_msvc_versions(dct) + self.gather_vswhere_versions(dct) Logs.debug('msvc: detected versions %r', list(dct.keys())) return dct @@ -668,7 +713,7 @@ def libname_msvc(self, libname, is_static=False): (lt_path, lt_libname, lt_static) = self.find_lt_names_msvc(lib, is_static) if lt_path != None and lt_libname != None: - if lt_static == True: + if lt_static: # file existence check has been made by find_lt_names return os.path.join(lt_path,lt_libname) @@ -765,7 +810,7 @@ def autodetect(conf, arch=False): v.MSVC_COMPILER = compiler try: v.MSVC_VERSION = float(version) - except TypeError: + except ValueError: v.MSVC_VERSION = float(version[:-3]) def _get_prog_names(conf, compiler): @@ -800,7 +845,8 @@ def find_msvc(conf): # before setting anything, check if the compiler is really msvc env = dict(conf.environ) - if path: env.update(PATH = ';'.join(path)) + if path: + env.update(PATH = ';'.join(path)) if not conf.cmd_and_log(cxx + ['/nologo', '/help'], env=env): conf.fatal('the msvc compiler could not be identified') @@ -810,8 +856,7 @@ def find_msvc(conf): # linker if not v.LINK_CXX: - # TODO: var=LINK_CXX to let so that LINK_CXX can be overridden? - v.LINK_CXX = conf.find_program(linker_name, path_list=path, errmsg='%s was not found (linker)' % linker_name) + conf.find_program(linker_name, path_list=path, errmsg='%s was not found (linker)' % linker_name, var='LINK_CXX') if not v.LINK_CC: v.LINK_CC = v.LINK_CXX @@ -868,13 +913,6 @@ def msvc_common_flags(conf): v.AR_TGT_F = v.CCLNK_TGT_F = v.CXXLNK_TGT_F = '/OUT:' - # Subsystem specific flags - v.CFLAGS_CONSOLE = v.CXXFLAGS_CONSOLE = ['/SUBSYSTEM:CONSOLE'] - v.CFLAGS_NATIVE = v.CXXFLAGS_NATIVE = ['/SUBSYSTEM:NATIVE'] - v.CFLAGS_POSIX = v.CXXFLAGS_POSIX = ['/SUBSYSTEM:POSIX'] - v.CFLAGS_WINDOWS = v.CXXFLAGS_WINDOWS = ['/SUBSYSTEM:WINDOWS'] - v.CFLAGS_WINDOWSCE = v.CXXFLAGS_WINDOWSCE = ['/SUBSYSTEM:WINDOWSCE'] - # CRT specific flags v.CFLAGS_CRT_MULTITHREADED = v.CXXFLAGS_CRT_MULTITHREADED = ['/MT'] v.CFLAGS_CRT_MULTITHREADED_DLL = v.CXXFLAGS_CRT_MULTITHREADED_DLL = ['/MD'] @@ -968,7 +1006,7 @@ def make_winphone_app(self): Insert configuration flags for windows phone applications (adds /ZW, /TP...) """ make_winapp(self, 'WINAPI_FAMILY_PHONE_APP') - conf.env.append_unique('LINKFLAGS', ['/NODEFAULTLIB:ole32.lib', 'PhoneAppModelHost.lib']) + self.env.append_unique('LINKFLAGS', ['/NODEFAULTLIB:ole32.lib', 'PhoneAppModelHost.lib']) @feature('winapp') @after_method('process_use') diff --git a/third_party/waf/waflib/Tools/nasm.py b/third_party/waf/waflib/Tools/nasm.py index ab0e21f4980..eedba82a8df 100644 --- a/third_party/waf/waflib/Tools/nasm.py +++ b/third_party/waf/waflib/Tools/nasm.py @@ -4,7 +4,7 @@ #!/usr/bin/env python # encoding: utf-8 -# Thomas Nagy, 2008-2016 (ita) +# Thomas Nagy, 2008-2018 (ita) """ Nasm tool (asm processing) diff --git a/third_party/waf/waflib/Tools/nobuild.py b/third_party/waf/waflib/Tools/nobuild.py index 4086a8b05b7..705c3dd0b0a 100644 --- a/third_party/waf/waflib/Tools/nobuild.py +++ b/third_party/waf/waflib/Tools/nobuild.py @@ -25,3 +25,4 @@ def build(bld): x.write('') for (name, cls) in Task.classes.items(): cls.run = run + diff --git a/third_party/waf/waflib/Tools/perl.py b/third_party/waf/waflib/Tools/perl.py index cc8fe478bf0..375346ddfdf 100644 --- a/third_party/waf/waflib/Tools/perl.py +++ b/third_party/waf/waflib/Tools/perl.py @@ -5,7 +5,7 @@ #!/usr/bin/env python # encoding: utf-8 # andersg at 0x63.nu 2007 -# Thomas Nagy 2016 (ita) +# Thomas Nagy 2016-2018 (ita) """ Support for Perl extensions. A C/C++ compiler is required:: @@ -28,7 +28,7 @@ Support for Perl extensions. A C/C++ compiler is required:: """ import os -from waflib import Task, Options, Utils +from waflib import Task, Options, Utils, Errors from waflib.Configure import conf from waflib.TaskGen import extension, feature, before_method @@ -40,7 +40,8 @@ def init_perlext(self): *lib* prefix from library names. """ self.uselib = self.to_list(getattr(self, 'uselib', [])) - if not 'PERLEXT' in self.uselib: self.uselib.append('PERLEXT') + if not 'PERLEXT' in self.uselib: + self.uselib.append('PERLEXT') self.env.cshlib_PATTERN = self.env.cxxshlib_PATTERN = self.env.perlext_PATTERN @extension('.xs') @@ -102,7 +103,7 @@ def check_perl_module(self, module): self.start_msg('perl module %s' % module) try: r = self.cmd_and_log(cmd) - except Exception: + except Errors.WafError: self.end_msg(False) return None self.end_msg(r or True) @@ -156,3 +157,4 @@ def options(opt): """ opt.add_option('--with-perl-binary', type='string', dest='perlbinary', help = 'Specify alternate perl binary', default=None) opt.add_option('--with-perl-archdir', type='string', dest='perlarchdir', help = 'Specify directory where to install arch specific files', default=None) + diff --git a/third_party/waf/waflib/Tools/python.py b/third_party/waf/waflib/Tools/python.py index 587fc9c199a..10e407387d3 100644 --- a/third_party/waf/waflib/Tools/python.py +++ b/third_party/waf/waflib/Tools/python.py @@ -23,7 +23,7 @@ Support for Python, detect the headers and libraries and provide """ import os, sys -from waflib import Utils, Options, Errors, Logs, Task, Node +from waflib import Errors, Logs, Node, Options, Task, Utils from waflib.TaskGen import extension, before_method, after_method, feature from waflib.Configure import conf @@ -54,7 +54,7 @@ import sys, py_compile py_compile.compile(sys.argv[1], sys.argv[2], sys.argv[3], True) ''' """ -Piece of Python code used in :py:func:`waflib.Tools.python.pytask` for byte-compiling python files +Piece of Python code used in :py:class:`waflib.Tools.python.pyo` and :py:class:`waflib.Tools.python.pyc` for byte-compiling python files """ DISTUTILS_IMP = ['from distutils.sysconfig import get_config_var, get_python_lib'] @@ -83,7 +83,7 @@ def process_py(self, node): """ Add signature of .py file, so it will be byte-compiled when necessary """ - assert(getattr(self, 'install_path')), 'add features="py"' + assert(hasattr(self, 'install_path')), 'add features="py"' # where to install the python file if self.install_path: @@ -557,7 +557,7 @@ def check_python_module(conf, module_name, condition=''): conf.start_msg(msg) try: ret = conf.cmd_and_log(conf.env.PYTHON + ['-c', PYTHON_MODULE_TEMPLATE % module_name]) - except Exception: + except Errors.WafError: conf.end_msg(False) conf.fatal('Could not find the python module %r' % module_name) @@ -596,7 +596,7 @@ def configure(conf): v.NOPYCACHE=Options.options.nopycache if not v.PYTHON: - v.PYTHON = getattr(Options.options, 'python', None) or sys.executable + v.PYTHON = [getattr(Options.options, 'python', None) or sys.executable] v.PYTHON = Utils.to_list(v.PYTHON) conf.find_program('python', var='PYTHON') @@ -628,3 +628,4 @@ def options(opt): help='Installation path for python modules (py, platform-independent .py and .pyc files)') pyopt.add_option('--pythonarchdir', dest='pythonarchdir', help='Installation path for python extension (pyext, platform-dependent .so or .dylib files)') + diff --git a/third_party/waf/waflib/Tools/qt4.py b/third_party/waf/waflib/Tools/qt4.py deleted file mode 100644 index f3a43c2d807..00000000000 --- a/third_party/waf/waflib/Tools/qt4.py +++ /dev/null @@ -1,696 +0,0 @@ -#! /usr/bin/env python -# encoding: utf-8 -# WARNING! Do not edit! https://waf.io/book/index.html#_obtaining_the_waf_file - -#!/usr/bin/env python -# encoding: utf-8 -# Thomas Nagy, 2006-2010 (ita) - -""" - -Tool Description -================ - -This tool helps with finding Qt4 tools and libraries, -and also provides syntactic sugar for using Qt4 tools. - -The following snippet illustrates the tool usage:: - - def options(opt): - opt.load('compiler_cxx qt4') - - def configure(conf): - conf.load('compiler_cxx qt4') - - def build(bld): - bld( - features = 'qt4 cxx cxxprogram', - uselib = 'QTCORE QTGUI QTOPENGL QTSVG', - source = 'main.cpp textures.qrc aboutDialog.ui', - target = 'window', - ) - -Here, the UI description and resource files will be processed -to generate code. - -Usage -===== - -Load the "qt4" tool. - -You also need to edit your sources accordingly: - -- the normal way of doing things is to have your C++ files - include the .moc file. - This is regarded as the best practice (and provides much faster - compilations). - It also implies that the include paths have beenset properly. - -- to have the include paths added automatically, use the following:: - - from waflib.TaskGen import feature, before_method, after_method - @feature('cxx') - @after_method('process_source') - @before_method('apply_incpaths') - def add_includes_paths(self): - incs = set(self.to_list(getattr(self, 'includes', ''))) - for x in self.compiled_tasks: - incs.add(x.inputs[0].parent.path_from(self.path)) - self.includes = list(incs) - -Note: another tool provides Qt processing that does not require -.moc includes, see 'playground/slow_qt/'. - -A few options (--qt{dir,bin,...}) and environment variables -(QT4_{ROOT,DIR,MOC,UIC,XCOMPILE}) allow finer tuning of the tool, -tool path selection, etc; please read the source for more info. - -""" - -try: - from xml.sax import make_parser - from xml.sax.handler import ContentHandler -except ImportError: - has_xml = False - ContentHandler = object -else: - has_xml = True - -import os, sys -from waflib.Tools import cxx -from waflib import Task, Utils, Options, Errors, Context -from waflib.TaskGen import feature, after_method, extension -from waflib.Configure import conf -from waflib import Logs - -MOC_H = ['.h', '.hpp', '.hxx', '.hh'] -""" -File extensions associated to the .moc files -""" - -EXT_RCC = ['.qrc'] -""" -File extension for the resource (.qrc) files -""" - -EXT_UI = ['.ui'] -""" -File extension for the user interface (.ui) files -""" - -EXT_QT4 = ['.cpp', '.cc', '.cxx', '.C'] -""" -File extensions of C++ files that may require a .moc processing -""" - -QT4_LIBS = "QtCore QtGui QtUiTools QtNetwork QtOpenGL QtSql QtSvg QtTest QtXml QtXmlPatterns QtWebKit Qt3Support QtHelp QtScript QtDeclarative QtDesigner" - -class qxx(Task.classes['cxx']): - """ - Each C++ file can have zero or several .moc files to create. - They are known only when the files are scanned (preprocessor) - To avoid scanning the c++ files each time (parsing C/C++), the results - are retrieved from the task cache (bld.node_deps/bld.raw_deps). - The moc tasks are also created *dynamically* during the build. - """ - - def __init__(self, *k, **kw): - Task.Task.__init__(self, *k, **kw) - self.moc_done = 0 - - def runnable_status(self): - """ - Compute the task signature to make sure the scanner was executed. Create the - moc tasks by using :py:meth:`waflib.Tools.qt4.qxx.add_moc_tasks` (if necessary), - then postpone the task execution (there is no need to recompute the task signature). - """ - if self.moc_done: - return Task.Task.runnable_status(self) - else: - for t in self.run_after: - if not t.hasrun: - return Task.ASK_LATER - self.add_moc_tasks() - return Task.Task.runnable_status(self) - - def create_moc_task(self, h_node, m_node): - """ - If several libraries use the same classes, it is possible that moc will run several times (Issue 1318) - It is not possible to change the file names, but we can assume that the moc transformation will be identical, - and the moc tasks can be shared in a global cache. - - The defines passed to moc will then depend on task generator order. If this is not acceptable, then - use the tool slow_qt4 instead (and enjoy the slow builds... :-( ) - """ - try: - moc_cache = self.generator.bld.moc_cache - except AttributeError: - moc_cache = self.generator.bld.moc_cache = {} - - try: - return moc_cache[h_node] - except KeyError: - tsk = moc_cache[h_node] = Task.classes['moc'](env=self.env, generator=self.generator) - tsk.set_inputs(h_node) - tsk.set_outputs(m_node) - - if self.generator: - self.generator.tasks.append(tsk) - - # direct injection in the build phase (safe because called from the main thread) - gen = self.generator.bld.producer - gen.outstanding.insert(0, tsk) - gen.total += 1 - - return tsk - - def moc_h_ext(self): - ext = [] - try: - ext = Options.options.qt_header_ext.split() - except AttributeError: - pass - if not ext: - ext = MOC_H - return ext - - def add_moc_tasks(self): - """ - Create the moc tasks by looking in ``bld.raw_deps[self.uid()]`` - """ - node = self.inputs[0] - bld = self.generator.bld - - try: - # compute the signature once to know if there is a moc file to create - self.signature() - except KeyError: - # the moc file may be referenced somewhere else - pass - else: - # remove the signature, it must be recomputed with the moc task - delattr(self, 'cache_sig') - - include_nodes = [node.parent] + self.generator.includes_nodes - - moctasks = [] - mocfiles = set([]) - for d in bld.raw_deps.get(self.uid(), []): - if not d.endswith('.moc'): - continue - - # process that base.moc only once - if d in mocfiles: - continue - mocfiles.add(d) - - # find the source associated with the moc file - h_node = None - - base2 = d[:-4] - for x in include_nodes: - for e in self.moc_h_ext(): - h_node = x.find_node(base2 + e) - if h_node: - break - if h_node: - m_node = h_node.change_ext('.moc') - break - else: - # foo.cpp -> foo.cpp.moc - for k in EXT_QT4: - if base2.endswith(k): - for x in include_nodes: - h_node = x.find_node(base2) - if h_node: - break - if h_node: - m_node = h_node.change_ext(k + '.moc') - break - - if not h_node: - raise Errors.WafError('No source found for %r which is a moc file' % d) - - # create the moc task - task = self.create_moc_task(h_node, m_node) - moctasks.append(task) - - # simple scheduler dependency: run the moc task before others - self.run_after.update(set(moctasks)) - self.moc_done = 1 - -class trans_update(Task.Task): - """Update a .ts files from a list of C++ files""" - run_str = '${QT_LUPDATE} ${SRC} -ts ${TGT}' - color = 'BLUE' -Task.update_outputs(trans_update) - -class XMLHandler(ContentHandler): - """ - Parser for *.qrc* files - """ - def __init__(self): - self.buf = [] - self.files = [] - def startElement(self, name, attrs): - if name == 'file': - self.buf = [] - def endElement(self, name): - if name == 'file': - self.files.append(str(''.join(self.buf))) - def characters(self, cars): - self.buf.append(cars) - -@extension(*EXT_RCC) -def create_rcc_task(self, node): - "Create rcc and cxx tasks for *.qrc* files" - rcnode = node.change_ext('_rc.cpp') - self.create_task('rcc', node, rcnode) - cpptask = self.create_task('cxx', rcnode, rcnode.change_ext('.o')) - try: - self.compiled_tasks.append(cpptask) - except AttributeError: - self.compiled_tasks = [cpptask] - return cpptask - -@extension(*EXT_UI) -def create_uic_task(self, node): - "hook for uic tasks" - uictask = self.create_task('ui4', node) - uictask.outputs = [self.path.find_or_declare(self.env['ui_PATTERN'] % node.name[:-3])] - -@extension('.ts') -def add_lang(self, node): - """add all the .ts file into self.lang""" - self.lang = self.to_list(getattr(self, 'lang', [])) + [node] - -@feature('qt4') -@after_method('apply_link') -def apply_qt4(self): - """ - Add MOC_FLAGS which may be necessary for moc:: - - def build(bld): - bld.program(features='qt4', source='main.cpp', target='app', use='QTCORE') - - The additional parameters are: - - :param lang: list of translation files (\*.ts) to process - :type lang: list of :py:class:`waflib.Node.Node` or string without the .ts extension - :param update: whether to process the C++ files to update the \*.ts files (use **waf --translate**) - :type update: bool - :param langname: if given, transform the \*.ts files into a .qrc files to include in the binary file - :type langname: :py:class:`waflib.Node.Node` or string without the .qrc extension - """ - if getattr(self, 'lang', None): - qmtasks = [] - for x in self.to_list(self.lang): - if isinstance(x, str): - x = self.path.find_resource(x + '.ts') - qmtasks.append(self.create_task('ts2qm', x, x.change_ext('.qm'))) - - if getattr(self, 'update', None) and Options.options.trans_qt4: - cxxnodes = [a.inputs[0] for a in self.compiled_tasks] + [ - a.inputs[0] for a in self.tasks if getattr(a, 'inputs', None) and a.inputs[0].name.endswith('.ui')] - for x in qmtasks: - self.create_task('trans_update', cxxnodes, x.inputs) - - if getattr(self, 'langname', None): - qmnodes = [x.outputs[0] for x in qmtasks] - rcnode = self.langname - if isinstance(rcnode, str): - rcnode = self.path.find_or_declare(rcnode + '.qrc') - t = self.create_task('qm2rcc', qmnodes, rcnode) - k = create_rcc_task(self, t.outputs[0]) - self.link_task.inputs.append(k.outputs[0]) - - lst = [] - for flag in self.to_list(self.env['CXXFLAGS']): - if len(flag) < 2: continue - f = flag[0:2] - if f in ('-D', '-I', '/D', '/I'): - if (f[0] == '/'): - lst.append('-' + flag[1:]) - else: - lst.append(flag) - self.env.append_value('MOC_FLAGS', lst) - -@extension(*EXT_QT4) -def cxx_hook(self, node): - """ - Re-map C++ file extensions to the :py:class:`waflib.Tools.qt4.qxx` task. - """ - return self.create_compiled_task('qxx', node) - -class rcc(Task.Task): - """ - Process *.qrc* files - """ - color = 'BLUE' - run_str = '${QT_RCC} -name ${tsk.rcname()} ${SRC[0].abspath()} ${RCC_ST} -o ${TGT}' - ext_out = ['.h'] - - def rcname(self): - return os.path.splitext(self.inputs[0].name)[0] - - def scan(self): - """Parse the *.qrc* files""" - if not has_xml: - Logs.error('no xml support was found, the rcc dependencies will be incomplete!') - return ([], []) - - parser = make_parser() - curHandler = XMLHandler() - parser.setContentHandler(curHandler) - fi = open(self.inputs[0].abspath(), 'r') - try: - parser.parse(fi) - finally: - fi.close() - - nodes = [] - names = [] - root = self.inputs[0].parent - for x in curHandler.files: - nd = root.find_resource(x) - if nd: nodes.append(nd) - else: names.append(x) - return (nodes, names) - -class moc(Task.Task): - """ - Create *.moc* files - """ - color = 'BLUE' - run_str = '${QT_MOC} ${MOC_FLAGS} ${MOCCPPPATH_ST:INCPATHS} ${MOCDEFINES_ST:DEFINES} ${SRC} ${MOC_ST} ${TGT}' - def keyword(self): - return "Creating" - def __str__(self): - return self.outputs[0].path_from(self.generator.bld.launch_node()) - -class ui4(Task.Task): - """ - Process *.ui* files - """ - color = 'BLUE' - run_str = '${QT_UIC} ${SRC} -o ${TGT}' - ext_out = ['.h'] - -class ts2qm(Task.Task): - """ - Create *.qm* files from *.ts* files - """ - color = 'BLUE' - run_str = '${QT_LRELEASE} ${QT_LRELEASE_FLAGS} ${SRC} -qm ${TGT}' - -class qm2rcc(Task.Task): - """ - Transform *.qm* files into *.rc* files - """ - color = 'BLUE' - after = 'ts2qm' - - def run(self): - """Create a qrc file including the inputs""" - txt = '\n'.join(['<file>%s</file>' % k.path_from(self.outputs[0].parent) for k in self.inputs]) - code = '<!DOCTYPE RCC><RCC version="1.0">\n<qresource>\n%s\n</qresource>\n</RCC>' % txt - self.outputs[0].write(code) - -def configure(self): - """ - Besides the configuration options, the environment variable QT4_ROOT may be used - to give the location of the qt4 libraries (absolute path). - - The detection will use the program *pkg-config* through :py:func:`waflib.Tools.config_c.check_cfg` - """ - self.find_qt4_binaries() - self.set_qt4_libs_to_check() - self.set_qt4_defines() - self.find_qt4_libraries() - self.add_qt4_rpath() - self.simplify_qt4_libs() - -@conf -def find_qt4_binaries(self): - env = self.env - opt = Options.options - - qtdir = getattr(opt, 'qtdir', '') - qtbin = getattr(opt, 'qtbin', '') - - paths = [] - - if qtdir: - qtbin = os.path.join(qtdir, 'bin') - - # the qt directory has been given from QT4_ROOT - deduce the qt binary path - if not qtdir: - qtdir = os.environ.get('QT4_ROOT', '') - qtbin = os.environ.get('QT4_BIN', None) or os.path.join(qtdir, 'bin') - - if qtbin: - paths = [qtbin] - - # no qtdir, look in the path and in /usr/local/Trolltech - if not qtdir: - paths = os.environ.get('PATH', '').split(os.pathsep) - paths.append('/usr/share/qt4/bin/') - try: - lst = Utils.listdir('/usr/local/Trolltech/') - except OSError: - pass - else: - if lst: - lst.sort() - lst.reverse() - - # keep the highest version - qtdir = '/usr/local/Trolltech/%s/' % lst[0] - qtbin = os.path.join(qtdir, 'bin') - paths.append(qtbin) - - # at the end, try to find qmake in the paths given - # keep the one with the highest version - cand = None - prev_ver = ['4', '0', '0'] - for qmk in ('qmake-qt4', 'qmake4', 'qmake'): - try: - qmake = self.find_program(qmk, path_list=paths) - except self.errors.ConfigurationError: - pass - else: - try: - version = self.cmd_and_log(qmake + ['-query', 'QT_VERSION']).strip() - except self.errors.WafError: - pass - else: - if version: - new_ver = version.split('.') - if new_ver > prev_ver: - cand = qmake - prev_ver = new_ver - if cand: - self.env.QMAKE = cand - else: - self.fatal('Could not find qmake for qt4') - - qtbin = self.cmd_and_log(self.env.QMAKE + ['-query', 'QT_INSTALL_BINS']).strip() + os.sep - - def find_bin(lst, var): - if var in env: - return - for f in lst: - try: - ret = self.find_program(f, path_list=paths) - except self.errors.ConfigurationError: - pass - else: - env[var]=ret - break - - find_bin(['uic-qt3', 'uic3'], 'QT_UIC3') - find_bin(['uic-qt4', 'uic'], 'QT_UIC') - if not env.QT_UIC: - self.fatal('cannot find the uic compiler for qt4') - - self.start_msg('Checking for uic version') - uicver = self.cmd_and_log(env.QT_UIC + ["-version"], output=Context.BOTH) - uicver = ''.join(uicver).strip() - uicver = uicver.replace('Qt User Interface Compiler ','').replace('User Interface Compiler for Qt', '') - self.end_msg(uicver) - if uicver.find(' 3.') != -1: - self.fatal('this uic compiler is for qt3, add uic for qt4 to your path') - - find_bin(['moc-qt4', 'moc'], 'QT_MOC') - find_bin(['rcc-qt4', 'rcc'], 'QT_RCC') - find_bin(['lrelease-qt4', 'lrelease'], 'QT_LRELEASE') - find_bin(['lupdate-qt4', 'lupdate'], 'QT_LUPDATE') - - env['UIC3_ST']= '%s -o %s' - env['UIC_ST'] = '%s -o %s' - env['MOC_ST'] = '-o' - env['ui_PATTERN'] = 'ui_%s.h' - env['QT_LRELEASE_FLAGS'] = ['-silent'] - env.MOCCPPPATH_ST = '-I%s' - env.MOCDEFINES_ST = '-D%s' - -@conf -def find_qt4_libraries(self): - qtlibs = getattr(Options.options, 'qtlibs', None) or os.environ.get("QT4_LIBDIR", None) - if not qtlibs: - try: - qtlibs = self.cmd_and_log(self.env.QMAKE + ['-query', 'QT_INSTALL_LIBS']).strip() - except Errors.WafError: - qtdir = self.cmd_and_log(self.env.QMAKE + ['-query', 'QT_INSTALL_PREFIX']).strip() + os.sep - qtlibs = os.path.join(qtdir, 'lib') - self.msg('Found the Qt4 libraries in', qtlibs) - - qtincludes = os.environ.get("QT4_INCLUDES", None) or self.cmd_and_log(self.env.QMAKE + ['-query', 'QT_INSTALL_HEADERS']).strip() - env = self.env - if not 'PKG_CONFIG_PATH' in os.environ: - os.environ['PKG_CONFIG_PATH'] = '%s:%s/pkgconfig:/usr/lib/qt4/lib/pkgconfig:/opt/qt4/lib/pkgconfig:/usr/lib/qt4/lib:/opt/qt4/lib' % (qtlibs, qtlibs) - - try: - if os.environ.get("QT4_XCOMPILE", None): - raise self.errors.ConfigurationError() - self.check_cfg(atleast_pkgconfig_version='0.1') - except self.errors.ConfigurationError: - for i in self.qt4_vars: - uselib = i.upper() - if Utils.unversioned_sys_platform() == "darwin": - # Since at least qt 4.7.3 each library locates in separate directory - frameworkName = i + ".framework" - qtDynamicLib = os.path.join(qtlibs, frameworkName, i) - if os.path.exists(qtDynamicLib): - env.append_unique('FRAMEWORK_' + uselib, i) - self.msg('Checking for %s' % i, qtDynamicLib, 'GREEN') - else: - self.msg('Checking for %s' % i, False, 'YELLOW') - env.append_unique('INCLUDES_' + uselib, os.path.join(qtlibs, frameworkName, 'Headers')) - elif env.DEST_OS != "win32": - qtDynamicLib = os.path.join(qtlibs, "lib" + i + ".so") - qtStaticLib = os.path.join(qtlibs, "lib" + i + ".a") - if os.path.exists(qtDynamicLib): - env.append_unique('LIB_' + uselib, i) - self.msg('Checking for %s' % i, qtDynamicLib, 'GREEN') - elif os.path.exists(qtStaticLib): - env.append_unique('LIB_' + uselib, i) - self.msg('Checking for %s' % i, qtStaticLib, 'GREEN') - else: - self.msg('Checking for %s' % i, False, 'YELLOW') - - env.append_unique('LIBPATH_' + uselib, qtlibs) - env.append_unique('INCLUDES_' + uselib, qtincludes) - env.append_unique('INCLUDES_' + uselib, os.path.join(qtincludes, i)) - else: - # Release library names are like QtCore4 - for k in ("lib%s.a", "lib%s4.a", "%s.lib", "%s4.lib"): - lib = os.path.join(qtlibs, k % i) - if os.path.exists(lib): - env.append_unique('LIB_' + uselib, i + k[k.find("%s") + 2 : k.find('.')]) - self.msg('Checking for %s' % i, lib, 'GREEN') - break - else: - self.msg('Checking for %s' % i, False, 'YELLOW') - - env.append_unique('LIBPATH_' + uselib, qtlibs) - env.append_unique('INCLUDES_' + uselib, qtincludes) - env.append_unique('INCLUDES_' + uselib, os.path.join(qtincludes, i)) - - # Debug library names are like QtCore4d - uselib = i.upper() + "_debug" - for k in ("lib%sd.a", "lib%sd4.a", "%sd.lib", "%sd4.lib"): - lib = os.path.join(qtlibs, k % i) - if os.path.exists(lib): - env.append_unique('LIB_' + uselib, i + k[k.find("%s") + 2 : k.find('.')]) - self.msg('Checking for %s' % i, lib, 'GREEN') - break - else: - self.msg('Checking for %s' % i, False, 'YELLOW') - - env.append_unique('LIBPATH_' + uselib, qtlibs) - env.append_unique('INCLUDES_' + uselib, qtincludes) - env.append_unique('INCLUDES_' + uselib, os.path.join(qtincludes, i)) - else: - for i in self.qt4_vars_debug + self.qt4_vars: - self.check_cfg(package=i, args='--cflags --libs', mandatory=False) - -@conf -def simplify_qt4_libs(self): - # the libpaths make really long command-lines - # remove the qtcore ones from qtgui, etc - env = self.env - def process_lib(vars_, coreval): - for d in vars_: - var = d.upper() - if var == 'QTCORE': - continue - - value = env['LIBPATH_'+var] - if value: - core = env[coreval] - accu = [] - for lib in value: - if lib in core: - continue - accu.append(lib) - env['LIBPATH_'+var] = accu - - process_lib(self.qt4_vars, 'LIBPATH_QTCORE') - process_lib(self.qt4_vars_debug, 'LIBPATH_QTCORE_DEBUG') - -@conf -def add_qt4_rpath(self): - # rpath if wanted - env = self.env - if getattr(Options.options, 'want_rpath', False): - def process_rpath(vars_, coreval): - for d in vars_: - var = d.upper() - value = env['LIBPATH_'+var] - if value: - core = env[coreval] - accu = [] - for lib in value: - if var != 'QTCORE': - if lib in core: - continue - accu.append('-Wl,--rpath='+lib) - env['RPATH_'+var] = accu - process_rpath(self.qt4_vars, 'LIBPATH_QTCORE') - process_rpath(self.qt4_vars_debug, 'LIBPATH_QTCORE_DEBUG') - -@conf -def set_qt4_libs_to_check(self): - if not hasattr(self, 'qt4_vars'): - self.qt4_vars = QT4_LIBS - self.qt4_vars = Utils.to_list(self.qt4_vars) - if not hasattr(self, 'qt4_vars_debug'): - self.qt4_vars_debug = [a + '_debug' for a in self.qt4_vars] - self.qt4_vars_debug = Utils.to_list(self.qt4_vars_debug) - -@conf -def set_qt4_defines(self): - if sys.platform != 'win32': - return - for x in self.qt4_vars: - y = x[2:].upper() - self.env.append_unique('DEFINES_%s' % x.upper(), 'QT_%s_LIB' % y) - self.env.append_unique('DEFINES_%s_DEBUG' % x.upper(), 'QT_%s_LIB' % y) - -def options(opt): - """ - Command-line options - """ - opt.add_option('--want-rpath', action='store_true', default=False, dest='want_rpath', help='enable the rpath for qt libraries') - - opt.add_option('--header-ext', - type='string', - default='', - help='header extension for moc files', - dest='qt_header_ext') - - for i in 'qtdir qtbin qtlibs'.split(): - opt.add_option('--'+i, type='string', default='', dest=i) - - opt.add_option('--translate', action="store_true", help="collect translation strings", dest="trans_qt4", default=False) diff --git a/third_party/waf/waflib/Tools/qt5.py b/third_party/waf/waflib/Tools/qt5.py index 05522a49f66..f4842a9ac55 100644 --- a/third_party/waf/waflib/Tools/qt5.py +++ b/third_party/waf/waflib/Tools/qt5.py @@ -4,7 +4,7 @@ #!/usr/bin/env python # encoding: utf-8 -# Thomas Nagy, 2006-2016 (ita) +# Thomas Nagy, 2006-2018 (ita) """ This tool helps with finding Qt5 tools and libraries, @@ -52,7 +52,7 @@ You also need to edit your sources accordingly: incs = set(self.to_list(getattr(self, 'includes', ''))) for x in self.compiled_tasks: incs.add(x.inputs[0].parent.path_from(self.path)) - self.includes = list(incs) + self.includes = sorted(incs) Note: another tool provides Qt processing that does not require .moc includes, see 'playground/slow_qt/'. @@ -65,6 +65,8 @@ The detection uses pkg-config on Linux by default. To force static library detec QT5_XCOMPILE=1 QT5_FORCE_STATIC=1 waf configure """ +from __future__ import with_statement + try: from xml.sax import make_parser from xml.sax.handler import ContentHandler @@ -153,7 +155,7 @@ class qxx(Task.classes['cxx']): # direct injection in the build phase (safe because called from the main thread) gen = self.generator.bld.producer - gen.outstanding.appendleft(tsk) + gen.outstanding.append(tsk) gen.total += 1 return tsk @@ -234,6 +236,7 @@ class XMLHandler(ContentHandler): Parses ``.qrc`` files """ def __init__(self): + ContentHandler.__init__(self) self.buf = [] self.files = [] def startElement(self, name, attrs): @@ -248,7 +251,7 @@ class XMLHandler(ContentHandler): @extension(*EXT_RCC) def create_rcc_task(self, node): "Creates rcc and cxx tasks for ``.qrc`` files" - rcnode = node.change_ext('_rc.cpp') + rcnode = node.change_ext('_rc.%d.cpp' % self.idx) self.create_task('rcc', node, rcnode) cpptask = self.create_task('cxx', rcnode, rcnode.change_ext('.o')) try: @@ -260,8 +263,21 @@ def create_rcc_task(self, node): @extension(*EXT_UI) def create_uic_task(self, node): "Create uic tasks for user interface ``.ui`` definition files" - uictask = self.create_task('ui5', node) - uictask.outputs = [node.parent.find_or_declare(self.env.ui_PATTERN % node.name[:-3])] + + """ + If UIC file is used in more than one bld, we would have a conflict in parallel execution + It is not possible to change the file names (like .self.idx. as for objects) as they have + to be referenced by the source file, but we can assume that the transformation will be identical + and the tasks can be shared in a global cache. + """ + try: + uic_cache = self.bld.uic_cache + except AttributeError: + uic_cache = self.bld.uic_cache = {} + + if node not in uic_cache: + uictask = uic_cache[node] = self.create_task('ui5', node) + uictask.outputs = [node.parent.find_or_declare(self.env.ui_PATTERN % node.name[:-3])] @extension('.ts') def add_lang(self, node): @@ -313,11 +329,11 @@ def apply_qt5(self): for x in self.to_list(self.lang): if isinstance(x, str): x = self.path.find_resource(x + '.ts') - qmtasks.append(self.create_task('ts2qm', x, x.change_ext('.qm'))) + qmtasks.append(self.create_task('ts2qm', x, x.change_ext('.%d.qm' % self.idx))) if getattr(self, 'update', None) and Options.options.trans_qt5: cxxnodes = [a.inputs[0] for a in self.compiled_tasks] + [ - a.inputs[0] for a in self.tasks if getattr(a, 'inputs', None) and a.inputs[0].name.endswith('.ui')] + a.inputs[0] for a in self.tasks if a.inputs and a.inputs[0].name.endswith('.ui')] for x in qmtasks: self.create_task('trans_update', cxxnodes, x.inputs) @@ -325,14 +341,15 @@ def apply_qt5(self): qmnodes = [x.outputs[0] for x in qmtasks] rcnode = self.langname if isinstance(rcnode, str): - rcnode = self.path.find_or_declare(rcnode + '.qrc') + rcnode = self.path.find_or_declare(rcnode + ('.%d.qrc' % self.idx)) t = self.create_task('qm2rcc', qmnodes, rcnode) k = create_rcc_task(self, t.outputs[0]) self.link_task.inputs.append(k.outputs[0]) lst = [] for flag in self.to_list(self.env.CXXFLAGS): - if len(flag) < 2: continue + if len(flag) < 2: + continue f = flag[0:2] if f in ('-D', '-I', '/D', '/I'): if (f[0] == '/'): @@ -368,19 +385,18 @@ class rcc(Task.Task): parser = make_parser() curHandler = XMLHandler() parser.setContentHandler(curHandler) - fi = open(self.inputs[0].abspath(), 'r') - try: - parser.parse(fi) - finally: - fi.close() + with open(self.inputs[0].abspath(), 'r') as f: + parser.parse(f) nodes = [] names = [] root = self.inputs[0].parent for x in curHandler.files: nd = root.find_resource(x) - if nd: nodes.append(nd) - else: names.append(x) + if nd: + nodes.append(nd) + else: + names.append(x) return (nodes, names) class moc(Task.Task): @@ -456,7 +472,6 @@ def configure(self): self.fatal('Could not build a simple Qt application') # FreeBSD does not add /usr/local/lib and the pkg-config files do not provide it either :-/ - from waflib import Utils if Utils.unversioned_sys_platform() == 'freebsd': frag = '#include <QApplication>\nint main(int argc, char **argv) { QApplication app(argc, argv); return NULL != (void*) (&app);}\n' try: @@ -572,7 +587,7 @@ def find_qt5_binaries(self): uicver = uicver.replace('Qt User Interface Compiler ','').replace('User Interface Compiler for Qt', '') self.end_msg(uicver) if uicver.find(' 3.') != -1 or uicver.find(' 4.') != -1: - self.fatal('this uic compiler is for qt3 or qt5, add uic for qt5 to your path') + self.fatal('this uic compiler is for qt3 or qt4, add uic for qt5 to your path') find_bin(['moc-qt5', 'moc'], 'QT_MOC') find_bin(['rcc-qt5', 'rcc'], 'QT_RCC') @@ -658,16 +673,14 @@ def find_qt5_libraries(self): self.msg('Checking for %s' % i, False, 'YELLOW') env.append_unique('INCLUDES_' + uselib, os.path.join(env.QTLIBS, frameworkName, 'Headers')) else: - for j in ('', 'd'): - k = '_DEBUG' if j == 'd' else '' - ret = self.find_single_qt5_lib(i + j, uselib + k, env.QTLIBS, qtincludes, force_static) - if not force_static and not ret: - ret = self.find_single_qt5_lib(i + j, uselib + k, env.QTLIBS, qtincludes, True) - self.msg('Checking for %s' % (i + j), ret, 'GREEN' if ret else 'YELLOW') + ret = self.find_single_qt5_lib(i, uselib, env.QTLIBS, qtincludes, force_static) + if not force_static and not ret: + ret = self.find_single_qt5_lib(i, uselib, env.QTLIBS, qtincludes, True) + self.msg('Checking for %s' % i, ret, 'GREEN' if ret else 'YELLOW') else: path = '%s:%s:%s/pkgconfig:/usr/lib/qt5/lib/pkgconfig:/opt/qt5/lib/pkgconfig:/usr/lib/qt5/lib:/opt/qt5/lib' % ( self.environ.get('PKG_CONFIG_PATH', ''), env.QTLIBS, env.QTLIBS) - for i in self.qt5_vars_debug + self.qt5_vars: + for i in self.qt5_vars: self.check_cfg(package=i, args='--cflags --libs', mandatory=False, force_static=force_static, pkg_config_path=path) @conf @@ -693,7 +706,6 @@ def simplify_qt5_libs(self): accu.append(lib) env['LIBPATH_'+var] = accu process_lib(self.qt5_vars, 'LIBPATH_QTCORE') - process_lib(self.qt5_vars_debug, 'LIBPATH_QTCORE_DEBUG') @conf def add_qt5_rpath(self): @@ -716,7 +728,6 @@ def add_qt5_rpath(self): accu.append('-Wl,--rpath='+lib) env['RPATH_' + var] = accu process_rpath(self.qt5_vars, 'LIBPATH_QTCORE') - process_rpath(self.qt5_vars_debug, 'LIBPATH_QTCORE_DEBUG') @conf def set_qt5_libs_to_check(self): @@ -743,10 +754,6 @@ def set_qt5_libs_to_check(self): if qtextralibs: self.qt5_vars.extend(qtextralibs.split(',')) - if not hasattr(self, 'qt5_vars_debug'): - self.qt5_vars_debug = [a + '_DEBUG' for a in self.qt5_vars] - self.qt5_vars_debug = Utils.to_list(self.qt5_vars_debug) - @conf def set_qt5_defines(self): if sys.platform != 'win32': @@ -754,7 +761,6 @@ def set_qt5_defines(self): for x in self.qt5_vars: y=x.replace('Qt5', 'Qt')[2:].upper() self.env.append_unique('DEFINES_%s' % x.upper(), 'QT_%s_LIB' % y) - self.env.append_unique('DEFINES_%s_DEBUG' % x.upper(), 'QT_%s_LIB' % y) def options(opt): """ @@ -766,3 +772,4 @@ def options(opt): opt.add_option('--translate', action='store_true', help='collect translation strings', dest='trans_qt5', default=False) opt.add_option('--qtextralibs', type='string', default='', dest='qtextralibs', help='additional qt libraries on the system to add to default ones, comma separated') + diff --git a/third_party/waf/waflib/Tools/ruby.py b/third_party/waf/waflib/Tools/ruby.py index b407c3698b8..f5107aaa141 100644 --- a/third_party/waf/waflib/Tools/ruby.py +++ b/third_party/waf/waflib/Tools/ruby.py @@ -5,7 +5,7 @@ #!/usr/bin/env python # encoding: utf-8 # daniel.svensson at purplescout.se 2008 -# Thomas Nagy 2016 (ita) +# Thomas Nagy 2016-2018 (ita) """ Support for Ruby extensions. A C/C++ compiler is required:: @@ -27,7 +27,7 @@ Support for Ruby extensions. A C/C++ compiler is required:: """ import os -from waflib import Options, Utils, Task +from waflib import Errors, Options, Task, Utils from waflib.TaskGen import before_method, feature, extension from waflib.Configure import conf @@ -64,13 +64,13 @@ def check_ruby_version(self, minver=()): try: version = self.cmd_and_log(ruby + ['-e', 'puts defined?(VERSION) ? VERSION : RUBY_VERSION']).strip() - except Exception: + except Errors.WafError: self.fatal('could not determine ruby version') self.env.RUBY_VERSION = version try: - ver = tuple(map(int, version.split("."))) - except Exception: + ver = tuple(map(int, version.split('.'))) + except Errors.WafError: self.fatal('unsupported ruby version %r' % version) cver = '' @@ -155,7 +155,7 @@ def check_ruby_module(self, module_name): self.start_msg('Ruby module %s' % module_name) try: self.cmd_and_log(self.env.RUBY + ['-e', 'require \'%s\';puts 1' % module_name]) - except Exception: + except Errors.WafError: self.end_msg(False) self.fatal('Could not find the ruby module %r' % module_name) self.end_msg(True) @@ -187,3 +187,4 @@ def options(opt): opt.add_option('--with-ruby-archdir', type='string', dest='rubyarchdir', help='Specify directory where to install arch specific files') opt.add_option('--with-ruby-libdir', type='string', dest='rubylibdir', help='Specify alternate ruby library path') opt.add_option('--with-ruby-binary', type='string', dest='rubybinary', help='Specify alternate ruby binary') + diff --git a/third_party/waf/waflib/Tools/suncc.py b/third_party/waf/waflib/Tools/suncc.py index cc59e54c2bd..5a3318368aa 100644 --- a/third_party/waf/waflib/Tools/suncc.py +++ b/third_party/waf/waflib/Tools/suncc.py @@ -4,9 +4,10 @@ #!/usr/bin/env python # encoding: utf-8 -# Thomas Nagy, 2006-2016 (ita) +# Thomas Nagy, 2006-2018 (ita) # Ralf Habacker, 2006 (rh) +from waflib import Errors from waflib.Tools import ccroot, ar from waflib.Configure import conf @@ -19,7 +20,7 @@ def find_scc(conf): cc = conf.find_program('cc', var='CC') try: conf.cmd_and_log(cc + ['-flags']) - except Exception: + except Errors.WafError: conf.fatal('%r is not a Sun compiler' % cc) v.CC_NAME = 'sun' conf.get_suncc_version(cc) @@ -67,3 +68,4 @@ def configure(conf): conf.cc_load_tools() conf.cc_add_flags() conf.link_add_flags() + diff --git a/third_party/waf/waflib/Tools/suncxx.py b/third_party/waf/waflib/Tools/suncxx.py index 8d024e5ec9e..5b00407edec 100644 --- a/third_party/waf/waflib/Tools/suncxx.py +++ b/third_party/waf/waflib/Tools/suncxx.py @@ -4,9 +4,10 @@ #!/usr/bin/env python # encoding: utf-8 -# Thomas Nagy, 2006-2016 (ita) +# Thomas Nagy, 2006-2018 (ita) # Ralf Habacker, 2006 (rh) +from waflib import Errors from waflib.Tools import ccroot, ar from waflib.Configure import conf @@ -19,7 +20,7 @@ def find_sxx(conf): cc = conf.find_program(['CC', 'c++'], var='CXX') try: conf.cmd_and_log(cc + ['-flags']) - except Exception: + except Errors.WafError: conf.fatal('%r is not a Sun compiler' % cc) v.CXX_NAME = 'sun' conf.get_suncc_version(cc) @@ -67,3 +68,4 @@ def configure(conf): conf.cxx_load_tools() conf.cxx_add_flags() conf.link_add_flags() + diff --git a/third_party/waf/waflib/Tools/tex.py b/third_party/waf/waflib/Tools/tex.py index e5888b92d19..0d72333889c 100644 --- a/third_party/waf/waflib/Tools/tex.py +++ b/third_party/waf/waflib/Tools/tex.py @@ -4,7 +4,7 @@ #!/usr/bin/env python # encoding: utf-8 -# Thomas Nagy, 2006-2016 (ita) +# Thomas Nagy, 2006-2018 (ita) """ TeX/LaTeX/PDFLaTeX/XeLaTeX support @@ -52,20 +52,23 @@ def bibunitscan(self): node = self.inputs[0] nodes = [] - if not node: return nodes + if not node: + return nodes code = node.read() for match in re_bibunit.finditer(code): path = match.group('file') if path: + found = None for k in ('', '.bib'): # add another loop for the tex include paths? Logs.debug('tex: trying %s%s', path, k) fi = node.parent.find_resource(path + k) if fi: + found = True nodes.append(fi) - # no break, people are crazy - else: + # no break + if not found: Logs.debug('tex: could not find %s', path) Logs.debug('tex: found the following bibunit files: %s', nodes) @@ -160,14 +163,14 @@ class tex(Task.Task): nodes = [] names = [] seen = [] - if not node: return (nodes, names) + if not node: + return (nodes, names) def parse_node(node): if node in seen: return seen.append(node) code = node.read() - global re_tex for match in re_tex.finditer(code): multibib = match.group('type') @@ -541,3 +544,4 @@ def configure(self): except self.errors.ConfigurationError: pass v.DVIPSFLAGS = '-Ppdf' + diff --git a/third_party/waf/waflib/Tools/vala.py b/third_party/waf/waflib/Tools/vala.py index f2154cd159f..699a80082c5 100644 --- a/third_party/waf/waflib/Tools/vala.py +++ b/third_party/waf/waflib/Tools/vala.py @@ -13,7 +13,7 @@ this tool to be too stable either (apis, etc) """ import re -from waflib import Context, Task, Utils, Logs, Options, Errors, Node +from waflib import Build, Context, Errors, Logs, Node, Options, Task, Utils from waflib.TaskGen import extension, taskgen_method from waflib.Configure import conf @@ -149,8 +149,13 @@ def init_vala_task(self): package_obj = self.bld.get_tgen_by_name(package) except Errors.WafError: continue + + # in practice the other task is already processed + # but this makes it explicit + package_obj.post() package_name = package_obj.target - for task in package_obj.tasks: + task = getattr(package_obj, 'valatask', None) + if task: for output in task.outputs: if output.name == package_name + ".vapi": valatask.set_run_after(task) @@ -185,21 +190,15 @@ def init_vala_task(self): if self.is_lib and valatask.install_binding: headers_list = [o for o in valatask.outputs if o.suffix() == ".h"] - try: - self.install_vheader.source = headers_list - except AttributeError: + if headers_list: self.install_vheader = self.add_install_files(install_to=valatask.header_path, install_from=headers_list) vapi_list = [o for o in valatask.outputs if (o.suffix() in (".vapi", ".deps"))] - try: - self.install_vapi.source = vapi_list - except AttributeError: + if vapi_list: self.install_vapi = self.add_install_files(install_to=valatask.vapi_path, install_from=vapi_list) gir_list = [o for o in valatask.outputs if o.suffix() == '.gir'] - try: - self.install_gir.source = gir_list - except AttributeError: + if gir_list: self.install_gir = self.add_install_files( install_to=getattr(self, 'gir_path', '${DATAROOTDIR}/gir-1.0'), install_from=gir_list) @@ -254,6 +253,15 @@ def vala_file(self, node): valatask.outputs.append(c_node) self.source.append(c_node) +@extension('.vapi') +def vapi_file(self, node): + try: + valatask = self.valatask + except AttributeError: + valatask = self.valatask = self.create_task('valac') + self.init_vala_task() + valatask.inputs.append(node) + @conf def find_valac(self, valac_name, min_version): """ @@ -268,7 +276,7 @@ def find_valac(self, valac_name, min_version): valac = self.find_program(valac_name, var='VALAC') try: output = self.cmd_and_log(valac + ['--version']) - except Exception: + except Errors.WafError: valac_version = None else: ver = re.search(r'\d+.\d+.\d+', output).group().split('.') @@ -348,3 +356,4 @@ def options(opt): valaopts.add_option('--vala-target-glib', default=None, dest='vala_target_glib', metavar='MAJOR.MINOR', help='Target version of glib for Vala GObject code generation') + diff --git a/third_party/waf/waflib/Tools/waf_unit_test.py b/third_party/waf/waflib/Tools/waf_unit_test.py index 3e4fec0f498..b1db1704c9c 100644 --- a/third_party/waf/waflib/Tools/waf_unit_test.py +++ b/third_party/waf/waflib/Tools/waf_unit_test.py @@ -5,10 +5,10 @@ #!/usr/bin/env python # encoding: utf-8 # Carlos Rafael Giani, 2006 -# Thomas Nagy, 2010-2016 (ita) +# Thomas Nagy, 2010-2018 (ita) """ -Unit testing system for C/C++/D providing test execution: +Unit testing system for C/C++/D and interpreted languages providing test execution: * in parallel, by using ``waf -j`` * partial (only the tests that have changed) or full (by using ``waf --alltests``) @@ -40,7 +40,7 @@ By passing --dump-test-scripts the build outputs corresponding python files (with extension _run.py) that are useful for debugging purposes. """ -import os, sys +import os, shlex, sys from waflib.TaskGen import feature, after_method, taskgen_method from waflib import Utils, Task, Logs, Options from waflib.Tools import ccroot @@ -56,6 +56,52 @@ status = subprocess.call(cmd, env=env, cwd=%(cwd)r, shell=isinstance(cmd, str)) sys.exit(status) """ +@taskgen_method +def handle_ut_cwd(self, key): + """ + Task generator method, used internally to limit code duplication. + This method may disappear anytime. + """ + cwd = getattr(self, key, None) + if cwd: + if isinstance(cwd, str): + # we want a Node instance + if os.path.isabs(cwd): + self.ut_cwd = self.bld.root.make_node(cwd) + else: + self.ut_cwd = self.path.make_node(cwd) + +@feature('test_scripts') +def make_interpreted_test(self): + """Create interpreted unit tests.""" + for x in ['test_scripts_source', 'test_scripts_template']: + if not hasattr(self, x): + Logs.warn('a test_scripts taskgen i missing %s' % x) + return + + self.ut_run, lst = Task.compile_fun(self.test_scripts_template, shell=getattr(self, 'test_scripts_shell', False)) + + script_nodes = self.to_nodes(self.test_scripts_source) + for script_node in script_nodes: + tsk = self.create_task('utest', [script_node]) + tsk.vars = lst + tsk.vars + tsk.env['SCRIPT'] = script_node.path_from(tsk.get_cwd()) + + self.handle_ut_cwd('test_scripts_cwd') + + env = getattr(self, 'test_scripts_env', None) + if env: + self.ut_env = env + else: + self.ut_env = dict(os.environ) + + paths = getattr(self, 'test_scripts_paths', {}) + for (k,v) in paths.items(): + p = self.ut_env.get(k, '').split(os.pathsep) + if isinstance(v, str): + v = v.split(os.pathsep) + self.ut_env[k] = os.pathsep.join(p + v) + @feature('test') @after_method('apply_link', 'process_use') def make_test(self): @@ -68,15 +114,7 @@ def make_test(self): self.ut_run, lst = Task.compile_fun(self.ut_str, shell=getattr(self, 'ut_shell', False)) tsk.vars = lst + tsk.vars - if getattr(self, 'ut_cwd', None): - if isinstance(self.ut_cwd, str): - # we want a Node instance - if os.path.isabs(self.ut_cwd): - self.ut_cwd = self.bld.root.make_node(self.ut_cwd) - else: - self.ut_cwd = self.path.make_node(self.ut_cwd) - else: - self.ut_cwd = tsk.inputs[0].parent + self.handle_ut_cwd('ut_cwd') if not hasattr(self, 'ut_paths'): paths = [] @@ -102,11 +140,17 @@ def make_test(self): else: add_path('LD_LIBRARY_PATH') + if not hasattr(self, 'ut_cmd'): + self.ut_cmd = getattr(Options.options, 'testcmd', False) + @taskgen_method def add_test_results(self, tup): """Override and return tup[1] to interrupt the build immediately if a test does not run""" Logs.debug("ut: %r", tup) - self.utest_result = tup + try: + self.utest_results.append(tup) + except AttributeError: + self.utest_results = [tup] try: self.bld.utest_results.append(tup) except AttributeError: @@ -156,24 +200,21 @@ class utest(Task.Task): if hasattr(self.generator, 'ut_run'): return self.generator.ut_run(self) - # TODO ut_exec, ut_fun, ut_cmd should be considered obsolete self.ut_exec = getattr(self.generator, 'ut_exec', [self.inputs[0].abspath()]) - if getattr(self.generator, 'ut_fun', None): - self.generator.ut_fun(self) - testcmd = getattr(self.generator, 'ut_cmd', False) or getattr(Options.options, 'testcmd', False) - if testcmd: - self.ut_exec = (testcmd % ' '.join(self.ut_exec)).split(' ') + ut_cmd = getattr(self.generator, 'ut_cmd', False) + if ut_cmd: + self.ut_exec = shlex.split(ut_cmd % ' '.join(self.ut_exec)) return self.exec_command(self.ut_exec) def exec_command(self, cmd, **kw): Logs.debug('runner: %r', cmd) if getattr(Options.options, 'dump_test_scripts', False): - global SCRIPT_TEMPLATE script_code = SCRIPT_TEMPLATE % { 'python': sys.executable, 'env': self.get_test_env(), - 'cwd': self.get_cwd().abspath(), 'cmd': cmd + 'cwd': self.get_cwd().abspath(), + 'cmd': cmd } script_file = self.inputs[0].abspath() + '_run.py' Utils.writef(script_file, script_code) @@ -182,7 +223,7 @@ class utest(Task.Task): Logs.info('Test debug file written as %r' % script_file) proc = Utils.subprocess.Popen(cmd, cwd=self.get_cwd().abspath(), env=self.get_test_env(), - stderr=Utils.subprocess.PIPE, stdout=Utils.subprocess.PIPE) + stderr=Utils.subprocess.PIPE, stdout=Utils.subprocess.PIPE, shell=isinstance(cmd,str)) (stdout, stderr) = proc.communicate() self.waf_unit_test_results = tup = (self.inputs[0].abspath(), proc.returncode, stdout, stderr) testlock.acquire() @@ -192,7 +233,12 @@ class utest(Task.Task): testlock.release() def get_cwd(self): - return self.generator.ut_cwd + return getattr(self.generator, 'ut_cwd', self.inputs[0].parent) + + def sig_explicit_deps(self): + lst = [os.stat(node.abspath()).st_mtime for node in self.inputs] + self.m.update(str(lst)) + return super(utest, self).sig_explicit_deps() def summary(bld): """ @@ -210,15 +256,15 @@ def summary(bld): total = len(lst) tfail = len([x for x in lst if x[1]]) - Logs.pprint('CYAN', ' tests that pass %d/%d' % (total-tfail, total)) + Logs.pprint('GREEN', ' tests that pass %d/%d' % (total-tfail, total)) for (f, code, out, err) in lst: if not code: - Logs.pprint('CYAN', ' %s' % f) + Logs.pprint('GREEN', ' %s' % f) - Logs.pprint('CYAN', ' tests that fail %d/%d' % (tfail, total)) + Logs.pprint('GREEN' if tfail == 0 else 'RED', ' tests that fail %d/%d' % (tfail, total)) for (f, code, out, err) in lst: if code: - Logs.pprint('CYAN', ' %s' % f) + Logs.pprint('RED', ' %s' % f) def set_exit_code(bld): """ @@ -249,10 +295,10 @@ 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' - ' %s" to run under valgrind', dest='testcmd') + 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, dest='testcmd', + help='Run the unit tests using the test-cmd string example "--testcmd="valgrind --error-exitcode=1 %s" to run under valgrind') opt.add_option('--dump-test-scripts', action='store_true', default=False, - help='Create python scripts to help debug tests', dest='dump_test_scripts') + help='Create python scripts to help debug tests', dest='dump_test_scripts') + diff --git a/third_party/waf/waflib/Tools/winres.py b/third_party/waf/waflib/Tools/winres.py index a4376372a5d..23fa27e54e0 100644 --- a/third_party/waf/waflib/Tools/winres.py +++ b/third_party/waf/waflib/Tools/winres.py @@ -42,7 +42,8 @@ class rc_parser(c_preproc.c_parser): """ code = node.read() if c_preproc.use_trigraphs: - for (a, b) in c_preproc.trig_def: code = code.split(a).join(b) + for (a, b) in c_preproc.trig_def: + code = code.split(a).join(b) code = c_preproc.re_nl.sub('', code) code = c_preproc.re_cpp.sub(c_preproc.repl, code) ret = [] @@ -78,3 +79,4 @@ def configure(conf): conf.find_program('windres', var='WINRC', path_list=v.PATH) v.WINRC_TGT_F = '-o' v.WINRC_SRC_F = '-i' + diff --git a/third_party/waf/waflib/Tools/xlc.py b/third_party/waf/waflib/Tools/xlc.py index c2e2ab6d738..6dfb4b04486 100644 --- a/third_party/waf/waflib/Tools/xlc.py +++ b/third_party/waf/waflib/Tools/xlc.py @@ -4,7 +4,7 @@ #!/usr/bin/env python # encoding: utf-8 -# Thomas Nagy, 2006-2016 (ita) +# Thomas Nagy, 2006-2018 (ita) # Ralf Habacker, 2006 (rh) # Yinon Ehrlich, 2009 # Michael Kuhn, 2009 @@ -66,3 +66,4 @@ def configure(conf): conf.cc_load_tools() conf.cc_add_flags() conf.link_add_flags() + diff --git a/third_party/waf/waflib/Tools/xlcxx.py b/third_party/waf/waflib/Tools/xlcxx.py index d7cafc052ec..a67ef502ba9 100644 --- a/third_party/waf/waflib/Tools/xlcxx.py +++ b/third_party/waf/waflib/Tools/xlcxx.py @@ -4,7 +4,7 @@ #!/usr/bin/env python # encoding: utf-8 -# Thomas Nagy, 2006-2016 (ita) +# Thomas Nagy, 2006-2018 (ita) # Ralf Habacker, 2006 (rh) # Yinon Ehrlich, 2009 # Michael Kuhn, 2009 @@ -66,3 +66,4 @@ def configure(conf): conf.cxx_load_tools() conf.cxx_add_flags() conf.link_add_flags() + |