From dac769a730bd18d71363bc633f9f101a5eb24e38 Mon Sep 17 00:00:00 2001 From: Matt Selsky Date: Sun, 8 Jul 2018 14:58:47 -0400 Subject: [PATCH 001/315] Ignore temporary directories created when using Python 3 --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 6a5db6aff2..f54a7ef593 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ build demos/*/build* playground/*/build* .waf-* +.waf3-* *.log .DS_Store .AppleDouble From ca65dda59021ce7199df868b36bce230aa7f4b17 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Mon, 9 Jul 2018 16:43:09 +0200 Subject: [PATCH 002/315] waf-2.0.9 --- waf-light | 2 +- waflib/Context.py | 6 +++--- wscript | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/waf-light b/waf-light index 29040b2160..d895b5be85 100755 --- a/waf-light +++ b/waf-light @@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. import os, sys, inspect -VERSION="2.0.8" +VERSION="2.0.9" REVISION="x" GIT="x" INSTALL="x" diff --git a/waflib/Context.py b/waflib/Context.py index 3222fb1551..4e7a63337c 100644 --- a/waflib/Context.py +++ b/waflib/Context.py @@ -11,13 +11,13 @@ import waflib.Node # the following 3 constants are updated on each new release (do not touch) -HEXVERSION=0x2000800 +HEXVERSION=0x2000900 """Constant updated on new releases""" -WAFVERSION="2.0.8" +WAFVERSION="2.0.9" """Constant updated on new releases""" -WAFREVISION="f78fbc32bb355a3291c9b5f79bbe0c8dfe81282a" +WAFREVISION="8a950e7bca9a3a9b1ae62aae039ef76e2adc4177" """Git revision when the waf version is updated""" ABI = 20 diff --git a/wscript b/wscript index 3158f58dae..e3567ef179 100644 --- a/wscript +++ b/wscript @@ -11,7 +11,7 @@ To add a tool that does not exist in the folder compat15, pass an absolute path: from __future__ import with_statement -VERSION="2.0.8" +VERSION="2.0.9" APPNAME='waf' REVISION='' From 3679b531fdbe96d763ba26eac153ba01b74e32f4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 2 Mar 2018 16:26:44 +1100 Subject: [PATCH 003/315] fixed cross-build for arm-none-eabi on cygwin we need to use relative paths and not use --enable-auto-import. The relative paths are needed to keep paths within the severe path length limitations of the cygwin cross-compiler for arm-none-eabi --- waflib/Node.py | 11 +++++++++++ waflib/Tools/c.py | 4 ++-- waflib/Tools/cxx.py | 4 ++-- waflib/Tools/gcc.py | 5 ++++- waflib/Tools/gxx.py | 5 ++++- 5 files changed, 23 insertions(+), 6 deletions(-) diff --git a/waflib/Node.py b/waflib/Node.py index 4ac1ea8a0b..237d75e463 100644 --- a/waflib/Node.py +++ b/waflib/Node.py @@ -554,6 +554,17 @@ def abspath(self): self.cache_abspath = val return val + def relpath(self): + """ + Returns the relative path. This is used in place of abspath() to keep paths short + for environments like cygwin where path lengths to file operations are severely limited + (for example, when cross-compiling for arm-none-eabi on cygwin) + + :rtype: string + """ + return os.path.relpath(self.abspath()) + + def is_child_of(self, node): """ Returns whether the object belongs to a subtree of the input node:: diff --git a/waflib/Tools/c.py b/waflib/Tools/c.py index effd6b6ee8..be7c746d71 100644 --- a/waflib/Tools/c.py +++ b/waflib/Tools/c.py @@ -17,14 +17,14 @@ def c_hook(self, node): class c(Task.Task): "Compiles C files into object files" - run_str = '${CC} ${ARCH_ST:ARCH} ${CFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${CC_SRC_F}${SRC} ${CC_TGT_F}${TGT[0].abspath()} ${CPPFLAGS}' + run_str = '${CC} ${ARCH_ST:ARCH} ${CFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${CC_SRC_F}${SRC} ${CC_TGT_F}${TGT[0].relpath()} ${CPPFLAGS}' vars = ['CCDEPS'] # unused variable to depend on, just in case ext_in = ['.h'] # set the build order easily by using ext_out=['.h'] scan = c_preproc.scan class cprogram(link_task): "Links object files into c programs" - run_str = '${LINK_CC} ${LINKFLAGS} ${CCLNK_SRC_F}${SRC} ${CCLNK_TGT_F}${TGT[0].abspath()} ${RPATH_ST:RPATH} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${FRAMEWORK_ST:FRAMEWORK} ${ARCH_ST:ARCH} ${STLIB_MARKER} ${STLIBPATH_ST:STLIBPATH} ${STLIB_ST:STLIB} ${SHLIB_MARKER} ${LIBPATH_ST:LIBPATH} ${LIB_ST:LIB} ${LDFLAGS}' + run_str = '${LINK_CC} ${LINKFLAGS} ${CCLNK_SRC_F}${SRC} ${CCLNK_TGT_F}${TGT[0].relpath()} ${RPATH_ST:RPATH} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${FRAMEWORK_ST:FRAMEWORK} ${ARCH_ST:ARCH} ${STLIB_MARKER} ${STLIBPATH_ST:STLIBPATH} ${STLIB_ST:STLIB} ${SHLIB_MARKER} ${LIBPATH_ST:LIBPATH} ${LIB_ST:LIB} ${LDFLAGS}' ext_out = ['.bin'] vars = ['LINKDEPS'] inst_to = '${BINDIR}' diff --git a/waflib/Tools/cxx.py b/waflib/Tools/cxx.py index 194fad7437..705ec74d06 100644 --- a/waflib/Tools/cxx.py +++ b/waflib/Tools/cxx.py @@ -18,14 +18,14 @@ def cxx_hook(self, node): class cxx(Task.Task): "Compiles C++ files into object files" - run_str = '${CXX} ${ARCH_ST:ARCH} ${CXXFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${CXX_SRC_F}${SRC} ${CXX_TGT_F}${TGT[0].abspath()} ${CPPFLAGS}' + run_str = '${CXX} ${ARCH_ST:ARCH} ${CXXFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${CXX_SRC_F}${SRC} ${CXX_TGT_F}${TGT[0].relpath()} ${CPPFLAGS}' vars = ['CXXDEPS'] # unused variable to depend on, just in case ext_in = ['.h'] # set the build order easily by using ext_out=['.h'] scan = c_preproc.scan class cxxprogram(link_task): "Links object files into c++ programs" - run_str = '${LINK_CXX} ${LINKFLAGS} ${CXXLNK_SRC_F}${SRC} ${CXXLNK_TGT_F}${TGT[0].abspath()} ${RPATH_ST:RPATH} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${FRAMEWORK_ST:FRAMEWORK} ${ARCH_ST:ARCH} ${STLIB_MARKER} ${STLIBPATH_ST:STLIBPATH} ${STLIB_ST:STLIB} ${SHLIB_MARKER} ${LIBPATH_ST:LIBPATH} ${LIB_ST:LIB} ${LDFLAGS}' + run_str = '${LINK_CXX} ${LINKFLAGS} ${CXXLNK_SRC_F}${SRC} ${CXXLNK_TGT_F}${TGT[0].relpath()} ${RPATH_ST:RPATH} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${FRAMEWORK_ST:FRAMEWORK} ${ARCH_ST:ARCH} ${STLIB_MARKER} ${STLIBPATH_ST:STLIBPATH} ${STLIB_ST:STLIB} ${SHLIB_MARKER} ${LIBPATH_ST:LIBPATH} ${LIB_ST:LIB} ${LDFLAGS}' vars = ['LINKDEPS'] ext_out = ['.bin'] inst_to = '${BINDIR}' diff --git a/waflib/Tools/gcc.py b/waflib/Tools/gcc.py index acdd473ada..2bda5f5242 100644 --- a/waflib/Tools/gcc.py +++ b/waflib/Tools/gcc.py @@ -76,7 +76,10 @@ def gcc_modifier_win32(conf): # Auto-import is enabled by default even without this option, # but enabling it explicitly has the nice effect of suppressing the rather boring, debug-level messages # that the linker emits otherwise. - v.append_value('LINKFLAGS', ['-Wl,--enable-auto-import']) + import sys + if sys.platform != "cygwin": + # disabled on cygwin as it breaks build with arm cross compiler + v.append_value('LINKFLAGS', ['-Wl,--enable-auto-import']) @conf def gcc_modifier_cygwin(conf): diff --git a/waflib/Tools/gxx.py b/waflib/Tools/gxx.py index 22c5d26f2a..2667258197 100644 --- a/waflib/Tools/gxx.py +++ b/waflib/Tools/gxx.py @@ -76,7 +76,10 @@ def gxx_modifier_win32(conf): # Auto-import is enabled by default even without this option, # but enabling it explicitly has the nice effect of suppressing the rather boring, debug-level messages # that the linker emits otherwise. - v.append_value('LINKFLAGS', ['-Wl,--enable-auto-import']) + import sys + if sys.platform != "cygwin": + # disabled on cygwin as it breaks build with arm cross compiler + v.append_value('LINKFLAGS', ['-Wl,--enable-auto-import']) @conf def gxx_modifier_cygwin(conf): From 02de87b4e074d6fbce609ec9e4936c4c458f0e5a Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Tue, 27 Mar 2018 22:06:39 -0700 Subject: [PATCH 004/315] Make error messages more useful Just convert the list by joining the elements with space. It may not be perfect since it may explode in cases we have spaces, but it's better than giving a list that you can't do anything with it. By adding the error output as a command one can manually build that single compilation unit to understand better the error and even switch to another compile to get a better error message. --- waflib/Task.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/waflib/Task.py b/waflib/Task.py index ffe7b16ead..12fe5804b0 100644 --- a/waflib/Task.py +++ b/waflib/Task.py @@ -446,10 +446,15 @@ def format_error(self): elif not self.hasrun: return 'task in %r was not executed for some reason: %r' % (name, self) elif self.hasrun == CRASHED: + if isinstance(msg, str): + txt = msg + else: + txt = ' '.join(repr(x) if ' ' in x else x for x in msg) + try: - return ' -> task in %r failed with exit status %r%s' % (name, self.err_code, msg) + return ' -> task in %r failed (exit status %r): %r\n%s' % (name, self.err_code, self, txt) except AttributeError: - return ' -> task in %r failed%s' % (name, msg) + return ' -> task in %r failed: %r\n%s' % (name, self, txt) elif self.hasrun == MISSING: return ' -> missing files in %r%s' % (name, msg) elif self.hasrun == CANCELED: From 0cd2882845c5d91f7943841e2158711398dcf9af Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 20 Jun 2018 19:55:18 +1000 Subject: [PATCH 005/315] gccdeps: ignore undeclared build products this fixes an issue with undeclared build products causing build errors --- waflib/extras/gccdeps.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/extras/gccdeps.py b/waflib/extras/gccdeps.py index d9758ab34d..0dd07fd039 100644 --- a/waflib/extras/gccdeps.py +++ b/waflib/extras/gccdeps.py @@ -141,7 +141,7 @@ def post_run(self): node = path_to_node(path, x, cached_nodes) if not node: - raise ValueError('could not find %r for %r' % (x, self)) + continue if id(node) == id(self.inputs[0]): # ignore the source file, it is already in the dependencies # this way, successful config tests may be retrieved from the cache From ac321c09b23052da0dc94bbc29b459a408bb30f2 Mon Sep 17 00:00:00 2001 From: cclauss Date: Fri, 18 Jan 2019 14:41:54 +0100 Subject: [PATCH 006/315] Define xrange() in Python 3 __xrange()__ was removed in Python 3 in favor of a reworked version of __range()__. Discovered via ArduPilot/ardupilot#10278 --- playground/compress/optim.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/playground/compress/optim.py b/playground/compress/optim.py index f61627329c..bd7ab927e6 100755 --- a/playground/compress/optim.py +++ b/playground/compress/optim.py @@ -2,6 +2,11 @@ import os, subprocess, shutil, random, optparse +try: + xrange # Python 2 +except NameError: # Python 3 + xrange = range + comp = { 'bz2': 'cjf', 'xz' : 'cJf', From 337b0a96beeac517ecde081fb76dedd039089734 Mon Sep 17 00:00:00 2001 From: cclauss Date: Fri, 18 Jan 2019 23:57:08 +0100 Subject: [PATCH 007/315] Match the change made in upstream https://gitlab.com/ita1024/waf/blob/master/playground/compress/optim.py --- playground/compress/optim.py | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/playground/compress/optim.py b/playground/compress/optim.py index bd7ab927e6..e318cef0b7 100755 --- a/playground/compress/optim.py +++ b/playground/compress/optim.py @@ -2,11 +2,6 @@ import os, subprocess, shutil, random, optparse -try: - xrange # Python 2 -except NameError: # Python 3 - xrange = range - comp = { 'bz2': 'cjf', 'xz' : 'cJf', @@ -48,20 +43,20 @@ def compare(a, b): LEN = len(lst) POP = 3*LEN + 1 - popul = [range(LEN) for x in xrange(POP)] - fitn = [0 for x in xrange(POP)] + popul = [range(LEN) for x in range(POP)] + fitn = [0 for x in range(POP)] def rnd(): return random.randint(0, LEN -1) def mutate(): - for x in xrange(LEN): + for x in range(LEN): # rotate the previous element by one v = popul[x+LEN] = popul[x+LEN - 1] a = v.pop(0) v.append(a) - for x in xrange(LEN): + for x in range(LEN): # swap elements a = rnd() b = rnd() @@ -71,7 +66,7 @@ def mutate(): v[a] = v[b] v[b] = c - for x in xrange(LEN): + for x in range(LEN): # get one element out, add at the end v = popul[x+2*LEN] @@ -84,7 +79,7 @@ def evil(): best = opti_ref pos = -1 - for x in xrange(len(popul)): + for x in range(len(popul)): v = popul[x] arr = [lst[a] for a in v] tmp = '%s %s' % (cmd, ' '.join(arr)) @@ -104,14 +99,14 @@ def evil(): assert (sum(popul[x]) == sum(range(LEN))) #print pos - for x in xrange(len(popul)): + for x in range(len(popul)): if x == pos: continue popul[x] = popul[pos][:] assert(len(popul[x]) == LEN) return best - for i in xrange(10000): + for i in range(10000): mutate() print(evil()) From 9a634fff4db87ac61961891cdb6b4c4a90e56e94 Mon Sep 17 00:00:00 2001 From: Peter Barker Date: Fri, 11 Oct 2019 22:14:53 +1100 Subject: [PATCH 008/315] Build.py: correct debug --- waflib/Build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/Build.py b/waflib/Build.py index 8347a287a8..772c66f60c 100644 --- a/waflib/Build.py +++ b/waflib/Build.py @@ -645,7 +645,7 @@ def add_group(self, name=None, move=True): :raises: :py:class:`waflib.Errors.WafError` if a group by the name given already exists """ if name and name in self.group_names: - raise Errors.WafError('add_group: name %s already present', name) + raise Errors.WafError('add_group: name %s already present' % name) g = [] self.group_names[name] = g self.groups.append(g) From 67b3eac550520cd8a7cd1dce0f77820e91fb8ad0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 29 Jan 2020 18:16:12 +1100 Subject: [PATCH 009/315] Fixed configure error with cygwin --- waflib/Tools/c_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/Tools/c_config.py b/waflib/Tools/c_config.py index 76082152cd..41b53ae7b2 100644 --- a/waflib/Tools/c_config.py +++ b/waflib/Tools/c_config.py @@ -1011,7 +1011,7 @@ 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'.encode(), env=env) + out, err = conf.cmd_and_log(cmd, output=0, stdin=open('/dev/null','r'), env=env) except Errors.WafError: conf.fatal('Could not determine the compiler version %r' % cmd) From 51f1529bd20759642e9fd0a8db648da9ba380b18 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 20 Apr 2021 14:08:50 +1000 Subject: [PATCH 010/315] Task: fixed handling of very long ar lines in cygwin --- waflib/Task.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/waflib/Task.py b/waflib/Task.py index 12fe5804b0..c358ce4796 100644 --- a/waflib/Task.py +++ b/waflib/Task.py @@ -266,6 +266,16 @@ def split_argfile(self, cmd): """ return ([cmd[0]], [self.quote_flag(x) for x in cmd[1:]]) + def should_split(self, cmd): + """return True if this command needs splitting for argument length""" + if isinstance(cmd, str): + return False + if Utils.is_win32 and len(repr(cmd)) >= 8192: + return True + if sys.platform.startswith("cygwin") and len(repr(cmd)) > 20000: + return True + return len(repr(cmd)) > 200000 + def exec_command(self, cmd, **kw): """ Wrapper for :py:meth:`waflib.Context.Context.exec_command`. @@ -302,15 +312,15 @@ def exec_command(self, cmd, **kw): # workaround for command line length limit: # http://support.microsoft.com/kb/830473 - if not isinstance(cmd, str) and (len(repr(cmd)) >= 8192 if Utils.is_win32 else len(cmd) > 200000): + if self.should_split(cmd): cmd, args = self.split_argfile(cmd) try: (fd, tmp) = tempfile.mkstemp() - os.write(fd, '\r\n'.join(args).encode()) + os.write(fd, '\r\n'.join(args[1:]).encode()) os.close(fd) if Logs.verbose: Logs.debug('argfile: @%r -> %r', tmp, args) - return self.generator.bld.exec_command(cmd + ['@' + tmp], **kw) + return self.generator.bld.exec_command(cmd + args[:1] + ['@' + tmp], **kw) finally: try: os.remove(tmp) From 53c179ed16ce773a685e9d8cf725c81095698f27 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Fri, 27 Jul 2018 11:16:36 +0200 Subject: [PATCH 011/315] Fix --help when no wscript is supplied #2184 --- waflib/Scripting.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/Scripting.py b/waflib/Scripting.py index 18203d5270..df99b5444e 100644 --- a/waflib/Scripting.py +++ b/waflib/Scripting.py @@ -34,7 +34,7 @@ def waf_entry_point(current_directory, version, wafdir): # Store current directory before any chdir Context.waf_dir = wafdir - Context.run_dir = Context.launch_dir = current_directory + Context.launch_dir = current_directory start_dir = current_directory no_climb = os.environ.get('NOCLIMB') From 7b68f96483d2e75badfe7f1bf71b333cfd89fd46 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sat, 28 Jul 2018 10:27:54 +0200 Subject: [PATCH 012/315] Fix deadlocks affecting generated Fortran files #2187 --- waflib/Runner.py | 6 ++++++ waflib/Task.py | 3 +++ waflib/Tools/fc.py | 2 ++ 3 files changed, 11 insertions(+) diff --git a/waflib/Runner.py b/waflib/Runner.py index 7535c83de9..975c32922f 100644 --- a/waflib/Runner.py +++ b/waflib/Runner.py @@ -226,6 +226,10 @@ def refill_task_list(self): pass else: if cond: + # The most common reason is conflicting build order declaration + # for example: "X run_after Y" and "Y run_after X" + # Another can be changing "run_after" dependencies while the build is running + # for example: updating "tsk.run_after" in the "runnable_status" method lst = [] for tsk in self.postponed: deps = [id(x) for x in tsk.run_after if not x.hasrun] @@ -298,6 +302,8 @@ def iteri(a, b): def mark_finished(self, tsk): def try_unfreeze(x): # DAG ancestors are likely to be in the incomplete set + # This assumes that the run_after contents have not changed + # after the build starts, else a deadlock may occur if x in self.incomplete: # TODO remove dependencies to free some memory? # x.run_after.remove(tsk) diff --git a/waflib/Task.py b/waflib/Task.py index c358ce4796..3e07ebfbb7 100644 --- a/waflib/Task.py +++ b/waflib/Task.py @@ -605,6 +605,9 @@ def set_run_after(self, task): """ Run this task only after the given *task*. + Calling this method from :py:meth:`waflib.Task.Task.runnable_status` may cause + build deadlocks; see :py:meth:`waflib.Tools.fc.fc.runnable_status` for details. + :param task: task :type task: :py:class:`waflib.Task.Task` """ diff --git a/waflib/Tools/fc.py b/waflib/Tools/fc.py index 621eb5029d..d9e8d8c442 100644 --- a/waflib/Tools/fc.py +++ b/waflib/Tools/fc.py @@ -121,6 +121,8 @@ def runnable_status(self): for k in ins.keys(): for a in ins[k]: a.run_after.update(outs[k]) + for x in outs[k]: + self.generator.bld.producer.revdeps[x].add(a) # the scanner cannot output nodes, so we have to set them # ourselves as task.dep_nodes (additional input nodes) From a0e4a9f108b90943bd58d05c1c599964275ad20b Mon Sep 17 00:00:00 2001 From: Matt Selsky Date: Sat, 28 Jul 2018 19:46:58 -0400 Subject: [PATCH 013/315] Fix typos --- demos/unit_test/wscript | 2 +- playground/gtest/wscript | 2 +- playground/pyqt5/wscript | 2 +- playground/qt5-and-pyqt5/pyqt5/wscript | 2 +- playground/test_fail/wscript | 2 +- utils/launcher/waf-launcher/Main.cs | 2 +- waflib/Build.py | 2 +- waflib/Configure.py | 2 +- waflib/Context.py | 2 +- waflib/TaskGen.py | 2 +- waflib/Tools/c_preproc.py | 2 +- waflib/Tools/ccroot.py | 2 +- waflib/Tools/fc_config.py | 2 +- waflib/extras/fc_cray.py | 2 +- waflib/extras/fc_nec.py | 2 +- waflib/extras/xcode6.py | 8 ++++---- 16 files changed, 19 insertions(+), 19 deletions(-) diff --git a/demos/unit_test/wscript b/demos/unit_test/wscript index 3f45c66b79..cf89b2e2ae 100644 --- a/demos/unit_test/wscript +++ b/demos/unit_test/wscript @@ -57,7 +57,7 @@ def build(bld): # to execute all tests: # $ waf --alltests - # to set this behaviour permanenly: + # to set this behaviour permanently: #bld.options.all_tests = True bld.options.clear_failed_tests = True diff --git a/playground/gtest/wscript b/playground/gtest/wscript index 759bc32fc1..df8e9b6d99 100644 --- a/playground/gtest/wscript +++ b/playground/gtest/wscript @@ -59,7 +59,7 @@ def build(bld): # to execute all tests: # $ waf --alltests - # to set this behaviour permanenly: + # to set this behaviour permanently: bld.options.all_tests = True # debugging zone: diff --git a/playground/pyqt5/wscript b/playground/pyqt5/wscript index 8a5379be6e..a5e242d934 100644 --- a/playground/pyqt5/wscript +++ b/playground/pyqt5/wscript @@ -19,7 +19,7 @@ def configure(conf): conf.check_python_version((2,7,4)) def build(bld): - # Demostrates mixed usage of py and pyqt5 module, and tests also install_path and install_from + # Demonstrates mixed usage of py and pyqt5 module, and tests also install_path and install_from # (since generated files go into build it has to be reset inside the pyqt5 tool) bld(features="py pyqt5", source="src/sample.py src/firstgui.ui", install_path="${PREFIX}/play/", install_from="src/") diff --git a/playground/qt5-and-pyqt5/pyqt5/wscript b/playground/qt5-and-pyqt5/pyqt5/wscript index 8a5379be6e..a5e242d934 100644 --- a/playground/qt5-and-pyqt5/pyqt5/wscript +++ b/playground/qt5-and-pyqt5/pyqt5/wscript @@ -19,7 +19,7 @@ def configure(conf): conf.check_python_version((2,7,4)) def build(bld): - # Demostrates mixed usage of py and pyqt5 module, and tests also install_path and install_from + # Demonstrates mixed usage of py and pyqt5 module, and tests also install_path and install_from # (since generated files go into build it has to be reset inside the pyqt5 tool) bld(features="py pyqt5", source="src/sample.py src/firstgui.ui", install_path="${PREFIX}/play/", install_from="src/") diff --git a/playground/test_fail/wscript b/playground/test_fail/wscript index b0e79a5679..a0dceb6b93 100644 --- a/playground/test_fail/wscript +++ b/playground/test_fail/wscript @@ -3,7 +3,7 @@ # Thomas Nagy, 2011 (ita) """ -Map a compilation failure to a successs status. People playing with C++ templates +Map a compilation failure to a success status. People playing with C++ templates might need this. """ diff --git a/utils/launcher/waf-launcher/Main.cs b/utils/launcher/waf-launcher/Main.cs index 1f76e7c596..006f8b73fb 100644 --- a/utils/launcher/waf-launcher/Main.cs +++ b/utils/launcher/waf-launcher/Main.cs @@ -91,7 +91,7 @@ public static void installPython(){ Console.WriteLine ("python2.7 downloaded to " + filename); Console.WriteLine ("Installing python"); - //filename must be qouted or else msiexec will fail + //filename must be quoted or else msiexec will fail exec("msiexec","/qn","/i","\"" +filename + "\""); Console.WriteLine ("Python is now installed"); } diff --git a/waflib/Build.py b/waflib/Build.py index 772c66f60c..4249beee21 100644 --- a/waflib/Build.py +++ b/waflib/Build.py @@ -884,7 +884,7 @@ def build(bld): :param dest: absolute path of the symlink :type dest: :py:class:`waflib.Node.Node` or string (absolute path) - :param src: link contents, which is a relative or abolute path which may exist or not + :param src: link contents, which is a relative or absolute path which may exist or not :type src: string :param env: configuration set for performing substitutions in dest :type env: :py:class:`waflib.ConfigSet.ConfigSet` diff --git a/waflib/Configure.py b/waflib/Configure.py index 20ca705e69..d0a4793a88 100644 --- a/waflib/Configure.py +++ b/waflib/Configure.py @@ -286,7 +286,7 @@ def post_recurse(self, node): def eval_rules(self, rules): """ - Execute configuration tests provided as list of funcitons to run + Execute configuration tests provided as list of functions to run :param rules: list of configuration method names :type rules: list of string diff --git a/waflib/Context.py b/waflib/Context.py index 4e7a63337c..6271550532 100644 --- a/waflib/Context.py +++ b/waflib/Context.py @@ -502,7 +502,7 @@ def to_log(self, msg): def build(bld): bld.to_log('starting the build') - Provide a logger on the context class or override this methid if necessary. + Provide a logger on the context class or override this method if necessary. :param msg: message :type msg: string diff --git a/waflib/TaskGen.py b/waflib/TaskGen.py index 40007b55ca..a74e6431d8 100644 --- a/waflib/TaskGen.py +++ b/waflib/TaskGen.py @@ -556,7 +556,7 @@ def build(bld): * chmod: permissions for the resulting files (integer value such as Utils.O755) * shell: set to False to execute the command directly (default is True to use a shell) * scan: scanner function - * vars: list of variables to trigger rebuilts, such as CFLAGS + * vars: list of variables to trigger rebuilds, such as CFLAGS * cls_str: string to display when executing the task * cls_keyword: label to display when executing the task * cache_rule: by default, try to re-use similar classes, set to False to disable diff --git a/waflib/Tools/c_preproc.py b/waflib/Tools/c_preproc.py index c2c239baa2..7e04b4a7c7 100644 --- a/waflib/Tools/c_preproc.py +++ b/waflib/Tools/c_preproc.py @@ -146,7 +146,7 @@ def repl(m): prec = {} """ -Operator precendence rules required for parsing expressions of the form:: +Operator precedence rules required for parsing expressions of the form:: #if 1 && 2 != 0 """ diff --git a/waflib/Tools/ccroot.py b/waflib/Tools/ccroot.py index 394f36b8e1..a90fdd8ffc 100644 --- a/waflib/Tools/ccroot.py +++ b/waflib/Tools/ccroot.py @@ -161,7 +161,7 @@ def add_target(self, target): nums = self.generator.vnum.split('.') if self.env.DEST_BINFMT == 'pe': # include the version in the dll file name, - # the import lib file name stays unversionned. + # the import lib file name stays unversioned. name = name + '-' + nums[0] elif self.env.DEST_OS == 'openbsd': pattern = '%s.%s' % (pattern, nums[0]) diff --git a/waflib/Tools/fc_config.py b/waflib/Tools/fc_config.py index 0df460b5d1..222f3a55d4 100644 --- a/waflib/Tools/fc_config.py +++ b/waflib/Tools/fc_config.py @@ -281,7 +281,7 @@ def _parse_flink_token(lexer, token, tmp_flags): elif POSIX_LIB_FLAGS.match(token): tmp_flags.append(token) else: - # ignore anything not explicitely taken into account + # ignore anything not explicitly taken into account pass t = lexer.get_token() diff --git a/waflib/extras/fc_cray.py b/waflib/extras/fc_cray.py index ec2906742b..da733fade3 100644 --- a/waflib/extras/fc_cray.py +++ b/waflib/extras/fc_cray.py @@ -20,7 +20,7 @@ def find_crayftn(conf): @conf def crayftn_flags(conf): v = conf.env - v['_FCMODOUTFLAGS'] = ['-em', '-J.'] # enable module files and put them in the current directoy + v['_FCMODOUTFLAGS'] = ['-em', '-J.'] # enable module files and put them in the current directory v['FCFLAGS_DEBUG'] = ['-m1'] # more verbose compiler warnings v['FCFLAGS_fcshlib'] = ['-h pic'] v['LINKFLAGS_fcshlib'] = ['-h shared'] diff --git a/waflib/extras/fc_nec.py b/waflib/extras/fc_nec.py index 4b70f3dccc..67c8680898 100644 --- a/waflib/extras/fc_nec.py +++ b/waflib/extras/fc_nec.py @@ -20,7 +20,7 @@ def find_sxfc(conf): @conf def sxfc_flags(conf): v = conf.env - v['_FCMODOUTFLAGS'] = [] # enable module files and put them in the current directoy + v['_FCMODOUTFLAGS'] = [] # enable module files and put them in the current directory v['FCFLAGS_DEBUG'] = [] # more verbose compiler warnings v['FCFLAGS_fcshlib'] = [] v['LINKFLAGS_fcshlib'] = [] diff --git a/waflib/extras/xcode6.py b/waflib/extras/xcode6.py index c062a74e4f..91bbff181e 100644 --- a/waflib/extras/xcode6.py +++ b/waflib/extras/xcode6.py @@ -147,7 +147,7 @@ def newid(): Represents a tree node in the XCode project plist file format. When written to a file, all attributes of XCodeNode are stringified together with its value. However, attributes starting with an underscore _ are ignored -during that process and allows you to store arbitray values that are not supposed +during that process and allows you to store arbitrary values that are not supposed to be written out. """ class XCodeNode(object): @@ -247,7 +247,7 @@ def __init__(self, fileRef, settings={}): # fileRef is a reference to a PBXFileReference object self.fileRef = fileRef - # A map of key/value pairs for additionnal settings. + # A map of key/value pairs for additional settings. self.settings = settings def __hash__(self): @@ -435,8 +435,8 @@ def __init__(self, name, version, env): def create_target_dependency(self, target, name): """ : param target : PXBNativeTarget """ proxy = PBXContainerItemProxy(self, target, name) - dependecy = PBXTargetDependency(target, proxy) - return dependecy + dependency = PBXTargetDependency(target, proxy) + return dependency def write(self, file): From ac12f5123a134660c5d141517680ea9a02b22913 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 29 Jul 2018 11:16:16 +0200 Subject: [PATCH 014/315] Add a new task semaphore system --- playground/task_semaphore/wscript | 44 ++++++++++++++++++++++ waflib/Runner.py | 41 +++++++++++++++------ waflib/Task.py | 61 +++++++++++++++++++++++++++++-- 3 files changed, 131 insertions(+), 15 deletions(-) create mode 100644 playground/task_semaphore/wscript diff --git a/playground/task_semaphore/wscript b/playground/task_semaphore/wscript new file mode 100644 index 0000000000..cd11486ebf --- /dev/null +++ b/playground/task_semaphore/wscript @@ -0,0 +1,44 @@ +#! /usr/bin/env python + +""" +Task semaphore demo. Compare the runtimes: + + waf configure build --fast # 0m08 + waf configure build # 1m15 +""" + +import random, time +from waflib import Task, TaskGen, Utils + +def options(opt): + opt.add_option('--fast', action='store_true', default=False, help='Disable the semaphore to compare the runtime', dest='fast') + +def configure(conf): + pass + +def build(bld): + # max 20 jobs globally + bld.jobs = 20 + + bld(features='make_100') + + class Foo(Task.Task): + always_run = True + + if not bld.options.fast: + semaphore = Task.TaskSemaphore(2) # 2 jobs maximum + + def uid(self): + # unique id for each object + return Utils.h_list(self.num) + + def run(self): + time.sleep(random.randint(1000, 2000) / 1000.) + print("Task %r" % self.num) + + @TaskGen.feature('make_100') + def make_100_bound_tasks(self): + for x in range(100): + tsk = self.create_task('Foo') + tsk.num = x + diff --git a/waflib/Runner.py b/waflib/Runner.py index 975c32922f..261084d274 100644 --- a/waflib/Runner.py +++ b/waflib/Runner.py @@ -329,6 +329,14 @@ def try_unfreeze(x): try_unfreeze(x) del self.revdeps[tsk] + if hasattr(tsk, 'semaphore'): + sem = tsk.semaphore + sem.release(tsk) + while sem.waiting and not sem.is_locked(): + # take a frozen task, make it ready to run + x = sem.waiting.pop() + self._add_task(x) + def get_out(self): """ Waits for a Task that task consumers add to :py:attr:`waflib.Runner.Parallel.out` after execution. @@ -352,8 +360,29 @@ def add_task(self, tsk): :param tsk: task instance :type tsk: :py:attr:`waflib.Task.Task` """ + # TODO change in waf 2.1 self.ready.put(tsk) + def _add_task(self, tsk): + if hasattr(tsk, 'semaphore'): + sem = tsk.semaphore + try: + sem.acquire(tsk) + except IndexError: + sem.waiting.add(tsk) + return + + self.count += 1 + self.processed += 1 + if self.numjobs == 1: + tsk.log_display(tsk.generator.bld) + try: + self.process_task(tsk) + finally: + self.out.put(tsk) + else: + self.add_task(tsk) + def process_task(self, tsk): """ Processes a task and attempts to stop the build in case of errors @@ -453,17 +482,7 @@ def start(self): st = self.task_status(tsk) if st == Task.RUN_ME: - self.count += 1 - self.processed += 1 - - if self.numjobs == 1: - tsk.log_display(tsk.generator.bld) - try: - self.process_task(tsk) - finally: - self.out.put(tsk) - else: - self.add_task(tsk) + self._add_task(tsk) elif st == Task.ASK_LATER: self.postpone(tsk) elif st == Task.SKIP_ME: diff --git a/waflib/Task.py b/waflib/Task.py index 3e07ebfbb7..b0b8cac6f8 100644 --- a/waflib/Task.py +++ b/waflib/Task.py @@ -133,10 +133,12 @@ def __init__(cls, name, bases, dict): class Task(evil): """ - This class deals with the filesystem (:py:class:`waflib.Node.Node`). The method :py:class:`waflib.Task.Task.runnable_status` - uses a hash value (from :py:class:`waflib.Task.Task.signature`) which is persistent from build to build. When the value changes, - the task has to be executed. The method :py:class:`waflib.Task.Task.post_run` will assign the task signature to the output - nodes (if present). + Task objects represents actions to perform such as commands to execute by calling the `run` method. + + Detecting when to execute a task occurs in the method :py:meth:`waflib.Task.Task.runnable_status`. + + Detecting which tasks to execute is performed through a hash value returned by + :py:meth:`waflib.Task.Task.signature`. The task signature is persistent from build to build. """ vars = [] """ConfigSet variables that should trigger a rebuild (class attribute used for :py:meth:`waflib.Task.Task.sig_vars`)""" @@ -1354,3 +1356,54 @@ def sig_explicit_deps(self): TaskBase = Task "Provided for compatibility reasons, TaskBase should not be used" +class TaskSemaphore(object): + """ + Task semaphores provide a simple and efficient way of throttling the amount of + a particular task to run concurrently. The throttling value is capped + by the amount of maximum jobs, so for example, a `TaskSemaphore(10)` + has no effect in a `-j2` build. + + Task semaphores are typically specified on the task class level:: + + class compile(waflib.Task.Task): + semaphore = waflib.Task.TaskSemaphore(2) + run_str = 'touch ${TGT}' + + Task semaphores are meant to be used by the build scheduler in the main + thread, so there are no guarantees of thread safety. + """ + def __init__(self, num): + """ + :param num: maximum value of concurrent tasks + :type num: int + """ + self.num = num + self.locking = set() + self.waiting = set() + + def is_locked(self): + """Returns True if this semaphore cannot be acquired by more tasks""" + return len(self.locking) >= self.num + + def acquire(self, tsk): + """ + Mark the semaphore as used by the given task (not re-entrant). + + :param tsk: task object + :type tsk: :py:class:`waflib.Task.Task` + :raises: :py:class:`IndexError` in case the resource is already acquired + """ + if self.is_locked(): + raise IndexError('Cannot lock more %r' % self.locking) + self.locking.add(tsk) + + def release(self, tsk): + """ + Mark the semaphore as unused by the given task. + + :param tsk: task object + :type tsk: :py:class:`waflib.Task.Task` + :raises: :py:class:`KeyError` in case the resource is not acquired by the task + """ + self.locking.remove(tsk) + From 907c273adf2f4f2a4b069a4d6d3bf29bcb3aadc6 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 29 Jul 2018 13:18:40 +0200 Subject: [PATCH 015/315] Rework 3e06a0b9a2e03b15aa476572a89e3cca7fa7198a --- waflib/Scripting.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/waflib/Scripting.py b/waflib/Scripting.py index df99b5444e..749d4f2e62 100644 --- a/waflib/Scripting.py +++ b/waflib/Scripting.py @@ -34,7 +34,7 @@ def waf_entry_point(current_directory, version, wafdir): # Store current directory before any chdir Context.waf_dir = wafdir - Context.launch_dir = current_directory + Context.run_dir = Context.launch_dir = current_directory start_dir = current_directory no_climb = os.environ.get('NOCLIMB') @@ -122,7 +122,8 @@ def waf_entry_point(current_directory, version, wafdir): if no_climb: break - if not Context.run_dir: + wscript = os.path.normpath(os.path.join(Context.run_dir, Context.WSCRIPT_FILE)) + if not os.path.exists(wscript): if options.whelp: Logs.warn('These are the generic options (no wscript/project found)') ctx.parser.print_help() @@ -137,7 +138,7 @@ def waf_entry_point(current_directory, version, wafdir): sys.exit(1) try: - set_main_module(os.path.normpath(os.path.join(Context.run_dir, Context.WSCRIPT_FILE))) + set_main_module(wscript) except Errors.WafError as e: Logs.pprint('RED', e.verbose_msg) Logs.error(str(e)) From 1bbd5978e364a8328724a360e3b31e3c8280aca8 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 29 Jul 2018 13:24:16 +0200 Subject: [PATCH 016/315] waf-2.0.10 --- ChangeLog | 6 ++++++ waf-light | 2 +- waflib/Context.py | 6 +++--- wscript | 2 +- 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8001b4f38f..d22c2edf51 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +NEW IN WAF 2.0.10 +----------------- +* Add a task semaphore system +* Fix --help when no wscript is supplied #2184 +* Fix Fortran processing with generated Fortran files + NEW IN WAF 2.0.9 ---------------- * Add dependencies on scriptlet outputs diff --git a/waf-light b/waf-light index d895b5be85..3836c9e483 100755 --- a/waf-light +++ b/waf-light @@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. import os, sys, inspect -VERSION="2.0.9" +VERSION="2.0.10" REVISION="x" GIT="x" INSTALL="x" diff --git a/waflib/Context.py b/waflib/Context.py index 6271550532..aeb651ca19 100644 --- a/waflib/Context.py +++ b/waflib/Context.py @@ -11,13 +11,13 @@ import waflib.Node # the following 3 constants are updated on each new release (do not touch) -HEXVERSION=0x2000900 +HEXVERSION=0x2000a00 """Constant updated on new releases""" -WAFVERSION="2.0.9" +WAFVERSION="2.0.10" """Constant updated on new releases""" -WAFREVISION="8a950e7bca9a3a9b1ae62aae039ef76e2adc4177" +WAFREVISION="31a5fa38292b9bd9fd3283ce5b1b401662e19a10" """Git revision when the waf version is updated""" ABI = 20 diff --git a/wscript b/wscript index e3567ef179..66e9b9580b 100644 --- a/wscript +++ b/wscript @@ -11,7 +11,7 @@ To add a tool that does not exist in the folder compat15, pass an absolute path: from __future__ import with_statement -VERSION="2.0.9" +VERSION="2.0.10" APPNAME='waf' REVISION='' From 8ac231d9534d4392f4492840581848fbb09fb025 Mon Sep 17 00:00:00 2001 From: Daniel Bartel Date: Fri, 10 Aug 2018 23:49:52 +0200 Subject: [PATCH 017/315] spawn a subprocess for cpplint to avoid threading issue --- waflib/extras/cpplint.py | 71 ++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 42 deletions(-) diff --git a/waflib/extras/cpplint.py b/waflib/extras/cpplint.py index fc914c2450..e3302e5bcf 100644 --- a/waflib/extras/cpplint.py +++ b/waflib/extras/cpplint.py @@ -38,15 +38,7 @@ def build(bld): from __future__ import absolute_import import sys, re import logging -import threading -from waflib import Task, TaskGen, Logs, Options, Node -try: - import cpplint.cpplint as cpplint_tool -except ImportError: - try: - import cpplint as cpplint_tool - except ImportError: - pass +from waflib import Errors, Task, TaskGen, Logs, Options, Node, Utils critical_errors = 0 @@ -58,6 +50,13 @@ def build(bld): 'vs7': re.compile('(?P.*)\((?P\d+)\): (?P.*) \[(?P.*)\] \[(?P\d+)\]'), 'eclipse': re.compile('(?P.*):(?P\d+): warning: (?P.*) \[(?P.*)\] \[(?P\d+)\]'), } +CPPLINT_STR = ('${CPPLINT} ' + '--verbose=${CPPLINT_LEVEL} ' + '--output=${CPPLINT_OUTPUT} ' + '--filter=${CPPLINT_FILTERS} ' + '--root=${CPPLINT_ROOT} ' + '--linelength=${CPPLINT_LINE_LENGTH} ') + def options(opt): opt.add_option('--cpplint-filters', type='string', @@ -71,24 +70,21 @@ def options(opt): opt.add_option('--cpplint-break', default=5, type='int', dest='CPPLINT_BREAK', help='break the build if error >= level (default: 5)') opt.add_option('--cpplint-root', type='string', - default=None, dest='CPPLINT_ROOT', + default='', dest='CPPLINT_ROOT', help='root directory used to derive header guard') opt.add_option('--cpplint-skip', action='store_true', default=False, dest='CPPLINT_SKIP', help='skip cpplint during build') opt.add_option('--cpplint-output', type='string', default='waf', dest='CPPLINT_OUTPUT', - help='select output format (waf, emacs, vs7)') + help='select output format (waf, emacs, vs7, eclipse)') def configure(conf): - conf.start_msg('Checking cpplint') try: - cpplint_tool._cpplint_state - conf.end_msg('ok') - except NameError: + conf.find_program('cpplint', var='CPPLINT') + except Errors.ConfigurationError: conf.env.CPPLINT_SKIP = True - conf.end_msg('not found, skipping it.') class cpplint_formatter(Logs.formatter, object): @@ -117,34 +113,22 @@ def emit(self, rec): class cpplint_wrapper(object): - stream = None - tasks_count = 0 - lock = threading.RLock() - def __init__(self, logger, threshold, fmt): self.logger = logger self.threshold = threshold - self.error_count = 0 self.fmt = fmt def __enter__(self): - with cpplint_wrapper.lock: - cpplint_wrapper.tasks_count += 1 - if cpplint_wrapper.tasks_count == 1: - sys.stderr.flush() - cpplint_wrapper.stream = sys.stderr - sys.stderr = self - return self + return self def __exit__(self, exc_type, exc_value, traceback): - with cpplint_wrapper.lock: - cpplint_wrapper.tasks_count -= 1 - if cpplint_wrapper.tasks_count == 0: - sys.stderr = cpplint_wrapper.stream - sys.stderr.flush() - - def isatty(self): - return True + if isinstance(exc_value, Utils.subprocess.CalledProcessError): + messages = [m for m in exc_value.output.splitlines() + if 'Done processing' not in m + and 'Total errors found' not in m] + for message in messages: + self.write(message) + return True def write(self, message): global critical_errors @@ -184,12 +168,15 @@ def __init__(self, *k, **kw): def run(self): global critical_errors with cpplint_wrapper(get_cpplint_logger(self.env.CPPLINT_OUTPUT), self.env.CPPLINT_BREAK, self.env.CPPLINT_OUTPUT): - if self.env.CPPLINT_OUTPUT != 'waf': - cpplint_tool._SetOutputFormat(self.env.CPPLINT_OUTPUT) - cpplint_tool._SetFilters(self.env.CPPLINT_FILTERS) - cpplint_tool._line_length = self.env.CPPLINT_LINE_LENGTH - cpplint_tool._root = self.env.CPPLINT_ROOT - cpplint_tool.ProcessFile(self.inputs[0].abspath(), self.env.CPPLINT_LEVEL) + params = {key: str(self.env[key]) for key in self.env if 'CPPLINT_' in key} + if params['CPPLINT_OUTPUT'] is 'waf': + params['CPPLINT_OUTPUT'] = 'emacs' + params['CPPLINT'] = self.env.get_flat('CPPLINT') + cmd = Utils.subst_vars(CPPLINT_STR, params) + env = self.env.env or None + Utils.subprocess.check_output(cmd + self.inputs[0].abspath(), + stderr=Utils.subprocess.STDOUT, + env=env, shell=True) return critical_errors @TaskGen.extension('.h', '.hh', '.hpp', '.hxx') From 38fced6995ced4cd140e23d9342c80c341a6c9cf Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Thu, 16 Aug 2018 23:30:05 +0200 Subject: [PATCH 018/315] docs --- TODO | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/TODO b/TODO index 656f8ab5d7..1392725b80 100644 --- a/TODO +++ b/TODO @@ -4,7 +4,9 @@ Waf 2.1 - Remove Winphone/WinCE detection in msvc.py - Fix the circular imports ccroot<->c_config.py - Remove superfluous *k in ctx.load() and other unused parameters -- Ensure conf.load() has the same interface as ctx.load() + Ensure conf.load() has the same interface as ctx.load() - Remove waflib.Runner.PriorityTasks.appendleft - Remove waflib.Task.TaskBase - Remove the upper class of waflib.Task.Task (metaclasses) +- Ordered_iter_dict in python 3.7 +- Change _add_task to add_task in Runner.py From 6d5199fa84a66fd441a972f9e919c62d18207a4b Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Thu, 16 Aug 2018 23:30:17 +0200 Subject: [PATCH 019/315] Disable warnings on versioned library installation --- waflib/Tools/ccroot.py | 1 + 1 file changed, 1 insertion(+) diff --git a/waflib/Tools/ccroot.py b/waflib/Tools/ccroot.py index a90fdd8ffc..cfef8bf51f 100644 --- a/waflib/Tools/ccroot.py +++ b/waflib/Tools/ccroot.py @@ -600,6 +600,7 @@ def build(bld): if getattr(self, 'install_task', None): self.install_task.hasrun = Task.SKIPPED + self.install_task.no_errcheck_out = True path = self.install_task.install_to if self.env.DEST_OS == 'openbsd': libname = self.link_task.outputs[0].name From 999a9435d6d8358c4a8f9bb8545d233653a02067 Mon Sep 17 00:00:00 2001 From: mmooij Date: Tue, 21 Aug 2018 17:52:09 +0200 Subject: [PATCH 020/315] Check if sources/include are Nonde3 type --- waflib/extras/cppcheck.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/waflib/extras/cppcheck.py b/waflib/extras/cppcheck.py index 43dc544df7..13ff42477f 100644 --- a/waflib/extras/cppcheck.py +++ b/waflib/extras/cppcheck.py @@ -205,11 +205,17 @@ def _tgen_create_cmd(self): args.append('--enable=%s' % lib_enable) for src in self.to_list(getattr(self, 'source', [])): - args.append('%r' % src) + if not isinstance(src, str): + src = repr(src) + args.append(src) for inc in self.to_incnodes(self.to_list(getattr(self, 'includes', []))): - args.append('-I%r' % inc) + if not isinstance(inc, str): + inc = repr(inc) + args.append('-I%s' % inc) for inc in self.to_incnodes(self.to_list(self.env.INCLUDES)): - args.append('-I%r' % inc) + if not isinstance(inc, str): + inc = repr(inc) + args.append('-I%s' % inc) return cmd + args From 962246418f0c88ea09a0e48535cd696d64721ba7 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Fri, 24 Aug 2018 22:40:23 +0200 Subject: [PATCH 021/315] Fix #2191 --- waflib/Build.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/waflib/Build.py b/waflib/Build.py index 4249beee21..a84e41859a 100644 --- a/waflib/Build.py +++ b/waflib/Build.py @@ -758,14 +758,31 @@ def tgpost(tg): elif not ln.is_child_of(self.srcnode): Logs.warn('CWD %s is not under %s, forcing --targets=* (run distclean?)', ln.abspath(), self.srcnode.abspath()) ln = self.srcnode - for tg in self.groups[self.current_group]: + + def is_post(tg, ln): try: p = tg.path except AttributeError: pass else: if p.is_child_of(ln): - tgpost(tg) + return True + + def is_post_group(): + for i, g in enumerate(self.groups): + if i > self.current_group: + for tg in g: + if is_post(tg, ln): + return True + + if self.post_mode == POST_LAZY and ln != self.srcnode: + # partial folder builds require all targets from a previous build group + if is_post_group(): + ln = self.srcnode + + for tg in self.groups[self.current_group]: + if is_post(tg, ln): + tgpost(tg) def get_tasks_group(self, idx): """ From ff2db00805f39733163ac7995dbaa2e971737212 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Tue, 28 Aug 2018 23:36:09 +0200 Subject: [PATCH 022/315] Do not raise an exception on check_cfg/mandatory=False/-vv #2193 --- waflib/Tools/c_config.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/waflib/Tools/c_config.py b/waflib/Tools/c_config.py index 41b53ae7b2..73320a1459 100644 --- a/waflib/Tools/c_config.py +++ b/waflib/Tools/c_config.py @@ -358,13 +358,12 @@ def configure(conf): ret = None try: ret = self.exec_cfg(kw) - except self.errors.WafError: + except self.errors.WafError as e: if 'errmsg' in kw: self.end_msg(kw['errmsg'], 'YELLOW', **kw) if Logs.verbose > 1: - raise - else: - self.fatal('The configuration failed') + self.to_log('Command failure: %s' % e) + self.fatal('The configuration failed') else: if not ret: ret = True From c17da139299fcb1c609e7f724c07a2c8d151f84c Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 2 Sep 2018 02:35:57 +0200 Subject: [PATCH 023/315] waf-2.0.11 --- ChangeLog | 7 +++++++ waf-light | 2 +- waflib/Context.py | 6 +++--- wscript | 2 +- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index d22c2edf51..713bb8fabf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +NEW IN WAF 2.0.11 +----------------- +* Do not raise an exception on check_cfg/mandatory=False/-vv #2193 +* Post past task generators in lazy sub-folder builds #2191 +* Disable warnings on versioned library installation +* Fix cpplint concurrent execution problems + NEW IN WAF 2.0.10 ----------------- * Add a task semaphore system diff --git a/waf-light b/waf-light index 3836c9e483..204bf2fdde 100755 --- a/waf-light +++ b/waf-light @@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. import os, sys, inspect -VERSION="2.0.10" +VERSION="2.0.11" REVISION="x" GIT="x" INSTALL="x" diff --git a/waflib/Context.py b/waflib/Context.py index aeb651ca19..bb47c92193 100644 --- a/waflib/Context.py +++ b/waflib/Context.py @@ -11,13 +11,13 @@ import waflib.Node # the following 3 constants are updated on each new release (do not touch) -HEXVERSION=0x2000a00 +HEXVERSION=0x2000b00 """Constant updated on new releases""" -WAFVERSION="2.0.10" +WAFVERSION="2.0.11" """Constant updated on new releases""" -WAFREVISION="31a5fa38292b9bd9fd3283ce5b1b401662e19a10" +WAFREVISION="a97f6fb0941091b4966b625f15ec32fa783a8bec" """Git revision when the waf version is updated""" ABI = 20 diff --git a/wscript b/wscript index 66e9b9580b..ddf0ff8f5f 100644 --- a/wscript +++ b/wscript @@ -11,7 +11,7 @@ To add a tool that does not exist in the folder compat15, pass an absolute path: from __future__ import with_statement -VERSION="2.0.10" +VERSION="2.0.11" APPNAME='waf' REVISION='' From 84b769a5497c916ea19961ee48f14824161b686e Mon Sep 17 00:00:00 2001 From: jadoro Date: Mon, 24 Sep 2018 10:05:28 +0000 Subject: [PATCH 024/315] Interpret relative install paths relative to PREFIX --- waflib/Build.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/waflib/Build.py b/waflib/Build.py index a84e41859a..7a64bf80ec 100644 --- a/waflib/Build.py +++ b/waflib/Build.py @@ -1054,6 +1054,8 @@ def post_run(self): def get_install_path(self, destdir=True): """ Returns the destination path where files will be installed, pre-pending `destdir`. + + Relative paths will be interpreted relative to `PREFIX` if no `destdir` is given. :rtype: string """ @@ -1061,6 +1063,8 @@ def get_install_path(self, destdir=True): dest = self.install_to.abspath() else: dest = Utils.subst_vars(self.install_to, self.env) + if not os.path.isabs(dest): + dest = os.path.join(self.env.PREFIX, dest) if destdir and Options.options.destdir: dest = os.path.join(Options.options.destdir, os.path.splitdrive(dest)[1].lstrip(os.sep)) return dest From 6db2edba7bad96fe4c19bec23ea9d13da7c08834 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Tue, 25 Sep 2018 18:05:10 +0200 Subject: [PATCH 025/315] Add tests for #2184 --- tests/install/wscript | 75 +++++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 28 deletions(-) diff --git a/tests/install/wscript b/tests/install/wscript index 718f796dc1..826d0ad469 100644 --- a/tests/install/wscript +++ b/tests/install/wscript @@ -4,7 +4,10 @@ # import os -from waflib import TaskGen, Build, Utils +from waflib import Build, Options, TaskGen, Utils + +def build(bld): + bld.fatal("Not implemented! Run 'waf configure'") @TaskGen.feature('ruler') @TaskGen.before('process_rule') @@ -21,13 +24,14 @@ def test(self): def configure(conf): - tmpdir = conf.bldnode.make_node('tmpdir') - tmpdir.delete(evict=False) + tmpdir_top = conf.bldnode.make_node('tmpdir') + tmpdir_top.delete(evict=False) + tmpdir = tmpdir_top.make_node('foo') def build(bld): bld.is_install = env.INSTALL bld.path.make_node('tmpfile').write('test') - bld.env.PREFIX = tmpdir.abspath() + bld.install_as('${PREFIX}/bin/foo', 'tmpfile', chmod=Utils.O755) bld.symlink_as('${PREFIX}/bin/bar', '../tmpfile') tsk = bld.install_files('${PREFIX}/bin', 'tmpfile', chmod=Utils.O755, name='cheese') @@ -43,30 +47,45 @@ def configure(conf): bld(features='subst', source='tmpfile', target='blah/blah/rel3', is_copy=True) bld.install_files('${PREFIX}', 'blah/blah/rel3', relative_base=bld.path.search_node('blah').get_bld(), relative_trick=True) + bld(features='subst', source='tmpfile', target='blah/blah/rel4', is_copy=True) + bld.install_files('lib', 'blah/blah/rel4') + + def check(env): + tmpdir_top.delete(evict=False) + + env.INSTALL = Build.INSTALL + conf.run_build(build_fun=build, msg='building', okmsg='ok', errmsg='eh', env=env) + + assert tmpdir.exists() + assert tmpdir.make_node('bin/foo').exists() + assert tmpdir.make_node('bin/tmpfile').exists() + assert tmpdir.make_node('bin/foo').read() == tmpdir.make_node('bin/tmpfile').read() + assert os.path.lexists(tmpdir.make_node('bin/bar').abspath()) + assert os.readlink(tmpdir.make_node('bin/bar').abspath()) == '../tmpfile' + assert tmpdir.make_node('rel1').exists() + assert tmpdir.make_node('blah/blah/rel2').exists() + assert tmpdir.make_node('blah/rel3').exists() + assert tmpdir.make_node('lib/rel4').exists() + + env.INSTALL = Build.UNINSTALL + conf.run_build(build_fun=build, msg='building', okmsg='ok', errmsg='eh', env=env) + assert not tmpdir.exists() + assert not tmpdir.make_node('bin/foo').exists() + assert not tmpdir.make_node('bin/tmpfile').exists() + assert not os.path.lexists(tmpdir.make_node('bin/bar').abspath()) + assert not tmpdir.exists() + assert not tmpdir.make_node('rel1').exists() + assert not tmpdir.make_node('blah/blah/rel2').exists() + assert not tmpdir.make_node('blah/rel3').exists() + env = conf.env.derive() - env.INSTALL = Build.INSTALL - conf.run_build(build_fun=build, msg='building', okmsg='ok', errmsg='eh', env=env) - assert tmpdir.exists() - assert tmpdir.make_node('bin/foo').exists() - assert tmpdir.make_node('bin/tmpfile').exists() - assert tmpdir.make_node('bin/foo').read() == tmpdir.make_node('bin/tmpfile').read() - assert os.path.lexists(tmpdir.make_node('bin/bar').abspath()) - assert os.readlink(tmpdir.make_node('bin/bar').abspath()) == '../tmpfile' - assert tmpdir.make_node('rel1').exists() - assert tmpdir.make_node('blah/blah/rel2').exists() - assert tmpdir.make_node('blah/rel3').exists() - - env.INSTALL = Build.UNINSTALL - conf.run_build(build_fun=build, msg='building', okmsg='ok', errmsg='eh', env=env) - assert not tmpdir.exists() - assert not tmpdir.make_node('bin/foo').exists() - assert not tmpdir.make_node('bin/tmpfile').exists() - assert not os.path.lexists(tmpdir.make_node('bin/bar').abspath()) - assert not tmpdir.exists() - assert not tmpdir.make_node('rel1').exists() - assert not tmpdir.make_node('blah/blah/rel2').exists() - assert not tmpdir.make_node('blah/rel3').exists() + env.PREFIX = tmpdir.abspath() + Options.options.destdir = None + check(env) + + env = conf.env.derive() + env.PREFIX = '/foo' + Options.options.destdir = tmpdir_top.abspath() + check(env) -def build(bld): - pass From a067ddcf4aac4b27e23ab5402ef5fb66ffcaf620 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Thu, 27 Sep 2018 19:25:11 +0200 Subject: [PATCH 026/315] Remove the exception raised by tests/install/wscript --- tests/install/wscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/install/wscript b/tests/install/wscript index 826d0ad469..8fe81a4529 100644 --- a/tests/install/wscript +++ b/tests/install/wscript @@ -7,7 +7,7 @@ import os from waflib import Build, Options, TaskGen, Utils def build(bld): - bld.fatal("Not implemented! Run 'waf configure'") + pass @TaskGen.feature('ruler') @TaskGen.before('process_rule') From 6b007987e8719eb36a32c5c77bd496af998db4f7 Mon Sep 17 00:00:00 2001 From: Adriano Scoditti Date: Wed, 3 Oct 2018 17:34:08 +0200 Subject: [PATCH 027/315] Update waf_unit_test command logging to be compatible with 'WAF_CMD_FORMAT' --- waflib/Tools/waf_unit_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/Tools/waf_unit_test.py b/waflib/Tools/waf_unit_test.py index a71ed1c090..74d6c0561d 100644 --- a/waflib/Tools/waf_unit_test.py +++ b/waflib/Tools/waf_unit_test.py @@ -205,7 +205,7 @@ def run(self): return self.exec_command(self.ut_exec) def exec_command(self, cmd, **kw): - Logs.debug('runner: %r', cmd) + self.generator.bld.log_command(cmd, kw) if getattr(Options.options, 'dump_test_scripts', False): script_code = SCRIPT_TEMPLATE % { 'python': sys.executable, From 15fb252d6c38c4b073cb3b254cae33482716e1a7 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Wed, 3 Oct 2018 21:28:42 +0200 Subject: [PATCH 028/315] Limit sig_vars calls to super() to fix #2194 --- waflib/Task.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/waflib/Task.py b/waflib/Task.py index b0b8cac6f8..afa35ca12a 100644 --- a/waflib/Task.py +++ b/waflib/Task.py @@ -50,6 +50,9 @@ def f(tsk): bld = gen.bld cwdx = tsk.get_cwd() p = env.get_flat + def to_list(xx): + if isinstance(xx, str): return [xx] + return xx tsk.last_cmd = cmd = \'\'\' %s \'\'\' % s return tsk.exec_command(cmd, cwd=cwdx, env=env.env or None) ''' @@ -77,7 +80,8 @@ def merge(lst1, lst2): COMPILE_TEMPLATE_SIG_VARS = ''' def f(tsk): - super(tsk.__class__, tsk).sig_vars() + sig = tsk.generator.bld.hash_env_vars(tsk.env, tsk.vars) + tsk.m.update(sig) env = tsk.env gen = tsk.generator bld = gen.bld @@ -791,6 +795,8 @@ def sig_vars(self): Used by :py:meth:`waflib.Task.Task.signature`; it hashes :py:attr:`waflib.Task.Task.env` variables/values When overriding this method, and if scriptlet expressions are used, make sure to follow the code in :py:meth:`waflib.Task.Task.compile_sig_vars` to enable dependencies on scriptlet results. + + This method may be replaced on subclasses by the metaclass to force dependencies on scriptlet code. """ sig = self.generator.bld.hash_env_vars(self.env, self.vars) self.m.update(sig) @@ -1208,7 +1214,7 @@ def replc(m): # plain code such as ${tsk.inputs[0].abspath()} call = '%s%s' % (var, code) add_dvar(call) - app('gen.to_list(%s)' % call) + app('to_list(%s)' % call) else: # a plain variable such as # a plain variable like ${AR} app('to_list(env[%r])' % var) From f4c873f7bd8de1cdc0b3a95409bec7528cfe076a Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 7 Oct 2018 20:02:43 +0200 Subject: [PATCH 029/315] waf-2.0.12 --- ChangeLog | 4 ++++ waf-light | 2 +- waflib/Context.py | 6 +++--- wscript | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 713bb8fabf..eef0590a27 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +NEW IN WAF 2.0.12 +----------------- +* Fix broken inheritance task trees #2194 + NEW IN WAF 2.0.11 ----------------- * Do not raise an exception on check_cfg/mandatory=False/-vv #2193 diff --git a/waf-light b/waf-light index 204bf2fdde..a2efc852c7 100755 --- a/waf-light +++ b/waf-light @@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. import os, sys, inspect -VERSION="2.0.11" +VERSION="2.0.12" REVISION="x" GIT="x" INSTALL="x" diff --git a/waflib/Context.py b/waflib/Context.py index bb47c92193..7c6cd9608f 100644 --- a/waflib/Context.py +++ b/waflib/Context.py @@ -11,13 +11,13 @@ import waflib.Node # the following 3 constants are updated on each new release (do not touch) -HEXVERSION=0x2000b00 +HEXVERSION=0x2000c00 """Constant updated on new releases""" -WAFVERSION="2.0.11" +WAFVERSION="2.0.12" """Constant updated on new releases""" -WAFREVISION="a97f6fb0941091b4966b625f15ec32fa783a8bec" +WAFREVISION="54841218840ffa34fddf834680a5a17db69caa12" """Git revision when the waf version is updated""" ABI = 20 diff --git a/wscript b/wscript index ddf0ff8f5f..8ed667a1a0 100644 --- a/wscript +++ b/wscript @@ -11,7 +11,7 @@ To add a tool that does not exist in the folder compat15, pass an absolute path: from __future__ import with_statement -VERSION="2.0.11" +VERSION="2.0.12" APPNAME='waf' REVISION='' From c7fd0bc53651da8bd75570646d6cfff0d154dfaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eric=20M=C3=BCller?= Date: Tue, 23 Oct 2018 12:38:41 +0200 Subject: [PATCH 030/315] Append python-config output only once --- waflib/Tools/python.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/waflib/Tools/python.py b/waflib/Tools/python.py index 25841d03cf..01a2c9aa1c 100644 --- a/waflib/Tools/python.py +++ b/waflib/Tools/python.py @@ -329,6 +329,10 @@ def check_python_headers(conf, features='pyembed pyext'): conf.find_program([''.join(pybin) + '-config', 'python%s-config' % num, 'python-config-%s' % num, 'python%sm-config' % num], var='PYTHON_CONFIG', msg="python-config", mandatory=False) if env.PYTHON_CONFIG: + # check python-config output only once + if conf.env.HAVE_PYTHON_H: + return + # python2.6-config requires 3 runs all_flags = [['--cflags', '--libs', '--ldflags']] if sys.hexversion < 0x2070000: From a17051e4a13dccc5a58c20cb37cc3853cc1bac3e Mon Sep 17 00:00:00 2001 From: Adriano Scoditti Date: Tue, 30 Oct 2018 12:00:48 +0100 Subject: [PATCH 031/315] Removes hard-coded 'c4che' references using 'Build.CACHE_DIR' instead --- waflib/Build.py | 3 ++- waflib/Scripting.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/waflib/Build.py b/waflib/Build.py index 7a64bf80ec..8eb612eb1a 100644 --- a/waflib/Build.py +++ b/waflib/Build.py @@ -1318,7 +1318,8 @@ def build(bld): lst = [] for env in self.all_envs.values(): lst.extend(self.root.find_or_declare(f) for f in env[CFG_FILES]) - for n in self.bldnode.ant_glob('**/*', excl='.lock* *conf_check_*/** config.log c4che/*', quiet=True): + excluded_dirs = '.lock* *conf_check_*/** config.log %s/*' % CACHE_DIR + for n in self.bldnode.ant_glob('**/*', excl=excluded_dirs, quiet=True): if n in lst: continue n.delete() diff --git a/waflib/Scripting.py b/waflib/Scripting.py index 749d4f2e62..3b24866726 100644 --- a/waflib/Scripting.py +++ b/waflib/Scripting.py @@ -280,7 +280,7 @@ def distclean_dir(dirname): pass try: - shutil.rmtree('c4che') + shutil.rmtree(Build.CACHE_DIR) except OSError: pass From 5164cb6de8424959b2facd40ebb4f82e16deb8b6 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Tue, 6 Nov 2018 00:19:41 +0100 Subject: [PATCH 032/315] Find more Swig dependencies - Issue 2206 --- playground/swig/extend/python/include.py | 1 + playground/swig/extend/python/test_swig_waf.i | 1 + waflib/extras/swig.py | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 playground/swig/extend/python/include.py diff --git a/playground/swig/extend/python/include.py b/playground/swig/extend/python/include.py new file mode 100644 index 0000000000..11b15b1a45 --- /dev/null +++ b/playground/swig/extend/python/include.py @@ -0,0 +1 @@ +print("hello") diff --git a/playground/swig/extend/python/test_swig_waf.i b/playground/swig/extend/python/test_swig_waf.i index 8a4291e7ae..41e20e8df8 100644 --- a/playground/swig/extend/python/test_swig_waf.i +++ b/playground/swig/extend/python/test_swig_waf.i @@ -6,3 +6,4 @@ %include "a.h" %module test_swig_waf +%pythoncode "python/include.py" diff --git a/waflib/extras/swig.py b/waflib/extras/swig.py index fd3d6d2c99..a582a69c88 100644 --- a/waflib/extras/swig.py +++ b/waflib/extras/swig.py @@ -20,7 +20,7 @@ re_module = re.compile('%module(?:\s*\(.*\))?\s+(.+)', re.M) re_1 = re.compile(r'^%module.*?\s+([\w]+)\s*?$', re.M) -re_2 = re.compile('[#%]include [<"](.*)[">]', re.M) +re_2 = re.compile('[#%](?:include|import(?:\(module=".*"\))+|python(?:begin|code)) [<"](.*)[">]', re.M) class swig(Task.Task): color = 'BLUE' From 8dde43b187c923ae3939ce7fd07f3ca5741bdcd3 Mon Sep 17 00:00:00 2001 From: Adriano Scoditti Date: Tue, 6 Nov 2018 18:16:18 +0100 Subject: [PATCH 033/315] Restore original launch_dir on autoconfigure to correctly parse cli options --- waflib/Configure.py | 1 + waflib/Scripting.py | 3 +++ 2 files changed, 4 insertions(+) diff --git a/waflib/Configure.py b/waflib/Configure.py index d0a4793a88..8ea1aa568b 100644 --- a/waflib/Configure.py +++ b/waflib/Configure.py @@ -180,6 +180,7 @@ def execute(self): env.hash = self.hash env.files = self.files env.environ = dict(self.environ) + env.launch_dir = Context.launch_dir if not (self.env.NO_LOCK_IN_RUN or env.environ.get('NO_LOCK_IN_RUN') or getattr(Options.options, 'no_lock_in_run')): env.store(os.path.join(Context.run_dir, Options.lockfile)) diff --git a/waflib/Scripting.py b/waflib/Scripting.py index 3b24866726..26d92f165d 100644 --- a/waflib/Scripting.py +++ b/waflib/Scripting.py @@ -598,12 +598,15 @@ def execute(self): cmd = env.config_cmd or 'configure' if Configure.autoconfig == 'clobber': tmp = Options.options.__dict__ + launch_dir_tmp = Context.launch_dir if env.options: Options.options.__dict__ = env.options + Context.launch_dir = env.launch_dir try: run_command(cmd) finally: Options.options.__dict__ = tmp + Context.launch_dir = launch_dir_tmp else: run_command(cmd) run_command(self.cmd) From 8c59d9b1d0a91a5efc1a9e967e61550663cb4175 Mon Sep 17 00:00:00 2001 From: Romain Le Godais Date: Sun, 11 Nov 2018 14:32:22 +0100 Subject: [PATCH 034/315] Fix TaskGen idx attribution when 'path' argument is given. When the 'path' argument was given at TaskGen creation, it was not taken into account for attributing idx (the path of the build context was). This is an issue when creating task generators from a waf tool because their idxs were attributed as if they were in the project root directory, even if another path was specified, which could lead to output files collisions. --- waflib/TaskGen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/TaskGen.py b/waflib/TaskGen.py index a74e6431d8..e328843b5b 100644 --- a/waflib/TaskGen.py +++ b/waflib/TaskGen.py @@ -74,7 +74,7 @@ def __init__(self, *k, **kw): else: self.bld = kw['bld'] self.env = self.bld.env.derive() - self.path = self.bld.path # emulate chdir when reading scripts + self.path = kw.get('path', self.bld.path) # by default, emulate chdir when reading scripts # Provide a unique index per folder # This is part of a measure to prevent output file name collisions From 287a781dda35e84ca511f2b26891a11b1717331a Mon Sep 17 00:00:00 2001 From: Romain Le Godais Date: Thu, 15 Nov 2018 10:22:39 +0100 Subject: [PATCH 035/315] Fix description of `before` and `after` attributes of Task class. Their descriptions were actually the opposite of what they really are. --- waflib/Task.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/waflib/Task.py b/waflib/Task.py index afa35ca12a..882df5cf7b 100644 --- a/waflib/Task.py +++ b/waflib/Task.py @@ -163,10 +163,10 @@ class Task(evil): """File extensions that objects of this task class may create""" before = [] - """List of task class names to execute before instances of this class""" + """The instances of this class are executed before the instances of classes whose names are in this list""" after = [] - """List of task class names to execute after instances of this class""" + """The instances of this class are executed after the instances of classes whose names are in this list""" hcode = Utils.SIG_NIL """String representing an additional hash for the class representation""" From d4efe5798575fec4507fb23be2fdf6cb917ce76a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sun, 18 Nov 2018 01:03:16 +0000 Subject: [PATCH 036/315] Fixes for broken python threading on AIX --- waflib/Configure.py | 1 + waflib/Runner.py | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/waflib/Configure.py b/waflib/Configure.py index 8ea1aa568b..61520b1938 100644 --- a/waflib/Configure.py +++ b/waflib/Configure.py @@ -568,6 +568,7 @@ def options(opt): cls_name = kw.get('run_build_cls') or getattr(self, 'run_build_cls', 'build') self.test_bld = bld = Context.create_context(cls_name, top_dir=dir, out_dir=bdir) + bld.jobs = 1 bld.init_dirs() bld.progress_bar = 0 bld.targets = '*' diff --git a/waflib/Runner.py b/waflib/Runner.py index 261084d274..bdb08d9728 100644 --- a/waflib/Runner.py +++ b/waflib/Runner.py @@ -181,10 +181,11 @@ def __init__(self, bld, j=2): The reverse dependency graph of dependencies obtained from Task.run_after """ - self.spawner = Spawner(self) - """ - Coordinating daemon thread that spawns thread consumers - """ + if self.numjobs > 1: + self.spawner = Spawner(self) + """ + Coordinating daemon thread that spawns thread consumers + """ def get_next_task(self): """ From 96d6a06f336c874961a31c1b0092da4b807f6287 Mon Sep 17 00:00:00 2001 From: Romain Le Godais Date: Sat, 17 Nov 2018 15:24:07 +0100 Subject: [PATCH 037/315] Configure: Fix bug when build directory creation fails. Seen thanks to pylint. --- waflib/Configure.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/Configure.py b/waflib/Configure.py index 61520b1938..b5773715ef 100644 --- a/waflib/Configure.py +++ b/waflib/Configure.py @@ -125,7 +125,7 @@ def init_dirs(self): self.bldnode.mkdir() if not os.path.isdir(self.bldnode.abspath()): - conf.fatal('Could not create the build directory %s' % self.bldnode.abspath()) + self.fatal('Could not create the build directory %s' % self.bldnode.abspath()) def execute(self): """ From 32bc5ac13084b95e853913f3116c352fcf3a52f4 Mon Sep 17 00:00:00 2001 From: Romain Le Godais Date: Sun, 18 Nov 2018 10:31:34 +0100 Subject: [PATCH 038/315] cython: Enhance import regexp. * avoid matching commented imports * support `from foo.bar import baz` syntax. --- waflib/extras/cython.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/waflib/extras/cython.py b/waflib/extras/cython.py index 481d6f4c34..db1f8f9c13 100644 --- a/waflib/extras/cython.py +++ b/waflib/extras/cython.py @@ -8,8 +8,9 @@ cy_api_pat = re.compile(r'\s*?cdef\s*?(public|api)\w*') re_cyt = re.compile(r""" - (?:from\s+(\w+)\s+)? # optionally match "from foo" and capture foo - c?import\s(\w+|[*]) # require "import bar" and capture bar + ^\s* # must begin with some whitespace characters + (?:from\s+(\w+)(?:\.\w+)*\s+)? # optionally match "from foo(.baz)" and capture foo + c?import\s(\w+|[*]) # require "import bar" and capture bar """, re.M | re.VERBOSE) @extension('.pyx') From 1f1f3a0a0b69b14ff8357bbc22bc26ae310e9367 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 18 Nov 2018 11:52:34 +0100 Subject: [PATCH 039/315] Always define the attribute "spawner" a2105efc6f6c2bdd3f0ed2d3cd783de2247dd0cf --- waflib/Runner.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/waflib/Runner.py b/waflib/Runner.py index bdb08d9728..e62cc5adf0 100644 --- a/waflib/Runner.py +++ b/waflib/Runner.py @@ -181,11 +181,12 @@ def __init__(self, bld, j=2): The reverse dependency graph of dependencies obtained from Task.run_after """ + self.spawner = None + """ + Coordinating daemon thread that spawns thread consumers + """ if self.numjobs > 1: self.spawner = Spawner(self) - """ - Coordinating daemon thread that spawns thread consumers - """ def get_next_task(self): """ From a46fca4457c1d7f39a5bfc2448fe2aff1f97926c Mon Sep 17 00:00:00 2001 From: Romain Le Godais Date: Wed, 21 Nov 2018 15:02:58 +0100 Subject: [PATCH 040/315] md5_tstamp: Fix documentation. According to the code, file size is not taken into account to know is the hash should be recomputed. --- waflib/Tools/md5_tstamp.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/waflib/Tools/md5_tstamp.py b/waflib/Tools/md5_tstamp.py index 6428e46024..2a5879251d 100644 --- a/waflib/Tools/md5_tstamp.py +++ b/waflib/Tools/md5_tstamp.py @@ -2,8 +2,7 @@ # encoding: utf-8 """ -Re-calculate md5 hashes of files only when the file times or the file -size have changed. +Re-calculate md5 hashes of files only when the file time have changed. The hashes can also reflect either the file contents (STRONGEST=True) or the file time and file size. From ecb4aef0547d862f32a4021ca31abebb2bdeab6b Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Wed, 21 Nov 2018 22:01:20 +0100 Subject: [PATCH 041/315] Keep running configuration tests with parallel jobs Passing "-j1" to "waf configure" already sets the maximum amount of jobs to 1, so the change in a2105efc6f6c2bdd3f0ed2d3cd783de2247dd0cf is deemed unnecessary. --- waflib/Configure.py | 1 - 1 file changed, 1 deletion(-) diff --git a/waflib/Configure.py b/waflib/Configure.py index b5773715ef..db09c0e3a4 100644 --- a/waflib/Configure.py +++ b/waflib/Configure.py @@ -568,7 +568,6 @@ def options(opt): cls_name = kw.get('run_build_cls') or getattr(self, 'run_build_cls', 'build') self.test_bld = bld = Context.create_context(cls_name, top_dir=dir, out_dir=bdir) - bld.jobs = 1 bld.init_dirs() bld.progress_bar = 0 bld.targets = '*' From 1e0462b0c5db44ff97b6f9bc5fd11bf43f8cd429 Mon Sep 17 00:00:00 2001 From: Romain Le Godais Date: Sun, 18 Nov 2018 10:36:40 +0100 Subject: [PATCH 042/315] cython: use a set for mods instead of a list. There can be multiple imports of the same module in a single file, so avoid evaluating them multiple times. --- waflib/extras/cython.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/waflib/extras/cython.py b/waflib/extras/cython.py index db1f8f9c13..591c274d95 100644 --- a/waflib/extras/cython.py +++ b/waflib/extras/cython.py @@ -86,12 +86,12 @@ def scan(self): node = self.inputs[0] txt = node.read() - mods = [] + mods = set() for m in re_cyt.finditer(txt): if m.group(1): # matches "from foo import bar" - mods.append(m.group(1)) + mods.add(m.group(1)) else: - mods.append(m.group(2)) + mods.add(m.group(2)) Logs.debug('cython: mods %r', mods) incs = getattr(self.generator, 'cython_includes', []) @@ -100,7 +100,7 @@ def scan(self): found = [] missing = [] - for x in mods: + for x in sorted(mods): for y in incs: k = y.find_resource(x + '.pxd') if k: From 2010b3f03ec0012bf340d6a5de3b54230824d65c Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Tue, 27 Nov 2018 07:42:34 +0100 Subject: [PATCH 043/315] Print PriorityTasks contents --- waflib/Runner.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/waflib/Runner.py b/waflib/Runner.py index e62cc5adf0..ae1c027336 100644 --- a/waflib/Runner.py +++ b/waflib/Runner.py @@ -37,6 +37,8 @@ def __len__(self): return len(self.lst) def __iter__(self): return iter(self.lst) + def __str__(self): + return 'PriorityTasks: [%s]' % '\n '.join(str(x) for x in self.lst) def clear(self): self.lst = [] def append(self, task): From 9a1cbacc01212e58b2a89f2e0b48afdef04bdfab Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Tue, 27 Nov 2018 07:54:52 +0100 Subject: [PATCH 044/315] Fix the extra message "Broken revdeps" that may appear on certain build failures --- waflib/Runner.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/waflib/Runner.py b/waflib/Runner.py index ae1c027336..5d27669871 100644 --- a/waflib/Runner.py +++ b/waflib/Runner.py @@ -258,6 +258,8 @@ def refill_task_list(self): self.outstanding.append(x) break else: + if self.stop or self.error: + break raise Errors.WafError('Broken revdeps detected on %r' % self.incomplete) else: tasks = next(self.biter) From 63cc4d2ffb06d5dee7b71f73d15103e1a3696ebb Mon Sep 17 00:00:00 2001 From: Romain Le Godais Date: Mon, 3 Dec 2018 09:41:40 +0100 Subject: [PATCH 045/315] playground/cython: Update cython cache files. The cache was generated with an old cython version (0.15.1). Update it by generating it with a more recent version (0.29). --- playground/cython/cython_cache/src/cy_ctest.c | 2788 +++++++++++---- .../cython/cython_cache/src/cy_cxxtest.cc | 3066 ++++++++++++----- .../cython/cython_cache/src/cy_cxxtest.h | 11 +- .../cython/cython_cache/src/cy_cxxtest_api.h | 47 +- 4 files changed, 4265 insertions(+), 1647 deletions(-) diff --git a/playground/cython/cython_cache/src/cy_ctest.c b/playground/cython/cython_cache/src/cy_ctest.c index 58fae2a72d..3a8930b664 100644 --- a/playground/cython/cython_cache/src/cy_ctest.c +++ b/playground/cython/cython_cache/src/cy_ctest.c @@ -1,16 +1,19 @@ -/* Generated by Cython 0.15.1 on Tue May 29 23:42:45 2012 */ +/* Generated by Cython 0.29 */ #define PY_SSIZE_T_CLEAN #include "Python.h" #ifndef Py_PYTHON_H #error Python headers needed to compile C extensions, please install development version of Python. +#elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000) + #error Cython requires Python 2.6+ or Python 3.3+. #else - -#include /* For offsetof */ +#define CYTHON_ABI "0_29" +#define CYTHON_HEX_VERSION 0x001D00F0 +#define CYTHON_FUTURE_DIVISION 0 +#include #ifndef offsetof -#define offsetof(type, member) ( (size_t) & ((type*)0) -> member ) + #define offsetof(type, member) ( (size_t) & ((type*)0) -> member ) #endif - #if !defined(WIN32) && !defined(MS_WINDOWS) #ifndef __stdcall #define __stdcall @@ -22,122 +25,494 @@ #define __fastcall #endif #endif - #ifndef DL_IMPORT #define DL_IMPORT(t) t #endif #ifndef DL_EXPORT #define DL_EXPORT(t) t #endif - +#define __PYX_COMMA , +#ifndef HAVE_LONG_LONG + #if PY_VERSION_HEX >= 0x02070000 + #define HAVE_LONG_LONG + #endif +#endif #ifndef PY_LONG_LONG #define PY_LONG_LONG LONG_LONG #endif - -#if PY_VERSION_HEX < 0x02040000 - #define METH_COEXIST 0 - #define PyDict_CheckExact(op) (Py_TYPE(op) == &PyDict_Type) - #define PyDict_Contains(d,o) PySequence_Contains(d,o) +#ifndef Py_HUGE_VAL + #define Py_HUGE_VAL HUGE_VAL #endif - -#if PY_VERSION_HEX < 0x02050000 - typedef int Py_ssize_t; - #define PY_SSIZE_T_MAX INT_MAX - #define PY_SSIZE_T_MIN INT_MIN - #define PY_FORMAT_SIZE_T "" - #define PyInt_FromSsize_t(z) PyInt_FromLong(z) - #define PyInt_AsSsize_t(o) __Pyx_PyInt_AsInt(o) - #define PyNumber_Index(o) PyNumber_Int(o) - #define PyIndex_Check(o) PyNumber_Check(o) - #define PyErr_WarnEx(category, message, stacklevel) PyErr_Warn(category, message) +#ifdef PYPY_VERSION + #define CYTHON_COMPILING_IN_PYPY 1 + #define CYTHON_COMPILING_IN_PYSTON 0 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #undef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 0 + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #if PY_VERSION_HEX < 0x03050000 + #undef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 0 + #elif !defined(CYTHON_USE_ASYNC_SLOTS) + #define CYTHON_USE_ASYNC_SLOTS 1 + #endif + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #undef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 0 + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #undef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 1 + #undef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 0 + #undef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 0 + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #undef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 0 + #undef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 0 + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 +#elif defined(PYSTON_VERSION) + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_PYSTON 1 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #ifndef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #endif + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #undef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 0 + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #ifndef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 1 + #endif + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #ifndef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 1 + #endif + #ifndef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 1 + #endif + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #undef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 0 + #undef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 0 + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 +#else + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_PYSTON 0 + #define CYTHON_COMPILING_IN_CPYTHON 1 + #ifndef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #endif + #if PY_VERSION_HEX < 0x02070000 + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #elif !defined(CYTHON_USE_PYTYPE_LOOKUP) + #define CYTHON_USE_PYTYPE_LOOKUP 1 + #endif + #if PY_MAJOR_VERSION < 3 + #undef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 0 + #elif !defined(CYTHON_USE_ASYNC_SLOTS) + #define CYTHON_USE_ASYNC_SLOTS 1 + #endif + #if PY_VERSION_HEX < 0x02070000 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #elif !defined(CYTHON_USE_PYLONG_INTERNALS) + #define CYTHON_USE_PYLONG_INTERNALS 1 + #endif + #ifndef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 1 + #endif + #ifndef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 1 + #endif + #if PY_VERSION_HEX < 0x030300F0 + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #elif !defined(CYTHON_USE_UNICODE_WRITER) + #define CYTHON_USE_UNICODE_WRITER 1 + #endif + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #ifndef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 1 + #endif + #ifndef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 1 + #endif + #ifndef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 1 + #endif + #ifndef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 1 + #endif + #ifndef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT (PY_VERSION_HEX >= 0x03050000) + #endif + #ifndef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE (PY_VERSION_HEX >= 0x030400a1) + #endif + #ifndef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX >= 0x030600B1) + #endif + #ifndef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK (PY_VERSION_HEX >= 0x030700A3) + #endif +#endif +#if !defined(CYTHON_FAST_PYCCALL) +#define CYTHON_FAST_PYCCALL (CYTHON_FAST_PYCALL && PY_VERSION_HEX >= 0x030600B1) +#endif +#if CYTHON_USE_PYLONG_INTERNALS + #include "longintrepr.h" + #undef SHIFT + #undef BASE + #undef MASK +#endif +#ifndef __has_attribute + #define __has_attribute(x) 0 +#endif +#ifndef __has_cpp_attribute + #define __has_cpp_attribute(x) 0 +#endif +#ifndef CYTHON_RESTRICT + #if defined(__GNUC__) + #define CYTHON_RESTRICT __restrict__ + #elif defined(_MSC_VER) && _MSC_VER >= 1400 + #define CYTHON_RESTRICT __restrict + #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define CYTHON_RESTRICT restrict + #else + #define CYTHON_RESTRICT + #endif +#endif +#ifndef CYTHON_UNUSED +# if defined(__GNUC__) +# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +# define CYTHON_UNUSED __attribute__ ((__unused__)) +# else +# define CYTHON_UNUSED +# endif +# elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER)) +# define CYTHON_UNUSED __attribute__ ((__unused__)) +# else +# define CYTHON_UNUSED +# endif +#endif +#ifndef CYTHON_MAYBE_UNUSED_VAR +# if defined(__cplusplus) + template void CYTHON_MAYBE_UNUSED_VAR( const T& ) { } +# else +# define CYTHON_MAYBE_UNUSED_VAR(x) (void)(x) +# endif +#endif +#ifndef CYTHON_NCP_UNUSED +# if CYTHON_COMPILING_IN_CPYTHON +# define CYTHON_NCP_UNUSED +# else +# define CYTHON_NCP_UNUSED CYTHON_UNUSED +# endif +#endif +#define __Pyx_void_to_None(void_result) ((void)(void_result), Py_INCREF(Py_None), Py_None) +#ifdef _MSC_VER + #ifndef _MSC_STDINT_H_ + #if _MSC_VER < 1300 + typedef unsigned char uint8_t; + typedef unsigned int uint32_t; + #else + typedef unsigned __int8 uint8_t; + typedef unsigned __int32 uint32_t; + #endif + #endif +#else + #include +#endif +#ifndef CYTHON_FALLTHROUGH + #if defined(__cplusplus) && __cplusplus >= 201103L + #if __has_cpp_attribute(fallthrough) + #define CYTHON_FALLTHROUGH [[fallthrough]] + #elif __has_cpp_attribute(clang::fallthrough) + #define CYTHON_FALLTHROUGH [[clang::fallthrough]] + #elif __has_cpp_attribute(gnu::fallthrough) + #define CYTHON_FALLTHROUGH [[gnu::fallthrough]] + #endif + #endif + #ifndef CYTHON_FALLTHROUGH + #if __has_attribute(fallthrough) + #define CYTHON_FALLTHROUGH __attribute__((fallthrough)) + #else + #define CYTHON_FALLTHROUGH + #endif + #endif + #if defined(__clang__ ) && defined(__apple_build_version__) + #if __apple_build_version__ < 7000000 + #undef CYTHON_FALLTHROUGH + #define CYTHON_FALLTHROUGH + #endif + #endif #endif -#if PY_VERSION_HEX < 0x02060000 - #define Py_REFCNT(ob) (((PyObject*)(ob))->ob_refcnt) - #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) - #define Py_SIZE(ob) (((PyVarObject*)(ob))->ob_size) - #define PyVarObject_HEAD_INIT(type, size) \ - PyObject_HEAD_INIT(type) size, - #define PyType_Modified(t) - - typedef struct { - void *buf; - PyObject *obj; - Py_ssize_t len; - Py_ssize_t itemsize; - int readonly; - int ndim; - char *format; - Py_ssize_t *shape; - Py_ssize_t *strides; - Py_ssize_t *suboffsets; - void *internal; - } Py_buffer; - - #define PyBUF_SIMPLE 0 - #define PyBUF_WRITABLE 0x0001 - #define PyBUF_FORMAT 0x0004 - #define PyBUF_ND 0x0008 - #define PyBUF_STRIDES (0x0010 | PyBUF_ND) - #define PyBUF_C_CONTIGUOUS (0x0020 | PyBUF_STRIDES) - #define PyBUF_F_CONTIGUOUS (0x0040 | PyBUF_STRIDES) - #define PyBUF_ANY_CONTIGUOUS (0x0080 | PyBUF_STRIDES) - #define PyBUF_INDIRECT (0x0100 | PyBUF_STRIDES) - +#ifndef CYTHON_INLINE + #if defined(__clang__) + #define CYTHON_INLINE __inline__ __attribute__ ((__unused__)) + #elif defined(__GNUC__) + #define CYTHON_INLINE __inline__ + #elif defined(_MSC_VER) + #define CYTHON_INLINE __inline + #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define CYTHON_INLINE inline + #else + #define CYTHON_INLINE + #endif #endif +#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x02070600 && !defined(Py_OptimizeFlag) + #define Py_OptimizeFlag 0 +#endif +#define __PYX_BUILD_PY_SSIZE_T "n" +#define CYTHON_FORMAT_SSIZE_T "z" #if PY_MAJOR_VERSION < 3 #define __Pyx_BUILTIN_MODULE_NAME "__builtin__" + #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ + PyCode_New(a+k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) + #define __Pyx_DefaultClassType PyClass_Type #else #define __Pyx_BUILTIN_MODULE_NAME "builtins" + #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ + PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) + #define __Pyx_DefaultClassType PyType_Type #endif - -#if PY_MAJOR_VERSION >= 3 +#ifndef Py_TPFLAGS_CHECKTYPES #define Py_TPFLAGS_CHECKTYPES 0 +#endif +#ifndef Py_TPFLAGS_HAVE_INDEX #define Py_TPFLAGS_HAVE_INDEX 0 #endif - -#if (PY_VERSION_HEX < 0x02060000) || (PY_MAJOR_VERSION >= 3) +#ifndef Py_TPFLAGS_HAVE_NEWBUFFER #define Py_TPFLAGS_HAVE_NEWBUFFER 0 #endif - +#ifndef Py_TPFLAGS_HAVE_FINALIZE + #define Py_TPFLAGS_HAVE_FINALIZE 0 +#endif +#ifndef METH_STACKLESS + #define METH_STACKLESS 0 +#endif +#if PY_VERSION_HEX <= 0x030700A3 || !defined(METH_FASTCALL) + #ifndef METH_FASTCALL + #define METH_FASTCALL 0x80 + #endif + typedef PyObject *(*__Pyx_PyCFunctionFast) (PyObject *self, PyObject *const *args, Py_ssize_t nargs); + typedef PyObject *(*__Pyx_PyCFunctionFastWithKeywords) (PyObject *self, PyObject *const *args, + Py_ssize_t nargs, PyObject *kwnames); +#else + #define __Pyx_PyCFunctionFast _PyCFunctionFast + #define __Pyx_PyCFunctionFastWithKeywords _PyCFunctionFastWithKeywords +#endif +#if CYTHON_FAST_PYCCALL +#define __Pyx_PyFastCFunction_Check(func)\ + ((PyCFunction_Check(func) && (METH_FASTCALL == (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))))) +#else +#define __Pyx_PyFastCFunction_Check(func) 0 +#endif +#if CYTHON_USE_DICT_VERSIONS +#define __PYX_GET_DICT_VERSION(dict) (((PyDictObject*)(dict))->ma_version_tag) +#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)\ + (version_var) = __PYX_GET_DICT_VERSION(dict);\ + (cache_var) = (value); +#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) {\ + static PY_UINT64_T __pyx_dict_version = 0;\ + static PyObject *__pyx_dict_cached_value = NULL;\ + if (likely(__PYX_GET_DICT_VERSION(DICT) == __pyx_dict_version)) {\ + (VAR) = __pyx_dict_cached_value;\ + } else {\ + (VAR) = __pyx_dict_cached_value = (LOOKUP);\ + __pyx_dict_version = __PYX_GET_DICT_VERSION(DICT);\ + }\ + } +#else +#define __PYX_GET_DICT_VERSION(dict) (0) +#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var) +#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) (VAR) = (LOOKUP); +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc) + #define PyObject_Malloc(s) PyMem_Malloc(s) + #define PyObject_Free(p) PyMem_Free(p) + #define PyObject_Realloc(p) PyMem_Realloc(p) +#endif +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030400A1 + #define PyMem_RawMalloc(n) PyMem_Malloc(n) + #define PyMem_RawRealloc(p, n) PyMem_Realloc(p, n) + #define PyMem_RawFree(p) PyMem_Free(p) +#endif +#if CYTHON_COMPILING_IN_PYSTON + #define __Pyx_PyCode_HasFreeVars(co) PyCode_HasFreeVars(co) + #define __Pyx_PyFrame_SetLineNumber(frame, lineno) PyFrame_SetLineNumber(frame, lineno) +#else + #define __Pyx_PyCode_HasFreeVars(co) (PyCode_GetNumFree(co) > 0) + #define __Pyx_PyFrame_SetLineNumber(frame, lineno) (frame)->f_lineno = (lineno) +#endif +#if !CYTHON_FAST_THREAD_STATE || PY_VERSION_HEX < 0x02070000 + #define __Pyx_PyThreadState_Current PyThreadState_GET() +#elif PY_VERSION_HEX >= 0x03060000 + #define __Pyx_PyThreadState_Current _PyThreadState_UncheckedGet() +#elif PY_VERSION_HEX >= 0x03000000 + #define __Pyx_PyThreadState_Current PyThreadState_GET() +#else + #define __Pyx_PyThreadState_Current _PyThreadState_Current +#endif +#if PY_VERSION_HEX < 0x030700A2 && !defined(PyThread_tss_create) && !defined(Py_tss_NEEDS_INIT) +#include "pythread.h" +#define Py_tss_NEEDS_INIT 0 +typedef int Py_tss_t; +static CYTHON_INLINE int PyThread_tss_create(Py_tss_t *key) { + *key = PyThread_create_key(); + return 0; // PyThread_create_key reports success always +} +static CYTHON_INLINE Py_tss_t * PyThread_tss_alloc(void) { + Py_tss_t *key = (Py_tss_t *)PyObject_Malloc(sizeof(Py_tss_t)); + *key = Py_tss_NEEDS_INIT; + return key; +} +static CYTHON_INLINE void PyThread_tss_free(Py_tss_t *key) { + PyObject_Free(key); +} +static CYTHON_INLINE int PyThread_tss_is_created(Py_tss_t *key) { + return *key != Py_tss_NEEDS_INIT; +} +static CYTHON_INLINE void PyThread_tss_delete(Py_tss_t *key) { + PyThread_delete_key(*key); + *key = Py_tss_NEEDS_INIT; +} +static CYTHON_INLINE int PyThread_tss_set(Py_tss_t *key, void *value) { + return PyThread_set_key_value(*key, value); +} +static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { + return PyThread_get_key_value(*key); +} +#endif // TSS (Thread Specific Storage) API +#if CYTHON_COMPILING_IN_CPYTHON || defined(_PyDict_NewPresized) +#define __Pyx_PyDict_NewPresized(n) ((n <= 8) ? PyDict_New() : _PyDict_NewPresized(n)) +#else +#define __Pyx_PyDict_NewPresized(n) PyDict_New() +#endif +#if PY_MAJOR_VERSION >= 3 || CYTHON_FUTURE_DIVISION + #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) + #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y) +#else + #define __Pyx_PyNumber_Divide(x,y) PyNumber_Divide(x,y) + #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceDivide(x,y) +#endif +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 && CYTHON_USE_UNICODE_INTERNALS +#define __Pyx_PyDict_GetItemStr(dict, name) _PyDict_GetItem_KnownHash(dict, name, ((PyASCIIObject *) name)->hash) +#else +#define __Pyx_PyDict_GetItemStr(dict, name) PyDict_GetItem(dict, name) +#endif +#if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND) + #define CYTHON_PEP393_ENABLED 1 + #define __Pyx_PyUnicode_READY(op) (likely(PyUnicode_IS_READY(op)) ?\ + 0 : _PyUnicode_Ready((PyObject *)(op))) + #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u) + #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i) + #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) PyUnicode_MAX_CHAR_VALUE(u) + #define __Pyx_PyUnicode_KIND(u) PyUnicode_KIND(u) + #define __Pyx_PyUnicode_DATA(u) PyUnicode_DATA(u) + #define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i) + #define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, ch) + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u))) +#else + #define CYTHON_PEP393_ENABLED 0 + #define PyUnicode_1BYTE_KIND 1 + #define PyUnicode_2BYTE_KIND 2 + #define PyUnicode_4BYTE_KIND 4 + #define __Pyx_PyUnicode_READY(op) (0) + #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_SIZE(u) + #define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i])) + #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) ((sizeof(Py_UNICODE) == 2) ? 65535 : 1114111) + #define __Pyx_PyUnicode_KIND(u) (sizeof(Py_UNICODE)) + #define __Pyx_PyUnicode_DATA(u) ((void*)PyUnicode_AS_UNICODE(u)) + #define __Pyx_PyUnicode_READ(k, d, i) ((void)(k), (Py_UCS4)(((Py_UNICODE*)d)[i])) + #define __Pyx_PyUnicode_WRITE(k, d, i, ch) (((void)(k)), ((Py_UNICODE*)d)[i] = ch) + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_SIZE(u)) +#endif +#if CYTHON_COMPILING_IN_PYPY + #define __Pyx_PyUnicode_Concat(a, b) PyNumber_Add(a, b) + #define __Pyx_PyUnicode_ConcatSafe(a, b) PyNumber_Add(a, b) +#else + #define __Pyx_PyUnicode_Concat(a, b) PyUnicode_Concat(a, b) + #define __Pyx_PyUnicode_ConcatSafe(a, b) ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ?\ + PyNumber_Add(a, b) : __Pyx_PyUnicode_Concat(a, b)) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyUnicode_Contains) + #define PyUnicode_Contains(u, s) PySequence_Contains(u, s) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyByteArray_Check) + #define PyByteArray_Check(obj) PyObject_TypeCheck(obj, &PyByteArray_Type) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Format) + #define PyObject_Format(obj, fmt) PyObject_CallMethod(obj, "__format__", "O", fmt) +#endif +#define __Pyx_PyString_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyString_Check(b) && !PyString_CheckExact(b)))) ? PyNumber_Remainder(a, b) : __Pyx_PyString_Format(a, b)) +#define __Pyx_PyUnicode_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyUnicode_Check(b) && !PyUnicode_CheckExact(b)))) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b)) +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyString_Format(a, b) PyUnicode_Format(a, b) +#else + #define __Pyx_PyString_Format(a, b) PyString_Format(a, b) +#endif +#if PY_MAJOR_VERSION < 3 && !defined(PyObject_ASCII) + #define PyObject_ASCII(o) PyObject_Repr(o) +#endif #if PY_MAJOR_VERSION >= 3 #define PyBaseString_Type PyUnicode_Type #define PyStringObject PyUnicodeObject #define PyString_Type PyUnicode_Type #define PyString_Check PyUnicode_Check #define PyString_CheckExact PyUnicode_CheckExact + #define PyObject_Unicode PyObject_Str #endif - -#if PY_VERSION_HEX < 0x02060000 - #define PyBytesObject PyStringObject - #define PyBytes_Type PyString_Type - #define PyBytes_Check PyString_Check - #define PyBytes_CheckExact PyString_CheckExact - #define PyBytes_FromString PyString_FromString - #define PyBytes_FromStringAndSize PyString_FromStringAndSize - #define PyBytes_FromFormat PyString_FromFormat - #define PyBytes_DecodeEscape PyString_DecodeEscape - #define PyBytes_AsString PyString_AsString - #define PyBytes_AsStringAndSize PyString_AsStringAndSize - #define PyBytes_Size PyString_Size - #define PyBytes_AS_STRING PyString_AS_STRING - #define PyBytes_GET_SIZE PyString_GET_SIZE - #define PyBytes_Repr PyString_Repr - #define PyBytes_Concat PyString_Concat - #define PyBytes_ConcatAndDel PyString_ConcatAndDel -#endif - -#if PY_VERSION_HEX < 0x02060000 - #define PySet_Check(obj) PyObject_TypeCheck(obj, &PySet_Type) - #define PyFrozenSet_Check(obj) PyObject_TypeCheck(obj, &PyFrozenSet_Type) +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyBaseString_Check(obj) PyUnicode_Check(obj) + #define __Pyx_PyBaseString_CheckExact(obj) PyUnicode_CheckExact(obj) +#else + #define __Pyx_PyBaseString_Check(obj) (PyString_Check(obj) || PyUnicode_Check(obj)) + #define __Pyx_PyBaseString_CheckExact(obj) (PyString_CheckExact(obj) || PyUnicode_CheckExact(obj)) #endif #ifndef PySet_CheckExact #define PySet_CheckExact(obj) (Py_TYPE(obj) == &PySet_Type) #endif - -#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type) - +#if CYTHON_ASSUME_SAFE_MACROS + #define __Pyx_PySequence_SIZE(seq) Py_SIZE(seq) +#else + #define __Pyx_PySequence_SIZE(seq) PySequence_Size(seq) +#endif #if PY_MAJOR_VERSION >= 3 #define PyIntObject PyLongObject #define PyInt_Type PyLong_Type @@ -153,13 +528,17 @@ #define PyInt_AsSsize_t PyLong_AsSsize_t #define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask + #define PyNumber_Int PyNumber_Long #endif - #if PY_MAJOR_VERSION >= 3 #define PyBoolObject PyLongObject #endif - -#if PY_VERSION_HEX < 0x03020000 +#if PY_MAJOR_VERSION >= 3 && CYTHON_COMPILING_IN_PYPY + #ifndef PyUnicode_InternFromString + #define PyUnicode_InternFromString(s) PyUnicode_FromString(s) + #endif +#endif +#if PY_VERSION_HEX < 0x030200A4 typedef long Py_hash_t; #define __Pyx_PyInt_FromHash_t PyInt_FromLong #define __Pyx_PyInt_AsHash_t PyInt_AsLong @@ -167,57 +546,54 @@ #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t #define __Pyx_PyInt_AsHash_t PyInt_AsSsize_t #endif - - #if PY_MAJOR_VERSION >= 3 - #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) - #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y) + #define __Pyx_PyMethod_New(func, self, klass) ((self) ? PyMethod_New(func, self) : (Py_INCREF(func), func)) #else - #define __Pyx_PyNumber_Divide(x,y) PyNumber_Divide(x,y) - #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceDivide(x,y) + #define __Pyx_PyMethod_New(func, self, klass) PyMethod_New(func, self, klass) #endif - -#if (PY_MAJOR_VERSION < 3) || (PY_VERSION_HEX >= 0x03010300) - #define __Pyx_PySequence_GetSlice(obj, a, b) PySequence_GetSlice(obj, a, b) - #define __Pyx_PySequence_SetSlice(obj, a, b, value) PySequence_SetSlice(obj, a, b, value) - #define __Pyx_PySequence_DelSlice(obj, a, b) PySequence_DelSlice(obj, a, b) +#if CYTHON_USE_ASYNC_SLOTS + #if PY_VERSION_HEX >= 0x030500B1 + #define __Pyx_PyAsyncMethodsStruct PyAsyncMethods + #define __Pyx_PyType_AsAsync(obj) (Py_TYPE(obj)->tp_as_async) + #else + #define __Pyx_PyType_AsAsync(obj) ((__Pyx_PyAsyncMethodsStruct*) (Py_TYPE(obj)->tp_reserved)) + #endif #else - #define __Pyx_PySequence_GetSlice(obj, a, b) (unlikely(!(obj)) ? \ - (PyErr_SetString(PyExc_SystemError, "null argument to internal routine"), (PyObject*)0) : \ - (likely((obj)->ob_type->tp_as_mapping) ? (PySequence_GetSlice(obj, a, b)) : \ - (PyErr_Format(PyExc_TypeError, "'%.200s' object is unsliceable", (obj)->ob_type->tp_name), (PyObject*)0))) - #define __Pyx_PySequence_SetSlice(obj, a, b, value) (unlikely(!(obj)) ? \ - (PyErr_SetString(PyExc_SystemError, "null argument to internal routine"), -1) : \ - (likely((obj)->ob_type->tp_as_mapping) ? (PySequence_SetSlice(obj, a, b, value)) : \ - (PyErr_Format(PyExc_TypeError, "'%.200s' object doesn't support slice assignment", (obj)->ob_type->tp_name), -1))) - #define __Pyx_PySequence_DelSlice(obj, a, b) (unlikely(!(obj)) ? \ - (PyErr_SetString(PyExc_SystemError, "null argument to internal routine"), -1) : \ - (likely((obj)->ob_type->tp_as_mapping) ? (PySequence_DelSlice(obj, a, b)) : \ - (PyErr_Format(PyExc_TypeError, "'%.200s' object doesn't support slice deletion", (obj)->ob_type->tp_name), -1))) + #define __Pyx_PyType_AsAsync(obj) NULL #endif - -#if PY_MAJOR_VERSION >= 3 - #define PyMethod_New(func, self, klass) ((self) ? PyMethod_New(func, self) : PyInstanceMethod_New(func)) +#ifndef __Pyx_PyAsyncMethodsStruct + typedef struct { + unaryfunc am_await; + unaryfunc am_aiter; + unaryfunc am_anext; + } __Pyx_PyAsyncMethodsStruct; #endif -#if PY_VERSION_HEX < 0x02050000 - #define __Pyx_GetAttrString(o,n) PyObject_GetAttrString((o),((char *)(n))) - #define __Pyx_SetAttrString(o,n,a) PyObject_SetAttrString((o),((char *)(n)),(a)) - #define __Pyx_DelAttrString(o,n) PyObject_DelAttrString((o),((char *)(n))) +#if defined(WIN32) || defined(MS_WINDOWS) + #define _USE_MATH_DEFINES +#endif +#include +#ifdef NAN +#define __PYX_NAN() ((float) NAN) #else - #define __Pyx_GetAttrString(o,n) PyObject_GetAttrString((o),(n)) - #define __Pyx_SetAttrString(o,n,a) PyObject_SetAttrString((o),(n),(a)) - #define __Pyx_DelAttrString(o,n) PyObject_DelAttrString((o),(n)) +static CYTHON_INLINE float __PYX_NAN() { + float value; + memset(&value, 0xFF, sizeof(value)); + return value; +} #endif - -#if PY_VERSION_HEX < 0x02050000 - #define __Pyx_NAMESTR(n) ((char *)(n)) - #define __Pyx_DOCSTR(n) ((char *)(n)) +#if defined(__CYGWIN__) && defined(_LDBL_EQ_DBL) +#define __Pyx_truncl trunc #else - #define __Pyx_NAMESTR(n) (n) - #define __Pyx_DOCSTR(n) (n) +#define __Pyx_truncl truncl #endif + +#define __PYX_ERR(f_index, lineno, Ln_error) \ +{ \ + __pyx_filename = __pyx_f[f_index]; __pyx_lineno = lineno; __pyx_clineno = __LINE__; goto Ln_error; \ +} + #ifndef __PYX_EXTERN_C #ifdef __cplusplus #define __PYX_EXTERN_C extern "C" @@ -226,88 +602,210 @@ #endif #endif -#if defined(WIN32) || defined(MS_WINDOWS) -#define _USE_MATH_DEFINES -#endif -#include #define __PYX_HAVE__cy_ctest #define __PYX_HAVE_API__cy_ctest +/* Early includes */ #include "lib.h" #ifdef _OPENMP #include #endif /* _OPENMP */ -#ifdef PYREX_WITHOUT_ASSERTIONS +#if defined(PYREX_WITHOUT_ASSERTIONS) && !defined(CYTHON_WITHOUT_ASSERTIONS) #define CYTHON_WITHOUT_ASSERTIONS #endif - -/* inline attribute */ -#ifndef CYTHON_INLINE - #if defined(__GNUC__) - #define CYTHON_INLINE __inline__ - #elif defined(_MSC_VER) - #define CYTHON_INLINE __inline - #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L - #define CYTHON_INLINE inline - #else - #define CYTHON_INLINE - #endif +typedef struct {PyObject **p; const char *s; const Py_ssize_t n; const char* encoding; + const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; + +#define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0 +#define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT 0 +#define __PYX_DEFAULT_STRING_ENCODING "" +#define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString +#define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize +#define __Pyx_uchar_cast(c) ((unsigned char)c) +#define __Pyx_long_cast(x) ((long)x) +#define __Pyx_fits_Py_ssize_t(v, type, is_signed) (\ + (sizeof(type) < sizeof(Py_ssize_t)) ||\ + (sizeof(type) > sizeof(Py_ssize_t) &&\ + likely(v < (type)PY_SSIZE_T_MAX ||\ + v == (type)PY_SSIZE_T_MAX) &&\ + (!is_signed || likely(v > (type)PY_SSIZE_T_MIN ||\ + v == (type)PY_SSIZE_T_MIN))) ||\ + (sizeof(type) == sizeof(Py_ssize_t) &&\ + (is_signed || likely(v < (type)PY_SSIZE_T_MAX ||\ + v == (type)PY_SSIZE_T_MAX))) ) +static CYTHON_INLINE int __Pyx_is_valid_index(Py_ssize_t i, Py_ssize_t limit) { + return (size_t) i < (size_t) limit; +} +#if defined (__cplusplus) && __cplusplus >= 201103L + #include + #define __Pyx_sst_abs(value) std::abs(value) +#elif SIZEOF_INT >= SIZEOF_SIZE_T + #define __Pyx_sst_abs(value) abs(value) +#elif SIZEOF_LONG >= SIZEOF_SIZE_T + #define __Pyx_sst_abs(value) labs(value) +#elif defined (_MSC_VER) + #define __Pyx_sst_abs(value) ((Py_ssize_t)_abs64(value)) +#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define __Pyx_sst_abs(value) llabs(value) +#elif defined (__GNUC__) + #define __Pyx_sst_abs(value) __builtin_llabs(value) +#else + #define __Pyx_sst_abs(value) ((value<0) ? -value : value) #endif - -/* unused attribute */ -#ifndef CYTHON_UNUSED -# if defined(__GNUC__) -# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) -# define CYTHON_UNUSED __attribute__ ((__unused__)) -# else -# define CYTHON_UNUSED -# endif -# elif defined(__ICC) || defined(__INTEL_COMPILER) -# define CYTHON_UNUSED __attribute__ ((__unused__)) -# else -# define CYTHON_UNUSED -# endif +static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject*); +static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t* length); +#define __Pyx_PyByteArray_FromString(s) PyByteArray_FromStringAndSize((const char*)s, strlen((const char*)s)) +#define __Pyx_PyByteArray_FromStringAndSize(s, l) PyByteArray_FromStringAndSize((const char*)s, l) +#define __Pyx_PyBytes_FromString PyBytes_FromString +#define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize +static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*); +#if PY_MAJOR_VERSION < 3 + #define __Pyx_PyStr_FromString __Pyx_PyBytes_FromString + #define __Pyx_PyStr_FromStringAndSize __Pyx_PyBytes_FromStringAndSize +#else + #define __Pyx_PyStr_FromString __Pyx_PyUnicode_FromString + #define __Pyx_PyStr_FromStringAndSize __Pyx_PyUnicode_FromStringAndSize #endif - -typedef struct {PyObject **p; char *s; const long n; const char* encoding; const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; /*proto*/ - - -/* Type Conversion Predeclarations */ - -#define __Pyx_PyBytes_FromUString(s) PyBytes_FromString((char*)s) -#define __Pyx_PyBytes_AsUString(s) ((unsigned char*) PyBytes_AsString(s)) - -#define __Pyx_Owned_Py_None(b) (Py_INCREF(Py_None), Py_None) -#define __Pyx_PyBool_FromLong(b) ((b) ? (Py_INCREF(Py_True), Py_True) : (Py_INCREF(Py_False), Py_False)) +#define __Pyx_PyBytes_AsWritableString(s) ((char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsWritableSString(s) ((signed char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsWritableUString(s) ((unsigned char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsString(s) ((const char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsSString(s) ((const signed char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsUString(s) ((const unsigned char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyObject_AsWritableString(s) ((char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsWritableSString(s) ((signed char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsWritableUString(s) ((unsigned char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsSString(s) ((const signed char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsUString(s) ((const unsigned char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_FromCString(s) __Pyx_PyObject_FromString((const char*)s) +#define __Pyx_PyBytes_FromCString(s) __Pyx_PyBytes_FromString((const char*)s) +#define __Pyx_PyByteArray_FromCString(s) __Pyx_PyByteArray_FromString((const char*)s) +#define __Pyx_PyStr_FromCString(s) __Pyx_PyStr_FromString((const char*)s) +#define __Pyx_PyUnicode_FromCString(s) __Pyx_PyUnicode_FromString((const char*)s) +static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u) { + const Py_UNICODE *u_end = u; + while (*u_end++) ; + return (size_t)(u_end - u - 1); +} +#define __Pyx_PyUnicode_FromUnicode(u) PyUnicode_FromUnicode(u, __Pyx_Py_UNICODE_strlen(u)) +#define __Pyx_PyUnicode_FromUnicodeAndLength PyUnicode_FromUnicode +#define __Pyx_PyUnicode_AsUnicode PyUnicode_AsUnicode +#define __Pyx_NewRef(obj) (Py_INCREF(obj), obj) +#define __Pyx_Owned_Py_None(b) __Pyx_NewRef(Py_None) +static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b); static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*); -static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x); - +static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject*); +static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x); +#define __Pyx_PySequence_Tuple(obj)\ + (likely(PyTuple_CheckExact(obj)) ? __Pyx_NewRef(obj) : PySequence_Tuple(obj)) static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*); static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t); -static CYTHON_INLINE size_t __Pyx_PyInt_AsSize_t(PyObject*); - +#if CYTHON_ASSUME_SAFE_MACROS #define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) +#else +#define __pyx_PyFloat_AsDouble(x) PyFloat_AsDouble(x) +#endif +#define __pyx_PyFloat_AsFloat(x) ((float) __pyx_PyFloat_AsDouble(x)) +#if PY_MAJOR_VERSION >= 3 +#define __Pyx_PyNumber_Int(x) (PyLong_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Long(x)) +#else +#define __Pyx_PyNumber_Int(x) (PyInt_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Int(x)) +#endif +#define __Pyx_PyNumber_Float(x) (PyFloat_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Float(x)) +#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII +static int __Pyx_sys_getdefaultencoding_not_ascii; +static int __Pyx_init_sys_getdefaultencoding_params(void) { + PyObject* sys; + PyObject* default_encoding = NULL; + PyObject* ascii_chars_u = NULL; + PyObject* ascii_chars_b = NULL; + const char* default_encoding_c; + sys = PyImport_ImportModule("sys"); + if (!sys) goto bad; + default_encoding = PyObject_CallMethod(sys, (char*) "getdefaultencoding", NULL); + Py_DECREF(sys); + if (!default_encoding) goto bad; + default_encoding_c = PyBytes_AsString(default_encoding); + if (!default_encoding_c) goto bad; + if (strcmp(default_encoding_c, "ascii") == 0) { + __Pyx_sys_getdefaultencoding_not_ascii = 0; + } else { + char ascii_chars[128]; + int c; + for (c = 0; c < 128; c++) { + ascii_chars[c] = c; + } + __Pyx_sys_getdefaultencoding_not_ascii = 1; + ascii_chars_u = PyUnicode_DecodeASCII(ascii_chars, 128, NULL); + if (!ascii_chars_u) goto bad; + ascii_chars_b = PyUnicode_AsEncodedString(ascii_chars_u, default_encoding_c, NULL); + if (!ascii_chars_b || !PyBytes_Check(ascii_chars_b) || memcmp(ascii_chars, PyBytes_AS_STRING(ascii_chars_b), 128) != 0) { + PyErr_Format( + PyExc_ValueError, + "This module compiled with c_string_encoding=ascii, but default encoding '%.200s' is not a superset of ascii.", + default_encoding_c); + goto bad; + } + Py_DECREF(ascii_chars_u); + Py_DECREF(ascii_chars_b); + } + Py_DECREF(default_encoding); + return 0; +bad: + Py_XDECREF(default_encoding); + Py_XDECREF(ascii_chars_u); + Py_XDECREF(ascii_chars_b); + return -1; +} +#endif +#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT && PY_MAJOR_VERSION >= 3 +#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeUTF8(c_str, size, NULL) +#else +#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_Decode(c_str, size, __PYX_DEFAULT_STRING_ENCODING, NULL) +#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT +static char* __PYX_DEFAULT_STRING_ENCODING; +static int __Pyx_init_sys_getdefaultencoding_params(void) { + PyObject* sys; + PyObject* default_encoding = NULL; + char* default_encoding_c; + sys = PyImport_ImportModule("sys"); + if (!sys) goto bad; + default_encoding = PyObject_CallMethod(sys, (char*) (const char*) "getdefaultencoding", NULL); + Py_DECREF(sys); + if (!default_encoding) goto bad; + default_encoding_c = PyBytes_AsString(default_encoding); + if (!default_encoding_c) goto bad; + __PYX_DEFAULT_STRING_ENCODING = (char*) malloc(strlen(default_encoding_c) + 1); + if (!__PYX_DEFAULT_STRING_ENCODING) goto bad; + strcpy(__PYX_DEFAULT_STRING_ENCODING, default_encoding_c); + Py_DECREF(default_encoding); + return 0; +bad: + Py_XDECREF(default_encoding); + return -1; +} +#endif +#endif -#ifdef __GNUC__ - /* Test for GCC > 2.95 */ - #if __GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)) - #define likely(x) __builtin_expect(!!(x), 1) - #define unlikely(x) __builtin_expect(!!(x), 0) - #else /* __GNUC__ > 2 ... */ - #define likely(x) (x) - #define unlikely(x) (x) - #endif /* __GNUC__ > 2 ... */ -#else /* __GNUC__ */ +/* Test for GCC > 2.95 */ +#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))) + #define likely(x) __builtin_expect(!!(x), 1) + #define unlikely(x) __builtin_expect(!!(x), 0) +#else /* !__GNUC__ or GCC < 2.95 */ #define likely(x) (x) #define unlikely(x) (x) #endif /* __GNUC__ */ - -static PyObject *__pyx_m; +static CYTHON_INLINE void __Pyx_pretend_to_initialize(void* ptr) { (void)ptr; } + +static PyObject *__pyx_m = NULL; +static PyObject *__pyx_d; static PyObject *__pyx_b; +static PyObject *__pyx_cython_runtime = NULL; static PyObject *__pyx_empty_tuple; static PyObject *__pyx_empty_bytes; +static PyObject *__pyx_empty_unicode; static int __pyx_lineno; static int __pyx_clineno = 0; static const char * __pyx_cfilenm= __FILE__; @@ -320,10 +818,11 @@ static const char *__pyx_f[] = { /*--- Type declarations ---*/ +/* --- Runtime support code (head) --- */ +/* Refnanny.proto */ #ifndef CYTHON_REFNANNY #define CYTHON_REFNANNY 0 #endif - #if CYTHON_REFNANNY typedef struct { void (*INCREF)(void*, PyObject*, int); @@ -334,10 +833,23 @@ static const char *__pyx_f[] = { void (*FinishContext)(void**); } __Pyx_RefNannyAPIStruct; static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL; - static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); /*proto*/ + static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL; - #define __Pyx_RefNannySetupContext(name) __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__) - #define __Pyx_RefNannyFinishContext() __Pyx_RefNanny->FinishContext(&__pyx_refnanny) +#ifdef WITH_THREAD + #define __Pyx_RefNannySetupContext(name, acquire_gil)\ + if (acquire_gil) {\ + PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ + PyGILState_Release(__pyx_gilstate_save);\ + } else {\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ + } +#else + #define __Pyx_RefNannySetupContext(name, acquire_gil)\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__) +#endif + #define __Pyx_RefNannyFinishContext()\ + __Pyx_RefNanny->FinishContext(&__pyx_refnanny) #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__) #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__) #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__) @@ -348,7 +860,7 @@ static const char *__pyx_f[] = { #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0) #else #define __Pyx_RefNannyDeclarations - #define __Pyx_RefNannySetupContext(name) + #define __Pyx_RefNannySetupContext(name, acquire_gil) #define __Pyx_RefNannyFinishContext() #define __Pyx_INCREF(r) Py_INCREF(r) #define __Pyx_DECREF(r) Py_DECREF(r) @@ -358,60 +870,139 @@ static const char *__pyx_f[] = { #define __Pyx_XDECREF(r) Py_XDECREF(r) #define __Pyx_XGOTREF(r) #define __Pyx_XGIVEREF(r) -#endif /* CYTHON_REFNANNY */ - -static CYTHON_INLINE unsigned char __Pyx_PyInt_AsUnsignedChar(PyObject *); - -static CYTHON_INLINE unsigned short __Pyx_PyInt_AsUnsignedShort(PyObject *); - -static CYTHON_INLINE unsigned int __Pyx_PyInt_AsUnsignedInt(PyObject *); - -static CYTHON_INLINE char __Pyx_PyInt_AsChar(PyObject *); - -static CYTHON_INLINE short __Pyx_PyInt_AsShort(PyObject *); - -static CYTHON_INLINE int __Pyx_PyInt_AsInt(PyObject *); - -static CYTHON_INLINE signed char __Pyx_PyInt_AsSignedChar(PyObject *); - -static CYTHON_INLINE signed short __Pyx_PyInt_AsSignedShort(PyObject *); - -static CYTHON_INLINE signed int __Pyx_PyInt_AsSignedInt(PyObject *); - -static CYTHON_INLINE int __Pyx_PyInt_AsLongDouble(PyObject *); - -static CYTHON_INLINE unsigned long __Pyx_PyInt_AsUnsignedLong(PyObject *); - -static CYTHON_INLINE unsigned PY_LONG_LONG __Pyx_PyInt_AsUnsignedLongLong(PyObject *); +#endif +#define __Pyx_XDECREF_SET(r, v) do {\ + PyObject *tmp = (PyObject *) r;\ + r = v; __Pyx_XDECREF(tmp);\ + } while (0) +#define __Pyx_DECREF_SET(r, v) do {\ + PyObject *tmp = (PyObject *) r;\ + r = v; __Pyx_DECREF(tmp);\ + } while (0) +#define __Pyx_CLEAR(r) do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0) +#define __Pyx_XCLEAR(r) do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0) + +/* PyObjectGetAttrStr.proto */ +#if CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name); +#else +#define __Pyx_PyObject_GetAttrStr(o,n) PyObject_GetAttr(o,n) +#endif -static CYTHON_INLINE long __Pyx_PyInt_AsLong(PyObject *); +/* PyThreadStateGet.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyThreadState_declare PyThreadState *__pyx_tstate; +#define __Pyx_PyThreadState_assign __pyx_tstate = __Pyx_PyThreadState_Current; +#define __Pyx_PyErr_Occurred() __pyx_tstate->curexc_type +#else +#define __Pyx_PyThreadState_declare +#define __Pyx_PyThreadState_assign +#define __Pyx_PyErr_Occurred() PyErr_Occurred() +#endif -static CYTHON_INLINE PY_LONG_LONG __Pyx_PyInt_AsLongLong(PyObject *); +/* PyErrFetchRestore.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyErr_Clear() __Pyx_ErrRestore(NULL, NULL, NULL) +#define __Pyx_ErrRestoreWithState(type, value, tb) __Pyx_ErrRestoreInState(PyThreadState_GET(), type, value, tb) +#define __Pyx_ErrFetchWithState(type, value, tb) __Pyx_ErrFetchInState(PyThreadState_GET(), type, value, tb) +#define __Pyx_ErrRestore(type, value, tb) __Pyx_ErrRestoreInState(__pyx_tstate, type, value, tb) +#define __Pyx_ErrFetch(type, value, tb) __Pyx_ErrFetchInState(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); +static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#if CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_PyErr_SetNone(exc) (Py_INCREF(exc), __Pyx_ErrRestore((exc), NULL, NULL)) +#else +#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) +#endif +#else +#define __Pyx_PyErr_Clear() PyErr_Clear() +#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) +#define __Pyx_ErrRestoreWithState(type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetchWithState(type, value, tb) PyErr_Fetch(type, value, tb) +#define __Pyx_ErrRestoreInState(tstate, type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetchInState(tstate, type, value, tb) PyErr_Fetch(type, value, tb) +#define __Pyx_ErrRestore(type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetch(type, value, tb) PyErr_Fetch(type, value, tb) +#endif -static CYTHON_INLINE signed long __Pyx_PyInt_AsSignedLong(PyObject *); +/* CLineInTraceback.proto */ +#ifdef CYTHON_CLINE_IN_TRACEBACK +#define __Pyx_CLineForTraceback(tstate, c_line) (((CYTHON_CLINE_IN_TRACEBACK)) ? c_line : 0) +#else +static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line); +#endif -static CYTHON_INLINE signed PY_LONG_LONG __Pyx_PyInt_AsSignedLongLong(PyObject *); +/* CodeObjectCache.proto */ +typedef struct { + PyCodeObject* code_object; + int code_line; +} __Pyx_CodeObjectCacheEntry; +struct __Pyx_CodeObjectCache { + int count; + int max_count; + __Pyx_CodeObjectCacheEntry* entries; +}; +static struct __Pyx_CodeObjectCache __pyx_code_cache = {0,0,NULL}; +static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line); +static PyCodeObject *__pyx_find_code_object(int code_line); +static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object); + +/* AddTraceback.proto */ +static void __Pyx_AddTraceback(const char *funcname, int c_line, + int py_line, const char *filename); + +/* CIntToPy.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value); + +/* CIntFromPy.proto */ +static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *); + +/* CIntFromPy.proto */ +static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *); + +/* FastTypeChecks.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_TypeCheck(obj, type) __Pyx_IsSubtype(Py_TYPE(obj), (PyTypeObject *)type) +static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b); +static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject *type); +static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *type1, PyObject *type2); +#else +#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type) +#define __Pyx_PyErr_GivenExceptionMatches(err, type) PyErr_GivenExceptionMatches(err, type) +#define __Pyx_PyErr_GivenExceptionMatches2(err, type1, type2) (PyErr_GivenExceptionMatches(err, type1) || PyErr_GivenExceptionMatches(err, type2)) +#endif +#define __Pyx_PyException_Check(obj) __Pyx_TypeCheck(obj, PyExc_Exception) +/* CheckBinaryVersion.proto */ static int __Pyx_check_binary_version(void); -static void __Pyx_AddTraceback(const char *funcname, int __pyx_clineno, - int __pyx_lineno, const char *__pyx_filename); /*proto*/ +/* InitStrings.proto */ +static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); -static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/ /* Module declarations from 'cy_ctest' */ #define __Pyx_MODULE_NAME "cy_ctest" +extern int __pyx_module_is_main_cy_ctest; int __pyx_module_is_main_cy_ctest = 0; /* Implementation of 'cy_ctest' */ -static char __pyx_k__pyhello[] = "pyhello"; -static char __pyx_k____main__[] = "__main__"; -static char __pyx_k____test__[] = "__test__"; -static char __pyx_k__cy_ctest[] = "cy_ctest"; -static PyObject *__pyx_n_s____main__; -static PyObject *__pyx_n_s____test__; -static PyObject *__pyx_n_s__cy_ctest; -static PyObject *__pyx_n_s__pyhello; +static const char __pyx_k_main[] = "__main__"; +static const char __pyx_k_name[] = "__name__"; +static const char __pyx_k_test[] = "__test__"; +static const char __pyx_k_pyhello[] = "pyhello"; +static const char __pyx_k_cy_ctest[] = "cy_ctest"; +static const char __pyx_k_cline_in_traceback[] = "cline_in_traceback"; +static const char __pyx_k_home_romain_dev_waf_wrapper_waf[] = "/home/romain/dev/waf-wrapper/waf/playground/cython/src/cy_ctest.pyx"; +static PyObject *__pyx_n_s_cline_in_traceback; +static PyObject *__pyx_n_s_cy_ctest; +static PyObject *__pyx_kp_s_home_romain_dev_waf_wrapper_waf; +static PyObject *__pyx_n_s_main; +static PyObject *__pyx_n_s_name; +static PyObject *__pyx_n_s_pyhello; +static PyObject *__pyx_n_s_test; +static PyObject *__pyx_pf_8cy_ctest_pyhello(CYTHON_UNUSED PyObject *__pyx_self); /* proto */ +static PyObject *__pyx_codeobj_; +/* Late includes */ /* "cy_ctest.pyx":3 * cimport cy_ctest @@ -420,21 +1011,40 @@ static PyObject *__pyx_n_s__pyhello; * cy_ctest.hello() */ -static PyObject *__pyx_pf_8cy_ctest_pyhello(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused); /*proto*/ -static PyMethodDef __pyx_mdef_8cy_ctest_pyhello = {__Pyx_NAMESTR("pyhello"), (PyCFunction)__pyx_pf_8cy_ctest_pyhello, METH_NOARGS, __Pyx_DOCSTR(0)}; -static PyObject *__pyx_pf_8cy_ctest_pyhello(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused) { - PyObject *__pyx_r = NULL; +/* Python wrapper */ +static PyObject *__pyx_pw_8cy_ctest_1pyhello(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused); /*proto*/ +static PyMethodDef __pyx_mdef_8cy_ctest_1pyhello = {"pyhello", (PyCFunction)__pyx_pw_8cy_ctest_1pyhello, METH_NOARGS, 0}; +static PyObject *__pyx_pw_8cy_ctest_1pyhello(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused) { + PyObject *__pyx_r = 0; __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("pyhello"); - __pyx_self = __pyx_self; + __Pyx_RefNannySetupContext("pyhello (wrapper)", 0); + __pyx_r = __pyx_pf_8cy_ctest_pyhello(__pyx_self); - /* "cy_ctest.pyx":4 - * - * def pyhello(): - * cy_ctest.hello() # <<<<<<<<<<<<<< + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_8cy_ctest_pyhello(CYTHON_UNUSED PyObject *__pyx_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("pyhello", 0); + + /* "cy_ctest.pyx":4 + * + * def pyhello(): + * cy_ctest.hello() # <<<<<<<<<<<<<< */ hello(); + /* "cy_ctest.pyx":3 + * cimport cy_ctest + * + * def pyhello(): # <<<<<<<<<<<<<< + * cy_ctest.hello() + */ + + /* function exit code */ __pyx_r = Py_None; __Pyx_INCREF(Py_None); __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); @@ -446,69 +1056,284 @@ static PyMethodDef __pyx_methods[] = { }; #if PY_MAJOR_VERSION >= 3 +#if CYTHON_PEP489_MULTI_PHASE_INIT +static PyObject* __pyx_pymod_create(PyObject *spec, PyModuleDef *def); /*proto*/ +static int __pyx_pymod_exec_cy_ctest(PyObject* module); /*proto*/ +static PyModuleDef_Slot __pyx_moduledef_slots[] = { + {Py_mod_create, (void*)__pyx_pymod_create}, + {Py_mod_exec, (void*)__pyx_pymod_exec_cy_ctest}, + {0, NULL} +}; +#endif + static struct PyModuleDef __pyx_moduledef = { PyModuleDef_HEAD_INIT, - __Pyx_NAMESTR("cy_ctest"), + "cy_ctest", 0, /* m_doc */ + #if CYTHON_PEP489_MULTI_PHASE_INIT + 0, /* m_size */ + #else -1, /* m_size */ + #endif __pyx_methods /* m_methods */, + #if CYTHON_PEP489_MULTI_PHASE_INIT + __pyx_moduledef_slots, /* m_slots */ + #else NULL, /* m_reload */ + #endif NULL, /* m_traverse */ NULL, /* m_clear */ NULL /* m_free */ }; #endif +#ifndef CYTHON_SMALL_CODE +#if defined(__clang__) + #define CYTHON_SMALL_CODE +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) + #define CYTHON_SMALL_CODE __attribute__((cold)) +#else + #define CYTHON_SMALL_CODE +#endif +#endif static __Pyx_StringTabEntry __pyx_string_tab[] = { - {&__pyx_n_s____main__, __pyx_k____main__, sizeof(__pyx_k____main__), 0, 0, 1, 1}, - {&__pyx_n_s____test__, __pyx_k____test__, sizeof(__pyx_k____test__), 0, 0, 1, 1}, - {&__pyx_n_s__cy_ctest, __pyx_k__cy_ctest, sizeof(__pyx_k__cy_ctest), 0, 0, 1, 1}, - {&__pyx_n_s__pyhello, __pyx_k__pyhello, sizeof(__pyx_k__pyhello), 0, 0, 1, 1}, + {&__pyx_n_s_cline_in_traceback, __pyx_k_cline_in_traceback, sizeof(__pyx_k_cline_in_traceback), 0, 0, 1, 1}, + {&__pyx_n_s_cy_ctest, __pyx_k_cy_ctest, sizeof(__pyx_k_cy_ctest), 0, 0, 1, 1}, + {&__pyx_kp_s_home_romain_dev_waf_wrapper_waf, __pyx_k_home_romain_dev_waf_wrapper_waf, sizeof(__pyx_k_home_romain_dev_waf_wrapper_waf), 0, 0, 1, 0}, + {&__pyx_n_s_main, __pyx_k_main, sizeof(__pyx_k_main), 0, 0, 1, 1}, + {&__pyx_n_s_name, __pyx_k_name, sizeof(__pyx_k_name), 0, 0, 1, 1}, + {&__pyx_n_s_pyhello, __pyx_k_pyhello, sizeof(__pyx_k_pyhello), 0, 0, 1, 1}, + {&__pyx_n_s_test, __pyx_k_test, sizeof(__pyx_k_test), 0, 0, 1, 1}, {0, 0, 0, 0, 0, 0, 0} }; -static int __Pyx_InitCachedBuiltins(void) { +static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(void) { return 0; } -static int __Pyx_InitCachedConstants(void) { +static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants"); + __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0); + + /* "cy_ctest.pyx":3 + * cimport cy_ctest + * + * def pyhello(): # <<<<<<<<<<<<<< + * cy_ctest.hello() + */ + __pyx_codeobj_ = (PyObject*)__Pyx_PyCode_New(0, 0, 0, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_romain_dev_waf_wrapper_waf, __pyx_n_s_pyhello, 3, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj_)) __PYX_ERR(0, 3, __pyx_L1_error) __Pyx_RefNannyFinishContext(); return 0; + __pyx_L1_error:; + __Pyx_RefNannyFinishContext(); + return -1; } -static int __Pyx_InitGlobals(void) { - if (__Pyx_InitStrings(__pyx_string_tab) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; +static CYTHON_SMALL_CODE int __Pyx_InitGlobals(void) { + if (__Pyx_InitStrings(__pyx_string_tab) < 0) __PYX_ERR(0, 1, __pyx_L1_error); return 0; __pyx_L1_error:; return -1; } +static CYTHON_SMALL_CODE int __Pyx_modinit_global_init_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_variable_export_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_function_export_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_type_init_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_type_import_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_variable_import_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_function_import_code(void); /*proto*/ + +static int __Pyx_modinit_global_init_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_global_init_code", 0); + /*--- Global init code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_variable_export_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_variable_export_code", 0); + /*--- Variable export code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_function_export_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_function_export_code", 0); + /*--- Function export code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_type_init_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_type_init_code", 0); + /*--- Type init code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_type_import_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_type_import_code", 0); + /*--- Type import code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_variable_import_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_variable_import_code", 0); + /*--- Variable import code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_function_import_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_function_import_code", 0); + /*--- Function import code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + + #if PY_MAJOR_VERSION < 3 -PyMODINIT_FUNC initcy_ctest(void); /*proto*/ -PyMODINIT_FUNC initcy_ctest(void) +#ifdef CYTHON_NO_PYINIT_EXPORT +#define __Pyx_PyMODINIT_FUNC void #else -PyMODINIT_FUNC PyInit_cy_ctest(void); /*proto*/ -PyMODINIT_FUNC PyInit_cy_ctest(void) +#define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC +#endif +#else +#ifdef CYTHON_NO_PYINIT_EXPORT +#define __Pyx_PyMODINIT_FUNC PyObject * +#else +#define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC +#endif +#endif + + +#if PY_MAJOR_VERSION < 3 +__Pyx_PyMODINIT_FUNC initcy_ctest(void) CYTHON_SMALL_CODE; /*proto*/ +__Pyx_PyMODINIT_FUNC initcy_ctest(void) +#else +__Pyx_PyMODINIT_FUNC PyInit_cy_ctest(void) CYTHON_SMALL_CODE; /*proto*/ +__Pyx_PyMODINIT_FUNC PyInit_cy_ctest(void) +#if CYTHON_PEP489_MULTI_PHASE_INIT +{ + return PyModuleDef_Init(&__pyx_moduledef); +} +static CYTHON_SMALL_CODE int __Pyx_check_single_interpreter(void) { + #if PY_VERSION_HEX >= 0x030700A1 + static PY_INT64_T main_interpreter_id = -1; + PY_INT64_T current_id = PyInterpreterState_GetID(PyThreadState_Get()->interp); + if (main_interpreter_id == -1) { + main_interpreter_id = current_id; + return (unlikely(current_id == -1)) ? -1 : 0; + } else if (unlikely(main_interpreter_id != current_id)) + #else + static PyInterpreterState *main_interpreter = NULL; + PyInterpreterState *current_interpreter = PyThreadState_Get()->interp; + if (!main_interpreter) { + main_interpreter = current_interpreter; + } else if (unlikely(main_interpreter != current_interpreter)) + #endif + { + PyErr_SetString( + PyExc_ImportError, + "Interpreter change detected - this module can only be loaded into one interpreter per process."); + return -1; + } + return 0; +} +static CYTHON_SMALL_CODE int __Pyx_copy_spec_to_module(PyObject *spec, PyObject *moddict, const char* from_name, const char* to_name) { + PyObject *value = PyObject_GetAttrString(spec, from_name); + int result = 0; + if (likely(value)) { + result = PyDict_SetItemString(moddict, to_name, value); + Py_DECREF(value); + } else if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + } else { + result = -1; + } + return result; +} +static CYTHON_SMALL_CODE PyObject* __pyx_pymod_create(PyObject *spec, CYTHON_UNUSED PyModuleDef *def) { + PyObject *module = NULL, *moddict, *modname; + if (__Pyx_check_single_interpreter()) + return NULL; + if (__pyx_m) + return __Pyx_NewRef(__pyx_m); + modname = PyObject_GetAttrString(spec, "name"); + if (unlikely(!modname)) goto bad; + module = PyModule_NewObject(modname); + Py_DECREF(modname); + if (unlikely(!module)) goto bad; + moddict = PyModule_GetDict(module); + if (unlikely(!moddict)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "loader", "__loader__") < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "origin", "__file__") < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "parent", "__package__") < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "submodule_search_locations", "__path__") < 0)) goto bad; + return module; +bad: + Py_XDECREF(module); + return NULL; +} + + +static CYTHON_SMALL_CODE int __pyx_pymod_exec_cy_ctest(PyObject *__pyx_pyinit_module) +#endif #endif { PyObject *__pyx_t_1 = NULL; __Pyx_RefNannyDeclarations - #if CYTHON_REFNANNY - __Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); - if (!__Pyx_RefNanny) { - PyErr_Clear(); - __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny"); - if (!__Pyx_RefNanny) - Py_FatalError("failed to import 'refnanny' module"); + #if CYTHON_PEP489_MULTI_PHASE_INIT + if (__pyx_m) { + if (__pyx_m == __pyx_pyinit_module) return 0; + PyErr_SetString(PyExc_RuntimeError, "Module 'cy_ctest' has already been imported. Re-initialisation is not supported."); + return -1; } + #elif PY_MAJOR_VERSION >= 3 + if (__pyx_m) return __Pyx_NewRef(__pyx_m); + #endif + #if CYTHON_REFNANNY +__Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); +if (!__Pyx_RefNanny) { + PyErr_Clear(); + __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny"); + if (!__Pyx_RefNanny) + Py_FatalError("failed to import 'refnanny' module"); +} +#endif + __Pyx_RefNannySetupContext("__Pyx_PyMODINIT_FUNC PyInit_cy_ctest(void)", 0); + if (__Pyx_check_binary_version() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #ifdef __Pxy_PyFrame_Initialize_Offsets + __Pxy_PyFrame_Initialize_Offsets(); + #endif + __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_empty_unicode = PyUnicode_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_unicode)) __PYX_ERR(0, 1, __pyx_L1_error) + #ifdef __Pyx_CyFunction_USED + if (__pyx_CyFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_FusedFunction_USED + if (__pyx_FusedFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif - __Pyx_RefNannySetupContext("PyMODINIT_FUNC PyInit_cy_ctest(void)"); - if ( __Pyx_check_binary_version() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - #ifdef __pyx_binding_PyCFunctionType_USED - if (__pyx_binding_PyCFunctionType_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + #ifdef __Pyx_Coroutine_USED + if (__pyx_Coroutine_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_Generator_USED + if (__pyx_Generator_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_AsyncGen_USED + if (__pyx_AsyncGen_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_StopAsyncIteration_USED + if (__pyx_StopAsyncIteration_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif /*--- Library function declarations ---*/ /*--- Threads initialization code ---*/ @@ -518,35 +1343,57 @@ PyMODINIT_FUNC PyInit_cy_ctest(void) #endif #endif /*--- Module creation code ---*/ + #if CYTHON_PEP489_MULTI_PHASE_INIT + __pyx_m = __pyx_pyinit_module; + Py_INCREF(__pyx_m); + #else #if PY_MAJOR_VERSION < 3 - __pyx_m = Py_InitModule4(__Pyx_NAMESTR("cy_ctest"), __pyx_methods, 0, 0, PYTHON_API_VERSION); + __pyx_m = Py_InitModule4("cy_ctest", __pyx_methods, 0, 0, PYTHON_API_VERSION); Py_XINCREF(__pyx_m); #else __pyx_m = PyModule_Create(&__pyx_moduledef); #endif - if (!__pyx_m) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - #if PY_MAJOR_VERSION < 3 - Py_INCREF(__pyx_m); + if (unlikely(!__pyx_m)) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + __pyx_d = PyModule_GetDict(__pyx_m); if (unlikely(!__pyx_d)) __PYX_ERR(0, 1, __pyx_L1_error) + Py_INCREF(__pyx_d); + __pyx_b = PyImport_AddModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_b)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_cython_runtime = PyImport_AddModule((char *) "cython_runtime"); if (unlikely(!__pyx_cython_runtime)) __PYX_ERR(0, 1, __pyx_L1_error) + #if CYTHON_COMPILING_IN_PYPY + Py_INCREF(__pyx_b); #endif - __pyx_b = PyImport_AddModule(__Pyx_NAMESTR(__Pyx_BUILTIN_MODULE_NAME)); - if (!__pyx_b) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - if (__Pyx_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; + if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) __PYX_ERR(0, 1, __pyx_L1_error); /*--- Initialize various global constants etc. ---*/ - if (unlikely(__Pyx_InitGlobals() < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__Pyx_InitGlobals() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #if PY_MAJOR_VERSION < 3 && (__PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT) + if (__Pyx_init_sys_getdefaultencoding_params() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif if (__pyx_module_is_main_cy_ctest) { - if (__Pyx_SetAttrString(__pyx_m, "__name__", __pyx_n_s____main__) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; + if (PyObject_SetAttr(__pyx_m, __pyx_n_s_name, __pyx_n_s_main) < 0) __PYX_ERR(0, 1, __pyx_L1_error) + } + #if PY_MAJOR_VERSION >= 3 + { + PyObject *modules = PyImport_GetModuleDict(); if (unlikely(!modules)) __PYX_ERR(0, 1, __pyx_L1_error) + if (!PyDict_GetItemString(modules, "cy_ctest")) { + if (unlikely(PyDict_SetItemString(modules, "cy_ctest", __pyx_m) < 0)) __PYX_ERR(0, 1, __pyx_L1_error) + } } + #endif /*--- Builtin init code ---*/ - if (unlikely(__Pyx_InitCachedBuiltins() < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__Pyx_InitCachedBuiltins() < 0) __PYX_ERR(0, 1, __pyx_L1_error) /*--- Constants init code ---*/ - if (unlikely(__Pyx_InitCachedConstants() < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - /*--- Global init code ---*/ - /*--- Variable export code ---*/ - /*--- Function export code ---*/ - /*--- Type init code ---*/ - /*--- Type import code ---*/ - /*--- Variable import code ---*/ - /*--- Function import code ---*/ + if (__Pyx_InitCachedConstants() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + /*--- Global type/function init code ---*/ + (void)__Pyx_modinit_global_init_code(); + (void)__Pyx_modinit_variable_export_code(); + (void)__Pyx_modinit_function_export_code(); + (void)__Pyx_modinit_type_init_code(); + (void)__Pyx_modinit_type_import_code(); + (void)__Pyx_modinit_variable_import_code(); + (void)__Pyx_modinit_function_import_code(); /*--- Execution code ---*/ + #if defined(__Pyx_Generator_USED) || defined(__Pyx_Coroutine_USED) + if (__Pyx_patch_abc() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif /* "cy_ctest.pyx":3 * cimport cy_ctest @@ -554,9 +1401,9 @@ PyMODINIT_FUNC PyInit_cy_ctest(void) * def pyhello(): # <<<<<<<<<<<<<< * cy_ctest.hello() */ - __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_8cy_ctest_pyhello, NULL, __pyx_n_s__cy_ctest); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_8cy_ctest_1pyhello, NULL, __pyx_n_s_cy_ctest); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__pyhello, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyDict_SetItem(__pyx_d, __pyx_n_s_pyhello, __pyx_t_1) < 0) __PYX_ERR(0, 3, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; /* "cy_ctest.pyx":1 @@ -564,37 +1411,44 @@ PyMODINIT_FUNC PyInit_cy_ctest(void) * * def pyhello(): */ - __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(((PyObject *)__pyx_t_1)); - if (PyObject_SetAttr(__pyx_m, __pyx_n_s____test__, ((PyObject *)__pyx_t_1)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /*--- Wrapped vars code ---*/ + goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); if (__pyx_m) { - __Pyx_AddTraceback("init cy_ctest", __pyx_clineno, __pyx_lineno, __pyx_filename); - Py_DECREF(__pyx_m); __pyx_m = 0; + if (__pyx_d) { + __Pyx_AddTraceback("init cy_ctest", __pyx_clineno, __pyx_lineno, __pyx_filename); + } + Py_CLEAR(__pyx_m); } else if (!PyErr_Occurred()) { PyErr_SetString(PyExc_ImportError, "init cy_ctest"); } __pyx_L0:; __Pyx_RefNannyFinishContext(); - #if PY_MAJOR_VERSION < 3 - return; - #else + #if CYTHON_PEP489_MULTI_PHASE_INIT + return (__pyx_m != NULL) ? 0 : -1; + #elif PY_MAJOR_VERSION >= 3 return __pyx_m; + #else + return; #endif } -/* Runtime support code */ - +/* --- Runtime support code --- */ +/* Refnanny */ #if CYTHON_REFNANNY static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) { PyObject *m = NULL, *p = NULL; void *r = NULL; - m = PyImport_ImportModule((char *)modname); + m = PyImport_ImportModule(modname); if (!m) goto end; - p = PyObject_GetAttrString(m, (char *)"RefNannyAPI"); + p = PyObject_GetAttrString(m, "RefNannyAPI"); if (!p) goto end; r = PyLong_AsVoidPtr(p); end: @@ -602,408 +1456,785 @@ static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) { Py_XDECREF(m); return (__Pyx_RefNannyAPIStruct *)r; } -#endif /* CYTHON_REFNANNY */ +#endif -static CYTHON_INLINE unsigned char __Pyx_PyInt_AsUnsignedChar(PyObject* x) { - const unsigned char neg_one = (unsigned char)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(unsigned char) < sizeof(long)) { - long val = __Pyx_PyInt_AsLong(x); - if (unlikely(val != (long)(unsigned char)val)) { - if (!unlikely(val == -1 && PyErr_Occurred())) { - PyErr_SetString(PyExc_OverflowError, - (is_unsigned && unlikely(val < 0)) ? - "can't convert negative value to unsigned char" : - "value too large to convert to unsigned char"); - } - return (unsigned char)-1; - } - return (unsigned char)val; - } - return (unsigned char)__Pyx_PyInt_AsUnsignedLong(x); +/* PyObjectGetAttrStr */ +#if CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name) { + PyTypeObject* tp = Py_TYPE(obj); + if (likely(tp->tp_getattro)) + return tp->tp_getattro(obj, attr_name); +#if PY_MAJOR_VERSION < 3 + if (likely(tp->tp_getattr)) + return tp->tp_getattr(obj, PyString_AS_STRING(attr_name)); +#endif + return PyObject_GetAttr(obj, attr_name); } +#endif -static CYTHON_INLINE unsigned short __Pyx_PyInt_AsUnsignedShort(PyObject* x) { - const unsigned short neg_one = (unsigned short)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(unsigned short) < sizeof(long)) { - long val = __Pyx_PyInt_AsLong(x); - if (unlikely(val != (long)(unsigned short)val)) { - if (!unlikely(val == -1 && PyErr_Occurred())) { - PyErr_SetString(PyExc_OverflowError, - (is_unsigned && unlikely(val < 0)) ? - "can't convert negative value to unsigned short" : - "value too large to convert to unsigned short"); - } - return (unsigned short)-1; - } - return (unsigned short)val; - } - return (unsigned short)__Pyx_PyInt_AsUnsignedLong(x); +/* PyErrFetchRestore */ +#if CYTHON_FAST_THREAD_STATE +static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { + PyObject *tmp_type, *tmp_value, *tmp_tb; + tmp_type = tstate->curexc_type; + tmp_value = tstate->curexc_value; + tmp_tb = tstate->curexc_traceback; + tstate->curexc_type = type; + tstate->curexc_value = value; + tstate->curexc_traceback = tb; + Py_XDECREF(tmp_type); + Py_XDECREF(tmp_value); + Py_XDECREF(tmp_tb); } - -static CYTHON_INLINE unsigned int __Pyx_PyInt_AsUnsignedInt(PyObject* x) { - const unsigned int neg_one = (unsigned int)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(unsigned int) < sizeof(long)) { - long val = __Pyx_PyInt_AsLong(x); - if (unlikely(val != (long)(unsigned int)val)) { - if (!unlikely(val == -1 && PyErr_Occurred())) { - PyErr_SetString(PyExc_OverflowError, - (is_unsigned && unlikely(val < 0)) ? - "can't convert negative value to unsigned int" : - "value too large to convert to unsigned int"); - } - return (unsigned int)-1; - } - return (unsigned int)val; - } - return (unsigned int)__Pyx_PyInt_AsUnsignedLong(x); +static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { + *type = tstate->curexc_type; + *value = tstate->curexc_value; + *tb = tstate->curexc_traceback; + tstate->curexc_type = 0; + tstate->curexc_value = 0; + tstate->curexc_traceback = 0; } +#endif -static CYTHON_INLINE char __Pyx_PyInt_AsChar(PyObject* x) { - const char neg_one = (char)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(char) < sizeof(long)) { - long val = __Pyx_PyInt_AsLong(x); - if (unlikely(val != (long)(char)val)) { - if (!unlikely(val == -1 && PyErr_Occurred())) { - PyErr_SetString(PyExc_OverflowError, - (is_unsigned && unlikely(val < 0)) ? - "can't convert negative value to char" : - "value too large to convert to char"); - } - return (char)-1; - } - return (char)val; +/* CLineInTraceback */ +#ifndef CYTHON_CLINE_IN_TRACEBACK +static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line) { + PyObject *use_cline; + PyObject *ptype, *pvalue, *ptraceback; +#if CYTHON_COMPILING_IN_CPYTHON + PyObject **cython_runtime_dict; +#endif + if (unlikely(!__pyx_cython_runtime)) { + return c_line; + } + __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); +#if CYTHON_COMPILING_IN_CPYTHON + cython_runtime_dict = _PyObject_GetDictPtr(__pyx_cython_runtime); + if (likely(cython_runtime_dict)) { + __PYX_PY_DICT_LOOKUP_IF_MODIFIED( + use_cline, *cython_runtime_dict, + __Pyx_PyDict_GetItemStr(*cython_runtime_dict, __pyx_n_s_cline_in_traceback)) + } else +#endif + { + PyObject *use_cline_obj = __Pyx_PyObject_GetAttrStr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback); + if (use_cline_obj) { + use_cline = PyObject_Not(use_cline_obj) ? Py_False : Py_True; + Py_DECREF(use_cline_obj); + } else { + PyErr_Clear(); + use_cline = NULL; + } + } + if (!use_cline) { + c_line = 0; + PyObject_SetAttr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback, Py_False); } - return (char)__Pyx_PyInt_AsLong(x); + else if (use_cline == Py_False || (use_cline != Py_True && PyObject_Not(use_cline) != 0)) { + c_line = 0; + } + __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); + return c_line; } +#endif -static CYTHON_INLINE short __Pyx_PyInt_AsShort(PyObject* x) { - const short neg_one = (short)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(short) < sizeof(long)) { - long val = __Pyx_PyInt_AsLong(x); - if (unlikely(val != (long)(short)val)) { - if (!unlikely(val == -1 && PyErr_Occurred())) { - PyErr_SetString(PyExc_OverflowError, - (is_unsigned && unlikely(val < 0)) ? - "can't convert negative value to short" : - "value too large to convert to short"); - } - return (short)-1; +/* CodeObjectCache */ +static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) { + int start = 0, mid = 0, end = count - 1; + if (end >= 0 && code_line > entries[end].code_line) { + return count; + } + while (start < end) { + mid = start + (end - start) / 2; + if (code_line < entries[mid].code_line) { + end = mid; + } else if (code_line > entries[mid].code_line) { + start = mid + 1; + } else { + return mid; } - return (short)val; } - return (short)__Pyx_PyInt_AsLong(x); + if (code_line <= entries[mid].code_line) { + return mid; + } else { + return mid + 1; + } } - -static CYTHON_INLINE int __Pyx_PyInt_AsInt(PyObject* x) { - const int neg_one = (int)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(int) < sizeof(long)) { - long val = __Pyx_PyInt_AsLong(x); - if (unlikely(val != (long)(int)val)) { - if (!unlikely(val == -1 && PyErr_Occurred())) { - PyErr_SetString(PyExc_OverflowError, - (is_unsigned && unlikely(val < 0)) ? - "can't convert negative value to int" : - "value too large to convert to int"); - } - return (int)-1; - } - return (int)val; +static PyCodeObject *__pyx_find_code_object(int code_line) { + PyCodeObject* code_object; + int pos; + if (unlikely(!code_line) || unlikely(!__pyx_code_cache.entries)) { + return NULL; + } + pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); + if (unlikely(pos >= __pyx_code_cache.count) || unlikely(__pyx_code_cache.entries[pos].code_line != code_line)) { + return NULL; } - return (int)__Pyx_PyInt_AsLong(x); + code_object = __pyx_code_cache.entries[pos].code_object; + Py_INCREF(code_object); + return code_object; } - -static CYTHON_INLINE signed char __Pyx_PyInt_AsSignedChar(PyObject* x) { - const signed char neg_one = (signed char)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(signed char) < sizeof(long)) { - long val = __Pyx_PyInt_AsLong(x); - if (unlikely(val != (long)(signed char)val)) { - if (!unlikely(val == -1 && PyErr_Occurred())) { - PyErr_SetString(PyExc_OverflowError, - (is_unsigned && unlikely(val < 0)) ? - "can't convert negative value to signed char" : - "value too large to convert to signed char"); - } - return (signed char)-1; +static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) { + int pos, i; + __Pyx_CodeObjectCacheEntry* entries = __pyx_code_cache.entries; + if (unlikely(!code_line)) { + return; + } + if (unlikely(!entries)) { + entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry)); + if (likely(entries)) { + __pyx_code_cache.entries = entries; + __pyx_code_cache.max_count = 64; + __pyx_code_cache.count = 1; + entries[0].code_line = code_line; + entries[0].code_object = code_object; + Py_INCREF(code_object); } - return (signed char)val; + return; } - return (signed char)__Pyx_PyInt_AsSignedLong(x); -} - -static CYTHON_INLINE signed short __Pyx_PyInt_AsSignedShort(PyObject* x) { - const signed short neg_one = (signed short)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(signed short) < sizeof(long)) { - long val = __Pyx_PyInt_AsLong(x); - if (unlikely(val != (long)(signed short)val)) { - if (!unlikely(val == -1 && PyErr_Occurred())) { - PyErr_SetString(PyExc_OverflowError, - (is_unsigned && unlikely(val < 0)) ? - "can't convert negative value to signed short" : - "value too large to convert to signed short"); - } - return (signed short)-1; + pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); + if ((pos < __pyx_code_cache.count) && unlikely(__pyx_code_cache.entries[pos].code_line == code_line)) { + PyCodeObject* tmp = entries[pos].code_object; + entries[pos].code_object = code_object; + Py_DECREF(tmp); + return; + } + if (__pyx_code_cache.count == __pyx_code_cache.max_count) { + int new_max = __pyx_code_cache.max_count + 64; + entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc( + __pyx_code_cache.entries, (size_t)new_max*sizeof(__Pyx_CodeObjectCacheEntry)); + if (unlikely(!entries)) { + return; } - return (signed short)val; + __pyx_code_cache.entries = entries; + __pyx_code_cache.max_count = new_max; } - return (signed short)__Pyx_PyInt_AsSignedLong(x); + for (i=__pyx_code_cache.count; i>pos; i--) { + entries[i] = entries[i-1]; + } + entries[pos].code_line = code_line; + entries[pos].code_object = code_object; + __pyx_code_cache.count++; + Py_INCREF(code_object); } -static CYTHON_INLINE signed int __Pyx_PyInt_AsSignedInt(PyObject* x) { - const signed int neg_one = (signed int)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(signed int) < sizeof(long)) { - long val = __Pyx_PyInt_AsLong(x); - if (unlikely(val != (long)(signed int)val)) { - if (!unlikely(val == -1 && PyErr_Occurred())) { - PyErr_SetString(PyExc_OverflowError, - (is_unsigned && unlikely(val < 0)) ? - "can't convert negative value to signed int" : - "value too large to convert to signed int"); - } - return (signed int)-1; - } - return (signed int)val; +/* AddTraceback */ +#include "compile.h" +#include "frameobject.h" +#include "traceback.h" +static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( + const char *funcname, int c_line, + int py_line, const char *filename) { + PyCodeObject *py_code = 0; + PyObject *py_srcfile = 0; + PyObject *py_funcname = 0; + #if PY_MAJOR_VERSION < 3 + py_srcfile = PyString_FromString(filename); + #else + py_srcfile = PyUnicode_FromString(filename); + #endif + if (!py_srcfile) goto bad; + if (c_line) { + #if PY_MAJOR_VERSION < 3 + py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + #else + py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + #endif + } + else { + #if PY_MAJOR_VERSION < 3 + py_funcname = PyString_FromString(funcname); + #else + py_funcname = PyUnicode_FromString(funcname); + #endif } - return (signed int)__Pyx_PyInt_AsSignedLong(x); + if (!py_funcname) goto bad; + py_code = __Pyx_PyCode_New( + 0, + 0, + 0, + 0, + 0, + __pyx_empty_bytes, /*PyObject *code,*/ + __pyx_empty_tuple, /*PyObject *consts,*/ + __pyx_empty_tuple, /*PyObject *names,*/ + __pyx_empty_tuple, /*PyObject *varnames,*/ + __pyx_empty_tuple, /*PyObject *freevars,*/ + __pyx_empty_tuple, /*PyObject *cellvars,*/ + py_srcfile, /*PyObject *filename,*/ + py_funcname, /*PyObject *name,*/ + py_line, + __pyx_empty_bytes /*PyObject *lnotab*/ + ); + Py_DECREF(py_srcfile); + Py_DECREF(py_funcname); + return py_code; +bad: + Py_XDECREF(py_srcfile); + Py_XDECREF(py_funcname); + return NULL; } - -static CYTHON_INLINE int __Pyx_PyInt_AsLongDouble(PyObject* x) { - const int neg_one = (int)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(int) < sizeof(long)) { - long val = __Pyx_PyInt_AsLong(x); - if (unlikely(val != (long)(int)val)) { - if (!unlikely(val == -1 && PyErr_Occurred())) { - PyErr_SetString(PyExc_OverflowError, - (is_unsigned && unlikely(val < 0)) ? - "can't convert negative value to int" : - "value too large to convert to int"); - } - return (int)-1; - } - return (int)val; +static void __Pyx_AddTraceback(const char *funcname, int c_line, + int py_line, const char *filename) { + PyCodeObject *py_code = 0; + PyFrameObject *py_frame = 0; + PyThreadState *tstate = __Pyx_PyThreadState_Current; + if (c_line) { + c_line = __Pyx_CLineForTraceback(tstate, c_line); } - return (int)__Pyx_PyInt_AsLong(x); + py_code = __pyx_find_code_object(c_line ? -c_line : py_line); + if (!py_code) { + py_code = __Pyx_CreateCodeObjectForTraceback( + funcname, c_line, py_line, filename); + if (!py_code) goto bad; + __pyx_insert_code_object(c_line ? -c_line : py_line, py_code); + } + py_frame = PyFrame_New( + tstate, /*PyThreadState *tstate,*/ + py_code, /*PyCodeObject *code,*/ + __pyx_d, /*PyObject *globals,*/ + 0 /*PyObject *locals*/ + ); + if (!py_frame) goto bad; + __Pyx_PyFrame_SetLineNumber(py_frame, py_line); + PyTraceBack_Here(py_frame); +bad: + Py_XDECREF(py_code); + Py_XDECREF(py_frame); } -static CYTHON_INLINE unsigned long __Pyx_PyInt_AsUnsignedLong(PyObject* x) { - const unsigned long neg_one = (unsigned long)-1, const_zero = 0; +/* CIntToPy */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { + const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; const int is_unsigned = neg_one > const_zero; -#if PY_VERSION_HEX < 0x03000000 - if (likely(PyInt_Check(x))) { - long val = PyInt_AS_LONG(x); - if (is_unsigned && unlikely(val < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to unsigned long"); - return (unsigned long)-1; - } - return (unsigned long)val; - } else + if (is_unsigned) { + if (sizeof(long) < sizeof(long)) { + return PyInt_FromLong((long) value); + } else if (sizeof(long) <= sizeof(unsigned long)) { + return PyLong_FromUnsignedLong((unsigned long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); #endif - if (likely(PyLong_Check(x))) { - if (is_unsigned) { - if (unlikely(Py_SIZE(x) < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to unsigned long"); - return (unsigned long)-1; - } - return (unsigned long)PyLong_AsUnsignedLong(x); - } else { - return (unsigned long)PyLong_AsLong(x); } } else { - unsigned long val; - PyObject *tmp = __Pyx_PyNumber_Int(x); - if (!tmp) return (unsigned long)-1; - val = __Pyx_PyInt_AsUnsignedLong(tmp); - Py_DECREF(tmp); - return val; - } -} - -static CYTHON_INLINE unsigned PY_LONG_LONG __Pyx_PyInt_AsUnsignedLongLong(PyObject* x) { - const unsigned PY_LONG_LONG neg_one = (unsigned PY_LONG_LONG)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; -#if PY_VERSION_HEX < 0x03000000 - if (likely(PyInt_Check(x))) { - long val = PyInt_AS_LONG(x); - if (is_unsigned && unlikely(val < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to unsigned PY_LONG_LONG"); - return (unsigned PY_LONG_LONG)-1; - } - return (unsigned PY_LONG_LONG)val; - } else + if (sizeof(long) <= sizeof(long)) { + return PyInt_FromLong((long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { + return PyLong_FromLongLong((PY_LONG_LONG) value); #endif - if (likely(PyLong_Check(x))) { - if (is_unsigned) { - if (unlikely(Py_SIZE(x) < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to unsigned PY_LONG_LONG"); - return (unsigned PY_LONG_LONG)-1; - } - return (unsigned PY_LONG_LONG)PyLong_AsUnsignedLongLong(x); - } else { - return (unsigned PY_LONG_LONG)PyLong_AsLongLong(x); } - } else { - unsigned PY_LONG_LONG val; - PyObject *tmp = __Pyx_PyNumber_Int(x); - if (!tmp) return (unsigned PY_LONG_LONG)-1; - val = __Pyx_PyInt_AsUnsignedLongLong(tmp); - Py_DECREF(tmp); - return val; + } + { + int one = 1; int little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&value; + return _PyLong_FromByteArray(bytes, sizeof(long), + little, !is_unsigned); } } -static CYTHON_INLINE long __Pyx_PyInt_AsLong(PyObject* x) { - const long neg_one = (long)-1, const_zero = 0; +/* CIntFromPyVerify */ +#define __PYX_VERIFY_RETURN_INT(target_type, func_type, func_value)\ + __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 0) +#define __PYX_VERIFY_RETURN_INT_EXC(target_type, func_type, func_value)\ + __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 1) +#define __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, exc)\ + {\ + func_type value = func_value;\ + if (sizeof(target_type) < sizeof(func_type)) {\ + if (unlikely(value != (func_type) (target_type) value)) {\ + func_type zero = 0;\ + if (exc && unlikely(value == (func_type)-1 && PyErr_Occurred()))\ + return (target_type) -1;\ + if (is_unsigned && unlikely(value < zero))\ + goto raise_neg_overflow;\ + else\ + goto raise_overflow;\ + }\ + }\ + return (target_type) value;\ + } + +/* CIntFromPy */ +static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) { + const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; const int is_unsigned = neg_one > const_zero; -#if PY_VERSION_HEX < 0x03000000 +#if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x))) { - long val = PyInt_AS_LONG(x); - if (is_unsigned && unlikely(val < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to long"); - return (long)-1; + if (sizeof(long) < sizeof(long)) { + __PYX_VERIFY_RETURN_INT(long, long, PyInt_AS_LONG(x)) + } else { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + goto raise_neg_overflow; + } + return (long) val; } - return (long)val; } else #endif if (likely(PyLong_Check(x))) { if (is_unsigned) { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (long) 0; + case 1: __PYX_VERIFY_RETURN_INT(long, digit, digits[0]) + case 2: + if (8 * sizeof(long) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 2 * PyLong_SHIFT) { + return (long) (((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + case 3: + if (8 * sizeof(long) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 3 * PyLong_SHIFT) { + return (long) (((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + case 4: + if (8 * sizeof(long) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 4 * PyLong_SHIFT) { + return (long) (((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + } +#endif +#if CYTHON_COMPILING_IN_CPYTHON if (unlikely(Py_SIZE(x) < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to long"); - return (long)-1; + goto raise_neg_overflow; + } +#else + { + int result = PyObject_RichCompareBool(x, Py_False, Py_LT); + if (unlikely(result < 0)) + return (long) -1; + if (unlikely(result == 1)) + goto raise_neg_overflow; + } +#endif + if (sizeof(long) <= sizeof(unsigned long)) { + __PYX_VERIFY_RETURN_INT_EXC(long, unsigned long, PyLong_AsUnsignedLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(long, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) +#endif } - return (long)PyLong_AsUnsignedLong(x); } else { - return (long)PyLong_AsLong(x); +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (long) 0; + case -1: __PYX_VERIFY_RETURN_INT(long, sdigit, (sdigit) (-(sdigit)digits[0])) + case 1: __PYX_VERIFY_RETURN_INT(long, digit, +digits[0]) + case -2: + if (8 * sizeof(long) - 1 > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 2: + if (8 * sizeof(long) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + return (long) ((((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case -3: + if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 3: + if (8 * sizeof(long) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + return (long) ((((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case -4: + if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 4: + if (8 * sizeof(long) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { + return (long) ((((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + } +#endif + if (sizeof(long) <= sizeof(long)) { + __PYX_VERIFY_RETURN_INT_EXC(long, long, PyLong_AsLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(long, PY_LONG_LONG, PyLong_AsLongLong(x)) +#endif + } + } + { +#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) + PyErr_SetString(PyExc_RuntimeError, + "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); +#else + long val; + PyObject *v = __Pyx_PyNumber_IntOrLong(x); + #if PY_MAJOR_VERSION < 3 + if (likely(v) && !PyLong_Check(v)) { + PyObject *tmp = v; + v = PyNumber_Long(tmp); + Py_DECREF(tmp); + } + #endif + if (likely(v)) { + int one = 1; int is_little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&val; + int ret = _PyLong_AsByteArray((PyLongObject *)v, + bytes, sizeof(val), + is_little, !is_unsigned); + Py_DECREF(v); + if (likely(!ret)) + return val; + } +#endif + return (long) -1; } } else { long val; - PyObject *tmp = __Pyx_PyNumber_Int(x); - if (!tmp) return (long)-1; - val = __Pyx_PyInt_AsLong(tmp); + PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); + if (!tmp) return (long) -1; + val = __Pyx_PyInt_As_long(tmp); Py_DECREF(tmp); return val; } +raise_overflow: + PyErr_SetString(PyExc_OverflowError, + "value too large to convert to long"); + return (long) -1; +raise_neg_overflow: + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to long"); + return (long) -1; } -static CYTHON_INLINE PY_LONG_LONG __Pyx_PyInt_AsLongLong(PyObject* x) { - const PY_LONG_LONG neg_one = (PY_LONG_LONG)-1, const_zero = 0; +/* CIntFromPy */ +static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) { + const int neg_one = (int) ((int) 0 - (int) 1), const_zero = (int) 0; const int is_unsigned = neg_one > const_zero; -#if PY_VERSION_HEX < 0x03000000 +#if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x))) { - long val = PyInt_AS_LONG(x); - if (is_unsigned && unlikely(val < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to PY_LONG_LONG"); - return (PY_LONG_LONG)-1; + if (sizeof(int) < sizeof(long)) { + __PYX_VERIFY_RETURN_INT(int, long, PyInt_AS_LONG(x)) + } else { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + goto raise_neg_overflow; + } + return (int) val; } - return (PY_LONG_LONG)val; } else #endif if (likely(PyLong_Check(x))) { if (is_unsigned) { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (int) 0; + case 1: __PYX_VERIFY_RETURN_INT(int, digit, digits[0]) + case 2: + if (8 * sizeof(int) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 2 * PyLong_SHIFT) { + return (int) (((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + case 3: + if (8 * sizeof(int) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 3 * PyLong_SHIFT) { + return (int) (((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + case 4: + if (8 * sizeof(int) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 4 * PyLong_SHIFT) { + return (int) (((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + } +#endif +#if CYTHON_COMPILING_IN_CPYTHON if (unlikely(Py_SIZE(x) < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to PY_LONG_LONG"); - return (PY_LONG_LONG)-1; + goto raise_neg_overflow; + } +#else + { + int result = PyObject_RichCompareBool(x, Py_False, Py_LT); + if (unlikely(result < 0)) + return (int) -1; + if (unlikely(result == 1)) + goto raise_neg_overflow; + } +#endif + if (sizeof(int) <= sizeof(unsigned long)) { + __PYX_VERIFY_RETURN_INT_EXC(int, unsigned long, PyLong_AsUnsignedLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(int, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) +#endif } - return (PY_LONG_LONG)PyLong_AsUnsignedLongLong(x); } else { - return (PY_LONG_LONG)PyLong_AsLongLong(x); +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (int) 0; + case -1: __PYX_VERIFY_RETURN_INT(int, sdigit, (sdigit) (-(sdigit)digits[0])) + case 1: __PYX_VERIFY_RETURN_INT(int, digit, +digits[0]) + case -2: + if (8 * sizeof(int) - 1 > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 2: + if (8 * sizeof(int) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + return (int) ((((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case -3: + if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 3: + if (8 * sizeof(int) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + return (int) ((((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case -4: + if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 4: + if (8 * sizeof(int) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { + return (int) ((((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + } +#endif + if (sizeof(int) <= sizeof(long)) { + __PYX_VERIFY_RETURN_INT_EXC(int, long, PyLong_AsLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(int, PY_LONG_LONG, PyLong_AsLongLong(x)) +#endif + } + } + { +#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) + PyErr_SetString(PyExc_RuntimeError, + "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); +#else + int val; + PyObject *v = __Pyx_PyNumber_IntOrLong(x); + #if PY_MAJOR_VERSION < 3 + if (likely(v) && !PyLong_Check(v)) { + PyObject *tmp = v; + v = PyNumber_Long(tmp); + Py_DECREF(tmp); + } + #endif + if (likely(v)) { + int one = 1; int is_little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&val; + int ret = _PyLong_AsByteArray((PyLongObject *)v, + bytes, sizeof(val), + is_little, !is_unsigned); + Py_DECREF(v); + if (likely(!ret)) + return val; + } +#endif + return (int) -1; } } else { - PY_LONG_LONG val; - PyObject *tmp = __Pyx_PyNumber_Int(x); - if (!tmp) return (PY_LONG_LONG)-1; - val = __Pyx_PyInt_AsLongLong(tmp); + int val; + PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); + if (!tmp) return (int) -1; + val = __Pyx_PyInt_As_int(tmp); Py_DECREF(tmp); return val; } +raise_overflow: + PyErr_SetString(PyExc_OverflowError, + "value too large to convert to int"); + return (int) -1; +raise_neg_overflow: + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to int"); + return (int) -1; } -static CYTHON_INLINE signed long __Pyx_PyInt_AsSignedLong(PyObject* x) { - const signed long neg_one = (signed long)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; -#if PY_VERSION_HEX < 0x03000000 - if (likely(PyInt_Check(x))) { - long val = PyInt_AS_LONG(x); - if (is_unsigned && unlikely(val < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to signed long"); - return (signed long)-1; +/* FastTypeChecks */ +#if CYTHON_COMPILING_IN_CPYTHON +static int __Pyx_InBases(PyTypeObject *a, PyTypeObject *b) { + while (a) { + a = a->tp_base; + if (a == b) + return 1; + } + return b == &PyBaseObject_Type; +} +static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b) { + PyObject *mro; + if (a == b) return 1; + mro = a->tp_mro; + if (likely(mro)) { + Py_ssize_t i, n; + n = PyTuple_GET_SIZE(mro); + for (i = 0; i < n; i++) { + if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b) + return 1; } - return (signed long)val; - } else + return 0; + } + return __Pyx_InBases(a, b); +} +#if PY_MAJOR_VERSION == 2 +static int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject* exc_type2) { + PyObject *exception, *value, *tb; + int res; + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ErrFetch(&exception, &value, &tb); + res = exc_type1 ? PyObject_IsSubclass(err, exc_type1) : 0; + if (unlikely(res == -1)) { + PyErr_WriteUnraisable(err); + res = 0; + } + if (!res) { + res = PyObject_IsSubclass(err, exc_type2); + if (unlikely(res == -1)) { + PyErr_WriteUnraisable(err); + res = 0; + } + } + __Pyx_ErrRestore(exception, value, tb); + return res; +} +#else +static CYTHON_INLINE int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject *exc_type2) { + int res = exc_type1 ? __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type1) : 0; + if (!res) { + res = __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type2); + } + return res; +} #endif - if (likely(PyLong_Check(x))) { - if (is_unsigned) { - if (unlikely(Py_SIZE(x) < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to signed long"); - return (signed long)-1; - } - return (signed long)PyLong_AsUnsignedLong(x); +static int __Pyx_PyErr_GivenExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { + Py_ssize_t i, n; + assert(PyExceptionClass_Check(exc_type)); + n = PyTuple_GET_SIZE(tuple); +#if PY_MAJOR_VERSION >= 3 + for (i=0; i const_zero; -#if PY_VERSION_HEX < 0x03000000 - if (likely(PyInt_Check(x))) { - long val = PyInt_AS_LONG(x); - if (is_unsigned && unlikely(val < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to signed PY_LONG_LONG"); - return (signed PY_LONG_LONG)-1; - } - return (signed PY_LONG_LONG)val; - } else -#endif - if (likely(PyLong_Check(x))) { - if (is_unsigned) { - if (unlikely(Py_SIZE(x) < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to signed PY_LONG_LONG"); - return (signed PY_LONG_LONG)-1; - } - return (signed PY_LONG_LONG)PyLong_AsUnsignedLongLong(x); +static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject* exc_type) { + if (likely(err == exc_type)) return 1; + if (likely(PyExceptionClass_Check(err))) { + if (likely(PyExceptionClass_Check(exc_type))) { + return __Pyx_inner_PyErr_GivenExceptionMatches2(err, NULL, exc_type); + } else if (likely(PyTuple_Check(exc_type))) { + return __Pyx_PyErr_GivenExceptionMatchesTuple(err, exc_type); } else { - return (signed PY_LONG_LONG)PyLong_AsLongLong(x); } - } else { - signed PY_LONG_LONG val; - PyObject *tmp = __Pyx_PyNumber_Int(x); - if (!tmp) return (signed PY_LONG_LONG)-1; - val = __Pyx_PyInt_AsSignedLongLong(tmp); - Py_DECREF(tmp); - return val; } + return PyErr_GivenExceptionMatches(err, exc_type); +} +static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *exc_type1, PyObject *exc_type2) { + assert(PyExceptionClass_Check(exc_type1)); + assert(PyExceptionClass_Check(exc_type2)); + if (likely(err == exc_type1 || err == exc_type2)) return 1; + if (likely(PyExceptionClass_Check(err))) { + return __Pyx_inner_PyErr_GivenExceptionMatches2(err, exc_type1, exc_type2); + } + return (PyErr_GivenExceptionMatches(err, exc_type1) || PyErr_GivenExceptionMatches(err, exc_type2)); } +#endif +/* CheckBinaryVersion */ static int __Pyx_check_binary_version(void) { char ctversion[4], rtversion[4]; PyOS_snprintf(ctversion, 4, "%d.%d", PY_MAJOR_VERSION, PY_MINOR_VERSION); @@ -1014,86 +2245,12 @@ static int __Pyx_check_binary_version(void) { "compiletime version %s of module '%.100s' " "does not match runtime version %s", ctversion, __Pyx_MODULE_NAME, rtversion); - #if PY_VERSION_HEX < 0x02050000 - return PyErr_Warn(NULL, message); - #else return PyErr_WarnEx(NULL, message, 1); - #endif } return 0; } -#include "compile.h" -#include "frameobject.h" -#include "traceback.h" - -static void __Pyx_AddTraceback(const char *funcname, int __pyx_clineno, - int __pyx_lineno, const char *__pyx_filename) { - PyObject *py_srcfile = 0; - PyObject *py_funcname = 0; - PyObject *py_globals = 0; - PyCodeObject *py_code = 0; - PyFrameObject *py_frame = 0; - - #if PY_MAJOR_VERSION < 3 - py_srcfile = PyString_FromString(__pyx_filename); - #else - py_srcfile = PyUnicode_FromString(__pyx_filename); - #endif - if (!py_srcfile) goto bad; - if (__pyx_clineno) { - #if PY_MAJOR_VERSION < 3 - py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, __pyx_clineno); - #else - py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, __pyx_clineno); - #endif - } - else { - #if PY_MAJOR_VERSION < 3 - py_funcname = PyString_FromString(funcname); - #else - py_funcname = PyUnicode_FromString(funcname); - #endif - } - if (!py_funcname) goto bad; - py_globals = PyModule_GetDict(__pyx_m); - if (!py_globals) goto bad; - py_code = PyCode_New( - 0, /*int argcount,*/ - #if PY_MAJOR_VERSION >= 3 - 0, /*int kwonlyargcount,*/ - #endif - 0, /*int nlocals,*/ - 0, /*int stacksize,*/ - 0, /*int flags,*/ - __pyx_empty_bytes, /*PyObject *code,*/ - __pyx_empty_tuple, /*PyObject *consts,*/ - __pyx_empty_tuple, /*PyObject *names,*/ - __pyx_empty_tuple, /*PyObject *varnames,*/ - __pyx_empty_tuple, /*PyObject *freevars,*/ - __pyx_empty_tuple, /*PyObject *cellvars,*/ - py_srcfile, /*PyObject *filename,*/ - py_funcname, /*PyObject *name,*/ - __pyx_lineno, /*int firstlineno,*/ - __pyx_empty_bytes /*PyObject *lnotab*/ - ); - if (!py_code) goto bad; - py_frame = PyFrame_New( - PyThreadState_GET(), /*PyThreadState *tstate,*/ - py_code, /*PyCodeObject *code,*/ - py_globals, /*PyObject *globals,*/ - 0 /*PyObject *locals*/ - ); - if (!py_frame) goto bad; - py_frame->f_lineno = __pyx_lineno; - PyTraceBack_Here(py_frame); -bad: - Py_XDECREF(py_srcfile); - Py_XDECREF(py_funcname); - Py_XDECREF(py_code); - Py_XDECREF(py_frame); -} - +/* InitStrings */ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) { while (t->p) { #if PY_MAJOR_VERSION < 3 @@ -1104,7 +2261,7 @@ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) { } else { *t->p = PyString_FromStringAndSize(t->s, t->n - 1); } - #else /* Python 3+ has unicode identifiers */ + #else if (t->is_unicode | t->is_str) { if (t->intern) { *t->p = PyUnicode_InternFromString(t->s); @@ -1119,56 +2276,158 @@ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) { #endif if (!*t->p) return -1; + if (PyObject_Hash(*t->p) == -1) + return -1; ++t; } return 0; } -/* Type Conversion Functions */ - +static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char* c_str) { + return __Pyx_PyUnicode_FromStringAndSize(c_str, (Py_ssize_t)strlen(c_str)); +} +static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject* o) { + Py_ssize_t ignore; + return __Pyx_PyObject_AsStringAndSize(o, &ignore); +} +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT +#if !CYTHON_PEP393_ENABLED +static const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { + char* defenc_c; + PyObject* defenc = _PyUnicode_AsDefaultEncodedString(o, NULL); + if (!defenc) return NULL; + defenc_c = PyBytes_AS_STRING(defenc); +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + { + char* end = defenc_c + PyBytes_GET_SIZE(defenc); + char* c; + for (c = defenc_c; c < end; c++) { + if ((unsigned char) (*c) >= 128) { + PyUnicode_AsASCIIString(o); + return NULL; + } + } + } +#endif + *length = PyBytes_GET_SIZE(defenc); + return defenc_c; +} +#else +static CYTHON_INLINE const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { + if (unlikely(__Pyx_PyUnicode_READY(o) == -1)) return NULL; +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + if (likely(PyUnicode_IS_ASCII(o))) { + *length = PyUnicode_GET_LENGTH(o); + return PyUnicode_AsUTF8(o); + } else { + PyUnicode_AsASCIIString(o); + return NULL; + } +#else + return PyUnicode_AsUTF8AndSize(o, length); +#endif +} +#endif +#endif +static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_t *length) { +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT + if ( +#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + __Pyx_sys_getdefaultencoding_not_ascii && +#endif + PyUnicode_Check(o)) { + return __Pyx_PyUnicode_AsStringAndSize(o, length); + } else +#endif +#if (!CYTHON_COMPILING_IN_PYPY) || (defined(PyByteArray_AS_STRING) && defined(PyByteArray_GET_SIZE)) + if (PyByteArray_Check(o)) { + *length = PyByteArray_GET_SIZE(o); + return PyByteArray_AS_STRING(o); + } else +#endif + { + char* result; + int r = PyBytes_AsStringAndSize(o, &result, length); + if (unlikely(r < 0)) { + return NULL; + } else { + return result; + } + } +} static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) { int is_true = x == Py_True; if (is_true | (x == Py_False) | (x == Py_None)) return is_true; else return PyObject_IsTrue(x); } - -static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x) { +static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject* x) { + int retval; + if (unlikely(!x)) return -1; + retval = __Pyx_PyObject_IsTrue(x); + Py_DECREF(x); + return retval; +} +static PyObject* __Pyx_PyNumber_IntOrLongWrongResultType(PyObject* result, const char* type_name) { +#if PY_MAJOR_VERSION >= 3 + if (PyLong_Check(result)) { + if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, + "__int__ returned non-int (type %.200s). " + "The ability to return an instance of a strict subclass of int " + "is deprecated, and may be removed in a future version of Python.", + Py_TYPE(result)->tp_name)) { + Py_DECREF(result); + return NULL; + } + return result; + } +#endif + PyErr_Format(PyExc_TypeError, + "__%.4s__ returned non-%.4s (type %.200s)", + type_name, type_name, Py_TYPE(result)->tp_name); + Py_DECREF(result); + return NULL; +} +static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x) { +#if CYTHON_USE_TYPE_SLOTS PyNumberMethods *m; +#endif const char *name = NULL; PyObject *res = NULL; -#if PY_VERSION_HEX < 0x03000000 - if (PyInt_Check(x) || PyLong_Check(x)) +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_Check(x) || PyLong_Check(x))) #else - if (PyLong_Check(x)) + if (likely(PyLong_Check(x))) #endif - return Py_INCREF(x), x; + return __Pyx_NewRef(x); +#if CYTHON_USE_TYPE_SLOTS m = Py_TYPE(x)->tp_as_number; -#if PY_VERSION_HEX < 0x03000000 + #if PY_MAJOR_VERSION < 3 if (m && m->nb_int) { name = "int"; - res = PyNumber_Int(x); + res = m->nb_int(x); } else if (m && m->nb_long) { name = "long"; - res = PyNumber_Long(x); + res = m->nb_long(x); } -#else - if (m && m->nb_int) { + #else + if (likely(m && m->nb_int)) { name = "int"; - res = PyNumber_Long(x); + res = m->nb_int(x); + } + #endif +#else + if (!PyBytes_CheckExact(x) && !PyUnicode_CheckExact(x)) { + res = PyNumber_Int(x); } #endif - if (res) { -#if PY_VERSION_HEX < 0x03000000 - if (!PyInt_Check(res) && !PyLong_Check(res)) { + if (likely(res)) { +#if PY_MAJOR_VERSION < 3 + if (unlikely(!PyInt_Check(res) && !PyLong_Check(res))) { #else - if (!PyLong_Check(res)) { + if (unlikely(!PyLong_CheckExact(res))) { #endif - PyErr_Format(PyExc_TypeError, - "__%s__ returned non-%s (type %.200s)", - name, name, Py_TYPE(res)->tp_name); - Py_DECREF(res); - return NULL; + return __Pyx_PyNumber_IntOrLongWrongResultType(res, name); } } else if (!PyErr_Occurred()) { @@ -1177,40 +2436,73 @@ static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x) { } return res; } - static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { Py_ssize_t ival; - PyObject* x = PyNumber_Index(b); + PyObject *x; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_CheckExact(b))) { + if (sizeof(Py_ssize_t) >= sizeof(long)) + return PyInt_AS_LONG(b); + else + return PyInt_AsSsize_t(b); + } +#endif + if (likely(PyLong_CheckExact(b))) { + #if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)b)->ob_digit; + const Py_ssize_t size = Py_SIZE(b); + if (likely(__Pyx_sst_abs(size) <= 1)) { + ival = likely(size) ? digits[0] : 0; + if (size == -1) ival = -ival; + return ival; + } else { + switch (size) { + case 2: + if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { + return (Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -2: + if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case 3: + if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { + return (Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -3: + if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case 4: + if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { + return (Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -4: + if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + } + } + #endif + return PyLong_AsSsize_t(b); + } + x = PyNumber_Index(b); if (!x) return -1; ival = PyInt_AsSsize_t(x); Py_DECREF(x); return ival; } - -static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) { -#if PY_VERSION_HEX < 0x02050000 - if (ival <= LONG_MAX) - return PyInt_FromLong((long)ival); - else { - unsigned char *bytes = (unsigned char *) &ival; - int one = 1; int little = (int)*(unsigned char*)&one; - return _PyLong_FromByteArray(bytes, sizeof(size_t), little, 0); - } -#else - return PyInt_FromSize_t(ival); -#endif +static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b) { + return b ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False); } - -static CYTHON_INLINE size_t __Pyx_PyInt_AsSize_t(PyObject* x) { - unsigned PY_LONG_LONG val = __Pyx_PyInt_AsUnsignedLongLong(x); - if (unlikely(val == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())) { - return (size_t)-1; - } else if (unlikely(val != (unsigned PY_LONG_LONG)(size_t)val)) { - PyErr_SetString(PyExc_OverflowError, - "value too large to convert to size_t"); - return (size_t)-1; - } - return (size_t)val; +static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) { + return PyInt_FromSize_t(ival); } diff --git a/playground/cython/cython_cache/src/cy_cxxtest.cc b/playground/cython/cython_cache/src/cy_cxxtest.cc index a37b1b1798..0d56fbddb0 100644 --- a/playground/cython/cython_cache/src/cy_cxxtest.cc +++ b/playground/cython/cython_cache/src/cy_cxxtest.cc @@ -1,16 +1,19 @@ -/* Generated by Cython 0.15.1 on Tue May 29 23:42:45 2012 */ +/* Generated by Cython 0.29 */ #define PY_SSIZE_T_CLEAN #include "Python.h" #ifndef Py_PYTHON_H #error Python headers needed to compile C extensions, please install development version of Python. +#elif PY_VERSION_HEX < 0x02060000 || (0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000) + #error Cython requires Python 2.6+ or Python 3.3+. #else - -#include /* For offsetof */ +#define CYTHON_ABI "0_29" +#define CYTHON_HEX_VERSION 0x001D00F0 +#define CYTHON_FUTURE_DIVISION 0 +#include #ifndef offsetof -#define offsetof(type, member) ( (size_t) & ((type*)0) -> member ) + #define offsetof(type, member) ( (size_t) & ((type*)0) -> member ) #endif - #if !defined(WIN32) && !defined(MS_WINDOWS) #ifndef __stdcall #define __stdcall @@ -22,122 +25,508 @@ #define __fastcall #endif #endif - #ifndef DL_IMPORT #define DL_IMPORT(t) t #endif #ifndef DL_EXPORT #define DL_EXPORT(t) t #endif - +#define __PYX_COMMA , +#ifndef HAVE_LONG_LONG + #if PY_VERSION_HEX >= 0x02070000 + #define HAVE_LONG_LONG + #endif +#endif #ifndef PY_LONG_LONG #define PY_LONG_LONG LONG_LONG #endif - -#if PY_VERSION_HEX < 0x02040000 - #define METH_COEXIST 0 - #define PyDict_CheckExact(op) (Py_TYPE(op) == &PyDict_Type) - #define PyDict_Contains(d,o) PySequence_Contains(d,o) +#ifndef Py_HUGE_VAL + #define Py_HUGE_VAL HUGE_VAL #endif - -#if PY_VERSION_HEX < 0x02050000 - typedef int Py_ssize_t; - #define PY_SSIZE_T_MAX INT_MAX - #define PY_SSIZE_T_MIN INT_MIN - #define PY_FORMAT_SIZE_T "" - #define PyInt_FromSsize_t(z) PyInt_FromLong(z) - #define PyInt_AsSsize_t(o) __Pyx_PyInt_AsInt(o) - #define PyNumber_Index(o) PyNumber_Int(o) - #define PyIndex_Check(o) PyNumber_Check(o) - #define PyErr_WarnEx(category, message, stacklevel) PyErr_Warn(category, message) +#ifdef PYPY_VERSION + #define CYTHON_COMPILING_IN_PYPY 1 + #define CYTHON_COMPILING_IN_PYSTON 0 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #undef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 0 + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #if PY_VERSION_HEX < 0x03050000 + #undef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 0 + #elif !defined(CYTHON_USE_ASYNC_SLOTS) + #define CYTHON_USE_ASYNC_SLOTS 1 + #endif + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #undef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 0 + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #undef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 1 + #undef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 0 + #undef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 0 + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #undef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 0 + #undef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 0 + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 +#elif defined(PYSTON_VERSION) + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_PYSTON 1 + #define CYTHON_COMPILING_IN_CPYTHON 0 + #ifndef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #endif + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #undef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 0 + #undef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 0 + #ifndef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 1 + #endif + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #ifndef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 1 + #endif + #ifndef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 1 + #endif + #undef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 0 + #undef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 0 + #undef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT 0 + #undef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE 0 + #undef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS 0 + #undef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK 0 +#else + #define CYTHON_COMPILING_IN_PYPY 0 + #define CYTHON_COMPILING_IN_PYSTON 0 + #define CYTHON_COMPILING_IN_CPYTHON 1 + #ifndef CYTHON_USE_TYPE_SLOTS + #define CYTHON_USE_TYPE_SLOTS 1 + #endif + #if PY_VERSION_HEX < 0x02070000 + #undef CYTHON_USE_PYTYPE_LOOKUP + #define CYTHON_USE_PYTYPE_LOOKUP 0 + #elif !defined(CYTHON_USE_PYTYPE_LOOKUP) + #define CYTHON_USE_PYTYPE_LOOKUP 1 + #endif + #if PY_MAJOR_VERSION < 3 + #undef CYTHON_USE_ASYNC_SLOTS + #define CYTHON_USE_ASYNC_SLOTS 0 + #elif !defined(CYTHON_USE_ASYNC_SLOTS) + #define CYTHON_USE_ASYNC_SLOTS 1 + #endif + #if PY_VERSION_HEX < 0x02070000 + #undef CYTHON_USE_PYLONG_INTERNALS + #define CYTHON_USE_PYLONG_INTERNALS 0 + #elif !defined(CYTHON_USE_PYLONG_INTERNALS) + #define CYTHON_USE_PYLONG_INTERNALS 1 + #endif + #ifndef CYTHON_USE_PYLIST_INTERNALS + #define CYTHON_USE_PYLIST_INTERNALS 1 + #endif + #ifndef CYTHON_USE_UNICODE_INTERNALS + #define CYTHON_USE_UNICODE_INTERNALS 1 + #endif + #if PY_VERSION_HEX < 0x030300F0 + #undef CYTHON_USE_UNICODE_WRITER + #define CYTHON_USE_UNICODE_WRITER 0 + #elif !defined(CYTHON_USE_UNICODE_WRITER) + #define CYTHON_USE_UNICODE_WRITER 1 + #endif + #ifndef CYTHON_AVOID_BORROWED_REFS + #define CYTHON_AVOID_BORROWED_REFS 0 + #endif + #ifndef CYTHON_ASSUME_SAFE_MACROS + #define CYTHON_ASSUME_SAFE_MACROS 1 + #endif + #ifndef CYTHON_UNPACK_METHODS + #define CYTHON_UNPACK_METHODS 1 + #endif + #ifndef CYTHON_FAST_THREAD_STATE + #define CYTHON_FAST_THREAD_STATE 1 + #endif + #ifndef CYTHON_FAST_PYCALL + #define CYTHON_FAST_PYCALL 1 + #endif + #ifndef CYTHON_PEP489_MULTI_PHASE_INIT + #define CYTHON_PEP489_MULTI_PHASE_INIT (PY_VERSION_HEX >= 0x03050000) + #endif + #ifndef CYTHON_USE_TP_FINALIZE + #define CYTHON_USE_TP_FINALIZE (PY_VERSION_HEX >= 0x030400a1) + #endif + #ifndef CYTHON_USE_DICT_VERSIONS + #define CYTHON_USE_DICT_VERSIONS (PY_VERSION_HEX >= 0x030600B1) + #endif + #ifndef CYTHON_USE_EXC_INFO_STACK + #define CYTHON_USE_EXC_INFO_STACK (PY_VERSION_HEX >= 0x030700A3) + #endif +#endif +#if !defined(CYTHON_FAST_PYCCALL) +#define CYTHON_FAST_PYCCALL (CYTHON_FAST_PYCALL && PY_VERSION_HEX >= 0x030600B1) +#endif +#if CYTHON_USE_PYLONG_INTERNALS + #include "longintrepr.h" + #undef SHIFT + #undef BASE + #undef MASK +#endif +#ifndef __has_attribute + #define __has_attribute(x) 0 +#endif +#ifndef __has_cpp_attribute + #define __has_cpp_attribute(x) 0 +#endif +#ifndef CYTHON_RESTRICT + #if defined(__GNUC__) + #define CYTHON_RESTRICT __restrict__ + #elif defined(_MSC_VER) && _MSC_VER >= 1400 + #define CYTHON_RESTRICT __restrict + #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define CYTHON_RESTRICT restrict + #else + #define CYTHON_RESTRICT + #endif +#endif +#ifndef CYTHON_UNUSED +# if defined(__GNUC__) +# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +# define CYTHON_UNUSED __attribute__ ((__unused__)) +# else +# define CYTHON_UNUSED +# endif +# elif defined(__ICC) || (defined(__INTEL_COMPILER) && !defined(_MSC_VER)) +# define CYTHON_UNUSED __attribute__ ((__unused__)) +# else +# define CYTHON_UNUSED +# endif +#endif +#ifndef CYTHON_MAYBE_UNUSED_VAR +# if defined(__cplusplus) + template void CYTHON_MAYBE_UNUSED_VAR( const T& ) { } +# else +# define CYTHON_MAYBE_UNUSED_VAR(x) (void)(x) +# endif +#endif +#ifndef CYTHON_NCP_UNUSED +# if CYTHON_COMPILING_IN_CPYTHON +# define CYTHON_NCP_UNUSED +# else +# define CYTHON_NCP_UNUSED CYTHON_UNUSED +# endif +#endif +#define __Pyx_void_to_None(void_result) ((void)(void_result), Py_INCREF(Py_None), Py_None) +#ifdef _MSC_VER + #ifndef _MSC_STDINT_H_ + #if _MSC_VER < 1300 + typedef unsigned char uint8_t; + typedef unsigned int uint32_t; + #else + typedef unsigned __int8 uint8_t; + typedef unsigned __int32 uint32_t; + #endif + #endif +#else + #include +#endif +#ifndef CYTHON_FALLTHROUGH + #if defined(__cplusplus) && __cplusplus >= 201103L + #if __has_cpp_attribute(fallthrough) + #define CYTHON_FALLTHROUGH [[fallthrough]] + #elif __has_cpp_attribute(clang::fallthrough) + #define CYTHON_FALLTHROUGH [[clang::fallthrough]] + #elif __has_cpp_attribute(gnu::fallthrough) + #define CYTHON_FALLTHROUGH [[gnu::fallthrough]] + #endif + #endif + #ifndef CYTHON_FALLTHROUGH + #if __has_attribute(fallthrough) + #define CYTHON_FALLTHROUGH __attribute__((fallthrough)) + #else + #define CYTHON_FALLTHROUGH + #endif + #endif + #if defined(__clang__ ) && defined(__apple_build_version__) + #if __apple_build_version__ < 7000000 + #undef CYTHON_FALLTHROUGH + #define CYTHON_FALLTHROUGH + #endif + #endif #endif -#if PY_VERSION_HEX < 0x02060000 - #define Py_REFCNT(ob) (((PyObject*)(ob))->ob_refcnt) - #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) - #define Py_SIZE(ob) (((PyVarObject*)(ob))->ob_size) - #define PyVarObject_HEAD_INIT(type, size) \ - PyObject_HEAD_INIT(type) size, - #define PyType_Modified(t) - - typedef struct { - void *buf; - PyObject *obj; - Py_ssize_t len; - Py_ssize_t itemsize; - int readonly; - int ndim; - char *format; - Py_ssize_t *shape; - Py_ssize_t *strides; - Py_ssize_t *suboffsets; - void *internal; - } Py_buffer; - - #define PyBUF_SIMPLE 0 - #define PyBUF_WRITABLE 0x0001 - #define PyBUF_FORMAT 0x0004 - #define PyBUF_ND 0x0008 - #define PyBUF_STRIDES (0x0010 | PyBUF_ND) - #define PyBUF_C_CONTIGUOUS (0x0020 | PyBUF_STRIDES) - #define PyBUF_F_CONTIGUOUS (0x0040 | PyBUF_STRIDES) - #define PyBUF_ANY_CONTIGUOUS (0x0080 | PyBUF_STRIDES) - #define PyBUF_INDIRECT (0x0100 | PyBUF_STRIDES) - +#ifndef __cplusplus + #error "Cython files generated with the C++ option must be compiled with a C++ compiler." +#endif +#ifndef CYTHON_INLINE + #if defined(__clang__) + #define CYTHON_INLINE __inline__ __attribute__ ((__unused__)) + #else + #define CYTHON_INLINE inline + #endif #endif +template +void __Pyx_call_destructor(T& x) { + x.~T(); +} +template +class __Pyx_FakeReference { + public: + __Pyx_FakeReference() : ptr(NULL) { } + __Pyx_FakeReference(const T& ref) : ptr(const_cast(&ref)) { } + T *operator->() { return ptr; } + T *operator&() { return ptr; } + operator T&() { return *ptr; } + template bool operator ==(U other) { return *ptr == other; } + template bool operator !=(U other) { return *ptr != other; } + private: + T *ptr; +}; +#if CYTHON_COMPILING_IN_PYPY && PY_VERSION_HEX < 0x02070600 && !defined(Py_OptimizeFlag) + #define Py_OptimizeFlag 0 +#endif +#define __PYX_BUILD_PY_SSIZE_T "n" +#define CYTHON_FORMAT_SSIZE_T "z" #if PY_MAJOR_VERSION < 3 #define __Pyx_BUILTIN_MODULE_NAME "__builtin__" + #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ + PyCode_New(a+k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) + #define __Pyx_DefaultClassType PyClass_Type #else #define __Pyx_BUILTIN_MODULE_NAME "builtins" + #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)\ + PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) + #define __Pyx_DefaultClassType PyType_Type #endif - -#if PY_MAJOR_VERSION >= 3 +#ifndef Py_TPFLAGS_CHECKTYPES #define Py_TPFLAGS_CHECKTYPES 0 +#endif +#ifndef Py_TPFLAGS_HAVE_INDEX #define Py_TPFLAGS_HAVE_INDEX 0 #endif - -#if (PY_VERSION_HEX < 0x02060000) || (PY_MAJOR_VERSION >= 3) +#ifndef Py_TPFLAGS_HAVE_NEWBUFFER #define Py_TPFLAGS_HAVE_NEWBUFFER 0 #endif - +#ifndef Py_TPFLAGS_HAVE_FINALIZE + #define Py_TPFLAGS_HAVE_FINALIZE 0 +#endif +#ifndef METH_STACKLESS + #define METH_STACKLESS 0 +#endif +#if PY_VERSION_HEX <= 0x030700A3 || !defined(METH_FASTCALL) + #ifndef METH_FASTCALL + #define METH_FASTCALL 0x80 + #endif + typedef PyObject *(*__Pyx_PyCFunctionFast) (PyObject *self, PyObject *const *args, Py_ssize_t nargs); + typedef PyObject *(*__Pyx_PyCFunctionFastWithKeywords) (PyObject *self, PyObject *const *args, + Py_ssize_t nargs, PyObject *kwnames); +#else + #define __Pyx_PyCFunctionFast _PyCFunctionFast + #define __Pyx_PyCFunctionFastWithKeywords _PyCFunctionFastWithKeywords +#endif +#if CYTHON_FAST_PYCCALL +#define __Pyx_PyFastCFunction_Check(func)\ + ((PyCFunction_Check(func) && (METH_FASTCALL == (PyCFunction_GET_FLAGS(func) & ~(METH_CLASS | METH_STATIC | METH_COEXIST | METH_KEYWORDS | METH_STACKLESS))))) +#else +#define __Pyx_PyFastCFunction_Check(func) 0 +#endif +#if CYTHON_USE_DICT_VERSIONS +#define __PYX_GET_DICT_VERSION(dict) (((PyDictObject*)(dict))->ma_version_tag) +#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var)\ + (version_var) = __PYX_GET_DICT_VERSION(dict);\ + (cache_var) = (value); +#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) {\ + static PY_UINT64_T __pyx_dict_version = 0;\ + static PyObject *__pyx_dict_cached_value = NULL;\ + if (likely(__PYX_GET_DICT_VERSION(DICT) == __pyx_dict_version)) {\ + (VAR) = __pyx_dict_cached_value;\ + } else {\ + (VAR) = __pyx_dict_cached_value = (LOOKUP);\ + __pyx_dict_version = __PYX_GET_DICT_VERSION(DICT);\ + }\ + } +#else +#define __PYX_GET_DICT_VERSION(dict) (0) +#define __PYX_UPDATE_DICT_CACHE(dict, value, cache_var, version_var) +#define __PYX_PY_DICT_LOOKUP_IF_MODIFIED(VAR, DICT, LOOKUP) (VAR) = (LOOKUP); +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Malloc) + #define PyObject_Malloc(s) PyMem_Malloc(s) + #define PyObject_Free(p) PyMem_Free(p) + #define PyObject_Realloc(p) PyMem_Realloc(p) +#endif +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX < 0x030400A1 + #define PyMem_RawMalloc(n) PyMem_Malloc(n) + #define PyMem_RawRealloc(p, n) PyMem_Realloc(p, n) + #define PyMem_RawFree(p) PyMem_Free(p) +#endif +#if CYTHON_COMPILING_IN_PYSTON + #define __Pyx_PyCode_HasFreeVars(co) PyCode_HasFreeVars(co) + #define __Pyx_PyFrame_SetLineNumber(frame, lineno) PyFrame_SetLineNumber(frame, lineno) +#else + #define __Pyx_PyCode_HasFreeVars(co) (PyCode_GetNumFree(co) > 0) + #define __Pyx_PyFrame_SetLineNumber(frame, lineno) (frame)->f_lineno = (lineno) +#endif +#if !CYTHON_FAST_THREAD_STATE || PY_VERSION_HEX < 0x02070000 + #define __Pyx_PyThreadState_Current PyThreadState_GET() +#elif PY_VERSION_HEX >= 0x03060000 + #define __Pyx_PyThreadState_Current _PyThreadState_UncheckedGet() +#elif PY_VERSION_HEX >= 0x03000000 + #define __Pyx_PyThreadState_Current PyThreadState_GET() +#else + #define __Pyx_PyThreadState_Current _PyThreadState_Current +#endif +#if PY_VERSION_HEX < 0x030700A2 && !defined(PyThread_tss_create) && !defined(Py_tss_NEEDS_INIT) +#include "pythread.h" +#define Py_tss_NEEDS_INIT 0 +typedef int Py_tss_t; +static CYTHON_INLINE int PyThread_tss_create(Py_tss_t *key) { + *key = PyThread_create_key(); + return 0; // PyThread_create_key reports success always +} +static CYTHON_INLINE Py_tss_t * PyThread_tss_alloc(void) { + Py_tss_t *key = (Py_tss_t *)PyObject_Malloc(sizeof(Py_tss_t)); + *key = Py_tss_NEEDS_INIT; + return key; +} +static CYTHON_INLINE void PyThread_tss_free(Py_tss_t *key) { + PyObject_Free(key); +} +static CYTHON_INLINE int PyThread_tss_is_created(Py_tss_t *key) { + return *key != Py_tss_NEEDS_INIT; +} +static CYTHON_INLINE void PyThread_tss_delete(Py_tss_t *key) { + PyThread_delete_key(*key); + *key = Py_tss_NEEDS_INIT; +} +static CYTHON_INLINE int PyThread_tss_set(Py_tss_t *key, void *value) { + return PyThread_set_key_value(*key, value); +} +static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { + return PyThread_get_key_value(*key); +} +#endif // TSS (Thread Specific Storage) API +#if CYTHON_COMPILING_IN_CPYTHON || defined(_PyDict_NewPresized) +#define __Pyx_PyDict_NewPresized(n) ((n <= 8) ? PyDict_New() : _PyDict_NewPresized(n)) +#else +#define __Pyx_PyDict_NewPresized(n) PyDict_New() +#endif +#if PY_MAJOR_VERSION >= 3 || CYTHON_FUTURE_DIVISION + #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) + #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y) +#else + #define __Pyx_PyNumber_Divide(x,y) PyNumber_Divide(x,y) + #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceDivide(x,y) +#endif +#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x030500A1 && CYTHON_USE_UNICODE_INTERNALS +#define __Pyx_PyDict_GetItemStr(dict, name) _PyDict_GetItem_KnownHash(dict, name, ((PyASCIIObject *) name)->hash) +#else +#define __Pyx_PyDict_GetItemStr(dict, name) PyDict_GetItem(dict, name) +#endif +#if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND) + #define CYTHON_PEP393_ENABLED 1 + #define __Pyx_PyUnicode_READY(op) (likely(PyUnicode_IS_READY(op)) ?\ + 0 : _PyUnicode_Ready((PyObject *)(op))) + #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_LENGTH(u) + #define __Pyx_PyUnicode_READ_CHAR(u, i) PyUnicode_READ_CHAR(u, i) + #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) PyUnicode_MAX_CHAR_VALUE(u) + #define __Pyx_PyUnicode_KIND(u) PyUnicode_KIND(u) + #define __Pyx_PyUnicode_DATA(u) PyUnicode_DATA(u) + #define __Pyx_PyUnicode_READ(k, d, i) PyUnicode_READ(k, d, i) + #define __Pyx_PyUnicode_WRITE(k, d, i, ch) PyUnicode_WRITE(k, d, i, ch) + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != (likely(PyUnicode_IS_READY(u)) ? PyUnicode_GET_LENGTH(u) : PyUnicode_GET_SIZE(u))) +#else + #define CYTHON_PEP393_ENABLED 0 + #define PyUnicode_1BYTE_KIND 1 + #define PyUnicode_2BYTE_KIND 2 + #define PyUnicode_4BYTE_KIND 4 + #define __Pyx_PyUnicode_READY(op) (0) + #define __Pyx_PyUnicode_GET_LENGTH(u) PyUnicode_GET_SIZE(u) + #define __Pyx_PyUnicode_READ_CHAR(u, i) ((Py_UCS4)(PyUnicode_AS_UNICODE(u)[i])) + #define __Pyx_PyUnicode_MAX_CHAR_VALUE(u) ((sizeof(Py_UNICODE) == 2) ? 65535 : 1114111) + #define __Pyx_PyUnicode_KIND(u) (sizeof(Py_UNICODE)) + #define __Pyx_PyUnicode_DATA(u) ((void*)PyUnicode_AS_UNICODE(u)) + #define __Pyx_PyUnicode_READ(k, d, i) ((void)(k), (Py_UCS4)(((Py_UNICODE*)d)[i])) + #define __Pyx_PyUnicode_WRITE(k, d, i, ch) (((void)(k)), ((Py_UNICODE*)d)[i] = ch) + #define __Pyx_PyUnicode_IS_TRUE(u) (0 != PyUnicode_GET_SIZE(u)) +#endif +#if CYTHON_COMPILING_IN_PYPY + #define __Pyx_PyUnicode_Concat(a, b) PyNumber_Add(a, b) + #define __Pyx_PyUnicode_ConcatSafe(a, b) PyNumber_Add(a, b) +#else + #define __Pyx_PyUnicode_Concat(a, b) PyUnicode_Concat(a, b) + #define __Pyx_PyUnicode_ConcatSafe(a, b) ((unlikely((a) == Py_None) || unlikely((b) == Py_None)) ?\ + PyNumber_Add(a, b) : __Pyx_PyUnicode_Concat(a, b)) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyUnicode_Contains) + #define PyUnicode_Contains(u, s) PySequence_Contains(u, s) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyByteArray_Check) + #define PyByteArray_Check(obj) PyObject_TypeCheck(obj, &PyByteArray_Type) +#endif +#if CYTHON_COMPILING_IN_PYPY && !defined(PyObject_Format) + #define PyObject_Format(obj, fmt) PyObject_CallMethod(obj, "__format__", "O", fmt) +#endif +#define __Pyx_PyString_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyString_Check(b) && !PyString_CheckExact(b)))) ? PyNumber_Remainder(a, b) : __Pyx_PyString_Format(a, b)) +#define __Pyx_PyUnicode_FormatSafe(a, b) ((unlikely((a) == Py_None || (PyUnicode_Check(b) && !PyUnicode_CheckExact(b)))) ? PyNumber_Remainder(a, b) : PyUnicode_Format(a, b)) +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyString_Format(a, b) PyUnicode_Format(a, b) +#else + #define __Pyx_PyString_Format(a, b) PyString_Format(a, b) +#endif +#if PY_MAJOR_VERSION < 3 && !defined(PyObject_ASCII) + #define PyObject_ASCII(o) PyObject_Repr(o) +#endif #if PY_MAJOR_VERSION >= 3 #define PyBaseString_Type PyUnicode_Type #define PyStringObject PyUnicodeObject #define PyString_Type PyUnicode_Type #define PyString_Check PyUnicode_Check #define PyString_CheckExact PyUnicode_CheckExact + #define PyObject_Unicode PyObject_Str #endif - -#if PY_VERSION_HEX < 0x02060000 - #define PyBytesObject PyStringObject - #define PyBytes_Type PyString_Type - #define PyBytes_Check PyString_Check - #define PyBytes_CheckExact PyString_CheckExact - #define PyBytes_FromString PyString_FromString - #define PyBytes_FromStringAndSize PyString_FromStringAndSize - #define PyBytes_FromFormat PyString_FromFormat - #define PyBytes_DecodeEscape PyString_DecodeEscape - #define PyBytes_AsString PyString_AsString - #define PyBytes_AsStringAndSize PyString_AsStringAndSize - #define PyBytes_Size PyString_Size - #define PyBytes_AS_STRING PyString_AS_STRING - #define PyBytes_GET_SIZE PyString_GET_SIZE - #define PyBytes_Repr PyString_Repr - #define PyBytes_Concat PyString_Concat - #define PyBytes_ConcatAndDel PyString_ConcatAndDel -#endif - -#if PY_VERSION_HEX < 0x02060000 - #define PySet_Check(obj) PyObject_TypeCheck(obj, &PySet_Type) - #define PyFrozenSet_Check(obj) PyObject_TypeCheck(obj, &PyFrozenSet_Type) +#if PY_MAJOR_VERSION >= 3 + #define __Pyx_PyBaseString_Check(obj) PyUnicode_Check(obj) + #define __Pyx_PyBaseString_CheckExact(obj) PyUnicode_CheckExact(obj) +#else + #define __Pyx_PyBaseString_Check(obj) (PyString_Check(obj) || PyUnicode_Check(obj)) + #define __Pyx_PyBaseString_CheckExact(obj) (PyString_CheckExact(obj) || PyUnicode_CheckExact(obj)) #endif #ifndef PySet_CheckExact #define PySet_CheckExact(obj) (Py_TYPE(obj) == &PySet_Type) #endif - -#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type) - +#if CYTHON_ASSUME_SAFE_MACROS + #define __Pyx_PySequence_SIZE(seq) Py_SIZE(seq) +#else + #define __Pyx_PySequence_SIZE(seq) PySequence_Size(seq) +#endif #if PY_MAJOR_VERSION >= 3 #define PyIntObject PyLongObject #define PyInt_Type PyLong_Type @@ -153,13 +542,17 @@ #define PyInt_AsSsize_t PyLong_AsSsize_t #define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask #define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask + #define PyNumber_Int PyNumber_Long #endif - #if PY_MAJOR_VERSION >= 3 #define PyBoolObject PyLongObject #endif - -#if PY_VERSION_HEX < 0x03020000 +#if PY_MAJOR_VERSION >= 3 && CYTHON_COMPILING_IN_PYPY + #ifndef PyUnicode_InternFromString + #define PyUnicode_InternFromString(s) PyUnicode_FromString(s) + #endif +#endif +#if PY_VERSION_HEX < 0x030200A4 typedef long Py_hash_t; #define __Pyx_PyInt_FromHash_t PyInt_FromLong #define __Pyx_PyInt_AsHash_t PyInt_AsLong @@ -167,57 +560,54 @@ #define __Pyx_PyInt_FromHash_t PyInt_FromSsize_t #define __Pyx_PyInt_AsHash_t PyInt_AsSsize_t #endif - - #if PY_MAJOR_VERSION >= 3 - #define __Pyx_PyNumber_Divide(x,y) PyNumber_TrueDivide(x,y) - #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceTrueDivide(x,y) + #define __Pyx_PyMethod_New(func, self, klass) ((self) ? PyMethod_New(func, self) : (Py_INCREF(func), func)) #else - #define __Pyx_PyNumber_Divide(x,y) PyNumber_Divide(x,y) - #define __Pyx_PyNumber_InPlaceDivide(x,y) PyNumber_InPlaceDivide(x,y) + #define __Pyx_PyMethod_New(func, self, klass) PyMethod_New(func, self, klass) #endif - -#if (PY_MAJOR_VERSION < 3) || (PY_VERSION_HEX >= 0x03010300) - #define __Pyx_PySequence_GetSlice(obj, a, b) PySequence_GetSlice(obj, a, b) - #define __Pyx_PySequence_SetSlice(obj, a, b, value) PySequence_SetSlice(obj, a, b, value) - #define __Pyx_PySequence_DelSlice(obj, a, b) PySequence_DelSlice(obj, a, b) +#if CYTHON_USE_ASYNC_SLOTS + #if PY_VERSION_HEX >= 0x030500B1 + #define __Pyx_PyAsyncMethodsStruct PyAsyncMethods + #define __Pyx_PyType_AsAsync(obj) (Py_TYPE(obj)->tp_as_async) + #else + #define __Pyx_PyType_AsAsync(obj) ((__Pyx_PyAsyncMethodsStruct*) (Py_TYPE(obj)->tp_reserved)) + #endif #else - #define __Pyx_PySequence_GetSlice(obj, a, b) (unlikely(!(obj)) ? \ - (PyErr_SetString(PyExc_SystemError, "null argument to internal routine"), (PyObject*)0) : \ - (likely((obj)->ob_type->tp_as_mapping) ? (PySequence_GetSlice(obj, a, b)) : \ - (PyErr_Format(PyExc_TypeError, "'%.200s' object is unsliceable", (obj)->ob_type->tp_name), (PyObject*)0))) - #define __Pyx_PySequence_SetSlice(obj, a, b, value) (unlikely(!(obj)) ? \ - (PyErr_SetString(PyExc_SystemError, "null argument to internal routine"), -1) : \ - (likely((obj)->ob_type->tp_as_mapping) ? (PySequence_SetSlice(obj, a, b, value)) : \ - (PyErr_Format(PyExc_TypeError, "'%.200s' object doesn't support slice assignment", (obj)->ob_type->tp_name), -1))) - #define __Pyx_PySequence_DelSlice(obj, a, b) (unlikely(!(obj)) ? \ - (PyErr_SetString(PyExc_SystemError, "null argument to internal routine"), -1) : \ - (likely((obj)->ob_type->tp_as_mapping) ? (PySequence_DelSlice(obj, a, b)) : \ - (PyErr_Format(PyExc_TypeError, "'%.200s' object doesn't support slice deletion", (obj)->ob_type->tp_name), -1))) + #define __Pyx_PyType_AsAsync(obj) NULL #endif - -#if PY_MAJOR_VERSION >= 3 - #define PyMethod_New(func, self, klass) ((self) ? PyMethod_New(func, self) : PyInstanceMethod_New(func)) +#ifndef __Pyx_PyAsyncMethodsStruct + typedef struct { + unaryfunc am_await; + unaryfunc am_aiter; + unaryfunc am_anext; + } __Pyx_PyAsyncMethodsStruct; #endif -#if PY_VERSION_HEX < 0x02050000 - #define __Pyx_GetAttrString(o,n) PyObject_GetAttrString((o),((char *)(n))) - #define __Pyx_SetAttrString(o,n,a) PyObject_SetAttrString((o),((char *)(n)),(a)) - #define __Pyx_DelAttrString(o,n) PyObject_DelAttrString((o),((char *)(n))) +#if defined(WIN32) || defined(MS_WINDOWS) + #define _USE_MATH_DEFINES +#endif +#include +#ifdef NAN +#define __PYX_NAN() ((float) NAN) #else - #define __Pyx_GetAttrString(o,n) PyObject_GetAttrString((o),(n)) - #define __Pyx_SetAttrString(o,n,a) PyObject_SetAttrString((o),(n),(a)) - #define __Pyx_DelAttrString(o,n) PyObject_DelAttrString((o),(n)) +static CYTHON_INLINE float __PYX_NAN() { + float value; + memset(&value, 0xFF, sizeof(value)); + return value; +} #endif - -#if PY_VERSION_HEX < 0x02050000 - #define __Pyx_NAMESTR(n) ((char *)(n)) - #define __Pyx_DOCSTR(n) ((char *)(n)) +#if defined(__CYGWIN__) && defined(_LDBL_EQ_DBL) +#define __Pyx_truncl trunc #else - #define __Pyx_NAMESTR(n) (n) - #define __Pyx_DOCSTR(n) (n) +#define __Pyx_truncl truncl #endif + +#define __PYX_ERR(f_index, lineno, Ln_error) \ +{ \ + __pyx_filename = __pyx_f[f_index]; __pyx_lineno = lineno; __pyx_clineno = __LINE__; goto Ln_error; \ +} + #ifndef __PYX_EXTERN_C #ifdef __cplusplus #define __PYX_EXTERN_C extern "C" @@ -226,88 +616,210 @@ #endif #endif -#if defined(WIN32) || defined(MS_WINDOWS) -#define _USE_MATH_DEFINES -#endif -#include #define __PYX_HAVE__cy_cxxtest #define __PYX_HAVE_API__cy_cxxtest +/* Early includes */ #include "lib.h" #ifdef _OPENMP #include #endif /* _OPENMP */ -#ifdef PYREX_WITHOUT_ASSERTIONS +#if defined(PYREX_WITHOUT_ASSERTIONS) && !defined(CYTHON_WITHOUT_ASSERTIONS) #define CYTHON_WITHOUT_ASSERTIONS #endif - -/* inline attribute */ -#ifndef CYTHON_INLINE - #if defined(__GNUC__) - #define CYTHON_INLINE __inline__ - #elif defined(_MSC_VER) - #define CYTHON_INLINE __inline - #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L - #define CYTHON_INLINE inline - #else - #define CYTHON_INLINE - #endif +typedef struct {PyObject **p; const char *s; const Py_ssize_t n; const char* encoding; + const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; + +#define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0 +#define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT 0 +#define __PYX_DEFAULT_STRING_ENCODING "" +#define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString +#define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize +#define __Pyx_uchar_cast(c) ((unsigned char)c) +#define __Pyx_long_cast(x) ((long)x) +#define __Pyx_fits_Py_ssize_t(v, type, is_signed) (\ + (sizeof(type) < sizeof(Py_ssize_t)) ||\ + (sizeof(type) > sizeof(Py_ssize_t) &&\ + likely(v < (type)PY_SSIZE_T_MAX ||\ + v == (type)PY_SSIZE_T_MAX) &&\ + (!is_signed || likely(v > (type)PY_SSIZE_T_MIN ||\ + v == (type)PY_SSIZE_T_MIN))) ||\ + (sizeof(type) == sizeof(Py_ssize_t) &&\ + (is_signed || likely(v < (type)PY_SSIZE_T_MAX ||\ + v == (type)PY_SSIZE_T_MAX))) ) +static CYTHON_INLINE int __Pyx_is_valid_index(Py_ssize_t i, Py_ssize_t limit) { + return (size_t) i < (size_t) limit; +} +#if defined (__cplusplus) && __cplusplus >= 201103L + #include + #define __Pyx_sst_abs(value) std::abs(value) +#elif SIZEOF_INT >= SIZEOF_SIZE_T + #define __Pyx_sst_abs(value) abs(value) +#elif SIZEOF_LONG >= SIZEOF_SIZE_T + #define __Pyx_sst_abs(value) labs(value) +#elif defined (_MSC_VER) + #define __Pyx_sst_abs(value) ((Py_ssize_t)_abs64(value)) +#elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + #define __Pyx_sst_abs(value) llabs(value) +#elif defined (__GNUC__) + #define __Pyx_sst_abs(value) __builtin_llabs(value) +#else + #define __Pyx_sst_abs(value) ((value<0) ? -value : value) #endif - -/* unused attribute */ -#ifndef CYTHON_UNUSED -# if defined(__GNUC__) -# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) -# define CYTHON_UNUSED __attribute__ ((__unused__)) -# else -# define CYTHON_UNUSED -# endif -# elif defined(__ICC) || defined(__INTEL_COMPILER) -# define CYTHON_UNUSED __attribute__ ((__unused__)) -# else -# define CYTHON_UNUSED -# endif +static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject*); +static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t* length); +#define __Pyx_PyByteArray_FromString(s) PyByteArray_FromStringAndSize((const char*)s, strlen((const char*)s)) +#define __Pyx_PyByteArray_FromStringAndSize(s, l) PyByteArray_FromStringAndSize((const char*)s, l) +#define __Pyx_PyBytes_FromString PyBytes_FromString +#define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize +static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char*); +#if PY_MAJOR_VERSION < 3 + #define __Pyx_PyStr_FromString __Pyx_PyBytes_FromString + #define __Pyx_PyStr_FromStringAndSize __Pyx_PyBytes_FromStringAndSize +#else + #define __Pyx_PyStr_FromString __Pyx_PyUnicode_FromString + #define __Pyx_PyStr_FromStringAndSize __Pyx_PyUnicode_FromStringAndSize #endif - -typedef struct {PyObject **p; char *s; const long n; const char* encoding; const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; /*proto*/ - - -/* Type Conversion Predeclarations */ - -#define __Pyx_PyBytes_FromUString(s) PyBytes_FromString((char*)s) -#define __Pyx_PyBytes_AsUString(s) ((unsigned char*) PyBytes_AsString(s)) - -#define __Pyx_Owned_Py_None(b) (Py_INCREF(Py_None), Py_None) -#define __Pyx_PyBool_FromLong(b) ((b) ? (Py_INCREF(Py_True), Py_True) : (Py_INCREF(Py_False), Py_False)) +#define __Pyx_PyBytes_AsWritableString(s) ((char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsWritableSString(s) ((signed char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsWritableUString(s) ((unsigned char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsString(s) ((const char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsSString(s) ((const signed char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyBytes_AsUString(s) ((const unsigned char*) PyBytes_AS_STRING(s)) +#define __Pyx_PyObject_AsWritableString(s) ((char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsWritableSString(s) ((signed char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsWritableUString(s) ((unsigned char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsSString(s) ((const signed char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_AsUString(s) ((const unsigned char*) __Pyx_PyObject_AsString(s)) +#define __Pyx_PyObject_FromCString(s) __Pyx_PyObject_FromString((const char*)s) +#define __Pyx_PyBytes_FromCString(s) __Pyx_PyBytes_FromString((const char*)s) +#define __Pyx_PyByteArray_FromCString(s) __Pyx_PyByteArray_FromString((const char*)s) +#define __Pyx_PyStr_FromCString(s) __Pyx_PyStr_FromString((const char*)s) +#define __Pyx_PyUnicode_FromCString(s) __Pyx_PyUnicode_FromString((const char*)s) +static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u) { + const Py_UNICODE *u_end = u; + while (*u_end++) ; + return (size_t)(u_end - u - 1); +} +#define __Pyx_PyUnicode_FromUnicode(u) PyUnicode_FromUnicode(u, __Pyx_Py_UNICODE_strlen(u)) +#define __Pyx_PyUnicode_FromUnicodeAndLength PyUnicode_FromUnicode +#define __Pyx_PyUnicode_AsUnicode PyUnicode_AsUnicode +#define __Pyx_NewRef(obj) (Py_INCREF(obj), obj) +#define __Pyx_Owned_Py_None(b) __Pyx_NewRef(Py_None) +static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b); static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*); -static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x); - +static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject*); +static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x); +#define __Pyx_PySequence_Tuple(obj)\ + (likely(PyTuple_CheckExact(obj)) ? __Pyx_NewRef(obj) : PySequence_Tuple(obj)) static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*); static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t); -static CYTHON_INLINE size_t __Pyx_PyInt_AsSize_t(PyObject*); - +#if CYTHON_ASSUME_SAFE_MACROS #define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x)) +#else +#define __pyx_PyFloat_AsDouble(x) PyFloat_AsDouble(x) +#endif +#define __pyx_PyFloat_AsFloat(x) ((float) __pyx_PyFloat_AsDouble(x)) +#if PY_MAJOR_VERSION >= 3 +#define __Pyx_PyNumber_Int(x) (PyLong_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Long(x)) +#else +#define __Pyx_PyNumber_Int(x) (PyInt_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Int(x)) +#endif +#define __Pyx_PyNumber_Float(x) (PyFloat_CheckExact(x) ? __Pyx_NewRef(x) : PyNumber_Float(x)) +#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII +static int __Pyx_sys_getdefaultencoding_not_ascii; +static int __Pyx_init_sys_getdefaultencoding_params(void) { + PyObject* sys; + PyObject* default_encoding = NULL; + PyObject* ascii_chars_u = NULL; + PyObject* ascii_chars_b = NULL; + const char* default_encoding_c; + sys = PyImport_ImportModule("sys"); + if (!sys) goto bad; + default_encoding = PyObject_CallMethod(sys, (char*) "getdefaultencoding", NULL); + Py_DECREF(sys); + if (!default_encoding) goto bad; + default_encoding_c = PyBytes_AsString(default_encoding); + if (!default_encoding_c) goto bad; + if (strcmp(default_encoding_c, "ascii") == 0) { + __Pyx_sys_getdefaultencoding_not_ascii = 0; + } else { + char ascii_chars[128]; + int c; + for (c = 0; c < 128; c++) { + ascii_chars[c] = c; + } + __Pyx_sys_getdefaultencoding_not_ascii = 1; + ascii_chars_u = PyUnicode_DecodeASCII(ascii_chars, 128, NULL); + if (!ascii_chars_u) goto bad; + ascii_chars_b = PyUnicode_AsEncodedString(ascii_chars_u, default_encoding_c, NULL); + if (!ascii_chars_b || !PyBytes_Check(ascii_chars_b) || memcmp(ascii_chars, PyBytes_AS_STRING(ascii_chars_b), 128) != 0) { + PyErr_Format( + PyExc_ValueError, + "This module compiled with c_string_encoding=ascii, but default encoding '%.200s' is not a superset of ascii.", + default_encoding_c); + goto bad; + } + Py_DECREF(ascii_chars_u); + Py_DECREF(ascii_chars_b); + } + Py_DECREF(default_encoding); + return 0; +bad: + Py_XDECREF(default_encoding); + Py_XDECREF(ascii_chars_u); + Py_XDECREF(ascii_chars_b); + return -1; +} +#endif +#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT && PY_MAJOR_VERSION >= 3 +#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeUTF8(c_str, size, NULL) +#else +#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_Decode(c_str, size, __PYX_DEFAULT_STRING_ENCODING, NULL) +#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT +static char* __PYX_DEFAULT_STRING_ENCODING; +static int __Pyx_init_sys_getdefaultencoding_params(void) { + PyObject* sys; + PyObject* default_encoding = NULL; + char* default_encoding_c; + sys = PyImport_ImportModule("sys"); + if (!sys) goto bad; + default_encoding = PyObject_CallMethod(sys, (char*) (const char*) "getdefaultencoding", NULL); + Py_DECREF(sys); + if (!default_encoding) goto bad; + default_encoding_c = PyBytes_AsString(default_encoding); + if (!default_encoding_c) goto bad; + __PYX_DEFAULT_STRING_ENCODING = (char*) malloc(strlen(default_encoding_c) + 1); + if (!__PYX_DEFAULT_STRING_ENCODING) goto bad; + strcpy(__PYX_DEFAULT_STRING_ENCODING, default_encoding_c); + Py_DECREF(default_encoding); + return 0; +bad: + Py_XDECREF(default_encoding); + return -1; +} +#endif +#endif -#ifdef __GNUC__ - /* Test for GCC > 2.95 */ - #if __GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95)) - #define likely(x) __builtin_expect(!!(x), 1) - #define unlikely(x) __builtin_expect(!!(x), 0) - #else /* __GNUC__ > 2 ... */ - #define likely(x) (x) - #define unlikely(x) (x) - #endif /* __GNUC__ > 2 ... */ -#else /* __GNUC__ */ +/* Test for GCC > 2.95 */ +#if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && (__GNUC_MINOR__ > 95))) + #define likely(x) __builtin_expect(!!(x), 1) + #define unlikely(x) __builtin_expect(!!(x), 0) +#else /* !__GNUC__ or GCC < 2.95 */ #define likely(x) (x) #define unlikely(x) (x) #endif /* __GNUC__ */ - -static PyObject *__pyx_m; +static CYTHON_INLINE void __Pyx_pretend_to_initialize(void* ptr) { (void)ptr; } + +static PyObject *__pyx_m = NULL; +static PyObject *__pyx_d; static PyObject *__pyx_b; +static PyObject *__pyx_cython_runtime = NULL; static PyObject *__pyx_empty_tuple; static PyObject *__pyx_empty_bytes; +static PyObject *__pyx_empty_unicode; static int __pyx_lineno; static int __pyx_clineno = 0; static const char * __pyx_cfilenm= __FILE__; @@ -320,10 +832,11 @@ static const char *__pyx_f[] = { /*--- Type declarations ---*/ +/* --- Runtime support code (head) --- */ +/* Refnanny.proto */ #ifndef CYTHON_REFNANNY #define CYTHON_REFNANNY 0 #endif - #if CYTHON_REFNANNY typedef struct { void (*INCREF)(void*, PyObject*, int); @@ -334,10 +847,23 @@ static const char *__pyx_f[] = { void (*FinishContext)(void**); } __Pyx_RefNannyAPIStruct; static __Pyx_RefNannyAPIStruct *__Pyx_RefNanny = NULL; - static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); /*proto*/ + static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname); #define __Pyx_RefNannyDeclarations void *__pyx_refnanny = NULL; - #define __Pyx_RefNannySetupContext(name) __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__) - #define __Pyx_RefNannyFinishContext() __Pyx_RefNanny->FinishContext(&__pyx_refnanny) +#ifdef WITH_THREAD + #define __Pyx_RefNannySetupContext(name, acquire_gil)\ + if (acquire_gil) {\ + PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ + PyGILState_Release(__pyx_gilstate_save);\ + } else {\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__);\ + } +#else + #define __Pyx_RefNannySetupContext(name, acquire_gil)\ + __pyx_refnanny = __Pyx_RefNanny->SetupContext((name), __LINE__, __FILE__) +#endif + #define __Pyx_RefNannyFinishContext()\ + __Pyx_RefNanny->FinishContext(&__pyx_refnanny) #define __Pyx_INCREF(r) __Pyx_RefNanny->INCREF(__pyx_refnanny, (PyObject *)(r), __LINE__) #define __Pyx_DECREF(r) __Pyx_RefNanny->DECREF(__pyx_refnanny, (PyObject *)(r), __LINE__) #define __Pyx_GOTREF(r) __Pyx_RefNanny->GOTREF(__pyx_refnanny, (PyObject *)(r), __LINE__) @@ -348,7 +874,7 @@ static const char *__pyx_f[] = { #define __Pyx_XGIVEREF(r) do { if((r) != NULL) {__Pyx_GIVEREF(r);}} while(0) #else #define __Pyx_RefNannyDeclarations - #define __Pyx_RefNannySetupContext(name) + #define __Pyx_RefNannySetupContext(name, acquire_gil) #define __Pyx_RefNannyFinishContext() #define __Pyx_INCREF(r) Py_INCREF(r) #define __Pyx_DECREF(r) Py_DECREF(r) @@ -358,79 +884,166 @@ static const char *__pyx_f[] = { #define __Pyx_XDECREF(r) Py_XDECREF(r) #define __Pyx_XGOTREF(r) #define __Pyx_XGIVEREF(r) -#endif /* CYTHON_REFNANNY */ - -static int __Pyx_Print(PyObject*, PyObject *, int); /*proto*/ -#if PY_MAJOR_VERSION >= 3 -static PyObject* __pyx_print = 0; -static PyObject* __pyx_print_kwargs = 0; +#endif +#define __Pyx_XDECREF_SET(r, v) do {\ + PyObject *tmp = (PyObject *) r;\ + r = v; __Pyx_XDECREF(tmp);\ + } while (0) +#define __Pyx_DECREF_SET(r, v) do {\ + PyObject *tmp = (PyObject *) r;\ + r = v; __Pyx_DECREF(tmp);\ + } while (0) +#define __Pyx_CLEAR(r) do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0) +#define __Pyx_XCLEAR(r) do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0) + +/* PyThreadStateGet.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyThreadState_declare PyThreadState *__pyx_tstate; +#define __Pyx_PyThreadState_assign __pyx_tstate = __Pyx_PyThreadState_Current; +#define __Pyx_PyErr_Occurred() __pyx_tstate->curexc_type +#else +#define __Pyx_PyThreadState_declare +#define __Pyx_PyThreadState_assign +#define __Pyx_PyErr_Occurred() PyErr_Occurred() #endif -static int __Pyx_PrintOne(PyObject* stream, PyObject *o); /*proto*/ - -static CYTHON_INLINE unsigned char __Pyx_PyInt_AsUnsignedChar(PyObject *); - -static CYTHON_INLINE unsigned short __Pyx_PyInt_AsUnsignedShort(PyObject *); - -static CYTHON_INLINE unsigned int __Pyx_PyInt_AsUnsignedInt(PyObject *); - -static CYTHON_INLINE char __Pyx_PyInt_AsChar(PyObject *); - -static CYTHON_INLINE short __Pyx_PyInt_AsShort(PyObject *); - -static CYTHON_INLINE int __Pyx_PyInt_AsInt(PyObject *); - -static CYTHON_INLINE signed char __Pyx_PyInt_AsSignedChar(PyObject *); - -static CYTHON_INLINE signed short __Pyx_PyInt_AsSignedShort(PyObject *); - -static CYTHON_INLINE signed int __Pyx_PyInt_AsSignedInt(PyObject *); +/* PyErrFetchRestore.proto */ +#if CYTHON_FAST_THREAD_STATE +#define __Pyx_PyErr_Clear() __Pyx_ErrRestore(NULL, NULL, NULL) +#define __Pyx_ErrRestoreWithState(type, value, tb) __Pyx_ErrRestoreInState(PyThreadState_GET(), type, value, tb) +#define __Pyx_ErrFetchWithState(type, value, tb) __Pyx_ErrFetchInState(PyThreadState_GET(), type, value, tb) +#define __Pyx_ErrRestore(type, value, tb) __Pyx_ErrRestoreInState(__pyx_tstate, type, value, tb) +#define __Pyx_ErrFetch(type, value, tb) __Pyx_ErrFetchInState(__pyx_tstate, type, value, tb) +static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb); +static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb); +#if CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_PyErr_SetNone(exc) (Py_INCREF(exc), __Pyx_ErrRestore((exc), NULL, NULL)) +#else +#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) +#endif +#else +#define __Pyx_PyErr_Clear() PyErr_Clear() +#define __Pyx_PyErr_SetNone(exc) PyErr_SetNone(exc) +#define __Pyx_ErrRestoreWithState(type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetchWithState(type, value, tb) PyErr_Fetch(type, value, tb) +#define __Pyx_ErrRestoreInState(tstate, type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetchInState(tstate, type, value, tb) PyErr_Fetch(type, value, tb) +#define __Pyx_ErrRestore(type, value, tb) PyErr_Restore(type, value, tb) +#define __Pyx_ErrFetch(type, value, tb) PyErr_Fetch(type, value, tb) +#endif -static CYTHON_INLINE int __Pyx_PyInt_AsLongDouble(PyObject *); +/* WriteUnraisableException.proto */ +static void __Pyx_WriteUnraisable(const char *name, int clineno, + int lineno, const char *filename, + int full_traceback, int nogil); -static CYTHON_INLINE unsigned long __Pyx_PyInt_AsUnsignedLong(PyObject *); +/* PyObjectGetAttrStr.proto */ +#if CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name); +#else +#define __Pyx_PyObject_GetAttrStr(o,n) PyObject_GetAttr(o,n) +#endif -static CYTHON_INLINE unsigned PY_LONG_LONG __Pyx_PyInt_AsUnsignedLongLong(PyObject *); +/* CLineInTraceback.proto */ +#ifdef CYTHON_CLINE_IN_TRACEBACK +#define __Pyx_CLineForTraceback(tstate, c_line) (((CYTHON_CLINE_IN_TRACEBACK)) ? c_line : 0) +#else +static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line); +#endif -static CYTHON_INLINE long __Pyx_PyInt_AsLong(PyObject *); +/* CodeObjectCache.proto */ +typedef struct { + PyCodeObject* code_object; + int code_line; +} __Pyx_CodeObjectCacheEntry; +struct __Pyx_CodeObjectCache { + int count; + int max_count; + __Pyx_CodeObjectCacheEntry* entries; +}; +static struct __Pyx_CodeObjectCache __pyx_code_cache = {0,0,NULL}; +static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line); +static PyCodeObject *__pyx_find_code_object(int code_line); +static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object); + +/* AddTraceback.proto */ +static void __Pyx_AddTraceback(const char *funcname, int c_line, + int py_line, const char *filename); + +/* Print.proto */ +static int __Pyx_Print(PyObject*, PyObject *, int); +#if CYTHON_COMPILING_IN_PYPY || PY_MAJOR_VERSION >= 3 +static PyObject* __pyx_print = 0; +static PyObject* __pyx_print_kwargs = 0; +#endif -static CYTHON_INLINE PY_LONG_LONG __Pyx_PyInt_AsLongLong(PyObject *); +/* PrintOne.proto */ +static int __Pyx_PrintOne(PyObject* stream, PyObject *o); -static CYTHON_INLINE signed long __Pyx_PyInt_AsSignedLong(PyObject *); +/* CIntToPy.proto */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value); -static CYTHON_INLINE signed PY_LONG_LONG __Pyx_PyInt_AsSignedLongLong(PyObject *); +/* CIntFromPy.proto */ +static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *); -static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/ -static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/ +/* CIntFromPy.proto */ +static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *); -static void __Pyx_WriteUnraisable(const char *name, int clineno, - int lineno, const char *filename); /*proto*/ +/* FastTypeChecks.proto */ +#if CYTHON_COMPILING_IN_CPYTHON +#define __Pyx_TypeCheck(obj, type) __Pyx_IsSubtype(Py_TYPE(obj), (PyTypeObject *)type) +static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b); +static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject *type); +static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *type1, PyObject *type2); +#else +#define __Pyx_TypeCheck(obj, type) PyObject_TypeCheck(obj, (PyTypeObject *)type) +#define __Pyx_PyErr_GivenExceptionMatches(err, type) PyErr_GivenExceptionMatches(err, type) +#define __Pyx_PyErr_GivenExceptionMatches2(err, type1, type2) (PyErr_GivenExceptionMatches(err, type1) || PyErr_GivenExceptionMatches(err, type2)) +#endif +#define __Pyx_PyException_Check(obj) __Pyx_TypeCheck(obj, PyExc_Exception) +/* CheckBinaryVersion.proto */ static int __Pyx_check_binary_version(void); -static int __Pyx_ExportFunction(const char *name, void (*f)(void), const char *sig); /*proto*/ +/* FunctionExport.proto */ +static int __Pyx_ExportFunction(const char *name, void (*f)(void), const char *sig); -static void __Pyx_AddTraceback(const char *funcname, int __pyx_clineno, - int __pyx_lineno, const char *__pyx_filename); /*proto*/ +/* InitStrings.proto */ +static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); -static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/ /* Module declarations from 'cy_cxxtest' */ -__PYX_EXTERN_C DL_EXPORT(void) cy_hello(void); /*proto*/ +__PYX_EXTERN_C void cy_hello(void); /*proto*/ #define __Pyx_MODULE_NAME "cy_cxxtest" +extern int __pyx_module_is_main_cy_cxxtest; int __pyx_module_is_main_cy_cxxtest = 0; /* Implementation of 'cy_cxxtest' */ -static char __pyx_k_1[] = "hello cython-world!"; -static char __pyx_k__pyhello[] = "pyhello"; -static char __pyx_k____main__[] = "__main__"; -static char __pyx_k____test__[] = "__test__"; -static char __pyx_k__cy_cxxtest[] = "cy_cxxtest"; -static PyObject *__pyx_kp_s_1; -static PyObject *__pyx_n_s____main__; -static PyObject *__pyx_n_s____test__; -static PyObject *__pyx_n_s__cy_cxxtest; -static PyObject *__pyx_n_s__pyhello; +static const char __pyx_k_end[] = "end"; +static const char __pyx_k_file[] = "file"; +static const char __pyx_k_main[] = "__main__"; +static const char __pyx_k_name[] = "__name__"; +static const char __pyx_k_test[] = "__test__"; +static const char __pyx_k_print[] = "print"; +static const char __pyx_k_pyhello[] = "pyhello"; +static const char __pyx_k_cy_cxxtest[] = "cy_cxxtest"; +static const char __pyx_k_cline_in_traceback[] = "cline_in_traceback"; +static const char __pyx_k_hello_cython_world[] = "hello cython-world!"; +static const char __pyx_k_home_romain_dev_waf_wrapper_waf[] = "/home/romain/dev/waf-wrapper/waf/playground/cython/src/cy_cxxtest.pyx"; +static PyObject *__pyx_n_s_cline_in_traceback; +static PyObject *__pyx_n_s_cy_cxxtest; +static PyObject *__pyx_n_s_end; +static PyObject *__pyx_n_s_file; +static PyObject *__pyx_kp_s_hello_cython_world; +static PyObject *__pyx_kp_s_home_romain_dev_waf_wrapper_waf; +static PyObject *__pyx_n_s_main; +static PyObject *__pyx_n_s_name; +static PyObject *__pyx_n_s_print; +static PyObject *__pyx_n_s_pyhello; +static PyObject *__pyx_n_s_test; +static PyObject *__pyx_pf_10cy_cxxtest_pyhello(CYTHON_UNUSED PyObject *__pyx_self); /* proto */ +static PyObject *__pyx_codeobj_; +/* Late includes */ /* "cy_cxxtest.pyx":3 * cimport cy_cxxtest @@ -440,16 +1053,27 @@ static PyObject *__pyx_n_s__pyhello; * */ -static PyObject *__pyx_pf_10cy_cxxtest_pyhello(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused); /*proto*/ -static PyMethodDef __pyx_mdef_10cy_cxxtest_pyhello = {__Pyx_NAMESTR("pyhello"), (PyCFunction)__pyx_pf_10cy_cxxtest_pyhello, METH_NOARGS, __Pyx_DOCSTR(0)}; -static PyObject *__pyx_pf_10cy_cxxtest_pyhello(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused) { - PyObject *__pyx_r = NULL; +/* Python wrapper */ +static PyObject *__pyx_pw_10cy_cxxtest_1pyhello(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused); /*proto*/ +static PyMethodDef __pyx_mdef_10cy_cxxtest_1pyhello = {"pyhello", (PyCFunction)__pyx_pw_10cy_cxxtest_1pyhello, METH_NOARGS, 0}; +static PyObject *__pyx_pw_10cy_cxxtest_1pyhello(PyObject *__pyx_self, CYTHON_UNUSED PyObject *unused) { + PyObject *__pyx_r = 0; __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("pyhello"); - __pyx_self = __pyx_self; + __Pyx_RefNannySetupContext("pyhello (wrapper)", 0); + __pyx_r = __pyx_pf_10cy_cxxtest_pyhello(__pyx_self); - /* "cy_cxxtest.pyx":4 - * + /* function exit code */ + __Pyx_RefNannyFinishContext(); + return __pyx_r; +} + +static PyObject *__pyx_pf_10cy_cxxtest_pyhello(CYTHON_UNUSED PyObject *__pyx_self) { + PyObject *__pyx_r = NULL; + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("pyhello", 0); + + /* "cy_cxxtest.pyx":4 + * * def pyhello(): * cy_cxxtest.hello() # <<<<<<<<<<<<<< * @@ -457,6 +1081,15 @@ static PyObject *__pyx_pf_10cy_cxxtest_pyhello(PyObject *__pyx_self, CYTHON_UNUS */ hello(); + /* "cy_cxxtest.pyx":3 + * cimport cy_cxxtest + * + * def pyhello(): # <<<<<<<<<<<<<< + * cy_cxxtest.hello() + * + */ + + /* function exit code */ __pyx_r = Py_None; __Pyx_INCREF(Py_None); __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); @@ -473,10 +1106,7 @@ static PyObject *__pyx_pf_10cy_cxxtest_pyhello(PyObject *__pyx_self, CYTHON_UNUS void cy_hello(void) { __Pyx_RefNannyDeclarations - int __pyx_lineno = 0; - const char *__pyx_filename = NULL; - int __pyx_clineno = 0; - __Pyx_RefNannySetupContext("cy_hello"); + __Pyx_RefNannySetupContext("cy_hello", 0); /* "cy_cxxtest.pyx":7 * @@ -484,11 +1114,20 @@ void cy_hello(void) { * print("hello cython-world!") # <<<<<<<<<<<<<< * */ - if (__Pyx_PrintOne(0, ((PyObject *)__pyx_kp_s_1)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 7; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__Pyx_PrintOne(0, __pyx_kp_s_hello_cython_world) < 0) __PYX_ERR(0, 7, __pyx_L1_error) + + /* "cy_cxxtest.pyx":6 + * cy_cxxtest.hello() + * + * cdef public api void cy_hello(): # <<<<<<<<<<<<<< + * print("hello cython-world!") + * + */ + /* function exit code */ goto __pyx_L0; __pyx_L1_error:; - __Pyx_WriteUnraisable("cy_cxxtest.cy_hello", __pyx_clineno, __pyx_lineno, __pyx_filename); + __Pyx_WriteUnraisable("cy_cxxtest.cy_hello", __pyx_clineno, __pyx_lineno, __pyx_filename, 1, 0); __pyx_L0:; __Pyx_RefNannyFinishContext(); } @@ -498,70 +1137,293 @@ static PyMethodDef __pyx_methods[] = { }; #if PY_MAJOR_VERSION >= 3 +#if CYTHON_PEP489_MULTI_PHASE_INIT +static PyObject* __pyx_pymod_create(PyObject *spec, PyModuleDef *def); /*proto*/ +static int __pyx_pymod_exec_cy_cxxtest(PyObject* module); /*proto*/ +static PyModuleDef_Slot __pyx_moduledef_slots[] = { + {Py_mod_create, (void*)__pyx_pymod_create}, + {Py_mod_exec, (void*)__pyx_pymod_exec_cy_cxxtest}, + {0, NULL} +}; +#endif + static struct PyModuleDef __pyx_moduledef = { PyModuleDef_HEAD_INIT, - __Pyx_NAMESTR("cy_cxxtest"), + "cy_cxxtest", 0, /* m_doc */ + #if CYTHON_PEP489_MULTI_PHASE_INIT + 0, /* m_size */ + #else -1, /* m_size */ + #endif __pyx_methods /* m_methods */, + #if CYTHON_PEP489_MULTI_PHASE_INIT + __pyx_moduledef_slots, /* m_slots */ + #else NULL, /* m_reload */ + #endif NULL, /* m_traverse */ NULL, /* m_clear */ NULL /* m_free */ }; #endif +#ifndef CYTHON_SMALL_CODE +#if defined(__clang__) + #define CYTHON_SMALL_CODE +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) + #define CYTHON_SMALL_CODE __attribute__((cold)) +#else + #define CYTHON_SMALL_CODE +#endif +#endif static __Pyx_StringTabEntry __pyx_string_tab[] = { - {&__pyx_kp_s_1, __pyx_k_1, sizeof(__pyx_k_1), 0, 0, 1, 0}, - {&__pyx_n_s____main__, __pyx_k____main__, sizeof(__pyx_k____main__), 0, 0, 1, 1}, - {&__pyx_n_s____test__, __pyx_k____test__, sizeof(__pyx_k____test__), 0, 0, 1, 1}, - {&__pyx_n_s__cy_cxxtest, __pyx_k__cy_cxxtest, sizeof(__pyx_k__cy_cxxtest), 0, 0, 1, 1}, - {&__pyx_n_s__pyhello, __pyx_k__pyhello, sizeof(__pyx_k__pyhello), 0, 0, 1, 1}, + {&__pyx_n_s_cline_in_traceback, __pyx_k_cline_in_traceback, sizeof(__pyx_k_cline_in_traceback), 0, 0, 1, 1}, + {&__pyx_n_s_cy_cxxtest, __pyx_k_cy_cxxtest, sizeof(__pyx_k_cy_cxxtest), 0, 0, 1, 1}, + {&__pyx_n_s_end, __pyx_k_end, sizeof(__pyx_k_end), 0, 0, 1, 1}, + {&__pyx_n_s_file, __pyx_k_file, sizeof(__pyx_k_file), 0, 0, 1, 1}, + {&__pyx_kp_s_hello_cython_world, __pyx_k_hello_cython_world, sizeof(__pyx_k_hello_cython_world), 0, 0, 1, 0}, + {&__pyx_kp_s_home_romain_dev_waf_wrapper_waf, __pyx_k_home_romain_dev_waf_wrapper_waf, sizeof(__pyx_k_home_romain_dev_waf_wrapper_waf), 0, 0, 1, 0}, + {&__pyx_n_s_main, __pyx_k_main, sizeof(__pyx_k_main), 0, 0, 1, 1}, + {&__pyx_n_s_name, __pyx_k_name, sizeof(__pyx_k_name), 0, 0, 1, 1}, + {&__pyx_n_s_print, __pyx_k_print, sizeof(__pyx_k_print), 0, 0, 1, 1}, + {&__pyx_n_s_pyhello, __pyx_k_pyhello, sizeof(__pyx_k_pyhello), 0, 0, 1, 1}, + {&__pyx_n_s_test, __pyx_k_test, sizeof(__pyx_k_test), 0, 0, 1, 1}, {0, 0, 0, 0, 0, 0, 0} }; -static int __Pyx_InitCachedBuiltins(void) { +static CYTHON_SMALL_CODE int __Pyx_InitCachedBuiltins(void) { return 0; } -static int __Pyx_InitCachedConstants(void) { +static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { __Pyx_RefNannyDeclarations - __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants"); + __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0); + + /* "cy_cxxtest.pyx":3 + * cimport cy_cxxtest + * + * def pyhello(): # <<<<<<<<<<<<<< + * cy_cxxtest.hello() + * + */ + __pyx_codeobj_ = (PyObject*)__Pyx_PyCode_New(0, 0, 0, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_romain_dev_waf_wrapper_waf, __pyx_n_s_pyhello, 3, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj_)) __PYX_ERR(0, 3, __pyx_L1_error) __Pyx_RefNannyFinishContext(); return 0; + __pyx_L1_error:; + __Pyx_RefNannyFinishContext(); + return -1; } -static int __Pyx_InitGlobals(void) { - if (__Pyx_InitStrings(__pyx_string_tab) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; +static CYTHON_SMALL_CODE int __Pyx_InitGlobals(void) { + if (__Pyx_InitStrings(__pyx_string_tab) < 0) __PYX_ERR(0, 1, __pyx_L1_error); return 0; __pyx_L1_error:; return -1; } +static CYTHON_SMALL_CODE int __Pyx_modinit_global_init_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_variable_export_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_function_export_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_type_init_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_type_import_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_variable_import_code(void); /*proto*/ +static CYTHON_SMALL_CODE int __Pyx_modinit_function_import_code(void); /*proto*/ + +static int __Pyx_modinit_global_init_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_global_init_code", 0); + /*--- Global init code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_variable_export_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_variable_export_code", 0); + /*--- Variable export code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_function_export_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_function_export_code", 0); + /*--- Function export code ---*/ + if (__Pyx_ExportFunction("cy_hello", (void (*)(void))cy_hello, "void (void)") < 0) __PYX_ERR(0, 1, __pyx_L1_error) + __Pyx_RefNannyFinishContext(); + return 0; + __pyx_L1_error:; + __Pyx_RefNannyFinishContext(); + return -1; +} + +static int __Pyx_modinit_type_init_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_type_init_code", 0); + /*--- Type init code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_type_import_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_type_import_code", 0); + /*--- Type import code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_variable_import_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_variable_import_code", 0); + /*--- Variable import code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + +static int __Pyx_modinit_function_import_code(void) { + __Pyx_RefNannyDeclarations + __Pyx_RefNannySetupContext("__Pyx_modinit_function_import_code", 0); + /*--- Function import code ---*/ + __Pyx_RefNannyFinishContext(); + return 0; +} + + #if PY_MAJOR_VERSION < 3 -PyMODINIT_FUNC initcy_cxxtest(void); /*proto*/ -PyMODINIT_FUNC initcy_cxxtest(void) +#ifdef CYTHON_NO_PYINIT_EXPORT +#define __Pyx_PyMODINIT_FUNC void +#else +#define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC +#endif #else -PyMODINIT_FUNC PyInit_cy_cxxtest(void); /*proto*/ -PyMODINIT_FUNC PyInit_cy_cxxtest(void) +#ifdef CYTHON_NO_PYINIT_EXPORT +#define __Pyx_PyMODINIT_FUNC PyObject * +#else +#define __Pyx_PyMODINIT_FUNC PyMODINIT_FUNC +#endif +#endif + + +#if PY_MAJOR_VERSION < 3 +__Pyx_PyMODINIT_FUNC initcy_cxxtest(void) CYTHON_SMALL_CODE; /*proto*/ +__Pyx_PyMODINIT_FUNC initcy_cxxtest(void) +#else +__Pyx_PyMODINIT_FUNC PyInit_cy_cxxtest(void) CYTHON_SMALL_CODE; /*proto*/ +__Pyx_PyMODINIT_FUNC PyInit_cy_cxxtest(void) +#if CYTHON_PEP489_MULTI_PHASE_INIT +{ + return PyModuleDef_Init(&__pyx_moduledef); +} +static CYTHON_SMALL_CODE int __Pyx_check_single_interpreter(void) { + #if PY_VERSION_HEX >= 0x030700A1 + static PY_INT64_T main_interpreter_id = -1; + PY_INT64_T current_id = PyInterpreterState_GetID(PyThreadState_Get()->interp); + if (main_interpreter_id == -1) { + main_interpreter_id = current_id; + return (unlikely(current_id == -1)) ? -1 : 0; + } else if (unlikely(main_interpreter_id != current_id)) + #else + static PyInterpreterState *main_interpreter = NULL; + PyInterpreterState *current_interpreter = PyThreadState_Get()->interp; + if (!main_interpreter) { + main_interpreter = current_interpreter; + } else if (unlikely(main_interpreter != current_interpreter)) + #endif + { + PyErr_SetString( + PyExc_ImportError, + "Interpreter change detected - this module can only be loaded into one interpreter per process."); + return -1; + } + return 0; +} +static CYTHON_SMALL_CODE int __Pyx_copy_spec_to_module(PyObject *spec, PyObject *moddict, const char* from_name, const char* to_name) { + PyObject *value = PyObject_GetAttrString(spec, from_name); + int result = 0; + if (likely(value)) { + result = PyDict_SetItemString(moddict, to_name, value); + Py_DECREF(value); + } else if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Clear(); + } else { + result = -1; + } + return result; +} +static CYTHON_SMALL_CODE PyObject* __pyx_pymod_create(PyObject *spec, CYTHON_UNUSED PyModuleDef *def) { + PyObject *module = NULL, *moddict, *modname; + if (__Pyx_check_single_interpreter()) + return NULL; + if (__pyx_m) + return __Pyx_NewRef(__pyx_m); + modname = PyObject_GetAttrString(spec, "name"); + if (unlikely(!modname)) goto bad; + module = PyModule_NewObject(modname); + Py_DECREF(modname); + if (unlikely(!module)) goto bad; + moddict = PyModule_GetDict(module); + if (unlikely(!moddict)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "loader", "__loader__") < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "origin", "__file__") < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "parent", "__package__") < 0)) goto bad; + if (unlikely(__Pyx_copy_spec_to_module(spec, moddict, "submodule_search_locations", "__path__") < 0)) goto bad; + return module; +bad: + Py_XDECREF(module); + return NULL; +} + + +static CYTHON_SMALL_CODE int __pyx_pymod_exec_cy_cxxtest(PyObject *__pyx_pyinit_module) +#endif #endif { PyObject *__pyx_t_1 = NULL; __Pyx_RefNannyDeclarations - #if CYTHON_REFNANNY - __Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); - if (!__Pyx_RefNanny) { - PyErr_Clear(); - __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny"); - if (!__Pyx_RefNanny) - Py_FatalError("failed to import 'refnanny' module"); + #if CYTHON_PEP489_MULTI_PHASE_INIT + if (__pyx_m) { + if (__pyx_m == __pyx_pyinit_module) return 0; + PyErr_SetString(PyExc_RuntimeError, "Module 'cy_cxxtest' has already been imported. Re-initialisation is not supported."); + return -1; } + #elif PY_MAJOR_VERSION >= 3 + if (__pyx_m) return __Pyx_NewRef(__pyx_m); + #endif + #if CYTHON_REFNANNY +__Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny"); +if (!__Pyx_RefNanny) { + PyErr_Clear(); + __Pyx_RefNanny = __Pyx_RefNannyImportAPI("Cython.Runtime.refnanny"); + if (!__Pyx_RefNanny) + Py_FatalError("failed to import 'refnanny' module"); +} +#endif + __Pyx_RefNannySetupContext("__Pyx_PyMODINIT_FUNC PyInit_cy_cxxtest(void)", 0); + if (__Pyx_check_binary_version() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #ifdef __Pxy_PyFrame_Initialize_Offsets + __Pxy_PyFrame_Initialize_Offsets(); #endif - __Pyx_RefNannySetupContext("PyMODINIT_FUNC PyInit_cy_cxxtest(void)"); - if ( __Pyx_check_binary_version() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - #ifdef __pyx_binding_PyCFunctionType_USED - if (__pyx_binding_PyCFunctionType_init() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_empty_tuple = PyTuple_New(0); if (unlikely(!__pyx_empty_tuple)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_empty_bytes = PyBytes_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_bytes)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_empty_unicode = PyUnicode_FromStringAndSize("", 0); if (unlikely(!__pyx_empty_unicode)) __PYX_ERR(0, 1, __pyx_L1_error) + #ifdef __Pyx_CyFunction_USED + if (__pyx_CyFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_FusedFunction_USED + if (__pyx_FusedFunction_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_Coroutine_USED + if (__pyx_Coroutine_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_Generator_USED + if (__pyx_Generator_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_AsyncGen_USED + if (__pyx_AsyncGen_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif + #ifdef __Pyx_StopAsyncIteration_USED + if (__pyx_StopAsyncIteration_init() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif /*--- Library function declarations ---*/ /*--- Threads initialization code ---*/ @@ -571,36 +1433,57 @@ PyMODINIT_FUNC PyInit_cy_cxxtest(void) #endif #endif /*--- Module creation code ---*/ + #if CYTHON_PEP489_MULTI_PHASE_INIT + __pyx_m = __pyx_pyinit_module; + Py_INCREF(__pyx_m); + #else #if PY_MAJOR_VERSION < 3 - __pyx_m = Py_InitModule4(__Pyx_NAMESTR("cy_cxxtest"), __pyx_methods, 0, 0, PYTHON_API_VERSION); + __pyx_m = Py_InitModule4("cy_cxxtest", __pyx_methods, 0, 0, PYTHON_API_VERSION); Py_XINCREF(__pyx_m); #else __pyx_m = PyModule_Create(&__pyx_moduledef); #endif - if (!__pyx_m) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - #if PY_MAJOR_VERSION < 3 - Py_INCREF(__pyx_m); + if (unlikely(!__pyx_m)) __PYX_ERR(0, 1, __pyx_L1_error) #endif - __pyx_b = PyImport_AddModule(__Pyx_NAMESTR(__Pyx_BUILTIN_MODULE_NAME)); - if (!__pyx_b) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; - if (__Pyx_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; + __pyx_d = PyModule_GetDict(__pyx_m); if (unlikely(!__pyx_d)) __PYX_ERR(0, 1, __pyx_L1_error) + Py_INCREF(__pyx_d); + __pyx_b = PyImport_AddModule(__Pyx_BUILTIN_MODULE_NAME); if (unlikely(!__pyx_b)) __PYX_ERR(0, 1, __pyx_L1_error) + __pyx_cython_runtime = PyImport_AddModule((char *) "cython_runtime"); if (unlikely(!__pyx_cython_runtime)) __PYX_ERR(0, 1, __pyx_L1_error) + #if CYTHON_COMPILING_IN_PYPY + Py_INCREF(__pyx_b); + #endif + if (PyObject_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) __PYX_ERR(0, 1, __pyx_L1_error); /*--- Initialize various global constants etc. ---*/ - if (unlikely(__Pyx_InitGlobals() < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__Pyx_InitGlobals() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #if PY_MAJOR_VERSION < 3 && (__PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT) + if (__Pyx_init_sys_getdefaultencoding_params() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif if (__pyx_module_is_main_cy_cxxtest) { - if (__Pyx_SetAttrString(__pyx_m, "__name__", __pyx_n_s____main__) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}; + if (PyObject_SetAttr(__pyx_m, __pyx_n_s_name, __pyx_n_s_main) < 0) __PYX_ERR(0, 1, __pyx_L1_error) } + #if PY_MAJOR_VERSION >= 3 + { + PyObject *modules = PyImport_GetModuleDict(); if (unlikely(!modules)) __PYX_ERR(0, 1, __pyx_L1_error) + if (!PyDict_GetItemString(modules, "cy_cxxtest")) { + if (unlikely(PyDict_SetItemString(modules, "cy_cxxtest", __pyx_m) < 0)) __PYX_ERR(0, 1, __pyx_L1_error) + } + } + #endif /*--- Builtin init code ---*/ - if (unlikely(__Pyx_InitCachedBuiltins() < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (__Pyx_InitCachedBuiltins() < 0) __PYX_ERR(0, 1, __pyx_L1_error) /*--- Constants init code ---*/ - if (unlikely(__Pyx_InitCachedConstants() < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - /*--- Global init code ---*/ - /*--- Variable export code ---*/ - /*--- Function export code ---*/ - if (__Pyx_ExportFunction("cy_hello", (void (*)(void))cy_hello, "void (void)") < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - /*--- Type init code ---*/ - /*--- Type import code ---*/ - /*--- Variable import code ---*/ - /*--- Function import code ---*/ + if (__Pyx_InitCachedConstants() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + /*--- Global type/function init code ---*/ + (void)__Pyx_modinit_global_init_code(); + (void)__Pyx_modinit_variable_export_code(); + if (unlikely(__Pyx_modinit_function_export_code() != 0)) goto __pyx_L1_error; + (void)__Pyx_modinit_type_init_code(); + (void)__Pyx_modinit_type_import_code(); + (void)__Pyx_modinit_variable_import_code(); + (void)__Pyx_modinit_function_import_code(); /*--- Execution code ---*/ + #if defined(__Pyx_Generator_USED) || defined(__Pyx_Coroutine_USED) + if (__Pyx_patch_abc() < 0) __PYX_ERR(0, 1, __pyx_L1_error) + #endif /* "cy_cxxtest.pyx":3 * cimport cy_cxxtest @@ -609,9 +1492,9 @@ PyMODINIT_FUNC PyInit_cy_cxxtest(void) * cy_cxxtest.hello() * */ - __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_10cy_cxxtest_pyhello, NULL, __pyx_n_s__cy_cxxtest); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_10cy_cxxtest_1pyhello, NULL, __pyx_n_s_cy_cxxtest); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); - if (PyObject_SetAttr(__pyx_m, __pyx_n_s__pyhello, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L1_error;} + if (PyDict_SetItem(__pyx_d, __pyx_n_s_pyhello, __pyx_t_1) < 0) __PYX_ERR(0, 3, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; /* "cy_cxxtest.pyx":1 @@ -619,37 +1502,44 @@ PyMODINIT_FUNC PyInit_cy_cxxtest(void) * * def pyhello(): */ - __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_GOTREF(((PyObject *)__pyx_t_1)); - if (PyObject_SetAttr(__pyx_m, __pyx_n_s____test__, ((PyObject *)__pyx_t_1)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;} - __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0; + __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + + /*--- Wrapped vars code ---*/ + goto __pyx_L0; __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); if (__pyx_m) { - __Pyx_AddTraceback("init cy_cxxtest", __pyx_clineno, __pyx_lineno, __pyx_filename); - Py_DECREF(__pyx_m); __pyx_m = 0; + if (__pyx_d) { + __Pyx_AddTraceback("init cy_cxxtest", __pyx_clineno, __pyx_lineno, __pyx_filename); + } + Py_CLEAR(__pyx_m); } else if (!PyErr_Occurred()) { PyErr_SetString(PyExc_ImportError, "init cy_cxxtest"); } __pyx_L0:; __Pyx_RefNannyFinishContext(); - #if PY_MAJOR_VERSION < 3 - return; - #else + #if CYTHON_PEP489_MULTI_PHASE_INIT + return (__pyx_m != NULL) ? 0 : -1; + #elif PY_MAJOR_VERSION >= 3 return __pyx_m; + #else + return; #endif } -/* Runtime support code */ - +/* --- Runtime support code --- */ +/* Refnanny */ #if CYTHON_REFNANNY static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) { PyObject *m = NULL, *p = NULL; void *r = NULL; - m = PyImport_ImportModule((char *)modname); + m = PyImport_ImportModule(modname); if (!m) goto end; - p = PyObject_GetAttrString(m, (char *)"RefNannyAPI"); + p = PyObject_GetAttrString(m, "RefNannyAPI"); if (!p) goto end; r = PyLong_AsVoidPtr(p); end: @@ -657,9 +1547,297 @@ static __Pyx_RefNannyAPIStruct *__Pyx_RefNannyImportAPI(const char *modname) { Py_XDECREF(m); return (__Pyx_RefNannyAPIStruct *)r; } -#endif /* CYTHON_REFNANNY */ +#endif +/* PyErrFetchRestore */ +#if CYTHON_FAST_THREAD_STATE +static CYTHON_INLINE void __Pyx_ErrRestoreInState(PyThreadState *tstate, PyObject *type, PyObject *value, PyObject *tb) { + PyObject *tmp_type, *tmp_value, *tmp_tb; + tmp_type = tstate->curexc_type; + tmp_value = tstate->curexc_value; + tmp_tb = tstate->curexc_traceback; + tstate->curexc_type = type; + tstate->curexc_value = value; + tstate->curexc_traceback = tb; + Py_XDECREF(tmp_type); + Py_XDECREF(tmp_value); + Py_XDECREF(tmp_tb); +} +static CYTHON_INLINE void __Pyx_ErrFetchInState(PyThreadState *tstate, PyObject **type, PyObject **value, PyObject **tb) { + *type = tstate->curexc_type; + *value = tstate->curexc_value; + *tb = tstate->curexc_traceback; + tstate->curexc_type = 0; + tstate->curexc_value = 0; + tstate->curexc_traceback = 0; +} +#endif + +/* WriteUnraisableException */ +static void __Pyx_WriteUnraisable(const char *name, CYTHON_UNUSED int clineno, + CYTHON_UNUSED int lineno, CYTHON_UNUSED const char *filename, + int full_traceback, CYTHON_UNUSED int nogil) { + PyObject *old_exc, *old_val, *old_tb; + PyObject *ctx; + __Pyx_PyThreadState_declare +#ifdef WITH_THREAD + PyGILState_STATE state; + if (nogil) + state = PyGILState_Ensure(); +#ifdef _MSC_VER + else state = (PyGILState_STATE)-1; +#endif +#endif + __Pyx_PyThreadState_assign + __Pyx_ErrFetch(&old_exc, &old_val, &old_tb); + if (full_traceback) { + Py_XINCREF(old_exc); + Py_XINCREF(old_val); + Py_XINCREF(old_tb); + __Pyx_ErrRestore(old_exc, old_val, old_tb); + PyErr_PrintEx(1); + } + #if PY_MAJOR_VERSION < 3 + ctx = PyString_FromString(name); + #else + ctx = PyUnicode_FromString(name); + #endif + __Pyx_ErrRestore(old_exc, old_val, old_tb); + if (!ctx) { + PyErr_WriteUnraisable(Py_None); + } else { + PyErr_WriteUnraisable(ctx); + Py_DECREF(ctx); + } +#ifdef WITH_THREAD + if (nogil) + PyGILState_Release(state); +#endif +} + +/* PyObjectGetAttrStr */ +#if CYTHON_USE_TYPE_SLOTS +static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name) { + PyTypeObject* tp = Py_TYPE(obj); + if (likely(tp->tp_getattro)) + return tp->tp_getattro(obj, attr_name); #if PY_MAJOR_VERSION < 3 + if (likely(tp->tp_getattr)) + return tp->tp_getattr(obj, PyString_AS_STRING(attr_name)); +#endif + return PyObject_GetAttr(obj, attr_name); +} +#endif + +/* CLineInTraceback */ +#ifndef CYTHON_CLINE_IN_TRACEBACK +static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line) { + PyObject *use_cline; + PyObject *ptype, *pvalue, *ptraceback; +#if CYTHON_COMPILING_IN_CPYTHON + PyObject **cython_runtime_dict; +#endif + if (unlikely(!__pyx_cython_runtime)) { + return c_line; + } + __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); +#if CYTHON_COMPILING_IN_CPYTHON + cython_runtime_dict = _PyObject_GetDictPtr(__pyx_cython_runtime); + if (likely(cython_runtime_dict)) { + __PYX_PY_DICT_LOOKUP_IF_MODIFIED( + use_cline, *cython_runtime_dict, + __Pyx_PyDict_GetItemStr(*cython_runtime_dict, __pyx_n_s_cline_in_traceback)) + } else +#endif + { + PyObject *use_cline_obj = __Pyx_PyObject_GetAttrStr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback); + if (use_cline_obj) { + use_cline = PyObject_Not(use_cline_obj) ? Py_False : Py_True; + Py_DECREF(use_cline_obj); + } else { + PyErr_Clear(); + use_cline = NULL; + } + } + if (!use_cline) { + c_line = 0; + PyObject_SetAttr(__pyx_cython_runtime, __pyx_n_s_cline_in_traceback, Py_False); + } + else if (use_cline == Py_False || (use_cline != Py_True && PyObject_Not(use_cline) != 0)) { + c_line = 0; + } + __Pyx_ErrRestoreInState(tstate, ptype, pvalue, ptraceback); + return c_line; +} +#endif + +/* CodeObjectCache */ +static int __pyx_bisect_code_objects(__Pyx_CodeObjectCacheEntry* entries, int count, int code_line) { + int start = 0, mid = 0, end = count - 1; + if (end >= 0 && code_line > entries[end].code_line) { + return count; + } + while (start < end) { + mid = start + (end - start) / 2; + if (code_line < entries[mid].code_line) { + end = mid; + } else if (code_line > entries[mid].code_line) { + start = mid + 1; + } else { + return mid; + } + } + if (code_line <= entries[mid].code_line) { + return mid; + } else { + return mid + 1; + } +} +static PyCodeObject *__pyx_find_code_object(int code_line) { + PyCodeObject* code_object; + int pos; + if (unlikely(!code_line) || unlikely(!__pyx_code_cache.entries)) { + return NULL; + } + pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); + if (unlikely(pos >= __pyx_code_cache.count) || unlikely(__pyx_code_cache.entries[pos].code_line != code_line)) { + return NULL; + } + code_object = __pyx_code_cache.entries[pos].code_object; + Py_INCREF(code_object); + return code_object; +} +static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object) { + int pos, i; + __Pyx_CodeObjectCacheEntry* entries = __pyx_code_cache.entries; + if (unlikely(!code_line)) { + return; + } + if (unlikely(!entries)) { + entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Malloc(64*sizeof(__Pyx_CodeObjectCacheEntry)); + if (likely(entries)) { + __pyx_code_cache.entries = entries; + __pyx_code_cache.max_count = 64; + __pyx_code_cache.count = 1; + entries[0].code_line = code_line; + entries[0].code_object = code_object; + Py_INCREF(code_object); + } + return; + } + pos = __pyx_bisect_code_objects(__pyx_code_cache.entries, __pyx_code_cache.count, code_line); + if ((pos < __pyx_code_cache.count) && unlikely(__pyx_code_cache.entries[pos].code_line == code_line)) { + PyCodeObject* tmp = entries[pos].code_object; + entries[pos].code_object = code_object; + Py_DECREF(tmp); + return; + } + if (__pyx_code_cache.count == __pyx_code_cache.max_count) { + int new_max = __pyx_code_cache.max_count + 64; + entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc( + __pyx_code_cache.entries, (size_t)new_max*sizeof(__Pyx_CodeObjectCacheEntry)); + if (unlikely(!entries)) { + return; + } + __pyx_code_cache.entries = entries; + __pyx_code_cache.max_count = new_max; + } + for (i=__pyx_code_cache.count; i>pos; i--) { + entries[i] = entries[i-1]; + } + entries[pos].code_line = code_line; + entries[pos].code_object = code_object; + __pyx_code_cache.count++; + Py_INCREF(code_object); +} + +/* AddTraceback */ +#include "compile.h" +#include "frameobject.h" +#include "traceback.h" +static PyCodeObject* __Pyx_CreateCodeObjectForTraceback( + const char *funcname, int c_line, + int py_line, const char *filename) { + PyCodeObject *py_code = 0; + PyObject *py_srcfile = 0; + PyObject *py_funcname = 0; + #if PY_MAJOR_VERSION < 3 + py_srcfile = PyString_FromString(filename); + #else + py_srcfile = PyUnicode_FromString(filename); + #endif + if (!py_srcfile) goto bad; + if (c_line) { + #if PY_MAJOR_VERSION < 3 + py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + #else + py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, c_line); + #endif + } + else { + #if PY_MAJOR_VERSION < 3 + py_funcname = PyString_FromString(funcname); + #else + py_funcname = PyUnicode_FromString(funcname); + #endif + } + if (!py_funcname) goto bad; + py_code = __Pyx_PyCode_New( + 0, + 0, + 0, + 0, + 0, + __pyx_empty_bytes, /*PyObject *code,*/ + __pyx_empty_tuple, /*PyObject *consts,*/ + __pyx_empty_tuple, /*PyObject *names,*/ + __pyx_empty_tuple, /*PyObject *varnames,*/ + __pyx_empty_tuple, /*PyObject *freevars,*/ + __pyx_empty_tuple, /*PyObject *cellvars,*/ + py_srcfile, /*PyObject *filename,*/ + py_funcname, /*PyObject *name,*/ + py_line, + __pyx_empty_bytes /*PyObject *lnotab*/ + ); + Py_DECREF(py_srcfile); + Py_DECREF(py_funcname); + return py_code; +bad: + Py_XDECREF(py_srcfile); + Py_XDECREF(py_funcname); + return NULL; +} +static void __Pyx_AddTraceback(const char *funcname, int c_line, + int py_line, const char *filename) { + PyCodeObject *py_code = 0; + PyFrameObject *py_frame = 0; + PyThreadState *tstate = __Pyx_PyThreadState_Current; + if (c_line) { + c_line = __Pyx_CLineForTraceback(tstate, c_line); + } + py_code = __pyx_find_code_object(c_line ? -c_line : py_line); + if (!py_code) { + py_code = __Pyx_CreateCodeObjectForTraceback( + funcname, c_line, py_line, filename); + if (!py_code) goto bad; + __pyx_insert_code_object(c_line ? -c_line : py_line, py_code); + } + py_frame = PyFrame_New( + tstate, /*PyThreadState *tstate,*/ + py_code, /*PyCodeObject *code,*/ + __pyx_d, /*PyObject *globals,*/ + 0 /*PyObject *locals*/ + ); + if (!py_frame) goto bad; + __Pyx_PyFrame_SetLineNumber(py_frame, py_line); + PyTraceBack_Here(py_frame); +bad: + Py_XDECREF(py_code); + Py_XDECREF(py_frame); +} + +/* Print */ +#if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION < 3 static PyObject *__Pyx_GetStdout(void) { PyObject *f = PySys_GetObject((char *)"stdout"); if (!f) { @@ -667,48 +1845,54 @@ static PyObject *__Pyx_GetStdout(void) { } return f; } - static int __Pyx_Print(PyObject* f, PyObject *arg_tuple, int newline) { - PyObject* v; int i; - if (!f) { if (!(f = __Pyx_GetStdout())) return -1; } + Py_INCREF(f); for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) { + PyObject* v; if (PyFile_SoftSpace(f, 1)) { if (PyFile_WriteString(" ", f) < 0) - return -1; + goto error; } v = PyTuple_GET_ITEM(arg_tuple, i); if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0) - return -1; + goto error; if (PyString_Check(v)) { char *s = PyString_AsString(v); Py_ssize_t len = PyString_Size(v); - if (len > 0 && - isspace(Py_CHARMASK(s[len-1])) && - s[len-1] != ' ') - PyFile_SoftSpace(f, 0); + if (len > 0) { + switch (s[len-1]) { + case ' ': break; + case '\f': case '\r': case '\n': case '\t': case '\v': + PyFile_SoftSpace(f, 0); + break; + default: break; + } + } } } if (newline) { if (PyFile_WriteString("\n", f) < 0) - return -1; + goto error; PyFile_SoftSpace(f, 0); } + Py_DECREF(f); return 0; +error: + Py_DECREF(f); + return -1; } - -#else /* Python 3 has a print function */ - +#else static int __Pyx_Print(PyObject* stream, PyObject *arg_tuple, int newline) { PyObject* kwargs = 0; PyObject* result = 0; PyObject* end_string; if (unlikely(!__pyx_print)) { - __pyx_print = __Pyx_GetAttrString(__pyx_b, "print"); + __pyx_print = PyObject_GetAttr(__pyx_b, __pyx_n_s_print); if (!__pyx_print) return -1; } @@ -716,13 +1900,13 @@ static int __Pyx_Print(PyObject* stream, PyObject *arg_tuple, int newline) { kwargs = PyDict_New(); if (unlikely(!kwargs)) return -1; - if (unlikely(PyDict_SetItemString(kwargs, "file", stream) < 0)) + if (unlikely(PyDict_SetItem(kwargs, __pyx_n_s_file, stream) < 0)) goto bad; if (!newline) { end_string = PyUnicode_FromStringAndSize(" ", 1); if (unlikely(!end_string)) goto bad; - if (PyDict_SetItemString(kwargs, "end", end_string) < 0) { + if (PyDict_SetItem(kwargs, __pyx_n_s_end, end_string) < 0) { Py_DECREF(end_string); goto bad; } @@ -736,7 +1920,7 @@ static int __Pyx_Print(PyObject* stream, PyObject *arg_tuple, int newline) { end_string = PyUnicode_FromStringAndSize(" ", 1); if (unlikely(!end_string)) return -1; - if (PyDict_SetItemString(__pyx_print_kwargs, "end", end_string) < 0) { + if (PyDict_SetItem(__pyx_print_kwargs, __pyx_n_s_end, end_string) < 0) { Py_DECREF(end_string); return -1; } @@ -756,492 +1940,577 @@ static int __Pyx_Print(PyObject* stream, PyObject *arg_tuple, int newline) { Py_XDECREF(kwargs); return -1; } - #endif -#if PY_MAJOR_VERSION < 3 - +/* PrintOne */ +#if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION < 3 static int __Pyx_PrintOne(PyObject* f, PyObject *o) { if (!f) { if (!(f = __Pyx_GetStdout())) return -1; } + Py_INCREF(f); if (PyFile_SoftSpace(f, 0)) { if (PyFile_WriteString(" ", f) < 0) - return -1; + goto error; } if (PyFile_WriteObject(o, f, Py_PRINT_RAW) < 0) - return -1; + goto error; if (PyFile_WriteString("\n", f) < 0) - return -1; + goto error; + Py_DECREF(f); return 0; - /* the line below is just to avoid compiler - * compiler warnings about unused functions */ +error: + Py_DECREF(f); + return -1; + /* the line below is just to avoid C compiler + * warnings about unused functions */ return __Pyx_Print(f, NULL, 0); } - -#else /* Python 3 has a print function */ - +#else static int __Pyx_PrintOne(PyObject* stream, PyObject *o) { int res; - PyObject* arg_tuple = PyTuple_New(1); + PyObject* arg_tuple = PyTuple_Pack(1, o); if (unlikely(!arg_tuple)) return -1; - Py_INCREF(o); - PyTuple_SET_ITEM(arg_tuple, 0, o); res = __Pyx_Print(stream, arg_tuple, 1); Py_DECREF(arg_tuple); return res; } +#endif -#endif - -static CYTHON_INLINE unsigned char __Pyx_PyInt_AsUnsignedChar(PyObject* x) { - const unsigned char neg_one = (unsigned char)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(unsigned char) < sizeof(long)) { - long val = __Pyx_PyInt_AsLong(x); - if (unlikely(val != (long)(unsigned char)val)) { - if (!unlikely(val == -1 && PyErr_Occurred())) { - PyErr_SetString(PyExc_OverflowError, - (is_unsigned && unlikely(val < 0)) ? - "can't convert negative value to unsigned char" : - "value too large to convert to unsigned char"); - } - return (unsigned char)-1; - } - return (unsigned char)val; - } - return (unsigned char)__Pyx_PyInt_AsUnsignedLong(x); -} - -static CYTHON_INLINE unsigned short __Pyx_PyInt_AsUnsignedShort(PyObject* x) { - const unsigned short neg_one = (unsigned short)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(unsigned short) < sizeof(long)) { - long val = __Pyx_PyInt_AsLong(x); - if (unlikely(val != (long)(unsigned short)val)) { - if (!unlikely(val == -1 && PyErr_Occurred())) { - PyErr_SetString(PyExc_OverflowError, - (is_unsigned && unlikely(val < 0)) ? - "can't convert negative value to unsigned short" : - "value too large to convert to unsigned short"); - } - return (unsigned short)-1; - } - return (unsigned short)val; - } - return (unsigned short)__Pyx_PyInt_AsUnsignedLong(x); -} - -static CYTHON_INLINE unsigned int __Pyx_PyInt_AsUnsignedInt(PyObject* x) { - const unsigned int neg_one = (unsigned int)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(unsigned int) < sizeof(long)) { - long val = __Pyx_PyInt_AsLong(x); - if (unlikely(val != (long)(unsigned int)val)) { - if (!unlikely(val == -1 && PyErr_Occurred())) { - PyErr_SetString(PyExc_OverflowError, - (is_unsigned && unlikely(val < 0)) ? - "can't convert negative value to unsigned int" : - "value too large to convert to unsigned int"); - } - return (unsigned int)-1; - } - return (unsigned int)val; - } - return (unsigned int)__Pyx_PyInt_AsUnsignedLong(x); -} - -static CYTHON_INLINE char __Pyx_PyInt_AsChar(PyObject* x) { - const char neg_one = (char)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(char) < sizeof(long)) { - long val = __Pyx_PyInt_AsLong(x); - if (unlikely(val != (long)(char)val)) { - if (!unlikely(val == -1 && PyErr_Occurred())) { - PyErr_SetString(PyExc_OverflowError, - (is_unsigned && unlikely(val < 0)) ? - "can't convert negative value to char" : - "value too large to convert to char"); - } - return (char)-1; - } - return (char)val; - } - return (char)__Pyx_PyInt_AsLong(x); -} - -static CYTHON_INLINE short __Pyx_PyInt_AsShort(PyObject* x) { - const short neg_one = (short)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(short) < sizeof(long)) { - long val = __Pyx_PyInt_AsLong(x); - if (unlikely(val != (long)(short)val)) { - if (!unlikely(val == -1 && PyErr_Occurred())) { - PyErr_SetString(PyExc_OverflowError, - (is_unsigned && unlikely(val < 0)) ? - "can't convert negative value to short" : - "value too large to convert to short"); - } - return (short)-1; - } - return (short)val; - } - return (short)__Pyx_PyInt_AsLong(x); -} - -static CYTHON_INLINE int __Pyx_PyInt_AsInt(PyObject* x) { - const int neg_one = (int)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(int) < sizeof(long)) { - long val = __Pyx_PyInt_AsLong(x); - if (unlikely(val != (long)(int)val)) { - if (!unlikely(val == -1 && PyErr_Occurred())) { - PyErr_SetString(PyExc_OverflowError, - (is_unsigned && unlikely(val < 0)) ? - "can't convert negative value to int" : - "value too large to convert to int"); - } - return (int)-1; - } - return (int)val; - } - return (int)__Pyx_PyInt_AsLong(x); -} - -static CYTHON_INLINE signed char __Pyx_PyInt_AsSignedChar(PyObject* x) { - const signed char neg_one = (signed char)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(signed char) < sizeof(long)) { - long val = __Pyx_PyInt_AsLong(x); - if (unlikely(val != (long)(signed char)val)) { - if (!unlikely(val == -1 && PyErr_Occurred())) { - PyErr_SetString(PyExc_OverflowError, - (is_unsigned && unlikely(val < 0)) ? - "can't convert negative value to signed char" : - "value too large to convert to signed char"); - } - return (signed char)-1; - } - return (signed char)val; - } - return (signed char)__Pyx_PyInt_AsSignedLong(x); -} - -static CYTHON_INLINE signed short __Pyx_PyInt_AsSignedShort(PyObject* x) { - const signed short neg_one = (signed short)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(signed short) < sizeof(long)) { - long val = __Pyx_PyInt_AsLong(x); - if (unlikely(val != (long)(signed short)val)) { - if (!unlikely(val == -1 && PyErr_Occurred())) { - PyErr_SetString(PyExc_OverflowError, - (is_unsigned && unlikely(val < 0)) ? - "can't convert negative value to signed short" : - "value too large to convert to signed short"); - } - return (signed short)-1; - } - return (signed short)val; - } - return (signed short)__Pyx_PyInt_AsSignedLong(x); -} - -static CYTHON_INLINE signed int __Pyx_PyInt_AsSignedInt(PyObject* x) { - const signed int neg_one = (signed int)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(signed int) < sizeof(long)) { - long val = __Pyx_PyInt_AsLong(x); - if (unlikely(val != (long)(signed int)val)) { - if (!unlikely(val == -1 && PyErr_Occurred())) { - PyErr_SetString(PyExc_OverflowError, - (is_unsigned && unlikely(val < 0)) ? - "can't convert negative value to signed int" : - "value too large to convert to signed int"); - } - return (signed int)-1; - } - return (signed int)val; - } - return (signed int)__Pyx_PyInt_AsSignedLong(x); -} - -static CYTHON_INLINE int __Pyx_PyInt_AsLongDouble(PyObject* x) { - const int neg_one = (int)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; - if (sizeof(int) < sizeof(long)) { - long val = __Pyx_PyInt_AsLong(x); - if (unlikely(val != (long)(int)val)) { - if (!unlikely(val == -1 && PyErr_Occurred())) { - PyErr_SetString(PyExc_OverflowError, - (is_unsigned && unlikely(val < 0)) ? - "can't convert negative value to int" : - "value too large to convert to int"); - } - return (int)-1; - } - return (int)val; - } - return (int)__Pyx_PyInt_AsLong(x); -} - -static CYTHON_INLINE unsigned long __Pyx_PyInt_AsUnsignedLong(PyObject* x) { - const unsigned long neg_one = (unsigned long)-1, const_zero = 0; +/* CIntToPy */ +static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { + const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; const int is_unsigned = neg_one > const_zero; -#if PY_VERSION_HEX < 0x03000000 - if (likely(PyInt_Check(x))) { - long val = PyInt_AS_LONG(x); - if (is_unsigned && unlikely(val < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to unsigned long"); - return (unsigned long)-1; - } - return (unsigned long)val; - } else + if (is_unsigned) { + if (sizeof(long) < sizeof(long)) { + return PyInt_FromLong((long) value); + } else if (sizeof(long) <= sizeof(unsigned long)) { + return PyLong_FromUnsignedLong((unsigned long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { + return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG) value); #endif - if (likely(PyLong_Check(x))) { - if (is_unsigned) { - if (unlikely(Py_SIZE(x) < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to unsigned long"); - return (unsigned long)-1; - } - return (unsigned long)PyLong_AsUnsignedLong(x); - } else { - return (unsigned long)PyLong_AsLong(x); } } else { - unsigned long val; - PyObject *tmp = __Pyx_PyNumber_Int(x); - if (!tmp) return (unsigned long)-1; - val = __Pyx_PyInt_AsUnsignedLong(tmp); - Py_DECREF(tmp); - return val; - } -} - -static CYTHON_INLINE unsigned PY_LONG_LONG __Pyx_PyInt_AsUnsignedLongLong(PyObject* x) { - const unsigned PY_LONG_LONG neg_one = (unsigned PY_LONG_LONG)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; -#if PY_VERSION_HEX < 0x03000000 - if (likely(PyInt_Check(x))) { - long val = PyInt_AS_LONG(x); - if (is_unsigned && unlikely(val < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to unsigned PY_LONG_LONG"); - return (unsigned PY_LONG_LONG)-1; - } - return (unsigned PY_LONG_LONG)val; - } else + if (sizeof(long) <= sizeof(long)) { + return PyInt_FromLong((long) value); +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { + return PyLong_FromLongLong((PY_LONG_LONG) value); #endif - if (likely(PyLong_Check(x))) { - if (is_unsigned) { - if (unlikely(Py_SIZE(x) < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to unsigned PY_LONG_LONG"); - return (unsigned PY_LONG_LONG)-1; - } - return (unsigned PY_LONG_LONG)PyLong_AsUnsignedLongLong(x); - } else { - return (unsigned PY_LONG_LONG)PyLong_AsLongLong(x); } - } else { - unsigned PY_LONG_LONG val; - PyObject *tmp = __Pyx_PyNumber_Int(x); - if (!tmp) return (unsigned PY_LONG_LONG)-1; - val = __Pyx_PyInt_AsUnsignedLongLong(tmp); - Py_DECREF(tmp); - return val; + } + { + int one = 1; int little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&value; + return _PyLong_FromByteArray(bytes, sizeof(long), + little, !is_unsigned); } } -static CYTHON_INLINE long __Pyx_PyInt_AsLong(PyObject* x) { - const long neg_one = (long)-1, const_zero = 0; +/* CIntFromPyVerify */ +#define __PYX_VERIFY_RETURN_INT(target_type, func_type, func_value)\ + __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 0) +#define __PYX_VERIFY_RETURN_INT_EXC(target_type, func_type, func_value)\ + __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, 1) +#define __PYX__VERIFY_RETURN_INT(target_type, func_type, func_value, exc)\ + {\ + func_type value = func_value;\ + if (sizeof(target_type) < sizeof(func_type)) {\ + if (unlikely(value != (func_type) (target_type) value)) {\ + func_type zero = 0;\ + if (exc && unlikely(value == (func_type)-1 && PyErr_Occurred()))\ + return (target_type) -1;\ + if (is_unsigned && unlikely(value < zero))\ + goto raise_neg_overflow;\ + else\ + goto raise_overflow;\ + }\ + }\ + return (target_type) value;\ + } + +/* CIntFromPy */ +static CYTHON_INLINE long __Pyx_PyInt_As_long(PyObject *x) { + const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; const int is_unsigned = neg_one > const_zero; -#if PY_VERSION_HEX < 0x03000000 +#if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x))) { - long val = PyInt_AS_LONG(x); - if (is_unsigned && unlikely(val < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to long"); - return (long)-1; + if (sizeof(long) < sizeof(long)) { + __PYX_VERIFY_RETURN_INT(long, long, PyInt_AS_LONG(x)) + } else { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + goto raise_neg_overflow; + } + return (long) val; } - return (long)val; } else #endif if (likely(PyLong_Check(x))) { if (is_unsigned) { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (long) 0; + case 1: __PYX_VERIFY_RETURN_INT(long, digit, digits[0]) + case 2: + if (8 * sizeof(long) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 2 * PyLong_SHIFT) { + return (long) (((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + case 3: + if (8 * sizeof(long) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 3 * PyLong_SHIFT) { + return (long) (((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + case 4: + if (8 * sizeof(long) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) >= 4 * PyLong_SHIFT) { + return (long) (((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0])); + } + } + break; + } +#endif +#if CYTHON_COMPILING_IN_CPYTHON if (unlikely(Py_SIZE(x) < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to long"); - return (long)-1; + goto raise_neg_overflow; + } +#else + { + int result = PyObject_RichCompareBool(x, Py_False, Py_LT); + if (unlikely(result < 0)) + return (long) -1; + if (unlikely(result == 1)) + goto raise_neg_overflow; + } +#endif + if (sizeof(long) <= sizeof(unsigned long)) { + __PYX_VERIFY_RETURN_INT_EXC(long, unsigned long, PyLong_AsUnsignedLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(unsigned PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(long, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) +#endif } - return (long)PyLong_AsUnsignedLong(x); } else { - return (long)PyLong_AsLong(x); +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (long) 0; + case -1: __PYX_VERIFY_RETURN_INT(long, sdigit, (sdigit) (-(sdigit)digits[0])) + case 1: __PYX_VERIFY_RETURN_INT(long, digit, +digits[0]) + case -2: + if (8 * sizeof(long) - 1 > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 2: + if (8 * sizeof(long) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + return (long) ((((((long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case -3: + if (8 * sizeof(long) - 1 > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 3: + if (8 * sizeof(long) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + return (long) ((((((((long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case -4: + if (8 * sizeof(long) - 1 > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { + return (long) (((long)-1)*(((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + case 4: + if (8 * sizeof(long) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(long, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(long) - 1 > 4 * PyLong_SHIFT) { + return (long) ((((((((((long)digits[3]) << PyLong_SHIFT) | (long)digits[2]) << PyLong_SHIFT) | (long)digits[1]) << PyLong_SHIFT) | (long)digits[0]))); + } + } + break; + } +#endif + if (sizeof(long) <= sizeof(long)) { + __PYX_VERIFY_RETURN_INT_EXC(long, long, PyLong_AsLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(long) <= sizeof(PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(long, PY_LONG_LONG, PyLong_AsLongLong(x)) +#endif + } + } + { +#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) + PyErr_SetString(PyExc_RuntimeError, + "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); +#else + long val; + PyObject *v = __Pyx_PyNumber_IntOrLong(x); + #if PY_MAJOR_VERSION < 3 + if (likely(v) && !PyLong_Check(v)) { + PyObject *tmp = v; + v = PyNumber_Long(tmp); + Py_DECREF(tmp); + } + #endif + if (likely(v)) { + int one = 1; int is_little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&val; + int ret = _PyLong_AsByteArray((PyLongObject *)v, + bytes, sizeof(val), + is_little, !is_unsigned); + Py_DECREF(v); + if (likely(!ret)) + return val; + } +#endif + return (long) -1; } } else { long val; - PyObject *tmp = __Pyx_PyNumber_Int(x); - if (!tmp) return (long)-1; - val = __Pyx_PyInt_AsLong(tmp); + PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); + if (!tmp) return (long) -1; + val = __Pyx_PyInt_As_long(tmp); Py_DECREF(tmp); return val; } +raise_overflow: + PyErr_SetString(PyExc_OverflowError, + "value too large to convert to long"); + return (long) -1; +raise_neg_overflow: + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to long"); + return (long) -1; } -static CYTHON_INLINE PY_LONG_LONG __Pyx_PyInt_AsLongLong(PyObject* x) { - const PY_LONG_LONG neg_one = (PY_LONG_LONG)-1, const_zero = 0; +/* CIntFromPy */ +static CYTHON_INLINE int __Pyx_PyInt_As_int(PyObject *x) { + const int neg_one = (int) ((int) 0 - (int) 1), const_zero = (int) 0; const int is_unsigned = neg_one > const_zero; -#if PY_VERSION_HEX < 0x03000000 +#if PY_MAJOR_VERSION < 3 if (likely(PyInt_Check(x))) { - long val = PyInt_AS_LONG(x); - if (is_unsigned && unlikely(val < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to PY_LONG_LONG"); - return (PY_LONG_LONG)-1; + if (sizeof(int) < sizeof(long)) { + __PYX_VERIFY_RETURN_INT(int, long, PyInt_AS_LONG(x)) + } else { + long val = PyInt_AS_LONG(x); + if (is_unsigned && unlikely(val < 0)) { + goto raise_neg_overflow; + } + return (int) val; } - return (PY_LONG_LONG)val; } else #endif if (likely(PyLong_Check(x))) { if (is_unsigned) { +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (int) 0; + case 1: __PYX_VERIFY_RETURN_INT(int, digit, digits[0]) + case 2: + if (8 * sizeof(int) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 2 * PyLong_SHIFT) { + return (int) (((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + case 3: + if (8 * sizeof(int) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 3 * PyLong_SHIFT) { + return (int) (((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + case 4: + if (8 * sizeof(int) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) >= 4 * PyLong_SHIFT) { + return (int) (((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0])); + } + } + break; + } +#endif +#if CYTHON_COMPILING_IN_CPYTHON if (unlikely(Py_SIZE(x) < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to PY_LONG_LONG"); - return (PY_LONG_LONG)-1; + goto raise_neg_overflow; + } +#else + { + int result = PyObject_RichCompareBool(x, Py_False, Py_LT); + if (unlikely(result < 0)) + return (int) -1; + if (unlikely(result == 1)) + goto raise_neg_overflow; + } +#endif + if (sizeof(int) <= sizeof(unsigned long)) { + __PYX_VERIFY_RETURN_INT_EXC(int, unsigned long, PyLong_AsUnsignedLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(unsigned PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(int, unsigned PY_LONG_LONG, PyLong_AsUnsignedLongLong(x)) +#endif } - return (PY_LONG_LONG)PyLong_AsUnsignedLongLong(x); } else { - return (PY_LONG_LONG)PyLong_AsLongLong(x); +#if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)x)->ob_digit; + switch (Py_SIZE(x)) { + case 0: return (int) 0; + case -1: __PYX_VERIFY_RETURN_INT(int, sdigit, (sdigit) (-(sdigit)digits[0])) + case 1: __PYX_VERIFY_RETURN_INT(int, digit, +digits[0]) + case -2: + if (8 * sizeof(int) - 1 > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 2: + if (8 * sizeof(int) > 1 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 2 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + return (int) ((((((int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case -3: + if (8 * sizeof(int) - 1 > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 3: + if (8 * sizeof(int) > 2 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 3 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + return (int) ((((((((int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case -4: + if (8 * sizeof(int) - 1 > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, long, -(long) (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { + return (int) (((int)-1)*(((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + case 4: + if (8 * sizeof(int) > 3 * PyLong_SHIFT) { + if (8 * sizeof(unsigned long) > 4 * PyLong_SHIFT) { + __PYX_VERIFY_RETURN_INT(int, unsigned long, (((((((((unsigned long)digits[3]) << PyLong_SHIFT) | (unsigned long)digits[2]) << PyLong_SHIFT) | (unsigned long)digits[1]) << PyLong_SHIFT) | (unsigned long)digits[0]))) + } else if (8 * sizeof(int) - 1 > 4 * PyLong_SHIFT) { + return (int) ((((((((((int)digits[3]) << PyLong_SHIFT) | (int)digits[2]) << PyLong_SHIFT) | (int)digits[1]) << PyLong_SHIFT) | (int)digits[0]))); + } + } + break; + } +#endif + if (sizeof(int) <= sizeof(long)) { + __PYX_VERIFY_RETURN_INT_EXC(int, long, PyLong_AsLong(x)) +#ifdef HAVE_LONG_LONG + } else if (sizeof(int) <= sizeof(PY_LONG_LONG)) { + __PYX_VERIFY_RETURN_INT_EXC(int, PY_LONG_LONG, PyLong_AsLongLong(x)) +#endif + } + } + { +#if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray) + PyErr_SetString(PyExc_RuntimeError, + "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers"); +#else + int val; + PyObject *v = __Pyx_PyNumber_IntOrLong(x); + #if PY_MAJOR_VERSION < 3 + if (likely(v) && !PyLong_Check(v)) { + PyObject *tmp = v; + v = PyNumber_Long(tmp); + Py_DECREF(tmp); + } + #endif + if (likely(v)) { + int one = 1; int is_little = (int)*(unsigned char *)&one; + unsigned char *bytes = (unsigned char *)&val; + int ret = _PyLong_AsByteArray((PyLongObject *)v, + bytes, sizeof(val), + is_little, !is_unsigned); + Py_DECREF(v); + if (likely(!ret)) + return val; + } +#endif + return (int) -1; } } else { - PY_LONG_LONG val; - PyObject *tmp = __Pyx_PyNumber_Int(x); - if (!tmp) return (PY_LONG_LONG)-1; - val = __Pyx_PyInt_AsLongLong(tmp); + int val; + PyObject *tmp = __Pyx_PyNumber_IntOrLong(x); + if (!tmp) return (int) -1; + val = __Pyx_PyInt_As_int(tmp); Py_DECREF(tmp); return val; } +raise_overflow: + PyErr_SetString(PyExc_OverflowError, + "value too large to convert to int"); + return (int) -1; +raise_neg_overflow: + PyErr_SetString(PyExc_OverflowError, + "can't convert negative value to int"); + return (int) -1; } -static CYTHON_INLINE signed long __Pyx_PyInt_AsSignedLong(PyObject* x) { - const signed long neg_one = (signed long)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; -#if PY_VERSION_HEX < 0x03000000 - if (likely(PyInt_Check(x))) { - long val = PyInt_AS_LONG(x); - if (is_unsigned && unlikely(val < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to signed long"); - return (signed long)-1; - } - return (signed long)val; - } else -#endif - if (likely(PyLong_Check(x))) { - if (is_unsigned) { - if (unlikely(Py_SIZE(x) < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to signed long"); - return (signed long)-1; - } - return (signed long)PyLong_AsUnsignedLong(x); - } else { - return (signed long)PyLong_AsLong(x); +/* FastTypeChecks */ +#if CYTHON_COMPILING_IN_CPYTHON +static int __Pyx_InBases(PyTypeObject *a, PyTypeObject *b) { + while (a) { + a = a->tp_base; + if (a == b) + return 1; + } + return b == &PyBaseObject_Type; +} +static CYTHON_INLINE int __Pyx_IsSubtype(PyTypeObject *a, PyTypeObject *b) { + PyObject *mro; + if (a == b) return 1; + mro = a->tp_mro; + if (likely(mro)) { + Py_ssize_t i, n; + n = PyTuple_GET_SIZE(mro); + for (i = 0; i < n; i++) { + if (PyTuple_GET_ITEM(mro, i) == (PyObject *)b) + return 1; } - } else { - signed long val; - PyObject *tmp = __Pyx_PyNumber_Int(x); - if (!tmp) return (signed long)-1; - val = __Pyx_PyInt_AsSignedLong(tmp); - Py_DECREF(tmp); - return val; + return 0; } + return __Pyx_InBases(a, b); } - -static CYTHON_INLINE signed PY_LONG_LONG __Pyx_PyInt_AsSignedLongLong(PyObject* x) { - const signed PY_LONG_LONG neg_one = (signed PY_LONG_LONG)-1, const_zero = 0; - const int is_unsigned = neg_one > const_zero; -#if PY_VERSION_HEX < 0x03000000 - if (likely(PyInt_Check(x))) { - long val = PyInt_AS_LONG(x); - if (is_unsigned && unlikely(val < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to signed PY_LONG_LONG"); - return (signed PY_LONG_LONG)-1; +#if PY_MAJOR_VERSION == 2 +static int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject* exc_type2) { + PyObject *exception, *value, *tb; + int res; + __Pyx_PyThreadState_declare + __Pyx_PyThreadState_assign + __Pyx_ErrFetch(&exception, &value, &tb); + res = exc_type1 ? PyObject_IsSubclass(err, exc_type1) : 0; + if (unlikely(res == -1)) { + PyErr_WriteUnraisable(err); + res = 0; + } + if (!res) { + res = PyObject_IsSubclass(err, exc_type2); + if (unlikely(res == -1)) { + PyErr_WriteUnraisable(err); + res = 0; } - return (signed PY_LONG_LONG)val; - } else + } + __Pyx_ErrRestore(exception, value, tb); + return res; +} +#else +static CYTHON_INLINE int __Pyx_inner_PyErr_GivenExceptionMatches2(PyObject *err, PyObject* exc_type1, PyObject *exc_type2) { + int res = exc_type1 ? __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type1) : 0; + if (!res) { + res = __Pyx_IsSubtype((PyTypeObject*)err, (PyTypeObject*)exc_type2); + } + return res; +} #endif - if (likely(PyLong_Check(x))) { - if (is_unsigned) { - if (unlikely(Py_SIZE(x) < 0)) { - PyErr_SetString(PyExc_OverflowError, - "can't convert negative value to signed PY_LONG_LONG"); - return (signed PY_LONG_LONG)-1; - } - return (signed PY_LONG_LONG)PyLong_AsUnsignedLongLong(x); +static int __Pyx_PyErr_GivenExceptionMatchesTuple(PyObject *exc_type, PyObject *tuple) { + Py_ssize_t i, n; + assert(PyExceptionClass_Check(exc_type)); + n = PyTuple_GET_SIZE(tuple); +#if PY_MAJOR_VERSION >= 3 + for (i=0; icurexc_type; - tmp_value = tstate->curexc_value; - tmp_tb = tstate->curexc_traceback; - tstate->curexc_type = type; - tstate->curexc_value = value; - tstate->curexc_traceback = tb; - Py_XDECREF(tmp_type); - Py_XDECREF(tmp_value); - Py_XDECREF(tmp_tb); -} - -static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb) { - PyThreadState *tstate = PyThreadState_GET(); - *type = tstate->curexc_type; - *value = tstate->curexc_value; - *tb = tstate->curexc_traceback; - - tstate->curexc_type = 0; - tstate->curexc_value = 0; - tstate->curexc_traceback = 0; +static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches(PyObject *err, PyObject* exc_type) { + if (likely(err == exc_type)) return 1; + if (likely(PyExceptionClass_Check(err))) { + if (likely(PyExceptionClass_Check(exc_type))) { + return __Pyx_inner_PyErr_GivenExceptionMatches2(err, NULL, exc_type); + } else if (likely(PyTuple_Check(exc_type))) { + return __Pyx_PyErr_GivenExceptionMatchesTuple(err, exc_type); + } else { + } + } + return PyErr_GivenExceptionMatches(err, exc_type); } - - -static void __Pyx_WriteUnraisable(const char *name, int clineno, - int lineno, const char *filename) { - PyObject *old_exc, *old_val, *old_tb; - PyObject *ctx; - __Pyx_ErrFetch(&old_exc, &old_val, &old_tb); - #if PY_MAJOR_VERSION < 3 - ctx = PyString_FromString(name); - #else - ctx = PyUnicode_FromString(name); - #endif - __Pyx_ErrRestore(old_exc, old_val, old_tb); - if (!ctx) { - PyErr_WriteUnraisable(Py_None); - } else { - PyErr_WriteUnraisable(ctx); - Py_DECREF(ctx); +static CYTHON_INLINE int __Pyx_PyErr_GivenExceptionMatches2(PyObject *err, PyObject *exc_type1, PyObject *exc_type2) { + assert(PyExceptionClass_Check(exc_type1)); + assert(PyExceptionClass_Check(exc_type2)); + if (likely(err == exc_type1 || err == exc_type2)) return 1; + if (likely(PyExceptionClass_Check(err))) { + return __Pyx_inner_PyErr_GivenExceptionMatches2(err, exc_type1, exc_type2); } + return (PyErr_GivenExceptionMatches(err, exc_type1) || PyErr_GivenExceptionMatches(err, exc_type2)); } +#endif +/* CheckBinaryVersion */ static int __Pyx_check_binary_version(void) { char ctversion[4], rtversion[4]; PyOS_snprintf(ctversion, 4, "%d.%d", PY_MAJOR_VERSION, PY_MINOR_VERSION); @@ -1252,15 +2521,12 @@ static int __Pyx_check_binary_version(void) { "compiletime version %s of module '%.100s' " "does not match runtime version %s", ctversion, __Pyx_MODULE_NAME, rtversion); - #if PY_VERSION_HEX < 0x02050000 - return PyErr_Warn(NULL, message); - #else return PyErr_WarnEx(NULL, message, 1); - #endif } return 0; } +/* FunctionExport */ static int __Pyx_ExportFunction(const char *name, void (*f)(void), const char *sig) { PyObject *d = 0; PyObject *cobj = 0; @@ -1268,7 +2534,6 @@ static int __Pyx_ExportFunction(const char *name, void (*f)(void), const char *s void (*fp)(void); void *p; } tmp; - d = PyObject_GetAttrString(__pyx_m, (char *)"__pyx_capi__"); if (!d) { PyErr_Clear(); @@ -1280,7 +2545,7 @@ static int __Pyx_ExportFunction(const char *name, void (*f)(void), const char *s goto bad; } tmp.fp = f; -#if PY_VERSION_HEX >= 0x02070000 && !(PY_MAJOR_VERSION==3&&PY_MINOR_VERSION==0) +#if PY_VERSION_HEX >= 0x02070000 cobj = PyCapsule_New(tmp.p, sig, 0); #else cobj = PyCObject_FromVoidPtrAndDesc(tmp.p, (void *)sig, 0); @@ -1298,77 +2563,7 @@ static int __Pyx_ExportFunction(const char *name, void (*f)(void), const char *s return -1; } -#include "compile.h" -#include "frameobject.h" -#include "traceback.h" - -static void __Pyx_AddTraceback(const char *funcname, int __pyx_clineno, - int __pyx_lineno, const char *__pyx_filename) { - PyObject *py_srcfile = 0; - PyObject *py_funcname = 0; - PyObject *py_globals = 0; - PyCodeObject *py_code = 0; - PyFrameObject *py_frame = 0; - - #if PY_MAJOR_VERSION < 3 - py_srcfile = PyString_FromString(__pyx_filename); - #else - py_srcfile = PyUnicode_FromString(__pyx_filename); - #endif - if (!py_srcfile) goto bad; - if (__pyx_clineno) { - #if PY_MAJOR_VERSION < 3 - py_funcname = PyString_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, __pyx_clineno); - #else - py_funcname = PyUnicode_FromFormat( "%s (%s:%d)", funcname, __pyx_cfilenm, __pyx_clineno); - #endif - } - else { - #if PY_MAJOR_VERSION < 3 - py_funcname = PyString_FromString(funcname); - #else - py_funcname = PyUnicode_FromString(funcname); - #endif - } - if (!py_funcname) goto bad; - py_globals = PyModule_GetDict(__pyx_m); - if (!py_globals) goto bad; - py_code = PyCode_New( - 0, /*int argcount,*/ - #if PY_MAJOR_VERSION >= 3 - 0, /*int kwonlyargcount,*/ - #endif - 0, /*int nlocals,*/ - 0, /*int stacksize,*/ - 0, /*int flags,*/ - __pyx_empty_bytes, /*PyObject *code,*/ - __pyx_empty_tuple, /*PyObject *consts,*/ - __pyx_empty_tuple, /*PyObject *names,*/ - __pyx_empty_tuple, /*PyObject *varnames,*/ - __pyx_empty_tuple, /*PyObject *freevars,*/ - __pyx_empty_tuple, /*PyObject *cellvars,*/ - py_srcfile, /*PyObject *filename,*/ - py_funcname, /*PyObject *name,*/ - __pyx_lineno, /*int firstlineno,*/ - __pyx_empty_bytes /*PyObject *lnotab*/ - ); - if (!py_code) goto bad; - py_frame = PyFrame_New( - PyThreadState_GET(), /*PyThreadState *tstate,*/ - py_code, /*PyCodeObject *code,*/ - py_globals, /*PyObject *globals,*/ - 0 /*PyObject *locals*/ - ); - if (!py_frame) goto bad; - py_frame->f_lineno = __pyx_lineno; - PyTraceBack_Here(py_frame); -bad: - Py_XDECREF(py_srcfile); - Py_XDECREF(py_funcname); - Py_XDECREF(py_code); - Py_XDECREF(py_frame); -} - +/* InitStrings */ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) { while (t->p) { #if PY_MAJOR_VERSION < 3 @@ -1379,7 +2574,7 @@ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) { } else { *t->p = PyString_FromStringAndSize(t->s, t->n - 1); } - #else /* Python 3+ has unicode identifiers */ + #else if (t->is_unicode | t->is_str) { if (t->intern) { *t->p = PyUnicode_InternFromString(t->s); @@ -1394,56 +2589,158 @@ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) { #endif if (!*t->p) return -1; + if (PyObject_Hash(*t->p) == -1) + return -1; ++t; } return 0; } -/* Type Conversion Functions */ - +static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(const char* c_str) { + return __Pyx_PyUnicode_FromStringAndSize(c_str, (Py_ssize_t)strlen(c_str)); +} +static CYTHON_INLINE const char* __Pyx_PyObject_AsString(PyObject* o) { + Py_ssize_t ignore; + return __Pyx_PyObject_AsStringAndSize(o, &ignore); +} +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT +#if !CYTHON_PEP393_ENABLED +static const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { + char* defenc_c; + PyObject* defenc = _PyUnicode_AsDefaultEncodedString(o, NULL); + if (!defenc) return NULL; + defenc_c = PyBytes_AS_STRING(defenc); +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + { + char* end = defenc_c + PyBytes_GET_SIZE(defenc); + char* c; + for (c = defenc_c; c < end; c++) { + if ((unsigned char) (*c) >= 128) { + PyUnicode_AsASCIIString(o); + return NULL; + } + } + } +#endif + *length = PyBytes_GET_SIZE(defenc); + return defenc_c; +} +#else +static CYTHON_INLINE const char* __Pyx_PyUnicode_AsStringAndSize(PyObject* o, Py_ssize_t *length) { + if (unlikely(__Pyx_PyUnicode_READY(o) == -1)) return NULL; +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + if (likely(PyUnicode_IS_ASCII(o))) { + *length = PyUnicode_GET_LENGTH(o); + return PyUnicode_AsUTF8(o); + } else { + PyUnicode_AsASCIIString(o); + return NULL; + } +#else + return PyUnicode_AsUTF8AndSize(o, length); +#endif +} +#endif +#endif +static CYTHON_INLINE const char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_t *length) { +#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT + if ( +#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII + __Pyx_sys_getdefaultencoding_not_ascii && +#endif + PyUnicode_Check(o)) { + return __Pyx_PyUnicode_AsStringAndSize(o, length); + } else +#endif +#if (!CYTHON_COMPILING_IN_PYPY) || (defined(PyByteArray_AS_STRING) && defined(PyByteArray_GET_SIZE)) + if (PyByteArray_Check(o)) { + *length = PyByteArray_GET_SIZE(o); + return PyByteArray_AS_STRING(o); + } else +#endif + { + char* result; + int r = PyBytes_AsStringAndSize(o, &result, length); + if (unlikely(r < 0)) { + return NULL; + } else { + return result; + } + } +} static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) { int is_true = x == Py_True; if (is_true | (x == Py_False) | (x == Py_None)) return is_true; else return PyObject_IsTrue(x); } - -static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x) { +static CYTHON_INLINE int __Pyx_PyObject_IsTrueAndDecref(PyObject* x) { + int retval; + if (unlikely(!x)) return -1; + retval = __Pyx_PyObject_IsTrue(x); + Py_DECREF(x); + return retval; +} +static PyObject* __Pyx_PyNumber_IntOrLongWrongResultType(PyObject* result, const char* type_name) { +#if PY_MAJOR_VERSION >= 3 + if (PyLong_Check(result)) { + if (PyErr_WarnFormat(PyExc_DeprecationWarning, 1, + "__int__ returned non-int (type %.200s). " + "The ability to return an instance of a strict subclass of int " + "is deprecated, and may be removed in a future version of Python.", + Py_TYPE(result)->tp_name)) { + Py_DECREF(result); + return NULL; + } + return result; + } +#endif + PyErr_Format(PyExc_TypeError, + "__%.4s__ returned non-%.4s (type %.200s)", + type_name, type_name, Py_TYPE(result)->tp_name); + Py_DECREF(result); + return NULL; +} +static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x) { +#if CYTHON_USE_TYPE_SLOTS PyNumberMethods *m; +#endif const char *name = NULL; PyObject *res = NULL; -#if PY_VERSION_HEX < 0x03000000 - if (PyInt_Check(x) || PyLong_Check(x)) +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_Check(x) || PyLong_Check(x))) #else - if (PyLong_Check(x)) + if (likely(PyLong_Check(x))) #endif - return Py_INCREF(x), x; + return __Pyx_NewRef(x); +#if CYTHON_USE_TYPE_SLOTS m = Py_TYPE(x)->tp_as_number; -#if PY_VERSION_HEX < 0x03000000 + #if PY_MAJOR_VERSION < 3 if (m && m->nb_int) { name = "int"; - res = PyNumber_Int(x); + res = m->nb_int(x); } else if (m && m->nb_long) { name = "long"; - res = PyNumber_Long(x); + res = m->nb_long(x); } -#else - if (m && m->nb_int) { + #else + if (likely(m && m->nb_int)) { name = "int"; - res = PyNumber_Long(x); + res = m->nb_int(x); + } + #endif +#else + if (!PyBytes_CheckExact(x) && !PyUnicode_CheckExact(x)) { + res = PyNumber_Int(x); } #endif - if (res) { -#if PY_VERSION_HEX < 0x03000000 - if (!PyInt_Check(res) && !PyLong_Check(res)) { + if (likely(res)) { +#if PY_MAJOR_VERSION < 3 + if (unlikely(!PyInt_Check(res) && !PyLong_Check(res))) { #else - if (!PyLong_Check(res)) { + if (unlikely(!PyLong_CheckExact(res))) { #endif - PyErr_Format(PyExc_TypeError, - "__%s__ returned non-%s (type %.200s)", - name, name, Py_TYPE(res)->tp_name); - Py_DECREF(res); - return NULL; + return __Pyx_PyNumber_IntOrLongWrongResultType(res, name); } } else if (!PyErr_Occurred()) { @@ -1452,40 +2749,73 @@ static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x) { } return res; } - static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { Py_ssize_t ival; - PyObject* x = PyNumber_Index(b); + PyObject *x; +#if PY_MAJOR_VERSION < 3 + if (likely(PyInt_CheckExact(b))) { + if (sizeof(Py_ssize_t) >= sizeof(long)) + return PyInt_AS_LONG(b); + else + return PyInt_AsSsize_t(b); + } +#endif + if (likely(PyLong_CheckExact(b))) { + #if CYTHON_USE_PYLONG_INTERNALS + const digit* digits = ((PyLongObject*)b)->ob_digit; + const Py_ssize_t size = Py_SIZE(b); + if (likely(__Pyx_sst_abs(size) <= 1)) { + ival = likely(size) ? digits[0] : 0; + if (size == -1) ival = -ival; + return ival; + } else { + switch (size) { + case 2: + if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { + return (Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -2: + if (8 * sizeof(Py_ssize_t) > 2 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case 3: + if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { + return (Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -3: + if (8 * sizeof(Py_ssize_t) > 3 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((((size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case 4: + if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { + return (Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + case -4: + if (8 * sizeof(Py_ssize_t) > 4 * PyLong_SHIFT) { + return -(Py_ssize_t) (((((((((size_t)digits[3]) << PyLong_SHIFT) | (size_t)digits[2]) << PyLong_SHIFT) | (size_t)digits[1]) << PyLong_SHIFT) | (size_t)digits[0])); + } + break; + } + } + #endif + return PyLong_AsSsize_t(b); + } + x = PyNumber_Index(b); if (!x) return -1; ival = PyInt_AsSsize_t(x); Py_DECREF(x); return ival; } - -static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) { -#if PY_VERSION_HEX < 0x02050000 - if (ival <= LONG_MAX) - return PyInt_FromLong((long)ival); - else { - unsigned char *bytes = (unsigned char *) &ival; - int one = 1; int little = (int)*(unsigned char*)&one; - return _PyLong_FromByteArray(bytes, sizeof(size_t), little, 0); - } -#else - return PyInt_FromSize_t(ival); -#endif +static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b) { + return b ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False); } - -static CYTHON_INLINE size_t __Pyx_PyInt_AsSize_t(PyObject* x) { - unsigned PY_LONG_LONG val = __Pyx_PyInt_AsUnsignedLongLong(x); - if (unlikely(val == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())) { - return (size_t)-1; - } else if (unlikely(val != (unsigned PY_LONG_LONG)(size_t)val)) { - PyErr_SetString(PyExc_OverflowError, - "value too large to convert to size_t"); - return (size_t)-1; - } - return (size_t)val; +static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) { + return PyInt_FromSize_t(ival); } diff --git a/playground/cython/cython_cache/src/cy_cxxtest.h b/playground/cython/cython_cache/src/cy_cxxtest.h index 981a6c7d42..af40fd5905 100644 --- a/playground/cython/cython_cache/src/cy_cxxtest.h +++ b/playground/cython/cython_cache/src/cy_cxxtest.h @@ -1,3 +1,5 @@ +/* Generated by Cython 0.29 */ + #ifndef __PYX_HAVE__cy_cxxtest #define __PYX_HAVE__cy_cxxtest @@ -12,10 +14,17 @@ #endif #endif -__PYX_EXTERN_C DL_IMPORT(void) cy_hello(void); +#ifndef DL_IMPORT + #define DL_IMPORT(_T) _T +#endif + +__PYX_EXTERN_C void cy_hello(void); #endif /* !__PYX_HAVE_API__cy_cxxtest */ +/* WARNING: the interface of the module init function changed in CPython 3.5. */ +/* It now returns a PyModuleDef instance instead of a PyModule instance. */ + #if PY_MAJOR_VERSION < 3 PyMODINIT_FUNC initcy_cxxtest(void); #else diff --git a/playground/cython/cython_cache/src/cy_cxxtest_api.h b/playground/cython/cython_cache/src/cy_cxxtest_api.h index 3f7f2c5bde..871d67313f 100644 --- a/playground/cython/cython_cache/src/cy_cxxtest_api.h +++ b/playground/cython/cython_cache/src/cy_cxxtest_api.h @@ -1,31 +1,18 @@ +/* Generated by Cython 0.29 */ + #ifndef __PYX_HAVE_API__cy_cxxtest #define __PYX_HAVE_API__cy_cxxtest #include "Python.h" #include "cy_cxxtest.h" -static void (*__pyx_f_10cy_cxxtest_cy_hello)(void) = 0; -#define cy_hello __pyx_f_10cy_cxxtest_cy_hello - -#ifndef __PYX_HAVE_RT_ImportModule -#define __PYX_HAVE_RT_ImportModule -static PyObject *__Pyx_ImportModule(const char *name) { - PyObject *py_name = 0; - PyObject *py_module = 0; - - #if PY_MAJOR_VERSION < 3 - py_name = PyString_FromString(name); - #else - py_name = PyUnicode_FromString(name); - #endif - if (!py_name) - goto bad; - py_module = PyImport_Import(py_name); - Py_DECREF(py_name); - return py_module; -bad: - Py_XDECREF(py_name); - return 0; -} +static void (*__pyx_api_f_10cy_cxxtest_cy_hello)(void) = 0; +#define cy_hello __pyx_api_f_10cy_cxxtest_cy_hello +#if !defined(__Pyx_PyIdentifier_FromString) +#if PY_MAJOR_VERSION < 3 + #define __Pyx_PyIdentifier_FromString(s) PyString_FromString(s) +#else + #define __Pyx_PyIdentifier_FromString(s) PyUnicode_FromString(s) +#endif #endif #ifndef __PYX_HAVE_RT_ImportFunction @@ -37,21 +24,20 @@ static int __Pyx_ImportFunction(PyObject *module, const char *funcname, void (** void (*fp)(void); void *p; } tmp; - d = PyObject_GetAttrString(module, (char *)"__pyx_capi__"); if (!d) goto bad; cobj = PyDict_GetItemString(d, funcname); if (!cobj) { PyErr_Format(PyExc_ImportError, - "%s does not export expected C function %s", + "%.200s does not export expected C function %.200s", PyModule_GetName(module), funcname); goto bad; } -#if PY_VERSION_HEX >= 0x02070000 && !(PY_MAJOR_VERSION==3&&PY_MINOR_VERSION==0) +#if PY_VERSION_HEX >= 0x02070000 if (!PyCapsule_IsValid(cobj, sig)) { PyErr_Format(PyExc_TypeError, - "C function %s.%s has wrong signature (expected %s, got %s)", + "C function %.200s.%.200s has wrong signature (expected %.500s, got %.500s)", PyModule_GetName(module), funcname, sig, PyCapsule_GetName(cobj)); goto bad; } @@ -65,7 +51,7 @@ static int __Pyx_ImportFunction(PyObject *module, const char *funcname, void (** while (*s1 != '\0' && *s1 == *s2) { s1++; s2++; } if (*s1 != *s2) { PyErr_Format(PyExc_TypeError, - "C function %s.%s has wrong signature (expected %s, got %s)", + "C function %.200s.%.200s has wrong signature (expected %.500s, got %.500s)", PyModule_GetName(module), funcname, sig, desc); goto bad; } @@ -82,11 +68,12 @@ static int __Pyx_ImportFunction(PyObject *module, const char *funcname, void (** } #endif + static int import_cy_cxxtest(void) { PyObject *module = 0; - module = __Pyx_ImportModule("cy_cxxtest"); + module = PyImport_ImportModule("cy_cxxtest"); if (!module) goto bad; - if (__Pyx_ImportFunction(module, "cy_hello", (void (**)(void))&__pyx_f_10cy_cxxtest_cy_hello, "void (void)") < 0) goto bad; + if (__Pyx_ImportFunction(module, "cy_hello", (void (**)(void))&__pyx_api_f_10cy_cxxtest_cy_hello, "void (void)") < 0) goto bad; Py_DECREF(module); module = 0; return 0; bad: From ae9fb311ffa68d60ea026d3e0e133e815fff423a Mon Sep 17 00:00:00 2001 From: Nicolas Pauss Date: Tue, 27 Nov 2018 15:21:22 +0100 Subject: [PATCH 046/315] cython: add 'from cpython.version cimport PY_VERSION' example in playground. This test the latest improvement of the regex in cython extra. --- playground/cython/cython_cache/src/cy_ctest.c | 224 ++++++++++++++++-- .../cython/cython_cache/src/cy_cxxtest.cc | 74 ++++-- playground/cython/src/cy_ctest.pyx | 3 + playground/cython/src/cy_cxxtest.pyx | 3 +- 4 files changed, 264 insertions(+), 40 deletions(-) diff --git a/playground/cython/cython_cache/src/cy_ctest.c b/playground/cython/cython_cache/src/cy_ctest.c index 3a8930b664..071c34479c 100644 --- a/playground/cython/cython_cache/src/cy_ctest.c +++ b/playground/cython/cython_cache/src/cy_ctest.c @@ -951,6 +951,16 @@ static void __pyx_insert_code_object(int code_line, PyCodeObject* code_object); static void __Pyx_AddTraceback(const char *funcname, int c_line, int py_line, const char *filename); +/* Print.proto */ +static int __Pyx_Print(PyObject*, PyObject *, int); +#if CYTHON_COMPILING_IN_PYPY || PY_MAJOR_VERSION >= 3 +static PyObject* __pyx_print = 0; +static PyObject* __pyx_print_kwargs = 0; +#endif + +/* PrintOne.proto */ +static int __Pyx_PrintOne(PyObject* stream, PyObject *o); + /* CIntToPy.proto */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value); @@ -980,35 +990,46 @@ static int __Pyx_check_binary_version(void); static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); +/* Module declarations from 'cpython.version' */ + /* Module declarations from 'cy_ctest' */ #define __Pyx_MODULE_NAME "cy_ctest" extern int __pyx_module_is_main_cy_ctest; int __pyx_module_is_main_cy_ctest = 0; /* Implementation of 'cy_ctest' */ +static const char __pyx_k_end[] = "end"; +static const char __pyx_k_file[] = "file"; static const char __pyx_k_main[] = "__main__"; static const char __pyx_k_name[] = "__name__"; static const char __pyx_k_test[] = "__test__"; +static const char __pyx_k_print[] = "print"; static const char __pyx_k_pyhello[] = "pyhello"; static const char __pyx_k_cy_ctest[] = "cy_ctest"; static const char __pyx_k_cline_in_traceback[] = "cline_in_traceback"; +static const char __pyx_k_Compiled_with_python_version_s[] = "Compiled with python version %s"; static const char __pyx_k_home_romain_dev_waf_wrapper_waf[] = "/home/romain/dev/waf-wrapper/waf/playground/cython/src/cy_ctest.pyx"; +static PyObject *__pyx_kp_s_Compiled_with_python_version_s; static PyObject *__pyx_n_s_cline_in_traceback; static PyObject *__pyx_n_s_cy_ctest; +static PyObject *__pyx_n_s_end; +static PyObject *__pyx_n_s_file; static PyObject *__pyx_kp_s_home_romain_dev_waf_wrapper_waf; static PyObject *__pyx_n_s_main; static PyObject *__pyx_n_s_name; +static PyObject *__pyx_n_s_print; static PyObject *__pyx_n_s_pyhello; static PyObject *__pyx_n_s_test; static PyObject *__pyx_pf_8cy_ctest_pyhello(CYTHON_UNUSED PyObject *__pyx_self); /* proto */ static PyObject *__pyx_codeobj_; /* Late includes */ -/* "cy_ctest.pyx":3 - * cimport cy_ctest +/* "cy_ctest.pyx":5 + * #cimport commented_import * * def pyhello(): # <<<<<<<<<<<<<< * cy_ctest.hello() + * print("Compiled with python version %s" % PY_VERSION) */ /* Python wrapper */ @@ -1028,24 +1049,48 @@ static PyObject *__pyx_pw_8cy_ctest_1pyhello(PyObject *__pyx_self, CYTHON_UNUSED static PyObject *__pyx_pf_8cy_ctest_pyhello(CYTHON_UNUSED PyObject *__pyx_self) { PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; __Pyx_RefNannySetupContext("pyhello", 0); - /* "cy_ctest.pyx":4 + /* "cy_ctest.pyx":6 * * def pyhello(): * cy_ctest.hello() # <<<<<<<<<<<<<< + * print("Compiled with python version %s" % PY_VERSION) */ hello(); - /* "cy_ctest.pyx":3 - * cimport cy_ctest + /* "cy_ctest.pyx":7 + * def pyhello(): + * cy_ctest.hello() + * print("Compiled with python version %s" % PY_VERSION) # <<<<<<<<<<<<<< + */ + __pyx_t_1 = __Pyx_PyObject_FromString(PY_VERSION); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyString_Format(__pyx_kp_s_Compiled_with_python_version_s, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 7, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (__Pyx_PrintOne(0, __pyx_t_2) < 0) __PYX_ERR(0, 7, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "cy_ctest.pyx":5 + * #cimport commented_import * * def pyhello(): # <<<<<<<<<<<<<< * cy_ctest.hello() + * print("Compiled with python version %s" % PY_VERSION) */ /* function exit code */ __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_AddTraceback("cy_ctest.pyhello", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; @@ -1097,11 +1142,15 @@ static struct PyModuleDef __pyx_moduledef = { #endif static __Pyx_StringTabEntry __pyx_string_tab[] = { + {&__pyx_kp_s_Compiled_with_python_version_s, __pyx_k_Compiled_with_python_version_s, sizeof(__pyx_k_Compiled_with_python_version_s), 0, 0, 1, 0}, {&__pyx_n_s_cline_in_traceback, __pyx_k_cline_in_traceback, sizeof(__pyx_k_cline_in_traceback), 0, 0, 1, 1}, {&__pyx_n_s_cy_ctest, __pyx_k_cy_ctest, sizeof(__pyx_k_cy_ctest), 0, 0, 1, 1}, + {&__pyx_n_s_end, __pyx_k_end, sizeof(__pyx_k_end), 0, 0, 1, 1}, + {&__pyx_n_s_file, __pyx_k_file, sizeof(__pyx_k_file), 0, 0, 1, 1}, {&__pyx_kp_s_home_romain_dev_waf_wrapper_waf, __pyx_k_home_romain_dev_waf_wrapper_waf, sizeof(__pyx_k_home_romain_dev_waf_wrapper_waf), 0, 0, 1, 0}, {&__pyx_n_s_main, __pyx_k_main, sizeof(__pyx_k_main), 0, 0, 1, 1}, {&__pyx_n_s_name, __pyx_k_name, sizeof(__pyx_k_name), 0, 0, 1, 1}, + {&__pyx_n_s_print, __pyx_k_print, sizeof(__pyx_k_print), 0, 0, 1, 1}, {&__pyx_n_s_pyhello, __pyx_k_pyhello, sizeof(__pyx_k_pyhello), 0, 0, 1, 1}, {&__pyx_n_s_test, __pyx_k_test, sizeof(__pyx_k_test), 0, 0, 1, 1}, {0, 0, 0, 0, 0, 0, 0} @@ -1114,13 +1163,14 @@ static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0); - /* "cy_ctest.pyx":3 - * cimport cy_ctest + /* "cy_ctest.pyx":5 + * #cimport commented_import * * def pyhello(): # <<<<<<<<<<<<<< * cy_ctest.hello() + * print("Compiled with python version %s" % PY_VERSION) */ - __pyx_codeobj_ = (PyObject*)__Pyx_PyCode_New(0, 0, 0, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_romain_dev_waf_wrapper_waf, __pyx_n_s_pyhello, 3, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj_)) __PYX_ERR(0, 3, __pyx_L1_error) + __pyx_codeobj_ = (PyObject*)__Pyx_PyCode_New(0, 0, 0, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_romain_dev_waf_wrapper_waf, __pyx_n_s_pyhello, 5, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj_)) __PYX_ERR(0, 5, __pyx_L1_error) __Pyx_RefNannyFinishContext(); return 0; __pyx_L1_error:; @@ -1395,21 +1445,22 @@ if (!__Pyx_RefNanny) { if (__Pyx_patch_abc() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif - /* "cy_ctest.pyx":3 - * cimport cy_ctest + /* "cy_ctest.pyx":5 + * #cimport commented_import * * def pyhello(): # <<<<<<<<<<<<<< * cy_ctest.hello() + * print("Compiled with python version %s" % PY_VERSION) */ - __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_8cy_ctest_1pyhello, NULL, __pyx_n_s_cy_ctest); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3, __pyx_L1_error) + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_8cy_ctest_1pyhello, NULL, __pyx_n_s_cy_ctest); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 5, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_pyhello, __pyx_t_1) < 0) __PYX_ERR(0, 3, __pyx_L1_error) + if (PyDict_SetItem(__pyx_d, __pyx_n_s_pyhello, __pyx_t_1) < 0) __PYX_ERR(0, 5, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; /* "cy_ctest.pyx":1 - * cimport cy_ctest # <<<<<<<<<<<<<< - * - * def pyhello(): + * from cpython.version cimport PY_VERSION # <<<<<<<<<<<<<< + * cimport cy_ctest + * #cimport commented_import */ __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); @@ -1703,6 +1754,149 @@ static void __Pyx_AddTraceback(const char *funcname, int c_line, Py_XDECREF(py_frame); } +/* Print */ +#if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION < 3 +static PyObject *__Pyx_GetStdout(void) { + PyObject *f = PySys_GetObject((char *)"stdout"); + if (!f) { + PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout"); + } + return f; +} +static int __Pyx_Print(PyObject* f, PyObject *arg_tuple, int newline) { + int i; + if (!f) { + if (!(f = __Pyx_GetStdout())) + return -1; + } + Py_INCREF(f); + for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) { + PyObject* v; + if (PyFile_SoftSpace(f, 1)) { + if (PyFile_WriteString(" ", f) < 0) + goto error; + } + v = PyTuple_GET_ITEM(arg_tuple, i); + if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0) + goto error; + if (PyString_Check(v)) { + char *s = PyString_AsString(v); + Py_ssize_t len = PyString_Size(v); + if (len > 0) { + switch (s[len-1]) { + case ' ': break; + case '\f': case '\r': case '\n': case '\t': case '\v': + PyFile_SoftSpace(f, 0); + break; + default: break; + } + } + } + } + if (newline) { + if (PyFile_WriteString("\n", f) < 0) + goto error; + PyFile_SoftSpace(f, 0); + } + Py_DECREF(f); + return 0; +error: + Py_DECREF(f); + return -1; +} +#else +static int __Pyx_Print(PyObject* stream, PyObject *arg_tuple, int newline) { + PyObject* kwargs = 0; + PyObject* result = 0; + PyObject* end_string; + if (unlikely(!__pyx_print)) { + __pyx_print = PyObject_GetAttr(__pyx_b, __pyx_n_s_print); + if (!__pyx_print) + return -1; + } + if (stream) { + kwargs = PyDict_New(); + if (unlikely(!kwargs)) + return -1; + if (unlikely(PyDict_SetItem(kwargs, __pyx_n_s_file, stream) < 0)) + goto bad; + if (!newline) { + end_string = PyUnicode_FromStringAndSize(" ", 1); + if (unlikely(!end_string)) + goto bad; + if (PyDict_SetItem(kwargs, __pyx_n_s_end, end_string) < 0) { + Py_DECREF(end_string); + goto bad; + } + Py_DECREF(end_string); + } + } else if (!newline) { + if (unlikely(!__pyx_print_kwargs)) { + __pyx_print_kwargs = PyDict_New(); + if (unlikely(!__pyx_print_kwargs)) + return -1; + end_string = PyUnicode_FromStringAndSize(" ", 1); + if (unlikely(!end_string)) + return -1; + if (PyDict_SetItem(__pyx_print_kwargs, __pyx_n_s_end, end_string) < 0) { + Py_DECREF(end_string); + return -1; + } + Py_DECREF(end_string); + } + kwargs = __pyx_print_kwargs; + } + result = PyObject_Call(__pyx_print, arg_tuple, kwargs); + if (unlikely(kwargs) && (kwargs != __pyx_print_kwargs)) + Py_DECREF(kwargs); + if (!result) + return -1; + Py_DECREF(result); + return 0; +bad: + if (kwargs != __pyx_print_kwargs) + Py_XDECREF(kwargs); + return -1; +} +#endif + +/* PrintOne */ +#if !CYTHON_COMPILING_IN_PYPY && PY_MAJOR_VERSION < 3 +static int __Pyx_PrintOne(PyObject* f, PyObject *o) { + if (!f) { + if (!(f = __Pyx_GetStdout())) + return -1; + } + Py_INCREF(f); + if (PyFile_SoftSpace(f, 0)) { + if (PyFile_WriteString(" ", f) < 0) + goto error; + } + if (PyFile_WriteObject(o, f, Py_PRINT_RAW) < 0) + goto error; + if (PyFile_WriteString("\n", f) < 0) + goto error; + Py_DECREF(f); + return 0; +error: + Py_DECREF(f); + return -1; + /* the line below is just to avoid C compiler + * warnings about unused functions */ + return __Pyx_Print(f, NULL, 0); +} +#else +static int __Pyx_PrintOne(PyObject* stream, PyObject *o) { + int res; + PyObject* arg_tuple = PyTuple_Pack(1, o); + if (unlikely(!arg_tuple)) + return -1; + res = __Pyx_Print(stream, arg_tuple, 1); + Py_DECREF(arg_tuple); + return res; +} +#endif + /* CIntToPy */ static CYTHON_INLINE PyObject* __Pyx_PyInt_From_long(long value) { const long neg_one = (long) ((long) 0 - (long) 1), const_zero = (long) 0; diff --git a/playground/cython/cython_cache/src/cy_cxxtest.cc b/playground/cython/cython_cache/src/cy_cxxtest.cc index 0d56fbddb0..3259cd812a 100644 --- a/playground/cython/cython_cache/src/cy_cxxtest.cc +++ b/playground/cython/cython_cache/src/cy_cxxtest.cc @@ -1012,6 +1012,8 @@ static int __Pyx_ExportFunction(const char *name, void (*f)(void), const char *s static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); +/* Module declarations from 'cpython.version' */ + /* Module declarations from 'cy_cxxtest' */ __PYX_EXTERN_C void cy_hello(void); /*proto*/ #define __Pyx_MODULE_NAME "cy_cxxtest" @@ -1029,7 +1031,9 @@ static const char __pyx_k_pyhello[] = "pyhello"; static const char __pyx_k_cy_cxxtest[] = "cy_cxxtest"; static const char __pyx_k_cline_in_traceback[] = "cline_in_traceback"; static const char __pyx_k_hello_cython_world[] = "hello cython-world!"; +static const char __pyx_k_Compiled_with_python_version_s[] = "Compiled with python version %s"; static const char __pyx_k_home_romain_dev_waf_wrapper_waf[] = "/home/romain/dev/waf-wrapper/waf/playground/cython/src/cy_cxxtest.pyx"; +static PyObject *__pyx_kp_s_Compiled_with_python_version_s; static PyObject *__pyx_n_s_cline_in_traceback; static PyObject *__pyx_n_s_cy_cxxtest; static PyObject *__pyx_n_s_end; @@ -1045,12 +1049,12 @@ static PyObject *__pyx_pf_10cy_cxxtest_pyhello(CYTHON_UNUSED PyObject *__pyx_sel static PyObject *__pyx_codeobj_; /* Late includes */ -/* "cy_cxxtest.pyx":3 +/* "cy_cxxtest.pyx":4 * cimport cy_cxxtest * * def pyhello(): # <<<<<<<<<<<<<< * cy_cxxtest.hello() - * + * print("Compiled with python version %s" % PY_VERSION) */ /* Python wrapper */ @@ -1070,58 +1074,79 @@ static PyObject *__pyx_pw_10cy_cxxtest_1pyhello(PyObject *__pyx_self, CYTHON_UNU static PyObject *__pyx_pf_10cy_cxxtest_pyhello(CYTHON_UNUSED PyObject *__pyx_self) { PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations + PyObject *__pyx_t_1 = NULL; + PyObject *__pyx_t_2 = NULL; __Pyx_RefNannySetupContext("pyhello", 0); - /* "cy_cxxtest.pyx":4 + /* "cy_cxxtest.pyx":5 * * def pyhello(): * cy_cxxtest.hello() # <<<<<<<<<<<<<< + * print("Compiled with python version %s" % PY_VERSION) * - * cdef public api void cy_hello(): */ hello(); - /* "cy_cxxtest.pyx":3 + /* "cy_cxxtest.pyx":6 + * def pyhello(): + * cy_cxxtest.hello() + * print("Compiled with python version %s" % PY_VERSION) # <<<<<<<<<<<<<< + * + * cdef public api void cy_hello(): + */ + __pyx_t_1 = __Pyx_PyObject_FromString(PY_VERSION); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_1); + __pyx_t_2 = __Pyx_PyString_Format(__pyx_kp_s_Compiled_with_python_version_s, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 6, __pyx_L1_error) + __Pyx_GOTREF(__pyx_t_2); + __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; + if (__Pyx_PrintOne(0, __pyx_t_2) < 0) __PYX_ERR(0, 6, __pyx_L1_error) + __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; + + /* "cy_cxxtest.pyx":4 * cimport cy_cxxtest * * def pyhello(): # <<<<<<<<<<<<<< * cy_cxxtest.hello() - * + * print("Compiled with python version %s" % PY_VERSION) */ /* function exit code */ __pyx_r = Py_None; __Pyx_INCREF(Py_None); + goto __pyx_L0; + __pyx_L1_error:; + __Pyx_XDECREF(__pyx_t_1); + __Pyx_XDECREF(__pyx_t_2); + __Pyx_AddTraceback("cy_cxxtest.pyhello", __pyx_clineno, __pyx_lineno, __pyx_filename); + __pyx_r = NULL; + __pyx_L0:; __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } -/* "cy_cxxtest.pyx":6 - * cy_cxxtest.hello() +/* "cy_cxxtest.pyx":8 + * print("Compiled with python version %s" % PY_VERSION) * * cdef public api void cy_hello(): # <<<<<<<<<<<<<< * print("hello cython-world!") - * */ void cy_hello(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("cy_hello", 0); - /* "cy_cxxtest.pyx":7 + /* "cy_cxxtest.pyx":9 * * cdef public api void cy_hello(): * print("hello cython-world!") # <<<<<<<<<<<<<< - * */ - if (__Pyx_PrintOne(0, __pyx_kp_s_hello_cython_world) < 0) __PYX_ERR(0, 7, __pyx_L1_error) + if (__Pyx_PrintOne(0, __pyx_kp_s_hello_cython_world) < 0) __PYX_ERR(0, 9, __pyx_L1_error) - /* "cy_cxxtest.pyx":6 - * cy_cxxtest.hello() + /* "cy_cxxtest.pyx":8 + * print("Compiled with python version %s" % PY_VERSION) * * cdef public api void cy_hello(): # <<<<<<<<<<<<<< * print("hello cython-world!") - * */ /* function exit code */ @@ -1178,6 +1203,7 @@ static struct PyModuleDef __pyx_moduledef = { #endif static __Pyx_StringTabEntry __pyx_string_tab[] = { + {&__pyx_kp_s_Compiled_with_python_version_s, __pyx_k_Compiled_with_python_version_s, sizeof(__pyx_k_Compiled_with_python_version_s), 0, 0, 1, 0}, {&__pyx_n_s_cline_in_traceback, __pyx_k_cline_in_traceback, sizeof(__pyx_k_cline_in_traceback), 0, 0, 1, 1}, {&__pyx_n_s_cy_cxxtest, __pyx_k_cy_cxxtest, sizeof(__pyx_k_cy_cxxtest), 0, 0, 1, 1}, {&__pyx_n_s_end, __pyx_k_end, sizeof(__pyx_k_end), 0, 0, 1, 1}, @@ -1199,14 +1225,14 @@ static CYTHON_SMALL_CODE int __Pyx_InitCachedConstants(void) { __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("__Pyx_InitCachedConstants", 0); - /* "cy_cxxtest.pyx":3 + /* "cy_cxxtest.pyx":4 * cimport cy_cxxtest * * def pyhello(): # <<<<<<<<<<<<<< * cy_cxxtest.hello() - * + * print("Compiled with python version %s" % PY_VERSION) */ - __pyx_codeobj_ = (PyObject*)__Pyx_PyCode_New(0, 0, 0, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_romain_dev_waf_wrapper_waf, __pyx_n_s_pyhello, 3, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj_)) __PYX_ERR(0, 3, __pyx_L1_error) + __pyx_codeobj_ = (PyObject*)__Pyx_PyCode_New(0, 0, 0, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_home_romain_dev_waf_wrapper_waf, __pyx_n_s_pyhello, 4, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj_)) __PYX_ERR(0, 4, __pyx_L1_error) __Pyx_RefNannyFinishContext(); return 0; __pyx_L1_error:; @@ -1485,22 +1511,22 @@ if (!__Pyx_RefNanny) { if (__Pyx_patch_abc() < 0) __PYX_ERR(0, 1, __pyx_L1_error) #endif - /* "cy_cxxtest.pyx":3 + /* "cy_cxxtest.pyx":4 * cimport cy_cxxtest * * def pyhello(): # <<<<<<<<<<<<<< * cy_cxxtest.hello() - * + * print("Compiled with python version %s" % PY_VERSION) */ - __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_10cy_cxxtest_1pyhello, NULL, __pyx_n_s_cy_cxxtest); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 3, __pyx_L1_error) + __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_10cy_cxxtest_1pyhello, NULL, __pyx_n_s_cy_cxxtest); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 4, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); - if (PyDict_SetItem(__pyx_d, __pyx_n_s_pyhello, __pyx_t_1) < 0) __PYX_ERR(0, 3, __pyx_L1_error) + if (PyDict_SetItem(__pyx_d, __pyx_n_s_pyhello, __pyx_t_1) < 0) __PYX_ERR(0, 4, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; /* "cy_cxxtest.pyx":1 - * cimport cy_cxxtest # <<<<<<<<<<<<<< + * from cpython.version cimport PY_VERSION # <<<<<<<<<<<<<< + * cimport cy_cxxtest * - * def pyhello(): */ __pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); diff --git a/playground/cython/src/cy_ctest.pyx b/playground/cython/src/cy_ctest.pyx index ddf4b0be98..2fc1f96cc8 100644 --- a/playground/cython/src/cy_ctest.pyx +++ b/playground/cython/src/cy_ctest.pyx @@ -1,4 +1,7 @@ +from cpython.version cimport PY_VERSION cimport cy_ctest +#cimport commented_import def pyhello(): cy_ctest.hello() + print("Compiled with python version %s" % PY_VERSION) diff --git a/playground/cython/src/cy_cxxtest.pyx b/playground/cython/src/cy_cxxtest.pyx index 1102b97b24..85edefc884 100644 --- a/playground/cython/src/cy_cxxtest.pyx +++ b/playground/cython/src/cy_cxxtest.pyx @@ -1,8 +1,9 @@ +from cpython.version cimport PY_VERSION cimport cy_cxxtest def pyhello(): cy_cxxtest.hello() + print("Compiled with python version %s" % PY_VERSION) cdef public api void cy_hello(): print("hello cython-world!") - From ff2db6a087efc5c0bd11c31261f5b0ac0fc89ad7 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Mon, 3 Dec 2018 15:46:09 +0100 Subject: [PATCH 047/315] waf-2.0.13 --- ChangeLog | 7 +++++++ waf-light | 2 +- waflib/Context.py | 6 +++--- wscript | 2 +- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index eef0590a27..d2e16c3334 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +NEW IN WAF 2.0.13 +----------------- +* Fix "broken revdeps" extra error message on certain build failures +* Avoid duplicate flags in Python configuration tests +* Find more Swig dependencies #2206 +* Avoid spawning threads with -j1 on AIX systems + NEW IN WAF 2.0.12 ----------------- * Fix broken inheritance task trees #2194 diff --git a/waf-light b/waf-light index a2efc852c7..10b1cd470a 100755 --- a/waf-light +++ b/waf-light @@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. import os, sys, inspect -VERSION="2.0.12" +VERSION="2.0.13" REVISION="x" GIT="x" INSTALL="x" diff --git a/waflib/Context.py b/waflib/Context.py index 7c6cd9608f..fce04790a4 100644 --- a/waflib/Context.py +++ b/waflib/Context.py @@ -11,13 +11,13 @@ import waflib.Node # the following 3 constants are updated on each new release (do not touch) -HEXVERSION=0x2000c00 +HEXVERSION=0x2000d00 """Constant updated on new releases""" -WAFVERSION="2.0.12" +WAFVERSION="2.0.13" """Constant updated on new releases""" -WAFREVISION="54841218840ffa34fddf834680a5a17db69caa12" +WAFREVISION="1607738e97e9453f5d5c7c911ba7dfdc0d4ddc2a" """Git revision when the waf version is updated""" ABI = 20 diff --git a/wscript b/wscript index 8ed667a1a0..f02913cc83 100644 --- a/wscript +++ b/wscript @@ -11,7 +11,7 @@ To add a tool that does not exist in the folder compat15, pass an absolute path: from __future__ import with_statement -VERSION="2.0.12" +VERSION="2.0.13" APPNAME='waf' REVISION='' From 81efa3a0f792e360157fb5c625b71804f948f457 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Wed, 5 Dec 2018 20:35:19 +0100 Subject: [PATCH 048/315] Try to load sha1 if md5 is unavailable Also, the minimum version of Python required is 2.5, so hashlib is always present. --- waflib/Utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/Utils.py b/waflib/Utils.py index b4665c4dc2..67917d8b55 100644 --- a/waflib/Utils.py +++ b/waflib/Utils.py @@ -49,7 +49,7 @@ class TimeoutExpired(Exception): from hashlib import md5 except ImportError: try: - from md5 import md5 + from hashlib import sha1 as md5 except ImportError: # never fail to enable fixes from another module pass From b5e323d60746e097109d9c460bda4ad9afbdbdc7 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Wed, 5 Dec 2018 20:49:07 +0100 Subject: [PATCH 049/315] Provide a better Cuda example #2212 --- playground/cuda/test.cpp | 5 +++++ playground/cuda/wscript | 11 ++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 playground/cuda/test.cpp diff --git a/playground/cuda/test.cpp b/playground/cuda/test.cpp new file mode 100644 index 0000000000..ffacf6e6c0 --- /dev/null +++ b/playground/cuda/test.cpp @@ -0,0 +1,5 @@ +int main() +{ + return 0; +} + diff --git a/playground/cuda/wscript b/playground/cuda/wscript index 64053112e0..f4b56f2ac7 100644 --- a/playground/cuda/wscript +++ b/playground/cuda/wscript @@ -16,14 +16,23 @@ def configure(conf): # conf.env.LIBPATH_CUDA = ['c:\\foo\\bar\\lib'] # conf.env.INCLUDES_CUDA = ['c:\\foo\\bar\\includes'] + conf.env = conf.all_envs['cuda'] = conf.env.derive() conf.load('cuda', tooldir='.') def build(bld): + # native application + bld.program( + source = 'test.cpp', + target = 'testapp', + ) + + # cuda application t = bld.program( source = 'test.cu main.cpp', target = 'app', - use = 'CUDA CUDART') + use = 'CUDA CUDART', + env = bld.all_envs['cuda']) #t.env.CUDAFLAGS = ['-deviceemu'] # --ptxas-options="-v" From 786e74bbdcdf42cd41d5ad4282e463e469c28011 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Thu, 6 Dec 2018 07:44:36 +0100 Subject: [PATCH 050/315] Fix broken cPython: md5.digest() is not supposed to raise exceptions #2213 --- waflib/Utils.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/waflib/Utils.py b/waflib/Utils.py index 67917d8b55..3d707a5843 100644 --- a/waflib/Utils.py +++ b/waflib/Utils.py @@ -51,8 +51,14 @@ class TimeoutExpired(Exception): try: from hashlib import sha1 as md5 except ImportError: - # never fail to enable fixes from another module + # never fail to enable potential fixes from another module pass +else: + try: + md5().digest() + except ValueError: + # Fips? #2213 + from hashlib import sha1 as md5 try: import threading From 1eb4f116a9d1c3cb3d4e9dafb555d10e715cbb74 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Fri, 7 Dec 2018 07:57:43 +0100 Subject: [PATCH 051/315] Improve the cuda example #2212 --- playground/cuda/cuda.py | 9 ++++++++- playground/cuda/wscript | 25 ++++++++++++++++--------- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/playground/cuda/cuda.py b/playground/cuda/cuda.py index 3c3a84bcb9..6b92a1cde9 100644 --- a/playground/cuda/cuda.py +++ b/playground/cuda/cuda.py @@ -4,7 +4,6 @@ "cuda" -import os from waflib import Task from waflib.TaskGen import extension from waflib.Tools import ccroot, c_preproc @@ -22,6 +21,14 @@ class cuda(Task.Task): def c_hook(self, node): return self.create_compiled_task('cuda', node) +@extension('.cpp') +def cxx_hook(self, node): + # override processing for one particular type of file + if getattr(self, 'cuda', False): + return self.create_compiled_task('cuda', node) + else: + return self.create_compiled_task('cxx', node) + def configure(conf): conf.find_program('nvcc', var='NVCC') conf.find_cuda_libs() diff --git a/playground/cuda/wscript b/playground/cuda/wscript index f4b56f2ac7..9daf81e481 100644 --- a/playground/cuda/wscript +++ b/playground/cuda/wscript @@ -16,25 +16,32 @@ def configure(conf): # conf.env.LIBPATH_CUDA = ['c:\\foo\\bar\\lib'] # conf.env.INCLUDES_CUDA = ['c:\\foo\\bar\\includes'] - conf.env = conf.all_envs['cuda'] = conf.env.derive() conf.load('cuda', tooldir='.') def build(bld): - # native application - bld.program( - source = 'test.cpp', - target = 'testapp', - ) - # cuda application t = bld.program( source = 'test.cu main.cpp', target = 'app', - use = 'CUDA CUDART', - env = bld.all_envs['cuda']) + use = 'CUDA CUDART') #t.env.CUDAFLAGS = ['-deviceemu'] # --ptxas-options="-v" # --ptxas-options="-v -maxrregcount=10" + # ----------------------- + + # native application + bld.program( + source = 'test.cpp', + target = 'testapp') + + # cuda application + bld.program( + source = 'test.cpp', + target = 'testapp', + cuda = True, + use = 'CUDA CUDART') + + From fa26374fecc7db2e800195e758ea39ef2f4349d0 Mon Sep 17 00:00:00 2001 From: fedepell Date: Wed, 12 Dec 2018 07:07:17 +0100 Subject: [PATCH 052/315] javaw: add recursive use processing if recurse_use=True --- .../java_recursive_use/a/src/JavaTestA.java | 2 + playground/java_recursive_use/a/wscript | 7 ++++ .../java_recursive_use/b/src/JavaTestB.java | 2 + playground/java_recursive_use/b/wscript | 8 ++++ .../java_recursive_use/c/src/JavaTestC.java | 2 + playground/java_recursive_use/c/wscript | 9 +++++ .../java_recursive_use/d/src/JavaTestD.java | 2 + playground/java_recursive_use/d/wscript | 9 +++++ playground/java_recursive_use/wscript | 22 ++++++++++ waflib/Tools/javaw.py | 40 +++++++++++++++++-- 10 files changed, 99 insertions(+), 4 deletions(-) create mode 100644 playground/java_recursive_use/a/src/JavaTestA.java create mode 100644 playground/java_recursive_use/a/wscript create mode 100644 playground/java_recursive_use/b/src/JavaTestB.java create mode 100644 playground/java_recursive_use/b/wscript create mode 100644 playground/java_recursive_use/c/src/JavaTestC.java create mode 100644 playground/java_recursive_use/c/wscript create mode 100644 playground/java_recursive_use/d/src/JavaTestD.java create mode 100644 playground/java_recursive_use/d/wscript create mode 100644 playground/java_recursive_use/wscript diff --git a/playground/java_recursive_use/a/src/JavaTestA.java b/playground/java_recursive_use/a/src/JavaTestA.java new file mode 100644 index 0000000000..cce730e740 --- /dev/null +++ b/playground/java_recursive_use/a/src/JavaTestA.java @@ -0,0 +1,2 @@ +public class JavaTestA { +} diff --git a/playground/java_recursive_use/a/wscript b/playground/java_recursive_use/a/wscript new file mode 100644 index 0000000000..26064a6aad --- /dev/null +++ b/playground/java_recursive_use/a/wscript @@ -0,0 +1,7 @@ + +def build(bld): + bld(features='javac jar', + srcdir='src', + name='a', + basedir='.' + ) diff --git a/playground/java_recursive_use/b/src/JavaTestB.java b/playground/java_recursive_use/b/src/JavaTestB.java new file mode 100644 index 0000000000..b2067ec415 --- /dev/null +++ b/playground/java_recursive_use/b/src/JavaTestB.java @@ -0,0 +1,2 @@ +public class JavaTestB extends JavaTestA { +} diff --git a/playground/java_recursive_use/b/wscript b/playground/java_recursive_use/b/wscript new file mode 100644 index 0000000000..a5e6785308 --- /dev/null +++ b/playground/java_recursive_use/b/wscript @@ -0,0 +1,8 @@ + +def build(bld): + bld(features='javac jar', + srcdir='src', + name='b', + basedir='.', + use='a' + ) diff --git a/playground/java_recursive_use/c/src/JavaTestC.java b/playground/java_recursive_use/c/src/JavaTestC.java new file mode 100644 index 0000000000..1f42f48b3c --- /dev/null +++ b/playground/java_recursive_use/c/src/JavaTestC.java @@ -0,0 +1,2 @@ +public class JavaTestC extends JavaTestB { +} diff --git a/playground/java_recursive_use/c/wscript b/playground/java_recursive_use/c/wscript new file mode 100644 index 0000000000..3cc393f8c3 --- /dev/null +++ b/playground/java_recursive_use/c/wscript @@ -0,0 +1,9 @@ + +def build(bld): + bld(features='javac jar', + srcdir='src', + name='c', + basedir='.', + use='b', + recurse_use = True + ) diff --git a/playground/java_recursive_use/d/src/JavaTestD.java b/playground/java_recursive_use/d/src/JavaTestD.java new file mode 100644 index 0000000000..308c741ba0 --- /dev/null +++ b/playground/java_recursive_use/d/src/JavaTestD.java @@ -0,0 +1,2 @@ +public class JavaTestD extends JavaTestC { +} diff --git a/playground/java_recursive_use/d/wscript b/playground/java_recursive_use/d/wscript new file mode 100644 index 0000000000..82580c45df --- /dev/null +++ b/playground/java_recursive_use/d/wscript @@ -0,0 +1,9 @@ + +def build(bld): + bld(features='javac jar', + srcdir='src', + name='d', + basedir='.', + use='b c', + recurse_use = True + ) diff --git a/playground/java_recursive_use/wscript b/playground/java_recursive_use/wscript new file mode 100644 index 0000000000..5211a6b167 --- /dev/null +++ b/playground/java_recursive_use/wscript @@ -0,0 +1,22 @@ +#! /usr/bin/env python +# encoding: utf-8# +# Federico Pellegrin, 2018 (fedepell) + +# Simple example testing usage of the recursive use processing for Java +# In the example b uses a, c uses b and d uses c. Therefore transitively +# for example c uses also a, but this by default is not enabled as it +# really depends on the code if the dependency is build or run time and +# so enabling by default may lead to unneeded work. On the other side for +# a project with many java artifacts and complex dependencies a manual +# management may be expensive. +# +# By setting recurse_use to True the recursive behaviour is enabled. +# +# Directory d tests the case when recursion stops earlier since +# a dependency is already explicitly defined + +def configure(conf): + conf.load('java') + +def build(bld): + bld.recurse('a b c d') diff --git a/waflib/Tools/javaw.py b/waflib/Tools/javaw.py index f6fd20cc68..2e332d73b7 100644 --- a/waflib/Tools/javaw.py +++ b/waflib/Tools/javaw.py @@ -29,7 +29,7 @@ import os, shutil from waflib import Task, Utils, Errors, Node from waflib.Configure import conf -from waflib.TaskGen import feature, before_method, after_method +from waflib.TaskGen import feature, before_method, after_method, taskgen_method from waflib.Tools import ccroot ccroot.USELIB_VARS['javac'] = set(['CLASSPATH', 'JAVACFLAGS']) @@ -107,6 +107,32 @@ def apply_java(self): if names: tsk.env.append_value('JAVACFLAGS', ['-sourcepath', names]) + +@taskgen_method +def java_use_rec(self, name, **kw): + """ + Processes recursively the *use* attribute for each referred java compilation + """ + if name in self.tmp_use_seen: + return + + self.tmp_use_seen.append(name) + + try: + y = self.bld.get_tgen_by_name(name) + except Errors.WafError: + self.uselib.append(name) + return + else: + y.post() + # Add generated JAR name for CLASSPATH. Task ordering (set_run_after) + # is already guaranted by ordering done between the single tasks + if hasattr(y, 'jar_task'): + self.use_lst.append(y.jar_task.outputs[0].abspath()) + + for x in self.to_list(getattr(y, 'use', [])): + self.java_use_rec(x) + @feature('javac') @before_method('propagate_uselib_vars') @after_method('apply_java') @@ -114,7 +140,8 @@ def use_javac_files(self): """ Processes the *use* attribute referring to other java compilations """ - lst = [] + self.use_lst = [] + self.tmp_use_seen = [] self.uselib = self.to_list(getattr(self, 'uselib', [])) names = self.to_list(getattr(self, 'use', [])) get = self.bld.get_tgen_by_name @@ -126,12 +153,17 @@ def use_javac_files(self): else: y.post() if hasattr(y, 'jar_task'): - lst.append(y.jar_task.outputs[0].abspath()) + self.use_lst.append(y.jar_task.outputs[0].abspath()) self.javac_task.set_run_after(y.jar_task) else: for tsk in y.tasks: self.javac_task.set_run_after(tsk) - self.env.append_value('CLASSPATH', lst) + + # If recurse_use then recursively add use attribute for each used one + if getattr(self, 'recurse_use', False): + self.java_use_rec(x) + + self.env.append_value('CLASSPATH', self.use_lst) @feature('javac') @after_method('apply_java', 'propagate_uselib_vars', 'use_javac_files') From f5a8d61c8aa052265617aa66a213576be20118cf Mon Sep 17 00:00:00 2001 From: fedepell Date: Thu, 13 Dec 2018 16:00:17 +0100 Subject: [PATCH 053/315] javaw: add some documentation on tool usage --- waflib/Tools/javaw.py | 81 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/waflib/Tools/javaw.py b/waflib/Tools/javaw.py index 2e332d73b7..04d867667b 100644 --- a/waflib/Tools/javaw.py +++ b/waflib/Tools/javaw.py @@ -24,6 +24,87 @@ java -jar /path/to/jython.jar waf configure [1] http://www.jython.org/ + +Usage +===== + +Load the "java" tool. + +def configure(conf): + conf.load('java') + +Java tools will be autodetected and eventually, if present, the quite +standard JAVA_HOME environment variable will be used. The also standard +CLASSPATH variable is used for library searching. + +In configuration phase checks can be done on the system environment, for +example to check if a class is known in the classpath: + + conf.check_java_class('java.io.FileOutputStream') + +or if the system supports JNI applications building: + + conf.check_jni_headers() + + +The java tool supports compiling java code, creating jar files and +creating javadoc documentation. This can be either done separately or +together in a single definition. +For example to manage them separately: + + bld(features = 'javac', + srcdir = 'src', + compat = '1.7', + use = 'animals', + name = 'cats-src', + ) + + bld(features = 'jar', + basedir = '.', + destfile = '../cats.jar', + name = 'cats', + use = 'cats-src' + ) + + +Or together by defining all the needed attributes: + + bld(features = 'javac jar javadoc', + srcdir = 'src/', # folder containing the sources to compile + outdir = 'src', # folder where to output the classes (in the build directory) + compat = '1.6', # java compatibility version number + classpath = ['.', '..'], + + # jar + basedir = 'src', # folder containing the classes and other files to package (must match outdir) + destfile = 'foo.jar', # do not put the destfile in the folder of the java classes! + use = 'NNN', + jaropts = ['-C', 'default/src/', '.'], # can be used to give files + manifest = 'src/Manifest.mf', # Manifest file to include + + # javadoc + javadoc_package = ['com.meow' , 'com.meow.truc.bar', 'com.meow.truc.foo'], + javadoc_output = 'javadoc', + ) + +External jar dependencies can be mapped to a standard waf "use" dependency by +setting an environment variable with a CLASSPATH_ prefix in the configuration, +for example: + + conf.env.CLASSPATH_NNN = ['aaaa.jar', 'bbbb.jar'] + +and then NNN can be freely used in rules as: + + use = 'NNN', + +In the java tool the dependencies via use are not transitive by default, as +this necessity depends on the code. To enable recursive dependency scanning +use: + recurse_use = True + +Unit tests can be integrated in the waf unit test environment using the +javatest extra. + """ import os, shutil From 63a7525a3217baaadc8275777b40a7c84c5ab62e Mon Sep 17 00:00:00 2001 From: James Harris Date: Thu, 13 Dec 2018 22:30:54 +0000 Subject: [PATCH 054/315] ccroot.py: add skip_stlib_deps feature --- demos/c/stlib-deps/libA/external_vars.c | 11 +++++++++++ demos/c/stlib-deps/libA/external_vars.h | 14 ++++++++++++++ demos/c/stlib-deps/libA/wscript_build | 7 +++++++ demos/c/stlib-deps/libB/sum.c | 12 ++++++++++++ demos/c/stlib-deps/libB/sum.h | 10 ++++++++++ demos/c/stlib-deps/libB/wscript_build | 9 +++++++++ demos/c/stlib-deps/libC/diff.c | 13 +++++++++++++ demos/c/stlib-deps/libC/diff.h | 10 ++++++++++ demos/c/stlib-deps/libC/wscript_build | 10 ++++++++++ demos/c/stlib-deps/main.c | 22 ++++++++++++++++++++++ demos/c/stlib-deps/wscript_build | 11 +++++++++++ demos/c/wscript | 2 +- waflib/Tools/ccroot.py | 17 ++++++++++++++++- 13 files changed, 146 insertions(+), 2 deletions(-) create mode 100644 demos/c/stlib-deps/libA/external_vars.c create mode 100644 demos/c/stlib-deps/libA/external_vars.h create mode 100644 demos/c/stlib-deps/libA/wscript_build create mode 100644 demos/c/stlib-deps/libB/sum.c create mode 100644 demos/c/stlib-deps/libB/sum.h create mode 100644 demos/c/stlib-deps/libB/wscript_build create mode 100644 demos/c/stlib-deps/libC/diff.c create mode 100644 demos/c/stlib-deps/libC/diff.h create mode 100644 demos/c/stlib-deps/libC/wscript_build create mode 100644 demos/c/stlib-deps/main.c create mode 100644 demos/c/stlib-deps/wscript_build diff --git a/demos/c/stlib-deps/libA/external_vars.c b/demos/c/stlib-deps/libA/external_vars.c new file mode 100644 index 0000000000..5ad3303313 --- /dev/null +++ b/demos/c/stlib-deps/libA/external_vars.c @@ -0,0 +1,11 @@ + +#include +#include "external_vars.h" + +int k = 5; + +void print_value_of_k() { + + printf("K = %d\n", k); + +} diff --git a/demos/c/stlib-deps/libA/external_vars.h b/demos/c/stlib-deps/libA/external_vars.h new file mode 100644 index 0000000000..3b2bb2cae3 --- /dev/null +++ b/demos/c/stlib-deps/libA/external_vars.h @@ -0,0 +1,14 @@ +/* + Export internal vars + */ + +#ifndef _EXTERNAL_VARS_H +#define _EXTERNAL_VARS_H + +extern int k; /* export k */ + +void print_value_of_k(); + +extern int r; + +#endif /*_EXTERNAL_VARS_H */ diff --git a/demos/c/stlib-deps/libA/wscript_build b/demos/c/stlib-deps/libA/wscript_build new file mode 100644 index 0000000000..d349c66198 --- /dev/null +++ b/demos/c/stlib-deps/libA/wscript_build @@ -0,0 +1,7 @@ +# This is a static library that provides a header to include reference to +# internal variables. +bld.stlib( + target='A', + source='external_vars.c', + includes='.', + export_includes='.') diff --git a/demos/c/stlib-deps/libB/sum.c b/demos/c/stlib-deps/libB/sum.c new file mode 100644 index 0000000000..0e6ad98817 --- /dev/null +++ b/demos/c/stlib-deps/libB/sum.c @@ -0,0 +1,12 @@ + +#include + +#include "sum.h" + +#include "external_vars.h" + +void sum(int j) { + printf("Adding %d...\n", j); + // Add our new value + k += j; +} diff --git a/demos/c/stlib-deps/libB/sum.h b/demos/c/stlib-deps/libB/sum.h new file mode 100644 index 0000000000..910101e82a --- /dev/null +++ b/demos/c/stlib-deps/libB/sum.h @@ -0,0 +1,10 @@ +/* + Export internal vars + */ + +#ifndef _SUM_H +#define _SUM_H + +void sum(int j); + +#endif /*_SUM_H */ diff --git a/demos/c/stlib-deps/libB/wscript_build b/demos/c/stlib-deps/libB/wscript_build new file mode 100644 index 0000000000..8accf77fc3 --- /dev/null +++ b/demos/c/stlib-deps/libB/wscript_build @@ -0,0 +1,9 @@ +# This script uses libA to do some internal logic. It uses the default +# behavior so it will be re-archived every time libA changes, even if +# changes in libA are only visible at runtime. +bld.stlib( + target='B', + source='sum.c', + use='A', + includes='.', + export_includes='.') diff --git a/demos/c/stlib-deps/libC/diff.c b/demos/c/stlib-deps/libC/diff.c new file mode 100644 index 0000000000..292210c4ee --- /dev/null +++ b/demos/c/stlib-deps/libC/diff.c @@ -0,0 +1,13 @@ + +#include + +#include "diff.h" + +#include "external_vars.h" + +void diff(int j) { + + printf("Subtracting %d...\n", j); + // subtract our new value + k -= j; +} diff --git a/demos/c/stlib-deps/libC/diff.h b/demos/c/stlib-deps/libC/diff.h new file mode 100644 index 0000000000..851746fce2 --- /dev/null +++ b/demos/c/stlib-deps/libC/diff.h @@ -0,0 +1,10 @@ +/* + Export internal vars + */ + +#ifndef _DIFF_H +#define _DIFF_H + +void diff(int j); + +#endif /* _DIFF_H */ diff --git a/demos/c/stlib-deps/libC/wscript_build b/demos/c/stlib-deps/libC/wscript_build new file mode 100644 index 0000000000..04d4a07b05 --- /dev/null +++ b/demos/c/stlib-deps/libC/wscript_build @@ -0,0 +1,10 @@ +# This script uses the logic that prevents static libraries from depending on +# eachother. This means that the only way libC is re-archived is if the source +# code file diff.c or any of its depenencies change. +bld.stlib( + target='C', + source='diff.c', + features='skip_stlib_link_deps', + use='A', + includes='.', + export_includes='.') diff --git a/demos/c/stlib-deps/main.c b/demos/c/stlib-deps/main.c new file mode 100644 index 0000000000..5e6d49fdb5 --- /dev/null +++ b/demos/c/stlib-deps/main.c @@ -0,0 +1,22 @@ + +#include + +#include "external_vars.h" +#include "sum.h" +#include "diff.h" + +int main() +{ + /* This should return to whatever the default value is. */ + print_value_of_k(); + sum(6); + print_value_of_k(); + diff(8); + print_value_of_k(); + sum(8); + print_value_of_k(); + diff(6); + print_value_of_k(); + + return 0; +} diff --git a/demos/c/stlib-deps/wscript_build b/demos/c/stlib-deps/wscript_build new file mode 100644 index 0000000000..855b10d803 --- /dev/null +++ b/demos/c/stlib-deps/wscript_build @@ -0,0 +1,11 @@ +#! /usr/bin/env python + +bld.recurse('libA') +bld.recurse('libB') +bld.recurse('libC') + +# Note that main has an implied dependency between our main program and libA +bld.program( + source = 'main.c', + target = 'test_static_link_chain', + use = 'B C') diff --git a/demos/c/wscript b/demos/c/wscript index b9c8b8a8f5..979651e55e 100644 --- a/demos/c/wscript +++ b/demos/c/wscript @@ -75,7 +75,7 @@ def configure(conf): def build(bld): bld.env.DEFINES=['WAF=1'] - bld.recurse('program stlib shlib') + bld.recurse('program stlib stlib-deps shlib') #bld.install_files('/tmp/foo', 'wscript') #bld.env.PREFIX='/tmp/foo' bld.install_files('${PREFIX}/', 'program/a.h program/main.c', relative_trick=False) diff --git a/waflib/Tools/ccroot.py b/waflib/Tools/ccroot.py index cfef8bf51f..8e16fe6c66 100644 --- a/waflib/Tools/ccroot.py +++ b/waflib/Tools/ccroot.py @@ -238,6 +238,17 @@ def wrap(self): setattr(cls, 'run', wrap) rm_tgt(stlink_task) +@feature('skip_stlib_link_deps') +@before_method('process_use') +def apply_skip_stlib_link_deps(self): + """ + This enables an optimization in the :py:func:wafilb.Tools.ccroot.processes_use: method that skips dependency and + link flag optimizations for targets that generate static libraries (via the :py:class:Tools.ccroot.stlink_task task). + The actual behavior is implemented in :py:func:wafilb.Tools.ccroot.processes_use: method so this feature only tells waf + to enable the new behavior. + """ + self.env.SKIP_STLIB_LINK_DEPS = True + @feature('c', 'cxx', 'd', 'fc', 'asm') @after_method('process_source') def apply_link(self): @@ -386,7 +397,11 @@ def build(bld): y = self.bld.get_tgen_by_name(x) var = y.tmp_use_var if var and link_task: - if var == 'LIB' or y.tmp_use_stlib or x in names: + if self.env.SKIP_STLIB_LINK_DEPS and isinstance(link_task, stlink_task): + # If the skip_stlib_link_deps feature is enabled then we should + # avoid adding lib deps to the stlink_task instance. + pass + elif var == 'LIB' or y.tmp_use_stlib or x in names: self.env.append_value(var, [y.target[y.target.rfind(os.sep) + 1:]]) self.link_task.dep_nodes.extend(y.link_task.outputs) tmp_path = y.link_task.outputs[0].parent.path_from(self.get_cwd()) From 490cc236082e0a3cda90ef35f83b87b55d82ebc0 Mon Sep 17 00:00:00 2001 From: fedepell Date: Fri, 14 Dec 2018 05:50:27 +0100 Subject: [PATCH 055/315] javaw: add possibility to enable recurse use also globally via env variable --- playground/java_recursive_use/wscript | 5 ++++- waflib/Tools/javaw.py | 11 ++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/playground/java_recursive_use/wscript b/playground/java_recursive_use/wscript index 5211a6b167..7d5f8d6259 100644 --- a/playground/java_recursive_use/wscript +++ b/playground/java_recursive_use/wscript @@ -10,13 +10,16 @@ # a project with many java artifacts and complex dependencies a manual # management may be expensive. # -# By setting recurse_use to True the recursive behaviour is enabled. +# By setting recurse_use to True (or build wise by setting RECURSE_JAVA env +# variable to True) the recursive behaviour is enabled. # # Directory d tests the case when recursion stops earlier since # a dependency is already explicitly defined def configure(conf): conf.load('java') + # For build wide enabling: + # conf.env.RECURSE_JAVA = True def build(bld): bld.recurse('a b c d') diff --git a/waflib/Tools/javaw.py b/waflib/Tools/javaw.py index 04d867667b..f7e8291eca 100644 --- a/waflib/Tools/javaw.py +++ b/waflib/Tools/javaw.py @@ -99,9 +99,14 @@ def configure(conf): In the java tool the dependencies via use are not transitive by default, as this necessity depends on the code. To enable recursive dependency scanning -use: +use on a specific rule: + recurse_use = True +Or build wise by setting the RECURSE_JAVA environment variable to True: + + bld.env.RECURSE_JAVA = True + Unit tests can be integrated in the waf unit test environment using the javatest extra. @@ -240,8 +245,8 @@ def use_javac_files(self): for tsk in y.tasks: self.javac_task.set_run_after(tsk) - # If recurse_use then recursively add use attribute for each used one - if getattr(self, 'recurse_use', False): + # If recurse use scan is enabled recursively add use attribute for each used one + if getattr(self, 'recurse_use', False) or self.bld.env.RECURSE_JAVA: self.java_use_rec(x) self.env.append_value('CLASSPATH', self.use_lst) From a8437d793e327abc8ab1beacf4dd6d2327d52b9b Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sat, 15 Dec 2018 19:45:47 +0100 Subject: [PATCH 056/315] Fix the api documentation build --- waflib/Tools/javaw.py | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/waflib/Tools/javaw.py b/waflib/Tools/javaw.py index f7e8291eca..fc76c9d868 100644 --- a/waflib/Tools/javaw.py +++ b/waflib/Tools/javaw.py @@ -38,19 +38,18 @@ def configure(conf): CLASSPATH variable is used for library searching. In configuration phase checks can be done on the system environment, for -example to check if a class is known in the classpath: +example to check if a class is known in the classpath:: conf.check_java_class('java.io.FileOutputStream') -or if the system supports JNI applications building: +or if the system supports JNI applications building:: conf.check_jni_headers() The java tool supports compiling java code, creating jar files and creating javadoc documentation. This can be either done separately or -together in a single definition. -For example to manage them separately: +together in a single definition. For example to manage them separately:: bld(features = 'javac', srcdir = 'src', @@ -67,7 +66,7 @@ def configure(conf): ) -Or together by defining all the needed attributes: +Or together by defining all the needed attributes:: bld(features = 'javac jar javadoc', srcdir = 'src/', # folder containing the sources to compile @@ -88,12 +87,12 @@ def configure(conf): ) External jar dependencies can be mapped to a standard waf "use" dependency by -setting an environment variable with a CLASSPATH_ prefix in the configuration, -for example: +setting an environment variable with a CLASSPATH prefix in the configuration, +for example:: conf.env.CLASSPATH_NNN = ['aaaa.jar', 'bbbb.jar'] -and then NNN can be freely used in rules as: +and then NNN can be freely used in rules as:: use = 'NNN', @@ -103,13 +102,11 @@ def configure(conf): recurse_use = True -Or build wise by setting the RECURSE_JAVA environment variable to True: +Or build-wise by setting RECURSE_JAVA: bld.env.RECURSE_JAVA = True -Unit tests can be integrated in the waf unit test environment using the -javatest extra. - +Unit tests can be integrated in the waf unit test environment using the javatest extra. """ import os, shutil From 179dfdf94be71171d9be9e0ca41f5e215b477c54 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Wed, 19 Dec 2018 11:30:45 +0100 Subject: [PATCH 057/315] docs --- waflib/extras/parallel_debug.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/waflib/extras/parallel_debug.py b/waflib/extras/parallel_debug.py index 35883a3dd7..4ffec5e53e 100644 --- a/waflib/extras/parallel_debug.py +++ b/waflib/extras/parallel_debug.py @@ -3,13 +3,16 @@ # Thomas Nagy, 2007-2010 (ita) """ -Debugging helper for parallel compilation, outputs -a file named pdebug.svg in the source directory:: +Debugging helper for parallel compilation. + +Copy it to your project and load it with:: def options(opt): - opt.load('parallel_debug') + opt.load('parallel_debug', tooldir='.') def build(bld): ... + +The build will then output a file named pdebug.svg in the source directory. """ import re, sys, threading, time, traceback From dab7c13ead987042677b5aa5e63ed79e5beaa28d Mon Sep 17 00:00:00 2001 From: fedepell Date: Wed, 19 Dec 2018 15:45:48 +0100 Subject: [PATCH 058/315] protoc: fix included protoc search on nested wscripts previously code was erroneously using tg.bld.path instead of tg.path so for nested wscript calls the wrong directory was used in search. added also better error handling with error message if an included directory does not exist --- playground/protoc/increcurse/increc/message.proto | 15 +++++++++++++++ .../protoc/increcurse/increc/message_inc.proto | 14 ++++++++++++++ playground/protoc/increcurse/wscript | 9 +++++++++ playground/protoc/wscript | 2 ++ waflib/extras/protoc.py | 9 +++++++-- 5 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 playground/protoc/increcurse/increc/message.proto create mode 100644 playground/protoc/increcurse/increc/message_inc.proto create mode 100644 playground/protoc/increcurse/wscript diff --git a/playground/protoc/increcurse/increc/message.proto b/playground/protoc/increcurse/increc/message.proto new file mode 100644 index 0000000000..4dbfd1a247 --- /dev/null +++ b/playground/protoc/increcurse/increc/message.proto @@ -0,0 +1,15 @@ +package udp.tc.tests; + +import "message_inc.proto"; + +option java_package ="com.udp.tc.tests"; +option java_outer_classname= "MessageProtos"; +option cc_generic_services = false; +option java_generic_services = false; +option py_generic_services = false; + +message Message { + required int32 test = 1; + optional uint32 blah = 2; + required IncludeMe custom = 3; +} diff --git a/playground/protoc/increcurse/increc/message_inc.proto b/playground/protoc/increcurse/increc/message_inc.proto new file mode 100644 index 0000000000..5da32dfdc8 --- /dev/null +++ b/playground/protoc/increcurse/increc/message_inc.proto @@ -0,0 +1,14 @@ +package udp.tc.tests; + +option java_package = "com.udp.tc.tests"; +option java_outer_classname = "MessageInc"; +option cc_generic_services = false; +option java_generic_services = false; +option py_generic_services = false; + + +message IncludeMe { + required int32 test = 1; + optional uint32 blah = 2; + optional uint32 justinc = 3; +} diff --git a/playground/protoc/increcurse/wscript b/playground/protoc/increcurse/wscript new file mode 100644 index 0000000000..226009a7b3 --- /dev/null +++ b/playground/protoc/increcurse/wscript @@ -0,0 +1,9 @@ +#! /usr/bin/env python + + +def build(bld): + bld( + features = 'py', + name = 'pbpyrec', + source = ['increc/message.proto'], + protoc_includes = ['increc']) diff --git a/playground/protoc/wscript b/playground/protoc/wscript index a21e4f95fe..e5fe1b51b9 100644 --- a/playground/protoc/wscript +++ b/playground/protoc/wscript @@ -53,3 +53,5 @@ def build(bld): source = ['inc/message_inc.proto', 'inc/message.proto'], use = 'PROTOBUF', protoc_includes = ['inc']) + + bld.recurse('increcurse') diff --git a/waflib/extras/protoc.py b/waflib/extras/protoc.py index f3cb4d86ab..a367f4f338 100644 --- a/waflib/extras/protoc.py +++ b/waflib/extras/protoc.py @@ -104,7 +104,7 @@ def scan(self): if 'py' in self.generator.features or 'javac' in self.generator.features: for incpath in getattr(self.generator, 'protoc_includes', []): - search_nodes.append(self.generator.bld.path.find_node(incpath)) + search_nodes.append(self.generator.path.find_node(incpath)) def parse_node(node): if node in seen: @@ -219,7 +219,12 @@ def process_protoc(self, node): # For C++ standard include files dirs are used, # but this doesn't apply to Python for example for incpath in getattr(self, 'protoc_includes', []): - incdirs.append(self.path.find_node(incpath).bldpath()) + incpath_node = self.path.find_node(incpath) + if incpath_node: + incdirs.append(incpath_node.bldpath()) + else: + raise Errors.WafError('protoc: include path %r does not exist' % incpath) + tsk.env.PROTOC_INCPATHS = incdirs # PR2115: protoc generates output of .proto files in nested From 642ba4a39deb4e101603615bd1775c3962bb6bd3 Mon Sep 17 00:00:00 2001 From: Daniel Welty Date: Wed, 19 Dec 2018 10:18:19 -0600 Subject: [PATCH 059/315] Use correct variable in gccdeps config The global value gccdeps was appended to CFLAGS and CXXFLAGS instead of the actual flags tested against the compiler. This ignored modifications to the GCCDEPS_FLAGS environment variable and complicated adding support for additional compilers at the project level. --- waflib/extras/gccdeps.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/waflib/extras/gccdeps.py b/waflib/extras/gccdeps.py index 0dd07fd039..e37f9749ca 100644 --- a/waflib/extras/gccdeps.py +++ b/waflib/extras/gccdeps.py @@ -197,7 +197,7 @@ def configure(conf): except Errors.ConfigurationError: pass else: - conf.env.append_value('CFLAGS', gccdeps_flags) + conf.env.append_value('CFLAGS', flags) conf.env.append_unique('ENABLE_GCCDEPS', 'c') if conf.env.CXX_NAME in supported_compilers: @@ -206,7 +206,7 @@ def configure(conf): except Errors.ConfigurationError: pass else: - conf.env.append_value('CXXFLAGS', gccdeps_flags) + conf.env.append_value('CXXFLAGS', flags) conf.env.append_unique('ENABLE_GCCDEPS', 'cxx') def options(opt): From 20e40e7f508628d1f934020e2bc78ddfbb2bb883 Mon Sep 17 00:00:00 2001 From: fedepell Date: Fri, 21 Dec 2018 06:16:08 +0100 Subject: [PATCH 060/315] protoc: handle extra taskgen and out of project include directories --- .../protoc/increcurse/increc/message.proto | 2 ++ playground/protoc/increcurse/wscript | 4 ++- .../othermod/deep/inc/message_inc_tl.proto | 11 +++++++ waflib/extras/protoc.py | 33 ++++++++++++++++--- 4 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 playground/protoc/othermod/deep/inc/message_inc_tl.proto diff --git a/playground/protoc/increcurse/increc/message.proto b/playground/protoc/increcurse/increc/message.proto index 4dbfd1a247..f65198dcef 100644 --- a/playground/protoc/increcurse/increc/message.proto +++ b/playground/protoc/increcurse/increc/message.proto @@ -1,6 +1,7 @@ package udp.tc.tests; import "message_inc.proto"; +import "message_inc_tl.proto"; option java_package ="com.udp.tc.tests"; option java_outer_classname= "MessageProtos"; @@ -12,4 +13,5 @@ message Message { required int32 test = 1; optional uint32 blah = 2; required IncludeMe custom = 3; + required IncludeMeFromTop customfromtop = 4; } diff --git a/playground/protoc/increcurse/wscript b/playground/protoc/increcurse/wscript index 226009a7b3..d94d5c65b6 100644 --- a/playground/protoc/increcurse/wscript +++ b/playground/protoc/increcurse/wscript @@ -6,4 +6,6 @@ def build(bld): features = 'py', name = 'pbpyrec', source = ['increc/message.proto'], - protoc_includes = ['increc']) + protoc_includes = ['increc', 'othermod/deep/inc'], + protoc_extincludes = ['/usr/include/pblib', '/usr/share/protos'] + ) diff --git a/playground/protoc/othermod/deep/inc/message_inc_tl.proto b/playground/protoc/othermod/deep/inc/message_inc_tl.proto new file mode 100644 index 0000000000..6a17dac28c --- /dev/null +++ b/playground/protoc/othermod/deep/inc/message_inc_tl.proto @@ -0,0 +1,11 @@ +package udp.tc.tests; + +option java_package = "com.udp.tc.tests"; +option java_outer_classname = "MessageInc"; +option cc_generic_services = false; +option java_generic_services = false; +option py_generic_services = false; + +message IncludeMeFromTop { + required int32 testext = 1; +} diff --git a/waflib/extras/protoc.py b/waflib/extras/protoc.py index a367f4f338..3d41021891 100644 --- a/waflib/extras/protoc.py +++ b/waflib/extras/protoc.py @@ -67,6 +67,13 @@ def build(bld): protoc_includes = ['inc']) # for protoc to search dependencies +Protoc includes passed via protoc_includes are either relative to the taskgen +or to the project and are searched in this order. + +Include directories external to the waf project can also be passed to the +extra by using protoc_extincludes + + protoc_extincludes = ['/usr/include/pblib'] Notes when using this tool: @@ -82,7 +89,7 @@ def build(bld): """ class protoc(Task): - run_str = '${PROTOC} ${PROTOC_FL:PROTOC_FLAGS} ${PROTOC_ST:INCPATHS} ${PROTOC_ST:PROTOC_INCPATHS} ${SRC[0].bldpath()}' + run_str = '${PROTOC} ${PROTOC_FL:PROTOC_FLAGS} ${PROTOC_ST:INCPATHS} ${PROTOC_ST:PROTOC_INCPATHS} ${PROTOC_ST:PROTOC_EXTINCPATHS} ${SRC[0].bldpath()}' color = 'BLUE' ext_out = ['.h', 'pb.cc', '.py', '.java'] def scan(self): @@ -104,7 +111,17 @@ def scan(self): if 'py' in self.generator.features or 'javac' in self.generator.features: for incpath in getattr(self.generator, 'protoc_includes', []): - search_nodes.append(self.generator.path.find_node(incpath)) + incpath_node = self.generator.path.find_node(incpath) + if incpath_node: + search_nodes.append(incpath_node) + else: + # Check if relative to top-level for extra tg dependencies + incpath_node = self.generator.bld.path.find_node(incpath) + if incpath_node: + search_nodes.append(incpath_node) + else: + raise Errors.WafError('protoc: include path %r does not exist' % incpath) + def parse_node(node): if node in seen: @@ -126,7 +143,7 @@ def parse_node(node): parse_node(node) # Add also dependencies path to INCPATHS so protoc will find the included file for deppath in nodes: - self.env.append_value('INCPATHS', deppath.parent.bldpath()) + self.env.append_unique('INCPATHS', deppath.parent.bldpath()) return (nodes, names) @extension('.proto') @@ -223,10 +240,18 @@ def process_protoc(self, node): if incpath_node: incdirs.append(incpath_node.bldpath()) else: - raise Errors.WafError('protoc: include path %r does not exist' % incpath) + # Check if relative to top-level for extra tg dependencies + incpath_node = self.bld.path.find_node(incpath) + if incpath_node: + incdirs.append(incpath_node.bldpath()) + else: + raise Errors.WafError('protoc: include path %r does not exist' % incpath) tsk.env.PROTOC_INCPATHS = incdirs + # Include paths external to the waf project (ie. shared pb repositories) + tsk.env.PROTOC_EXTINCPATHS = getattr(self, 'protoc_extincludes', []) + # PR2115: protoc generates output of .proto files in nested # directories by canonicalizing paths. To avoid this we have to pass # as first include the full directory file of the .proto file From 6812c026ab50ba01f1e04bdac97f503f3e578f02 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Fri, 21 Dec 2018 11:10:57 +0100 Subject: [PATCH 061/315] Let the protoc demo build even if java is missing --- playground/protoc/wscript | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/playground/protoc/wscript b/playground/protoc/wscript index e5fe1b51b9..0646d4842a 100644 --- a/playground/protoc/wscript +++ b/playground/protoc/wscript @@ -1,5 +1,8 @@ #! /usr/bin/env python +import os +from waflib import Logs + top = '.' out = 'build' @@ -10,7 +13,10 @@ def configure(conf): conf.load('compiler_cxx python java protoc') conf.check_python_version(minver=(2, 5, 0)) # Here you have to point to your protobuf-java JAR - conf.env.CLASSPATH_PROTOBUF = ['/tmp/cp/protobuf-java-2.5.0.jar'] + if os.path.isfile('/tmp/cp/protobuf-java-2.5.0.jar'): + conf.env.CLASSPATH_PROTOBUF = ['/tmp/cp/protobuf-java-2.5.0.jar'] + else: + Logs.warn('Edit the wscript file and set CLASSPATH_PROTOBUF for java') def build(bld): bld( @@ -46,12 +52,13 @@ def build(bld): source = ['incboth/messageboth_inc.proto', 'incboth/messageboth.proto'], protoc_includes = ['incboth']) # either protoc_includes or includes would work in this case - bld( - features = 'javac protoc', - name = 'pbjava', - srcdir = 'inc/', - source = ['inc/message_inc.proto', 'inc/message.proto'], - use = 'PROTOBUF', - protoc_includes = ['inc']) + if bld.env.CLASSPATH_PROTOBUF: + bld( + features = 'javac protoc', + name = 'pbjava', + srcdir = 'inc/', + source = ['inc/message_inc.proto', 'inc/message.proto'], + use = 'PROTOBUF', + protoc_includes = ['inc']) bld.recurse('increcurse') From 70c30ebd031321823fc673b743f83a629100e5bb Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Fri, 21 Dec 2018 11:47:51 +0100 Subject: [PATCH 062/315] Possible solution for Msys path issues #2217 --- waflib/Utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/Utils.py b/waflib/Utils.py index 3d707a5843..3f5eb93bf7 100644 --- a/waflib/Utils.py +++ b/waflib/Utils.py @@ -208,7 +208,7 @@ def __next__(self): next = __next__ -is_win32 = os.sep == '\\' or sys.platform == 'win32' # msys2 +is_win32 = os.sep == '\\' or sys.platform == 'win32' or os.name == 'nt' # msys2 """ Whether this system is a Windows series """ From 0e40f6eea6103312ccfe018dbf6fd0444d4119a1 Mon Sep 17 00:00:00 2001 From: Harald Klimach Date: Fri, 21 Dec 2018 19:53:12 +0100 Subject: [PATCH 063/315] Support for Fortran 2008 submodules. --- waflib/Tools/fc.py | 22 ++++++++++++++++++---- waflib/Tools/fc_scan.py | 8 +++++++- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/waflib/Tools/fc.py b/waflib/Tools/fc.py index d9e8d8c442..fd4d39c90a 100644 --- a/waflib/Tools/fc.py +++ b/waflib/Tools/fc.py @@ -28,10 +28,24 @@ def modfile(conf, name): Turns a module name into the right module file name. Defaults to all lower case. """ - return {'lower' :name.lower() + '.mod', - 'lower.MOD' :name.lower() + '.MOD', - 'UPPER.mod' :name.upper() + '.mod', - 'UPPER' :name.upper() + '.MOD'}[conf.env.FC_MOD_CAPITALIZATION or 'lower'] + if name.find(':') >= 0: + # Depending on a submodule! + separator = conf.env.FC_SUBMOD_SEPARATOR or '@' + # Ancestors of the submodule will be prefixed to the + # submodule name, separated by a colon. + modpath = name.split(':') + # Only the ancestor (actual) module and the submodule name + # will be used for the filename. + modname = modpath[0] + separator + modpath[-1] + suffix = conf.env.FC_SUBMOD_SUFFIX or '.smod' + else: + modname = name + suffix = '.mod' + + return {'lower' :modname.lower() + suffix.lower(), + 'lower.MOD' :modname.lower() + suffix.upper(), + 'UPPER.mod' :modname.upper() + suffix.lower(), + 'UPPER' :modname.upper() + suffix.upper()}[conf.env.FC_MOD_CAPITALIZATION or 'lower'] def get_fortran_tasks(tsk): """ diff --git a/waflib/Tools/fc_scan.py b/waflib/Tools/fc_scan.py index 12cb0fc041..dda5df7052 100644 --- a/waflib/Tools/fc_scan.py +++ b/waflib/Tools/fc_scan.py @@ -7,11 +7,13 @@ INC_REGEX = """(?:^|['">]\s*;)\s*(?:|#\s*)INCLUDE\s+(?:\w+_)?[<"'](.+?)(?=["'>])""" USE_REGEX = """(?:^|;)\s*USE(?:\s+|(?:(?:\s*,\s*(?:NON_)?INTRINSIC)?\s*::))\s*(\w+)""" -MOD_REGEX = """(?:^|;)\s*MODULE(?!\s*PROCEDURE)(?:\s+|(?:(?:\s*,\s*(?:NON_)?INTRINSIC)?\s*::))\s*(\w+)""" +MOD_REGEX = """(?:^|;)\s*MODULE(?!\s+(?:PROCEDURE|SUBROUTINE|FUNCTION))\s+(\w+)""" +SMD_REGEX = """(?:^|;)\s*SUBMODULE\s*\(([\w:]+)\)\s*(\w+)""" re_inc = re.compile(INC_REGEX, re.I) re_use = re.compile(USE_REGEX, re.I) re_mod = re.compile(MOD_REGEX, re.I) +re_smd = re.compile(SMD_REGEX, re.I) class fortran_parser(object): """ @@ -58,6 +60,10 @@ def find_deps(self, node): m = re_mod.search(line) if m: mods.append(m.group(1)) + m = re_smd.search(line) + if m: + uses.append(m.group(1)) + mods.append('{0}:{1}'.format(m.group(1),m.group(2)) return (incs, uses, mods) def start(self, node): From 98b494d2fe94e0c4e9455bb09054c7997f660b44 Mon Sep 17 00:00:00 2001 From: Harald Klimach Date: Fri, 21 Dec 2018 20:18:12 +0100 Subject: [PATCH 064/315] Support for the Fortran Compiler of the NEC SX-Aurora TSUBASA system. --- waflib/extras/fc_nfort.py | 52 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 waflib/extras/fc_nfort.py diff --git a/waflib/extras/fc_nfort.py b/waflib/extras/fc_nfort.py new file mode 100644 index 0000000000..c25886b8e7 --- /dev/null +++ b/waflib/extras/fc_nfort.py @@ -0,0 +1,52 @@ +#! /usr/bin/env python +# encoding: utf-8 +# Detection of the NEC Fortran compiler for Aurora Tsubasa + +import re +from waflib.Tools import fc,fc_config,fc_scan +from waflib.Configure import conf +from waflib.Tools.compiler_fc import fc_compiler +fc_compiler['linux'].append('fc_nfort') + +@conf +def find_nfort(conf): + fc=conf.find_program(['nfort'],var='FC') + conf.get_nfort_version(fc) + conf.env.FC_NAME='NFORT' + conf.env.FC_MOD_CAPITALIZATION='lower' + +@conf +def nfort_flags(conf): + v=conf.env + v['_FCMODOUTFLAGS']=[] + v['FCFLAGS_DEBUG']=[] + v['FCFLAGS_fcshlib']=[] + v['LINKFLAGS_fcshlib']=[] + v['FCSTLIB_MARKER']='' + v['FCSHLIB_MARKER']='' + +@conf +def get_nfort_version(conf,fc): + version_re=re.compile(r"nfort\s*\(NFORT\)\s*(?P\d+)\.(?P\d+)\.",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 not match: + return(False) + conf.fatal('Could not determine the NEC NFORT Fortran compiler version.') + else: + k=match.groupdict() + conf.env['FC_VERSION']=(k['major'],k['minor']) + +def configure(conf): + conf.find_nfort() + conf.find_program('nar',var='AR') + conf.add_os_flags('ARFLAGS') + if not conf.env.ARFLAGS: + conf.env.ARFLAGS=['rcs'] + conf.fc_flags() + conf.fc_add_flags() + conf.nfort_flags() From 35a6ecbb4ae99230a2526f8929d45c4d8d4cce36 Mon Sep 17 00:00:00 2001 From: Harald Klimach Date: Fri, 21 Dec 2018 23:13:35 +0100 Subject: [PATCH 065/315] Missing bracket in submodule appending of fc_scan. --- waflib/Tools/fc_scan.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/Tools/fc_scan.py b/waflib/Tools/fc_scan.py index dda5df7052..3689378089 100644 --- a/waflib/Tools/fc_scan.py +++ b/waflib/Tools/fc_scan.py @@ -63,7 +63,7 @@ def find_deps(self, node): m = re_smd.search(line) if m: uses.append(m.group(1)) - mods.append('{0}:{1}'.format(m.group(1),m.group(2)) + mods.append('{0}:{1}'.format(m.group(1),m.group(2))) return (incs, uses, mods) def start(self, node): From c985366609102ba354c1527769871ba686c01e60 Mon Sep 17 00:00:00 2001 From: Harald Klimach Date: Fri, 21 Dec 2018 23:14:19 +0100 Subject: [PATCH 066/315] Added submodules demonstrator to demos/fortran. Its only built if gfortran is used at least with version 6. --- demos/fortran/submodules/container.f90 | 13 +++++++++++++ demos/fortran/submodules/helper.f90 | 13 +++++++++++++ demos/fortran/submodules/parent.f90 | 21 +++++++++++++++++++++ demos/fortran/submodules/wscript | 20 ++++++++++++++++++++ demos/fortran/wscript | 2 ++ 5 files changed, 69 insertions(+) create mode 100644 demos/fortran/submodules/container.f90 create mode 100644 demos/fortran/submodules/helper.f90 create mode 100644 demos/fortran/submodules/parent.f90 create mode 100644 demos/fortran/submodules/wscript diff --git a/demos/fortran/submodules/container.f90 b/demos/fortran/submodules/container.f90 new file mode 100644 index 0000000000..1d9387c0a0 --- /dev/null +++ b/demos/fortran/submodules/container.f90 @@ -0,0 +1,13 @@ +submodule (parent) container + implicit none + +contains + + module function parent_weight(p) result(w) + type(parent_type), intent(in) :: p + real :: w + + w = p%mother**2 + p%father**2 + end function parent_weight + +end submodule container diff --git a/demos/fortran/submodules/helper.f90 b/demos/fortran/submodules/helper.f90 new file mode 100644 index 0000000000..b72de8c0ad --- /dev/null +++ b/demos/fortran/submodules/helper.f90 @@ -0,0 +1,13 @@ +submodule (parent:container) helper + implicit none + +contains + + module function parent_distance(pa, pb) result(dist) + type(parent_type), intent(in) :: pa, pb + real :: dist + + dist = sqrt(parent_weight(pa) + parent_weight(pb)) + end function parent_distance + +end submodule helper diff --git a/demos/fortran/submodules/parent.f90 b/demos/fortran/submodules/parent.f90 new file mode 100644 index 0000000000..e40fbca9ce --- /dev/null +++ b/demos/fortran/submodules/parent.f90 @@ -0,0 +1,21 @@ +module parent + implicit none + + type parent_type + real :: mother + real :: father + end type parent_type + + interface + module function parent_weight(p) result(w) + type(parent_type), intent(in) :: p + real :: w + end function parent_weight + + module function parent_distance(pa, pb) result(dist) + type(parent_type), intent(in) :: pa, pb + real :: dist + end function parent_distance + end interface + +end module parent diff --git a/demos/fortran/submodules/wscript b/demos/fortran/submodules/wscript new file mode 100644 index 0000000000..73f8be1314 --- /dev/null +++ b/demos/fortran/submodules/wscript @@ -0,0 +1,20 @@ +#! /usr/bin/env python + +top = '.' +out = 'build' + +def options(opt): + opt.load('compiler_c') + opt.load('compiler_fc') + +def configure(conf): + conf.load('compiler_c') + conf.load('compiler_fc') + +def build(bld): + + bld( + features = 'fc fcshlib', + source = 'parent.f90 container.f90 helper.f90', + target = 'fudge', + ) diff --git a/demos/fortran/wscript b/demos/fortran/wscript index f1fb5d7c18..f1223d8024 100644 --- a/demos/fortran/wscript +++ b/demos/fortran/wscript @@ -78,3 +78,5 @@ def build(bld): target = 'mod/two_mods') bld.recurse('typemap') + if bld.env.FC_NAME == 'GFORTRAN' and int(bld.env.FC_VERSION[0]) >= 6: + bld.recurse('submodules') From 5c9f28c81b08f600183da2e3d68f6e27f0cb337b Mon Sep 17 00:00:00 2001 From: Harald Klimach Date: Fri, 21 Dec 2018 23:36:55 +0100 Subject: [PATCH 067/315] Added more syntactic cases to the demos/fortran/submodules example. Also build a main program that uses the parent module. --- demos/fortran/submodules/container.f90 | 14 ++++++++++++++ demos/fortran/submodules/parent.f90 | 9 +++++++++ demos/fortran/submodules/submain.f90 | 18 ++++++++++++++++++ demos/fortran/submodules/wscript | 6 ++++++ 4 files changed, 47 insertions(+) create mode 100644 demos/fortran/submodules/submain.f90 diff --git a/demos/fortran/submodules/container.f90 b/demos/fortran/submodules/container.f90 index 1d9387c0a0..d8a6c4710d 100644 --- a/demos/fortran/submodules/container.f90 +++ b/demos/fortran/submodules/container.f90 @@ -3,6 +3,20 @@ contains + module procedure init + p%mother = mother + p%father = father + end procedure init + + module subroutine harmonize(p) + type(parent_type), intent(inout) :: p + real :: avg + + avg = 0.5 * (p%father + p%mother) + p%father = avg + p%mother = avg + end subroutine harmonize + module function parent_weight(p) result(w) type(parent_type), intent(in) :: p real :: w diff --git a/demos/fortran/submodules/parent.f90 b/demos/fortran/submodules/parent.f90 index e40fbca9ce..17b8370bb1 100644 --- a/demos/fortran/submodules/parent.f90 +++ b/demos/fortran/submodules/parent.f90 @@ -7,6 +7,15 @@ module parent end type parent_type interface + module subroutine init(p, mother, father) + type(parent_type), intent(out) :: p + real, intent(in) :: mother, father + end subroutine init + + module subroutine harmonize(p) + type(parent_type), intent(inout) :: p + end subroutine harmonize + module function parent_weight(p) result(w) type(parent_type), intent(in) :: p real :: w diff --git a/demos/fortran/submodules/submain.f90 b/demos/fortran/submodules/submain.f90 new file mode 100644 index 0000000000..e47013a599 --- /dev/null +++ b/demos/fortran/submodules/submain.f90 @@ -0,0 +1,18 @@ +program submain + use parent + + implicit none + + type(parent_type) :: a,b + real :: dist, weight + + call init(a, 1.0, 2.0) + call init(b, 10.0, 12.0) + + call harmonize(a) + weight = parent_weight(b) + write(*,*) weight + dist = parent_distance(a, b) + write(*,*) dist + +end program submain diff --git a/demos/fortran/submodules/wscript b/demos/fortran/submodules/wscript index 73f8be1314..771614e1c3 100644 --- a/demos/fortran/submodules/wscript +++ b/demos/fortran/submodules/wscript @@ -18,3 +18,9 @@ def build(bld): source = 'parent.f90 container.f90 helper.f90', target = 'fudge', ) + bld( + features = 'fc fcprogram', + source = 'submain.f90', + use = 'fudge', + target = 'submain', + ) From 09c181e3570919ef8f979d6dc763a671158828db Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 23 Dec 2018 11:52:46 +0100 Subject: [PATCH 068/315] waf-2.0.14 --- ChangeLog | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ChangeLog b/ChangeLog index d2e16c3334..e1557341ab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +NEW IN WAF 2.0.14 +----------------- +* Support Fortran 2008 submodules #2205 +* Possible solution for Msys/Python 3.6 path issues #2217 +* Support NEC SX-Aurora TSUBASA system's Fortran compiler extras/fc_nfort.py #2206 +* Fix ignored configuration flags in gccdeps extras/gccdeps.py #2203 +* Fix included protoc search on nested wscripts extras/protoc.py #2202 +* Support extra taskgen and out of project include directories extras/protoc.py #2204 + NEW IN WAF 2.0.13 ----------------- * Fix "broken revdeps" extra error message on certain build failures From bf1709becaa4b4ab0c56b36ec80187d11c6b84e7 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 23 Dec 2018 12:12:15 +0100 Subject: [PATCH 069/315] waf-2.0.14 --- waf-light | 2 +- waflib/Context.py | 6 +++--- wscript | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/waf-light b/waf-light index 10b1cd470a..5f4b30af92 100755 --- a/waf-light +++ b/waf-light @@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. import os, sys, inspect -VERSION="2.0.13" +VERSION="2.0.14" REVISION="x" GIT="x" INSTALL="x" diff --git a/waflib/Context.py b/waflib/Context.py index fce04790a4..ffe197e40a 100644 --- a/waflib/Context.py +++ b/waflib/Context.py @@ -11,13 +11,13 @@ import waflib.Node # the following 3 constants are updated on each new release (do not touch) -HEXVERSION=0x2000d00 +HEXVERSION=0x2000e00 """Constant updated on new releases""" -WAFVERSION="2.0.13" +WAFVERSION="2.0.14" """Constant updated on new releases""" -WAFREVISION="1607738e97e9453f5d5c7c911ba7dfdc0d4ddc2a" +WAFREVISION="907519cab9c1c8c7e4f7d4e468ed6200b9250d58" """Git revision when the waf version is updated""" ABI = 20 diff --git a/wscript b/wscript index f02913cc83..18bb365f4e 100644 --- a/wscript +++ b/wscript @@ -11,7 +11,7 @@ To add a tool that does not exist in the folder compat15, pass an absolute path: from __future__ import with_statement -VERSION="2.0.13" +VERSION="2.0.14" APPNAME='waf' REVISION='' From 171e8bb018391e11c4897132eb00390c032008ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Schoentgen?= Date: Sat, 5 Jan 2019 12:02:42 +0100 Subject: [PATCH 070/315] Fix all DeprecationWarning: invalid escape sequence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mickaël Schoentgen --- utils/genbench.py | 2 +- waflib/Build.py | 2 +- waflib/ConfigSet.py | 2 +- waflib/Context.py | 2 +- waflib/Task.py | 2 +- waflib/TaskGen.py | 2 +- waflib/Tools/c_config.py | 2 +- waflib/Tools/c_preproc.py | 6 +++--- waflib/Tools/d_scan.py | 8 ++++---- waflib/Tools/fc_config.py | 4 ++-- waflib/Tools/fc_scan.py | 8 ++++---- waflib/Tools/ifort.py | 2 +- waflib/Tools/msvc.py | 16 ++++++++-------- waflib/Tools/qt5.py | 4 ++-- waflib/Tools/winres.py | 4 ++-- waflib/Utils.py | 2 +- waflib/ansiterm.py | 2 +- waflib/extras/cpplint.py | 6 +++--- waflib/extras/distnet.py | 2 +- waflib/extras/erlang.py | 2 +- waflib/extras/gccdeps.py | 2 +- waflib/extras/kde4.py | 2 +- waflib/extras/ocaml.py | 2 +- waflib/extras/pgicc.py | 2 +- waflib/extras/pyqt5.py | 2 +- waflib/extras/qt4.py | 2 +- waflib/extras/remote.py | 2 +- waflib/extras/run_do_script.py | 2 +- waflib/extras/swig.py | 4 ++-- 29 files changed, 50 insertions(+), 50 deletions(-) diff --git a/utils/genbench.py b/utils/genbench.py index d68ec6fda7..8d98c06cef 100755 --- a/utils/genbench.py +++ b/utils/genbench.py @@ -174,7 +174,7 @@ def createVCProjFile(lib_number, classes): """) for i in range(classes): - handle.write(' \n') + handle.write(r' \n') handle.write(""" diff --git a/waflib/Build.py b/waflib/Build.py index 8eb612eb1a..4aa4b901bd 100644 --- a/waflib/Build.py +++ b/waflib/Build.py @@ -104,7 +104,7 @@ def __init__(self, **kw): """Amount of jobs to run in parallel""" self.targets = Options.options.targets - """List of targets to build (default: \*)""" + """List of targets to build (default: \\*)""" self.keep = Options.options.keep """Whether the build should continue past errors""" diff --git a/waflib/ConfigSet.py b/waflib/ConfigSet.py index b300bb56b7..9db8e90758 100644 --- a/waflib/ConfigSet.py +++ b/waflib/ConfigSet.py @@ -11,7 +11,7 @@ import copy, re, os from waflib import Logs, Utils -re_imp = re.compile('^(#)*?([^#=]*?)\ =\ (.*?)$', re.M) +re_imp = re.compile(r'^(#)*?([^#=]*?)\ =\ (.*?)$', re.M) class ConfigSet(object): """ diff --git a/waflib/Context.py b/waflib/Context.py index ffe197e40a..888091dfd3 100644 --- a/waflib/Context.py +++ b/waflib/Context.py @@ -607,7 +607,7 @@ def end_msg(self, *k, **kw): Logs.pprint(color, msg) def load_special_tools(self, var, ban=[]): - """ + r""" Loads third-party extensions modules for certain programming languages by trying to list certain files in the extras/ directory. This method is typically called once for a programming language group, see for diff --git a/waflib/Task.py b/waflib/Task.py index 882df5cf7b..a0450d429d 100644 --- a/waflib/Task.py +++ b/waflib/Task.py @@ -1059,7 +1059,7 @@ def funex(c): exec(c, dc) return dc['f'] -re_cond = re.compile('(?P\w+)|(?P\|)|(?P&)') +re_cond = re.compile(r'(?P\w+)|(?P\|)|(?P&)') re_novar = re.compile(r'^(SRC|TGT)\W+.*?$') reg_act = re.compile(r'(?P\\)|(?P\$\$)|(?P\$\{(?P\w+)(?P.*?)\})', re.M) def compile_fun_shell(line): diff --git a/waflib/TaskGen.py b/waflib/TaskGen.py index e328843b5b..532b7d5cdb 100644 --- a/waflib/TaskGen.py +++ b/waflib/TaskGen.py @@ -727,7 +727,7 @@ def sequence_order(self): self.bld.prev = self -re_m4 = re.compile('@(\w+)@', re.M) +re_m4 = re.compile(r'@(\w+)@', re.M) class subst_pc(Task.Task): """ diff --git a/waflib/Tools/c_config.py b/waflib/Tools/c_config.py index 73320a1459..71a3acacbf 100644 --- a/waflib/Tools/c_config.py +++ b/waflib/Tools/c_config.py @@ -239,7 +239,7 @@ def validate_cfg(self, kw): @conf def exec_cfg(self, kw): - """ + r""" 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 diff --git a/waflib/Tools/c_preproc.py b/waflib/Tools/c_preproc.py index 7e04b4a7c7..68e5f5aea2 100644 --- a/waflib/Tools/c_preproc.py +++ b/waflib/Tools/c_preproc.py @@ -75,13 +75,13 @@ class PreprocError(Errors.WafError): re.IGNORECASE | re.MULTILINE) """Match #include lines""" -re_mac = re.compile("^[a-zA-Z_]\w*") +re_mac = re.compile(r"^[a-zA-Z_]\w*") """Match macro definitions""" re_fun = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*[(]') """Match macro functions""" -re_pragma_once = re.compile('^\s*once\s*', re.IGNORECASE) +re_pragma_once = re.compile(r'^\s*once\s*', re.IGNORECASE) """Match #pragma once statements""" re_nl = re.compile('\\\\\r*\n', re.MULTILINE) @@ -660,7 +660,7 @@ def extract_macro(txt): # empty define, assign an empty token return (v, [[], [('T','')]]) -re_include = re.compile('^\s*(<(?:.*)>|"(?:.*)")') +re_include = re.compile(r'^\s*(<(?:.*)>|"(?:.*)")') def extract_include(txt, defs): """ Process a line in the form:: diff --git a/waflib/Tools/d_scan.py b/waflib/Tools/d_scan.py index 14c6c313e9..4e807a6b9f 100644 --- a/waflib/Tools/d_scan.py +++ b/waflib/Tools/d_scan.py @@ -93,8 +93,8 @@ def __init__(self, env, incpaths): self.allnames = [] - self.re_module = re.compile("module\s+([^;]+)") - self.re_import = re.compile("import\s+([^;]+)") + self.re_module = re.compile(r"module\s+([^;]+)") + self.re_import = re.compile(r"import\s+([^;]+)") self.re_import_bindings = re.compile("([^:]+):(.*)") self.re_import_alias = re.compile("[^=]+=(.+)") @@ -138,7 +138,7 @@ def get_strings(self, code): mod_name = self.re_module.search(code) if mod_name: - self.module = re.sub('\s+', '', mod_name.group(1)) # strip all whitespaces + self.module = re.sub(r'\s+', '', mod_name.group(1)) # strip all whitespaces # go through the code, have a look at all import occurrences @@ -146,7 +146,7 @@ def get_strings(self, code): import_iterator = self.re_import.finditer(code) if import_iterator: for import_match in import_iterator: - import_match_str = re.sub('\s+', '', import_match.group(1)) # strip all whitespaces + import_match_str = re.sub(r'\s+', '', import_match.group(1)) # strip all whitespaces # does this end with an import bindings declaration? # (import bindings always terminate the list of imports) diff --git a/waflib/Tools/fc_config.py b/waflib/Tools/fc_config.py index 222f3a55d4..dc5e5c9e9a 100644 --- a/waflib/Tools/fc_config.py +++ b/waflib/Tools/fc_config.py @@ -178,8 +178,8 @@ def check_fortran_dummy_main(self, *k, **kw): # ------------------------------------------------------------------------ GCC_DRIVER_LINE = re.compile('^Driving:') -POSIX_STATIC_EXT = re.compile('\S+\.a') -POSIX_LIB_FLAGS = re.compile('-l\S+') +POSIX_STATIC_EXT = re.compile(r'\S+\.a') +POSIX_LIB_FLAGS = re.compile(r'-l\S+') @conf def is_link_verbose(self, txt): diff --git a/waflib/Tools/fc_scan.py b/waflib/Tools/fc_scan.py index 3689378089..0824c92b7e 100644 --- a/waflib/Tools/fc_scan.py +++ b/waflib/Tools/fc_scan.py @@ -5,10 +5,10 @@ import re -INC_REGEX = """(?:^|['">]\s*;)\s*(?:|#\s*)INCLUDE\s+(?:\w+_)?[<"'](.+?)(?=["'>])""" -USE_REGEX = """(?:^|;)\s*USE(?:\s+|(?:(?:\s*,\s*(?:NON_)?INTRINSIC)?\s*::))\s*(\w+)""" -MOD_REGEX = """(?:^|;)\s*MODULE(?!\s+(?:PROCEDURE|SUBROUTINE|FUNCTION))\s+(\w+)""" -SMD_REGEX = """(?:^|;)\s*SUBMODULE\s*\(([\w:]+)\)\s*(\w+)""" +INC_REGEX = r"""(?:^|['">]\s*;)\s*(?:|#\s*)INCLUDE\s+(?:\w+_)?[<"'](.+?)(?=["'>])""" +USE_REGEX = r"""(?:^|;)\s*USE(?:\s+|(?:(?:\s*,\s*(?:NON_)?INTRINSIC)?\s*::))\s*(\w+)""" +MOD_REGEX = r"""(?:^|;)\s*MODULE(?!\s+(?:PROCEDURE|SUBROUTINE|FUNCTION))\s+(\w+)""" +SMD_REGEX = r"""(?:^|;)\s*SUBMODULE\s*\(([\w:]+)\)\s*(\w+)""" re_inc = re.compile(INC_REGEX, re.I) re_use = re.compile(USE_REGEX, re.I) diff --git a/waflib/Tools/ifort.py b/waflib/Tools/ifort.py index 74934f3f66..17d3052910 100644 --- a/waflib/Tools/ifort.py +++ b/waflib/Tools/ifort.py @@ -107,7 +107,7 @@ def gather_ifort_versions(conf, versions): """ List compiler versions by looking up registry keys """ - version_pattern = re.compile('^...?.?\....?.?') + version_pattern = re.compile(r'^...?.?\....?.?') try: all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Intel\\Compilers\\Fortran') except OSError: diff --git a/waflib/Tools/msvc.py b/waflib/Tools/msvc.py index 17b347d458..ff58449d0f 100644 --- a/waflib/Tools/msvc.py +++ b/waflib/Tools/msvc.py @@ -281,7 +281,7 @@ def gather_wince_supported_platforms(): def gather_msvc_detected_versions(): #Detected MSVC versions! - version_pattern = re.compile('^(\d\d?\.\d\d?)(Exp)?$') + version_pattern = re.compile(r'^(\d\d?\.\d\d?)(Exp)?$') detected_versions = [] for vcver,vcvar in (('VCExpress','Exp'), ('VisualStudio','')): prefix = 'SOFTWARE\\Wow6432node\\Microsoft\\' + vcver @@ -367,7 +367,7 @@ def gather_wsdk_versions(conf, versions): :param versions: list to modify :type versions: list """ - version_pattern = re.compile('^v..?.?\...?.?') + version_pattern = re.compile(r'^v..?.?\...?.?') try: all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Microsoft\\Microsoft SDKs\\Windows') except OSError: @@ -525,7 +525,7 @@ def gather_icl_versions(conf, versions): :param versions: list to modify :type versions: list """ - version_pattern = re.compile('^...?.?\....?.?') + version_pattern = re.compile(r'^...?.?\....?.?') try: all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Intel\\Compilers\\C++') except OSError: @@ -579,7 +579,7 @@ def gather_intel_composer_versions(conf, versions): :param versions: list to modify :type versions: list """ - version_pattern = re.compile('^...?.?\...?.?.?') + version_pattern = re.compile(r'^...?.?\...?.?.?') try: all_versions = Utils.winreg.OpenKey(Utils.winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\Wow6432node\\Intel\\Suites') except OSError: @@ -683,7 +683,7 @@ def find_lt_names_msvc(self, libname, is_static=False): if not is_static and ltdict.get('library_names', ''): dllnames=ltdict['library_names'].split() dll=dllnames[0].lower() - dll=re.sub('\.dll$', '', dll) + dll=re.sub(r'\.dll$', '', dll) return (lt_libdir, dll, False) elif ltdict.get('old_library', ''): olib=ltdict['old_library'] @@ -700,7 +700,7 @@ def find_lt_names_msvc(self, libname, is_static=False): @conf def libname_msvc(self, libname, is_static=False): lib = libname.lower() - lib = re.sub('\.lib$','',lib) + lib = re.sub(r'\.lib$','',lib) if lib in g_msvc_systemlibs: return lib @@ -747,11 +747,11 @@ def libname_msvc(self, libname, is_static=False): for libn in libnames: if os.path.exists(os.path.join(path, libn)): Logs.debug('msvc: lib found: %s', os.path.join(path,libn)) - return re.sub('\.lib$', '',libn) + return re.sub(r'\.lib$', '',libn) #if no lib can be found, just return the libname as msvc expects it self.fatal('The library %r could not be found' % libname) - return re.sub('\.lib$', '', libname) + return re.sub(r'\.lib$', '', libname) @conf def check_lib_msvc(self, libname, is_static=False, uselib_store=None): diff --git a/waflib/Tools/qt5.py b/waflib/Tools/qt5.py index 4f9c6908fc..52a85f4c48 100644 --- a/waflib/Tools/qt5.py +++ b/waflib/Tools/qt5.py @@ -305,7 +305,7 @@ def build(bld): @feature('qt5') @after_method('apply_link') def apply_qt5(self): - """ + r""" Adds MOC_FLAGS which may be necessary for moc:: def build(bld): @@ -762,7 +762,7 @@ def set_qt5_libs_to_check(self): if self.environ.get('QT5_FORCE_STATIC'): pat = self.env.cxxstlib_PATTERN if Utils.unversioned_sys_platform() == 'darwin': - pat = "%s\.framework" + pat = r"%s\.framework" re_qt = re.compile(pat%'Qt5?(?P.*)'+'$') for x in dirlst: m = re_qt.match(x) diff --git a/waflib/Tools/winres.py b/waflib/Tools/winres.py index 586c596cf9..9be1ed6600 100644 --- a/waflib/Tools/winres.py +++ b/waflib/Tools/winres.py @@ -24,8 +24,8 @@ def rc_file(self, node): self.compiled_tasks = [rctask] re_lines = re.compile( - '(?:^[ \t]*(#|%:)[ \t]*(ifdef|ifndef|if|else|elif|endif|include|import|define|undef|pragma)[ \t]*(.*?)\s*$)|'\ - '(?:^\w+[ \t]*(ICON|BITMAP|CURSOR|HTML|FONT|MESSAGETABLE|TYPELIB|REGISTRY|D3DFX)[ \t]*(.*?)\s*$)', + r'(?:^[ \t]*(#|%:)[ \t]*(ifdef|ifndef|if|else|elif|endif|include|import|define|undef|pragma)[ \t]*(.*?)\s*$)|'\ + r'(?:^\w+[ \t]*(ICON|BITMAP|CURSOR|HTML|FONT|MESSAGETABLE|TYPELIB|REGISTRY|D3DFX)[ \t]*(.*?)\s*$)', re.IGNORECASE | re.MULTILINE) class rc_parser(c_preproc.c_parser): diff --git a/waflib/Utils.py b/waflib/Utils.py index 3f5eb93bf7..b84de64bf5 100644 --- a/waflib/Utils.py +++ b/waflib/Utils.py @@ -736,7 +736,7 @@ def unversioned_sys_platform(): if s == 'cli' and os.name == 'nt': # ironpython is only on windows as far as we know return 'win32' - return re.split('\d+$', s)[0] + return re.split(r'\d+$', s)[0] def nada(*k, **kw): """ diff --git a/waflib/ansiterm.py b/waflib/ansiterm.py index 0d20c6374b..027f0ad68a 100644 --- a/waflib/ansiterm.py +++ b/waflib/ansiterm.py @@ -264,7 +264,7 @@ def hide_cursor(self,param): 'u': pop_cursor, } # Match either the escape sequence or text not containing escape sequence - ansi_tokens = re.compile('(?:\x1b\[([0-9?;]*)([a-zA-Z])|([^\x1b]+))') + ansi_tokens = re.compile(r'(?:\x1b\[([0-9?;]*)([a-zA-Z])|([^\x1b]+))') def write(self, text): try: wlock.acquire() diff --git a/waflib/extras/cpplint.py b/waflib/extras/cpplint.py index e3302e5bcf..8cdd6ddacb 100644 --- a/waflib/extras/cpplint.py +++ b/waflib/extras/cpplint.py @@ -43,12 +43,12 @@ def build(bld): critical_errors = 0 CPPLINT_FORMAT = '[CPPLINT] %(filename)s:\nline %(linenum)s, severity %(confidence)s, category: %(category)s\n%(message)s\n' -RE_EMACS = re.compile('(?P.*):(?P\d+): (?P.*) \[(?P.*)\] \[(?P\d+)\]') +RE_EMACS = re.compile(r'(?P.*):(?P\d+): (?P.*) \[(?P.*)\] \[(?P\d+)\]') CPPLINT_RE = { 'waf': RE_EMACS, 'emacs': RE_EMACS, - 'vs7': re.compile('(?P.*)\((?P\d+)\): (?P.*) \[(?P.*)\] \[(?P\d+)\]'), - 'eclipse': re.compile('(?P.*):(?P\d+): warning: (?P.*) \[(?P.*)\] \[(?P\d+)\]'), + 'vs7': re.compile(r'(?P.*)\((?P\d+)\): (?P.*) \[(?P.*)\] \[(?P\d+)\]'), + 'eclipse': re.compile(r'(?P.*):(?P\d+): warning: (?P.*) \[(?P.*)\] \[(?P\d+)\]'), } CPPLINT_STR = ('${CPPLINT} ' '--verbose=${CPPLINT_LEVEL} ' diff --git a/waflib/extras/distnet.py b/waflib/extras/distnet.py index 09a31a6d43..ff3ed8e114 100644 --- a/waflib/extras/distnet.py +++ b/waflib/extras/distnet.py @@ -44,7 +44,7 @@ def safe_urlencode(data): TIMEOUT = 60 REQUIRES = 'requires.txt' -re_com = re.compile('\s*#.*', re.M) +re_com = re.compile(r'\s*#.*', re.M) def total_version_order(num): lst = num.split('.') diff --git a/waflib/extras/erlang.py b/waflib/extras/erlang.py index 49f6d5b475..0b93d9a4f4 100644 --- a/waflib/extras/erlang.py +++ b/waflib/extras/erlang.py @@ -51,7 +51,7 @@ def scan(task): if n.abspath() in scanned: continue - for i in re.findall('-include\("(.*)"\)\.', n.read()): + for i in re.findall(r'-include\("(.*)"\)\.', n.read()): for d in task.erlc_incnodes: r = d.find_node(i) if r: diff --git a/waflib/extras/gccdeps.py b/waflib/extras/gccdeps.py index e37f9749ca..ba01b1b320 100644 --- a/waflib/extras/gccdeps.py +++ b/waflib/extras/gccdeps.py @@ -36,7 +36,7 @@ def scan(self): names = [] return (nodes, names) -re_o = re.compile("\.o$") +re_o = re.compile(r"\.o$") re_splitter = re.compile(r'(? search env.LINUX_32 and then env.LINUX""" diff --git a/waflib/extras/run_do_script.py b/waflib/extras/run_do_script.py index f3c58122c9..07e3aa2591 100644 --- a/waflib/extras/run_do_script.py +++ b/waflib/extras/run_do_script.py @@ -101,7 +101,7 @@ def check_erase_log_file(self): with open(**kwargs) as log: log_tail = log.readlines()[-10:] for line in log_tail: - error_found = re.match("r\(([0-9]+)\)", line) + error_found = re.match(r"r\(([0-9]+)\)", line) if error_found: return error_found.group(1), ''.join(log_tail) else: diff --git a/waflib/extras/swig.py b/waflib/extras/swig.py index a582a69c88..740ab46d96 100644 --- a/waflib/extras/swig.py +++ b/waflib/extras/swig.py @@ -17,10 +17,10 @@ SWIG_EXTS = ['.swig', '.i'] -re_module = re.compile('%module(?:\s*\(.*\))?\s+(.+)', re.M) +re_module = re.compile(r'%module(?:\s*\(.*\))?\s+(.+)', re.M) re_1 = re.compile(r'^%module.*?\s+([\w]+)\s*?$', re.M) -re_2 = re.compile('[#%](?:include|import(?:\(module=".*"\))+|python(?:begin|code)) [<"](.*)[">]', re.M) +re_2 = re.compile(r'[#%](?:include|import(?:\(module=".*"\))+|python(?:begin|code)) [<"](.*)[">]', re.M) class swig(Task.Task): color = 'BLUE' From c323c1b50bd5e5424b3dcc1f1b8f6fdb6cbbce64 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sat, 5 Jan 2019 16:16:48 +0100 Subject: [PATCH 071/315] Rework the previous changes --- waflib/Context.py | 4 ++-- waflib/Tools/c_config.py | 6 +++--- waflib/Tools/qt5.py | 8 ++++---- waflib/extras/pyqt5.py | 6 +++--- waflib/extras/qt4.py | 8 ++++---- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/waflib/Context.py b/waflib/Context.py index 888091dfd3..c30bbc0dc6 100644 --- a/waflib/Context.py +++ b/waflib/Context.py @@ -607,13 +607,13 @@ def end_msg(self, *k, **kw): Logs.pprint(color, msg) def load_special_tools(self, var, ban=[]): - r""" + """ Loads third-party extensions modules for certain programming languages by trying to list certain files in the extras/ directory. This method is typically called once for a programming language group, see for example :py:mod:`waflib.Tools.compiler_c` - :param var: glob expression, for example 'cxx\_\*.py' + :param var: glob expression, for example 'cxx\\_\\*.py' :type var: string :param ban: list of exact file names to exclude :type ban: list of string diff --git a/waflib/Tools/c_config.py b/waflib/Tools/c_config.py index 71a3acacbf..0977dabf26 100644 --- a/waflib/Tools/c_config.py +++ b/waflib/Tools/c_config.py @@ -239,7 +239,7 @@ def validate_cfg(self, kw): @conf def exec_cfg(self, kw): - r""" + """ 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 @@ -250,9 +250,9 @@ def exec_cfg(self, kw): :type atleast_pkgconfig_version: string :param package: package name, for example *gtk+-2.0* :type package: string - :param uselib_store: if the test is successful, define HAVE\_*name*. It is also used to define *conf.env.FLAGS_name* variables. + :param uselib_store: if the test is successful, define HAVE\\_*name*. It is also used to define *conf.env.FLAGS_name* variables. :type uselib_store: string - :param modversion: if provided, return the version of the given module and define *name*\_VERSION + :param modversion: if provided, return the version of the given module and define *name*\\_VERSION :type modversion: string :param args: arguments to give to *package* when retrieving flags :type args: list of string diff --git a/waflib/Tools/qt5.py b/waflib/Tools/qt5.py index 52a85f4c48..9f432801cb 100644 --- a/waflib/Tools/qt5.py +++ b/waflib/Tools/qt5.py @@ -305,7 +305,7 @@ def build(bld): @feature('qt5') @after_method('apply_link') def apply_qt5(self): - r""" + """ Adds MOC_FLAGS which may be necessary for moc:: def build(bld): @@ -313,11 +313,11 @@ def build(bld): The additional parameters are: - :param lang: list of translation files (\*.ts) to process + :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**) + :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 + :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): diff --git a/waflib/extras/pyqt5.py b/waflib/extras/pyqt5.py index 2f9dc23d33..80f43b8872 100644 --- a/waflib/extras/pyqt5.py +++ b/waflib/extras/pyqt5.py @@ -108,12 +108,12 @@ def add_pylang(self, node): @feature('pyqt5') def apply_pyqt5(self): - r""" + """ The additional parameters are: - :param lang: list of translation files (\*.ts) to process + :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 langname: if given, transform the \*.ts files into a .qrc files to include in the binary file + :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): diff --git a/waflib/extras/qt4.py b/waflib/extras/qt4.py index b064f9e35e..d19a4ddac3 100644 --- a/waflib/extras/qt4.py +++ b/waflib/extras/qt4.py @@ -282,7 +282,7 @@ def add_lang(self, node): @feature('qt4') @after_method('apply_link') def apply_qt4(self): - r""" + """ Add MOC_FLAGS which may be necessary for moc:: def build(bld): @@ -290,11 +290,11 @@ def build(bld): The additional parameters are: - :param lang: list of translation files (\*.ts) to process + :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**) + :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 + :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): From f39106e28bfc63560b548592036336d89a074fc8 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sat, 5 Jan 2019 16:20:45 +0100 Subject: [PATCH 072/315] docs --- waflib/Context.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/Context.py b/waflib/Context.py index c30bbc0dc6..38c64645c9 100644 --- a/waflib/Context.py +++ b/waflib/Context.py @@ -678,7 +678,7 @@ def load_module(path, encoding=None): def load_tool(tool, tooldir=None, ctx=None, with_sys_path=True): """ - Importx a Waf tool as a python module, and stores it in the dict :py:const:`waflib.Context.Context.tools` + Imports a Waf tool as a python module, and stores it in the dict :py:const:`waflib.Context.Context.tools` :type tool: string :param tool: Name of the tool From 51d0088d330acc73aadd268f5a3224a1232f9646 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Wed, 16 Jan 2019 06:51:14 +0100 Subject: [PATCH 073/315] Fix a few deprecation warnings --- build_system_kit/extpy/extpy.py | 2 +- waflib/ConfigSet.py | 2 +- waflib/Context.py | 4 ++-- waflib/Logs.py | 4 ++-- wscript | 6 +++--- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/build_system_kit/extpy/extpy.py b/build_system_kit/extpy/extpy.py index e6446850dc..73a8596682 100644 --- a/build_system_kit/extpy/extpy.py +++ b/build_system_kit/extpy/extpy.py @@ -27,7 +27,7 @@ def recurse(self, dirs, name=None, mandatory=True, once=True): cache[node] = True self.pre_recurse(node) try: - function_code = node.read('rU') + function_code = node.read('r') exec(compile(function_code, node.abspath(), 'exec'), self.exec_dict) finally: self.post_recurse(node) diff --git a/waflib/ConfigSet.py b/waflib/ConfigSet.py index 9db8e90758..901fba6c06 100644 --- a/waflib/ConfigSet.py +++ b/waflib/ConfigSet.py @@ -312,7 +312,7 @@ def load(self, filename): :type filename: string """ tbl = self.table - code = Utils.readf(filename, m='rU') + code = Utils.readf(filename, m='r') for m in re_imp.finditer(code): g = m.group tbl[g(2)] = eval(g(3)) diff --git a/waflib/Context.py b/waflib/Context.py index 38c64645c9..f6e9558f95 100644 --- a/waflib/Context.py +++ b/waflib/Context.py @@ -266,7 +266,7 @@ def recurse(self, dirs, name=None, mandatory=True, once=True, encoding=None): cache[node] = True self.pre_recurse(node) try: - function_code = node.read('rU', encoding) + function_code = node.read('r', encoding) exec(compile(function_code, node.abspath(), 'exec'), self.exec_dict) finally: self.post_recurse(node) @@ -662,7 +662,7 @@ def load_module(path, encoding=None): module = imp.new_module(WSCRIPT_FILE) try: - code = Utils.readf(path, m='rU', encoding=encoding) + code = Utils.readf(path, m='r', encoding=encoding) except EnvironmentError: raise Errors.WafError('Could not read the file %r' % path) diff --git a/waflib/Logs.py b/waflib/Logs.py index 2a475169b9..11dc34f356 100644 --- a/waflib/Logs.py +++ b/waflib/Logs.py @@ -276,9 +276,9 @@ def error(*k, **kw): def warn(*k, **kw): """ - Wraps logging.warn + Wraps logging.warning """ - log.warn(*k, **kw) + log.warning(*k, **kw) def info(*k, **kw): """ diff --git a/wscript b/wscript index 18bb365f4e..623be1adf2 100644 --- a/wscript +++ b/wscript @@ -30,7 +30,7 @@ from waflib import Configure Configure.autoconfig = 1 def sub_file(fname, lst): - with open(fname, 'rU') as f: + with open(fname, 'r') as f: txt = f.read() for (key, val) in lst: @@ -160,7 +160,7 @@ def process_tokens(tokens): body = ''.join(accu) return body -deco_re = re.compile('(def|class)\\s+(\w+)\\(.*') +deco_re = re.compile('(def|class)\\s+(\\w+)\\(.*') def process_decorators(body): lst = body.splitlines() accu = [] @@ -315,7 +315,7 @@ def create_waf(self, *k, **kw): tar.close() z.close() - with open('waf-light', 'rU') as f: + with open('waf-light', 'r') as f: code1 = f.read() # now store the revision unique number in waf From ee19eb2a00d2e4ae7d664ad43a8b1de2d5c10685 Mon Sep 17 00:00:00 2001 From: fedepell Date: Thu, 17 Jan 2019 14:45:40 +0100 Subject: [PATCH 074/315] protoc: fix filename generation for .java --- playground/protoc/inc/msgCaseTest.proto | 14 ++++++++++++++ playground/protoc/wscript | 2 +- waflib/extras/protoc.py | 6 ++++-- 3 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 playground/protoc/inc/msgCaseTest.proto diff --git a/playground/protoc/inc/msgCaseTest.proto b/playground/protoc/inc/msgCaseTest.proto new file mode 100644 index 0000000000..4d9b637440 --- /dev/null +++ b/playground/protoc/inc/msgCaseTest.proto @@ -0,0 +1,14 @@ +package udp.tc.tests; + +import "message_inc.proto"; + +option java_package ="com.udp.tc.tests"; +option cc_generic_services = false; +option java_generic_services = false; +option py_generic_services = false; + +message MessageCaseTest { + required int32 test = 1; + optional uint32 blah = 2; + required IncludeMe custom = 3; +} diff --git a/playground/protoc/wscript b/playground/protoc/wscript index 0646d4842a..45d4df6189 100644 --- a/playground/protoc/wscript +++ b/playground/protoc/wscript @@ -57,7 +57,7 @@ def build(bld): features = 'javac protoc', name = 'pbjava', srcdir = 'inc/', - source = ['inc/message_inc.proto', 'inc/message.proto'], + source = ['inc/message_inc.proto', 'inc/message.proto', 'inc/msgCaseTest.proto' ], use = 'PROTOBUF', protoc_includes = ['inc']) diff --git a/waflib/extras/protoc.py b/waflib/extras/protoc.py index 3d41021891..72b0f26ee5 100644 --- a/waflib/extras/protoc.py +++ b/waflib/extras/protoc.py @@ -210,10 +210,12 @@ def process_protoc(self, node): if javacn: nodename += javacn + '.java' else: + filenamebase = node.abspath()[node.abspath().rfind(os.sep)+1:node.abspath().rfind('.')].replace('_','') + filenamebase = filenamebase[:1].upper() + filenamebase[1:] if self.env.PROTOC_MAJOR > '2' and node.abspath()[node.abspath().rfind(os.sep)+1:node.abspath().rfind('.')].title() in messages: - nodename += node.abspath()[node.abspath().rfind(os.sep)+1:node.abspath().rfind('.')].title().replace('_','') + 'OuterClass.java' + nodename += filenamebase + 'OuterClass.java' else: - nodename += node.abspath()[node.abspath().rfind(os.sep)+1:node.abspath().rfind('.')].title().replace('_','') + '.java' + nodename += filenamebase + '.java' java_node = node.parent.find_or_declare(nodename) out_nodes.append(java_node) From 6b828a5f44e2643a06cebd186291f3c892713cd5 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sat, 19 Jan 2019 09:40:11 +0100 Subject: [PATCH 075/315] Prevent protoc errors on "waf list" --- waflib/extras/protoc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/waflib/extras/protoc.py b/waflib/extras/protoc.py index 72b0f26ee5..51994cc2e2 100644 --- a/waflib/extras/protoc.py +++ b/waflib/extras/protoc.py @@ -169,7 +169,7 @@ def process_protoc(self, node): out_nodes.append(py_node) protoc_flags.append('--python_out=%s' % node.parent.get_bld().bldpath()) - if 'javac' in self.features: + if 'javac' in self.features and node.exists(): pkgname, javapkg, javacn, nodename = None, None, None, None messages = [] @@ -225,7 +225,7 @@ def process_protoc(self, node): if not node.parent.get_bld() in self.javac_task.srcdir: self.javac_task.srcdir.append(node.parent.get_bld()) - if not out_nodes: + if not out_nodes and node.exists(): raise Errors.WafError('Feature %r not supported by protoc extra' % self.features) tsk = self.create_task('protoc', node, out_nodes) From d5da401be4ebad46864f9d6ff54a242a02c57339 Mon Sep 17 00:00:00 2001 From: Federico Pellegrin Date: Sun, 20 Jan 2019 10:41:51 +0000 Subject: [PATCH 076/315] protoc: simplify the java generation also solving problems with .proto input files generated during build --- playground/protoc_gen_java/proto.source | 14 ++++++ playground/protoc_gen_java/wscript | 51 ++++++++++++++++++++++ waflib/extras/protoc.py | 58 ++----------------------- 3 files changed, 68 insertions(+), 55 deletions(-) create mode 100644 playground/protoc_gen_java/proto.source create mode 100644 playground/protoc_gen_java/wscript diff --git a/playground/protoc_gen_java/proto.source b/playground/protoc_gen_java/proto.source new file mode 100644 index 0000000000..5da32dfdc8 --- /dev/null +++ b/playground/protoc_gen_java/proto.source @@ -0,0 +1,14 @@ +package udp.tc.tests; + +option java_package = "com.udp.tc.tests"; +option java_outer_classname = "MessageInc"; +option cc_generic_services = false; +option java_generic_services = false; +option py_generic_services = false; + + +message IncludeMe { + required int32 test = 1; + optional uint32 blah = 2; + optional uint32 justinc = 3; +} diff --git a/playground/protoc_gen_java/wscript b/playground/protoc_gen_java/wscript new file mode 100644 index 0000000000..5b4dc274b7 --- /dev/null +++ b/playground/protoc_gen_java/wscript @@ -0,0 +1,51 @@ +#! /usr/bin/env python +# encoding: utf-8 +# Federico Pellegrin, 2019 (fedepell) + +import os +from waflib import Logs + +top = '.' +out = 'build' + +def options(opt): + opt.load('compiler_cxx java') + +def configure(conf): + conf.load('compiler_cxx java protoc') + # Here you have to point to your protobuf-java JAR + conf.env.CLASSPATH_PROTOBUF = ['/usr/share/maven-repo/com/google/protobuf/protobuf-java/3.0.0/protobuf-java-3.0.0.jar'] + +def build(bld): + + # this simulates a .proto generator. the gen.proto is generated in build + genp = bld( + rule = "cp ${SRC} ${TGT}", + source = "proto.source", + target = "inc/gen.proto" + ) + + # cxx doesn't have a problem with this, just knows gen.proto will pop up later + bld( + features = 'cxx cxxshlib', + source = [ bld.path.find_or_declare(genp.target) ], + name = 'somelib', + target = 'somelib' + ) + + # but for java: + + # we either put grouping because of protoc java generations needs .proto to generate out fname (#2218) + # or accept that java dep is not strict on the .java file name (but relies just on explicit task ordering) + # bld.add_group() + + # inc/gen.proto is an implicit dependency, but the file is generated at + # build time while protoc extra uses it before to determine the .java file + # name that will get generated + bld( + features = 'javac protoc', + name = 'pbjava', + srcdir = bld.path.find_or_declare(genp.target).parent, + source = [ bld.path.find_or_declare(genp.target) ], + use = 'PROTOBUF', + ) diff --git a/waflib/extras/protoc.py b/waflib/extras/protoc.py index 51994cc2e2..839c510b94 100644 --- a/waflib/extras/protoc.py +++ b/waflib/extras/protoc.py @@ -6,7 +6,7 @@ import re, os from waflib.Task import Task from waflib.TaskGen import extension -from waflib import Errors, Context +from waflib import Errors, Context, Logs """ A simple tool to integrate protocol buffers into your build system. @@ -169,64 +169,12 @@ def process_protoc(self, node): out_nodes.append(py_node) protoc_flags.append('--python_out=%s' % node.parent.get_bld().bldpath()) - if 'javac' in self.features and node.exists(): - pkgname, javapkg, javacn, nodename = None, None, None, None - messages = [] - - # .java file name is done with some rules depending on .proto file content: - # -) package is either derived from option java_package if present - # or from package directive - # -) file name is either derived from option java_outer_classname if present - # or the .proto file is converted to camelcase. If a message - # is named the same then the behaviour depends on protoc version - # - # See also: https://developers.google.com/protocol-buffers/docs/reference/java-generated#invocation - - code = node.read().splitlines() - for line in code: - m = re.search(r'^package\s+(.*);', line) - if m: - pkgname = m.groups()[0] - m = re.search(r'^option\s+(\S*)\s*=\s*"(\S*)";', line) - if m: - optname = m.groups()[0] - if optname == 'java_package': - javapkg = m.groups()[1] - elif optname == 'java_outer_classname': - javacn = m.groups()[1] - if self.env.PROTOC_MAJOR > '2': - m = re.search(r'^message\s+(\w*)\s*{*', line) - if m: - messages.append(m.groups()[0]) - - if javapkg: - nodename = javapkg - elif pkgname: - nodename = pkgname - else: - raise Errors.WafError('Cannot derive java name from protoc file') - - nodename = nodename.replace('.',os.sep) + os.sep - if javacn: - nodename += javacn + '.java' - else: - filenamebase = node.abspath()[node.abspath().rfind(os.sep)+1:node.abspath().rfind('.')].replace('_','') - filenamebase = filenamebase[:1].upper() + filenamebase[1:] - if self.env.PROTOC_MAJOR > '2' and node.abspath()[node.abspath().rfind(os.sep)+1:node.abspath().rfind('.')].title() in messages: - nodename += filenamebase + 'OuterClass.java' - else: - nodename += filenamebase + '.java' - - java_node = node.parent.find_or_declare(nodename) - out_nodes.append(java_node) - protoc_flags.append('--java_out=%s' % node.parent.get_bld().bldpath()) - + if 'javac' in self.features: # Make javac get also pick java code generated in build if not node.parent.get_bld() in self.javac_task.srcdir: self.javac_task.srcdir.append(node.parent.get_bld()) - if not out_nodes and node.exists(): - raise Errors.WafError('Feature %r not supported by protoc extra' % self.features) + protoc_flags.append('--java_out=%s' % node.parent.get_bld().bldpath()) tsk = self.create_task('protoc', node, out_nodes) tsk.env.append_value('PROTOC_FLAGS', protoc_flags) From a530c852a95095430dcc6643a9def724cda999a7 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Mon, 21 Jan 2019 07:30:01 +0100 Subject: [PATCH 077/315] Add a pipelines file --- .pipelines/Jenkinsfile | 346 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 346 insertions(+) create mode 100644 .pipelines/Jenkinsfile diff --git a/.pipelines/Jenkinsfile b/.pipelines/Jenkinsfile new file mode 100644 index 0000000000..eef191b369 --- /dev/null +++ b/.pipelines/Jenkinsfile @@ -0,0 +1,346 @@ + +pipeline { + agent none + stages { + stage('Build and Lint') { + parallel { + stage('Python 2.7') { + agent { + label "ubuntu" + } + steps { + sh 'python2.7 ./waf-light' + stash includes: 'waf', name: 'waf' + } + } + stage('Python 3.6') { + agent { + label "freebsd" + } + steps { + sh 'python3.6 ./waf-light' + } + } + stage('Deprecation warnings') { + agent { + label "ubuntu" + } + steps { + sh ''' +cd waflib +find . -iname "*.pyc" -exec rm -f {} \\; || true +! (((PYTHONWARNINGS=all python3.6 -m compileall . > /dev/null) 2>&1 ) 2>&1) | grep -i DeprecationWarning +''' + } + } + stage('Pyflakes') { + agent { + label "freebsd" + } + steps { + sh ''' +cd waflib +var=`(/usr/local/bin/pyflakes3.py *.py Tools/*.py extras/*.py 2>&1) | egrep "undefined name|invalid syntax|inconsistent use|unindent does not match any outer indentation level" | wc -l` +if [ "0" -eq "$var" ] +then + /usr/local/bin/pyflakes3.py *.py Tools/*.py extras/*.py || true +else + # just do it again and fail + /usr/local/bin/pyflakes3.py *.py Tools/*.py extras/*.py + exit 1 +fi +''' + } + } + stage('Unit tests') { + agent { + label "fedora" + } + steps { + sh ''' +./waf-light +cd tests/preproc/ +../../waf distclean +../../waf configure build +cd ../..''' + sh ''' +cd tests/install/ +../../waf distclean +../../waf configure build +cd ../..''' + sh ''' +cd tests/general/ +../../waf distclean +../../waf configure build +cd ../..''' + sh ''' +export PATH=$PATH:$PWD +cd tests/init/ +../../waf distclean +../../waf configure build +cd ../..''' + sh ''' +export WAF_TEST_GROUP=waftest +cd tests/install_group/ +../../waf distclean +../../waf configure build +''' + } + } + } + } + stage('Integration') { + parallel { + stage('Ubuntu') { + stages { + stage('py25') { + agent { + label "ubuntu" + } + steps { + dir('demos') { + unstash 'waf' + } + sh '''cd demos; LD_LIBRARY_PATH=/opt/lib ./waf distclean configure clean build --top=c''' + sh '''cd demos; LD_LIBRARY_PATH=/opt/lib ./waf distclean configure clean build --top=c++''' + sh '''cd demos; LD_LIBRARY_PATH=/opt/lib ./waf distclean configure clean build --top=java''' + sh '''cd demos; LD_LIBRARY_PATH=/opt/lib ./waf distclean configure clean build --top=perl''' + sh '''cd demos; LD_LIBRARY_PATH=/opt/lib ./waf distclean configure clean build --top=python''' + sh '''cd demos; LD_LIBRARY_PATH=/opt/lib ./waf distclean configure clean build --top=qt5''' + sh '''cd demos; LD_LIBRARY_PATH=/opt/lib ./waf distclean configure clean build --top=subst''' + } + } + stage('py36') { + agent { + label "ubuntu" + } + steps { + dir('demos') { + unstash 'waf' + } + sh '''cd demos; python3 ./waf configure clean build --top=c''' + sh '''cd demos; python3 ./waf configure clean build --top=c++''' + sh '''cd demos; python3 ./waf configure clean build --top=java''' + sh '''cd demos; python3 ./waf configure clean build --top=perl''' + sh '''cd demos; python3 ./waf configure clean build --top=python''' + sh '''cd demos; python3 ./waf configure clean build --top=qt5''' + sh '''cd demos; python3 ./waf configure clean build --top=subst''' + } + } + stage('py27') { + agent { + label "ubuntu" + } + steps { + dir('demos') { + unstash 'waf' + } + sh '''cd demos; ./waf configure clean build --top=c''' + sh '''cd demos; ./waf configure clean build --top=c++''' + sh '''cd demos; ./waf configure clean build --top=java''' + sh '''cd demos; ./waf configure clean build --top=perl''' + sh '''cd demos; ./waf configure clean build --top=python''' + sh '''cd demos; ./waf configure clean build --top=qt5''' + sh '''cd demos; ./waf configure clean build --top=subst''' + } + } + } + } + stage('OpenBSD') { + stages { + stage('Jython') { + agent { + label "openbsd" + } + steps { + sh ''' + export WAF_NO_PREFORK=1 + /home/jenkins/jython/bin/jython ./waf-light + cp waf demos/c + cd demos/c + /home/jenkins/jython/bin/jython ./waf distclean configure clean build + ''' + } + } + stage('py27') { + agent { + label "openbsd" + } + steps { + dir('demos') { + unstash 'waf' + } + sh '''cd demos/asm; /usr/local/bin/python2.7 ../waf configure clean build''' + sh '''cd demos/c; /usr/local/bin/python2.7 ../waf configure clean build''' + sh '''cd demos/c++; /usr/local/bin/python2.7 ../waf configure clean build''' + sh '''cd demos/glib2; /usr/local/bin/python2.7 ../waf configure clean build''' + sh '''cd demos/perl; /usr/local/bin/python2.7 ../waf configure clean build''' + sh '''cd demos/python; /usr/local/bin/python2.7 ../waf configure clean build''' + sh '''cd demos/subst; /usr/local/bin/python2.7 ../waf configure clean build''' + } + } + stage('py36') { + agent { + label "openbsd" + } + steps { + dir('demos') { + unstash 'waf' + } + sh '''cd demos/asm; python3 ../waf configure clean build''' + sh '''cd demos/c; python3 ../waf configure clean build''' + sh '''cd demos/c++; python3 ../waf configure clean build''' + sh '''cd demos/glib2; python3 ../waf configure clean build''' + sh '''cd demos/perl; python3 ../waf configure clean build''' + sh '''cd demos/python; python3 ../waf configure clean build''' + sh '''cd demos/subst; python3 ../waf configure clean build''' + } + } + } + } + stage('Windows') { + stages { + stage('C/py34') { + agent { + label "windows" + } + steps { + bat ''' C:/Python34/python.exe waf-light --tools=msvs ''' + bat ''' + copy waf demos\\c /Y + cd demos\\c + C:/Python34/python.exe waf distclean + C:/Python34/python.exe waf configure --no-msvc-lazy build -v + ''' + bat ''' + copy waf demos\\qt5 /Y + cd demos\\qt5 + C:/Python34/python.exe waf distclean + C:/Python34/python.exe waf configure --no-msvc-lazy build -v + ''' + bat ''' + copy waf playground\\msvs /Y + cd playground\\msvs + C:/Python34/python.exe waf distclean + C:/Python34/python.exe waf configure + C:/Python34/python.exe waf msvs + ''' + } + } + stage('C/Msys2/py27') { + agent { + label "windows" + } + steps { + unstash 'waf' + bat ''' + copy waf demos\\c /Y + cd demos\\c + set MSYSTEM=MINGW64 + set WD=C:\\msys64\\usr\\bin + set CHERE_INVOKING=1 + C:\\msys64\\usr\\bin\\sh --login -c 'exec /bin/bash -c "python waf configure clean build && python waf distclean"' + ''' + } + } + stage('C/Msys2/py35') { + agent { + label "windows" + } + steps { + unstash 'waf' + bat ''' + copy waf demos\\c /Y + cd demos\\c + set MSYSTEM=MINGW64 + set WD=C:\\msys64\\usr\\bin + set CHERE_INVOKING=1 + C:\\msys64\\usr\\bin\\sh --login -c 'exec /bin/bash -c "python3 waf configure clean build && python3 waf distclean"' + ''' + } + } + stage('C/IronPython') { + agent { + label "windows" + } + steps { + bat ''' + C:/Python34/python.exe waf-light --zip-type=gz + ''' + bat ''' + copy waf demos\\c /Y + cd demos\\c + "C:\\Program Files (x86)\\IronPython 2.7\\ipy64.exe" waf distclean + "C:\\Program Files (x86)\\IronPython 2.7\\ipy64.exe" waf configure build build + ''' + } + } + } + } + stage('OpenIndiana') { + stages { + stage('py27') { + agent { + label "openindiana" + } + steps { + dir('demos') { + unstash 'waf' + } + sh '''export CFLAGS='-std=c99 -D_STDC_C99' ''' + sh '''cd demos; ./waf configure clean build --top=c''' + sh '''cd demos; ./waf configure clean build --top=c++''' + sh '''cd demos; ./waf configure clean build --top=dbus''' + sh '''cd demos; ./waf configure clean build --top=java''' + sh '''cd demos; ./waf configure clean build --top=perl''' + sh '''cd demos; ./waf configure clean build --top=python''' + sh '''cd demos; ./waf configure clean build --top=ruby''' + } + } + } + } + stage('FreeBSD') { + stages { + stage('py36') { + agent { + label "freebsd" + } + steps { + dir('demos') { + unstash 'waf' + } + sh '''cd demos/c; python3.6 ../waf distclean configure clean build''' + sh '''cd demos/c++; python3.6 ../waf distclean configure clean build''' + sh '''cd demos/java; python3.6 ../waf distclean configure clean build''' + sh '''cd demos/jni; python3.6 ../waf distclean configure clean build''' + sh '''cd demos/perl; python3.6 ../waf distclean configure clean build''' + sh '''cd demos/python; python3.6 ../waf distclean configure clean build''' + sh '''cd demos/ruby; python3.6 ../waf distclean configure clean build''' + sh '''cd demos/glib2; python3.6 ../waf distclean configure clean build''' + sh '''cd demos/qt5; python3.6 ../waf distclean configure clean build''' + sh '''cd demos/dbus; python3.6 ../waf distclean configure clean build''' + } + } + } + } + stage('MacOS') { + stages { + stage('py27') { + agent { + label "macos" + } + steps { + dir('demos') { + unstash 'waf' + } + sh '''cd demos/c; ../waf distclean configure clean build''' + sh '''cd demos/python; ../waf distclean configure clean build''' + sh '''cd demos/mac_app; ../waf distclean configure clean build''' + } + } + } + } + } + } + } +} From fa3e969e4496aae56d4e83c9a6d917ebcc49e70d Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Tue, 22 Jan 2019 08:08:55 +0100 Subject: [PATCH 078/315] Use .pipelines/Jenkinsfile instead of demos/wscript --- demos/wscript | 149 -------------------------------------------------- 1 file changed, 149 deletions(-) delete mode 100644 demos/wscript diff --git a/demos/wscript b/demos/wscript deleted file mode 100644 index 96036c0728..0000000000 --- a/demos/wscript +++ /dev/null @@ -1,149 +0,0 @@ -#! /usr/bin/env python -# encoding: utf-8 -# J. Carretero, 2010 (zougloub) -# Thomas Nagy, 2010 (ita) - -""" -https://launchpad.net/subunit/ -""" - - - -import sys, os - -if "uname" in dir(os): machine = os.uname()[1] -elif sys.platform == "win32": machine = os.environ["COMPUTERNAME"] -else: raise Exception("Unknown platform, cannot get machine name") - -from waflib import Logs, Errors - -# python 2.3 tends to hang for whatever reason :-/ -PYTHONS = "2.5 2.6 2.7 3.0 3.1 3.2 3.3 3.4 3.5".split() - -DIRS = ['c', 'python'] -if os.environ.get('BUILDFARM'): - DIRS = [x for x in os.listdir('.') if os.path.isdir(x) and x not in ('variants', 'build', 'mac_app', 'precious') and x.find('waf-') < 0] - -def options(opt): - for d in opt.path.ant_glob(DIRS, excl=['build', 'variants'], src=False, dir=True): - if d.name[0] == '.' or d.name == 'variants' or d.name == 'build': - continue - - try: - opt.recurse(d.name) - except Exception: - pass - # one sub-project uses autoconfig, but i do not want it here - from waflib import Configure - Configure.autoconfig = False - -def configure(conf): - - #Logs.info('Running action configure') # build farm - try: - sub = conf.find_file('subprocess.py', ['/usr/lib64/python', '/usr/lib/python', '/usr/local/lib64/python', '/usr/local/lib/python']) - except: - sub = '' - - curwaf = os.path.abspath(sys.argv[0]) - conf.exec_command('%s %s configure build --zip-type=gz --tools=doxygen,fluid,ocaml,swig,compiler_fc,fc_config,fc,fc_scan,g95,ifort,gfortran,batched_cc,%s --prelude='' && /bin/cp waf demos/' % (sys.executable, curwaf, sub), - cwd=conf.path.parent.abspath()) - - node = conf.path.find_resource('waf') - if not node: - conf.fatal('Could not find Waf') - #if conf.exec_command([node.abspath(), '--help'], shell=False, env={}, cwd=node.parent.abspath()): - # conf.fatal('the waf file cannot be executed') - conf.env.WAF = node.abspath() - - conf.in_msg += 1 - for d in conf.path.ant_glob(DIRS, excl=['build', 'variants', 'precious'], src=False, dir=True): - if d.name[0] == '.': - continue - conf.env.stash() - try: - conf.recurse(d.name) - except Exception: - conf.env.revert() - node = conf.path.find_node('%s/build/config.log' % d.name) - if node: - Logs.info('-- BEGIN %s config.log --\n%s-- END %s config.log --', d.name, node.read(), d.name) - try: - e = sys.exc_info()[1] - print(e) - print(e.stdout, e.stderr) - except Exception: - pass - else: - conf.env.revert() - conf.env.append_value('CFG', [d.name]) - - print("The configurations enabled are %r" % conf.env.CFG) - - # now remove the cache folders and re-create them - #conf.cmd_and_log('rm -rf .waf*') - for x in PYTHONS: - try: - conf.find_program('python'+x, var=x) - # unpacking the waf directory concurrently can lead to a race condition, we'll need to take care of this (thanks, build farm!) - conf.cmd_and_log(conf.env[x] + ['./waf', '--version'], env={}) - except Errors.WafError as e: - pass - else: - conf.env.append_value('PYTHONS', x) - - Logs.info('executing the build for folders %r and with pythons %r', conf.env.CFG, conf.env.PYTHONS) - Logs.info("contents of config.log:") - Logs.info(conf.path.find_node('build/config.log').read()) - -def build(bld): - print('Note: call "waf installcheck" (the default build does not do anything)') - -from waflib.Build import BuildContext -class abc(BuildContext): - cmd = "installcheck" - fun = "installcheck" - -def installcheck(bld): - bld.jobs = 1 - #if bld.cmd == 'build': - # Logs.info('Running action build') # build farm - - #print('testsuite: waflib') - def waf_cmd(self): - cmd = self.env[self.generator.python] + [self.env.WAF, 'distclean', 'configure', 'build', 'clean', 'build', '-o', 'build' + self.generator.python] - cwd = self.generator.cwd - env = dict(os.environ) - env['WAFDIR'] = '' - env['WAFLOCK'] = '.lock-wscript' + self.generator.python # use a different build directory for each build - try: - bld.cmd_and_log(cmd, cwd=cwd, env=env, quiet=0, ) - except Errors.WafError as e: - e = sys.exc_info()[1] - s = "testsuite: %s\ntestsuite-xfail: %s [ %s \n %s ]\n" % (self.generator.name, self.generator.name, e.stderr, e.stdout) - Logs.info(s) - else: - s = "testsuite: %s\ntestsuite-success: %s\n" % (self.generator.name, self.generator.name) - Logs.info(s) - - for x in bld.env.PYTHONS: - for dirname in bld.env.CFG: - bld(rule = waf_cmd, - cwd = dirname, - always = 1, - python = x, - name = '%s_%s' % (dirname, x)) - - #if bld.cmd == 'build': - # Logs.info('BUILD STATUS: 0\nACTION PASSED: build') # build farm - # Logs.info('Running action test') # build farm - #Logs.info('testsuite: abc') - #def end(bld): - # Logs.info('testsuite-success: abc') - # Logs.info('TEST STATUS: 0\nACTION FAILED: test') - #bld.add_post_fun(end) - #elif bld.cmd == 'install': - # Logs.info('Running action install') # build farm - # Logs.info('INSTALL STATUS: 0\nACTION PASSED: install') # build farm - - From dd691543fc2c5eb046df3b57712423eea05f3a91 Mon Sep 17 00:00:00 2001 From: xbreak <2669927-xbreak@users.noreply.gitlab.com> Date: Fri, 25 Jan 2019 11:46:39 +0000 Subject: [PATCH 079/315] buildcopy: Added warning if buildcopy is used without any files to copy --- waflib/extras/buildcopy.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/waflib/extras/buildcopy.py b/waflib/extras/buildcopy.py index a6d9ac8311..eaff7e605a 100644 --- a/waflib/extras/buildcopy.py +++ b/waflib/extras/buildcopy.py @@ -22,7 +22,7 @@ def build(bld): """ import os, shutil -from waflib import Errors, Task, TaskGen, Utils, Node +from waflib import Errors, Task, TaskGen, Utils, Node, Logs @TaskGen.before_method('process_source') @TaskGen.feature('buildcopy') @@ -58,10 +58,13 @@ def to_src_nodes(lst): raise Errors.WafError('buildcopy: File not found in src: %s'%os.path.join(*lst)) nodes = [ to_src_nodes(n) for n in getattr(self, 'buildcopy_source', getattr(self, 'source', [])) ] + if not nodes: + Logs.warn('buildcopy: No source files provided to buildcopy in %s (set `buildcopy_source` or `source`)', + self) + return node_pairs = [(n, n.get_bld()) for n in nodes] self.create_task('buildcopy', [n[0] for n in node_pairs], [n[1] for n in node_pairs], node_pairs=node_pairs) - class buildcopy(Task.Task): """ Copy for each pair `n` in `node_pairs`: n[0] -> n[1]. From f08ebcc5be3bf0cfb8e6fa7550e7b1335d5f0e68 Mon Sep 17 00:00:00 2001 From: Adriano Scoditti Date: Tue, 29 Jan 2019 11:48:54 +0100 Subject: [PATCH 080/315] Support multiple 'default_cmd' --- waflib/Scripting.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/waflib/Scripting.py b/waflib/Scripting.py index 26d92f165d..ae17a8b450 100644 --- a/waflib/Scripting.py +++ b/waflib/Scripting.py @@ -216,7 +216,10 @@ def parse_options(): ctx = Context.create_context('options') ctx.execute() if not Options.commands: - Options.commands.append(default_cmd) + if isinstance(default_cmd, list): + Options.commands.extend(default_cmd) + else: + Options.commands.append(default_cmd) if Options.options.whelp: ctx.parser.print_help() sys.exit(0) From e0db1e9351f8743a77371c28280583a11342b782 Mon Sep 17 00:00:00 2001 From: fedepell Date: Thu, 31 Jan 2019 06:58:39 +0100 Subject: [PATCH 081/315] javaw: add quiet=True to ant_globs to suppress warnings of globbing in build Most of the ant_globs used are explicitly and knowingly on build directory (ie. javadoc, jar re) so the warning is quite spurious. The only one that may be in doubt is the source re one: I added also here because if you use a code generator (ie. protoc) then it is also correct to glob on builds and the warning is misleading. --- waflib/Tools/javaw.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/waflib/Tools/javaw.py b/waflib/Tools/javaw.py index fc76c9d868..678a8d95d7 100644 --- a/waflib/Tools/javaw.py +++ b/waflib/Tools/javaw.py @@ -360,7 +360,7 @@ def runnable_status(self): return Task.ASK_LATER if not self.inputs: try: - self.inputs = [x for x in self.basedir.ant_glob(JAR_RE, remove=False) if id(x) != id(self.outputs[0])] + self.inputs = [x for x in self.basedir.ant_glob(JAR_RE, remove=False, quiet=True) if id(x) != id(self.outputs[0])] except Exception: raise Errors.WafError('Could not find the basedir %r for %r' % (self.basedir, self)) return super(jar_create, self).runnable_status() @@ -394,14 +394,14 @@ def runnable_status(self): self.inputs = [] for x in self.srcdir: if x.exists(): - self.inputs.extend(x.ant_glob(SOURCE_RE, remove=False)) + self.inputs.extend(x.ant_glob(SOURCE_RE, remove=False, quiet=True)) return super(javac, self).runnable_status() def post_run(self): """ List class files created """ - for node in self.generator.outdir.ant_glob('**/*.class'): + for node in self.generator.outdir.ant_glob('**/*.class', quiet=True): self.generator.bld.node_sigs[node] = self.uid() self.generator.bld.task_sigs[self.uid()] = self.cache_sig @@ -453,7 +453,7 @@ def run(self): self.generator.bld.cmd_and_log(lst, cwd=wd, env=env.env or None, quiet=0) def post_run(self): - nodes = self.generator.javadoc_output.ant_glob('**') + nodes = self.generator.javadoc_output.ant_glob('**', quiet=True) for node in nodes: self.generator.bld.node_sigs[node] = self.uid() self.generator.bld.task_sigs[self.uid()] = self.cache_sig From 5acd7b3736284ddaa744f65f08a5a5c60281933b Mon Sep 17 00:00:00 2001 From: Maurizio Drocco Date: Wed, 13 Feb 2019 23:40:47 +0000 Subject: [PATCH 082/315] added stubs/ to lib search paths --- playground/cuda/cuda.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playground/cuda/cuda.py b/playground/cuda/cuda.py index 6b92a1cde9..60266dc92a 100644 --- a/playground/cuda/cuda.py +++ b/playground/cuda/cuda.py @@ -50,7 +50,7 @@ def find_cuda_libs(self): _includes = node and node.abspath() or '' _libpath = [] - for x in ('lib64', 'lib'): + for x in ('lib64', 'lib64/stubs', 'lib', 'lib/stubs'): try: _libpath.append(d.find_node(x).abspath()) except: From 0b8a34fbed1eeeb4cfb2225503399c9c01070b96 Mon Sep 17 00:00:00 2001 From: James Harris Date: Fri, 15 Feb 2019 10:50:27 -0600 Subject: [PATCH 083/315] task: calculate correct cmdline bytes The previous patches to workaround http://support.microsoft.com/kb/830473 drastically over estimated the number of characters in commands by treating the repr() version of the command array as a reasonable estimator of commandline length. This caused commands attempt to write argsfiles before they should have. The new calculation calculates the number characters in the command array and adds the number of spaces that would be added by ' '.join(cmd) this provides a much closer estimate of the commandline length. This also limits the CLI-length on non windows platforms to 200kB. This prevents us hitting the much larger argument limits on Linux/BSD/MacOS platforms. --- waflib/Task.py | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/waflib/Task.py b/waflib/Task.py index a0450d429d..ead4eb6064 100644 --- a/waflib/Task.py +++ b/waflib/Task.py @@ -318,23 +318,29 @@ def exec_command(self, cmd, **kw): # workaround for command line length limit: # http://support.microsoft.com/kb/830473 - if self.should_split(cmd): - cmd, args = self.split_argfile(cmd) - try: - (fd, tmp) = tempfile.mkstemp() - os.write(fd, '\r\n'.join(args[1:]).encode()) - os.close(fd) - if Logs.verbose: - Logs.debug('argfile: @%r -> %r', tmp, args) - return self.generator.bld.exec_command(cmd + args[:1] + ['@' + tmp], **kw) - finally: + if not isinstance(cmd, str): + # Calculate commandline length: + cmd_bytes = sum([len(arg) for arg in cmd] + len(cmd) -1) + # Shunt arguments to a temporary file if the command is + # going to be too long. + if (cmd_bytes >= 8192 if Utils.is_win32 else cmd_bytes > 200000): + cmd, args = self.split_argfile(cmd) try: - os.remove(tmp) - except OSError: - # anti-virus and indexers can keep files open -_- - pass - else: - return self.generator.bld.exec_command(cmd, **kw) + (fd, tmp) = tempfile.mkstemp() + os.write(fd, '\r\n'.join(args).encode()) + os.close(fd) + if Logs.verbose: + Logs.debug('argfile: @%r -> %r', tmp, args) + return self.generator.bld.exec_command(cmd + ['@' + tmp], **kw) + finally: + try: + os.remove(tmp) + except OSError: + # anti-virus and indexers can keep files open -_- + pass + # If this line is hit then the command can be passed down stream + # directly. + return self.generator.bld.exec_command(cmd, **kw) def process(self): """ From 1daf0274a159c68a03e5f03ac387761d14c4ea6d Mon Sep 17 00:00:00 2001 From: James Harris Date: Mon, 18 Feb 2019 11:38:45 -0600 Subject: [PATCH 084/315] Address ntpath bug with empty prefix This patch addresses the bug described in issue #2225 where in using posix paths and an empty PREFIX value can result in files being installed to the root of the drive specified by destdir instead of to the desired prefix value. This is a bug in the assumption that user specified paths that are strings will contain directory separators that match the target operating system. --- waflib/Build.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/waflib/Build.py b/waflib/Build.py index 4aa4b901bd..fb752d145e 100644 --- a/waflib/Build.py +++ b/waflib/Build.py @@ -1054,7 +1054,7 @@ def post_run(self): def get_install_path(self, destdir=True): """ Returns the destination path where files will be installed, pre-pending `destdir`. - + Relative paths will be interpreted relative to `PREFIX` if no `destdir` is given. :rtype: string @@ -1062,7 +1062,7 @@ def get_install_path(self, destdir=True): if isinstance(self.install_to, Node.Node): dest = self.install_to.abspath() else: - dest = Utils.subst_vars(self.install_to, self.env) + dest = os.path.normpath(Utils.subst_vars(self.install_to, self.env)) if not os.path.isabs(dest): dest = os.path.join(self.env.PREFIX, dest) if destdir and Options.options.destdir: From 18cf23c908431697eba431d0b269355739dc4f02 Mon Sep 17 00:00:00 2001 From: James Harris Date: Tue, 19 Feb 2019 12:48:04 -0600 Subject: [PATCH 085/315] task: winres: allow tasks to disable @argsfile Not all tools executed by tasks support the '@argsfile' syntax for shunting commandline arguments to a file. This means that if such commands are shunted to a file early, he command will not work. On windows the rc.exe command is such an example, but some tools on linux have similar limitations. In the posix case, we artifically limit our commandline size because it is difficult/variable to caluclate what the actual limit is (it is partially dependent on environment size). This could artifically cause commands to fail due to commandline length when they otherwise wouldn't. This patch fixes this issue by adding the 'allow_argsfile' flag to the task. This way certain task instances will be able to specify if they are compatible with the '@argsfile' syntax or not. --- waflib/Task.py | 5 ++++- waflib/Tools/winres.py | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/waflib/Task.py b/waflib/Task.py index ead4eb6064..dee86606bf 100644 --- a/waflib/Task.py +++ b/waflib/Task.py @@ -150,6 +150,9 @@ class Task(evil): always_run = False """Specify whether task instances must always be executed or not (class attribute)""" + allow_argsfile = True + """Specify whether task instances support the @argsfile shortcut for sunting arguments to a file (class attribute)""" + shell = False """Execute the command with the shell (class attribute)""" @@ -323,7 +326,7 @@ def exec_command(self, cmd, **kw): cmd_bytes = sum([len(arg) for arg in cmd] + len(cmd) -1) # Shunt arguments to a temporary file if the command is # going to be too long. - if (cmd_bytes >= 8192 if Utils.is_win32 else cmd_bytes > 200000): + if self.allow_argsfile and (cmd_bytes >= 8192 if Utils.is_win32 else cmd_bytes > 200000): cmd, args = self.split_argfile(cmd) try: (fd, tmp) = tempfile.mkstemp() diff --git a/waflib/Tools/winres.py b/waflib/Tools/winres.py index 9be1ed6600..ecaf4f2261 100644 --- a/waflib/Tools/winres.py +++ b/waflib/Tools/winres.py @@ -32,6 +32,8 @@ class rc_parser(c_preproc.c_parser): """ Calculates dependencies in .rc files """ + allow_argsfile = False + def filter_comments(self, node): """ Overrides :py:meth:`waflib.Tools.c_preproc.c_parser.filter_comments` From caf9d7149abc0750bfcdfc5fd6c5a924ee61fa32 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 24 Feb 2019 10:49:30 +0100 Subject: [PATCH 086/315] Fix 4046e48ac10793b9a64289b1b69f48dcf1a0dcab from #2214 TypeError: can only concatenate list --- waflib/Task.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/Task.py b/waflib/Task.py index dee86606bf..721cb56b02 100644 --- a/waflib/Task.py +++ b/waflib/Task.py @@ -323,7 +323,7 @@ def exec_command(self, cmd, **kw): # http://support.microsoft.com/kb/830473 if not isinstance(cmd, str): # Calculate commandline length: - cmd_bytes = sum([len(arg) for arg in cmd] + len(cmd) -1) + cmd_bytes = sum([len(arg) for arg in cmd]) + len(cmd) -1 # Shunt arguments to a temporary file if the command is # going to be too long. if self.allow_argsfile and (cmd_bytes >= 8192 if Utils.is_win32 else cmd_bytes > 200000): From 43713447afe69fbe5adfef37125ba64413d40788 Mon Sep 17 00:00:00 2001 From: James Harris Date: Tue, 26 Feb 2019 17:26:32 +0000 Subject: [PATCH 087/315] Utils: only use msys2 paths from msys2 python This patch attempts to detects if, when we are running from within an MSYS2 environement (MSYSTEM is set) we are also executing inside an MSYS2 provided version of python. It does this by assuming that if we are not in a cygwin environment and we are building on windows, If the value of sys.executable is /usr/bin or /bin or /usr/local/bin (somethign unixy) then we are running in an MSYS2 python interpreter and shoudl compensate for msys2 root paths. Otherwise we shouldn't be doing extra path manipulation. --- waflib/Utils.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/waflib/Utils.py b/waflib/Utils.py index b84de64bf5..4b808a85e0 100644 --- a/waflib/Utils.py +++ b/waflib/Utils.py @@ -490,7 +490,9 @@ def split_path_msys(path): if sys.platform == 'cygwin': split_path = split_path_cygwin elif is_win32: - if os.environ.get('MSYSTEM'): + # Consider this an MSYSTEM environment if $MSYSTEM is set and python + # reports is executable from a unix like path on a windows host. + if os.environ.get('MSYSTEM') and sys.executable.startswith('/'): split_path = split_path_msys else: split_path = split_path_win32 From 08edd9a2c4607d84663ace26898fea5663adfcb6 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 3 Mar 2019 16:39:28 +0100 Subject: [PATCH 088/315] Do not expose Task.allow_argsfile and remove allow_argsfile from non-Task class #2216 The class waflib.Tools.winres.rc_parser is not a subclass of waflib.Task.Task: rc_parser -> c_preproc.c_parser -> object --- ChangeLog | 12 ++++++++++++ waflib/Task.py | 5 +---- waflib/Tools/winres.py | 2 -- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index e1557341ab..beb67c8085 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +NEW IN WAF 2.0.15 +----------------- +* Fix Python path detection under Git-Bash #2217 +* Provide an option to disable args files #2216 +* Improve command line length calculation for args files #2214 +* Add libs/stubs to Cuda library path #2213 +* Suppress ant_glob java warnings #2212 +* Support multiple 'default_cmd' #2211 +* Warn when buildcopy is used without any files to copy #2210 +* Protobuf examples enhancements #2208 #2209 +* Fix all DeprecationWarning: invalid escape sequence #2207 + NEW IN WAF 2.0.14 ----------------- * Support Fortran 2008 submodules #2205 diff --git a/waflib/Task.py b/waflib/Task.py index 721cb56b02..27d3325eda 100644 --- a/waflib/Task.py +++ b/waflib/Task.py @@ -150,9 +150,6 @@ class Task(evil): always_run = False """Specify whether task instances must always be executed or not (class attribute)""" - allow_argsfile = True - """Specify whether task instances support the @argsfile shortcut for sunting arguments to a file (class attribute)""" - shell = False """Execute the command with the shell (class attribute)""" @@ -326,7 +323,7 @@ def exec_command(self, cmd, **kw): cmd_bytes = sum([len(arg) for arg in cmd]) + len(cmd) -1 # Shunt arguments to a temporary file if the command is # going to be too long. - if self.allow_argsfile and (cmd_bytes >= 8192 if Utils.is_win32 else cmd_bytes > 200000): + if (cmd_bytes >= 8192 if Utils.is_win32 else cmd_bytes > 200000) and getattr(self, 'allow_argsfile', True): cmd, args = self.split_argfile(cmd) try: (fd, tmp) = tempfile.mkstemp() diff --git a/waflib/Tools/winres.py b/waflib/Tools/winres.py index ecaf4f2261..9be1ed6600 100644 --- a/waflib/Tools/winres.py +++ b/waflib/Tools/winres.py @@ -32,8 +32,6 @@ class rc_parser(c_preproc.c_parser): """ Calculates dependencies in .rc files """ - allow_argsfile = False - def filter_comments(self, node): """ Overrides :py:meth:`waflib.Tools.c_preproc.c_parser.filter_comments` From bca342fc985a90835dd8d6bab4cb19f3ef02f266 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 3 Mar 2019 17:32:28 +0100 Subject: [PATCH 089/315] Revert the args file threshold on non-win32 systems from #2214 --- waflib/Task.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/waflib/Task.py b/waflib/Task.py index 27d3325eda..a88c365252 100644 --- a/waflib/Task.py +++ b/waflib/Task.py @@ -316,14 +316,16 @@ def exec_command(self, cmd, **kw): if hasattr(self, 'stderr'): kw['stderr'] = self.stderr - # workaround for command line length limit: - # http://support.microsoft.com/kb/830473 if not isinstance(cmd, str): - # Calculate commandline length: - cmd_bytes = sum([len(arg) for arg in cmd]) + len(cmd) -1 - # Shunt arguments to a temporary file if the command is - # going to be too long. - if (cmd_bytes >= 8192 if Utils.is_win32 else cmd_bytes > 200000) and getattr(self, 'allow_argsfile', True): + if Utils.is_win32: + # win32 compares the resulting length http://support.microsoft.com/kb/830473 + too_long = sum([len(arg) for arg in cmd]) + len(cmd) > 8192 + else: + # non-win32 counts the amount of arguments (200k) + too_long = len(cmd) > 200000 + + if too_long and getattr(self, 'allow_argsfile', True): + # Shunt arguments to a temporary file if the command is too long. cmd, args = self.split_argfile(cmd) try: (fd, tmp) = tempfile.mkstemp() @@ -338,8 +340,6 @@ def exec_command(self, cmd, **kw): except OSError: # anti-virus and indexers can keep files open -_- pass - # If this line is hit then the command can be passed down stream - # directly. return self.generator.bld.exec_command(cmd, **kw) def process(self): From a2d346e1402a76d04638ec1586400fb998e87538 Mon Sep 17 00:00:00 2001 From: Matt Selsky Date: Thu, 7 Mar 2019 22:13:40 -0500 Subject: [PATCH 090/315] Typos --- waflib/Tools/ccroot.py | 2 +- waflib/Tools/javaw.py | 2 +- waflib/extras/fast_partial.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/waflib/Tools/ccroot.py b/waflib/Tools/ccroot.py index 8e16fe6c66..579d5b2b72 100644 --- a/waflib/Tools/ccroot.py +++ b/waflib/Tools/ccroot.py @@ -111,7 +111,7 @@ def apply_incpaths(self): tg = bld(features='includes', includes='.') The folders only need to be relative to the current directory, the equivalent build directory is - added automatically (for headers created in the build directory). This enable using a build directory + added automatically (for headers created in the build directory). This enables using a build directory or not (``top == out``). This method will add a list of nodes read by :py:func:`waflib.Tools.ccroot.to_incnodes` in ``tg.env.INCPATHS``, diff --git a/waflib/Tools/javaw.py b/waflib/Tools/javaw.py index 678a8d95d7..9daed395b3 100644 --- a/waflib/Tools/javaw.py +++ b/waflib/Tools/javaw.py @@ -209,7 +209,7 @@ def java_use_rec(self, name, **kw): else: y.post() # Add generated JAR name for CLASSPATH. Task ordering (set_run_after) - # is already guaranted by ordering done between the single tasks + # is already guaranteed by ordering done between the single tasks if hasattr(y, 'jar_task'): self.use_lst.append(y.jar_task.outputs[0].abspath()) diff --git a/waflib/extras/fast_partial.py b/waflib/extras/fast_partial.py index b3af513b25..d5b61448c6 100644 --- a/waflib/extras/fast_partial.py +++ b/waflib/extras/fast_partial.py @@ -17,7 +17,7 @@ def options(opt): opt.load('fast_partial') -Assuptions: +Assumptions: * Mostly for C/C++/Fortran targets with link tasks (object-only targets are not handled) * For full project builds: no --targets and no pruning from subfolders * The installation phase is ignored From d423dab8722ba81ebd58fba646ee90703241fa4e Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 10 Mar 2019 16:22:03 +0100 Subject: [PATCH 091/315] waf-2.0.15 --- waf-light | 2 +- waflib/Context.py | 6 +++--- wscript | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/waf-light b/waf-light index 5f4b30af92..08e42d4d58 100755 --- a/waf-light +++ b/waf-light @@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. import os, sys, inspect -VERSION="2.0.14" +VERSION="2.0.15" REVISION="x" GIT="x" INSTALL="x" diff --git a/waflib/Context.py b/waflib/Context.py index f6e9558f95..876ea46b92 100644 --- a/waflib/Context.py +++ b/waflib/Context.py @@ -11,13 +11,13 @@ import waflib.Node # the following 3 constants are updated on each new release (do not touch) -HEXVERSION=0x2000e00 +HEXVERSION=0x2000f00 """Constant updated on new releases""" -WAFVERSION="2.0.14" +WAFVERSION="2.0.15" """Constant updated on new releases""" -WAFREVISION="907519cab9c1c8c7e4f7d4e468ed6200b9250d58" +WAFREVISION="503db290b73ef738a495e0d116d6f8ee0b98dcc2" """Git revision when the waf version is updated""" ABI = 20 diff --git a/wscript b/wscript index 623be1adf2..cacb632f6a 100644 --- a/wscript +++ b/wscript @@ -11,7 +11,7 @@ To add a tool that does not exist in the folder compat15, pass an absolute path: from __future__ import with_statement -VERSION="2.0.14" +VERSION="2.0.15" APPNAME='waf' REVISION='' From 880be005762890f8f4209f47ab347f41185b831c Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 10 Mar 2019 16:44:06 +0100 Subject: [PATCH 092/315] waf-2.0.15 --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a7d9224a59..f27e73afc2 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,9 @@ Waf is a Python-based framework for configuring, compiling and installing applic * *Performance*: tasks are executed in parallel automatically, the startup time is meant to be fast (separation between configuration and build) * *Flexibility*: new commands and tasks can be added very easily through subclassing, bottlenecks for specific builds can be eliminated through dynamic method replacement * *Extensibility*: though many programming languages and compilers are already supported by default, many others are available as extensions - * *IDE support*: Eclipse, Visual Studio and Xcode project generators (waflib/extras/) + * *IDE support*: Eclipse, Visual Studio and Xcode project generators (`waflib/extras/`) * *Documentation*: the application is based on a robust model documented in [The Waf Book](https://waf.io/book/) and in the [API docs](https://waf.io/apidocs/) - * *Python compatibility*: cPython 2.5 to 3.4, Jython 2.5, IronPython, and Pypy + * *Python compatibility*: cPython 2.5 to 3.x, Jython 2.5, IronPython, and Pypy Waf is used in particular by innovative companies such as [Avalanche Studios](http://www.avalanchestudios.se) and by open-source projects such as [RTEMS](https://www.rtems.org/). Learn more about Waf by reading [The Waf Book](https://waf.io/book/). @@ -22,13 +22,15 @@ Download the project from our page on [waf.io](https://waf.io/) or from a mirror Python >= 2.6 is required to generate the waf script, and the resulting file can then run on Python 2.5. Just run: ```sh -$ ./waf-light configure build +$ python ./waf-light configure build ``` Or, if several python versions are installed: ```sh $ python3 ./waf-light configure build ``` +## CUSTOMIZATION + The Waf tools in waflib/extras are not added to the waf script. To add some of them, use the --tools switch. An absolute path can be passed if the module does not exist under the 'extras' folder: From b7be3f4f4a07dd50139175c44795600a1625dd75 Mon Sep 17 00:00:00 2001 From: fedepell Date: Tue, 12 Mar 2019 15:46:46 +0100 Subject: [PATCH 093/315] waf_unit_test: prevent error when dumping run to script and environment contains UTF-8 chars --- waflib/Tools/waf_unit_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/Tools/waf_unit_test.py b/waflib/Tools/waf_unit_test.py index 74d6c0561d..6ff6f72739 100644 --- a/waflib/Tools/waf_unit_test.py +++ b/waflib/Tools/waf_unit_test.py @@ -214,7 +214,7 @@ def exec_command(self, cmd, **kw): 'cmd': cmd } script_file = self.inputs[0].abspath() + '_run.py' - Utils.writef(script_file, script_code) + Utils.writef(script_file, script_code, encoding='utf-8') os.chmod(script_file, Utils.O755) if Logs.verbose > 1: Logs.info('Test debug file written as %r' % script_file) From c58ca8d1ed3cf1efd069a51f189e15fc46a88300 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Wed, 20 Mar 2019 01:25:48 +0000 Subject: [PATCH 094/315] Add color_msvc tool, which colorizes MSVC output like GCC does by default --- waflib/extras/color_msvc.py | 59 +++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 waflib/extras/color_msvc.py diff --git a/waflib/extras/color_msvc.py b/waflib/extras/color_msvc.py new file mode 100644 index 0000000000..60bacb7b24 --- /dev/null +++ b/waflib/extras/color_msvc.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +# encoding: utf-8 + +# Replaces the default formatter by one which understands MSVC output and colorizes it. +# Modified from color_gcc.py + +__author__ = __maintainer__ = "Alibek Omarov " +__copyright__ = "Alibek Omarov, 2019" + +import sys +from waflib import Logs + +class ColorMSVCFormatter(Logs.formatter): + def __init__(self, colors): + self.colors = colors + Logs.formatter.__init__(self) + + def parseMessage(self, line, color): + # Split messaage from 'disk:filepath: type: message' + arr = line.split(':', 3) + if len(arr) < 4: + return line + + colored = self.colors.BOLD + arr[0] + ':' + arr[1] + ':' + self.colors.NORMAL + colored += color + arr[2] + ':' + self.colors.NORMAL + colored += arr[3] + return colored + + def format(self, rec): + frame = sys._getframe() + while frame: + func = frame.f_code.co_name + if func == 'exec_command': + cmd = frame.f_locals.get('cmd') + if isinstance(cmd, list): + # Fix file case, it may be CL.EXE or cl.exe + argv0 = cmd[0].lower() + if 'cl.exe' in argv0: + lines = [] + # This will not work with "localized" versions + # of MSVC + for line in rec.msg.splitlines(): + if ': warning ' in line: + lines.append(self.parseMessage(line, self.colors.YELLOW)) + elif ': error ' in line: + lines.append(self.parseMessage(line, self.colors.RED)) + elif ': fatal error ' in line: + lines.append(self.parseMessage(line, self.colors.RED + self.colors.BOLD)) + elif ': note: ' in line: + lines.append(self.parseMessage(line, self.colors.CYAN)) + else: + lines.append(line) + rec.msg = "\n".join(lines) + frame = frame.f_back + return Logs.formatter.format(self, rec) + +def options(opt): + Logs.log.handlers[0].setFormatter(ColorMSVCFormatter(Logs.colors)) + From 77961db3b2283af7a46ae413fa4bc5d8cba7f348 Mon Sep 17 00:00:00 2001 From: William Light Date: Sun, 31 Mar 2019 19:26:11 +0200 Subject: [PATCH 095/315] extras/syms: fix symbol regex on mac-o binaries mac-o symbols are prefixed with an underscore. when specifying multiple sub-regexes (e.g. 'sym1|sym2|sym3'), only the first will be matched (since the expansion turns into '(?P_?sym1|sym2|sym3)'). here, this is remedied by wrapping the symbol regex in a paren group. --- waflib/extras/syms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/extras/syms.py b/waflib/extras/syms.py index dfa005930e..562f708e1e 100644 --- a/waflib/extras/syms.py +++ b/waflib/extras/syms.py @@ -31,7 +31,7 @@ def run(self): if self.env.DEST_BINFMT == 'pe': #gcc uses nm, and has a preceding _ on windows re_nm = re.compile(r'(T|D)\s+_(?P%s)\b' % reg) elif self.env.DEST_BINFMT=='mac-o': - re_nm=re.compile(r'(T|D)\s+(?P_?%s)\b' % reg) + re_nm=re.compile(r'(T|D)\s+(?P_?(%s))\b' % reg) else: re_nm = re.compile(r'(T|D)\s+(?P%s)\b' % reg) cmd = (self.env.NM or ['nm']) + ['-g', obj.abspath()] From d97d574019667887a523479777f77a16c09cf51e Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Mon, 15 Apr 2019 21:17:46 +0200 Subject: [PATCH 096/315] Python 2 encoding enhancements - Issue 2230 --- waflib/Logs.py | 5 ++++- waflib/Utils.py | 6 ++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/waflib/Logs.py b/waflib/Logs.py index 11dc34f356..298411db51 100644 --- a/waflib/Logs.py +++ b/waflib/Logs.py @@ -237,7 +237,10 @@ def format(self, rec): if rec.levelno >= logging.INFO: # the goal of this is to format without the leading "Logs, hour" prefix if rec.args: - return msg % rec.args + try: + return msg % rec.args + except UnicodeDecodeError: + return msg.encode('utf-8') % rec.args return msg rec.msg = msg diff --git a/waflib/Utils.py b/waflib/Utils.py index 4b808a85e0..0a069b12d5 100644 --- a/waflib/Utils.py +++ b/waflib/Utils.py @@ -604,6 +604,12 @@ def h_list(lst): """ return md5(repr(lst).encode()).digest() +if sys.hexversion < 0x3000000: + def h_list_python2(lst): + return md5(repr(lst)).digest() + h_list_python2.__doc__ = h_list.__doc__ + h_list = h_list_python2 + def h_fun(fun): """ Hash functions From 62ce16f030ccf0d1b49d0bcbd93902cde51f9736 Mon Sep 17 00:00:00 2001 From: James Harris Date: Thu, 8 Mar 2018 14:49:55 -0600 Subject: [PATCH 097/315] msvc: add pdb_install_task with /DEBUG:* flags Currently PDBs are only installed if the /DEBUG flag appears in the current toolchain's LINKFLAGS attribute. This patch expands support so that /DEBUG:FULL and /DEBUG:FASTLINK also cause PDBs to be installed. --- waflib/Tools/msvc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/Tools/msvc.py b/waflib/Tools/msvc.py index ff58449d0f..f169c7f441 100644 --- a/waflib/Tools/msvc.py +++ b/waflib/Tools/msvc.py @@ -969,7 +969,7 @@ def build(bld): if not is_static: for f in self.env.LINKFLAGS: d = f.lower() - if d[1:] == 'debug': + if d[1:] in ('debug', 'debug:full', 'debug:fastlink'): pdbnode = self.link_task.outputs[0].change_ext('.pdb') self.link_task.outputs.append(pdbnode) From 2656cc630288c63da689a6c14927dce8e4d9bbac Mon Sep 17 00:00:00 2001 From: Lucian Teodorescu Date: Mon, 25 Jul 2016 17:08:25 +0300 Subject: [PATCH 098/315] doxygen: maintain order of lines in doxyfile The order of the lines in a doxyfile are important. This patch uses an ordered dictionary to keep the keys of the doxyfile in the same order. This is particularly important for doxyfiles that contain @INCLUDE lines. In such cases, if the dictionary is not ordered, the @INCLUDE line can end up in the middle of the generated doxyfile and thus override all entries that were seen before it. --- waflib/extras/doxygen.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/waflib/extras/doxygen.py b/waflib/extras/doxygen.py index 28f56e9c7d..423d845502 100644 --- a/waflib/extras/doxygen.py +++ b/waflib/extras/doxygen.py @@ -27,6 +27,7 @@ def build(bld): """ import os, os.path, re +from collections import OrderedDict from waflib import Task, Utils, Node from waflib.TaskGen import feature @@ -40,7 +41,13 @@ def build(bld): re_rl = re.compile('\\\\\r*\n', re.MULTILINE) re_nl = re.compile('\r*\n', re.M) def parse_doxy(txt): - tbl = {} + ''' + Parses a doxygen file. + Returns an ordered dictionary. We cannot return a default dictionary, as the + order in which the entries are reported does matter, especially for the + '@INCLUDE' lines. + ''' + tbl = OrderedDict() txt = re_rl.sub('', txt) lines = re_nl.split(txt) for x in lines: From cd169d1d436fb9daf6bfd020c301fbab1d6458c3 Mon Sep 17 00:00:00 2001 From: Kevin Markussen Date: Mon, 14 May 2018 09:21:30 -0500 Subject: [PATCH 099/315] msvcdeps: fix 'WafError' AttributeError This patch corrects an error in the exec_response_command exception handler which always assumed that the execution's stdout would be bound to the the WafError exception object. However, this assumption is only true when the execution completes with a non-zero status code. For other exceptions, the stdout attribute is not bound. Now, when stdout is not available, the WafError msg will be used instead. --- waflib/extras/msvcdeps.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/waflib/extras/msvcdeps.py b/waflib/extras/msvcdeps.py index fc1ecd4d08..b9ec25f4fa 100644 --- a/waflib/extras/msvcdeps.py +++ b/waflib/extras/msvcdeps.py @@ -213,8 +213,12 @@ def exec_command(self, cmd, **kw): raw_out = self.generator.bld.cmd_and_log(cmd + ['@' + tmp], **kw) ret = 0 except Errors.WafError as e: - raw_out = e.stdout - ret = e.returncode + # Use e.msg if e.stdout is not set + raw_out = getattr(e, 'stdout', e.msg) + + # Return non-zero error code even if we didn't + # get one from the exception object + ret = getattr(e, 'returncode', 1) for line in raw_out.splitlines(): if line.startswith(INCLUDE_PATTERN): From 9ea7b5001dc683312b0926aa71b17ef92079149e Mon Sep 17 00:00:00 2001 From: Robert Herbst Date: Thu, 18 Oct 2018 16:41:26 -0500 Subject: [PATCH 100/315] javaw: make javadoc optional Make javadoc optional to support builds on platforms that don't include javadoc in their Java distribution. --- waflib/Tools/javaw.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/Tools/javaw.py b/waflib/Tools/javaw.py index 9daed395b3..a84c371df9 100644 --- a/waflib/Tools/javaw.py +++ b/waflib/Tools/javaw.py @@ -471,7 +471,7 @@ def configure(self): self.env.JAVA_HOME = [self.environ['JAVA_HOME']] for x in 'javac java jar javadoc'.split(): - self.find_program(x, var=x.upper(), path_list=java_path) + self.find_program(x, var=x.upper(), path_list=java_path, mandatory=(x not in ('javadoc'))) if 'CLASSPATH' in self.environ: v.CLASSPATH = self.environ['CLASSPATH'] From d8a55f96eda2087f7bc8c1a5785d234eba6524a9 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Fri, 19 Apr 2019 18:45:43 +0200 Subject: [PATCH 101/315] Describe how to load md5_tstamp - Issue 2231 --- waflib/Tools/md5_tstamp.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/waflib/Tools/md5_tstamp.py b/waflib/Tools/md5_tstamp.py index 2a5879251d..d1569fa9ec 100644 --- a/waflib/Tools/md5_tstamp.py +++ b/waflib/Tools/md5_tstamp.py @@ -2,7 +2,10 @@ # encoding: utf-8 """ -Re-calculate md5 hashes of files only when the file time have changed. +Re-calculate md5 hashes of files only when the file time have changed:: + + def options(opt): + opt.load('md5_tstamp') The hashes can also reflect either the file contents (STRONGEST=True) or the file time and file size. From 95255c65b1343e170c46f74f1dc3a7b03c678d70 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Mon, 22 Apr 2019 00:14:17 +0200 Subject: [PATCH 102/315] Workaround for Issue 2232 --- waflib/Runner.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/waflib/Runner.py b/waflib/Runner.py index 5d27669871..91d55479e2 100644 --- a/waflib/Runner.py +++ b/waflib/Runner.py @@ -337,11 +337,16 @@ def try_unfreeze(x): if hasattr(tsk, 'semaphore'): sem = tsk.semaphore - sem.release(tsk) - while sem.waiting and not sem.is_locked(): - # take a frozen task, make it ready to run - x = sem.waiting.pop() - self._add_task(x) + try: + sem.release(tsk) + except KeyError: + # TODO + pass + else: + while sem.waiting and not sem.is_locked(): + # take a frozen task, make it ready to run + x = sem.waiting.pop() + self._add_task(x) def get_out(self): """ From 1fdb091e1451653858bd7bc9f9b3f6dc937e12c0 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Tue, 23 Apr 2019 07:13:02 +0200 Subject: [PATCH 103/315] Node.listdir outputs are already sorted, do not sort it again in Node.ant_glob --- waflib/Node.py | 1 - 1 file changed, 1 deletion(-) diff --git a/waflib/Node.py b/waflib/Node.py index 237d75e463..11615a8572 100644 --- a/waflib/Node.py +++ b/waflib/Node.py @@ -606,7 +606,6 @@ def ant_iter(self, accept=None, maxdepth=25, pats=[], dir=False, src=True, remov :rtype: iterator """ dircont = self.listdir() - dircont.sort() try: lst = set(self.children.keys()) From 9c11d4339f74e85c14067e28db8168666a9bc5b9 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Tue, 23 Apr 2019 07:39:19 +0200 Subject: [PATCH 104/315] When creating the waf script, assume that the 'extras' folder only contains Python files Files are also listed in a static arbitrary order. --- wscript | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/wscript b/wscript index cacb632f6a..2d83ab08b4 100644 --- a/wscript +++ b/wscript @@ -258,20 +258,19 @@ def create_waf(self, *k, **kw): for x in Options.options.coretools.split(','): coretools.append(x + '.py') - for d in '. Tools extras'.split(): - dd = os.path.join('waflib', d) - for k in os.listdir(dd): - if k == '__init__.py': - files.append(os.path.normpath(os.path.join(dd, k))) + up_node = self.generator.bld.path + for node in up_node.find_dir('waflib').ant_glob(incl=['*.py', 'Tools/*.py', 'extras/*.py']): + relpath = node.path_from(up_node) + if node.name == '__init__.py': + files.append(relpath) + continue + if node.parent.name == 'Tools' and Options.options.coretools != 'default': + if node.name not in coretools: continue - if d == 'Tools' and Options.options.coretools != 'default': - if not k in coretools: - continue - if d == 'extras': - if not k in add3rdparty: - continue - if k.endswith('.py'): - files.append(os.path.normpath(os.path.join(dd, k))) + if node.parent.name == 'extras': + if node.name not in add3rdparty: + continue + files.append(relpath) if Options.options.namesfrom: with tarfile.open(Options.options.namesfrom) as tar: From 2986830a6553a878470188c1377504b60c5db0bb Mon Sep 17 00:00:00 2001 From: fedepell Date: Thu, 25 Apr 2019 11:53:00 +0200 Subject: [PATCH 105/315] pyqt5: add option to enable explicitly PyQt5 bindings Previously one could explicitly state to use PySide2 or PyQt4 but not PyQt5 which was picked just by default. In this way the option can override local configurations and also this prevents to have mixed tools versions if we are sure we need PyQt5. --- waflib/extras/pyqt5.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/waflib/extras/pyqt5.py b/waflib/extras/pyqt5.py index 80f43b8872..7121994558 100644 --- a/waflib/extras/pyqt5.py +++ b/waflib/extras/pyqt5.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # encoding: utf-8 -# Federico Pellegrin, 2016-2018 (fedepell) adapted for Python +# Federico Pellegrin, 2016-2019 (fedepell) adapted for Python """ This tool helps with finding Python Qt5 tools and libraries, @@ -211,7 +211,11 @@ def find_pyqt5_binaries(self): """ env = self.env - if getattr(Options.options, 'want_pyside2', True): + if getattr(Options.options, 'want_pyqt5', True): + self.find_program(['pyuic5'], var='QT_PYUIC') + self.find_program(['pyrcc5'], var='QT_PYRCC') + self.find_program(['pylupdate5'], var='QT_PYLUPDATE') + elif getattr(Options.options, 'want_pyside2', True): self.find_program(['pyside2-uic'], var='QT_PYUIC') self.find_program(['pyside2-rcc'], var='QT_PYRCC') self.find_program(['pyside2-lupdate'], var='QT_PYLUPDATE') @@ -237,5 +241,6 @@ def options(opt): Command-line options """ pyqt5opt=opt.add_option_group("Python QT5 Options") - pyqt5opt.add_option('--pyqt5-pyside2', action='store_true', default=False, dest='want_pyside2', help='use pyside2 bindings as python QT5 bindings (default PyQt5 is searched first, PySide2 after)') + pyqt5opt.add_option('--pyqt5-pyqt5', action='store_true', default=False, dest='want_pyqt5', help='use PyQt5 bindings as python QT5 bindings (default PyQt5 is searched first, PySide2 after, PyQt4 last)') + pyqt5opt.add_option('--pyqt5-pyside2', action='store_true', default=False, dest='want_pyside2', help='use pyside2 bindings as python QT5 bindings (default PyQt5 is searched first, PySide2 after, PyQt4 last)') pyqt5opt.add_option('--pyqt5-pyqt4', action='store_true', default=False, dest='want_pyqt4', help='use PyQt4 bindings as python QT5 bindings (default PyQt5 is searched first, PySide2 after, PyQt4 last)') From 00abb9e593e8f56a9de32deaa88b731e2c266b72 Mon Sep 17 00:00:00 2001 From: fedepell Date: Thu, 25 Apr 2019 11:55:31 +0200 Subject: [PATCH 106/315] pyqt5: correct the spelling to PySide2 in all occourences --- waflib/extras/pyqt5.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/waflib/extras/pyqt5.py b/waflib/extras/pyqt5.py index 7121994558..5a63d0ded7 100644 --- a/waflib/extras/pyqt5.py +++ b/waflib/extras/pyqt5.py @@ -30,7 +30,7 @@ def build(bld): Add into the sources list also the qrc resources files or ui5 definition files and they will be translated into python code -with the system tools (PyQt5, pyside2, PyQt4 are searched in this +with the system tools (PyQt5, PySide2, PyQt4 are searched in this order) and then compiled """ @@ -207,7 +207,7 @@ def configure(self): @conf def find_pyqt5_binaries(self): """ - Detects PyQt5 or pyside2 programs such as pyuic5/pyside2-uic, pyrcc5/pyside2-rcc + Detects PyQt5 or PySide2 programs such as pyuic5/pyside2-uic, pyrcc5/pyside2-rcc """ env = self.env @@ -242,5 +242,5 @@ def options(opt): """ pyqt5opt=opt.add_option_group("Python QT5 Options") pyqt5opt.add_option('--pyqt5-pyqt5', action='store_true', default=False, dest='want_pyqt5', help='use PyQt5 bindings as python QT5 bindings (default PyQt5 is searched first, PySide2 after, PyQt4 last)') - pyqt5opt.add_option('--pyqt5-pyside2', action='store_true', default=False, dest='want_pyside2', help='use pyside2 bindings as python QT5 bindings (default PyQt5 is searched first, PySide2 after, PyQt4 last)') + pyqt5opt.add_option('--pyqt5-pyside2', action='store_true', default=False, dest='want_pyside2', help='use PySide2 bindings as python QT5 bindings (default PyQt5 is searched first, PySide2 after, PyQt4 last)') pyqt5opt.add_option('--pyqt5-pyqt4', action='store_true', default=False, dest='want_pyqt4', help='use PyQt4 bindings as python QT5 bindings (default PyQt5 is searched first, PySide2 after, PyQt4 last)') From 80ea3fd25ec129b767cbee4bacfc59cd23e0bd5c Mon Sep 17 00:00:00 2001 From: fedepell Date: Thu, 25 Apr 2019 11:56:08 +0200 Subject: [PATCH 107/315] pyqt5: bugfix, check the correct variable for RCC executable --- waflib/extras/pyqt5.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/extras/pyqt5.py b/waflib/extras/pyqt5.py index 5a63d0ded7..9c941764cc 100644 --- a/waflib/extras/pyqt5.py +++ b/waflib/extras/pyqt5.py @@ -231,7 +231,7 @@ def find_pyqt5_binaries(self): if not env.QT_PYUIC: self.fatal('cannot find the uic compiler for python for qt5') - if not env.QT_PYUIC: + if not env.QT_PYRCC: self.fatal('cannot find the rcc compiler for python for qt5') self.find_program(['lrelease-qt5', 'lrelease'], var='QT_LRELEASE') From 2d74942022bbcbdec9765590a0c4764223665032 Mon Sep 17 00:00:00 2001 From: fedepell Date: Mon, 6 May 2019 08:17:20 +0200 Subject: [PATCH 108/315] protoc: make sure output directory exists for java --- waflib/extras/protoc.py | 1 + 1 file changed, 1 insertion(+) diff --git a/waflib/extras/protoc.py b/waflib/extras/protoc.py index 839c510b94..4a519cc6a0 100644 --- a/waflib/extras/protoc.py +++ b/waflib/extras/protoc.py @@ -175,6 +175,7 @@ def process_protoc(self, node): self.javac_task.srcdir.append(node.parent.get_bld()) protoc_flags.append('--java_out=%s' % node.parent.get_bld().bldpath()) + node.parent.get_bld().mkdir() tsk = self.create_task('protoc', node, out_nodes) tsk.env.append_value('PROTOC_FLAGS', protoc_flags) From c74522eee98731ef210746026b0827dd4304b3d4 Mon Sep 17 00:00:00 2001 From: fedepell Date: Tue, 7 May 2019 14:42:39 +0200 Subject: [PATCH 109/315] javaw: set dependency between javac task and use-d generated jars nodes --- demos/java/cats/src/org/example/Cat.java | 3 ++- waflib/Tools/javaw.py | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/demos/java/cats/src/org/example/Cat.java b/demos/java/cats/src/org/example/Cat.java index bf937dc9ad..b01788b496 100644 --- a/demos/java/cats/src/org/example/Cat.java +++ b/demos/java/cats/src/org/example/Cat.java @@ -6,9 +6,10 @@ class Cat extends Animal { public String sound() { + // Use base class just to be able to trigger possible rebuilds based on base class change + String base = super.sound(); return "Meow!"; } - } diff --git a/waflib/Tools/javaw.py b/waflib/Tools/javaw.py index a84c371df9..faa4a04c14 100644 --- a/waflib/Tools/javaw.py +++ b/waflib/Tools/javaw.py @@ -238,6 +238,7 @@ def use_javac_files(self): if hasattr(y, 'jar_task'): self.use_lst.append(y.jar_task.outputs[0].abspath()) self.javac_task.set_run_after(y.jar_task) + self.javac_task.dep_nodes.extend(y.jar_task.outputs) else: for tsk in y.tasks: self.javac_task.set_run_after(tsk) From aae615ce0f9a1e81fbf1ee3393615deefe1e1ad3 Mon Sep 17 00:00:00 2001 From: Federico Pellegrin Date: Wed, 8 May 2019 05:06:29 +0200 Subject: [PATCH 110/315] javaw: also when using non-jar CLASSPATH has to be populated to use-d tasks. In this case we point to the directory instead of the JAR file --- waflib/Tools/javaw.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/waflib/Tools/javaw.py b/waflib/Tools/javaw.py index faa4a04c14..adc92a4930 100644 --- a/waflib/Tools/javaw.py +++ b/waflib/Tools/javaw.py @@ -212,6 +212,8 @@ def java_use_rec(self, name, **kw): # is already guaranteed by ordering done between the single tasks if hasattr(y, 'jar_task'): self.use_lst.append(y.jar_task.outputs[0].abspath()) + else: + self.use_lst.append(y.outdir.abspath()) for x in self.to_list(getattr(y, 'use', [])): self.java_use_rec(x) @@ -240,6 +242,7 @@ def use_javac_files(self): self.javac_task.set_run_after(y.jar_task) self.javac_task.dep_nodes.extend(y.jar_task.outputs) else: + self.use_lst.append(y.outdir.abspath()) for tsk in y.tasks: self.javac_task.set_run_after(tsk) From ffef98af65b95a90601c2de6852493bed81e9fe3 Mon Sep 17 00:00:00 2001 From: Federico Pellegrin Date: Wed, 8 May 2019 05:18:31 +0200 Subject: [PATCH 111/315] javaw: add node dependencies for non-jar tasks to all generated class files --- waflib/Tools/javaw.py | 1 + 1 file changed, 1 insertion(+) diff --git a/waflib/Tools/javaw.py b/waflib/Tools/javaw.py index adc92a4930..c746556f6f 100644 --- a/waflib/Tools/javaw.py +++ b/waflib/Tools/javaw.py @@ -245,6 +245,7 @@ def use_javac_files(self): self.use_lst.append(y.outdir.abspath()) for tsk in y.tasks: self.javac_task.set_run_after(tsk) + self.javac_task.dep_nodes.extend([x for x in y.outdir.ant_glob(JAR_RE, remove=False, quiet=True)]) # If recurse use scan is enabled recursively add use attribute for each used one if getattr(self, 'recurse_use', False) or self.bld.env.RECURSE_JAVA: From 3705946c9a84ad372c3473211b19049676c38844 Mon Sep 17 00:00:00 2001 From: Michael Vincent Date: Mon, 29 Apr 2019 16:37:22 -0500 Subject: [PATCH 112/315] Node: escape parentheses in ant_glob() ant_matcher() converts an ANT glob pattern to an equivalent regex pattern. This commit adds support for escaping parenthesis in the input pattern so they don't end up being treated as a regex capture group. Also add a unit test to verify ant_glob()'s ability to handle special characters in the input pattern. --- tests/apis/wscript | 7 +++++-- waflib/Node.py | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/apis/wscript b/tests/apis/wscript index afeeeb8d54..91d7998dbf 100755 --- a/tests/apis/wscript +++ b/tests/apis/wscript @@ -143,9 +143,12 @@ def test(ctx): create('d.TXT') nd2 = bld.srcnode.make_node('d.TXT') nd2.write("test") + nd3 = bld.srcnode.make_node('e.e+(e).txt') + nd3.write("test") - tt("ant_glob ->", len(bld.srcnode.ant_glob('*.txt', flat=False)), 1) - tt("ant_glob (icase) ->", len(bld.srcnode.ant_glob('*.txt', flat=False, ignorecase=True)), 2) + tt("ant_glob ->", len(bld.srcnode.ant_glob('*.txt', flat=False)), 2) + tt("ant_glob (icase) ->", len(bld.srcnode.ant_glob('*.txt', flat=False, ignorecase=True)), 3) + tt("ant_glob (special) ->", len(bld.srcnode.ant_glob('e.e+(e).txt', flat=False)), 1) #print("ant_glob src ->", bld.srcnode.ant_glob('*.txt')) def abspath(self): diff --git a/waflib/Node.py b/waflib/Node.py index 11615a8572..f6ac261536 100644 --- a/waflib/Node.py +++ b/waflib/Node.py @@ -73,7 +73,7 @@ def ant_matcher(s, ignorecase): if k == '**': accu.append(k) else: - k = k.replace('.', '[.]').replace('*','.*').replace('?', '.').replace('+', '\\+') + k = k.replace('.', '[.]').replace('*','.*').replace('?', '.').replace('+', '\\+').replace('(', '\\(').replace(')', '\\)') k = '^%s$' % k try: exp = re.compile(k, flags=reflags) From 072ff0cfdb77721385c8cbbeedbdf2830a4edda2 Mon Sep 17 00:00:00 2001 From: Michael Vincent Date: Thu, 25 Apr 2019 16:28:19 -0500 Subject: [PATCH 113/315] msvcdeps: refactor cache lock Rework how msvcdeps' cached_nodes lock is used so acquiring the lock is only necessary on a cache miss. Also use a "with" context manager to simplify management of the lock lifecycle. --- waflib/extras/msvcdeps.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/waflib/extras/msvcdeps.py b/waflib/extras/msvcdeps.py index b9ec25f4fa..2c5577d309 100644 --- a/waflib/extras/msvcdeps.py +++ b/waflib/extras/msvcdeps.py @@ -64,14 +64,17 @@ def path_to_node(base_node, path, cached_nodes): else: # Not hashable, assume it is a list and join into a string node_lookup_key = (base_node, os.path.sep.join(path)) + try: - lock.acquire() node = cached_nodes[node_lookup_key] except KeyError: - node = base_node.find_resource(path) - cached_nodes[node_lookup_key] = node - finally: - lock.release() + # retry with lock on cache miss + with lock: + try: + node = cached_nodes[node_lookup_key] + except KeyError: + node = cached_nodes[node_lookup_key] = base_node.find_resource(path) + return node def post_run(self): From 40b394e1066bedf5833169726db670f2f49bfb6c Mon Sep 17 00:00:00 2001 From: Michael Vincent Date: Mon, 29 Apr 2019 17:03:57 -0500 Subject: [PATCH 114/315] msvcdeps: remove path_to_node()'s path list support Make path_to_node() only accept a path as a string instead of also as a list. That requires joining the list of path components in the relative path case before calling path_to_node(). Also use path.pop(0) to remove the first path component instead of copying the remainder of the path using a slice operator. --- waflib/extras/msvcdeps.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/waflib/extras/msvcdeps.py b/waflib/extras/msvcdeps.py index 2c5577d309..2c0bb2f3b1 100644 --- a/waflib/extras/msvcdeps.py +++ b/waflib/extras/msvcdeps.py @@ -56,14 +56,12 @@ def apply_msvcdeps_flags(taskgen): taskgen.msvcdeps_drive_lowercase = drive == drive.lower() def path_to_node(base_node, path, cached_nodes): - # Take the base node and the path and return a node - # Results are cached because searching the node tree is expensive - # The following code is executed by threads, it is not safe, so a lock is needed... - if getattr(path, '__hash__'): - node_lookup_key = (base_node, path) - else: - # Not hashable, assume it is a list and join into a string - node_lookup_key = (base_node, os.path.sep.join(path)) + ''' + Take the base node and the path and return a node + Results are cached because searching the node tree is expensive + The following code is executed by threads, it is not safe, so a lock is needed... + ''' + node_lookup_key = (base_node, path) try: node = cached_nodes[node_lookup_key] @@ -117,12 +115,13 @@ def post_run(self): path = drive.upper() + tail node = path_to_node(bld.root, path, cached_nodes) else: + # when calling find_resource, make sure the path does not begin with '..' base_node = bld.bldnode - # when calling find_resource, make sure the path does not begin by '..' path = [k for k in Utils.split_path(path) if k and k != '.'] while path[0] == '..': - path = path[1:] + path.pop(0) base_node = base_node.parent + path = os.sep.join(path) node = path_to_node(base_node, path, cached_nodes) From 07f5ff58120d39ce7c91ce617d898b23434acf67 Mon Sep 17 00:00:00 2001 From: Michael Vincent Date: Mon, 29 Apr 2019 17:09:54 -0500 Subject: [PATCH 115/315] msvcdeps: use ant_glob() to get correct case of include paths When using msvcdeps, header dependencies are not detected reliably for generated source files. The root cause is a bug in versions of MSVC prior to VS2019 16.0 in which it emits lower-case path prefixes when resolving include paths relative to the containing file. Absolute paths and paths relative to include directories passed in the MSVC command line are, in contrast, case-correct. Such a file-relative include directive with an incorrect lower-case prefix derails waf's node hash signature handling and fails silently. This change uses ant_glob() with the ignorecase keyword argument to find the file on the filesystem with the correct case. The prior case-correction code has been superseded and was removed. See the following Visual Studio bug report for details on the issue: https://developercommunity.visualstudio.com/content/problem/233871/showincludes-lowercases-some-path-segments.html --- waflib/extras/msvcdeps.py | 32 +++++++++----------------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/waflib/extras/msvcdeps.py b/waflib/extras/msvcdeps.py index 2c0bb2f3b1..54de25d384 100644 --- a/waflib/extras/msvcdeps.py +++ b/waflib/extras/msvcdeps.py @@ -50,17 +50,19 @@ def apply_msvcdeps_flags(taskgen): if taskgen.env.get_flat(flag).find(PREPROCESSOR_FLAG) < 0: taskgen.env.append_value(flag, PREPROCESSOR_FLAG) - # Figure out what casing conventions the user's shell used when - # launching Waf - (drive, _) = os.path.splitdrive(taskgen.bld.srcnode.abspath()) - taskgen.msvcdeps_drive_lowercase = drive == drive.lower() - def path_to_node(base_node, path, cached_nodes): ''' Take the base node and the path and return a node Results are cached because searching the node tree is expensive The following code is executed by threads, it is not safe, so a lock is needed... ''' + # normalize the path because ant_glob() does not understand + # parent path components (..) + path = os.path.normpath(path) + + # normalize the path case to increase likelihood of a cache hit + path = os.path.normcase(path) + node_lookup_key = (base_node, path) try: @@ -71,7 +73,8 @@ def path_to_node(base_node, path, cached_nodes): try: node = cached_nodes[node_lookup_key] except KeyError: - node = cached_nodes[node_lookup_key] = base_node.find_resource(path) + node_list = base_node.ant_glob([path], ignorecase=True, remove=False, quiet=True) + node = cached_nodes[node_lookup_key] = node_list[0] if node_list else None return node @@ -87,11 +90,6 @@ def post_run(self): unresolved_names = [] resolved_nodes = [] - lowercase = self.generator.msvcdeps_drive_lowercase - correct_case_path = bld.path.abspath() - correct_case_path_len = len(correct_case_path) - correct_case_path_norm = os.path.normcase(correct_case_path) - # Dynamically bind to the cache try: cached_nodes = bld.cached_nodes @@ -101,18 +99,6 @@ def post_run(self): for path in self.msvcdeps_paths: node = None if os.path.isabs(path): - # Force drive letter to match conventions of main source tree - drive, tail = os.path.splitdrive(path) - - if os.path.normcase(path[:correct_case_path_len]) == correct_case_path_norm: - # Path is in the sandbox, force it to be correct. MSVC sometimes returns a lowercase path. - path = correct_case_path + path[correct_case_path_len:] - else: - # Check the drive letter - if lowercase and (drive != drive.lower()): - path = drive.lower() + tail - elif (not lowercase) and (drive != drive.upper()): - path = drive.upper() + tail node = path_to_node(bld.root, path, cached_nodes) else: # when calling find_resource, make sure the path does not begin with '..' From 6b6251a9be67200d7399bd39a6440512c263b7bb Mon Sep 17 00:00:00 2001 From: Dragoon Date: Thu, 9 May 2019 23:18:15 +0200 Subject: [PATCH 116/315] Better support for cross compiling with Clang --- waflib/extras/clang_cross.py | 92 ++++++++++++++++++++++ waflib/extras/clang_cross_common.py | 113 ++++++++++++++++++++++++++++ waflib/extras/clangxx_cross.py | 106 ++++++++++++++++++++++++++ 3 files changed, 311 insertions(+) create mode 100644 waflib/extras/clang_cross.py create mode 100644 waflib/extras/clang_cross_common.py create mode 100644 waflib/extras/clangxx_cross.py diff --git a/waflib/extras/clang_cross.py b/waflib/extras/clang_cross.py new file mode 100644 index 0000000000..1b51e2886c --- /dev/null +++ b/waflib/extras/clang_cross.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Krzysztof Kosiński 2014 +# DragoonX6 2018 + +""" +Detect the Clang C compiler +This version is an attempt at supporting the -target and -sysroot flag of Clang. +""" + +from waflib.Tools import ccroot, ar, gcc +from waflib.Configure import conf +import waflib.Context +import waflib.extras.clang_cross_common + +def options(opt): + """ + Target triplet for clang:: + $ waf configure --clang-target-triple=x86_64-pc-linux-gnu + """ + cc_compiler_opts = opt.add_option_group('Configuration options') + cc_compiler_opts.add_option('--clang-target-triple', default=None, + help='Target triple for clang', + dest='clang_target_triple') + cc_compiler_opts.add_option('--clang-sysroot', default=None, + help='Sysroot for clang', + dest='clang_sysroot') + +@conf +def find_clang(conf): + """ + Finds the program clang and executes it to ensure it really is clang + """ + + import os + + cc = conf.find_program('clang', var='CC') + + if conf.options.clang_target_triple != None: + conf.env.append_value('CC', ['-target', conf.options.clang_target_triple]) + + if conf.options.clang_sysroot != None: + sysroot = str() + + if os.path.isabs(conf.options.clang_sysroot): + sysroot = conf.options.clang_sysroot + else: + sysroot = os.path.normpath(os.path.join(os.getcwd(), conf.options.clang_sysroot)) + + conf.env.append_value('CC', ['--sysroot', sysroot]) + + conf.get_cc_version(cc, clang=True) + conf.env.CC_NAME = 'clang' + +@conf +def clang_modifier_x86_64_w64_mingw32(conf): + conf.gcc_modifier_win32() + +@conf +def clang_modifier_i386_w64_mingw32(conf): + conf.gcc_modifier_win32() + +@conf +def clang_modifier_x86_64_windows_msvc(conf): + conf.clang_modifier_msvc() + + # Allow the user to override any flags if they so desire. + clang_modifier_user_func = getattr(conf, 'clang_modifier_x86_64_windows_msvc_user', None) + if clang_modifier_user_func: + clang_modifier_user_func() + +@conf +def clang_modifier_i386_windows_msvc(conf): + conf.clang_modifier_msvc() + + # Allow the user to override any flags if they so desire. + clang_modifier_user_func = getattr(conf, 'clang_modifier_i386_windows_msvc_user', None) + if clang_modifier_user_func: + clang_modifier_user_func() + +def configure(conf): + conf.find_clang() + conf.find_program(['llvm-ar', 'ar'], var='AR') + conf.find_ar() + conf.gcc_common_flags() + # Allow the user to provide flags for the target platform. + conf.gcc_modifier_platform() + # And allow more fine grained control based on the compiler's triplet. + conf.clang_modifier_target_triple() + conf.cc_load_tools() + conf.cc_add_flags() + conf.link_add_flags() diff --git a/waflib/extras/clang_cross_common.py b/waflib/extras/clang_cross_common.py new file mode 100644 index 0000000000..b76a070065 --- /dev/null +++ b/waflib/extras/clang_cross_common.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python +# encoding: utf-8 +# DragoonX6 2018 + +""" +Common routines for cross_clang.py and cross_clangxx.py +""" + +from waflib.Configure import conf +import waflib.Context + +def normalize_target_triple(target_triple): + target_triple = target_triple[:-1] + normalized_triple = target_triple.replace('--', '-unknown-') + + if normalized_triple.startswith('-'): + normalized_triple = 'unknown' + normalized_triple + + if normalized_triple.endswith('-'): + normalized_triple += 'unknown' + + # Normalize MinGW builds to *arch*-w64-mingw32 + if normalized_triple.endswith('windows-gnu'): + normalized_triple = normalized_triple[:normalized_triple.index('-')] + '-w64-mingw32' + + # Strip the vendor when doing msvc builds, since it's unused anyway. + if normalized_triple.endswith('windows-msvc'): + normalized_triple = normalized_triple[:normalized_triple.index('-')] + '-windows-msvc' + + return normalized_triple.replace('-', '_') + +@conf +def clang_modifier_msvc(conf): + import os + + """ + Really basic setup to use clang in msvc mode. + We actually don't really want to do a lot, even though clang is msvc compatible + in this mode, that doesn't mean we're actually using msvc. + It's probably the best to leave it to the user, we can assume msvc mode if the user + uses the clang-cl frontend, but this module only concerns itself with the gcc-like frontend. + """ + v = conf.env + v.cprogram_PATTERN = '%s.exe' + + v.cshlib_PATTERN = '%s.dll' + v.implib_PATTERN = '%s.lib' + v.IMPLIB_ST = '-Wl,-IMPLIB:%s' + v.SHLIB_MARKER = [] + + v.CFLAGS_cshlib = [] + v.LINKFLAGS_cshlib = ['-Wl,-DLL'] + v.cstlib_PATTERN = '%s.lib' + v.STLIB_MARKER = [] + + del(v.AR) + conf.find_program(['llvm-lib', 'lib'], var='AR') + v.ARFLAGS = ['-nologo'] + v.AR_TGT_F = ['-out:'] + + # Default to the linker supplied with llvm instead of link.exe or ld + v.LINK_CC = v.CC + ['-fuse-ld=lld', '-nostdlib'] + v.CCLNK_TGT_F = ['-o'] + v.def_PATTERN = '-Wl,-def:%s' + + v.LINKFLAGS = [] + + v.LIB_ST = '-l%s' + v.LIBPATH_ST = '-Wl,-LIBPATH:%s' + v.STLIB_ST = '-l%s' + v.STLIBPATH_ST = '-Wl,-LIBPATH:%s' + + CFLAGS_CRT_COMMON = [ + '-Xclang', '--dependent-lib=oldnames', + '-Xclang', '-fno-rtti-data', + '-D_MT' + ] + + v.CFLAGS_CRT_MULTITHREADED = CFLAGS_CRT_COMMON + [ + '-Xclang', '-flto-visibility-public-std', + '-Xclang', '--dependent-lib=libcmt', + ] + v.CXXFLAGS_CRT_MULTITHREADED = v.CFLAGS_CRT_MULTITHREADED + + v.CFLAGS_CRT_MULTITHREADED_DBG = CFLAGS_CRT_COMMON + [ + '-D_DEBUG', + '-Xclang', '-flto-visibility-public-std', + '-Xclang', '--dependent-lib=libcmtd', + ] + v.CXXFLAGS_CRT_MULTITHREADED_DBG = v.CFLAGS_CRT_MULTITHREADED_DBG + + v.CFLAGS_CRT_MULTITHREADED_DLL = CFLAGS_CRT_COMMON + [ + '-D_DLL', + '-Xclang', '--dependent-lib=msvcrt' + ] + v.CXXFLAGS_CRT_MULTITHREADED_DLL = v.CFLAGS_CRT_MULTITHREADED_DLL + + v.CFLAGS_CRT_MULTITHREADED_DLL_DBG = CFLAGS_CRT_COMMON + [ + '-D_DLL', + '-D_DEBUG', + '-Xclang', '--dependent-lib=msvcrtd', + ] + v.CXXFLAGS_CRT_MULTITHREADED_DLL_DBG = v.CFLAGS_CRT_MULTITHREADED_DLL_DBG + +@conf +def clang_modifier_target_triple(conf, cpp=False): + compiler = conf.env.CXX if cpp else conf.env.CC + output = conf.cmd_and_log(compiler + ['-dumpmachine'], output=waflib.Context.STDOUT) + + modifier = ('clangxx' if cpp else 'clang') + '_modifier_' + clang_modifier_func = getattr(conf, modifier + normalize_target_triple(output), None) + if clang_modifier_func: + clang_modifier_func() diff --git a/waflib/extras/clangxx_cross.py b/waflib/extras/clangxx_cross.py new file mode 100644 index 0000000000..0ad38ad46c --- /dev/null +++ b/waflib/extras/clangxx_cross.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy 2009-2018 (ita) +# DragoonX6 2018 + +""" +Detect the Clang++ C++ compiler +This version is an attempt at supporting the -target and -sysroot flag of Clang++. +""" + +from waflib.Tools import ccroot, ar, gxx +from waflib.Configure import conf +import waflib.extras.clang_cross_common + +def options(opt): + """ + Target triplet for clang++:: + $ waf configure --clangxx-target-triple=x86_64-pc-linux-gnu + """ + cxx_compiler_opts = opt.add_option_group('Configuration options') + cxx_compiler_opts.add_option('--clangxx-target-triple', default=None, + help='Target triple for clang++', + dest='clangxx_target_triple') + cxx_compiler_opts.add_option('--clangxx-sysroot', default=None, + help='Sysroot for clang++', + dest='clangxx_sysroot') + +@conf +def find_clangxx(conf): + """ + Finds the program clang++, and executes it to ensure it really is clang++ + """ + + import os + + cxx = conf.find_program('clang++', var='CXX') + + if conf.options.clangxx_target_triple != None: + conf.env.append_value('CXX', ['-target', conf.options.clangxx_target_triple]) + + if conf.options.clangxx_sysroot != None: + sysroot = str() + + if os.path.isabs(conf.options.clangxx_sysroot): + sysroot = conf.options.clangxx_sysroot + else: + sysroot = os.path.normpath(os.path.join(os.getcwd(), conf.options.clangxx_sysroot)) + + conf.env.append_value('CXX', ['--sysroot', sysroot]) + + conf.get_cc_version(cxx, clang=True) + conf.env.CXX_NAME = 'clang' + +@conf +def clangxx_modifier_x86_64_w64_mingw32(conf): + conf.gcc_modifier_win32() + +@conf +def clangxx_modifier_i386_w64_mingw32(conf): + conf.gcc_modifier_win32() + +@conf +def clangxx_modifier_msvc(conf): + v = conf.env + v.cxxprogram_PATTERN = v.cprogram_PATTERN + v.cxxshlib_PATTERN = v.cshlib_PATTERN + + v.CXXFLAGS_cxxshlib = [] + v.LINKFLAGS_cxxshlib = v.LINKFLAGS_cshlib + v.cxxstlib_PATTERN = v.cstlib_PATTERN + + v.LINK_CXX = v.CXX + ['-fuse-ld=lld', '-nostdlib'] + v.CXXLNK_TGT_F = v.CCLNK_TGT_F + +@conf +def clangxx_modifier_x86_64_windows_msvc(conf): + conf.clang_modifier_msvc() + conf.clangxx_modifier_msvc() + + # Allow the user to override any flags if they so desire. + clang_modifier_user_func = getattr(conf, 'clangxx_modifier_x86_64_windows_msvc_user', None) + if clang_modifier_user_func: + clang_modifier_user_func() + +@conf +def clangxx_modifier_i386_windows_msvc(conf): + conf.clang_modifier_msvc() + conf.clangxx_modifier_msvc() + + # Allow the user to override any flags if they so desire. + clang_modifier_user_func = getattr(conf, 'clangxx_modifier_i386_windows_msvc_user', None) + if clang_modifier_user_func: + clang_modifier_user_func() + +def configure(conf): + conf.find_clangxx() + conf.find_program(['llvm-ar', 'ar'], var='AR') + conf.find_ar() + conf.gxx_common_flags() + # Allow the user to provide flags for the target platform. + conf.gxx_modifier_platform() + # And allow more fine grained control based on the compiler's triplet. + conf.clang_modifier_target_triple(cpp=True) + conf.cxx_load_tools() + conf.cxx_add_flags() + conf.link_add_flags() From b0aa9fd1701b3c78d32bb2ea6845d7442c477b1b Mon Sep 17 00:00:00 2001 From: Dragoon Date: Thu, 9 May 2019 23:18:51 +0200 Subject: [PATCH 117/315] Add a simple example for using Clang as a cross compiler for MSVC --- playground/clang_cross/msvc/ReadMe.txt | 14 ++++++++ .../msvc/example_environment_linux.sh | 5 +++ playground/clang_cross/msvc/hello.c | 11 +++++++ playground/clang_cross/msvc/wscript | 32 +++++++++++++++++++ 4 files changed, 62 insertions(+) create mode 100644 playground/clang_cross/msvc/ReadMe.txt create mode 100644 playground/clang_cross/msvc/example_environment_linux.sh create mode 100644 playground/clang_cross/msvc/hello.c create mode 100644 playground/clang_cross/msvc/wscript diff --git a/playground/clang_cross/msvc/ReadMe.txt b/playground/clang_cross/msvc/ReadMe.txt new file mode 100644 index 0000000000..e82291a4f5 --- /dev/null +++ b/playground/clang_cross/msvc/ReadMe.txt @@ -0,0 +1,14 @@ +To cross compile for Windows in MSVC mode from Linux, you will require the following: +* A partition with Windows installed (NTFS). +* Visual Studio (Tested with 2017). +* The Windows SDK. +* lowntfs-3g file system driver. + +Make sure the Windows partition is mounted with "-t lowntfs-3g -o defaults,ignore_case,windows_names". +This will allow Clang to find all headers and libraries referenced by scripts and headers, otherwise you will run into case sensitivity errors. + +Clang uses the following environment variables to detect the Visual Studio install: VCINSTALLDIR, VCToolsInstallDir, INCLUDE, LIB, LIBPATH +I just copied these from the output of the "set" command in an MSVC command prompt on Windows and translated the paths to Linux paths. +Notice how the semicolon is still used as a path separator. +See "example_environment_linux.sh" for how my setup looks like. +It expects the Windows partition to be mounted on /mnt/windows, with VS2017 installed and Windows 10 SDK 10.0.17763.0. diff --git a/playground/clang_cross/msvc/example_environment_linux.sh b/playground/clang_cross/msvc/example_environment_linux.sh new file mode 100644 index 0000000000..1fd5a0054e --- /dev/null +++ b/playground/clang_cross/msvc/example_environment_linux.sh @@ -0,0 +1,5 @@ +export VCINSTALLDIR="/mnt/windows/program files (x86)/microsoft visual studio/2017/community/vc/" +export VCToolsInstallDir="/mnt/windows/program files (x86)/microsoft visual studio/2017/community/vc/tools/msvc/14.16.27023/" +export INCLUDE="/mnt/windows/program files (x86)/microsoft visual studio/2017/community/vc/tools/msvc/14.16.27023/atlmfc/include;/mnt/windows/program files (x86)/microsoft visual studio/2017/community/vc/tools/msvc/14.16.27023/include;/mnt/windows/program files (x86)/windows kits/10/include/10.0.17763.0/ucrt;/mnt/windows/program files (x86)/windows kits/10/include/10.0.17763.0/shared;/mnt/windows/program files (x86)/windows kits/10/include/10.0.17763.0/um;/mnt/windows/program files (x86)/windows kits/10/include/10.0.17763.0/winrt;/mnt/windows/program files (x86)/windows kits/10/include/10.0.17763.0/cppwinrt" +export LIB="/mnt/windows/program files (x86)/microsoft visual studio/2017/community/vc/tools/msvc/14.16.27023/atlmfc/lib/x64;/mnt/windows/program files (x86)/microsoft visual studio/2017/community/vc/tools/msvc/14.16.27023/lib/x64;/mnt/windows/program files (x86)/windows kits/10/lib/10.0.17763.0/ucrt/x64;/mnt/windows/program files (x86)/windows kits/10/lib/10.0.17763.0/um/x64" +export LIBPATH="/mnt/windows/program files (x86)/microsoft visual studio/2017/community/vc/tools/msvc/14.16.27023/atlmfc/lib/x64;/mnt/windows/program files (x86)/microsoft visual studio/2017/community/vc/tools/msvc/14.16.27023/lib/x64;/mnt/windows/program files (x86)/microsoft visual studio/2017/community/vc/tools/msvc/14.16.27023/lib/x86/store/references;/mnt/windows/program files (x86)/windows kits/10/unionmetadata/10.0.17763.0;/mnt/windows/program files (x86)/windows kits/10/references/10.0.17763.0" diff --git a/playground/clang_cross/msvc/hello.c b/playground/clang_cross/msvc/hello.c new file mode 100644 index 0000000000..3ae11826fb --- /dev/null +++ b/playground/clang_cross/msvc/hello.c @@ -0,0 +1,11 @@ +#include + +int main(int argc, char* argv[]) +{ + (void)argc; + (void)argv; + + WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), "Hello world!\n", 13, NULL, NULL); + + return 0; +} diff --git a/playground/clang_cross/msvc/wscript b/playground/clang_cross/msvc/wscript new file mode 100644 index 0000000000..a1ed74a32f --- /dev/null +++ b/playground/clang_cross/msvc/wscript @@ -0,0 +1,32 @@ +#! /usr/bin/env python +# encoding: utf-8 +# DragoonX6 2019 + +# the following two variables are used by the target "waf dist" +VERSION='0.0.1' +APPNAME='hello_msvc' + +top = '.' + +from waflib.Configure import conf, ConfigurationContext +from waflib.Options import OptionsContext + +def options(opt): + opt.load('clang_cross') + +def configure(conf): + conf.load('clang_cross') + + if not conf.env.implib_PATTERN == '%s.lib': + conf.fatal('''clang is not configured to compile in msvc mode. +Use flag '--clang-target-triple=x86_64-windows-msvc' to configure. +On Windows you're likely to require running from an MSVC command prompt. +On Linux you will need to have access to a Windows partition with VS installed, and the environment set up properly. +See the ReadMe for more information.''') + + conf.env.append_value('CFLAGS', conf.env.CFLAGS_CRT_MULTITHREADED_DLL) + +def build(bld): + bld.program( + source = 'hello.c', + target = 'hello_msvc') From b7c032d63d63b7a4de0ca975513084801e5174a0 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Fri, 10 May 2019 23:13:01 +0200 Subject: [PATCH 118/315] Undo parentheses escaping in ant_glob --- tests/apis/wscript | 2 +- waflib/Node.py | 2 +- waflib/extras/msvcdeps.py | 5 ++++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/apis/wscript b/tests/apis/wscript index 91d7998dbf..5713513292 100755 --- a/tests/apis/wscript +++ b/tests/apis/wscript @@ -148,7 +148,7 @@ def test(ctx): tt("ant_glob ->", len(bld.srcnode.ant_glob('*.txt', flat=False)), 2) tt("ant_glob (icase) ->", len(bld.srcnode.ant_glob('*.txt', flat=False, ignorecase=True)), 3) - tt("ant_glob (special) ->", len(bld.srcnode.ant_glob('e.e+(e).txt', flat=False)), 1) + tt("ant_glob (parentheses) ->", len(bld.srcnode.ant_glob('e.e+[(]e[)].txt', flat=False)), 1) #print("ant_glob src ->", bld.srcnode.ant_glob('*.txt')) def abspath(self): diff --git a/waflib/Node.py b/waflib/Node.py index f6ac261536..9a9ed0a62a 100644 --- a/waflib/Node.py +++ b/waflib/Node.py @@ -73,7 +73,7 @@ def ant_matcher(s, ignorecase): if k == '**': accu.append(k) else: - k = k.replace('.', '[.]').replace('*','.*').replace('?', '.').replace('+', '\\+').replace('(', '\\(').replace(')', '\\)') + k = k.replace('.', '[.]').replace('*', '.*').replace('?', '.').replace('+', '\\+') k = '^%s$' % k try: exp = re.compile(k, flags=reflags) diff --git a/waflib/extras/msvcdeps.py b/waflib/extras/msvcdeps.py index 54de25d384..873a419315 100644 --- a/waflib/extras/msvcdeps.py +++ b/waflib/extras/msvcdeps.py @@ -63,6 +63,9 @@ def path_to_node(base_node, path, cached_nodes): # normalize the path case to increase likelihood of a cache hit path = os.path.normcase(path) + # ant_glob interprets [] and () characters, so those must be replaced + path = path.replace('[', '?').replace(']', '?').replace('(', '[(]').replace(')', '[)]') + node_lookup_key = (base_node, path) try: @@ -73,7 +76,7 @@ def path_to_node(base_node, path, cached_nodes): try: node = cached_nodes[node_lookup_key] except KeyError: - node_list = base_node.ant_glob([path], ignorecase=True, remove=False, quiet=True) + node_list = base_node.ant_glob([path], ignorecase=True, remove=False, quiet=True, regex=False) node = cached_nodes[node_lookup_key] = node_list[0] if node_list else None return node From abdcf9144ca95fb5a68391b90fc8309aeb840d4d Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Wed, 15 May 2019 23:54:17 +0200 Subject: [PATCH 119/315] waf-2.0.16 --- ChangeLog | 15 +++++++++++++++ waf-light | 2 +- waflib/Context.py | 6 +++--- wscript | 2 +- 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index beb67c8085..9f0b6d64ea 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +NEW IN WAF 2.0.16 +----------------- +* Fix task semaphore errors on stateful tasks #2232 +* Fix encoding errors with UTF-8 paths on Python 2 #2230 +* Fix encoding errors in waf_unit_test #2220 +* Improve dependency between javac task and use-d generated jars nodes +* Install pdb files with /debug:* flags #2224 +* Make javadoc detection optional #2225 +* Improve md5_tstamp documentation #2221 +* Add extras/color_msvc to colorizes MSVC outputs #2221 +* Fix symbol regex on mac-o binaries in extras/syms #2222 +* Maintain order of lines in doxyfile in extras/doxygen #2223 +* Improve extras/msvcdeps path handling +* Add extras/clang_cross for cross-compilation using clang + NEW IN WAF 2.0.15 ----------------- * Fix Python path detection under Git-Bash #2217 diff --git a/waf-light b/waf-light index 08e42d4d58..9eb1e1795e 100755 --- a/waf-light +++ b/waf-light @@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. import os, sys, inspect -VERSION="2.0.15" +VERSION="2.0.16" REVISION="x" GIT="x" INSTALL="x" diff --git a/waflib/Context.py b/waflib/Context.py index 876ea46b92..4d9cce347e 100644 --- a/waflib/Context.py +++ b/waflib/Context.py @@ -11,13 +11,13 @@ import waflib.Node # the following 3 constants are updated on each new release (do not touch) -HEXVERSION=0x2000f00 +HEXVERSION=0x2001000 """Constant updated on new releases""" -WAFVERSION="2.0.15" +WAFVERSION="2.0.16" """Constant updated on new releases""" -WAFREVISION="503db290b73ef738a495e0d116d6f8ee0b98dcc2" +WAFREVISION="8cbc8da5ce54dafc16197e468e3578779dcf981d" """Git revision when the waf version is updated""" ABI = 20 diff --git a/wscript b/wscript index 2d83ab08b4..06a091db2f 100644 --- a/wscript +++ b/wscript @@ -11,7 +11,7 @@ To add a tool that does not exist in the folder compat15, pass an absolute path: from __future__ import with_statement -VERSION="2.0.15" +VERSION="2.0.16" APPNAME='waf' REVISION='' From 2c0352bf0c84facfc0ce3a4ef37d86b5a09c194b Mon Sep 17 00:00:00 2001 From: "Morten V. Pedersen" Date: Fri, 17 May 2019 05:46:17 +0000 Subject: [PATCH 120/315] Update colors of install step --- waflib/Build.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/waflib/Build.py b/waflib/Build.py index fb752d145e..b302861230 100644 --- a/waflib/Build.py +++ b/waflib/Build.py @@ -1164,7 +1164,11 @@ def do_install(self, src, tgt, lbl, **kw): return False if not self.generator.bld.progress_bar: - Logs.info('+ install %s (from %s)', tgt, lbl) + + c1 = Logs.colors.NORMAL + c2 = Logs.colors.BLUE + + Logs.info('%s+ install %s%s%s (from %s)', c1, c2, tgt, c1, lbl) # Give best attempt at making destination overwritable, # like the 'install' utility used by 'make install' does. From f08a60dec0102c7e1ec198167575fabaf2d6e00a Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Thu, 23 May 2019 19:37:54 +0000 Subject: [PATCH 121/315] Fix waf.bat ERRORLEVEL to return actual exit code of waf --- utils/waf.bat | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/utils/waf.bat b/utils/waf.bat index 59e3af07db..0816ec1384 100644 --- a/utils/waf.bat +++ b/utils/waf.bat @@ -93,5 +93,6 @@ goto running @echo Using %PYTHON% -"%PYTHON%" -x "%~dp0waf" %* & Endlocal & exit /b %ERRORLEVEL% - +"%PYTHON%" -x "%~dp0waf" %* +Endlocal +exit /b %ERRORLEVEL% \ No newline at end of file From 7a57381c10ff0e24f01d1c200249e176d3e8ed5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Fri, 24 May 2019 11:49:58 +0200 Subject: [PATCH 122/315] Python 3.8 has different flags for pyembed, needs --embed As recommended in the docs, to support both 3.8 and previous versions, we try to use python3-config --embed and fallback to the previous behavior. Fixes https://gitlab.com/ita1024/waf/issues/2239 See https://docs.python.org/dev/whatsnew/3.8.html#debug-build-uses-the-same-abi-as-release-build --- waflib/Tools/python.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/waflib/Tools/python.py b/waflib/Tools/python.py index 01a2c9aa1c..63a8917d7c 100644 --- a/waflib/Tools/python.py +++ b/waflib/Tools/python.py @@ -342,7 +342,13 @@ def check_python_headers(conf, features='pyembed pyext'): if 'pyembed' in features: for flags in all_flags: - conf.check_cfg(msg='Asking python-config for pyembed %r flags' % ' '.join(flags), path=env.PYTHON_CONFIG, package='', uselib_store='PYEMBED', args=flags) + # Python 3.8 has different flags for pyembed, needs --embed + embedflags = flags + ['--embed'] + try: + conf.check_cfg(msg='Asking python-config for pyembed %r flags' % ' '.join(embedflags), path=env.PYTHON_CONFIG, package='', uselib_store='PYEMBED', args=embedflags) + except conf.errors.ConfigurationError: + # However Python < 3.8 doesn't accept --embed, so we need a fallback + conf.check_cfg(msg='Asking python-config for pyembed %r flags' % ' '.join(flags), path=env.PYTHON_CONFIG, package='', uselib_store='PYEMBED', args=flags) try: conf.test_pyembed(xx) From cd472a1c59a2d9da8980079d2e7e9dae7245fbea Mon Sep 17 00:00:00 2001 From: Piotr Szubiakowski Date: Fri, 24 May 2019 14:29:35 +0200 Subject: [PATCH 123/315] sphinx: adds a tool for Sphinx documentation. Signed-off-by: Piotr Szubiakowski --- waflib/extras/sphinx.py | 81 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 waflib/extras/sphinx.py diff --git a/waflib/extras/sphinx.py b/waflib/extras/sphinx.py new file mode 100644 index 0000000000..ce11110e63 --- /dev/null +++ b/waflib/extras/sphinx.py @@ -0,0 +1,81 @@ +"""Support for Sphinx documentation + +This is a wrapper for sphinx-build program. Please note that sphinx-build supports only one output format which can +passed to build via sphinx_output_format attribute. The default output format is html. + +Example wscript: + +def configure(cnf): + conf.load('sphinx') + +def build(bld): + bld( + features='sphinx', + sphinx_source='sources', # path to source directory + sphinx_options='-a -v', # sphinx-build program additional options + sphinx_output_format='man' # output format of sphinx documentation + ) + +""" + +from waflib.Node import Node +from waflib import Utils +from waflib.Task import Task +from waflib.TaskGen import feature, after_method + + +def configure(cnf): + """Check if sphinx-build program is available and loads gnu_dirs tool.""" + cnf.find_program('sphinx-build', var='SPHINX_BUILD', mandatory=False) + cnf.load('gnu_dirs') + + +@feature('sphinx') +def build_sphinx(self): + """Builds sphinx sources. + """ + if not self.env.SPHINX_BUILD: + self.bld.fatal('Program SPHINX_BUILD not defined.') + if not getattr(self, 'sphinx_source', None): + self.bld.fatal('Attribute sphinx_source not defined.') + if not isinstance(self.sphinx_source, Node): + self.sphinx_source = self.path.find_node(self.sphinx_source) + if not self.sphinx_source: + self.bld.fatal('Can\'t find sphinx_source: %r' % self.sphinx_source) + + Utils.def_attrs(self, sphinx_output_format='html') + self.env.SPHINX_OUTPUT_FORMAT = self.sphinx_output_format + self.env.SPHINX_OPTIONS = getattr(self, 'sphinx_options', []) + + for source_file in self.sphinx_source.ant_glob('**/*'): + self.bld.add_manual_dependency(self.sphinx_source, source_file) + + sphinx_build_task = self.create_task('SphinxBuildingTask') + sphinx_build_task.set_inputs(self.sphinx_source) + sphinx_build_task.set_outputs(self.path.get_bld()) + + # the sphinx-build results are in directory + sphinx_output_directory = self.path.get_bld().make_node(self.env.SPHINX_OUTPUT_FORMAT) + sphinx_output_directory.mkdir() + Utils.def_attrs(self, install_path=get_install_path(self)) + self.add_install_files(install_to=self.install_path, + install_from=sphinx_output_directory.ant_glob('**/*'), + cwd=sphinx_output_directory, + relative_trick=True) + + +def get_install_path(tg): + if tg.env.SPHINX_OUTPUT_FORMAT == 'man': + return tg.env.MANDIR + elif tg.env.SPHINX_OUTPUT_FORMAT == 'info': + return tg.env.INFODIR + else: + return tg.env.DOCDIR + + +class SphinxBuildingTask(Task): + color = 'BOLD' + run_str = '${SPHINX_BUILD} -M ${SPHINX_OUTPUT_FORMAT} ${SRC} ${TGT} ${SPHINX_OPTIONS}' + + def keyword(self): + return 'Compiling (%s)' % self.env.SPHINX_OUTPUT_FORMAT From 0a29e8ff75a554bfe6823138d28107d46e0db321 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 26 May 2019 12:20:34 +0200 Subject: [PATCH 124/315] docs #2240 --- waflib/extras/fast_partial.py | 1 + 1 file changed, 1 insertion(+) diff --git a/waflib/extras/fast_partial.py b/waflib/extras/fast_partial.py index d5b61448c6..71b8318eec 100644 --- a/waflib/extras/fast_partial.py +++ b/waflib/extras/fast_partial.py @@ -19,6 +19,7 @@ def options(opt): Assumptions: * Mostly for C/C++/Fortran targets with link tasks (object-only targets are not handled) + try it in the folder generated by utils/genbench.py * For full project builds: no --targets and no pruning from subfolders * The installation phase is ignored * `use=` dependencies are specified up front even across build groups From 2c3a3d1744d560fe51a3f055031b13bac2fe429b Mon Sep 17 00:00:00 2001 From: Piotr Szubiakowski Date: Sun, 26 May 2019 13:37:34 +0200 Subject: [PATCH 125/315] sphinx: adds an example to the playground. --- playground/sphinx/src/conf.py | 173 ++++++++++++++++++++++++++++++++ playground/sphinx/src/index.rst | 20 ++++ playground/sphinx/wscript | 10 ++ 3 files changed, 203 insertions(+) create mode 100644 playground/sphinx/src/conf.py create mode 100644 playground/sphinx/src/index.rst create mode 100644 playground/sphinx/wscript diff --git a/playground/sphinx/src/conf.py b/playground/sphinx/src/conf.py new file mode 100644 index 0000000000..7bb1ed699e --- /dev/null +++ b/playground/sphinx/src/conf.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# +# Configuration file for the Sphinx documentation builder. +# +# This file does only contain a selection of the most common options. For a +# full list see the documentation: +# http://www.sphinx-doc.org/en/master/config + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + + +# -- Project information ----------------------------------------------------- + +project = 'project' +copyright = '2019, sphinx' +author = 'sphinx' + +# The short X.Y version +version = '' +# The full version, including alpha/beta/rc tags +release = '1.0.0' + + +# -- General configuration --------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = [] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = None + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'alabaster' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# The default sidebars (for documents that don't match any pattern) are +# defined by theme itself. Builtin themes are using these templates by +# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', +# 'searchbox.html']``. +# +# html_sidebars = {} + + +# -- Options for HTMLHelp output --------------------------------------------- + +# Output file base name for HTML help builder. +htmlhelp_basename = 'projectdoc' + + +# -- Options for LaTeX output ------------------------------------------------ + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'project.tex', 'project Documentation', + 'sphinx', 'manual'), +] + + +# -- Options for manual page output ------------------------------------------ + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'project', 'project Documentation', + [author], 1) +] + + +# -- Options for Texinfo output ---------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'project', 'project Documentation', + author, 'project', 'One line description of project.', + 'Miscellaneous'), +] + + +# -- Options for Epub output ------------------------------------------------- + +# Bibliographic Dublin Core info. +epub_title = project + +# The unique identifier of the text. This can be a ISBN number +# or the project homepage. +# +# epub_identifier = '' + +# A unique identification for the text. +# +# epub_uid = '' + +# A list of files that should not be packed into the epub file. +epub_exclude_files = ['search.html'] diff --git a/playground/sphinx/src/index.rst b/playground/sphinx/src/index.rst new file mode 100644 index 0000000000..e8606fe774 --- /dev/null +++ b/playground/sphinx/src/index.rst @@ -0,0 +1,20 @@ +.. project documentation master file, created by + sphinx-quickstart on Sun May 26 12:49:41 2019. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to project's documentation! +=================================== + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/playground/sphinx/wscript b/playground/sphinx/wscript new file mode 100644 index 0000000000..79ff287e93 --- /dev/null +++ b/playground/sphinx/wscript @@ -0,0 +1,10 @@ +"""Sphinx documentation wscript example +""" + + +def configure(cnf): + cnf.load('sphinx') + + +def build(bld): + bld(features='sphinx', sphinx_source='src', sphinx_output_format='html') From e2d76eeceae3e908546971b0d8096143193c87b8 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Mon, 27 May 2019 18:05:02 +0200 Subject: [PATCH 126/315] Optimize sub process startup with workers --- waflib/Utils.py | 2 +- waflib/processor.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/waflib/Utils.py b/waflib/Utils.py index 0a069b12d5..65cb32ef53 100644 --- a/waflib/Utils.py +++ b/waflib/Utils.py @@ -885,7 +885,7 @@ def get_process(): except IndexError: filepath = os.path.dirname(os.path.abspath(__file__)) + os.sep + 'processor.py' cmd = [sys.executable, '-c', readf(filepath)] - return subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE, bufsize=0) + return subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE, bufsize=0, close_fds=True) def run_prefork_process(cmd, kwargs, cargs): """ diff --git a/waflib/processor.py b/waflib/processor.py index 2eecf3bd93..eff2e69adf 100755 --- a/waflib/processor.py +++ b/waflib/processor.py @@ -27,6 +27,10 @@ def run(): [cmd, kwargs, cargs] = cPickle.loads(base64.b64decode(txt)) cargs = cargs or {} + if not 'close_fds' in kwargs: + # workers have no fds + kwargs['close_fds'] = False + ret = 1 out, err, ex, trace = (None, None, None, None) try: From c94dfb8e975e58a6d1f1d1392e57bec6b3b97a9f Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Mon, 27 May 2019 18:31:34 +0200 Subject: [PATCH 127/315] Do not attempt to close fds on Windows platforms --- waflib/Utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/Utils.py b/waflib/Utils.py index 65cb32ef53..7472226da5 100644 --- a/waflib/Utils.py +++ b/waflib/Utils.py @@ -885,7 +885,7 @@ def get_process(): except IndexError: filepath = os.path.dirname(os.path.abspath(__file__)) + os.sep + 'processor.py' cmd = [sys.executable, '-c', readf(filepath)] - return subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE, bufsize=0, close_fds=True) + return subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE, bufsize=0, close_fds=not is_win32) def run_prefork_process(cmd, kwargs, cargs): """ From 5170da35ebc752c5835e5684c328f8c2d9bc91a1 Mon Sep 17 00:00:00 2001 From: "Morten V. Pedersen" Date: Mon, 27 May 2019 19:14:18 +0000 Subject: [PATCH 128/315] Colors were missing when file already exists --- waflib/Build.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/waflib/Build.py b/waflib/Build.py index b302861230..e09c565b86 100644 --- a/waflib/Build.py +++ b/waflib/Build.py @@ -1160,7 +1160,11 @@ def do_install(self, src, tgt, lbl, **kw): # same size and identical timestamps -> make no copy if st1.st_mtime + 2 >= st2.st_mtime and st1.st_size == st2.st_size: if not self.generator.bld.progress_bar: - Logs.info('- install %s (from %s)', tgt, lbl) + + c1 = Logs.colors.NORMAL + c2 = Logs.colors.BLUE + + Logs.info('%s- install %s%s%s (from %s)', c1, c2, tgt, c1, lbl) return False if not self.generator.bld.progress_bar: From f1d416ea3906531df9a1372ad46db83d93172ed4 Mon Sep 17 00:00:00 2001 From: fedepell Date: Tue, 28 May 2019 11:40:43 +0200 Subject: [PATCH 129/315] javaw: make dependencies code introduced in !2232 more robust --- waflib/Tools/javaw.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/waflib/Tools/javaw.py b/waflib/Tools/javaw.py index c746556f6f..e04581fca4 100644 --- a/waflib/Tools/javaw.py +++ b/waflib/Tools/javaw.py @@ -213,7 +213,10 @@ def java_use_rec(self, name, **kw): if hasattr(y, 'jar_task'): self.use_lst.append(y.jar_task.outputs[0].abspath()) else: - self.use_lst.append(y.outdir.abspath()) + if hasattr(y,'outdir'): + self.use_lst.append(y.outdir.abspath()) + else: + self.use_lst.append(y.path.get_bld().abspath()) for x in self.to_list(getattr(y, 'use', [])): self.java_use_rec(x) @@ -242,10 +245,14 @@ def use_javac_files(self): self.javac_task.set_run_after(y.jar_task) self.javac_task.dep_nodes.extend(y.jar_task.outputs) else: - self.use_lst.append(y.outdir.abspath()) + if hasattr(y, 'outdir'): + self.use_lst.append(y.outdir.abspath()) + self.javac_task.dep_nodes.extend([x for x in y.outdir.ant_glob(JAR_RE, remove=False, quiet=True)]) + else: + self.use_lst.append(y.path.get_bld().abspath()) + self.javac_task.dep_nodes.extend([x for x in y.path.get_bld().ant_glob(JAR_RE, remove=False, quiet=True)]) for tsk in y.tasks: self.javac_task.set_run_after(tsk) - self.javac_task.dep_nodes.extend([x for x in y.outdir.ant_glob(JAR_RE, remove=False, quiet=True)]) # If recurse use scan is enabled recursively add use attribute for each used one if getattr(self, 'recurse_use', False) or self.bld.env.RECURSE_JAVA: From e7b64ed1e77cf7cd2a0372c0318a6df283c554ec Mon Sep 17 00:00:00 2001 From: fedepell Date: Sat, 1 Jun 2019 22:51:38 +0200 Subject: [PATCH 130/315] qt5: ignore moc generation on uninstall target --- waflib/Tools/qt5.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/waflib/Tools/qt5.py b/waflib/Tools/qt5.py index 9f432801cb..f4cc399921 100644 --- a/waflib/Tools/qt5.py +++ b/waflib/Tools/qt5.py @@ -167,6 +167,10 @@ def add_moc_tasks(self): node = self.inputs[0] bld = self.generator.bld + # on uninstall this is unnecessary and may lead to errors if files needed are generated + if bld.cmd == 'uninstall': + return + try: # compute the signature once to know if there is a moc file to create self.signature() From e5de8482e0caaf1172da8b87d50bfa66d2bbf554 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 2 Jun 2019 08:43:19 +0200 Subject: [PATCH 131/315] Improve Qt5 processing 1de43d82c036bf9e6c04ea852e5a8c718550c8ec --- waflib/Tools/qt5.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/waflib/Tools/qt5.py b/waflib/Tools/qt5.py index f4cc399921..f8d27ca4a1 100644 --- a/waflib/Tools/qt5.py +++ b/waflib/Tools/qt5.py @@ -167,8 +167,8 @@ def add_moc_tasks(self): node = self.inputs[0] bld = self.generator.bld - # on uninstall this is unnecessary and may lead to errors if files needed are generated - if bld.cmd == 'uninstall': + # skip on uninstall due to generated files + if bld.is_install < 0: return try: From e2ec1d8a8bddce7a58dcae5d0ec2f016ab29a478 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 2 Jun 2019 08:50:06 +0200 Subject: [PATCH 132/315] Refactor javaw.py 066a0511810f291c87810276b47427bf2101b70c --- waflib/Tools/javaw.py | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/waflib/Tools/javaw.py b/waflib/Tools/javaw.py index e04581fca4..fd1cf469ab 100644 --- a/waflib/Tools/javaw.py +++ b/waflib/Tools/javaw.py @@ -235,23 +235,25 @@ def use_javac_files(self): get = self.bld.get_tgen_by_name for x in names: try: - y = get(x) + tg = get(x) except Errors.WafError: self.uselib.append(x) else: - y.post() - if hasattr(y, 'jar_task'): - self.use_lst.append(y.jar_task.outputs[0].abspath()) - self.javac_task.set_run_after(y.jar_task) - self.javac_task.dep_nodes.extend(y.jar_task.outputs) + tg.post() + if hasattr(tg, 'jar_task'): + self.use_lst.append(tg.jar_task.outputs[0].abspath()) + self.javac_task.set_run_after(tg.jar_task) + self.javac_task.dep_nodes.extend(tg.jar_task.outputs) else: - if hasattr(y, 'outdir'): - self.use_lst.append(y.outdir.abspath()) - self.javac_task.dep_nodes.extend([x for x in y.outdir.ant_glob(JAR_RE, remove=False, quiet=True)]) + if hasattr(tg, 'outdir'): + base_node = tg.outdir.abspath() else: - self.use_lst.append(y.path.get_bld().abspath()) - self.javac_task.dep_nodes.extend([x for x in y.path.get_bld().ant_glob(JAR_RE, remove=False, quiet=True)]) - for tsk in y.tasks: + base_node = tg.path.get_bld() + + self.use_lst.append(base_node.abspath()) + self.javac_task.dep_nodes.extend([x for x in base_node.ant_glob(JAR_RE, remove=False, quiet=True)]) + + for tsk in tg.tasks: self.javac_task.set_run_after(tsk) # If recurse use scan is enabled recursively add use attribute for each used one From 07ce3709220ccbb5fc4f9b1d43e05474c7418eb3 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 2 Jun 2019 09:20:29 +0200 Subject: [PATCH 133/315] Rework installation colors --- waflib/Build.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/waflib/Build.py b/waflib/Build.py index e09c565b86..264cdbed33 100644 --- a/waflib/Build.py +++ b/waflib/Build.py @@ -1229,14 +1229,18 @@ def do_link(self, src, tgt, **kw): """ if os.path.islink(tgt) and os.readlink(tgt) == src: if not self.generator.bld.progress_bar: - Logs.info('- symlink %s (to %s)', tgt, src) + c1 = Logs.colors.NORMAL + c2 = Logs.colors.BLUE + Logs.info('%s- symlink %s%s%s (to %s)', c1, c2, tgt, c1, src) else: try: os.remove(tgt) except OSError: pass if not self.generator.bld.progress_bar: - Logs.info('+ symlink %s (to %s)', tgt, src) + c1 = Logs.colors.NORMAL + c2 = Logs.colors.BLUE + Logs.info('%s+ symlink %s%s%s (to %s)', c1, c2, tgt, c1, src) os.symlink(src, tgt) self.fix_perms(tgt) @@ -1245,7 +1249,9 @@ def do_uninstall(self, src, tgt, lbl, **kw): See :py:meth:`waflib.Build.inst.do_install` """ if not self.generator.bld.progress_bar: - Logs.info('- remove %s', tgt) + c1 = Logs.colors.NORMAL + c2 = Logs.colors.BLUE + Logs.info('%s- remove %s%s%s', c1, c2, tgt, c1) #self.uninstall.append(tgt) try: @@ -1265,7 +1271,9 @@ def do_unlink(self, src, tgt, **kw): """ try: if not self.generator.bld.progress_bar: - Logs.info('- remove %s', tgt) + c1 = Logs.colors.NORMAL + c2 = Logs.colors.BLUE + Logs.info('%s- remove %s%s%s', c1, c2, tgt, c1) os.remove(tgt) except OSError: pass From 054b036e7a33aaa2bf09789ee7815884fdc6edaf Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 2 Jun 2019 09:23:57 +0200 Subject: [PATCH 134/315] Use a constant instead of a hard-coded number (Qt5) --- waflib/Tools/qt5.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/waflib/Tools/qt5.py b/waflib/Tools/qt5.py index f8d27ca4a1..287c25374a 100644 --- a/waflib/Tools/qt5.py +++ b/waflib/Tools/qt5.py @@ -74,7 +74,7 @@ def add_includes_paths(self): import os, sys, re from waflib.Tools import cxx -from waflib import Task, Utils, Options, Errors, Context +from waflib import Build, Task, Utils, Options, Errors, Context from waflib.TaskGen import feature, after_method, extension, before_method from waflib.Configure import conf from waflib import Logs @@ -168,7 +168,7 @@ def add_moc_tasks(self): bld = self.generator.bld # skip on uninstall due to generated files - if bld.is_install < 0: + if bld.is_install == Build.UNINSTALL: return try: From f6a00bdfa8689722aefdc20d30acdf38751c4a76 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 2 Jun 2019 09:24:52 +0200 Subject: [PATCH 135/315] Ensure that 'waf test' raises a meaningful error message in the installation test --- tests/install/wscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/install/wscript b/tests/install/wscript index 8fe81a4529..adc25cf682 100644 --- a/tests/install/wscript +++ b/tests/install/wscript @@ -11,7 +11,7 @@ def build(bld): @TaskGen.feature('ruler') @TaskGen.before('process_rule') -def test(self): +def test_helper(self): if not self.bld.is_install or self.bld.is_install == Build.UNINSTALL: while self.meths: # do not generate tasks: the target file may not be there self.meths.pop() From 79554f3799a64620c34d070779b1857c98f90341 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 2 Jun 2019 09:45:17 +0200 Subject: [PATCH 136/315] waf-2.0.17 --- ChangeLog | 7 +++++++ waf-light | 2 +- waflib/Context.py | 6 +++--- wscript | 2 +- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9f0b6d64ea..3a13275164 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +NEW IN WAF 2.0.17 +----------------- +* Improve build performance on FreeBSD and Python3 #2241 +* Add Python 3.8 flag detection for building embedded interpreters #2239 +* Prevent Qt5 uninstallation errors when c++ files are generated +* Improve installation/uninstallation colors + NEW IN WAF 2.0.16 ----------------- * Fix task semaphore errors on stateful tasks #2232 diff --git a/waf-light b/waf-light index 9eb1e1795e..8c50d0b125 100755 --- a/waf-light +++ b/waf-light @@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. import os, sys, inspect -VERSION="2.0.16" +VERSION="2.0.17" REVISION="x" GIT="x" INSTALL="x" diff --git a/waflib/Context.py b/waflib/Context.py index 4d9cce347e..d0759aada5 100644 --- a/waflib/Context.py +++ b/waflib/Context.py @@ -11,13 +11,13 @@ import waflib.Node # the following 3 constants are updated on each new release (do not touch) -HEXVERSION=0x2001000 +HEXVERSION=0x2001100 """Constant updated on new releases""" -WAFVERSION="2.0.16" +WAFVERSION="2.0.17" """Constant updated on new releases""" -WAFREVISION="8cbc8da5ce54dafc16197e468e3578779dcf981d" +WAFREVISION="6bc6cb599c702e985780e9f705b291b812123693" """Git revision when the waf version is updated""" ABI = 20 diff --git a/wscript b/wscript index 06a091db2f..76067794e7 100644 --- a/wscript +++ b/wscript @@ -11,7 +11,7 @@ To add a tool that does not exist in the folder compat15, pass an absolute path: from __future__ import with_statement -VERSION="2.0.16" +VERSION="2.0.17" APPNAME='waf' REVISION='' From 061989d13d6445c7d9db8e6ae334a4d0f92f4b37 Mon Sep 17 00:00:00 2001 From: fedepell Date: Wed, 5 Jun 2019 14:59:26 +0200 Subject: [PATCH 137/315] qt5 demo: add example of unit testing using QtTest integrated into waf with standard waf_unit_test Tool --- demos/qt5/foo.cpp | 17 +++++++++++++++++ demos/qt5/foo.h | 7 +++++++ demos/qt5/main.cpp | 3 ++- demos/qt5/testqt5.cpp | 31 +++++++++++++++++++++++++++++++ demos/qt5/wscript | 27 +++++++++++++++++++++++++-- 5 files changed, 82 insertions(+), 3 deletions(-) create mode 100644 demos/qt5/testqt5.cpp diff --git a/demos/qt5/foo.cpp b/demos/qt5/foo.cpp index ab5620d66f..8366ec0a06 100644 --- a/demos/qt5/foo.cpp +++ b/demos/qt5/foo.cpp @@ -3,7 +3,24 @@ #include "foo.h" Foo::Foo() : QWidget(NULL) { + m_button = new QPushButton("Foo Button", this); + m_button->setGeometry(QRect(QPoint(50, 60), + QSize(120, 50))); + connect(m_button, SIGNAL (released()), this, SLOT (handleButton())); + myToggle = true; +} + +void Foo::handleButton() { + if (myToggle) { + m_button->setText("Button Foo"); + } else { + m_button->setText("Foo Button"); + } + myToggle = !myToggle; +} +int Foo::FortyTwo() { + return 42; } class Bar_private : public QWidget { diff --git a/demos/qt5/foo.h b/demos/qt5/foo.h index e05b3e99b6..50820d6584 100644 --- a/demos/qt5/foo.h +++ b/demos/qt5/foo.h @@ -4,13 +4,20 @@ #define _FOO #include +#include class Foo : public QWidget { Q_OBJECT signals: void test(); + private slots: + void handleButton(); public: Foo(); + int FortyTwo(); + QPushButton *m_button; + public: + bool myToggle; }; #endif diff --git a/demos/qt5/main.cpp b/demos/qt5/main.cpp index 4f407c6cad..966a1af8ac 100644 --- a/demos/qt5/main.cpp +++ b/demos/qt5/main.cpp @@ -4,12 +4,13 @@ //#include //#include "mainwindow.h" #include "ui_but.h" +#include "foo.h" int main(int argc, char **argv) { Q_INIT_RESOURCE(res); QApplication app(argc, argv); - QWidget window; + Foo window; Ui::Form ui; ui.setupUi(&window); window.show(); diff --git a/demos/qt5/testqt5.cpp b/demos/qt5/testqt5.cpp new file mode 100644 index 0000000000..935539b2c1 --- /dev/null +++ b/demos/qt5/testqt5.cpp @@ -0,0 +1,31 @@ +// Example of Qt5 Unit test with QtTest library +// Federico Pellegrin, 2019 (fedepell) + +#include "foo.h" +#include + +class TestQt5Test: public QObject { + Q_OBJECT + private: + Foo myFoo; + private slots: + void testGui(); + void testFunc(); +}; + +// Test of the UI by simulating a button click and button label reading +void TestQt5Test::testGui() { + QCOMPARE(myFoo.m_button->text(), QString("Foo Button")); + QTest::mouseClick(myFoo.m_button,Qt::LeftButton,Qt::NoModifier,QPoint(5,5),0); + QCOMPARE(myFoo.m_button->text(), QString("Button Foo")); +} + +// Test of a normal function +void TestQt5Test::testFunc() { + QCOMPARE(myFoo.FortyTwo(), 44); // this fails! 42 != 44 +} + +QTEST_MAIN(TestQt5Test) + +#include "testqt5.moc" + diff --git a/demos/qt5/wscript b/demos/qt5/wscript index 5ab374c916..73eb052171 100644 --- a/demos/qt5/wscript +++ b/demos/qt5/wscript @@ -1,6 +1,7 @@ #! /usr/bin/env python # encoding: utf-8 # Thomas Nagy, 2016 (ita) +# Federico Pellegrin, 2019 (fedepell) VERSION='0.0.1' APPNAME='qt5_test' @@ -9,10 +10,10 @@ top = '.' out = 'build' def options(opt): - opt.load('compiler_cxx qt5') + opt.load('compiler_cxx qt5 waf_unit_test') def configure(conf): - conf.load('compiler_cxx qt5') + conf.load('compiler_cxx qt5 waf_unit_test') #conf.env.append_value('CXXFLAGS', ['-g']) # test def build(bld): @@ -32,3 +33,25 @@ def build(bld): langname = 'somefile', # include the .qm files from somefile.qrc ) + # Example of integration of Qt5 Unit tests using Qt5Test using waf_unit_test + bld( + features = 'qt5 cxx cxxprogram test', + use = 'QT5CORE QT5WIDGETS QT5TEST', + source = 'foo.cpp testqt5.cpp', + moc = 'foo.h', + target = 'footest', + includes = '.', + # ut_str = './${SRC} -o test-report.xml,xunitxml', # put output to a xunit xml + ) + + bld.add_post_fun(print_test_results) # print output of test runner to user + + +def print_test_results(bld): + lst = getattr(bld, 'utest_results', []) + if not lst: + return + for (f, code, out, err) in lst: + print(out.decode('utf-8')) + print(err.decode('utf-8')) + From a302e11f174091bae43c7e8afdfc23c581a42dbe Mon Sep 17 00:00:00 2001 From: fedepell Date: Thu, 6 Jun 2019 15:06:41 +0200 Subject: [PATCH 138/315] javaw: bugfix outdir is always a node (since converted in apply_javac) --- waflib/Tools/javaw.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/Tools/javaw.py b/waflib/Tools/javaw.py index fd1cf469ab..ceb08c28c8 100644 --- a/waflib/Tools/javaw.py +++ b/waflib/Tools/javaw.py @@ -246,7 +246,7 @@ def use_javac_files(self): self.javac_task.dep_nodes.extend(tg.jar_task.outputs) else: if hasattr(tg, 'outdir'): - base_node = tg.outdir.abspath() + base_node = tg.outdir else: base_node = tg.path.get_bld() From 4d74bb72d703f2808a1f1bd29c5b2eb279307620 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Thu, 6 Jun 2019 16:37:19 +0200 Subject: [PATCH 139/315] Rework "qt5 demo: add example of unit testing using QtTest" --- demos/qt5/testqt5.cpp | 3 ++- demos/qt5/wscript | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/demos/qt5/testqt5.cpp b/demos/qt5/testqt5.cpp index 935539b2c1..60c76ffbdd 100644 --- a/demos/qt5/testqt5.cpp +++ b/demos/qt5/testqt5.cpp @@ -3,6 +3,7 @@ #include "foo.h" #include +#include class TestQt5Test: public QObject { Q_OBJECT @@ -16,7 +17,7 @@ class TestQt5Test: public QObject { // Test of the UI by simulating a button click and button label reading void TestQt5Test::testGui() { QCOMPARE(myFoo.m_button->text(), QString("Foo Button")); - QTest::mouseClick(myFoo.m_button,Qt::LeftButton,Qt::NoModifier,QPoint(5,5),0); + QTest::mouseClick(myFoo.m_button, Qt::LeftButton,Qt::NoModifier, QPoint(5,5), 0); QCOMPARE(myFoo.m_button->text(), QString("Button Foo")); } diff --git a/demos/qt5/wscript b/demos/qt5/wscript index 73eb052171..c18fbf4550 100644 --- a/demos/qt5/wscript +++ b/demos/qt5/wscript @@ -36,7 +36,8 @@ def build(bld): # Example of integration of Qt5 Unit tests using Qt5Test using waf_unit_test bld( features = 'qt5 cxx cxxprogram test', - use = 'QT5CORE QT5WIDGETS QT5TEST', + use = 'QT5CORE QT5GUI QT5WIDGETS QT5TEST', + defines = 'QT_WIDGETS_LIB', source = 'foo.cpp testqt5.cpp', moc = 'foo.h', target = 'footest', From 608a6ee84d17a690fbace02b9f2bb16669bf841d Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Thu, 6 Jun 2019 16:45:24 +0200 Subject: [PATCH 140/315] Rework "qt5 demo: add example of unit testing using QtTest" --- demos/qt5/testqt5.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/demos/qt5/testqt5.cpp b/demos/qt5/testqt5.cpp index 60c76ffbdd..a855b3fc33 100644 --- a/demos/qt5/testqt5.cpp +++ b/demos/qt5/testqt5.cpp @@ -3,7 +3,6 @@ #include "foo.h" #include -#include class TestQt5Test: public QObject { Q_OBJECT From d9089d5da596e719c9adc886f8cead38fb655337 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Thu, 6 Jun 2019 17:57:33 +0200 Subject: [PATCH 141/315] Add a configuration test for: "qt5 demo: add example of unit testing using QtTest" --- demos/qt5/wscript | 50 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/demos/qt5/wscript b/demos/qt5/wscript index c18fbf4550..5b4dbd503e 100644 --- a/demos/qt5/wscript +++ b/demos/qt5/wscript @@ -16,6 +16,31 @@ def configure(conf): conf.load('compiler_cxx qt5 waf_unit_test') #conf.env.append_value('CXXFLAGS', ['-g']) # test + # These tests would run on Ubuntu but not on other platforms + conf.check( + define_name = 'XYZ_QT5_TESTS', + mandatory = False, + execute = True, + features = 'qt5 cxx cxxprogram', + includes = '.', + defines = 'QT_WIDGETS_LIB', + use = 'QT5CORE QT5GUI QT5WIDGETS QT5TEST', + msg = 'Checking whether Qt5 tests can run', + fragment = ''' +#include +class TestQt5Test: public QObject { + Q_OBJECT + private: + void testGui() { + QWidget *widget = NULL; + QTest::mouseClick(widget, Qt::LeftButton, Qt::NoModifier, QPoint(5,5), 0); + } +}; + +QTEST_MAIN(TestQt5Test) +#include "test.moc" +''') + def build(bld): # According to the Qt5 documentation: # Qt classes in foo.h -> declare foo.h as a header to be processed by moc @@ -33,19 +58,20 @@ def build(bld): langname = 'somefile', # include the .qm files from somefile.qrc ) - # Example of integration of Qt5 Unit tests using Qt5Test using waf_unit_test - bld( - features = 'qt5 cxx cxxprogram test', - use = 'QT5CORE QT5GUI QT5WIDGETS QT5TEST', - defines = 'QT_WIDGETS_LIB', - source = 'foo.cpp testqt5.cpp', - moc = 'foo.h', - target = 'footest', - includes = '.', - # ut_str = './${SRC} -o test-report.xml,xunitxml', # put output to a xunit xml - ) + if bld.env.XYZ_QT5_TESTS: + # Example of integration of Qt5 Unit tests using Qt5Test using waf_unit_test + bld( + features = 'qt5 cxx cxxprogram test', + use = 'QT5CORE QT5GUI QT5WIDGETS QT5TEST', + defines = 'QT_WIDGETS_LIB', + source = 'foo.cpp testqt5.cpp', + moc = 'foo.h', + target = 'footest', + includes = '.', + # ut_str = './${SRC} -o test-report.xml,xunitxml', # put output to a xunit xml + ) - bld.add_post_fun(print_test_results) # print output of test runner to user + bld.add_post_fun(print_test_results) # print output of test runner to user def print_test_results(bld): From d218cca0551e0a381a9c7b09d42255a5d7635b96 Mon Sep 17 00:00:00 2001 From: Federico Pellegrin Date: Thu, 6 Jun 2019 20:33:43 +0200 Subject: [PATCH 142/315] java demo: add test case for !2242 --- demos/java/bengala/src/org/example/Bengala.java | 14 ++++++++++++++ demos/java/bengala/wscript | 12 ++++++++++++ demos/java/wscript | 2 +- 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 demos/java/bengala/src/org/example/Bengala.java create mode 100644 demos/java/bengala/wscript diff --git a/demos/java/bengala/src/org/example/Bengala.java b/demos/java/bengala/src/org/example/Bengala.java new file mode 100644 index 0000000000..30f50b7013 --- /dev/null +++ b/demos/java/bengala/src/org/example/Bengala.java @@ -0,0 +1,14 @@ + +package org.example; + +//import org.example.Animal; +import org.example.Cat; + +class Bengala extends Cat { + + public String sound() { + return "Bengala Meow!"; + } + +} + diff --git a/demos/java/bengala/wscript b/demos/java/bengala/wscript new file mode 100644 index 0000000000..ad9d763536 --- /dev/null +++ b/demos/java/bengala/wscript @@ -0,0 +1,12 @@ +#! /usr/bin/env python + +def build(bld): + + bld(features = 'javac', + srcdir = 'src', + compat = '1.7', + use = 'cats-src', + name = 'bengala-cat', + recurse_use = True, + ) + diff --git a/demos/java/wscript b/demos/java/wscript index 9c927c7c13..4ee2f9525f 100644 --- a/demos/java/wscript +++ b/demos/java/wscript @@ -49,5 +49,5 @@ def build(bld): javadoc_output = 'javadoc', ) - bld.recurse('animals cats') + bld.recurse('animals cats bengala') From 65028f4bd0e76498bda7499a4f936fb3b6c13483 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eric=20M=C3=BCller?= Date: Mon, 25 Jun 2018 16:30:23 +0200 Subject: [PATCH 143/315] Fix local_rpath tool --- waflib/extras/local_rpath.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/waflib/extras/local_rpath.py b/waflib/extras/local_rpath.py index b2507e17a1..e3923d9b9d 100644 --- a/waflib/extras/local_rpath.py +++ b/waflib/extras/local_rpath.py @@ -2,18 +2,20 @@ # encoding: utf-8 # Thomas Nagy, 2011 (ita) +import copy from waflib.TaskGen import after_method, feature @after_method('propagate_uselib_vars') @feature('cprogram', 'cshlib', 'cxxprogram', 'cxxshlib', 'fcprogram', 'fcshlib') def add_rpath_stuff(self): - all = self.to_list(getattr(self, 'use', [])) + all = copy.copy(self.to_list(getattr(self, 'use', []))) while all: name = all.pop() try: tg = self.bld.get_tgen_by_name(name) except: continue - self.env.append_value('RPATH', tg.link_task.outputs[0].parent.abspath()) - all.extend(self.to_list(getattr(tg, 'use', []))) + if hasattr(tg, 'link_task'): + self.env.append_value('RPATH', tg.link_task.outputs[0].parent.abspath()) + all.extend(self.to_list(getattr(tg, 'use', []))) From 5b23b94841af6685da942ba45a41f06cc2b3dfdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eric=20M=C3=BCller?= Date: Thu, 22 Mar 2018 12:50:03 +0100 Subject: [PATCH 144/315] Use cross_prefix option for objcopy if available --- waflib/extras/objcopy.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/waflib/extras/objcopy.py b/waflib/extras/objcopy.py index 82d8359ecf..bb7ca6ef22 100644 --- a/waflib/extras/objcopy.py +++ b/waflib/extras/objcopy.py @@ -15,7 +15,7 @@ """ from waflib.Utils import def_attrs -from waflib import Task +from waflib import Task, Options from waflib.TaskGen import feature, after_method class objcopy(Task.Task): @@ -46,5 +46,8 @@ def map_objcopy(self): self.add_install_files(install_to=self.objcopy_install_path, install_from=task.outputs[0]) def configure(ctx): - ctx.find_program('objcopy', var='OBJCOPY', mandatory=True) - + program_name = 'objcopy' + prefix = getattr(Options.options, 'cross_prefix', None) + if prefix: + program_name = '{}-{}'.format(prefix, program_name) + ctx.find_program(program_name, var='OBJCOPY', mandatory=True) From 26848cbb47633e228f126dccc0d1d5485b76a2c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eric=20M=C3=BCller?= Date: Mon, 29 Oct 2018 10:02:31 +0100 Subject: [PATCH 145/315] Allow for flat install of python files via `py` feature --- waflib/Tools/python.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/waflib/Tools/python.py b/waflib/Tools/python.py index 63a8917d7c..5885b499bb 100644 --- a/waflib/Tools/python.py +++ b/waflib/Tools/python.py @@ -79,14 +79,19 @@ def process_py(self, node): """ Add signature of .py file, so it will be byte-compiled when necessary """ - assert(hasattr(self, 'install_path')), 'add features="py"' + assert(hasattr(self, 'install_path')), 'add features="py" for target "%s" in "%s/wscript".' % (self.target, self.path.nice_path()) + self.install_from = getattr(self, 'install_from', None) + relative_trick = getattr(self, 'relative_trick', True) + if self.install_from: + assert isinstance(self.install_from, Node.Node), \ + 'add features="py" for target "%s" in "%s/wscript" (%s).' % (self.target, self.path.nice_path(), type(self.install_from)) # where to install the python file if self.install_path: if self.install_from: - self.add_install_files(install_to=self.install_path, install_from=node, cwd=self.install_from, relative_trick=True) + self.add_install_files(install_to=self.install_path, install_from=node, cwd=self.install_from, relative_trick=relative_trick) else: - self.add_install_files(install_to=self.install_path, install_from=node, relative_trick=True) + self.add_install_files(install_to=self.install_path, install_from=node, relative_trick=relative_trick) lst = [] if self.env.PYC: @@ -96,9 +101,11 @@ def process_py(self, node): if self.install_path: if self.install_from: - pyd = Utils.subst_vars("%s/%s" % (self.install_path, node.path_from(self.install_from)), self.env) + target_dir = node.path_from(self.install_from) if relative_trick else node.name + pyd = Utils.subst_vars("%s/%s" % (self.install_path, target_dir), self.env) else: - pyd = Utils.subst_vars("%s/%s" % (self.install_path, node.path_from(self.path)), self.env) + target_dir = node.path_from(self.path) if relative_trick else node.name + pyd = Utils.subst_vars("%s/%s" % (self.install_path, target_dir), self.env) else: pyd = node.abspath() @@ -115,7 +122,7 @@ def process_py(self, node): tsk.pyd = pyd if self.install_path: - self.add_install_files(install_to=os.path.dirname(pyd), install_from=pyobj, cwd=node.parent.get_bld(), relative_trick=True) + self.add_install_files(install_to=os.path.dirname(pyd), install_from=pyobj, cwd=node.parent.get_bld(), relative_trick=relative_trick) class pyc(Task.Task): """ From 8c66c5caaea160176acbc34da2786f62080712ef Mon Sep 17 00:00:00 2001 From: Yannik Stradmann Date: Wed, 19 Jun 2019 23:46:27 +0200 Subject: [PATCH 146/315] Add demo for nested/flat python file installation --- demos/python/nested_scripts/bar/nested_bar.py | 3 +++ demos/python/nested_scripts/foo/nested_foo.py | 3 +++ demos/python/wscript | 18 ++++++++++++++++++ 3 files changed, 24 insertions(+) create mode 100644 demos/python/nested_scripts/bar/nested_bar.py create mode 100644 demos/python/nested_scripts/foo/nested_foo.py diff --git a/demos/python/nested_scripts/bar/nested_bar.py b/demos/python/nested_scripts/bar/nested_bar.py new file mode 100644 index 0000000000..f74f2b5a61 --- /dev/null +++ b/demos/python/nested_scripts/bar/nested_bar.py @@ -0,0 +1,3 @@ +""" +Nested file in bar/ +""" diff --git a/demos/python/nested_scripts/foo/nested_foo.py b/demos/python/nested_scripts/foo/nested_foo.py new file mode 100644 index 0000000000..ba64dcb61f --- /dev/null +++ b/demos/python/nested_scripts/foo/nested_foo.py @@ -0,0 +1,3 @@ +""" +Nested file in foo/ +""" diff --git a/demos/python/wscript b/demos/python/wscript index 07b5b666f1..07b071d526 100644 --- a/demos/python/wscript +++ b/demos/python/wscript @@ -50,3 +50,21 @@ def build(bld): source = 'test.c', target = 'test') + # Install files keeping their directory structure (default: relative_trick=True) + # + # This will create two files: + # * lib/python2.7/site-packages/nested_scripts/bar/nested_bar.py + # * lib/python2.7/site-packages/nested_scripts/foo/nested_foo.py + bld(features='py', + source=bld.path.ant_glob('nested_scripts/**/*.py'), + install_from='.') + + # Install files flatting the directory structure (relative_trick=False) + # + # This will create two files: + # * lib/python2.7/site-packages/nested_bar.py + # * lib/python2.7/site-packages/nested_foo.py + bld(features='py', + source=bld.path.ant_glob('nested_scripts/**/*.py'), + relative_trick=False, + install_from='.') From 29182711b1542972aa9b954faf899a393139fc7f Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Thu, 20 Jun 2019 23:14:51 +0200 Subject: [PATCH 147/315] Add -fno-strict-aliasing flags only if missing https://gitlab.com/ita1024/waf/merge_requests/2248/diffs --- waflib/Tools/python.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/waflib/Tools/python.py b/waflib/Tools/python.py index 5885b499bb..7c45a76ffd 100644 --- a/waflib/Tools/python.py +++ b/waflib/Tools/python.py @@ -440,11 +440,11 @@ def check_python_headers(conf, features='pyembed pyext'): # Code using the Python API needs to be compiled with -fno-strict-aliasing if env.CC_NAME == 'gcc': - env.append_value('CFLAGS_PYEMBED', ['-fno-strict-aliasing']) - env.append_value('CFLAGS_PYEXT', ['-fno-strict-aliasing']) + env.append_unique('CFLAGS_PYEMBED', ['-fno-strict-aliasing']) + env.append_unique('CFLAGS_PYEXT', ['-fno-strict-aliasing']) if env.CXX_NAME == 'gcc': - env.append_value('CXXFLAGS_PYEMBED', ['-fno-strict-aliasing']) - env.append_value('CXXFLAGS_PYEXT', ['-fno-strict-aliasing']) + env.append_unique('CXXFLAGS_PYEMBED', ['-fno-strict-aliasing']) + env.append_unique('CXXFLAGS_PYEXT', ['-fno-strict-aliasing']) if env.CC_NAME == "msvc": from distutils.msvccompiler import MSVCCompiler From c1bedeff2f3e69a329bfdeb7633ed01be1f317df Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 23 Jun 2019 08:42:42 +0200 Subject: [PATCH 148/315] Improve fast_partial compatibility #2240 --- waflib/extras/fast_partial.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/waflib/extras/fast_partial.py b/waflib/extras/fast_partial.py index 71b8318eec..b0465fe02b 100644 --- a/waflib/extras/fast_partial.py +++ b/waflib/extras/fast_partial.py @@ -18,6 +18,7 @@ def options(opt): opt.load('fast_partial') Assumptions: +* Start with a clean build (run "waf distclean" after enabling) * Mostly for C/C++/Fortran targets with link tasks (object-only targets are not handled) try it in the folder generated by utils/genbench.py * For full project builds: no --targets and no pruning from subfolders @@ -131,12 +132,18 @@ def store(self): data[x] = getattr(self, x) db = os.path.join(self.variant_dir, Context.DBFILE + self.store_key) - try: - waflib.Node.pickle_lock.acquire() + with waflib.Node.pickle_lock: waflib.Node.Nod3 = self.node_class - x = Build.cPickle.dumps(data, Build.PROTOCOL) - finally: - waflib.Node.pickle_lock.release() + try: + x = Build.cPickle.dumps(data, Build.PROTOCOL) + except Build.cPickle.PicklingError: + root = data['root'] + for node_deps in data['node_deps'].values(): + for idx, node in enumerate(node_deps): + # there may be more cross-context Node objects to fix, + # but this should be the main source + node_deps[idx] = root.find_node(node.abspath()) + x = Build.cPickle.dumps(data, Build.PROTOCOL) Logs.debug('rev_use: storing %s', db) Utils.writef(db + '.tmp', x, m='wb') From 04a70b969c433a1cc8bed5070dcc3c746a504845 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Tue, 25 Jun 2019 11:51:44 +0200 Subject: [PATCH 149/315] Improve the configuration cache accuracy --- waflib/Configure.py | 21 ++++++++++++++++----- waflib/Tools/c_tests.py | 3 ++- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/waflib/Configure.py b/waflib/Configure.py index db09c0e3a4..fff2f7a131 100644 --- a/waflib/Configure.py +++ b/waflib/Configure.py @@ -524,7 +524,7 @@ def run_build(self, *k, **kw): Though this function returns *0* by default, the build may set an attribute named *retval* on the build context object to return a particular value. See :py:func:`waflib.Tools.c_config.test_exec_fun` for example. - This function also provides a limited cache. To use it, provide the following option:: + This function also features a cache which can be enabled by the following option:: def options(opt): opt.add_option('--confcache', dest='confcache', default=0, @@ -535,10 +535,22 @@ def options(opt): $ waf configure --confcache """ - lst = [str(v) for (p, v) in kw.items() if p != 'env'] - h = Utils.h_list(lst) + buf = [] + for key in sorted(kw.keys()): + if key != 'env': + v = kw[key] + if hasattr(v, '__call__'): + buf.append(Utils.h_fun(v)) + else: + buf.append(str(v)) + h = Utils.h_list(buf) dir = self.bldnode.abspath() + os.sep + (not Utils.is_win32 and '.' or '') + 'conf_check_' + Utils.to_hex(h) + cachemode = kw.get('confcache', getattr(Options.options, 'confcache', None)) + + if not cachemode and os.path.exists(dir): + shutil.rmtree(dir) + try: os.makedirs(dir) except OSError: @@ -549,7 +561,6 @@ def options(opt): except OSError: self.fatal('cannot use the configuration test folder %r' % dir) - cachemode = getattr(Options.options, 'confcache', None) if cachemode == 1: try: proj = ConfigSet.ConfigSet(os.path.join(dir, 'cache_run_build')) @@ -589,7 +600,7 @@ def options(opt): else: ret = getattr(bld, 'retval', 0) finally: - if cachemode == 1: + if cachemode: # cache the results each time proj = ConfigSet.ConfigSet() proj['cache_run_build'] = ret diff --git a/waflib/Tools/c_tests.py b/waflib/Tools/c_tests.py index f858df5763..7a4094f245 100644 --- a/waflib/Tools/c_tests.py +++ b/waflib/Tools/c_tests.py @@ -224,6 +224,7 @@ def check_endianness(self): def check_msg(self): return tmp[0] self.check(fragment=ENDIAN_FRAGMENT, features='c grep_for_endianness', - msg='Checking for endianness', define='ENDIANNESS', tmp=tmp, okmsg=check_msg) + msg='Checking for endianness', define='ENDIANNESS', tmp=tmp, + okmsg=check_msg, confcache=None) return tmp[0] From 0085f08b76d638327c22b02d811e54e14d096d49 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Tue, 25 Jun 2019 11:53:00 +0200 Subject: [PATCH 150/315] Limit fast_partial.py failures on configuration tests --- waflib/extras/fast_partial.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/waflib/extras/fast_partial.py b/waflib/extras/fast_partial.py index b0465fe02b..90a94723bb 100644 --- a/waflib/extras/fast_partial.py +++ b/waflib/extras/fast_partial.py @@ -400,12 +400,17 @@ def is_stale(self): Logs.debug('rev_use: must post %r because this is a clean build') return True - # 3. check if the configuration changed - if os.stat(self.bld.bldnode.find_node('c4che/build.config.py').abspath()).st_mtime > dbstat: + # 3.a check if the configuration exists + cache_node = self.bld.bldnode.find_node('c4che/build.config.py') + if not cache_node: + return True + + # 3.b check if the configuration changed + if os.stat(cache_node.abspath()).st_mtime > dbstat: Logs.debug('rev_use: must post %r because the configuration has changed', self.name) return True - # 3.a any tstamp data? + # 3.c any tstamp data? try: f_deps = self.bld.f_deps except AttributeError: From 61d3a94941dbac5b52b93cf9a8f8e7b008c07805 Mon Sep 17 00:00:00 2001 From: Adriano Scoditti Date: Wed, 26 Jun 2019 10:59:17 +0200 Subject: [PATCH 151/315] Do not clean lock files in top and run dirs if no-lock opts are set --- waflib/Scripting.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/waflib/Scripting.py b/waflib/Scripting.py index ae17a8b450..68dccf29ce 100644 --- a/waflib/Scripting.py +++ b/waflib/Scripting.py @@ -332,7 +332,12 @@ def remove_and_log(k, fun): else: remove_and_log(env.out_dir, shutil.rmtree) - for k in (env.out_dir, env.top_dir, env.run_dir): + env_dirs = [env.out_dir] + if not ctx.options.no_lock_in_top: + env_dirs.append(env.top_dir) + if not ctx.options.no_lock_in_run: + env_dirs.append(env.run_dir) + for k in env_dirs: p = os.path.join(k, Options.lockfile) remove_and_log(p, os.remove) From d74ca88443b73f8edaf76806c919705db0c38ad4 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Wed, 26 Jun 2019 11:51:56 +0200 Subject: [PATCH 152/315] Fix PIE errors in demos/asm/ --- demos/asm/test.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demos/asm/test.S b/demos/asm/test.S index 31f487b1b4..827dc82411 100644 --- a/demos/asm/test.S +++ b/demos/asm/test.S @@ -15,7 +15,7 @@ mult10: pushq %rbp movq %rsp,%rbp - movl val,%eax + movabs val,%eax imull %edi,%eax popq %rbp From e1fb58bca0858689b9fb6611afa3410da29fa0c4 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Wed, 26 Jun 2019 12:03:29 +0200 Subject: [PATCH 153/315] Detect of assembly features in bld.program()/bld.shlib() --- demos/asm/wscript | 1 + waflib/Tools/c_aliases.py | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/demos/asm/wscript b/demos/asm/wscript index 6d9e5ea504..b17b57db5c 100644 --- a/demos/asm/wscript +++ b/demos/asm/wscript @@ -18,6 +18,7 @@ def build(bld): source = 'main.c test.S', target = 'asmtest', defines = 'foo=12', + asflags = '-Os', includes = '.') def disp(ctx): diff --git a/waflib/Tools/c_aliases.py b/waflib/Tools/c_aliases.py index c9d53692e8..985e048bdb 100644 --- a/waflib/Tools/c_aliases.py +++ b/waflib/Tools/c_aliases.py @@ -47,10 +47,12 @@ def sniff_features(**kw): if x in exts: feats.append('cxx') break - if 'c' in exts or 'vala' in exts or 'gs' in exts: feats.append('c') + if 's' in exts or 'S' in exts: + feats.append('asm') + for x in 'f f90 F F90 for FOR'.split(): if x in exts: feats.append('fc') @@ -66,7 +68,7 @@ def sniff_features(**kw): if typ in ('program', 'shlib', 'stlib'): will_link = False for x in feats: - if x in ('cxx', 'd', 'fc', 'c'): + if x in ('cxx', 'd', 'fc', 'c', 'asm'): feats.append(x + typ) will_link = True if not will_link and not kw.get('features', []): From 410cd6a0579f3843131a0600534386a8822b6edc Mon Sep 17 00:00:00 2001 From: Adriano Scoditti Date: Wed, 13 Feb 2019 09:49:06 +0100 Subject: [PATCH 154/315] Waf Pip integration through a setup.py in root --- setup.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 setup.py diff --git a/setup.py b/setup.py new file mode 100644 index 0000000000..83e94df3a6 --- /dev/null +++ b/setup.py @@ -0,0 +1,22 @@ +import setuptools +import waflib.Context + +with open("README.md", "r") as fh: + long_description = fh.read() + +setuptools.setup( + name="waf", + version=waflib.Context.WAFVERSION, + author="Thomas Nagy", + author_email="author@example.com", + description="Build Framework", + long_description=long_description, + long_description_content_type="text/markdown", + url="https://gitlab.com/ita1024/waf", + packages=['waflib', 'waflib/Tools', 'waflib/extras'], + classifiers=[ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + ], +) From fcd173f8830800abc566b26adaf2e15b124f33a2 Mon Sep 17 00:00:00 2001 From: Adriano Scoditti Date: Wed, 26 Jun 2019 11:49:07 +0200 Subject: [PATCH 155/315] Adds script section to install waf-light bin and make it look for waflib in PYTHONPATH --- setup.py | 1 + waf-light | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 83e94df3a6..510d448edb 100644 --- a/setup.py +++ b/setup.py @@ -14,6 +14,7 @@ long_description_content_type="text/markdown", url="https://gitlab.com/ita1024/waf", packages=['waflib', 'waflib/Tools', 'waflib/extras'], + scripts=['waf-light'], classifiers=[ "Programming Language :: Python :: 3", "License :: OSI Approved :: MIT License", diff --git a/waf-light b/waf-light index 8c50d0b125..1562d957a5 100755 --- a/waf-light +++ b/waf-light @@ -130,6 +130,15 @@ def test(dir): except OSError: pass +def test_syspath(): + for dir in sys.path: + try: + os.stat(join(dir, 'waflib')) + return True + except OSError: + pass + return False + def find_lib(): src = os.path.abspath(inspect.getfile(inspect.getmodule(err))) base, name = os.path.split(src) @@ -142,6 +151,7 @@ def find_lib(): if name.endswith('waf-light'): w = test(base) if w: return w + if test_syspath(): return None err('waf-light requires waflib -> export WAFDIR=/folder') dirname = '%s-%s-%s' % (WAF, VERSION, REVISION) @@ -159,7 +169,8 @@ def find_lib(): return dir wafdir = find_lib() -sys.path.insert(0, wafdir) +if wafdir is not None: + sys.path.insert(0, wafdir) if __name__ == '__main__': #import waflib.extras.compat15#PRELUDE From 84f3c8083fffefa980fe1d59b4afe43010750f58 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Wed, 26 Jun 2019 15:00:03 +0200 Subject: [PATCH 156/315] Add a dependency scanner for gas/yasm and nasm (incomplete) --- waflib/Tools/asm.py | 37 ++++++++++++++++++++++++++++++++++++- waflib/Tools/gas.py | 1 + waflib/Tools/nasm.py | 5 +++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/waflib/Tools/asm.py b/waflib/Tools/asm.py index b6f26fb3df..a57e83bb5e 100644 --- a/waflib/Tools/asm.py +++ b/waflib/Tools/asm.py @@ -34,9 +34,22 @@ def build(bld): target = 'asmtest') """ -from waflib import Task +import re +from waflib import Errors, Logs, Task from waflib.Tools.ccroot import link_task, stlink_task from waflib.TaskGen import extension +from waflib.Tools import c_preproc + +re_lines = re.compile( + '^[ \t]*(?:%)[ \t]*(ifdef|ifndef|if|else|elif|endif|include|import|define|undef)[ \t]*(.*)\r*$', + re.IGNORECASE | re.MULTILINE) + +class asm_parser(c_preproc.c_parser): + def filter_comments(self, node): + code = node.read() + code = c_preproc.re_nl.sub('', code) + code = c_preproc.re_cpp.sub(c_preproc.repl, code) + return re_lines.findall(code) class asm(Task.Task): """ @@ -45,6 +58,28 @@ class asm(Task.Task): color = 'BLUE' run_str = '${AS} ${ASFLAGS} ${ASMPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${AS_SRC_F}${SRC} ${AS_TGT_F}${TGT}' + def scan(self): + if self.env.ASM_NAME == 'gas': + return c_preproc.scan(self) + Logs.warn('There is no dependency scanner for Nasm!') + return [[], []] + elif self.env.ASM_NAME == 'nasm': + Logs.warn('The Nasm dependency scanner is incomplete!') + + try: + incn = self.generator.includes_nodes + except AttributeError: + raise Errors.WafError('%r is missing the "asm" feature' % self.generator) + + if c_preproc.go_absolute: + nodepaths = incn + else: + nodepaths = [x for x in incn if x.is_child_of(x.ctx.srcnode) or x.is_child_of(x.ctx.bldnode)] + + tmp = asm_parser(nodepaths) + tmp.start(self.inputs[0], self.env) + return (tmp.nodes, tmp.names) + @extension('.s', '.S', '.asm', '.ASM', '.spp', '.SPP') def asm_hook(self, node): """ diff --git a/waflib/Tools/gas.py b/waflib/Tools/gas.py index 77afed7038..4a8745afd7 100644 --- a/waflib/Tools/gas.py +++ b/waflib/Tools/gas.py @@ -16,3 +16,4 @@ def configure(conf): conf.env.ASLNK_TGT_F = ['-o'] conf.find_ar() conf.load('asm') + conf.env.ASM_NAME = 'gas' diff --git a/waflib/Tools/nasm.py b/waflib/Tools/nasm.py index 411d5826b5..9c51c18de1 100644 --- a/waflib/Tools/nasm.py +++ b/waflib/Tools/nasm.py @@ -24,3 +24,8 @@ def configure(conf): conf.env.ASLNK_TGT_F = ['-o'] conf.load('asm') conf.env.ASMPATH_ST = '-I%s' + os.sep + txt = conf.cmd_and_log(conf.env.AS + ['--version']) + if 'yasm' in txt.lower(): + conf.env.ASM_NAME = 'yasm' + else: + conf.env.ASM_NAME = 'nasm' From d59f103188458222e9b280699c4fda3568eab205 Mon Sep 17 00:00:00 2001 From: Adriano Scoditti Date: Wed, 26 Jun 2019 15:37:45 +0200 Subject: [PATCH 157/315] Removing the incorrect License description --- setup.py | 1 - 1 file changed, 1 deletion(-) diff --git a/setup.py b/setup.py index 510d448edb..785354e720 100644 --- a/setup.py +++ b/setup.py @@ -17,7 +17,6 @@ scripts=['waf-light'], classifiers=[ "Programming Language :: Python :: 3", - "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", ], ) From 0b5762939d02336a9b25cbc260ebf5c270ee3842 Mon Sep 17 00:00:00 2001 From: Adriano Scoditti Date: Wed, 26 Jun 2019 15:51:48 +0200 Subject: [PATCH 158/315] Move setup.py in subdir to unclutter the project root --- setup.py => utils/setup.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) rename setup.py => utils/setup.py (80%) diff --git a/setup.py b/utils/setup.py similarity index 80% rename from setup.py rename to utils/setup.py index 785354e720..69c3bfcbb2 100644 --- a/setup.py +++ b/utils/setup.py @@ -1,7 +1,9 @@ import setuptools +import sys +sys.path.insert(0,'..') import waflib.Context -with open("README.md", "r") as fh: +with open("../README.md", "r") as fh: long_description = fh.read() setuptools.setup( @@ -13,8 +15,9 @@ long_description=long_description, long_description_content_type="text/markdown", url="https://gitlab.com/ita1024/waf", + package_dir={'': '../'}, packages=['waflib', 'waflib/Tools', 'waflib/extras'], - scripts=['waf-light'], + scripts=['../waf-light'], classifiers=[ "Programming Language :: Python :: 3", "Operating System :: OS Independent", From cb73820a113cf315f0f3be6846a4288605a76cf7 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Thu, 27 Jun 2019 08:38:33 +0200 Subject: [PATCH 159/315] Ensure waf-light is first in sys.path (Pip integration) --- waf-light | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/waf-light b/waf-light index 1562d957a5..509e11693e 100755 --- a/waf-light +++ b/waf-light @@ -130,15 +130,6 @@ def test(dir): except OSError: pass -def test_syspath(): - for dir in sys.path: - try: - os.stat(join(dir, 'waflib')) - return True - except OSError: - pass - return False - def find_lib(): src = os.path.abspath(inspect.getfile(inspect.getmodule(err))) base, name = os.path.split(src) @@ -151,7 +142,9 @@ def find_lib(): if name.endswith('waf-light'): w = test(base) if w: return w - if test_syspath(): return None + for dir in sys.path: + if test(dir): + return dir err('waf-light requires waflib -> export WAFDIR=/folder') dirname = '%s-%s-%s' % (WAF, VERSION, REVISION) @@ -169,8 +162,7 @@ def find_lib(): return dir wafdir = find_lib() -if wafdir is not None: - sys.path.insert(0, wafdir) +sys.path.insert(0, wafdir) if __name__ == '__main__': #import waflib.extras.compat15#PRELUDE From 14bede5cdf69bd582fa7fd4948a20a2e5b5bd66d Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Thu, 27 Jun 2019 09:38:49 +0200 Subject: [PATCH 160/315] Fix a deadlock with cython+subst tasks #2244 --- ChangeLog | 9 +++++++++ waflib/TaskGen.py | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 3a13275164..c87c7d7b9e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +NEW IN WAF 2.0.18 +----------------- +* Fix a deadlock with cython and subst tasks #2244 +* Fix rpath processing so that it no longer breaks dependency chains +* Fix fast_partial.py failures on configuration tests +* Fix duplicate -fno-strict-aliasing flags in Python compilation flags detection +* Add a dependency scanner for assembly files (Gas/Yasm) +* Add a QtTest example to demos/qt5/ + NEW IN WAF 2.0.17 ----------------- * Improve build performance on FreeBSD and Python3 #2241 diff --git a/waflib/TaskGen.py b/waflib/TaskGen.py index 532b7d5cdb..f8f92bd57c 100644 --- a/waflib/TaskGen.py +++ b/waflib/TaskGen.py @@ -905,7 +905,7 @@ def build(bld): # paranoid safety measure for the general case foo.in->foo.h with ambiguous dependencies for xt in HEADER_EXTS: if b.name.endswith(xt): - tsk.ext_in = tsk.ext_in + ['.h'] + tsk.ext_out = tsk.ext_out + ['.h'] break inst_to = getattr(self, 'install_path', None) From e822fb5481316348dd28362b90263c9ce344446f Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Fri, 28 Jun 2019 08:47:33 +0200 Subject: [PATCH 161/315] Add a testcase for #2244: deadlock with cython+subst tasks --- playground/cython/c_lib/extra_dep.h.in | 2 ++ playground/cython/wscript | 30 +++++++++++++++++++++----- 2 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 playground/cython/c_lib/extra_dep.h.in diff --git a/playground/cython/c_lib/extra_dep.h.in b/playground/cython/c_lib/extra_dep.h.in new file mode 100644 index 0000000000..acc41c53cd --- /dev/null +++ b/playground/cython/c_lib/extra_dep.h.in @@ -0,0 +1,2 @@ + +#define bindir "@BINDIR@" diff --git a/playground/cython/wscript b/playground/cython/wscript index 1cdd8a41cb..eb2a5f7dc8 100644 --- a/playground/cython/wscript +++ b/playground/cython/wscript @@ -40,13 +40,13 @@ def build(ctx): target = 'cxx_lib', includes = 'cxx_lib') - # first try to build a C-based cython extension + # build a C-based cython extension ctx( features = 'c cshlib pyext', source = 'src/cy_ctest.pyx', target = 'cy_ctest', includes = 'c_lib', - use = 'c_lib') + use = 'c_lib') # then a C++-based one ctx( @@ -54,7 +54,7 @@ def build(ctx): source = 'src/cy_cxxtest.pyx', target = 'cy_cxxtest', includes = 'cxx_lib', - use = 'cxx_lib') + use = 'cxx_lib') # a C++ application which uses a C function from a cython module ctx( @@ -62,5 +62,25 @@ def build(ctx): source = 'cxx_lib/app.cxx', target = 'cy-app', includes = 'cxx_lib src', - use = 'cxx_lib' - ) + use = 'cxx_lib') + + # --------------------------------------------------------------- + # Testcase for #2244 below + + ctx.get_tgen_by_name('cy_ctest').features += ' subst_header_order' + + # a generated header for cy_ctest + ctx( + features = 'subst', + source = 'c_lib/extra_dep.h.in', + target = 'c_lib/extra_dep.h', + ) + + from waflib import TaskGen + @TaskGen.feature('subst_header_order') + @TaskGen.after('process_source') + def set_subst_before_cython_tasks(self): + tg = self.bld.get_tgen_by_name('c_lib/extra_dep.h') + tg.post() + for tsk in self.tasks: + tsk.run_after.add(tg.tasks[-1]) From 0c96b0f26f7139d1a53b3e9995f1f89b17363fa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johann=20Kl=C3=A4hn?= Date: Thu, 19 Oct 2017 16:07:59 +0200 Subject: [PATCH 162/315] Add genpybind feature --- waflib/extras/genpybind.py | 183 +++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 waflib/extras/genpybind.py diff --git a/waflib/extras/genpybind.py b/waflib/extras/genpybind.py new file mode 100644 index 0000000000..7cebe5149b --- /dev/null +++ b/waflib/extras/genpybind.py @@ -0,0 +1,183 @@ +import os +import pipes +import subprocess +import sys + +from waflib import Logs, Task, Context +from waflib.Tools.c_preproc import scan as scan_impl +# ^-- Note: waflib.extras.gccdeps.scan does not work for us, +# due to its current implementation: +# The -MD flag is injected into the {C,CXX}FLAGS environment variable and +# dependencies are read out in a separate step after compiling by reading +# the .d file saved alongside the object file. +# As the genpybind task refers to a header file that is never compiled itself, +# gccdeps will not be able to extract the list of dependencies. + +from waflib.TaskGen import feature, before_method + + +def join_args(args): + return " ".join(pipes.quote(arg) for arg in args) + + +def configure(cfg): + cfg.load("compiler_cxx") + cfg.load("python") + cfg.check_python_version(minver=(2, 7)) + if not cfg.env.LLVM_CONFIG: + cfg.find_program("llvm-config", var="LLVM_CONFIG") + if not cfg.env.GENPYBIND: + cfg.find_program("genpybind", var="GENPYBIND") + + +@feature("genpybind") +@before_method("process_source") +def generate_genpybind_source(self): + """ + Run genpybind on the headers provided in `source` and compile/link the + generated code instead. This works by generating the code on the fly and + swapping the source node before `process_source` is run. + """ + # name of module defaults to name of target + module = getattr(self, "module", self.target) + + # create temporary source file in build directory to hold generated code + out = "genpybind-%s.%d.cpp" % (module, self.idx) + out = self.path.get_bld().find_or_declare(out) + + task = self.create_task("genpybind", self.to_nodes(self.source), out) + # used to detect whether CFLAGS or CXXFLAGS should be passed to genpybind + task.features = self.features + task.module = module + # can be used to select definitions to include in the current module + # (when header files are shared by more than one module) + task.genpybind_tags = self.to_list(getattr(self, "genpybind_tags", [])) + # additional include directories + task.includes = self.to_list(getattr(self, "includes", [])) + task.genpybind = self.env.GENPYBIND + + # Tell waf to compile/link the generated code instead of the headers + # originally passed-in via the `source` parameter. (see `process_source`) + self.source = [out] + + +class genpybind(Task.Task): # pylint: disable=invalid-name + """ + Runs genpybind on headers provided as input to this task. + Generated code will be written to the first (and only) output node. + """ + quiet = True + color = "PINK" + scan = scan_impl + + @staticmethod + def keyword(): + return "Analyzing" + + def run(self): + if not self.inputs: + return + + args = self.find_genpybind() + self._arguments() + + output = self.run_genpybind(args) + + # For debugging / log output + pasteable_command = join_args(args) + + # write generated code to file in build directory + # (will be compiled during process_source stage) + (output_node,) = self.outputs + output_node.write("// {}\n{}\n".format( + pasteable_command.replace("\n", "\n// "), output)) + + def find_genpybind(self): + return self.genpybind + + def run_genpybind(self, args): + bld = self.generator.bld + + kwargs = dict(cwd=bld.variant_dir) + if hasattr(bld, "log_command"): + bld.log_command(args, kwargs) + else: + Logs.debug("runner: {!r}".format(args)) + proc = subprocess.Popen( + args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs) + stdout, stderr = proc.communicate() + + if not isinstance(stdout, str): + stdout = stdout.decode(sys.stdout.encoding, errors="replace") + if not isinstance(stderr, str): + stderr = stderr.decode(sys.stderr.encoding, errors="replace") + + if proc.returncode != 0: + bld.fatal( + "genpybind returned {code} during the following call:" + "\n{command}\n\n{stdout}\n\n{stderr}".format( + code=proc.returncode, + command=join_args(args), + stdout=stdout, + stderr=stderr, + )) + + if stderr.strip(): + Logs.debug("non-fatal warnings during genpybind run:\n{}".format(stderr)) + + return stdout + + def _include_paths(self): + return self.generator.to_incnodes(self.includes + self.env.INCLUDES) + + def _inputs_as_relative_includes(self): + include_paths = self._include_paths() + relative_includes = [] + for node in self.inputs: + for inc in include_paths: + if node.is_child_of(inc): + relative_includes.append(node.path_from(inc)) + break + else: + self.generator.bld.fatal("could not resolve {}".format(node)) + return relative_includes + + def _arguments(self, genpybind_parse=None, resource_dir=None): + args = [] + relative_includes = self._inputs_as_relative_includes() + is_cxx = "cxx" in self.features + + # options for genpybind + args.extend(["--genpybind-module", self.module]) + if self.genpybind_tags: + args.extend(["--genpybind-tag"] + self.genpybind_tags) + if relative_includes: + args.extend(["--genpybind-include"] + relative_includes) + if genpybind_parse: + args.extend(["--genpybind-parse", genpybind_parse]) + + args.append("--") + + # headers to be processed by genpybind + args.extend(node.abspath() for node in self.inputs) + + args.append("--") + + # options for clang/genpybind-parse + args.append("-D__GENPYBIND__") + args.append("-xc++" if is_cxx else "-xc") + has_std_argument = False + for flag in self.env["CXXFLAGS" if is_cxx else "CFLAGS"]: + flag = flag.replace("-std=gnu", "-std=c") + if flag.startswith("-std=c"): + has_std_argument = True + args.append(flag) + if not has_std_argument: + args.append("-std=c++14") + args.extend("-I{}".format(n.abspath()) for n in self._include_paths()) + args.extend("-D{}".format(p) for p in self.env.DEFINES) + + # point to clang resource dir, if specified + if resource_dir: + args.append("-resource-dir={}".format(resource_dir)) + + return args From d0985ab13710e915f8139139039fb01cdbce556b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20St=C3=B6ckel?= Date: Mon, 29 Jan 2018 11:39:15 +0100 Subject: [PATCH 163/315] Set resource-dir explicitly for genpybind-parse --- waflib/extras/genpybind.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/waflib/extras/genpybind.py b/waflib/extras/genpybind.py index 7cebe5149b..ac206ee8a8 100644 --- a/waflib/extras/genpybind.py +++ b/waflib/extras/genpybind.py @@ -29,6 +29,16 @@ def configure(cfg): if not cfg.env.GENPYBIND: cfg.find_program("genpybind", var="GENPYBIND") + # find clang reasource dir for builtin headers + cfg.env.GENPYBIND_RESOURCE_DIR = os.path.join( + cfg.cmd_and_log(cfg.env.LLVM_CONFIG + ["--libdir"]).strip(), + "clang", + cfg.cmd_and_log(cfg.env.LLVM_CONFIG + ["--version"]).strip()) + if os.path.exists(cfg.env.GENPYBIND_RESOURCE_DIR): + cfg.msg("Checking clang resource dir", cfg.env.GENPYBIND_RESOURCE_DIR) + else: + cfg.fatal("Clang resource dir not found") + @feature("genpybind") @before_method("process_source") @@ -78,7 +88,8 @@ def run(self): if not self.inputs: return - args = self.find_genpybind() + self._arguments() + args = self.find_genpybind() + self._arguments( + resource_dir=self.env.GENPYBIND_RESOURCE_DIR) output = self.run_genpybind(args) From f2e7dcf6ca3651c2f5255e6ac9c22d83d4266edf Mon Sep 17 00:00:00 2001 From: Yannik Stradmann Date: Tue, 2 Jul 2019 11:50:25 +0200 Subject: [PATCH 164/315] Add genpybind example --- playground/genpybind/example.cpp | 9 +++++++ playground/genpybind/example.h | 20 +++++++++++++++ playground/genpybind/example_test.py | 9 +++++++ playground/genpybind/wscript | 37 ++++++++++++++++++++++++++++ 4 files changed, 75 insertions(+) create mode 100644 playground/genpybind/example.cpp create mode 100644 playground/genpybind/example.h create mode 100644 playground/genpybind/example_test.py create mode 100644 playground/genpybind/wscript diff --git a/playground/genpybind/example.cpp b/playground/genpybind/example.cpp new file mode 100644 index 0000000000..a237e56f8f --- /dev/null +++ b/playground/genpybind/example.cpp @@ -0,0 +1,9 @@ +#include "example.h" + +constexpr int Example::not_exposed; + +int Example::calculate(int some_argument) const { return _value + some_argument; } + +int Example::getSomething() const { return _value; } + +void Example::setSomething(int value) { _value = value; } diff --git a/playground/genpybind/example.h b/playground/genpybind/example.h new file mode 100644 index 0000000000..9563637722 --- /dev/null +++ b/playground/genpybind/example.h @@ -0,0 +1,20 @@ +#pragma once + +#include "genpybind.h" + +class GENPYBIND(visible) Example { +public: + static constexpr int GENPYBIND(hidden) not_exposed = 10; + + /// \brief Do a complicated calculation. + int calculate(int some_argument = 5) const; + + GENPYBIND(getter_for(something)) + int getSomething() const; + + GENPYBIND(setter_for(something)) + void setSomething(int value); + +private: + int _value = 0; +}; diff --git a/playground/genpybind/example_test.py b/playground/genpybind/example_test.py new file mode 100644 index 0000000000..1384390945 --- /dev/null +++ b/playground/genpybind/example_test.py @@ -0,0 +1,9 @@ +import pyexample as m + + +def test_example(): + obj = m.Example() + obj.something = 42 + assert obj.something == 42 + assert obj.calculate() == 47 # with default argument + assert obj.calculate(2) == 44 diff --git a/playground/genpybind/wscript b/playground/genpybind/wscript new file mode 100644 index 0000000000..1732ec83d1 --- /dev/null +++ b/playground/genpybind/wscript @@ -0,0 +1,37 @@ +#!/usr/bin/env python + + +def options(opt): + opt.load('python') + opt.load('compiler_cxx') + opt.load('genpybind') + + +def configure(cfg): + cfg.load('python') + cfg.load('compiler_cxx') + cfg.check_python_version((2, 7)) + cfg.check_python_headers() + cfg.load('genpybind') + + cfg.check(compiler='cxx', + features='cxx pyext', + uselib_store='PYBIND11GENPYBIND_EXAMPLE', + mandatory=True, + header_name='pybind11/pybind11.h') + + +def build(bld): + bld(target='example_inc', + export_includes='.') + + bld.shlib(target='example', + source='example.cpp', + features='use', + use='example_inc') + + bld(target='pyexample', + source='example.h', + genpybind_tags='genpybind_example', + features='use genpybind cxx cxxshlib pyext', + use=['PYBIND11GENPYBIND_EXAMPLE', 'example']) From ec83305903af810e683b0c16af65a890e1fec9a1 Mon Sep 17 00:00:00 2001 From: Philipp Spilger Date: Fri, 5 Jul 2019 10:38:10 +0000 Subject: [PATCH 165/315] Fix doxygen task-gen. pars input before processing * OUTPUT_DIRECTORY now is created for a present parameter in `pars` of the task. --- waflib/extras/doxygen.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/waflib/extras/doxygen.py b/waflib/extras/doxygen.py index 423d845502..20cd9e1a85 100644 --- a/waflib/extras/doxygen.py +++ b/waflib/extras/doxygen.py @@ -85,6 +85,12 @@ def runnable_status(self): if not getattr(self, 'pars', None): txt = self.inputs[0].read() self.pars = parse_doxy(txt) + + # Override with any parameters passed to the task generator + if getattr(self.generator, 'pars', None): + for k, v in self.generator.pars.items(): + self.pars[k] = v + if self.pars.get('OUTPUT_DIRECTORY'): # Use the path parsed from the Doxyfile as an absolute path output_node = self.inputs[0].parent.get_bld().make_node(self.pars['OUTPUT_DIRECTORY']) @@ -94,11 +100,6 @@ def runnable_status(self): output_node.mkdir() self.pars['OUTPUT_DIRECTORY'] = output_node.abspath() - # Override with any parameters passed to the task generator - if getattr(self.generator, 'pars', None): - for k, v in self.generator.pars.items(): - self.pars[k] = v - self.doxy_inputs = getattr(self, 'doxy_inputs', []) if not self.pars.get('INPUT'): self.doxy_inputs.append(self.inputs[0].parent) From 5e91bf9af7cafefa35ad07ab8bc2a01c51d51456 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Mon, 8 Jul 2019 19:23:50 +0200 Subject: [PATCH 166/315] Make the configuration cache more accurate #2251 --- waflib/Configure.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/waflib/Configure.py b/waflib/Configure.py index fff2f7a131..5762eb6695 100644 --- a/waflib/Configure.py +++ b/waflib/Configure.py @@ -537,12 +537,11 @@ def options(opt): """ buf = [] for key in sorted(kw.keys()): - if key != 'env': - v = kw[key] - if hasattr(v, '__call__'): - buf.append(Utils.h_fun(v)) - else: - buf.append(str(v)) + v = kw[key] + if hasattr(v, '__call__'): + buf.append(Utils.h_fun(v)) + else: + buf.append(str(v)) h = Utils.h_list(buf) dir = self.bldnode.abspath() + os.sep + (not Utils.is_win32 and '.' or '') + 'conf_check_' + Utils.to_hex(h) From 7782dc92a2973335100bc463c805d8b6646aa086 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Thu, 11 Jul 2019 07:48:40 +0200 Subject: [PATCH 167/315] Add executable arguments for configuration tests / execute=True conf.check(..., execute=True, test_args=['--abc=def']) --- demos/c/wscript | 7 +++++-- waflib/Tools/c_config.py | 9 +++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/demos/c/wscript b/demos/c/wscript index 979651e55e..c02184b095 100644 --- a/demos/c/wscript +++ b/demos/c/wscript @@ -27,12 +27,15 @@ def configure(conf): conf.check(fragment='int main() { return 0; }\n', features='c') try: - conf.check(fragment="int main() { return 0; }\n", execute=True) # 1 + conf.check(fragment="int main(int argc, char* argv[]) { return 0; }\n", execute=True) # 1 except conf.errors.WafError: Logs.warn('You are probably using a cross-compiler (disabling specific configuration tests)') conf.check_library(test_exec=False) else: - conf.check(fragment="""#include\nint main(){fprintf(stderr, "mu"); printf("%d", 22);return 0;}\n""", execute=True, define_name='HAVE_MU') + conf.check(fragment="""#include\nint main(){fprintf(stderr, "mu"); printf("%d", 22);return 0;}\n""", + msg='Checking for exec results', execute=True, define_name='HAVE_MU') + conf.check(fragment='int main(int argc, char* argv[]) { return argc - 2;}', + msg='Checking for test arguments', test_args=['--foo=bar'], execute=True) conf.check_library(test_exec=True) conf.check(lib='m', cflags='-Wall', defines=['var=foo', 'x=y'], uselib_store='M', mandatory=False) diff --git a/waflib/Tools/c_config.py b/waflib/Tools/c_config.py index 0977dabf26..43ae1507d8 100644 --- a/waflib/Tools/c_config.py +++ b/waflib/Tools/c_config.py @@ -659,20 +659,21 @@ class test_exec(Task.Task): """ color = 'PINK' def run(self): + cmd = [self.inputs[0].abspath()] + getattr(self.generator, 'test_args', []) if getattr(self.generator, 'rpath', None): if getattr(self.generator, 'define_ret', False): - self.generator.bld.retval = self.generator.bld.cmd_and_log([self.inputs[0].abspath()]) + self.generator.bld.retval = self.generator.bld.cmd_and_log(cmd) else: - self.generator.bld.retval = self.generator.bld.exec_command([self.inputs[0].abspath()]) + self.generator.bld.retval = self.generator.bld.exec_command(cmd) else: env = self.env.env or {} env.update(dict(os.environ)) for var in ('LD_LIBRARY_PATH', 'DYLD_LIBRARY_PATH', 'PATH'): env[var] = self.inputs[0].parent.abspath() + os.path.pathsep + env.get(var, '') if getattr(self.generator, 'define_ret', False): - self.generator.bld.retval = self.generator.bld.cmd_and_log([self.inputs[0].abspath()], env=env) + self.generator.bld.retval = self.generator.bld.cmd_and_log(cmd, env=env) else: - self.generator.bld.retval = self.generator.bld.exec_command([self.inputs[0].abspath()], env=env) + self.generator.bld.retval = self.generator.bld.exec_command(cmd, env=env) @feature('test_exec') @after_method('apply_link') From c4fd5bcf4ac94091fb0ad7ba4bf02412ba83b275 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Thu, 11 Jul 2019 19:13:14 +0200 Subject: [PATCH 168/315] Update the environment to IronPython 2.7.9 --- .pipelines/Jenkinsfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pipelines/Jenkinsfile b/.pipelines/Jenkinsfile index eef191b369..d3044f0c61 100644 --- a/.pipelines/Jenkinsfile +++ b/.pipelines/Jenkinsfile @@ -270,8 +270,8 @@ cd tests/install_group/ bat ''' copy waf demos\\c /Y cd demos\\c - "C:\\Program Files (x86)\\IronPython 2.7\\ipy64.exe" waf distclean - "C:\\Program Files (x86)\\IronPython 2.7\\ipy64.exe" waf configure build build + "C:\\Program Files\\IronPython 2.7\\ipy.exe" waf distclean + "C:\\Program Files\\IronPython 2.7\\ipy.exe" waf configure build build ''' } } From af13fcbd449284463f72591e5b08655c998e331d Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Thu, 11 Jul 2019 19:52:03 +0200 Subject: [PATCH 169/315] IronPython is broken --- .pipelines/Jenkinsfile | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/.pipelines/Jenkinsfile b/.pipelines/Jenkinsfile index d3044f0c61..c41dd29cb1 100644 --- a/.pipelines/Jenkinsfile +++ b/.pipelines/Jenkinsfile @@ -256,22 +256,6 @@ cd tests/install_group/ set WD=C:\\msys64\\usr\\bin set CHERE_INVOKING=1 C:\\msys64\\usr\\bin\\sh --login -c 'exec /bin/bash -c "python3 waf configure clean build && python3 waf distclean"' - ''' - } - } - stage('C/IronPython') { - agent { - label "windows" - } - steps { - bat ''' - C:/Python34/python.exe waf-light --zip-type=gz - ''' - bat ''' - copy waf demos\\c /Y - cd demos\\c - "C:\\Program Files\\IronPython 2.7\\ipy.exe" waf distclean - "C:\\Program Files\\IronPython 2.7\\ipy.exe" waf configure build build ''' } } From 8ef6fa586134717984f0637785592a11dbb68da8 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 14 Jul 2019 10:44:58 +0200 Subject: [PATCH 170/315] waf-2.0.18 --- ChangeLog | 8 +++++++- waf-light | 2 +- waflib/Context.py | 6 +++--- wscript | 2 +- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index c87c7d7b9e..a95e2b7f63 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,8 +4,14 @@ NEW IN WAF 2.0.18 * Fix rpath processing so that it no longer breaks dependency chains * Fix fast_partial.py failures on configuration tests * Fix duplicate -fno-strict-aliasing flags in Python compilation flags detection +* Fix annoying PIE errors in demos/asm/ +* Improve configuration tests cache accuracy #2251 +* Improve extras/fast_partial.py compatibility +* Improve extras/doxygen.py outdir parameter settings #2255 * Add a dependency scanner for assembly files (Gas/Yasm) -* Add a QtTest example to demos/qt5/ +* Add executable arguments for configuration tests / execute=True +* Add a QtTest example to demos/qt5/ #2241 +* Add a cross-compilation option to extras/objcopy.py #2247 NEW IN WAF 2.0.17 ----------------- diff --git a/waf-light b/waf-light index 509e11693e..713170e00b 100755 --- a/waf-light +++ b/waf-light @@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. import os, sys, inspect -VERSION="2.0.17" +VERSION="2.0.18" REVISION="x" GIT="x" INSTALL="x" diff --git a/waflib/Context.py b/waflib/Context.py index d0759aada5..e3305fa334 100644 --- a/waflib/Context.py +++ b/waflib/Context.py @@ -11,13 +11,13 @@ import waflib.Node # the following 3 constants are updated on each new release (do not touch) -HEXVERSION=0x2001100 +HEXVERSION=0x2001200 """Constant updated on new releases""" -WAFVERSION="2.0.17" +WAFVERSION="2.0.18" """Constant updated on new releases""" -WAFREVISION="6bc6cb599c702e985780e9f705b291b812123693" +WAFREVISION="314689b8994259a84f0de0aaef74d7ce91f541ad" """Git revision when the waf version is updated""" ABI = 20 diff --git a/wscript b/wscript index 76067794e7..75a6ec84f2 100644 --- a/wscript +++ b/wscript @@ -11,7 +11,7 @@ To add a tool that does not exist in the folder compat15, pass an absolute path: from __future__ import with_statement -VERSION="2.0.17" +VERSION="2.0.18" APPNAME='waf' REVISION='' From d645e598721c57ea7454194ac4d11a52a2f7570c Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Tue, 30 Jul 2019 18:45:07 +0200 Subject: [PATCH 171/315] Disable lto for the endianness configuration test #2250 --- waflib/Tools/c_tests.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/waflib/Tools/c_tests.py b/waflib/Tools/c_tests.py index 7a4094f245..253e08efa7 100644 --- a/waflib/Tools/c_tests.py +++ b/waflib/Tools/c_tests.py @@ -223,8 +223,11 @@ def check_endianness(self): tmp = [] def check_msg(self): return tmp[0] + + ltoflags = [x for x in self.env.CFLAGS if x.startswith('-flto')] + cflags = ['-fno-lto'] if len(ltoflags) else [] self.check(fragment=ENDIAN_FRAGMENT, features='c grep_for_endianness', msg='Checking for endianness', define='ENDIANNESS', tmp=tmp, - okmsg=check_msg, confcache=None) + okmsg=check_msg, confcache=None, cflags=cflags) return tmp[0] From 3cdd87bd7b7c453f7593afb62c5525581b08ec70 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Wed, 31 Jul 2019 21:04:53 +0200 Subject: [PATCH 172/315] Improve endianness detection --- waflib/Tools/c_tests.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/waflib/Tools/c_tests.py b/waflib/Tools/c_tests.py index 253e08efa7..2711719f31 100644 --- a/waflib/Tools/c_tests.py +++ b/waflib/Tools/c_tests.py @@ -208,12 +208,12 @@ def run(self): return -1 @feature('grep_for_endianness') -@after_method('process_source') +@after_method('apply_link') def grep_for_endianness_fun(self): """ Used by the endianness configuration test """ - self.create_task('grep_for_endianness', self.compiled_tasks[0].outputs[0]) + self.create_task('grep_for_endianness', self.link_task.outputs[0]) @conf def check_endianness(self): @@ -224,10 +224,8 @@ def check_endianness(self): def check_msg(self): return tmp[0] - ltoflags = [x for x in self.env.CFLAGS if x.startswith('-flto')] - cflags = ['-fno-lto'] if len(ltoflags) else [] - self.check(fragment=ENDIAN_FRAGMENT, features='c grep_for_endianness', + self.check(fragment=ENDIAN_FRAGMENT, features='c cshlib grep_for_endianness', msg='Checking for endianness', define='ENDIANNESS', tmp=tmp, - okmsg=check_msg, confcache=None, cflags=cflags) + okmsg=check_msg, confcache=None) return tmp[0] From fba789dc19afe396e8265c0a2be0fabb35dab149 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Thu, 1 Aug 2019 21:23:46 +0200 Subject: [PATCH 173/315] Add a new file-based waf cache implementation --- waflib/extras/wafcache.py | 410 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 410 insertions(+) create mode 100644 waflib/extras/wafcache.py diff --git a/waflib/extras/wafcache.py b/waflib/extras/wafcache.py new file mode 100644 index 0000000000..c3fcce6bc6 --- /dev/null +++ b/waflib/extras/wafcache.py @@ -0,0 +1,410 @@ +#! /usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2019 (ita) + +""" +Filesystem-based cache system to share and re-use build artifacts + +The following environment variables may be set: +* WAFCACHE: absolute path of the waf cache (/tmp/wafcache_user, + where `user` represents the currently logged-in user) +* WAFCACHE_TRIM_MAX_FOLDER: maximum amount of tasks to cache (1M) +* WAFCACHE_EVICT_MAX_BYTES: maximum amount of cache size in bytes (10GB) +* WAFCACHE_EVICT_INTERVAL_MINUTES: minimum time interval to try + and trim the cache (3 minutess) + +Cache access operations (copy to and from) are delegated to pre-forked +subprocesses. Though these processes perform atomic copies, they +are unaware of other processes running on the system + +The files are copied using hard links by default; if the cache is located +onto another partition, the system switches to file copies instead. + +Usage:: + + def build(bld): + bld.load('wafcache') + ... +""" + +import atexit, base64, errno, fcntl, getpass, os, shutil, sys, threading, time +try: + import subprocess32 as subprocess +except ImportError: + import subprocess + +CACHE_DIR = os.environ.get('WAFCACHE', '/tmp/wafcache_' + getpass.getuser()) +TRIM_MAX_FOLDERS = int(os.environ.get('WAFCACHE_TRIM_MAX_FOLDER', 1000000)) +EVICT_INTERVAL_MINUTES = int(os.environ.get('WAFCACHE_EVICT_INTERVAL_MINUTES', 3)) +EVICT_MAX_BYTES = int(os.environ.get('WAFCACHE_EVICT_MAX_BYTES', 10**10)) +OK = "ok" + +try: + import cPickle +except ImportError: + import pickle as cPickle + +if __name__ != '__main__': + from waflib import Task, Logs, Utils, Build + +def can_retrieve_cache(self): + """ + New method for waf Task classes + """ + if not self.outputs: + return False + + self.cached = False + + sig = self.signature() + ssig = Utils.to_hex(self.uid() + sig) + + files_to = [node.abspath() for node in self.outputs] + err = cache_command(ssig, [], files_to) + if not err.startswith(OK): + if Logs.verbose: + Logs.debug('wafcache: error getting from cache %s', err) + return False + + self.cached = True + return True + +def put_files_cache(self): + """ + New method for waf Task classes + """ + if not self.outputs: + return + + if getattr(self, 'cached', None): + return + + bld = self.generator.bld + sig = self.signature() + ssig = Utils.to_hex(self.uid() + sig) + + files_from = [node.abspath() for node in self.outputs] + err = cache_command(ssig, files_from, []) + + if not err.startswith(OK): + if Logs.verbose: + Logs.debug('wafcache: error caching %s', err) + + bld.task_sigs[self.uid()] = self.cache_sig + +def hash_env_vars(self, env, vars_lst): + """ + Reimplement BuildContext.hash_env_vars so that the resulting hash does not depend on local paths + """ + if not env.table: + env = env.parent + if not env: + return Utils.SIG_NIL + + idx = str(id(env)) + str(vars_lst) + try: + cache = self.cache_env + except AttributeError: + cache = self.cache_env = {} + else: + try: + return self.cache_env[idx] + except KeyError: + pass + + v = str([env[a] for a in vars_lst]) + v = v.replace(self.srcnode.abspath().__repr__()[:-1], '') + m = Utils.md5() + m.update(v.encode()) + ret = m.digest() + + Logs.debug('envhash: %r %r', ret, v) + + cache[idx] = ret + + return ret + +def uid(self): + """ + Reimplement Task.uid() so that the signature does not depend on local paths + """ + try: + return self.uid_ + except AttributeError: + m = Utils.md5() + src = self.generator.bld.srcnode + up = m.update + up(self.__class__.__name__.encode()) + for x in self.inputs + self.outputs: + up(x.path_from(src).encode()) + self.uid_ = m.digest() + return self.uid_ + + +def make_cached(cls): + """ + Enable the waf cache for a given task class + """ + if getattr(cls, 'nocache', None) or getattr(cls, 'has_cache', False): + return + + m1 = getattr(cls, 'run', None) + def run(self): + if getattr(self, 'nocache', False): + return m1(self) + if self.can_retrieve_cache(): + return 0 + return m1(self) + cls.run = run + + m2 = getattr(cls, 'post_run', None) + def post_run(self): + if getattr(self, 'nocache', False): + return m2(self) + ret = m2(self) + self.put_files_cache() + if hasattr(self, 'chmod'): + for node in self.outputs: + os.chmod(node.abspath(), self.chmod) + return ret + cls.post_run = post_run + cls.has_cache = True + +process_pool = [] +def get_process(): + """ + Returns a worker process that can process waf cache commands + The worker process is assumed to be returned to the process pool when unused + """ + try: + return process_pool.pop() + except IndexError: + filepath = os.path.dirname(os.path.abspath(__file__)) + os.sep + 'wafcache.py' + cmd = [sys.executable, '-c', Utils.readf(filepath)] + return subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE, bufsize=0) + +def atexit_pool(): + for k in process_pool: + try: + os.kill(k.pid, 9) + except OSError: + pass + else: + k.wait() +atexit.register(atexit_pool) + +def build(bld): + """ + Called during the build process to enable file caching + """ + if process_pool: + # already called once + return + + for x in range(bld.jobs): + process_pool.append(get_process()) + + Task.Task.can_retrieve_cache = can_retrieve_cache + Task.Task.put_files_cache = put_files_cache + Task.Task.uid = uid + Build.BuildContext.hash_env_vars = hash_env_vars + for x in Task.classes.values(): + make_cached(x) + +def cache_command(sig, files_from, files_to): + """ + Create a command for cache worker processes, returns a pickled + base64-encoded tuple containing the task signature, a list of files to + cache and a list of files files to get from cache (one of the lists + is assumed to be empty) + """ + proc = get_process() + + obj = base64.b64encode(cPickle.dumps([sig, files_from, files_to])) + proc.stdin.write(obj) + proc.stdin.write('\n'.encode()) + proc.stdin.flush() + obj = proc.stdout.readline() + if not obj: + raise OSError('Preforked sub-process %r died' % proc.pid) + process_pool.append(proc) + return cPickle.loads(base64.b64decode(obj)) + +try: + copyfun = os.link +except NameError: + copyfun = shutil.copy2 + +def atomic_copy(orig, dest): + """ + Copy files to the cache, the operation is atomic for a given file + """ + global copyfun + tmp = dest + '.tmp' + up = os.path.dirname(dest) + try: + os.makedirs(up) + except OSError: + pass + + try: + copyfun(orig, tmp) + except OSError as e: + if e.errno == errno.EXDEV: + copyfun = shutil.copy2 + copyfun(orig, tmp) + else: + raise + os.rename(tmp, dest) + +def lru_trim(): + """ + the cache folders take the form: + `CACHE_DIR/0b/0b180f82246d726ece37c8ccd0fb1cde2650d7bfcf122ec1f169079a3bfc0ab9` + they are listed in order of last access, and then removed + until the amount of folders is within TRIM_MAX_FOLDERS and the total space + taken by files is less than EVICT_MAX_BYTES + """ + lst = [] + for up in os.listdir(CACHE_DIR): + if len(up) == 2: + sub = os.path.join(CACHE_DIR, up) + for hval in os.listdir(sub): + path = os.path.join(sub, hval) + + size = 0 + for fname in os.listdir(path): + size += os.lstat(os.path.join(path, fname)).st_size + lst.append((os.stat(path).st_mtime, size, path)) + + lst.sort(key=lambda x: x[0]) + lst.reverse() + + tot = sum(x[1] for x in lst) + while tot > EVICT_MAX_BYTES or len(lst) > TRIM_MAX_FOLDERS: + _, tmp_size, path = lst.pop() + tot -= tmp_size + + tmp = path + '.tmp' + try: + shutil.rmtree(tmp) + except OSError: + pass + try: + os.rename(path, tmp) + except OSError: + sys.stderr.write('Could not rename %r to %r' % (path, tmp)) + else: + try: + shutil.rmtree(tmp) + except OSError: + sys.stderr.write('Could not remove %r' % tmp) + sys.stderr.write("Cache trimmed: %r bytes in %r folders left\n" % (tot, len(lst))) + + +def lru_evict(): + """ + Reduce the cache size + """ + lockfile = os.path.join(CACHE_DIR, 'all.lock') + try: + st = os.stat(lockfile) + except EnvironmentError as e: + if e.errno == errno.ENOENT: + with open(lockfile, 'w') as f: + f.write(''.encode()) + return + else: + raise + + if st.st_mtime < time.time() - EVICT_INTERVAL_MINUTES * 60: + # check every EVICT_INTERVAL_MINUTES minutes if the cache is too big + # OCLOEXEC is unnecessary because no processes are spawned + fd = os.open(lockfile, os.O_RDWR | os.O_CREAT, 0o755) + try: + try: + fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB) + except EnvironmentError: + sys.stderr.write('another process is running!\n') + pass + else: + # now dow the actual cleanup + lru_trim() + os.utime(lockfile, None) + finally: + os.close(fd) + +def copy_to_cache(sig, files_from, files_to): + """ + Copy files to the cache, existing files are overwritten, + and the copy is atomic only for a given file, not for all files + that belong to a given task object + """ + try: + for i, x in enumerate(files_from): + dest = os.path.join(CACHE_DIR, sig[:2], sig, str(i)) + atomic_copy(x, dest) + except EnvironmentError: + # no errors should be raised + pass + else: + # attempt trimming if caching was successful: + # we may have things to trim! + lru_evict() + +def copy_from_cache(sig, files_from, files_to): + """ + Copy files from the cache + """ + try: + for i, x in enumerate(files_to): + orig = os.path.join(CACHE_DIR, sig[:2], sig, str(i)) + atomic_copy(orig, x) + + # success! update the cache time + os.utime(os.path.join(CACHE_DIR, sig[:2], sig), None) + except EnvironmentError as e: + return "Failed to copy %r to %r: %s" % (orig, x, e) + return OK + +def loop(): + """ + This function is run when this file is run as a standalone python script, + it assumes a parent process that will communicate the commands to it + as pickled-encoded tuples (one line per command) + + The commands are to copy files to the cache or copy files from the + cache to a target destination + """ + # one operation is performed at a single time by a single process + # therefore stdin never has more than one line + txt = sys.stdin.readline().strip() + if not txt: + # parent process probably ended + sys.exit(1) + ret = OK + + [sig, files_from, files_to] = cPickle.loads(base64.b64decode(txt)) + if files_from: + # pushing to cache is done without any wait + th = threading.Thread(target=copy_to_cache, args=(sig, files_from, files_to)) + th.setDaemon(True) + th.start() + elif files_to: + # the build process waits for workers to (possibly) obtain files from the cache + ret = copy_from_cache(sig, files_from, files_to) + else: + ret = "Invalid command" + + obj = base64.b64encode(cPickle.dumps(ret)) + sys.stdout.write(obj.decode()) + sys.stdout.write('\n') + sys.stdout.flush() + +if __name__ == '__main__': + while 1: + try: + loop() + except KeyboardInterrupt: + break + From 5b0d7b097e38d60df875d3a1725269dc81caeb70 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Wed, 14 Aug 2019 22:05:45 +0200 Subject: [PATCH 174/315] Conceal imp warnings in Python3 --- waflib/Context.py | 9 ++++++++- waflib/Tools/python.py | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/waflib/Context.py b/waflib/Context.py index e3305fa334..4760bc8201 100644 --- a/waflib/Context.py +++ b/waflib/Context.py @@ -6,10 +6,17 @@ Classes and functions enabling the command system """ -import os, re, imp, sys +import os, re, sys from waflib import Utils, Errors, Logs import waflib.Node +if sys.hexversion > 0x3040000: + import types + class imp(object): + new_module = lambda x: types.ModuleType(x) +else: + import imp + # the following 3 constants are updated on each new release (do not touch) HEXVERSION=0x2001200 """Constant updated on new releases""" diff --git a/waflib/Tools/python.py b/waflib/Tools/python.py index 7c45a76ffd..b1c8dd0128 100644 --- a/waflib/Tools/python.py +++ b/waflib/Tools/python.py @@ -620,7 +620,7 @@ def configure(conf): v.PYO = getattr(Options.options, 'pyo', 1) try: - v.PYTAG = conf.cmd_and_log(conf.env.PYTHON + ['-c', "import imp;print(imp.get_tag())"]).strip() + v.PYTAG = conf.cmd_and_log(conf.env.PYTHON + ['-c', "import sys\ntry:\n print(sys.implementation.cache_tag)\nexcept AttributeError:\n import imp\n print(imp.get_tag())\n"]).strip() except Errors.WafError: pass From 2c7251f1c58c3796ef967e7563bd29e983b13e85 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Wed, 14 Aug 2019 22:20:01 +0200 Subject: [PATCH 175/315] Simplify the Python examples --- demos/python/wscript | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/demos/python/wscript b/demos/python/wscript index 07b071d526..0d662b63e9 100644 --- a/demos/python/wscript +++ b/demos/python/wscript @@ -52,19 +52,17 @@ def build(bld): # Install files keeping their directory structure (default: relative_trick=True) # - # This will create two files: - # * lib/python2.7/site-packages/nested_scripts/bar/nested_bar.py + # This will create: # * lib/python2.7/site-packages/nested_scripts/foo/nested_foo.py bld(features='py', - source=bld.path.ant_glob('nested_scripts/**/*.py'), + source=bld.path.ant_glob('nested_scripts/foo/*.py'), install_from='.') # Install files flatting the directory structure (relative_trick=False) # - # This will create two files: + # This will create: # * lib/python2.7/site-packages/nested_bar.py - # * lib/python2.7/site-packages/nested_foo.py bld(features='py', - source=bld.path.ant_glob('nested_scripts/**/*.py'), + source=bld.path.ant_glob('nested_scripts/bar/*.py'), relative_trick=False, install_from='.') From e00eb749ce5c9fd6208c17d66e51823bb82a772c Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 25 Aug 2019 22:31:12 +0200 Subject: [PATCH 176/315] Enable wafcache remote servers --- waflib/extras/wafcache.py | 120 +++++++++++++++++++++++++++----------- 1 file changed, 85 insertions(+), 35 deletions(-) diff --git a/waflib/extras/wafcache.py b/waflib/extras/wafcache.py index c3fcce6bc6..7ad5317e58 100644 --- a/waflib/extras/wafcache.py +++ b/waflib/extras/wafcache.py @@ -8,6 +8,11 @@ The following environment variables may be set: * WAFCACHE: absolute path of the waf cache (/tmp/wafcache_user, where `user` represents the currently logged-in user) + or a URL to a cache server, for example: + export WAFCACHE=http://localhost:8080/files/ + in that case, GET/POST requests are made to urls of the form + http://localhost:8080/files/000000000/0 (cache + management is then up to the server) * WAFCACHE_TRIM_MAX_FOLDER: maximum amount of tasks to cache (1M) * WAFCACHE_EVICT_MAX_BYTES: maximum amount of cache size in bytes (10GB) * WAFCACHE_EVICT_INTERVAL_MINUTES: minimum time interval to try @@ -27,7 +32,7 @@ def build(bld): ... """ -import atexit, base64, errno, fcntl, getpass, os, shutil, sys, threading, time +import atexit, base64, errno, fcntl, getpass, os, shutil, sys, threading, time, urllib3 try: import subprocess32 as subprocess except ImportError: @@ -334,40 +339,81 @@ def lru_evict(): finally: os.close(fd) -def copy_to_cache(sig, files_from, files_to): - """ - Copy files to the cache, existing files are overwritten, - and the copy is atomic only for a given file, not for all files - that belong to a given task object - """ - try: - for i, x in enumerate(files_from): - dest = os.path.join(CACHE_DIR, sig[:2], sig, str(i)) - atomic_copy(x, dest) - except EnvironmentError: - # no errors should be raised - pass - else: - # attempt trimming if caching was successful: - # we may have things to trim! - lru_evict() +class netcache(object): + def __init__(self): + self.http = urllib3.PoolManager() + + def url_of(self, sig, i): + return "%s/%s/%s" % (CACHE_DIR, sig, i) + + def upload(self, file_path, sig, i): + url = self.url_of(sig, i) + with open(file_path, 'rb') as f: + file_data = f.read() + r = self.http.request('POST', url, timeout=60, + fields={ 'file': ('%s/%s' % (sig, i), file_data), }) + if r.status >= 400: + raise OSError("Invalid status %r %r" % (url, r.status)) + + def download(self, file_path, sig, i): + url = self.url_of(sig, i) + with self.http.request('GET', url, preload_content=False, timeout=60) as inf: + if inf.status >= 400: + raise OSError("Invalid status %r %r" % (url, inf.status)) + with open(file_path, 'wb') as out: + shutil.copyfileobj(inf, out) + + def copy_to_cache(self, sig, files_from, files_to): + try: + for i, x in enumerate(files_from): + if not os.path.islink(x): + self.upload(x, sig, i) + except EnvironmentError: + pass -def copy_from_cache(sig, files_from, files_to): - """ - Copy files from the cache - """ - try: - for i, x in enumerate(files_to): - orig = os.path.join(CACHE_DIR, sig[:2], sig, str(i)) - atomic_copy(orig, x) + def copy_from_cache(self, sig, files_from, files_to): + try: + for i, x in enumerate(files_to): + self.download(x, sig, i) + return OK + except EnvironmentError as e: + return "Failed to download %r to %r: %s" % (files_from, files_to, e) + +class fcache(object): + def copy_to_cache(self, sig, files_from, files_to): + """ + Copy files to the cache, existing files are overwritten, + and the copy is atomic only for a given file, not for all files + that belong to a given task object + """ + try: + for i, x in enumerate(files_from): + dest = os.path.join(CACHE_DIR, sig[:2], sig, str(i)) + atomic_copy(x, dest) + except EnvironmentError: + # no errors should be raised + pass + else: + # attempt trimming if caching was successful: + # we may have things to trim! + lru_evict() + + def copy_from_cache(self, sig, files_from, files_to): + """ + Copy files from the cache + """ + try: + for i, x in enumerate(files_to): + orig = os.path.join(CACHE_DIR, sig[:2], sig, str(i)) + atomic_copy(orig, x) - # success! update the cache time - os.utime(os.path.join(CACHE_DIR, sig[:2], sig), None) - except EnvironmentError as e: - return "Failed to copy %r to %r: %s" % (orig, x, e) - return OK + # success! update the cache time + os.utime(os.path.join(CACHE_DIR, sig[:2], sig), None) + except EnvironmentError as e: + return "Failed to copy %r to %r: %s" % (files_from, files_to, e) + return OK -def loop(): +def loop(service): """ This function is run when this file is run as a standalone python script, it assumes a parent process that will communicate the commands to it @@ -387,12 +433,12 @@ def loop(): [sig, files_from, files_to] = cPickle.loads(base64.b64decode(txt)) if files_from: # pushing to cache is done without any wait - th = threading.Thread(target=copy_to_cache, args=(sig, files_from, files_to)) + th = threading.Thread(target=service.copy_to_cache, args=(sig, files_from, files_to)) th.setDaemon(True) th.start() elif files_to: # the build process waits for workers to (possibly) obtain files from the cache - ret = copy_from_cache(sig, files_from, files_to) + ret = service.copy_from_cache(sig, files_from, files_to) else: ret = "Invalid command" @@ -402,9 +448,13 @@ def loop(): sys.stdout.flush() if __name__ == '__main__': + if CACHE_DIR.startswith('http'): + service = netcache() + else: + service = fcache() while 1: try: - loop() + loop(service) except KeyboardInterrupt: break From 70a68fd8920520f90d6c87c51c97925faf308cae Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 1 Sep 2019 09:30:36 +0200 Subject: [PATCH 177/315] Add WAFCACHE_NO_PUSH to extras/wafcache --- waflib/extras/wafcache.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/waflib/extras/wafcache.py b/waflib/extras/wafcache.py index 7ad5317e58..f4053d6f73 100644 --- a/waflib/extras/wafcache.py +++ b/waflib/extras/wafcache.py @@ -17,6 +17,7 @@ * WAFCACHE_EVICT_MAX_BYTES: maximum amount of cache size in bytes (10GB) * WAFCACHE_EVICT_INTERVAL_MINUTES: minimum time interval to try and trim the cache (3 minutess) +* WAFCACHE_NO_PUSH: if set, disables pushing to the cache Cache access operations (copy to and from) are delegated to pre-forked subprocesses. Though these processes perform atomic copies, they @@ -42,6 +43,7 @@ def build(bld): TRIM_MAX_FOLDERS = int(os.environ.get('WAFCACHE_TRIM_MAX_FOLDER', 1000000)) EVICT_INTERVAL_MINUTES = int(os.environ.get('WAFCACHE_EVICT_INTERVAL_MINUTES', 3)) EVICT_MAX_BYTES = int(os.environ.get('WAFCACHE_EVICT_MAX_BYTES', 10**10)) +WAFCACHE_NO_PUSH = 1 if os.environ.get('WAFCACHE_NO_PUSH') else 0 OK = "ok" try: @@ -78,10 +80,7 @@ def put_files_cache(self): """ New method for waf Task classes """ - if not self.outputs: - return - - if getattr(self, 'cached', None): + if WAFCACHE_NO_PUSH or getattr(self, 'cached', None) or not self.outputs: return bld = self.generator.bld From 43fafa1ab0739cb3e3a15cd688a5de035ed70d79 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Sun, 8 Sep 2019 20:05:37 +0000 Subject: [PATCH 178/315] clang_compilation_database: fix #2247, add clangdb command to generate database by request without rebuilding, add tests (WIP) --- playground/clang_compilation_database/a.c | 0 playground/clang_compilation_database/b.cpp | 0 playground/clang_compilation_database/wscript | 68 +++++++ waflib/extras/clang_compilation_database.py | 174 ++++++++++++------ 4 files changed, 181 insertions(+), 61 deletions(-) create mode 100644 playground/clang_compilation_database/a.c create mode 100644 playground/clang_compilation_database/b.cpp create mode 100644 playground/clang_compilation_database/wscript diff --git a/playground/clang_compilation_database/a.c b/playground/clang_compilation_database/a.c new file mode 100644 index 0000000000..e69de29bb2 diff --git a/playground/clang_compilation_database/b.cpp b/playground/clang_compilation_database/b.cpp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/playground/clang_compilation_database/wscript b/playground/clang_compilation_database/wscript new file mode 100644 index 0000000000..06c2d9f5e9 --- /dev/null +++ b/playground/clang_compilation_database/wscript @@ -0,0 +1,68 @@ +#! /usr/bin/env python +# encoding: utf-8 +# Alibek Omarov, 2019 (a1batross) + +import os +from waflib import ConfigSet, Logs + +VERSION='0.0.1' +APPNAME='clang_compilation_database_test' + +top = '.' +out = 'build' + +INCLUDES_TO_TEST = ['common'] # check if include flag appeared in result json +DEFINES_TO_TEST = ['TEST'] # check if definition flag will appear in result json +SOURCE_FILES_TO_TEST = ['a.c', 'b.cpp'] # check if source files are persist in database + +def actual_test(bld): + db = bld.bldnode.find_node('compile_commands.json').read_json() + + for entry in db: + env = ConfigSet.ConfigSet() + line = ' '.join(entry['arguments'][1:]) # ignore compiler exe, unneeded + directory = entry['directory'] + srcname = entry['file'].split(os.sep)[-1] # file name only + + bld.parse_flags(line, 'test', env) # ignore unhandled flag, it's harmless for test + + if bld.bldnode.abspath() in directory: + Logs.info('Directory test passed') + else: + Logs.error('Directory test failed') + + if srcname in SOURCE_FILES_TO_TEST: + Logs.info('Source file test passed') + else: + Logs.error('Source file test failed') + + passed = True + for inc in INCLUDES_TO_TEST: + if inc not in env.INCLUDES_test: + passed = False + + if passed: Logs.info('Includes test passed') + else: Logs.error('Includes test failed') + + passed = True + for define in DEFINES_TO_TEST: + if define not in env.DEFINES_test: + passed = False + if passed: Logs.info('Defines test passed') + else: Logs.error('Defines test failed') + +def options(opt): + # check by ./waf clangdb + opt.load('compiler_c compiler_cxx clang_compilation_database') + +def configure(conf): + # check if database always generated before build + conf.load('compiler_c compiler_cxx clang_compilation_database') + +def build(bld): + bld.shlib(features = 'c cxx', source = SOURCE_FILES_TO_TEST, + defines = DEFINES_TO_TEST, + includes = INCLUDES_TO_TEST, + target = 'test') + + bld.add_post_fun(actual_test) diff --git a/waflib/extras/clang_compilation_database.py b/waflib/extras/clang_compilation_database.py index 4d9b5e275a..46fd40a8f2 100644 --- a/waflib/extras/clang_compilation_database.py +++ b/waflib/extras/clang_compilation_database.py @@ -1,6 +1,7 @@ #!/usr/bin/env python # encoding: utf-8 # Christoph Koke, 2013 +# Alibek Omarov, 2019 """ Writes the c and cpp compile commands into build/compile_commands.json @@ -8,14 +9,24 @@ Usage: - def configure(conf): - conf.load('compiler_cxx') - ... - conf.load('clang_compilation_database') + Load this tool in `options` to be able to generate database + by request in command-line and before build: + + $ waf clangdb + + def options(opt): + opt.load('clang_compilation_database') + + Otherwise, load only in `configure` to generate it always before build. + + def configure(conf): + conf.load('compiler_cxx') + ... + conf.load('clang_compilation_database') """ -import sys, os, json, shlex, pipes -from waflib import Logs, TaskGen, Task +import os +from waflib import Logs, TaskGen, Task, Build, Scripting Task.Task.keep_last_cmd = True @@ -23,63 +34,104 @@ def configure(conf): @TaskGen.after_method('process_use') def collect_compilation_db_tasks(self): "Add a compilation database entry for compiled tasks" - try: - clang_db = self.bld.clang_compilation_database_tasks - except AttributeError: - clang_db = self.bld.clang_compilation_database_tasks = [] - self.bld.add_post_fun(write_compilation_database) + if not isinstance(self.bld, ClangDbContext): + return tup = tuple(y for y in [Task.classes.get(x) for x in ('c', 'cxx')] if y) for task in getattr(self, 'compiled_tasks', []): if isinstance(task, tup): - clang_db.append(task) - -def write_compilation_database(ctx): - "Write the clang compilation database as JSON" - database_file = ctx.bldnode.make_node('compile_commands.json') - Logs.info('Build commands will be stored in %s', database_file.path_from(ctx.path)) - try: - root = json.load(database_file) - except IOError: - root = [] - clang_db = dict((x['file'], x) for x in root) - for task in getattr(ctx, 'clang_compilation_database_tasks', []): + self.bld.clang_compilation_database_tasks.append(task) + +class ClangDbContext(Build.BuildContext): + '''generates compile_commands.json by request''' + cmd = 'clangdb' + clang_compilation_database_tasks = [] + + def write_compilation_database(self): + """ + Write the clang compilation database as JSON + """ + database_file = self.bldnode.make_node('compile_commands.json') + Logs.info('Build commands will be stored in %s', database_file.path_from(self.path)) try: - cmd = task.last_cmd - except AttributeError: - continue - directory = getattr(task, 'cwd', ctx.variant_dir) - f_node = task.inputs[0] - filename = os.path.relpath(f_node.abspath(), directory) - entry = { - "directory": directory, - "arguments": cmd, - "file": filename, - } - clang_db[filename] = entry - root = list(clang_db.values()) - database_file.write(json.dumps(root, indent=2)) - -# Override the runnable_status function to do a dummy/dry run when the file doesn't need to be compiled. -# This will make sure compile_commands.json is always fully up to date. -# Previously you could end up with a partial compile_commands.json if the build failed. -for x in ('c', 'cxx'): - if x not in Task.classes: - continue - - t = Task.classes[x] - - def runnable_status(self): - def exec_command(cmd, **kw): - pass - - run_status = self.old_runnable_status() - if run_status == Task.SKIP_ME: - setattr(self, 'old_exec_command', getattr(self, 'exec_command', None)) - setattr(self, 'exec_command', exec_command) - self.run() - setattr(self, 'exec_command', getattr(self, 'old_exec_command', None)) - return run_status - - setattr(t, 'old_runnable_status', getattr(t, 'runnable_status', None)) - setattr(t, 'runnable_status', runnable_status) + root = database_file.read_json() + except IOError: + root = [] + clang_db = dict((x['file'], x) for x in root) + for task in self.clang_compilation_database_tasks: + try: + cmd = task.last_cmd + except AttributeError: + continue + directory = getattr(task, 'cwd', self.variant_dir) + f_node = task.inputs[0] + filename = os.path.relpath(f_node.abspath(), directory) + entry = { + "directory": directory, + "arguments": cmd, + "file": filename, + } + clang_db[filename] = entry + root = list(clang_db.values()) + database_file.write_json(root) + + def execute(self): + """ + Build dry run + """ + self.restore() + + if not self.all_envs: + self.load_envs() + + self.recurse([self.run_dir]) + self.pre_build() + + # we need only to generate last_cmd, so override + # exec_command temporarily + def exec_command(self, *k, **kw): + return 0 + + for g in self.groups: + for tg in g: + try: + f = tg.post + except AttributeError: + pass + else: + f() + + if isinstance(tg, Task.Task): + lst = [tg] + else: lst = tg.tasks + for tsk in lst: + tup = tuple(y for y in [Task.classes.get(x) for x in ('c', 'cxx')] if y) + if isinstance(tsk, tup): + old_exec = tsk.exec_command + tsk.exec_command = exec_command + tsk.run() + tsk.exec_command = old_exec + + self.write_compilation_database() + +EXECUTE_PATCHED = False +def patch_execute(): + global EXECUTE_PATCHED + + if EXECUTE_PATCHED: + return + + def new_execute_build(self): + """ + Invoke clangdb command before build + """ + if type(self) == Build.BuildContext: + Scripting.run_command('clangdb') + + old_execute_build(self) + + old_execute_build = getattr(Build.BuildContext, 'execute_build', None) + setattr(Build.BuildContext, 'execute_build', new_execute_build) + EXECUTE_PATCHED = True + +patch_execute() From 33cc2952623c0a0c934c261cb4fd42923aa9e8c5 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 8 Sep 2019 22:51:09 +0200 Subject: [PATCH 179/315] Unbreak the endianness test with msvc --- waflib/Tools/c_tests.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/waflib/Tools/c_tests.py b/waflib/Tools/c_tests.py index 2711719f31..bdd186c6bc 100644 --- a/waflib/Tools/c_tests.py +++ b/waflib/Tools/c_tests.py @@ -180,9 +180,15 @@ def check_large_file(self, **kw): ######################################################################################## ENDIAN_FRAGMENT = ''' +#ifdef _MSC_VER +#define testshlib_EXPORT __declspec(dllexport) +#else +#define testshlib_EXPORT +#endif + short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; -int use_ascii (int i) { +int testshlib_EXPORT use_ascii (int i) { return ascii_mm[i] + ascii_ii[i]; } short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; From 64b55b32390ba455c08f932a95bf6608c03872c7 Mon Sep 17 00:00:00 2001 From: Federico Pellegrin Date: Tue, 10 Sep 2019 09:55:17 +0200 Subject: [PATCH 180/315] pytest: add handling also of java dependencies via CLASSPATH (ie. JEP/Jython) --- waflib/extras/pytest.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/waflib/extras/pytest.py b/waflib/extras/pytest.py index 7dd5a1a087..fc9ad1c23e 100644 --- a/waflib/extras/pytest.py +++ b/waflib/extras/pytest.py @@ -40,6 +40,8 @@ - `pytest_libpath` attribute is used to manually specify additional linker paths. +3. Java class search path (CLASSPATH) of any Java/Javalike dependency + Note: `pytest` cannot automatically determine the correct `PYTHONPATH` for `pyext` taskgens because the extension might be part of a Python package or used standalone: @@ -119,6 +121,7 @@ def pytest_process_use(self): self.pytest_use_seen = [] self.pytest_paths = [] # strings or Nodes self.pytest_libpaths = [] # strings or Nodes + self.pytest_javapaths = [] # strings or Nodes self.pytest_dep_nodes = [] names = self.to_list(getattr(self, 'use', [])) @@ -157,6 +160,17 @@ def extend_unique(lst, varlst): extend_unique(self.pytest_dep_nodes, tg.source) extend_unique(self.pytest_paths, [pypath.abspath()]) + if 'javac' in tg.features: + # If a JAR is generated point to that, otherwise to directory + if getattr(tg, 'jar_task', None): + extend_unique(self.pytest_javapaths, [tg.jar_task.outputs[0].abspath()]) + else: + extend_unique(self.pytest_javapaths, [tg.path.get_bld()]) + + # And add respective dependencies if present + if tg.use_lst: + extend_unique(self.pytest_javapaths, tg.use_lst) + if getattr(tg, 'link_task', None): # For tasks with a link_task (C, C++, D et.c.) include their library paths: if not isinstance(tg.link_task, ccroot.stlink_task): @@ -212,8 +226,9 @@ def add_paths(var, lst): Logs.debug("ut: %s: Adding paths %s=%s", self, var, lst) self.ut_env[var] = os.pathsep.join(lst) + os.pathsep + self.ut_env.get(var, '') - # Prepend dependency paths to PYTHONPATH and LD_LIBRARY_PATH + # Prepend dependency paths to PYTHONPATH, CLASSPATH and LD_LIBRARY_PATH add_paths('PYTHONPATH', self.pytest_paths) + add_paths('CLASSPATH', self.pytest_javapaths) if Utils.is_win32: add_paths('PATH', self.pytest_libpaths) From f40bf14d4c8595943329a5521680240390ed53d2 Mon Sep 17 00:00:00 2001 From: Federico Pellegrin Date: Fri, 13 Sep 2019 09:23:39 +0200 Subject: [PATCH 181/315] swig playground: fix build for Python 3.x --- playground/swig/embed/src1.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/playground/swig/embed/src1.cpp b/playground/swig/embed/src1.cpp index 25f84820f0..a760dc7ba1 100644 --- a/playground/swig/embed/src1.cpp +++ b/playground/swig/embed/src1.cpp @@ -3,7 +3,11 @@ extern "C" { +#if PY_VERSION_HEX >= 0x03000000 + void PyInit__swigdemo(void); +#else void init_swigdemo(void); +#endif } TestClass* TestClass::_instance = 0; @@ -11,7 +15,11 @@ TestClass* TestClass::_instance = 0; int main() { Py_Initialize(); +#if PY_VERSION_HEX >= 0x03000000 + PyInit__swigdemo(); +#else init_swigdemo(); +#endif /*FILE* file_py; file_py = fopen(i_oFile.toLocal8Bit(), "r"); From d0f1d75d6dce0cca4bfa64d748af2d45c044f774 Mon Sep 17 00:00:00 2001 From: Federico Pellegrin Date: Fri, 13 Sep 2019 22:24:28 +0000 Subject: [PATCH 182/315] javatest: manage environment also for non-java dependencies (ie. JNI / JEP) --- playground/javatest/jni/java/StringUtils.java | 27 ++++ .../javatest/jni/jni/include/StringUtils.h | 29 +++++ .../javatest/jni/jni/source/StringUtils.c | 51 ++++++++ playground/javatest/jni/test/TestJni.java | 20 +++ playground/javatest/jni/test/testng.xml | 11 ++ playground/javatest/wscript | 27 +++- waflib/extras/javatest.py | 119 ++++++++++++++++-- 7 files changed, 274 insertions(+), 10 deletions(-) create mode 100644 playground/javatest/jni/java/StringUtils.java create mode 100644 playground/javatest/jni/jni/include/StringUtils.h create mode 100644 playground/javatest/jni/jni/source/StringUtils.c create mode 100644 playground/javatest/jni/test/TestJni.java create mode 100644 playground/javatest/jni/test/testng.xml diff --git a/playground/javatest/jni/java/StringUtils.java b/playground/javatest/jni/java/StringUtils.java new file mode 100644 index 0000000000..39ec05c407 --- /dev/null +++ b/playground/javatest/jni/java/StringUtils.java @@ -0,0 +1,27 @@ +public final class StringUtils +{ + + public static final String LIBRARY_NAME = "stringUtils"; + + static + { + System.loadLibrary(LIBRARY_NAME); + } + + private StringUtils() + { + } + + public static native boolean isAlpha(String string); + + public static native boolean isEmpty(String string); + + public static void main(String[] args) + { + System.out.println(StringUtils.isAlpha("sureIs")); + System.out.println(StringUtils.isAlpha("nope!")); + System.out.println(StringUtils.isEmpty(" ")); + System.out.println(StringUtils.isEmpty("nope")); + } + +} diff --git a/playground/javatest/jni/jni/include/StringUtils.h b/playground/javatest/jni/jni/include/StringUtils.h new file mode 100644 index 0000000000..2064f96dcf --- /dev/null +++ b/playground/javatest/jni/jni/include/StringUtils.h @@ -0,0 +1,29 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class StringUtils */ + +#ifndef _Included_StringUtils +#define _Included_StringUtils +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: StringUtils + * Method: isAlpha + * Signature: (Ljava/lang/String;)Z + */ +JNIEXPORT jboolean JNICALL Java_StringUtils_isAlpha + (JNIEnv *, jclass, jstring); + +/* + * Class: StringUtils + * Method: isEmpty + * Signature: (Ljava/lang/String;)Z + */ +JNIEXPORT jboolean JNICALL Java_StringUtils_isEmpty + (JNIEnv *, jclass, jstring); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/playground/javatest/jni/jni/source/StringUtils.c b/playground/javatest/jni/jni/source/StringUtils.c new file mode 100644 index 0000000000..d6567ab195 --- /dev/null +++ b/playground/javatest/jni/jni/source/StringUtils.c @@ -0,0 +1,51 @@ +#include "StringUtils.h" +#include +#include + +JNIEXPORT jboolean JNICALL Java_StringUtils_isAlpha(JNIEnv *env, jclass clazz, + jstring jStr) +{ + jboolean ret = JNI_TRUE; + char *sp = NULL, *s = NULL; + + if (!jStr) + return JNI_FALSE; + + s = (char*)(*env)->GetStringUTFChars(env, jStr, 0); + sp = s + strlen(s); + if (sp <= s) + ret = JNI_FALSE; + do + { + if (!isalpha(*(--sp))) + ret = JNI_FALSE; + } + while (sp > s); + + (*env)->ReleaseStringUTFChars(env, jStr, s); + return ret; +} + +JNIEXPORT jboolean JNICALL Java_StringUtils_isEmpty(JNIEnv *env, jclass clazz, + jstring jStr) +{ + jboolean ret = JNI_TRUE; + char *sp = NULL, *s = NULL; + + if (!jStr) + return JNI_TRUE; + + s = (char*)(*env)->GetStringUTFChars(env, jStr, 0); + sp = s + strlen(s); + if (sp <= s) + ret = JNI_TRUE; + do + { + if (!isspace(*(--sp))) + ret = JNI_FALSE; + } + while (sp > s); + + (*env)->ReleaseStringUTFChars(env, jStr, s); + return ret; +} diff --git a/playground/javatest/jni/test/TestJni.java b/playground/javatest/jni/test/TestJni.java new file mode 100644 index 0000000000..d8d9c22b70 --- /dev/null +++ b/playground/javatest/jni/test/TestJni.java @@ -0,0 +1,20 @@ +import org.testng.Assert; +import org.testng.annotations.Test; + +public class TestJni { + + @Test + public void testTrue() { + Assert.assertEquals(true, StringUtils.isAlpha("myfootest"), "'myfootest' is alpha"); + } + + @Test + public void testFalse() { + Assert.assertEquals(false, StringUtils.isAlpha("my f00 t3$t"), "'my f00 t3$t' is not alpha"); + } + + @Test + public void testIsEmpty() { + Assert.assertEquals(false, StringUtils.isEmpty("emptyNOT"), "'emptyNOT' is not empty"); + } +} diff --git a/playground/javatest/jni/test/testng.xml b/playground/javatest/jni/test/testng.xml new file mode 100644 index 0000000000..237f8b6dd5 --- /dev/null +++ b/playground/javatest/jni/test/testng.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/playground/javatest/wscript b/playground/javatest/wscript index c250a21a13..6a954cc37f 100644 --- a/playground/javatest/wscript +++ b/playground/javatest/wscript @@ -1,6 +1,6 @@ #! /usr/bin/env python # encoding: utf-8 -# Federico Pellegrin, 2017 (fedepell) +# Federico Pellegrin, 2019 (fedepell) # # Simple script to demonstrate integration of Java Unit testing inside @@ -21,9 +21,12 @@ def test_results(bld): def options(opt): opt.load('java waf_unit_test javatest') + opt.load('compiler_c') def configure(conf): conf.load('java javatest') + conf.load('compiler_c') + conf.check_jni_headers() def build(bld): bld(features = 'javac', @@ -39,7 +42,7 @@ def build(bld): srcdir = 'test/', # folder containing the sources to compile outdir = 'test', # folder where to output the classes (in the build directory) sourcepath = ['test'], - classpath = [ 'src' ], + classpath = [ 'src' ], basedir = 'test', # folder containing the classes and other files to package (must match outdir) use = ['JAVATEST', 'mainprog'], ut_str = 'java -cp ${CLASSPATH} ${JTRUNNER} ${SRC}', @@ -49,5 +52,25 @@ def build(bld): ) + # Demonstrate correct handling also of dependency to non-java tasks (see !2257) + bld(name='stjni', features='javac jar', srcdir='jni/java', outdir='jni/java', basedir='jni/java', destfile='stringUtils.jar') + + bld.shlib(source = 'jni/jni/source/StringUtils.c', + includes = 'jni/jni/include', + target = 'jni/stringUtils', + uselib = 'JAVA') + + bld(features = 'javac javatest', + srcdir = 'jni/test/', # folder containing the sources to compile + outdir = 'jni/test', # folder where to output the classes (in the build directory) + sourcepath = ['jni/test'], + classpath = [ 'jni/src' ], + basedir = 'jni/test', # folder containing the classes and other files to package (must match outdir) + use = ['JAVATEST', 'stjni', 'jni/stringUtils'], + ut_str = 'java -cp ${CLASSPATH} ${JTRUNNER} ${SRC}', + jtest_source = bld.path.ant_glob('jni/test/*.xml'), + ) + + bld.add_post_fun(test_results) diff --git a/waflib/extras/javatest.py b/waflib/extras/javatest.py index 979b8d8242..f3c6cbf7d2 100755 --- a/waflib/extras/javatest.py +++ b/waflib/extras/javatest.py @@ -1,6 +1,6 @@ #! /usr/bin/env python # encoding: utf-8 -# Federico Pellegrin, 2017 (fedepell) +# Federico Pellegrin, 2019 (fedepell) """ Provides Java Unit test support using :py:class:`waflib.Tools.waf_unit_test.utest` @@ -11,6 +11,10 @@ but should be easily expandable to other frameworks given the flexibility of ut_str provided by the standard waf unit test environment. +The extra takes care also of managing non-java dependencies (ie. C/C++ libraries +using JNI or Python modules via JEP) and setting up the environment needed to run +them. + Example usage: def options(opt): @@ -20,15 +24,15 @@ def configure(conf): conf.load('java javatest') def build(bld): - + [ ... mainprog is built here ... ] bld(features = 'javac javatest', - srcdir = 'test/', - outdir = 'test', + srcdir = 'test/', + outdir = 'test', sourcepath = ['test'], - classpath = [ 'src' ], - basedir = 'test', + classpath = [ 'src' ], + basedir = 'test', use = ['JAVATEST', 'mainprog'], # mainprog is the program being tested in src/ ut_str = 'java -cp ${CLASSPATH} ${JTRUNNER} ${SRC}', jtest_source = bld.path.ant_glob('test/*.xml'), @@ -53,10 +57,91 @@ def build(bld): """ import os -from waflib import Task, TaskGen, Options +from waflib import Task, TaskGen, Options, Errors, Utils, Logs +from waflib.Tools import ccroot + +def _process_use_rec(self, name): + """ + Recursively process ``use`` for task generator with name ``name``.. + Used by javatest_process_use. + """ + if name in self.javatest_use_not or name in self.javatest_use_seen: + return + try: + tg = self.bld.get_tgen_by_name(name) + except Errors.WafError: + self.javatest_use_not.add(name) + return + + self.javatest_use_seen.append(name) + tg.post() + + for n in self.to_list(getattr(tg, 'use', [])): + _process_use_rec(self, n) @TaskGen.feature('javatest') -@TaskGen.after_method('apply_java', 'use_javac_files', 'set_classpath') +@TaskGen.after_method('process_source', 'apply_link', 'use_javac_files') +def javatest_process_use(self): + """ + Process the ``use`` attribute which contains a list of task generator names and store + paths that later is used to populate the unit test runtime environment. + """ + self.javatest_use_not = set() + self.javatest_use_seen = [] + self.javatest_libpaths = [] # strings or Nodes + self.javatest_pypaths = [] # strings or Nodes + self.javatest_dep_nodes = [] + + names = self.to_list(getattr(self, 'use', [])) + for name in names: + _process_use_rec(self, name) + + def extend_unique(lst, varlst): + ext = [] + for x in varlst: + if x not in lst: + ext.append(x) + lst.extend(ext) + + # Collect type specific info needed to construct a valid runtime environment + # for the test. + for name in self.javatest_use_seen: + tg = self.bld.get_tgen_by_name(name) + + # Python-Java embedding crosstools such as JEP + if 'py' in tg.features: + # Python dependencies are added to PYTHONPATH + pypath = getattr(tg, 'install_from', tg.path) + + if 'buildcopy' in tg.features: + # Since buildcopy is used we assume that PYTHONPATH in build should be used, + # not source + extend_unique(self.javatest_pypaths, [pypath.get_bld().abspath()]) + + # Add buildcopy output nodes to dependencies + extend_unique(self.javatest_dep_nodes, [o for task in getattr(tg, 'tasks', []) for o in getattr(task, 'outputs', [])]) + else: + # If buildcopy is not used, depend on sources instead + extend_unique(self.javatest_dep_nodes, tg.source) + extend_unique(self.javatest_pypaths, [pypath.abspath()]) + + + if getattr(tg, 'link_task', None): + # For tasks with a link_task (C, C++, D et.c.) include their library paths: + if not isinstance(tg.link_task, ccroot.stlink_task): + extend_unique(self.javatest_dep_nodes, tg.link_task.outputs) + extend_unique(self.javatest_libpaths, tg.link_task.env.LIBPATH) + + if 'pyext' in tg.features: + # If the taskgen is extending Python we also want to add the interpreter libpath. + extend_unique(self.javatest_libpaths, tg.link_task.env.LIBPATH_PYEXT) + else: + # Only add to libpath if the link task is not a Python extension + extend_unique(self.javatest_libpaths, [tg.link_task.outputs[0].parent.abspath()]) + + +@TaskGen.feature('javatest') +@TaskGen.after_method('apply_java', 'use_javac_files', 'set_classpath', 'javatest_process_use') def make_javatest(self): """ Creates a ``utest`` task with a populated environment for Java Unit test execution @@ -65,6 +150,9 @@ def make_javatest(self): tsk = self.create_task('utest') tsk.set_run_after(self.javac_task) + # Dependencies from recursive use analysis + tsk.dep_nodes.extend(self.javatest_dep_nodes) + # Put test input files as waf_unit_test relies on that for some prints and log generation # If jtest_source is there, this is specially useful for passing XML for TestNG # that contain test specification, use that as inputs, otherwise test sources @@ -97,6 +185,21 @@ def make_javatest(self): if not hasattr(self, 'ut_env'): self.ut_env = dict(os.environ) + def add_paths(var, lst): + # Add list of paths to a variable, lst can contain strings or nodes + lst = [ str(n) for n in lst ] + Logs.debug("ut: %s: Adding paths %s=%s", self, var, lst) + self.ut_env[var] = os.pathsep.join(lst) + os.pathsep + self.ut_env.get(var, '') + + add_paths('PYTHONPATH', self.javatest_pypaths) + + if Utils.is_win32: + add_paths('PATH', self.javatest_libpaths) + elif Utils.unversioned_sys_platform() == 'darwin': + add_paths('DYLD_LIBRARY_PATH', self.javatest_libpaths) + add_paths('LD_LIBRARY_PATH', self.javatest_libpaths) + else: + add_paths('LD_LIBRARY_PATH', self.javatest_libpaths) def configure(ctx): cp = ctx.env.CLASSPATH or '.' From 40fbdbf7b1313dd2950b5d9f29f474289bf2a4d3 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Thu, 26 Sep 2019 21:50:18 +0200 Subject: [PATCH 183/315] Silently ignore negative values for -j --- waflib/Options.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/waflib/Options.py b/waflib/Options.py index ad802d4b90..da3d53c1b9 100644 --- a/waflib/Options.py +++ b/waflib/Options.py @@ -282,6 +282,8 @@ def parse_cmd_args(self, _args=None, cwd=None, allow_unknown=False): elif arg != 'options': commands.append(arg) + if options.jobs < 1: + options.jobs = 1 for name in 'top out destdir prefix bindir libdir'.split(): # those paths are usually expanded from Context.launch_dir if getattr(options, name, None): From be5c79dccaa328faf4bc8b6c640188cf93fd1542 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Tue, 8 Oct 2019 20:04:00 +0200 Subject: [PATCH 184/315] Improve error messages in c_aliases --- waflib/Tools/c_aliases.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/waflib/Tools/c_aliases.py b/waflib/Tools/c_aliases.py index 985e048bdb..928cfe29ca 100644 --- a/waflib/Tools/c_aliases.py +++ b/waflib/Tools/c_aliases.py @@ -38,7 +38,7 @@ def sniff_features(**kw): :return: the list of features for a task generator processing the source files :rtype: list of string """ - exts = get_extensions(kw['source']) + exts = get_extensions(kw.get('source', [])) typ = kw['typ'] feats = [] @@ -72,7 +72,7 @@ def sniff_features(**kw): feats.append(x + typ) will_link = True if not will_link and not kw.get('features', []): - raise Errors.WafError('Cannot link from %r, try passing eg: features="c cprogram"?' % kw) + raise Errors.WafError('Unable to determine how to link %r, try adding eg: features="c cshlib"?' % kw) return feats def set_features(kw, typ): From 77265a5948c282c9da05882bcb3c4d240b130711 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Mon, 14 Oct 2019 07:59:40 +0200 Subject: [PATCH 185/315] Tune the application name on --help #2254 --- ChangeLog | 7 +++++++ waflib/Context.py | 3 +++ waflib/Options.py | 8 ++++---- wscript | 5 +++++ 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index a95e2b7f63..a086f7460f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +NEW IN WAF 2.0.19 +----------------- +* Fix negative values for -j #2256 +* Fix the Swig example compatibility with Python3 #2259 +* Add extras/wafcache +* Tune the application name on --help #2254 + NEW IN WAF 2.0.18 ----------------- * Fix a deadlock with cython and subst tasks #2244 diff --git a/waflib/Context.py b/waflib/Context.py index 4760bc8201..52246c4b5e 100644 --- a/waflib/Context.py +++ b/waflib/Context.py @@ -27,6 +27,9 @@ class imp(object): WAFREVISION="314689b8994259a84f0de0aaef74d7ce91f541ad" """Git revision when the waf version is updated""" +WAFNAME="waf" +"""Application name displayed on --help""" + ABI = 20 """Version of the build data cache file format (used in :py:const:`waflib.Context.DBFILE`)""" diff --git a/waflib/Options.py b/waflib/Options.py index da3d53c1b9..db67953157 100644 --- a/waflib/Options.py +++ b/waflib/Options.py @@ -44,7 +44,7 @@ class opt_parser(optparse.OptionParser): """ def __init__(self, ctx, allow_unknown=False): optparse.OptionParser.__init__(self, conflict_handler='resolve', add_help_option=False, - version='waf %s (%s)' % (Context.WAFVERSION, Context.WAFREVISION)) + version='%s %s (%s)' % (Context.WAFNAME, Context.WAFVERSION, Context.WAFREVISION)) self.formatter.width = Logs.get_term_cols() self.ctx = ctx self.allow_unknown = allow_unknown @@ -96,11 +96,11 @@ def get_usage(self): lst.sort() ret = '\n'.join(lst) - return '''waf [commands] [options] + return '''%s [commands] [options] -Main commands (example: ./waf build -j4) +Main commands (example: ./%s build -j4) %s -''' % ret +''' % (Context.WAFNAME, Context.WAFNAME, ret) class OptionsContext(Context.Context): diff --git a/wscript b/wscript index 75a6ec84f2..81146f052b 100644 --- a/wscript +++ b/wscript @@ -101,6 +101,7 @@ def options(opt): # those ones are not too interesting opt.add_option('--set-version', default='', help='sets the version number for waf releases (for the maintainer)', dest='setver') + opt.add_option('--set-name', default='waf', help=optparse.SUPPRESS_HELP, dest='wafname') opt.add_option('--strip', action='store_true', default=True, help='shrinks waf (strip docstrings, saves 33kb)', @@ -317,6 +318,10 @@ def create_waf(self, *k, **kw): with open('waf-light', 'r') as f: code1 = f.read() + # tune the application name if necessary + if Options.options.wafname != 'waf': + Options.options.prelude = '\tfrom waflib import Context\n\tContext.WAFNAME=%r\n' % Options.options.wafname + Options.options.prelude + # now store the revision unique number in waf code1 = code1.replace("if sys.hexversion<0x206000f:\n\traise ImportError('Python >= 2.6 is required to create the waf file')\n", '') code1 = code1.replace('\t#import waflib.extras.compat15#PRELUDE', Options.options.prelude) From 12ae961b6160aa0b51c1dee89cf6a0f6dea6dc44 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sat, 19 Oct 2019 00:11:11 +0200 Subject: [PATCH 186/315] Propagate ldflags to fortran tasks #2262 --- waflib/Tools/fc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/waflib/Tools/fc.py b/waflib/Tools/fc.py index fd4d39c90a..7fbd76d365 100644 --- a/waflib/Tools/fc.py +++ b/waflib/Tools/fc.py @@ -13,8 +13,8 @@ from waflib.Configure import conf ccroot.USELIB_VARS['fc'] = set(['FCFLAGS', 'DEFINES', 'INCLUDES', 'FCPPFLAGS']) -ccroot.USELIB_VARS['fcprogram_test'] = ccroot.USELIB_VARS['fcprogram'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS']) -ccroot.USELIB_VARS['fcshlib'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS']) +ccroot.USELIB_VARS['fcprogram_test'] = ccroot.USELIB_VARS['fcprogram'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS', 'LDFLAGS']) +ccroot.USELIB_VARS['fcshlib'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS', 'LDFLAGS']) ccroot.USELIB_VARS['fcstlib'] = set(['ARFLAGS', 'LINKDEPS']) @extension('.f','.F','.f90','.F90','.for','.FOR','.f95','.F95','.f03','.F03','.f08','.F08') From 7ea236c9a59550d7b8ff28f118c9f0ba95309987 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C3=ABl=20Kooi?= <3961583-RA-Kooi@users.noreply.gitlab.com> Date: Sun, 20 Oct 2019 10:49:38 +0200 Subject: [PATCH 187/315] [MSVC/Fortran] Add /Fd flag when /Zi or /ZI flags are detected Fixes #1731 --- waflib/extras/msvc_pdb.py | 45 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 waflib/extras/msvc_pdb.py diff --git a/waflib/extras/msvc_pdb.py b/waflib/extras/msvc_pdb.py new file mode 100644 index 0000000000..5621569baa --- /dev/null +++ b/waflib/extras/msvc_pdb.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Rafaël Kooi 2019 + +from waflib import TaskGen, Tools +@TaskGen.feature('c', 'cxx', 'fc') +@TaskGen.after_method('propagate_uselib_vars') +def add_pdb_per_object(self): + """For msvc/fortran, specify a unique compile pdb per object, to work + around LNK4099. Flags are updated with a unique /Fd flag based on the + task output name. This is separate from the link pdb. + """ + + link_task = getattr(self, 'link_task', None) + + for task in self.compiled_tasks: + node = task.outputs[0].change_ext('.pdb') + pdb_flag = '/Fd:' + node.abspath() + + canAddNode = False + for flagname in ('CFLAGS', 'CXXFLAGS', 'FCFLAGS'): + if not flagname in task.env: + continue + + flags = task.env[flagname] + + for i, flag in reversed(list(enumerate(flags))): + # Capture both /Zi and /ZI, which cause the compiler to emit a PDB file. + if flag[1:].lower() == 'zi': + canAddNode = True + task.env.append_unique(flagname, pdb_flag) + + # Strip existing /Fd, /FS, or /MP flags. + # We have to check for /Fd case sensitive, so that we won't accidentally + # overwrite GCC flags such as "-fdata-sections". + if flag[1:3] == 'Fd' \ + or flag[1:].lower() == 'fs' \ + or flag[1:].lower() == 'mp': + del task.env[flagname][i] + + if canAddNode: + if link_task and not node in link_task.dep_nodes: + link_task.dep_nodes.append(node) + if not node in task.outputs: + task.outputs.append(node) From 6e3ea251855855f5f4ebe8b0ba2631e5eb5dba30 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Wed, 23 Oct 2019 19:52:06 +0200 Subject: [PATCH 188/315] Push wafcache files synchronously for now --- waflib/extras/wafcache.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/waflib/extras/wafcache.py b/waflib/extras/wafcache.py index f4053d6f73..58ef270b2c 100644 --- a/waflib/extras/wafcache.py +++ b/waflib/extras/wafcache.py @@ -431,10 +431,8 @@ def loop(service): [sig, files_from, files_to] = cPickle.loads(base64.b64decode(txt)) if files_from: - # pushing to cache is done without any wait - th = threading.Thread(target=service.copy_to_cache, args=(sig, files_from, files_to)) - th.setDaemon(True) - th.start() + # TODO return early when pushing files upstream + ret = service.copy_from_cache(sig, files_from, files_to) elif files_to: # the build process waits for workers to (possibly) obtain files from the cache ret = service.copy_from_cache(sig, files_from, files_to) From e1d0efa9908fe21a0c27ca0a0d7620346c7edd0d Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 27 Oct 2019 10:30:09 +0100 Subject: [PATCH 189/315] Improve cache activity verbosity --- waflib/extras/wafcache.py | 143 ++++++++++++++++++++++++++++---------- 1 file changed, 105 insertions(+), 38 deletions(-) diff --git a/waflib/extras/wafcache.py b/waflib/extras/wafcache.py index 58ef270b2c..8b9567faf1 100644 --- a/waflib/extras/wafcache.py +++ b/waflib/extras/wafcache.py @@ -5,45 +5,59 @@ """ Filesystem-based cache system to share and re-use build artifacts +Cache access operations (copy to and from) are delegated to +independent pre-forked worker subprocesses. + The following environment variables may be set: -* WAFCACHE: absolute path of the waf cache (/tmp/wafcache_user, - where `user` represents the currently logged-in user) - or a URL to a cache server, for example: - export WAFCACHE=http://localhost:8080/files/ - in that case, GET/POST requests are made to urls of the form - http://localhost:8080/files/000000000/0 (cache - management is then up to the server) +* WAFCACHE: several possibilities: + - File cache: + absolute path of the waf cache (~/.cache/wafcache_user, + where `user` represents the currently logged-in user) + - URL to a cache server, for example: + export WAFCACHE=http://localhost:8080/files/ + in that case, GET/POST requests are made to urls of the form + http://localhost:8080/files/000000000/0 (cache management is then up to the server) + - GCS or S3 bucket + gs://my-bucket/ + s3://my-bucket/ +* WAFCACHE_NO_PUSH: if set, disables pushing to the cache +* WAFCACHE_VERBOSITY: if set, displays more detailed cache operations + +File cache specific options: + Files are copied using hard links by default; if the cache is located + onto another partition, the system switches to file copies instead. * WAFCACHE_TRIM_MAX_FOLDER: maximum amount of tasks to cache (1M) * WAFCACHE_EVICT_MAX_BYTES: maximum amount of cache size in bytes (10GB) * WAFCACHE_EVICT_INTERVAL_MINUTES: minimum time interval to try and trim the cache (3 minutess) -* WAFCACHE_NO_PUSH: if set, disables pushing to the cache - -Cache access operations (copy to and from) are delegated to pre-forked -subprocesses. Though these processes perform atomic copies, they -are unaware of other processes running on the system - -The files are copied using hard links by default; if the cache is located -onto another partition, the system switches to file copies instead. - Usage:: def build(bld): bld.load('wafcache') ... + +To troubleshoot:: + + waf clean build --zones=wafcache """ -import atexit, base64, errno, fcntl, getpass, os, shutil, sys, threading, time, urllib3 +import atexit, base64, errno, fcntl, getpass, os, shutil, sys, time, traceback, urllib3 try: import subprocess32 as subprocess except ImportError: import subprocess -CACHE_DIR = os.environ.get('WAFCACHE', '/tmp/wafcache_' + getpass.getuser()) +base_cache = os.path.expanduser('~/.cache/') +if not os.path.isdir(base_cache): + base_cache = '/tmp/' +default_wafcache_dir = os.path.join(base_cache, 'wafcache_' + getpass.getuser()) + +CACHE_DIR = os.environ.get('WAFCACHE', default_wafcache_dir) TRIM_MAX_FOLDERS = int(os.environ.get('WAFCACHE_TRIM_MAX_FOLDER', 1000000)) EVICT_INTERVAL_MINUTES = int(os.environ.get('WAFCACHE_EVICT_INTERVAL_MINUTES', 3)) EVICT_MAX_BYTES = int(os.environ.get('WAFCACHE_EVICT_MAX_BYTES', 10**10)) WAFCACHE_NO_PUSH = 1 if os.environ.get('WAFCACHE_NO_PUSH') else 0 +WAFCACHE_VERBOSITY = 1 if os.environ.get('WAFCACHE_VERBOSITY') else 0 OK = "ok" try: @@ -68,9 +82,16 @@ def can_retrieve_cache(self): files_to = [node.abspath() for node in self.outputs] err = cache_command(ssig, [], files_to) - if not err.startswith(OK): - if Logs.verbose: - Logs.debug('wafcache: error getting from cache %s', err) + if err.startswith(OK): + if WAFCACHE_VERBOSITY: + Logs.pprint('CYAN', ' Fetched %r from cache' % files_to) + else: + Logs.debug('wafcache: fetched %r from cache', files_to) + else: + if WAFCACHE_VERBOSITY: + Logs.pprint('YELLOW', ' No cache entry %s' % files_to) + else: + Logs.debug('wafcache: No cache entry %s: %s', files_to, err) return False self.cached = True @@ -90,9 +111,16 @@ def put_files_cache(self): files_from = [node.abspath() for node in self.outputs] err = cache_command(ssig, files_from, []) - if not err.startswith(OK): - if Logs.verbose: - Logs.debug('wafcache: error caching %s', err) + if err.startswith(OK): + if WAFCACHE_VERBOSITY: + Logs.pprint('CYAN', ' Successfully uploaded %s to cache' % files_from) + else: + Logs.debug('wafcache: Successfully uploaded %r to cache', files_from) + else: + if WAFCACHE_VERBOSITY: + Logs.pprint('RED', ' Error caching step results %s: %s' % (files_from, err)) + else: + Logs.debug('wafcache: Error caching results %s: %s', files_from, err) bld.task_sigs[self.uid()] = self.cache_sig @@ -212,7 +240,7 @@ def build(bld): Task.Task.put_files_cache = put_files_cache Task.Task.uid = uid Build.BuildContext.hash_env_vars = hash_env_vars - for x in Task.classes.values(): + for x in reversed(list(Task.classes.values())): make_cached(x) def cache_command(sig, files_from, files_to): @@ -316,7 +344,7 @@ def lru_evict(): except EnvironmentError as e: if e.errno == errno.ENOENT: with open(lockfile, 'w') as f: - f.write(''.encode()) + f.write('') return else: raise @@ -367,18 +395,25 @@ def copy_to_cache(self, sig, files_from, files_to): for i, x in enumerate(files_from): if not os.path.islink(x): self.upload(x, sig, i) - except EnvironmentError: - pass + except Exception: + return traceback.format_exc() + return OK def copy_from_cache(self, sig, files_from, files_to): try: for i, x in enumerate(files_to): self.download(x, sig, i) - return OK - except EnvironmentError as e: - return "Failed to download %r to %r: %s" % (files_from, files_to, e) + except Exception: + return traceback.format_exc() + return OK class fcache(object): + def __init__(self): + if not os.path.exists(CACHE_DIR): + os.makedirs(CACHE_DIR) + if not os.path.exists(CACHE_DIR): + raise ValueError('Could not initialize the cache directory') + def copy_to_cache(self, sig, files_from, files_to): """ Copy files to the cache, existing files are overwritten, @@ -389,13 +424,13 @@ def copy_to_cache(self, sig, files_from, files_to): for i, x in enumerate(files_from): dest = os.path.join(CACHE_DIR, sig[:2], sig, str(i)) atomic_copy(x, dest) - except EnvironmentError: - # no errors should be raised - pass + except Exception: + return traceback.format_exc() else: # attempt trimming if caching was successful: # we may have things to trim! lru_evict() + return OK def copy_from_cache(self, sig, files_from, files_to): """ @@ -408,8 +443,38 @@ def copy_from_cache(self, sig, files_from, files_to): # success! update the cache time os.utime(os.path.join(CACHE_DIR, sig[:2], sig), None) - except EnvironmentError as e: - return "Failed to copy %r to %r: %s" % (files_from, files_to, e) + except Exception: + return traceback.format_exc() + return OK + +class bucket_cache(object): + def bucket_copy(self, source, target): + if CACHE_DIR.startswith('s3://'): + cmd = ['aws', 's3', 'cp', source, target] + else: + cmd = ['gsutil', 'cp', source, target] + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = proc.communicate() + if proc.returncode: + raise OSError('Error copy %r to %r using: %r (exit %r):\n out:%s\n err:%s' % ( + source, target, cmd, proc.returncode, out.decode(), err.decode())) + + def copy_to_cache(self, sig, files_from, files_to): + try: + for i, x in enumerate(files_from): + dest = os.path.join(CACHE_DIR, sig[:2], sig, str(i)) + self.bucket_copy(x, dest) + except Exception: + return traceback.format_exc() + return OK + + def copy_from_cache(self, sig, files_from, files_to): + try: + for i, x in enumerate(files_to): + orig = os.path.join(CACHE_DIR, sig[:2], sig, str(i)) + self.bucket_copy(orig, x) + except EnvironmentError: + return traceback.format_exc() return OK def loop(service): @@ -432,7 +497,7 @@ def loop(service): [sig, files_from, files_to] = cPickle.loads(base64.b64decode(txt)) if files_from: # TODO return early when pushing files upstream - ret = service.copy_from_cache(sig, files_from, files_to) + ret = service.copy_to_cache(sig, files_from, files_to) elif files_to: # the build process waits for workers to (possibly) obtain files from the cache ret = service.copy_from_cache(sig, files_from, files_to) @@ -445,7 +510,9 @@ def loop(service): sys.stdout.flush() if __name__ == '__main__': - if CACHE_DIR.startswith('http'): + if CACHE_DIR.startswith('s3://') or CACHE_DIR.startswith('gs://'): + service = bucket_cache() + elif CACHE_DIR.startswith('http'): service = netcache() else: service = fcache() From 2cc8a6e8c67e1c9cdee3778c5def26f4205f74f9 Mon Sep 17 00:00:00 2001 From: Federico Pellegrin Date: Sat, 2 Nov 2019 16:42:55 +0100 Subject: [PATCH 190/315] playground/swig: clean up java swig example --- playground/swig/wscript | 69 ++++++++++++----------------------------- 1 file changed, 19 insertions(+), 50 deletions(-) diff --git a/playground/swig/wscript b/playground/swig/wscript index 64353b925f..f9b88f299b 100644 --- a/playground/swig/wscript +++ b/playground/swig/wscript @@ -87,23 +87,11 @@ def build(bld): if not bld.env.HAVE_JAVA: return - from waflib.extras import swig + swigsrcdir = bld.path.get_bld().make_node('extend/java') # destination for generated java source from swig + swigoutdir = bld.path.get_bld().make_node('extend/jar') # destination for generated class files - srcdir = bld.path.get_bld().make_node('extend/java') # destination for generated java file - - #""" # BEGIN BLOCK 1 - d = bld.path.make_node('extend/java/foo/bar/pouet') - javanodes = [d.find_or_declare(x) for x in 'A.java test_swig_waf.java test_swig_wafJNI.java'.split()] - dec = bld.tools['swig'].swigf - #@dec <- python 2.3 does not support the @decorator notation - def swig_java(tsk): - tsk.outputs.extend(javanodes) - bld.tools['swig'].swigf(swig_java) - """ # END BLOCK 1 - #"""# do not remove - - - bld( + # Will generate code via swig and also the JNI library in C++ + jniswig = bld( features = 'cxx cxxshlib', source = 'extend/java/test_swig_waf.i', target = 'extend/java/_test_swig_waf', @@ -113,44 +101,25 @@ def build(bld): uselib = 'JAVA', use = 'mylib') - #""" # BEGIN BLOCK 2 - """ # END BLOCK 2 - - def move_java_files(task): - import os, shutil - from waflib import Utils - - node = srcdir.make_node('foo/bar/pouet/') - files = Utils.listdir(node.abspath()) - for x in files: - if x.endswith('.java'): - # create a node in the directory we want to - j = node.make_node(x) # create a node - # depend on the .i file to make sure the .java files are copied after swig is executed - bld(name='move_and_read', rule=move_java_files, source='extend/java/test_swig_waf.i', after=['swig'], before=['javac']) - #""" - - - bld(rule='cp ${SRC} ${TGT}', source=bld.path.find_resource('extend/java/Foo.java'), target=srcdir.make_node('foo/bar/pouet/Foo.java'), before=['javac'], after=['swig']) - - tmp = bld.path.get_bld().make_node('maha') - - bld(features = 'javac jar', - srcdir = srcdir, + # Java will contain the generated code from swigsrcdir plus the local sources + jswig = bld(features = 'javac jar', + srcdir = [ swigsrcdir , 'extend/java'] , sourcepath = [], - outdir = tmp, # we do need another folder here - basedir = tmp, - destfile = 'maha.jar' + outdir = swigoutdir, + basedir = swigoutdir, + destfile = 'maha.jar', ) - bld.add_post_fun(exec_test_java) + # Post JNI library and Java generators so we have tasks created + jniswig.post() + jswig.post() + # Now make sure javac task is executed after swig generation + for x in jniswig.tasks: + if x.__class__.__name__ == 'swig': + jswig.javac_task.set_run_after(x) - ######################################### - # listing the java nodes is required to ensure the swig task - # is executed whenever the java files are removed from - # the build directory - # - # to list the java files automatically, comment the starting character '#' in the lines "BEGIN BLOCK 1" and "BEGIN BLOCK 2" + # Launch the test after build + bld.add_post_fun(exec_test_java) def exec_test_java(bld): From a88ae5fb9fb2f35e94876d5b1edd7ad5807dec41 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 3 Nov 2019 10:23:31 +0100 Subject: [PATCH 191/315] Improve os.environ propagation #2264 --- waflib/Utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/Utils.py b/waflib/Utils.py index 7472226da5..fc64fa0515 100644 --- a/waflib/Utils.py +++ b/waflib/Utils.py @@ -891,7 +891,7 @@ def run_prefork_process(cmd, kwargs, cargs): """ Delegates process execution to a pre-forked process instance. """ - if not 'env' in kwargs: + if not kwargs.get('env'): kwargs['env'] = dict(os.environ) try: obj = base64.b64encode(cPickle.dumps([cmd, kwargs, cargs])) From 7bbf13e57a208b7db647af6bc15b974ad07f6822 Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Mon, 4 Nov 2019 16:31:58 +0300 Subject: [PATCH 192/315] msvc_pdb: check compiled_tasks existence, so it will not misleadingly throw a stacktrace if no sources was added --- waflib/extras/msvc_pdb.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/waflib/extras/msvc_pdb.py b/waflib/extras/msvc_pdb.py index 5621569baa..881a2d5370 100644 --- a/waflib/extras/msvc_pdb.py +++ b/waflib/extras/msvc_pdb.py @@ -10,6 +10,8 @@ def add_pdb_per_object(self): around LNK4099. Flags are updated with a unique /Fd flag based on the task output name. This is separate from the link pdb. """ + if not hasattr(self, 'compiled_tasks'): + return link_task = getattr(self, 'link_task', None) From a708d8285241acfe8feb4ba47a8fe2b40193cd89 Mon Sep 17 00:00:00 2001 From: Federico Pellegrin Date: Tue, 5 Nov 2019 14:01:51 +0100 Subject: [PATCH 193/315] Tools/c_config.py: update to documentation --- waflib/Tools/c_config.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/waflib/Tools/c_config.py b/waflib/Tools/c_config.py index 43ae1507d8..6db55d2cf7 100644 --- a/waflib/Tools/c_config.py +++ b/waflib/Tools/c_config.py @@ -86,6 +86,10 @@ def configure(conf): :type uselib_store: string :param env: config set or conf.env by default :type env: :py:class:`waflib.ConfigSet.ConfigSet` + :param force_static: force usage of static libraries + :type force_static: bool default False + :param posix: usage of POSIX mode for shlex lexical analiysis library + :type posix: bool default True """ assert(isinstance(line, str)) @@ -246,6 +250,8 @@ def exec_cfg(self, kw): * if modversion is given, then return the module version * else, execute the *-config* program with the *args* and *variables* given, and set the flags on the *conf.env.FLAGS_name* variable + :param path: the **-config program to use** + :type path: list of string :param atleast_pkgconfig_version: minimum pkg-config version to use (disable other tests) :type atleast_pkgconfig_version: string :param package: package name, for example *gtk+-2.0* @@ -260,6 +266,12 @@ def exec_cfg(self, kw): :type variables: list of string :param define_variable: additional variables to define (also in conf.env.PKG_CONFIG_DEFINES) :type define_variable: dict(string: string) + :param pkg_config_path: paths where pkg-config should search for .pc config files (overrides env.PKG_CONFIG_PATH if exists) + :type pkg_config_path: string, list of directories separated by colon + :param force_static: force usage of static libraries + :type force_static: bool default False + :param posix: usage of POSIX mode for shlex lexical analiysis library + :type posix: bool default True """ path = Utils.to_list(kw['path']) @@ -334,6 +346,7 @@ def check_cfg(self, *k, **kw): """ Checks for configuration flags using a **-config**-like program (pkg-config, sdl-config, etc). This wraps internal calls to :py:func:`waflib.Tools.c_config.validate_cfg` and :py:func:`waflib.Tools.c_config.exec_cfg` + so check exec_cfg parameters descriptions for more details on kw passed A few examples:: From b86438687ea4cac5f40cd0776beaf55f7e5c0610 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Fri, 8 Nov 2019 20:39:47 +0100 Subject: [PATCH 194/315] Ignore resource files --- waflib/extras/msvc_pdb.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/waflib/extras/msvc_pdb.py b/waflib/extras/msvc_pdb.py index 881a2d5370..89932dc04a 100644 --- a/waflib/extras/msvc_pdb.py +++ b/waflib/extras/msvc_pdb.py @@ -2,7 +2,8 @@ # encoding: utf-8 # Rafaël Kooi 2019 -from waflib import TaskGen, Tools +from waflib import TaskGen + @TaskGen.feature('c', 'cxx', 'fc') @TaskGen.after_method('propagate_uselib_vars') def add_pdb_per_object(self): @@ -16,6 +17,9 @@ def add_pdb_per_object(self): link_task = getattr(self, 'link_task', None) for task in self.compiled_tasks: + if task.inputs and task.inputs[0].name().lower().endswith('.rc'): + continue + node = task.outputs[0].change_ext('.pdb') pdb_flag = '/Fd:' + node.abspath() From f976fb5f6449f9e37e5bfd8e9596fa6c12ecf966 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Fri, 8 Nov 2019 20:43:30 +0100 Subject: [PATCH 195/315] Normalize the indentation according to the rest of the project --- waflib/extras/msvc_pdb.py | 74 +++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/waflib/extras/msvc_pdb.py b/waflib/extras/msvc_pdb.py index 89932dc04a..c0ebb61a01 100644 --- a/waflib/extras/msvc_pdb.py +++ b/waflib/extras/msvc_pdb.py @@ -7,45 +7,45 @@ @TaskGen.feature('c', 'cxx', 'fc') @TaskGen.after_method('propagate_uselib_vars') def add_pdb_per_object(self): - """For msvc/fortran, specify a unique compile pdb per object, to work - around LNK4099. Flags are updated with a unique /Fd flag based on the - task output name. This is separate from the link pdb. - """ - if not hasattr(self, 'compiled_tasks'): - return + """For msvc/fortran, specify a unique compile pdb per object, to work + around LNK4099. Flags are updated with a unique /Fd flag based on the + task output name. This is separate from the link pdb. + """ + if not hasattr(self, 'compiled_tasks'): + return - link_task = getattr(self, 'link_task', None) + link_task = getattr(self, 'link_task', None) - for task in self.compiled_tasks: + for task in self.compiled_tasks: if task.inputs and task.inputs[0].name().lower().endswith('.rc'): continue - node = task.outputs[0].change_ext('.pdb') - pdb_flag = '/Fd:' + node.abspath() - - canAddNode = False - for flagname in ('CFLAGS', 'CXXFLAGS', 'FCFLAGS'): - if not flagname in task.env: - continue - - flags = task.env[flagname] - - for i, flag in reversed(list(enumerate(flags))): - # Capture both /Zi and /ZI, which cause the compiler to emit a PDB file. - if flag[1:].lower() == 'zi': - canAddNode = True - task.env.append_unique(flagname, pdb_flag) - - # Strip existing /Fd, /FS, or /MP flags. - # We have to check for /Fd case sensitive, so that we won't accidentally - # overwrite GCC flags such as "-fdata-sections". - if flag[1:3] == 'Fd' \ - or flag[1:].lower() == 'fs' \ - or flag[1:].lower() == 'mp': - del task.env[flagname][i] - - if canAddNode: - if link_task and not node in link_task.dep_nodes: - link_task.dep_nodes.append(node) - if not node in task.outputs: - task.outputs.append(node) + node = task.outputs[0].change_ext('.pdb') + pdb_flag = '/Fd:' + node.abspath() + + canAddNode = False + for flagname in ('CFLAGS', 'CXXFLAGS', 'FCFLAGS'): + if not flagname in task.env: + continue + + flags = task.env[flagname] + + for i, flag in reversed(list(enumerate(flags))): + # Capture both /Zi and /ZI, which cause the compiler to emit a PDB file. + if flag[1:].lower() == 'zi': + canAddNode = True + task.env.append_unique(flagname, pdb_flag) + + # Strip existing /Fd, /FS, or /MP flags. + # We have to check for /Fd case sensitive, so that we won't accidentally + # overwrite GCC flags such as "-fdata-sections". + if flag[1:3] == 'Fd' \ + or flag[1:].lower() == 'fs' \ + or flag[1:].lower() == 'mp': + del task.env[flagname][i] + + if canAddNode: + if link_task and not node in link_task.dep_nodes: + link_task.dep_nodes.append(node) + if not node in task.outputs: + task.outputs.append(node) From 10561e48929ab13507c9d1c06b456992c5d942cc Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sat, 9 Nov 2019 00:16:15 +0100 Subject: [PATCH 196/315] Simplify msvc_pdb.py --- waflib/extras/msvc_pdb.py | 46 +++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/waflib/extras/msvc_pdb.py b/waflib/extras/msvc_pdb.py index c0ebb61a01..1cb9716aaa 100644 --- a/waflib/extras/msvc_pdb.py +++ b/waflib/extras/msvc_pdb.py @@ -17,34 +17,32 @@ def add_pdb_per_object(self): link_task = getattr(self, 'link_task', None) for task in self.compiled_tasks: - if task.inputs and task.inputs[0].name().lower().endswith('.rc'): - continue + if task.inputs and task.inputs[0].name().lower().endswith('.rc'): + continue - node = task.outputs[0].change_ext('.pdb') - pdb_flag = '/Fd:' + node.abspath() - - canAddNode = False + add_pdb = False for flagname in ('CFLAGS', 'CXXFLAGS', 'FCFLAGS'): - if not flagname in task.env: - continue - + # several languages may be used at once flags = task.env[flagname] - - for i, flag in reversed(list(enumerate(flags))): - # Capture both /Zi and /ZI, which cause the compiler to emit a PDB file. + for flag in flags: if flag[1:].lower() == 'zi': - canAddNode = True - task.env.append_unique(flagname, pdb_flag) - - # Strip existing /Fd, /FS, or /MP flags. - # We have to check for /Fd case sensitive, so that we won't accidentally - # overwrite GCC flags such as "-fdata-sections". - if flag[1:3] == 'Fd' \ - or flag[1:].lower() == 'fs' \ - or flag[1:].lower() == 'mp': - del task.env[flagname][i] - - if canAddNode: + add_pdb = True + break + + if add_pdb: + node = task.outputs[0].change_ext('.pdb') + pdb_flag = '/Fd:' + node.abspath() + + for flagname in ('CFLAGS', 'CXXFLAGS', 'FCFLAGS'): + task.env.append_unique(flagname, pdb_flag) + + buf = [pdb_flag] + for flag in task.env[flagname]: + if flag[1:3] == 'Fd' or flag[1:].lower() == 'fs' or flag[1:].lower() == 'mp': + continue + buf.append(flag) + task.env[flagname] = buf + if link_task and not node in link_task.dep_nodes: link_task.dep_nodes.append(node) if not node in task.outputs: From f883a4b69469e9a977770fb29aba57f8459815ad Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sat, 9 Nov 2019 00:22:31 +0100 Subject: [PATCH 197/315] Further simplifications --- waflib/extras/msvc_pdb.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/waflib/extras/msvc_pdb.py b/waflib/extras/msvc_pdb.py index 1cb9716aaa..889104874e 100644 --- a/waflib/extras/msvc_pdb.py +++ b/waflib/extras/msvc_pdb.py @@ -23,8 +23,7 @@ def add_pdb_per_object(self): add_pdb = False for flagname in ('CFLAGS', 'CXXFLAGS', 'FCFLAGS'): # several languages may be used at once - flags = task.env[flagname] - for flag in flags: + for flag in task.env[flagname]: if flag[1:].lower() == 'zi': add_pdb = True break @@ -34,8 +33,6 @@ def add_pdb_per_object(self): pdb_flag = '/Fd:' + node.abspath() for flagname in ('CFLAGS', 'CXXFLAGS', 'FCFLAGS'): - task.env.append_unique(flagname, pdb_flag) - buf = [pdb_flag] for flag in task.env[flagname]: if flag[1:3] == 'Fd' or flag[1:].lower() == 'fs' or flag[1:].lower() == 'mp': From 90dea12f067ff7cbb088db97affc9044d4b33dd5 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sat, 9 Nov 2019 00:55:18 +0100 Subject: [PATCH 198/315] Fix one more issue in msvc_pdb.py --- waflib/extras/msvc_pdb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/extras/msvc_pdb.py b/waflib/extras/msvc_pdb.py index 889104874e..077656b4f7 100644 --- a/waflib/extras/msvc_pdb.py +++ b/waflib/extras/msvc_pdb.py @@ -17,7 +17,7 @@ def add_pdb_per_object(self): link_task = getattr(self, 'link_task', None) for task in self.compiled_tasks: - if task.inputs and task.inputs[0].name().lower().endswith('.rc'): + if task.inputs and task.inputs[0].name.lower().endswith('.rc'): continue add_pdb = False From c00e7509326e1f388b80579eb54b2e854cdf7734 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 10 Nov 2019 10:36:30 +0100 Subject: [PATCH 199/315] Remove the dependency on Qt5Gui in the Qt5 detection --- waflib/Tools/qt5.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/waflib/Tools/qt5.py b/waflib/Tools/qt5.py index 287c25374a..3a2df68b2f 100644 --- a/waflib/Tools/qt5.py +++ b/waflib/Tools/qt5.py @@ -482,8 +482,8 @@ def configure(self): self.fatal('No CXX compiler defined: did you forget to configure compiler_cxx first?') # Qt5 may be compiled with '-reduce-relocations' which requires dependent programs to have -fPIE or -fPIC? - frag = '#include \nint main(int argc, char **argv) {return 0;}\n' - uses = 'QT5CORE QT5WIDGETS QT5GUI' + frag = '#include \nint main(int argc, char **argv) {return 0;}\n' + uses = 'QT5CORE' for flag in [[], '-fPIE', '-fPIC', '-std=c++11' , ['-std=c++11', '-fPIE'], ['-std=c++11', '-fPIC']]: msg = 'See if Qt files compile ' if flag: @@ -499,7 +499,7 @@ def configure(self): # FreeBSD does not add /usr/local/lib and the pkg-config files do not provide it either :-/ if Utils.unversioned_sys_platform() == 'freebsd': - frag = '#include \nint main(int argc, char **argv) { QApplication app(argc, argv); return NULL != (void*) (&app);}\n' + frag = '#include \nint main(int argc, char **argv) { QMap app(argc, argv); return NULL != (void*) (&app);}\n' try: self.check(features='qt5 cxx cxxprogram', use=uses, fragment=frag, msg='Can we link Qt programs on FreeBSD directly?') except self.errors.ConfigurationError: From a41d0fdcd2a05680f60781a2ffb77ecc3961d623 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 10 Nov 2019 12:32:20 +0100 Subject: [PATCH 200/315] Fix relative path comparisons in clang_compilation_database --- waflib/extras/clang_compilation_database.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/waflib/extras/clang_compilation_database.py b/waflib/extras/clang_compilation_database.py index 46fd40a8f2..9387668a6d 100644 --- a/waflib/extras/clang_compilation_database.py +++ b/waflib/extras/clang_compilation_database.py @@ -46,7 +46,7 @@ class ClangDbContext(Build.BuildContext): '''generates compile_commands.json by request''' cmd = 'clangdb' clang_compilation_database_tasks = [] - + def write_compilation_database(self): """ Write the clang compilation database as JSON @@ -63,9 +63,8 @@ def write_compilation_database(self): cmd = task.last_cmd except AttributeError: continue - directory = getattr(task, 'cwd', self.variant_dir) f_node = task.inputs[0] - filename = os.path.relpath(f_node.abspath(), directory) + filename = f_node.path_from(task.getcwd()) entry = { "directory": directory, "arguments": cmd, @@ -91,7 +90,7 @@ def execute(self): # exec_command temporarily def exec_command(self, *k, **kw): return 0 - + for g in self.groups: for tg in g: try: @@ -100,7 +99,7 @@ def exec_command(self, *k, **kw): pass else: f() - + if isinstance(tg, Task.Task): lst = [tg] else: lst = tg.tasks @@ -117,7 +116,7 @@ def exec_command(self, *k, **kw): EXECUTE_PATCHED = False def patch_execute(): global EXECUTE_PATCHED - + if EXECUTE_PATCHED: return @@ -127,11 +126,11 @@ def new_execute_build(self): """ if type(self) == Build.BuildContext: Scripting.run_command('clangdb') - + old_execute_build(self) old_execute_build = getattr(Build.BuildContext, 'execute_build', None) setattr(Build.BuildContext, 'execute_build', new_execute_build) EXECUTE_PATCHED = True - + patch_execute() From a4e9a9f2a0bb693edfa587b7a2655cb082fe9bd9 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 10 Nov 2019 12:34:18 +0100 Subject: [PATCH 201/315] Typo --- waflib/extras/clang_compilation_database.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/extras/clang_compilation_database.py b/waflib/extras/clang_compilation_database.py index 9387668a6d..916ef5b3b0 100644 --- a/waflib/extras/clang_compilation_database.py +++ b/waflib/extras/clang_compilation_database.py @@ -64,7 +64,7 @@ def write_compilation_database(self): except AttributeError: continue f_node = task.inputs[0] - filename = f_node.path_from(task.getcwd()) + filename = f_node.path_from(task.get_cwd()) entry = { "directory": directory, "arguments": cmd, From 4d13ae5669ef01824984b8b4678c2e1d268a06b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C3=ABl=20Kooi?= <3961583-RA-Kooi@users.noreply.gitlab.com> Date: Sun, 10 Nov 2019 15:43:45 +0100 Subject: [PATCH 202/315] Add back an accidentally deleted line clang_compilation_database.py --- waflib/extras/clang_compilation_database.py | 1 + 1 file changed, 1 insertion(+) diff --git a/waflib/extras/clang_compilation_database.py b/waflib/extras/clang_compilation_database.py index 916ef5b3b0..722bc70769 100644 --- a/waflib/extras/clang_compilation_database.py +++ b/waflib/extras/clang_compilation_database.py @@ -63,6 +63,7 @@ def write_compilation_database(self): cmd = task.last_cmd except AttributeError: continue + directory = getattr(task, 'cwd', self.variant_dir) f_node = task.inputs[0] filename = f_node.path_from(task.get_cwd()) entry = { From eac655a174351afbd13c80ec1f5518cdf416fd45 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 10 Nov 2019 19:00:50 +0100 Subject: [PATCH 203/315] Use task.get_cwd() in clang_compilation_database --- waflib/extras/clang_compilation_database.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/waflib/extras/clang_compilation_database.py b/waflib/extras/clang_compilation_database.py index 722bc70769..1398b0af5c 100644 --- a/waflib/extras/clang_compilation_database.py +++ b/waflib/extras/clang_compilation_database.py @@ -25,7 +25,6 @@ def configure(conf): conf.load('clang_compilation_database') """ -import os from waflib import Logs, TaskGen, Task, Build, Scripting Task.Task.keep_last_cmd = True @@ -63,11 +62,10 @@ def write_compilation_database(self): cmd = task.last_cmd except AttributeError: continue - directory = getattr(task, 'cwd', self.variant_dir) f_node = task.inputs[0] filename = f_node.path_from(task.get_cwd()) entry = { - "directory": directory, + "directory": task.get_cwd().abspath(), "arguments": cmd, "file": filename, } From 44b7497109d607d9cf54b7f8511aac15e46f1d8a Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sat, 16 Nov 2019 18:46:57 +0100 Subject: [PATCH 204/315] Improve the Qt5 fPIC/fPIE detection --- waflib/Tools/qt5.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/waflib/Tools/qt5.py b/waflib/Tools/qt5.py index 3a2df68b2f..99e021bae6 100644 --- a/waflib/Tools/qt5.py +++ b/waflib/Tools/qt5.py @@ -482,7 +482,7 @@ def configure(self): self.fatal('No CXX compiler defined: did you forget to configure compiler_cxx first?') # Qt5 may be compiled with '-reduce-relocations' which requires dependent programs to have -fPIE or -fPIC? - frag = '#include \nint main(int argc, char **argv) {return 0;}\n' + frag = '#include \nint main(int argc, char **argv) {QMap m;return m.keys().size();}\n' uses = 'QT5CORE' for flag in [[], '-fPIE', '-fPIC', '-std=c++11' , ['-std=c++11', '-fPIE'], ['-std=c++11', '-fPIC']]: msg = 'See if Qt files compile ' @@ -499,7 +499,7 @@ def configure(self): # FreeBSD does not add /usr/local/lib and the pkg-config files do not provide it either :-/ if Utils.unversioned_sys_platform() == 'freebsd': - frag = '#include \nint main(int argc, char **argv) { QMap app(argc, argv); return NULL != (void*) (&app);}\n' + frag = '#include \nint main(int argc, char **argv) {QMap m;return m.keys().size();}\n' try: self.check(features='qt5 cxx cxxprogram', use=uses, fragment=frag, msg='Can we link Qt programs on FreeBSD directly?') except self.errors.ConfigurationError: From ffa8ce5145eb375fd7207b653eca4c1f0e4e5197 Mon Sep 17 00:00:00 2001 From: Severin Strobl Date: Tue, 19 Nov 2019 10:32:09 +0100 Subject: [PATCH 205/315] Support versioned shared libraries. Shared libraries often use a suffix encoding their version which should be handled when parsing linker flags. --- waflib/Tools/c_config.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/waflib/Tools/c_config.py b/waflib/Tools/c_config.py index 6db55d2cf7..0514086218 100644 --- a/waflib/Tools/c_config.py +++ b/waflib/Tools/c_config.py @@ -107,6 +107,8 @@ def configure(conf): lex.commenters = '' lst = list(lex) + so_re = re.compile(r"\.so(?:\.[0-9]+)*$") + # append_unique is not always possible # for example, apple flags may require both -arch i386 and -arch ppc uselib = uselib_store @@ -184,7 +186,7 @@ def appu(var, val): app('CFLAGS', tmp) app('CXXFLAGS', tmp) app('LINKFLAGS', tmp) - elif x.endswith(('.a', '.so', '.dylib', '.lib')): + elif x.endswith(('.a', '.dylib', '.lib')) or so_re.search(x): appu('LINKFLAGS', x) # not cool, #762 else: self.to_log('Unhandled flag %r' % x) From 52f5e587f8966344ec888d8b5bf3445c7d9d5bfa Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 24 Nov 2019 10:42:23 +0100 Subject: [PATCH 206/315] waf-2.0.19 --- ChangeLog | 8 ++++++-- waf-light | 2 +- waflib/Context.py | 6 +++--- wscript | 2 +- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index a086f7460f..199d8b1781 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,9 +1,13 @@ NEW IN WAF 2.0.19 ----------------- +* Enable race-free pdb file generation waflib/extras/msvc_pdb.py #1731 * Fix negative values for -j #2256 -* Fix the Swig example compatibility with Python3 #2259 -* Add extras/wafcache +* Fix Swig example compatibility with Python3 #2259 +* Fix lto settings for endianness configuration tests #2250 * Tune the application name on --help #2254 +* Improve Qt5's fPIC/fPIE detection +* Propagate LDFLAGS to Fortran tasks (in addition to LINKFLAGS) +* Enable local and remote build object caches waflib/extras/wafcache.py NEW IN WAF 2.0.18 ----------------- diff --git a/waf-light b/waf-light index 713170e00b..d6cf32889f 100755 --- a/waf-light +++ b/waf-light @@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. import os, sys, inspect -VERSION="2.0.18" +VERSION="2.0.19" REVISION="x" GIT="x" INSTALL="x" diff --git a/waflib/Context.py b/waflib/Context.py index 52246c4b5e..ec3cb66b4d 100644 --- a/waflib/Context.py +++ b/waflib/Context.py @@ -18,13 +18,13 @@ class imp(object): import imp # the following 3 constants are updated on each new release (do not touch) -HEXVERSION=0x2001200 +HEXVERSION=0x2001300 """Constant updated on new releases""" -WAFVERSION="2.0.18" +WAFVERSION="2.0.19" """Constant updated on new releases""" -WAFREVISION="314689b8994259a84f0de0aaef74d7ce91f541ad" +WAFREVISION="e83405712e95b47c040763fdfa468c04dfe72e4b" """Git revision when the waf version is updated""" WAFNAME="waf" diff --git a/wscript b/wscript index 81146f052b..f95e568b52 100644 --- a/wscript +++ b/wscript @@ -11,7 +11,7 @@ To add a tool that does not exist in the folder compat15, pass an absolute path: from __future__ import with_statement -VERSION="2.0.18" +VERSION="2.0.19" APPNAME='waf' REVISION='' From b03ff9a0049eadc47a76552980dc5f62eec72b8d Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Fri, 29 Nov 2019 22:58:38 +0100 Subject: [PATCH 207/315] Update irixcc --- waflib/Tools/irixcc.py | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/waflib/Tools/irixcc.py b/waflib/Tools/irixcc.py index c3ae1ac915..dc09363dc7 100644 --- a/waflib/Tools/irixcc.py +++ b/waflib/Tools/irixcc.py @@ -13,22 +13,11 @@ @conf def find_irixcc(conf): v = conf.env - cc = None - if v.CC: - cc = v.CC - elif 'CC' in conf.environ: - cc = conf.environ['CC'] - if not cc: - cc = conf.find_program('cc', var='CC') - if not cc: - conf.fatal('irixcc was not found') - + cc = conf.find_program('cc', var='CC') try: conf.cmd_and_log(cc + ['-version']) except Errors.WafError: conf.fatal('%r -version could not be executed' % cc) - - v.CC = cc v.CC_NAME = 'irix' @conf From 24bce817b0bad8e5d3921fcc8ba75e1738135f1c Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Fri, 29 Nov 2019 23:07:26 +0100 Subject: [PATCH 208/315] Remove conf.find_cpp from irix compiler detection --- waflib/Tools/irixcc.py | 1 - 1 file changed, 1 deletion(-) diff --git a/waflib/Tools/irixcc.py b/waflib/Tools/irixcc.py index dc09363dc7..0335c13cb6 100644 --- a/waflib/Tools/irixcc.py +++ b/waflib/Tools/irixcc.py @@ -46,7 +46,6 @@ def irixcc_common_flags(conf): def configure(conf): conf.find_irixcc() - conf.find_cpp() conf.find_ar() conf.irixcc_common_flags() conf.cc_load_tools() From 11257de95c9d1c4cac3a18ab078e9095a8593b31 Mon Sep 17 00:00:00 2001 From: Adriano Scoditti Date: Thu, 28 Nov 2019 18:13:36 +0100 Subject: [PATCH 209/315] Make distclean target 'no_lock_in_top/run' modifiers compatible with env vars --- waflib/Options.py | 6 +++--- waflib/Scripting.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/waflib/Options.py b/waflib/Options.py index db67953157..0276de0543 100644 --- a/waflib/Options.py +++ b/waflib/Options.py @@ -141,9 +141,9 @@ def __init__(self, **kw): gr.add_option('-o', '--out', action='store', default='', help='build dir for the project', dest='out') gr.add_option('-t', '--top', action='store', default='', help='src dir for the project', dest='top') - gr.add_option('--no-lock-in-run', action='store_true', default='', help=optparse.SUPPRESS_HELP, dest='no_lock_in_run') - gr.add_option('--no-lock-in-out', action='store_true', default='', help=optparse.SUPPRESS_HELP, dest='no_lock_in_out') - gr.add_option('--no-lock-in-top', action='store_true', default='', help=optparse.SUPPRESS_HELP, dest='no_lock_in_top') + gr.add_option('--no-lock-in-run', action='store_true', default=os.environ.get('NO_LOCK_IN_RUN', ''), help=optparse.SUPPRESS_HELP, dest='no_lock_in_run') + gr.add_option('--no-lock-in-out', action='store_true', default=os.environ.get('NO_LOCK_IN_OUT', ''), help=optparse.SUPPRESS_HELP, dest='no_lock_in_out') + gr.add_option('--no-lock-in-top', action='store_true', default=os.environ.get('NO_LOCK_IN_TOP', ''), help=optparse.SUPPRESS_HELP, dest='no_lock_in_top') default_prefix = getattr(Context.g_module, 'default_prefix', os.environ.get('PREFIX')) if not default_prefix: diff --git a/waflib/Scripting.py b/waflib/Scripting.py index 68dccf29ce..da83a2166a 100644 --- a/waflib/Scripting.py +++ b/waflib/Scripting.py @@ -306,7 +306,7 @@ def remove_and_log(k, fun): # remove a build folder, if any cur = '.' - if ctx.options.no_lock_in_top: + if os.environ.get('NO_LOCK_IN_TOP') or ctx.options.no_lock_in_top: cur = ctx.options.out try: @@ -333,9 +333,9 @@ def remove_and_log(k, fun): remove_and_log(env.out_dir, shutil.rmtree) env_dirs = [env.out_dir] - if not ctx.options.no_lock_in_top: + if not (os.environ.get('NO_LOCK_IN_TOP') or ctx.options.no_lock_in_top): env_dirs.append(env.top_dir) - if not ctx.options.no_lock_in_run: + if not (os.environ.get('NO_LOCK_IN_RUN') or ctx.options.no_lock_in_run): env_dirs.append(env.run_dir) for k in env_dirs: p = os.path.join(k, Options.lockfile) From 2a98d0f1ea57fd211a490de1c2563b9500dd5609 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sat, 14 Dec 2019 23:49:03 +0100 Subject: [PATCH 210/315] Make multicheck collisions less likely --- waflib/Tools/c_config.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/waflib/Tools/c_config.py b/waflib/Tools/c_config.py index 0514086218..bf6f1a459c 100644 --- a/waflib/Tools/c_config.py +++ b/waflib/Tools/c_config.py @@ -1282,10 +1282,11 @@ def to_log(self, *k, **kw): tasks = [] id_to_task = {} - for dct in k: + for counter, dct in enumerate(k): x = Task.classes['cfgtask'](bld=bld, env=None) tasks.append(x) x.args = dct + x.args['multicheck_counter'] = counter x.bld = bld x.conf = self x.args = dct From 53b35e8846e4a28247958a67da67483e43b82c05 Mon Sep 17 00:00:00 2001 From: "Morten V. Pedersen" Date: Wed, 18 Dec 2019 11:24:32 +0100 Subject: [PATCH 211/315] Fix detection of build context when a custom context is used --- waflib/extras/clang_compilation_database.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/extras/clang_compilation_database.py b/waflib/extras/clang_compilation_database.py index 1398b0af5c..2c8747dc12 100644 --- a/waflib/extras/clang_compilation_database.py +++ b/waflib/extras/clang_compilation_database.py @@ -123,7 +123,7 @@ def new_execute_build(self): """ Invoke clangdb command before build """ - if type(self) == Build.BuildContext: + if isinstance(self, Build.BuildContext): Scripting.run_command('clangdb') old_execute_build(self) From eb469b17df6c244e878e4446d6f25d3b37a97021 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Fri, 20 Dec 2019 07:55:36 +0100 Subject: [PATCH 212/315] Exclude ConfigSet from altering ConfigurationContext.run_build caches #2273 --- waflib/Configure.py | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/waflib/Configure.py b/waflib/Configure.py index 5762eb6695..e733394848 100644 --- a/waflib/Configure.py +++ b/waflib/Configure.py @@ -508,23 +508,27 @@ def find_binary(self, filenames, exts, paths): @conf def run_build(self, *k, **kw): """ - Create a temporary build context to execute a build. A reference to that build - context is kept on self.test_bld for debugging purposes, and you should not rely - on it too much (read the note on the cache below). - The parameters given in the arguments to this function are passed as arguments for - a single task generator created in the build. Only three parameters are obligatory: + Create a temporary build context to execute a build. A temporary reference to that build + context is kept on self.test_bld for debugging purposes. + The arguments to this function are passed to a single task generator for that build. + Only three parameters are mandatory: :param features: features to pass to a task generator created in the build :type features: list of string :param compile_filename: file to create for the compilation (default: *test.c*) :type compile_filename: string - :param code: code to write in the filename to compile + :param code: input file contents :type code: string - Though this function returns *0* by default, the build may set an attribute named *retval* on the + Though this function returns *0* by default, the build may bind attribute named *retval* on the build context object to return a particular value. See :py:func:`waflib.Tools.c_config.test_exec_fun` for example. - This function also features a cache which can be enabled by the following option:: + The temporary builds creates a temporary folder; the name of that folder is calculated + by hashing input arguments to this function, with the exception of :py:class:`waflib.ConfigSet.ConfigSet` + objects which are used for both reading and writing values. + + This function also features a cache which is disabled by default; that cache relies + on the hash value calculated as indicated above:: def options(opt): opt.add_option('--confcache', dest='confcache', default=0, @@ -538,7 +542,10 @@ def options(opt): buf = [] for key in sorted(kw.keys()): v = kw[key] - if hasattr(v, '__call__'): + if isinstance(v, ConfigSet.ConfigSet): + # values are being written to, so they are excluded from contributing to the hash + continue + elif hasattr(v, '__call__'): buf.append(Utils.h_fun(v)) else: buf.append(str(v)) From 60c0d3e05eb48d0ba6897667ae1075d5e3776bae Mon Sep 17 00:00:00 2001 From: "Morten V. Pedersen" Date: Thu, 2 Jan 2020 14:47:39 +0100 Subject: [PATCH 213/315] Using suggested self.cmd.startswith approach --- waflib/extras/clang_compilation_database.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/extras/clang_compilation_database.py b/waflib/extras/clang_compilation_database.py index 2c8747dc12..ff71f22ecf 100644 --- a/waflib/extras/clang_compilation_database.py +++ b/waflib/extras/clang_compilation_database.py @@ -123,7 +123,7 @@ def new_execute_build(self): """ Invoke clangdb command before build """ - if isinstance(self, Build.BuildContext): + if self.cmd.startswith('build'): Scripting.run_command('clangdb') old_execute_build(self) From 8048358eebd616b484f59e9bbd9e7112fbfc18f5 Mon Sep 17 00:00:00 2001 From: Federico Pellegrin Date: Sat, 4 Jan 2020 09:35:07 +0100 Subject: [PATCH 214/315] javaw: fix buglet overwrites working variable while adding dependencies variable x is used in the outer loop and gets corrupted by inner enumeration in case of non-jar dependency to reproduce: use the demos/java and run waf build twice: the first time will work (since no class files around) while the second will not since will by bad luck pick a class file in the inner loop --- waflib/Tools/javaw.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/Tools/javaw.py b/waflib/Tools/javaw.py index ceb08c28c8..b7f5dd1f87 100644 --- a/waflib/Tools/javaw.py +++ b/waflib/Tools/javaw.py @@ -251,7 +251,7 @@ def use_javac_files(self): base_node = tg.path.get_bld() self.use_lst.append(base_node.abspath()) - self.javac_task.dep_nodes.extend([x for x in base_node.ant_glob(JAR_RE, remove=False, quiet=True)]) + self.javac_task.dep_nodes.extend([dx for dx in base_node.ant_glob(JAR_RE, remove=False, quiet=True)]) for tsk in tg.tasks: self.javac_task.set_run_after(tsk) From 958cd11ca566ffde35f96f3ae4c8a0c2806fc8b8 Mon Sep 17 00:00:00 2001 From: Federico Pellegrin Date: Sat, 4 Jan 2020 10:17:40 +0100 Subject: [PATCH 215/315] javatest: add dependency management for jar/java taskgens --- waflib/extras/javatest.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/waflib/extras/javatest.py b/waflib/extras/javatest.py index f3c6cbf7d2..76d40edf25 100755 --- a/waflib/extras/javatest.py +++ b/waflib/extras/javatest.py @@ -60,6 +60,8 @@ def build(bld): from waflib import Task, TaskGen, Options, Errors, Utils, Logs from waflib.Tools import ccroot +JAR_RE = '**/*' + def _process_use_rec(self, name): """ Recursively process ``use`` for task generator with name ``name``.. @@ -139,6 +141,20 @@ def extend_unique(lst, varlst): # Only add to libpath if the link task is not a Python extension extend_unique(self.javatest_libpaths, [tg.link_task.outputs[0].parent.abspath()]) + if 'javac' in tg.features or 'jar' in tg.features: + if hasattr(tg, 'jar_task'): + # For Java JAR tasks depend on generated JAR + extend_unique(self.javatest_dep_nodes, tg.jar_task.outputs) + else: + # For Java non-JAR ones we need to glob generated files (Java output files are not predictable) + if hasattr(tg, 'outdir'): + base_node = tg.outdir + else: + base_node = tg.path.get_bld() + + self.javatest_dep_nodes.extend([dx for dx in base_node.ant_glob(JAR_RE, remove=False, quiet=True)]) + + @TaskGen.feature('javatest') @TaskGen.after_method('apply_java', 'use_javac_files', 'set_classpath', 'javatest_process_use') From 4329c406c7ca8737794e9703f2f6ebfef1f0b0ea Mon Sep 17 00:00:00 2001 From: Federico Pellegrin Date: Mon, 17 Feb 2020 11:44:14 +0100 Subject: [PATCH 216/315] doxygen: add ext_int to force build ordering --- waflib/extras/doxygen.py | 1 + 1 file changed, 1 insertion(+) diff --git a/waflib/extras/doxygen.py b/waflib/extras/doxygen.py index 20cd9e1a85..de75bc2738 100644 --- a/waflib/extras/doxygen.py +++ b/waflib/extras/doxygen.py @@ -69,6 +69,7 @@ def parse_doxy(txt): class doxygen(Task.Task): vars = ['DOXYGEN', 'DOXYFLAGS'] color = 'BLUE' + ext_in = [ '.py', '.c', '.h', '.java', '.pb.cc' ] def runnable_status(self): ''' From 52077145e1f65465e9f88bd3cadb0a83d7919889 Mon Sep 17 00:00:00 2001 From: Michael Vincent Date: Mon, 24 Feb 2020 11:27:30 -0600 Subject: [PATCH 217/315] gccdeps: Add support for gas Add support for generating and using gcc's native dependency files with the GNU Assembler in addition to the existing C/C++ support. When the gas and gccdeps tools are loaded, the configure step will test whether gcc operating on an assembly file supports the -MMD argument. If so, waf will pass the -MMD argument to .S files assembled with gcc which will cause it to generate .d dependency files. Waf will then parse those files for dependency information. Note: This will only work for assembly files compiled through the gcc frontend, not with GNU as directly. It also requires assembly files to use the uppercase .S file extension. --- demos/asm/wscript | 2 +- waflib/extras/gccdeps.py | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/demos/asm/wscript b/demos/asm/wscript index b17b57db5c..ccd833251a 100644 --- a/demos/asm/wscript +++ b/demos/asm/wscript @@ -4,7 +4,7 @@ import sys def configure(conf): - conf.load('gcc gas') + conf.load('gcc gas gccdeps') try: size = sys.maxint except AttributeError: diff --git a/waflib/extras/gccdeps.py b/waflib/extras/gccdeps.py index ba01b1b320..c9c5c31c7b 100644 --- a/waflib/extras/gccdeps.py +++ b/waflib/extras/gccdeps.py @@ -27,7 +27,7 @@ def configure(conf): gccdeps_flags = ['-MMD'] # Third-party tools are allowed to add extra names in here with append() -supported_compilers = ['gcc', 'icc', 'clang'] +supported_compilers = ['gas', 'gcc', 'icc', 'clang'] def scan(self): if not self.__class__.__name__ in self.env.ENABLE_GCCDEPS: @@ -175,14 +175,14 @@ def wrap_compiled_task(classname): derived_class.scan = scan derived_class.sig_implicit_deps = sig_implicit_deps -for k in ('c', 'cxx'): +for k in ('asm', 'c', 'cxx'): if k in Task.classes: wrap_compiled_task(k) @before_method('process_source') @feature('force_gccdeps') def force_gccdeps(self): - self.env.ENABLE_GCCDEPS = ['c', 'cxx'] + self.env.ENABLE_GCCDEPS = ['asm', 'c', 'cxx'] def configure(conf): # in case someone provides a --enable-gccdeps command-line option @@ -191,6 +191,15 @@ def configure(conf): global gccdeps_flags flags = conf.env.GCCDEPS_FLAGS or gccdeps_flags + if conf.env.ASM_NAME in supported_compilers: + try: + conf.check(fragment='', features='asm force_gccdeps', asflags=flags, compile_filename='test.S', msg='Checking for asm flags %r' % ''.join(flags)) + except Errors.ConfigurationError: + pass + else: + conf.env.append_value('ASFLAGS', flags) + conf.env.append_unique('ENABLE_GCCDEPS', 'asm') + if conf.env.CC_NAME in supported_compilers: try: conf.check(fragment='int main() { return 0; }', features='c force_gccdeps', cflags=flags, msg='Checking for c flags %r' % ''.join(flags)) From 2ed75ac5740e85637b0964c5c8ff3ceef56e3c04 Mon Sep 17 00:00:00 2001 From: swaldhoer <34184299+swaldhoer@users.noreply.github.com> Date: Sat, 29 Feb 2020 11:00:12 +0100 Subject: [PATCH 218/315] add support for clang on cygwin --- waflib/Tools/compiler_c.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/Tools/compiler_c.py b/waflib/Tools/compiler_c.py index 2dba3f8270..931dc57efe 100644 --- a/waflib/Tools/compiler_c.py +++ b/waflib/Tools/compiler_c.py @@ -37,7 +37,7 @@ def build(bld): c_compiler = { 'win32': ['msvc', 'gcc', 'clang'], -'cygwin': ['gcc'], +'cygwin': ['gcc', 'clang'], 'darwin': ['clang', 'gcc'], 'aix': ['xlc', 'gcc', 'clang'], 'linux': ['gcc', 'clang', 'icc'], From 8359238445847edb839e637d6076ce8f1957e000 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sat, 29 Feb 2020 23:09:08 +0100 Subject: [PATCH 219/315] Remove the accidental gccdeps requirement --- demos/asm/wscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demos/asm/wscript b/demos/asm/wscript index ccd833251a..b17b57db5c 100644 --- a/demos/asm/wscript +++ b/demos/asm/wscript @@ -4,7 +4,7 @@ import sys def configure(conf): - conf.load('gcc gas gccdeps') + conf.load('gcc gas') try: size = sys.maxint except AttributeError: From c4434dff146f70a01550c75d21e3ad7ee2d1dadb Mon Sep 17 00:00:00 2001 From: swaldhoer <34184299+swaldhoer@users.noreply.github.com> Date: Sun, 1 Mar 2020 13:32:53 +0100 Subject: [PATCH 220/315] Add support for clang++ on cygwin --- waflib/Tools/compiler_cxx.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/Tools/compiler_cxx.py b/waflib/Tools/compiler_cxx.py index 1af65a226d..09fca7e4dc 100644 --- a/waflib/Tools/compiler_cxx.py +++ b/waflib/Tools/compiler_cxx.py @@ -38,7 +38,7 @@ def build(bld): cxx_compiler = { 'win32': ['msvc', 'g++', 'clang++'], -'cygwin': ['g++'], +'cygwin': ['g++', 'clang++'], 'darwin': ['clang++', 'g++'], 'aix': ['xlc++', 'g++', 'clang++'], 'linux': ['g++', 'clang++', 'icpc'], From f7d193a7fdd52f63c2e7651905058269246f6d71 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Wed, 4 Mar 2020 23:14:40 +0100 Subject: [PATCH 221/315] Improve custom option processing #2280 --- waflib/Options.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/waflib/Options.py b/waflib/Options.py index 0276de0543..d4104917c8 100644 --- a/waflib/Options.py +++ b/waflib/Options.py @@ -62,6 +62,21 @@ def _process_args(self, largs, rargs, values): else: self.error(str(e)) + def _process_long_opt(self, rargs, values): + # --custom-option=-ftxyz is interpreted as -f -t... see #2280 + if self.allow_unknown: + back = [] + rargs + try: + optparse.OptionParser._process_long_opt(self, rargs, values) + except optparse.BadOptionError: + while rargs: + rargs.pop() + rargs.extend(back) + rargs.pop(0) + raise + else: + optparse.OptionParser._process_long_opt(self, rargs, values) + def print_usage(self, file=None): return self.print_help(file) From 9dd2a369bce9c2cb28b3bbfad3ec210d7ca7bfe4 Mon Sep 17 00:00:00 2001 From: Federico Pellegrin Date: Thu, 19 Mar 2020 09:01:34 +0100 Subject: [PATCH 222/315] c_config: -flto and -fno-lto need to be passed also when linking --- waflib/Tools/c_config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/Tools/c_config.py b/waflib/Tools/c_config.py index bf6f1a459c..dace2b917f 100644 --- a/waflib/Tools/c_config.py +++ b/waflib/Tools/c_config.py @@ -150,7 +150,7 @@ def appu(var, val): elif x.startswith('-std='): prefix = 'CXXFLAGS' if '++' in x else 'CFLAGS' app(prefix, x) - elif x.startswith('+') or x in ('-pthread', '-fPIC', '-fpic', '-fPIE', '-fpie'): + elif x.startswith('+') or x in ('-pthread', '-fPIC', '-fpic', '-fPIE', '-fpie', '-flto', '-fno-lto'): app('CFLAGS', x) app('CXXFLAGS', x) app('LINKFLAGS', x) From c0d5ea057f3e56b57dcc464663a00d55b6b1d6e9 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sat, 28 Mar 2020 09:16:58 +0100 Subject: [PATCH 223/315] waf-2.0.20 --- ChangeLog | 11 +++++++++++ waf-light | 2 +- waflib/Context.py | 6 +++--- wscript | 2 +- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 199d8b1781..fbe7e06e8d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +NEW IN WAF 2.0.20 +----------------- +* Detect -flto and -fno-lto in parse_config #2281 +* Improve custom option processing #2280 +* Enable Clang on cygwin #2279 +* Make distclean target 'no_lock_in_top/run' modifiers compatible with env vars #2271 +* Update irix compiler detection +* Exclude ConfigSet from altering ConfigurationContext.run_build caches #2273 +* Add gas support in extras/gccdeps.py #2278 +* Improve compatibility with custom commands in extras/clang_compilation_database #2274 + NEW IN WAF 2.0.19 ----------------- * Enable race-free pdb file generation waflib/extras/msvc_pdb.py #1731 diff --git a/waf-light b/waf-light index d6cf32889f..e280b90a7b 100755 --- a/waf-light +++ b/waf-light @@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. import os, sys, inspect -VERSION="2.0.19" +VERSION="2.0.20" REVISION="x" GIT="x" INSTALL="x" diff --git a/waflib/Context.py b/waflib/Context.py index ec3cb66b4d..3f1b4fa48a 100644 --- a/waflib/Context.py +++ b/waflib/Context.py @@ -18,13 +18,13 @@ class imp(object): import imp # the following 3 constants are updated on each new release (do not touch) -HEXVERSION=0x2001300 +HEXVERSION=0x2001400 """Constant updated on new releases""" -WAFVERSION="2.0.19" +WAFVERSION="2.0.20" """Constant updated on new releases""" -WAFREVISION="e83405712e95b47c040763fdfa468c04dfe72e4b" +WAFREVISION="668769470956da8c5b60817cb8884cd7d0f87cd4" """Git revision when the waf version is updated""" WAFNAME="waf" diff --git a/wscript b/wscript index f95e568b52..3e127b73e6 100644 --- a/wscript +++ b/wscript @@ -11,7 +11,7 @@ To add a tool that does not exist in the folder compat15, pass an absolute path: from __future__ import with_statement -VERSION="2.0.19" +VERSION="2.0.20" APPNAME='waf' REVISION='' From 3c56a3b95b6213662dd8c52e12e5c231dbafe9e4 Mon Sep 17 00:00:00 2001 From: Mathieu Courtois Date: Thu, 9 Apr 2020 15:58:05 +0200 Subject: [PATCH 224/315] boost: fix removal of lib extension --- waflib/extras/boost.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/waflib/extras/boost.py b/waflib/extras/boost.py index c2aaaa938a..853623405d 100644 --- a/waflib/extras/boost.py +++ b/waflib/extras/boost.py @@ -270,10 +270,12 @@ def find_lib(re_lib, files): return file return None + # extensions from Tools.ccroot.lib_patterns + wo_ext = re.compile(r"\.(a|so|lib|dll|dylib)$") def format_lib_name(name): if name.startswith('lib') and self.env.CC_NAME != 'msvc': name = name[3:] - return name[:name.rfind('.')] + return wo_ext.sub("", name) def match_libs(lib_names, is_static): libs = [] @@ -522,4 +524,3 @@ def install_boost(self): except: continue install_boost.done = False - From a1ffcb62232f162d0b65c27f8de4c8a335a5f468 Mon Sep 17 00:00:00 2001 From: Mathieu Courtois Date: Fri, 10 Apr 2020 09:34:26 +0200 Subject: [PATCH 225/315] boost: ignore version number from library name --- waflib/extras/boost.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/extras/boost.py b/waflib/extras/boost.py index 853623405d..93b312a1e6 100644 --- a/waflib/extras/boost.py +++ b/waflib/extras/boost.py @@ -271,7 +271,7 @@ def find_lib(re_lib, files): return None # extensions from Tools.ccroot.lib_patterns - wo_ext = re.compile(r"\.(a|so|lib|dll|dylib)$") + wo_ext = re.compile(r"\.(a|so|lib|dll|dylib)(\.[0-9\.]+)?$") def format_lib_name(name): if name.startswith('lib') and self.env.CC_NAME != 'msvc': name = name[3:] From 71428c29da4184e2045014153b6a84899e2ae0d5 Mon Sep 17 00:00:00 2001 From: Michael Vincent Date: Wed, 22 Apr 2020 19:04:28 -0500 Subject: [PATCH 226/315] msvcdeps: Tweak debug output Print out which source file waf is gathering dependencies for and leave the leading spaces in the dependency debug output because it can be helpful to see the dependency hierarchy. --- waflib/extras/msvcdeps.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/waflib/extras/msvcdeps.py b/waflib/extras/msvcdeps.py index 873a419315..6c7f01539a 100644 --- a/waflib/extras/msvcdeps.py +++ b/waflib/extras/msvcdeps.py @@ -211,11 +211,14 @@ def exec_command(self, cmd, **kw): # get one from the exception object ret = getattr(e, 'returncode', 1) + Logs.debug('msvcdeps: Running for: %s' % self.inputs[0]) for line in raw_out.splitlines(): if line.startswith(INCLUDE_PATTERN): - inc_path = line[len(INCLUDE_PATTERN):].strip() + # Only strip whitespace after log to preserve + # dependency structure in debug output + inc_path = line[len(INCLUDE_PATTERN):] Logs.debug('msvcdeps: Regex matched %s', inc_path) - self.msvcdeps_paths.append(inc_path) + self.msvcdeps_paths.append(inc_path.strip()) else: out.append(line) From d609f8a9045d613fa68970aeaef252ae8e8949db Mon Sep 17 00:00:00 2001 From: Federico Pellegrin Date: Thu, 30 Apr 2020 07:59:03 +0200 Subject: [PATCH 227/315] qt5: improve documentation on library detection and options --- waflib/Tools/qt5.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/waflib/Tools/qt5.py b/waflib/Tools/qt5.py index 99e021bae6..3a23abaa46 100644 --- a/waflib/Tools/qt5.py +++ b/waflib/Tools/qt5.py @@ -57,7 +57,23 @@ def add_includes_paths(self): (QT5_{ROOT,DIR,MOC,UIC,XCOMPILE}) allow finer tuning of the tool, tool path selection, etc; please read the source for more info. -The detection uses pkg-config on Linux by default. To force static library detection use: +The detection uses pkg-config on Linux by default. The list of +libraries to be requested to pkg-config is formulated by scanning +in the QTLIBS directory (that can be passed via --qtlibs or by +setting the environment variable QT5_LIBDIR otherwise is derived +by querying qmake for QT_INSTALL_LIBS directory) for shared/static +libraries present. +Alternatively the list of libraries to be requested via pkg-config +can be set using the qt5_vars attribute, ie: + + conf.qt5_vars = ['Qt5Core', 'Qt5Gui', 'Qt5Widgets', 'Qt5Test']; + +This can speed up configuration phase if needed libraries are +known beforehand, can improve detection on systems with a +sparse QT5 libraries installation (ie. NIX) and can improve +detection of some header-only Qt modules (ie. Qt5UiPlugin). + +To force static library detection use: QT5_XCOMPILE=1 QT5_FORCE_STATIC=1 waf configure """ From 9ea3e94ef6ff705a078750ff97eace03ba42b8e9 Mon Sep 17 00:00:00 2001 From: Federico Pellegrin Date: Wed, 6 May 2020 13:50:26 +0200 Subject: [PATCH 228/315] sphinx: fix installation phase (as generated files are unknown until build) --- waflib/extras/sphinx.py | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/waflib/extras/sphinx.py b/waflib/extras/sphinx.py index ce11110e63..71d1028393 100644 --- a/waflib/extras/sphinx.py +++ b/waflib/extras/sphinx.py @@ -20,7 +20,7 @@ def build(bld): from waflib.Node import Node from waflib import Utils -from waflib.Task import Task +from waflib import Task from waflib.TaskGen import feature, after_method @@ -55,13 +55,9 @@ def build_sphinx(self): sphinx_build_task.set_outputs(self.path.get_bld()) # the sphinx-build results are in directory - sphinx_output_directory = self.path.get_bld().make_node(self.env.SPHINX_OUTPUT_FORMAT) - sphinx_output_directory.mkdir() + self.sphinx_output_directory = self.path.get_bld().make_node(self.env.SPHINX_OUTPUT_FORMAT) + self.sphinx_output_directory.mkdir() Utils.def_attrs(self, install_path=get_install_path(self)) - self.add_install_files(install_to=self.install_path, - install_from=sphinx_output_directory.ant_glob('**/*'), - cwd=sphinx_output_directory, - relative_trick=True) def get_install_path(tg): @@ -73,9 +69,37 @@ def get_install_path(tg): return tg.env.DOCDIR -class SphinxBuildingTask(Task): +class SphinxBuildingTask(Task.Task): color = 'BOLD' run_str = '${SPHINX_BUILD} -M ${SPHINX_OUTPUT_FORMAT} ${SRC} ${TGT} ${SPHINX_OPTIONS}' def keyword(self): return 'Compiling (%s)' % self.env.SPHINX_OUTPUT_FORMAT + + def runnable_status(self): + + for x in self.run_after: + if not x.hasrun: + return Task.ASK_LATER + + self.signature() + ret = Task.Task.runnable_status(self) + if ret == Task.SKIP_ME: + # in case the files were removed + self.add_install() + return ret + + + def post_run(self): + self.add_install() + return Task.Task.post_run(self) + + + def add_install(self): + nodes = self.generator.sphinx_output_directory.ant_glob('**/*', quiet=True) + self.outputs += nodes + self.generator.add_install_files(install_to=self.generator.install_path, + install_from=nodes, + postpone=False, + cwd=self.generator.sphinx_output_directory, + relative_trick=True) From 384fd603191900c61336dddabdf3f23e355d1c98 Mon Sep 17 00:00:00 2001 From: Johan Pauwels Date: Thu, 14 May 2020 20:26:43 +0000 Subject: [PATCH 229/315] Xcode6 py3 fix. The return type of .keys() in Python 3 is no longer a list, but a 'dict_keys', which does not support the '+' operator. --- waflib/extras/xcode6.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/extras/xcode6.py b/waflib/extras/xcode6.py index 91bbff181e..0dd68b94fb 100644 --- a/waflib/extras/xcode6.py +++ b/waflib/extras/xcode6.py @@ -591,7 +591,7 @@ def process_xcode(self): # The keys represents different build configuration, e.g. Debug, Release and so on.. # Insert our generated build settings to all configuration names - keys = set(settings.keys() + bld.env.PROJ_CONFIGURATION.keys()) + keys = set(settings.keys()) | set(bld.env.PROJ_CONFIGURATION.keys()) for k in keys: if k in settings: settings[k].update(bldsettings) From 227cd8be95d0f58bd08bdc0c1fa272e284dfd7bc Mon Sep 17 00:00:00 2001 From: Johan Pauwels Date: Mon, 18 May 2020 13:09:40 +0100 Subject: [PATCH 230/315] Fix alignment in generated Xcode file --- waflib/extras/xcode6.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/waflib/extras/xcode6.py b/waflib/extras/xcode6.py index 0dd68b94fb..deb956e1fc 100644 --- a/waflib/extras/xcode6.py +++ b/waflib/extras/xcode6.py @@ -167,8 +167,8 @@ def tostring(self, value): elif isinstance(value, list): result = "(\n" for i in value: - result = result + "\t\t\t%s,\n" % self.tostring(i) - result = result + "\t\t)" + result = result + "\t\t\t\t%s,\n" % self.tostring(i) + result = result + "\t\t\t)" return result elif isinstance(value, XCodeNode): return value._id From 5de5b3cad631f2a2e497466e9ec3389630b622aa Mon Sep 17 00:00:00 2001 From: Johan Pauwels Date: Mon, 18 May 2020 13:12:48 +0100 Subject: [PATCH 231/315] Fix configuration of linker flags in Xcode file --- waflib/extras/xcode6.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/waflib/extras/xcode6.py b/waflib/extras/xcode6.py index deb956e1fc..0d04837c9f 100644 --- a/waflib/extras/xcode6.py +++ b/waflib/extras/xcode6.py @@ -99,7 +99,7 @@ def delete_invalid_values(dct): ... } 'Release': { - 'ARCHS' x86_64' + 'ARCHS': x86_64' ... } } @@ -565,10 +565,9 @@ def process_xcode(self): # Override target specific build settings bldsettings = { 'HEADER_SEARCH_PATHS': ['$(inherited)'] + self.env['INCPATHS'], - 'LIBRARY_SEARCH_PATHS': ['$(inherited)'] + Utils.to_list(self.env.LIBPATH) + Utils.to_list(self.env.STLIBPATH) + Utils.to_list(self.env.LIBDIR) , + 'LIBRARY_SEARCH_PATHS': ['$(inherited)'] + Utils.to_list(self.env.LIBPATH) + Utils.to_list(self.env.STLIBPATH) + Utils.to_list(self.env.LIBDIR), 'FRAMEWORK_SEARCH_PATHS': ['$(inherited)'] + Utils.to_list(self.env.FRAMEWORKPATH), - 'OTHER_LDFLAGS': libs + ' ' + frameworks, - 'OTHER_LIBTOOLFLAGS': bld.env['LINKFLAGS'], + 'OTHER_LDFLAGS': libs + ' ' + frameworks + ' ' + ' '.join(bld.env['LINKFLAGS']), 'OTHER_CPLUSPLUSFLAGS': Utils.to_list(self.env['CXXFLAGS']), 'OTHER_CFLAGS': Utils.to_list(self.env['CFLAGS']), 'INSTALL_PATH': [] From 513484e76939cc824ed28757c098dc7874fe1e03 Mon Sep 17 00:00:00 2001 From: Johan Pauwels Date: Mon, 18 May 2020 13:13:51 +0100 Subject: [PATCH 232/315] Export preprocessor macros in Xcode project --- waflib/extras/xcode6.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/waflib/extras/xcode6.py b/waflib/extras/xcode6.py index 0d04837c9f..24f0d15990 100644 --- a/waflib/extras/xcode6.py +++ b/waflib/extras/xcode6.py @@ -570,7 +570,8 @@ def process_xcode(self): 'OTHER_LDFLAGS': libs + ' ' + frameworks + ' ' + ' '.join(bld.env['LINKFLAGS']), 'OTHER_CPLUSPLUSFLAGS': Utils.to_list(self.env['CXXFLAGS']), 'OTHER_CFLAGS': Utils.to_list(self.env['CFLAGS']), - 'INSTALL_PATH': [] + 'INSTALL_PATH': [], + 'GCC_PREPROCESSOR_DEFINITIONS': self.env['DEFINES'] } # Install path From c57a1e3f843688fbc113321d01c31bdf846a1cc1 Mon Sep 17 00:00:00 2001 From: Johan Pauwels Date: Mon, 18 May 2020 13:15:11 +0100 Subject: [PATCH 233/315] Escape quoted strings in Xcode project --- waflib/extras/xcode6.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/extras/xcode6.py b/waflib/extras/xcode6.py index 24f0d15990..c5b309120c 100644 --- a/waflib/extras/xcode6.py +++ b/waflib/extras/xcode6.py @@ -163,7 +163,7 @@ def tostring(self, value): result = result + "\t\t}" return result elif isinstance(value, str): - return "\"%s\"" % value + return '"%s"' % value.replace('"', '\\\\\\"') elif isinstance(value, list): result = "(\n" for i in value: From 04e393454bfae49c7286a5488940fac888ec8bef Mon Sep 17 00:00:00 2001 From: Andreu Montiel Date: Sat, 13 Jun 2020 16:45:18 +0200 Subject: [PATCH 234/315] Allow parameter "always" in doxygen tool (waflib/extra/doxygen.py) --- waflib/extras/doxygen.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/waflib/extras/doxygen.py b/waflib/extras/doxygen.py index de75bc2738..0fda70361f 100644 --- a/waflib/extras/doxygen.py +++ b/waflib/extras/doxygen.py @@ -208,10 +208,10 @@ def process_doxy(self): self.bld.fatal('doxygen file %s not found' % self.doxyfile) # the task instance - dsk = self.create_task('doxygen', node) + dsk = self.create_task('doxygen', node, always_run=getattr(self, 'always', False)) if getattr(self, 'doxy_tar', None): - tsk = self.create_task('tar') + tsk = self.create_task('tar', always_run=getattr(self, 'always', False)) tsk.input_tasks = [dsk] tsk.set_outputs(self.path.find_or_declare(self.doxy_tar)) if self.doxy_tar.endswith('bz2'): From ea65e240dec24235ffa331c688926b89391c5f97 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Thu, 18 Jun 2020 21:15:46 +0200 Subject: [PATCH 235/315] Update c_dumbpreproc (broken) --- waflib/extras/c_dumbpreproc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/extras/c_dumbpreproc.py b/waflib/extras/c_dumbpreproc.py index ce9e1a400b..1fdd5c364a 100644 --- a/waflib/extras/c_dumbpreproc.py +++ b/waflib/extras/c_dumbpreproc.py @@ -66,7 +66,7 @@ def start(self, node, env): if x == c_preproc.POPFILE: self.currentnode_stack.pop() continue - self.tryfind(y) + self.tryfind(y, env=env) c_preproc.c_parser = dumb_parser From e6bb2ebce4f61ed3d3f41bafba652c58f13836c5 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sat, 20 Jun 2020 00:45:00 +0200 Subject: [PATCH 236/315] gccdeps/msvcdeps: renaming a header must rebuild silently #2293 --- waflib/extras/gccdeps.py | 6 +++++- waflib/extras/msvcdeps.py | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/waflib/extras/gccdeps.py b/waflib/extras/gccdeps.py index c9c5c31c7b..1506033ed0 100644 --- a/waflib/extras/gccdeps.py +++ b/waflib/extras/gccdeps.py @@ -15,7 +15,7 @@ def configure(conf): conf.load('compiler_cxx gccdeps') """ -import os, re, threading +import errno, os, re, threading from waflib import Task, Logs, Utils, Errors from waflib.Tools import c_preproc from waflib.TaskGen import before_method, feature @@ -167,6 +167,10 @@ def sig_implicit_deps(self): return Task.Task.sig_implicit_deps(self) except Errors.WafError: return Utils.SIG_NIL + except EnvironmentError as e: + if e.errno == errno.ENOENT: + return Utils.SIG_NIL + raise def wrap_compiled_task(classname): derived_class = type(classname, (Task.classes[classname],), {}) diff --git a/waflib/extras/msvcdeps.py b/waflib/extras/msvcdeps.py index 6c7f01539a..c85c69490d 100644 --- a/waflib/extras/msvcdeps.py +++ b/waflib/extras/msvcdeps.py @@ -25,7 +25,7 @@ def configure(conf): conf.load('compiler_cxx msvcdeps') ''' -import os, sys, tempfile, threading +import errno, os, sys, tempfile, threading from waflib import Context, Errors, Logs, Task, Utils from waflib.Tools import c_preproc, c, cxx, msvc @@ -155,6 +155,10 @@ def sig_implicit_deps(self): return Task.Task.sig_implicit_deps(self) except Errors.WafError: return Utils.SIG_NIL + except EnvironmentError as e: + if e.errno == errno.ENOENT: + return Utils.SIG_NIL + raise def exec_command(self, cmd, **kw): if self.env.CC_NAME not in supported_compilers: From ec13b694925d803a6765389de8b1b66c949e58ac Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Thu, 25 Jun 2020 00:55:46 +0200 Subject: [PATCH 237/315] Conceal gccdeps/msvcdeps errors on inaccessible/unreadable files --- waflib/extras/gccdeps.py | 27 +++++++++++++++++++-------- waflib/extras/msvcdeps.py | 26 ++++++++++++++++++-------- 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/waflib/extras/gccdeps.py b/waflib/extras/gccdeps.py index 1506033ed0..0ecaad5d13 100644 --- a/waflib/extras/gccdeps.py +++ b/waflib/extras/gccdeps.py @@ -15,7 +15,7 @@ def configure(conf): conf.load('compiler_cxx gccdeps') """ -import errno, os, re, threading +import os, re, threading from waflib import Task, Logs, Utils, Errors from waflib.Tools import c_preproc from waflib.TaskGen import before_method, feature @@ -163,14 +163,25 @@ def post_run(self): def sig_implicit_deps(self): if not self.__class__.__name__ in self.env.ENABLE_GCCDEPS: return super(self.derived_gccdeps, self).sig_implicit_deps() + bld = self.generator.bld + try: - return Task.Task.sig_implicit_deps(self) - except Errors.WafError: - return Utils.SIG_NIL - except EnvironmentError as e: - if e.errno == errno.ENOENT: - return Utils.SIG_NIL - raise + return self.compute_sig_implicit_deps() + except Errors.TaskNotReady: + raise ValueError("Please specify the build order precisely with gccdeps (asm/c/c++ tasks)") + except EnvironmentError: + # If a file is renamed, assume the dependencies are stale and must be recalculated + for x in bld.node_deps.get(self.uid(), []): + if not x.is_bld() and not x.exists(): + try: + del x.parent.children[x.name] + except KeyError: + pass + + key = self.uid() + bld.node_deps[key] = [] + bld.raw_deps[key] = [] + return Utils.SIG_NIL def wrap_compiled_task(classname): derived_class = type(classname, (Task.classes[classname],), {}) diff --git a/waflib/extras/msvcdeps.py b/waflib/extras/msvcdeps.py index c85c69490d..52985dce05 100644 --- a/waflib/extras/msvcdeps.py +++ b/waflib/extras/msvcdeps.py @@ -25,7 +25,7 @@ def configure(conf): conf.load('compiler_cxx msvcdeps') ''' -import errno, os, sys, tempfile, threading +import os, sys, tempfile, threading from waflib import Context, Errors, Logs, Task, Utils from waflib.Tools import c_preproc, c, cxx, msvc @@ -150,15 +150,25 @@ def scan(self): def sig_implicit_deps(self): if self.env.CC_NAME not in supported_compilers: return super(self.derived_msvcdeps, self).sig_implicit_deps() + bld = self.generator.bld try: - return Task.Task.sig_implicit_deps(self) - except Errors.WafError: - return Utils.SIG_NIL - except EnvironmentError as e: - if e.errno == errno.ENOENT: - return Utils.SIG_NIL - raise + return self.compute_sig_implicit_deps() + except Errors.TaskNotReady: + raise ValueError("Please specify the build order precisely with msvcdeps (c/c++ tasks)") + except EnvironmentError: + # If a file is renamed, assume the dependencies are stale and must be recalculated + for x in bld.node_deps.get(self.uid(), []): + if not x.is_bld() and not x.exists(): + try: + del x.parent.children[x.name] + except KeyError: + pass + + key = self.uid() + bld.node_deps[key] = [] + bld.raw_deps[key] = [] + return Utils.SIG_NIL def exec_command(self, cmd, **kw): if self.env.CC_NAME not in supported_compilers: From 483ee0d2f04488af47445e14cc7abee3fa0fdbc1 Mon Sep 17 00:00:00 2001 From: Matt Selsky Date: Tue, 28 Apr 2020 19:27:51 -0400 Subject: [PATCH 238/315] Typo --- waflib/Context.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 waflib/Context.py diff --git a/waflib/Context.py b/waflib/Context.py old mode 100644 new mode 100755 index 3f1b4fa48a..e4445db322 --- a/waflib/Context.py +++ b/waflib/Context.py @@ -530,7 +530,7 @@ def msg(self, *k, **kw): """ Prints a configuration message of the form ``msg: result``. The second part of the message will be in colors. The output - can be disabled easly by setting ``in_msg`` to a positive value:: + can be disabled easily by setting ``in_msg`` to a positive value:: def configure(conf): self.in_msg = 1 From 6901a1e9ac401f3b5552ab9710ee6346b73cdeca Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Sun, 12 Jul 2020 14:33:33 +0000 Subject: [PATCH 239/315] c_config: add MCST Elbrus detection --- waflib/Tools/c_config.py | 1 + 1 file changed, 1 insertion(+) diff --git a/waflib/Tools/c_config.py b/waflib/Tools/c_config.py index dace2b917f..f8f664f82c 100644 --- a/waflib/Tools/c_config.py +++ b/waflib/Tools/c_config.py @@ -68,6 +68,7 @@ '__s390__' : 's390', '__sh__' : 'sh', '__xtensa__' : 'xtensa', +'__e2k__' : 'e2k', } @conf From 1bd658e04aff03d5273843afa0a961bd21ab7386 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Mon, 3 Aug 2020 23:20:53 +0200 Subject: [PATCH 240/315] Improve wafcache process pre-allocation --- waflib/extras/wafcache.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/waflib/extras/wafcache.py b/waflib/extras/wafcache.py index 8b9567faf1..f267edd3f6 100644 --- a/waflib/extras/wafcache.py +++ b/waflib/extras/wafcache.py @@ -233,8 +233,9 @@ def build(bld): # already called once return - for x in range(bld.jobs): - process_pool.append(get_process()) + # pre-allocation + processes = [get_process() for x in range(bld.jobs)] + process_pool.extend(processes) Task.Task.can_retrieve_cache = can_retrieve_cache Task.Task.put_files_cache = put_files_cache From f5468107ec067cb39eff948201b9a94fbaaae9db Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Mon, 3 Aug 2020 23:30:33 +0200 Subject: [PATCH 241/315] Port file_to_obj to Python3 --- waflib/extras/file_to_object.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/waflib/extras/file_to_object.py b/waflib/extras/file_to_object.py index 1393b511d6..13d2aef37d 100644 --- a/waflib/extras/file_to_object.py +++ b/waflib/extras/file_to_object.py @@ -31,7 +31,7 @@ """ -import os +import os, sys from waflib import Task, TaskGen, Errors def filename_c_escape(x): @@ -95,12 +95,17 @@ def run(self): name = "_binary_" + "".join(name) + def char_to_num(ch): + if sys.version_info[0] < 3: + return ord(ch) + return ch + data = self.inputs[0].read('rb') lines, line = [], [] for idx_byte, byte in enumerate(data): line.append(byte) if len(line) > 15 or idx_byte == size-1: - lines.append(", ".join(("0x%02x" % ord(x)) for x in line)) + lines.append(", ".join(("0x%02x" % char_to_num(x)) for x in line)) line = [] data = ",\n ".join(lines) From b37f481e4c557013853cf9adfff629d60bbd7a71 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Mon, 10 Aug 2020 21:16:06 +0200 Subject: [PATCH 242/315] Fix playground/pch's second example --- playground/pch/wscript | 2 +- waflib/extras/pch.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/playground/pch/wscript b/playground/pch/wscript index 0331618d53..9cbd556ba2 100644 --- a/playground/pch/wscript +++ b/playground/pch/wscript @@ -53,7 +53,7 @@ def build(bld): source = 'a.cpp', use = 'BOOST') - bld.program( + bld(features = 'cxx cxxprogram pch', target = 'test1', source = 'b.cpp c.cpp main.cpp', use = 'base-with-pch') diff --git a/waflib/extras/pch.py b/waflib/extras/pch.py index 103e752838..b44c7a2e8f 100644 --- a/waflib/extras/pch.py +++ b/waflib/extras/pch.py @@ -90,7 +90,7 @@ def apply_pch(self): if getattr(self, 'name', None): try: - task = self.bld.pch_tasks["%s.%s" % (self.name, self.idx)] + task = self.bld.pch_tasks[self.name] self.bld.fatal("Duplicated 'pch' task with name %r" % "%s.%s" % (self.name, self.idx)) except KeyError: pass @@ -104,7 +104,7 @@ def apply_pch(self): self.pch_task = task if getattr(self, 'name', None): - self.bld.pch_tasks["%s.%s" % (self.name, self.idx)] = task + self.bld.pch_tasks[self.name] = task @TaskGen.feature('cxx') @TaskGen.after_method('process_source', 'propagate_uselib_vars') From 5cf1fac6c1378adae5497ea8a6ab9815d415ea1b Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Mon, 10 Aug 2020 21:22:13 +0200 Subject: [PATCH 243/315] Remove an extra 'pch' annotation in playgroud/pch/wscript --- playground/pch/wscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playground/pch/wscript b/playground/pch/wscript index 9cbd556ba2..fb8e69fa90 100644 --- a/playground/pch/wscript +++ b/playground/pch/wscript @@ -53,7 +53,7 @@ def build(bld): source = 'a.cpp', use = 'BOOST') - bld(features = 'cxx cxxprogram pch', + bld(features = 'cxx cxxprogram', target = 'test1', source = 'b.cpp c.cpp main.cpp', use = 'base-with-pch') From 805f45bdc24febbd4b1efc152ea3b9cbfdff5d90 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sat, 15 Aug 2020 12:16:36 +0200 Subject: [PATCH 244/315] Force an asm-specific defines flag --- waflib/Tools/asm.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/waflib/Tools/asm.py b/waflib/Tools/asm.py index a57e83bb5e..1d34ddaca7 100644 --- a/waflib/Tools/asm.py +++ b/waflib/Tools/asm.py @@ -56,13 +56,11 @@ class asm(Task.Task): Compiles asm files by gas/nasm/yasm/... """ color = 'BLUE' - run_str = '${AS} ${ASFLAGS} ${ASMPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${AS_SRC_F}${SRC} ${AS_TGT_F}${TGT}' + run_str = '${AS} ${ASFLAGS} ${ASMPATH_ST:INCPATHS} ${ASMDEFINES_ST:DEFINES} ${AS_SRC_F}${SRC} ${AS_TGT_F}${TGT}' def scan(self): if self.env.ASM_NAME == 'gas': return c_preproc.scan(self) - Logs.warn('There is no dependency scanner for Nasm!') - return [[], []] elif self.env.ASM_NAME == 'nasm': Logs.warn('The Nasm dependency scanner is incomplete!') @@ -106,3 +104,4 @@ class asmstlib(stlink_task): def configure(conf): conf.env.ASMPATH_ST = '-I%s' + conf.env.ASMDEFINES_ST = '-D%s' From 1cdf2121b9954f530ccfb334436b4577d06c71cd Mon Sep 17 00:00:00 2001 From: Anthony DuPont Date: Wed, 19 Aug 2020 17:23:38 -0400 Subject: [PATCH 245/315] default to version of visual studio from command prompt if it exists --- waflib/Tools/msvc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/Tools/msvc.py b/waflib/Tools/msvc.py index f169c7f441..bc13eccf92 100644 --- a/waflib/Tools/msvc.py +++ b/waflib/Tools/msvc.py @@ -99,7 +99,7 @@ def build(bld): """List of icl platforms""" def options(opt): - opt.add_option('--msvc_version', type='string', help = 'msvc version, eg: "msvc 10.0,msvc 9.0"', default='') + opt.add_option('--msvc_version', type='string', help = 'msvc version, eg: "msvc 10.0,msvc 9.0"', default="msvc " + re.match("(^\d+\.\d+).*", os.getenv("VSCMD_VER"))[1] if os.getenv("VSCMD_VER") else "") opt.add_option('--msvc_targets', type='string', help = 'msvc targets, eg: "x64,arm"', default='') opt.add_option('--no-msvc-lazy', action='store_false', help = 'lazily check msvc target environments', default=True, dest='msvc_lazy') From d789983f6269c132dfb3899806f9c7e38146a7de Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Wed, 19 Aug 2020 23:49:18 +0200 Subject: [PATCH 246/315] Simplify the determination of --msvc_version's default value --- waflib/Tools/msvc.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/waflib/Tools/msvc.py b/waflib/Tools/msvc.py index bc13eccf92..37233be824 100644 --- a/waflib/Tools/msvc.py +++ b/waflib/Tools/msvc.py @@ -99,7 +99,13 @@ def build(bld): """List of icl platforms""" def options(opt): - opt.add_option('--msvc_version', type='string', help = 'msvc version, eg: "msvc 10.0,msvc 9.0"', default="msvc " + re.match("(^\d+\.\d+).*", os.getenv("VSCMD_VER"))[1] if os.getenv("VSCMD_VER") else "") + default_ver = '' + vsver = os.getenv('VSCMD_VER') + if vsver: + m = re.match(r'(^\d+\.\d+).*', vsver) + if m: + default_ver = 'msvc %s' % m.group(1) + opt.add_option('--msvc_version', type='string', help = 'msvc version, eg: "msvc 10.0,msvc 9.0"', default=default_ver) opt.add_option('--msvc_targets', type='string', help = 'msvc targets, eg: "x64,arm"', default='') opt.add_option('--no-msvc-lazy', action='store_false', help = 'lazily check msvc target environments', default=True, dest='msvc_lazy') From 92f1591967871630422c823dd0f862c81526e60c Mon Sep 17 00:00:00 2001 From: Dotan Cohen Date: Sun, 6 Sep 2020 11:31:31 +0000 Subject: [PATCH 247/315] Update tutorial.rst to use uniform parameter names in all places where the configure() method or its parameter is mentioned. --- docs/sphinx/tutorial.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/sphinx/tutorial.rst b/docs/sphinx/tutorial.rst index 23d2f9dc0f..e2b9fde96f 100644 --- a/docs/sphinx/tutorial.rst +++ b/docs/sphinx/tutorial.rst @@ -24,7 +24,7 @@ In general, a project will consist of several phases: Each phase is modelled in the wscript file as a python function which takes as argument an instance of :py:class:`waflib.Context.Context`. Let's start with a new wscript file in the directory '/tmp/myproject':: - def configure(conf): + def configure(cnf): print("configure!") def build(bld): @@ -111,9 +111,9 @@ Here is a script for a more complicated project:: The method :py:func:`waflib.Tools.c_config.check` executes a build internally to check if the library ``libm`` is present on the operating system. It will then define variables such as: -* ``conf.env.LIB_M = ['m']`` -* ``conf.env.CFLAGS_M = ['-Wall']`` -* ``conf.env.DEFINES_M = ['var=foo']`` +* ``cnf.env.LIB_M = ['m']`` +* ``cnf.env.CFLAGS_M = ['-Wall']`` +* ``cnf.env.DEFINES_M = ['var=foo']`` By stating ``use=['M', 'mylib']``, the program *app* is going to inherit all the *M* variables defined during the configuration. The program will also use the library *mylib* and both the build order and the dependencies From 660c5ffd23f19d943a2228296da04a8c522f6c44 Mon Sep 17 00:00:00 2001 From: Dotan Cohen Date: Sun, 6 Sep 2020 11:44:16 +0000 Subject: [PATCH 248/315] Update tutorial.rst to clarify that the env attribute is shared between the cnf and bld parameters to their respective methods. --- docs/sphinx/tutorial.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sphinx/tutorial.rst b/docs/sphinx/tutorial.rst index e2b9fde96f..1b405fd00a 100644 --- a/docs/sphinx/tutorial.rst +++ b/docs/sphinx/tutorial.rst @@ -62,7 +62,7 @@ by using the *${}* symbol, which reads the values from the attribute bld.env:: bld(rule='echo ${MESSAGE}', always=True) The bld object is an instance of :py:class:`waflib.Build.BuildContext`, its *env* attribute is an instance :py:class:`waflib.ConfigSet.ConfigSet`. -The values are set in this object to be shared/stored/loaded easily. Here is how to do the same thing by sharing data between the configuration and build:: +This object is also accessible as an attribute on the `configure()` method's `cnf` parameter. Therefore, values can be shared/stored/loaded easily: def configure(cnf): cnf.env.MESSAGE = 'Hello, world!' From 466272e47e5aaeed866169cdef6c10c9c5eae3a8 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sat, 19 Sep 2020 08:40:44 +0200 Subject: [PATCH 249/315] Make sure lupdate is explicitly required --- demos/qt5/wscript | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/demos/qt5/wscript b/demos/qt5/wscript index 5b4dbd503e..239269579f 100644 --- a/demos/qt5/wscript +++ b/demos/qt5/wscript @@ -16,6 +16,10 @@ def configure(conf): conf.load('compiler_cxx qt5 waf_unit_test') #conf.env.append_value('CXXFLAGS', ['-g']) # test + if not conf.env.QT_LUPDATE: + # While qt5 detects most Qt tools, most of them are optional + conf.fatal('lupdate was not found') + # These tests would run on Ubuntu but not on other platforms conf.check( define_name = 'XYZ_QT5_TESTS', From 1e84cb2dc79334714e293639252fdc7f147c4ca6 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sat, 19 Sep 2020 08:47:57 +0200 Subject: [PATCH 250/315] Fail Qt5 detection immediately when the c++ compiler is missing --- waflib/Tools/qt5.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/waflib/Tools/qt5.py b/waflib/Tools/qt5.py index 3a23abaa46..cff2028174 100644 --- a/waflib/Tools/qt5.py +++ b/waflib/Tools/qt5.py @@ -482,6 +482,9 @@ def configure(self): The detection uses the program ``pkg-config`` through :py:func:`waflib.Tools.config_c.check_cfg` """ + if 'COMPILER_CXX' not in self.env: + self.fatal('No CXX compiler defined: did you forget to configure compiler_cxx first?') + self.find_qt5_binaries() self.set_qt5_libs_dir() self.set_qt5_libs_to_check() @@ -494,9 +497,6 @@ def configure(self): if not has_xml: Logs.error('No xml.sax support was found, rcc dependencies will be incomplete!') - if 'COMPILER_CXX' not in self.env: - self.fatal('No CXX compiler defined: did you forget to configure compiler_cxx first?') - # Qt5 may be compiled with '-reduce-relocations' which requires dependent programs to have -fPIE or -fPIC? frag = '#include \nint main(int argc, char **argv) {QMap m;return m.keys().size();}\n' uses = 'QT5CORE' @@ -653,7 +653,7 @@ def set_qt5_libs_dir(self): except Errors.WafError: qtdir = self.cmd_and_log(env.QMAKE + ['-query', 'QT_INSTALL_PREFIX']).strip() qtlibs = os.path.join(qtdir, 'lib') - self.msg('Found the Qt5 libraries in', qtlibs) + self.msg('Found the Qt5 library path', qtlibs) env.QTLIBS = qtlibs @conf From 962e310613a158fbc91f3463c7b9ad51ba10ff16 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sat, 19 Sep 2020 10:09:18 +0200 Subject: [PATCH 251/315] The lrelease program is necessary, not lupdate --- demos/qt5/wscript | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/demos/qt5/wscript b/demos/qt5/wscript index 239269579f..fbc1691bc8 100644 --- a/demos/qt5/wscript +++ b/demos/qt5/wscript @@ -16,9 +16,9 @@ def configure(conf): conf.load('compiler_cxx qt5 waf_unit_test') #conf.env.append_value('CXXFLAGS', ['-g']) # test - if not conf.env.QT_LUPDATE: + if not conf.env.QT_LRELEASE: # While qt5 detects most Qt tools, most of them are optional - conf.fatal('lupdate was not found') + conf.fatal('lrelease was not found') # These tests would run on Ubuntu but not on other platforms conf.check( From 7b6cd4c3e047db5ad3af1a1e8142db2665461bf9 Mon Sep 17 00:00:00 2001 From: Federico Pellegrin Date: Wed, 14 Oct 2020 04:57:19 +0200 Subject: [PATCH 252/315] waf_unit_test: make sure test is rerun if ut_str changes --- waflib/Tools/waf_unit_test.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/waflib/Tools/waf_unit_test.py b/waflib/Tools/waf_unit_test.py index 6ff6f72739..beee974781 100644 --- a/waflib/Tools/waf_unit_test.py +++ b/waflib/Tools/waf_unit_test.py @@ -108,7 +108,8 @@ def make_test(self): tsk = self.create_task('utest', self.link_task.outputs) if getattr(self, 'ut_str', None): self.ut_run, lst = Task.compile_fun(self.ut_str, shell=getattr(self, 'ut_shell', False)) - tsk.vars = lst + tsk.vars + tsk.env['UT_STR'] = self.ut_str + tsk.vars = lst + tsk.vars + ['UT_STR'] self.handle_ut_cwd('ut_cwd') From ac6746d4b713e6dc01a2cd35892a712c8b886377 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Thu, 15 Oct 2020 18:54:14 +0200 Subject: [PATCH 253/315] Force unit test re-runs on environment or command changes --- waflib/Tools/waf_unit_test.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/waflib/Tools/waf_unit_test.py b/waflib/Tools/waf_unit_test.py index beee974781..696178d8f3 100644 --- a/waflib/Tools/waf_unit_test.py +++ b/waflib/Tools/waf_unit_test.py @@ -97,6 +97,7 @@ def make_interpreted_test(self): if isinstance(v, str): v = v.split(os.pathsep) self.ut_env[k] = os.pathsep.join(p + v) + self.env.append_value('UT_DEPS', ['%r%r' % (key, self.ut_env[key]) for key in self.ut_env]) @feature('test') @after_method('apply_link', 'process_use') @@ -108,8 +109,8 @@ def make_test(self): tsk = self.create_task('utest', self.link_task.outputs) if getattr(self, 'ut_str', None): self.ut_run, lst = Task.compile_fun(self.ut_str, shell=getattr(self, 'ut_shell', False)) - tsk.env['UT_STR'] = self.ut_str - tsk.vars = lst + tsk.vars + ['UT_STR'] + tsk.vars = tsk.vars + lst + self.env.append_value('UT_DEPS', self.ut_str) self.handle_ut_cwd('ut_cwd') @@ -139,6 +140,10 @@ def add_path(var): if not hasattr(self, 'ut_cmd'): self.ut_cmd = getattr(Options.options, 'testcmd', False) + self.env.append_value('UT_DEPS', str(self.ut_cmd)) + + self.env.append_value('UT_DEPS', self.ut_paths) + self.env.append_value('UT_DEPS', ['%r%r' % (key, self.ut_env[key]) for key in self.ut_env]) @taskgen_method def add_test_results(self, tup): @@ -160,7 +165,7 @@ class utest(Task.Task): """ color = 'PINK' after = ['vnum', 'inst'] - vars = [] + vars = ['UT_DEPS'] def runnable_status(self): """ From f77556cfb5d402ec3ee1f658c4f325fdedcd30c9 Mon Sep 17 00:00:00 2001 From: Federico Pellegrin Date: Thu, 15 Oct 2020 06:43:50 +0200 Subject: [PATCH 254/315] waf_unit_test: consider ut_cmd always for task signature --- waflib/Tools/waf_unit_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/Tools/waf_unit_test.py b/waflib/Tools/waf_unit_test.py index 696178d8f3..dc66fe9c18 100644 --- a/waflib/Tools/waf_unit_test.py +++ b/waflib/Tools/waf_unit_test.py @@ -140,8 +140,8 @@ def add_path(var): if not hasattr(self, 'ut_cmd'): self.ut_cmd = getattr(Options.options, 'testcmd', False) - self.env.append_value('UT_DEPS', str(self.ut_cmd)) + self.env.append_value('UT_DEPS', str(self.ut_cmd)) self.env.append_value('UT_DEPS', self.ut_paths) self.env.append_value('UT_DEPS', ['%r%r' % (key, self.ut_env[key]) for key in self.ut_env]) From 429c7587645aa07cee0cf6d85f83d6487aecb199 Mon Sep 17 00:00:00 2001 From: Federico Pellegrin Date: Mon, 2 Nov 2020 07:14:50 +0100 Subject: [PATCH 255/315] wafcache: add support for MinIO/mc cache Add support for MinIO object storage (https://min.io/) using the MinIO client (https://github.com/minio/mc) to wafcache. MinIO is an open-source, self-hostable, S3 compatible cache. The MinIO client supports MinIO connections as well as normal S3/GCS storages by configuring aliases beforehand. Hint: some distributions have `mc` (the GNU Midnight Commander) installed which is not the minio client, be aware of this (or your build may get stuck with waf waiting for `mc` to never finish) --- waflib/extras/wafcache.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/waflib/extras/wafcache.py b/waflib/extras/wafcache.py index f267edd3f6..73e4cb627e 100644 --- a/waflib/extras/wafcache.py +++ b/waflib/extras/wafcache.py @@ -17,9 +17,10 @@ export WAFCACHE=http://localhost:8080/files/ in that case, GET/POST requests are made to urls of the form http://localhost:8080/files/000000000/0 (cache management is then up to the server) - - GCS or S3 bucket - gs://my-bucket/ - s3://my-bucket/ + - GCS or S3 or MINIO bucket + gs://my-bucket/ (uses gsutil command line tool) + s3://my-bucket/ (uses aws command line tool) + minio://my-bucket/ (uses mc command line tool) * WAFCACHE_NO_PUSH: if set, disables pushing to the cache * WAFCACHE_VERBOSITY: if set, displays more detailed cache operations @@ -452,8 +453,10 @@ class bucket_cache(object): def bucket_copy(self, source, target): if CACHE_DIR.startswith('s3://'): cmd = ['aws', 's3', 'cp', source, target] - else: + elif CACHE_DIR.startswith('gs://'): cmd = ['gsutil', 'cp', source, target] + else: + cmd = ['mc', 'cp', source, target] proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = proc.communicate() if proc.returncode: @@ -511,7 +514,9 @@ def loop(service): sys.stdout.flush() if __name__ == '__main__': - if CACHE_DIR.startswith('s3://') or CACHE_DIR.startswith('gs://'): + if CACHE_DIR.startswith('s3://') or CACHE_DIR.startswith('gs://') or CACHE_DIR.startswith('minio://'): + if CACHE_DIR.startswith('minio://'): + CACHE_DIR = CACHE_DIR[8:] # minio doesn't need the protocol part, uses config aliases service = bucket_cache() elif CACHE_DIR.startswith('http'): service = netcache() From bcd8129f4274693bc5c10b400a15b92d6dcf85f1 Mon Sep 17 00:00:00 2001 From: Federico Pellegrin Date: Tue, 3 Nov 2020 20:55:47 +0000 Subject: [PATCH 256/315] wafcache: make the extra more configurable for cloud providers usage --- waflib/extras/wafcache.py | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/waflib/extras/wafcache.py b/waflib/extras/wafcache.py index 73e4cb627e..c96531647b 100644 --- a/waflib/extras/wafcache.py +++ b/waflib/extras/wafcache.py @@ -18,9 +18,9 @@ in that case, GET/POST requests are made to urls of the form http://localhost:8080/files/000000000/0 (cache management is then up to the server) - GCS or S3 or MINIO bucket - gs://my-bucket/ (uses gsutil command line tool) - s3://my-bucket/ (uses aws command line tool) - minio://my-bucket/ (uses mc command line tool) + gs://my-bucket/ (uses gsutil command line tool or WAFCACHE_CMD) + s3://my-bucket/ (uses aws command line tool or WAFCACHE_CMD) + minio://my-bucket/ (uses mc command line tool or WAFCACHE_CMD) * WAFCACHE_NO_PUSH: if set, disables pushing to the cache * WAFCACHE_VERBOSITY: if set, displays more detailed cache operations @@ -31,6 +31,12 @@ * WAFCACHE_EVICT_MAX_BYTES: maximum amount of cache size in bytes (10GB) * WAFCACHE_EVICT_INTERVAL_MINUTES: minimum time interval to try and trim the cache (3 minutess) + +Bucket cache specific options: +* WAFCACHE_CMD: command to use to access bucket cache. It must contain + exactly two %s, assuming first is substituted by source + and second by target (see defaults for examples) + Usage:: def build(bld): @@ -42,7 +48,7 @@ def build(bld): waf clean build --zones=wafcache """ -import atexit, base64, errno, fcntl, getpass, os, shutil, sys, time, traceback, urllib3 +import atexit, base64, errno, fcntl, getpass, os, shutil, sys, time, traceback, urllib3, shlex try: import subprocess32 as subprocess except ImportError: @@ -61,6 +67,18 @@ def build(bld): WAFCACHE_VERBOSITY = 1 if os.environ.get('WAFCACHE_VERBOSITY') else 0 OK = "ok" +WAFCACHE_CMD = os.environ.get('WAFCACHE_CMD', None) + +# Some defaults if WAFCACHE_CMD is not passed +if not WAFCACHE_CMD: + if CACHE_DIR.startswith('s3://'): + WAFCACHE_CMD = 'aws s3 cp "%s" "%s"' + elif CACHE_DIR.startswith('gs://'): + WAFCACHE_CMD = 'gsutil cp "%s" "%s"' + else: + WAFCACHE_CMD = 'mc cp "%s" "%s"' + + try: import cPickle except ImportError: @@ -451,12 +469,7 @@ def copy_from_cache(self, sig, files_from, files_to): class bucket_cache(object): def bucket_copy(self, source, target): - if CACHE_DIR.startswith('s3://'): - cmd = ['aws', 's3', 'cp', source, target] - elif CACHE_DIR.startswith('gs://'): - cmd = ['gsutil', 'cp', source, target] - else: - cmd = ['mc', 'cp', source, target] + cmd = shlex.split(WAFCACHE_CMD % (source, target)) proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = proc.communicate() if proc.returncode: From 243fd8e3cca5fe5ebb163ba2941a7f635dc6583f Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Tue, 3 Nov 2020 22:19:13 +0100 Subject: [PATCH 257/315] Improve WAFCACHE_CMD parameter handling --- waflib/extras/wafcache.py | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/waflib/extras/wafcache.py b/waflib/extras/wafcache.py index c96531647b..003fa4f9d6 100644 --- a/waflib/extras/wafcache.py +++ b/waflib/extras/wafcache.py @@ -21,6 +21,8 @@ gs://my-bucket/ (uses gsutil command line tool or WAFCACHE_CMD) s3://my-bucket/ (uses aws command line tool or WAFCACHE_CMD) minio://my-bucket/ (uses mc command line tool or WAFCACHE_CMD) +* WAFCACHE_CMD: custom upload/download command, for example: + WAFCACHE_CMD="gsutil cp %{SRC} %{TGT}" * WAFCACHE_NO_PUSH: if set, disables pushing to the cache * WAFCACHE_VERBOSITY: if set, displays more detailed cache operations @@ -32,11 +34,6 @@ * WAFCACHE_EVICT_INTERVAL_MINUTES: minimum time interval to try and trim the cache (3 minutess) -Bucket cache specific options: -* WAFCACHE_CMD: command to use to access bucket cache. It must contain - exactly two %s, assuming first is substituted by source - and second by target (see defaults for examples) - Usage:: def build(bld): @@ -48,7 +45,7 @@ def build(bld): waf clean build --zones=wafcache """ -import atexit, base64, errno, fcntl, getpass, os, shutil, sys, time, traceback, urllib3, shlex +import atexit, base64, errno, fcntl, getpass, os, re, shutil, sys, time, traceback, urllib3, shlex try: import subprocess32 as subprocess except ImportError: @@ -60,6 +57,7 @@ def build(bld): default_wafcache_dir = os.path.join(base_cache, 'wafcache_' + getpass.getuser()) CACHE_DIR = os.environ.get('WAFCACHE', default_wafcache_dir) +WAFCACHE_CMD = os.environ.get('WAFCACHE_CMD') TRIM_MAX_FOLDERS = int(os.environ.get('WAFCACHE_TRIM_MAX_FOLDER', 1000000)) EVICT_INTERVAL_MINUTES = int(os.environ.get('WAFCACHE_EVICT_INTERVAL_MINUTES', 3)) EVICT_MAX_BYTES = int(os.environ.get('WAFCACHE_EVICT_MAX_BYTES', 10**10)) @@ -67,17 +65,7 @@ def build(bld): WAFCACHE_VERBOSITY = 1 if os.environ.get('WAFCACHE_VERBOSITY') else 0 OK = "ok" -WAFCACHE_CMD = os.environ.get('WAFCACHE_CMD', None) - -# Some defaults if WAFCACHE_CMD is not passed -if not WAFCACHE_CMD: - if CACHE_DIR.startswith('s3://'): - WAFCACHE_CMD = 'aws s3 cp "%s" "%s"' - elif CACHE_DIR.startswith('gs://'): - WAFCACHE_CMD = 'gsutil cp "%s" "%s"' - else: - WAFCACHE_CMD = 'mc cp "%s" "%s"' - +re_waf_cmd = re.compile('(?P%{SRC})|(?P%{TGT})') try: import cPickle @@ -469,7 +457,20 @@ def copy_from_cache(self, sig, files_from, files_to): class bucket_cache(object): def bucket_copy(self, source, target): - cmd = shlex.split(WAFCACHE_CMD % (source, target)) + if WAFCACHE_CMD: + def replacer(match): + if match.group('src'): + return source + elif match.group('tgt'): + return target + cmd = [re_waf_cmd.sub(replacer, x) for x in shlex.split(WAFCACHE_CMD)] + elif CACHE_DIR.startswith('s3://'): + cmd = ['aws', 's3', 'cp', source, target] + elif CACHE_DIR.startswith('gs://'): + cmd = ['gsutil', 'cp', source, target] + else: + cmd = ['mc', 'cp', source, target] + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = proc.communicate() if proc.returncode: From b4effc9b73c5a5f1eae8bbff56982c3310b09916 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 8 Nov 2020 14:48:21 +0100 Subject: [PATCH 258/315] Reduce verbosity in out-of-tree builds --- waflib/Build.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/waflib/Build.py b/waflib/Build.py index 264cdbed33..e9b47203fd 100644 --- a/waflib/Build.py +++ b/waflib/Build.py @@ -753,10 +753,12 @@ def tgpost(tg): else: ln = self.launch_node() if ln.is_child_of(self.bldnode): - Logs.warn('Building from the build directory, forcing --targets=*') + if Logs.verbose > 1: + Logs.warn('Building from the build directory, forcing --targets=*') ln = self.srcnode elif not ln.is_child_of(self.srcnode): - Logs.warn('CWD %s is not under %s, forcing --targets=* (run distclean?)', ln.abspath(), self.srcnode.abspath()) + if Logs.verbose > 1: + Logs.warn('CWD %s is not under %s, forcing --targets=* (run distclean?)', ln.abspath(), self.srcnode.abspath()) ln = self.srcnode def is_post(tg, ln): From e219a104115ef0c84d4a11c092d04c800766935d Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 8 Nov 2020 19:53:57 +0100 Subject: [PATCH 259/315] Improve the WAFCACHE_CMD description --- waflib/extras/wafcache.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/waflib/extras/wafcache.py b/waflib/extras/wafcache.py index 003fa4f9d6..088fd0d098 100644 --- a/waflib/extras/wafcache.py +++ b/waflib/extras/wafcache.py @@ -16,13 +16,19 @@ - URL to a cache server, for example: export WAFCACHE=http://localhost:8080/files/ in that case, GET/POST requests are made to urls of the form - http://localhost:8080/files/000000000/0 (cache management is then up to the server) - - GCS or S3 or MINIO bucket + http://localhost:8080/files/000000000/0 (cache management is delegated to the server) + - GCS, S3 or MINIO bucket gs://my-bucket/ (uses gsutil command line tool or WAFCACHE_CMD) s3://my-bucket/ (uses aws command line tool or WAFCACHE_CMD) minio://my-bucket/ (uses mc command line tool or WAFCACHE_CMD) -* WAFCACHE_CMD: custom upload/download command, for example: - WAFCACHE_CMD="gsutil cp %{SRC} %{TGT}" +* WAFCACHE_CMD: bucket upload/download command, for example: + WAFCACHE_CMD="gsutil cp %{SRC} %{TGT}" + Note that the WAFCACHE bucket value is used for the source or destination + depending on the operation (upload or download). For example, with: + WAFCACHE="gs://mybucket/" + the following commands may be run: + gsutil cp build/myprogram gs://mybucket/aa/aaaaa/1 + gsutil cp gs://mybucket/bb/bbbbb/2 build/somefile * WAFCACHE_NO_PUSH: if set, disables pushing to the cache * WAFCACHE_VERBOSITY: if set, displays more detailed cache operations From a89ec350988d8bdc000b7d7a62027c98149c5c1c Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 8 Nov 2020 20:19:46 +0100 Subject: [PATCH 260/315] Update the ChangeLog file --- ChangeLog | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/ChangeLog b/ChangeLog index fbe7e06e8d..aa5cf37af3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +NEW IN WAF 2.0.21 +----------------- +* Set the default --msvc_version from VSCMD_VER if present #2299 +* Force unit-test reruns on ut_str, ut_cmd or ut_path changes #2302 +* Describe Qt5's library detection #2288 +* Introduce conf.env.ASMDEFINES_ST to enable assembly-specific define flags +* Update extras/xcode6 to Python3 #2290 +* Enable parameter "always" in extras/doxygen #2292 +* Fix extras/c_dumbpreproc as it was previously broken +* Fix extras/gccdeps and extras/msvcdeps on header renaming #2293 +* Improve extras/msvcdeps debug outputs and flags #2287 #2291 +* Add add MCST Elbrus CPU detection in c config #2297 +* Add minio object copies to extras/wafcache #2304 + NEW IN WAF 2.0.20 ----------------- * Detect -flto and -fno-lto in parse_config #2281 From 2db18aa22e84c6b0668c6f639c6aa9565eaaa816 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 8 Nov 2020 20:43:12 +0100 Subject: [PATCH 261/315] Update the project's public key --- utils/pubkey.asc | 95 ++++++++++++++++++++++++------------------------ 1 file changed, 48 insertions(+), 47 deletions(-) diff --git a/utils/pubkey.asc b/utils/pubkey.asc index 4c55fbc862..8c122700fc 100644 --- a/utils/pubkey.asc +++ b/utils/pubkey.asc @@ -1,50 +1,51 @@ -----BEGIN PGP PUBLIC KEY BLOCK----- -mQINBFddvK0BEACkGoEIkR4NrYk565assNc0zaBAJzeZvz8/9DBavbF8cxOJGRpQ -yk4AqKePlz3CY4HO5djw4suzblBDWPrHzGkEln0IRedGdUvuvjt13jI7KdyxdjQM -yRatD1mQOKSLfb/HPdHJuYP0Zx3Ck1NQqX1qe+zH83iPT3L2xA4RToLQBmxntAHc -4ko6AZ4QtYu4a2dx2LgDoNpX0R+1kz/5XY5qOQvxSi2LaLZK/feEYqRoIbPv5xQv -EbiYt1c6xkGy6lJHf9G3crjhED1C0L8pBnlH1Ee8Z004Z3LrctKpJYzZqDcZ4Ijg -YE5zzEdSYIO+noDKMeMlw736Whg0QaPRDvBSifwQbQUatUrkil1CWEWYOd9AUOnb -FeqMaCwQ1Oa+QP73mBaQHnwq2OPkYzHneMuT4Hvrwg1tL6AIe093X0CsG+4dbWcT -Ec0evflZRcgqWniOQ3b/gz7shXzmWBlzPFZJ8cEMdtVDRydbrTMijWT6Vewr2q0S -cKDaBgUlfUON6c+QYjvyCKyvl+yUCfC5H+sxyulhh1L15FFKwIsRZS3E907WSYpA -/FmwTv3z4HO9LqOUdbqBVzSWjVZpPN2ug1mgp26qcD6UJYiYtDcM9zzy/lEqI7Y0 -QwooQdfKQ+Hem+ao4zTKhjsToZNKpLG8a5fGRduUosGXZtvXQbcjs7aWbwARAQAB -tBpUaG9tYXMgTmFneSA8dG5hZ3lAd2FmLmlvPokCNQQTAQoAHwUCV128rQIbAwUJ -B4TOAAMLCQgFFQoJCAsCHgECF4AACgkQSbTGfAUneqqoQA//cqSP5QpLQM/XdEEg -OEU8gLwGLeN2HiBxB1AijbD2Wbm/rjUtu0TK0mkMiXJSzU87VIaMYyJtLg4ZWefs -lclnexS2ZAqGemsWbf0pa+KoTDl8c4vjR9UtQXJ9uyJO8EV3KeX0aBbVt/EEhIMZ -hOGgg1IzkO8qtNNxeBzp5aXdQKE18U+FC9Dx8PIldkew1+J7AA7i7mwDj/bHYH8i -VoLvIjU3DUR++TniJeM2s9ez8VzpStDldtQF1krTVCxsf5h/fD5XmgC+PmPZp8js -VRT4BMw54sSC+MOwVmEdk8Y+pdCqqL/pF++S0iKE/ZDCreT5GfrxCB0pY6VNptXG -BHbhstdoqqkuq46QsiWUYEQRh8GwwmECvyWSsf6gG4oNLWy9uvd7N2JOgxwZYEa1 -mLISst2RZY/HVlEyJuQlw5KwCE6opKS2gQaeRcr6dc3Ezqq4QHNeZpwoBNJuFxob -jGTgBaImgyvMxRiTcP+EUNNSldbwXZ7jhMrrsnbceuXtUN49ZBV5zNWG2Gz+D4Ph -HFqVEPTBaXUsJv7fa18fijG9krJSRb6tb/Ix2HfS5u9npN3PeuULV1dFXvdquwoF -P8KdmMEV/E7w9AZHjMaXPoUrnLzsexzsr5op17NykLkKbIVtrInUCrQt2ztQFkPy -YGSUYa6JjU6rfTI/fJUlZHrRhbK5Ag0EV128rQEQAM6ja77ILQQkhrunIHpAttae -zCULIMffXK8LVR2rxtRC1fFuvx7qWkzRePUB/+htU8kb6pFxHvY/4gdZWAe4Ft0M -2CDkEmGwZByOezk8cA7W32bR9iXhGRua719KkliMXEiUA1TsVjSbhgMAe2y2YhQc -yJtm/b4iTV0nz5g3F3/ml2LWb6aIQBDH1mvJy1F8iX9JLqQPXQop4SH3Fxj9Sjut -bQw1KoxWp8x3LLo/Jmdb2LSrHaBpHUIlRS7CX052mMujc4O8ffPz09QdFGoKSsCx -AZk+Br5uhe4mnQbMYVNGz8U5lTCiLgcxOd46tphzo/BJ/BWuOm0D6QY/KI974oPg -pQbk9jYfp23GUgrYlYZSuPNcCm+EWgVDOmcVYrb/28f8coSSo2knClOZACk84uIx -IZycbBdlFPDmyN1gPR/wfmygB0b/WBzhvzkEhHescDC++19Zy82OYNIyDk68ZYfl -ozINvLwqKJKPgQFRykuX139wp/tsgzL94STvyj2dLXvbjKHx/I8IuYpmj2FzLV11 -RCe5VaGSA1jM16FAOQdSJfbG3iO2oE43MnhJVFICp2WUVJkJV8cubB4Dhs5qNHWD -jZwYCMBNs7/letBBoO49LK/aD3blSNgjO3kZs70H9T+HAwdo+3pYdYAQjU7F3FvU -bipUYXw4R6dmGaA0IpZdABEBAAGJAiUEGAEKAA8FAlddvK0CGwwFCQeEzgAACgkQ -SbTGfAUneqoSLhAAg9BaWfrQk9ZPu6EbZtEP96rNYBnfyt3Aa8bPcdBGyWGFOL4q -q7lxYVz22P2drCzEUI39YIV8Y8sWhlvVE7ZTgYCCmKOvYGAukZ6lUxSNeEOpBsnw -v16vP/69WG+vFkmQinBzWcx3uu/8QnYyWd1PB0+MzyNXiN3Ekmlqd4TRwTzpc20i -iJvrYAHxuKNUQxlgTmFCKxhWBGS5bVEQ0QfWLBr/lniDRr2vF3nzHZiG/tclV37g -7wHAHrSkDaISahHtweP1RYuzPquu6QzKu9G7jq3QMOftOb2Rq7jR7ygFEIDDKeys -Wym2+SseFSXAZUzpIM6k76f99xzvq2pnY0jBOf9Q381OVciEYyWVhZ2vVoe+i3mA -AjDofMZfBW0CgNMqk8L0Fd5jXXw/ZPXv+oXJj6rrb462WMrZEgmxFH6olfUjIeyN -mDtqe5culR3t2MYU/HWbHmbaPpNsqEVsFh87leJenspuvsy2lOz7QOXbF16p30o/ -Uq2gdgs8A0t+qUZfouIJrWT/ZFXHaFEB6uMh1jIUC+hL5DHDZQtwS4P9s97qdk6y -nFv0qTF1rhim1wbkuA2AguQxASaDIP3dPq4flNJ3evlGnA7tm5Y9XaqwDQyd2ASF -fZwzkFlXyyBeiH+/G2sh8Idc1Qu8Z5y/PR7GTJ+xSXP73yjEqciWvuHeKPk= -=0PML +mQINBF+oSEgBEACtvXmcnUw2UqmCymZV2Ceie2V3mJDhx3uFnUAAkZp1is1Fv38l +vcyO+umT2S6E3ZMMon4WS1kuzQw2Eplzf43FXqP5IU1D4sR/SlUafcGQClCBGjsU +1V1dtyiFYQVKQw2ouPh/1i7h2aPkXG9qj3uk5QgFM1UxsxZuaG9TKmDZmC7gARaR ++21GX7M3vHCHy33GBENEJ5Pbb8yZDeTZRlypyZaFDJCqibqh0qB+nvIemyDQKp5e +yg0STFWmBZLDuKw3JtN6ykADsuWLWpXqxUCwD2WZboCNRqfircMTNoCmNYoOyiFf +h04Dy4ao0VPDKJlpMJyZODqHQx1mCoKXcLkVaEomMbimWeS+JKjNCtfJTKOI+hBF +H/0VyDlBju6BCkYXwgVDfQnnXWfXKYVOK4tAHeOkavfOFnLWee90VbSKhsPP3gXc +AcO+0FUKz7UH77PpFrhXrxZE+jY4CzfUqnLXll6Jlze8oqeJlxUxQptRyJTMCsq5 +twEySXXPU+4lUbbb4VDlGH0OAdG3k2DchHmPIhJn90sn+7PBC7LVaaCt8VM4n88M +VF311wgW9pUu+fDa7CKn2KDPDOpe24HuGjhY6WesIL4K0squnT2Bfx/J7iu1Gp7x +qjZGDg5da9VpMP4ZOdmrPbPK3bEZ8hPei3m7Ioyx2x2xJlKJa1BYgFC1xQARAQAB +tBpUaG9tYXMgTmFneSA8dG5hZ3lAd2FmLmlvPokCTAQTAQoANhYhBAs5crLZ4y6r +Qj0uDyK+DGL/v6VIBQJfqEhIAhsDBQkJZgGAAwsJCAUVCgkICwIeAQIXgAAKCRAi +vgxi/7+lSEpdD/9IbBZLYIvyeKDQoOZlnvyP0tpusfdPaqaCfOdgkklFiNDmxoCp +TATTlUfIS1Mnm8rULLVe1QmM5NZx40Y1qfs+j1mJK1awJXMpSFvIttlXjjNGwdbO +2dp536kP7X9CRq/9hzmSalwsSQHfpkBWTRdqennyQJHCMM+YhXFQhrb9qm8awePV +ZonCuf6o9e08im78rWSFWPi9gpOmRSvcoDY0kv7h8R5WlEjRuzrNDMePs42seoz9 +c70ITgM1fG1efIN78XMKSmdrXrf7rMRekfZ9rqxNbvgslYUohBE8jWBwON96YlGh ++qXLr3vgfjghTjHHMAMxSkdywAbps1JKB+mHDIHv4RGiBFXTJ6Qob8+O0dyrTY+k +dfswq1e1vZzABfj8JAekQtWv4syYdm2+fEC9oi4nqxXb1unLR8TthJuceUQwDdIG +pk6lqIkWqQftVu3FBbEGkwsCW3fDwqoJAhdjVxORgAe/JL0r0abpq+vm0+vN+lkL +ZdOWcSsnGxmpIzfuYRFo7W1qSz8UEfUKdpo5q/hsmCVHSR2aIsRVM23XByPtw6YU +CczlQ3Zz3YfJpknB1j+9uEd9wTTl7OC+xPwLBNzOa1lCa1hrPtnCbIFwtv49iVYd +sZf6RWZ4CQuV2MfdFWxpUh0KUfSuarv+u4bs8t0Me5RJlwcv7AnjeBH51bkCDQRf +qEhIARAAxcqbbAqivd1SvzqkWNu8RSTFtaofRbVFhyr1yIhXDA6rGuORj/NQRp6n +A5iPqBBvdpYR83xX8F2Bkv+33nIscxkAInuJVvAJ017LnYSDlikoUuwCrsjrS80k +haTO47i/VDbA75MlXqdejA9QKDSHu2S3+szjeU1/ACjWKdqHAN9I0LV4ATnybXEZ +178CxT3CTBbdkdAUV2Gv683awQfyBP0p+24MNjK+b+bAlyLXpN3CR59coyV8zH42 +5ReqXCeSoAhyvA5qa4KwZQ+zO2CVqb66LzuNjMZY536mPFTrUTXJRuPl+WmN0OjZ +FCbB8dBm7mnuEtgnUtZYK0UFyiHEG8jr4qbGlgbyJOcQYmQ/frba+eFL6LgXclNM +t4rOpD7KkM20zSU48aIyk+fANIN/MFAV1usJMri7DF4bmWgwBTm3T5xR0CELTlY7 +sE8VRssL5exMBSC0CbsTRmM4/qmU5NPRYS40BPVL8T0sYVnAzRUcF64bjjptMikN +DJkdASrzM23m/+m5N1rn5CfYDlwyN4cxlUmRQBQy25lkNPZZJKZfkUAbWYNfs9v3 +Jvp2zyWr4hO874dRU82ovfvQzCCIbtpy6SxhSmQ2E338c4GpAuv3Pp7Dr/lTWSCY +MUbNwd99SlGJ/FDqvbF+e0U9JZ2HA+0/NWS6pFZnR8ZeRarAr3EAEQEAAYkCPAQY +AQoAJhYhBAs5crLZ4y6rQj0uDyK+DGL/v6VIBQJfqEhIAhsMBQkJZgGAAAoJECK+ +DGL/v6VIzwIP/A4n5MFiB12OSokOdb5qtv66T9AwAg6G9LkZQExUtt2CLt+1BuxJ +f1V2kW/xFZ/EJi0ZiDmmf0npY3YTclYxcBPiNCDwNSL11p6wq3ACg/muhbz//NLL +tVKDEYf1DgYEqR0Ya9N8WtraI6MAeHPEYCZDBl2M7fm+r0pyErhKHnsXsMdtdV2k +1ZudjFHLeAGrHMkAm0IiyYUFY/Ww8KgVJex+m1nNpatMJhjQz+aAVv3EyVpyyaHc +684+t89vdnmWfdHQbQysyvNyWegtoalE66kUtk4cpwc8+voMuKl4y1U8jvZIR3Hh +XKqKKfY23V1Tr9etM7jnYLfChUkOK21xBk0I345cuy/XfZa1FED7Qq5Sia04zlFe +Mv4378hVt5VSSmr5mCVdVkopu1ctFjB3ZXD0TAUi8hmTks+laXFKpgLETD1iMQp2 +Inc2AWDX1ASIwvZxt/NqWika80ennnPUJY/hMVcozwQv1Z7PlfvhWxTXWGCl88Xw +ojLOD+TjNspMv/yXCaadAg4PrFJKXB6kX77rd0XCD9lOPATdMA60mvfHdCZyCHPp +B/wA41BB34+AC+I5TbMGM/mgQGpQ6nkCAU7pyxJ9Q+Egz2OSQibNAbcGrO5YZ6ko +cy15xEk3XzLqVLTA+euLC3z8ql6DFkBxt6Ta0pEUaYKRUAQYFADhd46E +=7TXb -----END PGP PUBLIC KEY BLOCK----- From 909b846d012aa3c1ce58af673d51ae0d5cee7580 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sun, 8 Nov 2020 20:53:12 +0100 Subject: [PATCH 262/315] waf-2.0.21 --- waf-light | 2 +- waflib/Context.py | 6 +++--- wscript | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/waf-light b/waf-light index e280b90a7b..cb9168a625 100755 --- a/waf-light +++ b/waf-light @@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. import os, sys, inspect -VERSION="2.0.20" +VERSION="2.0.21" REVISION="x" GIT="x" INSTALL="x" diff --git a/waflib/Context.py b/waflib/Context.py index e4445db322..0ce9df6e91 100755 --- a/waflib/Context.py +++ b/waflib/Context.py @@ -18,13 +18,13 @@ class imp(object): import imp # the following 3 constants are updated on each new release (do not touch) -HEXVERSION=0x2001400 +HEXVERSION=0x2001500 """Constant updated on new releases""" -WAFVERSION="2.0.20" +WAFVERSION="2.0.21" """Constant updated on new releases""" -WAFREVISION="668769470956da8c5b60817cb8884cd7d0f87cd4" +WAFREVISION="edde20a6425a5c3eb6b47d5f3f5c4fbc93fed5f4" """Git revision when the waf version is updated""" WAFNAME="waf" diff --git a/wscript b/wscript index 3e127b73e6..3c54df354b 100644 --- a/wscript +++ b/wscript @@ -11,7 +11,7 @@ To add a tool that does not exist in the folder compat15, pass an absolute path: from __future__ import with_statement -VERSION="2.0.20" +VERSION="2.0.21" APPNAME='waf' REVISION='' From d396fdcb744c0d838a5ba7826dcbcf127698ed1c Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Thu, 19 Nov 2020 07:40:28 +0100 Subject: [PATCH 263/315] Fix the file_to_object example --- playground/embedded_resources/wscript | 1 + 1 file changed, 1 insertion(+) diff --git a/playground/embedded_resources/wscript b/playground/embedded_resources/wscript index 3a872cbd13..b21e9f7b7a 100644 --- a/playground/embedded_resources/wscript +++ b/playground/embedded_resources/wscript @@ -24,6 +24,7 @@ def build(bld): name='example', source='main.c', features='file_to_object', + includes_nodes=[], ) bld( target = 'app', From db604201829edddb042cd3cbddc79d0086328300 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Tue, 8 Dec 2020 22:00:52 +0100 Subject: [PATCH 264/315] Exclude wafcache symlink handling - Exclude classes having folder or symlinks - Exclude well-known Task classes from wafcache processing - Remove stale 'waflib.Task.Task.chmod' processing --- waflib/extras/wafcache.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/waflib/extras/wafcache.py b/waflib/extras/wafcache.py index 088fd0d098..0bbf361929 100644 --- a/waflib/extras/wafcache.py +++ b/waflib/extras/wafcache.py @@ -117,11 +117,17 @@ def put_files_cache(self): if WAFCACHE_NO_PUSH or getattr(self, 'cached', None) or not self.outputs: return + files_from = [] + for node in self.outputs: + path = node.abspath() + if not os.path.isfile(path): + return + files_from.append(path) + bld = self.generator.bld sig = self.signature() ssig = Utils.to_hex(self.uid() + sig) - files_from = [node.abspath() for node in self.outputs] err = cache_command(ssig, files_from, []) if err.startswith(OK): @@ -193,6 +199,10 @@ def make_cached(cls): if getattr(cls, 'nocache', None) or getattr(cls, 'has_cache', False): return + full_name = "%s.%s" % (cls.__module__, cls.__name__) + if full_name in ('waflib.Tools.ccroot.vnum', 'waflib.Build.inst'): + return + m1 = getattr(cls, 'run', None) def run(self): if getattr(self, 'nocache', False): @@ -208,9 +218,6 @@ def post_run(self): return m2(self) ret = m2(self) self.put_files_cache() - if hasattr(self, 'chmod'): - for node in self.outputs: - os.chmod(node.abspath(), self.chmod) return ret cls.post_run = post_run cls.has_cache = True From f3c7369298d00fc818cf8482a97ae60f0e2ed986 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Tue, 15 Dec 2020 10:58:00 +0100 Subject: [PATCH 265/315] Conceal wafcache decoding errors in Python3 --- waflib/extras/wafcache.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/extras/wafcache.py b/waflib/extras/wafcache.py index 0bbf361929..5303b9f1ec 100644 --- a/waflib/extras/wafcache.py +++ b/waflib/extras/wafcache.py @@ -488,7 +488,7 @@ def replacer(match): out, err = proc.communicate() if proc.returncode: raise OSError('Error copy %r to %r using: %r (exit %r):\n out:%s\n err:%s' % ( - source, target, cmd, proc.returncode, out.decode(), err.decode())) + source, target, cmd, proc.returncode, out.decode(errors='replace'), err.decode(errors='replace'))) def copy_to_cache(self, sig, files_from, files_to): try: From b0424553bf3f02af2bbd9a1ce6a9427d411b405f Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Tue, 15 Dec 2020 11:06:05 +0100 Subject: [PATCH 266/315] Reduce wafcache verbosity on cleanup operations --- waflib/extras/wafcache.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/waflib/extras/wafcache.py b/waflib/extras/wafcache.py index 5303b9f1ec..83e5d7a57c 100644 --- a/waflib/extras/wafcache.py +++ b/waflib/extras/wafcache.py @@ -378,8 +378,8 @@ def lru_evict(): try: fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB) except EnvironmentError: - sys.stderr.write('another process is running!\n') - pass + if Logs.verbose: + Logs.debug('wafcache: another cleaning process is running') else: # now dow the actual cleanup lru_trim() From 0bf9456125223265daea37a3ea38da9002b4a7bd Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Tue, 15 Dec 2020 13:07:47 +0100 Subject: [PATCH 267/315] Improve clang_compilation_database interaction with wafcache --- waflib/extras/clang_compilation_database.py | 1 + 1 file changed, 1 insertion(+) diff --git a/waflib/extras/clang_compilation_database.py b/waflib/extras/clang_compilation_database.py index ff71f22ecf..0f8b362de5 100644 --- a/waflib/extras/clang_compilation_database.py +++ b/waflib/extras/clang_compilation_database.py @@ -105,6 +105,7 @@ def exec_command(self, *k, **kw): for tsk in lst: tup = tuple(y for y in [Task.classes.get(x) for x in ('c', 'cxx')] if y) if isinstance(tsk, tup): + tsk.nocache = True old_exec = tsk.exec_command tsk.exec_command = exec_command tsk.run() From 664258c60c5adcdb0186fc782a96e2114ab6476e Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Thu, 17 Dec 2020 14:17:35 +0100 Subject: [PATCH 268/315] Work around distutils MACOSX_DEPLOYMENT_TARGET regression #2330 --- waflib/Tools/python.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/Tools/python.py b/waflib/Tools/python.py index b1c8dd0128..07442561df 100644 --- a/waflib/Tools/python.py +++ b/waflib/Tools/python.py @@ -327,7 +327,7 @@ def check_python_headers(conf, features='pyembed pyext'): dct = dict(zip(v, lst)) x = 'MACOSX_DEPLOYMENT_TARGET' if dct[x]: - env[x] = conf.environ[x] = dct[x] + env[x] = conf.environ[x] = str(dct[x]) env.pyext_PATTERN = '%s' + dct['SO'] # not a mistake From 63d9ab741a5239d37120cb2f8f34ba6262d144be Mon Sep 17 00:00:00 2001 From: Andrew Brodko Date: Wed, 23 Dec 2020 20:38:58 +0000 Subject: [PATCH 269/315] Haxe support --- playground/haxe/bytecode/.haxerc | 4 + playground/haxe/bytecode/package.json | 18 +++ playground/haxe/bytecode/src/Main.hx | 5 + playground/haxe/bytecode/src/main.hxml | 2 + playground/haxe/bytecode/src/wscript | 7 + playground/haxe/bytecode/wscript | 8 ++ playground/haxe/executable/.haxerc | 4 + playground/haxe/executable/bin/wscript | 43 ++++++ .../haxe/executable/haxe_libraries/readme.txt | 1 + playground/haxe/executable/lib/readme.txt | 1 + playground/haxe/executable/package.json | 18 +++ playground/haxe/executable/src/Main.hx | 5 + playground/haxe/executable/src/main.hxml | 2 + playground/haxe/executable/src/wscript | 13 ++ playground/haxe/executable/wscript | 15 ++ waflib/extras/haxe.py | 131 ++++++++++++++++++ 16 files changed, 277 insertions(+) create mode 100644 playground/haxe/bytecode/.haxerc create mode 100644 playground/haxe/bytecode/package.json create mode 100644 playground/haxe/bytecode/src/Main.hx create mode 100644 playground/haxe/bytecode/src/main.hxml create mode 100644 playground/haxe/bytecode/src/wscript create mode 100644 playground/haxe/bytecode/wscript create mode 100644 playground/haxe/executable/.haxerc create mode 100644 playground/haxe/executable/bin/wscript create mode 100644 playground/haxe/executable/haxe_libraries/readme.txt create mode 100644 playground/haxe/executable/lib/readme.txt create mode 100644 playground/haxe/executable/package.json create mode 100644 playground/haxe/executable/src/Main.hx create mode 100644 playground/haxe/executable/src/main.hxml create mode 100644 playground/haxe/executable/src/wscript create mode 100644 playground/haxe/executable/wscript create mode 100644 waflib/extras/haxe.py diff --git a/playground/haxe/bytecode/.haxerc b/playground/haxe/bytecode/.haxerc new file mode 100644 index 0000000000..093ce54c70 --- /dev/null +++ b/playground/haxe/bytecode/.haxerc @@ -0,0 +1,4 @@ +{ + "version": "4.1.4", + "resolveLibs": "scoped" +} \ No newline at end of file diff --git a/playground/haxe/bytecode/package.json b/playground/haxe/bytecode/package.json new file mode 100644 index 0000000000..abe82fad30 --- /dev/null +++ b/playground/haxe/bytecode/package.json @@ -0,0 +1,18 @@ +{ + "name": "Haxe", + "version": "1.0.0", + "description": "", + "main": "index.js", + "directories": { + "lib": "lib" + }, + "scripts": { + "postinstall": "lix download" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "lix": "^15.10.1" + } +} diff --git a/playground/haxe/bytecode/src/Main.hx b/playground/haxe/bytecode/src/Main.hx new file mode 100644 index 0000000000..331e5bf830 --- /dev/null +++ b/playground/haxe/bytecode/src/Main.hx @@ -0,0 +1,5 @@ +class Main { + static function main() { + trace('hello'); + } +} diff --git a/playground/haxe/bytecode/src/main.hxml b/playground/haxe/bytecode/src/main.hxml new file mode 100644 index 0000000000..a567cc2912 --- /dev/null +++ b/playground/haxe/bytecode/src/main.hxml @@ -0,0 +1,2 @@ +-dce full +-main Main.hx diff --git a/playground/haxe/bytecode/src/wscript b/playground/haxe/bytecode/src/wscript new file mode 100644 index 0000000000..6ad108d679 --- /dev/null +++ b/playground/haxe/bytecode/src/wscript @@ -0,0 +1,7 @@ +def configure(ctx): + ctx.load('haxe') + +def build(ctx): + ctx.haxe( + source = 'main.hxml', + target = 'main.hl') diff --git a/playground/haxe/bytecode/wscript b/playground/haxe/bytecode/wscript new file mode 100644 index 0000000000..a753e5ddf8 --- /dev/null +++ b/playground/haxe/bytecode/wscript @@ -0,0 +1,8 @@ +top = '.' +out = 'bin/waf' + +def configure(ctx): + ctx.recurse('src') + +def build(ctx): + ctx.recurse('src') diff --git a/playground/haxe/executable/.haxerc b/playground/haxe/executable/.haxerc new file mode 100644 index 0000000000..093ce54c70 --- /dev/null +++ b/playground/haxe/executable/.haxerc @@ -0,0 +1,4 @@ +{ + "version": "4.1.4", + "resolveLibs": "scoped" +} \ No newline at end of file diff --git a/playground/haxe/executable/bin/wscript b/playground/haxe/executable/bin/wscript new file mode 100644 index 0000000000..a27e4c1adc --- /dev/null +++ b/playground/haxe/executable/bin/wscript @@ -0,0 +1,43 @@ +from waflib.TaskGen import feature + +def configure(ctx): + ctx.load('clang_cl') + ctx.env.CFLAGS.extend(['/EHsc', '/O12', '/TC', '/GL', '/w', '/U __llvm__']) + for lib in ['msvcrt']: + ctx.check( + compiler='c', + lib=lib, + uselib_store='SYSTEM') + for lib in ['libhl']: + ctx.check( + compiler='c', + lib=lib, + use='HL', + uselib_store='HL') + +def build(ctx): + ctx.env.LINKFLAGS.extend(['/NODEFAULTLIB:libcmt']) + ctx.program( + source = ['waf/src/main.c'], + includes = [ctx.env.ROOT_INCLUDE_DIR], + target = 'app', + use = ['SYSTEM', 'HL']) + +@feature('cxxprogram', 'cprogram') +def call_me_static(self): + attr_name = 'source' + attr = getattr(self, attr_name, []) + if len(attr): + setattr(self, attr_name, []) + for x in self.to_list(attr): + node = self.path.make_node(x) + tg = self.bld.get_tgen_by_name(node.name) + if not tg: + self.bld.fatal('Could not find a task generator by the name %r' % x) + tg.post() + for tsk in tg.tasks: + for out in tsk.outputs: + if out.name.endswith('.c'): + self.create_compiled_task('c', out) + if not self.compiled_tasks: + self.fatal('Could not find a source file for for %r' % self.name) diff --git a/playground/haxe/executable/haxe_libraries/readme.txt b/playground/haxe/executable/haxe_libraries/readme.txt new file mode 100644 index 0000000000..e2bc21ff01 --- /dev/null +++ b/playground/haxe/executable/haxe_libraries/readme.txt @@ -0,0 +1 @@ +this directory is served by lix automatically and stores versions of used haxe libraries diff --git a/playground/haxe/executable/lib/readme.txt b/playground/haxe/executable/lib/readme.txt new file mode 100644 index 0000000000..e5e14441ae --- /dev/null +++ b/playground/haxe/executable/lib/readme.txt @@ -0,0 +1 @@ +place hashlink c libraries here (e.g. libhl.lib) - dedicated directory is used for a case when hashlink libs are statically linked diff --git a/playground/haxe/executable/package.json b/playground/haxe/executable/package.json new file mode 100644 index 0000000000..abe82fad30 --- /dev/null +++ b/playground/haxe/executable/package.json @@ -0,0 +1,18 @@ +{ + "name": "Haxe", + "version": "1.0.0", + "description": "", + "main": "index.js", + "directories": { + "lib": "lib" + }, + "scripts": { + "postinstall": "lix download" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "lix": "^15.10.1" + } +} diff --git a/playground/haxe/executable/src/Main.hx b/playground/haxe/executable/src/Main.hx new file mode 100644 index 0000000000..331e5bf830 --- /dev/null +++ b/playground/haxe/executable/src/Main.hx @@ -0,0 +1,5 @@ +class Main { + static function main() { + trace('hello'); + } +} diff --git a/playground/haxe/executable/src/main.hxml b/playground/haxe/executable/src/main.hxml new file mode 100644 index 0000000000..a567cc2912 --- /dev/null +++ b/playground/haxe/executable/src/main.hxml @@ -0,0 +1,2 @@ +-dce full +-main Main.hx diff --git a/playground/haxe/executable/src/wscript b/playground/haxe/executable/src/wscript new file mode 100644 index 0000000000..412095635e --- /dev/null +++ b/playground/haxe/executable/src/wscript @@ -0,0 +1,13 @@ +def configure(ctx): + ctx.load('haxe') + ctx.ensure_lix_pkg( + compiler='hx', + libs=['hashlink'], + uselib_store='HLR') + +def build(ctx): + ctx.haxe( + source = 'main.hxml', + res = ctx.env.ROOT_RES_DIR, + target = 'main.c', + use = ['HLR']) diff --git a/playground/haxe/executable/wscript b/playground/haxe/executable/wscript new file mode 100644 index 0000000000..a7e3056528 --- /dev/null +++ b/playground/haxe/executable/wscript @@ -0,0 +1,15 @@ +top = '.' +out = 'bin/waf' + +def configure(ctx): + ctx.env.ROOT_INCLUDE_DIR = ctx.path.get_bld().make_node('src').abspath() + ctx.env.ROOT_RES_DIR = ctx.path.make_node('res').abspath() + ctx.env.LIBPATH_HAXE = ctx.path.make_node('haxe_libraries').abspath() + ctx.env.LIBPATH_HL = ctx.path.make_node('lib').abspath() + ctx.env.INCLUDES_HL = ['%hashlink%/hl-1.11.0-win/include'] + ctx.recurse('src') + ctx.recurse('bin') + +def build(ctx): + ctx.recurse('src') + ctx.recurse('bin') diff --git a/waflib/extras/haxe.py b/waflib/extras/haxe.py new file mode 100644 index 0000000000..cb3ba6a949 --- /dev/null +++ b/waflib/extras/haxe.py @@ -0,0 +1,131 @@ +import os, re +from waflib import Utils, Task, Errors +from waflib.TaskGen import extension, taskgen_method, feature +from waflib.Configure import conf + +@conf +def libname_haxe(self, libname): + return libname + +@conf +def check_lib_haxe(self, libname, uselib_store=None): + haxe_libs = [node.name for node in self.root.find_node('haxe_libraries').ant_glob()] + changed = False + self.start_msg('Checking for library %s' % libname) + if libname + '.hxml' in haxe_libs: + self.end_msg('yes') + else: + changed = True + try: + cmd = self.env.LIX + ['+lib', libname] + res = self.cmd_and_log(cmd) + if (res): + raise Errors.WafError(res) + else: + self.end_msg('downloaded', color = 'YELLOW') + except Errors.WafError as e: + self.end_msg('no', color = 'RED') + self.fatal('Getting %s has failed' % libname) + + postfix = uselib_store if uselib_store else libname.upper() + self.env['LIB_' + postfix] += [self.libname_haxe(libname)] + return changed + +@conf +def check_libs_haxe(self, libnames, uselib_store=None): + changed = False + for libname in Utils.to_list(libnames): + if self.check_lib_haxe(libname, uselib_store): + changed = True + return changed + +@conf +def ensure_lix_pkg(self, *k, **kw): + if kw.get('compiler') == 'hx': + if isinstance(kw.get('libs'), list) and len(kw.get('libs')): + changed = self.check_libs_haxe(kw.get('libs'), kw.get('uselib_store')) + if changed: + try: + cmd = self.env.LIX + ['download'] + res = self.cmd_and_log(cmd) + if (res): + raise Errors.WafError(res) + except Errors.WafError as e: + self.fatal('lix download has failed') + else: + self.check_lib_haxe(kw.get('lib'), kw.get('uselib_store')) + +@conf +def haxe(bld, *k, **kw): + task_gen = bld(*k, **kw) + +class haxe(Task.Task): + vars = ['HAXE', 'HAXE_VERSION', 'HAXEFLAGS'] + ext_out = ['.hl', '.c', '.h'] + + def run(self): + cmd = self.env.HAXE + self.env.HAXEFLAGS + return self.exec_command(cmd, stdout = open(os.devnull, 'w')) + +@taskgen_method +def init_haxe_task(self, node): + def addflags(flags): + self.env.append_value('HAXEFLAGS', flags) + + if node.suffix() == '.hxml': + addflags(self.path.abspath() + '/' + node.name) + else: + addflags(['-main', node.name]) + addflags(['-hl', self.path.get_bld().make_node(self.target).abspath()]) + addflags(['-cp', self.path.abspath()]) + addflags(['-D', 'resourcesPath=%s' % getattr(self, 'res', '')]) + if hasattr(self, 'use'): + for dep in self.use: + if self.env['LIB_' + dep]: + for lib in self.env['LIB_' + dep]: addflags(['-lib', lib]) + +@extension('.hx', '.hxml') +def haxe_file(self, node): + if len(self.source) > 1: + self.bld.fatal('Use separate task generators for multiple files') + + try: + haxetask = self.haxetask + except AttributeError: + haxetask = self.haxetask = self.create_task('haxe') + self.init_haxe_task(node) + + haxetask.inputs.append(node) + haxetask.outputs.append(self.path.get_bld().make_node(self.target)) + +@conf +def find_haxe(self, min_version): + npx = self.env.NPX = self.find_program('npx') + self.env.LIX = npx + ['lix'] + npx_haxe = self.env.HAXE = npx + ['haxe'] + try: + output = self.cmd_and_log(npx_haxe + ['-version']) + except Errors.WafError: + haxe_version = None + else: + ver = re.search(r'\d+.\d+.\d+', output).group().split('.') + haxe_version = tuple([int(x) for x in ver]) + + self.msg('Checking for haxe version', + haxe_version, haxe_version and haxe_version >= min_version) + if npx_haxe and haxe_version < min_version: + self.fatal('haxe version %r is too old, need >= %r' % (haxe_version, min_version)) + + self.env.HAXE_VERSION = haxe_version + return npx_haxe + +@conf +def check_haxe(self, min_version=(4,1,4)): + if self.env.HAXE_MINVER: + min_version = self.env.HAXE_MINVER + find_haxe(self, min_version) + +def configure(self): + self.env.HAXEFLAGS = [] + self.check_haxe() + self.add_os_flags('HAXEFLAGS', dup = False) From 28d030c3ca5fdded76cb0d5cd5fb10da7a01e274 Mon Sep 17 00:00:00 2001 From: Federico Pellegrin Date: Wed, 23 Dec 2020 14:22:21 +0100 Subject: [PATCH 270/315] wafcache: add simple cache statistics collection, configurable via env --- waflib/extras/wafcache.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/waflib/extras/wafcache.py b/waflib/extras/wafcache.py index 83e5d7a57c..f07c2f2bae 100644 --- a/waflib/extras/wafcache.py +++ b/waflib/extras/wafcache.py @@ -31,6 +31,7 @@ gsutil cp gs://mybucket/bb/bbbbb/2 build/somefile * WAFCACHE_NO_PUSH: if set, disables pushing to the cache * WAFCACHE_VERBOSITY: if set, displays more detailed cache operations +* WAFCACHE_STATS: if set, displays cache usage statistics on exit File cache specific options: Files are copied using hard links by default; if the cache is located @@ -69,6 +70,7 @@ def build(bld): EVICT_MAX_BYTES = int(os.environ.get('WAFCACHE_EVICT_MAX_BYTES', 10**10)) WAFCACHE_NO_PUSH = 1 if os.environ.get('WAFCACHE_NO_PUSH') else 0 WAFCACHE_VERBOSITY = 1 if os.environ.get('WAFCACHE_VERBOSITY') else 0 +WAFCACHE_STATS = 1 if os.environ.get('WAFCACHE_STATS') else 0 OK = "ok" re_waf_cmd = re.compile('(?P%{SRC})|(?P%{TGT})') @@ -93,6 +95,9 @@ def can_retrieve_cache(self): sig = self.signature() ssig = Utils.to_hex(self.uid() + sig) + if WAFCACHE_STATS: + self.generator.bld.cache_reqs += 1 + files_to = [node.abspath() for node in self.outputs] err = cache_command(ssig, [], files_to) if err.startswith(OK): @@ -100,6 +105,8 @@ def can_retrieve_cache(self): Logs.pprint('CYAN', ' Fetched %r from cache' % files_to) else: Logs.debug('wafcache: fetched %r from cache', files_to) + if WAFCACHE_STATS: + self.generator.bld.cache_hits += 1 else: if WAFCACHE_VERBOSITY: Logs.pprint('YELLOW', ' No cache entry %s' % files_to) @@ -135,6 +142,8 @@ def put_files_cache(self): Logs.pprint('CYAN', ' Successfully uploaded %s to cache' % files_from) else: Logs.debug('wafcache: Successfully uploaded %r to cache', files_from) + if WAFCACHE_STATS: + self.generator.bld.cache_puts += 1 else: if WAFCACHE_VERBOSITY: Logs.pprint('RED', ' Error caching step results %s: %s' % (files_from, err)) @@ -264,6 +273,19 @@ def build(bld): for x in reversed(list(Task.classes.values())): make_cached(x) + if WAFCACHE_STATS: + # Init counter for statistics and hook to print results at the end + bld.cache_reqs = bld.cache_hits = bld.cache_puts = 0 + + def printstats(bld): + hit_ratio = 0 + if bld.cache_reqs > 0: + hit_ratio = (bld.cache_hits / bld.cache_reqs) * 100 + Logs.pprint('CYAN', ' wafache stats: requests: %s, hits, %s, ratio: %.2f%%, writes %s' % + (bld.cache_reqs, bld.cache_hits, hit_ratio, bld.cache_puts) ) + + bld.add_post_fun(printstats) + def cache_command(sig, files_from, files_to): """ Create a command for cache worker processes, returns a pickled From 11d7a6f2fb293340d8221c6c66ef9210486032cd Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sat, 26 Dec 2020 20:43:37 +0100 Subject: [PATCH 271/315] Do not detect Qt6 when detecting Qt5 --- waflib/Tools/qt5.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/waflib/Tools/qt5.py b/waflib/Tools/qt5.py index cff2028174..82c83e18c8 100644 --- a/waflib/Tools/qt5.py +++ b/waflib/Tools/qt5.py @@ -566,7 +566,7 @@ def find_qt5_binaries(self): # at the end, try to find qmake in the paths given # keep the one with the highest version cand = None - prev_ver = ['5', '0', '0'] + prev_ver = ['0', '0', '0'] for qmk in ('qmake-qt5', 'qmake5', 'qmake'): try: qmake = self.find_program(qmk, path_list=paths) @@ -580,7 +580,7 @@ def find_qt5_binaries(self): else: if version: new_ver = version.split('.') - if new_ver > prev_ver: + if new_ver[0] == '5' and new_ver > prev_ver: cand = qmake prev_ver = new_ver @@ -783,7 +783,7 @@ def set_qt5_libs_to_check(self): pat = self.env.cxxstlib_PATTERN if Utils.unversioned_sys_platform() == 'darwin': pat = r"%s\.framework" - re_qt = re.compile(pat%'Qt5?(?P.*)'+'$') + re_qt = re.compile(pat % 'Qt5?(?P\\D+)' + '$') for x in dirlst: m = re_qt.match(x) if m: From 556b823dbdbb086435edc65deb4870a0c199dccf Mon Sep 17 00:00:00 2001 From: Federico Pellegrin Date: Thu, 7 Jan 2021 04:09:11 +0100 Subject: [PATCH 272/315] wafcache: fix small typo on stats log message --- waflib/extras/wafcache.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/extras/wafcache.py b/waflib/extras/wafcache.py index f07c2f2bae..28f28dadac 100644 --- a/waflib/extras/wafcache.py +++ b/waflib/extras/wafcache.py @@ -281,7 +281,7 @@ def printstats(bld): hit_ratio = 0 if bld.cache_reqs > 0: hit_ratio = (bld.cache_hits / bld.cache_reqs) * 100 - Logs.pprint('CYAN', ' wafache stats: requests: %s, hits, %s, ratio: %.2f%%, writes %s' % + Logs.pprint('CYAN', ' wafcache stats: requests: %s, hits, %s, ratio: %.2f%%, writes %s' % (bld.cache_reqs, bld.cache_hits, hit_ratio, bld.cache_puts) ) bld.add_post_fun(printstats) From ae57421705a7b75a6f7d43294effaabf63aee68e Mon Sep 17 00:00:00 2001 From: Federico Pellegrin Date: Thu, 7 Jan 2021 09:45:01 +0100 Subject: [PATCH 273/315] cuda: solve warnings due to testapp being created by two tg --- playground/cuda/wscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playground/cuda/wscript b/playground/cuda/wscript index 9daf81e481..30303a3d8d 100644 --- a/playground/cuda/wscript +++ b/playground/cuda/wscript @@ -35,7 +35,7 @@ def build(bld): # native application bld.program( source = 'test.cpp', - target = 'testapp') + target = 'testapp-native') # cuda application bld.program( From 8571aef2f9485a3e7ea67a667bc7833bd479d1f6 Mon Sep 17 00:00:00 2001 From: Federico Pellegrin Date: Thu, 7 Jan 2021 09:48:05 +0100 Subject: [PATCH 274/315] cuda: pass correctly compiler options from nvcc to the underlying compiler with --compiler-options --- playground/cuda/cuda.py | 3 ++- playground/cuda/wscript | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/playground/cuda/cuda.py b/playground/cuda/cuda.py index 60266dc92a..d4135eb189 100644 --- a/playground/cuda/cuda.py +++ b/playground/cuda/cuda.py @@ -10,7 +10,7 @@ from waflib.Configure import conf class cuda(Task.Task): - run_str = '${NVCC} ${CUDAFLAGS} ${CXXFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${CXX_SRC_F}${SRC} ${CXX_TGT_F} ${TGT}' + run_str = '${NVCC} ${CUDAFLAGS} ${NVCCFLAGS_ST:CXXFLAGS} ${FRAMEWORKPATH_ST:FRAMEWORKPATH} ${CPPPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${CXX_SRC_F}${SRC} ${CXX_TGT_F} ${TGT}' color = 'GREEN' ext_in = ['.h'] vars = ['CCDEPS'] @@ -32,6 +32,7 @@ def cxx_hook(self, node): def configure(conf): conf.find_program('nvcc', var='NVCC') conf.find_cuda_libs() + conf.env.NVCCFLAGS_ST = "--compiler-options=%s" @conf def find_cuda_libs(self): diff --git a/playground/cuda/wscript b/playground/cuda/wscript index 30303a3d8d..db592d4d62 100644 --- a/playground/cuda/wscript +++ b/playground/cuda/wscript @@ -18,6 +18,9 @@ def configure(conf): conf.load('cuda', tooldir='.') + # Add a few flags to test proper passing to nvcc + conf.env.CXXFLAGS=['-fPIC', '--std=c++11'] + def build(bld): # cuda application From e033cd5e8859ebd08f640821e618d5fd1da2d4b4 Mon Sep 17 00:00:00 2001 From: Federico Pellegrin Date: Mon, 11 Jan 2021 11:18:48 +0100 Subject: [PATCH 275/315] wafcache: fix reporting of concurrent trim error As this is run in the non-waf process we don't have Logs, so we write to stderr instead or we will get a NameError name 'Logs' is not defined. --- waflib/extras/wafcache.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/waflib/extras/wafcache.py b/waflib/extras/wafcache.py index 28f28dadac..e478ca67b2 100644 --- a/waflib/extras/wafcache.py +++ b/waflib/extras/wafcache.py @@ -400,8 +400,8 @@ def lru_evict(): try: fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB) except EnvironmentError: - if Logs.verbose: - Logs.debug('wafcache: another cleaning process is running') + if WAFCACHE_VERBOSITY: + sys.stderr.write('wafcache: another cleaning process is running\n') else: # now dow the actual cleanup lru_trim() From cc4fbe85e5c325b9d74edee066093be81cd2cce4 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Tue, 12 Jan 2021 18:16:57 +0100 Subject: [PATCH 276/315] Suppress cache trimming operation errors --- waflib/extras/wafcache.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/waflib/extras/wafcache.py b/waflib/extras/wafcache.py index e478ca67b2..cc23fcd667 100644 --- a/waflib/extras/wafcache.py +++ b/waflib/extras/wafcache.py @@ -349,7 +349,10 @@ def lru_trim(): size = 0 for fname in os.listdir(path): - size += os.lstat(os.path.join(path, fname)).st_size + try: + size += os.lstat(os.path.join(path, fname)).st_size + except OSError: + pass lst.append((os.stat(path).st_mtime, size, path)) lst.sort(key=lambda x: x[0]) @@ -360,7 +363,7 @@ def lru_trim(): _, tmp_size, path = lst.pop() tot -= tmp_size - tmp = path + '.tmp' + tmp = path + '.remove' try: shutil.rmtree(tmp) except OSError: @@ -368,12 +371,12 @@ def lru_trim(): try: os.rename(path, tmp) except OSError: - sys.stderr.write('Could not rename %r to %r' % (path, tmp)) + sys.stderr.write('Could not rename %r to %r\n' % (path, tmp)) else: try: shutil.rmtree(tmp) except OSError: - sys.stderr.write('Could not remove %r' % tmp) + sys.stderr.write('Could not remove %r\n' % tmp) sys.stderr.write("Cache trimmed: %r bytes in %r folders left\n" % (tot, len(lst))) @@ -472,7 +475,10 @@ def copy_to_cache(self, sig, files_from, files_to): else: # attempt trimming if caching was successful: # we may have things to trim! - lru_evict() + try: + lru_evict() + except Exception: + return traceback.format_exc() return OK def copy_from_cache(self, sig, files_from, files_to): From 78b97744e8e4d1fcc8f2df805f5257ed1d59bab9 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Wed, 13 Jan 2021 17:39:52 +0100 Subject: [PATCH 277/315] Increase clang_compilation_database and swig compatibility --- waflib/extras/clang_compilation_database.py | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/waflib/extras/clang_compilation_database.py b/waflib/extras/clang_compilation_database.py index 0f8b362de5..ff74e610ae 100644 --- a/waflib/extras/clang_compilation_database.py +++ b/waflib/extras/clang_compilation_database.py @@ -29,22 +29,9 @@ def configure(conf): Task.Task.keep_last_cmd = True -@TaskGen.feature('c', 'cxx') -@TaskGen.after_method('process_use') -def collect_compilation_db_tasks(self): - "Add a compilation database entry for compiled tasks" - if not isinstance(self.bld, ClangDbContext): - return - - tup = tuple(y for y in [Task.classes.get(x) for x in ('c', 'cxx')] if y) - for task in getattr(self, 'compiled_tasks', []): - if isinstance(task, tup): - self.bld.clang_compilation_database_tasks.append(task) - class ClangDbContext(Build.BuildContext): '''generates compile_commands.json by request''' cmd = 'clangdb' - clang_compilation_database_tasks = [] def write_compilation_database(self): """ @@ -78,6 +65,8 @@ def execute(self): Build dry run """ self.restore() + self.cur_tasks = [] + self.clang_compilation_database_tasks = [] if not self.all_envs: self.load_envs() @@ -103,8 +92,14 @@ def exec_command(self, *k, **kw): lst = [tg] else: lst = tg.tasks for tsk in lst: + if tsk.__class__.__name__ == "swig": + tsk.runnable_status() + if hasattr(tsk, 'more_tasks'): + lst.extend(tsk.more_tasks) + tup = tuple(y for y in [Task.classes.get(x) for x in ('c', 'cxx')] if y) if isinstance(tsk, tup): + self.clang_compilation_database_tasks.append(tsk) tsk.nocache = True old_exec = tsk.exec_command tsk.exec_command = exec_command From 935caea56b3367e059c633e69ef1fd5634befabf Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Tue, 19 Jan 2021 17:49:54 +0100 Subject: [PATCH 278/315] Add more docs to clang_compilation_database --- waflib/extras/clang_compilation_database.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/waflib/extras/clang_compilation_database.py b/waflib/extras/clang_compilation_database.py index ff74e610ae..17f6694937 100644 --- a/waflib/extras/clang_compilation_database.py +++ b/waflib/extras/clang_compilation_database.py @@ -96,6 +96,12 @@ def exec_command(self, *k, **kw): tsk.runnable_status() if hasattr(tsk, 'more_tasks'): lst.extend(tsk.more_tasks) + # Not all dynamic tasks can be processed, in some cases + # one may have to call the method "run()" like this: + #elif tsk.__class__.__name__ == 'src2c': + # tsk.run() + # if hasattr(tsk, 'more_tasks'): + # lst.extend(tsk.more_tasks) tup = tuple(y for y in [Task.classes.get(x) for x in ('c', 'cxx')] if y) if isinstance(tsk, tup): From 27a8e49904c746e245f3dcdaac06e4aeaecf0fdb Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Tue, 19 Jan 2021 17:50:25 +0100 Subject: [PATCH 279/315] Fix Build.py indentation --- waflib/Build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/Build.py b/waflib/Build.py index e9b47203fd..d490d2a4e2 100644 --- a/waflib/Build.py +++ b/waflib/Build.py @@ -1066,7 +1066,7 @@ def get_install_path(self, destdir=True): else: dest = os.path.normpath(Utils.subst_vars(self.install_to, self.env)) if not os.path.isabs(dest): - dest = os.path.join(self.env.PREFIX, dest) + dest = os.path.join(self.env.PREFIX, dest) if destdir and Options.options.destdir: dest = os.path.join(Options.options.destdir, os.path.splitdrive(dest)[1].lstrip(os.sep)) return dest From 5241d7b05e0a3a5366ac14bdd1ab1b535befffb9 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Tue, 19 Jan 2021 20:35:48 +0100 Subject: [PATCH 280/315] Allow mixing Unix paths with destdir on non-Unix platforms --- waflib/Build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/Build.py b/waflib/Build.py index d490d2a4e2..3b1f06cba5 100644 --- a/waflib/Build.py +++ b/waflib/Build.py @@ -1068,7 +1068,7 @@ def get_install_path(self, destdir=True): if not os.path.isabs(dest): dest = os.path.join(self.env.PREFIX, dest) if destdir and Options.options.destdir: - dest = os.path.join(Options.options.destdir, os.path.splitdrive(dest)[1].lstrip(os.sep)) + dest = Options.options.destdir.rstrip(os.sep) + os.sep + os.path.splitdrive(dest)[1].lstrip(os.sep) return dest def copy_fun(self, src, tgt): From 0f61ac6a86846c901d3c2447875022eead7a9d61 Mon Sep 17 00:00:00 2001 From: "Bootsma, James" Date: Wed, 20 Jan 2021 16:22:59 -0700 Subject: [PATCH 281/315] waf_unit_test: Fix command handling under windows The unit test tool moved from a simple split to using shlex.split for handling the unit test command. This results in the path separators on windows being treated as escapes. To handle this the unit test exec command is properly escaped before joining so that the subsequent split restores the original arguments. The quote function is also exposed in the Utilities module so that wscripts making use of the unit test tool can properly quote their contributions to the command as well. --- waflib/Tools/waf_unit_test.py | 2 +- waflib/Utils.py | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/waflib/Tools/waf_unit_test.py b/waflib/Tools/waf_unit_test.py index dc66fe9c18..8cff89bdeb 100644 --- a/waflib/Tools/waf_unit_test.py +++ b/waflib/Tools/waf_unit_test.py @@ -206,7 +206,7 @@ def run(self): self.ut_exec = getattr(self.generator, 'ut_exec', [self.inputs[0].abspath()]) ut_cmd = getattr(self.generator, 'ut_cmd', False) if ut_cmd: - self.ut_exec = shlex.split(ut_cmd % ' '.join(self.ut_exec)) + self.ut_exec = shlex.split(ut_cmd % Utils.shell_escape(self.ut_exec)) return self.exec_command(self.ut_exec) diff --git a/waflib/Utils.py b/waflib/Utils.py index fc64fa0515..669490ca90 100644 --- a/waflib/Utils.py +++ b/waflib/Utils.py @@ -11,7 +11,7 @@ from __future__ import with_statement -import atexit, os, sys, errno, inspect, re, datetime, platform, base64, signal, functools, time +import atexit, os, sys, errno, inspect, re, datetime, platform, base64, signal, functools, time, shlex try: import cPickle @@ -577,10 +577,13 @@ def quote_define_name(s): fu = fu.upper() return fu -re_sh = re.compile('\\s|\'|"') -""" -Regexp used for shell_escape below -""" +# shlex.quote didn't exist until python 3.3. Prior to that it was a non-documented +# function in pipes. +try: + shell_quote = shlex.quote +except AttributeError: + import pipes + shell_quote = pipes.quote def shell_escape(cmd): """ @@ -589,7 +592,7 @@ def shell_escape(cmd): """ if isinstance(cmd, str): return cmd - return ' '.join(repr(x) if re_sh.search(x) else x for x in cmd) + return ' '.join(shell_quote(x) for x in cmd) def h_list(lst): """ From 128960d16e6844bae8ec2e1b2b6709869ac699eb Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Fri, 29 Jan 2021 23:46:05 +0100 Subject: [PATCH 282/315] Work around faulty vcvarsall.bat scripts #2315 --- waflib/Tools/msvc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/Tools/msvc.py b/waflib/Tools/msvc.py index 37233be824..0c4703aaee 100644 --- a/waflib/Tools/msvc.py +++ b/waflib/Tools/msvc.py @@ -193,7 +193,7 @@ def get_msvc_version(conf, compiler, version, target, vcvars): echo INCLUDE=%%INCLUDE%% echo LIB=%%LIB%%;%%LIBPATH%% """ % (vcvars,target)) - sout = conf.cmd_and_log(['cmd.exe', '/E:on', '/V:on', '/C', batfile.abspath()]) + sout = conf.cmd_and_log(['cmd.exe', '/E:on', '/V:on', '/C', batfile.abspath()], stdin=getattr(Utils.subprocess, 'DEVNULL', None)) lines = sout.splitlines() if not lines[0]: From 2d39ad383842244abfe679417ab7c8aba5f9f923 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sat, 30 Jan 2021 16:41:29 +0100 Subject: [PATCH 283/315] waf-2.0.22 --- ChangeLog | 13 +++++++++++++ waf-light | 2 +- waflib/Context.py | 6 +++--- wscript | 2 +- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index aa5cf37af3..9ef9b42814 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +NEW IN WAF 2.0.22 +----------------- +* Fix stdin propagation with faulty vcvarsall scripts #2315 +* Enable mixing Unix-style paths with destdir on Windows platforms #2337 +* Fix shell escaping unit test parameters #2314 +* Improve extras/clang_compilation_database and extras/swig compatibility #2336 +* Propagate C++ flags to the Cuda compiler in extras/cuda #2311 +* Fix detection of Qt 5.0.0 (preparation for Qt6) #2331 +* Enable Haxe processing #2308 +* Fix regression in MACOSX_DEPLOYMENT_TARGET caused by distutils #2330 +* Fix extras/wafcache concurrent trimming issues #2312 +* Fix extras/wafcache symlink handling #2327 + NEW IN WAF 2.0.21 ----------------- * Set the default --msvc_version from VSCMD_VER if present #2299 diff --git a/waf-light b/waf-light index cb9168a625..97beb52058 100755 --- a/waf-light +++ b/waf-light @@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. import os, sys, inspect -VERSION="2.0.21" +VERSION="2.0.22" REVISION="x" GIT="x" INSTALL="x" diff --git a/waflib/Context.py b/waflib/Context.py index 0ce9df6e91..07ee1201f0 100755 --- a/waflib/Context.py +++ b/waflib/Context.py @@ -18,13 +18,13 @@ class imp(object): import imp # the following 3 constants are updated on each new release (do not touch) -HEXVERSION=0x2001500 +HEXVERSION=0x2001600 """Constant updated on new releases""" -WAFVERSION="2.0.21" +WAFVERSION="2.0.22" """Constant updated on new releases""" -WAFREVISION="edde20a6425a5c3eb6b47d5f3f5c4fbc93fed5f4" +WAFREVISION="816d5bc48ba2abc4ac22f2b44d94d322bf992b9c" """Git revision when the waf version is updated""" WAFNAME="waf" diff --git a/wscript b/wscript index 3c54df354b..0cbd14d860 100644 --- a/wscript +++ b/wscript @@ -11,7 +11,7 @@ To add a tool that does not exist in the folder compat15, pass an absolute path: from __future__ import with_statement -VERSION="2.0.21" +VERSION="2.0.22" APPNAME='waf' REVISION='' From 150796109fcde427a79cc40b2c5789c720f1593e Mon Sep 17 00:00:00 2001 From: Erik Parker Date: Fri, 12 Mar 2021 10:26:06 -0600 Subject: [PATCH 284/315] msvs: Update project sorting in visual studio solution file In order to correctly set a default project in visual studio any folders must be listed at the top of the solution file. This change ensures that any folders included in generated solutions sort to the top of the .sln file. The default project, if one exists, will be located after the folders. Note that it should also be correct to place the default at the top of the file, followed by any folders. --- waflib/extras/msvs.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/waflib/extras/msvs.py b/waflib/extras/msvs.py index 8aa2db0b75..03b739f849 100644 --- a/waflib/extras/msvs.py +++ b/waflib/extras/msvs.py @@ -787,8 +787,12 @@ def collect_projects(self): self.collect_dirs() default_project = getattr(self, 'default_project', None) def sortfun(x): - if x.name == default_project: + # folders should sort to the top + if getattr(x, 'VS_GUID_SOLUTIONFOLDER', None): return '' + # followed by the default project + elif x.name == default_project: + return ' ' return getattr(x, 'path', None) and x.path.win32path() or x.name self.all_projects.sort(key=sortfun) From fc825bd1fb5669624d508b7a84f37bedf3242196 Mon Sep 17 00:00:00 2001 From: Erik Parker Date: Mon, 5 Apr 2021 20:01:38 +0000 Subject: [PATCH 285/315] winres: Pass include paths by environment variable --- waflib/Tools/winres.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/waflib/Tools/winres.py b/waflib/Tools/winres.py index 9be1ed6600..73c0e95315 100644 --- a/waflib/Tools/winres.py +++ b/waflib/Tools/winres.py @@ -4,10 +4,12 @@ "Process *.rc* files for C/C++: X{.rc -> [.res|.rc.o]}" +import os import re from waflib import Task from waflib.TaskGen import extension from waflib.Tools import c_preproc +from waflib import Utils @extension('.rc') def rc_file(self, node): @@ -61,6 +63,39 @@ def scan(self): tmp.start(self.inputs[0], self.env) return (tmp.nodes, tmp.names) + def exec_command(self, cmd, **kw): + if self.env.WINRC_TGT_F == '/fo': + # Since winres include paths may contain spaces, they do not fit in + # response files and are best passed as environment variables + replace_cmd = [] + incpaths = [] + while cmd: + # filter include path flags + flag = cmd.pop(0) + if flag.upper().startswith('/I'): + if len(flag) == 2: + incpaths.append(cmd.pop(0)) + else: + incpaths.append(flag[2:]) + else: + replace_cmd.append(flag) + cmd = replace_cmd + if incpaths: + # append to existing environment variables in INCLUDE + env = kw['env'] = dict(kw.get('env') or self.env.env or os.environ) + pre_includes = env.get('INCLUDE', '') + env['INCLUDE'] = pre_includes + os.pathsep + os.pathsep.join(incpaths) + + return super(winrc, self).exec_command(cmd, **kw) + + def quote_flag(self, flag): + if self.env.WINRC_TGT_F == '/fo': + # winres does not support quotes around flags in response files + return flag + + return super(winrc, self).quote_flag(flag) + + def configure(conf): """ Detects the programs RC or windres, depending on the C/C++ compiler in use From 21ad2af0a5b25995a11d78f15536620c0673b90f Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Thu, 15 Apr 2021 12:37:06 +0000 Subject: [PATCH 286/315] c_config: add RISC-V generic detection --- waflib/Tools/c_config.py | 1 + 1 file changed, 1 insertion(+) diff --git a/waflib/Tools/c_config.py b/waflib/Tools/c_config.py index f8f664f82c..b1025f3711 100644 --- a/waflib/Tools/c_config.py +++ b/waflib/Tools/c_config.py @@ -69,6 +69,7 @@ '__sh__' : 'sh', '__xtensa__' : 'xtensa', '__e2k__' : 'e2k', +'__riscv' : 'riscv', } @conf From 4fe69fe8be27d7de944a88e4b559d07faf16ae8b Mon Sep 17 00:00:00 2001 From: Michael Vincent Date: Mon, 12 Apr 2021 16:06:54 -0500 Subject: [PATCH 287/315] msvcdeps: Faster case correction Visual Studio returns paths to dependencies with incorrect case. ant_glob() is very slow for this use case (40~50% impact to overall build time). This patch uses os.listdir() to find the correct case of each path component. --- waflib/extras/msvcdeps.py | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/waflib/extras/msvcdeps.py b/waflib/extras/msvcdeps.py index 52985dce05..a38812419c 100644 --- a/waflib/extras/msvcdeps.py +++ b/waflib/extras/msvcdeps.py @@ -50,23 +50,42 @@ def apply_msvcdeps_flags(taskgen): if taskgen.env.get_flat(flag).find(PREPROCESSOR_FLAG) < 0: taskgen.env.append_value(flag, PREPROCESSOR_FLAG) + +def get_correct_path_case(base_path, path): + ''' + Return a case-corrected version of ``path`` by searching the filesystem for + ``path``, relative to ``base_path``, using the case returned by the filesystem. + ''' + components = Utils.split_path(path) + + corrected_path = '' + if os.path.isabs(path): + corrected_path = components.pop(0).upper() + os.sep + + for part in components: + part = part.lower() + search_path = os.path.join(base_path, corrected_path) + for item in os.listdir(search_path): + if item.lower() == part: + corrected_path = os.path.join(corrected_path, item) + break + else: + raise ValueError("Can't find %r in %r" % (part, search_path)) + + return corrected_path + + def path_to_node(base_node, path, cached_nodes): ''' Take the base node and the path and return a node Results are cached because searching the node tree is expensive The following code is executed by threads, it is not safe, so a lock is needed... ''' - # normalize the path because ant_glob() does not understand - # parent path components (..) + # normalize the path to remove parent path components (..) path = os.path.normpath(path) # normalize the path case to increase likelihood of a cache hit - path = os.path.normcase(path) - - # ant_glob interprets [] and () characters, so those must be replaced - path = path.replace('[', '?').replace(']', '?').replace('(', '[(]').replace(')', '[)]') - - node_lookup_key = (base_node, path) + node_lookup_key = (base_node, os.path.normcase(path)) try: node = cached_nodes[node_lookup_key] @@ -76,8 +95,8 @@ def path_to_node(base_node, path, cached_nodes): try: node = cached_nodes[node_lookup_key] except KeyError: - node_list = base_node.ant_glob([path], ignorecase=True, remove=False, quiet=True, regex=False) - node = cached_nodes[node_lookup_key] = node_list[0] if node_list else None + path = get_correct_path_case(base_node.abspath(), path) + node = cached_nodes[node_lookup_key] = base_node.find_node(path) return node From 96ac7b39a0a04cba64a2362dda8811409ae22781 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Thu, 22 Apr 2021 02:19:25 +0200 Subject: [PATCH 288/315] Let msvcsdeps process relative paths and in a deterministic manner --- waflib/extras/msvcdeps.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/waflib/extras/msvcdeps.py b/waflib/extras/msvcdeps.py index a38812419c..2ca5299102 100644 --- a/waflib/extras/msvcdeps.py +++ b/waflib/extras/msvcdeps.py @@ -65,7 +65,12 @@ def get_correct_path_case(base_path, path): for part in components: part = part.lower() search_path = os.path.join(base_path, corrected_path) - for item in os.listdir(search_path): + if part == '..': + corrected_path = os.path.join(corrected_path, part) + search_path = os.path.normpath(search_path) + continue + + for item in sorted(os.listdir(search_path)): if item.lower() == part: corrected_path = os.path.join(corrected_path, item) break From e5c2a054c11ed7b58a5ec5a928b6d4e1bf2c1fa9 Mon Sep 17 00:00:00 2001 From: Michael Vincent Date: Fri, 9 Apr 2021 11:52:35 -0500 Subject: [PATCH 289/315] msvcdeps: Remove unused variable --- waflib/extras/msvcdeps.py | 1 - 1 file changed, 1 deletion(-) diff --git a/waflib/extras/msvcdeps.py b/waflib/extras/msvcdeps.py index 2ca5299102..ac323ed4fa 100644 --- a/waflib/extras/msvcdeps.py +++ b/waflib/extras/msvcdeps.py @@ -32,7 +32,6 @@ def configure(conf): from waflib.TaskGen import feature, before_method lock = threading.Lock() -nodes = {} # Cache the path -> Node lookup PREPROCESSOR_FLAG = '/showIncludes' INCLUDE_PATTERN = 'Note: including file:' From c64d4b908b854ee72fd9d16deeff973ca6c1f0b7 Mon Sep 17 00:00:00 2001 From: Michael Vincent Date: Fri, 9 Apr 2021 14:37:38 -0500 Subject: [PATCH 290/315] msvcdeps: Align with gccdeps Just a few small changes to make msvcdeps.py align with gccdeps.py better. --- waflib/extras/msvcdeps.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/waflib/extras/msvcdeps.py b/waflib/extras/msvcdeps.py index ac323ed4fa..e8985bde7c 100644 --- a/waflib/extras/msvcdeps.py +++ b/waflib/extras/msvcdeps.py @@ -112,9 +112,9 @@ def post_run(self): if getattr(self, 'cached', None): return Task.Task.post_run(self) - bld = self.generator.bld - unresolved_names = [] resolved_nodes = [] + unresolved_names = [] + bld = self.generator.bld # Dynamically bind to the cache try: @@ -147,11 +147,14 @@ def post_run(self): continue if id(node) == id(self.inputs[0]): - # Self-dependency + # ignore the source file, it is already in the dependencies + # this way, successful config tests may be retrieved from the cache continue resolved_nodes.append(node) + Logs.debug('deps: msvcdeps for %s returned %s', self, resolved_nodes) + bld.node_deps[self.uid()] = resolved_nodes bld.raw_deps[self.uid()] = unresolved_names From c46a9314f426ddab887378532d76b95e1b19bc0c Mon Sep 17 00:00:00 2001 From: Michael Vincent Date: Fri, 9 Apr 2021 13:46:09 -0500 Subject: [PATCH 291/315] gccdeps: Rename some variables Rename some local variables to clarify their purpose and to align with msvcdeps.py. --- waflib/extras/gccdeps.py | 58 +++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/waflib/extras/gccdeps.py b/waflib/extras/gccdeps.py index 0ecaad5d13..803ecade11 100644 --- a/waflib/extras/gccdeps.py +++ b/waflib/extras/gccdeps.py @@ -32,9 +32,10 @@ def configure(conf): def scan(self): if not self.__class__.__name__ in self.env.ENABLE_GCCDEPS: return super(self.derived_gccdeps, self).scan() - nodes = self.generator.bld.node_deps.get(self.uid(), []) - names = [] - return (nodes, names) + + resolved_nodes = self.generator.bld.node_deps.get(self.uid(), []) + unresolved_names = [] + return (resolved_nodes, unresolved_names) re_o = re.compile(r"\.o$") re_splitter = re.compile(r'(? Date: Fri, 9 Apr 2021 14:29:53 -0500 Subject: [PATCH 292/315] gccdeps: Move scan() method Move the scan() method down in the file to match msvcdeps' method ordering. This makes it easier to compare gccdeps.py and msvcdeps.py to keep them in sync. --- waflib/extras/gccdeps.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/waflib/extras/gccdeps.py b/waflib/extras/gccdeps.py index 803ecade11..6f078f29dd 100644 --- a/waflib/extras/gccdeps.py +++ b/waflib/extras/gccdeps.py @@ -29,14 +29,6 @@ def configure(conf): # Third-party tools are allowed to add extra names in here with append() supported_compilers = ['gas', 'gcc', 'icc', 'clang'] -def scan(self): - if not self.__class__.__name__ in self.env.ENABLE_GCCDEPS: - return super(self.derived_gccdeps, self).scan() - - resolved_nodes = self.generator.bld.node_deps.get(self.uid(), []) - unresolved_names = [] - return (resolved_nodes, unresolved_names) - re_o = re.compile(r"\.o$") re_splitter = re.compile(r'(? Date: Fri, 9 Apr 2021 13:53:20 -0500 Subject: [PATCH 293/315] gccdeps: Refactor cache lock Rework how gccdeps' cached_nodes lock is used so acquiring the lock is only necessary on a cache miss. Also use a "with" context manager to simplify management of the lock lifecycle. Ported from 8b5a2a2086dd67070ff26b6c65019bcbbea18836 --- waflib/extras/gccdeps.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/waflib/extras/gccdeps.py b/waflib/extras/gccdeps.py index 6f078f29dd..41e05e6932 100644 --- a/waflib/extras/gccdeps.py +++ b/waflib/extras/gccdeps.py @@ -54,14 +54,17 @@ def path_to_node(base_node, path, cached_nodes): else: # Not hashable, assume it is a list and join into a string node_lookup_key = (base_node, os.path.sep.join(path)) + try: - lock.acquire() node = cached_nodes[node_lookup_key] except KeyError: - node = base_node.find_resource(path) - cached_nodes[node_lookup_key] = node - finally: - lock.release() + # retry with lock on cache miss + with lock: + try: + node = cached_nodes[node_lookup_key] + except KeyError: + node = cached_nodes[node_lookup_key] = base_node.find_resource(path) + return node def post_run(self): From 6db64121b6b97979f280b4897ae569d0bab023d4 Mon Sep 17 00:00:00 2001 From: Federico Pellegrin Date: Thu, 29 Apr 2021 04:33:07 +0200 Subject: [PATCH 294/315] swig: skip CR (\r) if present in module name Handles presence of \r in module name (ie. DOS mode swig .i files) Should fix #2350 --- waflib/extras/swig.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/extras/swig.py b/waflib/extras/swig.py index 740ab46d96..967caeb5a8 100644 --- a/waflib/extras/swig.py +++ b/waflib/extras/swig.py @@ -17,7 +17,7 @@ SWIG_EXTS = ['.swig', '.i'] -re_module = re.compile(r'%module(?:\s*\(.*\))?\s+(.+)', re.M) +re_module = re.compile(r'%module(?:\s*\(.*\))?\s+([^\r\n]+)', re.M) re_1 = re.compile(r'^%module.*?\s+([\w]+)\s*?$', re.M) re_2 = re.compile(r'[#%](?:include|import(?:\(module=".*"\))+|python(?:begin|code)) [<"](.*)[">]', re.M) From c2b87ea226588647ed6d43542177568b7bce7c93 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Fri, 30 Apr 2021 18:38:01 +0200 Subject: [PATCH 295/315] On windows, try $INCLUDEPY/../libs to detect the Python library path --- waflib/Tools/python.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/waflib/Tools/python.py b/waflib/Tools/python.py index 07442561df..fb641e5e20 100644 --- a/waflib/Tools/python.py +++ b/waflib/Tools/python.py @@ -416,9 +416,14 @@ def check_python_headers(conf, features='pyembed pyext'): if not result: path = [os.path.join(dct['prefix'], "libs")] - conf.to_log("\n\n# try again with -L$prefix/libs, and pythonXY name rather than pythonX.Y (win32)\n") + conf.to_log("\n\n# try again with -L$prefix/libs, and pythonXY rather than pythonX.Y (win32)\n") result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in $prefix/libs' % name) + if not result: + path = [os.path.normpath(os.path.join(dct['INCLUDEPY'], '..', 'libs'))] + conf.to_log("\n\n# try again with -L$INCLUDEPY/../libs, and pythonXY rather than pythonX.Y (win32)\n") + result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in $INCLUDEPY/../libs' % name) + if result: break # do not forget to set LIBPATH_PYEMBED From f9e55907239c0730e40cfa24bc56d1071cef408e Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Wed, 5 May 2021 00:26:31 +0200 Subject: [PATCH 296/315] Disable OpenIndiana from the pipelines --- .pipelines/Jenkinsfile | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/.pipelines/Jenkinsfile b/.pipelines/Jenkinsfile index c41dd29cb1..fadc4995b5 100644 --- a/.pipelines/Jenkinsfile +++ b/.pipelines/Jenkinsfile @@ -261,28 +261,6 @@ cd tests/install_group/ } } } - stage('OpenIndiana') { - stages { - stage('py27') { - agent { - label "openindiana" - } - steps { - dir('demos') { - unstash 'waf' - } - sh '''export CFLAGS='-std=c99 -D_STDC_C99' ''' - sh '''cd demos; ./waf configure clean build --top=c''' - sh '''cd demos; ./waf configure clean build --top=c++''' - sh '''cd demos; ./waf configure clean build --top=dbus''' - sh '''cd demos; ./waf configure clean build --top=java''' - sh '''cd demos; ./waf configure clean build --top=perl''' - sh '''cd demos; ./waf configure clean build --top=python''' - sh '''cd demos; ./waf configure clean build --top=ruby''' - } - } - } - } stage('FreeBSD') { stages { stage('py36') { From 04a4a31f011ec46dfd3ded151eefa3f658539c8d Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Thu, 13 May 2021 17:10:55 +0200 Subject: [PATCH 297/315] Handle deprecated Thread.setDaemon in Python 3.10 --- waflib/Runner.py | 4 ++-- waflib/fixpy2.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/waflib/Runner.py b/waflib/Runner.py index 91d55479e2..350c86a22c 100644 --- a/waflib/Runner.py +++ b/waflib/Runner.py @@ -71,7 +71,7 @@ def __init__(self, spawner, task): """Task to execute""" self.spawner = spawner """Coordinator object""" - self.setDaemon(1) + self.daemon = True self.start() def run(self): """ @@ -98,7 +98,7 @@ def __init__(self, master): """:py:class:`waflib.Runner.Parallel` producer instance""" self.sem = Utils.threading.Semaphore(master.numjobs) """Bounded semaphore that prevents spawning more than *n* concurrent consumers""" - self.setDaemon(1) + self.daemon = True self.start() def run(self): """ diff --git a/waflib/fixpy2.py b/waflib/fixpy2.py index 24176e0664..c99bff4b9a 100644 --- a/waflib/fixpy2.py +++ b/waflib/fixpy2.py @@ -56,7 +56,7 @@ def r1(code): @subst('Runner.py') def r4(code): "generator syntax" - return code.replace('next(self.biter)', 'self.biter.next()') + return code.replace('next(self.biter)', 'self.biter.next()').replace('self.daemon = True', 'self.setDaemon(1)') @subst('Context.py') def r5(code): From 958c73a5ec828bb6aaf0b2585fba1aca9c96fd8c Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sat, 12 Jun 2021 08:12:33 +0200 Subject: [PATCH 298/315] Improve error messages from scanner errors #2356 --- waflib/TaskGen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/TaskGen.py b/waflib/TaskGen.py index f8f92bd57c..2fa462899b 100644 --- a/waflib/TaskGen.py +++ b/waflib/TaskGen.py @@ -635,7 +635,7 @@ def scan(self): for x in self.generator.to_list(getattr(self.generator, 'deps', None)): node = self.generator.path.find_resource(x) if not node: - self.generator.bld.fatal('Could not find %r (was it declared?)' % x) + self.generator.bld.fatal('Could not find %r in %r (was it declared?)' % (x, self.generator)) nodes.append(node) return [nodes, []] cls.scan = scan From fbba31193be68d9d01a3a1a77e7d22aa33708104 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Wed, 16 Jun 2021 22:12:57 +0200 Subject: [PATCH 299/315] Process dependency Nodes in bld(rule=..., deps=[..]) --- waflib/TaskGen.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/waflib/TaskGen.py b/waflib/TaskGen.py index 2fa462899b..89f6316991 100644 --- a/waflib/TaskGen.py +++ b/waflib/TaskGen.py @@ -631,12 +631,8 @@ def chmod_fun(tsk): cls.scan = self.scan elif has_deps: def scan(self): - nodes = [] - for x in self.generator.to_list(getattr(self.generator, 'deps', None)): - node = self.generator.path.find_resource(x) - if not node: - self.generator.bld.fatal('Could not find %r in %r (was it declared?)' % (x, self.generator)) - nodes.append(node) + deps = getattr(self.generator, 'deps', None) + nodes = self.generator.to_nodes(deps) return [nodes, []] cls.scan = scan From bb5bb1896589c07abeb85cf2abb43315caf5174c Mon Sep 17 00:00:00 2001 From: Erik Parker Date: Mon, 21 Jun 2021 13:45:26 -0500 Subject: [PATCH 300/315] color_gcc: Check that cmd has elements in it before processing it. --- waflib/extras/color_gcc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/extras/color_gcc.py b/waflib/extras/color_gcc.py index b68c5ebf2d..09729035fe 100644 --- a/waflib/extras/color_gcc.py +++ b/waflib/extras/color_gcc.py @@ -19,7 +19,7 @@ def format(self, rec): func = frame.f_code.co_name if func == 'exec_command': cmd = frame.f_locals.get('cmd') - if isinstance(cmd, list) and ('gcc' in cmd[0] or 'g++' in cmd[0]): + if isinstance(cmd, list) and (len(cmd) > 0) and ('gcc' in cmd[0] or 'g++' in cmd[0]): lines = [] for line in rec.msg.splitlines(): if 'warning: ' in line: From c40ee481cf1d1432691941b118ebf501fb886b2d Mon Sep 17 00:00:00 2001 From: Federico Giovanardi Date: Thu, 15 Jul 2021 10:57:23 +0200 Subject: [PATCH 301/315] Make clang_compilation_database compatible with variants In the current implementation if a project is using build variants it's not possible to use the clang_compilation_database plugin because it strips the variant information from the build object. --- waflib/extras/clang_compilation_database.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/extras/clang_compilation_database.py b/waflib/extras/clang_compilation_database.py index 17f6694937..bd29db93fd 100644 --- a/waflib/extras/clang_compilation_database.py +++ b/waflib/extras/clang_compilation_database.py @@ -126,7 +126,7 @@ def new_execute_build(self): Invoke clangdb command before build """ if self.cmd.startswith('build'): - Scripting.run_command('clangdb') + Scripting.run_command(self.cmd.replace('build','clangdb')) old_execute_build(self) From 51555ad682d3a7d604b31c6dbf7665ee160f1bdc Mon Sep 17 00:00:00 2001 From: Federico Pellegrin Date: Tue, 31 Aug 2021 10:40:10 +0200 Subject: [PATCH 302/315] eclipse: add generation of editor language settings Add automatic generation of editor language settings for C and C++, so the automatic code correction uses the correct compiler and compiler flags, including for example the correct C/C++ standard so construct from such standards are correctly managed by the IDE. Correct compiler and flags are automatically generated using the build environment data gathered during configure phase. The playground example has been modified to contain some code that is standard specific to demonstrate the new feature when run under Eclipse. --- playground/eclipse/c/exLibC/src/exLibC.cpp | 4 ++ playground/eclipse/c/wscript | 11 ++-- waflib/extras/eclipse.py | 63 ++++++++++++++++++++++ 3 files changed, 74 insertions(+), 4 deletions(-) diff --git a/playground/eclipse/c/exLibC/src/exLibC.cpp b/playground/eclipse/c/exLibC/src/exLibC.cpp index b8720ebeab..79877a3ddc 100644 --- a/playground/eclipse/c/exLibC/src/exLibC.cpp +++ b/playground/eclipse/c/exLibC/src/exLibC.cpp @@ -1,9 +1,13 @@ #include #include +#include #include int check_smaller(int value) { + const char* foo = u8"bar"; // u8 is C++17 only + std::cout << __cplusplus << std::endl; // Check version of C++ standard + if (value < HELLO_LIMIT) { return 0; } else { diff --git a/playground/eclipse/c/wscript b/playground/eclipse/c/wscript index dbdce20b51..7093bcd87e 100644 --- a/playground/eclipse/c/wscript +++ b/playground/eclipse/c/wscript @@ -2,12 +2,15 @@ # encoding: utf-8 def options(opt): - # We are using C++ - opt.load('compiler_cxx') + # We are using C and C++ + opt.load('compiler_c compiler_cxx') def configure(conf): - # We are using C++ - conf.load('compiler_cxx') + # We are using C and C++ + conf.load('compiler_c compiler_cxx') + # Force some standards to see that IDE will follow them + conf.env.CXXFLAGS=['-std=c++17'] + conf.env.CFLAGS=['-std=c17'] def build(bld): bld.shlib(source='exLibC/src/exLibC.cpp', includes='exLibC/src/include', target='exampleLibC', export_includes='exLibC/src/include/') diff --git a/waflib/extras/eclipse.py b/waflib/extras/eclipse.py index bb787416e9..e123fc1644 100644 --- a/waflib/extras/eclipse.py +++ b/waflib/extras/eclipse.py @@ -25,6 +25,8 @@ def options(opt): cdt_bld = oe_cdt + '.build.core' extbuilder_dir = '.externalToolBuilders' extbuilder_name = 'Waf_Builder.launch' +settings_dir = '.settings' +settings_name = 'language.settings.xml' class eclipse(Build.BuildContext): cmd = 'eclipse' @@ -156,6 +158,61 @@ def create_cproject(self, appname, workspace_includes=[], pythonpath=[]): project = self.impl_create_javaproject(javasrcpath, javalibpath) self.write_conf_to_xml('.classpath', project) + # Create editor language settings to have correct standards applied in IDE, as per project configuration + try: + os.mkdir(settings_dir) + except OSError: + pass # Ignore if dir already exists + + lang_settings = Document() + project = lang_settings.createElement('project') + + # Language configurations for C and C++ via cdt + if hasc: + configuration = self.add(lang_settings, project, 'configuration', + {'id' : 'org.eclipse.cdt.core.default.config.1', 'name': 'Default'}) + + extension = self.add(lang_settings, configuration, 'extension', {'point': 'org.eclipse.cdt.core.LanguageSettingsProvider'}) + + provider = self.add(lang_settings, extension, 'provider', + { 'copy-of': 'extension', + 'id': 'org.eclipse.cdt.ui.UserLanguageSettingsProvider'}) + + provider = self.add(lang_settings, extension, 'provider-reference', + { 'id': 'org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider', + 'ref': 'shared-provider'}) + + provider = self.add(lang_settings, extension, 'provider-reference', + { 'id': 'org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider', + 'ref': 'shared-provider'}) + + # C and C++ are kept as separated providers so appropriate flags are used also in mixed projects + if self.env.CC: + provider = self.add(lang_settings, extension, 'provider', + { 'class': 'org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector', + 'console': 'false', + 'id': 'org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector.1', + 'keep-relative-paths' : 'false', + 'name': 'CDT GCC Built-in Compiler Settings', + 'parameter': '%s %s ${FLAGS} -E -P -v -dD "${INPUTS}"'%(self.env.CC[0],' '.join(self.env['CFLAGS'])), + 'prefer-non-shared': 'true' }) + + self.add(lang_settings, provider, 'language-scope', { 'id': 'org.eclipse.cdt.core.gcc'}) + + if self.env.CXX: + provider = self.add(lang_settings, extension, 'provider', + { 'class': 'org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector', + 'console': 'false', + 'id': 'org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector.2', + 'keep-relative-paths' : 'false', + 'name': 'CDT GCC Built-in Compiler Settings', + 'parameter': '%s %s ${FLAGS} -E -P -v -dD "${INPUTS}"'%(self.env.CXX[0],' '.join(self.env['CXXFLAGS'])), + 'prefer-non-shared': 'true' }) + self.add(lang_settings, provider, 'language-scope', { 'id': 'org.eclipse.cdt.core.g++'}) + + lang_settings.appendChild(project) + self.write_conf_to_xml('%s%s%s'%(settings_dir, os.path.sep, settings_name), lang_settings) + def impl_create_project(self, executable, appname, hasc, hasjava, haspython, waf_executable): doc = Document() projectDescription = doc.createElement('projectDescription') @@ -348,6 +405,12 @@ def addTargetWrap(name, runAll): self.add(doc, storageModule, 'project', {'id': '%s.null.1'%appname, 'name': appname}) + storageModule = self.add(doc, cproject, 'storageModule', + {'moduleId': 'org.eclipse.cdt.core.LanguageSettingsProviders'}) + + storageModule = self.add(doc, cproject, 'storageModule', + {'moduleId': 'scannerConfiguration'}) + doc.appendChild(cproject) return doc From 0b28275084ab3cc6b2301ce4110f2947707993fc Mon Sep 17 00:00:00 2001 From: Federico Pellegrin Date: Fri, 3 Sep 2021 10:18:24 +0200 Subject: [PATCH 303/315] eclipse: remove repeated entries in include paths for C/C++ Make sure just unique include paths (both system and local) are added to prevent overcrowding with useless redundant include paths that grow up a lot the generated XML file and make the usage of the GUI messy. The filter was already there for Java/Python. --- waflib/extras/eclipse.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/waflib/extras/eclipse.py b/waflib/extras/eclipse.py index e123fc1644..ef057e8a34 100644 --- a/waflib/extras/eclipse.py +++ b/waflib/extras/eclipse.py @@ -133,9 +133,11 @@ def create_cproject(self, appname, workspace_includes=[], pythonpath=[]): path = p.path_from(self.srcnode) if (path.startswith("/")): - cpppath.append(path) + if path not in cpppath: + cpppath.append(path) else: - workspace_includes.append(path) + if path not in workspace_includes: + workspace_includes.append(path) if is_cc and path not in source_dirs: source_dirs.append(path) From 4b0499b1cb91f82959e67c995e925e3f3ca65c05 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Wed, 22 Sep 2021 19:52:15 +0200 Subject: [PATCH 304/315] Provide the classic runner system from waf 1.x as an extension --- waflib/extras/classic_runner.py | 68 +++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 waflib/extras/classic_runner.py diff --git a/waflib/extras/classic_runner.py b/waflib/extras/classic_runner.py new file mode 100644 index 0000000000..b08c794e88 --- /dev/null +++ b/waflib/extras/classic_runner.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python +# encoding: utf-8 +# Thomas Nagy, 2021 (ita) + +from waflib import Utils, Runner + +""" +Re-enable the classic threading system from waf 1.x + +def configure(conf): + conf.load('classic_runner') +""" + +class TaskConsumer(Utils.threading.Thread): + """ + Task consumers belong to a pool of workers + + They wait for tasks in the queue and then use ``task.process(...)`` + """ + def __init__(self, spawner): + Utils.threading.Thread.__init__(self) + """ + Obtain :py:class:`waflib.Task.TaskBase` instances from this queue. + """ + self.spawner = spawner + self.daemon = True + self.start() + + def run(self): + """ + Loop over the tasks to execute + """ + try: + self.loop() + except Exception: + pass + + def loop(self): + """ + Obtain tasks from :py:attr:`waflib.Runner.TaskConsumer.ready` and call + :py:meth:`waflib.Task.TaskBase.process`. If the object is a function, execute it. + """ + master = self.spawner.master + while 1: + if not master.stop: + try: + tsk = master.ready.get() + if tsk: + tsk.log_display(tsk.generator.bld) + master.process_task(tsk) + else: + break + finally: + master.out.put(tsk) + +class Spawner(object): + """ + Daemon thread that consumes tasks from :py:class:`waflib.Runner.Parallel` producer and + spawns a consuming thread :py:class:`waflib.Runner.Consumer` for each + :py:class:`waflib.Task.Task` instance. + """ + def __init__(self, master): + self.master = master + """:py:class:`waflib.Runner.Parallel` producer instance""" + + self.pool = [TaskConsumer(self) for i in range(master.numjobs)] + +Runner.Spawner = Spawner From 019f072b17516286cbcfb2aa6135758b708a5e3b Mon Sep 17 00:00:00 2001 From: Federico Pellegrin Date: Wed, 24 Nov 2021 13:19:50 +0100 Subject: [PATCH 305/315] wafcache: support stats also for multiple build commands --- waflib/extras/wafcache.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/waflib/extras/wafcache.py b/waflib/extras/wafcache.py index cc23fcd667..2cef46c0e1 100644 --- a/waflib/extras/wafcache.py +++ b/waflib/extras/wafcache.py @@ -258,6 +258,19 @@ def build(bld): """ Called during the build process to enable file caching """ + if WAFCACHE_STATS: + # Init counter for statistics and hook to print results at the end + bld.cache_reqs = bld.cache_hits = bld.cache_puts = 0 + + def printstats(bld): + hit_ratio = 0 + if bld.cache_reqs > 0: + hit_ratio = (bld.cache_hits / bld.cache_reqs) * 100 + Logs.pprint('CYAN', ' wafcache stats: requests: %s, hits, %s, ratio: %.2f%%, writes %s' % + (bld.cache_reqs, bld.cache_hits, hit_ratio, bld.cache_puts) ) + + bld.add_post_fun(printstats) + if process_pool: # already called once return @@ -273,19 +286,6 @@ def build(bld): for x in reversed(list(Task.classes.values())): make_cached(x) - if WAFCACHE_STATS: - # Init counter for statistics and hook to print results at the end - bld.cache_reqs = bld.cache_hits = bld.cache_puts = 0 - - def printstats(bld): - hit_ratio = 0 - if bld.cache_reqs > 0: - hit_ratio = (bld.cache_hits / bld.cache_reqs) * 100 - Logs.pprint('CYAN', ' wafcache stats: requests: %s, hits, %s, ratio: %.2f%%, writes %s' % - (bld.cache_reqs, bld.cache_hits, hit_ratio, bld.cache_puts) ) - - bld.add_post_fun(printstats) - def cache_command(sig, files_from, files_to): """ Create a command for cache worker processes, returns a pickled From 5eb2b2e448f79cdebd32e9482ac54b026d2e29d7 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Sat, 4 Dec 2021 09:38:20 +0100 Subject: [PATCH 306/315] Update the CI pipelines --- .pipelines/Jenkinsfile | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/.pipelines/Jenkinsfile b/.pipelines/Jenkinsfile index fadc4995b5..33d30e12c8 100644 --- a/.pipelines/Jenkinsfile +++ b/.pipelines/Jenkinsfile @@ -162,24 +162,7 @@ cd tests/install_group/ ''' } } - stage('py27') { - agent { - label "openbsd" - } - steps { - dir('demos') { - unstash 'waf' - } - sh '''cd demos/asm; /usr/local/bin/python2.7 ../waf configure clean build''' - sh '''cd demos/c; /usr/local/bin/python2.7 ../waf configure clean build''' - sh '''cd demos/c++; /usr/local/bin/python2.7 ../waf configure clean build''' - sh '''cd demos/glib2; /usr/local/bin/python2.7 ../waf configure clean build''' - sh '''cd demos/perl; /usr/local/bin/python2.7 ../waf configure clean build''' - sh '''cd demos/python; /usr/local/bin/python2.7 ../waf configure clean build''' - sh '''cd demos/subst; /usr/local/bin/python2.7 ../waf configure clean build''' - } - } - stage('py36') { + stage('py38') { agent { label "openbsd" } From e051e13304580e90cd3e1fe3be668a85c8df17f1 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Wed, 8 Dec 2021 02:16:52 +0100 Subject: [PATCH 307/315] Detect Qt3D* libraries #2368 --- waflib/Tools/qt5.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/Tools/qt5.py b/waflib/Tools/qt5.py index 82c83e18c8..6b3c887b36 100644 --- a/waflib/Tools/qt5.py +++ b/waflib/Tools/qt5.py @@ -783,7 +783,7 @@ def set_qt5_libs_to_check(self): pat = self.env.cxxstlib_PATTERN if Utils.unversioned_sys_platform() == 'darwin': pat = r"%s\.framework" - re_qt = re.compile(pat % 'Qt5?(?P\\D+)' + '$') + re_qt = re.compile(pat % 'Qt5?(?P\\w+)' + '$') for x in dirlst: m = re_qt.match(x) if m: From 61156b4fa2bd0cf24025eebaefd9be5be02a5515 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Wed, 8 Dec 2021 02:18:15 +0100 Subject: [PATCH 308/315] Detect qt5 libraries in alphabetical order --- waflib/Tools/qt5.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/Tools/qt5.py b/waflib/Tools/qt5.py index 6b3c887b36..b3e61325e5 100644 --- a/waflib/Tools/qt5.py +++ b/waflib/Tools/qt5.py @@ -784,7 +784,7 @@ def set_qt5_libs_to_check(self): if Utils.unversioned_sys_platform() == 'darwin': pat = r"%s\.framework" re_qt = re.compile(pat % 'Qt5?(?P\\w+)' + '$') - for x in dirlst: + for x in sorted(dirlst): m = re_qt.match(x) if m: self.qt5_vars.append("Qt5%s" % m.group('name')) From 5924c8593198133460002ce20f80e285b76aa1a8 Mon Sep 17 00:00:00 2001 From: Federico Pellegrin Date: Thu, 9 Dec 2021 09:11:39 +0100 Subject: [PATCH 309/315] eclipse: add possibility to add custom targets execution Make it easy to add custom target executions in the automatic eclipse configuration generation, for example to call other standard waf targets from other tools or with specific options. --- playground/eclipse/wscript | 1 + waflib/extras/eclipse.py | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/playground/eclipse/wscript b/playground/eclipse/wscript index 7d53ab79e3..f7601a5ab2 100644 --- a/playground/eclipse/wscript +++ b/playground/eclipse/wscript @@ -54,6 +54,7 @@ def options(opt): def configure(conf): + conf.env.ECLIPSE_EXTRA_TARGETS = ['test', 'lint', 'foo --bar'] conf.load('eclipse') # We recurse configurations in our submodules conf.recurse(module_list) diff --git a/waflib/extras/eclipse.py b/waflib/extras/eclipse.py index ef057e8a34..8e61007f24 100644 --- a/waflib/extras/eclipse.py +++ b/waflib/extras/eclipse.py @@ -10,6 +10,9 @@ def options(opt): opt.load('eclipse') +To add additional targets beside standard ones (configure, dist, install, check) +the environment ECLIPSE_EXTRA_TARGETS can be set (ie. to ['test', 'lint', 'docs']) + $ waf configure eclipse """ @@ -400,6 +403,8 @@ def addTargetWrap(name, runAll): addTargetWrap('dist', False) addTargetWrap('install', False) addTargetWrap('check', False) + for addTgt in getattr(self.env, 'ECLIPSE_EXTRA_TARGETS', []): + addTargetWrap(addTgt, False) storageModule = self.add(doc, cproject, 'storageModule', {'moduleId': 'cdtBuildSystem', From a17dc11c1c0470f7ccf73168b2838fb4ad664b43 Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Thu, 9 Dec 2021 15:46:12 +0100 Subject: [PATCH 310/315] Avoid errors in case ECLIPSE_EXTRA_TARGETS is is set to None --- waflib/extras/eclipse.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/waflib/extras/eclipse.py b/waflib/extras/eclipse.py index 8e61007f24..49ca9686b7 100644 --- a/waflib/extras/eclipse.py +++ b/waflib/extras/eclipse.py @@ -403,7 +403,7 @@ def addTargetWrap(name, runAll): addTargetWrap('dist', False) addTargetWrap('install', False) addTargetWrap('check', False) - for addTgt in getattr(self.env, 'ECLIPSE_EXTRA_TARGETS', []): + for addTgt in self.env.ECLIPSE_EXTRA_TARGETS or []: addTargetWrap(addTgt, False) storageModule = self.add(doc, cproject, 'storageModule', From 6ed3102d584941a9e8508d302d48d1c9b422eb42 Mon Sep 17 00:00:00 2001 From: Mathieu Parent Date: Mon, 13 Dec 2021 21:27:46 +0100 Subject: [PATCH 311/315] Add support for GNU/kFreeBSD Where default compiler is gcc --- waflib/Tools/compiler_c.py | 25 +++++++++++++------------ waflib/Tools/compiler_cxx.py | 25 +++++++++++++------------ 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/waflib/Tools/compiler_c.py b/waflib/Tools/compiler_c.py index 931dc57efe..e033ce6c5c 100644 --- a/waflib/Tools/compiler_c.py +++ b/waflib/Tools/compiler_c.py @@ -36,18 +36,19 @@ def build(bld): from waflib.Logs import debug c_compiler = { -'win32': ['msvc', 'gcc', 'clang'], -'cygwin': ['gcc', 'clang'], -'darwin': ['clang', 'gcc'], -'aix': ['xlc', 'gcc', 'clang'], -'linux': ['gcc', 'clang', 'icc'], -'sunos': ['suncc', 'gcc'], -'irix': ['gcc', 'irixcc'], -'hpux': ['gcc'], -'osf1V': ['gcc'], -'gnu': ['gcc', 'clang'], -'java': ['gcc', 'msvc', 'clang', 'icc'], -'default':['clang', 'gcc'], +'win32': ['msvc', 'gcc', 'clang'], +'cygwin': ['gcc', 'clang'], +'darwin': ['clang', 'gcc'], +'aix': ['xlc', 'gcc', 'clang'], +'linux': ['gcc', 'clang', 'icc'], +'sunos': ['suncc', 'gcc'], +'irix': ['gcc', 'irixcc'], +'hpux': ['gcc'], +'osf1V': ['gcc'], +'gnu': ['gcc', 'clang'], +'java': ['gcc', 'msvc', 'clang', 'icc'], +'gnukfreebsd': ['gcc', 'clang'], +'default': ['clang', 'gcc'], } """ Dict mapping platform names to Waf tools finding specific C compilers:: diff --git a/waflib/Tools/compiler_cxx.py b/waflib/Tools/compiler_cxx.py index 09fca7e4dc..42658c5847 100644 --- a/waflib/Tools/compiler_cxx.py +++ b/waflib/Tools/compiler_cxx.py @@ -37,18 +37,19 @@ def build(bld): from waflib.Logs import debug cxx_compiler = { -'win32': ['msvc', 'g++', 'clang++'], -'cygwin': ['g++', 'clang++'], -'darwin': ['clang++', 'g++'], -'aix': ['xlc++', 'g++', 'clang++'], -'linux': ['g++', 'clang++', 'icpc'], -'sunos': ['sunc++', 'g++'], -'irix': ['g++'], -'hpux': ['g++'], -'osf1V': ['g++'], -'gnu': ['g++', 'clang++'], -'java': ['g++', 'msvc', 'clang++', 'icpc'], -'default': ['clang++', 'g++'] +'win32': ['msvc', 'g++', 'clang++'], +'cygwin': ['g++', 'clang++'], +'darwin': ['clang++', 'g++'], +'aix': ['xlc++', 'g++', 'clang++'], +'linux': ['g++', 'clang++', 'icpc'], +'sunos': ['sunc++', 'g++'], +'irix': ['g++'], +'hpux': ['g++'], +'osf1V': ['g++'], +'gnu': ['g++', 'clang++'], +'java': ['g++', 'msvc', 'clang++', 'icpc'], +'gnukfreebsd': ['g++', 'clang++'], +'default': ['clang++', 'g++'] } """ Dict mapping the platform names to Waf tools finding specific C++ compilers:: From bb71f26c252ab03c73717c550a8f243d73baef5e Mon Sep 17 00:00:00 2001 From: Thomas Nagy Date: Wed, 15 Dec 2021 01:35:12 +0100 Subject: [PATCH 312/315] waf-2.0.23 --- ChangeLog | 8 ++++++++ waf-light | 2 +- waflib/Context.py | 6 +++--- wscript | 2 +- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9ef9b42814..c37e8d709e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +NEW IN WAF 2.0.23 +----------------- +* Fix the Qt3D* libraries detection #2368 +* Fix swig processing when \r is preset in the module name #2350 +* Add RISC-V generic detection #2322 +* Detect gcc first on GNU/kFreeBSD #2336 +* Improve waflib/extras/msvcdeps performance #2323 + NEW IN WAF 2.0.22 ----------------- * Fix stdin propagation with faulty vcvarsall scripts #2315 diff --git a/waf-light b/waf-light index 97beb52058..cc6310331c 100755 --- a/waf-light +++ b/waf-light @@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE. import os, sys, inspect -VERSION="2.0.22" +VERSION="2.0.23" REVISION="x" GIT="x" INSTALL="x" diff --git a/waflib/Context.py b/waflib/Context.py index 07ee1201f0..36d1ca74fe 100755 --- a/waflib/Context.py +++ b/waflib/Context.py @@ -18,13 +18,13 @@ class imp(object): import imp # the following 3 constants are updated on each new release (do not touch) -HEXVERSION=0x2001600 +HEXVERSION=0x2001700 """Constant updated on new releases""" -WAFVERSION="2.0.22" +WAFVERSION="2.0.23" """Constant updated on new releases""" -WAFREVISION="816d5bc48ba2abc4ac22f2b44d94d322bf992b9c" +WAFREVISION="cc6b34cf555d354c34f554c41206134072588de7" """Git revision when the waf version is updated""" WAFNAME="waf" diff --git a/wscript b/wscript index 0cbd14d860..ce214cadf6 100644 --- a/wscript +++ b/wscript @@ -11,7 +11,7 @@ To add a tool that does not exist in the folder compat15, pass an absolute path: from __future__ import with_statement -VERSION="2.0.22" +VERSION="2.0.23" APPNAME='waf' REVISION='' From f946941679a9ae2c30d8fbbbfa02cdb290362b97 Mon Sep 17 00:00:00 2001 From: David Kassa Date: Tue, 21 Dec 2021 20:43:50 +0200 Subject: [PATCH 313/315] modernize macos demo --- demos/mac_app/sources/main.m | 1 + demos/mac_app/wscript | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/demos/mac_app/sources/main.m b/demos/mac_app/sources/main.m index 4c696b7310..dfb8da3af2 100644 --- a/demos/mac_app/sources/main.m +++ b/demos/mac_app/sources/main.m @@ -1,6 +1,7 @@ // waf sample Mac application - main.m // Chris Pickel, 2011 +#import #import int main(int argc, const char* argv[]) { diff --git a/demos/mac_app/wscript b/demos/mac_app/wscript index 0cb9c5fff6..7fc96e70e2 100644 --- a/demos/mac_app/wscript +++ b/demos/mac_app/wscript @@ -21,7 +21,7 @@ def configure(conf): if not conf.env.ARCH_ST: conf.fatal('This example is for macs only') conf.env.FRAMEWORK_COCOA = 'Cocoa' - conf.env.ARCH_COCOA = ['i386', 'x86_64'] + conf.env.ARCH_COCOA = ['x86_64', 'arm64'] def build(bld): bld.program( From 8568c8522ba87a22dda072d41b92574e41d71fc4 Mon Sep 17 00:00:00 2001 From: cclauss Date: Fri, 18 Jan 2019 14:41:54 +0100 Subject: [PATCH 314/315] Define xrange() in Python 3 __xrange()__ was removed in Python 3 in favor of a reworked version of __range()__. Discovered via ArduPilot/ardupilot#10278 --- playground/compress/optim.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/playground/compress/optim.py b/playground/compress/optim.py index e318cef0b7..c4516f12fa 100755 --- a/playground/compress/optim.py +++ b/playground/compress/optim.py @@ -2,6 +2,11 @@ import os, subprocess, shutil, random, optparse +try: + xrange # Python 2 +except NameError: # Python 3 + xrange = range + comp = { 'bz2': 'cjf', 'xz' : 'cJf', From f60daab5639403cae7c37fb9b3b52114bbb88b81 Mon Sep 17 00:00:00 2001 From: cclauss Date: Fri, 18 Jan 2019 23:57:08 +0100 Subject: [PATCH 315/315] Match the change made in upstream https://gitlab.com/ita1024/waf/blob/master/playground/compress/optim.py --- playground/compress/optim.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/playground/compress/optim.py b/playground/compress/optim.py index c4516f12fa..e318cef0b7 100755 --- a/playground/compress/optim.py +++ b/playground/compress/optim.py @@ -2,11 +2,6 @@ import os, subprocess, shutil, random, optparse -try: - xrange # Python 2 -except NameError: # Python 3 - xrange = range - comp = { 'bz2': 'cjf', 'xz' : 'cJf',