summaryrefslogtreecommitdiff
path: root/third_party/waf/waflib/Build.py
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/waf/waflib/Build.py')
-rw-r--r--third_party/waf/waflib/Build.py162
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])
+