summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIvan Kravets <me@ikravets.com>2020-02-13 15:33:47 (GMT)
committerIvan Kravets <me@ikravets.com>2020-02-13 15:33:47 (GMT)
commitfe2680ddd07a4bc7c6064e7193f4979060e178ba (patch)
tree3719de5a3e9657881f1f2b8ef730a45fc4a00750
parent8bc187941d5ea8a11200432c099802eefa7a2356 (diff)
downloadSCons-fe2680ddd07a4bc7c6064e7193f4979060e178ba.zip
SCons-fe2680ddd07a4bc7c6064e7193f4979060e178ba.tar.gz
SCons-fe2680ddd07a4bc7c6064e7193f4979060e178ba.tar.bz2
Isolate CConditionalScanner from CScanner
-rw-r--r--src/engine/SCons/Scanner/C.py142
1 files changed, 107 insertions, 35 deletions
diff --git a/src/engine/SCons/Scanner/C.py b/src/engine/SCons/Scanner/C.py
index 37bf244..29cc396 100644
--- a/src/engine/SCons/Scanner/C.py
+++ b/src/engine/SCons/Scanner/C.py
@@ -46,27 +46,16 @@ class SConsCPPScanner(SCons.cpp.PreProcessor):
def __init__(self, *args, **kw):
SCons.cpp.PreProcessor.__init__(self, *args, **kw)
self.missing = []
- self._known_paths = []
-
def initialize_result(self, fname):
self.result = SCons.Util.UniqueList([fname])
-
+ def finalize_result(self, fname):
+ return self.result[1:]
def find_include_file(self, t):
keyword, quote, fname = t
- paths = tuple(self._known_paths) + self.searchpath[quote]
- if quote == '"':
- paths = (self.current_file.dir, ) + paths
- result = SCons.Node.FS.find_file(fname, paths)
- if result:
- result_path = result.get_abspath()
- for p in self.searchpath[quote]:
- if result_path.startswith(p.get_abspath()):
- self._known_paths.append(p)
- break
- else:
+ result = SCons.Node.FS.find_file(fname, self.searchpath[quote])
+ if not result:
self.missing.append((fname, self.current_file))
return result
-
def read_file(self, file):
try:
with open(str(file.rfile())) as fp:
@@ -83,11 +72,7 @@ def dictify_CPPDEFINES(env):
result = {}
for c in cppdefines:
if SCons.Util.is_Sequence(c):
- # handle tuple with 1 item (e.g. tuple("DEFINE", ))
- if len(c) > 1:
- result[c[0]] = c[1]
- else:
- result[c[0]] = None
+ result[c[0]] = c[1]
else:
result[c] = None
return result
@@ -107,11 +92,10 @@ class SConsCPPScannerWrapper(object):
def __init__(self, name, variable):
self.name = name
self.path = SCons.Scanner.FindPathDirs(variable)
- def __call__(self, node, env, path = (), depth=-1):
+ def __call__(self, node, env, path = ()):
cpp = SConsCPPScanner(current = node.get_dir(),
cpppath = path,
- dict = dictify_CPPDEFINES(env),
- depth = depth)
+ dict = dictify_CPPDEFINES(env))
result = cpp(node)
for included, includer in cpp.missing:
fmt = "No dependency generated for file: %s (included from: %s) -- file not found"
@@ -124,26 +108,114 @@ class SConsCPPScannerWrapper(object):
def select(self, node):
return self
+def CScanner():
+ """Return a prototype Scanner instance for scanning source files
+ that use the C pre-processor"""
+
+ # Here's how we would (or might) use the CPP scanner code above that
+ # knows how to evaluate #if/#ifdef/#else/#elif lines when searching
+ # for #includes. This is commented out for now until we add the
+ # right configurability to let users pick between the scanners.
+ #return SConsCPPScannerWrapper("CScanner", "CPPPATH")
-def CConditionalScanner():
+ cs = SCons.Scanner.ClassicCPP("CScanner",
+ "$CPPSUFFIXES",
+ "CPPPATH",
+ '^[ \t]*#[ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")')
+ return cs
+
+
+#
+# ConditionalScanner
+#
+
+
+class SConsCPPConditionalScanner(SCons.cpp.PreProcessor):
"""
- Return an advanced conditional Scanner instance for scanning source files
+ SCons-specific subclass of the cpp.py module's processing.
- Interprets C/C++ Preprocessor conditional syntax
- (#ifdef, #if, defined, #else, #elif, etc.).
+ We subclass this so that: 1) we can deal with files represented
+ by Nodes, not strings; 2) we can keep track of the files that are
+ missing.
"""
- return SConsCPPScannerWrapper("CScanner", "CPPPATH")
+ def __init__(self, *args, **kw):
+ SCons.cpp.PreProcessor.__init__(self, *args, **kw)
+ self.missing = []
+ self._known_paths = []
+
+ def initialize_result(self, fname):
+ self.result = SCons.Util.UniqueList([fname])
-def CScanner():
- """Return a simplified classic Scanner instance for scanning source files
+ def find_include_file(self, t):
+ keyword, quote, fname = t
+ paths = tuple(self._known_paths) + self.searchpath[quote]
+ if quote == '"':
+ paths = (self.current_file.dir,) + paths
+ result = SCons.Node.FS.find_file(fname, paths)
+ if result:
+ result_path = result.get_abspath()
+ for p in self.searchpath[quote]:
+ if result_path.startswith(p.get_abspath()):
+ self._known_paths.append(p)
+ break
+ else:
+ self.missing.append((fname, self.current_file))
+ return result
+
+ def read_file(self, file):
+ try:
+ with open(str(file.rfile())) as fp:
+ return fp.read()
+ except EnvironmentError:
+ self.missing.append((file, self.current_file))
+ return ""
+
+
+class SConsCPPConditionalScannerWrapper(object):
+ """
+ The SCons wrapper around a cpp.py scanner.
+
+ This is the actual glue between the calling conventions of generic
+ SCons scanners, and the (subclass of) cpp.py class that knows how
+ to look for #include lines with reasonably real C-preprocessor-like
+ evaluation of #if/#ifdef/#else/#elif lines.
+ """
- Takes into account the type of bracketing used to include the file, and
- uses classic CPP rules for searching for the files based on the bracketing.
+ def __init__(self, name, variable):
+ self.name = name
+ self.path = SCons.Scanner.FindPathDirs(variable)
+
+ def __call__(self, node, env, path=(), depth=-1):
+ cpp = SConsCPPConditionalScanner(
+ current=node.get_dir(),
+ cpppath=path,
+ dict=dictify_CPPDEFINES(env),
+ depth=depth,
+ )
+ result = cpp(node)
+ for included, includer in cpp.missing:
+ fmt = "No dependency generated for file: %s (included from: %s) -- file not found"
+ SCons.Warnings.warn(
+ SCons.Warnings.DependencyWarning, fmt % (included, includer)
+ )
+ return result
+
+ def recurse_nodes(self, nodes):
+ return nodes
+
+ def select(self, node):
+ return self
+
+
+def CConditionalScanner():
+ """
+ Return an advanced conditional Scanner instance for scanning source files
+
+ Interprets C/C++ Preprocessor conditional syntax
+ (#ifdef, #if, defined, #else, #elif, etc.).
"""
- return SCons.Scanner.ClassicCPP(
- "CScanner", "$CPPSUFFIXES", "CPPPATH",
- '^[ \t]*#[ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")')
+ return SConsCPPConditionalScannerWrapper("CConditionalScanner", "CPPPATH")
# Local Variables: