Make IntelJITEvents and OProfileJIT as optional libraries and add
[oota-llvm.git] / utils / llvm-build / llvmbuild / componentinfo.py
1 """
2 Descriptor objects for entities that are part of the LLVM project.
3 """
4
5 import ConfigParser
6 import StringIO
7 import sys
8
9 from util import *
10
11 class ParseError(Exception):
12     pass
13
14 class ComponentInfo(object):
15     """
16     Base class for component descriptions.
17     """
18
19     type_name = None
20
21     @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
30     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
41         # The parent instance, once loaded.
42         self.parent_instance = None
43         self.children = []
44
45         # The original source path.
46         self._source_path = None
47
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
51
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)
56
57     def get_component_references(self):
58         """get_component_references() -> iter
59
60         Return an iterator over the named references to other components from
61         this object. Items are of the form (reference-type, component-name).
62         """
63
64         # Parent references are handled specially.
65         for r in self.dependencies:
66             yield ('dependency', r)
67
68     def get_llvmbuild_fragment(self):
69         abstract
70
71 class GroupComponentInfo(ComponentInfo):
72     """
73     Group components have no semantics as far as the build system are concerned,
74     but exist to help organize other components into a logical tree structure.
75     """
76
77     type_name = 'Group'
78
79     @staticmethod
80     def parse(subpath, items):
81         kwargs = ComponentInfo.parse_items(items, has_dependencies = False)
82         return GroupComponentInfo(subpath, **kwargs)
83
84     def __init__(self, subpath, name, parent):
85         ComponentInfo.__init__(self, subpath, name, [], parent)
86
87     def get_llvmbuild_fragment(self):
88         result = StringIO.StringIO()
89         print >>result, 'type = %s' % self.type_name
90         print >>result, 'name = %s' % self.name
91         print >>result, 'parent = %s' % self.parent
92         return result.getvalue()
93
94 class LibraryComponentInfo(ComponentInfo):
95     type_name = 'Library'
96
97     @staticmethod
98     def parse_items(items):
99         kwargs = ComponentInfo.parse_items(items)
100         kwargs['library_name'] = items.get_optional_string('library_name')
101         kwargs['required_libraries'] = items.get_list('required_libraries')
102         kwargs['add_to_library_groups'] = items.get_list(
103             'add_to_library_groups')
104         return kwargs
105
106     @staticmethod
107     def parse(subpath, items):
108         kwargs = LibraryComponentInfo.parse_items(items)
109         return LibraryComponentInfo(subpath, **kwargs)
110
111     def __init__(self, subpath, name, dependencies, parent, library_name,
112                  required_libraries, add_to_library_groups):
113         ComponentInfo.__init__(self, subpath, name, dependencies, parent)
114
115         # If given, the name to use for the library instead of deriving it from
116         # the component name.
117         self.library_name = library_name
118
119         # The names of the library components which are required when linking
120         # with this component.
121         self.required_libraries = list(required_libraries)
122
123         # The names of the library group components this component should be
124         # considered part of.
125         self.add_to_library_groups = list(add_to_library_groups)
126
127     def get_component_references(self):
128         for r in ComponentInfo.get_component_references(self):
129             yield r
130         for r in self.required_libraries:
131             yield ('required library', r)
132         for r in self.add_to_library_groups:
133             yield ('library group', r)
134
135     def get_llvmbuild_fragment(self):
136         result = StringIO.StringIO()
137         print >>result, 'type = %s' % self.type_name
138         print >>result, 'name = %s' % self.name
139         print >>result, 'parent = %s' % self.parent
140         if self.library_name is not None:
141             print >>result, 'library_name = %s' % self.library_name
142         if self.required_libraries:
143             print >>result, 'required_libraries = %s' % ' '.join(
144                 self.required_libraries)
145         if self.add_to_library_groups:
146             print >>result, 'add_to_library_groups = %s' % ' '.join(
147                 self.add_to_library_groups)
148         return result.getvalue()
149
150     def get_library_name(self):
151         return self.library_name or self.name
152
153     def get_prefixed_library_name(self):
154         """
155         get_prefixed_library_name() -> str
156
157         Return the library name prefixed by the project name. This is generally
158         what the library name will be on disk.
159         """
160
161         basename = self.get_library_name()
162
163         # FIXME: We need to get the prefix information from an explicit project
164         # object, or something.
165         if basename in ('gtest', 'gtest_main'):
166             return basename
167
168         return 'LLVM%s' % basename
169
170     def get_llvmconfig_component_name(self):
171         return self.get_library_name().lower()
172
173 class OptionalLibraryComponentInfo(LibraryComponentInfo):
174     type_name = "OptionalLibrary"
175
176     @staticmethod
177     def parse(subpath, items):
178       kwargs = LibraryComponentInfo.parse_items(items)
179       return OptionalLibraryComponentInfo(subpath, **kwargs)
180
181     def __init__(self, subpath, name, dependencies, parent, library_name,
182                  required_libraries, add_to_library_groups):
183       LibraryComponentInfo.__init__(self, subpath, name, dependencies, parent,
184                                     library_name, required_libraries,
185                                     add_to_library_groups)
186
187 class LibraryGroupComponentInfo(ComponentInfo):
188     type_name = 'LibraryGroup'
189
190     @staticmethod
191     def parse(subpath, items):
192         kwargs = ComponentInfo.parse_items(items, has_dependencies = False)
193         kwargs['required_libraries'] = items.get_list('required_libraries')
194         kwargs['add_to_library_groups'] = items.get_list(
195             'add_to_library_groups')
196         return LibraryGroupComponentInfo(subpath, **kwargs)
197
198     def __init__(self, subpath, name, parent, required_libraries = [],
199                  add_to_library_groups = []):
200         ComponentInfo.__init__(self, subpath, name, [], parent)
201
202         # The names of the library components which are required when linking
203         # with this component.
204         self.required_libraries = list(required_libraries)
205
206         # The names of the library group components this component should be
207         # considered part of.
208         self.add_to_library_groups = list(add_to_library_groups)
209
210     def get_component_references(self):
211         for r in ComponentInfo.get_component_references(self):
212             yield r
213         for r in self.required_libraries:
214             yield ('required library', r)
215         for r in self.add_to_library_groups:
216             yield ('library group', r)
217
218     def get_llvmbuild_fragment(self):
219         result = StringIO.StringIO()
220         print >>result, 'type = %s' % self.type_name
221         print >>result, 'name = %s' % self.name
222         print >>result, 'parent = %s' % self.parent
223         if self.required_libraries and not self._is_special_group:
224             print >>result, 'required_libraries = %s' % ' '.join(
225                 self.required_libraries)
226         if self.add_to_library_groups:
227             print >>result, 'add_to_library_groups = %s' % ' '.join(
228                 self.add_to_library_groups)
229         return result.getvalue()
230
231     def get_llvmconfig_component_name(self):
232         return self.name.lower()
233
234 class TargetGroupComponentInfo(ComponentInfo):
235     type_name = 'TargetGroup'
236
237     @staticmethod
238     def parse(subpath, items):
239         kwargs = ComponentInfo.parse_items(items, has_dependencies = False)
240         kwargs['required_libraries'] = items.get_list('required_libraries')
241         kwargs['add_to_library_groups'] = items.get_list(
242             'add_to_library_groups')
243         kwargs['has_jit'] = items.get_optional_bool('has_jit', False)
244         kwargs['has_asmprinter'] = items.get_optional_bool('has_asmprinter',
245                                                            False)
246         kwargs['has_asmparser'] = items.get_optional_bool('has_asmparser',
247                                                           False)
248         kwargs['has_disassembler'] = items.get_optional_bool('has_disassembler',
249                                                              False)
250         return TargetGroupComponentInfo(subpath, **kwargs)
251
252     def __init__(self, subpath, name, parent, required_libraries = [],
253                  add_to_library_groups = [], has_jit = False,
254                  has_asmprinter = False, has_asmparser = False,
255                  has_disassembler = False):
256         ComponentInfo.__init__(self, subpath, name, [], parent)
257
258         # The names of the library components which are required when linking
259         # with this component.
260         self.required_libraries = list(required_libraries)
261
262         # The names of the library group components this component should be
263         # considered part of.
264         self.add_to_library_groups = list(add_to_library_groups)
265
266         # Whether or not this target supports the JIT.
267         self.has_jit = bool(has_jit)
268
269         # Whether or not this target defines an assembly printer.
270         self.has_asmprinter = bool(has_asmprinter)
271
272         # Whether or not this target defines an assembly parser.
273         self.has_asmparser = bool(has_asmparser)
274
275         # Whether or not this target defines an disassembler.
276         self.has_disassembler = bool(has_disassembler)
277
278         # Whether or not this target is enabled. This is set in response to
279         # configuration parameters.
280         self.enabled = False
281
282     def get_component_references(self):
283         for r in ComponentInfo.get_component_references(self):
284             yield r
285         for r in self.required_libraries:
286             yield ('required library', r)
287         for r in self.add_to_library_groups:
288             yield ('library group', r)
289
290     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         if self.required_libraries:
296             print >>result, 'required_libraries = %s' % ' '.join(
297                 self.required_libraries)
298         if self.add_to_library_groups:
299             print >>result, 'add_to_library_groups = %s' % ' '.join(
300                 self.add_to_library_groups)
301         for bool_key in ('has_asmparser', 'has_asmprinter', 'has_disassembler',
302                          'has_jit'):
303             if getattr(self, bool_key):
304                 print >>result, '%s = 1' % (bool_key,)
305         return result.getvalue()
306
307     def get_llvmconfig_component_name(self):
308         return self.name.lower()
309
310 class ToolComponentInfo(ComponentInfo):
311     type_name = 'Tool'
312
313     @staticmethod
314     def parse(subpath, items):
315         kwargs = ComponentInfo.parse_items(items)
316         kwargs['required_libraries'] = items.get_list('required_libraries')
317         return ToolComponentInfo(subpath, **kwargs)
318
319     def __init__(self, subpath, name, dependencies, parent,
320                  required_libraries):
321         ComponentInfo.__init__(self, subpath, name, dependencies, parent)
322
323         # The names of the library components which are required to link this
324         # tool.
325         self.required_libraries = list(required_libraries)
326
327     def get_component_references(self):
328         for r in ComponentInfo.get_component_references(self):
329             yield r
330         for r in self.required_libraries:
331             yield ('required library', r)
332
333     def get_llvmbuild_fragment(self):
334         result = StringIO.StringIO()
335         print >>result, 'type = %s' % self.type_name
336         print >>result, 'name = %s' % self.name
337         print >>result, 'parent = %s' % self.parent
338         print >>result, 'required_libraries = %s' % ' '.join(
339             self.required_libraries)
340         return result.getvalue()
341
342 class BuildToolComponentInfo(ToolComponentInfo):
343     type_name = 'BuildTool'
344
345     @staticmethod
346     def parse(subpath, items):
347         kwargs = ComponentInfo.parse_items(items)
348         kwargs['required_libraries'] = items.get_list('required_libraries')
349         return BuildToolComponentInfo(subpath, **kwargs)
350
351 ###
352
353 class IniFormatParser(dict):
354     def get_list(self, key):
355         # Check if the value is defined.
356         value = self.get(key)
357         if value is None:
358             return []
359
360         # Lists are just whitespace separated strings.
361         return value.split()
362
363     def get_optional_string(self, key):
364         value = self.get_list(key)
365         if not value:
366             return None
367         if len(value) > 1:
368             raise ParseError("multiple values for scalar key: %r" % key)
369         return value[0]
370
371     def get_string(self, key):
372         value = self.get_optional_string(key)
373         if not value:
374             raise ParseError("missing value for required string: %r" % key)
375         return value
376
377     def get_optional_bool(self, key, default = None):
378         value = self.get_optional_string(key)
379         if not value:
380             return default
381         if value not in ('0', '1'):
382             raise ParseError("invalid value(%r) for boolean property: %r" % (
383                     value, key))
384         return bool(int(value))
385
386     def get_bool(self, key):
387         value = self.get_optional_bool(key)
388         if value is None:
389             raise ParseError("missing value for required boolean: %r" % key)
390         return value
391
392 _component_type_map = dict(
393     (t.type_name, t)
394     for t in (GroupComponentInfo,
395               LibraryComponentInfo, LibraryGroupComponentInfo,
396               ToolComponentInfo, BuildToolComponentInfo,
397               TargetGroupComponentInfo, OptionalLibraryComponentInfo))
398 def load_from_path(path, subpath):
399     # Load the LLVMBuild.txt file as an .ini format file.
400     parser = ConfigParser.RawConfigParser()
401     parser.read(path)
402
403     # Extract the common section.
404     if parser.has_section("common"):
405         common = IniFormatParser(parser.items("common"))
406         parser.remove_section("common")
407     else:
408         common = IniFormatParser({})
409
410     return common, _read_components_from_parser(parser, path, subpath)
411
412 def _read_components_from_parser(parser, path, subpath):
413     # We load each section which starts with 'component' as a distinct component
414     # description (so multiple components can be described in one file).
415     for section in parser.sections():
416         if not section.startswith('component'):
417             # We don't expect arbitrary sections currently, warn the user.
418             warning("ignoring unknown section %r in %r" % (section, path))
419             continue
420
421         # Determine the type of the component to instantiate.
422         if not parser.has_option(section, 'type'):
423             fatal("invalid component %r in %r: %s" % (
424                     section, path, "no component type"))
425
426         type_name = parser.get(section, 'type')
427         type_class = _component_type_map.get(type_name)
428         if type_class is None:
429             fatal("invalid component %r in %r: %s" % (
430                     section, path, "invalid component type: %r" % type_name))
431
432         # Instantiate the component based on the remaining values.
433         try:
434             info = type_class.parse(subpath,
435                                     IniFormatParser(parser.items(section)))
436         except TypeError:
437             print >>sys.stderr, "error: invalid component %r in %r: %s" % (
438                 section, path, "unable to instantiate: %r" % type_name)
439             import traceback
440             traceback.print_exc()
441             raise SystemExit, 1
442         except ParseError,e:
443             fatal("unable to load component %r in %r: %s" % (
444                     section, path, e.message))
445
446         info._source_path = path
447         yield info