llvm-build: Add --native-target and --enable-targets options, and add logic to
[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     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
50     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
61     def get_llvmbuild_fragment(self):
62         abstract
63
64 class 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
72     @staticmethod
73     def parse(subpath, items):
74         kwargs = ComponentInfo.parse_items(items, has_dependencies = False)
75         return GroupComponentInfo(subpath, **kwargs)
76
77     def __init__(self, subpath, name, parent):
78         ComponentInfo.__init__(self, subpath, name, [], parent)
79
80     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
87 class LibraryComponentInfo(ComponentInfo):
88     type_name = 'Library'
89
90     @staticmethod
91     def parse(subpath, items):
92         kwargs = ComponentInfo.parse_items(items)
93         kwargs['library_name'] = items.get_optional_string('library_name')
94         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):
101         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
115     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
123     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
138     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
144 class LibraryGroupComponentInfo(ComponentInfo):
145     type_name = 'LibraryGroup'
146
147     @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
155     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
167     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
175     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
188     def get_llvmconfig_component_name(self):
189         return self.name.lower()
190
191 class 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)
201         return TargetGroupComponentInfo(subpath, **kwargs)
202
203     def __init__(self, subpath, name, parent, required_libraries = [],
204                  add_to_library_groups = [], has_jit = False):
205         ComponentInfo.__init__(self, subpath, name, [], parent)
206
207         # The names of the library components which are required when linking
208         # with this component.
209         self.required_libraries = list(required_libraries)
210
211         # The names of the library group components this component should be
212         # considered part of.
213         self.add_to_library_groups = list(add_to_library_groups)
214
215         # Whether or not this target supports the JIT.
216         self.has_jit = bool(has_jit)
217
218         # Whether or not this target is enabled. This is set in response to
219         # configuration parameters.
220         self.enabled = False
221
222     def get_component_references(self):
223         for r in ComponentInfo.get_component_references(self):
224             yield r
225         for r in self.required_libraries:
226             yield ('required library', r)
227         for r in self.add_to_library_groups:
228             yield ('library group', r)
229
230     def get_llvmbuild_fragment(self):
231         result = StringIO.StringIO()
232         print >>result, 'type = %s' % self.type_name
233         print >>result, 'name = %s' % self.name
234         print >>result, 'parent = %s' % self.parent
235         if self.required_libraries:
236             print >>result, 'required_libraries = %s' % ' '.join(
237                 self.required_libraries)
238         if self.add_to_library_groups:
239             print >>result, 'add_to_library_groups = %s' % ' '.join(
240                 self.add_to_library_groups)
241         if self.has_jit:
242             print >>result, 'has_jit = %s' % ' '.join(
243                 int(self.has_jit))
244         return result.getvalue()
245
246     def get_llvmconfig_component_name(self):
247         return self.name.lower()
248
249 class ToolComponentInfo(ComponentInfo):
250     type_name = 'Tool'
251
252     @staticmethod
253     def parse(subpath, items):
254         kwargs = ComponentInfo.parse_items(items)
255         kwargs['required_libraries'] = items.get_list('required_libraries')
256         return ToolComponentInfo(subpath, **kwargs)
257
258     def __init__(self, subpath, name, dependencies, parent,
259                  required_libraries):
260         ComponentInfo.__init__(self, subpath, name, dependencies, parent)
261
262         # The names of the library components which are required to link this
263         # tool.
264         self.required_libraries = list(required_libraries)
265
266     def get_component_references(self):
267         for r in ComponentInfo.get_component_references(self):
268             yield r
269         for r in self.required_libraries:
270             yield ('required library', r)
271
272     def get_llvmbuild_fragment(self):
273         result = StringIO.StringIO()
274         print >>result, 'type = %s' % self.type_name
275         print >>result, 'name = %s' % self.name
276         print >>result, 'parent = %s' % self.parent
277         print >>result, 'required_libraries = %s' % ' '.join(
278             self.required_libraries)
279         return result.getvalue()
280
281 class BuildToolComponentInfo(ToolComponentInfo):
282     type_name = 'BuildTool'
283
284     @staticmethod
285     def parse(subpath, items):
286         kwargs = ComponentInfo.parse_items(items)
287         kwargs['required_libraries'] = items.get_list('required_libraries')
288         return BuildToolComponentInfo(subpath, **kwargs)
289
290 ###
291
292 class IniFormatParser(dict):
293     def get_list(self, key):
294         # Check if the value is defined.
295         value = self.get(key)
296         if value is None:
297             return []
298
299         # Lists are just whitespace separated strings.
300         return value.split()
301
302     def get_optional_string(self, key):
303         value = self.get_list(key)
304         if not value:
305             return None
306         if len(value) > 1:
307             raise ParseError("multiple values for scalar key: %r" % key)
308         return value[0]
309
310     def get_string(self, key):
311         value = self.get_optional_string(key)
312         if not value:
313             raise ParseError("missing value for required string: %r" % key)
314         return value
315
316     def get_optional_bool(self, key, default = None):
317         value = self.get_optional_string(key)
318         if not value:
319             return default
320         if value not in ('0', '1'):
321             raise ParseError("invalid value(%r) for boolean property: %r" % (
322                     value, key))
323         return bool(int(value))
324
325     def get_bool(self, key):
326         value = self.get_optional_bool(key)
327         if value is None:
328             raise ParseError("missing value for required boolean: %r" % key)
329         return value
330
331 _component_type_map = dict(
332     (t.type_name, t)
333     for t in (GroupComponentInfo,
334               LibraryComponentInfo, LibraryGroupComponentInfo,
335               ToolComponentInfo, BuildToolComponentInfo,
336               TargetGroupComponentInfo))
337 def load_from_path(path, subpath):
338     # Load the LLVMBuild.txt file as an .ini format file.
339     parser = ConfigParser.RawConfigParser()
340     parser.read(path)
341
342     # We load each section which starts with 'component' as a distinct component
343     # description (so multiple components can be described in one file).
344     for section in parser.sections():
345         if not section.startswith('component'):
346             # We don't expect arbitrary sections currently, warn the user.
347             warning("ignoring unknown section %r in %r" % (section, path))
348             continue
349
350         # Determine the type of the component to instantiate.
351         if not parser.has_option(section, 'type'):
352             fatal("invalid component %r in %r: %s" % (
353                     section, path, "no component type"))
354
355         type_name = parser.get(section, 'type')
356         type_class = _component_type_map.get(type_name)
357         if type_class is None:
358             fatal("invalid component %r in %r: %s" % (
359                     section, path, "invalid component type: %r" % type_name))
360
361         # Instantiate the component based on the remaining values.
362         try:
363             info = type_class.parse(subpath,
364                                     IniFormatParser(parser.items(section)))
365         except TypeError:
366             print >>sys.stderr, "error: invalid component %r in %r: %s" % (
367                 section, path, "unable to instantiate: %r" % type_name)
368             import traceback
369             traceback.print_exc()
370             raise SystemExit, 1
371         except ParseError,e:
372             fatal("unable to load component %r in %r: %s" % (
373                     section, path, e.message))
374
375         yield info