1 # Copyright (c) 2013, 2015-2017 ARM Limited
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.
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.
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.
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.
41 from __future__
import print_function
46 from gem5_scons
.util
import get_termcap
49 termcap
= get_termcap()
51 def strip_build_path(path
, env
):
54 variant_base
= env
['BUILDROOT'] + os
.path
.sep
55 if path
.startswith(variant_base
):
56 path
= path
[len(variant_base
):]
57 elif path
.startswith(build_base
):
58 path
= path
[len(build_base
):]
61 # Generate a string of the form:
62 # common/path/prefix/src1, src2 -> tgt1, tgt2
63 # to print while building.
64 class Transform(object):
65 # all specific color settings should be here and nowhere else
66 tool_color
= termcap
.Normal
67 pfx_color
= termcap
.Yellow
68 srcs_color
= termcap
.Yellow
+ termcap
.Bold
69 arrow_color
= termcap
.Blue
+ termcap
.Bold
70 tgts_color
= termcap
.Yellow
+ termcap
.Bold
72 def __init__(self
, tool
, max_sources
=99):
73 self
.format
= self
.tool_color
+ (" [%8s] " % tool
) \
74 + self
.pfx_color
+ "%s" \
75 + self
.srcs_color
+ "%s" \
76 + self
.arrow_color
+ " -> " \
77 + self
.tgts_color
+ "%s" \
79 self
.max_sources
= max_sources
81 def __call__(self
, target
, source
, env
, for_signature
=None):
82 # truncate source list according to max_sources param
83 source
= source
[0:self
.max_sources
]
85 return strip_build_path(str(f
), env
)
87 srcs
= list(map(strip
, source
))
90 tgts
= list(map(strip
, target
))
91 # surprisingly, os.path.commonprefix is a dumb char-by-char string
92 # operation that has nothing to do with paths.
93 com_pfx
= os
.path
.commonprefix(srcs
+ tgts
)
94 com_pfx_len
= len(com_pfx
)
96 # do some cleanup and sanity checking on common prefix
97 if com_pfx
[-1] == ".":
98 # prefix matches all but file extension: ok
99 # back up one to change 'foo.cc -> o' to 'foo.cc -> .o'
100 com_pfx
= com_pfx
[0:-1]
101 elif com_pfx
[-1] == "/":
102 # common prefix is directory path: OK
105 src0_len
= len(srcs
[0])
106 tgt0_len
= len(tgts
[0])
107 if src0_len
== com_pfx_len
:
108 # source is a substring of target, OK
110 elif tgt0_len
== com_pfx_len
:
111 # target is a substring of source, need to back up to
112 # avoid empty string on RHS of arrow
113 sep_idx
= com_pfx
.rfind(".")
115 com_pfx
= com_pfx
[0:sep_idx
]
118 elif src0_len
> com_pfx_len
and srcs
[0][com_pfx_len
] == ".":
119 # still splitting at file extension: ok
122 # probably a fluke; ignore it
124 # recalculate length in case com_pfx was modified
125 com_pfx_len
= len(com_pfx
)
127 f
= list(map(lambda s
: s
[com_pfx_len
:], files
))
129 return self
.format
% (com_pfx
, fmt(srcs
), fmt(tgts
))
131 # The width warning and error messages should be wrapped at.
134 # This should work in python 3.3 and above.
135 if text_width
is None:
138 text_width
= shutil
.get_terminal_size().columns
142 # This should work if the curses python module is installed.
143 if text_width
is None:
147 _
, text_width
= curses
.initscr().getmaxyx()
153 # If all else fails, default to 80 columns.
154 if text_width
is None:
157 def print_message(prefix
, color
, message
, **kwargs
):
158 # Precompute some useful values.
159 prefix_len
= len(prefix
)
160 wrap_width
= text_width
- prefix_len
161 padding
= ' ' * prefix_len
163 # First split on newlines.
164 lines
= message
.split('\n')
165 # Then wrap each line to the required width.
168 wrapped_lines
.extend(textwrap
.wrap(line
, wrap_width
))
169 # Finally add the prefix and padding on extra lines, and glue it all back
171 message
= prefix
+ ('\n' + padding
).join(wrapped_lines
)
172 # Print the message in bold in the requested color.
173 print(color
+ termcap
.Bold
+ message
+ termcap
.Normal
, **kwargs
)
175 def warning(*args
, **kwargs
):
176 message
= ' '.join(args
)
177 print_message('Warning: ', termcap
.Yellow
, message
, **kwargs
)
179 def error(*args
, **kwargs
):
180 message
= ' '.join(args
)
181 print_message('Error: ', termcap
.Red
, message
, **kwargs
)
184 __all__
= ['Transform', 'warning', 'error']