2011-11-04 01:56:06 +08:00
|
|
|
"""
|
|
|
|
Descriptor objects for entities that are part of the LLVM project.
|
|
|
|
"""
|
|
|
|
|
|
|
|
import ConfigParser
|
|
|
|
import sys
|
|
|
|
|
2011-11-04 01:56:10 +08:00
|
|
|
from util import *
|
|
|
|
|
|
|
|
class ParseError(Exception):
|
|
|
|
pass
|
|
|
|
|
2011-11-04 01:56:06 +08:00
|
|
|
class ComponentInfo(object):
|
|
|
|
"""
|
|
|
|
Base class for component descriptions.
|
|
|
|
"""
|
|
|
|
|
|
|
|
type_name = None
|
|
|
|
|
2011-11-04 01:56:10 +08:00
|
|
|
@staticmethod
|
|
|
|
def parse_items(items, has_dependencies = True):
|
|
|
|
kwargs = {}
|
|
|
|
kwargs['name'] = items.get_string('name')
|
|
|
|
kwargs['parent'] = items.get_optional_string('parent')
|
|
|
|
if has_dependencies:
|
|
|
|
kwargs['dependencies'] = items.get_list('dependencies')
|
|
|
|
return kwargs
|
|
|
|
|
2011-11-04 01:56:06 +08:00
|
|
|
def __init__(self, subpath, name, dependencies, parent):
|
|
|
|
if not subpath.startswith('/'):
|
|
|
|
raise ValueError,"invalid subpath: %r" % subpath
|
|
|
|
self.subpath = subpath
|
|
|
|
self.name = name
|
|
|
|
self.dependencies = list(dependencies)
|
|
|
|
|
|
|
|
# The name of the parent component to logically group this component
|
|
|
|
# under.
|
|
|
|
self.parent = parent
|
|
|
|
|
2011-11-04 01:56:16 +08:00
|
|
|
# The parent instance, once loaded.
|
|
|
|
self.parent_instance = None
|
|
|
|
self.children = []
|
|
|
|
|
|
|
|
def set_parent_instance(self, parent):
|
|
|
|
assert parent.name == self.parent, "Unexpected parent!"
|
|
|
|
self.parent_instance = parent
|
|
|
|
self.parent_instance.children.append(self)
|
|
|
|
|
2011-11-04 01:56:12 +08:00
|
|
|
def get_component_references(self):
|
|
|
|
"""get_component_references() -> iter
|
|
|
|
|
|
|
|
Return an iterator over the named references to other components from
|
|
|
|
this object. Items are of the form (reference-type, component-name).
|
|
|
|
"""
|
|
|
|
|
|
|
|
# Parent references are handled specially.
|
|
|
|
for r in self.dependencies:
|
|
|
|
yield ('dependency', r)
|
|
|
|
|
2011-11-04 01:56:06 +08:00
|
|
|
class GroupComponentInfo(ComponentInfo):
|
|
|
|
"""
|
|
|
|
Group components have no semantics as far as the build system are concerned,
|
|
|
|
but exist to help organize other components into a logical tree structure.
|
|
|
|
"""
|
|
|
|
|
|
|
|
type_name = 'Group'
|
|
|
|
|
2011-11-04 01:56:10 +08:00
|
|
|
@staticmethod
|
|
|
|
def parse(subpath, items):
|
|
|
|
kwargs = ComponentInfo.parse_items(items, has_dependencies = False)
|
|
|
|
return GroupComponentInfo(subpath, **kwargs)
|
|
|
|
|
2011-11-04 01:56:06 +08:00
|
|
|
def __init__(self, subpath, name, parent):
|
|
|
|
ComponentInfo.__init__(self, subpath, name, [], parent)
|
|
|
|
|
|
|
|
class LibraryComponentInfo(ComponentInfo):
|
|
|
|
type_name = 'Library'
|
|
|
|
|
2011-11-04 01:56:10 +08:00
|
|
|
@staticmethod
|
|
|
|
def parse(subpath, items):
|
|
|
|
kwargs = ComponentInfo.parse_items(items)
|
|
|
|
kwargs['library_name'] = items.get_optional_string('name')
|
|
|
|
kwargs['required_libraries'] = items.get_list('required_libraries')
|
|
|
|
kwargs['add_to_library_groups'] = items.get_list(
|
|
|
|
'add_to_library_groups')
|
|
|
|
return LibraryComponentInfo(subpath, **kwargs)
|
|
|
|
|
|
|
|
def __init__(self, subpath, name, dependencies, parent, library_name,
|
|
|
|
required_libraries, add_to_library_groups):
|
2011-11-04 01:56:06 +08:00
|
|
|
ComponentInfo.__init__(self, subpath, name, dependencies, parent)
|
|
|
|
|
|
|
|
# If given, the name to use for the library instead of deriving it from
|
|
|
|
# the component name.
|
|
|
|
self.library_name = library_name
|
|
|
|
|
|
|
|
# The names of the library components which are required when linking
|
|
|
|
# with this component.
|
|
|
|
self.required_libraries = list(required_libraries)
|
|
|
|
|
|
|
|
# The names of the library group components this component should be
|
|
|
|
# considered part of.
|
|
|
|
self.add_to_library_groups = list(add_to_library_groups)
|
|
|
|
|
2011-11-04 01:56:12 +08:00
|
|
|
def get_component_references(self):
|
|
|
|
for r in ComponentInfo.get_component_references(self):
|
|
|
|
yield r
|
|
|
|
for r in self.required_libraries:
|
|
|
|
yield ('required library', r)
|
|
|
|
for r in self.add_to_library_groups:
|
|
|
|
yield ('library group', r)
|
|
|
|
|
2011-11-04 01:56:06 +08:00
|
|
|
class LibraryGroupComponentInfo(ComponentInfo):
|
|
|
|
type_name = 'LibraryGroup'
|
|
|
|
|
2011-11-04 01:56:10 +08:00
|
|
|
@staticmethod
|
|
|
|
def parse(subpath, items):
|
|
|
|
kwargs = ComponentInfo.parse_items(items, has_dependencies = False)
|
|
|
|
kwargs['required_libraries'] = items.get_list('required_libraries')
|
|
|
|
kwargs['add_to_library_groups'] = items.get_list(
|
|
|
|
'add_to_library_groups')
|
|
|
|
return LibraryGroupComponentInfo(subpath, **kwargs)
|
|
|
|
|
2011-11-04 01:56:06 +08:00
|
|
|
def __init__(self, subpath, name, parent, required_libraries = [],
|
|
|
|
add_to_library_groups = []):
|
|
|
|
ComponentInfo.__init__(self, subpath, name, [], parent)
|
|
|
|
|
|
|
|
# The names of the library components which are required when linking
|
|
|
|
# with this component.
|
|
|
|
self.required_libraries = list(required_libraries)
|
|
|
|
|
|
|
|
# The names of the library group components this component should be
|
|
|
|
# considered part of.
|
|
|
|
self.add_to_library_groups = list(add_to_library_groups)
|
|
|
|
|
2011-11-04 01:56:12 +08:00
|
|
|
def get_component_references(self):
|
|
|
|
for r in ComponentInfo.get_component_references(self):
|
|
|
|
yield r
|
|
|
|
for r in self.required_libraries:
|
|
|
|
yield ('required library', r)
|
|
|
|
for r in self.add_to_library_groups:
|
|
|
|
yield ('library group', r)
|
|
|
|
|
2011-11-04 01:56:06 +08:00
|
|
|
class ToolComponentInfo(ComponentInfo):
|
|
|
|
type_name = 'Tool'
|
|
|
|
|
2011-11-04 01:56:10 +08:00
|
|
|
@staticmethod
|
|
|
|
def parse(subpath, items):
|
|
|
|
kwargs = ComponentInfo.parse_items(items)
|
|
|
|
kwargs['required_libraries'] = items.get_list('required_libraries')
|
|
|
|
return ToolComponentInfo(subpath, **kwargs)
|
|
|
|
|
2011-11-04 01:56:06 +08:00
|
|
|
def __init__(self, subpath, name, dependencies, parent,
|
2011-11-04 01:56:10 +08:00
|
|
|
required_libraries):
|
2011-11-04 01:56:06 +08:00
|
|
|
ComponentInfo.__init__(self, subpath, name, dependencies, parent)
|
|
|
|
|
|
|
|
# The names of the library components which are required to link this
|
|
|
|
# tool.
|
|
|
|
self.required_libraries = list(required_libraries)
|
|
|
|
|
2011-11-04 01:56:12 +08:00
|
|
|
def get_component_references(self):
|
|
|
|
for r in ComponentInfo.get_component_references(self):
|
|
|
|
yield r
|
|
|
|
for r in self.required_libraries:
|
|
|
|
yield ('required library', r)
|
|
|
|
|
2011-11-04 01:56:06 +08:00
|
|
|
class BuildToolComponentInfo(ToolComponentInfo):
|
|
|
|
type_name = 'BuildTool'
|
|
|
|
|
2011-11-04 01:56:10 +08:00
|
|
|
@staticmethod
|
|
|
|
def parse(subpath, items):
|
|
|
|
kwargs = ComponentInfo.parse_items(items)
|
|
|
|
kwargs['required_libraries'] = items.get_list('required_libraries')
|
|
|
|
return BuildToolComponentInfo(subpath, **kwargs)
|
|
|
|
|
|
|
|
###
|
|
|
|
|
|
|
|
class IniFormatParser(dict):
|
|
|
|
def get_list(self, key):
|
|
|
|
# Check if the value is defined.
|
|
|
|
value = self.get(key)
|
|
|
|
if value is None:
|
|
|
|
return []
|
|
|
|
|
|
|
|
# Lists are just whitespace separated strings.
|
|
|
|
return value.split()
|
|
|
|
|
|
|
|
def get_optional_string(self, key):
|
|
|
|
value = self.get_list(key)
|
|
|
|
if not value:
|
|
|
|
return None
|
|
|
|
if len(value) > 1:
|
|
|
|
raise ParseError("multiple values for scalar key: %r" % key)
|
|
|
|
return value[0]
|
|
|
|
|
|
|
|
def get_string(self, key):
|
|
|
|
value = self.get_optional_string(key)
|
|
|
|
if not value:
|
|
|
|
raise ParseError("missing value for required string: %r" % key)
|
|
|
|
return value
|
|
|
|
|
2011-11-04 01:56:06 +08:00
|
|
|
_component_type_map = dict(
|
|
|
|
(t.type_name, t)
|
|
|
|
for t in (GroupComponentInfo,
|
|
|
|
LibraryComponentInfo, LibraryGroupComponentInfo,
|
|
|
|
ToolComponentInfo, BuildToolComponentInfo))
|
|
|
|
def load_from_path(path, subpath):
|
|
|
|
# Load the LLVMBuild.txt file as an .ini format file.
|
|
|
|
parser = ConfigParser.RawConfigParser()
|
|
|
|
parser.read(path)
|
|
|
|
|
|
|
|
# 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.
|
2011-11-04 01:56:10 +08:00
|
|
|
warning("ignoring unknown section %r in %r" % (section, path))
|
2011-11-04 01:56:06 +08:00
|
|
|
continue
|
|
|
|
|
2011-11-04 01:56:10 +08:00
|
|
|
# Determine the type of the component to instantiate.
|
2011-11-04 01:56:06 +08:00
|
|
|
if not parser.has_option(section, 'type'):
|
2011-11-04 01:56:10 +08:00
|
|
|
fatal("invalid component %r in %r: %s" % (
|
|
|
|
section, path, "no component type"))
|
2011-11-04 01:56:06 +08:00
|
|
|
|
|
|
|
type_name = parser.get(section, 'type')
|
|
|
|
type_class = _component_type_map.get(type_name)
|
|
|
|
if type_class is None:
|
2011-11-04 01:56:10 +08:00
|
|
|
fatal("invalid component %r in %r: %s" % (
|
|
|
|
section, path, "invalid component type: %r" % type_name))
|
2011-11-04 01:56:06 +08:00
|
|
|
|
|
|
|
# Instantiate the component based on the remaining values.
|
|
|
|
try:
|
2011-11-04 01:56:10 +08:00
|
|
|
info = type_class.parse(subpath,
|
|
|
|
IniFormatParser(parser.items(section)))
|
2011-11-04 01:56:06 +08:00
|
|
|
except TypeError:
|
|
|
|
print >>sys.stderr, "error: invalid component %r in %r: %s" % (
|
|
|
|
section, path, "unable to instantiate: %r" % type_name)
|
|
|
|
import traceback
|
|
|
|
traceback.print_exc()
|
|
|
|
raise SystemExit, 1
|
2011-11-04 01:56:10 +08:00
|
|
|
except ParseError,e:
|
|
|
|
fatal("unable to load component %r in %r: %s" % (
|
|
|
|
section, path, e.message))
|
2011-11-04 01:56:06 +08:00
|
|
|
|
|
|
|
yield info
|