Merge pull request #4655 from bdbaddog/fix_new_ninja_package
[scons.git] / SCons / Tool / MSCommon / MSVC / Policy.py
blob7e11a63ba53aa49b1dcb8afd7f95842c22b146b3
1 # MIT License
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.
24 """
25 Microsoft Visual C/C++ policy handlers.
27 Notes:
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.
35 """
37 from collections import (
38 namedtuple,
41 from contextlib import (
42 contextmanager,
45 import SCons.Warnings
47 from ..common import (
48 debug,
51 from .Exceptions import (
52 MSVCArgumentError,
53 MSVCVersionNotFound,
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
68 # ignore: continue
70 MSVC_NOTFOUND_POLICY_DEFINITION = namedtuple('MSVCNotFoundPolicyDefinition', [
71 'value',
72 'symbol',
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
98 # default definition
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
105 # ignore: continue
107 MSVC_SCRIPTERROR_POLICY_DEFINITION = namedtuple('MSVCBatchErrorPolicyDefinition', [
108 'value',
109 'symbol',
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
135 # default definition
136 _MSVC_SCRIPTERROR_POLICY_DEF = MSVC_SCRIPTERROR_POLICY_INTERNAL['ignore']
139 def _msvc_notfound_policy_lookup(symbol):
141 try:
142 notfound_policy_def = MSVC_NOTFOUND_POLICY_EXTERNAL[symbol]
143 except KeyError:
144 err_msg = "Value specified for MSVC_NOTFOUND_POLICY is not supported: {}.\n" \
145 " Valid values are: {}".format(
146 repr(symbol),
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.
156 Args:
157 MSVC_NOTFOUND_POLICY:
158 string representing the policy behavior
159 when MSVC is not found or None
161 Returns:
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
164 argument is None.
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)
175 debug(
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)
181 return prev_policy
183 def msvc_get_notfound_policy():
184 """Return the active policy when MSVC is not found."""
185 debug(
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)
200 else:
201 # active global setting
202 notfound_policy_def = _MSVC_NOTFOUND_POLICY_DEF
203 else:
204 # active global setting
205 notfound_policy_src = 'default'
206 policy = None
207 notfound_policy_def = _MSVC_NOTFOUND_POLICY_DEF
209 debug(
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:
215 # ignore
216 pass
217 elif notfound_policy_def.value:
218 raise MSVCVersionNotFound(msg)
219 else:
220 SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, msg)
222 @contextmanager
223 def msvc_notfound_policy_contextmanager(MSVC_NOTFOUND_POLICY=None):
224 """ Temporarily change the MSVC not found policy within a context.
226 Args:
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)
232 yield
233 msvc_set_notfound_policy(prev_policy)
235 def _msvc_scripterror_policy_lookup(symbol):
237 try:
238 scripterror_policy_def = MSVC_SCRIPTERROR_POLICY_EXTERNAL[symbol]
239 except KeyError:
240 err_msg = "Value specified for MSVC_SCRIPTERROR_POLICY is not supported: {}.\n" \
241 " Valid values are: {}".format(
242 repr(symbol),
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.
252 Args:
253 MSVC_SCRIPTERROR_POLICY:
254 string representing the policy behavior
255 when msvc batch file execution errors are detected or None
257 Returns:
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
260 argument is None.
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)
271 debug(
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)
277 return prev_policy
279 def msvc_get_scripterror_policy():
280 """Return the active policy when msvc batch file execution errors are detected."""
281 debug(
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)
296 else:
297 # active global setting
298 scripterror_policy_def = _MSVC_SCRIPTERROR_POLICY_DEF
299 else:
300 # active global setting
301 scripterror_policy_src = 'default'
302 policy = None
303 scripterror_policy_def = _MSVC_SCRIPTERROR_POLICY_DEF
305 debug(
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:
311 # ignore
312 pass
313 elif scripterror_policy_def.value:
314 raise MSVCScriptExecutionError(msg)
315 else:
316 SCons.Warnings.warn(MSVCScriptExecutionWarning, msg)
318 @contextmanager
319 def msvc_scripterror_policy_contextmanager(MSVC_SCRIPTERROR_POLICY=None):
320 """ Temporarily change the msvc batch execution errors policy within a context.
322 Args:
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)
328 yield
329 msvc_set_scripterror_policy(prev_policy)