blob: a434bd884c0ea2bf976e7a6e8514e4ec64ae5ece [file] [log] [blame]
Daniel Dunbardf578252011-11-03 17:56:06 +00001"""
2Descriptor objects for entities that are part of the LLVM project.
3"""
4
5import ConfigParser
6import sys
7
8class ComponentInfo(object):
9 """
10 Base class for component descriptions.
11 """
12
13 type_name = None
14
15 def __init__(self, subpath, name, dependencies, parent):
16 if not subpath.startswith('/'):
17 raise ValueError,"invalid subpath: %r" % subpath
18 self.subpath = subpath
19 self.name = name
20 self.dependencies = list(dependencies)
21
22 # The name of the parent component to logically group this component
23 # under.
24 self.parent = parent
25
26class GroupComponentInfo(ComponentInfo):
27 """
28 Group components have no semantics as far as the build system are concerned,
29 but exist to help organize other components into a logical tree structure.
30 """
31
32 type_name = 'Group'
33
34 def __init__(self, subpath, name, parent):
35 ComponentInfo.__init__(self, subpath, name, [], parent)
36
37class LibraryComponentInfo(ComponentInfo):
38 type_name = 'Library'
39
40 def __init__(self, subpath, name, dependencies, parent, library_name = None,
41 required_libraries = [], add_to_library_groups = []):
42 ComponentInfo.__init__(self, subpath, name, dependencies, parent)
43
44 # If given, the name to use for the library instead of deriving it from
45 # the component name.
46 self.library_name = library_name
47
48 # The names of the library components which are required when linking
49 # with this component.
50 self.required_libraries = list(required_libraries)
51
52 # The names of the library group components this component should be
53 # considered part of.
54 self.add_to_library_groups = list(add_to_library_groups)
55
56class LibraryGroupComponentInfo(ComponentInfo):
57 type_name = 'LibraryGroup'
58
59 def __init__(self, subpath, name, parent, required_libraries = [],
60 add_to_library_groups = []):
61 ComponentInfo.__init__(self, subpath, name, [], parent)
62
63 # The names of the library components which are required when linking
64 # with this component.
65 self.required_libraries = list(required_libraries)
66
67 # The names of the library group components this component should be
68 # considered part of.
69 self.add_to_library_groups = list(add_to_library_groups)
70
71class ToolComponentInfo(ComponentInfo):
72 type_name = 'Tool'
73
74 def __init__(self, subpath, name, dependencies, parent,
75 required_libraries = []):
76 ComponentInfo.__init__(self, subpath, name, dependencies, parent)
77
78 # The names of the library components which are required to link this
79 # tool.
80 self.required_libraries = list(required_libraries)
81
82class BuildToolComponentInfo(ToolComponentInfo):
83 type_name = 'BuildTool'
84
85_component_type_map = dict(
86 (t.type_name, t)
87 for t in (GroupComponentInfo,
88 LibraryComponentInfo, LibraryGroupComponentInfo,
89 ToolComponentInfo, BuildToolComponentInfo))
90def load_from_path(path, subpath):
91 # Load the LLVMBuild.txt file as an .ini format file.
92 parser = ConfigParser.RawConfigParser()
93 parser.read(path)
94
95 # We load each section which starts with 'component' as a distinct component
96 # description (so multiple components can be described in one file).
97 for section in parser.sections():
98 if not section.startswith('component'):
99 # We don't expect arbitrary sections currently, warn the user.
100 print >>sys.stderr, "warning: ignoring unknown section %r in %r" % (
101 section, path)
102 continue
103
104 # Load the component that this section describes. For now we just do
105 # this the trivial way by letting python validate the argument
106 # assignment. This is simple, but means users see lame diagnostics. We
107 # should audit the component manually, eventually.
108 if not parser.has_option(section, 'type'):
109 print >>sys.stderr, "error: invalid component %r in %r: %s" % (
110 section, path, "no component type")
111 raise SystemExit, 1
112
113 type_name = parser.get(section, 'type')
114 type_class = _component_type_map.get(type_name)
115 if type_class is None:
116 print >>sys.stderr, "error: invalid component %r in %r: %s" % (
117 section, path, "invalid component type: %r" % type_name)
118 raise SystemExit, 1
119
120 items = dict(parser.items(section))
121 items['subpath'] = subpath
122 items.pop('type')
123
124 # Instantiate the component based on the remaining values.
125 try:
126 info = type_class(**items)
127 except TypeError:
128 print >>sys.stderr, "error: invalid component %r in %r: %s" % (
129 section, path, "unable to instantiate: %r" % type_name)
130 import traceback
131 traceback.print_exc()
132 raise SystemExit, 1
133
134 yield info