From 9ec0b9861951cc72de39c742c1162a84696ce91f Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sat, 21 Jul 2018 11:55:31 -0600 Subject: Add ability for SConscript to fail on missing script SConscript call now takes an optional must_exist flag, which defaults to False for compatiility with current behavior. If True, an exception is raised if the file is missing. To improve readability, the decision is moved off to a new function rather than being inline in _SConscript. A global setting to control the overall behavior is also added. A deprecation warning is added for the current behavior, which is printed only once. Signed-off-by: Mats Wichmann --- src/CHANGES.txt | 1 + src/engine/SCons/Script/SConscript.py | 24 ++++++++++++++++++++++-- src/engine/SCons/Script/SConscript.xml | 18 ++++++++++++++---- src/engine/SCons/Script/__init__.py | 10 ++++++++++ src/engine/SCons/Warnings.py | 7 +++++-- 5 files changed, 52 insertions(+), 8 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 79d25db..3b0e603 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -97,6 +97,7 @@ RELEASE 3.1.0.alpha.yyyymmdd - NEW DATE WILL BE INSERTED HERE This changes SCons to better comply with normal Python installation practices. From Mats Wichmann: + - Begin adding support for SConscript() failing on missing script - Updated manpage scons.xml to fix a nested list problem - Updated doc terminiology: use prepend instead of append as appropriate - xml validity fixes from SConstruct.py change diff --git a/src/engine/SCons/Script/SConscript.py b/src/engine/SCons/Script/SConscript.py index db6552c..5968346 100644 --- a/src/engine/SCons/Script/SConscript.py +++ b/src/engine/SCons/Script/SConscript.py @@ -153,6 +153,27 @@ def Return(*vars, **kw): stack_bottom = '% Stack boTTom %' # hard to define a variable w/this name :) +def handle_missing_SConscript(f, must_exist): + """Take appropriate action on missing file in SConscript() call. + + The action may be to raise an exception, or print a warning. + On first warning, also print a deprecation warning. + """ + + if SCons.Script._no_missing_sconscript or must_exist: + msg = "Fatal: missing SConscript '%s'" % f.get_internal_path() + raise SCons.Errors.UserError(msg) + + if SCons.Script._warn_missing_sconscript_deprecated: + msg = "Calling missing SConscripts without error is deprecated.\n" + \ + "Transition by adding must_exist=0 to SConscript calls.\n" + \ + "Missing SConscript '%s'" % f.get_internal_path() + SCons.Warnings.warn(SCons.Warnings.DeprecatedMissingSConscriptWarning, msg) + SCons.Script._warn_missing_sconscript_deprecated = False + else: + msg = "Ignoring missing SConscript '%s'" % f.get_internal_path() + SCons.Warnings.warn(SCons.Warnings.MissingSConscriptWarning, msg) + def _SConscript(fs, *files, **kw): top = fs.Top sd = fs.SConstruct_dir.rdir() @@ -264,8 +285,7 @@ def _SConscript(fs, *files, **kw): if old_file is not None: call_stack[-1].globals.update({__file__:old_file}) else: - SCons.Warnings.warn(SCons.Warnings.MissingSConscriptWarning, - "Ignoring missing SConscript '%s'" % f.get_internal_path()) + handle_missing_SConscript(f, kw.get('must_exist', False)) finally: SCons.Script.sconscript_reading = SCons.Script.sconscript_reading - 1 diff --git a/src/engine/SCons/Script/SConscript.xml b/src/engine/SCons/Script/SConscript.xml index 8553fbe..29a89c2 100644 --- a/src/engine/SCons/Script/SConscript.xml +++ b/src/engine/SCons/Script/SConscript.xml @@ -357,12 +357,12 @@ Return('val1 val2') -(scripts, [exports, variant_dir, duplicate]) - +(scripts, [exports, variant_dir, duplicate, must_exist=flag]) + -(dirs=subdirs, [name=script, exports, variant_dir, duplicate]) - +(dirs=subdirs, [name=script, exports, variant_dir, duplicate, must_exist=flag]) + @@ -562,6 +562,16 @@ and what about this alternative? TODO??? SConscript('build/SConscript', src_dir='src') --> + +The optional +must_exist +argument, if true, causes an exception to be raised if a requested +&SConscript; file is not found. The default is false, +which only prints a warning, but this behavior is deprecated. +For scripts which truly intend to be optional, transition to +explicty supplying +must_exist=False to the call. + Here are some composite examples: diff --git a/src/engine/SCons/Script/__init__.py b/src/engine/SCons/Script/__init__.py index 89fc061..90bc311 100644 --- a/src/engine/SCons/Script/__init__.py +++ b/src/engine/SCons/Script/__init__.py @@ -276,6 +276,16 @@ def HelpFunction(text, append=False): # Will be non-zero if we are reading an SConscript file. sconscript_reading = 0 +_no_missing_sconscript = False +_warn_missing_sconscript_deprecated = True + +def set_missing_sconscript_error(flag=1): + """Set behavior on missing file in SConscript() call. Returns previous value""" + global _no_missing_sconscript + old = _no_missing_sconscript + _no_missing_sconscript = flag + return old + # def Variables(files=[], args=ARGUMENTS): return SCons.Variables.Variables(files, args) diff --git a/src/engine/SCons/Warnings.py b/src/engine/SCons/Warnings.py index e8158a4..63acd22 100644 --- a/src/engine/SCons/Warnings.py +++ b/src/engine/SCons/Warnings.py @@ -147,6 +147,9 @@ class DeprecatedSigModuleWarning(MandatoryDeprecatedWarning): class DeprecatedBuilderKeywordsWarning(MandatoryDeprecatedWarning): pass +class DeprecatedMissingSConscriptWarning(DeprecatedWarning): + pass + # The below is a list of 2-tuples. The first element is a class object. # The second element is true if that class is enabled, false if it is disabled. @@ -179,8 +182,8 @@ def warn(clazz, *args): global _enabled, _warningAsException, _warningOut warning = clazz(args) - for clazz, flag in _enabled: - if isinstance(warning, clazz): + for cls, flag in _enabled: + if isinstance(warning, cls): if flag: if _warningAsException: raise warning -- cgit v0.12