diff options
author | lloyd <[email protected]> | 2009-07-17 16:14:28 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2009-07-17 16:14:28 +0000 |
commit | 361105e0a35814e02147aec70cea705bc36a49d0 (patch) | |
tree | 50cabff6759974a24724fe912c0ff3701fa2d10b | |
parent | 63f978c3ec5664baa7ab1e5267f94b4d49c68bdb (diff) |
The previous dependency resolution logic would go into an infinite loop
when faced with the full set of module interdependencies. Use a new
algorithm that handles it OK.
-rwxr-xr-x | configure.py | 153 |
1 files changed, 87 insertions, 66 deletions
diff --git a/configure.py b/configure.py index f8c0affa4..a2bf27954 100755 --- a/configure.py +++ b/configure.py @@ -260,7 +260,11 @@ def lex_me_harder(infofile, to_obj, allowed_groups, name_val_pairs): to_obj.lives_in = dirname if basename == 'info.txt': - (dummy,to_obj.basename) = os.path.split(dirname) + (obj_dir,to_obj.basename) = os.path.split(dirname) + if os.access(os.path.join(obj_dir, 'info.txt'), os.R_OK): + to_obj.parent_module = os.path.basename(obj_dir) + else: + to_obj.parent_module = None else: to_obj.basename = basename @@ -349,6 +353,24 @@ class ModuleInfo(object): else: self.uses_tr1 = False + def compatible_cpu(self, arch, cpu): + return self.arch == [] or (arch in self.arch or cpu in self.arch) + + def compatible_os(self, os): + return self.os == [] or os in self.os + + def compatible_compiler(self, cc, with_tr1): + if self.uses_tr1 and with_tr1 not in ['boost', 'system']: + return False + return self.cc == [] or cc in self.cc + + def dependencies(self): + # utils is an implicit dep (contains types, etc) + deps = self.requires + ['utils'] + if self.parent_module != None: + deps.append(self.parent_module) + return deps + def __cmp__(self, other): if self.basename < other.basename: return -1 @@ -740,82 +762,78 @@ def create_template_vars(build_config, options, modules, cc, arch, osinfo): Determine which modules to load based on options, target, etc """ def choose_modules_to_use(options, modules): - def enable_module(module, for_dep = False): - # First check options for --enable-modules/--disable-modules - - if module.basename in options.disabled_modules: - return (False, 'disabled by user') - - # If it was specifically requested, skip most tests (trust the user) - if module.basename not in options.enabled_modules: - if module.arch != [] and options.arch not in module.arch \ - and options.cpu not in module.arch: - return (False, 'CPU incompatible') - - if module.os != [] and options.os not in module.os: - return (False, 'OS incompatable') - - if module.cc != [] and options.compiler not in module.cc: - return (False, 'compiler incompatible') - - if module.load_on == 'dep' and not for_dep: - return (False, 'loaded only if needed by dependency') - elif module.load_on == 'request': - return (False, 'loaded on request only') - elif module.load_on == 'never': - return (False, 'disabled as buggy') - elif module.load_on == 'asm_ok' and not options.asm_ok: - return (False, 'load_on asm_ok only') - - # TR1 checks - if module.uses_tr1: - if options.with_tr1 != 'boost' and options.with_tr1 != 'system': - return (False, 'TR1 disabled') - - # dependency checks - deps = [] - deps_met = True - for req in module.requires: - for mod in req.split('|'): - (can_enable, deps_or_reason) = enable_module(modules[mod], True) - if can_enable: - deps.append(mod) - deps += deps_or_reason - break - else: - deps_met = False - - if deps_met: - return (True, deps) - else: - return (False, 'dependency failure') - use_module = {} + to_load = [] + maybe_dep = [] not_using_because = {} - for (name,module) in modules.iteritems(): - if use_module.get(name, False) is False: - (should_use, deps_or_reason) = enable_module(module) - - use_module[name] = should_use - - if should_use: - for dep in deps_or_reason: - use_module[dep] = True + def cannot_use_because(mod, reason): + not_using_because.setdefault(reason, []).append(mod) + + for (modname, module) in modules.iteritems(): + if modname in options.disabled_modules: + cannot_use_because(modname, 'disabled by user') + elif not module.compatible_cpu(options.arch, options.cpu): + cannot_use_because(modname, 'CPU incompatible') + elif not module.compatible_os(options.os): + cannot_use_because(modname, 'OS incompatible') + elif not module.compatible_compiler(options.compiler, + options.with_tr1): + cannot_use_because(modname, 'compiler incompatible') + else: + if module.load_on == 'never': + cannot_use_because(modname, 'disabled as buggy') + elif module.load_on == 'request': + cannot_use_because(modname, 'loaded on request only') + elif module.load_on == 'dep': + maybe_dep.append(modname) + elif module.load_on in ['auto', 'asm_ok']: + if module.load_on == 'asm_ok' and not options.asm_ok: + cannot_use_because(modname, 'uses assembly and --disable-asm set') + else: + to_load.append(modname) else: - reason = deps_or_reason - not_using_because.setdefault(reason, []).append(module.basename) + logging.warning('Unknown load_on %s in %s' % (module.load_on, modname)) + + dependency_failure = True + + while dependency_failure: + dependency_failure = False + for modname in to_load: + for deplist in map(lambda s: s.split('|'), + modules[modname].dependencies()): + + dep_met = False + for mod in deplist: + if dep_met is True: + break + + if mod in to_load: + dep_met = True + elif mod in maybe_dep: + maybe_dep.remove(mod) + to_load.append(mod) + dep_met = True + + if dep_met == False: + dependency_failure = True + if modname in to_load: + to_load.remove(modname) + if modname in maybe_dep: + maybe_dep.remove(modname) + cannot_use_because(modname, 'of dependency failure') + + for not_a_dep in maybe_dep: + cannot_use_because(not_a_dep, 'loaded only if needed by dependency') for reason in sorted(not_using_because.keys()): - disabled_mods = [mod for mod in not_using_because[reason] if not use_module.get(mod, False)] + disabled_mods = sorted(set([mod for mod in not_using_because[reason]])) if disabled_mods != []: logging.info('Skipping mod because %s - %s' % ( reason, ' '.join(disabled_mods))) - return [modules[name] - for (name,useme) in use_module.items() - if useme] + return [modules[mod] for mod in to_load] """ Load the info files about modules, targets, etc @@ -934,6 +952,9 @@ def setup_build(build_config, options, template_vars): for header_file in build_config.headers: portable_symlink(header_file, build_config.full_include_dir) +""" +Main driver +""" def main(argv = None): if argv is None: argv = sys.argv |