blob: e9ef973d08a9fb4282a23bf667195b4e3ab83cd2 [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
Daniel Dunbara3217162011-12-12 22:45:35 +000045 # The original source path.
46 self._source_path = None
47
Daniel Dunbar86c119a2011-11-03 17:56:16 +000048 def set_parent_instance(self, parent):
49 assert parent.name == self.parent, "Unexpected parent!"
50 self.parent_instance = parent
51 self.parent_instance.children.append(self)
52
Daniel Dunbar1cf14af2011-11-03 17:56:12 +000053 def get_component_references(self):
54 """get_component_references() -> iter
55
56 Return an iterator over the named references to other components from
57 this object. Items are of the form (reference-type, component-name).
58 """
59
60 # Parent references are handled specially.
61 for r in self.dependencies:
62 yield ('dependency', r)
63
Daniel Dunbar43120df2011-11-03 17:56:21 +000064 def get_llvmbuild_fragment(self):
65 abstract
66
Daniel Dunbardf578252011-11-03 17:56:06 +000067class GroupComponentInfo(ComponentInfo):
68 """
69 Group components have no semantics as far as the build system are concerned,
70 but exist to help organize other components into a logical tree structure.
71 """
72
73 type_name = 'Group'
74
Daniel Dunbar9da6b122011-11-03 17:56:10 +000075 @staticmethod
76 def parse(subpath, items):
77 kwargs = ComponentInfo.parse_items(items, has_dependencies = False)
78 return GroupComponentInfo(subpath, **kwargs)
79
Daniel Dunbardf578252011-11-03 17:56:06 +000080 def __init__(self, subpath, name, parent):
81 ComponentInfo.__init__(self, subpath, name, [], parent)
82
Daniel Dunbar43120df2011-11-03 17:56:21 +000083 def get_llvmbuild_fragment(self):
84 result = StringIO.StringIO()
85 print >>result, 'type = %s' % self.type_name
86 print >>result, 'name = %s' % self.name
87 print >>result, 'parent = %s' % self.parent
88 return result.getvalue()
89
Daniel Dunbardf578252011-11-03 17:56:06 +000090class LibraryComponentInfo(ComponentInfo):
91 type_name = 'Library'
92
Daniel Dunbar9da6b122011-11-03 17:56:10 +000093 @staticmethod
94 def parse(subpath, items):
95 kwargs = ComponentInfo.parse_items(items)
Daniel Dunbar43120df2011-11-03 17:56:21 +000096 kwargs['library_name'] = items.get_optional_string('library_name')
Daniel Dunbar9da6b122011-11-03 17:56:10 +000097 kwargs['required_libraries'] = items.get_list('required_libraries')
98 kwargs['add_to_library_groups'] = items.get_list(
99 'add_to_library_groups')
100 return LibraryComponentInfo(subpath, **kwargs)
101
102 def __init__(self, subpath, name, dependencies, parent, library_name,
103 required_libraries, add_to_library_groups):
Daniel Dunbardf578252011-11-03 17:56:06 +0000104 ComponentInfo.__init__(self, subpath, name, dependencies, parent)
105
106 # If given, the name to use for the library instead of deriving it from
107 # the component name.
108 self.library_name = library_name
109
110 # The names of the library components which are required when linking
111 # with this component.
112 self.required_libraries = list(required_libraries)
113
114 # The names of the library group components this component should be
115 # considered part of.
116 self.add_to_library_groups = list(add_to_library_groups)
117
Daniel Dunbar1cf14af2011-11-03 17:56:12 +0000118 def get_component_references(self):
119 for r in ComponentInfo.get_component_references(self):
120 yield r
121 for r in self.required_libraries:
122 yield ('required library', r)
123 for r in self.add_to_library_groups:
124 yield ('library group', r)
125
Daniel Dunbar43120df2011-11-03 17:56:21 +0000126 def get_llvmbuild_fragment(self):
127 result = StringIO.StringIO()
128 print >>result, 'type = %s' % self.type_name
129 print >>result, 'name = %s' % self.name
130 print >>result, 'parent = %s' % self.parent
131 if self.library_name is not None:
132 print >>result, 'library_name = %s' % self.library_name
133 if self.required_libraries:
134 print >>result, 'required_libraries = %s' % ' '.join(
135 self.required_libraries)
136 if self.add_to_library_groups:
137 print >>result, 'add_to_library_groups = %s' % ' '.join(
138 self.add_to_library_groups)
139 return result.getvalue()
140
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000141 def get_library_name(self):
142 return self.library_name or self.name
143
Daniel Dunbar5086de62011-11-29 00:06:50 +0000144 def get_prefixed_library_name(self):
145 """
146 get_prefixed_library_name() -> str
147
148 Return the library name prefixed by the project name. This is generally
149 what the library name will be on disk.
150 """
151
152 basename = self.get_library_name()
153
154 # FIXME: We need to get the prefix information from an explicit project
155 # object, or something.
156 if basename in ('gtest', 'gtest_main'):
157 return basename
158
159 return 'LLVM%s' % basename
160
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000161 def get_llvmconfig_component_name(self):
162 return self.get_library_name().lower()
163
Daniel Dunbardf578252011-11-03 17:56:06 +0000164class LibraryGroupComponentInfo(ComponentInfo):
165 type_name = 'LibraryGroup'
166
Daniel Dunbar9da6b122011-11-03 17:56:10 +0000167 @staticmethod
168 def parse(subpath, items):
169 kwargs = ComponentInfo.parse_items(items, has_dependencies = False)
170 kwargs['required_libraries'] = items.get_list('required_libraries')
171 kwargs['add_to_library_groups'] = items.get_list(
172 'add_to_library_groups')
173 return LibraryGroupComponentInfo(subpath, **kwargs)
174
Daniel Dunbardf578252011-11-03 17:56:06 +0000175 def __init__(self, subpath, name, parent, required_libraries = [],
176 add_to_library_groups = []):
177 ComponentInfo.__init__(self, subpath, name, [], parent)
178
179 # The names of the library components which are required when linking
180 # with this component.
181 self.required_libraries = list(required_libraries)
182
183 # The names of the library group components this component should be
184 # considered part of.
185 self.add_to_library_groups = list(add_to_library_groups)
186
Daniel Dunbar1cf14af2011-11-03 17:56:12 +0000187 def get_component_references(self):
188 for r in ComponentInfo.get_component_references(self):
189 yield r
190 for r in self.required_libraries:
191 yield ('required library', r)
192 for r in self.add_to_library_groups:
193 yield ('library group', r)
194
Daniel Dunbar43120df2011-11-03 17:56:21 +0000195 def get_llvmbuild_fragment(self):
196 result = StringIO.StringIO()
197 print >>result, 'type = %s' % self.type_name
198 print >>result, 'name = %s' % self.name
199 print >>result, 'parent = %s' % self.parent
200 if self.required_libraries:
201 print >>result, 'required_libraries = %s' % ' '.join(
202 self.required_libraries)
203 if self.add_to_library_groups:
204 print >>result, 'add_to_library_groups = %s' % ' '.join(
205 self.add_to_library_groups)
206 return result.getvalue()
207
Daniel Dunbarefe2f642011-11-03 17:56:28 +0000208 def get_llvmconfig_component_name(self):
209 return self.name.lower()
210
Daniel Dunbarc352caf2011-11-10 00:49:51 +0000211class TargetGroupComponentInfo(ComponentInfo):
212 type_name = 'TargetGroup'
213
214 @staticmethod
215 def parse(subpath, items):
216 kwargs = ComponentInfo.parse_items(items, has_dependencies = False)
217 kwargs['required_libraries'] = items.get_list('required_libraries')
218 kwargs['add_to_library_groups'] = items.get_list(
219 'add_to_library_groups')
220 kwargs['has_jit'] = items.get_optional_bool('has_jit', False)
Daniel Dunbar5ed55062011-11-11 00:23:56 +0000221 kwargs['has_asmprinter'] = items.get_optional_bool('has_asmprinter',
222 False)
223 kwargs['has_asmparser'] = items.get_optional_bool('has_asmparser',
224 False)
225 kwargs['has_disassembler'] = items.get_optional_bool('has_disassembler',
226 False)
Daniel Dunbarc352caf2011-11-10 00:49:51 +0000227 return TargetGroupComponentInfo(subpath, **kwargs)
228
229 def __init__(self, subpath, name, parent, required_libraries = [],
Daniel Dunbar5ed55062011-11-11 00:23:56 +0000230 add_to_library_groups = [], has_jit = False,
231 has_asmprinter = False, has_asmparser = False,
232 has_disassembler = False):
Daniel Dunbarc352caf2011-11-10 00:49:51 +0000233 ComponentInfo.__init__(self, subpath, name, [], parent)
234
235 # The names of the library components which are required when linking
236 # with this component.
237 self.required_libraries = list(required_libraries)
238
239 # The names of the library group components this component should be
240 # considered part of.
241 self.add_to_library_groups = list(add_to_library_groups)
242
243 # Whether or not this target supports the JIT.
244 self.has_jit = bool(has_jit)
245
Daniel Dunbar5ed55062011-11-11 00:23:56 +0000246 # Whether or not this target defines an assembly printer.
247 self.has_asmprinter = bool(has_asmprinter)
248
249 # Whether or not this target defines an assembly parser.
250 self.has_asmparser = bool(has_asmparser)
251
252 # Whether or not this target defines an disassembler.
253 self.has_disassembler = bool(has_disassembler)
254
Daniel Dunbaraffc6cf2011-11-10 00:50:07 +0000255 # Whether or not this target is enabled. This is set in response to
256 # configuration parameters.
257 self.enabled = False
258
Daniel Dunbarc352caf2011-11-10 00:49:51 +0000259 def get_component_references(self):
260 for r in ComponentInfo.get_component_references(self):
261 yield r
262 for r in self.required_libraries:
263 yield ('required library', r)
264 for r in self.add_to_library_groups:
265 yield ('library group', r)
266
267 def get_llvmbuild_fragment(self):
268 result = StringIO.StringIO()
269 print >>result, 'type = %s' % self.type_name
270 print >>result, 'name = %s' % self.name
271 print >>result, 'parent = %s' % self.parent
272 if self.required_libraries:
273 print >>result, 'required_libraries = %s' % ' '.join(
274 self.required_libraries)
275 if self.add_to_library_groups:
276 print >>result, 'add_to_library_groups = %s' % ' '.join(
277 self.add_to_library_groups)
Daniel Dunbar5ed55062011-11-11 00:23:56 +0000278 for bool_key in ('has_asmparser', 'has_asmprinter', 'has_disassembler',
279 'has_jit'):
280 if getattr(self, bool_key):
281 print >>result, '%s = 1' % (bool_key,)
Daniel Dunbarc352caf2011-11-10 00:49:51 +0000282 return result.getvalue()
283
284 def get_llvmconfig_component_name(self):
285 return self.name.lower()
286
Daniel Dunbardf578252011-11-03 17:56:06 +0000287class ToolComponentInfo(ComponentInfo):
288 type_name = 'Tool'
289
Daniel Dunbar9da6b122011-11-03 17:56:10 +0000290 @staticmethod
291 def parse(subpath, items):
292 kwargs = ComponentInfo.parse_items(items)
293 kwargs['required_libraries'] = items.get_list('required_libraries')
294 return ToolComponentInfo(subpath, **kwargs)
295
Daniel Dunbardf578252011-11-03 17:56:06 +0000296 def __init__(self, subpath, name, dependencies, parent,
Daniel Dunbar9da6b122011-11-03 17:56:10 +0000297 required_libraries):
Daniel Dunbardf578252011-11-03 17:56:06 +0000298 ComponentInfo.__init__(self, subpath, name, dependencies, parent)
299
300 # The names of the library components which are required to link this
301 # tool.
302 self.required_libraries = list(required_libraries)
303
Daniel Dunbar1cf14af2011-11-03 17:56:12 +0000304 def get_component_references(self):
305 for r in ComponentInfo.get_component_references(self):
306 yield r
307 for r in self.required_libraries:
308 yield ('required library', r)
309
Daniel Dunbar43120df2011-11-03 17:56:21 +0000310 def get_llvmbuild_fragment(self):
311 result = StringIO.StringIO()
312 print >>result, 'type = %s' % self.type_name
313 print >>result, 'name = %s' % self.name
314 print >>result, 'parent = %s' % self.parent
315 print >>result, 'required_libraries = %s' % ' '.join(
316 self.required_libraries)
317 return result.getvalue()
318
Daniel Dunbardf578252011-11-03 17:56:06 +0000319class BuildToolComponentInfo(ToolComponentInfo):
320 type_name = 'BuildTool'
321
Daniel Dunbar9da6b122011-11-03 17:56:10 +0000322 @staticmethod
323 def parse(subpath, items):
324 kwargs = ComponentInfo.parse_items(items)
325 kwargs['required_libraries'] = items.get_list('required_libraries')
326 return BuildToolComponentInfo(subpath, **kwargs)
327
328###
329
330class IniFormatParser(dict):
331 def get_list(self, key):
332 # Check if the value is defined.
333 value = self.get(key)
334 if value is None:
335 return []
336
337 # Lists are just whitespace separated strings.
338 return value.split()
339
340 def get_optional_string(self, key):
341 value = self.get_list(key)
342 if not value:
343 return None
344 if len(value) > 1:
345 raise ParseError("multiple values for scalar key: %r" % key)
346 return value[0]
347
348 def get_string(self, key):
349 value = self.get_optional_string(key)
350 if not value:
351 raise ParseError("missing value for required string: %r" % key)
352 return value
353
Daniel Dunbarc352caf2011-11-10 00:49:51 +0000354 def get_optional_bool(self, key, default = None):
355 value = self.get_optional_string(key)
356 if not value:
357 return default
358 if value not in ('0', '1'):
359 raise ParseError("invalid value(%r) for boolean property: %r" % (
360 value, key))
361 return bool(int(value))
362
363 def get_bool(self, key):
364 value = self.get_optional_bool(key)
365 if value is None:
366 raise ParseError("missing value for required boolean: %r" % key)
367 return value
368
Daniel Dunbardf578252011-11-03 17:56:06 +0000369_component_type_map = dict(
370 (t.type_name, t)
371 for t in (GroupComponentInfo,
372 LibraryComponentInfo, LibraryGroupComponentInfo,
Daniel Dunbarc352caf2011-11-10 00:49:51 +0000373 ToolComponentInfo, BuildToolComponentInfo,
374 TargetGroupComponentInfo))
Daniel Dunbardf578252011-11-03 17:56:06 +0000375def load_from_path(path, subpath):
376 # Load the LLVMBuild.txt file as an .ini format file.
377 parser = ConfigParser.RawConfigParser()
378 parser.read(path)
379
380 # We load each section which starts with 'component' as a distinct component
381 # description (so multiple components can be described in one file).
382 for section in parser.sections():
383 if not section.startswith('component'):
384 # We don't expect arbitrary sections currently, warn the user.
Daniel Dunbar9da6b122011-11-03 17:56:10 +0000385 warning("ignoring unknown section %r in %r" % (section, path))
Daniel Dunbardf578252011-11-03 17:56:06 +0000386 continue
387
Daniel Dunbar9da6b122011-11-03 17:56:10 +0000388 # Determine the type of the component to instantiate.
Daniel Dunbardf578252011-11-03 17:56:06 +0000389 if not parser.has_option(section, 'type'):
Daniel Dunbar9da6b122011-11-03 17:56:10 +0000390 fatal("invalid component %r in %r: %s" % (
391 section, path, "no component type"))
Daniel Dunbardf578252011-11-03 17:56:06 +0000392
393 type_name = parser.get(section, 'type')
394 type_class = _component_type_map.get(type_name)
395 if type_class is None:
Daniel Dunbar9da6b122011-11-03 17:56:10 +0000396 fatal("invalid component %r in %r: %s" % (
397 section, path, "invalid component type: %r" % type_name))
Daniel Dunbardf578252011-11-03 17:56:06 +0000398
399 # Instantiate the component based on the remaining values.
400 try:
Daniel Dunbar9da6b122011-11-03 17:56:10 +0000401 info = type_class.parse(subpath,
402 IniFormatParser(parser.items(section)))
Daniel Dunbardf578252011-11-03 17:56:06 +0000403 except TypeError:
404 print >>sys.stderr, "error: invalid component %r in %r: %s" % (
405 section, path, "unable to instantiate: %r" % type_name)
406 import traceback
407 traceback.print_exc()
408 raise SystemExit, 1
Daniel Dunbar9da6b122011-11-03 17:56:10 +0000409 except ParseError,e:
410 fatal("unable to load component %r in %r: %s" % (
411 section, path, e.message))
Daniel Dunbardf578252011-11-03 17:56:06 +0000412
Daniel Dunbara3217162011-12-12 22:45:35 +0000413 info._source_path = path
Daniel Dunbardf578252011-11-03 17:56:06 +0000414 yield info