summaryrefslogtreecommitdiff
path: root/src/SConscript
diff options
context:
space:
mode:
Diffstat (limited to 'src/SConscript')
-rwxr-xr-xsrc/SConscript175
1 files changed, 84 insertions, 91 deletions
diff --git a/src/SConscript b/src/SConscript
index 6c3f22019..da8476d6c 100755
--- a/src/SConscript
+++ b/src/SConscript
@@ -59,56 +59,59 @@ from m5.util import code_formatter, compareVersions
########################################################################
# Code for adding source files of various types
#
-# 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.
+
+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)
class SourceMeta(type):
'''Meta class for source files that keeps track of all files of a
- particular type and has a get function for finding all functions
- of a certain type that match a set of guards'''
+ particular type.'''
def __init__(cls, name, bases, dict):
super(SourceMeta, cls).__init__(name, bases, dict)
- cls.all = []
-
- 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
+ cls.all = SourceList()
class SourceFile(object):
'''Base object that encapsulates the notion of a source file.
This includes, the source node, target node, various manipulations
- 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.'''
__metaclass__ = SourceMeta
- 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)
tnode = source
if not isinstance(source, SCons.Node.FS.File):
@@ -142,16 +145,6 @@ class SourceFile(object):
return self.basename[:index], self.basename[index+1:]
- @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
-
def __lt__(self, other): return self.filename < other.filename
def __le__(self, other): return self.filename <= other.filename
def __gt__(self, other): return self.filename > other.filename
@@ -168,24 +161,31 @@ class SourceFile(object):
class Source(SourceFile):
- current_group = None
- source_groups = { None : [] }
+ ungrouped_tag = 'No link group'
+ source_groups = set()
+
+ _current_group_tag = ungrouped_tag
+
+ @staticmethod
+ def link_group_tag(group):
+ return 'link group: %s' % group
@classmethod
def set_group(cls, group):
- 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)
- '''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)
+ '''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()
self.Werror = Werror
- Source.source_groups[Source.current_group].append(self)
-
class PySource(SourceFile):
'''Add a python source file to the named package'''
invalid_sym_char = re.compile('[^A-z0-9_]')
@@ -193,9 +193,9 @@ class PySource(SourceFile):
tnodes = {}
symnames = {}
- 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)
modname,ext = self.extname
assert ext == 'py'
@@ -235,10 +235,10 @@ class SimObject(PySource):
fixed = False
modnames = []
- 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
the m5.objects package)'''
- super(SimObject, self).__init__('m5.objects', source, **guards)
+ super(SimObject, self).__init__('m5.objects', source, tags, add_tags)
if self.fixed:
raise AttributeError, "Too late to call SimObject now."
@@ -247,9 +247,9 @@ class SimObject(PySource):
class ProtoBuf(SourceFile):
'''Add a Protocol Buffer to build'''
- 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)
# Get the file name and the extension
modname,ext = self.extname
@@ -267,14 +267,12 @@ class UnitTest(object):
def __init__(self, target, *sources, **kwargs):
'''Specify the target name and any sources. Sources that are
not SourceFiles are evalued with Source(). All files are
- guarded with a guard of the same name as the UnitTest
- target.'''
+ tagged with the name of the UnitTest target.'''
- srcs = []
+ srcs = SourceList()
for src in sources:
if not isinstance(src, SourceFile):
- src = Source(src, skip_lib=True)
- src.guards[target] = True
+ src = Source(src, tags=str(target))
srcs.append(src)
self.sources = srcs
@@ -770,7 +768,7 @@ if env['HAVE_PROTOBUF']:
Transform("PROTOC")))
# Add the C++ source file
- Source(proto.cc_file, **proto.guards)
+ Source(proto.cc_file, tags=proto.tags)
elif ProtoBuf.all:
print 'Got protobuf to build, but lacks support!'
Exit(1)
@@ -936,7 +934,7 @@ EmbeddedPython embedded_${sym}(
for source in PySource.all:
env.Command(source.cpp, source.tnode,
MakeAction(embedPyFile, Transform("EMBED PY")))
- Source(source.cpp, skip_no_python=True)
+ Source(source.cpp, tags=source.tags, add_tags='python')
########################################################################
#
@@ -945,7 +943,7 @@ for source in PySource.all:
#
# List of constructed environments to pass back to SConstruct
-date_source = Source('base/date.cc', skip_lib=True)
+date_source = Source('base/date.cc', tags=[])
# Function to create a new build environment as clone of current
# environment 'env' with modified object suffix and optional stripped
@@ -1028,28 +1026,24 @@ def makeEnv(env, label, objsfx, strip=False, disable_partial=False, **kwargs):
return obj
- lib_guards = {'main': False, 'skip_lib': False}
+ lib_sources = Source.all.with_tag('gem5 lib')
# Without Python, leave out all Python content from the library
# builds. The option doesn't affect gem5 built as a program
if GetOption('without_python'):
- lib_guards['skip_no_python'] = False
+ lib_sources = lib_sources.without_tag('python')
static_objs = []
shared_objs = []
- for s in guarded_source_iterator(Source.source_groups[None], **lib_guards):
+
+ for s in lib_sources.with_tag(Source.ungrouped_tag):
static_objs.append(make_obj(s, True))
shared_objs.append(make_obj(s, False))
partial_objs = []
- for group, all_srcs in Source.source_groups.iteritems():
- # If these are the ungrouped source files, skip them.
- if not group:
- continue
- # 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))
if not srcs:
continue
@@ -1087,11 +1081,10 @@ def makeEnv(env, label, objsfx, strip=False, disable_partial=False, **kwargs):
shared_lib = new_env.SharedLibrary(libname, shared_objs)
# Now link a stub with main() and the static library.
- 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') ]
for test in UnitTest.all:
- flags = { test.target : True }
- test_sources = Source.get(**flags)
+ test_sources = Source.all.with_tag(str(test.target))
test_objs = [ make_obj(s, static=True) for s in test_sources ]
if test.main:
test_objs += main_objs