mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
9731979098
The function samba_before_apply_obj_vars serves to remove system paths, it is certainly not an optimisation and has no place in that module. By optimisation, we mean that the build process could run without it. Signed-off-by: Thomas Nagy <tnagy@waf.io> Reviewed-by: Uri Simchoni uri@samba.org Reviewed-by: Andrew Bartlett <abartlet@samba.org>
270 lines
8.0 KiB
Python
270 lines
8.0 KiB
Python
# This file contains waf optimisations for Samba
|
|
|
|
# most of these optimisations are possible because of the restricted build environment
|
|
# that Samba has. For example, Samba doesn't attempt to cope with Win32 paths during the
|
|
# build, and Samba doesn't need build varients
|
|
|
|
# overall this makes some build tasks quite a bit faster
|
|
|
|
import os
|
|
import Build, Utils, Node
|
|
from TaskGen import feature, after, before
|
|
import preproc
|
|
|
|
@feature('c', 'cc', 'cxx')
|
|
@after('apply_type_vars', 'apply_lib_vars', 'apply_core')
|
|
def apply_incpaths(self):
|
|
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('c', 'cc')
|
|
@after('apply_incpaths')
|
|
def apply_obj_vars_cc(self):
|
|
"""after apply_incpaths for INC_PATHS"""
|
|
env = self.env
|
|
app = env.append_unique
|
|
cpppath_st = env['CPPPATH_ST']
|
|
|
|
lss = env['_CCINCFLAGS']
|
|
|
|
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['INC_PATHS']:
|
|
|
|
try:
|
|
lss.extend(cac[i.id])
|
|
except KeyError:
|
|
|
|
cac[i.id] = [cpppath_st % i.bldpath(env), cpppath_st % i.srcpath(env)]
|
|
lss.extend(cac[i.id])
|
|
|
|
env['_CCINCFLAGS'] = lss
|
|
# set the library include paths
|
|
for i in env['CPPPATH']:
|
|
app('_CCINCFLAGS', cpppath_st % i)
|
|
|
|
import Node, Environment
|
|
|
|
def vari(self):
|
|
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"
|
|
Node.Node.variant = variant
|
|
|
|
|
|
import TaskGen, Task
|
|
|
|
def create_task(self, name, src=None, tgt=None):
|
|
task = Task.TaskBase.classes[name](self.env, generator=self)
|
|
if src:
|
|
task.set_inputs(src)
|
|
if tgt:
|
|
task.set_outputs(tgt)
|
|
return task
|
|
TaskGen.task_gen.create_task = create_task
|
|
|
|
def hash_constraints(self):
|
|
a = self.attr
|
|
sum = hash((str(a('before', '')),
|
|
str(a('after', '')),
|
|
str(a('ext_in', '')),
|
|
str(a('ext_out', '')),
|
|
self.__class__.maxjobs))
|
|
return sum
|
|
Task.TaskBase.hash_constraints = hash_constraints
|
|
|
|
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.get_tgen_by_name(name).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('c', '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.get_tgen_by_name(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)
|
|
|
|
|