# overall this makes some build tasks quite a bit faster
-from TaskGen import feature, before, after
-import preproc
import os
+import Build, Utils, Node
+from TaskGen import feature, after, before
+import preproc, Task
-kak = {}
@feature('cc', 'cxx')
@after('apply_type_vars', 'apply_lib_vars', 'apply_core')
def apply_incpaths(self):
- lst = []
- # TODO move the uselib processing out of here
- for lib in self.to_list(self.uselib):
- for path in self.env['CPPPATH_' + lib]:
- if not path in lst:
- lst.append(path)
- if preproc.go_absolute:
- for path in preproc.standard_includes:
- if not path in lst:
- lst.append(path)
-
- for path in self.to_list(self.includes):
- if not path in lst:
- if preproc.go_absolute or path[0] != '/': #os.path.isabs(path):
- lst.append(path)
- else:
- self.env.prepend_value('CPPPATH', path)
-
- for path in lst:
- node = None
- if path[0] == '/': # os.path.isabs(path):
- if preproc.go_absolute:
- node = self.bld.root.find_dir(path)
- elif path[0] == '#':
- node = self.bld.srcnode
- if len(path) > 1:
- try:
- node = kak[path]
- except KeyError:
- kak[path] = node = node.find_dir(path[1:])
- else:
- try:
- node = kak[(self.path.id, path)]
- except KeyError:
- kak[(self.path.id, path)] = node = self.path.find_dir(path)
-
- if node:
- self.env.append_value('INC_PATHS', node)
-
-cac = {}
+ lst = []
+
+ try:
+ kak = self.bld.kak
+ except AttributeError:
+ kak = self.bld.kak = {}
+
+ # TODO move the uselib processing out of here
+ for lib in self.to_list(self.uselib):
+ for path in self.env['CPPPATH_' + lib]:
+ if not path in lst:
+ lst.append(path)
+ if preproc.go_absolute:
+ for path in preproc.standard_includes:
+ if not path in lst:
+ lst.append(path)
+
+ for path in self.to_list(self.includes):
+ if not path in lst:
+ if preproc.go_absolute or path[0] != '/': # os.path.isabs(path):
+ lst.append(path)
+ else:
+ self.env.prepend_value('CPPPATH', path)
+
+ for path in lst:
+ node = None
+ if path[0] == '/': # os.path.isabs(path):
+ if preproc.go_absolute:
+ node = self.bld.root.find_dir(path)
+ elif path[0] == '#':
+ node = self.bld.srcnode
+ if len(path) > 1:
+ try:
+ node = kak[path]
+ except KeyError:
+ kak[path] = node = node.find_dir(path[1:])
+ else:
+ try:
+ node = kak[(self.path.id, path)]
+ except KeyError:
+ kak[(self.path.id, path)] = node = self.path.find_dir(path)
+
+ if node:
+ self.env.append_value('INC_PATHS', node)
+
+@feature('cc')
+@before('apply_incpaths')
+def samba_stash_cppflags(self):
+ """Fix broken waf ordering of CPPFLAGS"""
+ self.env['SAVED_CPPFLAGS'] = self.env['CPPFLAGS']
+ self.env['CPPFLAGS'] = []
+
@feature('cc')
@after('apply_incpaths')
def apply_obj_vars_cc(self):
lss = env['_CCINCFLAGS']
- global cac
+ try:
+ cac = self.bld.cac
+ except AttributeError:
+ cac = self.bld.cac = {}
# local flags come first
# set the user-defined includes paths
for i in env['CPPPATH']:
app('_CCINCFLAGS', cpppath_st % i)
+ # append stashed user CPPFLAGS after our internally computed flags
+ app('_CCINCFLAGS', env['SAVED_CPPFLAGS'])
+ env['SAVED_CPPFLAGS'] = []
+
import Node, Environment
def vari(self):
- return "default"
+ return "default"
Environment.Environment.variant = vari
def variant(self, env):
- if not env: return 0
- elif self.id & 3 == Node.FILE: return 0
- else: return "default"
+ if not env: return 0
+ elif self.id & 3 == Node.FILE: return 0
+ else: return "default"
Node.Node.variant = variant
TaskGen.task_gen.create_task = create_task
def hash_constraints(self):
- a = self.attr
- sum = hash((str(a('before', '')),
+ a = self.attr
+ sum = hash((str(a('before', '')),
str(a('after', '')),
str(a('ext_in', '')),
str(a('ext_out', '')),
self.__class__.maxjobs))
- return sum
+ return sum
Task.TaskBase.hash_constraints = hash_constraints
# @extension(cc.EXT_CC)
# def c_hook(self, node):
-# task = self.create_task('cc', node, node.change_ext('.o'))
-# try:
-# self.compiled_tasks.append(task)
-# except AttributeError:
-# raise Utils.WafError('Have you forgotten to set the feature "cc" on %s?' % str(self))
+# task = self.create_task('cc', node, node.change_ext('.o'))
+# try:
+# self.compiled_tasks.append(task)
+# except AttributeError:
+# raise Utils.WafError('Have you forgotten to set the feature "cc" on %s?' % str(self))
+
+# bld = self.bld
+# try:
+# dc = bld.dc
+# except AttributeError:
+# dc = bld.dc = {}
+
+# if task.outputs[0].id in dc:
+# raise Utils.WafError('Samba, you are doing it wrong %r %s %s' % (task.outputs, task.generator, dc[task.outputs[0].id].generator))
+# else:
+# dc[task.outputs[0].id] = task
+
+# return task
+
+
+def suncc_wrap(cls):
+ '''work around a problem with cc on solaris not handling module aliases
+ which have empty libs'''
+ if getattr(cls, 'solaris_wrap', False):
+ return
+ cls.solaris_wrap = True
+ oldrun = cls.run
+ def run(self):
+ if self.env.CC_NAME == "sun" and not self.inputs:
+ self.env = self.env.copy()
+ self.env.append_value('LINKFLAGS', '-')
+ return oldrun(self)
+ cls.run = run
+suncc_wrap(Task.TaskBase.classes['cc_link'])
+
+
+
+def hash_env_vars(self, env, vars_lst):
+ idx = str(id(env)) + str(vars_lst)
+ try:
+ return self.cache_sig_vars[idx]
+ except KeyError:
+ pass
+
+ m = Utils.md5()
+ m.update(''.join([str(env[a]) for a in vars_lst]))
+
+ ret = self.cache_sig_vars[idx] = m.digest()
+ return ret
+Build.BuildContext.hash_env_vars = hash_env_vars
+
+
+def store_fast(self, filename):
+ file = open(filename, 'wb')
+ data = self.get_merged_dict()
+ try:
+ Build.cPickle.dump(data, file, -1)
+ finally:
+ file.close()
+Environment.Environment.store_fast = store_fast
+
+def load_fast(self, filename):
+ file = open(filename, 'rb')
+ try:
+ data = Build.cPickle.load(file)
+ finally:
+ file.close()
+ self.table.update(data)
+Environment.Environment.load_fast = load_fast
+
+def is_this_a_static_lib(self, name):
+ try:
+ cache = self.cache_is_this_a_static_lib
+ except AttributeError:
+ cache = self.cache_is_this_a_static_lib = {}
+ try:
+ return cache[name]
+ except KeyError:
+ ret = cache[name] = 'cstaticlib' in self.bld.name_to_obj(name, self.env).features
+ return ret
+TaskGen.task_gen.is_this_a_static_lib = is_this_a_static_lib
+
+def shared_ancestors(self):
+ try:
+ cache = self.cache_is_this_a_static_lib
+ except AttributeError:
+ cache = self.cache_is_this_a_static_lib = {}
+ try:
+ return cache[id(self)]
+ except KeyError:
+
+ ret = []
+ if 'cshlib' in self.features: # or 'cprogram' in self.features:
+ if getattr(self, 'uselib_local', None):
+ lst = self.to_list(self.uselib_local)
+ ret = [x for x in lst if not self.is_this_a_static_lib(x)]
+ cache[id(self)] = ret
+ return ret
+TaskGen.task_gen.shared_ancestors = shared_ancestors
+
+@feature('cc', 'cxx')
+@after('apply_link', 'init_cc', 'init_cxx', 'apply_core')
+def apply_lib_vars(self):
+ """after apply_link because of 'link_task'
+ after default_cc because of the attribute 'uselib'"""
+
+ # after 'apply_core' in case if 'cc' if there is no link
+
+ env = self.env
+ app = env.append_value
+ seen_libpaths = set([])
+
+ # OPTIMIZATION 1: skip uselib variables already added (700ms)
+ seen_uselib = set([])
+
+ # 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(self.uselib)
+ names = self.to_list(self.uselib_local)
+
+ seen = set([])
+ tmp = Utils.deque(names) # consume a copy of the list of names
+ while tmp:
+ lib_name = tmp.popleft()
+ # visit dependencies only once
+ if lib_name in seen:
+ continue
+
+ y = self.name_to_obj(lib_name)
+ if not y:
+ raise Utils.WafError('object %r was not found in uselib_local (required by %r)' % (lib_name, self.name))
+ y.post()
+ seen.add(lib_name)
+
+ # OPTIMIZATION 2: pre-compute ancestors shared libraries (100ms)
+ tmp.extend(y.shared_ancestors())
+
+ # link task and flags
+ if getattr(y, 'link_task', None):
+
+ link_name = y.target[y.target.rfind('/') + 1:]
+ if 'cstaticlib' in y.features:
+ app('STATICLIB', link_name)
+ elif 'cshlib' in y.features or 'cprogram' in y.features:
+ # WARNING some linkers can link against programs
+ app('LIB', link_name)
+
+ # the order
+ self.link_task.set_run_after(y.link_task)
+
+ # for the recompilation
+ dep_nodes = getattr(self.link_task, 'dep_nodes', [])
+ self.link_task.dep_nodes = dep_nodes + y.link_task.outputs
+
+ # OPTIMIZATION 3: reduce the amount of function calls
+ # add the link path too
+ par = y.link_task.outputs[0].parent
+ if id(par) not in seen_libpaths:
+ seen_libpaths.add(id(par))
+ tmp_path = par.bldpath(self.env)
+ 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
+ for v in self.to_list(y.uselib):
+ if v not in seen_uselib:
+ seen_uselib.add(v)
+ if not env['STATICLIB_' + v]:
+ if not v in self.uselib:
+ self.uselib.insert(0, v)
+
+ # 2. the case of the libs defined outside
+ for x in self.uselib:
+ for v in self.p_flag_vars:
+ val = self.env[v + '_' + x]
+ if val:
+ self.env.append_value(v, val)
+
+@feature('cprogram', 'cshlib', 'cstaticlib')
+@after('apply_lib_vars')
+@before('apply_obj_vars')
+def samba_before_apply_obj_vars(self):
+ """before apply_obj_vars for uselib, this removes the standard pathes"""
+
+ def is_standard_libpath(env, path):
+ for _path in env.STANDARD_LIBPATH:
+ if _path == os.path.normpath(path):
+ return True
+ return False
+
+ v = self.env
+
+ for i in v['RPATH']:
+ if is_standard_libpath(v, i):
+ v['RPATH'].remove(i)
+
+ for i in v['LIBPATH']:
+ if is_standard_libpath(v, i):
+ v['LIBPATH'].remove(i)
-# bld = self.bld
-# try:
-# dc = bld.dc
-# except AttributeError:
-# dc = bld.dc = {}
+@feature('cprogram', 'cshlib', 'cstaticlib')
+@before('apply_obj_vars', 'add_extra_flags')
+def samba_stash_linkflags(self):
+ """stash away LINKFLAGS in order to fix waf's broken ordering wrt or
+ user LDFLAGS"""
-# if task.outputs[0].id in dc:
-# raise Utils.WafError('Samba, you are doing it wrong %r %s %s' % (task.outputs, task.generator, dc[task.outputs[0].id].generator))
-# else:
-# dc[task.outputs[0].id] = task
+ self.env.SAVE_LINKFLAGS = self.env['LINKFLAGS']
+ self.env['LINKFLAGS'] = []
-# return task
+@feature('cprogram', 'cshlib', 'cstaticlib')
+@after('apply_obj_vars', 'add_extra_flags')
+def samba_pop_linkflags(self):
+ """after apply_obj_vars append saved LDFLAGS"""
+ self.env.append_value('LINKFLAGS', self.env.SAVE_LINKFLAGS)
+ self.env.SAVE_LINKFLAGS = []