# compatibility layer for building with more recent waf versions
import os, shlex, sys
-from waflib import Build, Configure, Node, Utils, Options, Logs
+from waflib import Build, Configure, Node, Utils, Options, Logs, TaskGen
from waflib import ConfigSet
from waflib.TaskGen import feature, after
from waflib.Configure import conf, ConfigurationContext
def cmd_output(cmd, **kw):
- silent = False
- if 'silent' in kw:
- silent = kw['silent']
- del(kw['silent'])
-
- if 'e' in kw:
- tmp = kw['e']
- del(kw['e'])
- kw['env'] = tmp
-
- kw['shell'] = isinstance(cmd, str)
- kw['stdout'] = Utils.subprocess.PIPE
- if silent:
- kw['stderr'] = Utils.subprocess.PIPE
-
- try:
- p = Utils.subprocess.Popen(cmd, **kw)
- output = p.communicate()[0]
- except OSError as e:
- raise ValueError(str(e))
-
- if p.returncode:
- if not silent:
- msg = "command execution failed: %s -> %r" % (cmd, str(output))
- raise ValueError(msg)
- output = ''
- return output
+ silent = False
+ if 'silent' in kw:
+ silent = kw['silent']
+ del(kw['silent'])
+
+ if 'e' in kw:
+ tmp = kw['e']
+ del(kw['e'])
+ kw['env'] = tmp
+
+ kw['shell'] = isinstance(cmd, str)
+ kw['stdout'] = Utils.subprocess.PIPE
+ if silent:
+ kw['stderr'] = Utils.subprocess.PIPE
+
+ try:
+ p = Utils.subprocess.Popen(cmd, **kw)
+ output = p.communicate()[0]
+ except OSError as e:
+ raise ValueError(str(e))
+
+ if p.returncode:
+ if not silent:
+ msg = "command execution failed: %s -> %r" % (cmd, str(output))
+ raise ValueError(msg)
+ output = ''
+ return output
Utils.cmd_output = cmd_output
+
+
+@TaskGen.feature('c', 'cxx', 'd')
+@TaskGen.before('apply_incpaths', 'propagate_uselib_vars')
+@TaskGen.after('apply_link', 'process_source')
+def apply_uselib_local(self):
+ """
+ process the uselib_local attribute
+ execute after apply_link because of the execution order set on 'link_task'
+ """
+ env = self.env
+ from waflib.Tools.ccroot import stlink_task
+
+ # 1. the case of the libs defined in the project (visit ancestors first)
+ # the ancestors external libraries (uselib) will be prepended
+ self.uselib = self.to_list(getattr(self, 'uselib', []))
+ self.includes = self.to_list(getattr(self, 'includes', []))
+ names = self.to_list(getattr(self, 'uselib_local', []))
+ get = self.bld.get_tgen_by_name
+ seen = set()
+ seen_uselib = set()
+ tmp = Utils.deque(names) # consume a copy of the list of names
+ if tmp:
+ if Logs.verbose:
+ Logs.warn('compat: "uselib_local" is deprecated, replace by "use"')
+ while tmp:
+ lib_name = tmp.popleft()
+ # visit dependencies only once
+ if lib_name in seen:
+ continue
+
+ y = get(lib_name)
+ y.post()
+ seen.add(lib_name)
+
+ # object has ancestors to process (shared libraries): add them to the end of the list
+ if getattr(y, 'uselib_local', None):
+ for x in self.to_list(getattr(y, 'uselib_local', [])):
+ obj = get(x)
+ obj.post()
+ if getattr(obj, 'link_task', None):
+ if not isinstance(obj.link_task, stlink_task):
+ tmp.append(x)
+
+ # link task and flags
+ if getattr(y, 'link_task', None):
+
+ link_name = y.target[y.target.rfind(os.sep) + 1:]
+ if isinstance(y.link_task, stlink_task):
+ env.append_value('STLIB', [link_name])
+ else:
+ # some linkers can link against programs
+ env.append_value('LIB', [link_name])
+
+ # the order
+ self.link_task.set_run_after(y.link_task)
+
+ # for the recompilation
+ self.link_task.dep_nodes += y.link_task.outputs
+
+ # add the link path too
+ tmp_path = y.link_task.outputs[0].parent.bldpath()
+ if not tmp_path in env['LIBPATH']:
+ env.prepend_value('LIBPATH', [tmp_path])
+
+ # add ancestors uselib too - but only propagate those that have no staticlib defined
+ for v in self.to_list(getattr(y, 'uselib', [])):
+ if v not in seen_uselib:
+ seen_uselib.add(v)
+ if not env['STLIB_' + v]:
+ if not v in self.uselib:
+ self.uselib.insert(0, v)
+
+ # if the library task generator provides 'export_includes', add to the include path
+ # the export_includes must be a list of paths relative to the other library
+ if getattr(y, 'export_includes', None):
+ self.includes.extend(y.to_incnodes(y.export_includes))
+
+@TaskGen.feature('cprogram', 'cxxprogram', 'cstlib', 'cxxstlib', 'cshlib', 'cxxshlib', 'dprogram', 'dstlib', 'dshlib')
+@TaskGen.after('apply_link')
+def apply_objdeps(self):
+ "add the .o files produced by some other object files in the same manner as uselib_local"
+ names = getattr(self, 'add_objects', [])
+ if not names:
+ return
+ names = self.to_list(names)
+
+ get = self.bld.get_tgen_by_name
+ seen = []
+ while names:
+ x = names[0]
+
+ # visit dependencies only once
+ if x in seen:
+ names = names[1:]
+ continue
+
+ # object does not exist ?
+ y = get(x)
+
+ # object has ancestors to process first ? update the list of names
+ if getattr(y, 'add_objects', None):
+ added = 0
+ lst = y.to_list(y.add_objects)
+ lst.reverse()
+ for u in lst:
+ if u in seen:
+ continue
+ added = 1
+ names = [u]+names
+ if added:
+ continue # list of names modified, loop
+
+ # safe to process the current object
+ y.post()
+ seen.append(x)
+
+ for t in getattr(y, 'compiled_tasks', []):
+ self.link_task.inputs.extend(t.outputs)
+
+@TaskGen.after('apply_link')
+def process_obj_files(self):
+ if not hasattr(self, 'obj_files'):
+ return
+ for x in self.obj_files:
+ node = self.path.find_resource(x)
+ self.link_task.inputs.append(node)
+
+@TaskGen.taskgen_method
+def add_obj_file(self, file):
+ """Small example on how to link object files as if they were source
+ obj = bld.create_obj('cc')
+ obj.add_obj_file('foo.o')"""
+ if not hasattr(self, 'obj_files'):
+ self.obj_files = []
+ if not 'process_obj_files' in self.meths:
+ self.meths.append('process_obj_files')
+ self.obj_files.append(file)