62,86c62,63
< # When specifying a source file of some type, a set of guards can be
< # specified for that file. When get() is used to find the files, if
< # get specifies a set of filters, only files that match those filters
< # will be accepted (unspecified filters on files are assumed to be
< # false). Current filters are:
< # main -- specifies the gem5 main() function
< # skip_lib -- do not put this file into the gem5 library
< # skip_no_python -- do not put this file into a no_python library
< # as it embeds compiled Python
< # <unittest> -- unit tests use filters based on the unit test name
< #
< # A parent can now be specified for a source file and default filter
< # values will be retrieved recursively from parents (children override
< # parents).
< #
< def guarded_source_iterator(sources, **guards):
< '''Iterate over a set of sources, gated by a set of guards.'''
< for src in sources:
< for flag,value in guards.iteritems():
< # if the flag is found and has a different value, skip
< # this file
< if src.all_guards.get(flag, False) != value:
< break
< else:
< yield src
---
> # When specifying a source file of some type, a set of tags can be
> # specified for that file.
87a65,91
> class SourceList(list):
> def with_tags_that(self, predicate):
> '''Return a list of sources with tags that satisfy a predicate.'''
> def match(source):
> return predicate(source.tags)
> return SourceList(filter(match, self))
>
> def with_any_tags(self, *tags):
> '''Return a list of sources with any of the supplied tags.'''
> return self.with_tags_that(lambda stags: len(tags & stags) > 0)
>
> def with_all_tags(self, *tags):
> '''Return a list of sources with all of the supplied tags.'''
> return self.with_tags_that(lambda stags: tags <= stags)
>
> def with_tag(self, tag):
> '''Return a list of sources with the supplied tag.'''
> return self.with_tags_that(lambda stags: tag in stags)
>
> def without_tags(self, *tags):
> '''Return a list of sources without any of the supplied tags.'''
> return self.with_tags_that(lambda stags: len(tags & stags) == 0)
>
> def without_tag(self, tag):
> '''Return a list of sources with the supplied tag.'''
> return self.with_tags_that(lambda stags: tag not in stags)
>
90,91c94
< particular type and has a get function for finding all functions
< of a certain type that match a set of guards'''
---
> particular type.'''
94c97
< cls.all = []
---
> cls.all = SourceList()
96,101d98
< def get(cls, **guards):
< '''Find all files that match the specified guards. If a source
< file does not specify a flag, the default is False'''
< for s in guarded_source_iterator(cls.all, **guards):
< yield s
<
105,107c102,103
< of those. A source file also specifies a set of guards which
< describing which builds the source file applies to. A parent can
< also be specified to get default guards from'''
---
> of those. A source file also specifies a set of tags which
> describing arbitrary properties of the source file.'''
109,111c105,114
< def __init__(self, source, parent=None, **guards):
< self.guards = guards
< self.parent = parent
---
> def __init__(self, source, tags=None, add_tags=None):
> if tags is None:
> tags='gem5 lib'
> if isinstance(tags, basestring):
> tags = set([tags])
> if isinstance(add_tags, basestring):
> add_tags = set([add_tags])
> if add_tags:
> tags = tags | add_tags
> self.tags = set(tags)
145,154d147
< @property
< def all_guards(self):
< '''find all guards for this object getting default values
< recursively from its parents'''
< guards = {}
< if self.parent:
< guards.update(self.parent.guards)
< guards.update(self.guards)
< return guards
<
171,172c164,165
< current_group = None
< source_groups = { None : [] }
---
> ungrouped_tag = 'No link group'
> source_groups = set()
173a167,172
> _current_group_tag = ungrouped_tag
>
> @staticmethod
> def link_group_tag(group):
> return 'link group: %s' % group
>
176,178c175,177
< if not group in Source.source_groups:
< Source.source_groups[group] = []
< Source.current_group = group
---
> new_tag = Source.link_group_tag(group)
> Source._current_group_tag = new_tag
> Source.source_groups.add(group)
180,183c179,180
< '''Add a c/c++ source file to the build'''
< def __init__(self, source, Werror=True, **guards):
< '''specify the source file, and any guards'''
< super(Source, self).__init__(source, **guards)
---
> def _add_link_group_tag(self):
> self.tags.add(Source._current_group_tag)
184a182,186
> '''Add a c/c++ source file to the build'''
> def __init__(self, source, tags=None, add_tags=None, Werror=True):
> '''specify the source file, and any tags'''
> super(Source, self).__init__(source, tags, add_tags)
> self._add_link_group_tag()
187,188d188
< Source.source_groups[Source.current_group].append(self)
<
196,198c196,198
< def __init__(self, package, source, **guards):
< '''specify the python package, the source file, and any guards'''
< super(PySource, self).__init__(source, **guards)
---
> def __init__(self, package, source, tags=None, add_tags=None):
> '''specify the python package, the source file, and any tags'''
> super(PySource, self).__init__(source, tags, add_tags)
238,239c238,239
< def __init__(self, source, **guards):
< '''Specify the source file and any guards (automatically in
---
> def __init__(self, source, tags=None, add_tags=None):
> '''Specify the source file and any tags (automatically in
241c241
< super(SimObject, self).__init__('m5.objects', source, **guards)
---
> super(SimObject, self).__init__('m5.objects', source, tags, add_tags)
250,252c250,252
< def __init__(self, source, **guards):
< '''Specify the source file, and any guards'''
< super(ProtoBuf, self).__init__(source, **guards)
---
> def __init__(self, source, tags=None, add_tags=None):
> '''Specify the source file, and any tags'''
> super(ProtoBuf, self).__init__(source, tags, add_tags)
270,271c270
< guarded with a guard of the same name as the UnitTest
< target.'''
---
> tagged with the name of the UnitTest target.'''
273c272
< srcs = []
---
> srcs = SourceList()
276,277c275
< src = Source(src, skip_lib=True)
< src.guards[target] = True
---
> src = Source(src, tags=str(target))
773c771
< Source(proto.cc_file, **proto.guards)
---
> Source(proto.cc_file, tags=proto.tags)
939c937
< Source(source.cpp, skip_no_python=True)
---
> Source(source.cpp, tags=source.tags, add_tags='python')
948c946
< date_source = Source('base/date.cc', skip_lib=True)
---
> date_source = Source('base/date.cc', tags=[])
1031c1029
< lib_guards = {'main': False, 'skip_lib': False}
---
> lib_sources = Source.all.with_tag('gem5 lib')
1036c1034
< lib_guards['skip_no_python'] = False
---
> lib_sources = lib_sources.without_tag('python')
1040c1038,1039
< for s in guarded_source_iterator(Source.source_groups[None], **lib_guards):
---
>
> for s in lib_sources.with_tag(Source.ungrouped_tag):
1045,1048d1043
< for group, all_srcs in Source.source_groups.iteritems():
< # If these are the ungrouped source files, skip them.
< if not group:
< continue
1050,1052c1045,1046
< # Get a list of the source files compatible with the current guards.
< srcs = [ s for s in guarded_source_iterator(all_srcs, **lib_guards) ]
< # If there aren't any left, skip this group.
---
> for group in Source.source_groups:
> srcs = lib_sources.with_tag(Source.link_group_tag(group))
1090c1084
< main_objs = [ make_obj(s, True) for s in Source.get(main=True) ]
---
> main_objs = [ make_obj(s, True) for s in Source.all.with_tag('main') ]
1093,1094c1087
< flags = { test.target : True }
< test_sources = Source.get(**flags)
---
> test_sources = Source.all.with_tag(str(test.target))