1df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar"""
2df578254a1241a6cab122aa6d5396995d928e24aDaniel DunbarDescriptor objects for entities that are part of the LLVM project.
3df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar"""
4df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar
5b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbarfrom __future__ import absolute_import
6b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbartry:
7b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbar    import configparser
8b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbarexcept:
9b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbar    import ConfigParser as configparser
10df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbarimport sys
11df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar
12dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesfrom llvmbuild.util import fatal, warning
139da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar
149da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbarclass ParseError(Exception):
159da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar    pass
169da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar
17df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbarclass ComponentInfo(object):
18df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar    """
19df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar    Base class for component descriptions.
20df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar    """
21df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar
22df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar    type_name = None
23df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar
249da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar    @staticmethod
259da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar    def parse_items(items, has_dependencies = True):
269da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        kwargs = {}
279da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        kwargs['name'] = items.get_string('name')
289da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        kwargs['parent'] = items.get_optional_string('parent')
299da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        if has_dependencies:
309da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar            kwargs['dependencies'] = items.get_list('dependencies')
319da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        return kwargs
329da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar
33df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar    def __init__(self, subpath, name, dependencies, parent):
34df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        if not subpath.startswith('/'):
35b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbar            raise ValueError("invalid subpath: %r" % subpath)
36df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        self.subpath = subpath
37df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        self.name = name
38df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        self.dependencies = list(dependencies)
39df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar
40df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        # The name of the parent component to logically group this component
41df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        # under.
42df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        self.parent = parent
43df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar
4486c119a507570144b02645dd262e7d0b8864aa2dDaniel Dunbar        # The parent instance, once loaded.
4586c119a507570144b02645dd262e7d0b8864aa2dDaniel Dunbar        self.parent_instance = None
4686c119a507570144b02645dd262e7d0b8864aa2dDaniel Dunbar        self.children = []
4786c119a507570144b02645dd262e7d0b8864aa2dDaniel Dunbar
48a3217165c6d2ef7caf58665eb0a61c64ab229b9fDaniel Dunbar        # The original source path.
49a3217165c6d2ef7caf58665eb0a61c64ab229b9fDaniel Dunbar        self._source_path = None
50a3217165c6d2ef7caf58665eb0a61c64ab229b9fDaniel Dunbar
5154d8c7fc0359cf9a0b857d27ea6816ea6b050281Daniel Dunbar        # A flag to mark "special" components which have some amount of magic
5254d8c7fc0359cf9a0b857d27ea6816ea6b050281Daniel Dunbar        # handling (generally based on command line options).
5354d8c7fc0359cf9a0b857d27ea6816ea6b050281Daniel Dunbar        self._is_special_group = False
5454d8c7fc0359cf9a0b857d27ea6816ea6b050281Daniel Dunbar
5586c119a507570144b02645dd262e7d0b8864aa2dDaniel Dunbar    def set_parent_instance(self, parent):
5686c119a507570144b02645dd262e7d0b8864aa2dDaniel Dunbar        assert parent.name == self.parent, "Unexpected parent!"
5786c119a507570144b02645dd262e7d0b8864aa2dDaniel Dunbar        self.parent_instance = parent
5886c119a507570144b02645dd262e7d0b8864aa2dDaniel Dunbar        self.parent_instance.children.append(self)
5986c119a507570144b02645dd262e7d0b8864aa2dDaniel Dunbar
601cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar    def get_component_references(self):
611cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar        """get_component_references() -> iter
621cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar
631cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar        Return an iterator over the named references to other components from
641cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar        this object. Items are of the form (reference-type, component-name).
651cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar        """
661cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar
671cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar        # Parent references are handled specially.
681cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar        for r in self.dependencies:
691cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar            yield ('dependency', r)
701cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar
7143120df44b629cc1ef0b587007bec5c31fb799a1Daniel Dunbar    def get_llvmbuild_fragment(self):
7243120df44b629cc1ef0b587007bec5c31fb799a1Daniel Dunbar        abstract
7343120df44b629cc1ef0b587007bec5c31fb799a1Daniel Dunbar
74177a119621f14a6ced87982ada75372815b636cfDaniel Dunbar    def get_parent_target_group(self):
75177a119621f14a6ced87982ada75372815b636cfDaniel Dunbar        """get_parent_target_group() -> ComponentInfo or None
76177a119621f14a6ced87982ada75372815b636cfDaniel Dunbar
77177a119621f14a6ced87982ada75372815b636cfDaniel Dunbar        Return the nearest parent target group (if any), or None if the
78177a119621f14a6ced87982ada75372815b636cfDaniel Dunbar        component is not part of any target group.
79177a119621f14a6ced87982ada75372815b636cfDaniel Dunbar        """
80177a119621f14a6ced87982ada75372815b636cfDaniel Dunbar
81177a119621f14a6ced87982ada75372815b636cfDaniel Dunbar        # If this is a target group, return it.
82177a119621f14a6ced87982ada75372815b636cfDaniel Dunbar        if self.type_name == 'TargetGroup':
83177a119621f14a6ced87982ada75372815b636cfDaniel Dunbar            return self
84177a119621f14a6ced87982ada75372815b636cfDaniel Dunbar
85177a119621f14a6ced87982ada75372815b636cfDaniel Dunbar        # Otherwise recurse on the parent, if any.
86177a119621f14a6ced87982ada75372815b636cfDaniel Dunbar        if self.parent_instance:
87177a119621f14a6ced87982ada75372815b636cfDaniel Dunbar            return self.parent_instance.get_parent_target_group()
88177a119621f14a6ced87982ada75372815b636cfDaniel Dunbar
89df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbarclass GroupComponentInfo(ComponentInfo):
90df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar    """
91df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar    Group components have no semantics as far as the build system are concerned,
92df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar    but exist to help organize other components into a logical tree structure.
93df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar    """
94df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar
95df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar    type_name = 'Group'
96df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar
979da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar    @staticmethod
989da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar    def parse(subpath, items):
999da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        kwargs = ComponentInfo.parse_items(items, has_dependencies = False)
1009da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        return GroupComponentInfo(subpath, **kwargs)
1019da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar
102df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar    def __init__(self, subpath, name, parent):
103df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        ComponentInfo.__init__(self, subpath, name, [], parent)
104df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar
10543120df44b629cc1ef0b587007bec5c31fb799a1Daniel Dunbar    def get_llvmbuild_fragment(self):
106b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbar        return """\
107b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbartype = %s
108b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbarname = %s
109b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbarparent = %s
110b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbar""" % (self.type_name, self.name, self.parent)
11143120df44b629cc1ef0b587007bec5c31fb799a1Daniel Dunbar
112df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbarclass LibraryComponentInfo(ComponentInfo):
113df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar    type_name = 'Library'
114df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar
1159da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar    @staticmethod
116754935418133ece1f51d1857a61d538797c34891Preston Gurd    def parse_items(items):
1179da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        kwargs = ComponentInfo.parse_items(items)
11843120df44b629cc1ef0b587007bec5c31fb799a1Daniel Dunbar        kwargs['library_name'] = items.get_optional_string('library_name')
1199da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        kwargs['required_libraries'] = items.get_list('required_libraries')
1209da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        kwargs['add_to_library_groups'] = items.get_list(
1219da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar            'add_to_library_groups')
122b5cd41e26f89aad2f2dc4f5dc37577f7abf8528aDaniel Dunbar        kwargs['installed'] = items.get_optional_bool('installed', True)
123754935418133ece1f51d1857a61d538797c34891Preston Gurd        return kwargs
124754935418133ece1f51d1857a61d538797c34891Preston Gurd
125754935418133ece1f51d1857a61d538797c34891Preston Gurd    @staticmethod
126754935418133ece1f51d1857a61d538797c34891Preston Gurd    def parse(subpath, items):
127754935418133ece1f51d1857a61d538797c34891Preston Gurd        kwargs = LibraryComponentInfo.parse_items(items)
1289da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        return LibraryComponentInfo(subpath, **kwargs)
1299da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar
1309da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar    def __init__(self, subpath, name, dependencies, parent, library_name,
131b5cd41e26f89aad2f2dc4f5dc37577f7abf8528aDaniel Dunbar                 required_libraries, add_to_library_groups, installed):
132df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        ComponentInfo.__init__(self, subpath, name, dependencies, parent)
133df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar
134df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        # If given, the name to use for the library instead of deriving it from
135df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        # the component name.
136df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        self.library_name = library_name
137df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar
138df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        # The names of the library components which are required when linking
139df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        # with this component.
140df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        self.required_libraries = list(required_libraries)
141df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar
142df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        # The names of the library group components this component should be
143df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        # considered part of.
144df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        self.add_to_library_groups = list(add_to_library_groups)
145df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar
146b5cd41e26f89aad2f2dc4f5dc37577f7abf8528aDaniel Dunbar        # Whether or not this library is installed.
147b5cd41e26f89aad2f2dc4f5dc37577f7abf8528aDaniel Dunbar        self.installed = installed
148b5cd41e26f89aad2f2dc4f5dc37577f7abf8528aDaniel Dunbar
1491cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar    def get_component_references(self):
1501cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar        for r in ComponentInfo.get_component_references(self):
1511cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar            yield r
1521cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar        for r in self.required_libraries:
1531cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar            yield ('required library', r)
1541cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar        for r in self.add_to_library_groups:
1551cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar            yield ('library group', r)
1561cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar
15743120df44b629cc1ef0b587007bec5c31fb799a1Daniel Dunbar    def get_llvmbuild_fragment(self):
158b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbar        result = """\
159b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbartype = %s
160b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbarname = %s
161b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbarparent = %s
162b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbar""" % (self.type_name, self.name, self.parent)
16343120df44b629cc1ef0b587007bec5c31fb799a1Daniel Dunbar        if self.library_name is not None:
164b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbar            result += 'library_name = %s\n' % self.library_name
16543120df44b629cc1ef0b587007bec5c31fb799a1Daniel Dunbar        if self.required_libraries:
166b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbar            result += 'required_libraries = %s\n' % ' '.join(
16743120df44b629cc1ef0b587007bec5c31fb799a1Daniel Dunbar                self.required_libraries)
16843120df44b629cc1ef0b587007bec5c31fb799a1Daniel Dunbar        if self.add_to_library_groups:
169b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbar            result += 'add_to_library_groups = %s\n' % ' '.join(
17043120df44b629cc1ef0b587007bec5c31fb799a1Daniel Dunbar                self.add_to_library_groups)
171b5cd41e26f89aad2f2dc4f5dc37577f7abf8528aDaniel Dunbar        if not self.installed:
172b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbar            result += 'installed = 0\n'
173b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbar        return result
17443120df44b629cc1ef0b587007bec5c31fb799a1Daniel Dunbar
175efe2f644ec15913aa84460bb7ac97b8fa6164b3fDaniel Dunbar    def get_library_name(self):
176efe2f644ec15913aa84460bb7ac97b8fa6164b3fDaniel Dunbar        return self.library_name or self.name
177efe2f644ec15913aa84460bb7ac97b8fa6164b3fDaniel Dunbar
1785086de6f878187f4419351b2b24c766e0d0d25dcDaniel Dunbar    def get_prefixed_library_name(self):
1795086de6f878187f4419351b2b24c766e0d0d25dcDaniel Dunbar        """
1805086de6f878187f4419351b2b24c766e0d0d25dcDaniel Dunbar        get_prefixed_library_name() -> str
1815086de6f878187f4419351b2b24c766e0d0d25dcDaniel Dunbar
1825086de6f878187f4419351b2b24c766e0d0d25dcDaniel Dunbar        Return the library name prefixed by the project name. This is generally
1835086de6f878187f4419351b2b24c766e0d0d25dcDaniel Dunbar        what the library name will be on disk.
1845086de6f878187f4419351b2b24c766e0d0d25dcDaniel Dunbar        """
1855086de6f878187f4419351b2b24c766e0d0d25dcDaniel Dunbar
1865086de6f878187f4419351b2b24c766e0d0d25dcDaniel Dunbar        basename = self.get_library_name()
1875086de6f878187f4419351b2b24c766e0d0d25dcDaniel Dunbar
1885086de6f878187f4419351b2b24c766e0d0d25dcDaniel Dunbar        # FIXME: We need to get the prefix information from an explicit project
1895086de6f878187f4419351b2b24c766e0d0d25dcDaniel Dunbar        # object, or something.
1905086de6f878187f4419351b2b24c766e0d0d25dcDaniel Dunbar        if basename in ('gtest', 'gtest_main'):
1915086de6f878187f4419351b2b24c766e0d0d25dcDaniel Dunbar            return basename
1925086de6f878187f4419351b2b24c766e0d0d25dcDaniel Dunbar
1935086de6f878187f4419351b2b24c766e0d0d25dcDaniel Dunbar        return 'LLVM%s' % basename
1945086de6f878187f4419351b2b24c766e0d0d25dcDaniel Dunbar
195efe2f644ec15913aa84460bb7ac97b8fa6164b3fDaniel Dunbar    def get_llvmconfig_component_name(self):
196efe2f644ec15913aa84460bb7ac97b8fa6164b3fDaniel Dunbar        return self.get_library_name().lower()
197efe2f644ec15913aa84460bb7ac97b8fa6164b3fDaniel Dunbar
198754935418133ece1f51d1857a61d538797c34891Preston Gurdclass OptionalLibraryComponentInfo(LibraryComponentInfo):
199754935418133ece1f51d1857a61d538797c34891Preston Gurd    type_name = "OptionalLibrary"
200754935418133ece1f51d1857a61d538797c34891Preston Gurd
201754935418133ece1f51d1857a61d538797c34891Preston Gurd    @staticmethod
202754935418133ece1f51d1857a61d538797c34891Preston Gurd    def parse(subpath, items):
203754935418133ece1f51d1857a61d538797c34891Preston Gurd      kwargs = LibraryComponentInfo.parse_items(items)
204754935418133ece1f51d1857a61d538797c34891Preston Gurd      return OptionalLibraryComponentInfo(subpath, **kwargs)
205754935418133ece1f51d1857a61d538797c34891Preston Gurd
206754935418133ece1f51d1857a61d538797c34891Preston Gurd    def __init__(self, subpath, name, dependencies, parent, library_name,
207b5cd41e26f89aad2f2dc4f5dc37577f7abf8528aDaniel Dunbar                 required_libraries, add_to_library_groups, installed):
208754935418133ece1f51d1857a61d538797c34891Preston Gurd      LibraryComponentInfo.__init__(self, subpath, name, dependencies, parent,
209754935418133ece1f51d1857a61d538797c34891Preston Gurd                                    library_name, required_libraries,
210b5cd41e26f89aad2f2dc4f5dc37577f7abf8528aDaniel Dunbar                                    add_to_library_groups, installed)
211754935418133ece1f51d1857a61d538797c34891Preston Gurd
212df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbarclass LibraryGroupComponentInfo(ComponentInfo):
213df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar    type_name = 'LibraryGroup'
214df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar
2159da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar    @staticmethod
2169da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar    def parse(subpath, items):
2179da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        kwargs = ComponentInfo.parse_items(items, has_dependencies = False)
2189da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        kwargs['required_libraries'] = items.get_list('required_libraries')
2199da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        kwargs['add_to_library_groups'] = items.get_list(
2209da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar            'add_to_library_groups')
2219da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        return LibraryGroupComponentInfo(subpath, **kwargs)
2229da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar
223df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar    def __init__(self, subpath, name, parent, required_libraries = [],
224df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar                 add_to_library_groups = []):
225df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        ComponentInfo.__init__(self, subpath, name, [], parent)
226df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar
227df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        # The names of the library components which are required when linking
228df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        # with this component.
229df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        self.required_libraries = list(required_libraries)
230df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar
231df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        # The names of the library group components this component should be
232df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        # considered part of.
233df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        self.add_to_library_groups = list(add_to_library_groups)
234df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar
2351cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar    def get_component_references(self):
2361cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar        for r in ComponentInfo.get_component_references(self):
2371cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar            yield r
2381cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar        for r in self.required_libraries:
2391cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar            yield ('required library', r)
2401cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar        for r in self.add_to_library_groups:
2411cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar            yield ('library group', r)
2421cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar
24343120df44b629cc1ef0b587007bec5c31fb799a1Daniel Dunbar    def get_llvmbuild_fragment(self):
244b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbar        result = """\
245b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbartype = %s
246b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbarname = %s
247b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbarparent = %s
248b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbar""" % (self.type_name, self.name, self.parent)
24954d8c7fc0359cf9a0b857d27ea6816ea6b050281Daniel Dunbar        if self.required_libraries and not self._is_special_group:
250b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbar            result += 'required_libraries = %s\n' % ' '.join(
25143120df44b629cc1ef0b587007bec5c31fb799a1Daniel Dunbar                self.required_libraries)
25243120df44b629cc1ef0b587007bec5c31fb799a1Daniel Dunbar        if self.add_to_library_groups:
253b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbar            result += 'add_to_library_groups = %s\n' % ' '.join(
25443120df44b629cc1ef0b587007bec5c31fb799a1Daniel Dunbar                self.add_to_library_groups)
255b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbar        return result
25643120df44b629cc1ef0b587007bec5c31fb799a1Daniel Dunbar
257efe2f644ec15913aa84460bb7ac97b8fa6164b3fDaniel Dunbar    def get_llvmconfig_component_name(self):
258efe2f644ec15913aa84460bb7ac97b8fa6164b3fDaniel Dunbar        return self.name.lower()
259efe2f644ec15913aa84460bb7ac97b8fa6164b3fDaniel Dunbar
260c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbarclass TargetGroupComponentInfo(ComponentInfo):
261c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar    type_name = 'TargetGroup'
262c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar
263c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar    @staticmethod
264c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar    def parse(subpath, items):
265c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar        kwargs = ComponentInfo.parse_items(items, has_dependencies = False)
266c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar        kwargs['required_libraries'] = items.get_list('required_libraries')
267c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar        kwargs['add_to_library_groups'] = items.get_list(
268c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar            'add_to_library_groups')
269c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar        kwargs['has_jit'] = items.get_optional_bool('has_jit', False)
2705ed5506f18fcc0a277c863f7a21b39f58e892ca5Daniel Dunbar        kwargs['has_asmprinter'] = items.get_optional_bool('has_asmprinter',
2715ed5506f18fcc0a277c863f7a21b39f58e892ca5Daniel Dunbar                                                           False)
2725ed5506f18fcc0a277c863f7a21b39f58e892ca5Daniel Dunbar        kwargs['has_asmparser'] = items.get_optional_bool('has_asmparser',
2735ed5506f18fcc0a277c863f7a21b39f58e892ca5Daniel Dunbar                                                          False)
2745ed5506f18fcc0a277c863f7a21b39f58e892ca5Daniel Dunbar        kwargs['has_disassembler'] = items.get_optional_bool('has_disassembler',
2755ed5506f18fcc0a277c863f7a21b39f58e892ca5Daniel Dunbar                                                             False)
276c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar        return TargetGroupComponentInfo(subpath, **kwargs)
277c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar
278c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar    def __init__(self, subpath, name, parent, required_libraries = [],
2795ed5506f18fcc0a277c863f7a21b39f58e892ca5Daniel Dunbar                 add_to_library_groups = [], has_jit = False,
2805ed5506f18fcc0a277c863f7a21b39f58e892ca5Daniel Dunbar                 has_asmprinter = False, has_asmparser = False,
2815ed5506f18fcc0a277c863f7a21b39f58e892ca5Daniel Dunbar                 has_disassembler = False):
282c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar        ComponentInfo.__init__(self, subpath, name, [], parent)
283c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar
284c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar        # The names of the library components which are required when linking
285c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar        # with this component.
286c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar        self.required_libraries = list(required_libraries)
287c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar
288c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar        # The names of the library group components this component should be
289c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar        # considered part of.
290c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar        self.add_to_library_groups = list(add_to_library_groups)
291c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar
292c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar        # Whether or not this target supports the JIT.
293c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar        self.has_jit = bool(has_jit)
294c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar
2955ed5506f18fcc0a277c863f7a21b39f58e892ca5Daniel Dunbar        # Whether or not this target defines an assembly printer.
2965ed5506f18fcc0a277c863f7a21b39f58e892ca5Daniel Dunbar        self.has_asmprinter = bool(has_asmprinter)
2975ed5506f18fcc0a277c863f7a21b39f58e892ca5Daniel Dunbar
2985ed5506f18fcc0a277c863f7a21b39f58e892ca5Daniel Dunbar        # Whether or not this target defines an assembly parser.
2995ed5506f18fcc0a277c863f7a21b39f58e892ca5Daniel Dunbar        self.has_asmparser = bool(has_asmparser)
3005ed5506f18fcc0a277c863f7a21b39f58e892ca5Daniel Dunbar
3015ed5506f18fcc0a277c863f7a21b39f58e892ca5Daniel Dunbar        # Whether or not this target defines an disassembler.
3025ed5506f18fcc0a277c863f7a21b39f58e892ca5Daniel Dunbar        self.has_disassembler = bool(has_disassembler)
3035ed5506f18fcc0a277c863f7a21b39f58e892ca5Daniel Dunbar
304affc6cf9d2b2b74532ce82027ac4524d1e29a658Daniel Dunbar        # Whether or not this target is enabled. This is set in response to
305affc6cf9d2b2b74532ce82027ac4524d1e29a658Daniel Dunbar        # configuration parameters.
306affc6cf9d2b2b74532ce82027ac4524d1e29a658Daniel Dunbar        self.enabled = False
307affc6cf9d2b2b74532ce82027ac4524d1e29a658Daniel Dunbar
308c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar    def get_component_references(self):
309c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar        for r in ComponentInfo.get_component_references(self):
310c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar            yield r
311c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar        for r in self.required_libraries:
312c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar            yield ('required library', r)
313c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar        for r in self.add_to_library_groups:
314c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar            yield ('library group', r)
315c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar
316c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar    def get_llvmbuild_fragment(self):
317b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbar        result = """\
318b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbartype = %s
319b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbarname = %s
320b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbarparent = %s
321b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbar""" % (self.type_name, self.name, self.parent)
322c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar        if self.required_libraries:
323b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbar            result += 'required_libraries = %s\n' % ' '.join(
324c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar                self.required_libraries)
325c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar        if self.add_to_library_groups:
326b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbar            result += 'add_to_library_groups = %s\n' % ' '.join(
327c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar                self.add_to_library_groups)
3285ed5506f18fcc0a277c863f7a21b39f58e892ca5Daniel Dunbar        for bool_key in ('has_asmparser', 'has_asmprinter', 'has_disassembler',
3295ed5506f18fcc0a277c863f7a21b39f58e892ca5Daniel Dunbar                         'has_jit'):
3305ed5506f18fcc0a277c863f7a21b39f58e892ca5Daniel Dunbar            if getattr(self, bool_key):
331b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbar                result += '%s = 1\n' % (bool_key,)
332b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbar        return result
333c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar
334c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar    def get_llvmconfig_component_name(self):
335c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar        return self.name.lower()
336c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar
337df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbarclass ToolComponentInfo(ComponentInfo):
338df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar    type_name = 'Tool'
339df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar
3409da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar    @staticmethod
3419da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar    def parse(subpath, items):
3429da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        kwargs = ComponentInfo.parse_items(items)
3439da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        kwargs['required_libraries'] = items.get_list('required_libraries')
3449da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        return ToolComponentInfo(subpath, **kwargs)
3459da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar
346df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar    def __init__(self, subpath, name, dependencies, parent,
3479da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar                 required_libraries):
348df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        ComponentInfo.__init__(self, subpath, name, dependencies, parent)
349df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar
350df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        # The names of the library components which are required to link this
351df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        # tool.
352df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        self.required_libraries = list(required_libraries)
353df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar
3541cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar    def get_component_references(self):
3551cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar        for r in ComponentInfo.get_component_references(self):
3561cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar            yield r
3571cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar        for r in self.required_libraries:
3581cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar            yield ('required library', r)
3591cf14aff1bd7aa9343262f26f39c7f10fae68c0eDaniel Dunbar
36043120df44b629cc1ef0b587007bec5c31fb799a1Daniel Dunbar    def get_llvmbuild_fragment(self):
361b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbar        return """\
362b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbartype = %s
363b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbarname = %s
364b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbarparent = %s
365b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbarrequired_libraries = %s
366b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbar""" % (self.type_name, self.name, self.parent,
367b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbar       ' '.join(self.required_libraries))
36843120df44b629cc1ef0b587007bec5c31fb799a1Daniel Dunbar
369df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbarclass BuildToolComponentInfo(ToolComponentInfo):
370df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar    type_name = 'BuildTool'
371df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar
3729da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar    @staticmethod
3739da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar    def parse(subpath, items):
3749da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        kwargs = ComponentInfo.parse_items(items)
3759da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        kwargs['required_libraries'] = items.get_list('required_libraries')
3769da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        return BuildToolComponentInfo(subpath, **kwargs)
3779da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar
3789da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar###
3799da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar
3809da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbarclass IniFormatParser(dict):
3819da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar    def get_list(self, key):
3829da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        # Check if the value is defined.
3839da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        value = self.get(key)
3849da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        if value is None:
3859da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar            return []
3869da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar
3879da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        # Lists are just whitespace separated strings.
3889da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        return value.split()
3899da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar
3909da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar    def get_optional_string(self, key):
3919da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        value = self.get_list(key)
3929da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        if not value:
3939da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar            return None
3949da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        if len(value) > 1:
3959da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar            raise ParseError("multiple values for scalar key: %r" % key)
3969da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        return value[0]
3979da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar
3989da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar    def get_string(self, key):
3999da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        value = self.get_optional_string(key)
4009da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        if not value:
4019da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar            raise ParseError("missing value for required string: %r" % key)
4029da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        return value
4039da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar
404c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar    def get_optional_bool(self, key, default = None):
405c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar        value = self.get_optional_string(key)
406c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar        if not value:
407c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar            return default
408c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar        if value not in ('0', '1'):
409c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar            raise ParseError("invalid value(%r) for boolean property: %r" % (
410c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar                    value, key))
411c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar        return bool(int(value))
412c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar
413c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar    def get_bool(self, key):
414c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar        value = self.get_optional_bool(key)
415c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar        if value is None:
416c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar            raise ParseError("missing value for required boolean: %r" % key)
417c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar        return value
418c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar
419df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar_component_type_map = dict(
420df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar    (t.type_name, t)
421df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar    for t in (GroupComponentInfo,
422df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar              LibraryComponentInfo, LibraryGroupComponentInfo,
423c352caf168094c83f05a8010ca14c2e643dbf618Daniel Dunbar              ToolComponentInfo, BuildToolComponentInfo,
424754935418133ece1f51d1857a61d538797c34891Preston Gurd              TargetGroupComponentInfo, OptionalLibraryComponentInfo))
425df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbardef load_from_path(path, subpath):
426df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar    # Load the LLVMBuild.txt file as an .ini format file.
427b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbar    parser = configparser.RawConfigParser()
428df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar    parser.read(path)
429df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar
430e5609abccbd329ef4b07270c8b71a5b59cfe8bceDaniel Dunbar    # Extract the common section.
431e5609abccbd329ef4b07270c8b71a5b59cfe8bceDaniel Dunbar    if parser.has_section("common"):
432e5609abccbd329ef4b07270c8b71a5b59cfe8bceDaniel Dunbar        common = IniFormatParser(parser.items("common"))
433e5609abccbd329ef4b07270c8b71a5b59cfe8bceDaniel Dunbar        parser.remove_section("common")
434e5609abccbd329ef4b07270c8b71a5b59cfe8bceDaniel Dunbar    else:
435e5609abccbd329ef4b07270c8b71a5b59cfe8bceDaniel Dunbar        common = IniFormatParser({})
436e5609abccbd329ef4b07270c8b71a5b59cfe8bceDaniel Dunbar
437e5609abccbd329ef4b07270c8b71a5b59cfe8bceDaniel Dunbar    return common, _read_components_from_parser(parser, path, subpath)
438e5609abccbd329ef4b07270c8b71a5b59cfe8bceDaniel Dunbar
439e5609abccbd329ef4b07270c8b71a5b59cfe8bceDaniel Dunbardef _read_components_from_parser(parser, path, subpath):
440df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar    # We load each section which starts with 'component' as a distinct component
441df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar    # description (so multiple components can be described in one file).
442df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar    for section in parser.sections():
443df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        if not section.startswith('component'):
444df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar            # We don't expect arbitrary sections currently, warn the user.
4459da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar            warning("ignoring unknown section %r in %r" % (section, path))
446df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar            continue
447df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar
4489da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar        # Determine the type of the component to instantiate.
449df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        if not parser.has_option(section, 'type'):
4509da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar            fatal("invalid component %r in %r: %s" % (
4519da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar                    section, path, "no component type"))
452df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar
453df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        type_name = parser.get(section, 'type')
454df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        type_class = _component_type_map.get(type_name)
455df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        if type_class is None:
4569da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar            fatal("invalid component %r in %r: %s" % (
4579da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar                    section, path, "invalid component type: %r" % type_name))
458df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar
459df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        # Instantiate the component based on the remaining values.
460df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        try:
4619da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar            info = type_class.parse(subpath,
4629da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar                                    IniFormatParser(parser.items(section)))
463df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        except TypeError:
464df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar            print >>sys.stderr, "error: invalid component %r in %r: %s" % (
465df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar                section, path, "unable to instantiate: %r" % type_name)
466df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar            import traceback
467df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar            traceback.print_exc()
468b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbar            raise SystemExit(1)
469b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbar        except ParseError:
470b49fb7bcd5001567d2da06f6a6e1c7ba79649e1bDaniel Dunbar            e = sys.exc_info()[1]
4719da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar            fatal("unable to load component %r in %r: %s" % (
4729da6b1244191319b39779307d60d7729811d3d5cDaniel Dunbar                    section, path, e.message))
473df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar
474a3217165c6d2ef7caf58665eb0a61c64ab229b9fDaniel Dunbar        info._source_path = path
475df578254a1241a6cab122aa6d5396995d928e24aDaniel Dunbar        yield info
476