From 654e4414d80324b2a4c2edf3c685a38feec514f6 Mon Sep 17 00:00:00 2001 From: William Blevins Date: Wed, 13 May 2015 00:06:05 -0400 Subject: Issue 2264: Added SWIG recursive dependency tests. --- QMTest/TestCommon.py | 32 ++++++++++ test/SWIG/recursive-includes-cpp.py | 123 ++++++++++++++++++++++++++++++++++++ 2 files changed, 155 insertions(+) create mode 100644 test/SWIG/recursive-includes-cpp.py diff --git a/QMTest/TestCommon.py b/QMTest/TestCommon.py index 4e90e16..275d4f2 100644 --- a/QMTest/TestCommon.py +++ b/QMTest/TestCommon.py @@ -36,6 +36,8 @@ provided by the TestCommon class: test.must_contain('file', 'required text\n') + test.must_contain_all(output, lines, ['title', find]) + test.must_contain_all_lines(output, lines, ['title', find]) test.must_contain_any_line(output, lines, ['title', find]) @@ -305,6 +307,36 @@ class TestCommon(TestCmd): print file_contents self.fail_test(not contains) + def must_contain_all(self, output, input, title=None, find=None): + """Ensures that the specified output string (first argument) + contains all of the specified input as a block (second argument). + + An optional third argument can be used to describe the type + of output being searched, and only shows up in failure output. + + An optional fourth argument can be used to supply a different + function, of the form "find(line, output), to use when searching + for lines in the output. + """ + if find is None: + def find(o, i): + try: + return o.index(i) + except ValueError: + return None + + if is_List(output): + output = os.newline.join(output) + + if find(output, input) is None: + if title is None: + title = 'output' + print 'Missing expected input from %s:' % title + print input + print self.banner(title + ' ') + print output + self.fail_test() + def must_contain_all_lines(self, output, lines, title=None, find=None): """Ensures that the specified output string (first argument) contains all of the specified lines (second argument). diff --git a/test/SWIG/recursive-includes-cpp.py b/test/SWIG/recursive-includes-cpp.py new file mode 100644 index 0000000..364bd73 --- /dev/null +++ b/test/SWIG/recursive-includes-cpp.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify that SWIG include directives produce the correct dependencies +in cases of recursive inclusion. +""" + +import os +import TestSCons +from SCons.Defaults import DefaultEnvironment + +DefaultEnvironment( tools = [ 'swig' ] ) + +test = TestSCons.TestSCons() + +# Check for prerequisites of this test. +for pre_req in ['swig', 'python']: + if not test.where_is(pre_req): + test.skip_test('Can not find installed "' + pre_req + '", skipping test.%s' % os.linesep) + +test.write("recursive.h", """\ +/* An empty header file. */ +""") + +test.write("main.h", """\ +#include "recursive.h" +""") + +test.write("main.c", """\ +#include "main.h" +""") + +test.write("mod.i", """\ +%module mod + +%include "main.h" + +#include "main.h" +""") + +test.write('SConstruct', """\ +import distutils.sysconfig + +DefaultEnvironment( tools = [ 'swig' ] ) + +env = Environment( + SWIGFLAGS = [ + '-python' + ], + CPPPATH = [ + distutils.sysconfig.get_python_inc() + ], + SHLIBPREFIX = "" +) + +env.SharedLibrary( + 'mod.so', + [ + "mod.i", + "main.c", + ] +) +""") + +expectMain = """\ ++-main.os + +-main.c + +-main.h + +-recursive.h""" + +expectMod = """\ ++-mod_wrap.os + +-mod_wrap.c + | +-mod.i + | +-main.h + | +-recursive.h""" + +# Validate that the recursive dependencies are found with SWIG scanning first. +test.run( arguments = '--tree=all mod_wrap.os main.os' ) + +test.must_contain_all( test.stdout(), expectMain ) +test.must_contain_all( test.stdout(), expectMod ) + +# Validate that the recursive dependencies are found consistently. +test.run( arguments = '--tree=all main.os mod_wrap.os' ) + +test.must_contain_all( test.stdout(), expectMain ) +test.must_contain_all( test.stdout(), expectMod ) + +test.run() +test.up_to_date() + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: -- cgit v0.12 From b27b2316842dfa291feef332c80f676fd097d809 Mon Sep 17 00:00:00 2001 From: William Blevins Date: Sun, 17 May 2015 19:57:44 -0400 Subject: Issue 2264: Added cross-language scanner support. --- src/engine/SCons/Defaults.py | 2 +- src/engine/SCons/Executor.py | 26 ++++++---------------- src/engine/SCons/Node/__init__.py | 26 +++++++++++++--------- src/engine/SCons/Scanner/SWIG.py | 45 +++++++++++++++++++++++++++++++++++++++ src/engine/SCons/Tool/__init__.py | 7 ++++++ src/engine/SCons/Tool/swig.py | 6 ------ 6 files changed, 75 insertions(+), 37 deletions(-) create mode 100644 src/engine/SCons/Scanner/SWIG.py diff --git a/src/engine/SCons/Defaults.py b/src/engine/SCons/Defaults.py index 6500443..3e37fa5 100644 --- a/src/engine/SCons/Defaults.py +++ b/src/engine/SCons/Defaults.py @@ -484,7 +484,7 @@ class Variable_Method_Caller(object): ConstructionEnvironment = { 'BUILDERS' : {}, - 'SCANNERS' : [], + 'SCANNERS' : [ SCons.Tool.SourceFileScanner ], 'CONFIGUREDIR' : '#/.sconf_temp', 'CONFIGURELOG' : '#/config.log', 'CPPSUFFIXES' : SCons.Tool.CSuffixes, diff --git a/src/engine/SCons/Executor.py b/src/engine/SCons/Executor.py index 98ed758..59e57e3 100644 --- a/src/engine/SCons/Executor.py +++ b/src/engine/SCons/Executor.py @@ -486,29 +486,15 @@ class Executor(object): each individual target, which is a hell of a lot more efficient. """ env = self.get_build_env() + path = self.get_build_scanner_path + kw = self.get_kw() # TODO(batch): scan by batches) deps = [] - if scanner: - for node in node_list: - node.disambiguate() - s = scanner.select(node) - if not s: - continue - path = self.get_build_scanner_path(s) - deps.extend(node.get_implicit_deps(env, s, path)) - else: - kw = self.get_kw() - for node in node_list: - node.disambiguate() - scanner = node.get_env_scanner(env, kw) - if not scanner: - continue - scanner = scanner.select(node) - if not scanner: - continue - path = self.get_build_scanner_path(scanner) - deps.extend(node.get_implicit_deps(env, scanner, path)) + + for node in node_list: + node.disambiguate() + deps.extend(node.get_implicit_deps(env, scanner, path, kw)) deps.extend(self.get_implicit_deps()) diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index f2d37c2..5721442 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -916,32 +916,38 @@ class Node(object): """ return [] - def get_implicit_deps(self, env, scanner, path): + def get_implicit_deps(self, env, scanner, path, kw = {}): """Return a list of implicit dependencies for this node. This method exists to handle recursive invocation of the scanner on the implicit dependencies returned by the scanner, if the scanner's recursive flag says that we should. """ - if not scanner: - return [] - - # Give the scanner a chance to select a more specific scanner - # for this Node. - #scanner = scanner.select(self) - nodes = [self] seen = {} seen[self] = 1 deps = [] while nodes: n = nodes.pop(0) - d = [x for x in n.get_found_includes(env, scanner, path) if x not in seen] + + if not scanner: + s = n.get_env_scanner(env, kw) + if s: + s = s.select(n) + else: + s = scanner.select(n) + + if not s: + continue + + p = path(s) + + d = [x for x in n.get_found_includes(env, s, p) if x not in seen] if d: deps.extend(d) for n in d: seen[n] = 1 - nodes.extend(scanner.recurse_nodes(d)) + nodes.extend(s.recurse_nodes(d)) return deps diff --git a/src/engine/SCons/Scanner/SWIG.py b/src/engine/SCons/Scanner/SWIG.py new file mode 100644 index 0000000..2650e4b --- /dev/null +++ b/src/engine/SCons/Scanner/SWIG.py @@ -0,0 +1,45 @@ +"""SCons.Scanner.SWIG + +This module implements the dependency scanner for SWIG code. + +""" + +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import SCons.Scanner + +SWIGSuffixes = [ '.i' ] + +def SWIGScanner(): + expr = '^[ \t]*%[ \t]*(?:include|import|extern)[ \t]*(<|"?)([^>\s"]+)(?:>|"?)' + scanner = SCons.Scanner.ClassicCPP("SWIGScanner", ".i", "SWIGPATH", expr) + return scanner + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py index efd2e33..6002d72 100644 --- a/src/engine/SCons/Tool/__init__.py +++ b/src/engine/SCons/Tool/__init__.py @@ -51,6 +51,7 @@ import SCons.Scanner.C import SCons.Scanner.D import SCons.Scanner.LaTeX import SCons.Scanner.Prog +import SCons.Scanner.SWIG DefaultToolpath=[] @@ -60,6 +61,7 @@ LaTeXScanner = SCons.Scanner.LaTeX.LaTeXScanner() PDFLaTeXScanner = SCons.Scanner.LaTeX.PDFLaTeXScanner() ProgramScanner = SCons.Scanner.Prog.ProgramScanner() SourceFileScanner = SCons.Scanner.Base({}, name='SourceFileScanner') +SWIGScanner = SCons.Scanner.SWIG.SWIGScanner() CSuffixes = [".c", ".C", ".cxx", ".cpp", ".c++", ".cc", ".h", ".H", ".hxx", ".hpp", ".hh", @@ -73,12 +75,17 @@ IDLSuffixes = [".idl", ".IDL"] LaTeXSuffixes = [".tex", ".ltx", ".latex"] +SWIGSuffixes = ['.i'] + for suffix in CSuffixes: SourceFileScanner.add_scanner(suffix, CScanner) for suffix in DSuffixes: SourceFileScanner.add_scanner(suffix, DScanner) +for suffix in SWIGSuffixes: + SourceFileScanner.add_scanner(suffix, SWIGScanner) + # FIXME: what should be done here? Two scanners scan the same extensions, # but look for different files, e.g., "picture.eps" vs. "picture.pdf". # The builders for DVI and PDF explicitly reference their scanners diff --git a/src/engine/SCons/Tool/swig.py b/src/engine/SCons/Tool/swig.py index a315182..959d5fe 100644 --- a/src/engine/SCons/Tool/swig.py +++ b/src/engine/SCons/Tool/swig.py @@ -39,7 +39,6 @@ import subprocess import SCons.Action import SCons.Defaults -import SCons.Scanner import SCons.Tool import SCons.Util import SCons.Node @@ -173,11 +172,6 @@ def generate(env): env['_SWIGINCFLAGS'] = '$( ${_concat(SWIGINCPREFIX, SWIGPATH, SWIGINCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)' env['SWIGCOM'] = '$SWIG -o $TARGET ${_SWIGOUTDIR} ${_SWIGINCFLAGS} $SWIGFLAGS $SOURCES' - expr = '^[ \t]*%[ \t]*(?:include|import|extern)[ \t]*(<|"?)([^>\s"]+)(?:>|"?)' - scanner = SCons.Scanner.ClassicCPP("SWIGScan", ".i", "SWIGPATH", expr) - - env.Append(SCANNERS = scanner) - def exists(env): swig = env.get('SWIG') or env.Detect(['swig']) return swig -- cgit v0.12 From 279caec8f29b92cc569be83eb7b0c7a271136ad4 Mon Sep 17 00:00:00 2001 From: William Blevins Date: Sun, 17 May 2015 23:38:23 -0400 Subject: Issue 2264: Updated tests to reflect Node changes. --- src/engine/SCons/ExecutorTests.py | 4 ++- src/engine/SCons/Node/NodeTests.py | 19 ++++++++----- test/Fortran/FORTRANSUFFIXES.py | 56 +++++++++++++++++++------------------- test/QT/manual.py | 6 ++-- test/Scanner/exception.py | 14 +++++----- test/Scanner/generated.py | 1 + 6 files changed, 55 insertions(+), 45 deletions(-) diff --git a/src/engine/SCons/ExecutorTests.py b/src/engine/SCons/ExecutorTests.py index 9df0b2d..f390319 100644 --- a/src/engine/SCons/ExecutorTests.py +++ b/src/engine/SCons/ExecutorTests.py @@ -83,7 +83,9 @@ class MyNode(object): executor(self) def get_env_scanner(self, env, kw): return MyScanner('dep-') - def get_implicit_deps(self, env, scanner, path): + def get_implicit_deps(self, env, scanner, path, kw={}): + if not scanner: + scanner = self.get_env_scanner(env, kw) return [scanner.prefix + str(self)] def add_to_implicit(self, deps): self.implicit.extend(deps) diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py index a6471b4..4639cf9 100644 --- a/src/engine/SCons/Node/NodeTests.py +++ b/src/engine/SCons/Node/NodeTests.py @@ -132,7 +132,12 @@ class Environment(object): def get_factory(self, factory): return factory or MyNode def get_scanner(self, scanner_key): - return self._dict['SCANNERS'][0] + try: + return self._dict['SCANNERS'][0] + except: + pass + + return [] class Builder(object): def __init__(self, env=None, is_explicit=1): @@ -185,7 +190,7 @@ class Scanner(object): def __call__(self, node): self.called = 1 return node.GetTag('found_includes') - def path(self, env, dir, target=None, source=None): + def path(self, env, dir=None, target=None, source=None, kw={}): return () def select(self, node): return self @@ -928,7 +933,7 @@ class NodeTestCase(unittest.TestCase): node.Tag('found_includes', [d1, d2]) # Simple return of the found includes - deps = node.get_implicit_deps(env, s, target) + deps = node.get_implicit_deps(env, s, s.path) assert deps == [d1, d2], deps # By default, our fake scanner recurses @@ -938,24 +943,24 @@ class NodeTestCase(unittest.TestCase): d1.Tag('found_includes', [e, f]) d2.Tag('found_includes', [e, f]) f.Tag('found_includes', [g]) - deps = node.get_implicit_deps(env, s, target) + deps = node.get_implicit_deps(env, s, s.path) assert deps == [d1, d2, e, f, g], list(map(str, deps)) # Recursive scanning eliminates duplicates e.Tag('found_includes', [f]) - deps = node.get_implicit_deps(env, s, target) + deps = node.get_implicit_deps(env, s, s.path) assert deps == [d1, d2, e, f, g], list(map(str, deps)) # Scanner method can select specific nodes to recurse def no_fff(nodes): return [n for n in nodes if str(n)[0] != 'f'] s.recurse_nodes = no_fff - deps = node.get_implicit_deps(env, s, target) + deps = node.get_implicit_deps(env, s, s.path) assert deps == [d1, d2, e, f], list(map(str, deps)) # Scanner method can short-circuit recursing entirely s.recurse_nodes = lambda nodes: [] - deps = node.get_implicit_deps(env, s, target) + deps = node.get_implicit_deps(env, s, s.path) assert deps == [d1, d2], list(map(str, deps)) def test_get_env_scanner(self): diff --git a/test/Fortran/FORTRANSUFFIXES.py b/test/Fortran/FORTRANSUFFIXES.py index 583b71b..9673e6f 100644 --- a/test/Fortran/FORTRANSUFFIXES.py +++ b/test/Fortran/FORTRANSUFFIXES.py @@ -56,51 +56,51 @@ env = Environment(FORTRANPATH = ['.'], env.Append(FORTRANSUFFIXES = ['.x']) env.Object(target = 'test1', source = 'test1.f') env.InstallAs('test1_f', 'test1.f') -env.InstallAs('test1_h', 'test1.h') env.InstallAs('test1_x', 'test1.x') +env.InstallAs('test2_f', 'test2.f') """ % locals()) test.write('test1.f', """\ test1.f 1 - INCLUDE 'test1.h' + INCLUDE 'test2.f' INCLUDE 'test1.x' """) -test.write('test1.h', """\ - test1.h 1 - INCLUDE 'foo.h' +test.write('test2.f', """\ + test2.f 1 + INCLUDE 'foo.f' """) test.write('test1.x', """\ test1.x 1 - INCLUDE 'foo.h' + INCLUDE 'foo.f' """) -test.write('foo.h', """\ - foo.h 1 +test.write('foo.f', """\ + foo.f 1 """) expect = test.wrap_stdout("""\ %(_python_)s myfc.py test1.o test1.f Install file: "test1.f" as "test1_f" -Install file: "test1.h" as "test1_h" Install file: "test1.x" as "test1_x" +Install file: "test2.f" as "test2_f" """ % locals()) test.run(arguments='.', stdout=expect) test.must_match('test1.o', """\ test1.f 1 - test1.h 1 - foo.h 1 + test2.f 1 + foo.f 1 test1.x 1 - foo.h 1 + foo.f 1 """) test.up_to_date(arguments='.') -test.write('foo.h', """\ - foo.h 2 +test.write('foo.f', """\ + foo.f 2 """) expect = test.wrap_stdout("""\ @@ -111,17 +111,17 @@ test.run(arguments='.', stdout=expect) test.must_match('test1.o', """\ test1.f 1 - test1.h 1 - foo.h 2 + test2.f 1 + foo.f 2 test1.x 1 - foo.h 2 + foo.f 2 """) test.up_to_date(arguments='.') test.write('test1.x', """\ test1.x 2 - INCLUDE 'foo.h' + INCLUDE 'foo.f' """) expect = test.wrap_stdout("""\ @@ -133,32 +133,32 @@ test.run(arguments='.', stdout=expect) test.must_match('test1.o', """\ test1.f 1 - test1.h 1 - foo.h 2 + test2.f 1 + foo.f 2 test1.x 2 - foo.h 2 + foo.f 2 """) test.up_to_date(arguments='.') -test.write('test1.h', """\ - test1.h 2 - INCLUDE 'foo.h' +test.write('test2.f', """\ + test2.f 2 + INCLUDE 'foo.f' """) expect = test.wrap_stdout("""\ %(_python_)s myfc.py test1.o test1.f -Install file: "test1.h" as "test1_h" +Install file: "test2.f" as "test2_f" """ % locals()) test.run(arguments='.', stdout=expect) test.must_match('test1.o', """\ test1.f 1 - test1.h 2 - foo.h 2 + test2.f 2 + foo.f 2 test1.x 2 - foo.h 2 + foo.f 2 """) test.up_to_date(arguments='.') diff --git a/test/QT/manual.py b/test/QT/manual.py index ff38f32..d911fb3 100644 --- a/test/QT/manual.py +++ b/test/QT/manual.py @@ -46,13 +46,15 @@ sources = ['aaa.cpp', 'bbb.cpp', 'ddd.cpp', 'eee.cpp', 'main.cpp'] # normal invocation sources.append(env.Moc('include/aaa.h')) -env.Moc('bbb.cpp') +moc = env.Moc('bbb.cpp') +env.Ignore( moc, moc ) sources.extend(env.Uic('ui/ccc.ui')[1:]) # manual target specification sources.append(env.Moc('moc-ddd.cpp', 'include/ddd.h', QT_MOCHPREFIX='')) # Watch out ! -env.Moc('moc_eee.cpp', 'eee.cpp') +moc = env.Moc('moc_eee.cpp', 'eee.cpp') +env.Ignore( moc, moc ) sources.extend(env.Uic(['include/uic_fff.hpp', 'fff.cpp', 'fff.moc.cpp'], 'ui/fff.ui')[1:]) diff --git a/test/Scanner/exception.py b/test/Scanner/exception.py index 1a14152..de0a795 100644 --- a/test/Scanner/exception.py +++ b/test/Scanner/exception.py @@ -83,23 +83,23 @@ env.Cat('bar', bar_in) test.write('foo.k', """foo.k 1 line 1 -include xxx -include yyy +include xxx.k +include yyy.k foo.k 1 line 4 """) test.write('bar.in', -"""include yyy +"""include yyy.k bar.in 1 line 2 bar.in 1 line 3 -include zzz +include zzz.k """) -test.write('xxx', "xxx 1\n") +test.write('xxx.k', "xxx 1\n") -test.write('yyy', "exception yyy 1\n") +test.write('yyy.k', "exception yyy 1\n") -test.write('zzz', "zzz 1\n") +test.write('zzz.k', "zzz 1\n") test.run(arguments = '.', status = 2, diff --git a/test/Scanner/generated.py b/test/Scanner/generated.py index 845111c..b41c7c8 100644 --- a/test/Scanner/generated.py +++ b/test/Scanner/generated.py @@ -338,6 +338,7 @@ class CScannerCounter(object): import SCons.Tool MyCScanner = CScannerCounter(SCons.Script.CScanner) SCons.Tool.SourceFileScanner.add_scanner('.c', MyCScanner) +SCons.Tool.SourceFileScanner.add_scanner('.h', MyCScanner) env = Environment(CPPPATH = ".") l = env.StaticLibrary("g", Split("libg_1.c libg_2.c libg_3.c")) -- cgit v0.12 From 5260437c85052289702664c6a1025202eaf7111a Mon Sep 17 00:00:00 2001 From: William Blevins Date: Mon, 29 Jun 2015 16:12:02 -0400 Subject: Issue 2264: Corrected comment description of new output validation function. --- QMTest/TestCommon.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/QMTest/TestCommon.py b/QMTest/TestCommon.py index 275d4f2..c4a5373 100644 --- a/QMTest/TestCommon.py +++ b/QMTest/TestCommon.py @@ -36,7 +36,7 @@ provided by the TestCommon class: test.must_contain('file', 'required text\n') - test.must_contain_all(output, lines, ['title', find]) + test.must_contain_all(output, input, ['title', find]) test.must_contain_all_lines(output, lines, ['title', find]) -- cgit v0.12 From e5ac090e378fd5cda31dd70f762ea2792eed7dc7 Mon Sep 17 00:00:00 2001 From: William Blevins Date: Mon, 29 Jun 2015 23:32:45 -0400 Subject: Issue 2264: Updated behaviour when scanning included dependencies for nodes without scanner_key mappings. --- src/engine/SCons/Node/NodeTests.py | 2 ++ src/engine/SCons/Node/__init__.py | 63 +++++++++++++++++++++++++++----------- test/Scanner/exception.py | 14 ++++----- 3 files changed, 54 insertions(+), 25 deletions(-) diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py index 4639cf9..1478419 100644 --- a/src/engine/SCons/Node/NodeTests.py +++ b/src/engine/SCons/Node/NodeTests.py @@ -121,6 +121,8 @@ class Environment(object): self._dict.update(kw) def __getitem__(self, key): return self._dict[key] + def get(self, key, default = None): + return self._dict.get(key, default) def Dictionary(self, *args): return {} def Override(self, overrides): diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index 5721442..64a513b 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -916,7 +916,7 @@ class Node(object): """ return [] - def get_implicit_deps(self, env, scanner, path, kw = {}): + def get_implicit_deps(self, env, initial_scanner, path_func, kw = {}): """Return a list of implicit dependencies for this node. This method exists to handle recursive invocation of the scanner @@ -926,31 +926,58 @@ class Node(object): nodes = [self] seen = {} seen[self] = 1 - deps = [] + dependencies = [] + + root_node_scanner = self._get_scanner(env, initial_scanner, None, kw) + while nodes: - n = nodes.pop(0) + node = nodes.pop(0) - if not scanner: - s = n.get_env_scanner(env, kw) - if s: - s = s.select(n) - else: - s = scanner.select(n) + scanner = node._get_scanner(env, initial_scanner, root_node_scanner, kw) - if not s: + if not scanner: continue - p = path(s) + path = path_func(scanner) - d = [x for x in n.get_found_includes(env, s, p) if x not in seen] - if d: - deps.extend(d) - for n in d: - seen[n] = 1 - nodes.extend(s.recurse_nodes(d)) + included_deps = [x for x in node.get_found_includes(env, scanner, path) if x not in seen] + if included_deps: + dependencies.extend(included_deps) + for dep in included_deps: + seen[dep] = 1 + nodes.extend(scanner.recurse_nodes(included_deps)) - return deps + return dependencies + def _get_scanner(self, env, initial_scanner, root_node_scanner, kw): + if not initial_scanner: + # handle implicit scanner case + scanner = self.get_env_scanner(env, kw) + if scanner: + scanner = scanner.select(self) + else: + # handle explicit scanner case + scanner = initial_scanner.select(self) + + if not scanner: + # no scanner could be found for the given node's scanner key; + # thus, make an attempt at using a default. + + # check for a user specified scanner hint + scanner = env.get( 'SCANNER_HINT' ) + + if scanner: + # Ensure scanner hint returned a valid Scanner object + if not instanceof( scanner, SCons.Scanner.Base ): + raise SCons.Error.UserError( + 'SCANNER_HINT object must be instance of ' + str(SCons.Scanner.Base) + ) + else: + # no scanner hint, so do best guess (IE. return the root's scanner). + scanner = root_node_scanner + + return scanner + def get_env_scanner(self, env, kw={}): return env.get_scanner(self.scanner_key()) diff --git a/test/Scanner/exception.py b/test/Scanner/exception.py index de0a795..1a14152 100644 --- a/test/Scanner/exception.py +++ b/test/Scanner/exception.py @@ -83,23 +83,23 @@ env.Cat('bar', bar_in) test.write('foo.k', """foo.k 1 line 1 -include xxx.k -include yyy.k +include xxx +include yyy foo.k 1 line 4 """) test.write('bar.in', -"""include yyy.k +"""include yyy bar.in 1 line 2 bar.in 1 line 3 -include zzz.k +include zzz """) -test.write('xxx.k', "xxx 1\n") +test.write('xxx', "xxx 1\n") -test.write('yyy.k', "exception yyy 1\n") +test.write('yyy', "exception yyy 1\n") -test.write('zzz.k', "zzz 1\n") +test.write('zzz', "zzz 1\n") test.run(arguments = '.', status = 2, -- cgit v0.12 From 829492d37c7b85e22c169e1171265abdf4841af6 Mon Sep 17 00:00:00 2001 From: William Blevins Date: Tue, 30 Jun 2015 01:12:48 -0400 Subject: Issue 2264: Added test for SCANNER_HINT support, plus bug fixes. --- src/engine/SCons/Node/__init__.py | 4 +- test/Scanner/ScannerHint.py | 119 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 test/Scanner/ScannerHint.py diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index 64a513b..d709f11 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -968,8 +968,8 @@ class Node(object): if scanner: # Ensure scanner hint returned a valid Scanner object - if not instanceof( scanner, SCons.Scanner.Base ): - raise SCons.Error.UserError( + if not isinstance( scanner, SCons.Scanner.Base ): + raise SCons.Errors.UserError( 'SCANNER_HINT object must be instance of ' + str(SCons.Scanner.Base) ) else: diff --git a/test/Scanner/ScannerHint.py b/test/Scanner/ScannerHint.py new file mode 100644 index 0000000..b12b847 --- /dev/null +++ b/test/Scanner/ScannerHint.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import TestSCons + +_python_ = TestSCons._python_ + +test = TestSCons.TestSCons() + +# Test behavior of Scanners when evaluating implicit dependencies +# for nodes that do not have mappings from their scanner_key +# to a scanner instance + +test.write('SConstruct', """ +import re + +include_re = re.compile(r'^include\s+(\S+)$', re.M) + +def scan(node, env, scanpaths, arg): + contents = node.get_text_contents() + includes = include_re.findall(contents) + return includes + +def kfile_scan(node, env, scanpaths, arg): + print 'kscan: ' + str(node) + return scan(node, env, scanpaths, arg) + +def k2file_scan(node, env, scanpaths, arg): + print 'k2scan: ' + str(node) + return scan(node, env, scanpaths, arg) + +kscan = Scanner(name = 'kfile', + function = kfile_scan, + argument = None, + skeys = ['.k'], + recursive = True) + +k2scan = Scanner(name = 'k2', + function = k2file_scan, + argument = None, + skeys = ['.k2']) + +env1 = Environment() +env1.Append(SCANNERS = [ kscan, k2scan ] ) +env1.Command( 'k', 'foo.k', Copy( '$TARGET', '$SOURCE' ) ) + +env2 = env1.Clone() +env2.Replace(SCANNER_HINT = k2scan) +env2.Command( 'k2', 'foo.k', Copy( '$TARGET', '$SOURCE' ) ) + +env3 = env1.Clone() +env3.Replace(SCANNER_HINT = 'raise') +env3.Command( 'raise', 'foo.k', Copy( '$TARGET', '$SOURCE' ) ) +""") + +test.write('foo.k', +"""foo.k 1 line 1 +include xxx.k +include yyy +foo.k 1 line 4 +""") + +test.write('xxx.k', "xxx.k 1\n") +test.write('yyy', "yyy 1\n") +test.write('yyy.k2', "yyy.k2 1\n") + +expected_stdout = test.wrap_stdout("""\ +kscan: foo.k +kscan: xxx.k +kscan: yyy +Copy("k", "foo.k") +kscan: foo.k +kscan: xxx.k +k2scan: yyy +Copy("k2", "foo.k") +""") + +test.run(arguments='k k2', stdout=expected_stdout) + +expected_stdout = test.wrap_stdout("""\ +kscan: foo.k +kscan: xxx.k +""", error = True) + +expected_stderr = """\ +scons: *** [raise] SCANNER_HINT object must be instance of +""" + +test.run(arguments='raise', stderr=expected_stderr, stdout=expected_stdout, status = 2) +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: -- cgit v0.12 From 27ae977d3fa04e29166e172fa64f7b5439d9f0c8 Mon Sep 17 00:00:00 2001 From: William Blevins Date: Fri, 7 Aug 2015 00:25:40 -0400 Subject: Issue 2264: Removed redundant SCANNER_HINT for preference of SCANNERS. Also possibly SCons.Tool.SourceFileScanner (global only). Updated test to reflect with case using SCANNERS plus root node default. --- src/engine/SCons/Node/__init__.py | 14 +--- test/Scanner/CrossLanguageNoExtension.py | 110 ++++++++++++++++++++++++++++ test/Scanner/ScannerHint.py | 119 ------------------------------- 3 files changed, 111 insertions(+), 132 deletions(-) create mode 100644 test/Scanner/CrossLanguageNoExtension.py delete mode 100644 test/Scanner/ScannerHint.py diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index d709f11..5aa9600 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -962,19 +962,7 @@ class Node(object): if not scanner: # no scanner could be found for the given node's scanner key; # thus, make an attempt at using a default. - - # check for a user specified scanner hint - scanner = env.get( 'SCANNER_HINT' ) - - if scanner: - # Ensure scanner hint returned a valid Scanner object - if not isinstance( scanner, SCons.Scanner.Base ): - raise SCons.Errors.UserError( - 'SCANNER_HINT object must be instance of ' + str(SCons.Scanner.Base) - ) - else: - # no scanner hint, so do best guess (IE. return the root's scanner). - scanner = root_node_scanner + scanner = root_node_scanner return scanner diff --git a/test/Scanner/CrossLanguageNoExtension.py b/test/Scanner/CrossLanguageNoExtension.py new file mode 100644 index 0000000..5bf205f --- /dev/null +++ b/test/Scanner/CrossLanguageNoExtension.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import TestSCons + +_python_ = TestSCons._python_ + +test = TestSCons.TestSCons() + +# Test behavior of Scanners when evaluating implicit dependencies +# for nodes that do not have mappings from their scanner_key +# to a scanner instance + +test.write('SConstruct', """ +import re + +include_re = re.compile(r'^include\s+(\S+)$', re.M) + +def scan(node, env, scanpaths, arg): + contents = node.get_text_contents() + includes = include_re.findall(contents) + return includes + +def kfile_scan(node, env, scanpaths, arg): + print 'kscan: ' + str(node) + return scan(node, env, scanpaths, arg) + +def k2file_scan(node, env, scanpaths, arg): + print 'k2scan: ' + str(node) + return scan(node, env, scanpaths, arg) + +kscan = Scanner(name = 'kfile', + function = kfile_scan, + argument = None, + skeys = ['.k'], + recursive = True) + +k2scan = Scanner(name = 'k2', + function = k2file_scan, + argument = None, + skeys = ['.k2']) + +k2scan2 = Scanner(name = 'k2', + function = k2file_scan, + argument = None, + skeys = ['']) + +env1 = Environment() +env1.Append(SCANNERS = [ kscan, k2scan ] ) +env1.Command( 'k', 'foo.k', Copy( '$TARGET', '$SOURCE' ) ) + +env2 = env1.Clone() +env2.Append(SCANNERS = [ k2scan2 ] ) +env2.Command( 'k2', 'foo.k', Copy( '$TARGET', '$SOURCE' ) ) +""") + +test.write('foo.k', +"""foo.k 1 line 1 +include xxx.k +include yyy +foo.k 1 line 4 +""") + +test.write('xxx.k', "xxx.k 1\n") +test.write('yyy', "yyy 1\n") +test.write('yyy.k2', "yyy.k2 1\n") + +expected_stdout = test.wrap_stdout("""\ +kscan: foo.k +kscan: xxx.k +kscan: yyy +Copy("k", "foo.k") +kscan: foo.k +kscan: xxx.k +k2scan: yyy +Copy("k2", "foo.k") +""") + +test.run(arguments='k k2', stdout=expected_stdout) + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Scanner/ScannerHint.py b/test/Scanner/ScannerHint.py deleted file mode 100644 index b12b847..0000000 --- a/test/Scanner/ScannerHint.py +++ /dev/null @@ -1,119 +0,0 @@ -#!/usr/bin/env python -# -# __COPYRIGHT__ -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - -import TestSCons - -_python_ = TestSCons._python_ - -test = TestSCons.TestSCons() - -# Test behavior of Scanners when evaluating implicit dependencies -# for nodes that do not have mappings from their scanner_key -# to a scanner instance - -test.write('SConstruct', """ -import re - -include_re = re.compile(r'^include\s+(\S+)$', re.M) - -def scan(node, env, scanpaths, arg): - contents = node.get_text_contents() - includes = include_re.findall(contents) - return includes - -def kfile_scan(node, env, scanpaths, arg): - print 'kscan: ' + str(node) - return scan(node, env, scanpaths, arg) - -def k2file_scan(node, env, scanpaths, arg): - print 'k2scan: ' + str(node) - return scan(node, env, scanpaths, arg) - -kscan = Scanner(name = 'kfile', - function = kfile_scan, - argument = None, - skeys = ['.k'], - recursive = True) - -k2scan = Scanner(name = 'k2', - function = k2file_scan, - argument = None, - skeys = ['.k2']) - -env1 = Environment() -env1.Append(SCANNERS = [ kscan, k2scan ] ) -env1.Command( 'k', 'foo.k', Copy( '$TARGET', '$SOURCE' ) ) - -env2 = env1.Clone() -env2.Replace(SCANNER_HINT = k2scan) -env2.Command( 'k2', 'foo.k', Copy( '$TARGET', '$SOURCE' ) ) - -env3 = env1.Clone() -env3.Replace(SCANNER_HINT = 'raise') -env3.Command( 'raise', 'foo.k', Copy( '$TARGET', '$SOURCE' ) ) -""") - -test.write('foo.k', -"""foo.k 1 line 1 -include xxx.k -include yyy -foo.k 1 line 4 -""") - -test.write('xxx.k', "xxx.k 1\n") -test.write('yyy', "yyy 1\n") -test.write('yyy.k2', "yyy.k2 1\n") - -expected_stdout = test.wrap_stdout("""\ -kscan: foo.k -kscan: xxx.k -kscan: yyy -Copy("k", "foo.k") -kscan: foo.k -kscan: xxx.k -k2scan: yyy -Copy("k2", "foo.k") -""") - -test.run(arguments='k k2', stdout=expected_stdout) - -expected_stdout = test.wrap_stdout("""\ -kscan: foo.k -kscan: xxx.k -""", error = True) - -expected_stderr = """\ -scons: *** [raise] SCANNER_HINT object must be instance of -""" - -test.run(arguments='raise', stderr=expected_stderr, stdout=expected_stdout, status = 2) -test.pass_test() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: -- cgit v0.12 From 352c0ef0203f0f09de077d1662f95d896f08ff1c Mon Sep 17 00:00:00 2001 From: William Blevins Date: Fri, 7 Aug 2015 10:29:05 -0400 Subject: Issue 2264: removed implicit dependency recursion from install targets. Resolves performance issue with implicit dependencies (without builders) reinstalling. Example (C++): A.h includes B.h and both are installed somewhere. B.h is updated so both A.h and B.h would be reinstalled because B.h changed. A.h didn't need to be reinstalled for obvious reasons. Background info: this was already an issue for any scanner added to SCANNERS environment. Did not occur originally because default scanners not in SCANNERS environment. --- src/engine/SCons/Tool/install.py | 1 + test/IDL/IDLSUFFIXES.py | 5 ----- test/explain/basic.py | 25 +++++++++++-------------- test/explain/save-info.py | 7 ++----- 4 files changed, 14 insertions(+), 24 deletions(-) diff --git a/src/engine/SCons/Tool/install.py b/src/engine/SCons/Tool/install.py index 9f2e937..847af34 100644 --- a/src/engine/SCons/Tool/install.py +++ b/src/engine/SCons/Tool/install.py @@ -447,6 +447,7 @@ def generate(env): source_factory = env.fs.Entry, multi = 1, emitter = [ add_targets_to_INSTALLED_FILES, ], + source_scanner = SCons.Scanner.Base( {}, name = 'Install', recursive = False ), name = 'InstallBuilder') global BaseVersionedInstallBuilder diff --git a/test/IDL/IDLSUFFIXES.py b/test/IDL/IDLSUFFIXES.py index f71ceba..0a9a50c 100644 --- a/test/IDL/IDLSUFFIXES.py +++ b/test/IDL/IDLSUFFIXES.py @@ -60,11 +60,6 @@ test.up_to_date(arguments='.') test.write('foo.h', "foo.h 2\n") -test.run(arguments='.', stdout=test.wrap_stdout("""\ -Install file: "foo.idl" as "foo_idl" -Install file: "foo.x" as "foo_x" -""")) - test.up_to_date(arguments='.') test.pass_test() diff --git a/test/explain/basic.py b/test/explain/basic.py index 5e31cfd..1072ac4 100644 --- a/test/explain/basic.py +++ b/test/explain/basic.py @@ -169,10 +169,18 @@ test.write(['src', 'file6.in'], "file6.in 1\n") test.write(['src', 'subdir', 'file7.in'], "subdir/file7.in 1\n") -args = '--debug=explain .' +args = '--debug=explain ..' expect = test.wrap_stdout("""\ +scons: building `%(inc_aaa)s' because it doesn't exist +Install file: "aaa" as "%(inc_aaa)s" +scons: building `%(inc_bbb_k)s' because it doesn't exist +Install file: "bbb.k" as "%(inc_bbb_k)s" +scons: building `%(inc_ddd)s' because it doesn't exist +Install file: "ddd" as "%(inc_ddd)s" +scons: building `%(inc_eee)s' because it doesn't exist +Install file: "eee.in" as "%(inc_eee)s" scons: building `file1' because it doesn't exist %(_python_)s %(cat_py)s file1 file1.in scons: building `file2' because it doesn't exist @@ -181,14 +189,6 @@ scons: building `file3' because it doesn't exist %(_python_)s %(cat_py)s file3 xxx yyy zzz scons: building `file4' because it doesn't exist %(_python_)s %(cat_py)s file4 - file4.in -scons: building `%(inc_aaa)s' because it doesn't exist -Install file: "aaa" as "%(inc_aaa)s" -scons: building `%(inc_ddd)s' because it doesn't exist -Install file: "ddd" as "%(inc_ddd)s" -scons: building `%(inc_eee)s' because it doesn't exist -Install file: "eee.in" as "%(inc_eee)s" -scons: building `%(inc_bbb_k)s' because it doesn't exist -Install file: "bbb.k" as "%(inc_bbb_k)s" scons: building `file5' because it doesn't exist %(_python_)s %(cat_py)s file5 file5.k scons: building `file6' because it doesn't exist @@ -236,6 +236,8 @@ test_value = '"second"' WriteInitialTest( locals() ) expect = test.wrap_stdout("""\ +scons: rebuilding `%(inc_bbb_k)s' because `bbb.k' changed +Install file: "bbb.k" as "%(inc_bbb_k)s" scons: rebuilding `file1' because `file1.in' changed %(_python_)s %(cat_py)s file1 file1.in scons: rebuilding `file2' because `yyy' changed @@ -244,11 +246,6 @@ scons: rebuilding `file3' because: `yyy' changed `zzz' changed %(_python_)s %(cat_py)s file3 xxx yyy zzz -scons: rebuilding `%(inc_bbb_k)s' because: - `%(inc_ddd)s' is no longer a dependency - `%(inc_eee)s' is no longer a dependency - `bbb.k' changed -Install file: "bbb.k" as "%(inc_bbb_k)s" scons: rebuilding `file5' because `%(inc_bbb_k)s' changed %(_python_)s %(cat_py)s file5 file5.k scons: rebuilding `file6' because AlwaysBuild() is specified diff --git a/test/explain/save-info.py b/test/explain/save-info.py index d2ffc7d..af4c3f5 100644 --- a/test/explain/save-info.py +++ b/test/explain/save-info.py @@ -141,7 +141,7 @@ file5.k 1 line 4 test.write(['src', 'subdir', 'file6.in'], "subdir/file6.in 1\n") # -test.run(chdir='src', arguments='.') +test.run(chdir='src', arguments='..') test.must_match(['src', 'file1'], "file1.in 1\n") test.must_match(['src', 'file2'], """\ @@ -176,10 +176,7 @@ scons: rebuilding `file3' because: `yyy' changed `zzz' changed %(_python_)s %(cat_py)s file3 xxx yyy zzz -scons: rebuilding `%(inc_bbb_k)s' because: - `%(inc_ddd)s' is no longer a dependency - `%(inc_eee)s' is no longer a dependency - `bbb.k' changed +scons: rebuilding `%(inc_bbb_k)s' because `bbb.k' changed Install file: "bbb.k" as "%(inc_bbb_k)s" scons: rebuilding `file5' because `%(inc_bbb_k)s' changed %(_python_)s %(cat_py)s file5 file5.k -- cgit v0.12 From 04b306103a2c37b90f2d764112c0cb5527313849 Mon Sep 17 00:00:00 2001 From: William Blevins Date: Fri, 7 Aug 2015 18:04:38 -0400 Subject: Issue 2264: Update announcement and change logs. --- src/Announce.txt | 27 +++++++++++++++++++++++++++ src/CHANGES.txt | 6 ++++++ 2 files changed, 33 insertions(+) diff --git a/src/Announce.txt b/src/Announce.txt index f96e703..ab278ec 100644 --- a/src/Announce.txt +++ b/src/Announce.txt @@ -18,6 +18,33 @@ So that everyone using SCons can help each other learn how to use it more effectively, please go to http://scons.org/lists.php#users to sign up for the scons-users mailing list. +==============IMPORTANT NOTICE FOR NEXT VERSION V2.X.X========== + +PLEASE READ. CHANGES COMING IN NEXT MAJOR RELEASE V2.X.X + +We're enhancing implicit language scanning functionality to improve +correctness. SCons now honors scanner keys for implicit +dependencies and correctly changes scanner type (if necessary) when +traversing implicit dependency trees. This enhancement resolves +missing dependencies with built-in scanners including SWIG (#2264) +and QT: +* http://scons.tigris.org/issues/show_bug.cgi?id=2264 + +This enhancement broadens the horizon for handling heterogeneous +data flow environments (E.G. software builds): +* http://article.gmane.org/gmane.comp.programming.tools.scons.user/26596 + +Notes: +* SCons may find new (and correct) dependencies in cross-langauge contexts. +** Update may cause rebuilds, especially in heterogeneous data environments. +** Update may find previously missed dependencies errors (E.G. cycles). +*** Discovered in some QT test cases. +* SCons handles the SCANNERS variable differently. +** Previously, the Install builder would scan implicit dependencies for + a scanner found in SCANNERS (but not for built-in scanners), but now + the Install builder will not scan recursively regardless in order + to optimize Install behaviour and bring orthogonality to previous behaviour. + ==============IMPORTANT NOTICE FOR NEXT VERSION V2.4.0=========== PLEASE READ. CHANGES COMING IN NEXT MAJOR RELEASE V2.4.0 diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 977d00f..89bf7b5 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -6,6 +6,12 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER + From William Blevins: + - Added support for cross-language dependency scanning; + SCons now respects scanner keys for implicit dependencies. + - Resolved missing cross-language dependencies for + SWIG bindings (fixes #2264). + From Dirk Baechle: - Switched several core classes to using "slots", for reducing the overall memory consumption in large -- cgit v0.12