misc: Run pre-commit run on all files in repo

The following command was run:

```
pre-commit run --all-files
```

This ensures all the files in the repository are formatted to pass our
checks.

Change-Id: Ia2fe3529a50ad925d1076a612d60a4280adc40de
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/62572
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Maintainer: Jason Lowe-Power <power.jg@gmail.com>
Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
This commit is contained in:
Bobby R. Bruce
2022-08-22 12:34:19 -07:00
committed by Bobby Bruce
parent 64add0e04d
commit 2bc5a8b71a
181 changed files with 1445 additions and 1229 deletions

View File

@@ -52,34 +52,38 @@ import SCons.Script
termcap = get_termcap()
def strip_build_path(path, env):
path = str(path)
build_base = 'build/'
variant_base = env['BUILDROOT'] + os.path.sep
build_base = "build/"
variant_base = env["BUILDROOT"] + os.path.sep
if path.startswith(variant_base):
path = path[len(variant_base):]
path = path[len(variant_base) :]
elif path.startswith(build_base):
path = path[len(build_base):]
path = path[len(build_base) :]
return path
def TempFileSpawn(scons_env):
old_pspawn = scons_env['PSPAWN']
old_spawn = scons_env['SPAWN']
old_pspawn = scons_env["PSPAWN"]
old_spawn = scons_env["SPAWN"]
def wrapper(old, sh, esc, cmd, sh_args, *py_args):
with tempfile.NamedTemporaryFile() as temp:
temp.write(' '.join(sh_args).encode())
temp.write(" ".join(sh_args).encode())
temp.flush()
sh_args = [sh, esc(temp.name)]
return old(sh, esc, sh, sh_args, *py_args)
def new_pspawn(sh, esc, cmd, args, sh_env, stdout, stderr):
return wrapper(old_pspawn, sh, esc, cmd, args, sh_env, stdout, stderr)
def new_spawn(sh, esc, cmd, args, sh_env):
return wrapper(old_spawn, sh, esc, cmd, args, sh_env)
scons_env['PSPAWN'] = new_pspawn
scons_env['SPAWN'] = new_spawn
scons_env["PSPAWN"] = new_pspawn
scons_env["SPAWN"] = new_spawn
# Generate a string of the form:
# common/path/prefix/src1, src2 -> tgt1, tgt2
@@ -93,23 +97,32 @@ class Transform(object):
tgts_color = termcap.Yellow + termcap.Bold
def __init__(self, tool, max_sources=99):
self.format = self.tool_color + (" [%8s] " % tool) \
+ self.pfx_color + "%s" \
+ self.srcs_color + "%s" \
+ self.arrow_color + " -> " \
+ self.tgts_color + "%s" \
+ termcap.Normal
self.format = (
self.tool_color
+ (" [%8s] " % tool)
+ self.pfx_color
+ "%s"
+ self.srcs_color
+ "%s"
+ self.arrow_color
+ " -> "
+ self.tgts_color
+ "%s"
+ termcap.Normal
)
self.max_sources = max_sources
def __call__(self, target, source, env, for_signature=None):
# truncate source list according to max_sources param
source = source[0:self.max_sources]
source = source[0 : self.max_sources]
def strip(f):
return strip_build_path(str(f), env)
if len(source) > 0:
srcs = list(map(strip, source))
else:
srcs = ['']
srcs = [""]
tgts = list(map(strip, target))
# surprisingly, os.path.commonprefix is a dumb char-by-char string
# operation that has nothing to do with paths.
@@ -137,20 +150,23 @@ class Transform(object):
if sep_idx != -1:
com_pfx = com_pfx[0:sep_idx]
else:
com_pfx = ''
com_pfx = ""
elif src0_len > com_pfx_len and srcs[0][com_pfx_len] == ".":
# still splitting at file extension: ok
pass
else:
# probably a fluke; ignore it
com_pfx = ''
com_pfx = ""
# recalculate length in case com_pfx was modified
com_pfx_len = len(com_pfx)
def fmt(files):
f = list(map(lambda s: s[com_pfx_len:], files))
return ', '.join(f)
return ", ".join(f)
return self.format % (com_pfx, fmt(srcs), fmt(tgts))
# The width warning and error messages should be wrapped at.
text_width = None
@@ -162,6 +178,7 @@ if not sys.stdout.isatty():
if text_width is None:
try:
import shutil
text_width = shutil.get_terminal_size().columns
except:
pass
@@ -170,6 +187,7 @@ if text_width is None:
if text_width is None:
try:
import curses
try:
_, text_width = curses.initscr().getmaxyx()
finally:
@@ -181,21 +199,22 @@ if text_width is None:
if text_width is None:
text_width = 80
def print_message(prefix, color, message, **kwargs):
prefix_len = len(prefix)
if text_width > prefix_len:
wrap_width = text_width - prefix_len
padding = ' ' * prefix_len
padding = " " * prefix_len
# First split on newlines.
lines = message.split('\n')
lines = message.split("\n")
# Then wrap each line to the required width.
wrapped_lines = []
for line in lines:
wrapped_lines.extend(textwrap.wrap(line, wrap_width))
# Finally add the prefix and padding on extra lines, and glue it all
# back together.
message = prefix + ('\n' + padding).join(wrapped_lines)
message = prefix + ("\n" + padding).join(wrapped_lines)
else:
# We have very small terminal, indent formatting doesn't help.
message = prefix + message
@@ -205,27 +224,36 @@ def print_message(prefix, color, message, **kwargs):
print(message, **kwargs)
return message
all_warnings = []
def summarize_warnings():
if not all_warnings:
return
print(termcap.Yellow + termcap.Bold +
'*** Summary of Warnings ***' +
termcap.Normal)
print(
termcap.Yellow
+ termcap.Bold
+ "*** Summary of Warnings ***"
+ termcap.Normal
)
list(map(print, all_warnings))
def warning(*args, **kwargs):
message = ' '.join(args)
printed = print_message('Warning: ', termcap.Yellow, message, **kwargs)
message = " ".join(args)
printed = print_message("Warning: ", termcap.Yellow, message, **kwargs)
all_warnings.append(printed)
def error(*args, **kwargs):
message = ' '.join(args)
print_message('Error: ', termcap.Red, message, **kwargs)
message = " ".join(args)
print_message("Error: ", termcap.Red, message, **kwargs)
SCons.Script.Exit(1)
def parse_build_path(target):
path_dirs = target.split('/')
path_dirs = target.split("/")
# Pop off the target file.
path_dirs.pop()
@@ -233,40 +261,55 @@ def parse_build_path(target):
# Search backwards for the "build" directory. Whatever was just before it
# was the name of the variant.
variant_dir = path_dirs.pop()
while path_dirs and path_dirs[-1] != 'build':
while path_dirs and path_dirs[-1] != "build":
variant_dir = path_dirs.pop()
if not path_dirs:
error("No non-leaf 'build' dir found on target path.", t)
return os.path.join('/', *path_dirs), variant_dir
return os.path.join("/", *path_dirs), variant_dir
# The MakeAction wrapper, and a SCons tool to set up the *COMSTR variables.
if SCons.Script.GetOption('verbose'):
if SCons.Script.GetOption("verbose"):
def MakeAction(action, string, *args, **kwargs):
return SCons.Script.Action(action, *args, **kwargs)
def MakeActionTool(env):
pass
else:
MakeAction = SCons.Script.Action
def MakeActionTool(env):
env['CCCOMSTR'] = Transform("CC")
env['CXXCOMSTR'] = Transform("CXX")
env['ASCOMSTR'] = Transform("AS")
env['ARCOMSTR'] = Transform("AR", 0)
env['LINKCOMSTR'] = Transform("LINK", 0)
env['SHLINKCOMSTR'] = Transform("SHLINK", 0)
env['RANLIBCOMSTR'] = Transform("RANLIB", 0)
env['M4COMSTR'] = Transform("M4")
env['SHCCCOMSTR'] = Transform("SHCC")
env['SHCXXCOMSTR'] = Transform("SHCXX")
env["CCCOMSTR"] = Transform("CC")
env["CXXCOMSTR"] = Transform("CXX")
env["ASCOMSTR"] = Transform("AS")
env["ARCOMSTR"] = Transform("AR", 0)
env["LINKCOMSTR"] = Transform("LINK", 0)
env["SHLINKCOMSTR"] = Transform("SHLINK", 0)
env["RANLIBCOMSTR"] = Transform("RANLIB", 0)
env["M4COMSTR"] = Transform("M4")
env["SHCCCOMSTR"] = Transform("SHCC")
env["SHCXXCOMSTR"] = Transform("SHCXX")
def ToValue(obj):
return SCons.Node.Python.Value(pickle.dumps(obj))
def FromValue(node):
return pickle.loads(node.read())
__all__ = ['Configure', 'EnvDefaults', 'Transform', 'warning', 'error',
'MakeAction', 'MakeActionTool', 'ToValue', 'FromValue']
__all__ = [
"Configure",
"EnvDefaults",
"Transform",
"warning",
"error",
"MakeAction",
"MakeActionTool",
"ToValue",
"FromValue",
]

