16bb753af52fc6d3c86923876f20c68c66edfc03
[gem5.git] / site_scons / gem5_scons / __init__.py
1 # Copyright (c) 2013, 2015-2017 ARM Limited
2 # All rights reserved.
3 #
4 # The license below extends only to copyright in the software and shall
5 # not be construed as granting a license to any other intellectual
6 # property including but not limited to intellectual property relating
7 # to a hardware implementation of the functionality of the software
8 # licensed hereunder. You may use the software subject to the license
9 # terms below provided that you ensure that this notice is replicated
10 # unmodified and in its entirety in all distributions of the software,
11 # modified or unmodified, in source code or in binary form.
12 #
13 # Copyright (c) 2011 Advanced Micro Devices, Inc.
14 # Copyright (c) 2009 The Hewlett-Packard Development Company
15 # Copyright (c) 2004-2005 The Regents of The University of Michigan
16 # All rights reserved.
17 #
18 # Redistribution and use in source and binary forms, with or without
19 # modification, are permitted provided that the following conditions are
20 # met: redistributions of source code must retain the above copyright
21 # notice, this list of conditions and the following disclaimer;
22 # redistributions in binary form must reproduce the above copyright
23 # notice, this list of conditions and the following disclaimer in the
24 # documentation and/or other materials provided with the distribution;
25 # neither the name of the copyright holders nor the names of its
26 # contributors may be used to endorse or promote products derived from
27 # this software without specific prior written permission.
28 #
29 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40
41 from __future__ import print_function
42
43 import os
44
45 from gem5_scons.util import get_termcap
46 import SCons.Script
47
48 termcap = get_termcap()
49
50 def strip_build_path(path, env):
51 path = str(path)
52 build_base = 'build/'
53 variant_base = env['BUILDROOT'] + os.path.sep
54 if path.startswith(variant_base):
55 path = path[len(variant_base):]
56 elif path.startswith(build_base):
57 path = path[len(build_base):]
58 return path
59
60 # Generate a string of the form:
61 # common/path/prefix/src1, src2 -> tgt1, tgt2
62 # to print while building.
63 class Transform(object):
64 # all specific color settings should be here and nowhere else
65 tool_color = termcap.Normal
66 pfx_color = termcap.Yellow
67 srcs_color = termcap.Yellow + termcap.Bold
68 arrow_color = termcap.Blue + termcap.Bold
69 tgts_color = termcap.Yellow + termcap.Bold
70
71 def __init__(self, tool, max_sources=99):
72 self.format = self.tool_color + (" [%8s] " % tool) \
73 + self.pfx_color + "%s" \
74 + self.srcs_color + "%s" \
75 + self.arrow_color + " -> " \
76 + self.tgts_color + "%s" \
77 + termcap.Normal
78 self.max_sources = max_sources
79
80 def __call__(self, target, source, env, for_signature=None):
81 # truncate source list according to max_sources param
82 source = source[0:self.max_sources]
83 def strip(f):
84 return strip_build_path(str(f), env)
85 if len(source) > 0:
86 srcs = list(map(strip, source))
87 else:
88 srcs = ['']
89 tgts = list(map(strip, target))
90 # surprisingly, os.path.commonprefix is a dumb char-by-char string
91 # operation that has nothing to do with paths.
92 com_pfx = os.path.commonprefix(srcs + tgts)
93 com_pfx_len = len(com_pfx)
94 if com_pfx:
95 # do some cleanup and sanity checking on common prefix
96 if com_pfx[-1] == ".":
97 # prefix matches all but file extension: ok
98 # back up one to change 'foo.cc -> o' to 'foo.cc -> .o'
99 com_pfx = com_pfx[0:-1]
100 elif com_pfx[-1] == "/":
101 # common prefix is directory path: OK
102 pass
103 else:
104 src0_len = len(srcs[0])
105 tgt0_len = len(tgts[0])
106 if src0_len == com_pfx_len:
107 # source is a substring of target, OK
108 pass
109 elif tgt0_len == com_pfx_len:
110 # target is a substring of source, need to back up to
111 # avoid empty string on RHS of arrow
112 sep_idx = com_pfx.rfind(".")
113 if sep_idx != -1:
114 com_pfx = com_pfx[0:sep_idx]
115 else:
116 com_pfx = ''
117 elif src0_len > com_pfx_len and srcs[0][com_pfx_len] == ".":
118 # still splitting at file extension: ok
119 pass
120 else:
121 # probably a fluke; ignore it
122 com_pfx = ''
123 # recalculate length in case com_pfx was modified
124 com_pfx_len = len(com_pfx)
125 def fmt(files):
126 f = list(map(lambda s: s[com_pfx_len:], files))
127 return ', '.join(f)
128 return self.format % (com_pfx, fmt(srcs), fmt(tgts))
129
130 def print_message(prefix, color, message, **kwargs):
131 lines = message.split('\n')
132 message = prefix + ('\n' + ' ' * len(prefix)).join(lines)
133 print(color + termcap.Bold + message + termcap.Normal, **kwargs)
134
135 def warning(*args, **kwargs):
136 message = ' '.join(args)
137 print_message('Warning: ', termcap.Yellow, message, **kwargs)
138
139 def error(*args, **kwargs):
140 message = ' '.join(args)
141 print_message('Error: ', termcap.Red, message, **kwargs)
142 SCons.Script.Exit(1)
143
144 __all__ = ['Transform', 'warning', 'error']