def build_direct_deps(bld, tgt_list): '''build the direct_objects and direct_libs sets for each target''' targets = LOCAL_CACHE(bld, 'TARGET_TYPE') syslib_deps = LOCAL_CACHE(bld, 'SYSLIB_DEPS') global_deps = bld.env.GLOBAL_DEPENDENCIES global_deps_exclude = set() for dep in global_deps: t = bld.get_tgen_by_name(dep) for d in t.samba_deps: # prevent loops from the global dependencies list global_deps_exclude.add(d) global_deps_exclude.add(d + '.objlist') for t in tgt_list: t.direct_objects = set() t.direct_libs = set() t.direct_syslibs = set() deps = t.samba_deps_extended[:] if getattr(t, 'samba_use_global_deps', False) and not t.sname in global_deps_exclude: deps.extend(global_deps) for d in deps: if d == t.sname: continue if not d in targets: Logs.error("Unknown dependency '%s' in '%s'" % (d, t.sname)) sys.exit(1) if targets[d] in [ 'EMPTY', 'DISABLED' ]: continue if targets[d] == 'PYTHON' and targets[t.sname] != 'PYTHON' and t.sname.find('.objlist') == -1: # this check should be more restrictive, but for now we have pidl-generated python # code that directly depends on other python modules Logs.error('ERROR: Target %s has dependency on python module %s' % (t.sname, d)) sys.exit(1) if targets[d] == 'SYSLIB': t.direct_syslibs.add(d) if d in syslib_deps: for implied in TO_LIST(syslib_deps[d]): if BUILTIN_LIBRARY(bld, implied): t.direct_objects.add(implied) elif targets[implied] == 'SYSLIB': t.direct_syslibs.add(implied) elif targets[implied] in ['LIBRARY', 'MODULE']: t.direct_libs.add(implied) else: Logs.error('Implied dependency %s in %s is of type %s' % ( implied, t.sname, targets[implied])) sys.exit(1) continue t2 = bld.get_tgen_by_name(d) if t2 is None: Logs.error("no task %s of type %s in %s" % (d, targets[d], t.sname)) sys.exit(1) if t2.samba_type in [ 'LIBRARY', 'MODULE' ]: t.direct_libs.add(d) elif t2.samba_type in [ 'SUBSYSTEM', 'ASN1', 'PYTHON' ]: t.direct_objects.add(d) debug('deps: built direct dependencies')
def collect(self): pidl_headers = LOCAL_CACHE(self.bld, 'PIDL_HEADERS') for (name, hd) in pidl_headers.items(): y = self.bld.get_tgen_by_name(name) self.bld.ASSERT(y is not None, 'Failed to find PIDL header {0!s}'.format(name)) y.post() for node in hd: self.bld.ASSERT(node is not None, 'Got None as build node generating PIDL table for {0!s}'.format(name)) self.source += " " + node.relpath_gen(self.path)
def collect(self): pidl_headers = LOCAL_CACHE(self.bld, 'PIDL_HEADERS') for (name, hd) in pidl_headers.items(): y = self.bld.get_tgen_by_name(name) self.bld.ASSERT(y is not None, 'Failed to find PIDL header %s' % name) y.post() for node in hd: self.bld.ASSERT( node is not None, 'Got None as build node generating PIDL table for %s' % name) self.source += " " + node.relpath_gen(self.path)
def collect(self): pidl_headers = LOCAL_CACHE(self.bld, 'PIDL_HEADERS') # The first source is tables.pl itself self.source = Utils.to_list(self.source) for (name, hd) in pidl_headers.items(): y = self.bld.get_tgen_by_name(name) self.bld.ASSERT(y is not None, 'Failed to find PIDL header %s' % name) y.post() for node in hd: self.bld.ASSERT( node is not None, 'Got None as build node generating PIDL table for %s' % name) self.source.append(node)
def replace_grouping_libraries(bld, tgt_list): '''replace dependencies based on grouping libraries If a library is marked as a grouping library, then any target that depends on a subsystem that is part of that grouping library gets that dependency replaced with a dependency on the grouping library ''' targets = LOCAL_CACHE(bld, 'TARGET_TYPE') grouping = {} # find our list of grouping libraries, mapped from the subsystems they depend on for t in tgt_list: if not getattr(t, 'grouping_library', False): continue for dep in t.samba_deps_extended: bld.ASSERT(dep in targets, "grouping library target %s not declared in %s" % (dep, t.sname)) if targets[dep] == 'SUBSYSTEM': grouping[dep] = t.sname # now replace any dependencies on elements of grouping libraries for t in tgt_list: for i in range(len(t.samba_deps_extended)): dep = t.samba_deps_extended[i] if dep in grouping: if t.sname != grouping[dep]: debug("deps: target %s: replacing dependency %s with grouping library %s" % (t.sname, dep, grouping[dep])) t.samba_deps_extended[i] = grouping[dep]
def build_autodeps(bld, t): '''build the set of dependencies for a target''' deps = set() name = real_name(t.sname) targets = LOCAL_CACHE(bld, 'TARGET_TYPE') for sym in t.undefined_symbols: if sym in t.public_symbols: continue if sym in bld.env.symbol_map: depname = bld.env.symbol_map[sym] if depname == [ name ]: # self dependencies aren't interesting continue if t.in_library == depname: # no need to depend on the library we are part of continue if depname[0] in ['c', 'python']: # these don't go into autodeps continue if targets[depname[0]] in [ 'SYSLIB' ]: deps.add(depname[0]) continue t2 = bld.get_tgen_by_name(depname[0]) if len(t2.in_library) != 1: deps.add(depname[0]) continue if t2.in_library == t.in_library: # if we're part of the same library, we don't need to autodep continue deps.add(t2.in_library[0]) t.autodeps = deps
def show_object_duplicates(bld, tgt_list): '''show a list of object files that are included in more than one library or binary''' targets = LOCAL_CACHE(bld, 'TARGET_TYPE') used_by = {} Logs.info("showing duplicate objects") for t in tgt_list: if not targets[t.sname] in [ 'LIBRARY', 'PYTHON' ]: continue for n in getattr(t, 'final_objects', set()): t2 = bld.get_tgen_by_name(n) if not n in used_by: used_by[n] = set() used_by[n].add(t.sname) for n in used_by: if len(used_by[n]) > 1: Logs.info("target '%s' is used by %s" % (n, used_by[n])) Logs.info("showing indirect dependency counts (sorted by count)") def indirect_count(t1, t2): return len(t2.indirect_objects) - len(t1.indirect_objects) sorted_list = sorted(tgt_list, cmp=indirect_count) for t in sorted_list: if len(t.indirect_objects) > 1: Logs.info("%s depends on %u indirect objects" % (t.sname, len(t.indirect_objects)))
def show_final_deps(bld, tgt_list): '''show the final dependencies for all targets''' targets = LOCAL_CACHE(bld, 'TARGET_TYPE') for t in tgt_list: if not targets[t.sname] in ['LIBRARY', 'BINARY', 'PYTHON', 'SUBSYSTEM']: continue debug('deps: final dependencies for target %s: uselib=%s uselib_local=%s add_objects=%s', t.sname, t.uselib, getattr(t, 'uselib_local', []), getattr(t, 'add_objects', []))
def check_duplicate_sources(bld, tgt_list): '''see if we are compiling the same source file more than once without an allow_duplicates attribute''' debug('deps: checking for duplicate sources') targets = LOCAL_CACHE(bld, 'TARGET_TYPE') ret = True global tstart for t in tgt_list: source_list = TO_LIST(getattr(t, 'source', '')) tpath = os.path.normpath( os_path_relpath(t.path.abspath(bld.env), t.env.BUILD_DIRECTORY + '/default')) obj_sources = set() for s in source_list: p = os.path.normpath(os.path.join(tpath, s)) if p in obj_sources: Logs.error("ERROR: source %s appears twice in target '%s'" % (p, t.sname)) sys.exit(1) obj_sources.add(p) t.samba_source_set = obj_sources subsystems = {} # build a list of targets that each source file is part of for t in tgt_list: sources = [] if not targets[t.sname] in ['LIBRARY', 'BINARY', 'PYTHON']: continue for obj in t.add_objects: t2 = t.bld.get_tgen_by_name(obj) source_set = getattr(t2, 'samba_source_set', set()) for s in source_set: if not s in subsystems: subsystems[s] = {} if not t.sname in subsystems[s]: subsystems[s][t.sname] = [] subsystems[s][t.sname].append(t2.sname) for s in subsystems: if len(subsystems[s]) > 1 and Options.options.SHOW_DUPLICATES: Logs.warn("WARNING: source %s is in more than one target: %s" % (s, subsystems[s].keys())) for tname in subsystems[s]: if len(subsystems[s][tname]) > 1: raise Utils.WafError( "ERROR: source %s is in more than one subsystem of target '%s': %s" % (s, tname, subsystems[s][tname])) return ret
def expand_subsystem_deps(bld): '''expand the reverse dependencies resulting from subsystem attributes of modules. This is walking over the complete list of declared subsystems, and expands the samba_deps_extended list for any module<->subsystem dependencies''' subsystem_list = LOCAL_CACHE(bld, 'INIT_FUNCTIONS') targets = LOCAL_CACHE(bld, 'TARGET_TYPE') for subsystem_name in subsystem_list: bld.ASSERT(subsystem_name in targets, "Subsystem target %s not declared" % subsystem_name) type = targets[subsystem_name] if type == 'DISABLED' or type == 'EMPTY': continue # for example, # subsystem_name = dcerpc_server (a subsystem) # subsystem = dcerpc_server (a subsystem object) # module_name = rpc_epmapper (a module within the dcerpc_server subsystem) # module = rpc_epmapper (a module object within the dcerpc_server subsystem) subsystem = bld.get_tgen_by_name(subsystem_name) bld.ASSERT(subsystem is not None, "Unable to find subsystem %s" % subsystem_name) for d in subsystem_list[subsystem_name]: module_name = d['TARGET'] module_type = targets[module_name] if module_type in ['DISABLED', 'EMPTY']: continue bld.ASSERT( subsystem is not None, "Subsystem target %s for %s (%s) not found" % (subsystem_name, module_name, module_type)) if module_type in ['SUBSYSTEM']: # if a module is a plain object type (not a library) then the # subsystem it is part of needs to have it as a dependency, so targets # that depend on this subsystem get the modules of that subsystem subsystem.samba_deps_extended.append(module_name) subsystem.samba_deps_extended = unique_list( subsystem.samba_deps_extended)
def save_samba_deps(bld, tgt_list): '''save the dependency calculations between builds, to make further builds faster''' denv = ConfigSet.ConfigSet() denv.version = savedeps_version denv.savedeps_inputs = savedeps_inputs denv.savedeps_outputs = savedeps_outputs denv.input = {} denv.output = {} denv.outenv = {} denv.caches = {} denv.envvar = {} denv.files = {} for f in savedeps_files: denv.files[f] = os.stat(os.path.join(bld.srcnode.abspath(), f)).st_mtime for c in savedeps_caches: denv.caches[c] = LOCAL_CACHE(bld, c) for e in savedeps_envvars: denv.envvar[e] = bld.env[e] for t in tgt_list: # save all the input attributes for each target tdeps = {} for attr in savedeps_inputs: v = getattr(t, attr, None) if v is not None: tdeps[attr] = v if tdeps != {}: denv.input[t.sname] = tdeps # save all the output attributes for each target tdeps = {} for attr in savedeps_outputs: v = getattr(t, attr, None) if v is not None: tdeps[attr] = v if tdeps != {}: denv.output[t.sname] = tdeps tdeps = {} for attr in savedeps_outenv: if attr in t.env: tdeps[attr] = t.env[attr] if tdeps != {}: denv.outenv[t.sname] = tdeps depsfile = os.path.join(bld.cache_dir, "sambadeps") denv.store_fast(depsfile)
def symbols_dupcheck(task, fail_on_error=False): '''check for symbols defined in two different subsystems''' bld = task.env.bld tgt_list = get_tgt_list(bld) targets = LOCAL_CACHE(bld, 'TARGET_TYPE') build_library_dict(bld, tgt_list) for t in tgt_list: if t.samba_type == 'BINARY': binname = os_path_relpath(t.link_task.outputs[0].abspath(bld.env), os.getcwd()) symbols_dupcheck_binary(bld, binname, fail_on_error)
def add_samba_attributes(bld, tgt_list): '''ensure a target has a the required samba attributes''' targets = LOCAL_CACHE(bld, 'TARGET_TYPE') for t in tgt_list: if t.name != '': t.sname = t.name else: t.sname = t.target t.samba_type = targets[t.sname] t.samba_abspath = t.path.abspath(bld.env) t.samba_deps_extended = t.samba_deps[:] t.samba_includes_extended = TO_LIST(t.samba_includes)[:] t.cflags = getattr(t, 'samba_cflags', '')
def check_orphaned_targets(bld, tgt_list): '''check if any build targets are orphaned''' target_dict = LOCAL_CACHE(bld, 'TARGET_TYPE') debug('deps: checking for orphaned targets') for t in tgt_list: if getattr(t, 'samba_used', False): continue type = target_dict[t.sname] if not type in ['BINARY', 'LIBRARY', 'MODULE', 'ET', 'PYTHON']: if re.search('^PIDL_', t.sname) is None: Logs.warn( "Target %s of type %s is unused by any other target" % (t.sname, type))
def check_group_ordering(bld, tgt_list): '''see if we have any dependencies that violate the group ordering It is an error for a target to depend on a target from a later build group ''' def group_name(g): tm = bld.task_manager return [x for x in tm.groups_names if id(tm.groups_names[x]) == id(g)][0] for g in bld.task_manager.groups: gname = group_name(g) for t in g.tasks_gen: t.samba_group = gname grp_map = {} idx = 0 for g in bld.task_manager.groups: name = group_name(g) grp_map[name] = idx idx += 1 targets = LOCAL_CACHE(bld, 'TARGET_TYPE') ret = True for t in tgt_list: tdeps = getattr(t, 'add_objects', []) + getattr(t, 'uselib_local', []) for d in tdeps: t2 = bld.get_tgen_by_name(d) if t2 is None: continue map1 = grp_map[t.samba_group] map2 = grp_map[t2.samba_group] if map2 > map1: Logs.error( "Target %r in build group %r depends on target %r from later build group %r" % (t.sname, t.samba_group, t2.sname, t2.samba_group)) ret = False return ret
def rewrite_compile_targets(): '''cope with the bin/ form of compile target''' if not Options.options.compile_targets: return bld = fake_build_environment(info=False) targets = LOCAL_CACHE(bld, 'TARGET_TYPE') tlist = [] for t in Options.options.compile_targets.split(','): if not os.path.islink(t): tlist.append(t) continue link = os.readlink(t) list = link.split('/') for name in [list[-1], '/'.join(list[-2:])]: if name in targets: tlist.append(name) continue Options.options.compile_targets = ",".join(tlist)
def includes_objects(bld, t, chain, inc_loops): '''recursively calculate the includes object dependencies for a target includes dependencies come from either library or object dependencies ''' ret = getattr(t, 'includes_objects', None) if ret is not None: return ret ret = t.direct_objects.copy() ret = ret.union(t.direct_libs) for obj in t.direct_objects: if obj in chain: dependency_loop(inc_loops, t, obj) continue chain.add(obj) t2 = bld.get_tgen_by_name(obj) r2 = includes_objects(bld, t2, chain, inc_loops) chain.remove(obj) ret = ret.union(t2.direct_objects) ret = ret.union(r2) for lib in t.direct_libs: if lib in chain: dependency_loop(inc_loops, t, lib) continue chain.add(lib) t2 = bld.get_tgen_by_name(lib) if t2 is None: targets = LOCAL_CACHE(bld, 'TARGET_TYPE') Logs.error('Target %s of type %s not found in direct_libs for %s' % ( lib, targets[lib], t.sname)) sys.exit(1) r2 = includes_objects(bld, t2, chain, inc_loops) chain.remove(lib) ret = ret.union(t2.direct_objects) ret = ret.union(r2) t.includes_objects = ret return ret
def check_dependencies(bld, t): '''check for depenencies that should be changed''' if bld.get_tgen_by_name(t.sname + ".objlist"): return targets = LOCAL_CACHE(bld, 'TARGET_TYPE') remaining = t.undefined_symbols.copy() remaining = remaining.difference(t.public_symbols) sname = real_name(t.sname) deps = set(t.samba_deps) for d in t.samba_deps: if targets[d] in ['EMPTY', 'DISABLED', 'SYSLIB', 'GENERATOR']: continue bld.ASSERT(d in bld.env.public_symbols, "Failed to find symbol list for dependency '%s'" % d) diff = remaining.intersection(bld.env.public_symbols[d]) if not diff and targets[sname] != 'LIBRARY': Logs.info("Target '%s' has no dependency on %s" % (sname, d)) else: remaining = remaining.difference(diff) t.unsatisfied_symbols = set() needed = {} for sym in remaining: if sym in bld.env.symbol_map: dep = bld.env.symbol_map[sym] if not dep[0] in needed: needed[dep[0]] = set() needed[dep[0]].add(sym) else: t.unsatisfied_symbols.add(sym) for dep in needed: Logs.info("Target '%s' should add dep '%s' for symbols %s" % (sname, dep, " ".join(needed[dep])))
def build_symbol_sets(bld, tgt_list): '''build the public_symbols and undefined_symbols attributes for each target''' if bld.env.public_symbols: return objlist = [] # list of object file objmap = {} # map from object filename to target (subsystem) name for t in tgt_list: t.public_symbols = set() t.undefined_symbols = set() t.used_symbols = set() for tsk in getattr(t, 'compiled_tasks', []): for output in tsk.outputs: objpath = output.abspath(bld.env) objlist.append(objpath) objmap[objpath] = t symbols = symbols_extract(bld, objlist) for obj in objlist: t = objmap[obj] t.public_symbols = t.public_symbols.union(symbols[obj]["PUBLIC"]) t.undefined_symbols = t.undefined_symbols.union(symbols[obj]["UNDEFINED"]) t.used_symbols = t.used_symbols.union(symbols[obj]["UNDEFINED"]) t.undefined_symbols = t.undefined_symbols.difference(t.public_symbols) # and the reverse map of public symbols to subsystem name bld.env.symbol_map = {} for t in tgt_list: for s in t.public_symbols: if not s in bld.env.symbol_map: bld.env.symbol_map[s] = [] bld.env.symbol_map[s].append(real_name(t.sname)) targets = LOCAL_CACHE(bld, 'TARGET_TYPE') bld.env.public_symbols = {} for t in tgt_list: name = real_name(t.sname) if name in bld.env.public_symbols: bld.env.public_symbols[name] = bld.env.public_symbols[name].union(t.public_symbols) else: bld.env.public_symbols[name] = t.public_symbols if t.samba_type == 'LIBRARY': for dep in t.add_objects: t2 = bld.get_tgen_by_name(dep) bld.ASSERT(t2 is not None, "Library '%s' has unknown dependency '%s'" % (name, dep)) bld.env.public_symbols[name] = bld.env.public_symbols[name].union(t2.public_symbols) bld.env.used_symbols = {} for t in tgt_list: name = real_name(t.sname) if name in bld.env.used_symbols: bld.env.used_symbols[name] = bld.env.used_symbols[name].union(t.used_symbols) else: bld.env.used_symbols[name] = t.used_symbols if t.samba_type == 'LIBRARY': for dep in t.add_objects: t2 = bld.get_tgen_by_name(dep) bld.ASSERT(t2 is not None, "Library '%s' has unknown dependency '%s'" % (name, dep)) bld.env.used_symbols[name] = bld.env.used_symbols[name].union(t2.used_symbols)
def calculate_final_deps(bld, tgt_list, loops): '''calculate the final library and object dependencies''' for t in tgt_list: # start with the maximum possible list t.final_libs = t.direct_libs.union(indirect_libs(bld, t, set(), loops)) t.final_objects = t.direct_objects.union(indirect_objects(bld, t, set(), loops)) for t in tgt_list: # don't depend on ourselves if t.sname in t.final_libs: t.final_libs.remove(t.sname) if t.sname in t.final_objects: t.final_objects.remove(t.sname) # handle any non-shared binaries for t in tgt_list: if t.samba_type == 'BINARY' and bld.NONSHARED_BINARY(t.sname): subsystem_list = LOCAL_CACHE(bld, 'INIT_FUNCTIONS') targets = LOCAL_CACHE(bld, 'TARGET_TYPE') # replace lib deps with objlist deps for l in t.final_libs: objname = l + '.objlist' t2 = bld.get_tgen_by_name(objname) if t2 is None: Logs.error('ERROR: subsystem %s not found' % objname) sys.exit(1) t.final_objects.add(objname) t.final_objects = t.final_objects.union(extended_objects(bld, t2, set())) if l in subsystem_list: # its a subsystem - we also need the contents of any modules for d in subsystem_list[l]: module_name = d['TARGET'] if targets[module_name] == 'LIBRARY': objname = module_name + '.objlist' elif targets[module_name] == 'SUBSYSTEM': objname = module_name else: continue t2 = bld.get_tgen_by_name(objname) if t2 is None: Logs.error('ERROR: subsystem %s not found' % objname) sys.exit(1) t.final_objects.add(objname) t.final_objects = t.final_objects.union(extended_objects(bld, t2, set())) t.final_libs = set() # find any library loops for t in tgt_list: if t.samba_type in ['LIBRARY', 'PYTHON']: for l in t.final_libs.copy(): t2 = bld.get_tgen_by_name(l) if t.sname in t2.final_libs: if getattr(bld.env, "ALLOW_CIRCULAR_LIB_DEPENDENCIES", False): # we could break this in either direction. If one of the libraries # has a version number, and will this be distributed publicly, then # we should make it the lower level library in the DAG Logs.warn('deps: removing library loop %s from %s' % (t.sname, t2.sname)) dependency_loop(loops, t, t2.sname) t2.final_libs.remove(t.sname) else: Logs.error('ERROR: circular library dependency between %s and %s' % (t.sname, t2.sname)) show_library_loop(bld, t.sname, t2.sname, t.sname, set()) show_library_loop(bld, t2.sname, t.sname, t2.sname, set()) sys.exit(1) for loop in loops: debug('deps: Found dependency loops for target %s : %s', loop, loops[loop]) # we now need to make corrections for any library loops we broke up # any target that depended on the target of the loop and doesn't # depend on the source of the loop needs to get the loop source added for type in ['BINARY','PYTHON','LIBRARY','BINARY']: for t in tgt_list: if t.samba_type != type: continue for loop in loops: if loop in t.final_libs: diff = loops[loop].difference(t.final_libs) if t.sname in diff: diff.remove(t.sname) if t.sname in diff: diff.remove(t.sname) # make sure we don't recreate the loop again! for d in diff.copy(): t2 = bld.get_tgen_by_name(d) if t2.samba_type == 'LIBRARY': if t.sname in t2.final_libs: debug('deps: removing expansion %s from %s', d, t.sname) diff.remove(d) if diff: debug('deps: Expanded target %s by loop %s libraries (loop %s) %s', t.sname, loop, loops[loop], diff) t.final_libs = t.final_libs.union(diff) # remove objects that are also available in linked libs count = 0 while reduce_objects(bld, tgt_list): count += 1 if count > 100: Logs.warn("WARNING: Unable to remove all inter-target object duplicates") break debug('deps: Object reduction took %u iterations', count) # add in any syslib dependencies for t in tgt_list: if not t.samba_type in ['BINARY','PYTHON','LIBRARY','SUBSYSTEM']: continue syslibs = set() for d in t.final_objects: t2 = bld.get_tgen_by_name(d) syslibs = syslibs.union(t2.direct_syslibs) # this adds the indirect syslibs as well, which may not be needed # depending on the linker flags for d in t.final_libs: t2 = bld.get_tgen_by_name(d) syslibs = syslibs.union(t2.direct_syslibs) t.final_syslibs = syslibs # find any unresolved library loops lib_loop_error = False for t in tgt_list: if t.samba_type in ['LIBRARY', 'PYTHON']: for l in t.final_libs.copy(): t2 = bld.get_tgen_by_name(l) if t.sname in t2.final_libs: Logs.error('ERROR: Unresolved library loop %s from %s' % (t.sname, t2.sname)) lib_loop_error = True if lib_loop_error: sys.exit(1) debug('deps: removed duplicate dependencies')
def SAMBA_PIDL(bld, pname, source, options='', output_dir='.', generate_tables=True): '''Build a IDL file using pidl. This will produce up to 13 output files depending on the options used''' bname = source[0:-4] # strip off the .idl suffix bname = os.path.basename(bname) name = "%s_%s" % (pname, bname.upper()) if not SET_TARGET_TYPE(bld, name, 'PIDL'): return bld.SET_BUILD_GROUP('build_source') # the output files depend on the options used. Use this dictionary # to map between the options and the resulting file names options_map = { '--header': '%s.h', '--ndr-parser': 'ndr_%s.c ndr_%s.h', '--samba3-ndr-server': 'srv_%s.c srv_%s.h', '--samba3-ndr-client': 'cli_%s.c cli_%s.h', '--server': 'ndr_%s_s.c', '--client': 'ndr_%s_c.c ndr_%s_c.h', '--python': 'py_%s.c', '--tdr-parser': 'tdr_%s.c tdr_%s.h', '--dcom-proxy': '%s_p.c', '--com-header': 'com_%s.h' } table_header_idx = None out_files = [] options_list = TO_LIST(options) for o in options_list: if o in options_map: ofiles = TO_LIST(options_map[o]) for f in ofiles: out_files.append(os.path.join(output_dir, f % bname)) if f == 'ndr_%s.h': # remember this one for the tables generation table_header_idx = len(out_files) - 1 # depend on the full pidl sources source = TO_LIST(source) try: pidl_src_nodes = bld.pidl_files_cache except AttributeError: bld.pidl_files_cache = bld.srcnode.ant_glob('pidl/lib/Parse/**/*.pm', flat=False) bld.pidl_files_cache.extend(bld.srcnode.ant_glob('pidl', flat=False)) pidl_src_nodes = bld.pidl_files_cache # the cd .. is needed because pidl currently is sensitive to the directory it is run in cpp = "" cc = "" if bld.CONFIG_SET("CPP") and bld.CONFIG_GET("CPP") != "": if isinstance(bld.CONFIG_GET("CPP"), list): cpp = 'CPP="%s"' % " ".join(bld.CONFIG_GET("CPP")) else: cpp = 'CPP="%s"' % bld.CONFIG_GET("CPP") if cpp == "CPP=xlc_r": cpp = "" if bld.env['PIDL_DEVELOPER_MODE']: pidl_dev = 'PIDL_DEVELOPER=1 ' else: pidl_dev = '' if bld.CONFIG_SET("CC"): if isinstance(bld.CONFIG_GET("CC"), list): cc = 'CC="%s"' % " ".join(bld.CONFIG_GET("CC")) else: cc = 'CC="%s"' % bld.CONFIG_GET("CC") t = bld( rule= 'cd ${PIDL_LAUNCH_DIR} && %s%s %s ${PERL} ${PIDL} --quiet ${OPTIONS} --outputdir ${OUTPUTDIR} -- "${IDLSRC}"' % (pidl_dev, cpp, cc), ext_out='.c', before='c', update_outputs=True, shell=True, source=source, target=out_files, name=name, samba_type='PIDL') t.env.PIDL_LAUNCH_DIR = bld.srcnode.path_from(bld.bldnode) pnode = bld.srcnode.find_resource('pidl/pidl') t.env.PIDL = pnode.path_from(bld.srcnode) t.env.OPTIONS = TO_LIST(options) snode = t.path.find_resource(source[0]) t.env.IDLSRC = snode.path_from(bld.srcnode) t.env.OUTPUTDIR = bld.bldnode.path_from( bld.srcnode) + '/' + bld.path.find_dir(output_dir).path_from( bld.srcnode) bld.add_manual_dependency(snode, pidl_src_nodes) if generate_tables and table_header_idx is not None: pidl_headers = LOCAL_CACHE(bld, 'PIDL_HEADERS') pidl_headers[name] = [ bld.path.find_or_declare(out_files[table_header_idx]) ] t.more_includes = '#' + bld.path.path_from(bld.srcnode)
def reduce_objects(bld, tgt_list): '''reduce objects by looking for indirect object dependencies''' targets = LOCAL_CACHE(bld, 'TARGET_TYPE') rely_on = {} for t in tgt_list: t.extended_objects = None changed = False for type in ['BINARY', 'PYTHON', 'LIBRARY', 'PLUGIN']: for t in tgt_list: if t.samba_type != type: continue # if we will indirectly link to a target then we don't need it new = t.final_objects.copy() for l in t.final_libs: t2 = bld.get_tgen_by_name(l) t2_obj = extended_objects(bld, t2, set()) dup = new.intersection(t2_obj) if t.sname in rely_on: dup = dup.difference(rely_on[t.sname]) if dup: # Do not remove duplicates of BUILTINS for d in iter(dup.copy()): dtype = targets[d] if dtype == 'BUILTIN': debug( 'deps: BUILTIN SKIP: removing dups from %s of type %s: %s also in %s %s', t.sname, t.samba_type, d, t2.samba_type, l) dup.remove(d) if len(dup) == 0: continue debug( 'deps: removing dups from %s of type %s: %s also in %s %s', t.sname, t.samba_type, dup, t2.samba_type, l) new = new.difference(dup) changed = True if not l in rely_on: rely_on[l] = set() rely_on[l] = rely_on[l].union(dup) for n in iter(new.copy()): # if we got the builtin version as well # as the native one, we keep using the # builtin one and remove the rest. # Otherwise our check_duplicate_sources() # checks would trigger! if n.endswith('.builtin.objlist'): unused = n.replace('.builtin.objlist', '.objlist') if unused in new: new.remove(unused) unused = n.replace('.builtin.objlist', '') if unused in new: new.remove(unused) t.final_objects = new if not changed: return False # add back in any objects that were relied upon by the reduction rules for r in rely_on: t = bld.get_tgen_by_name(r) t.final_objects = t.final_objects.union(rely_on[r]) return True
def add_init_functions(self): '''This builds the right set of init functions''' bld = self.bld subsystems = LOCAL_CACHE(bld, 'INIT_FUNCTIONS') # cope with the separated object lists from BINARY and LIBRARY targets sname = self.sname if sname.endswith('.objlist'): sname = sname[0:-8] modules = [] if sname in subsystems: modules.append(sname) m = getattr(self, 'samba_modules', None) if m is not None: modules.extend(TO_LIST(m)) m = getattr(self, 'samba_subsystem', None) if m is not None: modules.append(m) if 'pyembed' in self.features: return sentinel = getattr(self, 'init_function_sentinel', 'NULL') targets = LOCAL_CACHE(bld, 'TARGET_TYPE') cflags = getattr(self, 'samba_cflags', [])[:] if modules == []: sname = sname.replace('-','_') sname = sname.replace('.','_') sname = sname.replace('/','_') cflags.append('-DSTATIC_%s_MODULES=%s' % (sname, sentinel)) if sentinel == 'NULL': proto = "extern void __%s_dummy_module_proto(void)" % (sname) cflags.append('-DSTATIC_%s_MODULES_PROTO=%s' % (sname, proto)) self.cflags = cflags return for m in modules: bld.ASSERT(m in subsystems, "No init_function defined for module '%s' in target '%s'" % (m, self.sname)) init_fn_list = [] for d in subsystems[m]: if targets[d['TARGET']] != 'DISABLED': init_fn_list.append(d['INIT_FUNCTION']) if init_fn_list == []: cflags.append('-DSTATIC_%s_MODULES=%s' % (m, sentinel)) if sentinel == 'NULL': proto = "extern void __%s_dummy_module_proto(void)" % (m) cflags.append('-DSTATIC_%s_MODULES_PROTO=%s' % (m, proto)) else: cflags.append('-DSTATIC_%s_MODULES=%s' % (m, ','.join(init_fn_list) + ',' + sentinel)) proto='' for f in init_fn_list: proto += '_MODULE_PROTO(%s)' % f proto += "extern void __%s_dummy_module_proto(void)" % (m) cflags.append('-DSTATIC_%s_MODULES_PROTO=%s' % (m, proto)) self.cflags = cflags
def SET_SYSLIB_DEPS(conf, target, deps): '''setup some implied dependencies for a SYSLIB''' cache = LOCAL_CACHE(conf, 'SYSLIB_DEPS') cache[target] = deps
def load_samba_deps(bld, tgt_list): '''load a previous set of build dependencies if possible''' depsfile = os.path.join(bld.bldnode.abspath(), "sambadeps") denv = ConfigSet.ConfigSet() try: debug('deps: checking saved dependencies') denv.load_fast(depsfile) if (denv.version != savedeps_version or denv.savedeps_inputs != savedeps_inputs or denv.savedeps_outputs != savedeps_outputs): return False except Exception: return False # check if critical files have changed for f in savedeps_files: if f not in denv.files: return False if denv.files[f] != os.stat(os.path.join(bld.srcnode.abspath(), f)).st_mtime: return False # check if caches are the same for c in savedeps_caches: if c not in denv.caches or denv.caches[c] != LOCAL_CACHE(bld, c): return False # check if caches are the same for e in savedeps_envvars: if e not in denv.envvar or denv.envvar[e] != bld.env[e]: return False # check inputs are the same for t in tgt_list: tdeps = {} for attr in savedeps_inputs: v = getattr(t, attr, None) if v is not None: tdeps[attr] = v if t.sname in denv.input: olddeps = denv.input[t.sname] else: olddeps = {} if tdeps != olddeps: #print '%s: \ntdeps=%s \nodeps=%s' % (t.sname, tdeps, olddeps) return False # put outputs in place for t in tgt_list: if not t.sname in denv.output: continue tdeps = denv.output[t.sname] for a in tdeps: setattr(t, a, tdeps[a]) # put output env vars in place for t in tgt_list: if not t.sname in denv.outenv: continue tdeps = denv.outenv[t.sname] for a in tdeps: t.env[a] = tdeps[a] debug('deps: loaded saved dependencies') return True
def replace_builtin_subsystem_deps(bld, tgt_list): '''replace dependencies based on builtin subsystems/libraries ''' targets = LOCAL_CACHE(bld, 'TARGET_TYPE') # If either the target or the dependency require builtin linking # we should replace the dependency for t in tgt_list: t_require_builtin_deps = getattr(t, 'samba_require_builtin_deps', False) if t_require_builtin_deps: debug("deps: target %s: requires builtin dependencies..." % (t.sname)) else: debug("deps: target %s: does not require builtin dependencies..." % (t.sname)) replacing = {} for dep in t.samba_deps_extended: bld.ASSERT( dep in targets, "target %s: dependency target %s not declared" % (t.sname, dep)) dtype = targets[dep] bld.ASSERT( dtype != 'BUILTIN', "target %s: dependency target %s is BUILTIN" % (t.sname, dep)) bld.ASSERT( dtype != 'PLUGIN', "target %s: dependency target %s is PLUGIN" % (t.sname, dep)) if dtype not in ['SUBSYSTEM', 'LIBRARY']: debug("deps: target %s: keep %s dependency %s" % (t.sname, dtype, dep)) continue dt = bld.get_tgen_by_name(dep) bld.ASSERT( dt is not None, "target %s: dependency target %s not found by name" % (t.sname, dep)) dt_require_builtin_deps = getattr(dt, 'samba_require_builtin_deps', False) if not dt_require_builtin_deps and not t_require_builtin_deps: # both target and dependency don't require builtin linking continue sdt = getattr(dt, 'samba_builtin_subsystem', None) if not t_require_builtin_deps: if sdt is None: debug( "deps: target %s: dependency %s requires builtin deps only" % (t.sname, dep)) continue debug( "deps: target %s: dependency %s requires builtin linking" % (t.sname, dep)) bld.ASSERT( sdt is not None, "target %s: dependency target %s is missing samba_builtin_subsystem" % (t.sname, dep)) sdep = sdt.sname bld.ASSERT( sdep in targets, "target %s: builtin dependency target %s (from %s) not declared" % (t.sname, sdep, dep)) sdt = targets[sdep] bld.ASSERT( sdt == 'BUILTIN', "target %s: builtin dependency target %s (from %s) is not BUILTIN" % (t.sname, sdep, dep)) replacing[dep] = sdep for i in range(len(t.samba_deps_extended)): dep = t.samba_deps_extended[i] if dep in replacing: sdep = replacing[dep] debug( "deps: target %s: replacing dependency %s with builtin subsystem %s" % (t.sname, dep, sdep)) t.samba_deps_extended[i] = sdep