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