From 49cf9fded08741099d25848807442a89c4d21399 Mon Sep 17 00:00:00 2001 From: Gabe Black Date: Wed, 8 Nov 2017 19:59:04 -0800 Subject: [PATCH] scons: Move Transform and termcap functionality into their own files. Change-Id: Ica08e93f3873a7eafd02fe7d44c3bdbf0ce7f6b7 Reviewed-on: https://gem5-review.googlesource.com/5565 Reviewed-by: Gabe Black Maintainer: Gabe Black --- SConstruct | 91 +-------------------- site_scons/gem5_scons/__init__.py | 127 ++++++++++++++++++++++++++++++ site_scons/gem5_scons/util.py | 5 ++ src/SConscript | 2 + src/arch/SConscript | 2 + src/mem/protocol/SConscript | 2 + src/mem/ruby/SConscript | 2 + tests/SConscript | 3 +- 8 files changed, 146 insertions(+), 88 deletions(-) diff --git a/SConstruct b/SConstruct index 9816c86be..095b58be4 100755 --- a/SConstruct +++ b/SConstruct @@ -96,7 +96,6 @@ import SCons import SCons.Node from m5.util import compareVersions, readCommand -from m5.util.terminal import get_termcap help_texts = { "options" : "", @@ -168,8 +167,6 @@ if GetOption('no_lto') and GetOption('force_lto'): print '--no-lto and --force-lto are mutually exclusive' Exit(1) -termcap = get_termcap(GetOption('use_colors')) - ######################################################################## # # Set up the main build environment. @@ -178,6 +175,10 @@ termcap = get_termcap(GetOption('use_colors')) main = Environment() +from gem5_scons import Transform +from gem5_scons.util import get_termcap +termcap = get_termcap() + main_dict_keys = main.Dictionary().keys() # Check that we have a C/C++ compiler @@ -301,90 +302,6 @@ main.Append(CPPPATH=[Dir('ext')]) # Add shared top-level headers main.Prepend(CPPPATH=Dir('include')) -def strip_build_path(path, env): - path = str(path) - variant_base = env['BUILDROOT'] + os.path.sep - if path.startswith(variant_base): - path = path[len(variant_base):] - elif path.startswith('build/'): - path = path[6:] - return path - -# Generate a string of the form: -# common/path/prefix/src1, src2 -> tgt1, tgt2 -# to print while building. -class Transform(object): - # all specific color settings should be here and nowhere else - tool_color = termcap.Normal - pfx_color = termcap.Yellow - srcs_color = termcap.Yellow + termcap.Bold - arrow_color = termcap.Blue + termcap.Bold - 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.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] - def strip(f): - return strip_build_path(str(f), env) - if len(source) > 0: - srcs = map(strip, source) - else: - srcs = [''] - tgts = map(strip, target) - # surprisingly, os.path.commonprefix is a dumb char-by-char string - # operation that has nothing to do with paths. - com_pfx = os.path.commonprefix(srcs + tgts) - com_pfx_len = len(com_pfx) - if com_pfx: - # do some cleanup and sanity checking on common prefix - if com_pfx[-1] == ".": - # prefix matches all but file extension: ok - # back up one to change 'foo.cc -> o' to 'foo.cc -> .o' - com_pfx = com_pfx[0:-1] - elif com_pfx[-1] == "/": - # common prefix is directory path: OK - pass - else: - src0_len = len(srcs[0]) - tgt0_len = len(tgts[0]) - if src0_len == com_pfx_len: - # source is a substring of target, OK - pass - elif tgt0_len == com_pfx_len: - # target is a substring of source, need to back up to - # avoid empty string on RHS of arrow - sep_idx = com_pfx.rfind(".") - if sep_idx != -1: - com_pfx = com_pfx[0:sep_idx] - else: - 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 = '' - # recalculate length in case com_pfx was modified - com_pfx_len = len(com_pfx) - def fmt(files): - f = map(lambda s: s[com_pfx_len:], files) - return ', '.join(f) - return self.format % (com_pfx, fmt(srcs), fmt(tgts)) - -Export('Transform') - -# enable the regression script to use the termcap -main['TERMCAP'] = termcap - if GetOption('verbose'): def MakeAction(action, string, *args, **kwargs): return Action(action, *args, **kwargs) diff --git a/site_scons/gem5_scons/__init__.py b/site_scons/gem5_scons/__init__.py index e69de29bb..0521862df 100644 --- a/site_scons/gem5_scons/__init__.py +++ b/site_scons/gem5_scons/__init__.py @@ -0,0 +1,127 @@ +# Copyright (c) 2013, 2015-2017 ARM Limited +# All rights reserved. +# +# 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) 2011 Advanced Micro Devices, Inc. +# Copyright (c) 2009 The Hewlett-Packard Development Company +# 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 os + +from gem5_scons.util import get_termcap + +termcap = get_termcap() + +def strip_build_path(path, env): + path = str(path) + build_base = 'build/' + variant_base = env['BUILDROOT'] + os.path.sep + if path.startswith(variant_base): + path = path[len(variant_base):] + elif path.startswith(build_base): + path = path[len(build_base):] + return path + +# Generate a string of the form: +# common/path/prefix/src1, src2 -> tgt1, tgt2 +# to print while building. +class Transform(object): + # all specific color settings should be here and nowhere else + tool_color = termcap.Normal + pfx_color = termcap.Yellow + srcs_color = termcap.Yellow + termcap.Bold + arrow_color = termcap.Blue + termcap.Bold + 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.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] + def strip(f): + return strip_build_path(str(f), env) + if len(source) > 0: + srcs = map(strip, source) + else: + srcs = [''] + tgts = map(strip, target) + # surprisingly, os.path.commonprefix is a dumb char-by-char string + # operation that has nothing to do with paths. + com_pfx = os.path.commonprefix(srcs + tgts) + com_pfx_len = len(com_pfx) + if com_pfx: + # do some cleanup and sanity checking on common prefix + if com_pfx[-1] == ".": + # prefix matches all but file extension: ok + # back up one to change 'foo.cc -> o' to 'foo.cc -> .o' + com_pfx = com_pfx[0:-1] + elif com_pfx[-1] == "/": + # common prefix is directory path: OK + pass + else: + src0_len = len(srcs[0]) + tgt0_len = len(tgts[0]) + if src0_len == com_pfx_len: + # source is a substring of target, OK + pass + elif tgt0_len == com_pfx_len: + # target is a substring of source, need to back up to + # avoid empty string on RHS of arrow + sep_idx = com_pfx.rfind(".") + if sep_idx != -1: + com_pfx = com_pfx[0:sep_idx] + else: + 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 = '' + # recalculate length in case com_pfx was modified + com_pfx_len = len(com_pfx) + def fmt(files): + f = map(lambda s: s[com_pfx_len:], files) + return ', '.join(f) + return self.format % (com_pfx, fmt(srcs), fmt(tgts)) + +__all__ = ['Transform'] diff --git a/site_scons/gem5_scons/util.py b/site_scons/gem5_scons/util.py index 4781cc543..1a196c227 100644 --- a/site_scons/gem5_scons/util.py +++ b/site_scons/gem5_scons/util.py @@ -42,6 +42,11 @@ import sys 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() + +def get_termcap(): + return m5.util.terminal.get_termcap(SCons.Script.GetOption('use_colors')) diff --git a/src/SConscript b/src/SConscript index 76bf8d1b4..6c3f22019 100755 --- a/src/SConscript +++ b/src/SConscript @@ -42,6 +42,8 @@ from os.path import basename, dirname, exists, isdir, isfile, join as joinpath import SCons +from gem5_scons import Transform + # This file defines how to build a particular configuration of gem5 # based on variable settings in the 'env' build environment. diff --git a/src/arch/SConscript b/src/arch/SConscript index 1030be7d0..728377dc5 100644 --- a/src/arch/SConscript +++ b/src/arch/SConscript @@ -44,6 +44,8 @@ import sys import os import re +from gem5_scons import Transform + Import('*') ################################################################# diff --git a/src/mem/protocol/SConscript b/src/mem/protocol/SConscript index 0eccdf3e5..e66c6b303 100644 --- a/src/mem/protocol/SConscript +++ b/src/mem/protocol/SConscript @@ -36,6 +36,8 @@ from os.path import isdir, isfile, join as joinpath from SCons.Scanner import Classic +from gem5_scons import Transform + Import('*') if env['PROTOCOL'] == 'None': diff --git a/src/mem/ruby/SConscript b/src/mem/ruby/SConscript index 88edb44a4..5cae880bd 100644 --- a/src/mem/ruby/SConscript +++ b/src/mem/ruby/SConscript @@ -35,6 +35,8 @@ from os.path import basename, isdir, join as joinpath import SCons +from gem5_scons import Transform + Import('*') DebugFlag('ProtocolTrace') diff --git a/tests/SConscript b/tests/SConscript index d1fee7ad1..3ed3e248b 100644 --- a/tests/SConscript +++ b/tests/SConscript @@ -50,11 +50,12 @@ import sys sys.path.insert(0, Dir(".").srcnode().abspath) import testing.tests as tests import testing.results as results +from gem5_scons.util import get_termcap Import('env') # get the termcap from the environment -termcap = env['TERMCAP'] +termcap = get_termcap() # Dict that accumulates lists of tests by category (quick, medium, long) env.Tests = {} -- 2.30.2