View File

@@ -43,26 +43,23 @@ import sys
import SCons.Node.FS
def AddLocalRPATH(env):
def add_local_rpath(env, *targets):
'''Set up an RPATH for a library which lives in the build directory.
"""Set up an RPATH for a library which lives in the build directory.
The construction environment variable BIN_RPATH_PREFIX should be set
to the relative path of the build directory starting from the location
of the binary.'''
of the binary."""
for target in targets:
target = env.Entry(target)
if not isinstance(target, SCons.Node.FS.Dir):
target = target.dir
relpath = os.path.relpath(target.abspath, env['BUILDDIR'])
components = [
'\\$$ORIGIN',
'${BIN_RPATH_PREFIX}',
relpath
]
relpath = os.path.relpath(target.abspath, env["BUILDDIR"])
components = ["\\$$ORIGIN", "${BIN_RPATH_PREFIX}", relpath]
env.Append(RPATH=[env.Literal(os.path.join(*components))])
if sys.platform != "darwin":
env.Append(LINKFLAGS=env.Split('-z origin'))
env.Append(LINKFLAGS=env.Split("-z origin"))
env.AddMethod(add_local_rpath, 'AddLocalRPATH')
env.AddMethod(add_local_rpath, "AddLocalRPATH")

View File

@@ -46,19 +46,21 @@ from code_formatter import code_formatter
import SCons.Node.Python
def build_blob(target, source, env):
'''
"""
Embed an arbitrary blob into the gem5 executable,
and make it accessible to C++ as a byte array.
'''
"""
with open(str(source[0]), 'rb') as f:
with open(str(source[0]), "rb") as f:
data = f.read()
symbol = str(source[1])
cc, hh = target
hh_code = code_formatter()
hh_code('''\
hh_code(
"""\
#include <cstddef>
#include <cstdint>
@@ -72,13 +74,15 @@ extern const std::uint8_t ${symbol}[];
} // namespace Blobs
} // namespace gem5
''')
"""
)
hh_code.write(str(hh))
include_path = os.path.relpath(hh.abspath, env['BUILDDIR'])
include_path = os.path.relpath(hh.abspath, env["BUILDDIR"])
cc_code = code_formatter()
cc_code('''\
cc_code(
"""\
#include "${include_path}"
namespace gem5
@@ -87,22 +91,28 @@ namespace Blobs
{
const std::size_t ${symbol}_len = ${{len(data)}};
''')
"""
)
bytesToCppArray(cc_code, symbol, data)
cc_code('''
cc_code(
"""
} // namespace Blobs
} // namespace gem5
''')
"""
)
cc_code.write(str(cc))
blob_action = MakeAction(build_blob, Transform("EMBED BLOB"))
def blob_emitter(target, source, env):
symbol = str(target[0])
cc_file = env.File(symbol + '.cc')
hh_file = env.File(symbol + '.hh')
cc_file = env.File(symbol + ".cc")
hh_file = env.File(symbol + ".hh")
return [cc_file, hh_file], [source, SCons.Node.Python.Value(symbol)]
def Blob(env):
blob_builder = env.Builder(action=blob_action, emitter=blob_emitter)
env.Append(BUILDERS={'Blob': blob_builder})
env.Append(BUILDERS={"Blob": blob_builder})

View File

@@ -46,15 +46,16 @@ from gem5_scons import Transform, MakeAction
#
###################################################
def ConfigFile(env):
# This function generates a config header file that #defines the
# variable symbol to the current variable setting (0 or 1). The source
# operands are the name of the variable and a Value node containing the
# value of the variable.
def build_config_file(target, source, env):
(variable, value) = [s.get_contents().decode('utf-8') for s in source]
with open(str(target[0].abspath), 'w') as f:
print('#define', variable, value, file=f)
(variable, value) = [s.get_contents().decode("utf-8") for s in source]
with open(str(target[0].abspath), "w") as f:
print("#define", variable, value, file=f)
return None
# Combine the two functions into a scons Action object.
@@ -66,8 +67,8 @@ def ConfigFile(env):
# extract variable name from Builder arg
variable = str(target[0])
# True target is config header file
target = env.Dir('config').File(variable.lower() + '.hh')
val = env['CONF'][variable]
target = env.Dir("config").File(variable.lower() + ".hh")
val = env["CONF"][variable]
if isinstance(val, bool):
# Force value to 0/1
val = str(int(val))
@@ -79,4 +80,4 @@ def ConfigFile(env):
config_builder = env.Builder(emitter=config_emitter, action=config_action)
env.Append(BUILDERS = { 'ConfigFile' : config_builder })
env.Append(BUILDERS={"ConfigFile": config_builder})

View File

@@ -51,27 +51,32 @@ from gem5_scons import Transform, MakeAction
#
###################################################
def SwitchingHeaders(env):
def build_switching_header(target, source, env):
path = str(target[0])
subdir = str(source[0])
dp, fp = os.path.split(path)
dp = os.path.relpath(os.path.realpath(dp),
os.path.realpath(env['BUILDDIR']))
with open(path, 'w') as hdr:
dp = os.path.relpath(
os.path.realpath(dp), os.path.realpath(env["BUILDDIR"])
)
with open(path, "w") as hdr:
print('#include "%s/%s/%s"' % (dp, subdir, fp), file=hdr)
switching_header_action = MakeAction(build_switching_header,
Transform('GENERATE'))
switching_header_action = MakeAction(
build_switching_header, Transform("GENERATE")
)
switching_header_builder = env.Builder(action=switching_header_action,
source_factory=env.Value,
single_source=True)
switching_header_builder = env.Builder(
action=switching_header_action,
source_factory=env.Value,
single_source=True,
)
env.Append(BUILDERS = { 'SwitchingHeader': switching_header_builder })
env.Append(BUILDERS={"SwitchingHeader": switching_header_builder})
def switching_headers(self, headers, source):
for header in headers:
self.SwitchingHeader(header, source)
env.AddMethod(switching_headers, 'SwitchingHeaders')
env.AddMethod(switching_headers, "SwitchingHeaders")

View File

@@ -44,39 +44,41 @@ import os
import SCons.Script
import SCons.Util
def CheckCxxFlag(context, flag, autoadd=True):
context.Message("Checking for compiler %s support... " % flag)
last_cxxflags = context.env['CXXFLAGS']
last_cxxflags = context.env["CXXFLAGS"]
context.env.Append(CXXFLAGS=[flag])
pre_werror = context.env['CXXFLAGS']
context.env.Append(CXXFLAGS=['-Werror'])
ret = context.TryCompile('// CheckCxxFlag DO NOTHING', '.cc')
context.env['CXXFLAGS'] = pre_werror
pre_werror = context.env["CXXFLAGS"]
context.env.Append(CXXFLAGS=["-Werror"])
ret = context.TryCompile("// CheckCxxFlag DO NOTHING", ".cc")
context.env["CXXFLAGS"] = pre_werror
if not (ret and autoadd):
context.env['CXXFLAGS'] = last_cxxflags
context.env["CXXFLAGS"] = last_cxxflags
context.Result(ret)
return ret
def CheckLinkFlag(context, flag, autoadd=True, set_for_shared=True):
context.Message("Checking for linker %s support... " % flag)
last_linkflags = context.env['LINKFLAGS']
last_linkflags = context.env["LINKFLAGS"]
context.env.Append(LINKFLAGS=[flag])
pre_werror = context.env['LINKFLAGS']
context.env.Append(LINKFLAGS=['-Werror'])
ret = context.TryLink('int main(int, char *[]) { return 0; }', '.cc')
context.env['LINKFLAGS'] = pre_werror
pre_werror = context.env["LINKFLAGS"]
context.env.Append(LINKFLAGS=["-Werror"])
ret = context.TryLink("int main(int, char *[]) { return 0; }", ".cc")
context.env["LINKFLAGS"] = pre_werror
if not (ret and autoadd):
context.env['LINKFLAGS'] = last_linkflags
if (ret and set_for_shared):
assert(autoadd)
context.env["LINKFLAGS"] = last_linkflags
if ret and set_for_shared:
assert autoadd
context.env.Append(SHLINKFLAGS=[flag])
context.Result(ret)
return ret
# Add a custom Check function to test for structure members.
def CheckMember(context, include, decl, member, include_quotes="<>"):
context.Message("Checking for member %s in %s..." %
(member, decl))
context.Message("Checking for member %s in %s..." % (member, decl))
text = """
#include %(header)s
int main(){
@@ -84,18 +86,21 @@ int main(){
(void)test.%(member)s;
return 0;
};
""" % { "header" : include_quotes[0] + include + include_quotes[1],
"decl" : decl,
"member" : member,
}
""" % {
"header": include_quotes[0] + include + include_quotes[1],
"decl": decl,
"member": member,
}
ret = context.TryCompile(text, extension=".cc")
context.Result(ret)
return ret
def CheckPythonLib(context):
context.Message('Checking Python version... ')
ret = context.TryRun(r"""
context.Message("Checking Python version... ")
ret = context.TryRun(
r"""
#include <pybind11/embed.h>
int
@@ -107,21 +112,24 @@ main(int argc, char **argv) {
"sys.stdout.write('%i.%i.%i' % (vi.major, vi.minor, vi.micro));\n");
return 0;
}
""", extension=".cc")
""",
extension=".cc",
)
context.Result(ret[1] if ret[0] == 1 else 0)
if ret[0] == 0:
return None
else:
return tuple(map(int, ret[1].split(".")))
def CheckPkgConfig(context, pkgs, *args):
if not SCons.Util.is_List(pkgs):
pkgs = [pkgs]
assert(pkgs)
assert pkgs
for pkg in pkgs:
context.Message('Checking for pkg-config package %s... ' % pkg)
ret = context.TryAction('pkg-config %s' % pkg)[0]
context.Message("Checking for pkg-config package %s... " % pkg)
ret = context.TryAction("pkg-config %s" % pkg)[0]
if not ret:
context.Result(ret)
continue
@@ -129,7 +137,7 @@ def CheckPkgConfig(context, pkgs, *args):
if len(args) == 0:
break
cmd = ' '.join(['pkg-config'] + list(args) + [pkg])
cmd = " ".join(["pkg-config"] + list(args) + [pkg])
try:
context.env.ParseConfig(cmd)
ret = 1
@@ -141,20 +149,25 @@ def CheckPkgConfig(context, pkgs, *args):
return ret
@contextlib.contextmanager
def Configure(env, *args, **kwargs):
kwargs.setdefault('conf_dir',
os.path.join(env['GEM5BUILD'], 'scons_config'))
kwargs.setdefault('log_file',
os.path.join(env['GEM5BUILD'], 'scons_config.log'))
kwargs.setdefault('custom_tests', {})
kwargs['custom_tests'].update({
'CheckCxxFlag' : CheckCxxFlag,
'CheckLinkFlag' : CheckLinkFlag,
'CheckMember' : CheckMember,
'CheckPkgConfig' : CheckPkgConfig,
'CheckPythonLib' : CheckPythonLib,
})
kwargs.setdefault(
"conf_dir", os.path.join(env["GEM5BUILD"], "scons_config")
)
kwargs.setdefault(
"log_file", os.path.join(env["GEM5BUILD"], "scons_config.log")
)
kwargs.setdefault("custom_tests", {})
kwargs["custom_tests"].update(
{
"CheckCxxFlag": CheckCxxFlag,
"CheckLinkFlag": CheckLinkFlag,
"CheckMember": CheckMember,
"CheckPkgConfig": CheckPkgConfig,
"CheckPythonLib": CheckPythonLib,
}
)
conf = SCons.Script.Configure(env, *args, **kwargs)
# Recent versions of scons substitute a "Null" object for Configure()
@@ -163,14 +176,17 @@ def Configure(env, *args, **kwargs):
# breaking all our configuration checks. We replace it with our own
# more optimistic null object that returns True instead.
if not conf:
def NullCheck(*args, **kwargs):
return True
class NullConf:
def __init__(self, env):
self.env = env
def Finish(self):
return self.env
def __getattr__(self, mname):
return NullCheck

View File

@@ -42,56 +42,76 @@ import os
from gem5_python_paths import extra_python_paths
def EnvDefaults(env):
# export TERM so that clang reports errors in color
use_vars = set([ 'AS', 'AR', 'CC', 'CXX', 'HOME', 'LD_LIBRARY_PATH',
'LIBRARY_PATH', 'PATH', 'PKG_CONFIG_PATH', 'PROTOC',
'PYTHONPATH', 'RANLIB', 'TERM', 'PYTHON_CONFIG',
'CCFLAGS_EXTRA', 'GEM5PY_CCFLAGS_EXTRA',
'GEM5PY_LINKFLAGS_EXTRA', 'LINKFLAGS_EXTRA', 'LANG'])
use_vars = set(
[
"AS",
"AR",
"CC",
"CXX",
"HOME",
"LD_LIBRARY_PATH",
"LIBRARY_PATH",
"PATH",
"PKG_CONFIG_PATH",
"PROTOC",
"PYTHONPATH",
"RANLIB",
"TERM",
"PYTHON_CONFIG",
"CCFLAGS_EXTRA",
"GEM5PY_CCFLAGS_EXTRA",
"GEM5PY_LINKFLAGS_EXTRA",
"LINKFLAGS_EXTRA",
"LANG",
]
)
use_prefixes = [
"ASAN_", # address sanitizer symbolizer path and settings
"CCACHE_", # ccache (caching compiler wrapper) configuration
"CCC_", # clang static analyzer configuration
"DISTCC_", # distcc (distributed compiler wrapper) config
"INCLUDE_SERVER_", # distcc pump server settings
"M5", # M5 configuration (e.g., path to kernels)
"NIX_", # wrapped binaries if using nix package manager
]
"ASAN_", # address sanitizer symbolizer path and settings
"CCACHE_", # ccache (caching compiler wrapper) configuration
"CCC_", # clang static analyzer configuration
"DISTCC_", # distcc (distributed compiler wrapper) config
"INCLUDE_SERVER_", # distcc pump server settings
"M5", # M5 configuration (e.g., path to kernels)
"NIX_", # wrapped binaries if using nix package manager
]
for key,val in sorted(os.environ.items()):
if key in use_vars or \
any([key.startswith(prefix) for prefix in use_prefixes]):
env['ENV'][key] = val
for key, val in sorted(os.environ.items()):
if key in use_vars or any(
[key.startswith(prefix) for prefix in use_prefixes]
):
env["ENV"][key] = val
# These variables from the environment override/become SCons variables,
# with a default if they weren't in the host environment.
var_overrides = {
'CC': env['CC'],
'CXX': env['CXX'],
'PROTOC': 'protoc',
'PYTHON_CONFIG': [ 'python3-config', 'python-config' ],
'CCFLAGS_EXTRA': '',
'GEM5PY_CCFLAGS_EXTRA': '',
'GEM5PY_LINKFLAGS_EXTRA': '',
'LINKFLAGS_EXTRA': '',
"CC": env["CC"],
"CXX": env["CXX"],
"PROTOC": "protoc",
"PYTHON_CONFIG": ["python3-config", "python-config"],
"CCFLAGS_EXTRA": "",
"GEM5PY_CCFLAGS_EXTRA": "",
"GEM5PY_LINKFLAGS_EXTRA": "",
"LINKFLAGS_EXTRA": "",
}
for key,default in var_overrides.items():
env[key] = env['ENV'].get(key, default)
for key, default in var_overrides.items():
env[key] = env["ENV"].get(key, default)
# Tell scons to avoid implicit command dependencies to avoid issues
# with the param wrappes being compiled twice (see
# https://github.com/SCons/scons/issues/2811
env['IMPLICIT_COMMAND_DEPENDENCIES'] = 0
env.Decider('MD5-timestamp')
env["IMPLICIT_COMMAND_DEPENDENCIES"] = 0
env.Decider("MD5-timestamp")
# add useful python code PYTHONPATH so it can be used by subprocesses
# as well
env.AppendENVPath('PYTHONPATH', extra_python_paths)
env.AppendENVPath("PYTHONPATH", extra_python_paths)
# Default duplicate option is to use hard links, but this messes up
# when you use emacs to edit a file in the target dir, as emacs moves
# file to file~ then copies to file, breaking the link. Symbolic
# (soft) links work better.
env.SetOption('duplicate', 'soft-copy')
env.SetOption("duplicate", "soft-copy")

View File

@@ -47,8 +47,9 @@ import SCons.Script
# 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:
@@ -72,10 +73,10 @@ def tag_implies(env, tag, tag_list):
So that any use of a tag will automatically include its transitive tags
after being resolved.
'''
"""
env.SetDefault(_tag_implies={})
implications = env['_tag_implies']
implications = env["_tag_implies"]
if isinstance(tag_list, str):
tag_list = frozenset([tag_list])
@@ -95,21 +96,23 @@ def tag_implies(env, tag, tag_list):
# Check if another tag depends on this tag. If so, add this tag's
# implications to that tag.
for t,implied in implications.items():
for t, implied in implications.items():
if tag in implied:
implications[t] |= implications[tag]
def TagImpliesTool(env):
env.AddMethod(tag_implies, 'TagImplies')
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']
implications = env["_tag_implies"]
if isinstance(tags, str):
tags = frozenset([tags])
@@ -122,53 +125,71 @@ def resolve_tags(env, tags):
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))
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))
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)
"""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 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 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)
"""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 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,
})
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, resolve_tags(env, source.tags))
return SourceList(filter(match, self))
def __getattr__(self, name):
@@ -179,33 +200,38 @@ class SourceList(list):
@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.'''
"""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 SourceItem(object, metaclass=SourceMeta):
'''Base object that encapsulates the notion of a source component for
"""Base object that encapsulates the notion of a source component for
gem5. This specifies a set of tags which help group components into groups
based on arbitrary properties.'''
based on arbitrary properties."""
def __init__(self, source, tags=None, add_tags=None, append=None):
self.source = source
if tags is None:
tags='gem5 lib'
tags = "gem5 lib"
if isinstance(tags, str):
tags = { tags }
tags = {tags}
if not isinstance(tags, set):
tags = set(tags)
self.tags = tags.copy()
if add_tags:
if isinstance(add_tags, str):
add_tags = { add_tags }
add_tags = {add_tags}
if not isinstance(add_tags, set):
add_tags = set(add_tags)
self.tags |= add_tags
@@ -216,10 +242,11 @@ class SourceItem(object, metaclass=SourceMeta):
if issubclass(base, SourceItem):
base.all.append(self)
class SourceFile(SourceItem):
'''Base object that encapsulates the notion of a source file.
"""Base object that encapsulates the notion of a source file.
This includes, the source node, target node, various manipulations
of those.'''
of those."""
def __init__(self, source, tags=None, add_tags=None, append=None):
super().__init__(source, tags=tags, add_tags=add_tags, append=append)
@@ -243,6 +270,15 @@ class SourceFile(SourceItem):
return env.SharedObject(self.tnode)
__all__ = ['TagImpliesTool', 'SourceFilter', 'SourceList', 'SourceFile',
'SourceItem', 'with_any_tags', 'with_all_tags', 'with_tag',
'without_tags', 'without_tag']
__all__ = [
"TagImpliesTool",
"SourceFilter",
"SourceList",
"SourceFile",
"SourceItem",
"with_any_tags",
"with_all_tags",
"with_tag",
"without_tags",
"without_tag",
]

View File

@@ -46,12 +46,15 @@ import SCons.Script
import m5.util.terminal
def ignore_style():
"""Determine whether we should ignore style checks"""
return SCons.Script.GetOption('ignore_style') or not sys.stdin.isatty()
return SCons.Script.GetOption("ignore_style") or not sys.stdin.isatty()
def get_termcap():
return m5.util.terminal.get_termcap(SCons.Script.GetOption('use_colors'))
return m5.util.terminal.get_termcap(SCons.Script.GetOption("use_colors"))
def readCommand(cmd, **kwargs):
"""
@@ -68,13 +71,13 @@ def readCommand(cmd, **kwargs):
if isinstance(cmd, str):
cmd = cmd.split()
no_exception = 'exception' in kwargs
exception = kwargs.pop('exception', None)
no_exception = "exception" in kwargs
exception = kwargs.pop("exception", None)
kwargs.setdefault('shell', False)
kwargs.setdefault('stdout', PIPE)
kwargs.setdefault('stderr', STDOUT)
kwargs.setdefault('close_fds', True)
kwargs.setdefault("shell", False)
kwargs.setdefault("stdout", PIPE)
kwargs.setdefault("stderr", STDOUT)
kwargs.setdefault("close_fds", True)
try:
subp = Popen(cmd, **kwargs)
except Exception as e:
@@ -82,20 +85,23 @@ def readCommand(cmd, **kwargs):
return -1, exception
raise
output = subp.communicate()[0].decode('utf-8')
output = subp.communicate()[0].decode("utf-8")
return output
def compareVersions(v1, v2):
"""helper function: compare arrays or strings of version numbers.
E.g., compare_version((1,3,25), (1,4,1)')
returns -1, 0, 1 if v1 is <, ==, > v2
"""
def make_version_list(v):
if isinstance(v, (list,tuple)):
if isinstance(v, (list, tuple)):
return v
elif isinstance(v, str):
return list(map(lambda x: int(re.match('\d+', x).group()),
v.split('.')))
return list(
map(lambda x: int(re.match("\d+", x).group()), v.split("."))
)
else:
raise TypeError()
@@ -104,8 +110,10 @@ def compareVersions(v1, v2):
# Compare corresponding elements of lists
# The shorter list is filled with 0 till the lists have the same length
for n1,n2 in itertools.zip_longest(v1, v2, fillvalue=0):
if n1 < n2: return -1
if n1 > n2: return 1
for n1, n2 in itertools.zip_longest(v1, v2, fillvalue=0):
if n1 < n2:
return -1
if n1 > n2:
return 1
return 0