def recurse(subpath): # Load the LLVMBuild file. llvmbuild_path = os.path.join(llvmbuild_source_root + subpath, 'LLVMBuild.txt') if not os.path.exists(llvmbuild_path): fatal("missing LLVMBuild.txt file at: %r" % (llvmbuild_path,)) # Parse the components from it. common,info_iter = componentinfo.load_from_path(llvmbuild_path, subpath) for info in info_iter: yield info # Recurse into the specified subdirectories. for subdir in common.get_list("subdirectories"): for item in recurse(os.path.join(subpath, subdir)): yield item
def recurse(subpath): # Load the LLVMBuild file. llvmbuild_path = os.path.join(llvmbuild_source_root + subpath, 'LLVMBuild.txt') if not os.path.exists(llvmbuild_path): fatal("missing LLVMBuild.txt file at: %r" % (llvmbuild_path, )) # Parse the components from it. common, info_iter = componentinfo.load_from_path( llvmbuild_path, subpath) for info in info_iter: yield info # Recurse into the specified subdirectories. for subdir in common.get_list("subdirectories"): for item in recurse(os.path.join(subpath, subdir)): yield item
def visit_component_info(ci, current_stack, current_set): # Check for a cycles. if ci in current_set: # We found a cycle, report it and error out. # cycle_description = ' -> '.join( # '%r (%s)' % (ci.name, relation) # for relation,ci in current_stack) # fatal("found cycle to %r after following: %s -> %s" % ( # ci.name, cycle_description, ci.name)) return # If we have already visited this item, we are done. if ci not in components_to_visit: return # Otherwise, mark the component info as visited and traverse. components_to_visit.remove(ci) # Validate the parent reference, which we treat specially. if ci.parent is not None: parent = self.component_info_map.get(ci.parent) if parent is None: fatal("component %r has invalid reference %r (via %r)" % (ci.name, ci.parent, 'parent')) ci.set_parent_instance(parent) for relation, referent_name in ci.get_component_references(): # Validate that the reference is ok. referent = self.component_info_map.get(referent_name) if referent is None: fatal("component %r has invalid reference %r (via %r)" % (ci.name, referent_name, relation)) # Visit the reference. current_stack.append((relation, ci)) current_set.add(ci) visit_component_info(referent, current_stack, current_set) current_set.remove(ci) current_stack.pop() # Finally, add the component info to the ordered list. self.ordered_component_infos.append(ci)
def find_special_group(name): info = info_map.get(name) if info is None: fatal("expected project to contain special %r component" % (name, )) if info.type_name != 'LibraryGroup': fatal("special component %r should be a LibraryGroup" % (name, )) if info.required_libraries: fatal("special component %r must have empty %r list" % (name, 'required_libraries')) if info.add_to_library_groups: fatal("special component %r must have empty %r list" % (name, 'add_to_library_groups')) info._is_special_group = True return info
def find_special_group(name): info = info_map.get(name) if info is None: fatal("expected project to contain special %r component" % ( name,)) if info.type_name != 'LibraryGroup': fatal("special component %r should be a LibraryGroup" % ( name,)) if info.required_libraries: fatal("special component %r must have empty %r list" % ( name, 'required_libraries')) if info.add_to_library_groups: fatal("special component %r must have empty %r list" % ( name, 'add_to_library_groups')) info._is_special_group = True return info
def visit_component_info(ci, current_stack, current_set): # Check for a cycles. if ci in current_set: # We found a cycle, report it and error out. cycle_description = ' -> '.join( '%r (%s)' % (ci.name, relation) for relation,ci in current_stack) fatal("found cycle to %r after following: %s -> %s" % ( ci.name, cycle_description, ci.name)) # If we have already visited this item, we are done. if ci not in components_to_visit: return # Otherwise, mark the component info as visited and traverse. components_to_visit.remove(ci) # Validate the parent reference, which we treat specially. if ci.parent is not None: parent = self.component_info_map.get(ci.parent) if parent is None: fatal("component %r has invalid reference %r (via %r)" % ( ci.name, ci.parent, 'parent')) ci.set_parent_instance(parent) for relation,referent_name in ci.get_component_references(): # Validate that the reference is ok. referent = self.component_info_map.get(referent_name) if referent is None: fatal("component %r has invalid reference %r (via %r)" % ( ci.name, referent_name, relation)) # Visit the reference. current_stack.append((relation,ci)) current_set.add(ci) visit_component_info(referent, current_stack, current_set) current_set.remove(ci) current_stack.pop() # Finally, add the component info to the ordered list. self.ordered_component_infos.append(ci)
def _read_components_from_parser(parser, path, subpath): # We load each section which starts with 'component' as a distinct component # description (so multiple components can be described in one file). for section in parser.sections(): if not section.startswith('component'): # We don't expect arbitrary sections currently, warn the user. warning("ignoring unknown section %r in %r" % (section, path)) continue # Determine the type of the component to instantiate. if not parser.has_option(section, 'type'): fatal("invalid component %r in %r: %s" % (section, path, "no component type")) type_name = parser.get(section, 'type') type_class = _component_type_map.get(type_name) if type_class is None: fatal("invalid component %r in %r: %s" % (section, path, "invalid component type: %r" % type_name)) # Instantiate the component based on the remaining values. try: info = type_class.parse(subpath, IniFormatParser(parser.items(section))) except TypeError: print("error: invalid component %r in %r: %s" % (section, path, "unable to instantiate: %r" % type_name), file=sys.stderr) import traceback traceback.print_exc() raise SystemExit(1) except ParseError: e = sys.exc_info()[1] fatal("unable to load component %r in %r: %s" % (section, path, e.message)) info._source_path = path yield info
def _read_components_from_parser(parser, path, subpath): # We load each section which starts with 'component' as a distinct component # description (so multiple components can be described in one file). for section in parser.sections(): if not section.startswith('component'): # We don't expect arbitrary sections currently, warn the user. warning("ignoring unknown section %r in %r" % (section, path)) continue # Determine the type of the component to instantiate. if not parser.has_option(section, 'type'): fatal("invalid component %r in %r: %s" % ( section, path, "no component type")) type_name = parser.get(section, 'type') type_class = _component_type_map.get(type_name) if type_class is None: fatal("invalid component %r in %r: %s" % ( section, path, "invalid component type: %r" % type_name)) # Instantiate the component based on the remaining values. try: info = type_class.parse(subpath, IniFormatParser(parser.items(section))) except TypeError: print("error: invalid component %r in %r: %s" % ( section, path, "unable to instantiate: %r" % type_name), file=sys.stderr) import traceback traceback.print_exc() raise SystemExit(1) except ParseError: e = sys.exc_info()[1] fatal("unable to load component %r in %r: %s" % ( section, path, e.message)) info._source_path = path yield info
def validate_components(self): """validate_components() -> None Validate that the project components are well-defined. Among other things, this checks that: - Components have valid references. - Components references do not form cycles. We also construct the map from component names to info, and the topological ordering of components. """ # Create the component info map and validate that component names are # unique. self.component_info_map = {} for ci in self.component_infos: existing = self.component_info_map.get(ci.name) if existing is not None: # We found a duplicate component name, report it and error out. fatal("found duplicate component %r (at %r and %r)" % (ci.name, ci.subpath, existing.subpath)) self.component_info_map[ci.name] = ci # Disallow 'all' as a component name, which is a special case. if 'all' in self.component_info_map: fatal("project is not allowed to define 'all' component") # Add the root component. if '$ROOT' in self.component_info_map: fatal("project is not allowed to define $ROOT component") self.component_info_map['$ROOT'] = componentinfo.GroupComponentInfo( '/', '$ROOT', None) self.component_infos.append(self.component_info_map['$ROOT']) # Topologically order the component information according to their # component references. def visit_component_info(ci, current_stack, current_set): # Check for a cycles. if ci in current_set: # We found a cycle, report it and error out. cycle_description = ' -> '.join( '%r (%s)' % (ci.name, relation) for relation, ci in current_stack) fatal("found cycle to %r after following: %s -> %s" % (ci.name, cycle_description, ci.name)) # If we have already visited this item, we are done. if ci not in components_to_visit: return # Otherwise, mark the component info as visited and traverse. components_to_visit.remove(ci) # Validate the parent reference, which we treat specially. if ci.parent is not None: parent = self.component_info_map.get(ci.parent) if parent is None: fatal("component %r has invalid reference %r (via %r)" % (ci.name, ci.parent, 'parent')) ci.set_parent_instance(parent) for relation, referent_name in ci.get_component_references(): # Validate that the reference is ok. referent = self.component_info_map.get(referent_name) if referent is None: fatal("component %r has invalid reference %r (via %r)" % (ci.name, referent_name, relation)) # Visit the reference. current_stack.append((relation, ci)) current_set.add(ci) visit_component_info(referent, current_stack, current_set) current_set.remove(ci) current_stack.pop() # Finally, add the component info to the ordered list. self.ordered_component_infos.append(ci) # FIXME: We aren't actually correctly checking for cycles along the # parent edges. Haven't decided how I want to handle this -- I thought # about only checking cycles by relation type. If we do that, it falls # out easily. If we don't, we should special case the check. self.ordered_component_infos = [] components_to_visit = sorted(set(self.component_infos), key=lambda c: c.name) while components_to_visit: visit_component_info(components_to_visit[0], [], set()) # Canonicalize children lists. for c in self.ordered_component_infos: c.children.sort(key=lambda c: c.name)
def validate_components(self): """validate_components() -> None Validate that the project components are well-defined. Among other things, this checks that: - Components have valid references. - Components references do not form cycles. We also construct the map from component names to info, and the topological ordering of components. """ # Create the component info map and validate that component names are # unique. self.component_info_map = {} for ci in self.component_infos: existing = self.component_info_map.get(ci.name) if existing is not None: # We found a duplicate component name, report it and error out. fatal("found duplicate component %r (at %r and %r)" % ( ci.name, ci.subpath, existing.subpath)) self.component_info_map[ci.name] = ci # Disallow 'all' as a component name, which is a special case. if 'all' in self.component_info_map: fatal("project is not allowed to define 'all' component") # Add the root component. if '$ROOT' in self.component_info_map: fatal("project is not allowed to define $ROOT component") self.component_info_map['$ROOT'] = componentinfo.GroupComponentInfo( '/', '$ROOT', None) self.component_infos.append(self.component_info_map['$ROOT']) # Topologically order the component information according to their # component references. def visit_component_info(ci, current_stack, current_set): # Check for a cycles. if ci in current_set: # We found a cycle, report it and error out. cycle_description = ' -> '.join( '%r (%s)' % (ci.name, relation) for relation,ci in current_stack) fatal("found cycle to %r after following: %s -> %s" % ( ci.name, cycle_description, ci.name)) # If we have already visited this item, we are done. if ci not in components_to_visit: return # Otherwise, mark the component info as visited and traverse. components_to_visit.remove(ci) # Validate the parent reference, which we treat specially. if ci.parent is not None: parent = self.component_info_map.get(ci.parent) if parent is None: fatal("component %r has invalid reference %r (via %r)" % ( ci.name, ci.parent, 'parent')) ci.set_parent_instance(parent) for relation,referent_name in ci.get_component_references(): # Validate that the reference is ok. referent = self.component_info_map.get(referent_name) if referent is None: fatal("component %r has invalid reference %r (via %r)" % ( ci.name, referent_name, relation)) # Visit the reference. current_stack.append((relation,ci)) current_set.add(ci) visit_component_info(referent, current_stack, current_set) current_set.remove(ci) current_stack.pop() # Finally, add the component info to the ordered list. self.ordered_component_infos.append(ci) # FIXME: We aren't actually correctly checking for cycles along the # parent edges. Haven't decided how I want to handle this -- I thought # about only checking cycles by relation type. If we do that, it falls # out easily. If we don't, we should special case the check. self.ordered_component_infos = [] components_to_visit = sorted( set(self.component_infos), key = lambda c: c.name) while components_to_visit: visit_component_info(components_to_visit[0], [], set()) # Canonicalize children lists. for c in self.ordered_component_infos: c.children.sort(key = lambda c: c.name)