blob: b9a2d4f1dcedbbcddb7a0c8dad2597158e9f095e [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
Daniel Dunbar43120df2011-11-03 17:56:21 +00006import StringIO
Daniel Dunbardf578252011-11-03 17:56:06 +00007import sys
8
Daniel Dunbar9da6b122011-11-03 17:56:10 +00009from util import *
10
11class ParseError(Exception):
12 pass
13
Daniel Dunbardf578252011-11-03 17:56:06 +000014class ComponentInfo(object):
15 """
16 Base class for component descriptions.
17 """
18
19 type_name = None
20
Daniel Dunbar9da6b122011-11-03 17:56:10 +000021 @staticmethod
22 def parse_items(items, has_dependencies = True):
23 kwargs = {}
24 kwargs['name'] = items.get_string('name')
25 kwargs['parent'] = items.get_optional_string('parent')
26 if has_dependencies:
27 kwargs['dependencies'] = items.get_list('dependencies')
28 return kwargs
29
Daniel Dunbardf578252011-11-03 17:56:06 +000030 def __init__(self, subpath, name, dependencies, parent):
31 if not subpath.startswith('/'):
32 raise ValueError,"invalid subpath: %r" % subpath
33 self.subpath = subpath
34 self.name = name
35 self.dependencies = list(dependencies)
36
37 # The name of the parent component to logically group this component
38 # under.
39 self.parent = parent
40
Daniel Dunbar86c119a2011-11-03 17:56:16 +000041 # The parent instance, once loaded.
42 self.parent_instance = None
43 self.children = []
44
45 def set_parent_instance(self, parent):
46 assert parent.name == self.parent, "Unexpected parent!"
47 self.parent_instance = parent
48 self.parent_instance.children.append(self)
49
Daniel Dunbar1cf14af2011-11-03 17:56:12 +000050 def get_component_references(self):
51 """get_component_references() -> iter
52
53 Return an iterator over the named references to other components from
54 this object. Items are of the form (reference-type, component-name).
55 """
56
57 # Parent references are handled specially.
58 for r in self.dependencies:
59 yield ('dependency', r)
60
Daniel Dunbar43120df2011-11-03 17:56:21 +000061 def get_llvmbuild_fragment(self):
62 abstract
63
Daniel Dunbardf578252011-11-03 17:56:06 +000064class GroupComponentInfo(ComponentInfo):
65 """
66 Group components have no semantics as far as the build system are concerned,
67 but exist to help organize other components into a logical tree structure.
68 """
69
70 type_name = 'Group'
71
Daniel Dunbar9da6b122011-11-03 17:56:10 +000072 @staticmethod
73 def parse(subpath, items):
74 kwargs = ComponentInfo.parse_items(items, has_dependencies = False)
75 return GroupComponentInfo(subpath, **kwargs)
76
Daniel Dunbardf578252011-11-03 17:56:06 +000077 def __init__(self, subpath, name, parent):
78 ComponentInfo.__init__(self, subpath, name, [], parent)
79
Daniel Dunbar43120df2011-11-03 17:56:21 +000080 def get_llvmbuild_fragment(self):
81 result = StringIO.StringIO()
82 print >>result, 'type = %s' % self.type_name
83 print >>result, 'name = %s' % self.name
84 print >>result, 'parent = %s' % self.parent
85 return result.getvalue()
86
Daniel Dunbardf578252011-11-03 17:56:06 +000087class LibraryComponentInfo(ComponentInfo):
88 type_name = 'Library'
89
Daniel Dunbar9da6b122011-11-03 17:56:10 +000090 @staticmethod
91 def parse(subpath, items):
92 kwargs = ComponentInfo.parse_items(items)
Daniel Dunbar43120df2011-11-03 17:56:21 +000093 kwargs['library_name'] = items.get_optional_string('library_name')
Daniel Dunbar9da6b122011-11-03 17:56:10 +000094 kwargs['required_libraries'] = items.get_list('required_libraries')
95 kwargs['add_to_library_groups'] = items.get_list(
96 'add_to_library_groups')
97 return LibraryComponentInfo(subpath, **kwargs)
98
99 def __init__(self, subpath, name, dependencies, parent, library_name,
100 required_libraries, add_to_library_groups):
Daniel Dunbardf578252011-11-03 17:56:06 +0000101 ComponentInfo.__init__(self, subpath, name, dependencies, parent)
102
103 # If given, the name to use for the library instead of deriving it from
104 # the component name.
105 self.library_name = library_name
106
107 # The names of the library components which are required when linking
108 # with this component.
109 self.required_libraries = list(required_libraries)
110
111 # The names of the library group components this component should be
112 # considered part of.
113 self.add_to_library_groups = list(add_to_library_groups)
114
Daniel Dunbar1cf14af2011-11-03 17:56:12 +0000115 def get_component_references(self):
116 for r in ComponentInfo.get_component_references(self):
117 yield r
118 for r in self.required_libraries:
119 yield ('required library', r)
120 for r in self.add_to_library_groups:
121 yield ('library group', r)
122
Daniel Dunbar43120df2011-11-03 17:56:21 +0000123 def get_llvmbuild_fragment(self):
124 result = StringIO.StringIO()
125 print >>result, 'type = %s' % self.type_name
126 print >>result, 'name = %s' % self.name
127 print >>result, 'parent = %s' % self.parent
128 if self.library_name is not None:
129 print >>result, 'library_name = %s' % self.library_name
130 if self.required_libraries:
131 print >>result, 'required_libraries = %s' % ' '.join(
132 self.required_libraries)
133 if self.add_to_library_groups:
134 print >>result, 'add_to_library_groups = %s' % ' '.join(
135 self.add_to_library_groups)
136 return result.getvalue()
137
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000138 def get_library_name(self):
139 return self.library_name or self.name
140
141 def get_llvmconfig_component_name(self):
142 return self.get_library_name().lower()
143
Daniel Dunbardf578252011-11-03 17:56:06 +0000144class LibraryGroupComponentInfo(ComponentInfo):
145 type_name = 'LibraryGroup'
146
Daniel Dunbar9da6b122011-11-03 17:56:10 +0000147 @staticmethod
148 def parse(subpath, items):
149 kwargs = ComponentInfo.parse_items(items, has_dependencies = False)
150 kwargs['required_libraries'] = items.get_list('required_libraries')
151 kwargs['add_to_library_groups'] = items.get_list(
152 'add_to_library_groups')
153 return LibraryGroupComponentInfo(subpath, **kwargs)
154
Daniel Dunbardf578252011-11-03 17:56:06 +0000155 def __init__(self, subpath, name, parent, required_libraries = [],
156 add_to_library_groups = []):
157 ComponentInfo.__init__(self, subpath, name, [], parent)
158
159 # The names of the library components which are required when linking
160 # with this component.
161 self.required_libraries = list(required_libraries)
162
163 # The names of the library group components this component should be
164 # considered part of.
165 self.add_to_library_groups = list(add_to_library_groups)
166
Daniel Dunbar1cf14af2011-11-03 17:56:12 +0000167 def get_component_references(self):
168 for r in ComponentInfo.get_component_references(self):
169 yield r
170 for r in self.required_libraries:
171 yield ('required library', r)
172 for r in self.add_to_library_groups:
173 yield ('library group', r)
174
Daniel Dunbar43120df2011-11-03 17:56:21 +0000175 def get_llvmbuild_fragment(self):
176 result = StringIO.StringIO()
177 print >>result, 'type = %s' % self.type_name
178 print >>result, 'name = %s' % self.name
179 print >>result, 'parent = %s' % self.parent
180 if self.required_libraries:
181 print >>result, 'required_libraries = %s' % ' '.join(
182 self.required_libraries)
183 if self.add_to_library_groups:
184 print >>result, 'add_to_library_groups = %s' % ' '.join(
185 self.add_to_library_groups)
186 return result.getvalue()
187
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000188 def get_llvmconfig_component_name(self):
189 return self.name.lower()
190
Daniel Dunbarc352caf2011-11-10 00:49:51 +0000191class TargetGroupComponentInfo(ComponentInfo):
192 type_name = 'TargetGroup'
193
194 @staticmethod
195 def parse(subpath, items):
196 kwargs = ComponentInfo.parse_items(items, has_dependencies = False)
197 kwargs['required_libraries'] = items.get_list('required_libraries')
198 kwargs['add_to_library_groups'] = items.get_list(
199 'add_to_library_groups')
200 kwargs['has_jit'] = items.get_optional_bool('has_jit', False)
Daniel Dunbar5ed55062011-11-11 00:23:56 +0000201 kwargs['has_asmprinter'] = items.get_optional_bool('has_asmprinter',
202 False)
203 kwargs['has_asmparser'] = items.get_optional_bool('has_asmparser',
204 False)
205 kwargs['has_disassembler'] = items.get_optional_bool('has_disassembler',
206 False)
Daniel Dunbarc352caf2011-11-10 00:49:51 +0000207 return TargetGroupComponentInfo(subpath, **kwargs)
208
209 def __init__(self, subpath, name, parent, required_libraries = [],
Daniel Dunbar5ed55062011-11-11 00:23:56 +0000210 add_to_library_groups = [], has_jit = False,
211 has_asmprinter = False, has_asmparser = False,
212 has_disassembler = False):
Daniel Dunbarc352caf2011-11-10 00:49:51 +0000213 ComponentInfo.__init__(self, subpath, name, [], parent)
214
215 # The names of the library components which are required when linking
216 # with this component.
217 self.required_libraries = list(required_libraries)
218
219 # The names of the library group components this component should be
220 # considered part of.
221 self.add_to_library_groups = list(add_to_library_groups)
222
223 # Whether or not this target supports the JIT.
224 self.has_jit = bool(has_jit)
225
Daniel Dunbar5ed55062011-11-11 00:23:56 +0000226 # Whether or not this target defines an assembly printer.
227 self.has_asmprinter = bool(has_asmprinter)
228
229 # Whether or not this target defines an assembly parser.
230 self.has_asmparser = bool(has_asmparser)
231
232 # Whether or not this target defines an disassembler.
233 self.has_disassembler = bool(has_disassembler)
234
Daniel Dunbaraffc6cf2011-11-10 00:50:07 +0000235 # Whether or not this target is enabled. This is set in response to
236 # configuration parameters.
237 self.enabled = False
238
Daniel Dunbarc352caf2011-11-10 00:49:51 +0000239 def get_component_references(self):
240 for r in ComponentInfo.get_component_references(self):
241 yield r
242 for r in self.required_libraries:
243 yield ('required library', r)
244 for r in self.add_to_library_groups:
245 yield ('library group', r)
246
247 def get_llvmbuild_fragment(self):
248 result = StringIO.StringIO()
249 print >>result, 'type = %s' % self.type_name
250 print >>result, 'name = %s' % self.name
251 print >>result, 'parent = %s' % self.parent
252 if self.required_libraries:
253 print >>result, 'required_libraries = %s' % ' '.join(
254 self.required_libraries)
255 if self.add_to_library_groups:
256 print >>result, 'add_to_library_groups = %s' % ' '.join(
257 self.add_to_library_groups)
Daniel Dunbar5ed55062011-11-11 00:23:56 +0000258 for bool_key in ('has_asmparser', 'has_asmprinter', 'has_disassembler',
259 'has_jit'):
260 if getattr(self, bool_key):
261 print >>result, '%s = 1' % (bool_key,)
Daniel Dunbarc352caf2011-11-10 00:49:51 +0000262 return result.getvalue()
263
264 def get_llvmconfig_component_name(self):
265 return self.name.lower()
266
Daniel Dunbardf578252011-11-03 17:56:06 +0000267class ToolComponentInfo(ComponentInfo):
268 type_name = 'Tool'
269
Daniel Dunbar9da6b122011-11-03 17:56:10 +0000270 @staticmethod
271 def parse(subpath, items):
272 kwargs = ComponentInfo.parse_items(items)
273 kwargs['required_libraries'] = items.get_list('required_libraries')
274 return ToolComponentInfo(subpath, **kwargs)
275
Daniel Dunbardf578252011-11-03 17:56:06 +0000276 def __init__(self, subpath, name, dependencies, parent,
Daniel Dunbar9da6b122011-11-03 17:56:10 +0000277 required_libraries):
Daniel Dunbardf578252011-11-03 17:56:06 +0000278 ComponentInfo.__init__(self, subpath, name, dependencies, parent)
279
280 # The names of the library components which are required to link this
281 # tool.
282 self.required_libraries = list(required_libraries)
283
Daniel Dunbar1cf14af2011-11-03 17:56:12 +0000284 def get_component_references(self):
285 for r in ComponentInfo.get_component_references(self):
286 yield r
287 for r in self.required_libraries:
288 yield ('required library', r)
289
Daniel Dunbar43120df2011-11-03 17:56:21 +0000290 def get_llvmbuild_fragment(self):
291 result = StringIO.StringIO()
292 print >>result, 'type = %s' % self.type_name
293 print >>result, 'name = %s' % self.name
294 print >>result, 'parent = %s' % self.parent
295 print >>result, 'required_libraries = %s' % ' '.join(
296 self.required_libraries)
297 return result.getvalue()
298
Daniel Dunbardf578252011-11-03 17:56:06 +0000299class BuildToolComponentInfo(ToolComponentInfo):
300 type_name = 'BuildTool'
301
Daniel Dunbar9da6b122011-11-03 17:56:10 +0000302 @staticmethod
303 def parse(subpath, items):
304 kwargs = ComponentInfo.parse_items(items)
305 kwargs['required_libraries'] = items.get_list('required_libraries')
306 return BuildToolComponentInfo(subpath, **kwargs)
307
308###
309
310class IniFormatParser(dict):
311 def get_list(self, key):
312 # Check if the value is defined.
313 value = self.get(key)
314 if value is None:
315 return []
316
317 # Lists are just whitespace separated strings.
318 return value.split()
319
320 def get_optional_string(self, key):
321 value = self.get_list(key)
322 if not value:
323 return None
324 if len(value) > 1:
325 raise ParseError("multiple values for scalar key: %r" % key)
326 return value[0]
327
328 def get_string(self, key):
329 value = self.get_optional_string(key)
330 if not value:
331 raise ParseError("missing value for required string: %r" % key)
332 return value
333
Daniel Dunbarc352caf2011-11-10 00:49:51 +0000334 def get_optional_bool(self, key, default = None):
335 value = self.get_optional_string(key)
336 if not value:
337 return default
338 if value not in ('0', '1'):
339 raise ParseError("invalid value(%r) for boolean property: %r" % (
340 value, key))
341 return bool(int(value))
342
343 def get_bool(self, key):
344 value = self.get_optional_bool(key)
345 if value is None:
346 raise ParseError("missing value for required boolean: %r" % key)
347 return value
348
Daniel Dunbardf578252011-11-03 17:56:06 +0000349_component_type_map = dict(
350 (t.type_name, t)
351 for t in (GroupComponentInfo,
352 LibraryComponentInfo, LibraryGroupComponentInfo,
Daniel Dunbarc352caf2011-11-10 00:49:51 +0000353 ToolComponentInfo, BuildToolComponentInfo,
354 TargetGroupComponentInfo))
Daniel Dunbardf578252011-11-03 17:56:06 +0000355def load_from_path(path, subpath):
356 # Load the LLVMBuild.txt file as an .ini format file.
357 parser = ConfigParser.RawConfigParser()
358 parser.read(path)
359
360 # We load each section which starts with 'component' as a distinct component
361 # description (so multiple components can be described in one file).
362 for section in parser.sections():
363 if not section.startswith('component'):
364 # We don't expect arbitrary sections currently, warn the user.
Daniel Dunbar9da6b122011-11-03 17:56:10 +0000365 warning("ignoring unknown section %r in %r" % (section, path))
Daniel Dunbardf578252011-11-03 17:56:06 +0000366 continue
367
Daniel Dunbar9da6b122011-11-03 17:56:10 +0000368 # Determine the type of the component to instantiate.
Daniel Dunbardf578252011-11-03 17:56:06 +0000369 if not parser.has_option(section, 'type'):
Daniel Dunbar9da6b122011-11-03 17:56:10 +0000370 fatal("invalid component %r in %r: %s" % (
371 section, path, "no component type"))
Daniel Dunbardf578252011-11-03 17:56:06 +0000372
373 type_name = parser.get(section, 'type')
374 type_class = _component_type_map.get(type_name)
375 if type_class is None:
Daniel Dunbar9da6b122011-11-03 17:56:10 +0000376 fatal("invalid component %r in %r: %s" % (
377 section, path, "invalid component type: %r" % type_name))
Daniel Dunbardf578252011-11-03 17:56:06 +0000378
379 # Instantiate the component based on the remaining values.
380 try:
Daniel Dunbar9da6b122011-11-03 17:56:10 +0000381 info = type_class.parse(subpath,
382 IniFormatParser(parser.items(section)))
Daniel Dunbardf578252011-11-03 17:56:06 +0000383 except TypeError:
384 print >>sys.stderr, "error: invalid component %r in %r: %s" % (
385 section, path, "unable to instantiate: %r" % type_name)
386 import traceback
387 traceback.print_exc()
388 raise SystemExit, 1
Daniel Dunbar9da6b122011-11-03 17:56:10 +0000389 except ParseError,e:
390 fatal("unable to load component %r in %r: %s" % (
391 section, path, e.message))
Daniel Dunbardf578252011-11-03 17:56:06 +0000392
393 yield info