2 Descriptor objects for entities that are part of the LLVM project.
11 class ParseError(Exception):
14 class ComponentInfo(object):
16 Base class for component descriptions.
22 def parse_items(items, has_dependencies = True):
24 kwargs['name'] = items.get_string('name')
25 kwargs['parent'] = items.get_optional_string('parent')
27 kwargs['dependencies'] = items.get_list('dependencies')
30 def __init__(self, subpath, name, dependencies, parent):
31 if not subpath.startswith('/'):
32 raise ValueError,"invalid subpath: %r" % subpath
33 self.subpath = subpath
35 self.dependencies = list(dependencies)
37 # The name of the parent component to logically group this component
41 # The parent instance, once loaded.
42 self.parent_instance = None
45 # The original source path.
46 self._source_path = None
48 # A flag to mark "special" components which have some amount of magic
49 # handling (generally based on command line options).
50 self._is_special_group = False
52 def set_parent_instance(self, parent):
53 assert parent.name == self.parent, "Unexpected parent!"
54 self.parent_instance = parent
55 self.parent_instance.children.append(self)
57 def get_component_references(self):
58 """get_component_references() -> iter
60 Return an iterator over the named references to other components from
61 this object. Items are of the form (reference-type, component-name).
64 # Parent references are handled specially.
65 for r in self.dependencies:
66 yield ('dependency', r)
68 def get_llvmbuild_fragment(self):
71 def get_parent_target_group(self):
72 """get_parent_target_group() -> ComponentInfo or None
74 Return the nearest parent target group (if any), or None if the
75 component is not part of any target group.
78 # If this is a target group, return it.
79 if self.type_name == 'TargetGroup':
82 # Otherwise recurse on the parent, if any.
83 if self.parent_instance:
84 return self.parent_instance.get_parent_target_group()
86 class GroupComponentInfo(ComponentInfo):
88 Group components have no semantics as far as the build system are concerned,
89 but exist to help organize other components into a logical tree structure.
95 def parse(subpath, items):
96 kwargs = ComponentInfo.parse_items(items, has_dependencies = False)
97 return GroupComponentInfo(subpath, **kwargs)
99 def __init__(self, subpath, name, parent):
100 ComponentInfo.__init__(self, subpath, name, [], parent)
102 def get_llvmbuild_fragment(self):
103 result = StringIO.StringIO()
104 print >>result, 'type = %s' % self.type_name
105 print >>result, 'name = %s' % self.name
106 print >>result, 'parent = %s' % self.parent
107 return result.getvalue()
109 class LibraryComponentInfo(ComponentInfo):
110 type_name = 'Library'
113 def parse_items(items):
114 kwargs = ComponentInfo.parse_items(items)
115 kwargs['library_name'] = items.get_optional_string('library_name')
116 kwargs['required_libraries'] = items.get_list('required_libraries')
117 kwargs['add_to_library_groups'] = items.get_list(
118 'add_to_library_groups')
122 def parse(subpath, items):
123 kwargs = LibraryComponentInfo.parse_items(items)
124 return LibraryComponentInfo(subpath, **kwargs)
126 def __init__(self, subpath, name, dependencies, parent, library_name,
127 required_libraries, add_to_library_groups):
128 ComponentInfo.__init__(self, subpath, name, dependencies, parent)
130 # If given, the name to use for the library instead of deriving it from
131 # the component name.
132 self.library_name = library_name
134 # The names of the library components which are required when linking
135 # with this component.
136 self.required_libraries = list(required_libraries)
138 # The names of the library group components this component should be
139 # considered part of.
140 self.add_to_library_groups = list(add_to_library_groups)
142 def get_component_references(self):
143 for r in ComponentInfo.get_component_references(self):
145 for r in self.required_libraries:
146 yield ('required library', r)
147 for r in self.add_to_library_groups:
148 yield ('library group', r)
150 def get_llvmbuild_fragment(self):
151 result = StringIO.StringIO()
152 print >>result, 'type = %s' % self.type_name
153 print >>result, 'name = %s' % self.name
154 print >>result, 'parent = %s' % self.parent
155 if self.library_name is not None:
156 print >>result, 'library_name = %s' % self.library_name
157 if self.required_libraries:
158 print >>result, 'required_libraries = %s' % ' '.join(
159 self.required_libraries)
160 if self.add_to_library_groups:
161 print >>result, 'add_to_library_groups = %s' % ' '.join(
162 self.add_to_library_groups)
163 return result.getvalue()
165 def get_library_name(self):
166 return self.library_name or self.name
168 def get_prefixed_library_name(self):
170 get_prefixed_library_name() -> str
172 Return the library name prefixed by the project name. This is generally
173 what the library name will be on disk.
176 basename = self.get_library_name()
178 # FIXME: We need to get the prefix information from an explicit project
179 # object, or something.
180 if basename in ('gtest', 'gtest_main'):
183 return 'LLVM%s' % basename
185 def get_llvmconfig_component_name(self):
186 return self.get_library_name().lower()
188 class OptionalLibraryComponentInfo(LibraryComponentInfo):
189 type_name = "OptionalLibrary"
192 def parse(subpath, items):
193 kwargs = LibraryComponentInfo.parse_items(items)
194 return OptionalLibraryComponentInfo(subpath, **kwargs)
196 def __init__(self, subpath, name, dependencies, parent, library_name,
197 required_libraries, add_to_library_groups):
198 LibraryComponentInfo.__init__(self, subpath, name, dependencies, parent,
199 library_name, required_libraries,
200 add_to_library_groups)
202 class LibraryGroupComponentInfo(ComponentInfo):
203 type_name = 'LibraryGroup'
206 def parse(subpath, items):
207 kwargs = ComponentInfo.parse_items(items, has_dependencies = False)
208 kwargs['required_libraries'] = items.get_list('required_libraries')
209 kwargs['add_to_library_groups'] = items.get_list(
210 'add_to_library_groups')
211 return LibraryGroupComponentInfo(subpath, **kwargs)
213 def __init__(self, subpath, name, parent, required_libraries = [],
214 add_to_library_groups = []):
215 ComponentInfo.__init__(self, subpath, name, [], parent)
217 # The names of the library components which are required when linking
218 # with this component.
219 self.required_libraries = list(required_libraries)
221 # The names of the library group components this component should be
222 # considered part of.
223 self.add_to_library_groups = list(add_to_library_groups)
225 def get_component_references(self):
226 for r in ComponentInfo.get_component_references(self):
228 for r in self.required_libraries:
229 yield ('required library', r)
230 for r in self.add_to_library_groups:
231 yield ('library group', r)
233 def get_llvmbuild_fragment(self):
234 result = StringIO.StringIO()
235 print >>result, 'type = %s' % self.type_name
236 print >>result, 'name = %s' % self.name
237 print >>result, 'parent = %s' % self.parent
238 if self.required_libraries and not self._is_special_group:
239 print >>result, 'required_libraries = %s' % ' '.join(
240 self.required_libraries)
241 if self.add_to_library_groups:
242 print >>result, 'add_to_library_groups = %s' % ' '.join(
243 self.add_to_library_groups)
244 return result.getvalue()
246 def get_llvmconfig_component_name(self):
247 return self.name.lower()
249 class TargetGroupComponentInfo(ComponentInfo):
250 type_name = 'TargetGroup'
253 def parse(subpath, items):
254 kwargs = ComponentInfo.parse_items(items, has_dependencies = False)
255 kwargs['required_libraries'] = items.get_list('required_libraries')
256 kwargs['add_to_library_groups'] = items.get_list(
257 'add_to_library_groups')
258 kwargs['has_jit'] = items.get_optional_bool('has_jit', False)
259 kwargs['has_asmprinter'] = items.get_optional_bool('has_asmprinter',
261 kwargs['has_asmparser'] = items.get_optional_bool('has_asmparser',
263 kwargs['has_disassembler'] = items.get_optional_bool('has_disassembler',
265 return TargetGroupComponentInfo(subpath, **kwargs)
267 def __init__(self, subpath, name, parent, required_libraries = [],
268 add_to_library_groups = [], has_jit = False,
269 has_asmprinter = False, has_asmparser = False,
270 has_disassembler = False):
271 ComponentInfo.__init__(self, subpath, name, [], parent)
273 # The names of the library components which are required when linking
274 # with this component.
275 self.required_libraries = list(required_libraries)
277 # The names of the library group components this component should be
278 # considered part of.
279 self.add_to_library_groups = list(add_to_library_groups)
281 # Whether or not this target supports the JIT.
282 self.has_jit = bool(has_jit)
284 # Whether or not this target defines an assembly printer.
285 self.has_asmprinter = bool(has_asmprinter)
287 # Whether or not this target defines an assembly parser.
288 self.has_asmparser = bool(has_asmparser)
290 # Whether or not this target defines an disassembler.
291 self.has_disassembler = bool(has_disassembler)
293 # Whether or not this target is enabled. This is set in response to
294 # configuration parameters.
297 def get_component_references(self):
298 for r in ComponentInfo.get_component_references(self):
300 for r in self.required_libraries:
301 yield ('required library', r)
302 for r in self.add_to_library_groups:
303 yield ('library group', r)
305 def get_llvmbuild_fragment(self):
306 result = StringIO.StringIO()
307 print >>result, 'type = %s' % self.type_name
308 print >>result, 'name = %s' % self.name
309 print >>result, 'parent = %s' % self.parent
310 if self.required_libraries:
311 print >>result, 'required_libraries = %s' % ' '.join(
312 self.required_libraries)
313 if self.add_to_library_groups:
314 print >>result, 'add_to_library_groups = %s' % ' '.join(
315 self.add_to_library_groups)
316 for bool_key in ('has_asmparser', 'has_asmprinter', 'has_disassembler',
318 if getattr(self, bool_key):
319 print >>result, '%s = 1' % (bool_key,)
320 return result.getvalue()
322 def get_llvmconfig_component_name(self):
323 return self.name.lower()
325 class ToolComponentInfo(ComponentInfo):
329 def parse(subpath, items):
330 kwargs = ComponentInfo.parse_items(items)
331 kwargs['required_libraries'] = items.get_list('required_libraries')
332 return ToolComponentInfo(subpath, **kwargs)
334 def __init__(self, subpath, name, dependencies, parent,
336 ComponentInfo.__init__(self, subpath, name, dependencies, parent)
338 # The names of the library components which are required to link this
340 self.required_libraries = list(required_libraries)
342 def get_component_references(self):
343 for r in ComponentInfo.get_component_references(self):
345 for r in self.required_libraries:
346 yield ('required library', r)
348 def get_llvmbuild_fragment(self):
349 result = StringIO.StringIO()
350 print >>result, 'type = %s' % self.type_name
351 print >>result, 'name = %s' % self.name
352 print >>result, 'parent = %s' % self.parent
353 print >>result, 'required_libraries = %s' % ' '.join(
354 self.required_libraries)
355 return result.getvalue()
357 class BuildToolComponentInfo(ToolComponentInfo):
358 type_name = 'BuildTool'
361 def parse(subpath, items):
362 kwargs = ComponentInfo.parse_items(items)
363 kwargs['required_libraries'] = items.get_list('required_libraries')
364 return BuildToolComponentInfo(subpath, **kwargs)
368 class IniFormatParser(dict):
369 def get_list(self, key):
370 # Check if the value is defined.
371 value = self.get(key)
375 # Lists are just whitespace separated strings.
378 def get_optional_string(self, key):
379 value = self.get_list(key)
383 raise ParseError("multiple values for scalar key: %r" % key)
386 def get_string(self, key):
387 value = self.get_optional_string(key)
389 raise ParseError("missing value for required string: %r" % key)
392 def get_optional_bool(self, key, default = None):
393 value = self.get_optional_string(key)
396 if value not in ('0', '1'):
397 raise ParseError("invalid value(%r) for boolean property: %r" % (
399 return bool(int(value))
401 def get_bool(self, key):
402 value = self.get_optional_bool(key)
404 raise ParseError("missing value for required boolean: %r" % key)
407 _component_type_map = dict(
409 for t in (GroupComponentInfo,
410 LibraryComponentInfo, LibraryGroupComponentInfo,
411 ToolComponentInfo, BuildToolComponentInfo,
412 TargetGroupComponentInfo, OptionalLibraryComponentInfo))
413 def load_from_path(path, subpath):
414 # Load the LLVMBuild.txt file as an .ini format file.
415 parser = ConfigParser.RawConfigParser()
418 # Extract the common section.
419 if parser.has_section("common"):
420 common = IniFormatParser(parser.items("common"))
421 parser.remove_section("common")
423 common = IniFormatParser({})
425 return common, _read_components_from_parser(parser, path, subpath)
427 def _read_components_from_parser(parser, path, subpath):
428 # We load each section which starts with 'component' as a distinct component
429 # description (so multiple components can be described in one file).
430 for section in parser.sections():
431 if not section.startswith('component'):
432 # We don't expect arbitrary sections currently, warn the user.
433 warning("ignoring unknown section %r in %r" % (section, path))
436 # Determine the type of the component to instantiate.
437 if not parser.has_option(section, 'type'):
438 fatal("invalid component %r in %r: %s" % (
439 section, path, "no component type"))
441 type_name = parser.get(section, 'type')
442 type_class = _component_type_map.get(type_name)
443 if type_class is None:
444 fatal("invalid component %r in %r: %s" % (
445 section, path, "invalid component type: %r" % type_name))
447 # Instantiate the component based on the remaining values.
449 info = type_class.parse(subpath,
450 IniFormatParser(parser.items(section)))
452 print >>sys.stderr, "error: invalid component %r in %r: %s" % (
453 section, path, "unable to instantiate: %r" % type_name)
455 traceback.print_exc()
458 fatal("unable to load component %r in %r: %s" % (
459 section, path, e.message))
461 info._source_path = path