Gabe Black has submitted this change. (
https://gem5-review.googlesource.com/c/public/gem5/+/48376 )
10 is the latest approved patch-set.
No files were changed between the latest approved patch-set and the
submitted one.
Change subject: scons: Move the source related helper classes out of
src/SConscript.
......................................................................
scons: Move the source related helper classes out of src/SConscript.
By having them in gem5_scons.sources, they can be used by mechanisms
outside of src/SConscript, like separated out builders.
Change-Id: Ic3769723c8413e7db48aef536572ad3f2f948658
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/48376
Maintainer: Bobby R. Bruce <[email protected]>
Tested-by: kokoro <[email protected]>
Reviewed-by: Hoa Nguyen <[email protected]>
---
M SConstruct
A site_scons/gem5_scons/sources.py
M src/SConscript
3 files changed, 244 insertions(+), 196 deletions(-)
Approvals:
Hoa Nguyen: Looks good to me, approved
Bobby R. Bruce: Looks good to me, approved
kokoro: Regressions pass
diff --git a/SConstruct b/SConstruct
index 4e2ed47..3cc0cf1 100755
--- a/SConstruct
+++ b/SConstruct
@@ -130,6 +130,7 @@
from gem5_scons import TempFileSpawn, EnvDefaults, MakeAction,
MakeActionTool
import gem5_scons
from gem5_scons.builders import ConfigFile, AddLocalRPATH, SwitchingHeaders
+from gem5_scons.sources import TagImpliesTool
from gem5_scons.util import compareVersions, readCommand
# Disable warnings when targets can be built with multiple environments but
@@ -149,7 +150,7 @@
main = Environment(tools=[
'default', 'git', TempFileSpawn, EnvDefaults, MakeActionTool,
- ConfigFile, AddLocalRPATH, SwitchingHeaders
+ ConfigFile, AddLocalRPATH, SwitchingHeaders, TagImpliesTool
])
main.Tool(SCons.Tool.FindTool(['gcc', 'clang'], main))
diff --git a/site_scons/gem5_scons/sources.py
b/site_scons/gem5_scons/sources.py
new file mode 100644
index 0000000..6f44041
--- /dev/null
+++ b/site_scons/gem5_scons/sources.py
@@ -0,0 +1,239 @@
+# -*- mode:python -*-
+
+# Copyright (c) 2018, 2020 ARM Limited
+#
+# The license below extends only to copyright in the software and shall
+# not be construed as granting a license to any other intellectual
+# property including but not limited to intellectual property relating
+# to a hardware implementation of the functionality of the software
+# licensed hereunder. You may use the software subject to the license
+# terms below provided that you ensure that this notice is replicated
+# unmodified and in its entirety in all distributions of the software,
+# modified or unmodified, in source code or in binary form.
+#
+# Copyright (c) 2004-2005 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import functools
+
+import SCons.Script
+
+########################################################################
+# Code for adding source files of various types
+#
+# When specifying a source file of some type, a set of tags can be
+# specified for that file.
+
+def tag_implies(env, tag, tag_list):
+ '''
+ Associates a tag X to a list of tags which are implied by X.
+
+ For example, assume:
+ - Each file <X>.cc is tagged with the tag "Tag <X>".
+ - B.cc refers to symbols from A.cc
+ - C.cc refers to symbols from B.cc
+ - D.cc refers to symbols from A.cc and C.cc
+
+ Then:
+ - "Tag A" is implied by "Tag B"
+ - "Tag B" is implied by "Tag C"
+ - "Tag A" is transitively implied by "Tag C" (from "Tag B")
+ - "Tag A" and "Tag C" are implied by "Tag D"
+ - "Tag B" is transitively implied by "Tag D" (from "Tag C")
+ - "Tag A" is transitively implied by "Tag D" (from transitive "Tag B")
+
+ All of these implications are simply declared as:
+ env.TagImplies("Tag B", "Tag A")
+ env.TagImplies("Tag C", "Tag B")
+ env.TagImplies("Tag D", ["Tag A", "Tag C"])
+
+ So that any use of a tag will automatically include its transitive tags
+ after being resolved.
+ '''
+
+ env.SetDefault(_tag_implies={})
+ implications = env['_tag_implies']
+
+ if isinstance(tag_list, str):
+ tag_list = frozenset([tag_list])
+ if not isinstance(tag_list, frozenset):
+ tag_list = frozenset(tag_list)
+ if tag in implications:
+ implications[tag] |= tag_list
+ else:
+ implications[tag] = tag_list
+
+ # Check if any of the tags on which the new tag depends on already
+ # has a list of implications. If so, add the list to the new tag's
+ # implications
+ for t in tag_list:
+ if t in implications:
+ implications[tag] |= implications[t]
+
+ # Check if another tag depends on this tag. If so, add this tag's
+ # implications to that tag.
+ for t,implied in implications.items():
+ if tag in implied:
+ implications[t] |= implications[tag]
+
+def TagImpliesTool(env):
+ env.AddMethod(tag_implies, 'TagImplies')
+
+def resolve_tags(env, tags):
+ '''
+ Returns the complete set of tags implied (dependencies) by the
+ supplied tags.
+ '''
+
+ 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):
+ factories = {}
+ def __init__(self, predicate):
+ self.predicate = predicate
+
+ def __or__(self, other):
+ return SourceFilter(lambda env, tags: self.predicate(env, tags) or
+ other.predicate(env, tags))
+
+ def __and__(self, other):
+ return SourceFilter(lambda env, tags: self.predicate(env, tags) and
+ other.predicate(env, tags))
+
+def with_any_tags(*tags):
+ '''Return a list of sources with any of the supplied tags.'''
+ 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 env, stags: resolve_tags(env, tags) <=
stags)
+
+def with_tag(tag):
+ '''Return a list of sources with the supplied tag.'''
+ return with_any_tags(*[tag])
+
+def without_tags(*tags):
+ '''Return a list of sources without any of the supplied tags.'''
+ 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.'''
+ return without_tags(*[tag])
+
+SourceFilter.factories.update({
+ 'with_any_tags': with_any_tags,
+ 'with_all_tags': with_all_tags,
+ 'with_tag': with_tag,
+ 'without_tags': without_tags,
+ 'without_tag': without_tag,
+})
+
+class SourceList(list):
+ def apply_filter(self, env, f):
+ def match(source):
+ return f.predicate(env, source.tags)
+ return SourceList(filter(match, self))
+
+ def __getattr__(self, name):
+ func = SourceFilter.factories.get(name, None)
+ if not func:
+ raise AttributeError
+
+ @functools.wraps(func)
+ def wrapper(env, *args, **kwargs):
+ return self.apply_filter(env, func(*args, **kwargs))
+ return wrapper
+
+class SourceMeta(type):
+ '''Meta class for source files that keeps track of all files of a
+ particular type.'''
+ def __init__(cls, name, bases, dict):
+ super(SourceMeta, cls).__init__(name, bases, dict)
+ cls.all = SourceList()
+
+class SourceFile(object, metaclass=SourceMeta):
+ '''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 tags which
+ describing arbitrary properties of the source file.'''
+
+ def __init__(self, source, tags=None, add_tags=None, append=None):
+ if tags is None:
+ tags='gem5 lib'
+ if isinstance(tags, str):
+ tags = { tags }
+ if not isinstance(tags, set):
+ tags = set(tags)
+ self.tags = tags
+
+ if add_tags:
+ if isinstance(add_tags, str):
+ add_tags = { add_tags }
+ if not isinstance(add_tags, set):
+ add_tags = set(add_tags)
+ self.tags |= add_tags
+
+ self.append = append
+
+ tnode = SCons.Script.File(source)
+
+ self.tnode = tnode
+ self.filename = str(self.tnode)
+ self.snode = tnode.srcnode()
+
+ for base in type(self).__mro__:
+ if issubclass(base, SourceFile):
+ base.all.append(self)
+
+ def static(self, env):
+ if self.append:
+ env = env.Clone()
+ env.Append(**self.append)
+ return env.StaticObject(self.tnode)
+
+ def shared(self, env):
+ if self.append:
+ env = env.Clone()
+ env.Append(**self.append)
+ return env.SharedObject(self.tnode)
+
+__all__ = ['TagImpliesTool', 'SourceFilter', 'SourceList', 'SourceFile',
+ 'with_any_tags', 'with_all_tags', 'with_tag', 'without_tags',
+ 'without_tag']
diff --git a/src/SConscript b/src/SConscript
index 9dadd99..c819ad7 100644
--- a/src/SConscript
+++ b/src/SConscript
@@ -41,7 +41,6 @@
import bisect
import distutils.spawn
import functools
-import imp
import importlib
import importlib.abc
import importlib.machinery
@@ -55,6 +54,9 @@
import SCons
from gem5_scons import Transform, warning, error, ToValue, FromValue
+from gem5_scons.sources import *
+
+Export(SourceFilter.factories)
# This file defines how to build a particular configuration of gem5
# based on variable settings in the 'env' build environment.
@@ -68,200 +70,6 @@
from m5.util import code_formatter
-########################################################################
-# Code for adding source files of various types
-#
-# When specifying a source file of some type, a set of tags can be
-# specified for that file.
-
-def tag_implies(env, tag, tag_list):
- '''
- Associates a tag X to a list of tags which are implied by X.
-
- For example, assume:
- - Each file <X>.cc is tagged with the tag "Tag <X>".
- - B.cc refers to symbols from A.cc
- - C.cc refers to symbols from B.cc
- - D.cc refers to symbols from A.cc and C.cc
-
- Then:
- - "Tag A" is implied by "Tag B"
- - "Tag B" is implied by "Tag C"
- - "Tag A" is transitively implied by "Tag C" (from "Tag B")
- - "Tag A" and "Tag C" are implied by "Tag D"
- - "Tag B" is transitively implied by "Tag D" (from "Tag C")
- - "Tag A" is transitively implied by "Tag D" (from transitive "Tag B")
-
- All of these implications are simply declared as:
- env.TagImplies("Tag B", "Tag A")
- env.TagImplies("Tag C", "Tag B")
- env.TagImplies("Tag D", ["Tag A", "Tag C"])
-
- So that any use of a tag will automatically include its transitive tags
- after being resolved.
- '''
-
- env.SetDefault(_tag_implies={})
- implications = env['_tag_implies']
-
- if isinstance(tag_list, str):
- tag_list = frozenset([tag_list])
- if not isinstance(tag_list, frozenset):
- tag_list = frozenset(tag_list)
- if tag in implications:
- implications[tag] |= tag_list
- else:
- implications[tag] = tag_list
-
- # Check if any of the tags on which the new tag depends on already
- # has a list of implications. If so, add the list to the new tag's
- # implications
- for t in tag_list:
- if t in implications:
- implications[tag] |= implications[t]
-
- # Check if another tag depends on this tag. If so, add this tag's
- # implications to that tag.
- for t,implied in implications.items():
- if tag in implied:
- implications[t] |= implications[tag]
-
-env.AddMethod(tag_implies, 'TagImplies')
-
-def resolve_tags(env, tags):
- '''
- Returns the complete set of tags implied (dependencies) by the
- supplied tags.
- '''
-
- 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):
- factories = {}
- def __init__(self, predicate):
- self.predicate = predicate
-
- def __or__(self, other):
- return SourceFilter(lambda env, tags: self.predicate(env, tags) or
- other.predicate(env, tags))
-
- def __and__(self, other):
- return SourceFilter(lambda env, tags: self.predicate(env, tags) and
- other.predicate(env, tags))
-
-def with_any_tags(*tags):
- '''Return a list of sources with any of the supplied tags.'''
- 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 env, stags: resolve_tags(env, tags) <=
stags)
-
-def with_tag(tag):
- '''Return a list of sources with the supplied tag.'''
- return with_any_tags(*[tag])
-
-def without_tags(*tags):
- '''Return a list of sources without any of the supplied tags.'''
- 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.'''
- return without_tags(*[tag])
-
-SourceFilter.factories.update({
- 'with_any_tags': with_any_tags,
- 'with_all_tags': with_all_tags,
- 'with_tag': with_tag,
- 'without_tags': without_tags,
- 'without_tag': without_tag,
-})
-
-Export(SourceFilter.factories)
-
-class SourceList(list):
- def apply_filter(self, env, f):
- def match(source):
- return f.predicate(env, source.tags)
- return SourceList(filter(match, self))
-
- def __getattr__(self, name):
- func = SourceFilter.factories.get(name, None)
- if not func:
- raise AttributeError
-
- @functools.wraps(func)
- def wrapper(env, *args, **kwargs):
- return self.apply_filter(env, func(*args, **kwargs))
- return wrapper
-
-class SourceMeta(type):
- '''Meta class for source files that keeps track of all files of a
- particular type.'''
- def __init__(cls, name, bases, dict):
- super(SourceMeta, cls).__init__(name, bases, dict)
- cls.all = SourceList()
-
-class SourceFile(object, metaclass=SourceMeta):
- '''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 tags which
- describing arbitrary properties of the source file.'''
-
- def __init__(self, source, tags=None, add_tags=None, append=None):
- if tags is None:
- tags='gem5 lib'
- if isinstance(tags, str):
- tags = { tags }
- if not isinstance(tags, set):
- tags = set(tags)
- self.tags = tags
-
- if add_tags:
- if isinstance(add_tags, str):
- add_tags = { add_tags }
- if not isinstance(add_tags, set):
- add_tags = set(add_tags)
- self.tags |= add_tags
-
- self.append = append
-
- tnode = File(source)
-
- self.tnode = tnode
- self.filename = str(self.tnode)
- self.snode = tnode.srcnode()
-
- for base in type(self).__mro__:
- if issubclass(base, SourceFile):
- base.all.append(self)
-
- def static(self, env):
- if self.append:
- env = env.Clone()
- env.Append(**self.append)
- return env.StaticObject(self.tnode)
-
- def shared(self, env):
- if self.append:
- env = env.Clone()
- env.Append(**self.append)
- return env.SharedObject(self.tnode)
-
def bytesToCppArray(code, symbol, data):
'''
Output an array of bytes to a code formatter as a c++ array
declaration.
--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/48376
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: Ic3769723c8413e7db48aef536572ad3f2f948658
Gerrit-Change-Number: 48376
Gerrit-PatchSet: 12
Gerrit-Owner: Gabe Black <[email protected]>
Gerrit-Reviewer: Bobby R. Bruce <[email protected]>
Gerrit-Reviewer: Gabe Black <[email protected]>
Gerrit-Reviewer: Hoa Nguyen <[email protected]>
Gerrit-Reviewer: kokoro <[email protected]>
Gerrit-MessageType: merged
_______________________________________________
gem5-dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s