2 Descriptor objects for entities that are part of the LLVM project.
5 from __future__
import absolute_import
, print_function
9 import ConfigParser
as configparser
12 from llvmbuild
.util
import fatal
, warning
14 class ParseError(Exception):
17 class ComponentInfo(object):
19 Base class for component descriptions.
25 def parse_items(items
, has_dependencies
= True):
27 kwargs
['name'] = items
.get_string('name')
28 kwargs
['parent'] = items
.get_optional_string('parent')
30 kwargs
['dependencies'] = items
.get_list('dependencies')
33 def __init__(self
, subpath
, name
, dependencies
, parent
):
34 if not subpath
.startswith('/'):
35 raise ValueError("invalid subpath: %r" % subpath
)
36 self
.subpath
= subpath
38 self
.dependencies
= list(dependencies
)
40 # The name of the parent component to logically group this component
44 # The parent instance, once loaded.
45 self
.parent_instance
= None
48 # The original source path.
49 self
._source
_path
= None
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
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
)
60 def get_component_references(self
):
61 """get_component_references() -> iter
63 Return an iterator over the named references to other components from
64 this object. Items are of the form (reference-type, component-name).
67 # Parent references are handled specially.
68 for r
in self
.dependencies
:
69 yield ('dependency', r
)
71 def get_llvmbuild_fragment(self
):
74 def get_parent_target_group(self
):
75 """get_parent_target_group() -> ComponentInfo or None
77 Return the nearest parent target group (if any), or None if the
78 component is not part of any target group.
81 # If this is a target group, return it.
82 if self
.type_name
== 'TargetGroup':
85 # Otherwise recurse on the parent, if any.
86 if self
.parent_instance
:
87 return self
.parent_instance
.get_parent_target_group()
89 class GroupComponentInfo(ComponentInfo
):
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.
98 def parse(subpath
, items
):
99 kwargs
= ComponentInfo
.parse_items(items
, has_dependencies
= False)
100 return GroupComponentInfo(subpath
, **kwargs
)
102 def __init__(self
, subpath
, name
, parent
):
103 ComponentInfo
.__init
__(self
, subpath
, name
, [], parent
)
105 def get_llvmbuild_fragment(self
):
110 """ % (self
.type_name
, self
.name
, self
.parent
)
112 class LibraryComponentInfo(ComponentInfo
):
113 type_name
= 'Library'
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)
126 def parse(subpath
, items
):
127 kwargs
= LibraryComponentInfo
.parse_items(items
)
128 return LibraryComponentInfo(subpath
, **kwargs
)
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
)
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
138 # The names of the library components which are required when linking
139 # with this component.
140 self
.required_libraries
= list(required_libraries
)
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
)
146 # Whether or not this library is installed.
147 self
.installed
= installed
149 def get_component_references(self
):
150 for r
in ComponentInfo
.get_component_references(self
):
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
)
157 def get_llvmbuild_fragment(self
):
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'
175 def get_library_name(self
):
176 return self
.library_name
or self
.name
178 def get_prefixed_library_name(self
):
180 get_prefixed_library_name() -> str
182 Return the library name prefixed by the project name. This is generally
183 what the library name will be on disk.
186 basename
= self
.get_library_name()
188 # FIXME: We need to get the prefix information from an explicit project
189 # object, or something.
190 if basename
in ('gtest', 'gtest_main'):
193 return 'LLVM%s' % basename
195 def get_llvmconfig_component_name(self
):
196 return self
.get_library_name().lower()
198 class OptionalLibraryComponentInfo(LibraryComponentInfo
):
199 type_name
= "OptionalLibrary"
202 def parse(subpath
, items
):
203 kwargs
= LibraryComponentInfo
.parse_items(items
)
204 return OptionalLibraryComponentInfo(subpath
, **kwargs
)
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
)
212 class LibraryGroupComponentInfo(ComponentInfo
):
213 type_name
= 'LibraryGroup'
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
)
223 def __init__(self
, subpath
, name
, parent
, required_libraries
= [],
224 add_to_library_groups
= []):
225 ComponentInfo
.__init
__(self
, subpath
, name
, [], parent
)
227 # The names of the library components which are required when linking
228 # with this component.
229 self
.required_libraries
= list(required_libraries
)
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
)
235 def get_component_references(self
):
236 for r
in ComponentInfo
.get_component_references(self
):
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
)
243 def get_llvmbuild_fragment(self
):
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
)
257 def get_llvmconfig_component_name(self
):
258 return self
.name
.lower()
260 class TargetGroupComponentInfo(ComponentInfo
):
261 type_name
= 'TargetGroup'
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',
272 kwargs
['has_asmparser'] = items
.get_optional_bool('has_asmparser',
274 kwargs
['has_disassembler'] = items
.get_optional_bool('has_disassembler',
276 return TargetGroupComponentInfo(subpath
, **kwargs
)
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
)
284 # The names of the library components which are required when linking
285 # with this component.
286 self
.required_libraries
= list(required_libraries
)
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
)
292 # Whether or not this target supports the JIT.
293 self
.has_jit
= bool(has_jit
)
295 # Whether or not this target defines an assembly printer.
296 self
.has_asmprinter
= bool(has_asmprinter
)
298 # Whether or not this target defines an assembly parser.
299 self
.has_asmparser
= bool(has_asmparser
)
301 # Whether or not this target defines an disassembler.
302 self
.has_disassembler
= bool(has_disassembler
)
304 # Whether or not this target is enabled. This is set in response to
305 # configuration parameters.
308 def get_component_references(self
):
309 for r
in ComponentInfo
.get_component_references(self
):
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
)
316 def get_llvmbuild_fragment(self
):
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',
330 if getattr(self
, bool_key
):
331 result
+= '%s = 1\n' % (bool_key
,)
334 def get_llvmconfig_component_name(self
):
335 return self
.name
.lower()
337 class ToolComponentInfo(ComponentInfo
):
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
)
346 def __init__(self
, subpath
, name
, dependencies
, parent
,
348 ComponentInfo
.__init
__(self
, subpath
, name
, dependencies
, parent
)
350 # The names of the library components which are required to link this
352 self
.required_libraries
= list(required_libraries
)
354 def get_component_references(self
):
355 for r
in ComponentInfo
.get_component_references(self
):
357 for r
in self
.required_libraries
:
358 yield ('required library', r
)
360 def get_llvmbuild_fragment(self
):
365 required_libraries = %s
366 """ % (self
.type_name
, self
.name
, self
.parent
,
367 ' '.join(self
.required_libraries
))
369 class BuildToolComponentInfo(ToolComponentInfo
):
370 type_name
= 'BuildTool'
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
)
380 class IniFormatParser(dict):
381 def get_list(self
, key
):
382 # Check if the value is defined.
383 value
= self
.get(key
)
387 # Lists are just whitespace separated strings.
390 def get_optional_string(self
, key
):
391 value
= self
.get_list(key
)
395 raise ParseError("multiple values for scalar key: %r" % key
)
398 def get_string(self
, key
):
399 value
= self
.get_optional_string(key
)
401 raise ParseError("missing value for required string: %r" % key
)
404 def get_optional_bool(self
, key
, default
= None):
405 value
= self
.get_optional_string(key
)
408 if value
not in ('0', '1'):
409 raise ParseError("invalid value(%r) for boolean property: %r" % (
411 return bool(int(value
))
413 def get_bool(self
, key
):
414 value
= self
.get_optional_bool(key
)
416 raise ParseError("missing value for required boolean: %r" % key
)
419 _component_type_map
= dict(
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()
430 # Extract the common section.
431 if parser
.has_section("common"):
432 common
= IniFormatParser(parser
.items("common"))
433 parser
.remove_section("common")
435 common
= IniFormatParser({})
437 return common
, _read_components_from_parser(parser
, path
, subpath
)
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
))
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"))
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
))
459 # Instantiate the component based on the remaining values.
461 info
= type_class
.parse(subpath
,
462 IniFormatParser(parser
.items(section
)))
464 print("error: invalid component %r in %r: %s" % (
465 section
, path
, "unable to instantiate: %r" % type_name
), file=sys
.stderr
)
467 traceback
.print_exc()
470 e
= sys
.exc_info()[1]
471 fatal("unable to load component %r in %r: %s" % (
472 section
, path
, e
.message
))
474 info
._source
_path
= path