3 # Copyright The SCons Foundation
5 # Permission is hereby granted, free of charge, to any person obtaining
6 # a copy of this software and associated documentation files (the
7 # "Software"), to deal in the Software without restriction, including
8 # without limitation the rights to use, copy, modify, merge, publish,
9 # distribute, sublicense, and/or sell copies of the Software, and to
10 # permit persons to whom the Software is furnished to do so, subject to
11 # the following conditions:
13 # The above copyright notice and this permission notice shall be included
14 # in all copies or substantial portions of the Software.
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
17 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
18 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 Microsoft Visual C/C++ policy handlers.
28 * The default msvc not found policy is that a warning is issued. This can be
29 changed globally via the function set_msvc_notfound_policy and/or through
30 the environment via the MSVC_NOTFOUND_POLICY construction variable.
31 * The default msvc script error policy is to suppress all msvc batch file
32 error messages. This can be changed globally via the function
33 set_msvc_scripterror_policy and/or through the environment via the
34 MSVC_SCRIPTERROR_POLICY construction variable.
37 from collections
import (
41 from contextlib
import (
47 from ..common
import (
51 from .Exceptions
import (
54 MSVCScriptExecutionError
,
57 from .Warnings
import (
58 MSVCScriptExecutionWarning
,
61 from . import Dispatcher
62 Dispatcher
.register_modulename(__name__
)
65 # MSVC_NOTFOUND_POLICY definition:
66 # error: raise exception
67 # warning: issue warning and continue
70 MSVC_NOTFOUND_POLICY_DEFINITION
= namedtuple('MSVCNotFoundPolicyDefinition', [
75 MSVC_NOTFOUND_DEFINITION_LIST
= []
77 MSVC_NOTFOUND_POLICY_INTERNAL
= {}
78 MSVC_NOTFOUND_POLICY_EXTERNAL
= {}
80 for policy_value
, policy_symbol_list
in [
81 (True, ['Error', 'Exception']),
82 (False, ['Warning', 'Warn']),
83 (None, ['Ignore', 'Suppress']),
86 policy_symbol
= policy_symbol_list
[0].lower()
87 policy_def
= MSVC_NOTFOUND_POLICY_DEFINITION(policy_value
, policy_symbol
)
89 MSVC_NOTFOUND_DEFINITION_LIST
.append(policy_def
)
91 MSVC_NOTFOUND_POLICY_INTERNAL
[policy_symbol
] = policy_def
93 for policy_symbol
in policy_symbol_list
:
94 MSVC_NOTFOUND_POLICY_EXTERNAL
[policy_symbol
.lower()] = policy_def
95 MSVC_NOTFOUND_POLICY_EXTERNAL
[policy_symbol
] = policy_def
96 MSVC_NOTFOUND_POLICY_EXTERNAL
[policy_symbol
.upper()] = policy_def
99 _MSVC_NOTFOUND_POLICY_DEF
= MSVC_NOTFOUND_POLICY_INTERNAL
['warning']
102 # MSVC_SCRIPTERROR_POLICY definition:
103 # error: raise exception
104 # warning: issue warning and continue
107 MSVC_SCRIPTERROR_POLICY_DEFINITION
= namedtuple('MSVCBatchErrorPolicyDefinition', [
112 MSVC_SCRIPTERROR_DEFINITION_LIST
= []
114 MSVC_SCRIPTERROR_POLICY_INTERNAL
= {}
115 MSVC_SCRIPTERROR_POLICY_EXTERNAL
= {}
117 for policy_value
, policy_symbol_list
in [
118 (True, ['Error', 'Exception']),
119 (False, ['Warning', 'Warn']),
120 (None, ['Ignore', 'Suppress']),
123 policy_symbol
= policy_symbol_list
[0].lower()
124 policy_def
= MSVC_SCRIPTERROR_POLICY_DEFINITION(policy_value
, policy_symbol
)
126 MSVC_SCRIPTERROR_DEFINITION_LIST
.append(policy_def
)
128 MSVC_SCRIPTERROR_POLICY_INTERNAL
[policy_symbol
] = policy_def
130 for policy_symbol
in policy_symbol_list
:
131 MSVC_SCRIPTERROR_POLICY_EXTERNAL
[policy_symbol
.lower()] = policy_def
132 MSVC_SCRIPTERROR_POLICY_EXTERNAL
[policy_symbol
] = policy_def
133 MSVC_SCRIPTERROR_POLICY_EXTERNAL
[policy_symbol
.upper()] = policy_def
136 _MSVC_SCRIPTERROR_POLICY_DEF
= MSVC_SCRIPTERROR_POLICY_INTERNAL
['ignore']
139 def _msvc_notfound_policy_lookup(symbol
):
142 notfound_policy_def
= MSVC_NOTFOUND_POLICY_EXTERNAL
[symbol
]
144 err_msg
= "Value specified for MSVC_NOTFOUND_POLICY is not supported: {}.\n" \
145 " Valid values are: {}".format(
147 ', '.join([repr(s
) for s
in MSVC_NOTFOUND_POLICY_EXTERNAL
.keys()])
149 raise MSVCArgumentError(err_msg
)
151 return notfound_policy_def
153 def msvc_set_notfound_policy(MSVC_NOTFOUND_POLICY
=None):
154 """ Set the default policy when MSVC is not found.
157 MSVC_NOTFOUND_POLICY:
158 string representing the policy behavior
159 when MSVC is not found or None
162 The previous policy is returned when the MSVC_NOTFOUND_POLICY argument
163 is not None. The active policy is returned when the MSVC_NOTFOUND_POLICY
167 global _MSVC_NOTFOUND_POLICY_DEF
169 prev_policy
= _MSVC_NOTFOUND_POLICY_DEF
.symbol
171 policy
= MSVC_NOTFOUND_POLICY
172 if policy
is not None:
173 _MSVC_NOTFOUND_POLICY_DEF
= _msvc_notfound_policy_lookup(policy
)
176 'prev_policy=%s, set_policy=%s, policy.symbol=%s, policy.value=%s',
177 repr(prev_policy
), repr(policy
),
178 repr(_MSVC_NOTFOUND_POLICY_DEF
.symbol
), repr(_MSVC_NOTFOUND_POLICY_DEF
.value
)
183 def msvc_get_notfound_policy():
184 """Return the active policy when MSVC is not found."""
186 'policy.symbol=%s, policy.value=%s',
187 repr(_MSVC_NOTFOUND_POLICY_DEF
.symbol
), repr(_MSVC_NOTFOUND_POLICY_DEF
.value
)
189 return _MSVC_NOTFOUND_POLICY_DEF
.symbol
191 def msvc_notfound_handler(env
, msg
):
193 if env
and 'MSVC_NOTFOUND_POLICY' in env
:
194 # environment setting
195 notfound_policy_src
= 'environment'
196 policy
= env
['MSVC_NOTFOUND_POLICY']
197 if policy
is not None:
198 # user policy request
199 notfound_policy_def
= _msvc_notfound_policy_lookup(policy
)
201 # active global setting
202 notfound_policy_def
= _MSVC_NOTFOUND_POLICY_DEF
204 # active global setting
205 notfound_policy_src
= 'default'
207 notfound_policy_def
= _MSVC_NOTFOUND_POLICY_DEF
210 'source=%s, set_policy=%s, policy.symbol=%s, policy.value=%s',
211 notfound_policy_src
, repr(policy
), repr(notfound_policy_def
.symbol
), repr(notfound_policy_def
.value
)
214 if notfound_policy_def
.value
is None:
217 elif notfound_policy_def
.value
:
218 raise MSVCVersionNotFound(msg
)
220 SCons
.Warnings
.warn(SCons
.Warnings
.VisualCMissingWarning
, msg
)
223 def msvc_notfound_policy_contextmanager(MSVC_NOTFOUND_POLICY
=None):
224 """ Temporarily change the MSVC not found policy within a context.
227 MSVC_NOTFOUND_POLICY:
228 string representing the policy behavior
229 when MSVC is not found or None
231 prev_policy
= msvc_set_notfound_policy(MSVC_NOTFOUND_POLICY
)
233 msvc_set_notfound_policy(prev_policy
)
235 def _msvc_scripterror_policy_lookup(symbol
):
238 scripterror_policy_def
= MSVC_SCRIPTERROR_POLICY_EXTERNAL
[symbol
]
240 err_msg
= "Value specified for MSVC_SCRIPTERROR_POLICY is not supported: {}.\n" \
241 " Valid values are: {}".format(
243 ', '.join([repr(s
) for s
in MSVC_SCRIPTERROR_POLICY_EXTERNAL
.keys()])
245 raise MSVCArgumentError(err_msg
)
247 return scripterror_policy_def
249 def msvc_set_scripterror_policy(MSVC_SCRIPTERROR_POLICY
=None):
250 """ Set the default policy when msvc batch file execution errors are detected.
253 MSVC_SCRIPTERROR_POLICY:
254 string representing the policy behavior
255 when msvc batch file execution errors are detected or None
258 The previous policy is returned when the MSVC_SCRIPTERROR_POLICY argument
259 is not None. The active policy is returned when the MSVC_SCRIPTERROR_POLICY
263 global _MSVC_SCRIPTERROR_POLICY_DEF
265 prev_policy
= _MSVC_SCRIPTERROR_POLICY_DEF
.symbol
267 policy
= MSVC_SCRIPTERROR_POLICY
268 if policy
is not None:
269 _MSVC_SCRIPTERROR_POLICY_DEF
= _msvc_scripterror_policy_lookup(policy
)
272 'prev_policy=%s, set_policy=%s, policy.symbol=%s, policy.value=%s',
273 repr(prev_policy
), repr(policy
),
274 repr(_MSVC_SCRIPTERROR_POLICY_DEF
.symbol
), repr(_MSVC_SCRIPTERROR_POLICY_DEF
.value
)
279 def msvc_get_scripterror_policy():
280 """Return the active policy when msvc batch file execution errors are detected."""
282 'policy.symbol=%s, policy.value=%s',
283 repr(_MSVC_SCRIPTERROR_POLICY_DEF
.symbol
), repr(_MSVC_SCRIPTERROR_POLICY_DEF
.value
)
285 return _MSVC_SCRIPTERROR_POLICY_DEF
.symbol
287 def msvc_scripterror_handler(env
, msg
):
289 if env
and 'MSVC_SCRIPTERROR_POLICY' in env
:
290 # environment setting
291 scripterror_policy_src
= 'environment'
292 policy
= env
['MSVC_SCRIPTERROR_POLICY']
293 if policy
is not None:
294 # user policy request
295 scripterror_policy_def
= _msvc_scripterror_policy_lookup(policy
)
297 # active global setting
298 scripterror_policy_def
= _MSVC_SCRIPTERROR_POLICY_DEF
300 # active global setting
301 scripterror_policy_src
= 'default'
303 scripterror_policy_def
= _MSVC_SCRIPTERROR_POLICY_DEF
306 'source=%s, set_policy=%s, policy.symbol=%s, policy.value=%s',
307 scripterror_policy_src
, repr(policy
), repr(scripterror_policy_def
.symbol
), repr(scripterror_policy_def
.value
)
310 if scripterror_policy_def
.value
is None:
313 elif scripterror_policy_def
.value
:
314 raise MSVCScriptExecutionError(msg
)
316 SCons
.Warnings
.warn(MSVCScriptExecutionWarning
, msg
)
319 def msvc_scripterror_policy_contextmanager(MSVC_SCRIPTERROR_POLICY
=None):
320 """ Temporarily change the msvc batch execution errors policy within a context.
323 MSVC_SCRIPTERROR_POLICY:
324 string representing the policy behavior
325 when msvc batch file execution errors are detected or None
327 prev_policy
= msvc_set_scripterror_policy(MSVC_SCRIPTERROR_POLICY
)
329 msvc_set_scripterror_policy(prev_policy
)