Gabe Black has uploaded this change for review. ( https://gem5-review.googlesource.com/c/public/gem5/+/44388 )

Change subject: scons: Move loose tag_implies to env.TagImplies.
......................................................................

scons: Move loose tag_implies to env.TagImplies.

Also plumb through an environment to resolve tags against when applying
filters to source lists.

Change-Id: I93010d208272fcfa5f1a13219d58f237f82e3ed9
---
M src/SConscript
1 file changed, 60 insertions(+), 69 deletions(-)



diff --git a/src/SConscript b/src/SConscript
index 6206e1a..e5536dd 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -71,7 +71,7 @@
 # When specifying a source file of some type, a set of tags can be
 # specified for that file.

-class TagImplies(object):
+def tag_implies(env, tag, tag_list):
     '''
     Associates a tag X to a list of tags which are implied by X.

@@ -98,73 +98,64 @@
     after being resolved.
     '''

-    # The dictionary of tag dependencies, which is populated with every
-    # instance of this class
-    _dependencies = {}
+    env.SetDefault(_tag_implies={})
+    implications = env['_tag_implies']
+    if tag in implications:
+        raise AttributeError("Dependency list of tag {} has already " \
+            "been specified".format(tag))

-    def __init__(self, tag, tag_list):
-        if tag in TagImplies._dependencies:
-            raise AttributeError("Dependency list of tag {} has already " \
-                "been specified".format(tag))
+    if isinstance(tag_list, str):
+        tag_list = frozenset([tag_list])
+    if not isinstance(tag_list, frozenset):
+        tag_list = frozenset(tag_list)
+    implications[tag] = tag_list

-        if isinstance(tag_list, str):
-            tag_list = frozenset([tag_list])
-        if not isinstance(tag_list, frozenset):
-            tag_list = frozenset(tag_list)
-        TagImplies._dependencies[tag] = tag_list
+    # Check if any of the tags on which the new tag depends on already
+    # has a list of dependencies. If so, add the list to the new tag's
+    # dependencies
+    for t in tag_list:
+        if t in implications:
+            implications[tag] |= implications[t]

-        # Check if any of the tags on which the new tag depends on already
-        # has a list of dependencies. If so, add the list to the new tag's
-        # dependencies
-        for t in tag_list:
-            if t in TagImplies._dependencies:
-                TagImplies._dependencies[tag] |= \
-                    TagImplies._dependencies[t]
+    # Check if another tag depends on this tag. If so, add this tag's
+    # dependencies to that tag.
+    for t,dep in implications.items():
+        if tag in dep:
+            implications[t] |= implications[tag]

-        # Check if another tag depends on this tag. If so, add this tag's
-        # dependencies to that tag.
-        for t,dep in TagImplies._dependencies.items():
-            if tag in dep:
-                TagImplies._dependencies[t] |= \
-                    TagImplies._dependencies[tag]
+env.AddMethod(tag_implies, 'TagImplies')

-    def resolve(tags):
-        '''
-        Returns the complete set of tags implied (dependencies) by the
-        supplied tags.
-        '''
-        if isinstance(tags, str):
-            tags = frozenset([tags])
-        if not isinstance(tags, frozenset):
-            tags = frozenset(tags)
-
-        dependencies = set()
-        dependencies |= tags
-        for tag in tags:
-            if tag in TagImplies._dependencies:
-                dependencies |= TagImplies._dependencies[tag]
-        return dependencies
-
-# External API
-def tag_implies(tag, implied_tags):
+def resolve_tags(env, tags):
     '''
-    Associates a tag X to a list of tags which are implied by X.
-    @see TagImplies
+    Returns the complete set of tags implied (dependencies) by the
+    supplied tags.
     '''
-    TagImplies(tag, implied_tags)
-Export('tag_implies')
+
+    implications = env.SetDefault(_tag_implies={})
+    implications = env['_tag_implies']
+
+    if isinstance(tags, str):
+        tags = frozenset([tags])
+    if not isinstance(tags, frozenset):
+        tags = frozenset(tags)
+
+    tags = tags.copy()
+    for tag in tags:
+        if tag in implications:
+            tags |= implications[tag]
+    return tags

 class SourceFilter(object):
     def __init__(self, predicate):
         self.predicate = predicate

     def __or__(self, other):
-        return SourceFilter(lambda tags: self.predicate(tags) or
-                                         other.predicate(tags))
+        return SourceFilter(lambda env, tags: self.predicate(env, tags) or
+                                              other.predicate(env, tags))

     def __and__(self, other):
-        return SourceFilter(lambda tags: self.predicate(tags) and
-                                         other.predicate(tags))
+        return SourceFilter(lambda env, tags: self.predicate(env, tags) and
+                                              other.predicate(env, tags))

 def with_tags_that(predicate):
     '''Return a list of sources with tags that satisfy a predicate.'''
@@ -172,13 +163,12 @@

 def with_any_tags(*tags):
     '''Return a list of sources with any of the supplied tags.'''
-    return SourceFilter(lambda stags: \
-        len(TagImplies.resolve(tags) & stags) > 0)
+    return SourceFilter(lambda env, stags: \
+        len(resolve_tags(env, tags) & stags) > 0)

 def with_all_tags(*tags):
     '''Return a list of sources with all of the supplied tags.'''
-    return SourceFilter(lambda stags: \
-        TagImplies.resolve(tags) <= stags)
+ return SourceFilter(lambda env, stags: resolve_tags(env, tags) <= stags)

 def with_tag(tag):
     '''Return a list of sources with the supplied tag.'''
@@ -186,8 +176,8 @@

 def without_tags(*tags):
     '''Return a list of sources without any of the supplied tags.'''
-    return SourceFilter(lambda stags: \
-        len(TagImplies.resolve(tags) & stags) == 0)
+    return SourceFilter(lambda env, stags: \
+        len(resolve_tags(env, tags) & stags) == 0)

 def without_tag(tag):
     '''Return a list of sources without the supplied tag.'''
@@ -205,9 +195,9 @@
 Export(source_filter_factories)

 class SourceList(list):
-    def apply_filter(self, f):
+    def apply_filter(self, env, f):
         def match(source):
-            return f.predicate(source.tags)
+            return f.predicate(env, source.tags)
         return SourceList(filter(match, self))

     def __getattr__(self, name):
@@ -216,8 +206,8 @@
             raise AttributeError

         @functools.wraps(func)
-        def wrapper(*args, **kwargs):
-            return self.apply_filter(func(*args, **kwargs))
+        def wrapper(env, *args, **kwargs):
+            return self.apply_filter(env, func(*args, **kwargs))
         return wrapper

 class SourceMeta(type):
@@ -609,7 +599,7 @@
     def declare(self, env):
         sources = list(self.sources)
         for f in self.filters:
-            sources += Source.all.apply_filter(f)
+            sources += Source.all.apply_filter(env, f)
         objs = self.srcs_to_objs(env, sources) + env['STATIC_OBJS']
         if self.main:
             objs += env['MAIN_OBJS']
@@ -628,7 +618,7 @@
         env = env.Clone()
         env.Append(LIBS=env['GTEST_LIBS'])
         env.Append(CPPFLAGS=env['GTEST_CPPFLAGS'])
-        env['GTEST_LIB_SOURCES'] = Source.all.with_tag('gtest lib')
+        env['GTEST_LIB_SOURCES'] = Source.all.with_tag(env, 'gtest lib')
         env['GTEST_OUT_DIR'] = \
             Dir(env['BUILDDIR']).Dir('unittests.' + env['EXE_SUFFIX'])
         return super(GTest, cls).declare_all(env)
@@ -638,7 +628,7 @@
         if not self.skip_lib:
             sources += env['GTEST_LIB_SOURCES']
         for f in self.filters:
-            sources += Source.all.apply_filter(f)
+            sources += Source.all.apply_filter(env, f)
         objs = self.srcs_to_objs(env, sources)

         binary = super(GTest, self).declare(env, objs)
@@ -1372,12 +1362,12 @@
     new_env.Label = label
     new_env.Append(**kwargs)

-    lib_sources = Source.all.with_tag('gem5 lib')
+    lib_sources = Source.all.with_tag(new_env, '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_sources = lib_sources.without_tag('python')
+        lib_sources = lib_sources.without_tag(new_env, 'python')

     static_objs = list([ s.static(new_env) for s in lib_sources ])
     shared_objs = list([ s.shared(new_env) for s in lib_sources ])
@@ -1390,7 +1380,8 @@
     new_env.Depends(shared_date, shared_objs)
     shared_objs.extend(shared_date)

-    main_objs = [ s.static(new_env) for s in Source.all.with_tag('main') ]
+    main_objs = [ s.static(new_env) for s in
+            Source.all.with_tag(new_env, 'main') ]

     # First make a library of everything but main() so other programs can
     # link against m5.

--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/44388
To unsubscribe, or for help writing mail filters, visit https://gem5-review.googlesource.com/settings

Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: I93010d208272fcfa5f1a13219d58f237f82e3ed9
Gerrit-Change-Number: 44388
Gerrit-PatchSet: 1
Gerrit-Owner: Gabe Black <[email protected]>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s

Reply via email to