diff options
Diffstat (limited to 'third_party/waf/waflib/Build.py')
-rw-r--r-- | third_party/waf/waflib/Build.py | 162 |
1 files changed, 68 insertions, 94 deletions
diff --git a/third_party/waf/waflib/Build.py b/third_party/waf/waflib/Build.py index 58583484f16..70ebd697c24 100644 --- a/third_party/waf/waflib/Build.py +++ b/third_party/waf/waflib/Build.py @@ -4,7 +4,7 @@ #!/usr/bin/env python # encoding: utf-8 -# Thomas Nagy, 2005-2016 (ita) +# Thomas Nagy, 2005-2018 (ita) """ Classes related to the build phase (build, clean, install, step, etc) @@ -147,17 +147,11 @@ class BuildContext(Context.Context): if not hasattr(self, v): setattr(self, v, {}) - def set_cur(self, cur): - self.current_group = cur - def get_cur(self): - return self.current_group - cur = property(get_cur, set_cur) - def get_variant_dir(self): """Getter for the variant_dir attribute""" if not self.variant: return self.out_dir - return os.path.join(self.out_dir, self.variant) + return os.path.join(self.out_dir, os.path.normpath(self.variant)) variant_dir = property(get_variant_dir, None) def __call__(self, *k, **kw): @@ -185,30 +179,6 @@ class BuildContext(Context.Context): self.add_to_group(ret, group=kw.get('group')) return ret - def rule(self, *k, **kw): - """ - Wrapper for creating a task generator using the decorator notation. The following code:: - - @bld.rule(target="foo") - def _(tsk): - print("bar") - - is equivalent to:: - - def bar(tsk): - print("bar") - - bld( - target = "foo", - rule = bar, - ) - """ - def f(rule): - ret = self(*k, **kw) - ret.rule = rule - return ret - return f - def __copy__(self): """ Build contexts cannot be copied @@ -323,7 +293,7 @@ class BuildContext(Context.Context): Node.Nod3 = self.node_class try: data = cPickle.loads(data) - except Exception ,e: + except Exception as e: Logs.debug('build: Could not pickle the build cache %s: %r', dbfn, e) else: for x in SAVED_ATTRS: @@ -378,15 +348,19 @@ class BuildContext(Context.Context): try: self.producer.start() except KeyboardInterrupt: - self.store() + if self.is_dirty(): + self.store() raise else: - if self.producer.dirty: + if self.is_dirty(): self.store() if self.producer.error: raise Errors.BuildError(self.producer.error) + def is_dirty(self): + return self.producer.dirty + def setup(self, tool, tooldir=None, funs=None): """ Import waf tools defined during the configuration:: @@ -404,11 +378,13 @@ class BuildContext(Context.Context): :param funs: unused variable """ if isinstance(tool, list): - for i in tool: self.setup(i, tooldir) + for i in tool: + self.setup(i, tooldir) return module = Context.load_tool(tool, tooldir) - if hasattr(module, "setup"): module.setup(self) + if hasattr(module, "setup"): + module.setup(self) def get_env(self): """Getter for the env property""" @@ -548,7 +524,8 @@ class BuildContext(Context.Context): right = '][%s%s%s]' % (col1, self.timer, col2) cols = Logs.get_term_cols() - len(left) - len(right) + 2*len(col1) + 2*len(col2) - if cols < 7: cols = 7 + if cols < 7: + cols = 7 ratio = ((cols * idx)//total) - 1 @@ -621,7 +598,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) @@ -722,10 +699,16 @@ class BuildContext(Context.Context): def get_targets(self): """ - Returns the task generator corresponding to the 'targets' list; used internally - by :py:meth:`waflib.Build.BuildContext.get_build_iterator` to perform partial builds:: + This method returns a pair containing the index of the last build group to post, + and the list of task generator objects corresponding to the target names. + + This is used internally by :py:meth:`waflib.Build.BuildContext.get_build_iterator` + to perform partial builds:: $ waf --targets=myprogram,myshlib + + :return: the minimum build group index, and list of task generators + :rtype: tuple """ to_post = [] min_grp = 0 @@ -753,23 +736,21 @@ class BuildContext(Context.Context): Post task generators from the group indexed by self.current_group; used internally by :py:meth:`waflib.Build.BuildContext.get_build_iterator` """ + def tgpost(tg): + try: + f = tg.post + except AttributeError: + pass + else: + f() + if self.targets == '*': for tg in self.groups[self.current_group]: - try: - f = tg.post - except AttributeError: - pass - else: - f() + tgpost(tg) elif self.targets: if self.current_group < self._min_grp: for tg in self.groups[self.current_group]: - try: - f = tg.post - except AttributeError: - pass - else: - f() + tgpost(tg) else: for tg in self._exact_tg: tg.post() @@ -783,19 +764,19 @@ class BuildContext(Context.Context): ln = self.srcnode for tg in self.groups[self.current_group]: try: - f = tg.post + p = tg.path except AttributeError: pass else: - if tg.path.is_child_of(ln): - f() + if p.is_child_of(ln): + tgpost(tg) def get_tasks_group(self, idx): """ 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]: @@ -810,27 +791,23 @@ 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 immediately - :rtype: generator returning lists of :py:class:`waflib.Task.TaskBase` + :rtype: generator returning lists of :py:class:`waflib.Task.Task` """ - self.current_group = 0 - if self.targets and self.targets != '*': (self._min_grp, self._exact_tg) = self.get_targets() - global lazy_post if self.post_mode != POST_LAZY: - while self.current_group < len(self.groups): + for self.current_group, _ in enumerate(self.groups): self.post_group() - self.current_group += 1 - self.current_group = 0 - while self.current_group < len(self.groups): + for self.current_group, _ in enumerate(self.groups): # first post the task generators for the group if self.post_mode != POST_AT_ONCE: self.post_group() # then extract the tasks tasks = self.get_tasks_group(self.current_group) + # if the constraints are set properly (ext_in/ext_out, before/after) # the call to set_file_constraints may be removed (can be a 15% penalty on no-op rebuilds) # (but leave set_file_constraints for the installation step) @@ -841,12 +818,11 @@ class BuildContext(Context.Context): Task.set_precedence_constraints(tasks) self.cur_tasks = tasks - self.current_group += 1 - if not tasks: # return something else the build will stop - continue - yield tasks + if tasks: + yield tasks while 1: + # the build stops once there are no tasks to process yield [] def install_files(self, dest, files, **kw): @@ -1188,7 +1164,7 @@ class inst(Task.Task): try: self.copy_fun(src, tgt) - except EnvironmentError ,e: + except EnvironmentError as e: if not os.path.exists(src): Logs.error('File %r does not exist', src) elif not os.path.isfile(src): @@ -1249,7 +1225,7 @@ class inst(Task.Task): #self.uninstall.append(tgt) try: os.remove(tgt) - except OSError ,e: + except OSError as e: if e.errno != errno.ENOENT: if not getattr(self, 'uninstall_error', None): self.uninstall_error = True @@ -1286,22 +1262,6 @@ class UninstallContext(InstallContext): super(UninstallContext, self).__init__(**kw) self.is_install = UNINSTALL - def execute(self): - """ - See :py:func:`waflib.Build.BuildContext.execute`. - """ - # TODO just mark the tasks are already run with hasrun=Task.SKIPPED? - try: - # do not execute any tasks - def runnable_status(self): - return Task.SKIP_ME - setattr(Task.Task, 'runnable_status_back', Task.Task.runnable_status) - setattr(Task.Task, 'runnable_status', runnable_status) - - super(UninstallContext, self).execute() - finally: - setattr(Task.Task, 'runnable_status', Task.Task.runnable_status_back) - class CleanContext(BuildContext): '''cleans the project''' cmd = 'clean' @@ -1320,10 +1280,23 @@ class CleanContext(BuildContext): self.store() def clean(self): - """Remove files from the build directory if possible, and reset the caches""" + """ + Remove most files from the build directory, and reset all caches. + + Custom lists of files to clean can be declared as `bld.clean_files`. + For example, exclude `build/program/myprogram` from getting removed:: + + def build(bld): + bld.clean_files = bld.bldnode.ant_glob('**', + excl='.lock* config.log c4che/* config.h program/myprogram', + quiet=True, generator=True) + """ Logs.debug('build: clean called') - if self.bldnode != self.srcnode: + if hasattr(self, 'clean_files'): + for n in self.clean_files: + n.delete() + elif self.bldnode != self.srcnode: # would lead to a disaster if top == out lst = [] for env in self.all_envs.values(): @@ -1434,17 +1407,17 @@ 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 for tsk in lst: do_exec = False - for node in getattr(tsk, 'inputs', []): + for node in tsk.inputs: if matcher(node, output=False): do_exec = True break - for node in getattr(tsk, 'outputs', []): + for node in tsk.outputs: if matcher(node, output=True): do_exec = True break @@ -1480,9 +1453,9 @@ class StepContext(BuildContext): pattern = re.compile(pat) def match(node, output): - if output == True and not out: + if output and not out: return False - if output == False and not inn: + if not output and not inn: return False if anode: @@ -1502,3 +1475,4 @@ class EnvContext(BuildContext): if not self.all_envs: self.load_envs() self.recurse([self.run_dir]) + |