diff --git a/build_system_kit/makefile_dumper/wscript b/build_system_kit/makefile_dumper/wscript index 4a90fbbe..d3a3d6bc 100644 --- a/build_system_kit/makefile_dumper/wscript +++ b/build_system_kit/makefile_dumper/wscript @@ -39,16 +39,16 @@ def dump(bld): bld.targets = [] # store the command executed - old_exec = Task.TaskBase.exec_command + old_exec = Task.Task.exec_command def exec_command(self, *k, **kw): ret = old_exec(self, *k, **kw) self.command_executed = k[0] self.path = kw['cwd'] or self.generator.bld.cwd return ret - Task.TaskBase.exec_command = exec_command + Task.Task.exec_command = exec_command # perform a fake build, and accumulate the makefile bits - old_process = Task.TaskBase.process + old_process = Task.Task.process def process(self): old_process(self) @@ -67,7 +67,7 @@ def dump(bld): else: bld.commands.append(' '.join(lst)) bld.commands.append('\tcd %s && %s' % (self.path, self.command_executed)) - Task.TaskBase.process = process + Task.Task.process = process # write the makefile after the build is complete def output_makefile(self): diff --git a/playground/maxjobs2/compute/wscript b/playground/maxjobs2/compute/wscript index c160ad90..381ef8fd 100644 --- a/playground/maxjobs2/compute/wscript +++ b/playground/maxjobs2/compute/wscript @@ -95,9 +95,9 @@ def process(self): except Exception, e: print type(e), e -Task.TaskBase.process_bound_maxjobs = Task.TaskBase.process +Task.Task.process_bound_maxjobs = Task.Task.process Task.Task.process = process -Task.TaskBase.lock_maxjob = lock_maxjob -Task.TaskBase.release_maxjob = release_maxjob -Task.TaskBase.wait_maxjob = wait_maxjob +Task.Task.lock_maxjob = lock_maxjob +Task.Task.release_maxjob = release_maxjob +Task.Task.wait_maxjob = wait_maxjob diff --git a/playground/parallel_cmd/wscript b/playground/parallel_cmd/wscript index 99307b59..b540eb92 100644 --- a/playground/parallel_cmd/wscript +++ b/playground/parallel_cmd/wscript @@ -65,7 +65,7 @@ def build_all_at_once(ctx): f(self) sem.release() return f2 - Task.TaskBase.process = with_sem(Task.TaskBase.process) + Task.Task.process = with_sem(Task.Task.process) threads = [] for var in ctx.all_envs: diff --git a/waflib/Build.py b/waflib/Build.py index de3a45c0..e0181026 100644 --- a/waflib/Build.py +++ b/waflib/Build.py @@ -587,7 +587,7 @@ class BuildContext(Context.Context): def add_to_group(self, tgen, group=None): """Adds a task or a task generator to the build; there is no attempt to remove it if it was already added.""" - assert(isinstance(tgen, TaskGen.task_gen) or isinstance(tgen, Task.TaskBase)) + assert(isinstance(tgen, TaskGen.task_gen) or isinstance(tgen, Task.Task)) tgen.bld = self self.get_group(group).append(tgen) @@ -761,7 +761,7 @@ class BuildContext(Context.Context): Returns all task instances for the build group at position idx, used internally by :py:meth:`waflib.Build.BuildContext.get_build_iterator` - :rtype: list of :py:class:`waflib.Task.TaskBase` + :rtype: list of :py:class:`waflib.Task.Task` """ tasks = [] for tg in self.groups[idx]: @@ -776,7 +776,7 @@ class BuildContext(Context.Context): Creates a Python generator object that returns lists of tasks that may be processed in parallel. :return: tasks which can be executed immediatly - :rtype: generator returning lists of :py:class:`waflib.Task.TaskBase` + :rtype: generator returning lists of :py:class:`waflib.Task.Task` """ self.cur = 0 @@ -1366,7 +1366,7 @@ class StepContext(BuildContext): for pat in self.files.split(','): matcher = self.get_matcher(pat) for tg in g: - if isinstance(tg, Task.TaskBase): + if isinstance(tg, Task.Task): lst = [tg] else: lst = tg.tasks diff --git a/waflib/Runner.py b/waflib/Runner.py index f47700ba..c488628b 100644 --- a/waflib/Runner.py +++ b/waflib/Runner.py @@ -49,7 +49,7 @@ class Spawner(Utils.threading.Thread): """ 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.TaskBase` instance. + :py:class:`waflib.Task.Task` instance. """ def __init__(self, master): Utils.threading.Thread.__init__(self) @@ -103,16 +103,16 @@ class Parallel(object): """ self.outstanding = Utils.deque() - """List of :py:class:`waflib.Task.TaskBase` that may be ready to be executed""" + """List of :py:class:`waflib.Task.Task` that may be ready to be executed""" self.frozen = Utils.deque() - """List of :py:class:`waflib.Task.TaskBase` that are not ready yet""" + """List of :py:class:`waflib.Task.Task` that are not ready yet""" self.ready = Queue(0) - """List of :py:class:`waflib.Task.TaskBase` ready to be executed by consumers""" + """List of :py:class:`waflib.Task.Task` ready to be executed by consumers""" self.out = Queue(0) - """List of :py:class:`waflib.Task.TaskBase` returned by the task consumers""" + """List of :py:class:`waflib.Task.Task` returned by the task consumers""" self.count = 0 """Amount of tasks that may be processed by :py:class:`waflib.Runner.TaskConsumer`""" @@ -143,7 +143,7 @@ class Parallel(object): """ Obtains the next Task instance to run - :rtype: :py:class:`waflib.Task.TaskBase` + :rtype: :py:class:`waflib.Task.Task` """ if not self.outstanding: return None @@ -155,7 +155,7 @@ class Parallel(object): The order is scrambled so as to consume as many tasks in parallel as possible. :param tsk: task instance - :type tsk: :py:class:`waflib.Task.TaskBase` + :type tsk: :py:class:`waflib.Task.Task` """ if random.randint(0, 1): self.frozen.appendleft(tsk) @@ -200,11 +200,11 @@ class Parallel(object): def add_more_tasks(self, tsk): """ - If a task provides :py:attr:`waflib.Task.TaskBase.more_tasks`, then the tasks contained + If a task provides :py:attr:`waflib.Task.Task.more_tasks`, then the tasks contained in that list are added to the current build and will be processed before the next build group. :param tsk: task instance - :type tsk: :py:attr:`waflib.Task.TaskBase` + :type tsk: :py:attr:`waflib.Task.Task` """ if getattr(tsk, 'more_tasks', None): self.outstanding.extend(tsk.more_tasks) @@ -215,7 +215,7 @@ class Parallel(object): Waits for a Task that task consumers add to :py:attr:`waflib.Runner.Parallel.out` after execution. Adds more Tasks if necessary through :py:attr:`waflib.Runner.Parallel.add_more_tasks`. - :rtype: :py:attr:`waflib.Task.TaskBase` + :rtype: :py:attr:`waflib.Task.Task` """ tsk = self.out.get() if not self.stop: @@ -229,7 +229,7 @@ class Parallel(object): Enqueue a Task to :py:attr:`waflib.Runner.Parallel.ready` so that consumers can run them. :param tsk: task instance - :type tsk: :py:attr:`waflib.Task.TaskBase` + :type tsk: :py:attr:`waflib.Task.Task` """ self.ready.put(tsk) @@ -253,7 +253,7 @@ class Parallel(object): $ waf build -k :param tsk: task instance - :type tsk: :py:attr:`waflib.Task.TaskBase` + :type tsk: :py:attr:`waflib.Task.Task` """ if hasattr(tsk, 'scan') and hasattr(tsk, 'uid'): # TODO waf 2.0 - this breaks encapsulation diff --git a/waflib/Task.py b/waflib/Task.py index 58e5fbb1..33cb3a3b 100644 --- a/waflib/Task.py +++ b/waflib/Task.py @@ -92,7 +92,7 @@ class store_task_type(type): super(store_task_type, cls).__init__(name, bases, dict) name = cls.__name__ - if name != 'evil' and name != 'TaskBase': + if name != 'evil' and name != 'Task': global classes if getattr(cls, 'run_str', None): # if a string is provided, convert it to a method @@ -114,20 +114,21 @@ class store_task_type(type): evil = store_task_type('evil', (object,), {}) "Base class provided to avoid writing a metaclass, so the code can run in python 2.6 and 3.x unmodified" -class TaskBase(evil): +class Task(evil): """ - Base class for all Waf tasks, which should be seen as an interface. - For illustration purposes, instances of this class will execute the attribute - 'fun' in :py:meth:`waflib.Task.TaskBase.run`. When in doubt, create - subclasses of :py:class:`waflib.Task.Task` instead. - - Subclasses must override these methods: - - #. __str__: string to display to the user - #. runnable_status: ask the task if it should be run, skipped, or if we have to ask later - #. run: what to do to execute the task - #. post_run: what to do after the task has been executed + 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). """ + vars = [] + """ConfigSet variables that should trigger a rebuild (class attribute used for :py:meth:`waflib.Task.Task.sig_vars`)""" + + always_run = False + """Specify whether task instances must always be executed or not (class attribute)""" + + shell = False + """Execute the command with the shell (class attribute)""" color = 'GREEN' """Color for the console display, see :py:const:`waflib.Logs.colors_lst`""" @@ -152,32 +153,29 @@ class TaskBase(evil): This may be useful for certain extensions but it can a lot of memory. """ - __slots__ = ('hasrun', 'generator') + __slots__ = ('hasrun', 'generator', 'env', 'inputs', 'outputs', 'dep_nodes', 'run_after') def __init__(self, *k, **kw): - """ - The base task class requires a task generator (set to *self* if missing) - """ self.hasrun = NOT_RUN try: self.generator = kw['generator'] except KeyError: self.generator = self - def __repr__(self): - return '\n\t{task %r: %s %s}' % (self.__class__.__name__, id(self), str(getattr(self, 'fun', ''))) + self.env = kw['env'] + """:py:class:`waflib.ConfigSet.ConfigSet` object (make sure to provide one)""" - def __str__(self): - "String to display to the user" - if hasattr(self, 'fun'): - return self.fun.__name__ - return self.__class__.__name__ + self.inputs = [] + """List of input nodes, which represent the files used by the task instance""" - def keyword(self): - "Display keyword used to prettify the console outputs" - if hasattr(self, 'fun'): - return 'Function' - return 'Processing' + self.outputs = [] + """List of output nodes, which represent the files created by the task instance""" + + self.dep_nodes = [] + """List of additional nodes to depend on""" + + self.run_after = set() + """Set of tasks that must be executed before this one""" def get_cwd(self): """ @@ -262,24 +260,6 @@ class TaskBase(evil): else: return self.generator.bld.exec_command(cmd, **kw) - def runnable_status(self): - """ - Returns the Task status - - :return: a task state in :py:const:`waflib.Task.RUN_ME`, - :py:const:`waflib.Task.SKIP_ME`, :py:const:`waflib.Task.CANCEL_ME` or :py:const:`waflib.Task.ASK_LATER`. - :rtype: int - """ - return RUN_ME - - def uid(self): - """ - Computes a unique identifier for the task - - :rtype: string or bytes - """ - return Utils.SIG_NIL - def process(self): """ Assume that the task has had a ``master`` which is an instance of :py:class:`waflib.Runner.Parallel`. @@ -324,20 +304,6 @@ class TaskBase(evil): if self.hasrun != SUCCESS: m.error_handler(self) - def run(self): - """ - Called by threads to execute the tasks. The default is empty and meant to be overridden in subclasses. - - .. warning:: It is a bad idea to create nodes in this method, so avoid :py:meth:`waflib.Node.Node.ant_glob` - - :rtype: int - """ - if hasattr(self, 'fun'): - return self.fun(self) - return 0 - - def post_run(self): - "Update build data after successful Task execution. Override in subclasses." pass def log_display(self, bld): @@ -472,40 +438,6 @@ class TaskBase(evil): lst.append(y) return lst -class Task(TaskBase): - """ - 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). - """ - vars = [] - """ConfigSet variables that should trigger a rebuild (class attribute used for :py:meth:`waflib.Task.Task.sig_vars`)""" - - always_run = False - """Specify whether task instances must always be executed or not (class attribute)""" - - shell = False - """Execute the command with the shell (class attribute)""" - - def __init__(self, *k, **kw): - TaskBase.__init__(self, *k, **kw) - - self.env = kw['env'] - """:py:class:`waflib.ConfigSet.ConfigSet` object (make sure to provide one)""" - - self.inputs = [] - """List of input nodes, which represent the files used by the task instance""" - - self.outputs = [] - """List of output nodes, which represent the files created by the task instance""" - - self.dep_nodes = [] - """List of additional nodes to depend on""" - - self.run_after = set() - """Set of tasks that must be executed before this one""" - def __str__(self): "string to display to the user" name = self.__class__.__name__ @@ -526,9 +458,7 @@ class Task(TaskBase): return '%s: %s%s%s' % (self.__class__.__name__, src_str, sep, tgt_str) def keyword(self): - """ - See :py:meth:`waflib.Task.TaskBase` - """ + "Display keyword used to prettify the console outputs" name = self.__class__.__name__ if name.endswith(('lib', 'program')): return 'Linking' @@ -605,7 +535,7 @@ class Task(TaskBase): :param task: task :type task: :py:class:`waflib.Task.Task` """ - assert isinstance(task, TaskBase) + assert isinstance(task, Task) self.run_after.add(task) def signature(self): @@ -654,7 +584,11 @@ class Task(TaskBase): def runnable_status(self): """ - See :py:meth:`waflib.Task.TaskBase.runnable_status` + Returns the Task status + + :return: a task state in :py:const:`waflib.Task.RUN_ME`, + :py:const:`waflib.Task.SKIP_ME`, :py:const:`waflib.Task.CANCEL_ME` or :py:const:`waflib.Task.ASK_LATER`. + :rtype: int """ bld = self.generator.bld if bld.is_install < 0: @@ -897,9 +831,9 @@ def is_before(t1, t2): waflib.Task.is_before(t1, t2) # True :param t1: Task object - :type t1: :py:class:`waflib.Task.TaskBase` + :type t1: :py:class:`waflib.Task.Task` :param t2: Task object - :type t2: :py:class:`waflib.Task.TaskBase` + :type t2: :py:class:`waflib.Task.Task` """ to_list = Utils.to_list for k in to_list(t2.ext_in): @@ -919,7 +853,7 @@ def set_file_constraints(tasks): Updates the ``run_after`` attribute of all tasks based on the task inputs and outputs :param tasks: tasks - :type tasks: list of :py:class:`waflib.Task.TaskBase` + :type tasks: list of :py:class:`waflib.Task.Task` """ ins = Utils.defaultdict(set) outs = Utils.defaultdict(set) @@ -939,7 +873,7 @@ def set_precedence_constraints(tasks): Updates the ``run_after`` attribute of all tasks based on the after/before/ext_out/ext_in attributes :param tasks: tasks - :type tasks: list of :py:class:`waflib.Task.TaskBase` + :type tasks: list of :py:class:`waflib.Task.Task` """ cstr_groups = Utils.defaultdict(list) for x in tasks: @@ -1144,7 +1078,7 @@ def compile_fun(line, shell=False): """ Parses a string expression such as '${CC} ${SRC} -o ${TGT}' and returns a pair containing: - * The function created (compiled) for use as :py:meth:`waflib.Task.TaskBase.run` + * The function created (compiled) for use as :py:meth:`waflib.Task.Task.run` * The list of variables that must cause rebuilds when *env* data is modified for example:: @@ -1230,3 +1164,6 @@ def task_factory(name, func=None, vars=None, color='GREEN', ext_in=[], ext_out=[ return cls +TaskBase = Task +"Provided for compatibility reasons, TaskBase should not be used" + diff --git a/waflib/TaskGen.py b/waflib/TaskGen.py index 63c87517..9673c75b 100644 --- a/waflib/TaskGen.py +++ b/waflib/TaskGen.py @@ -20,7 +20,7 @@ HEADER_EXTS = ['.h', '.hpp', '.hxx', '.hh'] class task_gen(object): """ - Instances of this class create :py:class:`waflib.Task.TaskBase` when + Instances of this class create :py:class:`waflib.Task.Task` when calling the method :py:meth:`waflib.TaskGen.task_gen.post` from the main thread. A few notes: @@ -264,7 +264,7 @@ class task_gen(object): :param tgt: output nodes :type tgt: list of :py:class:`waflib.Tools.Node.Node` :return: A task object - :rtype: :py:class:`waflib.Task.TaskBase` + :rtype: :py:class:`waflib.Task.Task` """ task = Task.classes[name](env=self.env.derive(), generator=self) if src: diff --git a/waflib/Tools/c_config.py b/waflib/Tools/c_config.py index b38d0eae..9413d345 100644 --- a/waflib/Tools/c_config.py +++ b/waflib/Tools/c_config.py @@ -1160,14 +1160,14 @@ def add_as_needed(self): # ============ parallel configuration -class cfgtask(Task.TaskBase): +class cfgtask(Task.Task): """ A task that executes build configuration tests (calls conf.check) Make sure to use locks if concurrent access to the same conf.env data is necessary. """ def __init__(self, *k, **kw): - Task.TaskBase.__init__(self, *k, **kw) + Task.Task.__init__(self, *k, **kw) self.run_after = set() def display(self): @@ -1182,6 +1182,9 @@ class cfgtask(Task.TaskBase): def uid(self): return Utils.SIG_NIL + def signature(self): + return Utils.SIG_NIL + def run(self): conf = self.conf bld = Build.BuildContext(top_dir=conf.srcnode.abspath(), out_dir=conf.bldnode.abspath()) @@ -1209,7 +1212,7 @@ class cfgtask(Task.TaskBase): return 1 def process(self): - Task.TaskBase.process(self) + Task.Task.process(self) if 'msg' in self.args: with self.generator.bld.multicheck_lock: self.conf.start_msg(self.args['msg']) @@ -1265,11 +1268,12 @@ def multicheck(self, *k, **kw): bld = par() bld.keep = kw.get('run_all_tests', True) + bld.imp_sigs = {} # TODO tasks = [] id_to_task = {} for dct in k: - x = Task.classes['cfgtask'](bld=bld) + x = Task.classes['cfgtask'](bld=bld, env=None) tasks.append(x) x.args = dct x.bld = bld diff --git a/waflib/extras/clang_compilation_database.py b/waflib/extras/clang_compilation_database.py index 98bf59fe..578d58e7 100644 --- a/waflib/extras/clang_compilation_database.py +++ b/waflib/extras/clang_compilation_database.py @@ -17,7 +17,7 @@ Usage: import sys, os, json, shlex, pipes from waflib import Logs, TaskGen, Task -Task.TaskBase.keep_last_cmd = True +Task.Task.keep_last_cmd = True if sys.hexversion >= 0x3030000: quote = shlex.quote diff --git a/waflib/extras/compat15.py b/waflib/extras/compat15.py index 7c63b5c7..df9b0e56 100644 --- a/waflib/extras/compat15.py +++ b/waflib/extras/compat15.py @@ -122,7 +122,7 @@ Options.OptionsContext.tool_options = Context.Context.load Options.Handler = Options.OptionsContext Task.simple_task_type = Task.task_type_from_func = Task.task_factory -Task.TaskBase.classes = Task.classes +Task.Task.classes = Task.classes def setitem(self, key, value): if key.startswith('CCFLAGS'): diff --git a/waflib/extras/make.py b/waflib/extras/make.py index c9208857..85096440 100644 --- a/waflib/extras/make.py +++ b/waflib/extras/make.py @@ -48,7 +48,7 @@ class MakeContext(BuildContext): for pat in self.files.split(','): matcher = self.get_matcher(pat) for tg in g: - if isinstance(tg, Task.TaskBase): + if isinstance(tg, Task.Task): lst = [tg] else: lst = tg.tasks diff --git a/waflib/extras/parallel_debug.py b/waflib/extras/parallel_debug.py index 8f02b5c3..4098deda 100644 --- a/waflib/extras/parallel_debug.py +++ b/waflib/extras/parallel_debug.py @@ -244,8 +244,8 @@ def process(self): self.generator.bld.producer.set_running(-1, id(Utils.threading.currentThread()), self) -Task.TaskBase.process_back = Task.TaskBase.process -Task.TaskBase.process = process +Task.Task.process_back = Task.Task.process +Task.Task.process = process old_start = Runner.Parallel.start def do_start(self): diff --git a/waflib/extras/smart_continue.py b/waflib/extras/smart_continue.py index f7381dcc..01fbc519 100644 --- a/waflib/extras/smart_continue.py +++ b/waflib/extras/smart_continue.py @@ -10,7 +10,7 @@ from waflib import Task, Runner Task.CANCELED = 4 def cancel_next(self, tsk): - if not isinstance(tsk, Task.TaskBase): + if not isinstance(tsk, Task.Task): return if tsk.hasrun >= Task.SKIPPED: # normal execution, no need to do anything here