From 46aae9c7906a8638d90488bdd2f3c6c964bd5e8d Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Tue, 22 Oct 2019 09:51:51 -0500 Subject: Add Python scanner and tests This change adds a python scanner that allows consumers to take dependencies upon any packages imported by scripts that are run. It also adds tests to verify proper functionality of the scanner. --- src/engine/SCons/Scanner/Python.py | 156 ++++++++++++++++++ src/engine/SCons/Scanner/PythonTests.py | 271 ++++++++++++++++++++++++++++++++ 2 files changed, 427 insertions(+) create mode 100644 src/engine/SCons/Scanner/Python.py create mode 100644 src/engine/SCons/Scanner/PythonTests.py diff --git a/src/engine/SCons/Scanner/Python.py b/src/engine/SCons/Scanner/Python.py new file mode 100644 index 0000000..eddff0f --- /dev/null +++ b/src/engine/SCons/Scanner/Python.py @@ -0,0 +1,156 @@ +"""SCons.Scanner.Python + +This module implements the dependency scanner for Python code. + +One important note about the design is that this does not take any dependencies +upon packages or binaries in the Python installation unless they are listed in +PYTHONPATH. To do otherwise would have required code to determine where the +Python installation is, which is outside of the scope of a scanner like this. +If consumers want to pick up dependencies upon these packages, they must put +those directories in PYTHONPATH. + +""" + +# +# __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 itertools +import os +import re +import SCons.Scanner + +# Capture python "from a import b" and "import a" statements. +from_cre = re.compile('^\s*from\s+([^\s]+)\s+import\s+(.*)', re.M) +import_cre = re.compile('^\s*import\s+([^\s]+)', re.M) + + +def path_function(env, dir=None, target=None, source=None, argument=None): + """Retrieves a tuple with all search paths.""" + paths = env['ENV'].get('PYTHONPATH', '').split(os.pathsep) + if source: + paths.append(source[0].dir.abspath) + return tuple(paths) + + +def find_include_names(node): + """ + Scans the node for all imports. + + Returns a list of tuples. Each tuple has two elements: + 1. The main import (e.g. module, module.file, module.module2) + 2. Additional optional imports that could be functions or files + in the case of a "from X import Y" statement. In the case of a + normal "import" statement, this is None. + """ + text = node.get_text_contents() + all_matches = [] + matches = from_cre.findall(text) + if matches: + for match in matches: + imports = match[1].split(',') + all_matches.append((match[0], [i.strip() for i in imports])) + + matches = import_cre.findall(text) + if matches: + for match in matches: + all_matches.append((match, None)) + + return all_matches + + +def scan(node, env, path=()): + # cache the includes list in node so we only scan it once: + if node.includes is not None: + includes = node.includes + else: + includes = find_include_names(node) + # Intern the names of the include files. Saves some memory + # if the same header is included many times. + node.includes = list(map(SCons.Util.silent_intern, includes)) + + # XXX TODO: Sort? + nodes = [] + if callable(path): + path = path() + for module, imports in includes: + is_relative = module.startswith('.') + if is_relative: + # This is a relative include, so we must ignore PYTHONPATH. + module_lstripped = module.lstrip('.') + # One dot is current directory, two is parent, three is + # grandparent, etc. + num_parents = len(module) - len(module_lstripped) - 1 + current_dir = node.get_dir() + for i in itertools.repeat(None, num_parents): + current_dir = current_dir.up() + + search_paths = [current_dir.abspath] + search_string = module_lstripped + else: + search_paths = path + search_string = module + + module_components = search_string.split('.') + for search_path in search_paths: + candidate_path = os.path.join(search_path, *module_components) + # The import stored in "module" could refer to a directory or file. + import_dirs = [] + if os.path.isdir(candidate_path): + import_dirs = module_components + + # Because this resolved to a directory, there is a chance that + # additional imports (e.g. from module import A, B) could refer + # to files to import. + if imports: + for imp in imports: + file = os.path.join(candidate_path, imp + '.py') + if os.path.isfile(file): + nodes.append(file) + elif os.path.isfile(candidate_path + '.py'): + nodes.append(candidate_path + '.py') + import_dirs = module_components[:-1] + + # We can ignore imports because this resolved to a file. Any + # additional imports (e.g. from module.file import A, B) would + # only refer to functions in this file. + + # Take a dependency on all __init__.py files from all imported + # packages unless it's a relative import. If it's a relative + # import, we don't need to take the dependency because Python + # requires that all referenced packages have already been imported, + # which means that the dependency has already been established. + if import_dirs and not is_relative: + for i in range(len(import_dirs)): + init_components = module_components[:i+1] + ['__init__.py'] + init_path = os.path.join(search_path, *(init_components)) + if os.path.isfile(init_path): + nodes.append(init_path) + break + + return sorted(nodes) + + +PythonScanner = SCons.Scanner.Base(scan, name='PythonScanner', skeys=['.py'], + path_function=path_function, recursive=1) diff --git a/src/engine/SCons/Scanner/PythonTests.py b/src/engine/SCons/Scanner/PythonTests.py new file mode 100644 index 0000000..4db9215 --- /dev/null +++ b/src/engine/SCons/Scanner/PythonTests.py @@ -0,0 +1,271 @@ +# +# __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.compat + +import collections +import os +import unittest + +import TestCmd + +import SCons.Node.FS +import SCons.Scanner.Python + +test = TestCmd.TestCmd(workdir='') + +# This directory is a simple empty package. +test.subdir('simple_package') +test.write(['simple_package', '__init__.py'], '') +test.write(['simple_package', 'module.py'], '') + +# Two files that import from simple_package. +test.write('imports_simple_package.py', r""" +import simple_package +""") +test.write('import_simple_package_module.py', r""" +import simple_package.module +""") +test.write('from_import_simple_package_module.py', r""" +from simple_package import module +""") + +# This directory holds a script that imports another from the current dir. +test.subdir('curdir_reference') +test.write(['curdir_reference', 'script.py'], r""" +from . import helper +""") +test.write(['curdir_reference', 'helper.py'], r'') + +# Create the directory structure: +# imports_nested3.py +# nested1 +# |- __init__.py +# |- module.py +# |- nested2 +# | |- __init__.py +# | |- module.py +# | '- nested3 +# | |- __init__.py +# | |- imports_grandparent_module.py +# | |- imports_parent_module.py +# | |- imports_parent_then_submodule.py +# | '- module.py +# '- nested2a +# |- __init__.py +# '- module.py +# This is used for more advanced relative path test cases. +test.write('imports_nested3.py', r""" +import nested1.nested2.nested3 +""") +test.subdir('nested1', ['nested1', 'nested2'], ['nested1', 'nested2a'], + ['nested1', 'nested2', 'nested3']) +test.write(['nested1', '__init__.py'], r'') +test.write(['nested1', 'module.py'], r'') +test.write(['nested1', 'nested2', '__init__.py'], r'') +test.write(['nested1', 'nested2', 'module.py'], r'') +test.write(['nested1', 'nested2a', '__init__.py'], r'') +test.write(['nested1', 'nested2a', 'module.py'], r'') +test.write(['nested1', 'nested2', 'nested3', '__init__.py'], r'') +test.write(['nested1', 'nested2', 'nested3', + 'imports_grandparent_module.py'], r""" +from ... import module +""") +test.write(['nested1', 'nested2', 'nested3', 'imports_parent_module.py'], r""" +from .. import module +""") +test.write(['nested1', 'nested2', 'nested3', + 'imports_parent_then_submodule.py'], r""" +from ...nested2a import module +""") +test.write(['nested1', 'nested2', 'nested3', 'module.py'], r'') + +if os.path.normcase('foo') == os.path.normcase('FOO'): + my_normpath = os.path.normcase +else: + my_normpath = os.path.normpath + + +def deps_match(self, deps, headers): + global my_normpath + scanned = list(map(my_normpath, list(map(str, deps)))) + expect = list(map(my_normpath, headers)) + self.assertTrue(scanned == expect, + "expect %s != scanned %s" % (expect, scanned)) + + +# Copied from LaTeXTests.py. +class DummyEnvironment(collections.UserDict): + def __init__(self, **kw): + collections.UserDict.__init__(self) + self.data.update(kw) + self.fs = SCons.Node.FS.FS(test.workpath('')) + self['ENV'] = {} + + def Dictionary(self, *args): + return self.data + + def subst(self, strSubst, target=None, source=None, conv=None): + if strSubst[0] == '$': + return self.data[strSubst[1:]] + return strSubst + + def subst_list(self, strSubst, target=None, source=None, conv=None): + if strSubst[0] == '$': + return [self.data[strSubst[1:]]] + return [[strSubst]] + + def subst_path(self, path, target=None, source=None, conv=None): + if not isinstance(path, list): + path = [path] + return list(map(self.subst, path)) + + def get_calculator(self): + return None + + def get_factory(self, factory): + return factory or self.fs.File + + def Dir(self, filename): + return self.fs.Dir(filename) + + def File(self, filename): + return self.fs.File(filename) + + +class PythonScannerTestPythonPath(unittest.TestCase): + def runTest(self): + env = DummyEnvironment() + s = SCons.Scanner.Python.PythonScanner + env['ENV']['PYTHONPATH'] = test.workpath('') + path = s.path(env) + deps = s(env.File('imports_simple_package.py'), env, path) + files = ['simple_package/__init__.py'] + deps_match(self, deps, files) + + +class PythonScannerTestImportSimplePackage(unittest.TestCase): + def runTest(self): + env = DummyEnvironment() + s = SCons.Scanner.Python.PythonScanner + node = env.File('imports_simple_package.py') + path = s.path(env, source=[node]) + deps = s(node, env, path) + files = ['simple_package/__init__.py'] + deps_match(self, deps, files) + + +class PythonScannerTestImportSimplePackageModule(unittest.TestCase): + def runTest(self): + env = DummyEnvironment() + s = SCons.Scanner.Python.PythonScanner + node = env.File('import_simple_package_module.py') + path = s.path(env, source=[node]) + deps = s(node, env, path) + files = ['simple_package/__init__.py', 'simple_package/module.py'] + deps_match(self, deps, files) + + +class PythonScannerTestFromImportSimplePackageModule(unittest.TestCase): + def runTest(self): + env = DummyEnvironment() + s = SCons.Scanner.Python.PythonScanner + node = env.File('from_import_simple_package_module.py') + path = s.path(env, source=[node]) + deps = s(node, env, path) + files = ['simple_package/__init__.py', 'simple_package/module.py'] + deps_match(self, deps, files) + + +class PythonScannerTestCurdirReferenceScript(unittest.TestCase): + def runTest(self): + env = DummyEnvironment() + s = SCons.Scanner.Python.PythonScanner + node = env.Dir('curdir_reference').File('script.py') + path = s.path(env, source=[node]) + deps = s(node, env, path) + files = ['curdir_reference/helper.py'] + deps_match(self, deps, files) + + +class PythonScannerTestImportsNested3(unittest.TestCase): + def runTest(self): + env = DummyEnvironment() + s = SCons.Scanner.Python.PythonScanner + node = env.File('imports_nested3.py') + path = s.path(env, source=[node]) + deps = s(node, env, path) + files = ['nested1/__init__.py', 'nested1/nested2/__init__.py', + 'nested1/nested2/nested3/__init__.py'] + deps_match(self, deps, files) + + +class PythonScannerTestImportsGrandparentModule(unittest.TestCase): + def runTest(self): + env = DummyEnvironment() + s = SCons.Scanner.Python.PythonScanner + node = env.File( + 'nested1/nested2/nested3/imports_grandparent_module.py') + path = s.path(env, source=[node]) + deps = s(node, env, path) + # Note: there is some ambiguity here in what the scanner should return. + # Relative imports require that the referenced packages have already + # been imported. + files = ['nested1/module.py'] + deps_match(self, deps, files) + + +class PythonScannerTestImportsParentModule(unittest.TestCase): + def runTest(self): + env = DummyEnvironment() + s = SCons.Scanner.Python.PythonScanner + node = env.File( + 'nested1/nested2/nested3/imports_parent_module.py') + path = s.path(env, source=[node]) + deps = s(node, env, path) + files = ['nested1/nested2/module.py'] + deps_match(self, deps, files) + + +class PythonScannerTestImportsParentThenSubmodule(unittest.TestCase): + def runTest(self): + env = DummyEnvironment() + s = SCons.Scanner.Python.PythonScanner + node = env.File( + 'nested1/nested2/nested3/imports_parent_then_submodule.py') + path = s.path(env, source=[node]) + deps = s(node, env, path) + files = ['nested1/nested2a/module.py'] + deps_match(self, deps, files) + + +if __name__ == "__main__": + unittest.main() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: -- cgit v0.12 From 52f6c16a99633d6b226b7bfd36203425e9c5d53b Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Tue, 22 Oct 2019 10:20:35 -0500 Subject: Updated CHANGES.txt --- src/CHANGES.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index af448d5..c567f2b 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -6,6 +6,10 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER + From Adam Gross: + + - Added new module SCons.Scanner.PythonScanner to allow scanning .py files. + From Mathew Robinson: - Improved threading performance by ensuring NodeInfo is shared -- cgit v0.12 From 8be1911e74367a14dda42ba14baad03a774aa831 Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Tue, 22 Oct 2019 10:22:15 -0500 Subject: Fixed typo in CHANGES.txt --- src/CHANGES.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index c567f2b..211f571 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -8,7 +8,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER From Adam Gross: - - Added new module SCons.Scanner.PythonScanner to allow scanning .py files. + - Added new module SCons.Scanner.Python to allow scanning .py files. From Mathew Robinson: -- cgit v0.12 From 702ec6e6ac1ea26546ed3ae9b7b5c597271c87a0 Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Wed, 23 Oct 2019 11:22:24 -0500 Subject: Improvements to patch This change does the following: 1. Fixes bug related to "from a import b as c". 2. Adds test cases for "from a import b as c" and "import a as b". 3. Adds a few more tests to get to 100% coverage of Python.py. --- src/engine/SCons/Scanner/Python.py | 11 +++- src/engine/SCons/Scanner/PythonTests.py | 98 +++++++++++++++++++++++++++++---- 2 files changed, 96 insertions(+), 13 deletions(-) diff --git a/src/engine/SCons/Scanner/Python.py b/src/engine/SCons/Scanner/Python.py index eddff0f..825928d 100644 --- a/src/engine/SCons/Scanner/Python.py +++ b/src/engine/SCons/Scanner/Python.py @@ -69,8 +69,15 @@ def find_include_names(node): matches = from_cre.findall(text) if matches: for match in matches: - imports = match[1].split(',') - all_matches.append((match[0], [i.strip() for i in imports])) + imports = [i.strip() for i in match[1].split(',')] + + # Add some custom logic to strip out "as" because the regex + # includes it. + last_import_split = imports[-1].split() + if len(last_import_split) > 1: + imports[-1] = last_import_split[0] + + all_matches.append((match[0], imports)) matches = import_cre.findall(text) if matches: diff --git a/src/engine/SCons/Scanner/PythonTests.py b/src/engine/SCons/Scanner/PythonTests.py index 4db9215..18f75e2 100644 --- a/src/engine/SCons/Scanner/PythonTests.py +++ b/src/engine/SCons/Scanner/PythonTests.py @@ -39,17 +39,30 @@ test = TestCmd.TestCmd(workdir='') # This directory is a simple empty package. test.subdir('simple_package') test.write(['simple_package', '__init__.py'], '') -test.write(['simple_package', 'module.py'], '') +test.write(['simple_package', 'module1.py'], '') +test.write(['simple_package', 'module2.py'], '') # Two files that import from simple_package. test.write('imports_simple_package.py', r""" import simple_package """) -test.write('import_simple_package_module.py', r""" -import simple_package.module +test.write('import_simple_package_module1.py', r""" +import simple_package.module1 """) -test.write('from_import_simple_package_module.py', r""" -from simple_package import module +test.write('import_simple_package_module1_as.py', r""" +import simple_package.module1 as m1 +""") +test.write('from_import_simple_package_module1.py', r""" +from simple_package import module1 +""") +test.write('from_import_simple_package_module1_as.py', r""" +from simple_package import module1 as m1 +""") +test.write('from_import_simple_package_modules_no_space.py', r""" +from simple_package import module1,module2 +""") +test.write('from_import_simple_package_modules_with_space.py', r""" +from simple_package import module1, module2 """) # This directory holds a script that imports another from the current dir. @@ -166,6 +179,17 @@ class PythonScannerTestPythonPath(unittest.TestCase): deps_match(self, deps, files) +class PythonScannerTestPythonCallablePath(unittest.TestCase): + def runTest(self): + env = DummyEnvironment() + s = SCons.Scanner.Python.PythonScanner + env['ENV']['PYTHONPATH'] = test.workpath('') + path = lambda : s.path(env) + deps = s(env.File('imports_simple_package.py'), env, path) + files = ['simple_package/__init__.py'] + deps_match(self, deps, files) + + class PythonScannerTestImportSimplePackage(unittest.TestCase): def runTest(self): env = DummyEnvironment() @@ -176,26 +200,78 @@ class PythonScannerTestImportSimplePackage(unittest.TestCase): files = ['simple_package/__init__.py'] deps_match(self, deps, files) + # Repeat the test in case there are any issues caching includes. + deps = s(node, env, path) + deps_match(self, deps, files) + + +class PythonScannerTestImportSimplePackageModule1As(unittest.TestCase): + def runTest(self): + env = DummyEnvironment() + s = SCons.Scanner.Python.PythonScanner + node = env.File('import_simple_package_module1_as.py') + path = s.path(env, source=[node]) + deps = s(node, env, path) + files = ['simple_package/__init__.py', 'simple_package/module1.py'] + deps_match(self, deps, files) + + +class PythonScannerTestImportSimplePackageModuleAs(unittest.TestCase): + def runTest(self): + env = DummyEnvironment() + s = SCons.Scanner.Python.PythonScanner + node = env.File('import_simple_package_module1.py') + path = s.path(env, source=[node]) + deps = s(node, env, path) + files = ['simple_package/__init__.py', 'simple_package/module1.py'] + deps_match(self, deps, files) + + +class PythonScannerTestFromImportSimplePackageModule1(unittest.TestCase): + def runTest(self): + env = DummyEnvironment() + s = SCons.Scanner.Python.PythonScanner + node = env.File('from_import_simple_package_module1.py') + path = s.path(env, source=[node]) + deps = s(node, env, path) + files = ['simple_package/__init__.py', 'simple_package/module1.py'] + deps_match(self, deps, files) + + +class PythonScannerTestFromImportSimplePackageModule1As(unittest.TestCase): + def runTest(self): + env = DummyEnvironment() + s = SCons.Scanner.Python.PythonScanner + node = env.File('from_import_simple_package_module1_as.py') + path = s.path(env, source=[node]) + deps = s(node, env, path) + files = ['simple_package/__init__.py', 'simple_package/module1.py'] + deps_match(self, deps, files) + -class PythonScannerTestImportSimplePackageModule(unittest.TestCase): +class PythonScannerTestFromImportSimplePackageModulesNoSpace( + unittest.TestCase): def runTest(self): env = DummyEnvironment() s = SCons.Scanner.Python.PythonScanner - node = env.File('import_simple_package_module.py') + node = env.File('from_import_simple_package_modules_no_space.py') path = s.path(env, source=[node]) deps = s(node, env, path) - files = ['simple_package/__init__.py', 'simple_package/module.py'] + files = ['simple_package/__init__.py', 'simple_package/module1.py', + 'simple_package/module2.py'] deps_match(self, deps, files) -class PythonScannerTestFromImportSimplePackageModule(unittest.TestCase): +class PythonScannerTestFromImportSimplePackageModulesWithSpace( + unittest.TestCase): def runTest(self): env = DummyEnvironment() s = SCons.Scanner.Python.PythonScanner - node = env.File('from_import_simple_package_module.py') + node = env.File('from_import_simple_package_modules_with_space.py') path = s.path(env, source=[node]) deps = s(node, env, path) - files = ['simple_package/__init__.py', 'simple_package/module.py'] + files = ['simple_package/__init__.py', 'simple_package/module1.py', + 'simple_package/module2.py'] deps_match(self, deps, files) -- cgit v0.12 From cdd4d0cc8f7c69b275860baa01293544c3bde40d Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Wed, 23 Oct 2019 11:26:23 -0500 Subject: Fix sider issue related to lambda usage --- src/engine/SCons/Scanner/PythonTests.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/engine/SCons/Scanner/PythonTests.py b/src/engine/SCons/Scanner/PythonTests.py index 18f75e2..48f6cfc 100644 --- a/src/engine/SCons/Scanner/PythonTests.py +++ b/src/engine/SCons/Scanner/PythonTests.py @@ -184,8 +184,8 @@ class PythonScannerTestPythonCallablePath(unittest.TestCase): env = DummyEnvironment() s = SCons.Scanner.Python.PythonScanner env['ENV']['PYTHONPATH'] = test.workpath('') - path = lambda : s.path(env) - deps = s(env.File('imports_simple_package.py'), env, path) + deps = s(env.File('imports_simple_package.py'), env, + lambda : s.path(env)) files = ['simple_package/__init__.py'] deps_match(self, deps, files) -- cgit v0.12 From 5f3064a00556705cc5eebacab159091da29255b3 Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Thu, 24 Oct 2019 14:12:40 -0400 Subject: Convert PythonTests to use directory fixture --- src/engine/SCons/Scanner/PythonTests.py | 80 +--------------------- .../python_scanner/curdir_reference/helper.py | 0 .../python_scanner/curdir_reference/script.py | 1 + .../from_import_simple_package_module1.py | 1 + .../from_import_simple_package_module1_as.py | 1 + .../from_import_simple_package_modules_no_space.py | 1 + ...rom_import_simple_package_modules_with_space.py | 1 + .../import_simple_package_module1.py | 1 + .../import_simple_package_module1_as.py | 1 + test/fixture/python_scanner/imports_nested3.py | 1 + .../python_scanner/imports_simple_package.py | 1 + test/fixture/python_scanner/nested1/__init__.py | 0 test/fixture/python_scanner/nested1/module.py | 0 .../python_scanner/nested1/nested2/__init__.py | 0 .../python_scanner/nested1/nested2/module.py | 0 .../nested1/nested2/nested3/__init__.py | 0 .../nested2/nested3/imports_grandparent_module.py | 1 + .../nested2/nested3/imports_parent_module.py | 1 + .../nested3/imports_parent_then_submodule.py | 1 + .../nested1/nested2/nested3/module.py | 0 .../python_scanner/nested1/nested2a/__init__.py | 0 .../python_scanner/nested1/nested2a/module.py | 0 .../python_scanner/simple_package/__init__.py | 0 .../python_scanner/simple_package/module1.py | 0 .../python_scanner/simple_package/module2.py | 0 25 files changed, 13 insertions(+), 79 deletions(-) create mode 100644 test/fixture/python_scanner/curdir_reference/helper.py create mode 100644 test/fixture/python_scanner/curdir_reference/script.py create mode 100644 test/fixture/python_scanner/from_import_simple_package_module1.py create mode 100644 test/fixture/python_scanner/from_import_simple_package_module1_as.py create mode 100644 test/fixture/python_scanner/from_import_simple_package_modules_no_space.py create mode 100644 test/fixture/python_scanner/from_import_simple_package_modules_with_space.py create mode 100644 test/fixture/python_scanner/import_simple_package_module1.py create mode 100644 test/fixture/python_scanner/import_simple_package_module1_as.py create mode 100644 test/fixture/python_scanner/imports_nested3.py create mode 100644 test/fixture/python_scanner/imports_simple_package.py create mode 100644 test/fixture/python_scanner/nested1/__init__.py create mode 100644 test/fixture/python_scanner/nested1/module.py create mode 100644 test/fixture/python_scanner/nested1/nested2/__init__.py create mode 100644 test/fixture/python_scanner/nested1/nested2/module.py create mode 100644 test/fixture/python_scanner/nested1/nested2/nested3/__init__.py create mode 100644 test/fixture/python_scanner/nested1/nested2/nested3/imports_grandparent_module.py create mode 100644 test/fixture/python_scanner/nested1/nested2/nested3/imports_parent_module.py create mode 100644 test/fixture/python_scanner/nested1/nested2/nested3/imports_parent_then_submodule.py create mode 100644 test/fixture/python_scanner/nested1/nested2/nested3/module.py create mode 100644 test/fixture/python_scanner/nested1/nested2a/__init__.py create mode 100644 test/fixture/python_scanner/nested1/nested2a/module.py create mode 100644 test/fixture/python_scanner/simple_package/__init__.py create mode 100644 test/fixture/python_scanner/simple_package/module1.py create mode 100644 test/fixture/python_scanner/simple_package/module2.py diff --git a/src/engine/SCons/Scanner/PythonTests.py b/src/engine/SCons/Scanner/PythonTests.py index 48f6cfc..0d4e628 100644 --- a/src/engine/SCons/Scanner/PythonTests.py +++ b/src/engine/SCons/Scanner/PythonTests.py @@ -35,85 +35,7 @@ import SCons.Node.FS import SCons.Scanner.Python test = TestCmd.TestCmd(workdir='') - -# This directory is a simple empty package. -test.subdir('simple_package') -test.write(['simple_package', '__init__.py'], '') -test.write(['simple_package', 'module1.py'], '') -test.write(['simple_package', 'module2.py'], '') - -# Two files that import from simple_package. -test.write('imports_simple_package.py', r""" -import simple_package -""") -test.write('import_simple_package_module1.py', r""" -import simple_package.module1 -""") -test.write('import_simple_package_module1_as.py', r""" -import simple_package.module1 as m1 -""") -test.write('from_import_simple_package_module1.py', r""" -from simple_package import module1 -""") -test.write('from_import_simple_package_module1_as.py', r""" -from simple_package import module1 as m1 -""") -test.write('from_import_simple_package_modules_no_space.py', r""" -from simple_package import module1,module2 -""") -test.write('from_import_simple_package_modules_with_space.py', r""" -from simple_package import module1, module2 -""") - -# This directory holds a script that imports another from the current dir. -test.subdir('curdir_reference') -test.write(['curdir_reference', 'script.py'], r""" -from . import helper -""") -test.write(['curdir_reference', 'helper.py'], r'') - -# Create the directory structure: -# imports_nested3.py -# nested1 -# |- __init__.py -# |- module.py -# |- nested2 -# | |- __init__.py -# | |- module.py -# | '- nested3 -# | |- __init__.py -# | |- imports_grandparent_module.py -# | |- imports_parent_module.py -# | |- imports_parent_then_submodule.py -# | '- module.py -# '- nested2a -# |- __init__.py -# '- module.py -# This is used for more advanced relative path test cases. -test.write('imports_nested3.py', r""" -import nested1.nested2.nested3 -""") -test.subdir('nested1', ['nested1', 'nested2'], ['nested1', 'nested2a'], - ['nested1', 'nested2', 'nested3']) -test.write(['nested1', '__init__.py'], r'') -test.write(['nested1', 'module.py'], r'') -test.write(['nested1', 'nested2', '__init__.py'], r'') -test.write(['nested1', 'nested2', 'module.py'], r'') -test.write(['nested1', 'nested2a', '__init__.py'], r'') -test.write(['nested1', 'nested2a', 'module.py'], r'') -test.write(['nested1', 'nested2', 'nested3', '__init__.py'], r'') -test.write(['nested1', 'nested2', 'nested3', - 'imports_grandparent_module.py'], r""" -from ... import module -""") -test.write(['nested1', 'nested2', 'nested3', 'imports_parent_module.py'], r""" -from .. import module -""") -test.write(['nested1', 'nested2', 'nested3', - 'imports_parent_then_submodule.py'], r""" -from ...nested2a import module -""") -test.write(['nested1', 'nested2', 'nested3', 'module.py'], r'') +test.dir_fixture('python_scanner') if os.path.normcase('foo') == os.path.normcase('FOO'): my_normpath = os.path.normcase diff --git a/test/fixture/python_scanner/curdir_reference/helper.py b/test/fixture/python_scanner/curdir_reference/helper.py new file mode 100644 index 0000000..e69de29 diff --git a/test/fixture/python_scanner/curdir_reference/script.py b/test/fixture/python_scanner/curdir_reference/script.py new file mode 100644 index 0000000..d533863 --- /dev/null +++ b/test/fixture/python_scanner/curdir_reference/script.py @@ -0,0 +1 @@ +from . import helper diff --git a/test/fixture/python_scanner/from_import_simple_package_module1.py b/test/fixture/python_scanner/from_import_simple_package_module1.py new file mode 100644 index 0000000..dcc86de --- /dev/null +++ b/test/fixture/python_scanner/from_import_simple_package_module1.py @@ -0,0 +1 @@ +from simple_package import module1 diff --git a/test/fixture/python_scanner/from_import_simple_package_module1_as.py b/test/fixture/python_scanner/from_import_simple_package_module1_as.py new file mode 100644 index 0000000..51061c6 --- /dev/null +++ b/test/fixture/python_scanner/from_import_simple_package_module1_as.py @@ -0,0 +1 @@ +from simple_package import module1 as m1 diff --git a/test/fixture/python_scanner/from_import_simple_package_modules_no_space.py b/test/fixture/python_scanner/from_import_simple_package_modules_no_space.py new file mode 100644 index 0000000..17b82f8 --- /dev/null +++ b/test/fixture/python_scanner/from_import_simple_package_modules_no_space.py @@ -0,0 +1 @@ +from simple_package import module1,module2 diff --git a/test/fixture/python_scanner/from_import_simple_package_modules_with_space.py b/test/fixture/python_scanner/from_import_simple_package_modules_with_space.py new file mode 100644 index 0000000..169e6f7 --- /dev/null +++ b/test/fixture/python_scanner/from_import_simple_package_modules_with_space.py @@ -0,0 +1 @@ +from simple_package import module1, module2 diff --git a/test/fixture/python_scanner/import_simple_package_module1.py b/test/fixture/python_scanner/import_simple_package_module1.py new file mode 100644 index 0000000..bd85010 --- /dev/null +++ b/test/fixture/python_scanner/import_simple_package_module1.py @@ -0,0 +1 @@ +import simple_package.module1 diff --git a/test/fixture/python_scanner/import_simple_package_module1_as.py b/test/fixture/python_scanner/import_simple_package_module1_as.py new file mode 100644 index 0000000..a706672 --- /dev/null +++ b/test/fixture/python_scanner/import_simple_package_module1_as.py @@ -0,0 +1 @@ +import simple_package.module1 as m1 diff --git a/test/fixture/python_scanner/imports_nested3.py b/test/fixture/python_scanner/imports_nested3.py new file mode 100644 index 0000000..c2929d0 --- /dev/null +++ b/test/fixture/python_scanner/imports_nested3.py @@ -0,0 +1 @@ +import nested1.nested2.nested3 diff --git a/test/fixture/python_scanner/imports_simple_package.py b/test/fixture/python_scanner/imports_simple_package.py new file mode 100644 index 0000000..d974128 --- /dev/null +++ b/test/fixture/python_scanner/imports_simple_package.py @@ -0,0 +1 @@ +import simple_package diff --git a/test/fixture/python_scanner/nested1/__init__.py b/test/fixture/python_scanner/nested1/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/fixture/python_scanner/nested1/module.py b/test/fixture/python_scanner/nested1/module.py new file mode 100644 index 0000000..e69de29 diff --git a/test/fixture/python_scanner/nested1/nested2/__init__.py b/test/fixture/python_scanner/nested1/nested2/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/fixture/python_scanner/nested1/nested2/module.py b/test/fixture/python_scanner/nested1/nested2/module.py new file mode 100644 index 0000000..e69de29 diff --git a/test/fixture/python_scanner/nested1/nested2/nested3/__init__.py b/test/fixture/python_scanner/nested1/nested2/nested3/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/fixture/python_scanner/nested1/nested2/nested3/imports_grandparent_module.py b/test/fixture/python_scanner/nested1/nested2/nested3/imports_grandparent_module.py new file mode 100644 index 0000000..06bb7f5 --- /dev/null +++ b/test/fixture/python_scanner/nested1/nested2/nested3/imports_grandparent_module.py @@ -0,0 +1 @@ +from ... import module diff --git a/test/fixture/python_scanner/nested1/nested2/nested3/imports_parent_module.py b/test/fixture/python_scanner/nested1/nested2/nested3/imports_parent_module.py new file mode 100644 index 0000000..be10279 --- /dev/null +++ b/test/fixture/python_scanner/nested1/nested2/nested3/imports_parent_module.py @@ -0,0 +1 @@ +from .. import module diff --git a/test/fixture/python_scanner/nested1/nested2/nested3/imports_parent_then_submodule.py b/test/fixture/python_scanner/nested1/nested2/nested3/imports_parent_then_submodule.py new file mode 100644 index 0000000..39f1a1a --- /dev/null +++ b/test/fixture/python_scanner/nested1/nested2/nested3/imports_parent_then_submodule.py @@ -0,0 +1 @@ +from ...nested2a import module diff --git a/test/fixture/python_scanner/nested1/nested2/nested3/module.py b/test/fixture/python_scanner/nested1/nested2/nested3/module.py new file mode 100644 index 0000000..e69de29 diff --git a/test/fixture/python_scanner/nested1/nested2a/__init__.py b/test/fixture/python_scanner/nested1/nested2a/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/fixture/python_scanner/nested1/nested2a/module.py b/test/fixture/python_scanner/nested1/nested2a/module.py new file mode 100644 index 0000000..e69de29 diff --git a/test/fixture/python_scanner/simple_package/__init__.py b/test/fixture/python_scanner/simple_package/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test/fixture/python_scanner/simple_package/module1.py b/test/fixture/python_scanner/simple_package/module1.py new file mode 100644 index 0000000..e69de29 diff --git a/test/fixture/python_scanner/simple_package/module2.py b/test/fixture/python_scanner/simple_package/module2.py new file mode 100644 index 0000000..e69de29 -- cgit v0.12 From 8c49f0a6748688f98b10f6bb9b3d244baa49b3e4 Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Fri, 25 Oct 2019 08:44:11 -0400 Subject: Add sconstest.skip files and improve test-framework.rst docs in that area --- test/fixture/python_scanner/curdir_reference/sconstest.skip | 0 test/fixture/python_scanner/nested1/nested2/nested3/sconstest.skip | 0 test/fixture/python_scanner/nested1/nested2/sconstest.skip | 0 test/fixture/python_scanner/nested1/nested2a/sconstest.skip | 0 test/fixture/python_scanner/nested1/sconstest.skip | 0 test/fixture/python_scanner/sconstest.skip | 0 test/fixture/python_scanner/simple_package/sconstest.skip | 0 testing/framework/test-framework.rst | 3 +++ 8 files changed, 3 insertions(+) create mode 100644 test/fixture/python_scanner/curdir_reference/sconstest.skip create mode 100644 test/fixture/python_scanner/nested1/nested2/nested3/sconstest.skip create mode 100644 test/fixture/python_scanner/nested1/nested2/sconstest.skip create mode 100644 test/fixture/python_scanner/nested1/nested2a/sconstest.skip create mode 100644 test/fixture/python_scanner/nested1/sconstest.skip create mode 100644 test/fixture/python_scanner/sconstest.skip create mode 100644 test/fixture/python_scanner/simple_package/sconstest.skip diff --git a/test/fixture/python_scanner/curdir_reference/sconstest.skip b/test/fixture/python_scanner/curdir_reference/sconstest.skip new file mode 100644 index 0000000..e69de29 diff --git a/test/fixture/python_scanner/nested1/nested2/nested3/sconstest.skip b/test/fixture/python_scanner/nested1/nested2/nested3/sconstest.skip new file mode 100644 index 0000000..e69de29 diff --git a/test/fixture/python_scanner/nested1/nested2/sconstest.skip b/test/fixture/python_scanner/nested1/nested2/sconstest.skip new file mode 100644 index 0000000..e69de29 diff --git a/test/fixture/python_scanner/nested1/nested2a/sconstest.skip b/test/fixture/python_scanner/nested1/nested2a/sconstest.skip new file mode 100644 index 0000000..e69de29 diff --git a/test/fixture/python_scanner/nested1/sconstest.skip b/test/fixture/python_scanner/nested1/sconstest.skip new file mode 100644 index 0000000..e69de29 diff --git a/test/fixture/python_scanner/sconstest.skip b/test/fixture/python_scanner/sconstest.skip new file mode 100644 index 0000000..e69de29 diff --git a/test/fixture/python_scanner/simple_package/sconstest.skip b/test/fixture/python_scanner/simple_package/sconstest.skip new file mode 100644 index 0000000..e69de29 diff --git a/testing/framework/test-framework.rst b/testing/framework/test-framework.rst index cb6b8e1..dc6b2aa 100644 --- a/testing/framework/test-framework.rst +++ b/testing/framework/test-framework.rst @@ -308,6 +308,9 @@ in that sense: "the fixture for this test is foo", instead of writing a whole bunch of strings to create files. Since these setups can be reusable across multiple tests, the *fixture* terminology applies well. +Note: fixtures must not be treated by SCons as runnable tests. To exclude +them, see instructions in the above section named "Finding Tests". + Directory Fixtures ################## -- cgit v0.12 From 3b0b2b13b3b47886bd097685c863068a5ca8c5dd Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Mon, 25 Nov 2019 10:59:49 -0500 Subject: Memoize environment.Value() to improve performance The code I work on calls env.Value() often on the same values as part of consolidating outside dependencies. This change improves performance of that call by memoizing the results. --- src/engine/SCons/Environment.py | 2 +- src/engine/SCons/Node/Python.py | 30 ++++++++++++++++++++++++------ 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 1296f54..968cc9f 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -2220,7 +2220,7 @@ class Base(SubstitutionEnvironment): def Value(self, value, built_value=None): """ """ - return SCons.Node.Python.Value(value, built_value) + return SCons.Node.Python.ValueWithMemo(value, built_value) def VariantDir(self, variant_dir, src_dir, duplicate=1): variant_dir = self.arg2nodes(variant_dir, self.fs.Dir)[0] diff --git a/src/engine/SCons/Node/Python.py b/src/engine/SCons/Node/Python.py index 4a62f04..f817402 100644 --- a/src/engine/SCons/Node/Python.py +++ b/src/engine/SCons/Node/Python.py @@ -31,6 +31,9 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import SCons.Node +_memoLookupMap = {} + + class ValueNodeInfo(SCons.Node.NodeInfoBase): __slots__ = ('csig',) current_version_id = 2 @@ -38,18 +41,18 @@ class ValueNodeInfo(SCons.Node.NodeInfoBase): field_list = ['csig'] def str_to_node(self, s): - return Value(s) + return ValueWithMemo(s) def __getstate__(self): """ Return all fields that shall be pickled. Walk the slots in the class - hierarchy and add those to the state dictionary. If a '__dict__' slot is - available, copy all entries to the dictionary. Also include the version - id, which is fixed for all instances of a class. + hierarchy and add those to the state dictionary. If a '__dict__' slot + is available, copy all entries to the dictionary. Also include the + version id, which is fixed for all instances of a class. """ state = getattr(self, '__dict__', {}).copy() for obj in type(self).mro(): - for name in getattr(obj,'__slots__',()): + for name in getattr(obj, '__slots__', ()): if hasattr(self, name): state[name] = getattr(self, name) @@ -76,6 +79,7 @@ class ValueBuildInfo(SCons.Node.BuildInfoBase): __slots__ = () current_version_id = 2 + class Value(SCons.Node.Node): """A class for Python variables, typically passed on the command line or generated by a script, but not from a file or some other source. @@ -148,7 +152,6 @@ class Value(SCons.Node.Node): # Already encoded as python2 str are bytes return text_contents - def changed_since_last_build(self, target, prev_ni): cur_csig = self.get_csig() try: @@ -173,6 +176,21 @@ class Value(SCons.Node.Node): self.get_ninfo().csig = contents return contents + +def ValueWithMemo(value, built_value=None): + # No current support for memoizing a value that needs to be built. + if built_value: + return Value(value, built_value) + + value_str = str(value) + if value_str in _memoLookupMap: + return _memoLookupMap[value_str] + + v = Value(value) + _memoLookupMap[value_str] = v + return v + + # Local Variables: # tab-width:4 # indent-tabs-mode:nil -- cgit v0.12 From e0d0b38fdfcb832c8b924b3e5a969e14cd1058e5 Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Mon, 25 Nov 2019 11:03:53 -0500 Subject: Update CHANGES.txt --- src/CHANGES.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index db0a5f2..94c7a11 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -6,6 +6,11 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER + From Adam Gross: + + - Added memoization support for calls to Environment.Value() in order to + improve performance of repeated calls. + From Philipp Maierhöfer: - Avoid crash with UnicodeDecodeError on Python 3 when a Latex log file in non-UTF-8 encoding (e.g. containing umlauts in Latin-1 encoding when -- cgit v0.12 From 0cbaf9cc537c2d4de5b3185d222d74c47d49755d Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Mon, 25 Nov 2019 11:11:03 -0500 Subject: Improve readability by explicitly declaring _memoLookupMap as global --- src/engine/SCons/Node/Python.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/engine/SCons/Node/Python.py b/src/engine/SCons/Node/Python.py index f817402..7b25edb 100644 --- a/src/engine/SCons/Node/Python.py +++ b/src/engine/SCons/Node/Python.py @@ -178,6 +178,8 @@ class Value(SCons.Node.Node): def ValueWithMemo(value, built_value=None): + global _memoLookupMap + # No current support for memoizing a value that needs to be built. if built_value: return Value(value, built_value) -- cgit v0.12 From 6b48b335179b246b0a3f7fb5ab228c0e0cc1da9f Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Mon, 25 Nov 2019 11:15:07 -0500 Subject: Add test cases for memoization --- src/engine/SCons/Node/PythonTests.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/engine/SCons/Node/PythonTests.py b/src/engine/SCons/Node/PythonTests.py index 8a01503..51345e7 100644 --- a/src/engine/SCons/Node/PythonTests.py +++ b/src/engine/SCons/Node/PythonTests.py @@ -110,6 +110,17 @@ class ValueBuildInfoTestCase(unittest.TestCase): vvv = SCons.Node.Python.Value('vvv') bi = SCons.Node.Python.ValueBuildInfo() +class ValueMemoTestCase(unittest.TestCase): + def test___init__(self): + """Test memoization""" + value1 = SCons.Node.Python.ValueWithMemo('vvv') + value2 = SCons.Node.Python.ValueWithMemo('vvv') + assert value1 == value2 + + ni = SCons.Node.Python.ValueNodeInfo() + value3 = ni.str_to_node('vvv') + assert value1 == value3 + if __name__ == "__main__": unittest.main() -- cgit v0.12 From 14c9be3e3d923bafe6c2f9f7524b03b55cfecaf0 Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Mon, 25 Nov 2019 11:17:04 -0500 Subject: Fix some existing flake8 validation issues in PythonTests.py --- src/engine/SCons/Node/PythonTests.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/engine/SCons/Node/PythonTests.py b/src/engine/SCons/Node/PythonTests.py index 51345e7..e0dd885 100644 --- a/src/engine/SCons/Node/PythonTests.py +++ b/src/engine/SCons/Node/PythonTests.py @@ -23,14 +23,13 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" -import sys import unittest import SCons.Errors import SCons.Node.Python -class ValueTestCase(unittest.TestCase): +class ValueTestCase(unittest.TestCase): def test_Value(self): """Test creating a Value() object """ @@ -42,7 +41,7 @@ class ValueTestCase(unittest.TestCase): assert v2.value == value2, v2.value assert v2.value is value2, v2.value - assert not v1 is v2 + assert v1 is not v2 assert v1.value == v2.value v3 = SCons.Node.Python.Value('c', 'cb') @@ -98,28 +97,31 @@ class ValueTestCase(unittest.TestCase): csig = v3.get_csig(None) assert csig == 'None', csig + class ValueNodeInfoTestCase(unittest.TestCase): def test___init__(self): """Test ValueNodeInfo initialization""" vvv = SCons.Node.Python.Value('vvv') ni = SCons.Node.Python.ValueNodeInfo() + class ValueBuildInfoTestCase(unittest.TestCase): def test___init__(self): """Test ValueBuildInfo initialization""" vvv = SCons.Node.Python.Value('vvv') bi = SCons.Node.Python.ValueBuildInfo() + class ValueMemoTestCase(unittest.TestCase): def test___init__(self): """Test memoization""" value1 = SCons.Node.Python.ValueWithMemo('vvv') value2 = SCons.Node.Python.ValueWithMemo('vvv') - assert value1 == value2 + assert value1 is value2 ni = SCons.Node.Python.ValueNodeInfo() value3 = ni.str_to_node('vvv') - assert value1 == value3 + assert value1 is value3 if __name__ == "__main__": unittest.main() -- cgit v0.12 From c588a56230ad864b009da19e914c9fb50fbc4b97 Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Mon, 25 Nov 2019 13:01:49 -0500 Subject: Fix EnvironmentTests.py now that env.Value() is memoized --- src/engine/SCons/EnvironmentTests.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index 0957361..2911de0 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -3315,8 +3315,7 @@ def generate(env): assert v2.value == value2, v2.value assert v2.value is value2, v2.value - assert not v1 is v2 - assert v1.value == v2.value + assert v1 is v2 v3 = env.Value('c', 'build-c') assert v3.value == 'c', v3.value -- cgit v0.12 From e76e874f44824172d1118b0f028256124332a101 Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Mon, 25 Nov 2019 14:05:19 -0500 Subject: Add support for Value objects being implicit dependencies As part of consolidating outside dependencies, the code I work on takes on Value objects as implicit dependencies. That allows us to take on a dependecy to an entire build (e.g. our compiler) rather than 500 files from it. This has worked fine in practice for months now, but it turns out to break when using caching, because Node.get_contents() expects all dependencies to have the "name" attribute. This change adds that attribute to the Value class and a test to confirm that Node.get_contents() works now. --- src/CHANGES.txt | 5 +++++ src/engine/SCons/Node/Python.py | 4 ++++ src/engine/SCons/Node/PythonTests.py | 10 ++++++++++ 3 files changed, 19 insertions(+) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index db0a5f2..36ab52c 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -6,6 +6,11 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER + From Adam Gross: + + - Added support for taking instances of the Value class as implicit + dependencies. + From Philipp Maierhöfer: - Avoid crash with UnicodeDecodeError on Python 3 when a Latex log file in non-UTF-8 encoding (e.g. containing umlauts in Latin-1 encoding when diff --git a/src/engine/SCons/Node/Python.py b/src/engine/SCons/Node/Python.py index 4a62f04..546769d 100644 --- a/src/engine/SCons/Node/Python.py +++ b/src/engine/SCons/Node/Python.py @@ -92,6 +92,10 @@ class Value(SCons.Node.Node): if built_value is not None: self.built_value = built_value + # Set a name so it can be a child of a node and not break + # its parent's implementation of Node.get_contents. + self.name = value + def str_for_display(self): return repr(self.value) diff --git a/src/engine/SCons/Node/PythonTests.py b/src/engine/SCons/Node/PythonTests.py index 8a01503..4c15e96 100644 --- a/src/engine/SCons/Node/PythonTests.py +++ b/src/engine/SCons/Node/PythonTests.py @@ -110,6 +110,16 @@ class ValueBuildInfoTestCase(unittest.TestCase): vvv = SCons.Node.Python.Value('vvv') bi = SCons.Node.Python.ValueBuildInfo() + +class ValueChildTestCase(unittest.TestCase): + def test___init__(self): + """Test support for a Value() being an implicit dependency of a Node""" + value = SCons.Node.Python.Value('v') + node = SCons.Node.Node() + node._func_get_contents = 2 # Pretend to be a Dir. + node.add_to_implicit([value]) + contents = node.get_contents() + if __name__ == "__main__": unittest.main() -- cgit v0.12 From 9ac3a25ea28dae718c095a7b1909c42b817ec9b8 Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Mon, 25 Nov 2019 14:12:42 -0500 Subject: Avoid a flake8 warning where "contents" is unused --- src/engine/SCons/Node/PythonTests.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/engine/SCons/Node/PythonTests.py b/src/engine/SCons/Node/PythonTests.py index 4c15e96..9d3c6b5 100644 --- a/src/engine/SCons/Node/PythonTests.py +++ b/src/engine/SCons/Node/PythonTests.py @@ -119,6 +119,7 @@ class ValueChildTestCase(unittest.TestCase): node._func_get_contents = 2 # Pretend to be a Dir. node.add_to_implicit([value]) contents = node.get_contents() + assert len(contents) > 0 if __name__ == "__main__": unittest.main() -- cgit v0.12 From 1bb22663dd05fd6de2aa8a462e1fc695cb50de0a Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Wed, 27 Nov 2019 13:18:43 -0500 Subject: Add a test to confirm that built values are not memoized --- src/engine/SCons/Node/PythonTests.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/engine/SCons/Node/PythonTests.py b/src/engine/SCons/Node/PythonTests.py index e0dd885..e05cfc9 100644 --- a/src/engine/SCons/Node/PythonTests.py +++ b/src/engine/SCons/Node/PythonTests.py @@ -115,14 +115,25 @@ class ValueBuildInfoTestCase(unittest.TestCase): class ValueMemoTestCase(unittest.TestCase): def test___init__(self): """Test memoization""" + # First confirm that ValueWithMemo does memoization. value1 = SCons.Node.Python.ValueWithMemo('vvv') value2 = SCons.Node.Python.ValueWithMemo('vvv') assert value1 is value2 + # Next confirm that ValueNodeInfo.str_to_node does memoization using + # the same cache as ValueWithMemo. ni = SCons.Node.Python.ValueNodeInfo() value3 = ni.str_to_node('vvv') assert value1 is value3 + +class BuiltValueNoMemoTestCase(unittest.TestCase): + def test___init__(self): + """Confirm that built values are not memoized.""" + v1 = SCons.Node.Python.Value('c', 'ca') + v2 = SCons.Node.Python.Value('c', 'ca') + assert v1 is not v2 + if __name__ == "__main__": unittest.main() -- cgit v0.12 From e6dc8216872085749db83e14c9545cabb1ed0483 Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Mon, 2 Dec 2019 09:54:28 -0500 Subject: Add a functional test --- src/engine/SCons/Node/Python.py | 1 - src/engine/SCons/Node/__init__.py | 4 +-- test/CacheDir/value.py | 47 ++++++++++++++++++++++++++++++ test/fixture/cachedir_foo_value/SConstruct | 19 ++++++++++++ test/fixture/cachedir_foo_value/foo.c | 1 + 5 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 test/CacheDir/value.py create mode 100644 test/fixture/cachedir_foo_value/SConstruct create mode 100644 test/fixture/cachedir_foo_value/foo.c diff --git a/src/engine/SCons/Node/Python.py b/src/engine/SCons/Node/Python.py index 546769d..83e38f0 100644 --- a/src/engine/SCons/Node/Python.py +++ b/src/engine/SCons/Node/Python.py @@ -152,7 +152,6 @@ class Value(SCons.Node.Node): # Already encoded as python2 str are bytes return text_contents - def changed_since_last_build(self, target, prev_ni): cur_csig = self.get_csig() try: diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index daf79ba..4200965 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -741,12 +741,12 @@ class Node(object, with_metaclass(NoSlotsPyPy)): if self.depends is not None: for d in self.depends: if d.missing(): - msg = "Explicit dependency `%s' not found, needed by target `%s'." + msg = "Explicit dependency '%s' not found, needed by target '%s'." raise SCons.Errors.StopError(msg % (d, self)) if self.implicit is not None: for i in self.implicit: if i.missing(): - msg = "Implicit dependency `%s' not found, needed by target `%s'." + msg = "Implicit dependency '%s' not found, needed by target '%s'." raise SCons.Errors.StopError(msg % (i, self)) self.binfo = self.get_binfo() diff --git a/test/CacheDir/value.py b/test/CacheDir/value.py new file mode 100644 index 0000000..fd89a9e --- /dev/null +++ b/test/CacheDir/value.py @@ -0,0 +1,47 @@ +#!/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 bwuilds with caching work for an action with a Value as a child. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.dir_fixture('cachedir_foo_value') +test.subdir('cache') + +# First build, populates the cache +test.run(arguments='.') + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/fixture/cachedir_foo_value/SConstruct b/test/fixture/cachedir_foo_value/SConstruct new file mode 100644 index 0000000..b144799 --- /dev/null +++ b/test/fixture/cachedir_foo_value/SConstruct @@ -0,0 +1,19 @@ +import SCons.Node + +CacheDir('cache') + +def b(target, source, env): + with open(target[0].abspath, 'w') as f: + pass + +def scan(node, env, path): + return [env.Value('a')] + +scanner = Scanner(function=scan, node_class=SCons.Node.Node) +builder = Builder(action=b, source_scanner=scanner) + +env = Environment() +env.Append(BUILDERS={'B': builder}) + +env.B(target='File1.out', source='foo.c') +#env.Program('foo', foo_c) diff --git a/test/fixture/cachedir_foo_value/foo.c b/test/fixture/cachedir_foo_value/foo.c new file mode 100644 index 0000000..5ab8d0f --- /dev/null +++ b/test/fixture/cachedir_foo_value/foo.c @@ -0,0 +1 @@ +int main(void){ return 0; } -- cgit v0.12 From 4463d8629c5945d8973818a32be55334617e0d6c Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Thu, 12 Dec 2019 08:06:20 -0500 Subject: Address PR feedback --- src/engine/SCons/Node/PythonTests.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/engine/SCons/Node/PythonTests.py b/src/engine/SCons/Node/PythonTests.py index e05cfc9..e1aa58b 100644 --- a/src/engine/SCons/Node/PythonTests.py +++ b/src/engine/SCons/Node/PythonTests.py @@ -113,7 +113,7 @@ class ValueBuildInfoTestCase(unittest.TestCase): class ValueMemoTestCase(unittest.TestCase): - def test___init__(self): + def test_memo(self): """Test memoization""" # First confirm that ValueWithMemo does memoization. value1 = SCons.Node.Python.ValueWithMemo('vvv') @@ -126,9 +126,7 @@ class ValueMemoTestCase(unittest.TestCase): value3 = ni.str_to_node('vvv') assert value1 is value3 - -class BuiltValueNoMemoTestCase(unittest.TestCase): - def test___init__(self): + def test_built_value(self): """Confirm that built values are not memoized.""" v1 = SCons.Node.Python.Value('c', 'ca') v2 = SCons.Node.Python.Value('c', 'ca') -- cgit v0.12 From 1098fdbdd9bba34baaf25266e4f4e7166d17ac68 Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Tue, 17 Dec 2019 16:39:48 -0500 Subject: Separate out Python suffixes into another variable --- src/engine/SCons/Scanner/Python.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/engine/SCons/Scanner/Python.py b/src/engine/SCons/Scanner/Python.py index 825928d..bbe65ff 100644 --- a/src/engine/SCons/Scanner/Python.py +++ b/src/engine/SCons/Scanner/Python.py @@ -159,5 +159,6 @@ def scan(node, env, path=()): return sorted(nodes) -PythonScanner = SCons.Scanner.Base(scan, name='PythonScanner', skeys=['.py'], +PythonSuffixes = ['.py'] +PythonScanner = SCons.Scanner.Base(scan, name='PythonScanner', skeys=PythonSuffixes, path_function=path_function, recursive=1) -- cgit v0.12 From 99318498919eb5f7132bc1be239c8eba86e230d7 Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Tue, 17 Dec 2019 18:32:24 -0500 Subject: Fix over-80-characters issue and add formatting block at bottom --- src/engine/SCons/Scanner/Python.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/engine/SCons/Scanner/Python.py b/src/engine/SCons/Scanner/Python.py index bbe65ff..0ab3111 100644 --- a/src/engine/SCons/Scanner/Python.py +++ b/src/engine/SCons/Scanner/Python.py @@ -160,5 +160,12 @@ def scan(node, env, path=()): PythonSuffixes = ['.py'] -PythonScanner = SCons.Scanner.Base(scan, name='PythonScanner', skeys=PythonSuffixes, +PythonScanner = SCons.Scanner.Base(scan, name='PythonScanner', + skeys=PythonSuffixes, path_function=path_function, recursive=1) + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: -- cgit v0.12 From dc488653a4612b2d8f2fcc75ea1269e1a9d2235f Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 18 Dec 2019 15:34:20 -0500 Subject: Add new paths for mingw and msys64 for appveyor VS2019 image. Hopefully doens't break other images --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index 09cd996..b1b718d 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -19,7 +19,7 @@ install: - cmd: "C:\\%WINPYTHON%\\python.exe --version" - cmd: for /F "tokens=*" %%g in ('C:\\%WINPYTHON%\\python.exe -m site --user-site') do (set PYSITEDIR=%%g) # use mingw 32 bit until #3291 is resolved - - cmd: "set PATH=C:\\%WINPYTHON%;C:\\%WINPYTHON%\\Scripts;C:\\ProgramData\\chocolatey\\bin;C:\\MinGW\\bin;C:\\MinGW\\msys\\1.0\\bin;C:\\cygwin\\bin;%PATH%" + - cmd: "set PATH=C:\\%WINPYTHON%;C:\\%WINPYTHON%\\Scripts;C:\\ProgramData\\chocolatey\\bin;C:\\MinGW\\bin;C:\\MinGW\\msys\\1.0\\bin;C:\\cygwin\\bin;C:\msys64\usr\bin;C:\msys64\mingw64\bin;%PATH%" - cmd: "C:\\%WINPYTHON%\\python.exe -m pip install -U --progress-bar off pip setuptools wheel " - cmd: "C:\\%WINPYTHON%\\python.exe -m pip install -U --progress-bar off pypiwin32 coverage codecov" - cmd: set STATIC_DEPS=true & C:\\%WINPYTHON%\\python.exe -m pip install -U --progress-bar off lxml -- cgit v0.12 From 4d53fb2838087c2284cf5756a3be69adc2c67245 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 18 Dec 2019 15:55:00 -0500 Subject: [travis skip] Fix YAML escaping --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index b1b718d..9a94529 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -19,7 +19,7 @@ install: - cmd: "C:\\%WINPYTHON%\\python.exe --version" - cmd: for /F "tokens=*" %%g in ('C:\\%WINPYTHON%\\python.exe -m site --user-site') do (set PYSITEDIR=%%g) # use mingw 32 bit until #3291 is resolved - - cmd: "set PATH=C:\\%WINPYTHON%;C:\\%WINPYTHON%\\Scripts;C:\\ProgramData\\chocolatey\\bin;C:\\MinGW\\bin;C:\\MinGW\\msys\\1.0\\bin;C:\\cygwin\\bin;C:\msys64\usr\bin;C:\msys64\mingw64\bin;%PATH%" + - cmd: "set PATH=C:\\%WINPYTHON%;C:\\%WINPYTHON%\\Scripts;C:\\ProgramData\\chocolatey\\bin;C:\\MinGW\\bin;C:\\MinGW\\msys\\1.0\\bin;C:\\cygwin\\bin;C:\\msys64\\usr\\bin;C:\\msys64\\mingw64\\bin;%PATH%" - cmd: "C:\\%WINPYTHON%\\python.exe -m pip install -U --progress-bar off pip setuptools wheel " - cmd: "C:\\%WINPYTHON%\\python.exe -m pip install -U --progress-bar off pypiwin32 coverage codecov" - cmd: set STATIC_DEPS=true & C:\\%WINPYTHON%\\python.exe -m pip install -U --progress-bar off lxml -- cgit v0.12 From 9cb4b26d0b22fadb5ffbe2f612890b0dc024de98 Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Wed, 18 Dec 2019 19:12:08 -0500 Subject: Add Python.py to the manifest file --- src/engine/MANIFEST.in | 1 + 1 file changed, 1 insertion(+) diff --git a/src/engine/MANIFEST.in b/src/engine/MANIFEST.in index 3125824..7cd9928 100644 --- a/src/engine/MANIFEST.in +++ b/src/engine/MANIFEST.in @@ -40,6 +40,7 @@ SCons/Scanner/Fortran.py SCons/Scanner/IDL.py SCons/Scanner/LaTeX.py SCons/Scanner/Prog.py +SCons/Scanner/Python.py SCons/Scanner/RC.py SCons/Scanner/SWIG.py SCons/SConf.py -- cgit v0.12 From d252e54734cf5c0501a689f37a00a27c0ff1a39d Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sat, 14 Dec 2019 07:40:27 -0700 Subject: Update manpage intro section [ci skip] Side effect: added an entry to scons.mod for the sconscript function (it didn't have one since the name itself was already in use). Change the type of a few entities. Those changes don't have a content effect, just a presentation effect. Signed-off-by: Mats Wichmann --- doc/generated/variables.gen | 11 -- doc/man/scons.xml | 307 ++++++++++++++++++++++---------------------- doc/scons.mod | 45 +++---- 3 files changed, 176 insertions(+), 187 deletions(-) diff --git a/doc/generated/variables.gen b/doc/generated/variables.gen index 9050832..21e0b1f 100644 --- a/doc/generated/variables.gen +++ b/doc/generated/variables.gen @@ -3448,17 +3448,6 @@ If this is not set, then - LDMODULEEMITTER - - -Contains the emitter specification for the -LoadableModule builder. -The manpage section "Builder Objects" contains -general information on specifying emitters. - - - LDMODULEFLAGS diff --git a/doc/man/scons.xml b/doc/man/scons.xml index 899669e..26370f6 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -93,72 +93,67 @@ -DESCRIPTION -The + +DESCRIPTION + scons -utility builds software (or other files) by determining which -component pieces must be rebuilt and executing the necessary commands to -rebuild them. +orchestrates the construction of software +(and other tangible products such as documentation files) +by determining which +component pieces must be built or rebuilt and invoking the necessary +commands to build them. + +You instruct +scons by writing a configuration file +which specifies the files to be built (targets), +and, if necessary, the rules to build those files. Premade +rules exist for building many common software components +(such as executable programs, object files, libraries), +so that for most software projects, +only the target and input files need be specified. -By default, -scons + +When invoked, scons searches for a file named -SConstruct, -Sconstruct, -sconstruct, -SConstruct.py -Sconstruct.py -or -sconstruct.py -(in that order) in the current directory and reads its -configuration from the first file found. +&SConstruct; +(going on to check alternative names +&Sconstruct;, &sconstruct;, &SConstruct.py; &Sconstruct.py; +and &sconstruct.py; +in that order) in the current directory and reads its +configuration from that file. An alternate file name may be specified via the -option. - -The -SConstruct +option. +The &SConstruct; file can specify subsidiary configuration files using the -SConscript() -function. +&SConscriptFunc; function. By convention, these subsidiary files are named -SConscript, +&SConscript;, although any name may be used. -(Because of this naming convention, -the term "SConscript files" -is sometimes used to refer -generically to all -scons -configuration files, -regardless of actual file name.) - -The configuration files -specify the target files to be built, and -(optionally) the rules to build those targets. Reasonable default -rules exist for building common software components (executable -programs, object files, libraries), so that for most software -projects, only the target and input files need be specified. - -Before reading the -SConstruct -file, +As a result of this naming convention, +the term SConscript files +is often used to refer +generically to the complete set of +configuration files for a project, +including the &SConstruct; file, +regardless of the actual file names or number of files. + +Before reading the SConscript files, scons looks for a directory named -site_scons -in various system directories (see below) and the directory containing the -SConstruct -file; for each of those dirs which exists, -site_scons -is prepended to sys.path, -the file -site_scons/site_init.py, -is evaluated if it exists, +site_scons +in various system directories and the directory containing the +&SConstruct; file: each such directory which exists +is prepended to sys.path; +the file site_init.py +is evaluated if it exists in that directory; and the directory -site_scons/site_tools -is prepended to the default toolpath if it exists. +site_tools +is prepended to the default toolpath +if it exists in that directory. See the and @@ -169,12 +164,14 @@ options for more details. reads and executes the SConscript files as Python scripts, so you may use normal Python scripting capabilities (such as flow control, data manipulation, and imported Python libraries) -to handle complicated build situations. -scons, -however, reads and executes all of the SConscript files +to handle complicated build situations. + + +scons +reads and executes all of the SConscript files before it begins building any targets. -To make this obvious, +To make this clear, scons prints the following messages about what it is doing: @@ -189,7 +186,7 @@ $ The status messages -(everything except the line that reads "cp foo.in foo.out") +(lines beginning with the scons: tag) may be suppressed using the option. @@ -209,34 +206,28 @@ that you want to use to build your target files are not in standard system locations, scons will not find them unless -you explicitly set the PATH +you explicitly set the scons +PATH in the internal environment to include those locations. -Whenever you create an -scons -construction environment, +Whenever you create a &consenv;, you can propagate the value of PATH from your external environment as follows: import os -env = Environment(ENV = {'PATH' : os.environ['PATH']}) +env = Environment(ENV={'PATH': os.environ['PATH']}) -Similarly, if the commands use external environment variables -like -PATH, -HOME, -JAVA_HOME, -LANG, -SHELL, -TERM, -etc., -these variables can also be explicitly propagated: +Similarly, if the commands use specific +external environment variables that scons +does not recognize, they can be propagated into +the internal environment: import os -env = Environment(ENV = {'PATH': os.environ['PATH'], - 'HOME': os.environ['HOME']}) +env = Environment(ENV={'PATH': os.environ['PATH'], + 'ANDROID_HOME': os.environ['ANDROID_HOME'], + 'ANDROID_NDK_HOME': os.environ['ANDROID_NDK_HOME']}) Or you may explicitly propagate the invoking user's @@ -244,17 +235,23 @@ complete external environment: import os -env = Environment(ENV = os.environ) +env = Environment(ENV=os.environ) This comes at the expense of making your build dependent on the user's environment being set correctly, -but it may be more convenient for many configurations. +but it may be more convenient for many configurations. +It should not cause problems if done in a build setup which tightly +controls how the environment is set up before invoking +scons, as in many continuous +integration setups. + scons can scan known input files automatically for dependency -information (for example, #include statements -in C or C++ files) and will rebuild dependent files appropriately +information (for example, #include +preprocessor directives in C or C++ files) +and will rebuild dependent files appropriately whenever any "included" input file changes. scons supports the @@ -266,41 +263,46 @@ SCCS or RCS subdirectories using SCCS, RCS or BitKeeper. scons -is normally executed in a top-level directory containing a -SConstruct -file, optionally specifying -as command-line arguments -the target file or files to be built. - -By default, the command - - -scons - +is normally executed in a top-level directory containing an +&SConstruct; file. +When scons is invoked, +the command line (including the contents +of the &SCONSFLAGS; environment variable, +if set) is processed. +The options are consumed (see ; +and also note that SConscript files may define additional options +for the project using the &AddOption; function). +Any variable argument assignments (see below) are also consumed. +Any remaining arguments are taken as the targets to build. +Targets on the command line may be files, directories, +or phony targets defined using the &Alias; function. +The command line targets are available in the +&COMMAND_LINE_TARGETS; list. + -will build all target files in or below the current directory. -Explicit default targets -(to be built when no targets are specified on the command line) -may be defined in the SConscript file(s) -using the -Default() -function, described below. +If no targets are specified on the command line, +scons +will build the default targets. The default targets +are those specified in the SConscript files via calls +to the &Default; function; if none, the default targets are +those target files in or below the current directory. +Targets specified via the &Default; function are available +in the &DEFAULT_TARGETS; list. + -Even when -Default() -targets are specified in the SConscript file(s), -all target files in or below the current directory -may be built by explicitly specifying -the current directory (.) +To ignore the default targets specified +through calls to &Default; and instead build all +target files in or below the current directory +specify the current directory (.) as a command-line target: scons . -Building all target files, +To build all target files, including any files outside of the current directory, -may be specified by supplying a command-line target +supply a command-line target of the root directory (on POSIX systems): @@ -314,15 +316,33 @@ should be built (on Windows systems): scons C:\ D:\ -To build only specific targets, -supply them as command-line arguments: +A subset of a hierarchical tree may be built by +remaining at the top-level directory (where the +&SConstruct; +file lives) and specifying the subdirectory as the target to +build: -scons foo bar +scons src/subdir + + +or by changing directory and invoking scons with the + +option, which traverses up the directory +hierarchy until it finds the +&SConstruct; +file, and then builds +targets relatively to the current subdirectory (see +also the related and options): + + +cd src/subdir +scons -u . -in which case only the specified targets will be built -(along with any derived files on which they depend). +In all cases, more files may be built than are +requested, as scons needs to make +sure any dependent files are built. Specifying "cleanup" targets in SConscript files is not usually necessary. The @@ -334,45 +354,22 @@ necessary to build the specified target: scons -c . -to remove all target files, or: +to remove all target files in or under the current directory, or: scons -c build export -to remove target files under build and export. +to remove target files under build +and export. + + Additional files or directories to remove can be specified using the -Clean() -function. +&Clean; function in the SConscript files. Conversely, targets that would normally be removed by the -invocation -can be prevented from being removed by using the -NoClean() -function. - -A subset of a hierarchical tree may be built by -remaining at the top-level directory (where the -SConstruct -file lives) and specifying the subdirectory as the target to be -built: - - -scons src/subdir - - -or by changing directory and invoking scons with the - -option, which traverses up the directory -hierarchy until it finds the -SConstruct -file, and then builds -targets relatively to the current subdirectory: - - -cd src/subdir -scons -u . - +invocation can be retained by calling the +&NoClean; function with those targets. scons supports building multiple targets in parallel via a @@ -405,16 +402,16 @@ command-line options. The option is useful to prevent multiple builds from trying to update the cache simultaneously. -Values of variables to be passed to the SConscript file(s) +Values of variables to be passed to the SConscript files may be specified on the command line: scons debug=1 . -These variables are available in SConscript files -through the ARGUMENTS dictionary, -and can be used in the SConscript file(s) to modify +These variables are available +through the &ARGUMENTS; dictionary, +and can be used in the SConscript files to modify the build in any way: @@ -425,13 +422,12 @@ else: The command-line variable arguments are also available -in the ARGLIST list, +in the &ARGLIST; list, indexed by their order on the command line. This allows you to process them in order rather than by name, -if necessary. -ARGLIST[0] returns a tuple -containing (argname, argvalue). -A Python exception is thrown if you +if necessary. Each &ARGLIST; entry is a tuple +containing (argname, argvalue). +A Python IndexError exception is raised if you try to access a list member that does not exist. @@ -443,24 +439,28 @@ There should be no other dependencies or requirements to run + By default, scons -knows how to search for available programming tools -on various systems. -On Windows systems, +searches for known programming tools +on various systems and initializes itself based on what is found. +On Windows systems which identify as win32, scons searches in order for the Microsoft Visual C++ tools, the MinGW tool chain, the Intel compiler tools, and the PharLap ETS compiler. +On Windows system which identify as cygwin +(that is, if scons is invoked from a cygwin shell), +the order changes to prefer the GCC toolchain over the MSVC tools. On OS/2 systems, scons searches in order for the OS/2 compiler, the GCC tool chain, and the Microsoft Visual C++ tools, -On SGI IRIX, IBM AIX, Hewlett Packard HP-UX, and Sun Solaris systems, +On SGI IRIX, IBM AIX, Hewlett Packard HP-UX, and Oracle Solaris systems, scons searches for the native compiler tools (MIPSpro, Visual Age, aCC, and Forte tools respectively) @@ -470,7 +470,6 @@ including POSIX (Linux and UNIX) platforms, scons searches in order for the GCC tool chain, -the Microsoft Visual C++ tools, and the Intel compiler tools. You may, of course, override these default values by appropriate configuration of diff --git a/doc/scons.mod b/doc/scons.mod index 3e843a0..024afab 100644 --- a/doc/scons.mod +++ b/doc/scons.mod @@ -225,6 +225,7 @@ NoCache"> Objects"> Options"> +SConscript"> Variables"> PackageOption"> PackageVariable"> @@ -418,27 +419,27 @@ --> -builder function"> -build action"> -build actions"> -builder method"> +builder function"> +build action"> +build actions"> +builder method"> -Configure Contexts"> -configure context"> +Configure Contexts"> +configure context"> -Construction Environment"> -Construction Environments"> -Construction environment"> -Construction environments"> -construction environment"> -construction environments"> +Construction Environment"> +Construction Environments"> +Construction environment"> +Construction environments"> +construction environment"> +construction environments"> -Construction Variable"> -Construction Variables"> -Construction variable"> -Construction variables"> -construction variable"> -construction variables"> +Construction Variable"> +Construction Variables"> +Construction variable"> +Construction variables"> +construction variable"> +construction variables"> CPPPATH"> @@ -529,14 +530,14 @@ --> -announce@scons.tigris.org"> -scons-dev@scons.org"> -scons-users@scons.org"> +announce@scons.tigris.org"> +scons-dev@scons.org"> +scons-users@scons.org"> -- cgit v0.12 From 7fed3fac34613ca78cddf7fc7279032eca6fd989 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 20 Dec 2019 15:41:34 -0700 Subject: [PR #3501] review - modify site_scons description [ci skip] Signed-off-by: Mats Wichmann --- doc/man/scons.xml | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index 26370f6..7ec972e 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -145,20 +145,23 @@ regardless of the actual file names or number of files. scons looks for a directory named site_scons -in various system directories and the directory containing the -&SConstruct; file: each such directory which exists -is prepended to sys.path; -the file site_init.py -is evaluated if it exists in that directory; -and the directory -site_tools -is prepended to the default toolpath -if it exists in that directory. +in various system directories and in the directory containing the +&SConstruct; file and prepends the ones it +finds to the Python module search path (sys.path), +thus allowing modules in such directories to be imported in +the normal Python way in SConscript files. +For each found site directory, +if it contains a file site_init.py +it is evaluated, and if it contains a directory +site_tools the path to it +is prepended to the default toolpath. See the - -and -options for more details. +and + +options for details on default paths and +controlling the site directories. + scons reads and executes the SConscript files as Python scripts, -- cgit v0.12 From 7ba3919aa8d401d07c6920c6b84dc657a381cb5e Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sat, 21 Dec 2019 11:56:08 -0700 Subject: checker fixes: None, trailing ws, list init checker-suggested fixes: Mostly, fix remaining instances of comparing none without "is" Some trailing whitespace on lines A couple of instances of list init followed immediately by several appends, turned into a single list init Some double comparisons turned into a single expression Signed-off-by: Mats Wichmann --- doc/SConscript | 2 +- src/engine/SCons/Node/FSTests.py | 13 +++++----- src/engine/SCons/SConf.py | 2 +- src/engine/SCons/Scanner/ScannerTests.py | 4 +--- src/engine/SCons/Tool/MSCommon/vc.py | 4 ++-- .../docbook-xsl-1.76.1/extensions/docbook.py | 12 +++++----- src/engine/SCons/Util.py | 28 ++++++++++++---------- src/engine/SCons/UtilTests.py | 10 ++++---- test/Value.py | 6 ++--- testing/framework/TestCmd.py | 2 +- testing/framework/TestCmdTests.py | 18 +++++++------- 11 files changed, 51 insertions(+), 50 deletions(-) diff --git a/doc/SConscript b/doc/SConscript index 51ef2db..ff29a70 100644 --- a/doc/SConscript +++ b/doc/SConscript @@ -525,7 +525,7 @@ if not epydoc_cli: # first arg is a list where can be names of python package dirs, # python files, object names or objects itself docindex = build_doc_index([str(src) for src in source]) - if docindex == None: + if docindex is None: return -1 if env['EPYDOCFLAGS'] == '--html': diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index eddfdf0..9c19481 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -2508,8 +2508,8 @@ class FileTestCase(_tempdirTestCase): build_f1, src_f1) def test_changed(self): - """ - Verify that changes between BuildInfo's list of souces, depends, and implicit + """ + Verify that changes between BuildInfo's list of souces, depends, and implicit dependencies do not corrupt content signature values written to .SConsign when using CacheDir and Timestamp-MD5 decider. This is for issue #2980 @@ -3374,10 +3374,11 @@ class find_fileTestCase(unittest.TestCase): node_pseudo.set_src_builder(1) # Any non-zero value. paths = tuple(map(fs.Dir, ['.', 'same', './bar'])) - nodes = [SCons.Node.FS.find_file('foo', paths)] - nodes.append(SCons.Node.FS.find_file('baz', paths)) - nodes.append(SCons.Node.FS.find_file('pseudo', paths)) - nodes.append(SCons.Node.FS.find_file('same', paths)) + nodes = [SCons.Node.FS.find_file('foo', paths), + SCons.Node.FS.find_file('baz', paths), + SCons.Node.FS.find_file('pseudo', paths), + SCons.Node.FS.find_file('same', paths) + ] file_names = list(map(str, nodes)) file_names = list(map(os.path.normpath, file_names)) diff --git a/src/engine/SCons/SConf.py b/src/engine/SCons/SConf.py index 71729c9..0195ac4 100644 --- a/src/engine/SCons/SConf.py +++ b/src/engine/SCons/SConf.py @@ -1067,7 +1067,7 @@ def CheckLibWithHeader(context, libs, header, language, """ prog_prefix, dummy = \ createIncludesFromHeaders(header, 0) - if libs == []: + if not libs: libs = [None] if not SCons.Util.is_List(libs): diff --git a/src/engine/SCons/Scanner/ScannerTests.py b/src/engine/SCons/Scanner/ScannerTests.py index 64a2345..abe4042 100644 --- a/src/engine/SCons/Scanner/ScannerTests.py +++ b/src/engine/SCons/Scanner/ScannerTests.py @@ -236,7 +236,7 @@ class BaseTestCase(unittest.TestCase): def test___cmp__(self): """Test the Scanner.Base class __cmp__() method""" s = SCons.Scanner.Base(self.func, "Cmp") - assert s != None + assert s is not None def test_hash(self): """Test the Scanner.Base class __hash__() method""" @@ -578,8 +578,6 @@ class ClassicTestCase(unittest.TestCase): "recursive = 1 didn't return all nodes: %s" % n) - - class ClassicCPPTestCase(unittest.TestCase): def test_find_include(self): """Test the Scanner.ClassicCPP find_include() method""" diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py index 86bdbe0..53b9d59 100644 --- a/src/engine/SCons/Tool/MSCommon/vc.py +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -509,7 +509,7 @@ def _check_cl_exists_in_vc_dir(env, vc_dir, msvc_version): debug('_check_cl_exists_in_vc_dir(): found ' + _CL_EXE_NAME + '!') return True - elif ver_num <= 14 and ver_num >= 8: + elif 14 >= ver_num >= 8: # Set default value to be -1 as "" which is the value for x86/x86 yields true when tested # if not host_trgt_dir @@ -541,7 +541,7 @@ def _check_cl_exists_in_vc_dir(env, vc_dir, msvc_version): debug('_check_cl_exists_in_vc_dir(): found ' + _CL_EXE_NAME + '!') return True - elif ver_num < 8 and ver_num >= 6: + elif 8 > ver_num >= 6: # not sure about these versions so if a walk the VC dir (could be slow) for root, _, files in os.walk(vc_dir): if _CL_EXE_NAME in files: diff --git a/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/docbook.py b/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/docbook.py index e7b8cfa..5d2de3e 100644 --- a/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/docbook.py +++ b/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/docbook.py @@ -33,7 +33,7 @@ def adjustColumnWidths(ctx, nodeset): # Get the nominal table width varString = lookupVariable(tctxt, "nominal.table.width", None) - if varString == None: + if varString is None: nominalWidth = 6 * pixelsPerInch; else: nominalWidth = convertLength(varString); @@ -58,13 +58,13 @@ def adjustColumnWidths(ctx, nodeset): colChildren = colgroup.children col = colChildren - while col != None: + while col is not None: if foStylesheet: width = col.prop("column-width") else: width = col.prop("width") - if width == None: + if width is None: width = "1*" relPart = 0.0 @@ -145,7 +145,7 @@ def adjustColumnWidths(ctx, nodeset): # Side-effect free? We don' need no steenkin' side-effect free! count = 0 col = colChildren - while col != None: + while col is not None: if foStylesheet: col.setProp("column-width", widths[count]) else: @@ -162,7 +162,7 @@ def convertLength(length): global unitHash m = re.search('([+-]?[\d\.]+)(\S+)', length) - if m != None and m.lastindex > 1: + if m is not None and m.lastindex > 1: unit = pixelsPerInch if m.group(2) in unitHash: unit = unitHash[m.group(2)] @@ -204,7 +204,7 @@ def correctRoundingError(floatWidths): def lookupVariable(tctxt, varName, default): varString = tctxt.variableLookup(varName, None) - if varString == None: + if varString is None: return default # If it's a list, get the first element diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index 8519a98..28674d1 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -312,18 +312,21 @@ def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited=None): '\n') sys.stdout.write(legend) - tags = ['['] - tags.append(' E'[IDX(root.exists())]) - tags.append(' R'[IDX(root.rexists() and not root.exists())]) - tags.append(' BbB'[[0,1][IDX(root.has_explicit_builder())] + - [0,2][IDX(root.has_builder())]]) - tags.append(' S'[IDX(root.side_effect)]) - tags.append(' P'[IDX(root.precious)]) - tags.append(' A'[IDX(root.always_build)]) - tags.append(' C'[IDX(root.is_up_to_date())]) - tags.append(' N'[IDX(root.noclean)]) - tags.append(' H'[IDX(root.nocache)]) - tags.append(']') + tags = [ + '[', + ' E'[IDX(root.exists())], + ' R'[IDX(root.rexists() and not root.exists())], + ' BbB'[ + [0, 1][IDX(root.has_explicit_builder())] + + [0, 2][IDX(root.has_builder())] + ], + ' S'[IDX(root.side_effect)], ' P'[IDX(root.precious)], + ' A'[IDX(root.always_build)], + ' C'[IDX(root.is_up_to_date())], + ' N'[IDX(root.noclean)], + ' H'[IDX(root.nocache)], + ']' + ] else: tags = [] @@ -352,7 +355,6 @@ def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited=None): margin.pop() - # Functions for deciding if things are like various types, mainly to # handle UserDict, UserList and UserString like their underlying types. # diff --git a/src/engine/SCons/UtilTests.py b/src/engine/SCons/UtilTests.py index 0017844..7f6508d 100644 --- a/src/engine/SCons/UtilTests.py +++ b/src/engine/SCons/UtilTests.py @@ -451,11 +451,11 @@ class UtilTestCase(unittest.TestCase): assert get_environment_var("${BAR}") == "BAR", get_environment_var("${BAR}") assert get_environment_var("$FOO_BAR1234") == "FOO_BAR1234", get_environment_var("$FOO_BAR1234") assert get_environment_var("${BAR_FOO1234}") == "BAR_FOO1234", get_environment_var("${BAR_FOO1234}") - assert get_environment_var("${BAR}FOO") == None, get_environment_var("${BAR}FOO") - assert get_environment_var("$BAR ") == None, get_environment_var("$BAR ") - assert get_environment_var("FOO$BAR") == None, get_environment_var("FOO$BAR") - assert get_environment_var("$FOO[0]") == None, get_environment_var("$FOO[0]") - assert get_environment_var("${some('complex expression')}") == None, get_environment_var( + assert get_environment_var("${BAR}FOO") is None, get_environment_var("${BAR}FOO") + assert get_environment_var("$BAR ") is None, get_environment_var("$BAR ") + assert get_environment_var("FOO$BAR") is None, get_environment_var("FOO$BAR") + assert get_environment_var("$FOO[0]") is None, get_environment_var("$FOO[0]") + assert get_environment_var("${some('complex expression')}") is None, get_environment_var( "${some('complex expression')}") def test_Proxy(self): diff --git a/test/Value.py b/test/Value.py index c1f764a..8f6c7fe 100644 --- a/test/Value.py +++ b/test/Value.py @@ -102,7 +102,7 @@ for source_signature in ['MD5', 'timestamp-newer']: test.must_contain_all_lines(test.stdout(), [out1, out2, out7, out8]) #print test.stdout() - test.fail_test(re.search(out3, test.stdout()) == None) + test.fail_test(re.search(out3, test.stdout()) is None) test.must_match('f1.out', "/usr/local") test.must_match('f2.out', "10") @@ -118,7 +118,7 @@ for source_signature in ['MD5', 'timestamp-newer']: out6 = """create\\(\\["f3.out"\\], \\[<.*.Custom (instance|object) at """ #" <- unconfuses emacs syntax highlighting test.must_contain_all_lines(test.stdout(), [out4, out5]) - test.fail_test(re.search(out6, test.stdout()) == None) + test.fail_test(re.search(out6, test.stdout()) is None) test.must_match('f1.out', "/usr") test.must_match('f2.out', "4") @@ -134,7 +134,7 @@ for source_signature in ['MD5', 'timestamp-newer']: test.must_contain_all_lines(test.stdout(), [out4, out7, out8]) test.must_not_contain_any_line(test.stdout(), [out5]) - test.fail_test(re.search(out6, test.stdout()) == None) + test.fail_test(re.search(out6, test.stdout()) is None) test.up_to_date(options='prefix=/var', arguments='.') diff --git a/testing/framework/TestCmd.py b/testing/framework/TestCmd.py index 9218f60..447d050 100644 --- a/testing/framework/TestCmd.py +++ b/testing/framework/TestCmd.py @@ -1805,7 +1805,7 @@ class TestCmd(object): path name. If the path is a null string (''), a unique directory name is created. """ - if (path != None): + if path is not None: if path == '': path = None path = self.tempdir(path) diff --git a/testing/framework/TestCmdTests.py b/testing/framework/TestCmdTests.py index ef76228..541df71 100644 --- a/testing/framework/TestCmdTests.py +++ b/testing/framework/TestCmdTests.py @@ -1737,7 +1737,7 @@ class run_TestCase(TestCmdTestCase): pass test.run(program = 'no_script', interpreter = 'python') - assert test.status != None, test.status + assert test.status is not None, test.status try: test.run(program = 'no_script', interpreter = 'no_interpreter') @@ -1750,7 +1750,7 @@ class run_TestCase(TestCmdTestCase): # Python versions that use os.popen3() or the Popen3 # class run things through the shell, which just returns # a non-zero exit status. - assert test.status != None, test.status + assert test.status is not None, test.status testx = TestCmd.TestCmd(program = t.scriptx, workdir = '', @@ -1816,7 +1816,7 @@ class run_TestCase(TestCmdTestCase): # Python versions that use os.popen3() or the Popen3 # class run things through the shell, which just returns # a non-zero exit status. - assert test.status != None + assert test.status is not None test1 = TestCmd.TestCmd(program = t.script1, interpreter = ['python', '-x'], @@ -2388,7 +2388,7 @@ with open(r'%s', 'wb') as logfp: p = test.start(program='no_script', interpreter='python') status = p.wait() - assert status != None, status + assert status is not None, status try: p = test.start(program='no_script', interpreter='no_interpreter') @@ -2402,7 +2402,7 @@ with open(r'%s', 'wb') as logfp: # Python versions that use os.popen3() or the Popen3 # class run things through the shell, which just returns # a non-zero exit status. - assert status != None, status + assert status is not None, status testx = TestCmd.TestCmd(program = t.scriptx, workdir = '', @@ -3054,11 +3054,11 @@ class workdir_TestCase(TestCmdTestCase): assert test.workdir is None test = TestCmd.TestCmd(workdir = '') - assert test.workdir != None + assert test.workdir is not None assert os.path.isdir(test.workdir) test = TestCmd.TestCmd(workdir = 'dir') - assert test.workdir != None + assert test.workdir is not None assert os.path.isdir(test.workdir) no_such_subdir = os.path.join('no', 'such', 'subdir') @@ -3071,11 +3071,11 @@ class workdir_TestCase(TestCmdTestCase): test = TestCmd.TestCmd(workdir = 'foo') workdir_foo = test.workdir - assert workdir_foo != None + assert workdir_foo is not None test.workdir_set('bar') workdir_bar = test.workdir - assert workdir_bar != None + assert workdir_bar is not None try: test.workdir_set(no_such_subdir) -- cgit v0.12 From 4f6fa862878fa4c14ea8895bec2476d394385d57 Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Mon, 23 Dec 2019 10:10:01 -0500 Subject: Exclude non-primitive values from memoization --- src/engine/SCons/Node/Python.py | 5 +++++ src/engine/SCons/Node/PythonTests.py | 12 ++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/engine/SCons/Node/Python.py b/src/engine/SCons/Node/Python.py index 7b25edb..1fb2866 100644 --- a/src/engine/SCons/Node/Python.py +++ b/src/engine/SCons/Node/Python.py @@ -184,6 +184,11 @@ def ValueWithMemo(value, built_value=None): if built_value: return Value(value, built_value) + # No current support for memoizing non-primitive types in case they change + # after this call. + if not isinstance(value, (int, str, float, bool)): + return Value(value, built_value) + value_str = str(value) if value_str in _memoLookupMap: return _memoLookupMap[value_str] diff --git a/src/engine/SCons/Node/PythonTests.py b/src/engine/SCons/Node/PythonTests.py index e1aa58b..6af3e60 100644 --- a/src/engine/SCons/Node/PythonTests.py +++ b/src/engine/SCons/Node/PythonTests.py @@ -132,6 +132,18 @@ class ValueMemoTestCase(unittest.TestCase): v2 = SCons.Node.Python.Value('c', 'ca') assert v1 is not v2 + def test_non_primitive_values(self): + """Confirm that non-primitive values are not memoized.""" + d = {'a': 1} + v1 = SCons.Node.Python.Value(d) + v2 = SCons.Node.Python.Value(d) + assert v1 is not v2 + + l = [1] + v3 = SCons.Node.Python.Value(l) + v4 = SCons.Node.Python.Value(l) + assert v3 is not v4 + if __name__ == "__main__": unittest.main() -- cgit v0.12 From a5359e3f10a6bcdb5d9667c95c40ddd890b551e8 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sun, 22 Dec 2019 08:44:29 -0700 Subject: syntax fixups suggested by PyCharm Drop unneeded parens. Drop trailing semicolons. Triple double-quote docstrings. Regexes drop unneeded escapes. Spaces around parens, braces: remove/add. Some one-tuples get their missing closing comma. A couple of sets use set init syntax {foo} instead of set([iter]) now. And a fiddle in Node to reduce lookup time on md5 signature functions (came about because of a line-too-long issue, initially) Signed-off-by: Mats Wichmann --- bin/SConsExamples.py | 2 +- bin/scons-diff.py | 10 +++--- bin/scons_dev_master.py | 4 +-- bin/svn-bisect.py | 2 +- bin/update-release-info.py | 26 ++++----------- site_scons/Utilities.py | 2 +- site_scons/soe_utils.py | 2 +- src/CHANGES.txt | 1 + src/engine/SCons/BuilderTests.py | 4 +-- src/engine/SCons/Environment.py | 2 +- src/engine/SCons/EnvironmentTests.py | 16 ++++----- src/engine/SCons/EnvironmentValues.py | 4 +-- src/engine/SCons/JobTests.py | 26 +++++++-------- src/engine/SCons/Node/Alias.py | 3 +- src/engine/SCons/Node/FS.py | 39 +++++++++++----------- src/engine/SCons/Node/NodeTests.py | 4 +-- src/engine/SCons/Node/__init__.py | 7 ++-- src/engine/SCons/PathListTests.py | 2 +- src/engine/SCons/Platform/virtualenv.py | 2 +- src/engine/SCons/SConf.py | 10 +++--- src/engine/SCons/SConfTests.py | 2 +- src/engine/SCons/Script/Main.py | 2 +- src/engine/SCons/Script/SConsOptions.py | 2 +- src/engine/SCons/Subst.py | 2 +- src/engine/SCons/SubstTests.py | 6 ++-- src/engine/SCons/Tool/JavaCommon.py | 6 ++-- src/engine/SCons/Tool/MSCommon/sdk.py | 4 +-- src/engine/SCons/Tool/MSCommon/vc.py | 4 +-- src/engine/SCons/Tool/__init__.py | 10 +++--- src/engine/SCons/Tool/docbook/__init__.py | 4 +-- .../docbook-xsl-1.76.1/extensions/docbook.py | 6 ++-- .../docbook/docbook-xsl-1.76.1/extensions/xslt.py | 2 +- src/engine/SCons/Tool/intelc.py | 2 +- src/engine/SCons/Tool/jar.py | 2 +- src/engine/SCons/Tool/javah.py | 2 +- src/engine/SCons/Tool/mslink.py | 4 +-- src/engine/SCons/Tool/msvs.py | 14 ++++---- src/engine/SCons/Tool/packaging/msi.py | 2 +- src/engine/SCons/Tool/tex.py | 8 ++--- src/engine/SCons/Tool/xgettext.py | 2 +- src/engine/SCons/Util.py | 2 +- src/engine/SCons/dblite.py | 15 +++++---- src/script/scons-configure-cache.py | 8 ++--- src/script/scons-time.py | 2 +- src/script/sconsign.py | 2 +- test/CC/SHCCFLAGS.py | 2 +- test/CC/SHCFLAGS.py | 2 +- test/CacheDir/readonly-cache.py | 10 +++--- test/Configure/ConfigureDryRunError.py | 2 +- test/D/Support/executablesSearch.py | 4 +-- test/Exit.py | 2 +- test/LINK/LINKCOMSTR.py | 2 +- test/LINK/SHLINKCOMSTR.py | 2 +- test/LINK/applelink.py | 2 +- test/MSVS/vs-10.0-exec.py | 2 +- test/MSVS/vs-10.0Exp-exec.py | 2 +- test/MSVS/vs-11.0-exec.py | 2 +- test/MSVS/vs-11.0Exp-exec.py | 2 +- test/MSVS/vs-14.0-exec.py | 2 +- test/MSVS/vs-14.1-exec.py | 2 +- test/MSVS/vs-6.0-exec.py | 2 +- test/MSVS/vs-7.0-exec.py | 2 +- test/MSVS/vs-7.1-exec.py | 2 +- test/MSVS/vs-8.0-exec.py | 2 +- test/MSVS/vs-8.0Exp-exec.py | 2 +- test/MSVS/vs-9.0-exec.py | 2 +- test/MSVS/vs-9.0Exp-exec.py | 2 +- test/NodeOps.py | 2 +- test/QT/up-to-date.py | 2 +- test/Repository/SharedLibrary.py | 2 +- test/SWIG/recursive-includes-cpp.py | 2 +- test/TEX/LATEX.py | 2 +- test/TEX/LATEX2.py | 2 +- test/Win32/bad-drive.py | 2 +- test/implicit-cache/SetOption.py | 2 +- test/site_scons/sysdirs.py | 2 +- testing/framework/TestCmd.py | 2 +- testing/framework/TestCmdTests.py | 8 ++--- testing/framework/TestSCons.py | 2 +- testing/framework/TestUnit/taprunner.py | 2 +- 80 files changed, 179 insertions(+), 190 deletions(-) diff --git a/bin/SConsExamples.py b/bin/SConsExamples.py index dbb8715..50fbb4e 100644 --- a/bin/SConsExamples.py +++ b/bin/SConsExamples.py @@ -830,7 +830,7 @@ def create_scons_output(e): # regardless of reported addresses or Python version. # Massage addresses in object repr strings to a constant. - address_re = re.compile(r' at 0x[0-9a-fA-F]*\>') + address_re = re.compile(r' at 0x[0-9a-fA-F]*>') # Massage file names in stack traces (sometimes reported as absolute # paths) to a consistent relative path. diff --git a/bin/scons-diff.py b/bin/scons-diff.py index 687e7fa..0bed74b 100644 --- a/bin/scons-diff.py +++ b/bin/scons-diff.py @@ -30,7 +30,7 @@ Options: opts, args = getopt.getopt(sys.argv[1:], 'c:dhnqrsu:', - ['context=', 'help', 'recursive', 'unified=']) + ['context=', 'help', 'recursive', 'unified=']) diff_type = None edit_type = None @@ -53,17 +53,17 @@ for o, a in opts: diff_options.append(o) elif o in ('-h', '--help'): print(Usage) - sys.exit(0) - elif o in ('-n'): + sys.exit(0) + elif o in ('-n',): diff_options.append(o) edit_type = o - elif o in ('-q'): + elif o in ('-q',): diff_type = o diff_line = lambda l, r: None elif o in ('-r', '--recursive'): recursive = True diff_options.append(o) - elif o in ('-s'): + elif o in ('-s',): report_same = True try: diff --git a/bin/scons_dev_master.py b/bin/scons_dev_master.py index cdbd68e..d4c8e90 100755 --- a/bin/scons_dev_master.py +++ b/bin/scons_dev_master.py @@ -152,11 +152,11 @@ Usage: scons_dev_master.py [-hnqy] [--password PASSWORD] [--username USER] sys.exit(0) elif o in ('-n', '--no-exec'): CommandRunner.execute = CommandRunner.do_not_execute - elif o in ('--password'): + elif o in '--password': password = a elif o in ('-q', '--quiet'): CommandRunner.display = CommandRunner.do_not_display - elif o in ('--username'): + elif o in '--username': username = a elif o in ('-y', '--yes', '--assume-yes'): yesflag = o diff --git a/bin/svn-bisect.py b/bin/svn-bisect.py index dbf8dd9..575b15e 100755 --- a/bin/svn-bisect.py +++ b/bin/svn-bisect.py @@ -33,7 +33,7 @@ def error(s): # update to the specified version and run test def testfail(revision): - "Return true if test fails" + """Return true if test fails""" print("Updating to revision", revision) if subprocess.call(["svn","up","-qr",str(revision)]) != 0: m = "SVN did not update properly to revision %d" diff --git a/bin/update-release-info.py b/bin/update-release-info.py index fe5bbcf..fa7a5f8 100644 --- a/bin/update-release-info.py +++ b/bin/update-release-info.py @@ -146,13 +146,9 @@ except KeyError: if DEBUG: print('copyright years', copyright_years) class UpdateFile(object): - """ - XXX - """ + """ XXX """ def __init__(self, file, orig = None): - ''' - ''' if orig is None: orig = file try: with open(orig, 'r') as f: @@ -171,15 +167,11 @@ class UpdateFile(object): self.orig = '' def sub(self, pattern, replacement, count = 1): - ''' - XXX - ''' + """ XXX """ self.content = re.sub(pattern, replacement, self.content, count) def replace_assign(self, name, replacement, count = 1): - ''' - XXX - ''' + """ XXX """ self.sub('\n' + name + ' = .*', '\n' + name + ' = ' + replacement) # Determine the pattern to match a version @@ -189,9 +181,7 @@ class UpdateFile(object): match_rel = re.compile(match_pat) def replace_version(self, replacement = version_string, count = 1): - ''' - XXX - ''' + """ XXX """ self.content = self.match_rel.sub(replacement, self.content, count) # Determine the release date and the pattern to match a date @@ -213,15 +203,11 @@ class UpdateFile(object): match_date = re.compile(match_date) def replace_date(self, replacement = new_date, count = 1): - ''' - XXX - ''' + """ XXX """ self.content = self.match_date.sub(replacement, self.content, count) def __del__(self): - ''' - XXX - ''' + """ XXX """ if self.file is not None and self.content != self.orig: print('Updating ' + self.file + '...') with open(self.file, 'w') as f: diff --git a/site_scons/Utilities.py b/site_scons/Utilities.py index e8c0585..5bdcbf2 100644 --- a/site_scons/Utilities.py +++ b/site_scons/Utilities.py @@ -7,7 +7,7 @@ import distutils.util platform = distutils.util.get_platform() def is_windows(): - " Check if we're on a Windows platform" + """ Check if we're on a Windows platform""" if platform.startswith('win'): return True else: diff --git a/site_scons/soe_utils.py b/site_scons/soe_utils.py index 3b87dee..dfd605c 100644 --- a/site_scons/soe_utils.py +++ b/site_scons/soe_utils.py @@ -28,7 +28,7 @@ def soelim(target, source, env): def soscan(node, env, path): c = node.get_text_contents() - return re.compile(r"^[\.']so\s+(\S+)", re.M).findall(c) + return re.compile(r"^[.']so\s+(\S+)", re.M).findall(c) soelimbuilder = Builder(action = Action(soelim), source_scanner = Scanner(soscan)) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 87980a8..bd055f3 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -16,6 +16,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER From Mats Wichmann: - Remove deprecated SourceCode - str.format syntax errors fixed + - a bunch of linter/checker syntax fixups RELEASE 3.1.2 - Mon, 17 Dec 2019 02:06:27 +0000 diff --git a/src/engine/SCons/BuilderTests.py b/src/engine/SCons/BuilderTests.py index b03a425..f28e201 100644 --- a/src/engine/SCons/BuilderTests.py +++ b/src/engine/SCons/BuilderTests.py @@ -581,7 +581,7 @@ class BuilderTestCase(unittest.TestCase): assert b5.src_suffixes(env) == ['.y'], b5.src_suffixes(env) def test_srcsuffix_nonext(self): - "Test target generation from non-extension source suffixes" + """Test target generation from non-extension source suffixes""" env = Environment() b6 = SCons.Builder.Builder(action = '', src_suffix='_src.a', @@ -679,7 +679,7 @@ class BuilderTestCase(unittest.TestCase): """create the file""" with open(str(target[0]), "w"): pass - if (len(source) == 1 and len(target) == 1): + if len(source) == 1 and len(target) == 1: env['CNT'][0] = env['CNT'][0] + 1 env = Environment() diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 2c80424..19e7bd1 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -2247,7 +2247,7 @@ class Base(SubstitutionEnvironment): build_source(node.all_children()) def final_source(node): - while (node != node.srcnode()): + while node != node.srcnode(): node = node.srcnode() return node sources = list(map(final_source, sources)) diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index 52ab859..0e71f9e 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -726,7 +726,7 @@ sys.exit(0) assert r == 'replace_func2', r def test_Override(self): - "Test overriding construction variables" + """Test overriding construction variables""" env = SubstitutionEnvironment(ONE=1, TWO=2, THREE=3, FOUR=4) assert env['ONE'] == 1, env['ONE'] assert env['TWO'] == 2, env['TWO'] @@ -1408,7 +1408,7 @@ def exists(env): assert env['XYZ'] == 'ddd', env def test_concat(self): - "Test _concat()" + """Test _concat()""" e1 = self.TestEnvironment(PRE='pre', SUF='suf', STR='a b', LIST=['a', 'b']) s = e1.subst x = s("${_concat('', '', '', __env__)}") @@ -1423,7 +1423,7 @@ def exists(env): assert x == 'preasuf prebsuf', x def test_concat_nested(self): - "Test _concat() on a nested substitution strings." + """Test _concat() on a nested substitution strings.""" e = self.TestEnvironment(PRE='pre', SUF='suf', L1=['a', 'b'], L2=['c', 'd'], @@ -1956,7 +1956,7 @@ def generate(env): assert 'XXX' not in env.Dictionary() def test_FindIxes(self): - "Test FindIxes()" + """Test FindIxes()""" env = self.TestEnvironment(LIBPREFIX='lib', LIBSUFFIX='.a', SHLIBPREFIX='lib', @@ -2398,7 +2398,7 @@ f5: \ assert hasattr(env3, 'b2'), "b2 was not set" def test_ReplaceIxes(self): - "Test ReplaceIxes()" + """Test ReplaceIxes()""" env = self.TestEnvironment(LIBPREFIX='lib', LIBSUFFIX='.a', SHLIBPREFIX='lib', @@ -3431,7 +3431,7 @@ def generate(env): assert x in over, bad_msg % x def test_parse_flags(self): - '''Test the Base class parse_flags argument''' + """Test the Base class parse_flags argument""" # all we have to show is that it gets to MergeFlags internally env = Environment(tools=[], parse_flags = '-X') assert env['CCFLAGS'] == ['-X'], env['CCFLAGS'] @@ -3445,7 +3445,7 @@ def generate(env): assert env['CPPDEFINES'] == ['FOO', 'BAR'], env['CPPDEFINES'] def test_clone_parse_flags(self): - '''Test the env.Clone() parse_flags argument''' + """Test the env.Clone() parse_flags argument""" # all we have to show is that it gets to MergeFlags internally env = Environment(tools = []) env2 = env.Clone(parse_flags = '-X') @@ -3714,7 +3714,7 @@ class OverrideEnvironmentTestCase(unittest.TestCase,TestEnvironmentFixture): assert x == ['x3', 'y3', 'z3'], x def test_parse_flags(self): - '''Test the OverrideEnvironment parse_flags argument''' + """Test the OverrideEnvironment parse_flags argument""" # all we have to show is that it gets to MergeFlags internally env = SubstitutionEnvironment() env2 = env.Override({'parse_flags' : '-X'}) diff --git a/src/engine/SCons/EnvironmentValues.py b/src/engine/SCons/EnvironmentValues.py index d94bf3a..6599196 100644 --- a/src/engine/SCons/EnvironmentValues.py +++ b/src/engine/SCons/EnvironmentValues.py @@ -3,7 +3,7 @@ import re _is_valid_var = re.compile(r'[_a-zA-Z]\w*$') _rm = re.compile(r'\$[()]') -_remove = re.compile(r'\$\([^\$]*(\$[^\)][^\$]*)*\$\)') +_remove = re.compile(r'\$\([^$]*(\$[^)][^$]*)*\$\)') # Regular expressions for splitting strings and handling substitutions, # for use by the scons_subst() and scons_subst_list() functions: @@ -28,7 +28,7 @@ _remove = re.compile(r'\$\([^\$]*(\$[^\)][^\$]*)*\$\)') # _dollar_exps_str = r'\$[\$\(\)]|\$[_a-zA-Z][\.\w]*|\${[^}]*}' _dollar_exps = re.compile(r'(%s)' % _dollar_exps_str) -_separate_args = re.compile(r'(%s|\s+|[^\s\$]+|\$)' % _dollar_exps_str) +_separate_args = re.compile(r'(%s|\s+|[^\s$]+|\$)' % _dollar_exps_str) # This regular expression is used to replace strings of multiple white # space characters in the string result from the scons_subst() function. diff --git a/src/engine/SCons/JobTests.py b/src/engine/SCons/JobTests.py index 26e3d37..2e3af4f 100644 --- a/src/engine/SCons/JobTests.py +++ b/src/engine/SCons/JobTests.py @@ -46,7 +46,7 @@ def get_cpu_nums(): return int( os.popen2( "sysctl -n hw.ncpu")[1].read() ) # Windows: if "NUMBER_OF_PROCESSORS" in os.environ: - ncpus = int( os.environ[ "NUMBER_OF_PROCESSORS" ] ); + ncpus = int(os.environ["NUMBER_OF_PROCESSORS"]) if ncpus > 0: return ncpus return 1 # Default @@ -59,14 +59,14 @@ num_jobs = get_cpu_nums()*2 # in case we werent able to detect num cpus for this test # just make a hardcoded suffcient large number, though not future proof -if(num_jobs == 2): +if num_jobs == 2: num_jobs = 33 # how many tasks to perform for the test num_tasks = num_jobs*5 class DummyLock(object): - "fake lock class to use if threads are not supported" + """fake lock class to use if threads are not supported""" def acquire(self): pass @@ -74,7 +74,7 @@ class DummyLock(object): pass class NoThreadsException(Exception): - "raised by the ParallelTestCase if threads are not supported" + """raised by the ParallelTestCase if threads are not supported""" def __str__(self): return "the interpreter doesn't support threads" @@ -113,7 +113,7 @@ class Task(object): # check if task was executing while another was also executing for j in range(1, self.taskmaster.num_tasks): - if(self.taskmaster.parallel_list[j+1] == 1): + if self.taskmaster.parallel_list[j + 1] == 1: self.taskmaster.found_parallel = True break @@ -237,7 +237,7 @@ class Taskmaster(object): return self.num_postprocessed == self.num_tasks def tasks_were_serial(self): - "analyze the task order to see if they were serial" + """analyze the task order to see if they were serial""" return not self.found_parallel def exception_set(self): @@ -251,7 +251,7 @@ ThreadPoolCallList = [] class ParallelTestCase(unittest.TestCase): def runTest(self): - "test parallel jobs" + """test parallel jobs""" try: import threading @@ -319,7 +319,7 @@ class ParallelTestCase(unittest.TestCase): class SerialTestCase(unittest.TestCase): def runTest(self): - "test a serial job" + """test a serial job""" taskmaster = Taskmaster(num_tasks, self, RandomTask) jobs = SCons.Job.Jobs(1, taskmaster) @@ -338,7 +338,7 @@ class SerialTestCase(unittest.TestCase): class NoParallelTestCase(unittest.TestCase): def runTest(self): - "test handling lack of parallel support" + """test handling lack of parallel support""" def NoParallel(tm, num, stack_size): raise NameError save_Parallel = SCons.Job.Parallel @@ -365,7 +365,7 @@ class NoParallelTestCase(unittest.TestCase): class SerialExceptionTestCase(unittest.TestCase): def runTest(self): - "test a serial job with tasks that raise exceptions" + """test a serial job with tasks that raise exceptions""" taskmaster = Taskmaster(num_tasks, self, ExceptionTask) jobs = SCons.Job.Jobs(1, taskmaster) @@ -382,7 +382,7 @@ class SerialExceptionTestCase(unittest.TestCase): class ParallelExceptionTestCase(unittest.TestCase): def runTest(self): - "test parallel jobs with tasks that raise exceptions" + """test parallel jobs with tasks that raise exceptions""" taskmaster = Taskmaster(num_tasks, self, ExceptionTask) jobs = SCons.Job.Jobs(num_jobs, taskmaster) @@ -534,13 +534,13 @@ class _SConsTaskTest(unittest.TestCase): class SerialTaskTest(_SConsTaskTest): def runTest(self): - "test serial jobs with actual Taskmaster and Task" + """test serial jobs with actual Taskmaster and Task""" self._test_seq(1) class ParallelTaskTest(_SConsTaskTest): def runTest(self): - "test parallel jobs with actual Taskmaster and Task" + """test parallel jobs with actual Taskmaster and Task""" self._test_seq(num_jobs) diff --git a/src/engine/SCons/Node/Alias.py b/src/engine/SCons/Node/Alias.py index a035816..55d94f9 100644 --- a/src/engine/SCons/Node/Alias.py +++ b/src/engine/SCons/Node/Alias.py @@ -37,6 +37,7 @@ import collections import SCons.Errors import SCons.Node import SCons.Util +from SCons.Util import MD5signature class AliasNameSpace(collections.UserDict): def Alias(self, name, **kw): @@ -166,7 +167,7 @@ class Alias(SCons.Node.Node): pass contents = self.get_contents() - csig = SCons.Util.MD5signature(contents) + csig = MD5signature(contents) self.get_ninfo().csig = csig return csig diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index 4c68358..e1d6f68 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -54,6 +54,7 @@ import SCons.Node import SCons.Node.Alias import SCons.Subst import SCons.Util +from SCons.Util import MD5signature, MD5filesignature, MD5collect import SCons.Warnings from SCons.Debug import Trace @@ -1862,7 +1863,7 @@ class Dir(Base): node is called which has a child directory, the child directory should return the hash of its contents.""" contents = self.get_contents() - return SCons.Util.MD5signature(contents) + return MD5signature(contents) def do_duplicate(self, src): pass @@ -2501,14 +2502,14 @@ class FileBuildInfo(SCons.Node.BuildInfoBase): Attributes unique to FileBuildInfo: dependency_map : Caches file->csig mapping - for all dependencies. Currently this is only used when using - MD5-timestamp decider. - It's used to ensure that we copy the correct - csig from previous build to be written to .sconsign when current build - is done. Previously the matching of csig to file was strictly by order - they appeared in bdepends, bsources, or bimplicit, and so a change in order - or count of any of these could yield writing wrong csig, and then false positive - rebuilds + for all dependencies. Currently this is only used when using + MD5-timestamp decider. + It's used to ensure that we copy the correct csig from the + previous build to be written to .sconsign when current build + is done. Previously the matching of csig to file was strictly + by order they appeared in bdepends, bsources, or bimplicit, + and so a change in order or count of any of these could + yield writing wrong csig, and then false positive rebuilds """ __slots__ = ['dependency_map', ] current_version_id = 2 @@ -2723,11 +2724,10 @@ class File(Base): Compute and return the MD5 hash for this file. """ if not self.rexists(): - return SCons.Util.MD5signature('') + return MD5signature('') fname = self.rfile().get_abspath() try: - cs = SCons.Util.MD5filesignature(fname, - chunksize=SCons.Node.FS.File.md5_chunksize*1024) + cs = MD5filesignature(fname, chunksize=File.md5_chunksize * 1024) except EnvironmentError as e: if not e.filename: e.filename = fname @@ -3028,7 +3028,7 @@ class File(Base): @see: built() and Node.release_target_info() """ - if (self.released_target_info or SCons.Node.interactive): + if self.released_target_info or SCons.Node.interactive: return if not hasattr(self.attributes, 'keep_targetinfo'): @@ -3210,7 +3210,7 @@ class File(Base): if csig is None: try: - if self.get_size() < SCons.Node.FS.File.md5_chunksize: + if self.get_size() < File.md5_chunksize: contents = self.get_contents() else: csig = self.get_content_hash() @@ -3312,7 +3312,7 @@ class File(Base): # For an "empty" binfo properties like bsources # do not exist: check this to avoid exception. - if (len(binfo.bsourcesigs) + len(binfo.bdependsigs) + \ + if (len(binfo.bsourcesigs) + len(binfo.bdependsigs) + len(binfo.bimplicitsigs)) == 0: return {} @@ -3580,7 +3580,7 @@ class File(Base): node = repo_dir.file_on_disk(self.name) if node and node.exists() and \ - (isinstance(node, File) or isinstance(node, Entry) \ + (isinstance(node, File) or isinstance(node, Entry) or not node.is_derived()): retvals.append(node) @@ -3611,8 +3611,7 @@ class File(Base): cachedir, cachefile = self.get_build_env().get_CacheDir().cachepath(self) if not self.exists() and cachefile and os.path.exists(cachefile): - self.cachedir_csig = SCons.Util.MD5filesignature(cachefile, \ - SCons.Node.FS.File.md5_chunksize * 1024) + self.cachedir_csig = MD5filesignature(cachefile, File.md5_chunksize * 1024) else: self.cachedir_csig = self.get_csig() return self.cachedir_csig @@ -3632,7 +3631,7 @@ class File(Base): executor = self.get_executor() - result = self.contentsig = SCons.Util.MD5signature(executor.get_contents()) + result = self.contentsig = MD5signature(executor.get_contents()) return result def get_cachedir_bsig(self): @@ -3663,7 +3662,7 @@ class File(Base): sigs.append(self.get_internal_path()) # Merge this all into a single signature - result = self.cachesig = SCons.Util.MD5collect(sigs) + result = self.cachesig = MD5collect(sigs) return result default_fs = None diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py index 678e03e..d8179ff 100644 --- a/src/engine/SCons/Node/NodeTests.py +++ b/src/engine/SCons/Node/NodeTests.py @@ -1304,7 +1304,7 @@ class NodeTestCase(unittest.TestCase): def test_postprocess(self): """Test calling the base Node postprocess() method""" n = SCons.Node.Node() - n.waiting_parents = set( ['foo','bar'] ) + n.waiting_parents = {'foo', 'bar'} n.postprocess() assert n.waiting_parents == set(), n.waiting_parents @@ -1316,7 +1316,7 @@ class NodeTestCase(unittest.TestCase): assert n1.waiting_parents == set(), n1.waiting_parents r = n1.add_to_waiting_parents(n2) assert r == 1, r - assert n1.waiting_parents == set((n2,)), n1.waiting_parents + assert n1.waiting_parents == {n2}, n1.waiting_parents r = n1.add_to_waiting_parents(n2) assert r == 0, r diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index daf79ba..0b58282 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -60,6 +60,7 @@ from SCons.Debug import logInstanceCreation import SCons.Executor import SCons.Memoize import SCons.Util +from SCons.Util import MD5signature from SCons.Debug import Trace @@ -1167,7 +1168,7 @@ class Node(object, with_metaclass(NoSlotsPyPy)): if self.has_builder(): binfo.bact = str(executor) - binfo.bactsig = SCons.Util.MD5signature(executor.get_contents()) + binfo.bactsig = MD5signature(executor.get_contents()) if self._specific_sources: sources = [s for s in self.sources if s not in ignore_set] @@ -1205,7 +1206,7 @@ class Node(object, with_metaclass(NoSlotsPyPy)): return self.ninfo.csig except AttributeError: ninfo = self.get_ninfo() - ninfo.csig = SCons.Util.MD5signature(self.get_contents()) + ninfo.csig = MD5signature(self.get_contents()) return self.ninfo.csig def get_cachedir_csig(self): @@ -1496,7 +1497,7 @@ class Node(object, with_metaclass(NoSlotsPyPy)): if self.has_builder(): contents = self.get_executor().get_contents() - newsig = SCons.Util.MD5signature(contents) + newsig = MD5signature(contents) if bi.bactsig != newsig: if t: Trace(': bactsig %s != newsig %s' % (bi.bactsig, newsig)) result = True diff --git a/src/engine/SCons/PathListTests.py b/src/engine/SCons/PathListTests.py index b5989bb..104be73 100644 --- a/src/engine/SCons/PathListTests.py +++ b/src/engine/SCons/PathListTests.py @@ -108,7 +108,7 @@ class subst_pathTestCase(unittest.TestCase): self.env.subst = lambda s, target, source, conv: 'NOT THIS STRING' - pl = SCons.PathList.PathList(('x')) + pl = SCons.PathList.PathList(('x',)) result = pl.subst_path(self.env, 'y', 'z') diff --git a/src/engine/SCons/Platform/virtualenv.py b/src/engine/SCons/Platform/virtualenv.py index 4127d8c..4708cb2 100644 --- a/src/engine/SCons/Platform/virtualenv.py +++ b/src/engine/SCons/Platform/virtualenv.py @@ -61,7 +61,7 @@ def _is_path_in(path, base): if not path or not base: # empty path may happen, base too return False rp = os.path.relpath(path, base) - return ((not rp.startswith(os.path.pardir)) and (not rp == os.path.curdir)) + return (not rp.startswith(os.path.pardir)) and (not rp == os.path.curdir) def _inject_venv_variables(env): diff --git a/src/engine/SCons/SConf.py b/src/engine/SCons/SConf.py index 0195ac4..e706dae 100644 --- a/src/engine/SCons/SConf.py +++ b/src/engine/SCons/SConf.py @@ -270,7 +270,7 @@ class SConfBuildTask(SCons.Taskmaster.AlwaysTask): cached_error = False cachable = True for t in self.targets: - if T: Trace('%s' % (t)) + if T: Trace('%s' % t) bi = t.get_stored_info().binfo if isinstance(bi, SConfBuildInfo): if T: Trace(': SConfBuildInfo') @@ -280,7 +280,7 @@ class SConfBuildTask(SCons.Taskmaster.AlwaysTask): else: if T: Trace(': get_state() %s' % t.get_state()) if T: Trace(': changed() %s' % t.changed()) - if (t.get_state() != SCons.Node.up_to_date and t.changed()): + if t.get_state() != SCons.Node.up_to_date and t.changed(): changed = True if T: Trace(': changed %s' % changed) cached_error = cached_error or bi.result @@ -668,7 +668,7 @@ class SConfBase(object): is saved in self.lastTarget (for further processing). """ ok = self.TryLink(text, extension) - if( ok ): + if ok: prog = self.lastTarget pname = prog.get_internal_path() output = self.confdir.File(os.path.basename(pname)+'.out') @@ -866,9 +866,9 @@ class CheckContext(object): return self.sconf.TryRun(*args, **kw) def __getattr__( self, attr ): - if( attr == 'env' ): + if attr == 'env': return self.sconf.env - elif( attr == 'lastTarget' ): + elif attr == 'lastTarget': return self.sconf.lastTarget else: raise AttributeError("CheckContext instance has no attribute '%s'" % attr) diff --git a/src/engine/SCons/SConfTests.py b/src/engine/SCons/SConfTests.py index 787138e..c5d1fbd 100644 --- a/src/engine/SCons/SConfTests.py +++ b/src/engine/SCons/SConfTests.py @@ -151,7 +151,7 @@ class SConfTestCase(unittest.TestCase): log_file=self.test.workpath('config.log')) no_std_header_h = self.test.workpath('config.tests', 'no_std_header.h') test_h = self.test.write( no_std_header_h, - "/* we are changing a dependency now */\n" ); + "/* we are changing a dependency now */\n" ) try: res = checks( self, sconf, TryFunc ) log = self.test.read( self.test.workpath('config.log') ) diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py index 238a828..f9c8384 100644 --- a/src/engine/SCons/Script/Main.py +++ b/src/engine/SCons/Script/Main.py @@ -355,7 +355,7 @@ class CleanTask(SCons.Taskmaster.AlwaysTask): display("Removed directory " + pathstr) else: errstr = "Path '%s' exists but isn't a file or directory." - raise SCons.Errors.UserError(errstr % (pathstr)) + raise SCons.Errors.UserError(errstr % pathstr) except SCons.Errors.UserError as e: print(e) except (IOError, OSError) as e: diff --git a/src/engine/SCons/Script/SConsOptions.py b/src/engine/SCons/Script/SConsOptions.py index 66c7239..8ec8ccf 100644 --- a/src/engine/SCons/Script/SConsOptions.py +++ b/src/engine/SCons/Script/SConsOptions.py @@ -28,7 +28,7 @@ import re import sys import textwrap -no_hyphen_re = re.compile(r'(\s+|(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))') +no_hyphen_re = re.compile(r'(\s+|(?<=[\w!\"\'&.,?])-{2,}(?=\w))') try: from gettext import gettext diff --git a/src/engine/SCons/Subst.py b/src/engine/SCons/Subst.py index f3693a1..664cd6c 100644 --- a/src/engine/SCons/Subst.py +++ b/src/engine/SCons/Subst.py @@ -754,7 +754,7 @@ _list_remove = [ _rm_list, None, _remove_list ] # _dollar_exps_str = r'\$[\$\(\)]|\$[_a-zA-Z][\.\w]*|\${[^}]*}' _dollar_exps = re.compile(r'(%s)' % _dollar_exps_str) -_separate_args = re.compile(r'(%s|\s+|[^\s\$]+|\$)' % _dollar_exps_str) +_separate_args = re.compile(r'(%s|\s+|[^\s$]+|\$)' % _dollar_exps_str) # This regular expression is used to replace strings of multiple white # space characters in the string result from the scons_subst() function. diff --git a/src/engine/SCons/SubstTests.py b/src/engine/SCons/SubstTests.py index f6fe1ec..c25b377 100644 --- a/src/engine/SCons/SubstTests.py +++ b/src/engine/SCons/SubstTests.py @@ -133,8 +133,8 @@ class SubstTestCase(unittest.TestCase): return self.value # only use of this is currently commented out below - def function_foo(arg): - pass + #def function_foo(arg): + # pass target = [ MyNode("./foo/bar.exe"), MyNode("/bar/baz with spaces.obj"), @@ -207,7 +207,7 @@ class SubstTestCase(unittest.TestCase): 'S' : 'x y', 'LS' : ['x y'], 'L' : ['x', 'y'], - 'TS' : ('x y'), + 'TS' : ('x y',), 'T' : ('x', 'y'), 'CS' : cs, 'CL' : cl, diff --git a/src/engine/SCons/Tool/JavaCommon.py b/src/engine/SCons/Tool/JavaCommon.py index a7e247d..1711de1 100644 --- a/src/engine/SCons/Tool/JavaCommon.py +++ b/src/engine/SCons/Tool/JavaCommon.py @@ -40,7 +40,7 @@ default_java_version = '1.4' # a switch for which jdk versions to use the Scope state for smarter # anonymous inner class parsing. -scopeStateVersions = ('1.8') +scopeStateVersions = ('1.8',) # Glob patterns for use in finding where the JDK is. # These are pairs, *dir_glob used in the general case, @@ -87,8 +87,8 @@ if java_parsing: # any alphanumeric token surrounded by angle brackets (generics); # the multi-line comment begin and end tokens /* and */; # array declarations "[]". - _reToken = re.compile(r'(\n|\\\\|//|\\[\'"]|[\'"\{\}\;\.\(\)]|' + - r'\d*\.\d*|[A-Za-z_][\w\$\.]*|<[A-Za-z_]\w+>|' + + _reToken = re.compile(r'(\n|\\\\|//|\\[\'"]|[\'"{\};.()]|' + + r'\d*\.\d*|[A-Za-z_][\w$.]*|<[A-Za-z_]\w+>|' + r'/\*|\*/|\[\])') diff --git a/src/engine/SCons/Tool/MSCommon/sdk.py b/src/engine/SCons/Tool/MSCommon/sdk.py index 281c1e3..9627f17 100644 --- a/src/engine/SCons/Tool/MSCommon/sdk.py +++ b/src/engine/SCons/Tool/MSCommon/sdk.py @@ -110,12 +110,12 @@ class SDKDefinition(object): """ Return the script to initialize the VC compiler installed by SDK """ - if (host_arch == 'amd64' and target_arch == 'x86'): + if host_arch == 'amd64' and target_arch == 'x86': # No cross tools needed compiling 32 bits on 64 bit machine host_arch=target_arch arch_string=target_arch - if (host_arch != target_arch): + if host_arch != target_arch: arch_string='%s_%s'%(host_arch,target_arch) debug("get_sdk_vc_script():arch_string:%s host_arch:%s target_arch:%s"%(arch_string, diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py index 53b9d59..6f9bd12 100644 --- a/src/engine/SCons/Tool/MSCommon/vc.py +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -766,12 +766,12 @@ def msvc_find_valid_batch_script(env, version): vc_script=None continue if not vc_script and sdk_script: - debug('msvc_find_valid_batch_script() use_script 4: trying sdk script: %s'%(sdk_script)) + debug('msvc_find_valid_batch_script() use_script 4: trying sdk script: %s' % sdk_script) try: d = script_env(sdk_script) found = sdk_script except BatchFileExecutionError as e: - debug('msvc_find_valid_batch_script() use_script 5: failed running SDK script %s: Error:%s'%(repr(sdk_script),e)) + debug('msvc_find_valid_batch_script() use_script 5: failed running SDK script %s: Error:%s'%(repr(sdk_script), e)) continue elif not vc_script and not sdk_script: debug('msvc_find_valid_batch_script() use_script 6: Neither VC script nor SDK script found') diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py index f255b21..14306ab 100644 --- a/src/engine/SCons/Tool/__init__.py +++ b/src/engine/SCons/Tool/__init__.py @@ -774,11 +774,11 @@ def EmitLibSymlinks(env, symlinks, libnode, **kw): for link, linktgt in symlinks: env.SideEffect(link, linktgt) - if (Verbose): + if Verbose: print("EmitLibSymlinks: SideEffect(%r,%r)" % (link.get_path(), linktgt.get_path())) clean_list = [x for x in nodes if x != linktgt] env.Clean(list(set([linktgt] + clean_targets)), clean_list) - if (Verbose): + if Verbose: print("EmitLibSymlinks: Clean(%r,%r)" % (linktgt.get_path(), [x.get_path() for x in clean_list])) @@ -792,18 +792,18 @@ def CreateLibSymlinks(env, symlinks): for link, linktgt in symlinks: linktgt = link.get_dir().rel_path(linktgt) link = link.get_path() - if (Verbose): + if Verbose: print("CreateLibSymlinks: preparing to add symlink %r -> %r" % (link, linktgt)) # Delete the (previously created) symlink if exists. Let only symlinks # to be deleted to prevent accidental deletion of source files... if env.fs.islink(link): env.fs.unlink(link) - if (Verbose): + if Verbose: print("CreateLibSymlinks: removed old symlink %r" % link) # If a file or directory exists with the same name as link, an OSError # will be thrown, which should be enough, I think. env.fs.symlink(linktgt, link) - if (Verbose): + if Verbose: print("CreateLibSymlinks: add symlink %r -> %r" % (link, linktgt)) return 0 diff --git a/src/engine/SCons/Tool/docbook/__init__.py b/src/engine/SCons/Tool/docbook/__init__.py index b93d916..c4fdfba 100644 --- a/src/engine/SCons/Tool/docbook/__init__.py +++ b/src/engine/SCons/Tool/docbook/__init__.py @@ -135,7 +135,7 @@ def __get_xml_text(root): """ Return the text for the given root node (xml.dom.minidom). """ txt = "" for e in root.childNodes: - if (e.nodeType == e.TEXT_NODE): + if e.nodeType == e.TEXT_NODE: txt += e.data return txt @@ -207,7 +207,7 @@ def _detect(env): if env.get('DOCBOOK_PREFER_XSLTPROC',''): prefer_xsltproc = True - if ((not has_libxml2 and not has_lxml) or (prefer_xsltproc)): + if (not has_libxml2 and not has_lxml) or prefer_xsltproc: # Try to find the XSLT processors __detect_cl_tool(env, 'DOCBOOK_XSLTPROC', xsltproc_com, xsltproc_com_priority) __detect_cl_tool(env, 'DOCBOOK_XMLLINT', xmllint_com) diff --git a/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/docbook.py b/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/docbook.py index 5d2de3e..de1375d 100644 --- a/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/docbook.py +++ b/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/docbook.py @@ -34,9 +34,9 @@ def adjustColumnWidths(ctx, nodeset): # Get the nominal table width varString = lookupVariable(tctxt, "nominal.table.width", None) if varString is None: - nominalWidth = 6 * pixelsPerInch; + nominalWidth = 6 * pixelsPerInch else: - nominalWidth = convertLength(varString); + nominalWidth = convertLength(varString) # Get the requested table width tableWidth = lookupVariable(tctxt, "table.width", "100%") @@ -161,7 +161,7 @@ def convertLength(length): global pixelsPerInch global unitHash - m = re.search('([+-]?[\d\.]+)(\S+)', length) + m = re.search('([+-]?[\d.]+)(\S+)', length) if m is not None and m.lastindex > 1: unit = pixelsPerInch if m.group(2) in unitHash: diff --git a/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/xslt.py b/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/xslt.py index 77ca0de..d5529b8 100644 --- a/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/xslt.py +++ b/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/xslt.py @@ -36,7 +36,7 @@ try: outfile = None count = 4 - while (sys.argv[count]): + while sys.argv[count]: try: name, value = sys.argv[count].split("=", 2) if name in params: diff --git a/src/engine/SCons/Tool/intelc.py b/src/engine/SCons/Tool/intelc.py index 7550c34..5a101b4 100644 --- a/src/engine/SCons/Tool/intelc.py +++ b/src/engine/SCons/Tool/intelc.py @@ -318,7 +318,7 @@ def get_intel_compiler_top(version, abi): if not os.path.exists(os.path.join(top, "Bin", "icl.exe")) \ and not os.path.exists(os.path.join(top, "Bin", abi, "icl.exe")) \ and not os.path.exists(os.path.join(top, "Bin", archdir, "icl.exe")): - raise MissingDirError("Can't find Intel compiler in %s"%(top)) + raise MissingDirError("Can't find Intel compiler in %s" % top) elif is_mac or is_linux: def find_in_2008style_dir(version): # first dir is new (>=9.0) style, second is old (8.0) style. diff --git a/src/engine/SCons/Tool/jar.py b/src/engine/SCons/Tool/jar.py index e75fa13..502aa60 100644 --- a/src/engine/SCons/Tool/jar.py +++ b/src/engine/SCons/Tool/jar.py @@ -158,7 +158,7 @@ def Jar(env, target = None, source = [], *args, **kw): # files. def dir_to_class(s): dir_targets = env.JavaClassDir(source = s, *args, **kw) - if(dir_targets == []): + if dir_targets == []: # no classes files could be built from the source dir # so pass the dir as is. return [env.fs.Dir(s)] diff --git a/src/engine/SCons/Tool/javah.py b/src/engine/SCons/Tool/javah.py index 80f8a6b..fbfcbe2 100644 --- a/src/engine/SCons/Tool/javah.py +++ b/src/engine/SCons/Tool/javah.py @@ -115,7 +115,7 @@ def getJavaHClassPath(env,target, source, for_signature): path = "${SOURCE.attributes.java_classdir}" if 'JAVACLASSPATH' in env and env['JAVACLASSPATH']: path = SCons.Util.AppendPath(path, env['JAVACLASSPATH']) - return "-classpath %s" % (path) + return "-classpath %s" % path def generate(env): """Add Builders and construction variables for javah to an Environment.""" diff --git a/src/engine/SCons/Tool/mslink.py b/src/engine/SCons/Tool/mslink.py index 0fa6454..fc5f009 100644 --- a/src/engine/SCons/Tool/mslink.py +++ b/src/engine/SCons/Tool/mslink.py @@ -220,7 +220,7 @@ def embedManifestDllCheck(target, source, env): if env.get('WINDOWS_EMBED_MANIFEST', 0): manifestSrc = target[0].get_abspath() + '.manifest' if os.path.exists(manifestSrc): - ret = (embedManifestDllAction) ([target[0]],None,env) + ret = embedManifestDllAction([target[0]], None, env) if ret: raise SCons.Errors.UserError("Unable to embed manifest into %s" % (target[0])) return ret @@ -234,7 +234,7 @@ def embedManifestExeCheck(target, source, env): if env.get('WINDOWS_EMBED_MANIFEST', 0): manifestSrc = target[0].get_abspath() + '.manifest' if os.path.exists(manifestSrc): - ret = (embedManifestExeAction) ([target[0]],None,env) + ret = embedManifestExeAction([target[0]], None, env) if ret: raise SCons.Errors.UserError("Unable to embed manifest into %s" % (target[0])) return ret diff --git a/src/engine/SCons/Tool/msvs.py b/src/engine/SCons/Tool/msvs.py index 7dca9e1..929e558 100644 --- a/src/engine/SCons/Tool/msvs.py +++ b/src/engine/SCons/Tool/msvs.py @@ -172,9 +172,9 @@ def makeHierarchy(sources): return hierarchy class _UserGenerator(object): - ''' + """ Base class for .dsp.user file generator - ''' + """ # Default instance values. # Ok ... a bit defensive, but it does not seem reasonable to crash the # build for a workspace user file. :-) @@ -980,7 +980,7 @@ class _GenerateV7DSP(_DSPGenerator, _GenerateV7User): if SCons.Util.is_Dict(value): self.file.write('\t\t\t\n' % (key)) + '\t\t\t\tFilter="">\n' % key) self.printSources(value, commonprefix) self.file.write('\t\t\t\n') @@ -992,7 +992,7 @@ class _GenerateV7DSP(_DSPGenerator, _GenerateV7User): file = os.path.normpath(file) self.file.write('\t\t\t\n' - '\t\t\t\n' % (file)) + '\t\t\t\n' % file) def PrintSourceFiles(self): categories = {'Source Files': 'cpp;c;cxx;l;y;def;odl;idl;hpj;bat', @@ -2047,17 +2047,17 @@ def generate(env): (version_num, suite) = (7.0, None) # guess at a default if 'MSVS' not in env: env['MSVS'] = {} - if (version_num < 7.0): + if version_num < 7.0: env['MSVS']['PROJECTSUFFIX'] = '.dsp' env['MSVS']['SOLUTIONSUFFIX'] = '.dsw' - elif (version_num < 10.0): + elif version_num < 10.0: env['MSVS']['PROJECTSUFFIX'] = '.vcproj' env['MSVS']['SOLUTIONSUFFIX'] = '.sln' else: env['MSVS']['PROJECTSUFFIX'] = '.vcxproj' env['MSVS']['SOLUTIONSUFFIX'] = '.sln' - if (version_num >= 10.0): + if version_num >= 10.0: env['MSVSENCODING'] = 'utf-8' else: env['MSVSENCODING'] = 'Windows-1252' diff --git a/src/engine/SCons/Tool/packaging/msi.py b/src/engine/SCons/Tool/packaging/msi.py index 34e4f0f..9f28b72 100644 --- a/src/engine/SCons/Tool/packaging/msi.py +++ b/src/engine/SCons/Tool/packaging/msi.py @@ -182,7 +182,7 @@ def generate_guids(root): def string_wxsfile(target, source, env): - return "building WiX file %s"%( target[0].path ) + return "building WiX file %s" % target[0].path def build_wxsfile(target, source, env): """ Compiles a .wxs file from the keywords given in env['msi_spec'] and diff --git a/src/engine/SCons/Tool/tex.py b/src/engine/SCons/Tool/tex.py index 5cf7bca..fa18cf9 100644 --- a/src/engine/SCons/Tool/tex.py +++ b/src/engine/SCons/Tool/tex.py @@ -204,7 +204,7 @@ def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None # with LaTeXAction and from the pdflatex.py with PDFLaTeXAction # set this up now for the case where the user requests a different extension # for the target filename - if (XXXLaTeXAction == LaTeXAction): + if XXXLaTeXAction == LaTeXAction: callerSuffix = ".dvi" else: callerSuffix = env['PDFSUFFIX'] @@ -283,7 +283,7 @@ def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None count = 0 - while (must_rerun_latex and count < int(env.subst('$LATEXRETRIES'))) : + while must_rerun_latex and count < int(env.subst('$LATEXRETRIES')): result = XXXLaTeXAction(target, source, env) if result != 0: return result @@ -461,7 +461,7 @@ def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None if Verbose: print("rerun Latex due to undefined references or citations") - if (count >= int(env.subst('$LATEXRETRIES')) and must_rerun_latex): + if count >= int(env.subst('$LATEXRETRIES')) and must_rerun_latex: print("reached max number of retries on Latex ,",int(env.subst('$LATEXRETRIES'))) # end of while loop @@ -861,7 +861,7 @@ def generate_darwin(env): environ = {} env['ENV'] = environ - if (platform.system() == 'Darwin'): + if platform.system() == 'Darwin': try: ospath = env['ENV']['PATHOSX'] except: diff --git a/src/engine/SCons/Tool/xgettext.py b/src/engine/SCons/Tool/xgettext.py index 936924b..11ca32f 100644 --- a/src/engine/SCons/Tool/xgettext.py +++ b/src/engine/SCons/Tool/xgettext.py @@ -133,7 +133,7 @@ def _update_pot_file(target, source, env): re_cdate = re.compile(r'^"POT-Creation-Date: .*"$[\r\n]?', re.M) old_content_nocdate = re.sub(re_cdate, "", old_content) new_content_nocdate = re.sub(re_cdate, "", new_content) - if (old_content_nocdate == new_content_nocdate): + if old_content_nocdate == new_content_nocdate: # Messages are up-to-date needs_update = False explain = "messages in file found to be up-to-date" diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index 28674d1..4b4ead5 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -392,7 +392,7 @@ except NameError: try: BaseStringTypes = (str, unicode) except NameError: - BaseStringTypes = (str) + BaseStringTypes = str def is_Dict(obj, isinstance=isinstance, DictTypes=DictTypes): return isinstance(obj, DictTypes) diff --git a/src/engine/SCons/dblite.py b/src/engine/SCons/dblite.py index 14bd93d..55254b3 100644 --- a/src/engine/SCons/dblite.py +++ b/src/engine/SCons/dblite.py @@ -131,9 +131,10 @@ class dblite(object): # Note how we catch KeyErrors too here, which might happen # when we don't have cPickle available (default pickle # throws it). - if (ignore_corrupt_dbfiles == 0): raise - if (ignore_corrupt_dbfiles == 1): + if ignore_corrupt_dbfiles: corruption_warning(self._file_name) + else: + raise def close(self): if self._needs_sync: @@ -166,13 +167,13 @@ class dblite(object): except OSError: pass self._needs_sync = 00000 - if (keep_all_files): + if keep_all_files: self._shutil_copyfile( self._file_name, self._file_name + "_" + str(int(self._time_time()))) def _check_writable(self): - if (self._flag == "r"): + if self._flag == "r": raise IOError("Read-only database: %s" % self._file_name) def __getitem__(self, key): @@ -180,9 +181,9 @@ class dblite(object): def __setitem__(self, key, value): self._check_writable() - if (not is_string(key)): + if not is_string(key): raise TypeError("key `%s' must be a string but is %s" % (key, type(key))) - if (not is_bytes(value)): + if not is_bytes(value): raise TypeError("value `%s' must be a bytes but is %s" % (value, type(value))) self._dict[key] = value self._needs_sync = 0o001 @@ -280,7 +281,7 @@ def _exercise(): raise RuntimeError("IOError expected.") -if (__name__ == "__main__"): +if __name__ == "__main__": _exercise() # Local Variables: diff --git a/src/script/scons-configure-cache.py b/src/script/scons-configure-cache.py index 3c096e1..a687c9c 100644 --- a/src/script/scons-configure-cache.py +++ b/src/script/scons-configure-cache.py @@ -23,13 +23,13 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -'''Show or convert the configuration of an SCons cache directory. +"""Show or convert the configuration of an SCons cache directory. A cache of derived files is stored by file signature. The files are split into directories named by the first few digits of the signature. The prefix length used for directory names can be changed by this script. -''' +""" from __future__ import print_function import argparse @@ -51,11 +51,11 @@ __developer__ = "__DEVELOPER__" def rearrange_cache_entries(current_prefix_len, new_prefix_len): - '''Move cache files if prefix length changed. + """Move cache files if prefix length changed. Move the existing cache files to new directories of the appropriate name length and clean up the old directories. - ''' + """ print('Changing prefix length from', current_prefix_len, 'to', new_prefix_len) dirs = set() diff --git a/src/script/scons-time.py b/src/script/scons-time.py index 62d2784..91a105b 100644 --- a/src/script/scons-time.py +++ b/src/script/scons-time.py @@ -625,7 +625,7 @@ class SConsTimer(object): if not contents: sys.stderr.write('file %s has no contents!\n' % repr(file)) return None - result = re.findall(r'%s: ([\d\.]*)' % search_string, contents)[-4:] + result = re.findall(r'%s: ([\d.]*)' % search_string, contents)[-4:] result = [ float(r) for r in result ] if time_string is not None: try: diff --git a/src/script/sconsign.py b/src/script/sconsign.py index c7050bc..593c536 100644 --- a/src/script/sconsign.py +++ b/src/script/sconsign.py @@ -524,7 +524,7 @@ def Do_SConsignDir(name): except KeyboardInterrupt: raise except pickle.UnpicklingError: - err = "sconsign: ignoring invalid .sconsign file `%s'\n" % (name) + err = "sconsign: ignoring invalid .sconsign file `%s'\n" % name sys.stderr.write(err) return except Exception as e: diff --git a/test/CC/SHCCFLAGS.py b/test/CC/SHCCFLAGS.py index 72d36b1..0bb349b 100644 --- a/test/CC/SHCCFLAGS.py +++ b/test/CC/SHCCFLAGS.py @@ -120,7 +120,7 @@ foomain_obj = barMain.Object(target='foomain', source='main.c') barmain_obj = barMain.Object(target='barmain', source='main.c') barMain.Program(target='barprog', source=foomain_obj) barMain.Program(target='fooprog', source=barmain_obj) -""" % (barflags)) +""" % barflags) test.run(arguments = '.') diff --git a/test/CC/SHCFLAGS.py b/test/CC/SHCFLAGS.py index 3ec6778..a691dba 100644 --- a/test/CC/SHCFLAGS.py +++ b/test/CC/SHCFLAGS.py @@ -120,7 +120,7 @@ foomain_obj = barMain.Object(target='foomain', source='main.c') barmain_obj = barMain.Object(target='barmain', source='main.c') barMain.Program(target='barprog', source=foomain_obj) barMain.Program(target='fooprog', source=barmain_obj) -""" % (barflags)) +""" % barflags) test.run(arguments = '.') diff --git a/test/CacheDir/readonly-cache.py b/test/CacheDir/readonly-cache.py index 6520106..63cfd22 100755 --- a/test/CacheDir/readonly-cache.py +++ b/test/CacheDir/readonly-cache.py @@ -64,11 +64,11 @@ if time1 <= time0: test.unlink('file.out') -for root, dirs, files in os.walk("cache",topdown=False): - for file in files: - os.chmod(os.path.join(root,file),0o444) - for dir in dirs: - os.chmod(os.path.join(root,dir),0o555) +for root, dirs, files in os.walk("cache", topdown=False): + for file in files: + os.chmod(os.path.join(root,file), 0o444) + for dir in dirs: + os.chmod(os.path.join(root,dir), 0o555) test.run(arguments = '--debug=explain --cache-debug=- .') diff --git a/test/Configure/ConfigureDryRunError.py b/test/Configure/ConfigureDryRunError.py index 2a8e449..1b89b03 100644 --- a/test/Configure/ConfigureDryRunError.py +++ b/test/Configure/ConfigureDryRunError.py @@ -56,7 +56,7 @@ r2 = conf.CheckLib('hopefullynolib') # will fail env = conf.Finish() if not (r1 and not r2): Exit(1) -""" % (lib)) +""" % lib) expect = """ scons: *** Cannot create configure directory ".sconf_temp" within a dry-run. diff --git a/test/D/Support/executablesSearch.py b/test/D/Support/executablesSearch.py index c572f56..e24601c 100755 --- a/test/D/Support/executablesSearch.py +++ b/test/D/Support/executablesSearch.py @@ -56,11 +56,11 @@ if __name__ == '__main__': import TestSCons class VariousTests(unittest.TestCase): - ''' + """ These tests are somewhat self referential in that isExecutableOfToolAvailable uses where_is to do most of it's work and we use the same function in the tests. - ''' + """ def setUp(self): self.test = TestSCons.TestSCons() diff --git a/test/Exit.py b/test/Exit.py index f00986d..abaa382 100644 --- a/test/Exit.py +++ b/test/Exit.py @@ -121,7 +121,7 @@ exit_builder(["%s"], ["%s"]) """ % (subdir_foo_out, subdir_foo_in), error=1), stderr = """\ scons: *** [%s] Explicit exit, status 27 -""" % (subdir_foo_out)) +""" % subdir_foo_out) test.must_match(['subdir', 'foo.out'], "subdir/foo.in\n") diff --git a/test/LINK/LINKCOMSTR.py b/test/LINK/LINKCOMSTR.py index df070fb..419056c 100644 --- a/test/LINK/LINKCOMSTR.py +++ b/test/LINK/LINKCOMSTR.py @@ -75,7 +75,7 @@ int main(int argc, char **argv) {} """) test.run() -if ("Linking" not in test.stdout()): +if "Linking" not in test.stdout(): test.fail_test() test.pass_test() diff --git a/test/LINK/SHLINKCOMSTR.py b/test/LINK/SHLINKCOMSTR.py index 4dd5c7c..18cfc9b 100644 --- a/test/LINK/SHLINKCOMSTR.py +++ b/test/LINK/SHLINKCOMSTR.py @@ -87,7 +87,7 @@ int i; """) test.run() - if ("Shared-Linking" not in test.stdout()): + if "Shared-Linking" not in test.stdout(): test.fail_test() test.pass_test() diff --git a/test/LINK/applelink.py b/test/LINK/applelink.py index e1b2837..c631e32 100644 --- a/test/LINK/applelink.py +++ b/test/LINK/applelink.py @@ -135,7 +135,7 @@ for SHLIBVERSION, \ test.must_contain_all_lines(test.stdout(), ['-Wl,-compatibility_version,{APPLELINK_COMPATIBILITY_VERSION}'.format(**locals())]) - if not (extra_flags): + if not extra_flags: # Now run otool -L to get the compat and current version info and verify it's correct in the library. # We expect output such as this # libfoo.1.2.3.dylib: diff --git a/test/MSVS/vs-10.0-exec.py b/test/MSVS/vs-10.0-exec.py index 090bde8..df13454 100644 --- a/test/MSVS/vs-10.0-exec.py +++ b/test/MSVS/vs-10.0-exec.py @@ -59,7 +59,7 @@ if env.WhereIs('cl'): print("os.environ.update(%%s)" %% repr(env['ENV'])) """ % locals()) -if(test.stdout() == ""): +if test.stdout() == "": msg = "Visual Studio %s missing cl.exe; skipping test.\n" % msvs_version test.skip_test(msg) diff --git a/test/MSVS/vs-10.0Exp-exec.py b/test/MSVS/vs-10.0Exp-exec.py index d6114bd..1c3b561 100644 --- a/test/MSVS/vs-10.0Exp-exec.py +++ b/test/MSVS/vs-10.0Exp-exec.py @@ -59,7 +59,7 @@ if env.WhereIs('cl'): print("os.environ.update(%%s)" %% repr(env['ENV'])) """ % locals()) -if(test.stdout() == ""): +if test.stdout() == "": msg = "Visual Studio %s missing cl.exe; skipping test.\n" % msvs_version test.skip_test(msg) diff --git a/test/MSVS/vs-11.0-exec.py b/test/MSVS/vs-11.0-exec.py index 48acd1c..8286841 100644 --- a/test/MSVS/vs-11.0-exec.py +++ b/test/MSVS/vs-11.0-exec.py @@ -59,7 +59,7 @@ if env.WhereIs('cl'): print("os.environ.update(%%s)" %% repr(env['ENV'])) """ % locals()) -if(test.stdout() == ""): +if test.stdout() == "": msg = "Visual Studio %s missing cl.exe; skipping test.\n" % msvs_version test.skip_test(msg) diff --git a/test/MSVS/vs-11.0Exp-exec.py b/test/MSVS/vs-11.0Exp-exec.py index 6a288a5..e7cffad 100644 --- a/test/MSVS/vs-11.0Exp-exec.py +++ b/test/MSVS/vs-11.0Exp-exec.py @@ -59,7 +59,7 @@ if env.WhereIs('cl'): print("os.environ.update(%%s)" %% repr(env['ENV'])) """ % locals()) -if(test.stdout() == ""): +if test.stdout() == "": msg = "Visual Studio %s missing cl.exe; skipping test.\n" % msvs_version test.skip_test(msg) diff --git a/test/MSVS/vs-14.0-exec.py b/test/MSVS/vs-14.0-exec.py index d2b7112..1d5b9bc 100644 --- a/test/MSVS/vs-14.0-exec.py +++ b/test/MSVS/vs-14.0-exec.py @@ -59,7 +59,7 @@ if env.WhereIs('cl'): print("os.environ.update(%%s)" %% repr(env['ENV'])) """ % locals()) -if(test.stdout() == ""): +if test.stdout() == "": msg = "Visual Studio %s missing cl.exe; skipping test.\n" % msvs_version test.skip_test(msg) diff --git a/test/MSVS/vs-14.1-exec.py b/test/MSVS/vs-14.1-exec.py index 2f593e0..bcf4fbe 100644 --- a/test/MSVS/vs-14.1-exec.py +++ b/test/MSVS/vs-14.1-exec.py @@ -59,7 +59,7 @@ if env.WhereIs('cl'): print("os.environ.update(%%s)" %% repr(env['ENV'])) """ % locals()) -if(test.stdout() == ""): +if test.stdout() == "": msg = "Visual Studio %s missing cl.exe; skipping test.\n" % msvs_version test.skip_test(msg) diff --git a/test/MSVS/vs-6.0-exec.py b/test/MSVS/vs-6.0-exec.py index 0864f76..ab70872 100644 --- a/test/MSVS/vs-6.0-exec.py +++ b/test/MSVS/vs-6.0-exec.py @@ -58,7 +58,7 @@ if env.WhereIs('cl'): print("os.environ.update(%%s)" %% repr(env['ENV'])) """ % locals()) -if(test.stdout() == ""): +if test.stdout() == "": msg = "Visual Studio %s missing cl.exe; skipping test.\n" % msvs_version test.skip_test(msg) diff --git a/test/MSVS/vs-7.0-exec.py b/test/MSVS/vs-7.0-exec.py index e95ca83..3c41aa5 100644 --- a/test/MSVS/vs-7.0-exec.py +++ b/test/MSVS/vs-7.0-exec.py @@ -58,7 +58,7 @@ if env.WhereIs('cl'): print("os.environ.update(%%s)" %% repr(env['ENV'])) """ % locals()) -if(test.stdout() == ""): +if test.stdout() == "": msg = "Visual Studio %s missing cl.exe; skipping test.\n" % msvs_version test.skip_test(msg) diff --git a/test/MSVS/vs-7.1-exec.py b/test/MSVS/vs-7.1-exec.py index 11ea617..f66b92d 100644 --- a/test/MSVS/vs-7.1-exec.py +++ b/test/MSVS/vs-7.1-exec.py @@ -58,7 +58,7 @@ if env.WhereIs('cl'): print("os.environ.update(%%s)" %% repr(env['ENV'])) """ % locals()) -if(test.stdout() == ""): +if test.stdout() == "": msg = "Visual Studio %s missing cl.exe; skipping test.\n" % msvs_version test.skip_test(msg) diff --git a/test/MSVS/vs-8.0-exec.py b/test/MSVS/vs-8.0-exec.py index 4b0a6dd..91e99dd 100644 --- a/test/MSVS/vs-8.0-exec.py +++ b/test/MSVS/vs-8.0-exec.py @@ -59,7 +59,7 @@ if env.WhereIs('cl'): print("os.environ.update(%%s)" %% repr(env['ENV'])) """ % locals()) -if(test.stdout() == ""): +if test.stdout() == "": msg = "Visual Studio %s missing cl.exe; skipping test.\n" % msvs_version test.skip_test(msg) diff --git a/test/MSVS/vs-8.0Exp-exec.py b/test/MSVS/vs-8.0Exp-exec.py index 0e4396d..77cae64 100644 --- a/test/MSVS/vs-8.0Exp-exec.py +++ b/test/MSVS/vs-8.0Exp-exec.py @@ -59,7 +59,7 @@ if env.WhereIs('cl'): print("os.environ.update(%%s)" %% repr(env['ENV'])) """ % locals()) -if(test.stdout() == ""): +if test.stdout() == "": msg = "Visual Studio %s missing cl.exe; skipping test.\n" % msvs_version test.skip_test(msg) diff --git a/test/MSVS/vs-9.0-exec.py b/test/MSVS/vs-9.0-exec.py index 3f823fa..26a115d 100644 --- a/test/MSVS/vs-9.0-exec.py +++ b/test/MSVS/vs-9.0-exec.py @@ -59,7 +59,7 @@ if env.WhereIs('cl'): print("os.environ.update(%%s)" %% repr(env['ENV'])) """ % locals()) -if(test.stdout() == ""): +if test.stdout() == "": msg = "Visual Studio %s missing cl.exe; skipping test.\n" % msvs_version test.skip_test(msg) diff --git a/test/MSVS/vs-9.0Exp-exec.py b/test/MSVS/vs-9.0Exp-exec.py index 5a65faf..0c274ba 100644 --- a/test/MSVS/vs-9.0Exp-exec.py +++ b/test/MSVS/vs-9.0Exp-exec.py @@ -59,7 +59,7 @@ if env.WhereIs('cl'): print("os.environ.update(%%s)" %% repr(env['ENV'])) """ % locals()) -if(test.stdout() == ""): +if test.stdout() == "": msg = "Visual Studio %s missing cl.exe; skipping test.\n" % msvs_version test.skip_test(msg) diff --git a/test/NodeOps.py b/test/NodeOps.py index 99a3f6a..ae200f6 100644 --- a/test/NodeOps.py +++ b/test/NodeOps.py @@ -213,7 +213,7 @@ build_nodes = ['fooprog' + _exe, ] + builddir_srcnodes + sub_build_nodes def cleanup_test(): - "cleanup after running a test" + """cleanup after running a test""" for F in builddir_srcnodes: test.unlink(F) # will be repopulated during clean operation test.run(arguments = '-c') diff --git a/test/QT/up-to-date.py b/test/QT/up-to-date.py index 7a7e565..e1734bd 100644 --- a/test/QT/up-to-date.py +++ b/test/QT/up-to-date.py @@ -134,7 +134,7 @@ test.run(arguments = my_obj, stderr=None) expect = my_obj.replace( '/', os.sep ) test.up_to_date(options = '--debug=explain', - arguments = (expect), + arguments =expect, stderr=None) test.pass_test() diff --git a/test/Repository/SharedLibrary.py b/test/Repository/SharedLibrary.py index 51142aa..04ce1a5 100644 --- a/test/Repository/SharedLibrary.py +++ b/test/Repository/SharedLibrary.py @@ -56,7 +56,7 @@ if ARGUMENTS.get('PROGRAM'): """) for fx in ['1', '2', '3']: - test.write(['repository', 'f%s.c' % (fx)], r""" + test.write(['repository', 'f%s.c' % fx], r""" #include void diff --git a/test/SWIG/recursive-includes-cpp.py b/test/SWIG/recursive-includes-cpp.py index dcd9d05..1a9091f 100644 --- a/test/SWIG/recursive-includes-cpp.py +++ b/test/SWIG/recursive-includes-cpp.py @@ -49,7 +49,7 @@ python, python_include, python_libpath, python_lib = \ if sys.platform == 'win32': python_lib = os.path.dirname(sys.executable) + "/libs/" + ('python%d%d'%(sys.version_info[0],sys.version_info[1])) + '.lib' - if( not os.path.isfile(python_lib)): + if not os.path.isfile(python_lib): test.skip_test('Can not find python lib at "' + python_lib + '", skipping test.%s' % os.linesep) test.write("recursive.h", """\ diff --git a/test/TEX/LATEX.py b/test/TEX/LATEX.py index dabe8b1..85cc7d8 100644 --- a/test/TEX/LATEX.py +++ b/test/TEX/LATEX.py @@ -168,7 +168,7 @@ This is the include file. mod %s test.write('makeindex.idx', '') test.subdir('subdir') - test.write('latexi.tex', latex1 % 'latexi.tex'); + test.write('latexi.tex', latex1 % 'latexi.tex') test.write([ 'subdir', 'latexinputfile'], latex2) test.write([ 'subdir', 'latexincludefile.tex'], latex3 % '1') diff --git a/test/TEX/LATEX2.py b/test/TEX/LATEX2.py index a3ac125..1628bb9 100644 --- a/test/TEX/LATEX2.py +++ b/test/TEX/LATEX2.py @@ -95,7 +95,7 @@ This is the include file. mod %s test.write('makeindex.idx', '') test.subdir('subdir') - test.write('latexi.tex', latex1 % 'latexi.tex'); + test.write('latexi.tex', latex1 % 'latexi.tex') test.write([ 'subdir', 'latexinputfile'], latex2) test.write([ 'subdir', 'latexincludefile.tex'], latex3 % '1') diff --git a/test/Win32/bad-drive.py b/test/Win32/bad-drive.py index 78f5395..28d926b 100644 --- a/test/Win32/bad-drive.py +++ b/test/Win32/bad-drive.py @@ -53,7 +53,7 @@ for d in reversed(ascii_uppercase): if bad_drive is None: print("All drive letters appear to be in use.") print("Cannot test SCons handling of invalid Windows drive letters.") - test.no_result(1); + test.no_result(1) test.write('SConstruct', """ def cat(env, source, target): diff --git a/test/implicit-cache/SetOption.py b/test/implicit-cache/SetOption.py index f86ad47..d98ff8b 100644 --- a/test/implicit-cache/SetOption.py +++ b/test/implicit-cache/SetOption.py @@ -63,7 +63,7 @@ test.run(arguments = '.') test.write('i1/foo.h', """ this line will cause a syntax error if it's included by a rebuild -"""); +""") test.up_to_date(arguments = '.') diff --git a/test/site_scons/sysdirs.py b/test/site_scons/sysdirs.py index 60b4f0b..36a581e 100644 --- a/test/site_scons/sysdirs.py +++ b/test/site_scons/sysdirs.py @@ -50,7 +50,7 @@ import SCons.Platform platform = SCons.Platform.platform_default() if platform in ('win32', 'cygwin'): dir_to_check_for='Application Data' -elif platform in ('darwin'): +elif platform in 'darwin': dir_to_check_for='Library' else: dir_to_check_for='.scons' diff --git a/testing/framework/TestCmd.py b/testing/framework/TestCmd.py index 447d050..b98445c 100644 --- a/testing/framework/TestCmd.py +++ b/testing/framework/TestCmd.py @@ -667,7 +667,7 @@ def diff_re(a, b, fromfile='', tofile='', if os.name == 'posix': def escape(arg): - "escape shell special characters" + """escape shell special characters""" slash = '\\' special = '"$' arg = arg.replace(slash, slash + slash) diff --git a/testing/framework/TestCmdTests.py b/testing/framework/TestCmdTests.py index 541df71..0c7b455 100644 --- a/testing/framework/TestCmdTests.py +++ b/testing/framework/TestCmdTests.py @@ -121,8 +121,8 @@ class TestCmdTestCase(unittest.TestCase): else: textx = '#! /usr/bin/env python\n' + textx + '\n' text1 = 'A first line to be ignored!\n' + fmt % (t.script1, t.script1) - textout = fmtout % (t.scriptout) - texterr = fmterr % (t.scripterr) + textout = fmtout % t.scriptout + texterr = fmterr % t.scripterr run_env = TestCmd.TestCmd(workdir = '') run_env.subdir('sub dir') @@ -1974,7 +1974,7 @@ class run_verbose_TestCase(TestCmdTestCase): assert expect == o, (expect, o) e = sys.stderr.getvalue() - expect = 'python "%s" "arg1 arg2"\n' % (t.scriptout_path) + expect = 'python "%s" "arg1 arg2"\n' % t.scriptout_path assert e == expect, (e, expect) test = TestCmd.TestCmd(program = t.scriptout, @@ -1993,7 +1993,7 @@ class run_verbose_TestCase(TestCmdTestCase): assert expect == o, (expect, o) e = sys.stderr.getvalue() - expect = 'python "%s" "arg1 arg2"\n' % (t.scriptout_path) + expect = 'python "%s" "arg1 arg2"\n' % t.scriptout_path assert e == expect, (e, expect) # Test letting TestCmd() pick up verbose = 2 from the environment. diff --git a/testing/framework/TestSCons.py b/testing/framework/TestSCons.py index d1aed28..a633617 100644 --- a/testing/framework/TestSCons.py +++ b/testing/framework/TestSCons.py @@ -817,7 +817,7 @@ class TestSCons(TestCommon): sp = subprocess.Popen([where_java_bin, "-version"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = sp.communicate() sp.wait() - if("No Java runtime" in str(stderr)): + if "No Java runtime" in str(stderr): self.skip_test("Could not find Java " + java_bin_name + ", skipping test(s).\n") def java_where_jar(self, version=None): diff --git a/testing/framework/TestUnit/taprunner.py b/testing/framework/TestUnit/taprunner.py index 5c2e87c..0dde327 100644 --- a/testing/framework/TestUnit/taprunner.py +++ b/testing/framework/TestUnit/taprunner.py @@ -62,7 +62,7 @@ class TAPTestResult(TextTestResult): def addExpectedFailure(self, test, err): super(TextTestResult, self).addExpectedFailure(test, err) - self._process(test, "not ok", directive=(" # TODO")) + self._process(test, "not ok", directive=" # TODO") def addUnexpectedSuccess(self, test): super(TextTestResult, self).addUnexpectedSuccess(test) -- cgit v0.12 From d88e0e7b976c2f9e261f03189441ab6af4c37de3 Mon Sep 17 00:00:00 2001 From: Mathew Robinson Date: Mon, 23 Dec 2019 10:05:36 -0500 Subject: Prevent unnecessary eval calls in Subst --- src/CHANGES.txt | 3 ++ src/engine/SCons/Subst.py | 70 +++++++++++++++++++++++++---------------------- 2 files changed, 41 insertions(+), 32 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 87980a8..f8452c7 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -12,6 +12,9 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Improve performance of Subst by preventing unnecessary frame allocations by no longer defining the *Subber classes inside of their respective function calls. + - Improve performance of Subst in some cases by preventing + unnecessary calls to eval when a token is surrounded in braces + but is not a function call. From Mats Wichmann: - Remove deprecated SourceCode diff --git a/src/engine/SCons/Subst.py b/src/engine/SCons/Subst.py index f3693a1..2e469ce 100644 --- a/src/engine/SCons/Subst.py +++ b/src/engine/SCons/Subst.py @@ -375,23 +375,26 @@ class StringSubber(object): if key[0] == '{' or '.' in key: if key[0] == '{': key = key[1:-1] - try: - s = eval(key, self.gvars, lvars) - except KeyboardInterrupt: - raise - except Exception as e: - if e.__class__ in AllowableExceptions: - return '' - raise_exception(e, lvars['TARGETS'], s) + + s = None + if key in lvars: + s = lvars[key] + elif key in self.gvars: + s = self.gvars[key] else: - if key in lvars: - s = lvars[key] - elif key in self.gvars: - s = self.gvars[key] - elif NameError not in AllowableExceptions: - raise_exception(NameError(key), lvars['TARGETS'], s) - else: - return '' + try: + s = eval(key, self.gvars, lvars) + except KeyboardInterrupt: + raise + except Exception as e: + if e.__class__ in AllowableExceptions: + return '' + raise_exception(e, lvars['TARGETS'], s) + + if s is None and NameError not in AllowableExceptions: + raise_exception(NameError(key), lvars['TARGETS'], s) + elif s is None: + return '' # Before re-expanding the result, handle # recursive expansion by copying the local @@ -524,23 +527,26 @@ class ListSubber(collections.UserList): if key[0] == '{' or key.find('.') >= 0: if key[0] == '{': key = key[1:-1] - try: - s = eval(key, self.gvars, lvars) - except KeyboardInterrupt: - raise - except Exception as e: - if e.__class__ in AllowableExceptions: - return - raise_exception(e, lvars['TARGETS'], s) + + s = None + if key in lvars: + s = lvars[key] + elif key in self.gvars: + s = self.gvars[key] else: - if key in lvars: - s = lvars[key] - elif key in self.gvars: - s = self.gvars[key] - elif NameError not in AllowableExceptions: - raise_exception(NameError(), lvars['TARGETS'], s) - else: - return + try: + s = eval(key, self.gvars, lvars) + except KeyboardInterrupt: + raise + except Exception as e: + if e.__class__ in AllowableExceptions: + return + raise_exception(e, lvars['TARGETS'], s) + + if s is None and NameError not in AllowableExceptions: + raise_exception(NameError(), lvars['TARGETS'], s) + elif s is None: + return # Before re-expanding the result, handle # recursive expansion by copying the local -- cgit v0.12 From c4e058dc877e9330110ab7a732b82de1224dc815 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 23 Dec 2019 17:43:32 -0800 Subject: Add propagating VCINSTALLDIR and VCToolsInstallDir which are used by CLang to find MSVC files including header files aka stdio.h,etc --- src/engine/SCons/Tool/MSCommon/common.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/engine/SCons/Tool/MSCommon/common.py b/src/engine/SCons/Tool/MSCommon/common.py index bbccf61..386f445 100644 --- a/src/engine/SCons/Tool/MSCommon/common.py +++ b/src/engine/SCons/Tool/MSCommon/common.py @@ -50,7 +50,7 @@ elif LOGFILE: level=logging.DEBUG) debug = logging.getLogger(name=__name__).debug else: - debug = lambda x: None + def debug(x): return None # SCONS_CACHE_MSVC_CONFIG is public, and is documented. @@ -58,6 +58,7 @@ CONFIG_CACHE = os.environ.get('SCONS_CACHE_MSVC_CONFIG') if CONFIG_CACHE in ('1', 'true', 'True'): CONFIG_CACHE = os.path.join(os.path.expanduser('~'), '.scons_msvc_cache') + def read_script_env_cache(): """ fetch cached msvc env vars if requested, else return empty dict """ envcache = {} @@ -65,7 +66,7 @@ def read_script_env_cache(): try: with open(CONFIG_CACHE, 'r') as f: envcache = json.load(f) - #TODO can use more specific FileNotFoundError when py2 dropped + # TODO can use more specific FileNotFoundError when py2 dropped except IOError: # don't fail if no cache file, just proceed without it pass @@ -88,6 +89,7 @@ def write_script_env_cache(cache): _is_win64 = None + def is_win64(): """Return true if running on windows 64 bits. @@ -122,6 +124,7 @@ def is_win64(): def read_reg(value, hkroot=SCons.Util.HKEY_LOCAL_MACHINE): return SCons.Util.RegGetValue(hkroot, value)[0] + def has_reg(value): """Return True if the given key exists in HKEY_LOCAL_MACHINE, False otherwise.""" @@ -134,6 +137,7 @@ def has_reg(value): # Functions for fetching environment variable settings from batch files. + def normalize_env(env, keys, force=False): """Given a dictionary representing a shell environment, add the variables from os.environ needed for the processing of .bat files; the keys are @@ -172,11 +176,12 @@ def normalize_env(env, keys, force=False): if sys32_wbem_dir not in normenv['PATH']: normenv['PATH'] = normenv['PATH'] + os.pathsep + sys32_wbem_dir - debug("PATH: %s"%normenv['PATH']) + debug("PATH: %s" % normenv['PATH']) return normenv -def get_output(vcbat, args = None, env = None): + +def get_output(vcbat, args=None, env=None): """Parse the output of given bat file, with given args.""" if env is None: @@ -242,7 +247,13 @@ def get_output(vcbat, args = None, env = None): output = stdout.decode("mbcs") return output -KEEPLIST = ("INCLUDE", "LIB", "LIBPATH", "PATH", 'VSCMD_ARG_app_plat') + +KEEPLIST = ("INCLUDE", "LIB", "LIBPATH", "PATH", 'VSCMD_ARG_app_plat', + 'VCINSTALLDIR', # needed by clang -VS 2017 and newer + 'VCToolsInstallDir', # needed by clang - VS 2015 and older + ) + + def parse_output(output, keep=KEEPLIST): """ Parse output from running visual c++/studios vcvarsall.bat and running set -- cgit v0.12 From cac7a17bad265db91ba06c9c97862d31edca306d Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Tue, 24 Dec 2019 07:51:10 -0700 Subject: [PR #3509] change tuple syntax per review comment [ci skip] A couple of tools in bin had argument-handling lines that looked like: elif o in ('--username') original change made that into a tuple: ('--username',) except where I missed it and the parens were just dropped. Now these are elif o == '--username' Skipped CI builds on this one since the change doesn't affect scons code itself and is not run by CI. Signed-off-by: Mats Wichmann --- bin/scons-diff.py | 6 +++--- bin/scons_dev_master.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bin/scons-diff.py b/bin/scons-diff.py index 0bed74b..c62b926 100644 --- a/bin/scons-diff.py +++ b/bin/scons-diff.py @@ -54,16 +54,16 @@ for o, a in opts: elif o in ('-h', '--help'): print(Usage) sys.exit(0) - elif o in ('-n',): + elif o == '-n': diff_options.append(o) edit_type = o - elif o in ('-q',): + elif o == '-q': diff_type = o diff_line = lambda l, r: None elif o in ('-r', '--recursive'): recursive = True diff_options.append(o) - elif o in ('-s',): + elif o '-s': report_same = True try: diff --git a/bin/scons_dev_master.py b/bin/scons_dev_master.py index d4c8e90..c8cc0f9 100755 --- a/bin/scons_dev_master.py +++ b/bin/scons_dev_master.py @@ -152,11 +152,11 @@ Usage: scons_dev_master.py [-hnqy] [--password PASSWORD] [--username USER] sys.exit(0) elif o in ('-n', '--no-exec'): CommandRunner.execute = CommandRunner.do_not_execute - elif o in '--password': + elif o == '--password': password = a elif o in ('-q', '--quiet'): CommandRunner.display = CommandRunner.do_not_display - elif o in '--username': + elif o == '--username': username = a elif o in ('-y', '--yes', '--assume-yes'): yesflag = o -- cgit v0.12 From fc0e28b11d21fc6a39d2575cc523e385b713a5e9 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Tue, 24 Dec 2019 10:00:35 -0700 Subject: fix error in scons-diff.py [ci skip] --- bin/scons-diff.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/scons-diff.py b/bin/scons-diff.py index c62b926..09b3dcc 100644 --- a/bin/scons-diff.py +++ b/bin/scons-diff.py @@ -63,7 +63,7 @@ for o, a in opts: elif o in ('-r', '--recursive'): recursive = True diff_options.append(o) - elif o '-s': + elif o == '-s': report_same = True try: -- cgit v0.12 From 71bf1efe99a488d482032ad0d64f1defd9b32b04 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 25 Dec 2019 12:17:44 -0800 Subject: Add c:\msys64\mingw64\bin for appveyor vs2019 --- src/engine/SCons/Tool/clangCommon/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/engine/SCons/Tool/clangCommon/__init__.py b/src/engine/SCons/Tool/clangCommon/__init__.py index 37efbf6..5501457 100644 --- a/src/engine/SCons/Tool/clangCommon/__init__.py +++ b/src/engine/SCons/Tool/clangCommon/__init__.py @@ -6,6 +6,7 @@ clang_win32_dirs = [ r'C:\Program Files\LLVM\bin', r'C:\cygwin64\bin', r'C:\msys64', + r'C:\msys64\mingw64\bin', r'C:\cygwin\bin', r'C:\msys', ] -- cgit v0.12 From caafe1f472fed10d7888ea26b39bf0c1eb71c026 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 25 Dec 2019 12:34:45 -0800 Subject: Update clang logic to initialize MSVC shell environment variables needed for clang to find include files --- src/engine/SCons/Tool/clang.py | 5 +++++ src/engine/SCons/Tool/clangxx.py | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/engine/SCons/Tool/clang.py b/src/engine/SCons/Tool/clang.py index 081ab67..162daad 100644 --- a/src/engine/SCons/Tool/clang.py +++ b/src/engine/SCons/Tool/clang.py @@ -46,6 +46,7 @@ import sys import SCons.Util import SCons.Tool.cc from SCons.Tool.clangCommon import get_clang_install_dirs +from SCons.Tool.MSCommon import msvc_setup_env_once compilers = ['clang'] @@ -62,6 +63,10 @@ def generate(env): clang_bin_dir = os.path.dirname(clang) env.AppendENVPath('PATH', clang_bin_dir) + # Set-up ms tools paths + msvc_setup_env_once(env) + + env['CC'] = env.Detect(compilers) or 'clang' if env['PLATFORM'] in ['cygwin', 'win32']: env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS') diff --git a/src/engine/SCons/Tool/clangxx.py b/src/engine/SCons/Tool/clangxx.py index a29cf79..b1dc6f3 100644 --- a/src/engine/SCons/Tool/clangxx.py +++ b/src/engine/SCons/Tool/clangxx.py @@ -47,6 +47,7 @@ import SCons.Tool import SCons.Util import SCons.Tool.cxx from SCons.Tool.clangCommon import get_clang_install_dirs +from SCons.Tool.MSCommon import msvc_setup_env_once compilers = ['clang++'] @@ -75,6 +76,10 @@ def generate(env): clangxx_bin_dir = os.path.dirname(clangxx) env.AppendENVPath('PATH', clangxx_bin_dir) + # Set-up ms tools paths + msvc_setup_env_once(env) + + # determine compiler version if env['CXX']: pipe = SCons.Action._subproc(env, [env['CXX'], '--version'], -- cgit v0.12 From 63714ab2bb12b8aa1f77e49dc6d17b024405c68c Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 25 Dec 2019 12:42:08 -0800 Subject: [ci skip] Updated CHANGES.txt --- src/CHANGES.txt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 968a2c4..328196c 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -8,9 +8,12 @@ NOTE: The 4.0.0 Release of SCons will drop Python 2.7 Support RELEASE VERSION/DATE TO BE FILLED IN LATER - From John Doe: - - - Whatever John Doe did. + From William Deegan: + - Fix broken clang + MSVC 2019 combination by using MSVC configuration logic to + propagate'VCINSTALLDIR' and 'VCToolsInstallDir' which clang tools use to locate + header files and libraries from MSVC install. (Fixes GH Issue #3480) + - Added C:\msys64\mingw64\bin to default mingw and clang windows PATH's. This + is a reasonable default and also aligns with changes in Appveyor's VS2019 image. RELEASE 3.1.2 - Mon, 17 Dec 2019 02:06:27 +0000 -- cgit v0.12 From 6e0dc8d3d9968425d711e88f03a3714d5f8643eb Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 25 Dec 2019 14:54:36 -0800 Subject: Reduce default PATH addtions to match VS2019 debug appveyor's. --- privileged/cache/config | 1 + 1 file changed, 1 insertion(+) create mode 100644 privileged/cache/config diff --git a/privileged/cache/config b/privileged/cache/config new file mode 100644 index 0000000..b39e891 --- /dev/null +++ b/privileged/cache/config @@ -0,0 +1 @@ +{"prefix_len": 2} \ No newline at end of file -- cgit v0.12 From 7b2721fe6ed1a93ac7a40c4302114518877141ea Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 26 Dec 2019 13:40:38 -0800 Subject: Fix CacheDirTest so that temp dir is not under the directory that the runtest.py is run from, but rather from the temp dir created for the test --- privileged/cache/config | 1 - src/engine/SCons/CacheDirTests.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 100644 privileged/cache/config diff --git a/privileged/cache/config b/privileged/cache/config deleted file mode 100644 index b39e891..0000000 --- a/privileged/cache/config +++ /dev/null @@ -1 +0,0 @@ -{"prefix_len": 2} \ No newline at end of file diff --git a/src/engine/SCons/CacheDirTests.py b/src/engine/SCons/CacheDirTests.py index 07c32b4..0e242c4 100644 --- a/src/engine/SCons/CacheDirTests.py +++ b/src/engine/SCons/CacheDirTests.py @@ -130,7 +130,7 @@ class ExceptionTestCase(unittest.TestCase): @unittest.skipIf(sys.platform.startswith("win"), "This fixture will not trigger an OSError on Windows") def test_throws_correct_on_OSError(self): """Test that the correct error is thrown when cache directory cannot be created.""" - privileged_dir = os.path.join(os.getcwd(), "privileged") + privileged_dir = os.path.join(self.tmpdir, "privileged") try: os.mkdir(privileged_dir) os.chmod(privileged_dir, stat.S_IREAD) -- cgit v0.12 From 5c9a3cffbbcdd19529aca9d34d9c1a9cb375735c Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 26 Dec 2019 16:15:49 -0800 Subject: Speed up test on windows by setting tools=[] --- test/SConscript/must_exist.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/test/SConscript/must_exist.py b/test/SConscript/must_exist.py index 3faf0ce..7c721ed 100644 --- a/test/SConscript/must_exist.py +++ b/test/SConscript/must_exist.py @@ -42,6 +42,7 @@ import SCons from SCons.Warnings import _warningOut import sys +DefaultEnvironment(tools=[]) # 1. call should succeed with deprecation warning try: SConscript('missing/SConscript') @@ -89,27 +90,27 @@ warn1 = """ scons: warning: Calling missing SConscript without error is deprecated. Transition by adding must_exist=0 to SConscript calls. Missing SConscript '{}' -""".format(missing) + test.python_file_line(SConstruct_path, 7) +""".format(missing) + test.python_file_line(SConstruct_path, 8) warn2 = """ scons: warning: Ignoring missing SConscript '{}' -""".format(missing) + test.python_file_line(SConstruct_path, 13) +""".format(missing) + test.python_file_line(SConstruct_path, 14) err1 = """ scons: warning: Fatal: missing SConscript '{}' -""".format(missing) + test.python_file_line(SConstruct_path, 22) +""".format(missing) + test.python_file_line(SConstruct_path, 23) warn3 = """ scons: warning: Ignoring missing SConscript '{}' -""".format(missing) + test.python_file_line(SConstruct_path, 25) +""".format(missing) + test.python_file_line(SConstruct_path, 26) err2 = """ scons: warning: Fatal: missing SConscript '{}' -""".format(missing) + test.python_file_line(SConstruct_path, 35) +""".format(missing) + test.python_file_line(SConstruct_path, 36) warn4 = """ scons: warning: Ignoring missing SConscript '{}' -""".format(missing) + test.python_file_line(SConstruct_path, 38) +""".format(missing) + test.python_file_line(SConstruct_path, 39) expect_stderr = warn1 + warn2 + err1 + warn3 + err2 + warn4 test.run(arguments = ".", stderr = expect_stderr) -- cgit v0.12 From 6d3cb377534dbf4ad4492a1451a7e3bfaf2987c6 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 26 Dec 2019 18:13:53 -0800 Subject: FIx packaging tests to use correct tar when running via os.system. Fix variantdir to use mingw on windows for linking fortran programs. --- test/VariantDir/VariantDir.py | 13 +++++-- test/packaging/place-files-in-subdirectory.py | 2 +- test/packaging/tar/bz2_packaging.py | 11 ++++-- test/packaging/use-builddir.py | 50 ++++++++++++++++----------- 4 files changed, 50 insertions(+), 26 deletions(-) diff --git a/test/VariantDir/VariantDir.py b/test/VariantDir/VariantDir.py index d212b0d..a988831 100644 --- a/test/VariantDir/VariantDir.py +++ b/test/VariantDir/VariantDir.py @@ -56,6 +56,7 @@ bar52 = test.workpath('build', 'var5', 'bar2' + _exe) test.subdir('work1', 'work2', 'work3') test.write(['work1', 'SConstruct'], """ +DefaultEnvironment(tools=[]) src = Dir('src') var2 = Dir('build/var2') var3 = Dir('build/var3') @@ -88,6 +89,7 @@ SConscript('../build/var6/SConscript', "env") test.subdir(['work1', 'src']) test.write(['work1', 'src', 'SConscript'], """ import os.path +import sys def buildIt(target, source, env): if not os.path.exists('build'): @@ -116,9 +118,16 @@ except: fortran = None if fortran and env.Detect(fortran): + if sys.platform =='win32': + env_prog=Environment(tools=['mingw'], + # BUILD = env['BUILD'], SRC = ENV['src'], + CPPPATH=env['CPPPATH'], FORTRANPATH=env['FORTRANPATH'] ) + else: + env_prog=env.Clone() + env.Command(target='b2.f', source='b2.in', action=buildIt) - env.Clone().Program(target='bar2', source='b2.f') - env.Clone().Program(target='bar1', source='b1.f') + env_prog.Program(target='bar2', source='b2.f') + env_prog.Program(target='bar1', source='b1.f') """) test.write(['work1', 'src', 'f1.c'], r""" diff --git a/test/packaging/place-files-in-subdirectory.py b/test/packaging/place-files-in-subdirectory.py index 23ff543..511f27a 100644 --- a/test/packaging/place-files-in-subdirectory.py +++ b/test/packaging/place-files-in-subdirectory.py @@ -102,7 +102,7 @@ env.Package( NAME = 'libfoo', test.run(stderr = None) -with os.popen('tar -tzf %s'%test.workpath('libfoo-1.2.3.tar.gz')) as p: +with os.popen('%s -tzf %s'%(tar,test.workpath('libfoo-1.2.3.tar.gz'))) as p: str = p.read() test.fail_test(str != "libfoo-1.2.3/src/main.c\nlibfoo-1.2.3/SConstruct\n") diff --git a/test/packaging/tar/bz2_packaging.py b/test/packaging/tar/bz2_packaging.py index 812c08e..3c1afe3 100644 --- a/test/packaging/tar/bz2_packaging.py +++ b/test/packaging/tar/bz2_packaging.py @@ -32,6 +32,7 @@ This tests the SRC bz2 packager, which does the following: import TestSCons import os +import os.path import sys python = TestSCons.python @@ -42,10 +43,12 @@ tar = test.detect('TAR', 'tar') if not tar: test.skip_test('tar not found, skipping test\n') +bz2 = test.where_is('bzip2') +bz2_path = os.path.dirname(bz2) + if sys.platform == 'win32': # windows 10 causes fresh problems by supplying a tar, not bzip2 # but if git is installed, there's a bzip2 there, but can't be used - bz2 = test.where_is('bzip2') if not bz2: test.skip_test('tar found, but helper bzip2 not found, skipping test\n') bz2 = os.path.splitdrive(bz2)[1] @@ -65,11 +68,15 @@ int main( int argc, char* argv[] ) test.write('SConstruct', """ Program( 'src/main.c' ) env=Environment(tools=['packaging', 'filesystem', 'tar']) + +# needed for windows to prevent picking up windows tar and thinking non-windows bzip2 would work. +env.PrependENVPath('PATH', r'%s') + env.Package( PACKAGETYPE = 'src_tarbz2', target = 'src.tar.bz2', PACKAGEROOT = 'test', source = [ 'src/main.c', 'SConstruct' ] ) -""") +"""%bz2_path) test.run(arguments='', stderr=None) diff --git a/test/packaging/use-builddir.py b/test/packaging/use-builddir.py index 812f2d6..2395a8e 100644 --- a/test/packaging/use-builddir.py +++ b/test/packaging/use-builddir.py @@ -34,22 +34,25 @@ import TestSCons python = TestSCons.python test = TestSCons.TestSCons() - -tar = test.detect('TAR', 'tar') +test.verbose_set(3) +tar = test.detect("TAR", "tar") if not tar: - test.skip_test('tar not found, skipping test\n') + test.skip_test("tar not found, skipping test\n") # # TEST: builddir usage. # -test.subdir('src') -test.subdir('build') +test.subdir("src") +test.subdir("build") -test.write('src/main.c', '') +test.write("src/main.c", "") -test.write('SConstruct', """ +test.write( + "SConstruct", + """ VariantDir('build', 'src') +DefaultEnvironment(tools=[]) env=Environment(tools=['packaging', 'filesystem', 'zip']) env.Package( NAME = 'libfoo', PACKAGEROOT = 'build/libfoo', @@ -57,38 +60,43 @@ env.Package( NAME = 'libfoo', PACKAGETYPE = 'src_zip', target = 'build/libfoo-1.2.3.zip', source = [ 'src/main.c', 'SConstruct' ] ) -""") +""", +) -test.run(stderr = None) +test.run(stderr=None) -test.must_exist( 'build/libfoo-1.2.3.zip' ) +test.must_exist("build/libfoo-1.2.3.zip") # TEST: builddir not placed in archive # XXX: VariantDir should be stripped. # -test.subdir('src') -test.subdir('build') -test.subdir('temp') +test.subdir("src") +test.subdir("build") +test.subdir("temp") -test.write('src/main.c', '') +test.write("src/main.c", "") -test.write('SConstruct', """ +test.write( + "SConstruct", + """ +DefaultEnvironment(tools=[]) VariantDir('build', 'src') env=Environment(tools=['packaging', 'filesystem', 'tar']) env.Package( NAME = 'libfoo', VERSION = '1.2.3', PAKCAGETYPE = 'src_targz', source = [ 'src/main.c', 'SConstruct' ] ) -""") +""", +) -test.run(stderr = None) +test.run(stderr=None) -test.must_exist( 'libfoo-1.2.3.tar.gz' ) +test.must_exist("libfoo-1.2.3.tar.gz") -os.system('tar -C temp -xzf %s'%test.workpath('libfoo-1.2.3.tar.gz') ) +os.system('%s -C temp -xzf %s'%(tar, test.workpath('libfoo-1.2.3.tar.gz') )) -test.must_exist( 'temp/libfoo-1.2.3/src/main.c' ) -test.must_exist( 'temp/libfoo-1.2.3/SConstruct' ) +test.must_exist("temp/libfoo-1.2.3/src/main.c") +test.must_exist("temp/libfoo-1.2.3/SConstruct") test.pass_test() -- cgit v0.12 From 947626eca6c9b77b7f157d16616cd54c49a0b73f Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 26 Dec 2019 19:58:31 -0800 Subject: [travis skip] Turn on verbose info when running this test. --- test/option/taskmastertrace.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/option/taskmastertrace.py b/test/option/taskmastertrace.py index b38645f..11cbf1e 100644 --- a/test/option/taskmastertrace.py +++ b/test/option/taskmastertrace.py @@ -31,6 +31,7 @@ Simple tests of the --taskmastertrace= option. import TestSCons test = TestSCons.TestSCons() +test.verbose_set(3) test.write('SConstruct', """ DefaultEnvironment(tools=[]) -- cgit v0.12 From 8ab869c9cb245e70aacd81d7981335ff1aaabbfb Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 26 Dec 2019 21:05:02 -0800 Subject: [skip travis] Fix tar xz packaging on appveyor/windows --- test/packaging/tar/xz_packaging.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/test/packaging/tar/xz_packaging.py b/test/packaging/tar/xz_packaging.py index 1d80f7f..1f83632 100644 --- a/test/packaging/tar/xz_packaging.py +++ b/test/packaging/tar/xz_packaging.py @@ -28,13 +28,12 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" This tests the SRC xz packager, which does the following: - create a tar package from the specified files """ - +import os.path import TestSCons python = TestSCons.python test = TestSCons.TestSCons() - tar = test.detect('TAR', 'tar') if not tar: test.skip_test('tar not found, skipping test\n') @@ -46,6 +45,8 @@ xz = test.where_is('xz') if not xz: test.skip_test('tar found, but helper xz not found, skipping test\n') +xz_path = os.path.dirname(xz) + test.subdir('src') test.write([ 'src', 'main.c'], r""" @@ -56,13 +57,18 @@ int main( int argc, char* argv[] ) """) test.write('SConstruct', """ +DefaultEnvironment(tools=[]) Program( 'src/main.c' ) env=Environment(tools=['packaging', 'filesystem', 'tar']) + +# needed for windows to prevent picking up windows tar and thinking non-windows bzip2 would work. +env.PrependENVPath('PATH', r'%s') + env.Package( PACKAGETYPE = 'src_tarxz', target = 'src.tar.xz', PACKAGEROOT = 'test', source = [ 'src/main.c', 'SConstruct' ] ) -""") +"""%xz_path) test.run(arguments='', stderr=None) -- cgit v0.12 From cd25d093cb4c9be8ca0e8f766dc5b60463c4daf0 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 27 Dec 2019 08:14:21 -0800 Subject: Fix Program() usage in xz test. --- test/packaging/tar/xz_packaging.py | 1 - 1 file changed, 1 deletion(-) diff --git a/test/packaging/tar/xz_packaging.py b/test/packaging/tar/xz_packaging.py index 1f83632..5144235 100644 --- a/test/packaging/tar/xz_packaging.py +++ b/test/packaging/tar/xz_packaging.py @@ -57,7 +57,6 @@ int main( int argc, char* argv[] ) """) test.write('SConstruct', """ -DefaultEnvironment(tools=[]) Program( 'src/main.c' ) env=Environment(tools=['packaging', 'filesystem', 'tar']) -- cgit v0.12 From 0dfb7626a5b15007be01fec23966a5a28c4159f3 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 27 Dec 2019 08:17:01 -0800 Subject: Try running each flavor in a single job instead of splitting into 4. --- .appveyor.yml | 122 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 9a94529..0cca999 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -54,84 +54,84 @@ environment: PYVER: 27 BUILD_JOB_NUM: 1 COVERAGE: 0 - - WINPYTHON: "Python27" - PYTHON: "2.7" - PYVER: 27 - BUILD_JOB_NUM: 2 - COVERAGE: 0 - - WINPYTHON: "Python27" - PYTHON: "2.7" - PYVER: 27 - BUILD_JOB_NUM: 3 - COVERAGE: 0 - - WINPYTHON: "Python27" - PYTHON: "2.7" - PYVER: 27 - BUILD_JOB_NUM: 4 - COVERAGE: 0 + # - WINPYTHON: "Python27" + # PYTHON: "2.7" + # PYVER: 27 + # BUILD_JOB_NUM: 2 + # COVERAGE: 0 + # - WINPYTHON: "Python27" + # PYTHON: "2.7" + # PYVER: 27 + # BUILD_JOB_NUM: 3 + # COVERAGE: 0 + # - WINPYTHON: "Python27" + # PYTHON: "2.7" + # PYVER: 27 + # BUILD_JOB_NUM: 4 + # COVERAGE: 0 - WINPYTHON: "Python35" PYTHON: "3.5" PYVER: 35 BUILD_JOB_NUM: 1 COVERAGE: 0 - - WINPYTHON: "Python35" - PYTHON: "3.5" - PYVER: 35 - BUILD_JOB_NUM: 2 - COVERAGE: 0 - - WINPYTHON: "Python35" - PYTHON: "3.5" - PYVER: 35 - BUILD_JOB_NUM: 3 - COVERAGE: 0 - - WINPYTHON: "Python35" - PYTHON: "3.5" - PYVER: 35 - BUILD_JOB_NUM: 4 - COVERAGE: 0 + # - WINPYTHON: "Python35" + # PYTHON: "3.5" + # PYVER: 35 + # BUILD_JOB_NUM: 2 + # COVERAGE: 0 + # - WINPYTHON: "Python35" + # PYTHON: "3.5" + # PYVER: 35 + # BUILD_JOB_NUM: 3 + # COVERAGE: 0 + # - WINPYTHON: "Python35" + # PYTHON: "3.5" + # PYVER: 35 + # BUILD_JOB_NUM: 4 + # COVERAGE: 0 - WINPYTHON: "Python36" PYTHON: "3.6" PYVER: 36 BUILD_JOB_NUM: 1 COVERAGE: 1 - - WINPYTHON: "Python36" - PYTHON: "3.6" - PYVER: 36 - BUILD_JOB_NUM: 2 - COVERAGE: 1 - - WINPYTHON: "Python36" - PYTHON: "3.6" - PYVER: 36 - BUILD_JOB_NUM: 3 - COVERAGE: 1 - - WINPYTHON: "Python36" - PYTHON: "3.6" - PYVER: 36 - BUILD_JOB_NUM: 4 - COVERAGE: 1 + # - WINPYTHON: "Python36" + # PYTHON: "3.6" + # PYVER: 36 + # BUILD_JOB_NUM: 2 + # COVERAGE: 1 + # - WINPYTHON: "Python36" + # PYTHON: "3.6" + # PYVER: 36 + # BUILD_JOB_NUM: 3 + # COVERAGE: 1 + # - WINPYTHON: "Python36" + # PYTHON: "3.6" + # PYVER: 36 + # BUILD_JOB_NUM: 4 + # COVERAGE: 1 - WINPYTHON: "Python37" PYTHON: "3.7" PYVER: 37 BUILD_JOB_NUM: 1 COVERAGE: 0 - - WINPYTHON: "Python37" - PYTHON: "3.7" - PYVER: 37 - BUILD_JOB_NUM: 2 - COVERAGE: 0 - - WINPYTHON: "Python37" - PYTHON: "3.7" - PYVER: 37 - BUILD_JOB_NUM: 3 - COVERAGE: 0 - - WINPYTHON: "Python37" - PYTHON: "3.7" - PYVER: 37 - BUILD_JOB_NUM: 4 - COVERAGE: 0 + # - WINPYTHON: "Python37" + # PYTHON: "3.7" + # PYVER: 37 + # BUILD_JOB_NUM: 2 + # COVERAGE: 0 + # - WINPYTHON: "Python37" + # PYTHON: "3.7" + # PYVER: 37 + # BUILD_JOB_NUM: 3 + # COVERAGE: 0 + # - WINPYTHON: "Python37" + # PYTHON: "3.7" + # PYVER: 37 + # BUILD_JOB_NUM: 4 + # COVERAGE: 0 # remove sets of build jobs based on critia below # to fine tune the number and platforms tested @@ -207,7 +207,7 @@ build_script: # setup portion of tests for this build job (1-4) - ps: | - $TOTAL_BUILD_JOBS = 4; + $TOTAL_BUILD_JOBS = 1; $Lines = (Get-Content all_tests.txt | Measure-Object -line).Lines; $start = ($Lines / $TOTAL_BUILD_JOBS) * ($Env:BUILD_JOB_NUM - 1); $end = ($Lines / $TOTAL_BUILD_JOBS) * $Env:BUILD_JOB_NUM; -- cgit v0.12 From 3b7df24765e56e6723f249081b65ab4215451863 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 27 Dec 2019 10:18:00 -0800 Subject: Speed up some tests by setting (Default)Environment(tools=[]) --- test/Actions/pre-post-fixture/work2/SConstruct | 4 ++-- test/Actions/pre-post-fixture/work3/SConstruct | 2 +- test/Actions/pre-post.py | 6 +++++- test/file-names.py | 2 +- test/option--max-drift.py | 8 ++++++-- 5 files changed, 15 insertions(+), 7 deletions(-) diff --git a/test/Actions/pre-post-fixture/work2/SConstruct b/test/Actions/pre-post-fixture/work2/SConstruct index 6f03a53..e0af0ee 100644 --- a/test/Actions/pre-post-fixture/work2/SConstruct +++ b/test/Actions/pre-post-fixture/work2/SConstruct @@ -1,8 +1,8 @@ def b(target, source, env): with open(str(target[0]), 'wb') as f: f.write((env['X'] + '\n').encode()) -env1 = Environment(X='111') -env2 = Environment(X='222') +env1 = Environment(X='111', tools=[]) +env2 = Environment(X='222', tools=[]) B = Builder(action = b, env = env1, multi=1) print("B =", B) print("B.env =", B.env) diff --git a/test/Actions/pre-post-fixture/work3/SConstruct b/test/Actions/pre-post-fixture/work3/SConstruct index d523295..e0aa257 100644 --- a/test/Actions/pre-post-fixture/work3/SConstruct +++ b/test/Actions/pre-post-fixture/work3/SConstruct @@ -5,7 +5,7 @@ def post(target, source, env): def build(target, source, env): with open(str(target[0]), 'wb') as f: f.write(b'build()\n') -env = Environment() +env = Environment(tools=[]) AddPreAction('dir', pre) AddPostAction('dir', post) env.Command('dir/file', [], build) diff --git a/test/Actions/pre-post.py b/test/Actions/pre-post.py index cd0bfb4..4d22b07 100644 --- a/test/Actions/pre-post.py +++ b/test/Actions/pre-post.py @@ -43,6 +43,7 @@ test.write(['work1', 'SConstruct'], """ import os.path import stat +# DefaultEnvironment(tools=[]) env = Environment(XXX='bar%(_exe)s') def before(env, target, source): @@ -103,13 +104,16 @@ test.must_match(['work3', 'dir', 'file'], "build()\n") # work4 start test.write(['work4', 'SConstruct'], """\ + +DefaultEnvironment(tools=[]) + def pre_action(target, source, env): with open(str(target[0]), 'ab') as f: f.write(('pre %%s\\n' %% source[0]).encode()) def post_action(target, source, env): with open(str(target[0]), 'ab') as f: f.write(('post %%s\\n' %% source[0]).encode()) -env = Environment() +env = Environment(tools=[]) o = env.Command(['pre-post', 'file.out'], 'file.in', r'%(_python_)s build.py ${TARGETS[1]} $SOURCE') diff --git a/test/file-names.py b/test/file-names.py index 4b8ec1a..baafbee 100644 --- a/test/file-names.py +++ b/test/file-names.py @@ -98,7 +98,7 @@ def create_command(a, b, c): b = ('', 'out')[b] return 'env.Command("' + a + get_filename('',c) + b + '", "'+get_filename("in",c)+ '","' + commandString + '")' -sconstruct = [ 'import sys', 'env = Environment()' ] +sconstruct = [ 'import sys', 'env = Environment(tools=[])' ] for c in goodChars: if c == '$': c = '$$' diff --git a/test/option--max-drift.py b/test/option--max-drift.py index b90ecdf..9db3933 100644 --- a/test/option--max-drift.py +++ b/test/option--max-drift.py @@ -39,8 +39,9 @@ with open(sys.argv[1], 'wb') as f, open(sys.argv[2], 'rb') as ifp: """) test.write('SConstruct', """ +DefaultEnvironment(tools=[]) B = Builder(action = r'%(_python_)s build.py $TARGETS $SOURCES') -env = Environment(BUILDERS = { 'B' : B }) +env = Environment(BUILDERS = { 'B' : B }, tools=[]) env.B(target = 'f1.out', source = 'f1.in') env.B(target = 'f2.out', source = 'f2.in') """ % locals()) @@ -77,6 +78,7 @@ test.run(arguments = '--max-drift=-1 f1.out f2.out', stdout = expect) # Test that Set/GetOption('max_drift') works: test.write('SConstruct', """ +DefaultEnvironment(tools=[]) assert GetOption('max_drift') == 2*24*60*60 SetOption('max_drift', 1) assert GetOption('max_drift') == 1 @@ -85,6 +87,7 @@ assert GetOption('max_drift') == 1 test.run() test.write('SConstruct', """ +DefaultEnvironment(tools=[]) assert GetOption('max_drift') == 1 SetOption('max_drift', 10) assert GetOption('max_drift') == 1 @@ -95,9 +98,10 @@ test.run(arguments='--max-drift=1') # Test that SetOption('max_drift') actually sets max_drift # by mucking with the file timestamps to make SCons not realize the source has changed test.write('SConstruct', """ +DefaultEnvironment(tools=[]) SetOption('max_drift', 0) B = Builder(action = r'%(_python_)s build.py $TARGETS $SOURCES') -env = Environment(BUILDERS = { 'B' : B }) +env = Environment(BUILDERS = { 'B' : B }, tools=[]) env.B(target = 'foo.out', source = 'foo.in') """ % locals()) -- cgit v0.12 From d13894cdf838a09c49fa6afe201b8b8eb3999e21 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 27 Dec 2019 10:46:25 -0800 Subject: debug py27 taskmastertrace test failure. --- .appveyor.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 0cca999..6459709 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -7,6 +7,9 @@ image: - Visual Studio 2017 - Visual Studio 2019 +on_finish: + - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) + cache: - downloads -> appveyor.yml - '%LOCALAPPDATA%\pip\Cache' @@ -145,13 +148,13 @@ matrix: - image: Visual Studio 2015 WINPYTHON: "Python37" - # test python 2.7, 3.6 on Visual Studio 2017 image + # test python 3.5, 3.6 on Visual Studio 2017 image - image: Visual Studio 2017 WINPYTHON: "Python35" - image: Visual Studio 2017 WINPYTHON: "Python37" - # test python 3.7 on Visual Studio 2019 image + # test python 2.7, 3.5, 3.6 on Visual Studio 2019 image - image: Visual Studio 2019 WINPYTHON: "Python27" - image: Visual Studio 2019 @@ -159,7 +162,7 @@ matrix: - image: Visual Studio 2019 WINPYTHON: "Python36" - # test python 3.7 on Ubuntu + # test python 2.7, 3.5, 3.6 on Ubuntu - image: Ubuntu WINPYTHON: "Python27" - image: Ubuntu -- cgit v0.12 From 05c10a004d653265b4d0497511ea10fc97f173c5 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 27 Dec 2019 10:47:45 -0800 Subject: [skip travis] debugging --- .appveyor.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 6459709..3cbe26d 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -7,9 +7,6 @@ image: - Visual Studio 2017 - Visual Studio 2019 -on_finish: - - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) - cache: - downloads -> appveyor.yml - '%LOCALAPPDATA%\pip\Cache' @@ -258,3 +255,5 @@ on_finish: #- cmd: "C:\\%WINPYTHON%\\python.exe -m pip install --user -U coveralls" #- sh: python$PYTHON -m pip install --user -U coveralls #- ps: coveralls --rcfile="$($env:COVERAGE_PROCESS_START)" + - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) + -- cgit v0.12 From 03dc611bc7c64e0c7534749fc5558fb6aa5f81ab Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 27 Dec 2019 10:54:25 -0800 Subject: [skip travis] debug --- .appveyor.yml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 3cbe26d..01e0644 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -145,21 +145,30 @@ matrix: - image: Visual Studio 2015 WINPYTHON: "Python37" - # test python 3.5, 3.6 on Visual Studio 2017 image + - image: Visual Studio 2015 + WINPYTHON: "Python35" + + # test python 2.7, 3.8 on Visual Studio 2017 image - image: Visual Studio 2017 WINPYTHON: "Python35" - image: Visual Studio 2017 WINPYTHON: "Python37" - # test python 2.7, 3.5, 3.6 on Visual Studio 2019 image + - image: Visual Studio 2017 + WINPYTHON: "Python36" + + # test python 3.7 on Visual Studio 2019 image - image: Visual Studio 2019 WINPYTHON: "Python27" - image: Visual Studio 2019 WINPYTHON: "Python35" - image: Visual Studio 2019 WINPYTHON: "Python36" + + - image: Visual Studio 2019 + WINPYTHON: "Python37" - # test python 2.7, 3.5, 3.6 on Ubuntu + # skip on Ubuntu - image: Ubuntu WINPYTHON: "Python27" - image: Ubuntu -- cgit v0.12 From d439f374d3eee72c4bac6a7c98503d7682b33a93 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 27 Dec 2019 10:59:15 -0800 Subject: [skip travis] debug --- .appveyor.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index 01e0644..e930e0c 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -164,7 +164,7 @@ matrix: WINPYTHON: "Python35" - image: Visual Studio 2019 WINPYTHON: "Python36" - + - image: Visual Studio 2019 WINPYTHON: "Python37" @@ -232,6 +232,8 @@ build_script: if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq $workaround_image) { Add-Content -Path 'exclude_list.txt' -Value 'test\MSVS\vs-10.0-exec.py' } + Remove-Item -Path 'all_tests.txt' + Add-Content -Path 'all_tests.txt' -Value 'test\options\taskmastertrace.py' # Windows run the tests # NOTE: running powershell from cmd on purpose because it formats the output -- cgit v0.12 From f948471e75086c112cf3a31de43a6e043514609b Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 27 Dec 2019 11:03:59 -0800 Subject: [skip travis] debug --- .appveyor.yml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index e930e0c..8ad2ab0 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -228,17 +228,14 @@ build_script: # https://help.appveyor.com/discussions/problems/19283-visual-studio-2010-trial-license-has-expired - ps: | New-Item -Name exclude_list.txt -ItemType File - $workaround_image = "Visual Studio 2015" - if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq $workaround_image) { - Add-Content -Path 'exclude_list.txt' -Value 'test\MSVS\vs-10.0-exec.py' - } Remove-Item -Path 'all_tests.txt' - Add-Content -Path 'all_tests.txt' -Value 'test\options\taskmastertrace.py' + New-Item -Name all_tests.txt -ItemType File + Add-Content -Path 'all_tests.txt' -Value 'test\option\taskmastertrace.py' # Windows run the tests # NOTE: running powershell from cmd on purpose because it formats the output # correctly - - cmd: powershell -Command "& { if($env:COVERAGE -eq 1) { coverage run -p --rcfile=$($env:COVERAGE_PROCESS_START) runtest.py -j 2 -t --exclude-list exclude_list.txt -f build_tests.txt } else { C:\\%WINPYTHON%\\python.exe runtest.py -j 2 -t --exclude-list exclude_list.txt -f build_tests.txt }; if($LastExitCode -eq 2 -Or $LastExitCode -eq 0) { $host.SetShouldExit(0 )} else {$host.SetShouldExit(1)}}" + - cmd: powershell -Command "& { if($env:COVERAGE -eq 99) { coverage run -p --rcfile=$($env:COVERAGE_PROCESS_START) runtest.py -j 2 -t --exclude-list exclude_list.txt -f build_tests.txt } else { C:\\%WINPYTHON%\\python.exe runtest.py -j 2 -t --exclude-list exclude_list.txt -f build_tests.txt }; if($LastExitCode -eq 2 -Or $LastExitCode -eq 0) { $host.SetShouldExit(0 )} else {$host.SetShouldExit(1)}}" # linux run the tests # unset JAVA_TOOL_OPTIONS because newer java prints this to stderr -- cgit v0.12 From 78d62652009205461d5d7a7eaf3bb8c2cf7e12a8 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 27 Dec 2019 11:07:43 -0800 Subject: [travis skip] debug --- .appveyor.yml | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 8ad2ab0..a55eecb 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -214,6 +214,13 @@ build_script: $coveragercFile|Set-Content "$($env:COVERAGE_PROCESS_START)"; } + # Only run one test for now. + - ps: | + New-Item -Name exclude_list.txt -ItemType File + Remove-Item -Path 'all_tests.txt' + New-Item -Name all_tests.txt -ItemType File + Add-Content -Path 'all_tests.txt' -Value 'test\option\taskmastertrace.py' + # setup portion of tests for this build job (1-4) - ps: | $TOTAL_BUILD_JOBS = 1; @@ -224,14 +231,6 @@ build_script: if ( $start -eq 0 ){ $start = 1 }; get-content all_tests.txt | select -first ($end - $start) -skip ($start - 1) | Out-File -Encoding ASCII build_tests.txt; - # exclude VS 10.0 because it hangs the testing until this is resolved: - # https://help.appveyor.com/discussions/problems/19283-visual-studio-2010-trial-license-has-expired - - ps: | - New-Item -Name exclude_list.txt -ItemType File - Remove-Item -Path 'all_tests.txt' - New-Item -Name all_tests.txt -ItemType File - Add-Content -Path 'all_tests.txt' -Value 'test\option\taskmastertrace.py' - # Windows run the tests # NOTE: running powershell from cmd on purpose because it formats the output # correctly -- cgit v0.12 From 4882d361c6bb9c7ea2863227bc5ff411b15e1da4 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 27 Dec 2019 11:27:44 -0800 Subject: [travis skip] restore to non-debug settings. --- .appveyor.yml | 18 +++++------------- test/option/taskmastertrace.py | 6 +----- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index a55eecb..e22ed9b 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -145,8 +145,6 @@ matrix: - image: Visual Studio 2015 WINPYTHON: "Python37" - - image: Visual Studio 2015 - WINPYTHON: "Python35" # test python 2.7, 3.8 on Visual Studio 2017 image - image: Visual Studio 2017 @@ -154,9 +152,6 @@ matrix: - image: Visual Studio 2017 WINPYTHON: "Python37" - - image: Visual Studio 2017 - WINPYTHON: "Python36" - # test python 3.7 on Visual Studio 2019 image - image: Visual Studio 2019 WINPYTHON: "Python27" @@ -165,9 +160,6 @@ matrix: - image: Visual Studio 2019 WINPYTHON: "Python36" - - image: Visual Studio 2019 - WINPYTHON: "Python37" - # skip on Ubuntu - image: Ubuntu WINPYTHON: "Python27" @@ -214,12 +206,12 @@ build_script: $coveragercFile|Set-Content "$($env:COVERAGE_PROCESS_START)"; } - # Only run one test for now. + # Create exclude_list.txt (was used to exclude some failing tests due to appveyor issues) - ps: | New-Item -Name exclude_list.txt -ItemType File - Remove-Item -Path 'all_tests.txt' - New-Item -Name all_tests.txt -ItemType File - Add-Content -Path 'all_tests.txt' -Value 'test\option\taskmastertrace.py' + # Remove-Item -Path 'all_tests.txt' + # New-Item -Name all_tests.txt -ItemType File + # Add-Content -Path 'all_tests.txt' -Value 'test\option\taskmastertrace.py' # setup portion of tests for this build job (1-4) - ps: | @@ -234,7 +226,7 @@ build_script: # Windows run the tests # NOTE: running powershell from cmd on purpose because it formats the output # correctly - - cmd: powershell -Command "& { if($env:COVERAGE -eq 99) { coverage run -p --rcfile=$($env:COVERAGE_PROCESS_START) runtest.py -j 2 -t --exclude-list exclude_list.txt -f build_tests.txt } else { C:\\%WINPYTHON%\\python.exe runtest.py -j 2 -t --exclude-list exclude_list.txt -f build_tests.txt }; if($LastExitCode -eq 2 -Or $LastExitCode -eq 0) { $host.SetShouldExit(0 )} else {$host.SetShouldExit(1)}}" + - cmd: powershell -Command "& { if($env:COVERAGE -eq 1) { coverage run -p --rcfile=$($env:COVERAGE_PROCESS_START) runtest.py -j 2 -t --exclude-list exclude_list.txt -f build_tests.txt } else { C:\\%WINPYTHON%\\python.exe runtest.py -j 2 -t --exclude-list exclude_list.txt -f build_tests.txt }; if($LastExitCode -eq 2 -Or $LastExitCode -eq 0) { $host.SetShouldExit(0 )} else {$host.SetShouldExit(1)}}" # linux run the tests # unset JAVA_TOOL_OPTIONS because newer java prints this to stderr diff --git a/test/option/taskmastertrace.py b/test/option/taskmastertrace.py index 11cbf1e..d48590e 100644 --- a/test/option/taskmastertrace.py +++ b/test/option/taskmastertrace.py @@ -31,7 +31,7 @@ Simple tests of the --taskmastertrace= option. import TestSCons test = TestSCons.TestSCons() -test.verbose_set(3) +# test.verbose_set(3) test.write('SConstruct', """ DefaultEnvironment(tools=[]) @@ -129,12 +129,8 @@ Taskmaster: No candidate anymore. test.run(arguments='--taskmastertrace=- .', stdout=expect_stdout) - - test.run(arguments='-c .') - - expect_stdout = test.wrap_stdout("""\ Copy("Tfile.mid", "Tfile.in") Copy("Tfile.out", "Tfile.mid") -- cgit v0.12 From c6b363a158da93a75d6a12620b5b221025e23312 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 27 Dec 2019 11:33:27 -0800 Subject: [skip travis] Add Py38 vs2019 --- .appveyor.yml | 72 +++++++++-------------------------------------------------- 1 file changed, 11 insertions(+), 61 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index e22ed9b..2440ec0 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -54,84 +54,31 @@ environment: PYVER: 27 BUILD_JOB_NUM: 1 COVERAGE: 0 - # - WINPYTHON: "Python27" - # PYTHON: "2.7" - # PYVER: 27 - # BUILD_JOB_NUM: 2 - # COVERAGE: 0 - # - WINPYTHON: "Python27" - # PYTHON: "2.7" - # PYVER: 27 - # BUILD_JOB_NUM: 3 - # COVERAGE: 0 - # - WINPYTHON: "Python27" - # PYTHON: "2.7" - # PYVER: 27 - # BUILD_JOB_NUM: 4 - # COVERAGE: 0 - WINPYTHON: "Python35" PYTHON: "3.5" PYVER: 35 BUILD_JOB_NUM: 1 COVERAGE: 0 - # - WINPYTHON: "Python35" - # PYTHON: "3.5" - # PYVER: 35 - # BUILD_JOB_NUM: 2 - # COVERAGE: 0 - # - WINPYTHON: "Python35" - # PYTHON: "3.5" - # PYVER: 35 - # BUILD_JOB_NUM: 3 - # COVERAGE: 0 - # - WINPYTHON: "Python35" - # PYTHON: "3.5" - # PYVER: 35 - # BUILD_JOB_NUM: 4 - # COVERAGE: 0 - WINPYTHON: "Python36" PYTHON: "3.6" PYVER: 36 BUILD_JOB_NUM: 1 COVERAGE: 1 - # - WINPYTHON: "Python36" - # PYTHON: "3.6" - # PYVER: 36 - # BUILD_JOB_NUM: 2 - # COVERAGE: 1 - # - WINPYTHON: "Python36" - # PYTHON: "3.6" - # PYVER: 36 - # BUILD_JOB_NUM: 3 - # COVERAGE: 1 - # - WINPYTHON: "Python36" - # PYTHON: "3.6" - # PYVER: 36 - # BUILD_JOB_NUM: 4 - # COVERAGE: 1 - WINPYTHON: "Python37" PYTHON: "3.7" PYVER: 37 BUILD_JOB_NUM: 1 COVERAGE: 0 - # - WINPYTHON: "Python37" - # PYTHON: "3.7" - # PYVER: 37 - # BUILD_JOB_NUM: 2 - # COVERAGE: 0 - # - WINPYTHON: "Python37" - # PYTHON: "3.7" - # PYVER: 37 - # BUILD_JOB_NUM: 3 - # COVERAGE: 0 - # - WINPYTHON: "Python37" - # PYTHON: "3.7" - # PYVER: 37 - # BUILD_JOB_NUM: 4 - # COVERAGE: 0 + + - WINPYTHON: "Python38" + PYTHON: "3.8" + PYVER: 38 + BUILD_JOB_NUM: 1 + COVERAGE: 0 + # remove sets of build jobs based on critia below # to fine tune the number and platforms tested @@ -144,13 +91,16 @@ matrix: WINPYTHON: "Python36" - image: Visual Studio 2015 WINPYTHON: "Python37" - + - image: Visual Studio 2015 + WINPYTHON: "Python38" # test python 2.7, 3.8 on Visual Studio 2017 image - image: Visual Studio 2017 WINPYTHON: "Python35" - image: Visual Studio 2017 WINPYTHON: "Python37" + - image: Visual Studio 2017 + WINPYTHON: "Python38" # test python 3.7 on Visual Studio 2019 image - image: Visual Studio 2019 -- cgit v0.12 From 71e703b352068d39b66415c64a422034bb823aa9 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 27 Dec 2019 11:39:44 -0800 Subject: [skip appveyor] bump to bionic for py37 tests. --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8a55575..4ce42e0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -93,12 +93,12 @@ jobs: dist: xenial # required for Python >= 3.7 - <<: *test_job - python: 3.8-dev + python: 3.8 env: - PYVER=38 - PYTHON=3.8 sudo: required - dist: xenial # required for Python >= 3.7 + dist: bionic # required for Python >= 3.8 - &coverage_jobs -- cgit v0.12 From f14b48f27828a154b351edc70fb12f38f50626fb Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 27 Dec 2019 12:04:35 -0800 Subject: Try running a single job for coverage instead of 4. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4ce42e0..b974fe4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -130,7 +130,7 @@ jobs: - echo "coverage.process_startup()" | sudo tee --append ${PYSITEDIR}/usercustomize.py script: - - export TOTAL_BUILD_JOBS=4 + - export TOTAL_BUILD_JOBS=1 # write the coverage config file - export COVERAGE_PROCESS_START=$PWD/.coveragerc - echo "[run]" >> .coveragerc -- cgit v0.12 From 6eb63f830238784e6065ddb5473ef79b688d530b Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 27 Dec 2019 12:09:31 -0800 Subject: reduce coverage jobs --- .travis.yml | 68 ++++++++++++++++++++++++++++++------------------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/.travis.yml b/.travis.yml index b974fe4..581662d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -164,22 +164,22 @@ jobs: - PYVER=27 - PYTHON=2.7 - BUILD_JOB_NUM=1 - - - <<: *coverage_jobs - env: - - PYVER=27 - - PYTHON=2.7 - - BUILD_JOB_NUM=2 - - <<: *coverage_jobs - env: - - PYVER=27 - - PYTHON=2.7 - - BUILD_JOB_NUM=3 - - <<: *coverage_jobs - env: - - PYVER=27 - - PYTHON=2.7 - - BUILD_JOB_NUM=4 +# +# - <<: *coverage_jobs +# env: +# - PYVER=27 +# - PYTHON=2.7 +# - BUILD_JOB_NUM=2 +# - <<: *coverage_jobs +# env: +# - PYVER=27 +# - PYTHON=2.7 +# - BUILD_JOB_NUM=3 +# - <<: *coverage_jobs +# env: +# - PYVER=27 +# - PYTHON=2.7 +# - BUILD_JOB_NUM=4 - <<: *coverage_jobs python: 3.6 @@ -187,22 +187,22 @@ jobs: - PYVER=36 - PYTHON=3.6 - BUILD_JOB_NUM=1 - - <<: *coverage_jobs - python: 3.6 - env: - - PYVER=36 - - PYTHON=3.6 - - BUILD_JOB_NUM=2 - - <<: *coverage_jobs - python: 3.6 - env: - - PYVER=36 - - PYTHON=3.6 - - BUILD_JOB_NUM=3 - - <<: *coverage_jobs - python: 3.6 - env: - - PYVER=36 - - PYTHON=3.6 - - BUILD_JOB_NUM=4 +# - <<: *coverage_jobs +# python: 3.6 +# env: +# - PYVER=36 +# - PYTHON=3.6 +# - BUILD_JOB_NUM=2 +# - <<: *coverage_jobs +# python: 3.6 +# env: +# - PYVER=36 +# - PYTHON=3.6 +# - BUILD_JOB_NUM=3 +# - <<: *coverage_jobs +# python: 3.6 +# env: +# - PYVER=36 +# - PYTHON=3.6 +# - BUILD_JOB_NUM=4 -- cgit v0.12 From 9a32fc08310f914cb449ff3ddc27c9e30ba5ac02 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 27 Dec 2019 17:27:30 -0800 Subject: remove RDP --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index 2440ec0..52eab43 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -204,5 +204,5 @@ on_finish: #- cmd: "C:\\%WINPYTHON%\\python.exe -m pip install --user -U coveralls" #- sh: python$PYTHON -m pip install --user -U coveralls #- ps: coveralls --rcfile="$($env:COVERAGE_PROCESS_START)" - - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) + # - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) -- cgit v0.12 From f70ce3eb6015b6fd6204920e1bdcba607603da33 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 27 Dec 2019 21:18:03 -0800 Subject: set tools=[] for test/SConsignFile/use-dbm.py --- test/SConsignFile/use-dbm.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/SConsignFile/use-dbm.py b/test/SConsignFile/use-dbm.py index fcf4420..e02346a 100644 --- a/test/SConsignFile/use-dbm.py +++ b/test/SConsignFile/use-dbm.py @@ -60,7 +60,8 @@ import sys import %(use_db)s SConsignFile('.sconsign', %(use_db)s) B = Builder(action = r'%(_python_)s build.py $TARGETS $SOURCES') -env = Environment(BUILDERS = { 'B' : B }) +DefaultEnvironment(tools=[]) +env = Environment(BUILDERS = { 'B' : B }, tools=[]) env.B(target = 'f1.out', source = 'f1.in') env.B(target = 'f2.out', source = 'f2.in') env.B(target = 'subdir/f3.out', source = 'subdir/f3.in') @@ -89,6 +90,7 @@ test.must_match(['subdir', 'f4.out'], "subdir/f4.in\n") test.up_to_date(arguments = '.') + test.must_not_exist(test.workpath('.sconsign')) test.must_not_exist(test.workpath('.sconsign.dblite')) test.must_not_exist(test.workpath('subdir', '.sconsign')) -- cgit v0.12 From 33f3efad1aeb9d0f7046fc84d70e8f8a3ffa115c Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 27 Dec 2019 21:18:49 -0800 Subject: [skip appveyor] - reduce coverage to just py37 --- .travis.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 581662d..0a576bf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -103,7 +103,7 @@ jobs: - &coverage_jobs stage: Coverage - python: 2.7 + python: 3.7 before_script: # install our own python so we can modify usercustomize.py - deactivate @@ -161,8 +161,8 @@ jobs: #- coveralls --rcfile=$PWD/.coveragerc env: - - PYVER=27 - - PYTHON=2.7 + - PYVER=37 + - PYTHON=3.7 - BUILD_JOB_NUM=1 # # - <<: *coverage_jobs @@ -181,12 +181,12 @@ jobs: # - PYTHON=2.7 # - BUILD_JOB_NUM=4 - - <<: *coverage_jobs - python: 3.6 - env: - - PYVER=36 - - PYTHON=3.6 - - BUILD_JOB_NUM=1 +# - <<: *coverage_jobs +# python: 3.6 +# env: +# - PYVER=36 +# - PYTHON=3.6 +# - BUILD_JOB_NUM=1 # - <<: *coverage_jobs # python: 3.6 # env: -- cgit v0.12 From c7afaf08bdd06b834ccdbdb4e0498d76d451a4b5 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 28 Dec 2019 14:58:32 -0800 Subject: [skip travis] Split builds in 2. py35 is timing out. --- .appveyor.yml | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index 52eab43..8ab64dc 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -79,6 +79,36 @@ environment: BUILD_JOB_NUM: 1 COVERAGE: 0 + - WINPYTHON: "Python27" + PYTHON: "2.7" + PYVER: 27 + BUILD_JOB_NUM: 2 + COVERAGE: 0 + + - WINPYTHON: "Python35" + PYTHON: "3.5" + PYVER: 35 + BUILD_JOB_NUM: 2 + COVERAGE: 0 + + - WINPYTHON: "Python36" + PYTHON: "3.6" + PYVER: 36 + BUILD_JOB_NUM: 2 + COVERAGE: 1 + + - WINPYTHON: "Python37" + PYTHON: "3.7" + PYVER: 37 + BUILD_JOB_NUM: 2 + COVERAGE: 0 + + - WINPYTHON: "Python38" + PYTHON: "3.8" + PYVER: 38 + BUILD_JOB_NUM: 2 + COVERAGE: 0 + # remove sets of build jobs based on critia below # to fine tune the number and platforms tested @@ -165,7 +195,7 @@ build_script: # setup portion of tests for this build job (1-4) - ps: | - $TOTAL_BUILD_JOBS = 1; + $TOTAL_BUILD_JOBS = 2; $Lines = (Get-Content all_tests.txt | Measure-Object -line).Lines; $start = ($Lines / $TOTAL_BUILD_JOBS) * ($Env:BUILD_JOB_NUM - 1); $end = ($Lines / $TOTAL_BUILD_JOBS) * $Env:BUILD_JOB_NUM; -- cgit v0.12 From b61f24e775b688f06e37f05158a873b1d6a65d10 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 28 Dec 2019 16:43:45 -0800 Subject: [skip travis] back to 1 run per build type. --- .appveyor.yml | 60 +++++++++++++++++++++++++++++------------------------------ 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 8ab64dc..070587f 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -79,35 +79,35 @@ environment: BUILD_JOB_NUM: 1 COVERAGE: 0 - - WINPYTHON: "Python27" - PYTHON: "2.7" - PYVER: 27 - BUILD_JOB_NUM: 2 - COVERAGE: 0 - - - WINPYTHON: "Python35" - PYTHON: "3.5" - PYVER: 35 - BUILD_JOB_NUM: 2 - COVERAGE: 0 - - - WINPYTHON: "Python36" - PYTHON: "3.6" - PYVER: 36 - BUILD_JOB_NUM: 2 - COVERAGE: 1 - - - WINPYTHON: "Python37" - PYTHON: "3.7" - PYVER: 37 - BUILD_JOB_NUM: 2 - COVERAGE: 0 - - - WINPYTHON: "Python38" - PYTHON: "3.8" - PYVER: 38 - BUILD_JOB_NUM: 2 - COVERAGE: 0 + # - WINPYTHON: "Python27" + # PYTHON: "2.7" + # PYVER: 27 + # BUILD_JOB_NUM: 2 + # COVERAGE: 0 + + # - WINPYTHON: "Python35" + # PYTHON: "3.5" + # PYVER: 35 + # BUILD_JOB_NUM: 2 + # COVERAGE: 0 + + # - WINPYTHON: "Python36" + # PYTHON: "3.6" + # PYVER: 36 + # BUILD_JOB_NUM: 2 + # COVERAGE: 1 + + # - WINPYTHON: "Python37" + # PYTHON: "3.7" + # PYVER: 37 + # BUILD_JOB_NUM: 2 + # COVERAGE: 0 + + # - WINPYTHON: "Python38" + # PYTHON: "3.8" + # PYVER: 38 + # BUILD_JOB_NUM: 2 + # COVERAGE: 0 # remove sets of build jobs based on critia below @@ -195,7 +195,7 @@ build_script: # setup portion of tests for this build job (1-4) - ps: | - $TOTAL_BUILD_JOBS = 2; + $TOTAL_BUILD_JOBS = 1; $Lines = (Get-Content all_tests.txt | Measure-Object -line).Lines; $start = ($Lines / $TOTAL_BUILD_JOBS) * ($Env:BUILD_JOB_NUM - 1); $end = ($Lines / $TOTAL_BUILD_JOBS) * $Env:BUILD_JOB_NUM; -- cgit v0.12 From 1f143a5d3520c09b8b55ce5f510d4924c4ea6da1 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sat, 28 Dec 2019 11:42:21 -0700 Subject: Clarify behavior of -C option plus speedups Manpage now indicates that the additive behavior of multiple -C options applies only to non-absolute paths. A test for a -C absolute-path is added. Along the way this and several other option flag testcases were sped up through the tools=[] trick. On the Windows box under test, these changes took 150 seconds off a (non-parallel) test run. Signed-off-by: Mats Wichmann --- doc/man/scons.xml | 38 +++++++++++--------------- doc/user/MANIFEST | 1 - test/option--C.py | 68 ++++++++++++++++++++++++++++++----------------- test/option--W.py | 4 ++- test/option--duplicate.py | 1 + test/option-f.py | 4 +++ test/option-j.py | 28 ++++++++++--------- test/option-k.py | 58 ++++++++++++++++++++-------------------- test/option-n.py | 28 ++++++++++--------- test/option-s.py | 18 +++++++------ 10 files changed, 137 insertions(+), 111 deletions(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index 899669e..19affcf 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -638,11 +638,12 @@ yet have any results in the cache. - -C directory, --directory=directory + -C directory, --directory=directory -Change to the specified -directory -before searching for the +Run as if &scons; was started in +directory +instead of the current working directory. +That is, change directory before searching for the SConstruct, Sconstruct, sconstruct, @@ -651,23 +652,18 @@ before searching for the or sconstruct.py file, or doing anything -else. Multiple - -options are interpreted -relative to the previous one, and the right-most +else. When multiple -option wins. (This option is nearly -equivalent to -, -except that it will search for -SConstruct, -Sconstruct, -sconstruct, -SConstruct.py -Sconstruct.py -or -sconstruct.py -in the specified directory.) +options are given, each subsequent non-absolute + directory +is interpreted relative to the preceding one. +This option is similar to +, +but does not search for any of the +predefined SConstruct names +in the specified directory. + + @@ -675,8 +671,6 @@ in the specified directory.) - - -D diff --git a/doc/user/MANIFEST b/doc/user/MANIFEST index 62da288..3110c2a 100644 --- a/doc/user/MANIFEST +++ b/doc/user/MANIFEST @@ -43,7 +43,6 @@ scanners.xml sconf.xml separate.xml simple.xml -sourcecode.xml tasks.xml tools.xml troubleshoot.xml diff --git a/test/option--C.py b/test/option--C.py index 3802bce..b5b5f98 100644 --- a/test/option--C.py +++ b/test/option--C.py @@ -22,6 +22,11 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # +""" +Test that the -C option changes directory as expected - additively, +except if a full path is given +""" + __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import os @@ -50,44 +55,59 @@ wpath_sub_foo_bar = test.workpath('sub', 'foo', 'bar') test.subdir('sub', ['sub', 'dir']) test.write('SConstruct', """ +DefaultEnvironment(tools=[]) import os print("SConstruct "+os.getcwd()) """) test.write(['sub', 'SConstruct'], """ +DefaultEnvironment(tools=[]) import os print(GetBuildPath('..')) """) test.write(['sub', 'dir', 'SConstruct'], """ +DefaultEnvironment(tools=[]) import os -env = Environment(FOO='foo', BAR='bar') +env = Environment(FOO='foo', BAR='bar', tools=[]) print(env.GetBuildPath('../$FOO/$BAR')) """) -test.run(arguments = '-C sub .', - stdout = "scons: Entering directory `%s'\n" % wpath_sub \ - + test.wrap_stdout(read_str = '%s\n' % wpath, - build_str = "scons: `.' is up to date.\n")) - -test.run(arguments = '-C sub -C dir .', - stdout = "scons: Entering directory `%s'\n" % wpath_sub_dir \ - + test.wrap_stdout(read_str = '%s\n' % wpath_sub_foo_bar, - build_str = "scons: `.' is up to date.\n")) - -test.run(arguments = ".", - stdout = test.wrap_stdout(read_str = 'SConstruct %s\n' % wpath, - build_str = "scons: `.' is up to date.\n")) - -test.run(arguments = '--directory=sub/dir .', - stdout = "scons: Entering directory `%s'\n" % wpath_sub_dir \ - + test.wrap_stdout(read_str = '%s\n' % wpath_sub_foo_bar, - build_str = "scons: `.' is up to date.\n")) - -test.run(arguments = '-C %s -C %s .' % (wpath_sub_dir, wpath_sub), - stdout = "scons: Entering directory `%s'\n" % wpath_sub \ - + test.wrap_stdout(read_str = '%s\n' % wpath, - build_str = "scons: `.' is up to date.\n")) +test.run(arguments='-C sub .', + stdout="scons: Entering directory `%s'\n" % wpath_sub \ + + test.wrap_stdout(read_str='%s\n' % wpath, + build_str="scons: `.' is up to date.\n")) + +test.run(arguments='-C sub -C dir .', + stdout="scons: Entering directory `%s'\n" % wpath_sub_dir \ + + test.wrap_stdout(read_str='%s\n' % wpath_sub_foo_bar, + build_str="scons: `.' is up to date.\n")) + +test.run(arguments=".", + stdout=test.wrap_stdout(read_str='SConstruct %s\n' % wpath, + build_str="scons: `.' is up to date.\n")) + +test.run(arguments='--directory=sub/dir .', + stdout="scons: Entering directory `%s'\n" % wpath_sub_dir \ + + test.wrap_stdout(read_str='%s\n' % wpath_sub_foo_bar, + build_str="scons: `.' is up to date.\n")) + +test.run(arguments='-C %s -C %s .' % (wpath_sub_dir, wpath_sub), + stdout="scons: Entering directory `%s'\n" % wpath_sub \ + + test.wrap_stdout(read_str='%s\n' % wpath, + build_str="scons: `.' is up to date.\n")) + +import tempfile +with tempfile.TemporaryDirectory() as full: + test.write([full, 'SConstruct'], """ +DefaultEnvironment(tools=[]) +import os +print("SConstruct " + os.getcwd()) +""") + test.run(arguments='-C sub -C {} .'.format(full), + stdout="scons: Entering directory `{}'\n".format(full) \ + + test.wrap_stdout(read_str='SConstruct {}\n'.format(full), + build_str="scons: `.' is up to date.\n")) test.pass_test() diff --git a/test/option--W.py b/test/option--W.py index e29cd7c..3f68fbc 100644 --- a/test/option--W.py +++ b/test/option--W.py @@ -28,7 +28,9 @@ import TestSCons test = TestSCons.TestSCons() -test.write('SConstruct', "") +test.write('SConstruct', """\ +DefaultEnvironment(tools=[]) +""") test.option_not_yet_implemented('-W', 'foo .') diff --git a/test/option--duplicate.py b/test/option--duplicate.py index 2d21d74..91dc61c 100644 --- a/test/option--duplicate.py +++ b/test/option--duplicate.py @@ -39,6 +39,7 @@ python = TestSCons.python test = TestSCons.TestSCons() test.write('SConstruct', """ +DefaultEnvironment(tools=[]) try: duplicate = ARGUMENTS['duplicate'] SetOption('duplicate', duplicate) diff --git a/test/option-f.py b/test/option-f.py index 46e2686..94e7e46 100644 --- a/test/option-f.py +++ b/test/option-f.py @@ -35,16 +35,19 @@ test.subdir('subdir') subdir_BuildThis = os.path.join('subdir', 'Buildthis') test.write('SConscript', """ +DefaultEnvironment(tools=[]) import os print("SConscript " + os.getcwd()) """) test.write(subdir_BuildThis, """ +DefaultEnvironment(tools=[]) import os print("subdir/BuildThis "+ os.getcwd()) """) test.write('Build2', """ +DefaultEnvironment(tools=[]) import os print("Build2 "+ os.getcwd()) """) @@ -84,6 +87,7 @@ test.run(arguments = '--sconstruct=%s .' % subdir_BuildThis, build_str = "scons: `.' is up to date.\n")) test.run(arguments = '-f - .', stdin = """ +DefaultEnvironment(tools=[]) import os print("STDIN " + os.getcwd()) """, diff --git a/test/option-j.py b/test/option-j.py index 278fd30..0b0078f 100644 --- a/test/option-j.py +++ b/test/option-j.py @@ -51,11 +51,10 @@ test = TestSCons.TestSCons() test.write('build.py', r""" import time import sys -file = open(sys.argv[1], 'w') -file.write(str(time.time()) + '\n') -time.sleep(1) -file.write(str(time.time())) -file.close() +with open(sys.argv[1], 'w') as f: + f.write(str(time.time()) + '\n') + time.sleep(1) + f.write(str(time.time())) """) test.subdir('foo') @@ -65,11 +64,12 @@ foo you """) test.write('SConstruct', """ +DefaultEnvironment(tools=[]) MyBuild = Builder(action = r'%(_python_)s build.py $TARGETS') -env = Environment(BUILDERS = { 'MyBuild' : MyBuild }) +env = Environment(BUILDERS={'MyBuild': MyBuild}, tools=[]) env.Tool('install') -env.MyBuild(target = 'f1', source = 'f1.in') -env.MyBuild(target = 'f2', source = 'f2.in') +env.MyBuild(target='f1', source='f1.in') +env.MyBuild(target='f2', source='f2.in') def copyn(env, target, source): import shutil @@ -161,8 +161,9 @@ if sys.platform != 'win32' and sys.version_info[0] == 2: # Test SetJobs() with no -j: test.write('SConstruct', """ -MyBuild = Builder(action = r'%(_python_)s build.py $TARGETS') -env = Environment(BUILDERS = { 'MyBuild' : MyBuild }) +DefaultEnvironment(tools=[]) +MyBuild = Builder(action=r'%(_python_)s build.py $TARGETS') +env = Environment(BUILDERS={'MyBuild': MyBuild}, tools=[]) env.Tool('install') env.MyBuild(target = 'f1', source = 'f1.in') env.MyBuild(target = 'f2', source = 'f2.in') @@ -190,11 +191,12 @@ test.fail_test(not (start2 < finish1)) # Test SetJobs() with -j: test.write('SConstruct', """ +DefaultEnvironment(tools=[]) MyBuild = Builder(action = r'%(_python_)s build.py $TARGETS') -env = Environment(BUILDERS = { 'MyBuild' : MyBuild }) +env = Environment(BUILDERS = {'MyBuild': MyBuild}, tools=[]) env.Tool('install') -env.MyBuild(target = 'f1', source = 'f1.in') -env.MyBuild(target = 'f2', source = 'f2.in') +env.MyBuild(target='f1', source='f1.in') +env.MyBuild(target='f2', source='f2.in') def copyn(env, target, source): import shutil diff --git a/test/option-k.py b/test/option-k.py index 7a01ed3..4f4c86b 100644 --- a/test/option-k.py +++ b/test/option-k.py @@ -56,30 +56,30 @@ sys.exit(1) test.write(['work1', 'SConstruct'], """\ DefaultEnvironment(tools=[]) -Succeed = Builder(action = r'%(_python_)s ../succeed.py $TARGETS') -Fail = Builder(action = r'%(_python_)s ../fail.py $TARGETS') -env = Environment(BUILDERS = { 'Succeed' : Succeed, 'Fail' : Fail }) -env.Fail(target = 'aaa.1', source = 'aaa.in') -env.Succeed(target = 'aaa.out', source = 'aaa.1') -env.Succeed(target = 'bbb.out', source = 'bbb.in') +Succeed = Builder(action=r'%(_python_)s ../succeed.py $TARGETS') +Fail = Builder(action=r'%(_python_)s ../fail.py $TARGETS') +env = Environment(BUILDERS={'Succeed': Succeed, 'Fail': Fail}, tools=[]) +env.Fail(target='aaa.1', source='aaa.in') +env.Succeed(target='aaa.out', source='aaa.1') +env.Succeed(target='bbb.out', source='bbb.in') """ % locals()) test.write(['work1', 'aaa.in'], "aaa.in\n") test.write(['work1', 'bbb.in'], "bbb.in\n") -test.run(chdir = 'work1', - arguments = 'aaa.out bbb.out', - stderr = 'scons: *** [aaa.1] Error 1\n', - status = 2) +test.run(chdir='work1', + arguments='aaa.out bbb.out', + stderr='scons: *** [aaa.1] Error 1\n', + status=2) test.must_not_exist(test.workpath('work1', 'aaa.1')) test.must_not_exist(test.workpath('work1', 'aaa.out')) test.must_not_exist(test.workpath('work1', 'bbb.out')) -test.run(chdir = 'work1', - arguments = '-k aaa.out bbb.out', - stderr = 'scons: *** [aaa.1] Error 1\n', - status = 2) +test.run(chdir='work1', + arguments='-k aaa.out bbb.out', + stderr='scons: *** [aaa.1] Error 1\n', + status=2) test.must_not_exist(test.workpath('work1', 'aaa.1')) test.must_not_exist(test.workpath('work1', 'aaa.out')) @@ -88,9 +88,9 @@ test.must_match(['work1', 'bbb.out'], "succeed.py: bbb.out\n", mode='r') test.unlink(['work1', 'bbb.out']) test.run(chdir = 'work1', - arguments = '--keep-going aaa.out bbb.out', - stderr = 'scons: *** [aaa.1] Error 1\n', - status = 2) + arguments='--keep-going aaa.out bbb.out', + stderr='scons: *** [aaa.1] Error 1\n', + status=2) test.must_not_exist(test.workpath('work1', 'aaa.1')) test.must_not_exist(test.workpath('work1', 'aaa.out')) @@ -104,9 +104,9 @@ Removed bbb.out scons: done cleaning targets. """ -test.run(chdir = 'work1', - arguments = '--clean --keep-going aaa.out bbb.out', - stdout = expect) +test.run(chdir='work1', + arguments='--clean --keep-going aaa.out bbb.out', + stdout=expect) test.must_not_exist(test.workpath('work1', 'aaa.1')) test.must_not_exist(test.workpath('work1', 'aaa.out')) @@ -120,9 +120,9 @@ test.must_not_exist(test.workpath('work1', 'bbb.out')) test.write(['work2', 'SConstruct'], """\ DefaultEnvironment(tools=[]) -Succeed = Builder(action = r'%(_python_)s ../succeed.py $TARGETS') -Fail = Builder(action = r'%(_python_)s ../fail.py $TARGETS') -env = Environment(BUILDERS = { 'Succeed' : Succeed, 'Fail' : Fail }) +Succeed = Builder(action=r'%(_python_)s ../succeed.py $TARGETS') +Fail = Builder(action=r'%(_python_)s ../fail.py $TARGETS') +env = Environment(BUILDERS={'Succeed': Succeed, 'Fail': Fail}, tools=[]) env.Fail('aaa.out', 'aaa.in') env.Succeed('bbb.out', 'aaa.out') env.Succeed('ccc.out', 'ccc.in') @@ -132,11 +132,11 @@ env.Succeed('ddd.out', 'ccc.in') test.write(['work2', 'aaa.in'], "aaa.in\n") test.write(['work2', 'ccc.in'], "ccc.in\n") -test.run(chdir = 'work2', - arguments = '-k .', - status = 2, - stderr = None, - stdout = """\ +test.run(chdir='work2', + arguments='-k .', + status=2, + stderr=None, + stdout="""\ scons: Reading SConscript files ... scons: done reading SConscript files. scons: Building targets ... @@ -178,7 +178,7 @@ test.write(['work3', 'SConstruct'], """\ DefaultEnvironment(tools=[]) Succeed = Builder(action = r'%(_python_)s ../succeed.py $TARGETS') Fail = Builder(action = r'%(_python_)s ../fail.py $TARGETS') -env = Environment(BUILDERS = { 'Succeed' : Succeed, 'Fail' : Fail }) +env = Environment(BUILDERS = {'Succeed': Succeed, 'Fail': Fail}, tools=[]) a = env.Fail('aaa.out', 'aaa.in') b = env.Succeed('bbb.out', 'bbb.in') c = env.Succeed('ccc.out', 'ccc.in') diff --git a/test/option-n.py b/test/option-n.py index f952428..2ec3fdc 100644 --- a/test/option-n.py +++ b/test/option-n.py @@ -57,11 +57,12 @@ with open(sys.argv[1], 'w') as ofp: """) test.write('SConstruct', """ -MyBuild = Builder(action = r'%(_python_)s build.py $TARGETS') -env = Environment(BUILDERS = { 'MyBuild' : MyBuild }) +DefaultEnvironment(tools=[]) +MyBuild = Builder(action=r'%(_python_)s build.py $TARGETS') +env = Environment(BUILDERS={'MyBuild': MyBuild}, tools=[]) env.Tool('install') -env.MyBuild(target = 'f1.out', source = 'f1.in') -env.MyBuild(target = 'f2.out', source = 'f2.in') +env.MyBuild(target='f1.out', source='f1.in') +env.MyBuild(target='f2.out', source='f2.in') env.Install('install', 'f3.in') VariantDir('build', 'src', duplicate=1) SConscript('build/SConscript', "env") @@ -69,7 +70,7 @@ SConscript('build/SConscript', "env") test.write(['src', 'SConscript'], """ Import("env") -env.MyBuild(target = 'f4.out', source = 'f4.in') +env.MyBuild(target='f4.out', source='f4.in') """) test.write('f1.in', "f1.in\n") @@ -83,7 +84,7 @@ expect = test.wrap_stdout("""\ %(_python_)s build.py f2.out """ % locals()) -test.run(arguments = args, stdout = expect) +test.run(arguments=args, stdout=expect) test.fail_test(not os.path.exists(test.workpath('f1.out'))) test.fail_test(not os.path.exists(test.workpath('f2.out'))) @@ -169,8 +170,9 @@ test.fail_test(os.path.exists(test.workpath('build', 'f4.in'))) test.subdir('configure') test.set_match_function(TestSCons.match_re_dotall) test.set_diff_function(TestSCons.diff_re) -test.write('configure/SConstruct', -"""def CustomTest(context): +test.write('configure/SConstruct', """\ +DefaultEnvironment(tools=[]) +def CustomTest(context): def userAction(target,source,env): import shutil shutil.copyfile( str(source[0]), str(target[0])) @@ -182,11 +184,11 @@ test.write('configure/SConstruct', context.Result(ok) return ok -env = Environment() -conf = Configure( env, - custom_tests={'CustomTest':CustomTest}, - conf_dir="config.test", - log_file="config.log" ) +env = Environment(tools=[]) +conf = Configure(env, + custom_tests={'CustomTest':CustomTest}, + conf_dir="config.test", + log_file="config.log") if not conf.CustomTest(): Exit(1) else: diff --git a/test/option-s.py b/test/option-s.py index df7cd50..89a0c62 100644 --- a/test/option-s.py +++ b/test/option-s.py @@ -40,47 +40,49 @@ file.close() """) test.write('SConstruct', """ +DefaultEnvironment(tools=[]) MyBuild = Builder(action = r'%(_python_)s build.py $TARGET') silent = ARGUMENTS.get('QUIET',0) if silent: SetOption('silent',True) -env = Environment(BUILDERS = { 'MyBuild' : MyBuild }) -env.MyBuild(target = 'f1.out', source = 'f1.in') -env.MyBuild(target = 'f2.out', source = 'f2.in') +env = Environment(BUILDERS={'MyBuild': MyBuild}, tools=[]) +env.MyBuild(target='f1.out', source='f1.in') +env.MyBuild(target='f2.out', source='f2.in') """ % locals()) test.write('f1.in', "f1.in\n") test.write('f2.in', "f2.in\n") -test.run(arguments = '-s f1.out f2.out', stdout = "") +test.run(arguments='-s f1.out f2.out', stdout="") test.fail_test(not os.path.exists(test.workpath('f1.out'))) test.fail_test(not os.path.exists(test.workpath('f2.out'))) test.unlink('f1.out') test.unlink('f2.out') -test.run(arguments = '--silent f1.out f2.out', stdout = "") +test.run(arguments='--silent f1.out f2.out', stdout="") test.fail_test(not os.path.exists(test.workpath('f1.out'))) test.fail_test(not os.path.exists(test.workpath('f2.out'))) test.unlink('f1.out') test.unlink('f2.out') -test.run(arguments = '--quiet f1.out f2.out', stdout = "") +test.run(arguments='--quiet f1.out f2.out', stdout="") test.fail_test(not os.path.exists(test.workpath('f1.out'))) test.fail_test(not os.path.exists(test.workpath('f2.out'))) # -C should also be quiet Issue#2796 test.subdir( 'sub' ) test.write(['sub','SConstruct'],"") -test.run(arguments = '-s -C sub', stdout = "" ) +test.run(arguments='-s -C sub', stdout="" ) test.unlink('f1.out') test.unlink('f2.out') -test.run(arguments = 'QUIET=1 f1.out f2.out', stdout = "scons: Reading SConscript files ...\nscons: done reading SConscript files.\n") +test.run(arguments='QUIET=1 f1.out f2.out', + stdout="scons: Reading SConscript files ...\nscons: done reading SConscript files.\n") test.fail_test(not os.path.exists(test.workpath('f1.out'))) test.fail_test(not os.path.exists(test.workpath('f2.out'))) -- cgit v0.12 From 0efc325b5f10052f785624979714c7eff06bbe4b Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sun, 29 Dec 2019 05:59:57 -0700 Subject: [PR #3511] extra -C test was not needed, drop Instead of fixing for PY2, just drop the test: turns out the existing 5th testcase covers it adequately. Leave a bit of a commen trail though. Signed-off-by: Mats Wichmann --- doc/man/scons.xml | 29 ++++++++++++++++++----------- test/option--C.py | 23 ++++++++--------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index 19affcf..bd8d5f0 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -644,24 +644,31 @@ yet have any results in the cache. directory instead of the current working directory. That is, change directory before searching for the -SConstruct, -Sconstruct, -sconstruct, -SConstruct.py -Sconstruct.py +&SConstruct;, +&Sconstruct;, +&sconstruct;, +&SConstruct.py;, +&Sconstruct.py; or -sconstruct.py -file, or doing anything -else. When multiple +&sconstruct.py; +file, or doing anything else. +When multiple options are given, each subsequent non-absolute directory is interpreted relative to the preceding one. -This option is similar to +This option is similar to using , but does not search for any of the -predefined SConstruct names -in the specified directory. +predefined &SConstruct; names +in the specified directory. +See also options +, + +and + +to change the &SConstruct; search behavior when this option is used. + diff --git a/test/option--C.py b/test/option--C.py index b5b5f98..2d86fac 100644 --- a/test/option--C.py +++ b/test/option--C.py @@ -23,8 +23,8 @@ # """ -Test that the -C option changes directory as expected - additively, -except if a full path is given +Test that the -C option changes directory as expected and that +multiple -C options are additive, except if a full path is given """ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" @@ -57,7 +57,7 @@ test.subdir('sub', ['sub', 'dir']) test.write('SConstruct', """ DefaultEnvironment(tools=[]) import os -print("SConstruct "+os.getcwd()) +print("SConstruct " + os.getcwd()) """) test.write(['sub', 'SConstruct'], """ @@ -73,11 +73,13 @@ env = Environment(FOO='foo', BAR='bar', tools=[]) print(env.GetBuildPath('../$FOO/$BAR')) """) +# single -C test.run(arguments='-C sub .', stdout="scons: Entering directory `%s'\n" % wpath_sub \ + test.wrap_stdout(read_str='%s\n' % wpath, build_str="scons: `.' is up to date.\n")) +# multiple -C test.run(arguments='-C sub -C dir .', stdout="scons: Entering directory `%s'\n" % wpath_sub_dir \ + test.wrap_stdout(read_str='%s\n' % wpath_sub_foo_bar, @@ -85,29 +87,20 @@ test.run(arguments='-C sub -C dir .', test.run(arguments=".", stdout=test.wrap_stdout(read_str='SConstruct %s\n' % wpath, - build_str="scons: `.' is up to date.\n")) + build_str="scons: `.' is up to date.\n")) +# alternate form test.run(arguments='--directory=sub/dir .', stdout="scons: Entering directory `%s'\n" % wpath_sub_dir \ + test.wrap_stdout(read_str='%s\n' % wpath_sub_foo_bar, build_str="scons: `.' is up to date.\n")) +# checks that using full paths is not additive test.run(arguments='-C %s -C %s .' % (wpath_sub_dir, wpath_sub), stdout="scons: Entering directory `%s'\n" % wpath_sub \ + test.wrap_stdout(read_str='%s\n' % wpath, build_str="scons: `.' is up to date.\n")) -import tempfile -with tempfile.TemporaryDirectory() as full: - test.write([full, 'SConstruct'], """ -DefaultEnvironment(tools=[]) -import os -print("SConstruct " + os.getcwd()) -""") - test.run(arguments='-C sub -C {} .'.format(full), - stdout="scons: Entering directory `{}'\n".format(full) \ - + test.wrap_stdout(read_str='SConstruct {}\n'.format(full), - build_str="scons: `.' is up to date.\n")) test.pass_test() -- cgit v0.12 From fed1de490fcaa06ffec6f6a96fbdc7be3981d4f6 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 29 Dec 2019 12:40:10 -0800 Subject: Change coverage worker to use Ubuntu Bionic instead of trusty for py37 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 0a576bf..cc1eaae 100644 --- a/.travis.yml +++ b/.travis.yml @@ -103,6 +103,7 @@ jobs: - &coverage_jobs stage: Coverage + dist: bionic python: 3.7 before_script: # install our own python so we can modify usercustomize.py -- cgit v0.12 From 2d2e281765f411b659f19d1ef2ce825a0d07b767 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 29 Dec 2019 12:43:43 -0800 Subject: Remove adding deadsnakes ppa. We're using newer python --- .travis.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index cc1eaae..7b57af9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -108,11 +108,11 @@ jobs: before_script: # install our own python so we can modify usercustomize.py - deactivate - - sudo add-apt-repository -y ppa:deadsnakes/ppa - - sudo apt-get update || true - - sudo apt-get -y install python$PYTHON - - wget https://bootstrap.pypa.io/get-pip.py - - sudo -H python$PYTHON get-pip.py +# - sudo add-apt-repository -y ppa:deadsnakes/ppa +# - sudo apt-get update || true +# - sudo apt-get -y install python$PYTHON +# - wget https://bootstrap.pypa.io/get-pip.py +# - sudo -H python$PYTHON get-pip.py - which python$PYTHON - python$PYTHON --version - python$PYTHON -m pip install --user -U coverage codecov -- cgit v0.12 From 45699b6c069b2cb15eff3c3dec0cb325680ab3c9 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 29 Dec 2019 12:51:52 -0800 Subject: debugging coverage failures --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7b57af9..3758925 100644 --- a/.travis.yml +++ b/.travis.yml @@ -119,8 +119,8 @@ jobs: # set this ensure user sites are available - export PYTHONNOUSERSITE= # attempt to get a location where we can store the usercustomize.py file - - python$PYTHON -m site - - export PYSITEDIR=$(python$PYTHON -m site --user-site) + - python -m site + - export PYSITEDIR=$(python -m site --user-site) - sudo mkdir -p $PYSITEDIR - sudo touch ${PYSITEDIR}/usercustomize.py - export COVERAGE_FILE=$PWD/.coverage @@ -143,7 +143,7 @@ jobs: - echo "[report]" >> .coveragerc - printf "omit =\n\t*Tests.py\n\tsrc/test_*\n\tsrc/setup.py\n\n" >> .coveragerc # get a list of all the tests to split them up - - python$PYTHON runtest.py -l -a > all_tests + - python runtest.py -l -a > all_tests - let "start = ($(wc -l < all_tests) / ${TOTAL_BUILD_JOBS}) * (${BUILD_JOB_NUM} - 1)"; true; - let "end = ($(wc -l < all_tests) / ${TOTAL_BUILD_JOBS}) * ${BUILD_JOB_NUM}" - if (( ${BUILD_JOB_NUM} == ${TOTAL_BUILD_JOBS} )); then end=$(wc -l < all_tests); fi -- cgit v0.12 From 381b61c7cca76603d1bfea85881a2aaee97e0652 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 29 Dec 2019 12:54:36 -0800 Subject: debugging coverage failures --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3758925..4431eb1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -113,9 +113,9 @@ jobs: # - sudo apt-get -y install python$PYTHON # - wget https://bootstrap.pypa.io/get-pip.py # - sudo -H python$PYTHON get-pip.py - - which python$PYTHON - - python$PYTHON --version - - python$PYTHON -m pip install --user -U coverage codecov + - which python + - python --version + - python -m pip install --user -U coverage codecov # set this ensure user sites are available - export PYTHONNOUSERSITE= # attempt to get a location where we can store the usercustomize.py file -- cgit v0.12 From a085ae3a6f6904893a534eb72923abadf4d043ee Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Sun, 29 Dec 2019 17:17:05 -0500 Subject: Clean up the code and use try/except more to optimize things --- src/engine/SCons/Node/Python.py | 28 ++++++++++++++-------------- src/engine/SCons/Node/PythonTests.py | 12 ++++++------ 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/engine/SCons/Node/Python.py b/src/engine/SCons/Node/Python.py index 1fb2866..a5bcd4b 100644 --- a/src/engine/SCons/Node/Python.py +++ b/src/engine/SCons/Node/Python.py @@ -31,7 +31,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import SCons.Node -_memoLookupMap = {} +_memo_lookup_map = {} class ValueNodeInfo(SCons.Node.NodeInfoBase): @@ -178,24 +178,24 @@ class Value(SCons.Node.Node): def ValueWithMemo(value, built_value=None): - global _memoLookupMap + global _memo_lookup_map # No current support for memoizing a value that needs to be built. if built_value: return Value(value, built_value) - # No current support for memoizing non-primitive types in case they change - # after this call. - if not isinstance(value, (int, str, float, bool)): - return Value(value, built_value) - - value_str = str(value) - if value_str in _memoLookupMap: - return _memoLookupMap[value_str] - - v = Value(value) - _memoLookupMap[value_str] = v - return v + try: + memo_lookup_key = hash(value) + except TypeError: + # Non-primitive types will hit this codepath. + return Value(value) + + try: + return _memo_lookup_map[memo_lookup_key] + except KeyError: + v = Value(value) + _memo_lookup_map[memo_lookup_key] = v + return v # Local Variables: diff --git a/src/engine/SCons/Node/PythonTests.py b/src/engine/SCons/Node/PythonTests.py index 6af3e60..b69f47d 100644 --- a/src/engine/SCons/Node/PythonTests.py +++ b/src/engine/SCons/Node/PythonTests.py @@ -128,20 +128,20 @@ class ValueMemoTestCase(unittest.TestCase): def test_built_value(self): """Confirm that built values are not memoized.""" - v1 = SCons.Node.Python.Value('c', 'ca') - v2 = SCons.Node.Python.Value('c', 'ca') + v1 = SCons.Node.Python.ValueWithMemo('c', 'ca') + v2 = SCons.Node.Python.ValueWithMemo('c', 'ca') assert v1 is not v2 def test_non_primitive_values(self): """Confirm that non-primitive values are not memoized.""" d = {'a': 1} - v1 = SCons.Node.Python.Value(d) - v2 = SCons.Node.Python.Value(d) + v1 = SCons.Node.Python.ValueWithMemo(d) + v2 = SCons.Node.Python.ValueWithMemo(d) assert v1 is not v2 l = [1] - v3 = SCons.Node.Python.Value(l) - v4 = SCons.Node.Python.Value(l) + v3 = SCons.Node.Python.ValueWithMemo(l) + v4 = SCons.Node.Python.ValueWithMemo(l) assert v3 is not v4 if __name__ == "__main__": -- cgit v0.12 From 909d76d92ecc7b1eb4b341c06f0be8193341d2fa Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Sun, 29 Dec 2019 17:24:28 -0500 Subject: Fix ambiguous variable name sider issue --- src/engine/SCons/Node/PythonTests.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/engine/SCons/Node/PythonTests.py b/src/engine/SCons/Node/PythonTests.py index b69f47d..dbb4ec8 100644 --- a/src/engine/SCons/Node/PythonTests.py +++ b/src/engine/SCons/Node/PythonTests.py @@ -139,9 +139,9 @@ class ValueMemoTestCase(unittest.TestCase): v2 = SCons.Node.Python.ValueWithMemo(d) assert v1 is not v2 - l = [1] - v3 = SCons.Node.Python.ValueWithMemo(l) - v4 = SCons.Node.Python.ValueWithMemo(l) + a = [1] + v3 = SCons.Node.Python.ValueWithMemo(a) + v4 = SCons.Node.Python.ValueWithMemo(a) assert v3 is not v4 if __name__ == "__main__": -- cgit v0.12 From 7a24dab5d4fffccd5e596962ff119c3353279b7a Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 29 Dec 2019 16:46:17 -0800 Subject: Fix py35 hang due to bad VS2010 install on VS2015 appveyor image. --- .appveyor.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 070587f..0287df9 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -186,12 +186,14 @@ build_script: $coveragercFile|Set-Content "$($env:COVERAGE_PROCESS_START)"; } - # Create exclude_list.txt (was used to exclude some failing tests due to appveyor issues) + # exclude VS 10.0 because it hangs the testing until this is resolved: + # https://help.appveyor.com/discussions/problems/19283-visual-studio-2010-trial-license-has-expired - ps: | New-Item -Name exclude_list.txt -ItemType File - # Remove-Item -Path 'all_tests.txt' - # New-Item -Name all_tests.txt -ItemType File - # Add-Content -Path 'all_tests.txt' -Value 'test\option\taskmastertrace.py' + $workaround_image = "Visual Studio 2015" + if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq $workaround_image) { + Add-Content -Path 'exclude_list.txt' -Value 'test\MSVS\vs-10.0-exec.py' + } # setup portion of tests for this build job (1-4) - ps: | -- cgit v0.12 From 9368c9247952ff8a8b40da6cd15cd662cfcfdf0d Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sun, 29 Dec 2019 08:28:53 -0700 Subject: Get rid of remaining mktemp calls Except for Platform/win32.py, the engine code no longer called insecure/deprecated tempfile.mktemp. That location is now also changed to use better methods. A couple of vestiges of old ways (like in comments) cleaned out. A couple of unit tests also converted - these don't have any impact on the scons engine, of course. Signed-off-by: Mats Wichmann --- runtest.py | 1 - src/CHANGES.txt | 1 + src/engine/SCons/Platform/__init__.py | 7 +-- src/engine/SCons/Platform/win32.py | 107 ++++++++++++++++++---------------- src/engine/SCons/UtilTests.py | 11 ++-- src/engine/SCons/cppTests.py | 20 ++----- testing/framework/TestCmdTests.py | 3 +- 7 files changed, 72 insertions(+), 78 deletions(-) diff --git a/runtest.py b/runtest.py index 464b593..554b4f6 100755 --- a/runtest.py +++ b/runtest.py @@ -556,7 +556,6 @@ if external: os.environ['SCONS_RUNTEST_DIR'] = scons_runtest_dir os.environ['SCONS_SCRIPT_DIR'] = scons_script_dir os.environ['SCONS_CWD'] = cwd - os.environ['SCONS_VERSION'] = version old_pythonpath = os.environ.get('PYTHONPATH') diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 5d0e3a2..f97b87e 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -24,6 +24,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Remove deprecated SourceCode - str.format syntax errors fixed - a bunch of linter/checker syntax fixups + - Convert remaining uses of insecure/deprecated mktemp method. RELEASE 3.1.2 - Mon, 17 Dec 2019 02:06:27 +0000 diff --git a/src/engine/SCons/Platform/__init__.py b/src/engine/SCons/Platform/__init__.py index 7d959b7..058241d 100644 --- a/src/engine/SCons/Platform/__init__.py +++ b/src/engine/SCons/Platform/__init__.py @@ -192,11 +192,6 @@ class TempFileMunge(object): if cmdlist is not None: return cmdlist - # We do a normpath because mktemp() has what appears to be - # a bug in Windows that will use a forward slash as a path - # delimiter. Windows' link mistakes that for a command line - # switch and barfs. - # # Default to the .lnk suffix for the benefit of the Phar Lap # linkloc linker, which likes to append an .lnk suffix if # none is given. @@ -206,7 +201,7 @@ class TempFileMunge(object): suffix = '.lnk' fd, tmp = tempfile.mkstemp(suffix, text=True) - native_tmp = SCons.Util.get_native_path(os.path.normpath(tmp)) + native_tmp = SCons.Util.get_native_path(tmp) if env.get('SHELL', None) == 'sh': # The sh shell will try to escape the backslashes in the diff --git a/src/engine/SCons/Platform/win32.py b/src/engine/SCons/Platform/win32.py index 77c048e..bb1b46d 100644 --- a/src/engine/SCons/Platform/win32.py +++ b/src/engine/SCons/Platform/win32.py @@ -178,61 +178,68 @@ def piped_spawn(sh, escape, cmd, args, env, stdout, stderr): # we redirect it into a temporary file tmpFileStdout # (tmpFileStderr) and copy the contents of this file # to stdout (stderr) given in the argument + # Note that because this will paste shell redirection syntax + # into the cmdline, we have to call a shell to run the command, + # even though that's a bit of a performance hit. if not sh: sys.stderr.write("scons: Could not find command interpreter, is it in your PATH?\n") return 127 - else: - # one temporary file for stdout and stderr - tmpFileStdout = os.path.normpath(tempfile.mktemp()) - tmpFileStderr = os.path.normpath(tempfile.mktemp()) - - # check if output is redirected - stdoutRedirected = 0 - stderrRedirected = 0 - for arg in args: - # are there more possibilities to redirect stdout ? - if arg.find( ">", 0, 1 ) != -1 or arg.find( "1>", 0, 2 ) != -1: - stdoutRedirected = 1 - # are there more possibilities to redirect stderr ? - if arg.find( "2>", 0, 2 ) != -1: - stderrRedirected = 1 - - # redirect output of non-redirected streams to our tempfiles - if stdoutRedirected == 0: - args.append(">" + str(tmpFileStdout)) - if stderrRedirected == 0: - args.append("2>" + str(tmpFileStderr)) - - # actually do the spawn + + # one temporary file for stdout and stderr + tmpFileStdout, tmpFileStdoutName = tempfile.mkstemp(text=True) + os.close(tmpFileStdout) # don't need open until the subproc is done + tmpFileStderr, tmpFileStderrName = tempfile.mkstemp(text=True) + os.close(tmpFileStderr) + + # check if output is redirected + stdoutRedirected = False + stderrRedirected = False + for arg in args: + # are there more possibilities to redirect stdout ? + if arg.find(">", 0, 1) != -1 or arg.find("1>", 0, 2) != -1: + stdoutRedirected = True + # are there more possibilities to redirect stderr ? + if arg.find("2>", 0, 2) != -1: + stderrRedirected = True + + # redirect output of non-redirected streams to our tempfiles + if not stdoutRedirected: + args.append(">" + tmpFileStdoutName) + if not stderrRedirected: + args.append("2>" + tmpFileStderrName) + + # actually do the spawn + try: + args = [sh, '/C', escape(' '.join(args))] + ret = spawnve(os.P_WAIT, sh, args, env) + except OSError as e: + # catch any error try: - args = [sh, '/C', escape(' '.join(args))] - ret = spawnve(os.P_WAIT, sh, args, env) - except OSError as e: - # catch any error - try: - ret = exitvalmap[e.errno] - except KeyError: - sys.stderr.write("scons: unknown OSError exception code %d - %s: %s\n" % (e.errno, cmd, e.strerror)) - if stderr is not None: - stderr.write("scons: %s: %s\n" % (cmd, e.strerror)) - # copy child output from tempfiles to our streams - # and do clean up stuff - if stdout is not None and stdoutRedirected == 0: - try: - with open(tmpFileStdout, "r" ) as tmp: - stdout.write(tmp.read()) - os.remove(tmpFileStdout) - except (IOError, OSError): - pass + ret = exitvalmap[e.errno] + except KeyError: + sys.stderr.write("scons: unknown OSError exception code %d - %s: %s\n" % (e.errno, cmd, e.strerror)) + if stderr is not None: + stderr.write("scons: %s: %s\n" % (cmd, e.strerror)) - if stderr is not None and stderrRedirected == 0: - try: - with open(tmpFileStderr, "r" ) as tmp: - stderr.write(tmp.read()) - os.remove(tmpFileStderr) - except (IOError, OSError): - pass - return ret + # copy child output from tempfiles to our streams + # and do clean up stuff + if stdout is not None and not stdoutRedirected: + try: + with open(tmpFileStdoutName, "r") as tmpFileStdout: + stdout.write(tmpFileStdout.read()) + os.remove(tmpFileStdoutName) + except (IOError, OSError): + pass + + if stderr is not None and not stderrRedirected: + try: + with open(tmpFileStderrName, "r") as tmpFileStderr: + stderr.write(tmpFileStderr.read()) + os.remove(tmpFileStderrName) + except (IOError, OSError): + pass + + return ret def exec_spawn(l, env): diff --git a/src/engine/SCons/UtilTests.py b/src/engine/SCons/UtilTests.py index 7f6508d..e2dd57f 100644 --- a/src/engine/SCons/UtilTests.py +++ b/src/engine/SCons/UtilTests.py @@ -506,13 +506,14 @@ class UtilTestCase(unittest.TestCase): def test_get_native_path(self): """Test the get_native_path() function.""" import tempfile - filename = tempfile.mktemp() - str = '1234567890 ' + filename + f, filename = tempfile.mkstemp(text=True) + os.close(f) + data = '1234567890 ' + filename try: with open(filename, 'w') as f: - f.write(str) - with open(get_native_path(filename)) as f: - assert f.read() == str + f.write(data) + with open(get_native_path(filename), 'r') as f: + assert f.read() == data finally: try: os.unlink(filename) diff --git a/src/engine/SCons/cppTests.py b/src/engine/SCons/cppTests.py index 0b346e8..eff7715 100644 --- a/src/engine/SCons/cppTests.py +++ b/src/engine/SCons/cppTests.py @@ -770,12 +770,6 @@ import re import shutil import tempfile -tempfile.template = 'cppTests.' -if os.name in ('posix', 'nt'): - tempfile.template = 'cppTests.' + str(os.getpid()) + '.' -else: - tempfile.template = 'cppTests.' - _Cleanup = [] def _clean(): @@ -785,19 +779,17 @@ def _clean(): atexit.register(_clean) +if os.name in ('posix', 'nt'): + tmpprefix = 'cppTests.' + str(os.getpid()) + '.' +else: + tmpprefix = 'cppTests.' + class fileTestCase(unittest.TestCase): cpp_class = cpp.DumbPreProcessor def setUp(self): - try: - path = tempfile.mktemp(prefix=tempfile.template) - except TypeError: - # The tempfile.mktemp() function in earlier versions of Python - # has no prefix argument, but uses the tempfile.template - # value that we set above. - path = tempfile.mktemp() + path = tempfile.mkdtemp(prefix=tmpprefix) _Cleanup.append(path) - os.mkdir(path) self.tempdir = path self.orig_cwd = os.getcwd() os.chdir(path) diff --git a/testing/framework/TestCmdTests.py b/testing/framework/TestCmdTests.py index 0c7b455..48eba1e 100644 --- a/testing/framework/TestCmdTests.py +++ b/testing/framework/TestCmdTests.py @@ -2814,8 +2814,7 @@ class symlink_TestCase(TestCmdTestCase): class tempdir_TestCase(TestCmdTestCase): def setUp(self): TestCmdTestCase.setUp(self) - self._tempdir = tempfile.mktemp() - os.mkdir(self._tempdir) + self._tempdir = tempfile.mkdtemp() os.chdir(self._tempdir) def tearDown(self): -- cgit v0.12 From b62749ff5d1efd32dbef28345d06919e5a9acd78 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 28 Dec 2019 21:23:44 -0800 Subject: Remove Python 2.7 from CI --- .appveyor.yml | 20 +------------------- .travis.yml | 49 ------------------------------------------------- 2 files changed, 1 insertion(+), 68 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 0287df9..a5d7dbe 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -49,12 +49,6 @@ install: # split builds into sets of four jobs due to appveyor per-job time limit environment: matrix: - - WINPYTHON: "Python27" - PYTHON: "2.7" - PYVER: 27 - BUILD_JOB_NUM: 1 - COVERAGE: 0 - - WINPYTHON: "Python35" PYTHON: "3.5" PYVER: 35 @@ -79,12 +73,6 @@ environment: BUILD_JOB_NUM: 1 COVERAGE: 0 - # - WINPYTHON: "Python27" - # PYTHON: "2.7" - # PYVER: 27 - # BUILD_JOB_NUM: 2 - # COVERAGE: 0 - # - WINPYTHON: "Python35" # PYTHON: "3.5" # PYVER: 35 @@ -116,15 +104,13 @@ matrix: exclude: # test python 3.5 on Visual Studio 2015 image - image: Visual Studio 2015 - WINPYTHON: "Python27" - - image: Visual Studio 2015 WINPYTHON: "Python36" - image: Visual Studio 2015 WINPYTHON: "Python37" - image: Visual Studio 2015 WINPYTHON: "Python38" - # test python 2.7, 3.8 on Visual Studio 2017 image + # test python 3.8 on Visual Studio 2017 image - image: Visual Studio 2017 WINPYTHON: "Python35" - image: Visual Studio 2017 @@ -134,16 +120,12 @@ matrix: # test python 3.7 on Visual Studio 2019 image - image: Visual Studio 2019 - WINPYTHON: "Python27" - - image: Visual Studio 2019 WINPYTHON: "Python35" - image: Visual Studio 2019 WINPYTHON: "Python36" # skip on Ubuntu - image: Ubuntu - WINPYTHON: "Python27" - - image: Ubuntu WINPYTHON: "Python35" - image: Ubuntu WINPYTHON: "Python36" diff --git a/.travis.yml b/.travis.yml index 4431eb1..0c84271 100644 --- a/.travis.yml +++ b/.travis.yml @@ -64,13 +64,6 @@ jobs: sudo: required - <<: *test_job - python: 2.7 - env: - - PYVER=27 - - PYTHON=2.7 - sudo: required - - - <<: *test_job python: 3.5 env: - PYVER=35 @@ -165,45 +158,3 @@ jobs: - PYVER=37 - PYTHON=3.7 - BUILD_JOB_NUM=1 -# -# - <<: *coverage_jobs -# env: -# - PYVER=27 -# - PYTHON=2.7 -# - BUILD_JOB_NUM=2 -# - <<: *coverage_jobs -# env: -# - PYVER=27 -# - PYTHON=2.7 -# - BUILD_JOB_NUM=3 -# - <<: *coverage_jobs -# env: -# - PYVER=27 -# - PYTHON=2.7 -# - BUILD_JOB_NUM=4 - -# - <<: *coverage_jobs -# python: 3.6 -# env: -# - PYVER=36 -# - PYTHON=3.6 -# - BUILD_JOB_NUM=1 -# - <<: *coverage_jobs -# python: 3.6 -# env: -# - PYVER=36 -# - PYTHON=3.6 -# - BUILD_JOB_NUM=2 -# - <<: *coverage_jobs -# python: 3.6 -# env: -# - PYVER=36 -# - PYTHON=3.6 -# - BUILD_JOB_NUM=3 -# - <<: *coverage_jobs -# python: 3.6 -# env: -# - PYVER=36 -# - PYTHON=3.6 -# - BUILD_JOB_NUM=4 - -- cgit v0.12 From af3b2cdcb1772d89a0837604f7b5a59ca542e65f Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 28 Dec 2019 21:24:09 -0800 Subject: Remove PY 27 from README. Now only PY 3.5+ --- README-SF.rst | 2 +- README.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README-SF.rst b/README-SF.rst index 67301d4..0c66bb3 100755 --- a/README-SF.rst +++ b/README-SF.rst @@ -48,7 +48,7 @@ version at the SCons download page: Execution Requirements ====================== -Running SCons requires either Python version 2.7.* or Python 3.5 or higher. +Running SCons requires Python 3.5 or higher. There should be no other dependencies or requirements to run SCons. The default SCons configuration assumes use of the Microsoft Visual C++ diff --git a/README.rst b/README.rst index 2fbefc5..2954904 100755 --- a/README.rst +++ b/README.rst @@ -72,7 +72,7 @@ version at the SCons download page: Execution Requirements ====================== -Running SCons requires either Python version 2.7.* or Python 3.5 or higher. +Running SCons requires Python 3.5 or higher. There should be no other dependencies or requirements to run SCons. The default SCons configuration assumes use of the Microsoft Visual C++ -- cgit v0.12 From 626dae1c958b5edb002b4bd97969d3d1cfcc9a47 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 28 Dec 2019 21:24:36 -0800 Subject: Change scons and sconsign to error out if run with Python < 3.5 --- src/script/scons.py | 4 ++-- src/script/sconsign.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/script/scons.py b/src/script/scons.py index 351fb9f..2e76365 100755 --- a/src/script/scons.py +++ b/src/script/scons.py @@ -59,9 +59,9 @@ import sys ############################################################################## # compatibility check -if (3,0,0) < sys.version_info < (3,5,0) or sys.version_info < (2,7,0): +if sys.version_info < (3,5,0): msg = "scons: *** SCons version %s does not run under Python version %s.\n\ -Python 2.7 or >= 3.5 is required.\n" +Python >= 3.5 is required.\n" sys.stderr.write(msg % (__version__, sys.version.split()[0])) sys.exit(1) diff --git a/src/script/sconsign.py b/src/script/sconsign.py index 593c536..5ea5ea5 100644 --- a/src/script/sconsign.py +++ b/src/script/sconsign.py @@ -50,9 +50,9 @@ import sys ############################################################################## # compatibility check -if (3,0,0) < sys.version_info < (3,5,0) or sys.version_info < (2,7,0): +if sys.version_info < (3,5,0): msg = "scons: *** SCons version %s does not run under Python version %s.\n\ -Python 2.7 or >= 3.5 is required.\n" +Python >= 3.5 is required.\n" sys.stderr.write(msg % (__version__, sys.version.split()[0])) sys.exit(1) -- cgit v0.12 From b746597e2bc93dcdd8483a3ade04c7cb777f18d0 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 28 Dec 2019 21:25:18 -0800 Subject: Remove Py27 vs Py 35+ compat code. --- src/engine/SCons/compat/__init__.py | 56 ++----------------------------------- 1 file changed, 2 insertions(+), 54 deletions(-) diff --git a/src/engine/SCons/compat/__init__.py b/src/engine/SCons/compat/__init__.py index d34243e..18bef48 100644 --- a/src/engine/SCons/compat/__init__.py +++ b/src/engine/SCons/compat/__init__.py @@ -78,12 +78,8 @@ def rename_module(new, old): return False -# TODO: FIXME -# In 3.x, 'pickle' automatically loads the fast version if available. -rename_module('pickle', 'cPickle') - -# Default pickle protocol. Higher protocols are more efficient/featureful -# but incompatible with older Python versions. On Python 2.7 this is 2. +# Default pickle protocol. Higher protocols are more efficient/featured +# but incompatible with older Python versions. # Negative numbers choose the highest available protocol. import pickle @@ -91,54 +87,6 @@ import pickle # Changed to 2 so py3.5+'s pickle will be compatible with py2.7. PICKLE_PROTOCOL = pickle.HIGHEST_PROTOCOL -# TODO: FIXME -# In 3.x, 'profile' automatically loads the fast version if available. -rename_module('profile', 'cProfile') - -# TODO: FIXME -# Before Python 3.0, the 'queue' module was named 'Queue'. -rename_module('queue', 'Queue') - -# TODO: FIXME -# Before Python 3.0, the 'winreg' module was named '_winreg' -rename_module('winreg', '_winreg') - -# Python 3 moved builtin intern() to sys package -# To make porting easier, make intern always live -# in sys package (for python 2.7.x) -try: - sys.intern -except AttributeError: - # We must be using python 2.7.x so monkey patch - # intern into the sys package - sys.intern = intern - -# UserDict, UserList, UserString are in # collections for 3.x, -# but standalone in 2.7.x. Monkey-patch into collections for 2.7. -import collections - -try: - collections.UserDict -except AttributeError: - from UserDict import UserDict as _UserDict - collections.UserDict = _UserDict - del _UserDict - -try: - collections.UserList -except AttributeError: - from UserList import UserList as _UserList - collections.UserList = _UserList - del _UserList - -try: - collections.UserString -except AttributeError: - from UserString import UserString as _UserString - collections.UserString = _UserString - del _UserString - - import shutil try: shutil.SameFileError -- cgit v0.12 From c50b86d06fb17daa365286e439d3808f82f98bef Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 30 Dec 2019 10:53:56 -0800 Subject: [appveyor skip] Drop pypy from build matrix. (it's py27) --- .travis.yml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0c84271..ddc2829 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,6 @@ install: # allow coverage to fail, so we can still do testing for all platforms matrix: allow_failures: - - python: pypy - python: pypy3 - stage: Coverage @@ -56,12 +55,6 @@ jobs: - PYTHON=pypy3 sudo: required - - <<: *test_job - python: pypy - env: - - PYVER=pypy - - PYTHON=pypy - sudo: required - <<: *test_job python: 3.5 @@ -100,7 +93,7 @@ jobs: python: 3.7 before_script: # install our own python so we can modify usercustomize.py - - deactivate +# - deactivate # - sudo add-apt-repository -y ppa:deadsnakes/ppa # - sudo apt-get update || true # - sudo apt-get -y install python$PYTHON -- cgit v0.12 From de833c7158f70db546298728cc7a8298e820d1ca Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 30 Dec 2019 18:37:25 -0800 Subject: remove --user from pip install coverage --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ddc2829..4ad842d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -101,7 +101,7 @@ jobs: # - sudo -H python$PYTHON get-pip.py - which python - python --version - - python -m pip install --user -U coverage codecov + - python -m pip install -U coverage codecov # set this ensure user sites are available - export PYTHONNOUSERSITE= # attempt to get a location where we can store the usercustomize.py file -- cgit v0.12 From d82262295ae272ba147d6f056cffa8225cb1629c Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 1 Jan 2020 14:21:12 -0800 Subject: Fix use-dbm test to work with sconsign files using dbm but where the underlying dbm implementation still writes the file without applying a suffix (like .db). This is due to Travis-ci's py3.8's dbm not applying suffix. Which seems unusual, but still valid --- .travis/.coveragerc | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 .travis/.coveragerc diff --git a/.travis/.coveragerc b/.travis/.coveragerc new file mode 100644 index 0000000..e69de29 -- cgit v0.12 From 315cee3763145f01e600d4c09929743ba474891a Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 1 Jan 2020 14:21:38 -0800 Subject: Fix use-dbm test to work with sconsign files using dbm but where the underlying dbm implementation still writes the file without applying a suffix (like .db). This is due to Travis-ci's py3.8's dbm not applying suffix. Which seems unusual, but still valid --- test/SConsignFile/use-dbm.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/test/SConsignFile/use-dbm.py b/test/SConsignFile/use-dbm.py index e02346a..d6c596f 100644 --- a/test/SConsignFile/use-dbm.py +++ b/test/SConsignFile/use-dbm.py @@ -27,20 +27,22 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" """ Verify SConsignFile() when used with dbm. """ - +import os.path +import dbm import TestSCons _python_ = TestSCons._python_ test = TestSCons.TestSCons() - try: import dbm.ndbm + use_db = 'dbm.ndbm' except ImportError: try: import dbm + use_db = 'dbm' except ImportError: test.skip_test('No dbm.ndbm in this version of Python; skipping test.\n') @@ -78,20 +80,21 @@ test.run() # We don't check for explicit .db or other file, because base "dbm" # can use different file extensions on different implementations. -test.must_not_exist(test.workpath('.sconsign')) +test.fail_test(os.path.exists('.sconsign') and 'dbm' not in dbm.whichdb('.sconsign'), + message=".sconsign existed an wasn't any type of dbm file") test.must_not_exist(test.workpath('.sconsign.dblite')) test.must_not_exist(test.workpath('subdir', '.sconsign')) test.must_not_exist(test.workpath('subdir', '.sconsign.dblite')) - + test.must_match('f1.out', "f1.in\n") test.must_match('f2.out', "f2.in\n") test.must_match(['subdir', 'f3.out'], "subdir/f3.in\n") test.must_match(['subdir', 'f4.out'], "subdir/f4.in\n") -test.up_to_date(arguments = '.') - +test.up_to_date(arguments='.') -test.must_not_exist(test.workpath('.sconsign')) +test.fail_test(os.path.exists('.sconsign') and 'dbm' not in dbm.whichdb('.sconsign'), + message=".sconsign existed an wasn't any type of dbm file") test.must_not_exist(test.workpath('.sconsign.dblite')) test.must_not_exist(test.workpath('subdir', '.sconsign')) test.must_not_exist(test.workpath('subdir', '.sconsign.dblite')) -- cgit v0.12 From 1b975d13c3ae848f1cda830b526d4bcf2bd202f5 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 1 Jan 2020 15:54:22 -0800 Subject: try non-sudo'd usercustomize.py file in sys.path[-1] instead of user site dir which is somehow broken --- .travis.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4ad842d..a988b19 100644 --- a/.travis.yml +++ b/.travis.yml @@ -106,15 +106,15 @@ jobs: - export PYTHONNOUSERSITE= # attempt to get a location where we can store the usercustomize.py file - python -m site - - export PYSITEDIR=$(python -m site --user-site) - - sudo mkdir -p $PYSITEDIR - - sudo touch ${PYSITEDIR}/usercustomize.py +# - export PYSITEDIR=$(python -m site --user-site) + - export PYSITEDIR=$(python -c "import sys; print(sys.path[-1])) + - mkdir -p $PYSITEDIR - export COVERAGE_FILE=$PWD/.coverage # write the usercustomize.py file so all python processes use coverage and know where the config file is - - echo "import os" | sudo tee --append ${PYSITEDIR}/usercustomize.py - - echo "os.environ['COVERAGE_PROCESS_START'] = '$PWD/.coveragerc'" | sudo tee --append ${PYSITEDIR}/usercustomize.py - - echo "import coverage" | sudo tee --append ${PYSITEDIR}/usercustomize.py - - echo "coverage.process_startup()" | sudo tee --append ${PYSITEDIR}/usercustomize.py + - echo "import os" | tee --append ${PYSITEDIR}/usercustomize.py + - echo "os.environ['COVERAGE_PROCESS_START'] = '$PWD/.coveragerc'" | tee --append ${PYSITEDIR}/usercustomize.py + - echo "import coverage" | tee --append ${PYSITEDIR}/usercustomize.py + - echo "coverage.process_startup()" | tee --append ${PYSITEDIR}/usercustomize.py script: - export TOTAL_BUILD_JOBS=1 -- cgit v0.12 From 603063f20000a4026fea324aa32b0ddd37efa3e4 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 1 Jan 2020 15:57:17 -0800 Subject: fix typo --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index a988b19..0c1c51f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -107,7 +107,7 @@ jobs: # attempt to get a location where we can store the usercustomize.py file - python -m site # - export PYSITEDIR=$(python -m site --user-site) - - export PYSITEDIR=$(python -c "import sys; print(sys.path[-1])) + - export PYSITEDIR=$(python -c "import sys; print(sys.path[-1])") - mkdir -p $PYSITEDIR - export COVERAGE_FILE=$PWD/.coverage # write the usercustomize.py file so all python processes use coverage and know where the config file is -- cgit v0.12 From cc6145513d6f4b5f0dcafafd8af6ae316feed460 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 1 Jan 2020 17:11:52 -0800 Subject: move coverage startuplogic to sitecustomize.py from usercustomize.py --- .travis/.coveragerc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.travis/.coveragerc b/.travis/.coveragerc index e69de29..d94c366 100644 --- a/.travis/.coveragerc +++ b/.travis/.coveragerc @@ -0,0 +1,8 @@ +echo "[run]" >> .coveragerc +echo "source = $PWD/src" >> .coveragerc +echo "parallel = True" >> .coveragerc +printf "omit =\n\t*Tests.py\n\tsrc/test_*\n\tsrc/setup.py\n\n" >> .coveragerc +echo "[path]" >> .coveragerc +echo "source = $PWD" >> .coveragerc +echo "[report]" >> .coveragerc +printf "omit =\n\t*Tests.py\n\tsrc/test_*\n\tsrc/setup.py\n\n" >> .coveragerc -- cgit v0.12 From f2f447627771cf53678eb3c4b61fa65c0e53a709 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 1 Jan 2020 17:39:01 -0800 Subject: move coverage startuplogic to sitecustomize.py from usercustomize.py --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0c1c51f..985a544 100644 --- a/.travis.yml +++ b/.travis.yml @@ -111,10 +111,10 @@ jobs: - mkdir -p $PYSITEDIR - export COVERAGE_FILE=$PWD/.coverage # write the usercustomize.py file so all python processes use coverage and know where the config file is - - echo "import os" | tee --append ${PYSITEDIR}/usercustomize.py - - echo "os.environ['COVERAGE_PROCESS_START'] = '$PWD/.coveragerc'" | tee --append ${PYSITEDIR}/usercustomize.py - - echo "import coverage" | tee --append ${PYSITEDIR}/usercustomize.py - - echo "coverage.process_startup()" | tee --append ${PYSITEDIR}/usercustomize.py + - echo "import os" | tee --append ${PYSITEDIR}/sitecustomize.py + - echo "os.environ['COVERAGE_PROCESS_START'] = '$PWD/.coveragerc'" | tee --append ${PYSITEDIR}/sitecustomize.py + - echo "import coverage" | tee --append ${PYSITEDIR}/sitecustomize.py + - echo "coverage.process_startup()" | tee --append ${PYSITEDIR}/sitecustomize.py script: - export TOTAL_BUILD_JOBS=1 -- cgit v0.12 From c01be1e4c4a0bb438ca351995c2c3778622939db Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 1 Jan 2020 19:50:36 -0800 Subject: [ci skip] Add to CHANGES.txt --- src/CHANGES.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 5d0e3a2..6479710 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -14,6 +14,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER header files and libraries from MSVC install. (Fixes GH Issue #3480) - Added C:\msys64\mingw64\bin to default mingw and clang windows PATH's. This is a reasonable default and also aligns with changes in Appveyor's VS2019 image. + - Drop support for Python 2.7. SCons will be Python 3.5+ going forward. From Mathew Robinson: - Improve performance of Subst by preventing unnecessary frame -- cgit v0.12 From e8d186bb28a12d8de0742b0ba27c642b49faaf74 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 1 Jan 2020 19:53:20 -0800 Subject: kick github CI's for PR --- src/CHANGES.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 6479710..400e3b7 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -16,6 +16,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER is a reasonable default and also aligns with changes in Appveyor's VS2019 image. - Drop support for Python 2.7. SCons will be Python 3.5+ going forward. + From Mathew Robinson: - Improve performance of Subst by preventing unnecessary frame allocations by no longer defining the *Subber classes inside of their -- cgit v0.12 From 5c5bf0347c2f5be62240fc9e1cb8e9ef0ec2b84c Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 2 Jan 2020 11:39:58 -0800 Subject: [ci skip] Add logic to know when running in pypy --- src/engine/SCons/Util.py | 5 +++++ testing/framework/TestCmd.py | 1 + 2 files changed, 6 insertions(+) diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index 4b4ead5..8c5cecf 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -36,6 +36,8 @@ import pprint import hashlib PY3 = sys.version_info[0] == 3 +PYPY = hasattr(sys, 'pypy_translation_info') + try: from collections import UserDict, UserList, UserString @@ -612,6 +614,7 @@ class Proxy(object): return self._subject == other return self.__dict__ == other.__dict__ + class Delegate(object): """A Python Descriptor class that delegates attribute fetches to an underlying wrapped subject of a Proxy. Typical use: @@ -621,7 +624,9 @@ class Delegate(object): """ def __init__(self, attribute): self.attribute = attribute + def __get__(self, obj, cls): + print("IN GET") if isinstance(obj, cls): return getattr(obj._subject, self.attribute) else: diff --git a/testing/framework/TestCmd.py b/testing/framework/TestCmd.py index b98445c..6beed24 100644 --- a/testing/framework/TestCmd.py +++ b/testing/framework/TestCmd.py @@ -310,6 +310,7 @@ import types IS_PY3 = sys.version_info[0] == 3 IS_WINDOWS = sys.platform == 'win32' IS_64_BIT = sys.maxsize > 2**32 +IS_PYPY = hasattr(sys, 'pypy_translation_info') class null(object): pass -- cgit v0.12 From 68814f3ea56bd4f9e7dbc21309e5a8f509304c45 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 2 Jan 2020 11:50:42 -0800 Subject: [ci skip] typo in error message in test --- test/SConsignFile/use-dbm.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/SConsignFile/use-dbm.py b/test/SConsignFile/use-dbm.py index d6c596f..5100916 100644 --- a/test/SConsignFile/use-dbm.py +++ b/test/SConsignFile/use-dbm.py @@ -81,7 +81,7 @@ test.run() # can use different file extensions on different implementations. test.fail_test(os.path.exists('.sconsign') and 'dbm' not in dbm.whichdb('.sconsign'), - message=".sconsign existed an wasn't any type of dbm file") + message=".sconsign existed and wasn't any type of dbm file") test.must_not_exist(test.workpath('.sconsign.dblite')) test.must_not_exist(test.workpath('subdir', '.sconsign')) test.must_not_exist(test.workpath('subdir', '.sconsign.dblite')) @@ -94,7 +94,7 @@ test.must_match(['subdir', 'f4.out'], "subdir/f4.in\n") test.up_to_date(arguments='.') test.fail_test(os.path.exists('.sconsign') and 'dbm' not in dbm.whichdb('.sconsign'), - message=".sconsign existed an wasn't any type of dbm file") + message=".sconsign existed and wasn't any type of dbm file") test.must_not_exist(test.workpath('.sconsign.dblite')) test.must_not_exist(test.workpath('subdir', '.sconsign')) test.must_not_exist(test.workpath('subdir', '.sconsign.dblite')) -- cgit v0.12 From f59d3a33ca816f9b6a9d3cc21b867d19a7a8a150 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 2 Jan 2020 13:06:20 -0800 Subject: Remove extraneous debug output --- src/engine/SCons/Util.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index 8c5cecf..d930dde 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -626,7 +626,6 @@ class Delegate(object): self.attribute = attribute def __get__(self, obj, cls): - print("IN GET") if isinstance(obj, cls): return getattr(obj._subject, self.attribute) else: -- cgit v0.12 From 57b830dc04da3710ad8ded9eef469ddddd1ff94e Mon Sep 17 00:00:00 2001 From: Andrew Morrow Date: Mon, 28 Oct 2019 13:54:41 -0400 Subject: [WIP] #3469 - Make conftests have unique names --- src/engine/SCons/SConf.py | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/src/engine/SCons/SConf.py b/src/engine/SCons/SConf.py index e706dae..ed039b7 100644 --- a/src/engine/SCons/SConf.py +++ b/src/engine/SCons/SConf.py @@ -56,6 +56,7 @@ import SCons.Warnings import SCons.Conftest from SCons.Debug import Trace +from collections import defaultdict # Turn off the Conftest error logging SCons.Conftest.LogInputFiles = 0 @@ -98,7 +99,7 @@ def SetProgressDisplay(display): SConfFS = None -_ac_build_counter = 0 # incremented, whenever TryBuild is called +_ac_build_counter = defaultdict(int) _ac_config_logs = {} # all config.log files created in this build _ac_config_hs = {} # all config.h files created in this build sconf_global = None # current sconf object @@ -592,8 +593,30 @@ class SConfBase(object): raise SCons.Errors.UserError('Missing SPAWN construction variable.') nodesToBeBuilt = [] + sourcetext = self.env.Value(text) + f = "conftest" + + if text is not None: + textSig = SCons.Util.MD5signature(sourcetext) + textSigCounter = str(_ac_build_counter[textSig]) + _ac_build_counter[textSig] += 1 + + f = "_".join([f, textSig, textSigCounter]) + textFile = self.confdir.File(f + extension) + textFileNode = self.env.SConfSourceBuilder(target=textFile, + source=sourcetext) + nodesToBeBuilt.extend(textFileNode) + + source = textFile + target = textFile.File(f + "SConfActionsContentDummyTarget") + else: + source = None + target = None + + action = builder.builder.action.get_contents(target=target, source=[source], env=self.env) + actionsig = str(SCons.Util.MD5signature(action)) + f = "_".join([f, actionsig]) - f = "conftest_" + str(_ac_build_counter) pref = self.env.subst( builder.builder.prefix ) suff = self.env.subst( builder.builder.suffix ) target = self.confdir.File(pref + f + suff) @@ -602,16 +625,6 @@ class SConfBase(object): # Slide our wrapper into the construction environment as # the SPAWN function. self.env['SPAWN'] = self.pspawn_wrapper - sourcetext = self.env.Value(text) - - if text is not None: - textFile = self.confdir.File(f + extension) - textFileNode = self.env.SConfSourceBuilder(target=textFile, - source=sourcetext) - nodesToBeBuilt.extend(textFileNode) - source = textFileNode - else: - source = None nodes = builder(target = target, source = source) if not SCons.Util.is_List(nodes): @@ -622,7 +635,6 @@ class SConfBase(object): finally: self.env['SPAWN'] = save_spawn - _ac_build_counter = _ac_build_counter + 1 if result: self.lastTarget = nodes[0] else: -- cgit v0.12 From 0aaa5d29927629baa7025b26735e5169b6fba955 Mon Sep 17 00:00:00 2001 From: Mathew Robinson Date: Mon, 6 Jan 2020 14:14:22 -0500 Subject: Store unexpanded string for reporting in error messages --- src/engine/SCons/Subst.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/engine/SCons/Subst.py b/src/engine/SCons/Subst.py index 2e469ce..59b0fcb 100644 --- a/src/engine/SCons/Subst.py +++ b/src/engine/SCons/Subst.py @@ -376,6 +376,9 @@ class StringSubber(object): if key[0] == '{': key = key[1:-1] + # Store for error messages if we fail to expand the + # value + old_s = s s = None if key in lvars: s = lvars[key] @@ -389,10 +392,10 @@ class StringSubber(object): except Exception as e: if e.__class__ in AllowableExceptions: return '' - raise_exception(e, lvars['TARGETS'], s) + raise_exception(e, lvars['TARGETS'], old_s) if s is None and NameError not in AllowableExceptions: - raise_exception(NameError(key), lvars['TARGETS'], s) + raise_exception(NameError(key), lvars['TARGETS'], old_s) elif s is None: return '' @@ -528,6 +531,9 @@ class ListSubber(collections.UserList): if key[0] == '{': key = key[1:-1] + # Store for error messages if we fail to expand the + # value + old_s = s s = None if key in lvars: s = lvars[key] @@ -541,10 +547,10 @@ class ListSubber(collections.UserList): except Exception as e: if e.__class__ in AllowableExceptions: return - raise_exception(e, lvars['TARGETS'], s) + raise_exception(e, lvars['TARGETS'], old_s) if s is None and NameError not in AllowableExceptions: - raise_exception(NameError(), lvars['TARGETS'], s) + raise_exception(NameError(), lvars['TARGETS'], old_s) elif s is None: return -- cgit v0.12 From bcea663cf1b442354a13474cc744b172caef10ab Mon Sep 17 00:00:00 2001 From: Mathew Robinson Date: Mon, 23 Dec 2019 13:34:42 -0500 Subject: Prevent unnecessary recursion when value is already expanded --- src/CHANGES.txt | 1 + src/engine/SCons/Subst.py | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 81664aa..a9417c7 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -24,6 +24,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Improve performance of Subst in some cases by preventing unnecessary calls to eval when a token is surrounded in braces but is not a function call. + - Improve performance of subst by removing unnecessary recursion. From Mats Wichmann: - Remove deprecated SourceCode diff --git a/src/engine/SCons/Subst.py b/src/engine/SCons/Subst.py index 92aa52c..e81131d 100644 --- a/src/engine/SCons/Subst.py +++ b/src/engine/SCons/Subst.py @@ -499,6 +499,9 @@ class ListSubber(collections.UserList): self.in_strip = None self.next_line() + def expanded(self, s): + return is_String(s) and _separate_args.findall(s) is None + def expand(self, s, lvars, within_list): """Expand a single "token" as necessary, appending the expansion to the current result. @@ -554,6 +557,10 @@ class ListSubber(collections.UserList): elif s is None: return + if self.expanded(s): + self.append(s) + return + # Before re-expanding the result, handle # recursive expansion by copying the local # variable dictionary and overwriting a null -- cgit v0.12 From 9ac66132c5189274c130182d1bc2a3c8c526aa47 Mon Sep 17 00:00:00 2001 From: Mathew Robinson Date: Mon, 6 Jan 2020 14:21:09 -0500 Subject: Handle UserString in ListSubber.expanded --- src/engine/SCons/Subst.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/engine/SCons/Subst.py b/src/engine/SCons/Subst.py index e81131d..eec4adf 100644 --- a/src/engine/SCons/Subst.py +++ b/src/engine/SCons/Subst.py @@ -500,7 +500,11 @@ class ListSubber(collections.UserList): self.next_line() def expanded(self, s): - return is_String(s) and _separate_args.findall(s) is None + if not is_String(s) or isinstance(s, CmdStringHolder): + return False + + s = str(s) # in case it's a UserString + return _separate_args.findall(s) is None def expand(self, s, lvars, within_list): """Expand a single "token" as necessary, appending the -- cgit v0.12 From 2ff7ea17b28e6962c48238550d77ec9cdd96c02c Mon Sep 17 00:00:00 2001 From: Mathew Robinson Date: Mon, 6 Jan 2020 17:42:41 -0500 Subject: [ci skip] Document ListSubber.expanded and usage --- src/engine/SCons/Subst.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/engine/SCons/Subst.py b/src/engine/SCons/Subst.py index eec4adf..a1ef053 100644 --- a/src/engine/SCons/Subst.py +++ b/src/engine/SCons/Subst.py @@ -500,6 +500,14 @@ class ListSubber(collections.UserList): self.next_line() def expanded(self, s): + """Determines if the string s requires further expansion. + + Due to the implementation of ListSubber expand will call + itself 2 additional times for an already expanded string. This + method is used to determine if a string is already fully + expanded and if so exit the loop early to prevent these + recursive calls. + """ if not is_String(s) or isinstance(s, CmdStringHolder): return False @@ -561,6 +569,8 @@ class ListSubber(collections.UserList): elif s is None: return + # If the string is already full expanded there's no + # need to continue recursion. if self.expanded(s): self.append(s) return -- cgit v0.12 From ae5461ca714ea06e135899a8b08d615008aab4ee Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Tue, 7 Jan 2020 09:51:46 -0700 Subject: Fixup some doc inconsistencies. [CI skip] PR #3464 removed SourceSignatures, TargetSignatures but left a dangling reference in the User Guide (referred to the existence of the functions but did not give their names, which is how they were missed). [Fixes #3519] PR #3506 removed SourceCode, and accidentally removed the documentation of the Split function as well. In the PR history is a note that it was discovered and restored, but somehow it is still missing from master so restoring (again) with small markup changes. Signed-off-by: Mats Wichmann --- doc/user/depends.xml | 37 +++++++++++++++++----------------- src/engine/SCons/Environment.xml | 32 +++++++++++++++++++++++++++++ src/engine/SCons/Script/SConscript.xml | 12 +++++------ 3 files changed, 56 insertions(+), 25 deletions(-) diff --git a/doc/user/depends.xml b/doc/user/depends.xml index cd5094a..3cba64c 100644 --- a/doc/user/depends.xml +++ b/doc/user/depends.xml @@ -2,7 +2,7 @@ %scons; - + %builders-mod; @@ -372,7 +372,7 @@ int main() { printf("Hello, world!\n"); } instead of timestamp-match, would be if you have some specific reason - to require this &Make;-like behavior of + to require this &Make;-like behavior of not rebuilding a target when an otherwise-modified source file is older. @@ -747,25 +747,24 @@ int main() { printf("Hello, world!\n"); }
- Older Functions for Deciding When an Input File Has Changed + Obsolete Functions for Deciding When an Input File Has Changed - &SCons; still supports two functions that used to be the - primary methods for configuring the - decision about whether or not an input file has changed. - These functions have been officially deprecated - as &SCons; version 2.0, - and their use is discouraged, - mainly because they rely on a somewhat - confusing distinction between how - source files and target files are handled. - These functions are documented here mainly in case you - encounter them in older &SConscript; files. + In the past, &SCons; supported two functions + (SourceSignatures and + TargetSignatures) + that once were the primary methods for configuring the + decision about whether or not an input file had changed. + These functions were deprecated since &SCons; version 2.0, + and removed in &SCons; version 3.1 and + are mentioned here solely for identification purposes, + as there are a number of very old examples that may turn up + in web searches and in the SCons Wiki that may reference them.
- +
Implicit Dependencies: The &cv-CPPPATH; Construction Variable @@ -1426,11 +1425,11 @@ Ignore(hello, '/usr/include/stdio.h') - &Ignore; can also be used to prevent a generated file from being built - by default. This is due to the fact that directories depend on - their contents. So to ignore a generated file from the default build, + &Ignore; can also be used to prevent a generated file from being built + by default. This is due to the fact that directories depend on + their contents. So to ignore a generated file from the default build, you specify that the directory should ignore the generated file. - Note that the file will still be built if the user specifically + Note that the file will still be built if the user specifically requests the target on scons command line, or if the file is a dependency of another file which is requested and/or is built by default. diff --git a/src/engine/SCons/Environment.xml b/src/engine/SCons/Environment.xml index b1c2039..35e4bd8 100644 --- a/src/engine/SCons/Environment.xml +++ b/src/engine/SCons/Environment.xml @@ -2879,6 +2879,38 @@ function. + +(arg) + + +Returns a list of file names or other objects. +If arg is a string, +it will be split on strings of white-space characters +within the string, +making it easier to write long lists of file names. +If arg is already a list, +the list will be returned untouched. +If arg is any other type of object, +it will be returned as a list +containing just the object. + + + +Example: + + + +files = Split("f1.c f2.c f3.c") +files = env.Split("f4.c f5.c f6.c") +files = Split(""" + f7.c + f8.c + f9.c +""") + + + + (input, [raw, target, source, conv]) diff --git a/src/engine/SCons/Script/SConscript.xml b/src/engine/SCons/Script/SConscript.xml index 874c110..a1e0129 100644 --- a/src/engine/SCons/Script/SConscript.xml +++ b/src/engine/SCons/Script/SConscript.xml @@ -252,16 +252,16 @@ This specifies help text to be printed if the argument is given to &scons;. -If +If &f-Help; -is called multiple times, the text is appended together in the order that +is called multiple times, the text is appended together in the order that &f-Help; -is called. With append set to False, any +is called. With append set to False, any &f-Help; -text generated with +text generated with &f-AddOption; is clobbered. If append is True, the AddOption help is prepended to the help -string, thus preserving the +string, thus preserving the message. @@ -393,7 +393,7 @@ A single script may be specified as a string; multiple scripts must be specified as a list (either explicitly or as created by a function like -&f-Split;). +&f-link-Split;). Examples: -- cgit v0.12 From fa3aa9e79912faa7673587d7d461d9c016f133d2 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Tue, 7 Jan 2020 10:48:31 -0700 Subject: [PR #3520] just drop the userguide section Pre review comment, drop the section which referenced the *Signatures functions, rather than trying to fix it up. The functions were previously dropped. Signed-off-by: Mats Wichmann --- doc/user/depends.xml | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/doc/user/depends.xml b/doc/user/depends.xml index 3cba64c..703855d 100644 --- a/doc/user/depends.xml +++ b/doc/user/depends.xml @@ -747,25 +747,6 @@ int main() { printf("Hello, world!\n"); }
- Obsolete Functions for Deciding When an Input File Has Changed - - - - In the past, &SCons; supported two functions - (SourceSignatures and - TargetSignatures) - that once were the primary methods for configuring the - decision about whether or not an input file had changed. - These functions were deprecated since &SCons; version 2.0, - and removed in &SCons; version 3.1 and - are mentioned here solely for identification purposes, - as there are a number of very old examples that may turn up - in web searches and in the SCons Wiki that may reference them. - - -
- -
Implicit Dependencies: The &cv-CPPPATH; Construction Variable -- cgit v0.12 From c5531583f832b59c7d5ec0af682e33e04ef7ff4a Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 9 Jan 2020 16:33:06 -0800 Subject: Remove UnicodeType as py35+ has unicode strings. Remove some py27 imports. Mainly cleanup of Util.py and tests depending on these changes --- src/engine/SCons/Taskmaster.py | 2 +- src/engine/SCons/Tool/xgettext.py | 2 +- src/engine/SCons/Util.py | 27 ++++++--------------------- src/engine/SCons/UtilTests.py | 31 ++----------------------------- 4 files changed, 10 insertions(+), 52 deletions(-) diff --git a/src/engine/SCons/Taskmaster.py b/src/engine/SCons/Taskmaster.py index 06fc94c..7363915 100644 --- a/src/engine/SCons/Taskmaster.py +++ b/src/engine/SCons/Taskmaster.py @@ -792,7 +792,7 @@ class Taskmaster(object): self.ready_exc = None T = self.trace - if T: T.write(SCons.Util.UnicodeType('\n') + self.trace_message('Looking for a node to evaluate')) + if T: T.write(str('\n') + self.trace_message('Looking for a node to evaluate')) while True: node = self.next_candidate() diff --git a/src/engine/SCons/Tool/xgettext.py b/src/engine/SCons/Tool/xgettext.py index 11ca32f..7aba08d 100644 --- a/src/engine/SCons/Tool/xgettext.py +++ b/src/engine/SCons/Tool/xgettext.py @@ -70,7 +70,7 @@ class _CmdRunner(object): self.out, self.err = proc.communicate() self.status = proc.wait() if self.err: - sys.stderr.write(SCons.Util.UnicodeType(self.err)) + sys.stderr.write(str(self.err)) return self.status def strfunction(self, target, source, env): diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index d930dde..8ff7b4f 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -39,18 +39,8 @@ PY3 = sys.version_info[0] == 3 PYPY = hasattr(sys, 'pypy_translation_info') -try: - from collections import UserDict, UserList, UserString -except ImportError: - from UserDict import UserDict - from UserList import UserList - from UserString import UserString - -try: - from collections.abc import Iterable, MappingView -except ImportError: - from collections import Iterable - +from collections import UserDict, UserList, UserString +from collections.abc import Iterable, MappingView from collections import OrderedDict # Don't "from types import ..." these because we need to get at the @@ -62,13 +52,6 @@ from collections import OrderedDict MethodType = types.MethodType FunctionType = types.FunctionType -try: - _ = type(unicode) -except NameError: - UnicodeType = str -else: - UnicodeType = unicode - def dictify(keys, values, result={}): for k, v in zip(keys, values): result[k] = v @@ -210,14 +193,16 @@ def get_environment_var(varstr): else: return None + class DisplayEngine(object): print_it = True + def __call__(self, text, append_newline=1): if not self.print_it: return if append_newline: text = text + '\n' try: - sys.stdout.write(UnicodeType(text)) + sys.stdout.write(str(text)) except IOError: # Stdout might be connected to a pipe that has been closed # by now. The most likely reason for the pipe being closed @@ -1582,7 +1567,7 @@ del __revision__ def to_bytes(s): if s is None: return b'None' - if not PY3 and isinstance(s, UnicodeType): + if not PY3 and isinstance(s, str): # PY2, must encode unicode return bytearray(s, 'utf-8') if isinstance (s, (bytes, bytearray)) or bytes is str: diff --git a/src/engine/SCons/UtilTests.py b/src/engine/SCons/UtilTests.py index e2dd57f..870e79f 100644 --- a/src/engine/SCons/UtilTests.py +++ b/src/engine/SCons/UtilTests.py @@ -37,14 +37,6 @@ import SCons.Errors from SCons.Util import * -try: - eval('unicode') -except NameError: - HasUnicode = False -else: - HasUnicode = True - - class OutBuffer(object): def __init__(self): self.buffer = "" @@ -274,8 +266,7 @@ class UtilTestCase(unittest.TestCase): assert not is_Dict([]) assert not is_Dict(()) assert not is_Dict("") - if HasUnicode: - exec ("assert not is_Dict(u'')") + def test_is_List(self): assert is_List([]) @@ -290,13 +281,9 @@ class UtilTestCase(unittest.TestCase): assert not is_List(()) assert not is_List({}) assert not is_List("") - if HasUnicode: - exec ("assert not is_List(u'')") def test_is_String(self): assert is_String("") - if HasUnicode: - exec ("assert is_String(u'')") assert is_String(UserString('')) try: class mystr(str): @@ -321,13 +308,11 @@ class UtilTestCase(unittest.TestCase): assert not is_Tuple([]) assert not is_Tuple({}) assert not is_Tuple("") - if HasUnicode: - exec ("assert not is_Tuple(u'')") def test_to_Bytes(self): """ Test the to_Bytes method""" if not PY3: - self.assertEqual(to_bytes(UnicodeType('Hello')), + self.assertEqual(to_bytes(str('Hello')), bytearray(u'Hello', 'utf-8'), "Check that to_bytes creates byte array when presented with unicode string. PY2 only") @@ -352,18 +337,6 @@ class UtilTestCase(unittest.TestCase): assert to_String(s2) == s2, s2 assert to_String(s2) == 'foo', s2 - if HasUnicode: - s3 = UserString(unicode('bar')) - assert to_String(s3) == s3, s3 - assert to_String(s3) == unicode('bar'), s3 - assert isinstance(to_String(s3), unicode), \ - type(to_String(s3)) - - if HasUnicode: - s4 = unicode('baz') - assert to_String(s4) == unicode('baz'), to_String(s4) - assert isinstance(to_String(s4), unicode), \ - type(to_String(s4)) def test_WhereIs(self): test = TestCmd.TestCmd(workdir='') -- cgit v0.12 From 3b10a27fab8a646c499c38630b1d27d64ae8b1c3 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 9 Jan 2020 16:42:20 -0800 Subject: Remove if PY3 code. --- src/engine/SCons/CacheDir.py | 6 +----- src/engine/SCons/CacheDirTests.py | 6 +----- src/engine/SCons/Tool/suncxx.py | 18 +++++------------- src/engine/SCons/Tool/textfile.py | 12 +++--------- src/engine/SCons/Util.py | 11 ++++------- src/engine/SCons/UtilTests.py | 7 +++---- 6 files changed, 17 insertions(+), 43 deletions(-) diff --git a/src/engine/SCons/CacheDir.py b/src/engine/SCons/CacheDir.py index 10c088d..9bb7ef3 100644 --- a/src/engine/SCons/CacheDir.py +++ b/src/engine/SCons/CacheDir.py @@ -36,7 +36,6 @@ import sys import SCons import SCons.Action import SCons.Warnings -from SCons.Util import PY3 cache_enabled = True cache_debug = False @@ -160,10 +159,7 @@ class CacheDir(object): if path is None: return - if PY3: - self._readconfig3(path) - else: - self._readconfig2(path) + self._readconfig3(path) def _readconfig3(self, path): diff --git a/src/engine/SCons/CacheDirTests.py b/src/engine/SCons/CacheDirTests.py index 0e242c4..ff22d01 100644 --- a/src/engine/SCons/CacheDirTests.py +++ b/src/engine/SCons/CacheDirTests.py @@ -33,7 +33,6 @@ import stat from TestCmd import TestCmd import SCons.CacheDir -from SCons.Util import PY3 built_it = None @@ -169,10 +168,7 @@ class ExceptionTestCase(unittest.TestCase): os.remove(old_config) try: - if PY3: - self._CacheDir._readconfig3(self._CacheDir.path) - else: - self._CacheDir._readconfig2(self._CacheDir.path) + self._CacheDir._readconfig3(self._CacheDir.path) assert False, "Should have raised exception and did not" except SCons.Errors.SConsEnvironmentError as e: assert str(e) == "Failed to write cache configuration for {}".format(self._CacheDir.path) diff --git a/src/engine/SCons/Tool/suncxx.py b/src/engine/SCons/Tool/suncxx.py index c155484..1c35612 100644 --- a/src/engine/SCons/Tool/suncxx.py +++ b/src/engine/SCons/Tool/suncxx.py @@ -39,7 +39,6 @@ import os import re import subprocess -from SCons.Util import PY3 import SCons.Tool.cxx cplusplus = SCons.Tool.cxx # cplusplus = __import__('c++', globals(), locals(), []) @@ -53,10 +52,7 @@ def get_package_info(package_name, pkginfo, pkgchk): except KeyError: version = None pathname = None - try: - from subprocess import DEVNULL # py3k - except ImportError: - DEVNULL = open(os.devnull, 'wb') + from subprocess import DEVNULL try: with open('/var/sadm/install/contents', 'r') as f: @@ -72,16 +68,14 @@ def get_package_info(package_name, pkginfo, pkgchk): try: popen_args = {'stdout': subprocess.PIPE, 'stderr': DEVNULL} - if PY3: - popen_args['universal_newlines'] = True + popen_args['universal_newlines'] = True p = subprocess.Popen([pkginfo, '-l', package_name], **popen_args) except EnvironmentError: pass else: pkginfo_contents = p.communicate()[0] - if not PY3: - pkginfo_contents.decode() + pkginfo_contents.decode() version_re = re.compile(r'^ *VERSION:\s*(.*)$', re.M) version_match = version_re.search(pkginfo_contents) if version_match: @@ -91,16 +85,14 @@ def get_package_info(package_name, pkginfo, pkgchk): try: popen_args = {'stdout': subprocess.PIPE, 'stderr': DEVNULL} - if PY3: - popen_args['universal_newlines'] = True + popen_args['universal_newlines'] = True p = subprocess.Popen([pkgchk, '-l', package_name], **popen_args) except EnvironmentError: pass else: pkgchk_contents = p.communicate()[0] - if not PY3: - pkgchk_contents.decode() + pkgchk_contents.decode() pathname_re = re.compile(r'^Pathname:\s*(.*/bin/CC)$', re.M) pathname_match = pathname_re.search(pkgchk_contents) if pathname_match: diff --git a/src/engine/SCons/Tool/textfile.py b/src/engine/SCons/Tool/textfile.py index 9e2327a..48a2904 100644 --- a/src/engine/SCons/Tool/textfile.py +++ b/src/engine/SCons/Tool/textfile.py @@ -53,13 +53,10 @@ import re from SCons.Node import Node from SCons.Node.Python import Value -from SCons.Util import is_String, is_Sequence, is_Dict, to_bytes, PY3 +from SCons.Util import is_String, is_Sequence, is_Dict, to_bytes -if PY3: - TEXTFILE_FILE_WRITE_MODE = 'w' -else: - TEXTFILE_FILE_WRITE_MODE = 'wb' +TEXTFILE_FILE_WRITE_MODE = 'w' LINESEP = '\n' @@ -126,10 +123,7 @@ def _action(target, source, env): # write the file try: - if SCons.Util.PY3: - target_file = open(target[0].get_path(), TEXTFILE_FILE_WRITE_MODE, newline='') - else: - target_file = open(target[0].get_path(), TEXTFILE_FILE_WRITE_MODE) + target_file = open(target[0].get_path(), TEXTFILE_FILE_WRITE_MODE, newline='') except (OSError, IOError): raise SCons.Errors.UserError("Can't write target file %s" % target[0]) diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index 8ff7b4f..130cc5e 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -1567,11 +1567,8 @@ del __revision__ def to_bytes(s): if s is None: return b'None' - if not PY3 and isinstance(s, str): - # PY2, must encode unicode - return bytearray(s, 'utf-8') - if isinstance (s, (bytes, bytearray)) or bytes is str: - # Above case not covered here as py2 bytes and strings are the same + if isinstance(s, (bytes, bytearray)): + # if already bytes return. return s return bytes(s, 'utf-8') @@ -1579,9 +1576,9 @@ def to_bytes(s): def to_str(s): if s is None: return 'None' - if bytes is str or is_String(s): + if is_String(s): return s - return str (s, 'utf-8') + return str(s, 'utf-8') def cmp(a, b): diff --git a/src/engine/SCons/UtilTests.py b/src/engine/SCons/UtilTests.py index 870e79f..3e700c9 100644 --- a/src/engine/SCons/UtilTests.py +++ b/src/engine/SCons/UtilTests.py @@ -311,10 +311,9 @@ class UtilTestCase(unittest.TestCase): def test_to_Bytes(self): """ Test the to_Bytes method""" - if not PY3: - self.assertEqual(to_bytes(str('Hello')), - bytearray(u'Hello', 'utf-8'), - "Check that to_bytes creates byte array when presented with unicode string. PY2 only") + self.assertEqual(to_bytes(str('Hello')), + bytearray(u'Hello', 'utf-8'), + "Check that to_bytes creates byte array when presented with unicode string.") def test_to_String(self): """Test the to_String() method.""" -- cgit v0.12 From ef41a6e48ba1f29daf762e5a8624a6b44fe97fa8 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 9 Jan 2020 17:00:52 -0800 Subject: Resolve mwichmann's commments on PR removing extraneous code --- src/engine/SCons/Taskmaster.py | 2 +- src/engine/SCons/UtilTests.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/engine/SCons/Taskmaster.py b/src/engine/SCons/Taskmaster.py index 7363915..1e5776c 100644 --- a/src/engine/SCons/Taskmaster.py +++ b/src/engine/SCons/Taskmaster.py @@ -792,7 +792,7 @@ class Taskmaster(object): self.ready_exc = None T = self.trace - if T: T.write(str('\n') + self.trace_message('Looking for a node to evaluate')) + if T: T.write('\n' + self.trace_message('Looking for a node to evaluate')) while True: node = self.next_candidate() diff --git a/src/engine/SCons/UtilTests.py b/src/engine/SCons/UtilTests.py index 3e700c9..ee07e61 100644 --- a/src/engine/SCons/UtilTests.py +++ b/src/engine/SCons/UtilTests.py @@ -311,8 +311,8 @@ class UtilTestCase(unittest.TestCase): def test_to_Bytes(self): """ Test the to_Bytes method""" - self.assertEqual(to_bytes(str('Hello')), - bytearray(u'Hello', 'utf-8'), + self.assertEqual(to_bytes('Hello'), + bytearray('Hello', 'utf-8'), "Check that to_bytes creates byte array when presented with unicode string.") def test_to_String(self): -- cgit v0.12 From 589b0a4a29353df1d1fe4177eae578fc6754f7ac Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Fri, 10 Jan 2020 10:26:46 -0500 Subject: Update and improve tests This change integrates various review feedback, including: 1. Validates the result of Dir.get_contents() in PythonTests.py. 2. Adds a functional test for having value as a dependency. --- src/engine/SCons/Node/PythonTests.py | 3 +- test/CacheDir/value.py | 47 -------------------------- test/CacheDir/value_dependencies.py | 52 +++++++++++++++++++++++++++++ test/CacheDir/value_dependencies/SConstruct | 30 +++++++++++++++++ test/CacheDir/value_dependencies/testfile | 0 test/fixture/cachedir_foo_value/SConstruct | 19 ----------- test/fixture/cachedir_foo_value/foo.c | 1 - 7 files changed, 84 insertions(+), 68 deletions(-) delete mode 100644 test/CacheDir/value.py create mode 100644 test/CacheDir/value_dependencies.py create mode 100644 test/CacheDir/value_dependencies/SConstruct create mode 100644 test/CacheDir/value_dependencies/testfile delete mode 100644 test/fixture/cachedir_foo_value/SConstruct delete mode 100644 test/fixture/cachedir_foo_value/foo.c diff --git a/src/engine/SCons/Node/PythonTests.py b/src/engine/SCons/Node/PythonTests.py index 45248d3..da71074 100644 --- a/src/engine/SCons/Node/PythonTests.py +++ b/src/engine/SCons/Node/PythonTests.py @@ -120,7 +120,8 @@ class ValueChildTestCase(unittest.TestCase): node._func_get_contents = 2 # Pretend to be a Dir. node.add_to_implicit([value]) contents = node.get_contents() - assert len(contents) > 0 + expected_contents = '%s %s\n' % (value.get_csig(), value.name) + assert contents == expected_contents class ValueMemoTestCase(unittest.TestCase): diff --git a/test/CacheDir/value.py b/test/CacheDir/value.py deleted file mode 100644 index fd89a9e..0000000 --- a/test/CacheDir/value.py +++ /dev/null @@ -1,47 +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__" - -""" -Verify that bwuilds with caching work for an action with a Value as a child. -""" - -import TestSCons - -test = TestSCons.TestSCons() - -test.dir_fixture('cachedir_foo_value') -test.subdir('cache') - -# First build, populates the cache -test.run(arguments='.') - -test.pass_test() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/CacheDir/value_dependencies.py b/test/CacheDir/value_dependencies.py new file mode 100644 index 0000000..7992bef --- /dev/null +++ b/test/CacheDir/value_dependencies.py @@ -0,0 +1,52 @@ +#!/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 bwuilds with caching work for an action with a Value as a child +in a variety of cases. Specifically: + +1. A source file that depends on a Value. +2. A source directory that depends on a Value. +3. A scanner that returns a Value and a directory that depends on a Value. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.dir_fixture('value_dependencies') +test.subdir('cache') + +# First build, populates the cache +test.run(arguments='.') + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/CacheDir/value_dependencies/SConstruct b/test/CacheDir/value_dependencies/SConstruct new file mode 100644 index 0000000..649648b --- /dev/null +++ b/test/CacheDir/value_dependencies/SConstruct @@ -0,0 +1,30 @@ +import SCons.Node + +CacheDir('cache') + +def b(target, source, env): + with open(target[0].abspath, 'w') as f: + pass + +def scan(node, env, path): + # Have the node depend on a directory, which depends on an instance of + # SCons.Node.Python.Value. + sample_dir = env.fs.Dir('dir2') + env.Depends(sample_dir, env.Value('c')) + return [sample_dir, env.Value('d')] + +scanner = Scanner(function=scan, node_class=SCons.Node.Node) +builder = Builder(action=b, source_scanner=scanner) + +env = Environment() +env.Append(BUILDERS={'B': builder}) + +# Create a node and a directory that each depend on an instance of +# SCons.Node.Python.Value. +sample_dir = env.fs.Dir('dir1') +env.Depends(sample_dir, env.Value('a')) + +sample_file = env.fs.File('testfile') +env.Depends(sample_file, env.Value('b')) + +env.B(target='File1.out', source=[sample_dir, sample_file]) diff --git a/test/CacheDir/value_dependencies/testfile b/test/CacheDir/value_dependencies/testfile new file mode 100644 index 0000000..e69de29 diff --git a/test/fixture/cachedir_foo_value/SConstruct b/test/fixture/cachedir_foo_value/SConstruct deleted file mode 100644 index b144799..0000000 --- a/test/fixture/cachedir_foo_value/SConstruct +++ /dev/null @@ -1,19 +0,0 @@ -import SCons.Node - -CacheDir('cache') - -def b(target, source, env): - with open(target[0].abspath, 'w') as f: - pass - -def scan(node, env, path): - return [env.Value('a')] - -scanner = Scanner(function=scan, node_class=SCons.Node.Node) -builder = Builder(action=b, source_scanner=scanner) - -env = Environment() -env.Append(BUILDERS={'B': builder}) - -env.B(target='File1.out', source='foo.c') -#env.Program('foo', foo_c) diff --git a/test/fixture/cachedir_foo_value/foo.c b/test/fixture/cachedir_foo_value/foo.c deleted file mode 100644 index 5ab8d0f..0000000 --- a/test/fixture/cachedir_foo_value/foo.c +++ /dev/null @@ -1 +0,0 @@ -int main(void){ return 0; } -- cgit v0.12 From 5c708ef1fbc6767582ccb71f2dffc28e6efd11c8 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 10 Jan 2020 07:49:48 -0700 Subject: Clean up some manpage duplication, File, Dir Removed some dupes in the Construction Variables section - the JAR entries plus File, Dir. Tweaked the File and Dir function entries, and the File and Directory Nodes section. The end-to-end tests for File and Dir didn't test the case of supplying a list-of-strings (thus returning a list-of-nodes) to those two functions, added a primitive one. Signed-off-by: Mats Wichmann --- doc/man/scons.xml | 145 ++++++++++++++++-------------------- src/engine/SCons/Environment.xml | 46 +++++------- src/engine/SCons/Tool/packaging.xml | 66 +--------------- test/Dir/Dir.py | 18 +++-- test/File.py | 14 +++- 5 files changed, 107 insertions(+), 182 deletions(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index bd8d5f0..289d840 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -4383,20 +4383,17 @@ vars.AddVariables( -File and Directory Nodes + +File and Directory Nodes -The -File() -and -Dir() -functions return -File -and -Dir -Nodes, respectively. -Python objects, respectively. -Those objects have several user-visible attributes -and methods that are often useful: + +The &f-link-File; and &f-link-Dir; +functions/methods return +File and Directory Nodes, respectively. +Such nodes are Python objects with +several user-visible attributes +and methods that are often useful to access +in SConscript files: @@ -4412,33 +4409,31 @@ file is found). The build path is the same as the source path if variant_dir is not being used. - + abspath The absolute build path of the given file or directory. - + srcnode() The srcnode() method -returns another -File -or -Dir -object representing the -source -path of the given -File -or -Dir. -The +returns another File or Directory Node +representing the source path of the given +File or Directory Node. + + + + + +For example: # Get the current build dir's path, relative to top. @@ -4451,98 +4446,90 @@ File('foo.c').srcnode().path # source path of the given source file. # Builders also return File objects: foo = env.Program('foo.c') -print("foo will be built in %s"%foo.path) +print("foo will be built in", foo.path) -A -Dir -Node or -File -Node can also be used to create -file and subdirectory Nodes relative to the generating Node. -A -Dir -Node will place the new Nodes within the directory it represents. -A -File -node will place the new Nodes within its parent directory -(that is, "beside" the file in question). -If -d -is a -Dir -(directory) Node and -f -is a -File -(file) Node, -then these methods are available: + +Node objects have methods to create +File and Directory Nodes relative to the orignal Node. + + + +If the object is a Directory Node, +these methods will place the the new Node within the directory +the Node represents: + - - - - d.Dir(name) + d.Dir(name) Returns a directory Node for a subdirectory of -d +d named -name. - +name. + - d.File(name) + d.File(name) Returns a file Node for a file within -d +d named -name. - +name. + - d.Entry(name) + d.Entry(name) Returns an unresolved Node within -d +d named -name. - +name. + + + +If the object is a File Node, +these methods will place the the new Node in the same +directory as the one the Node represents: + + + - f.Dir(name) + d.Dir(name) Returns a directory named -name +name within the parent directory of -f. - +f. + - f.File(name) + d.File(name) Returns a file named -name +name within the parent directory of -f. - +f. + - f.Entry(name) + d.Entry(name) Returns an unresolved Node named -name +name within the parent directory of -f. - +f. + For example: @@ -5923,7 +5910,7 @@ action='$CC -c -o $TARGET $SOURCES' cc -c -o foo foo.c bar.c -Variable names may be surrounded by curly braces +Variable names may be surrounded by curly braces { } to separate the name from surrounding characters which are not part of the name. @@ -7200,7 +7187,7 @@ in addition to those passed on the command line. (Windows only). If set, save the shell environment variables generated when setting up the Microsoft Visual C++ compiler -(and/or Build Tools) to a file to give these settings, +(and/or Build Tools) to a file to give these settings, which are expensive to generate, persistence across &scons; invocations. Use of this option is primarily intended to aid performance diff --git a/src/engine/SCons/Environment.xml b/src/engine/SCons/Environment.xml index 35e4bd8..286e882 100644 --- a/src/engine/SCons/Environment.xml +++ b/src/engine/SCons/Environment.xml @@ -65,15 +65,6 @@ env['BUILDERS']['NewBuilder'] = foo - - - -A function that converts a string -into a Dir instance relative to the target being built. - - - - @@ -130,15 +121,6 @@ env = Environment(ENV = {'PATH' : os.environ['PATH']}) - - - -A function that converts a string into a File instance relative to the -target being built. - - - - @@ -1351,11 +1333,10 @@ cc_values = env.Dictionary('CC', 'CCFLAGS', 'CCCOM') -This returns a Directory Node, -an object that represents the specified directory -name. +Returns Directory Node(s). +A Directory Node is an object that represents a directory. name -can be a relative or absolute path. +can be a relative or absolute path or a list of such paths. directory is an optional directory that will be used as the parent directory. If no @@ -1366,7 +1347,10 @@ is specified, the current script's directory is used as the parent. If name -is a list, SCons returns a list of Dir nodes. +is a single pathname, the corresponding node is returned. +If +name +is a list, SCons returns a list of nodes. Construction variables are expanded in name. @@ -1511,20 +1495,24 @@ if Execute("mkdir sub/dir/ectory"): -This returns a -File Node, -an object that represents the specified file -name. +Returns File Node(s). +A File Node is an object that represents a file. name -can be a relative or absolute path. +can be a relative or absolute path or a list of such paths. directory is an optional directory that will be used as the parent directory. +If no +directory +is specified, the current script's directory is used as the parent. If name -is a list, SCons returns a list of File nodes. +is a single pathname, the corresponding node is returned. +If +name +is a list, SCons returns a list of nodes. Construction variables are expanded in name. diff --git a/src/engine/SCons/Tool/packaging.xml b/src/engine/SCons/Tool/packaging.xml index 8ab4912..55fecec 100644 --- a/src/engine/SCons/Tool/packaging.xml +++ b/src/engine/SCons/Tool/packaging.xml @@ -34,7 +34,7 @@ A framework for building binary and source packages. -Builds a Binary Package of the given source files. +Builds a Binary Package of the given source files. @@ -43,68 +43,4 @@ env.Package(source = FindInstalledFiles()) - - - -The Java archive tool. - - - - - - - -The directory to which the Java archive tool should change -(using the - -option). - - - - - - - -The command line used to call the Java archive tool. - - - - - - - -The string displayed when the Java archive tool -is called -If this is not set, then &cv-JARCOM; (the command line) is displayed. - - - -env = Environment(JARCOMSTR = "JARchiving $SOURCES into $TARGET") - - - - - - - -General options passed to the Java archive tool. -By default this is set to - -to create the necessary -jar -file. - - - - - - - -The suffix for Java archives: -.jar -by default. - - - - diff --git a/test/Dir/Dir.py b/test/Dir/Dir.py index e726b94..42a48f3 100644 --- a/test/Dir/Dir.py +++ b/test/Dir/Dir.py @@ -36,28 +36,34 @@ test = TestSCons.TestSCons() test.write('SConstruct', """ DefaultEnvironment(tools=[]) -env = Environment(tools=[], FOO = 'fff', BAR = 'bbb') +env = Environment(tools=[], FOO='fff', BAR='bbb') print(Dir('ddd')) print(Dir('$FOO')) print(Dir('${BAR}_$BAR')) +rv = Dir(['mmm', 'nnn']) +rv_msg = [node.path for node in rv] +print(rv_msg) print(env.Dir('eee')) print(env.Dir('$FOO')) print(env.Dir('${BAR}_$BAR')) +rv = env.Dir(['ooo', 'ppp']) +rv_msg = [node.path for node in rv] +print(rv_msg) """) -test.run(stdout = test.wrap_stdout(read_str = """\ +test.run(stdout=test.wrap_stdout(read_str="""\ ddd $FOO ${BAR}_$BAR +['mmm', 'nnn'] eee fff bbb_bbb -""", build_str = """\ +['ooo', 'ppp'] +""", build_str="""\ scons: `.' is up to date. """)) - - test.write('SConstruct', """\ DefaultEnvironment(tools=[]) import os @@ -66,7 +72,7 @@ def my_mkdir(target=None, source=None, env=None): MDBuilder = Builder(action=my_mkdir, target_factory=Dir) env = Environment(tools=[]) -env.Append(BUILDERS = {'MD':MDBuilder}) +env.Append(BUILDERS={'MD': MDBuilder}) env.MD(target='sub1', source=['SConstruct']) env.MD(target='sub2', source=['SConstruct'], OVERRIDE='foo') """) diff --git a/test/File.py b/test/File.py index ec148b2..bde4449 100644 --- a/test/File.py +++ b/test/File.py @@ -37,13 +37,19 @@ import TestSCons test = TestSCons.TestSCons() test.write('SConstruct', """ -env = Environment(FOO = 'fff', BAR = 'bbb') +env = Environment(FOO='fff', BAR='bbb') print(File('ddd')) print(File('$FOO')) print(File('${BAR}_$BAR')) +rv = File(['mmm', 'nnn']) +rv_msg = [node.path for node in rv] +print(rv_msg) print(env.File('eee')) print(env.File('$FOO')) print(env.File('${BAR}_$BAR')) +rv = env.File(['ooo', 'ppp']) +rv_msg = [node.path for node in rv] +print(rv_msg) f1 = env.File('f1') print(f1) f2 = f1.File('f2') @@ -54,16 +60,18 @@ expect = test.wrap_stdout(read_str = """\ ddd $FOO ${BAR}_$BAR +['mmm', 'nnn'] eee fff bbb_bbb +['ooo', 'ppp'] f1 f2 -""", build_str = """\ +""", build_str="""\ scons: `.' is up to date. """) -test.run(stdout = expect) +test.run(stdout=expect) test.pass_test() -- cgit v0.12 From 16a7153d8564fe9f14bac7e6ec4136dbbef6df5a Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Fri, 10 Jan 2020 12:49:12 -0500 Subject: Add a Tool that hooks up the python scanner --- src/engine/SCons/Tool/__init__.py | 2 ++ src/engine/SCons/Tool/python.py | 49 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 src/engine/SCons/Tool/python.py diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py index 14306ab..99a958c 100644 --- a/src/engine/SCons/Tool/__init__.py +++ b/src/engine/SCons/Tool/__init__.py @@ -1312,6 +1312,8 @@ def tool_list(platform, env): 'tar', 'zip', # File builders (text) 'textfile', + # Python scanner tool + 'python', ], env) tools = ([linker, c_compiler, cxx_compiler, diff --git a/src/engine/SCons/Tool/python.py b/src/engine/SCons/Tool/python.py new file mode 100644 index 0000000..c61fc8d --- /dev/null +++ b/src/engine/SCons/Tool/python.py @@ -0,0 +1,49 @@ +"""SCons.Tool.python + +Registers the Python scanner for the supported Python source file suffixes. + +""" + +# +# __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.Tool +from SCons.Scanner.Python import PythonScanner, PythonSuffixes + + +def generate(env): + """Hook the python builder and scanner into the environment.""" + for suffix in PythonSuffixes: + SCons.Tool.SourceFileScanner.add_scanner(suffix, PythonScanner) + + +def exists(env): + return True + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: -- cgit v0.12 From 3247b7e825c78eae110651d363d0bfd36d0e1081 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Wed, 23 Jan 2019 18:26:46 -0700 Subject: Align way TeX and related tool names reported by tests Two concrete changes: DVIPS/DVIPS test ran only if dvips tool is found, but did not leave any message if not. Print a skip message if tool not found, which also lets us dedent the rest of the test for the case where we continue due to having found it. TEX/variant_dir test did not check for dvipdf tool, but then calls the tool. Add a check so we get a skip message instead of a fail (the fail had lots of lines but it hard to see actual reason). Fix one test which failed for me due to not checking for its tool. For the rest, align "Could not find" messages to quote the tool name, which most of the tests do - so this is just stylistic, has no functional effect. Also stylistic: use any/all for checking multiple tools' existence. Signed-off-by: Mats Wichmann --- test/DVIPDF/makeindex.py | 6 ++-- test/DVIPS/DVIPS.py | 40 +++++++++++------------ test/TEX/TEX.py | 2 +- test/TEX/auxiliaries.py | 4 +-- test/TEX/bibliography.py | 6 ++-- test/TEX/bibtex-latex-rerun.py | 2 +- test/TEX/clean.py | 2 +- test/TEX/configure.py | 4 +-- test/TEX/dryrun.py | 2 +- test/TEX/glossaries.py | 2 +- test/TEX/glossary.py | 2 +- test/TEX/lstinputlisting.py | 2 +- test/TEX/makeindex.py | 4 +-- test/TEX/multi-line_include_options.py | 2 +- test/TEX/multi-run.py | 7 ++-- test/TEX/newglossary.py | 2 +- test/TEX/nomencl.py | 2 +- test/TEX/recursive_scanner_dependencies_import.py | 2 +- test/TEX/recursive_scanner_dependencies_input.py | 2 +- test/TEX/rename_result.py | 2 +- test/TEX/synctex.py | 2 +- test/TEX/usepackage.py | 2 +- test/TEX/variant_dir.py | 5 +-- test/TEX/variant_dir_bibunit.py | 4 +-- test/TEX/variant_dir_dup0.py | 4 +-- test/TEX/variant_dir_newglossary.py | 2 +- test/TEX/variant_dir_style_dup0.py | 4 +-- 27 files changed, 59 insertions(+), 61 deletions(-) diff --git a/test/DVIPDF/makeindex.py b/test/DVIPDF/makeindex.py index b4ac2d0..bb44d27 100644 --- a/test/DVIPDF/makeindex.py +++ b/test/DVIPDF/makeindex.py @@ -32,15 +32,15 @@ test = TestSCons.TestSCons() dvipdf = test.where_is('dvipdf') if not dvipdf: - test.skip_test('Could not find dvipdf; skipping test(s).\n') + test.skip_test("Could not find 'dvipdf'; skipping test(s).\n") tex = test.where_is('tex') if not tex: - test.skip_test('Could not find tex; skipping test(s).\n') + test.skip_test("Could not find 'tex'; skipping test(s).\n") latex = test.where_is('latex') if not latex: - test.skip_test('Could not find latex; skipping test(s).\n') + test.skip_test("Could not find 'latex'; skipping test(s).\n") diff --git a/test/DVIPS/DVIPS.py b/test/DVIPS/DVIPS.py index 27e89ba..df7811a 100644 --- a/test/DVIPS/DVIPS.py +++ b/test/DVIPS/DVIPS.py @@ -116,13 +116,13 @@ test.must_match('test4.ps', "This is a .latex test.\n", mode='r') have_latex = test.where_is('latex') if not have_latex: - test.skip_test('Could not find latex; skipping test(s).\n') + test.skip_test("Could not find 'latex'; skipping test(s).\n") dvips = test.where_is('dvips') +if not dvips: + test.skip_test("Could not find 'dvips'; skipping test(s).\n") -if dvips: - - test.write("wrapper.py", """ +test.write("wrapper.py", """ import os import sys cmd = " ".join(sys.argv[1:]) @@ -130,7 +130,7 @@ open('%s', 'a').write("%%s\\n" %% cmd) os.system(cmd) """ % test.workpath('wrapper.out').replace('\\', '\\\\')) - test.write('SConstruct', """ +test.write('SConstruct', """ import os ENV = { 'PATH' : os.environ['PATH'] } foo = Environment(ENV = ENV) @@ -142,41 +142,41 @@ bar.PostScript(target = 'bar2', source = 'bar2.ltx') bar.PostScript(target = 'bar3', source = 'bar3.latex') """ % locals()) - tex = r""" +tex = r""" This is the %s TeX file. \end """ - latex = r""" +latex = r""" \documentclass{letter} \begin{document} This is the %s LaTeX file. \end{document} """ - test.write('foo.tex', tex % 'foo.tex') - test.write('bar1.tex', tex % 'bar1.tex') - test.write('bar2.ltx', latex % 'bar2.ltx') - test.write('bar3.latex', latex % 'bar3.latex') +test.write('foo.tex', tex % 'foo.tex') +test.write('bar1.tex', tex % 'bar1.tex') +test.write('bar2.ltx', latex % 'bar2.ltx') +test.write('bar3.latex', latex % 'bar3.latex') - test.run(arguments = 'foo.dvi', stderr = None) +test.run(arguments = 'foo.dvi', stderr = None) - test.must_not_exist(test.workpath('wrapper.out')) +test.must_not_exist(test.workpath('wrapper.out')) - test.must_exist(test.workpath('foo.dvi')) +test.must_exist(test.workpath('foo.dvi')) - test.run(arguments = 'bar1.ps bar2.ps bar3.ps', stderr = None) +test.run(arguments = 'bar1.ps bar2.ps bar3.ps', stderr = None) - expect = """dvips -o bar1.ps bar1.dvi +expect = """dvips -o bar1.ps bar1.dvi dvips -o bar2.ps bar2.dvi dvips -o bar3.ps bar3.dvi """ - test.must_match('wrapper.out', expect, mode='r') +test.must_match('wrapper.out', expect, mode='r') - test.must_exist(test.workpath('bar1.ps')) - test.must_exist(test.workpath('bar2.ps')) - test.must_exist(test.workpath('bar3.ps')) +test.must_exist(test.workpath('bar1.ps')) +test.must_exist(test.workpath('bar2.ps')) +test.must_exist(test.workpath('bar3.ps')) test.pass_test() diff --git a/test/TEX/TEX.py b/test/TEX/TEX.py index 3964eb8..f0d4043 100644 --- a/test/TEX/TEX.py +++ b/test/TEX/TEX.py @@ -38,7 +38,7 @@ test = TestSCons.TestSCons() have_latex = test.where_is('latex') if not have_latex: - test.skip_test('Could not find latex; skipping test(s).\n') + test.skip_test("Could not find 'latex'; skipping test(s).\n") test.write('mytex.py', r""" diff --git a/test/TEX/auxiliaries.py b/test/TEX/auxiliaries.py index e28c212..1e37e7a 100644 --- a/test/TEX/auxiliaries.py +++ b/test/TEX/auxiliaries.py @@ -45,8 +45,8 @@ test = TestSCons.TestSCons() dvips = test.where_is('dvips') latex = test.where_is('latex') -if not dvips or not latex: - test.skip_test("Could not find dvips or latex; skipping test(s).\n") +if not all((dvips, latex)): + test.skip_test("Could not find 'dvips' and/or 'latex'; skipping test(s).\n") test.subdir(['docs']) diff --git a/test/TEX/bibliography.py b/test/TEX/bibliography.py index a8032db..afccf8f 100644 --- a/test/TEX/bibliography.py +++ b/test/TEX/bibliography.py @@ -38,15 +38,15 @@ test = TestSCons.TestSCons() dvips = test.where_is('dvips') if not dvips: - test.skip_test("Could not find dvips; skipping test(s).\n") + test.skip_test("Could not find 'dvips'; skipping test(s).\n") bibtex = test.where_is('bibtex') if not bibtex: - test.skip_test("Could not find bibtex; skipping test(s).\n") + test.skip_test("Could not find 'bibtex'; skipping test(s).\n") have_latex = test.where_is('latex') if not have_latex: - test.skip_test('Could not find latex; skipping test(s).\n') + test.skip_test("Could not find 'latex'; skipping test(s).\n") test.write('SConstruct', """\ diff --git a/test/TEX/bibtex-latex-rerun.py b/test/TEX/bibtex-latex-rerun.py index 300f03b..f0f8c34 100644 --- a/test/TEX/bibtex-latex-rerun.py +++ b/test/TEX/bibtex-latex-rerun.py @@ -39,7 +39,7 @@ test = TestSCons.TestSCons() pdflatex = test.where_is('pdflatex') if not pdflatex: - test.skip_test("Could not find pdflatex; skipping test(s).\n") + test.skip_test("Could not find 'pdflatex'; skipping test(s).\n") test.write(['SConstruct'], """\ import os diff --git a/test/TEX/clean.py b/test/TEX/clean.py index ad828d2..781caa1 100644 --- a/test/TEX/clean.py +++ b/test/TEX/clean.py @@ -36,7 +36,7 @@ test = TestSCons.TestSCons() latex = test.where_is('latex') if not latex: - test.skip_test("Could not find tex or latex; skipping test(s).\n") + test.skip_test("Could not find 'latex'; skipping test(s).\n") comment = os.system('kpsewhich comment.sty') if not comment==0: diff --git a/test/TEX/configure.py b/test/TEX/configure.py index 763f86f..9fb4b3e 100644 --- a/test/TEX/configure.py +++ b/test/TEX/configure.py @@ -40,8 +40,8 @@ test = TestSCons.TestSCons() dvips = test.where_is('dvips') latex = test.where_is('latex') -if not dvips or not latex: - test.skip_test("Could not find dvips or latex; skipping test(s).\n") +if not all((dvips, latex)): + test.skip_test("Could not find 'dvips' and/or 'latex'; skipping test(s).\n") NCR = test.NCR # non-cached rebuild diff --git a/test/TEX/dryrun.py b/test/TEX/dryrun.py index 4265791..90357fc 100644 --- a/test/TEX/dryrun.py +++ b/test/TEX/dryrun.py @@ -39,7 +39,7 @@ test = TestSCons.TestSCons() latex = test.where_is('latex') if not latex: - test.skip_test('could not find latex; skipping test\n') + test.skip_test("could not find 'latex'; skipping test\n") test.write('SConstruct', """ import os diff --git a/test/TEX/glossaries.py b/test/TEX/glossaries.py index 21180a0..cbb6964 100644 --- a/test/TEX/glossaries.py +++ b/test/TEX/glossaries.py @@ -39,7 +39,7 @@ test = TestSCons.TestSCons() latex = test.where_is('latex') if not latex: - test.skip_test("Could not find latex; skipping test(s).\n") + test.skip_test("Could not find 'latex'; skipping test(s).\n") gloss = os.system('kpsewhich glossaries.sty') if not gloss==0: diff --git a/test/TEX/glossary.py b/test/TEX/glossary.py index 0becb40..ef13ca1 100644 --- a/test/TEX/glossary.py +++ b/test/TEX/glossary.py @@ -39,7 +39,7 @@ test = TestSCons.TestSCons() latex = test.where_is('latex') if not latex: - test.skip_test("Could not find latex; skipping test(s).\n") + test.skip_test("Could not find 'latex'; skipping test(s).\n") gloss = os.system('kpsewhich glossary.sty') if not gloss==0: diff --git a/test/TEX/lstinputlisting.py b/test/TEX/lstinputlisting.py index 1d60df7..1f5020b 100644 --- a/test/TEX/lstinputlisting.py +++ b/test/TEX/lstinputlisting.py @@ -39,7 +39,7 @@ test = TestSCons.TestSCons() pdflatex = test.where_is('pdflatex') if not pdflatex: - test.skip_test("Could not find pdflatex; skipping test(s).\n") + test.skip_test("Could not find 'pdflatex'; skipping test(s).\n") listings = os.system('kpsewhich listings.sty') if not listings==0: diff --git a/test/TEX/makeindex.py b/test/TEX/makeindex.py index 960ed68..0b81f31 100644 --- a/test/TEX/makeindex.py +++ b/test/TEX/makeindex.py @@ -38,8 +38,8 @@ test = TestSCons.TestSCons() pdflatex = test.where_is('pdflatex') makeindex = test.where_is('makeindex') -if not pdflatex or not makeindex: - test.skip_test("Could not find pdflatex or makeindex; skipping test(s).\n") +if not all((pdflatex, makeindex)): + test.skip_test("Could not find 'pdflatex' and/or 'makeindex'; skipping test(s).\n") test.write('SConstruct', """\ import os diff --git a/test/TEX/multi-line_include_options.py b/test/TEX/multi-line_include_options.py index bb8a5f2..94466b6 100644 --- a/test/TEX/multi-line_include_options.py +++ b/test/TEX/multi-line_include_options.py @@ -44,7 +44,7 @@ test = TestSCons.TestSCons() latex = test.where_is('latex') if not latex: - test.skip_test("Could not find latex; skipping test(s).\n") + test.skip_test("Could not find 'latex'; skipping test(s).\n") test.write('SConstruct', """\ import os diff --git a/test/TEX/multi-run.py b/test/TEX/multi-run.py index 9de0da4..3c4e901 100644 --- a/test/TEX/multi-run.py +++ b/test/TEX/multi-run.py @@ -38,11 +38,8 @@ test = TestSCons.TestSCons() tex = test.where_is('tex') latex = test.where_is('latex') - -if not latex: - test.skip_test("Could not find latex; skipping test(s).\n") -if not tex and not latex: - test.skip_test("Could not find tex or latex; skipping test(s).\n") +if not all((tex, latex)): + test.skip_test("Could not find 'tex' and/or 'latex'; skipping test(s).\n") test.subdir('work1', 'work2', 'work3', 'work4') diff --git a/test/TEX/newglossary.py b/test/TEX/newglossary.py index faae7d3..5d868a8 100644 --- a/test/TEX/newglossary.py +++ b/test/TEX/newglossary.py @@ -39,7 +39,7 @@ test = TestSCons.TestSCons() latex = test.where_is('latex') if not latex: - test.skip_test("Could not find latex; skipping test(s).\n") + test.skip_test("Could not find 'latex'; skipping test(s).\n") gloss = os.system('kpsewhich glossaries.sty') if not gloss==0: diff --git a/test/TEX/nomencl.py b/test/TEX/nomencl.py index 7afb84b..0eb0b84 100644 --- a/test/TEX/nomencl.py +++ b/test/TEX/nomencl.py @@ -39,7 +39,7 @@ test = TestSCons.TestSCons() latex = test.where_is('latex') if not latex: - test.skip_test("Could not find latex; skipping test(s).\n") + test.skip_test("Could not find 'latex'; skipping test(s).\n") nomencl = os.system('kpsewhich nomencl.sty') if not nomencl==0: diff --git a/test/TEX/recursive_scanner_dependencies_import.py b/test/TEX/recursive_scanner_dependencies_import.py index c8c6569..a7b5e4a 100644 --- a/test/TEX/recursive_scanner_dependencies_import.py +++ b/test/TEX/recursive_scanner_dependencies_import.py @@ -42,7 +42,7 @@ test = TestSCons.TestSCons() pdflatex = test.where_is('pdflatex') if not pdflatex: - test.skip_test("Could not find pdflatex; skipping test(s).\n") + test.skip_test("Could not find 'pdflatex'; skipping test(s).\n") latex_import = os.system('kpsewhich import.sty') if latex_import != 0: diff --git a/test/TEX/recursive_scanner_dependencies_input.py b/test/TEX/recursive_scanner_dependencies_input.py index 5f37bf1..5afcbc2 100644 --- a/test/TEX/recursive_scanner_dependencies_input.py +++ b/test/TEX/recursive_scanner_dependencies_input.py @@ -36,7 +36,7 @@ test = TestSCons.TestSCons() pdflatex = test.where_is('pdflatex') if not pdflatex: - test.skip_test("Could not find pdflatex; skipping test(s).\n") + test.skip_test("Could not find 'pdflatex'; skipping test(s).\n") test.write(['SConstruct'], """\ env = Environment(tools=['pdftex', 'tex']) diff --git a/test/TEX/rename_result.py b/test/TEX/rename_result.py index b06d388..f67e569 100644 --- a/test/TEX/rename_result.py +++ b/test/TEX/rename_result.py @@ -38,7 +38,7 @@ test = TestSCons.TestSCons() latex = test.where_is('latex') if not latex: - test.skip_test('could not find latex; skipping test\n') + test.skip_test("could not find 'latex'; skipping test\n") test.write('SConstruct', """ import os diff --git a/test/TEX/synctex.py b/test/TEX/synctex.py index f07db78..385a173 100644 --- a/test/TEX/synctex.py +++ b/test/TEX/synctex.py @@ -39,7 +39,7 @@ test = TestSCons.TestSCons() latex = test.where_is('latex') if not latex: - test.skip_test("Could not find latex; skipping test(s).\n") + test.skip_test("Could not find 'latex'; skipping test(s).\n") test.write('SConstruct', """\ import os diff --git a/test/TEX/usepackage.py b/test/TEX/usepackage.py index 0bb8c22..66510c2 100644 --- a/test/TEX/usepackage.py +++ b/test/TEX/usepackage.py @@ -39,7 +39,7 @@ test = TestSCons.TestSCons() latex = test.where_is('latex') if not latex: - test.skip_test('could not find latex; skipping test\n') + test.skip_test("could not find 'latex'; skipping test\n") test.write('SConstruct', """ import os diff --git a/test/TEX/variant_dir.py b/test/TEX/variant_dir.py index d81f542..9d05863 100644 --- a/test/TEX/variant_dir.py +++ b/test/TEX/variant_dir.py @@ -36,8 +36,9 @@ import TestSCons test = TestSCons.TestSCons() latex = test.where_is('latex') -if not latex: - test.skip_test("Could not find 'latex'; skipping test.\n") +dvipdf = test.where_is('dvipdf') +if not all((latex, dvipdf)): + test.skip_test("Could not find 'latex' and/or 'dvipdf'; skipping test(s).\n") test.subdir(['docs']) diff --git a/test/TEX/variant_dir_bibunit.py b/test/TEX/variant_dir_bibunit.py index cd3409e..e127a76 100644 --- a/test/TEX/variant_dir_bibunit.py +++ b/test/TEX/variant_dir_bibunit.py @@ -41,8 +41,8 @@ test = TestSCons.TestSCons() latex = test.where_is('pdflatex') bibtex = test.where_is('bibtex') -if not latex or not bibtex: - test.skip_test("Could not find 'latex' or 'bibtex'; skipping test.\n") +if not all((latex, bibtex)): + test.skip_test("Could not find 'latex' and/or 'bibtex'; skipping test.\n") bibunits = os.system('kpsewhich bibunits.sty') if not bibunits==0: diff --git a/test/TEX/variant_dir_dup0.py b/test/TEX/variant_dir_dup0.py index 8f4334f..ea6b51e 100644 --- a/test/TEX/variant_dir_dup0.py +++ b/test/TEX/variant_dir_dup0.py @@ -42,8 +42,8 @@ latex = test.where_is('latex') dvipdf = test.where_is('dvipdf') makeindex = test.where_is('makeindex') bibtex = test.where_is('bibtex') -if not latex or not makeindex or not bibtex or not dvipdf: - test.skip_test("Could not find 'latex', 'makeindex', 'bibtex', or dvipdf; skipping test.\n") +if not all((latex, makeindex, bibtex, dvipdf)): + test.skip_test("Could not find one or more of 'latex', 'makeindex', 'bibtex', or 'dvipdf'; skipping test.\n") test.subdir(['docs']) diff --git a/test/TEX/variant_dir_newglossary.py b/test/TEX/variant_dir_newglossary.py index 1e6ab43..5e4d10d 100644 --- a/test/TEX/variant_dir_newglossary.py +++ b/test/TEX/variant_dir_newglossary.py @@ -39,7 +39,7 @@ test = TestSCons.TestSCons() latex = test.where_is('latex') if not latex: - test.skip_test("Could not find latex; skipping test(s).\n") + test.skip_test("Could not find 'latex'; skipping test(s).\n") gloss = os.system('kpsewhich glossaries.sty') if gloss!=0: diff --git a/test/TEX/variant_dir_style_dup0.py b/test/TEX/variant_dir_style_dup0.py index a9649b0..430b792 100644 --- a/test/TEX/variant_dir_style_dup0.py +++ b/test/TEX/variant_dir_style_dup0.py @@ -45,8 +45,8 @@ latex = test.where_is('latex') dvipdf = test.where_is('dvipdf') makeindex = test.where_is('makeindex') bibtex = test.where_is('bibtex') -if not latex or not makeindex or not bibtex or not dvipdf: - test.skip_test("Could not find 'latex', 'makeindex', 'bibtex', or 'dvipdf'; skipping test.\n") +if not all((latex, makeindex, bibtex, dvipdf)): + test.skip_test("Could not find one or more of 'latex', 'makeindex', 'bibtex', or 'dvipdf'; skipping test.\n") test.subdir(['docs']) -- cgit v0.12 From 1ba8e04976c39dc68b17ef0d40f34b423028923e Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 11 Jan 2020 15:57:58 -0800 Subject: [ci skip] minor fixups on PR #3522 --- doc/man/scons.xml | 4 ++-- src/CHANGES.txt | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index 289d840..00df1a7 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -4450,8 +4450,8 @@ print("foo will be built in", foo.path) -Node objects have methods to create -File and Directory Nodes relative to the orignal Node. +File and Directory Node objects have methods to create +File and Directory Nodes relative to the original Node. diff --git a/src/CHANGES.txt b/src/CHANGES.txt index a9417c7..37aead1 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -31,6 +31,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - str.format syntax errors fixed - a bunch of linter/checker syntax fixups - Convert remaining uses of insecure/deprecated mktemp method. + - Clean up some duplications in manpage. Clarify portion of manpage on Dir and File nodes. RELEASE 3.1.2 - Mon, 17 Dec 2019 02:06:27 +0000 -- cgit v0.12 From c45ad100d6b940bce7be57619e3eaf61c43d5a95 Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Mon, 13 Jan 2020 13:57:41 -0500 Subject: [ci skip] Add documentation for the python tool --- src/engine/SCons/Tool/python.xml | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/engine/SCons/Tool/python.xml diff --git a/src/engine/SCons/Tool/python.xml b/src/engine/SCons/Tool/python.xml new file mode 100644 index 0000000..e3f7da3 --- /dev/null +++ b/src/engine/SCons/Tool/python.xml @@ -0,0 +1,36 @@ + + + + +%scons; + +%builders-mod; + +%functions-mod; + +%tools-mod; + +%variables-mod; +]> + + + + + + +Loads the Python scanner scanner into the invoking environment. When loaded, the scanner will +attempt to find implicit dependencies for any Python source files in the list of sources +provided to an actual that uses this environment. + + + + + -- cgit v0.12 From 0ab03698067fe6e6fc0a3e245a0a5d42f20960c6 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 13 Jan 2020 14:36:51 -0800 Subject: [ci skip] add new python tool module to manifest --- src/engine/MANIFEST.in | 1 + 1 file changed, 1 insertion(+) diff --git a/src/engine/MANIFEST.in b/src/engine/MANIFEST.in index 7cd9928..3c2c0c2 100644 --- a/src/engine/MANIFEST.in +++ b/src/engine/MANIFEST.in @@ -141,6 +141,7 @@ SCons/Tool/pdf.py SCons/Tool/pdflatex.py SCons/Tool/pdftex.py SCons/Tool/PharLapCommon.py +SCons/Tool/python.py SCons/Tool/qt.py SCons/Tool/rmic.py SCons/Tool/rpcgen.py -- cgit v0.12 From 44e28045d9a4a0ee64b40ce4b469fd461df885bb Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Tue, 7 Jan 2020 09:36:47 -0700 Subject: docs: refer *COM* and SH*COM* to each other [ci skip] [fixes #2565] Object code intended for use in a shared library may need different compilation options than object code not intended for such use. When SCons tools recognize this need they define parallel sets of variables, such that for FOO there is both FOOCOM and SHFOOCOM, FOOCOMSTR and SHFOOCOMSTR, etc. Refer such pairs to each other. Issue 2565 described a case where a user did not realize they needed to use SHCXXCOMSTR to affect the output for certain C++-compiled objects. The discussion concluded this was just a doc fix. Some examination turned up cases of this in docs for the C compiler, C++ compiler, D compiler, Fortran compiler and linker modules, seemed better to just hit all of those. I would have preferred to move the pairs together into a single entry but it seems the scons doc markup doesn't support this kind of usage - a can take only a single name attribute, and uses it to generate tags, etc. so there would have been a ton of surgery needed to implement that way. Signed-off-by: Mats Wichmann --- doc/generated/variables.mod | 4 ++++ doc/user/output.xml | 13 ++++++++++++- src/engine/SCons/Tool/DCommon.xml | 24 ++++++++++++++++++++++++ src/engine/SCons/Tool/c++.xml | 17 +++++++++++++---- src/engine/SCons/Tool/cc.xml | 22 ++++++++++++++++------ src/engine/SCons/Tool/link.xml | 12 +++++++----- 6 files changed, 76 insertions(+), 16 deletions(-) diff --git a/doc/generated/variables.mod b/doc/generated/variables.mod index ba92aa9..ff44a23 100644 --- a/doc/generated/variables.mod +++ b/doc/generated/variables.mod @@ -65,6 +65,7 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $CXXVERSION"> $DC"> $DCOM"> +$DCOMSTR"> $DDEBUG"> $DDEBUGPREFIX"> $DDEBUGSUFFIX"> @@ -457,6 +458,7 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $SHCXXFLAGS"> $SHDC"> $SHDCOM"> +$SHDCOMSTR"> $SHDLIBVERSION"> $SHDLIBVERSIONFLAGS"> $SHDLINK"> @@ -706,6 +708,7 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $CXXVERSION"> $DC"> $DCOM"> +$DCOMSTR"> $DDEBUG"> $DDEBUGPREFIX"> $DDEBUGSUFFIX"> @@ -1098,6 +1101,7 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $SHCXXFLAGS"> $SHDC"> $SHDCOM"> +$SHDCOMSTR"> $SHDLIBVERSION"> $SHDLIBVERSIONFLAGS"> $SHDLINK"> diff --git a/doc/user/output.xml b/doc/user/output.xml index f9e1a98..d1082a9 100644 --- a/doc/user/output.xml +++ b/doc/user/output.xml @@ -47,7 +47,7 @@ A key aspect of creating a usable build configuration - is providing good output from the build + is providing useful output from the build so its users can readily understand what the build is doing and get information about how to control the build. @@ -355,6 +355,17 @@ cc -o foo.o -c foo.c cc -o foo foo.o + + + A gentle reminder here: many of the commands for building come in + pairs, depending on whether the intent is to build an object for + use in a shared library or not. The command strings mirror this, + so it may be necessary to set, for example, both + CCCOMSTR and SHCCCOMSTR + to get the desired results. + + +
diff --git a/src/engine/SCons/Tool/DCommon.xml b/src/engine/SCons/Tool/DCommon.xml index 7cc47da..6ff08da 100644 --- a/src/engine/SCons/Tool/DCommon.xml +++ b/src/engine/SCons/Tool/DCommon.xml @@ -27,6 +27,7 @@ See its __doc__ string for a discussion of the format. The D compiler to use. +See also &cv-link-SHDC;. @@ -37,6 +38,18 @@ The D compiler to use. The command line used to compile a D file to an object file. Any options specified in the &cv-link-DFLAGS; construction variable is included on this command line. +See also &cv-link-SHDCOM;. + + + + + + + +If set, the string displayed when a D source file +is compiled to a (static) object file. +If not set, then &cv-link-DCOM; (the command line) is displayed. +See also &cv-link-SHDCOMSTR;. @@ -290,6 +303,17 @@ The command line to use when compiling code to be part of shared objects. + + + +If set, the string displayed when a D source file +is compiled to a (shared) object file. +If not set, then &cv-link-SHDCOM; (the command line) is displayed. +See also &cv-link-DCOMSTR;. + + + + diff --git a/src/engine/SCons/Tool/c++.xml b/src/engine/SCons/Tool/c++.xml index b59816b..0918b5f 100644 --- a/src/engine/SCons/Tool/c++.xml +++ b/src/engine/SCons/Tool/c++.xml @@ -47,6 +47,7 @@ Sets construction variables for generic POSIX C++ compilers. CXXCOMSTR +SHCXXCOMSTR @@ -54,6 +55,7 @@ Sets construction variables for generic POSIX C++ compilers. The C++ compiler. +See also &cv-link-SHCXX;. @@ -65,6 +67,7 @@ The command line used to compile a C++ source file to an object file. Any options specified in the &cv-link-CXXFLAGS; and &cv-link-CPPFLAGS; construction variables are included on this command line. +See also &cv-link-SHCXXCOM;. @@ -72,9 +75,10 @@ are included on this command line. -The string displayed when a C++ source file +If set, the string displayed when a C++ source file is compiled to a (static) object file. -If this is not set, then &cv-link-CXXCOM; (the command line) is displayed. +If not set, then &cv-link-CXXCOM; (the command line) is displayed. +See also &cv-link-SHCXXCOMSTR;. @@ -91,6 +95,7 @@ By default, this includes the value of &cv-link-CCFLAGS;, so that setting &cv-CCFLAGS; affects both C and C++ compilation. If you want to add C++-specific flags, you must set or override the value of &cv-link-CXXFLAGS;. +See also &cv-link-SHCXXFLAGS;. @@ -99,6 +104,7 @@ you must set or override the value of &cv-link-CXXFLAGS;. The C++ compiler used for generating shared-library objects. +See also &cv-link-CXX;. @@ -111,6 +117,7 @@ to a shared-library object file. Any options specified in the &cv-link-SHCXXFLAGS; and &cv-link-CPPFLAGS; construction variables are included on this command line. +See also &cv-link-CXXCOM;. @@ -118,9 +125,10 @@ are included on this command line. -The string displayed when a C++ source file +If set, the string displayed when a C++ source file is compiled to a shared object file. -If this is not set, then &cv-link-SHCXXCOM; (the command line) is displayed. +If not set, then &cv-link-SHCXXCOM; (the command line) is displayed. +See also &cv-link-CXXCOMSTR;. @@ -134,6 +142,7 @@ env = Environment(SHCXXCOMSTR = "Compiling shared object $TARGET") Options that are passed to the C++ compiler to generate shared-library objects. +See also &cv-link-CXXFLAGS;. diff --git a/src/engine/SCons/Tool/cc.xml b/src/engine/SCons/Tool/cc.xml index 06e73ff..4150e23 100644 --- a/src/engine/SCons/Tool/cc.xml +++ b/src/engine/SCons/Tool/cc.xml @@ -51,6 +51,8 @@ Sets construction variables for generic POSIX C compilers. PLATFORM +CCCOMSTR +SHCCCOMSTR @@ -67,8 +69,8 @@ The C compiler. The command line used to compile a C source file to a (static) object file. Any options specified in the &cv-link-CFLAGS;, &cv-link-CCFLAGS; and -&cv-link-CPPFLAGS; construction variables are included on this command -line. +&cv-link-CPPFLAGS; construction variables are included on this command line. +See also &cv-link-SHCCCOM;. @@ -76,9 +78,10 @@ line. -The string displayed when a C source file +If set, the string displayed when a C source file is compiled to a (static) object file. -If this is not set, then &cv-link-CCCOM; (the command line) is displayed. +If not set, then &cv-link-CCCOM; (the command line) is displayed. +See also &cv-link-SHCCCOMSTR;. @@ -91,6 +94,7 @@ env = Environment(CCCOMSTR = "Compiling static object $TARGET") General options that are passed to the C and C++ compilers. +See also &cv-link-SHCCFLAGS;. @@ -99,6 +103,7 @@ General options that are passed to the C and C++ compilers. General options that are passed to the C compiler (C only; not C++). +See also &cv-link-SHCFLAGS;. @@ -156,6 +161,7 @@ The default list is: The C compiler used for generating shared-library objects. +See also &cv-link-CC;. @@ -169,6 +175,7 @@ Any options specified in the &cv-link-SHCFLAGS;, &cv-link-SHCCFLAGS; and &cv-link-CPPFLAGS; construction variables are included on this command line. +See also &cv-link-CCCOM;. @@ -176,9 +183,10 @@ are included on this command line. -The string displayed when a C source file +If set, the string displayed when a C source file is compiled to a shared object file. -If this is not set, then &cv-link-SHCCCOM; (the command line) is displayed. +If not set, then &cv-link-SHCCCOM; (the command line) is displayed. +See also &cv-link-CCCOMSTR;. @@ -192,6 +200,7 @@ env = Environment(SHCCCOMSTR = "Compiling shared object $TARGET") Options that are passed to the C and C++ compilers to generate shared-library objects. +See also &cv-link-CCFLAGS;. @@ -201,6 +210,7 @@ to generate shared-library objects. Options that are passed to the C compiler (only; not C++) to generate shared-library objects. +See also &cv-link-CFLAGS;. diff --git a/src/engine/SCons/Tool/link.xml b/src/engine/SCons/Tool/link.xml index 654dafc..7a84e1a 100644 --- a/src/engine/SCons/Tool/link.xml +++ b/src/engine/SCons/Tool/link.xml @@ -55,8 +55,8 @@ based on the types of source files. __LDMODULEVERSIONFLAGS -SHLINKCOMSTR LINKCOMSTR +SHLINKCOMSTR LDMODULECOMSTR @@ -184,8 +184,8 @@ On other systems, this is the same as &cv-link-SHLINK;. -The string displayed when building loadable modules. -If this is not set, then &cv-link-LDMODULECOM; (the command line) is displayed. +If set, the string displayed when building loadable modules. +If not set, then &cv-link-LDMODULECOM; (the command line) is displayed. @@ -258,9 +258,10 @@ The command line used to link object files into an executable. -The string displayed when object files +If set, the string displayed when object files are linked into an executable. -If this is not set, then &cv-link-LINKCOM; (the command line) is displayed. +If not set, then &cv-link-LINKCOM; (the command line) is displayed. +See also &cv-link-SHLINKCOMSTR;. @@ -334,6 +335,7 @@ The command line used to link programs using shared libraries. The string displayed when programs using shared libraries are linked. If this is not set, then &cv-link-SHLINKCOM; (the command line) is displayed. +See also &cv-link-LINKCOMSTR;. -- cgit v0.12 From e76236cde61b5e38b4a86ec83533533e4263eec2 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Tue, 14 Jan 2020 09:26:46 -0700 Subject: [PR #3524] add two more xrefs in D vars [ci skip] Signed-off-by: Mats Wichmann --- src/engine/SCons/Tool/DCommon.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/engine/SCons/Tool/DCommon.xml b/src/engine/SCons/Tool/DCommon.xml index 6ff08da..da496fc 100644 --- a/src/engine/SCons/Tool/DCommon.xml +++ b/src/engine/SCons/Tool/DCommon.xml @@ -291,6 +291,7 @@ DVERSUFFIX. The name of the compiler to use when compiling D source destined to be in a shared objects. +See also &cv-link-DC;. @@ -299,6 +300,7 @@ destined to be in a shared objects. The command line to use when compiling code to be part of shared objects. +See also &cv-link-DCOM;. -- cgit v0.12 From ac8b6c8c4ca2ca15ab1c04ce759faecf8372b654 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Mon, 13 Jan 2020 13:43:09 -0700 Subject: Tweak docs a bit [ci skip] * Some clarification on Aliases. * Markup improvements. * Custom decider manpage entry didn't mention fourth arg. While fixing that, noticed an ordering problem in matching User Guide section, and converted example there to use hasttr instead of depending on mainly-for-REPL dir() function. * Call it "empty string" instead of "null string" (more common Python terminology) * Fix the table of installers (again, seems old fixes got lost) * Added a note on installation to try to forestall common confusion. Signed-off-by: Mats Wichmann --- doc/user/depends.xml | 52 ++++++++-------- src/engine/SCons/Environment.xml | 26 ++++---- src/engine/SCons/Script/Main.xml | 88 +++++++++++++++------------- src/engine/SCons/Subst.xml | 2 +- src/engine/SCons/Tool/install.xml | 37 +++++++++--- src/engine/SCons/Tool/javac.xml | 12 ++-- src/engine/SCons/Tool/packaging/__init__.xml | 56 +++++++++--------- src/engine/SCons/Tool/textfile.xml | 10 ++-- 8 files changed, 163 insertions(+), 120 deletions(-) diff --git a/doc/user/depends.xml b/doc/user/depends.xml index 703855d..24bede6 100644 --- a/doc/user/depends.xml +++ b/doc/user/depends.xml @@ -561,13 +561,6 @@ int main() { printf("Hello, world!\n"); } - - The fourth argument repo_node, - is the &Node; to use if it is not None when comparing &BuildInfo;. - This is typically only set when the target node only exists in a - &Repository; - - @@ -612,22 +605,33 @@ int main() { printf("Hello, world!\n"); } - Note that ignoring some of the arguments - in your custom &Decider; function - is a perfectly normal thing to do, - if they don't impact the way you want to - decide if the dependency file has changed. + These attributes may not be present at the time of the + first run. Without any prior build, no targets have been + created and no .sconsign DB file exists yet. + So you should always check whether the + prev_ni attribute in question is available + (use the Python hasattr method or a + try-except block). + + + + + + + The fourth argument repo_node + is the &Node; to use if it is not None when comparing &BuildInfo;. + This is typically only set when the target node only exists in a + &Repository; - Another thing to look out for is the fact that the three - attributes above may not be present at the time of the first run. - Without any prior build, no targets have been created and no - .sconsign DB file exists yet. - So, you should always check whether the - prev_ni attribute in question is available. + Note that ignoring some of the arguments + in your custom &Decider; function + is a perfectly normal thing to do, + if they don't impact the way you want to + decide if the dependency file has changed. @@ -644,13 +648,14 @@ int main() { printf("Hello, world!\n"); } env = Environment() + def config_file_decider(dependency, target, prev_ni, repo_node=None): import os.path # We always have to init the .csig value... dep_csig = dependency.get_csig() # .csig may not exist, because no target was built yet... - if 'csig' not in dir(prev_ni): + if not prev_ni.hasattr("csig"): return True # Target file may not exist yet if not os.path.exists(str(target.abspath)): @@ -660,17 +665,18 @@ def config_file_decider(dependency, target, prev_ni, repo_node=None): return True return False + def update_file(): - f = open("test.txt","a") - f.write("some line\n") - f.close() + with open("test.txt", "a") as f: + f.write("some line\n") + update_file() # Activate our own decider function env.Decider(config_file_decider) -env.Install("install","test.txt") +env.Install("install", "test.txt")
diff --git a/src/engine/SCons/Environment.xml b/src/engine/SCons/Environment.xml index 286e882..502e434 100644 --- a/src/engine/SCons/Environment.xml +++ b/src/engine/SCons/Environment.xml @@ -442,6 +442,8 @@ including another alias. can be called multiple times for the same alias to add additional targets to the alias, or additional actions to the list for this alias. +Aliases are global even if set through +the construction environment method. @@ -1145,17 +1147,16 @@ env.Decider('content') -In addition to the above already-available functions, -the +In addition to the above already-available functions, the function -argument may be an actual Python function -that takes the following three arguments: +argument may be a Python function you supply. +Such a function must accept the following four arguments: -dependency +dependency The Node (file) which @@ -1169,7 +1170,7 @@ was built. -target +target The Node (file) being built. @@ -1182,7 +1183,7 @@ has "changed." -prev_ni +prev_ni Stored information about the state of the @@ -1198,12 +1199,17 @@ size, or content signature. -repo_node +repo_node -Use this node instead of the one specified by +If set, use this Node instead of the one specified by dependency - to determine if the dependency has changed. +to determine if the dependency has changed. +This argument is optional so should be written +as a default argument (typically it would be +written as repo_node=None). +A caller will normally only set this if the +target only exists in a Repository. diff --git a/src/engine/SCons/Script/Main.xml b/src/engine/SCons/Script/Main.xml index 5c68dee..b54df0e 100644 --- a/src/engine/SCons/Script/Main.xml +++ b/src/engine/SCons/Script/Main.xml @@ -312,7 +312,7 @@ The options supported are: cache_debug -which corresponds to --cache-debug; +which corresponds to ; @@ -320,7 +320,7 @@ which corresponds to --cache-debug; cache_disable -which corresponds to --cache-disable; +which corresponds to ; @@ -328,7 +328,7 @@ which corresponds to --cache-disable; cache_force -which corresponds to --cache-force; +which corresponds to ; @@ -336,7 +336,7 @@ which corresponds to --cache-force; cache_show -which corresponds to --cache-show; +which corresponds to ; @@ -344,7 +344,8 @@ which corresponds to --cache-show; clean -which corresponds to -c, --clean and --remove; +which corresponds to , +and ; @@ -352,7 +353,7 @@ which corresponds to -c, --clean and --remove; config -which corresponds to --config; +which corresponds to ; @@ -360,7 +361,7 @@ which corresponds to --config; directory -which corresponds to -C and --directory; +which corresponds to and ; @@ -368,7 +369,7 @@ which corresponds to -C and --directory; diskcheck -which corresponds to --diskcheck +which corresponds to ; @@ -376,7 +377,7 @@ which corresponds to --diskcheck duplicate -which corresponds to --duplicate; +which corresponds to ; @@ -384,7 +385,7 @@ which corresponds to --duplicate; file -which corresponds to -f, --file, --makefile and --sconstruct; +which corresponds to , , and ; @@ -392,7 +393,7 @@ which corresponds to -f, --file, --makefile and --sconstruct; help -which corresponds to -h and --help; +which corresponds to and ; @@ -400,7 +401,7 @@ which corresponds to -h and --help; ignore_errors -which corresponds to --ignore-errors; +which corresponds to ; @@ -408,7 +409,7 @@ which corresponds to --ignore-errors; implicit_cache -which corresponds to --implicit-cache; +which corresponds to ; @@ -416,7 +417,7 @@ which corresponds to --implicit-cache; implicit_deps_changed -which corresponds to --implicit-deps-changed; +which corresponds to ; @@ -424,7 +425,7 @@ which corresponds to --implicit-deps-changed; implicit_deps_unchanged -which corresponds to --implicit-deps-unchanged; +which corresponds to ; @@ -432,7 +433,7 @@ which corresponds to --implicit-deps-unchanged; interactive -which corresponds to --interact and --interactive; +which corresponds to and ; @@ -440,7 +441,7 @@ which corresponds to --interact and --interactive; keep_going -which corresponds to -k and --keep-going; +which corresponds to and ; @@ -448,7 +449,7 @@ which corresponds to -k and --keep-going; max_drift -which corresponds to --max-drift; +which corresponds to ; @@ -456,7 +457,9 @@ which corresponds to --max-drift; no_exec -which corresponds to -n, --no-exec, --just-print, --dry-run and --recon; +which corresponds to , +, , + and ; @@ -464,7 +467,7 @@ which corresponds to -n, --no-exec, --just-print, --dry-run and --recon; no_site_dir -which corresponds to --no-site-dir; +which corresponds to ; @@ -472,7 +475,7 @@ which corresponds to --no-site-dir; num_jobs -which corresponds to -j and --jobs; +which corresponds to and ; @@ -480,7 +483,7 @@ which corresponds to -j and --jobs; profile_file -which corresponds to --profile; +which corresponds to ; @@ -488,7 +491,7 @@ which corresponds to --profile; question -which corresponds to -q and --question; +which corresponds to and ; @@ -496,7 +499,7 @@ which corresponds to -q and --question; random -which corresponds to --random; +which corresponds to ; @@ -504,7 +507,7 @@ which corresponds to --random; repository -which corresponds to -Y, --repository and --srcdir; +which corresponds to , and ; @@ -512,7 +515,7 @@ which corresponds to -Y, --repository and --srcdir; silent -which corresponds to -s, --silent and --quiet; +which corresponds to , and ; @@ -520,7 +523,7 @@ which corresponds to -s, --silent and --quiet; site_dir -which corresponds to --site-dir; +which corresponds to ; @@ -528,7 +531,7 @@ which corresponds to --site-dir; stack_size -which corresponds to --stack-size; +which corresponds to ; @@ -536,7 +539,7 @@ which corresponds to --stack-size; taskmastertrace_file -which corresponds to --taskmastertrace; and +which corresponds to ; and @@ -544,7 +547,7 @@ which corresponds to --taskmastertrace; and warn -which corresponds to --warn and --warning. +which corresponds to and . @@ -553,7 +556,7 @@ which corresponds to --warn and --warning. See the documentation for the -corresponding command line object for information about each specific +corresponding command line option for information about each specific option. @@ -749,7 +752,8 @@ line options from a SConscript file. The options supported are: clean -which corresponds to -c, --clean and --remove; +which corresponds to , +and ; @@ -757,7 +761,7 @@ which corresponds to -c, --clean and --remove; duplicate -which corresponds to --duplicate; +which corresponds to ; @@ -765,7 +769,7 @@ which corresponds to --duplicate; help -which corresponds to -h and --help; +which corresponds to and ; @@ -773,7 +777,7 @@ which corresponds to -h and --help; implicit_cache -which corresponds to --implicit-cache; +which corresponds to ; @@ -781,7 +785,7 @@ which corresponds to --implicit-cache; max_drift -which corresponds to --max-drift; +which corresponds to ; @@ -789,7 +793,9 @@ which corresponds to --max-drift; no_exec -which corresponds to -n, --no-exec, --just-print, --dry-run and --recon; +which corresponds to , , +, +and ; @@ -797,7 +803,7 @@ which corresponds to -n, --no-exec, --just-print, --dry-run and --recon; num_jobs -which corresponds to -j and --jobs; +which corresponds to and ; @@ -805,7 +811,7 @@ which corresponds to -j and --jobs; random -which corresponds to --random; and +which corresponds to ; and @@ -813,7 +819,7 @@ which corresponds to --random; and silent -which corresponds to --silent. +which corresponds to . @@ -830,7 +836,7 @@ which corresponds to --stack-size. See the documentation for the -corresponding command line object for information about each specific +corresponding command line option for information about each specific option. diff --git a/src/engine/SCons/Subst.xml b/src/engine/SCons/Subst.xml index 980a9ad..77372ce 100644 --- a/src/engine/SCons/Subst.xml +++ b/src/engine/SCons/Subst.xml @@ -39,7 +39,7 @@ or IndexError exception will expand to a '' -(a null string) and not cause scons to fail. +(an empty string) and not cause scons to fail. All exceptions not in the specified list will generate an error message and terminate processing. diff --git a/src/engine/SCons/Tool/install.xml b/src/engine/SCons/Tool/install.xml index 150308b..ce70d91 100644 --- a/src/engine/SCons/Tool/install.xml +++ b/src/engine/SCons/Tool/install.xml @@ -50,10 +50,24 @@ a builder. -env.Install('/usr/local/bin', source = ['foo', 'bar']) +env.Install(target='/usr/local/bin', source=['foo', 'bar']) +Note that if target paths chosen for the +&Install; builder (and the related &InstallAs; and +&InstallVersionedLib; builders) are outside the +project tree, such as in the example above, +they may not be selected for "building" by default, +since in the absence of other instructions +&scons; builds targets that are underneath the top directory +(the directory that contains the &SConstruct; file, +usually the current directory). +Use command line targets or the &Default; function +in this case. + + + If the command line option is given, the target directory will be prefixed by the directory path specified. @@ -86,12 +100,16 @@ arguments list different numbers of files or directories. -env.InstallAs(target = '/usr/local/bin/foo', - source = 'foo_debug') -env.InstallAs(target = ['../lib/libfoo.a', '../lib/libbar.a'], - source = ['libFOO.a', 'libBAR.a']) +env.InstallAs(target='/usr/local/bin/foo', + source='foo_debug') +env.InstallAs(target=['../lib/libfoo.a', '../lib/libbar.a'], + source=['libFOO.a', 'libBAR.a']) + +See the note under &Install;. + + @@ -103,9 +121,14 @@ architecture will be generated based on symlinks of the source library. -env.InstallVersionedLib(target = '/usr/local/bin/foo', - source = 'libxyz.1.5.2.so') +env.InstallVersionedLib(target='/usr/local/bin/foo', + source='libxyz.1.5.2.so') + + +See the note under &Install;. + + diff --git a/src/engine/SCons/Tool/javac.xml b/src/engine/SCons/Tool/javac.xml index bc89342..893130b 100644 --- a/src/engine/SCons/Tool/javac.xml +++ b/src/engine/SCons/Tool/javac.xml @@ -95,9 +95,9 @@ See its __doc__ string for a discussion of the format. - env.Java(target = 'classes', source = 'src') - env.Java(target = 'classes', source = ['src1', 'src2']) - env.Java(target = 'classes', source = ['File1.java', 'File2.java']) +env.Java(target = 'classes', source = 'src') +env.Java(target = 'classes', source = ['src1', 'src2']) +env.Java(target = 'classes', source = ['File1.java', 'File2.java']) @@ -114,8 +114,8 @@ See its __doc__ string for a discussion of the format. - env = Environment() - env['ENV']['LANG'] = 'en_GB.UTF-8' +env = Environment() +env['ENV']['LANG'] = 'en_GB.UTF-8' @@ -174,7 +174,7 @@ See its __doc__ string for a discussion of the format. - env = Environment(JAVACCOMSTR = "Compiling class files $TARGETS from $SOURCES") +env = Environment(JAVACCOMSTR = "Compiling class files $TARGETS from $SOURCES") diff --git a/src/engine/SCons/Tool/packaging/__init__.xml b/src/engine/SCons/Tool/packaging/__init__.xml index 31c6eed..66a7aa0 100644 --- a/src/engine/SCons/Tool/packaging/__init__.xml +++ b/src/engine/SCons/Tool/packaging/__init__.xml @@ -62,24 +62,25 @@ option or with the &cv-PACKAGETYPE; construction variable. Currently the following packagers available: - - * msi - Microsoft Installer - * rpm - RPM Package Manger - * ipkg - Itsy Package Management System - * tarbz2 - bzip2 compressed tar - * targz - gzip compressed tar - * tarxz - xz compressed tar - * zip - zip file - * src_tarbz2 - bzip2 compressed tar source - * src_targz - gzip compressed tar source - * src_tarxz - xz compressed tar source - * src_zip - zip file source - +msi - Microsoft Installer +rpm - RPM Package Manger +ipkg - Itsy Package Management System +tarbz2 - bzip2 compressed tar +targz - gzip compressed tar +tarxz - xz compressed tar +zip - zip file +src_tarbz2 - bzip2 compressed tar source +src_targz - gzip compressed tar source +src_tarxz - xz compressed tar source +src_zip - zip file source -An updated list is always available under the "package_type" option when -running "scons --help" on a project that has packaging activated. +An updated list is always available under the +package_type option when +running scons --help +on a project that has packaging activated. + env = Environment(tools=['default', 'packaging']) env.Install('/bin/', 'my_program') @@ -198,20 +199,21 @@ placed if applicable. The default value is "$NAME-$VERSION". Selects the package type to build. Currently these are available: - - * msi - Microsoft Installer - * rpm - Redhat Package Manger - * ipkg - Itsy Package Management System - * tarbz2 - compressed tar - * targz - compressed tar - * zip - zip file - * src_tarbz2 - compressed tar source - * src_targz - compressed tar source - * src_zip - zip file source - +msi - Microsoft Installer +rpm - RPM Package Manger +ipkg - Itsy Package Management System +tarbz2 - bzip2 compressed tar +targz - gzip compressed tar +tarxz - xz compressed tar +zip - zip file +src_tarbz2 - bzip2 compressed tar source +src_targz - gzip compressed tar source +src_tarxz - xz compressed tar source +src_zip - zip file source -This may be overridden with the "package_type" command line option. +This may be overridden with the +command line option. diff --git a/src/engine/SCons/Tool/textfile.xml b/src/engine/SCons/Tool/textfile.xml index 957e18c..878eb9f 100644 --- a/src/engine/SCons/Tool/textfile.xml +++ b/src/engine/SCons/Tool/textfile.xml @@ -59,7 +59,7 @@ see the &b-Substfile; description for details. The prefix and suffix specified by the &cv-TEXTFILEPREFIX; and &cv-TEXTFILESUFFIX; construction variables -(the null string and .txt by default, respectively) +(an empty string and .txt by default, respectively) are automatically added to the target if they are not already present. Examples: @@ -124,7 +124,7 @@ the suffix is stripped and the remainder is used as the default target name. The prefix and suffix specified by the &cv-SUBSTFILEPREFIX; and &cv-SUBSTFILESUFFIX; construction variables -(the null string by default in both cases) +(an empty string by default in both cases) are automatically added to the target if they are not already present. @@ -218,7 +218,7 @@ lists of tuples are also acceptable. The prefix used for &b-Substfile; file names, -the null string by default. +an empty string by default. @@ -227,7 +227,7 @@ the null string by default. The suffix used for &b-Substfile; file names, -the null string by default. +an empty string by default. @@ -236,7 +236,7 @@ the null string by default. The prefix used for &b-Textfile; file names, -the null string by default. +an empty string by default. -- cgit v0.12 From a7da390bcfa5ba07b1f780db54dce30e3ba7857e Mon Sep 17 00:00:00 2001 From: Jeremy Elson Date: Tue, 14 Jan 2020 13:42:28 -0800 Subject: Change 'Dependency' to 'Depends' in documentation, to match implementation --- doc/design/engine.xml | 14 +++++++------- src/CHANGES.txt | 3 ++- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/doc/design/engine.xml b/doc/design/engine.xml index 39289f9..6b8b2a6 100644 --- a/doc/design/engine.xml +++ b/doc/design/engine.xml @@ -1104,13 +1104,13 @@ you set it up with another environment... - env.Dependency(target = 'output1', dependency = 'input_1 input_2') - env.Dependency(target = 'output2', dependency = ['input_1', 'input_2']) - env.Dependency(target = 'output3', dependency = ['white space input']) + env.Depends(target = 'output1', dependency = 'input_1 input_2') + env.Depends(target = 'output2', dependency = ['input_1', 'input_2']) + env.Depends(target = 'output3', dependency = ['white space input']) - env.Dependency(target = 'output_a output_b', dependency = 'input_3') - env.Dependency(target = ['output_c', 'output_d'], dependency = 'input_4') - env.Dependency(target = ['white space output'], dependency = 'input_5') + env.Depends(target = 'output_a output_b', dependency = 'input_3') + env.Depends(target = ['output_c', 'output_d'], dependency = 'input_4') + env.Depends(target = ['white space output'], dependency = 'input_5') @@ -1129,7 +1129,7 @@ you set it up with another environment... - env.Dependency(target = 'archive.tar.gz', dependency = 'SConstruct') + env.Depends(target = 'archive.tar.gz', dependency = 'SConstruct') diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 7a2144d..694aca0 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -8,7 +8,6 @@ NOTE: The 4.0.0 Release of SCons will drop Python 2.7 Support RELEASE VERSION/DATE TO BE FILLED IN LATER - From William Deegan: - Fix broken clang + MSVC 2019 combination by using MSVC configuration logic to propagate'VCINSTALLDIR' and 'VCToolsInstallDir' which clang tools use to locate @@ -37,6 +36,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Convert remaining uses of insecure/deprecated mktemp method. - Clean up some duplications in manpage. Clarify portion of manpage on Dir and File nodes. + From Jeremy Elson: + - Updated design doc to use the correct syntax for Depends() RELEASE 3.1.2 - Mon, 17 Dec 2019 02:06:27 +0000 -- cgit v0.12 From 9c2ea57587fb2d3e2d8c469e2bcf3578d2c7d390 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 14 Jan 2020 15:44:00 -0800 Subject: minor formatting --- src/engine/SCons/Conftest.py | 4 ++-- src/engine/SCons/SConf.py | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/engine/SCons/Conftest.py b/src/engine/SCons/Conftest.py index c24adf8..4491884 100644 --- a/src/engine/SCons/Conftest.py +++ b/src/engine/SCons/Conftest.py @@ -315,8 +315,8 @@ int main(void) { return ret -def CheckHeader(context, header_name, header = None, language = None, - include_quotes = None): +def CheckHeader(context, header_name, header=None, language=None, + include_quotes=None): """ Configure check for a C or C++ header file "header_name". Optional "header" can be defined to do something before including the diff --git a/src/engine/SCons/SConf.py b/src/engine/SCons/SConf.py index ed039b7..7e35e98 100644 --- a/src/engine/SCons/SConf.py +++ b/src/engine/SCons/SConf.py @@ -574,8 +574,7 @@ class SConfBase(object): """ return self.pspawn(sh, escape, cmd, args, env, self.logstream, self.logstream) - - def TryBuild(self, builder, text = None, extension = ""): + def TryBuild(self, builder, text=None, extension=""): """Low level TryBuild implementation. Normally you don't need to call that - you can use TryCompile / TryLink / TryRun instead """ -- cgit v0.12 From 50154d0eb7afc564cb13e47c7524fcf2f6ff0450 Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Tue, 14 Jan 2020 19:44:24 -0500 Subject: Add name parameter as requested in PR --- src/engine/SCons/Environment.py | 4 ++-- src/engine/SCons/Node/Python.py | 9 ++++++--- src/engine/SCons/Node/PythonTests.py | 5 +++++ test/CacheDir/value_dependencies/SConstruct | 8 +++++--- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 3e23196..099d143 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -2220,10 +2220,10 @@ class Base(SubstitutionEnvironment): else: return [self.subst(arg)] - def Value(self, value, built_value=None): + def Value(self, value, built_value=None, name=None): """ """ - return SCons.Node.Python.ValueWithMemo(value, built_value) + return SCons.Node.Python.ValueWithMemo(value, built_value, name) def VariantDir(self, variant_dir, src_dir, duplicate=1): variant_dir = self.arg2nodes(variant_dir, self.fs.Dir)[0] diff --git a/src/engine/SCons/Node/Python.py b/src/engine/SCons/Node/Python.py index 385a645..8437385 100644 --- a/src/engine/SCons/Node/Python.py +++ b/src/engine/SCons/Node/Python.py @@ -88,7 +88,7 @@ class Value(SCons.Node.Node): NodeInfo = ValueNodeInfo BuildInfo = ValueBuildInfo - def __init__(self, value, built_value=None): + def __init__(self, value, built_value=None, name=None): SCons.Node.Node.__init__(self) self.value = value self.changed_since_last_build = 6 @@ -98,7 +98,10 @@ class Value(SCons.Node.Node): # Set a name so it can be a child of a node and not break # its parent's implementation of Node.get_contents. - self.name = value + if name: + self.name = name + else: + self.name = str(value) def str_for_display(self): return repr(self.value) @@ -181,7 +184,7 @@ class Value(SCons.Node.Node): return contents -def ValueWithMemo(value, built_value=None): +def ValueWithMemo(value, built_value=None, name=None): global _memo_lookup_map # No current support for memoizing a value that needs to be built. diff --git a/src/engine/SCons/Node/PythonTests.py b/src/engine/SCons/Node/PythonTests.py index da71074..302bb59 100644 --- a/src/engine/SCons/Node/PythonTests.py +++ b/src/engine/SCons/Node/PythonTests.py @@ -64,6 +64,11 @@ class ValueTestCase(unittest.TestCase): v2.build() assert v2.built_value == 'faked', v2.built_value + v3 = SCons.Node.Python.Value(b'\x00\x0F', name='name') + v3.executor = fake_executor() + v3.build() + assert v3.built_value == 'faked', v3.built_value + def test_read(self): """Test the Value.read() method """ diff --git a/test/CacheDir/value_dependencies/SConstruct b/test/CacheDir/value_dependencies/SConstruct index 649648b..7b7e596 100644 --- a/test/CacheDir/value_dependencies/SConstruct +++ b/test/CacheDir/value_dependencies/SConstruct @@ -11,7 +11,7 @@ def scan(node, env, path): # SCons.Node.Python.Value. sample_dir = env.fs.Dir('dir2') env.Depends(sample_dir, env.Value('c')) - return [sample_dir, env.Value('d')] + return [sample_dir, env.Value('d'), env.Value(b'\x03\x0F', name='name3')] scanner = Scanner(function=scan, node_class=SCons.Node.Node) builder = Builder(action=b, source_scanner=scanner) @@ -22,9 +22,11 @@ env.Append(BUILDERS={'B': builder}) # Create a node and a directory that each depend on an instance of # SCons.Node.Python.Value. sample_dir = env.fs.Dir('dir1') -env.Depends(sample_dir, env.Value('a')) +env.Depends(sample_dir, + [env.Value('a'), env.Value(b'\x01\x0F', name='name1')]) sample_file = env.fs.File('testfile') -env.Depends(sample_file, env.Value('b')) +env.Depends(sample_file, + [env.Value('b'), env.Value(b'\x02\x0F', name='name2')]) env.B(target='File1.out', source=[sample_dir, sample_file]) -- cgit v0.12 From 1f0cd4eac841791d9c0f16f111e627779e566f40 Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Wed, 15 Jan 2020 09:35:14 -0500 Subject: Plumb through name in ValueWithMemo --- src/engine/SCons/EnvironmentTests.py | 4 ++++ src/engine/SCons/Node/Python.py | 2 +- src/engine/SCons/Node/PythonTests.py | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index f3779c7..0cb8418 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -3289,6 +3289,10 @@ def generate(env): v3 = env.Value('c', 'build-c') assert v3.value == 'c', v3.value + v4 = env.Value(b'\x00\x0F', name='name') + assert v4.value == b'\x00\x0F', v4.value + assert v4.name == 'name', v4.name + def test_Environment_global_variable(self): """Test setting Environment variable to an Environment.Base subclass""" diff --git a/src/engine/SCons/Node/Python.py b/src/engine/SCons/Node/Python.py index 8437385..d26c185 100644 --- a/src/engine/SCons/Node/Python.py +++ b/src/engine/SCons/Node/Python.py @@ -200,7 +200,7 @@ def ValueWithMemo(value, built_value=None, name=None): try: return _memo_lookup_map[memo_lookup_key] except KeyError: - v = Value(value) + v = Value(value, built_value, name) _memo_lookup_map[memo_lookup_key] = v return v diff --git a/src/engine/SCons/Node/PythonTests.py b/src/engine/SCons/Node/PythonTests.py index 302bb59..6db07ab 100644 --- a/src/engine/SCons/Node/PythonTests.py +++ b/src/engine/SCons/Node/PythonTests.py @@ -67,6 +67,7 @@ class ValueTestCase(unittest.TestCase): v3 = SCons.Node.Python.Value(b'\x00\x0F', name='name') v3.executor = fake_executor() v3.build() + assert v3.name == 'name', v3.name assert v3.built_value == 'faked', v3.built_value def test_read(self): -- cgit v0.12 From 73fa5cc34dbe44fc4f1a95ececc9cb7e578215df Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Wed, 15 Jan 2020 09:55:29 -0500 Subject: [ci skip] Update Environment.xml based on the change to env.Value() --- src/engine/SCons/Environment.xml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/engine/SCons/Environment.xml b/src/engine/SCons/Environment.xml index 35e4bd8..601436e 100644 --- a/src/engine/SCons/Environment.xml +++ b/src/engine/SCons/Environment.xml @@ -3087,7 +3087,7 @@ env.Tool('opengl', toolpath = ['build/tools']) -(value, [built_value]) +(value, [built_value], [name]) @@ -3102,6 +3102,10 @@ will be rebuilt. files are up-to-date.) When using timestamp source signatures, Value Nodes' timestamps are equal to the system time when the Node is created. +name can be provided as an alternative name +for the resulting Value node; this is advised +if the value parameter can't be converted to +a string. -- cgit v0.12 From ad1c42372bffff3327d1ebc3feb9ca4009430ea7 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Wed, 15 Jan 2020 07:25:58 -0700 Subject: [PR #3524] add _why_ you should follow xref [ci skip] per review, note a reason for referring a static/shared construction variable to its shared/static analogue. added a few more xrefs. Signed-off-by: Mats Wichmann --- src/engine/SCons/Tool/DCommon.xml | 18 ++++++++++++------ src/engine/SCons/Tool/c++.xml | 16 ++++++++-------- src/engine/SCons/Tool/cc.xml | 18 +++++++++--------- src/engine/SCons/Tool/f03.xml | 16 ++++++++-------- src/engine/SCons/Tool/f08.xml | 16 ++++++++-------- src/engine/SCons/Tool/f77.xml | 16 ++++++++-------- src/engine/SCons/Tool/f90.xml | 16 ++++++++-------- src/engine/SCons/Tool/f95.xml | 16 ++++++++-------- src/engine/SCons/Tool/fortran.xml | 16 ++++++++-------- src/engine/SCons/Tool/link.xml | 16 +++++++++++----- 10 files changed, 88 insertions(+), 76 deletions(-) diff --git a/src/engine/SCons/Tool/DCommon.xml b/src/engine/SCons/Tool/DCommon.xml index da496fc..6d907c6 100644 --- a/src/engine/SCons/Tool/DCommon.xml +++ b/src/engine/SCons/Tool/DCommon.xml @@ -27,7 +27,7 @@ See its __doc__ string for a discussion of the format. The D compiler to use. -See also &cv-link-SHDC;. +See also &cv-link-SHDC; for compiling to shared objects. @@ -38,7 +38,7 @@ See also &cv-link-SHDC;. The command line used to compile a D file to an object file. Any options specified in the &cv-link-DFLAGS; construction variable is included on this command line. -See also &cv-link-SHDCOM;. +See also &cv-link-SHDCOM; for compiling to shared objects. @@ -49,7 +49,7 @@ See also &cv-link-SHDCOM;. If set, the string displayed when a D source file is compiled to a (static) object file. If not set, then &cv-link-DCOM; (the command line) is displayed. -See also &cv-link-SHDCOMSTR;. +See also &cv-link-SHDCOMSTR; for compiling to shared objects. @@ -194,6 +194,7 @@ DLIBLINKSUFFIX. Name of the linker to use for linking systems including D sources. +See also &cv-link-SHDLINK; for linking shared objects. @@ -202,6 +203,7 @@ Name of the linker to use for linking systems including D sources. The command line to use when linking systems including D sources. +See also &cv-link-SHDLINKCOM; for linking shared objects. @@ -210,6 +212,7 @@ The command line to use when linking systems including D sources. List of linker flags. +See also &cv-link-SHDLINKFLAGS; for linking shared objects. @@ -291,7 +294,7 @@ DVERSUFFIX. The name of the compiler to use when compiling D source destined to be in a shared objects. -See also &cv-link-DC;. +See also &cv-link-DC; for compiling to static objects. @@ -300,7 +303,7 @@ See also &cv-link-DC;. The command line to use when compiling code to be part of shared objects. -See also &cv-link-DCOM;. +See also &cv-link-DCOM; for compiling to static objects. @@ -311,7 +314,7 @@ See also &cv-link-DCOM;. If set, the string displayed when a D source file is compiled to a (shared) object file. If not set, then &cv-link-SHDCOM; (the command line) is displayed. -See also &cv-link-DCOMSTR;. +See also &cv-link-DCOMSTR; for compiling to static objects. @@ -337,6 +340,7 @@ SHDLIBVERSIONFLAGS. The linker to use when creating shared objects for code bases include D sources. +See also &cv-link-DLINK; for linking static objects. @@ -345,6 +349,7 @@ include D sources. The command line to use when generating shared objects. +See also &cv-link-DLINKCOM; for linking static objects. @@ -353,6 +358,7 @@ The command line to use when generating shared objects. The list of flags to use when generating a shared object. +See also &cv-link-DLINKFLAGS; for linking static objects. diff --git a/src/engine/SCons/Tool/c++.xml b/src/engine/SCons/Tool/c++.xml index 0918b5f..019821c 100644 --- a/src/engine/SCons/Tool/c++.xml +++ b/src/engine/SCons/Tool/c++.xml @@ -55,7 +55,7 @@ Sets construction variables for generic POSIX C++ compilers. The C++ compiler. -See also &cv-link-SHCXX;. +See also &cv-link-SHCXX; for compiling to shared objects.. @@ -67,7 +67,7 @@ The command line used to compile a C++ source file to an object file. Any options specified in the &cv-link-CXXFLAGS; and &cv-link-CPPFLAGS; construction variables are included on this command line. -See also &cv-link-SHCXXCOM;. +See also &cv-link-SHCXXCOM; for compiling to shared objects.. @@ -78,7 +78,7 @@ See also &cv-link-SHCXXCOM;. If set, the string displayed when a C++ source file is compiled to a (static) object file. If not set, then &cv-link-CXXCOM; (the command line) is displayed. -See also &cv-link-SHCXXCOMSTR;. +See also &cv-link-SHCXXCOMSTR; for compiling to shared objects.. @@ -95,7 +95,7 @@ By default, this includes the value of &cv-link-CCFLAGS;, so that setting &cv-CCFLAGS; affects both C and C++ compilation. If you want to add C++-specific flags, you must set or override the value of &cv-link-CXXFLAGS;. -See also &cv-link-SHCXXFLAGS;. +See also &cv-link-SHCXXFLAGS; for compiling to shared objects.. @@ -104,7 +104,7 @@ See also &cv-link-SHCXXFLAGS;. The C++ compiler used for generating shared-library objects. -See also &cv-link-CXX;. +See also &cv-link-CXX; for compiling to static objects. @@ -117,7 +117,7 @@ to a shared-library object file. Any options specified in the &cv-link-SHCXXFLAGS; and &cv-link-CPPFLAGS; construction variables are included on this command line. -See also &cv-link-CXXCOM;. +See also &cv-link-CXXCOM; for compiling to static objects. @@ -128,7 +128,7 @@ See also &cv-link-CXXCOM;. If set, the string displayed when a C++ source file is compiled to a shared object file. If not set, then &cv-link-SHCXXCOM; (the command line) is displayed. -See also &cv-link-CXXCOMSTR;. +See also &cv-link-CXXCOMSTR; for compiling to static objects. @@ -142,7 +142,7 @@ env = Environment(SHCXXCOMSTR = "Compiling shared object $TARGET") Options that are passed to the C++ compiler to generate shared-library objects. -See also &cv-link-CXXFLAGS;. +See also &cv-link-CXXFLAGS; for compiling to static objects. diff --git a/src/engine/SCons/Tool/cc.xml b/src/engine/SCons/Tool/cc.xml index 4150e23..e47cf2d 100644 --- a/src/engine/SCons/Tool/cc.xml +++ b/src/engine/SCons/Tool/cc.xml @@ -70,7 +70,7 @@ The C compiler. The command line used to compile a C source file to a (static) object file. Any options specified in the &cv-link-CFLAGS;, &cv-link-CCFLAGS; and &cv-link-CPPFLAGS; construction variables are included on this command line. -See also &cv-link-SHCCCOM;. +See also &cv-link-SHCCCOM; for compiling to shared objects. @@ -81,7 +81,7 @@ See also &cv-link-SHCCCOM;. If set, the string displayed when a C source file is compiled to a (static) object file. If not set, then &cv-link-CCCOM; (the command line) is displayed. -See also &cv-link-SHCCCOMSTR;. +See also &cv-link-SHCCCOMSTR; for compiling to shared objects. @@ -94,7 +94,7 @@ env = Environment(CCCOMSTR = "Compiling static object $TARGET") General options that are passed to the C and C++ compilers. -See also &cv-link-SHCCFLAGS;. +See also &cv-link-SHCCFLAGS; for compiling to shared objects. @@ -103,7 +103,7 @@ See also &cv-link-SHCCFLAGS;. General options that are passed to the C compiler (C only; not C++). -See also &cv-link-SHCFLAGS;. +See also &cv-link-SHCFLAGS; for compiling to shared objects. @@ -161,7 +161,7 @@ The default list is: The C compiler used for generating shared-library objects. -See also &cv-link-CC;. +See also &cv-link-CC; for compiling to static objects. @@ -175,7 +175,7 @@ Any options specified in the &cv-link-SHCFLAGS;, &cv-link-SHCCFLAGS; and &cv-link-CPPFLAGS; construction variables are included on this command line. -See also &cv-link-CCCOM;. +See also &cv-link-CCCOM; for compiling to static objects. @@ -186,7 +186,7 @@ See also &cv-link-CCCOM;. If set, the string displayed when a C source file is compiled to a shared object file. If not set, then &cv-link-SHCCCOM; (the command line) is displayed. -See also &cv-link-CCCOMSTR;. +See also &cv-link-CCCOMSTR; for compiling to static objects. @@ -200,7 +200,7 @@ env = Environment(SHCCCOMSTR = "Compiling shared object $TARGET") Options that are passed to the C and C++ compilers to generate shared-library objects. -See also &cv-link-CCFLAGS;. +See also &cv-link-CCFLAGS; for compiling to static objects. @@ -210,7 +210,7 @@ See also &cv-link-CCFLAGS;. Options that are passed to the C compiler (only; not C++) to generate shared-library objects. -See also &cv-link-CFLAGS;. +See also &cv-link-CFLAGS; for compiling to static objects. diff --git a/src/engine/SCons/Tool/f03.xml b/src/engine/SCons/Tool/f03.xml index c020b81..61c02ef 100644 --- a/src/engine/SCons/Tool/f03.xml +++ b/src/engine/SCons/Tool/f03.xml @@ -77,9 +77,9 @@ for all Fortran versions. -The string displayed when a Fortran 03 source file +If set, the string displayed when a Fortran 03 source file is compiled to an object file. -If this is not set, then &cv-link-F03COM; or &cv-link-FORTRANCOM; +If not set, then &cv-link-F03COM; or &cv-link-FORTRANCOM; (the command line) is displayed. @@ -217,10 +217,10 @@ for all Fortran versions. -The string displayed when a Fortran 03 source file +If set, the string displayed when a Fortran 03 source file is compiled to an object file after first running the file through the C preprocessor. -If this is not set, then &cv-link-F03PPCOM; or &cv-link-FORTRANPPCOM; +If not set, then &cv-link-F03PPCOM; or &cv-link-FORTRANPPCOM; (the command line) is displayed. @@ -256,9 +256,9 @@ for all Fortran versions. -The string displayed when a Fortran 03 source file +If set, the string displayed when a Fortran 03 source file is compiled to a shared-library object file. -If this is not set, then &cv-link-SHF03COM; or &cv-link-SHFORTRANCOM; +If not set, then &cv-link-SHF03COM; or &cv-link-SHFORTRANCOM; (the command line) is displayed. @@ -299,10 +299,10 @@ for all Fortran versions. -The string displayed when a Fortran 03 source file +If set, the string displayed when a Fortran 03 source file is compiled to a shared-library object file after first running the file through the C preprocessor. -If this is not set, then &cv-link-SHF03PPCOM; or &cv-link-SHFORTRANPPCOM; +If not set, then &cv-link-SHF03PPCOM; or &cv-link-SHFORTRANPPCOM; (the command line) is displayed. diff --git a/src/engine/SCons/Tool/f08.xml b/src/engine/SCons/Tool/f08.xml index 802e4cc..a56d60b 100644 --- a/src/engine/SCons/Tool/f08.xml +++ b/src/engine/SCons/Tool/f08.xml @@ -77,9 +77,9 @@ for all Fortran versions. -The string displayed when a Fortran 08 source file +If set, the string displayed when a Fortran 08 source file is compiled to an object file. -If this is not set, then &cv-link-F08COM; or &cv-link-FORTRANCOM; +If not set, then &cv-link-F08COM; or &cv-link-FORTRANCOM; (the command line) is displayed. @@ -217,10 +217,10 @@ for all Fortran versions. -The string displayed when a Fortran 08 source file +If set, the string displayed when a Fortran 08 source file is compiled to an object file after first running the file through the C preprocessor. -If this is not set, then &cv-link-F08PPCOM; or &cv-link-FORTRANPPCOM; +If not set, then &cv-link-F08PPCOM; or &cv-link-FORTRANPPCOM; (the command line) is displayed. @@ -256,9 +256,9 @@ for all Fortran versions. -The string displayed when a Fortran 08 source file +If set, the string displayed when a Fortran 08 source file is compiled to a shared-library object file. -If this is not set, then &cv-link-SHF08COM; or &cv-link-SHFORTRANCOM; +If not set, then &cv-link-SHF08COM; or &cv-link-SHFORTRANCOM; (the command line) is displayed. @@ -299,10 +299,10 @@ for all Fortran versions. -The string displayed when a Fortran 08 source file +If set, the string displayed when a Fortran 08 source file is compiled to a shared-library object file after first running the file through the C preprocessor. -If this is not set, then &cv-link-SHF08PPCOM; or &cv-link-SHFORTRANPPCOM; +If not set, then &cv-link-SHF08PPCOM; or &cv-link-SHFORTRANPPCOM; (the command line) is displayed. diff --git a/src/engine/SCons/Tool/f77.xml b/src/engine/SCons/Tool/f77.xml index abfc4a2..70ec721 100644 --- a/src/engine/SCons/Tool/f77.xml +++ b/src/engine/SCons/Tool/f77.xml @@ -108,9 +108,9 @@ F77 dialect will be used. By default, this is empty -The string displayed when a Fortran 77 source file +If set, the string displayed when a Fortran 77 source file is compiled to an object file. -If this is not set, then &cv-link-F77COM; or &cv-link-FORTRANCOM; +If not set, then &cv-link-F77COM; or &cv-link-FORTRANCOM; (the command line) is displayed. @@ -230,10 +230,10 @@ for all Fortran versions. -The string displayed when a Fortran 77 source file +If set, the string displayed when a Fortran 77 source file is compiled to an object file after first running the file through the C preprocessor. -If this is not set, then &cv-link-F77PPCOM; or &cv-link-FORTRANPPCOM; +If not set, then &cv-link-F77PPCOM; or &cv-link-FORTRANPPCOM; (the command line) is displayed. @@ -269,9 +269,9 @@ for all Fortran versions. -The string displayed when a Fortran 77 source file +If set, the string displayed when a Fortran 77 source file is compiled to a shared-library object file. -If this is not set, then &cv-link-SHF77COM; or &cv-link-SHFORTRANCOM; +If not set, then &cv-link-SHF77COM; or &cv-link-SHFORTRANCOM; (the command line) is displayed. @@ -312,10 +312,10 @@ for all Fortran versions. -The string displayed when a Fortran 77 source file +If set, the string displayed when a Fortran 77 source file is compiled to a shared-library object file after first running the file through the C preprocessor. -If this is not set, then &cv-link-SHF77PPCOM; or &cv-link-SHFORTRANPPCOM; +If not set, then &cv-link-SHF77PPCOM; or &cv-link-SHFORTRANPPCOM; (the command line) is displayed. diff --git a/src/engine/SCons/Tool/f90.xml b/src/engine/SCons/Tool/f90.xml index 94249a3..64dc6e1 100644 --- a/src/engine/SCons/Tool/f90.xml +++ b/src/engine/SCons/Tool/f90.xml @@ -77,9 +77,9 @@ for all Fortran versions. -The string displayed when a Fortran 90 source file +If set, the string displayed when a Fortran 90 source file is compiled to an object file. -If this is not set, then &cv-link-F90COM; or &cv-link-FORTRANCOM; +If not set, then &cv-link-F90COM; or &cv-link-FORTRANCOM; (the command line) is displayed. @@ -217,9 +217,9 @@ for all Fortran versions. -The string displayed when a Fortran 90 source file +If set, the string displayed when a Fortran 90 source file is compiled after first running the file through the C preprocessor. -If this is not set, then &cv-link-F90PPCOM; or &cv-link-FORTRANPPCOM; +If not set, then &cv-link-F90PPCOM; or &cv-link-FORTRANPPCOM; (the command line) is displayed. @@ -255,9 +255,9 @@ for all Fortran versions. -The string displayed when a Fortran 90 source file +If set, the string displayed when a Fortran 90 source file is compiled to a shared-library object file. -If this is not set, then &cv-link-SHF90COM; or &cv-link-SHFORTRANCOM; +If not set, then &cv-link-SHF90COM; or &cv-link-SHFORTRANCOM; (the command line) is displayed. @@ -298,10 +298,10 @@ for all Fortran versions. -The string displayed when a Fortran 90 source file +If set, the string displayed when a Fortran 90 source file is compiled to a shared-library object file after first running the file through the C preprocessor. -If this is not set, then &cv-link-SHF90PPCOM; or &cv-link-SHFORTRANPPCOM; +If not set, then &cv-link-SHF90PPCOM; or &cv-link-SHFORTRANPPCOM; (the command line) is displayed. diff --git a/src/engine/SCons/Tool/f95.xml b/src/engine/SCons/Tool/f95.xml index 4a4db46..4bda653 100644 --- a/src/engine/SCons/Tool/f95.xml +++ b/src/engine/SCons/Tool/f95.xml @@ -77,9 +77,9 @@ for all Fortran versions. -The string displayed when a Fortran 95 source file +If set, the string displayed when a Fortran 95 source file is compiled to an object file. -If this is not set, then &cv-link-F95COM; or &cv-link-FORTRANCOM; +If not set, then &cv-link-F95COM; or &cv-link-FORTRANCOM; (the command line) is displayed. @@ -217,10 +217,10 @@ for all Fortran versions. -The string displayed when a Fortran 95 source file +If set, the string displayed when a Fortran 95 source file is compiled to an object file after first running the file through the C preprocessor. -If this is not set, then &cv-link-F95PPCOM; or &cv-link-FORTRANPPCOM; +If not set, then &cv-link-F95PPCOM; or &cv-link-FORTRANPPCOM; (the command line) is displayed. @@ -256,9 +256,9 @@ for all Fortran versions. -The string displayed when a Fortran 95 source file +If set, the string displayed when a Fortran 95 source file is compiled to a shared-library object file. -If this is not set, then &cv-link-SHF95COM; or &cv-link-SHFORTRANCOM; +If not set, then &cv-link-SHF95COM; or &cv-link-SHFORTRANCOM; (the command line) is displayed. @@ -299,10 +299,10 @@ for all Fortran versions. -The string displayed when a Fortran 95 source file +If set, the string displayed when a Fortran 95 source file is compiled to a shared-library object file after first running the file through the C preprocessor. -If this is not set, then &cv-link-SHF95PPCOM; or &cv-link-SHFORTRANPPCOM; +If not set, then &cv-link-SHF95PPCOM; or &cv-link-SHFORTRANPPCOM; (the command line) is displayed. diff --git a/src/engine/SCons/Tool/fortran.xml b/src/engine/SCons/Tool/fortran.xml index 53bcfb1..7b3c51f 100644 --- a/src/engine/SCons/Tool/fortran.xml +++ b/src/engine/SCons/Tool/fortran.xml @@ -73,9 +73,9 @@ are included on this command line. -The string displayed when a Fortran source file +If set, the string displayed when a Fortran source file is compiled to an object file. -If this is not set, then &cv-link-FORTRANCOM; +If not set, then &cv-link-FORTRANCOM; (the command line) is displayed. @@ -285,10 +285,10 @@ construction variables are included on this command line. -The string displayed when a Fortran source file +If set, the string displayed when a Fortran source file is compiled to an object file after first running the file through the C preprocessor. -If this is not set, then &cv-link-FORTRANPPCOM; +If not set, then &cv-link-FORTRANPPCOM; (the command line) is displayed. @@ -330,9 +330,9 @@ to a shared-library object file. -The string displayed when a Fortran source file +If set, the string displayed when a Fortran source file is compiled to a shared-library object file. -If this is not set, then &cv-link-SHFORTRANCOM; +If not set, then &cv-link-SHFORTRANCOM; (the command line) is displayed. @@ -364,10 +364,10 @@ are included on this command line. -The string displayed when a Fortran source file +If set, the string displayed when a Fortran source file is compiled to a shared-library object file after first running the file through the C preprocessor. -If this is not set, then &cv-link-SHFORTRANPPCOM; +If not set, then &cv-link-SHFORTRANPPCOM; (the command line) is displayed. diff --git a/src/engine/SCons/Tool/link.xml b/src/engine/SCons/Tool/link.xml index 7a84e1a..281e147 100644 --- a/src/engine/SCons/Tool/link.xml +++ b/src/engine/SCons/Tool/link.xml @@ -32,9 +32,6 @@ based on the types of source files. -SHLINK -SHLINKFLAGS -SHLINKCOM LINK LINKFLAGS LINKCOM @@ -42,6 +39,9 @@ based on the types of source files. LIBDIRSUFFIX LIBLINKPREFIX LIBLINKSUFFIX +SHLINK +SHLINKFLAGS +SHLINKCOM SHLIBSUFFIX __SHLIBVERSIONFLAGS LDMODULE @@ -243,6 +243,7 @@ set. The linker. +See also &cv-link-SHLINK; for linking shared objects. @@ -251,6 +252,7 @@ The linker. The command line used to link object files into an executable. +See also &cv-link-SHLINKCOM; for linking shared objects. @@ -261,7 +263,7 @@ The command line used to link object files into an executable. If set, the string displayed when object files are linked into an executable. If not set, then &cv-link-LINKCOM; (the command line) is displayed. -See also &cv-link-SHLINKCOMSTR;. +See also &cv-link-SHLINKCOMSTR;. for linking shared objects. @@ -291,6 +293,7 @@ and &cv-link-_LIBDIRFLAGS; above, for the variable that expands to library search path options. +See also &cv-link-SHLINKFLAGS;. for linking shared objects. @@ -318,6 +321,7 @@ set. The linker for programs that use shared libraries. +See also &cv-link-LINK; for linking static objects. @@ -326,6 +330,7 @@ The linker for programs that use shared libraries. The command line used to link programs using shared libraries. +See also &cv-link-LINKCOM; for linking static objects. @@ -335,7 +340,7 @@ The command line used to link programs using shared libraries. The string displayed when programs using shared libraries are linked. If this is not set, then &cv-link-SHLINKCOM; (the command line) is displayed. -See also &cv-link-LINKCOMSTR;. +See also &cv-link-LINKCOMSTR; for linking static objects. @@ -365,6 +370,7 @@ and &cv-link-_LIBDIRFLAGS; above, for the variable that expands to library search path options. +See also &cv-link-LINKFLAGS; for linking static objects. -- cgit v0.12 From e5c71f8a819fba93047d17966bfb85835637ea6a Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 15 Jan 2020 21:06:57 -0500 Subject: Change ValueWithMemo() to take into account any name passed when memoizing Value()'s --- src/CHANGES.txt | 3 +-- src/engine/SCons/Node/Python.py | 9 ++++++--- src/engine/SCons/Node/PythonTests.py | 16 ++++++++++++++++ 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 97934ff..fd9eba5 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -19,10 +19,9 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER From Adam Gross: - Added support for taking instances of the Value class as implicit dependencies. - - From Adam Gross: - Added new module SCons.Scanner.Python to allow scanning .py files. + From Mathew Robinson: - Improve performance of Subst by preventing unnecessary frame allocations by no longer defining the *Subber classes inside of their diff --git a/src/engine/SCons/Node/Python.py b/src/engine/SCons/Node/Python.py index d26c185..68c6ee8 100644 --- a/src/engine/SCons/Node/Python.py +++ b/src/engine/SCons/Node/Python.py @@ -185,17 +185,20 @@ class Value(SCons.Node.Node): def ValueWithMemo(value, built_value=None, name=None): + """ + Memoized Value() node factory. + """ global _memo_lookup_map # No current support for memoizing a value that needs to be built. if built_value: - return Value(value, built_value) + return Value(value, built_value, name=name) try: - memo_lookup_key = hash(value) + memo_lookup_key = hash((value, name)) except TypeError: # Non-primitive types will hit this codepath. - return Value(value) + return Value(value, name=name) try: return _memo_lookup_map[memo_lookup_key] diff --git a/src/engine/SCons/Node/PythonTests.py b/src/engine/SCons/Node/PythonTests.py index 6db07ab..51a49c0 100644 --- a/src/engine/SCons/Node/PythonTests.py +++ b/src/engine/SCons/Node/PythonTests.py @@ -104,6 +104,9 @@ class ValueTestCase(unittest.TestCase): assert csig == 'None', csig + + + class ValueNodeInfoTestCase(unittest.TestCase): def test___init__(self): """Test ValueNodeInfo initialization""" @@ -162,6 +165,19 @@ class ValueMemoTestCase(unittest.TestCase): v4 = SCons.Node.Python.ValueWithMemo(a) assert v3 is not v4 + def test_value_set_name(self): + """ Confirm setting name and caching takes the name into account """ + + v1 = SCons.Node.Python.ValueWithMemo(b'\x00\x0F', name='name') + v2 = SCons.Node.Python.ValueWithMemo(b'\x00\x0F', name='name2') + v3 = SCons.Node.Python.ValueWithMemo('Jibberish') + + self.assertEqual(v1.name,'name', msg=v1.name) + self.assertEqual(v2.name,'name2', msg=v2.name) + self.assertEqual(v3.name,'Jibberish', msg=v3.name) + self.assertTrue(v1 is not v2, msg="v1 and v2 should be different as they have different names but same values") + + if __name__ == "__main__": unittest.main() -- cgit v0.12 From f0ed0de157ab13e6a8767b1aae66ce3deaa6066e Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 15 Jan 2020 21:46:54 -0500 Subject: updated CHANGES.txt --- src/CHANGES.txt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index fd9eba5..d2b5110 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -15,12 +15,17 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Added C:\msys64\mingw64\bin to default mingw and clang windows PATH's. This is a reasonable default and also aligns with changes in Appveyor's VS2019 image. - Drop support for Python 2.7. SCons will be Python 3.5+ going forward. + - Change SCons.Node.ValueWithMemo to consider any name passed when memoizing Value() nodes + + From Jeremy Elson: + - Updated design doc to use the correct syntax for Depends() From Adam Gross: - Added support for taking instances of the Value class as implicit dependencies. - Added new module SCons.Scanner.Python to allow scanning .py files. - + - Added support for explicitly passing a name when creating Value() nodes. This may be useful + when the value can't be converted to a string or if having a name is otherwise desirable. From Mathew Robinson: - Improve performance of Subst by preventing unnecessary frame @@ -38,8 +43,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Convert remaining uses of insecure/deprecated mktemp method. - Clean up some duplications in manpage. Clarify portion of manpage on Dir and File nodes. - From Jeremy Elson: - - Updated design doc to use the correct syntax for Depends() + RELEASE 3.1.2 - Mon, 17 Dec 2019 02:06:27 +0000 -- cgit v0.12 From 407dda1715776a962119cbf8442286af7cae79b9 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Mon, 12 Aug 2019 09:33:24 -0600 Subject: Stop converting to list where not needed Python 3 returns a special object, which is iterable, rather than a list when you ask for dictionary keys(), values(), items(). if you then proceed to iterate over it it's being used as expected and doesn't have to be forced to a list first. This occurs a number of places in this form: for k in list(something.keys()): Also there are several places where the code loops over the result of dict.keys() and then uses the key to index into the dictionary, this can be replaced by: for k, v in something.items(): Signed-off-by: Mats Wichmann --- src/CHANGES.txt | 1 + src/engine/SCons/Builder.py | 2 +- src/engine/SCons/Environment.py | 4 ++-- src/engine/SCons/Node/FS.py | 4 ++-- src/engine/SCons/SConf.py | 6 +++--- src/engine/SCons/Script/Interactive.py | 2 +- src/engine/SCons/Script/Main.py | 4 ++-- src/engine/SCons/Tool/MSCommon/common.py | 4 ++-- src/engine/SCons/Tool/__init__.py | 2 +- src/engine/SCons/Tool/intelc.py | 8 ++++---- src/engine/SCons/Tool/msvs.py | 21 +++++++-------------- src/engine/SCons/Tool/msvsTests.py | 4 ++-- src/engine/SCons/Tool/packaging/ipk.py | 2 +- src/engine/SCons/Tool/packaging/rpm.py | 2 +- src/engine/SCons/cpp.py | 4 ++-- src/test_interrupts.py | 2 +- 16 files changed, 33 insertions(+), 39 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 694aca0..2f85fe6 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -35,6 +35,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - a bunch of linter/checker syntax fixups - Convert remaining uses of insecure/deprecated mktemp method. - Clean up some duplications in manpage. Clarify portion of manpage on Dir and File nodes. + - Reduce needless list conversions. From Jeremy Elson: - Updated design doc to use the correct syntax for Depends() diff --git a/src/engine/SCons/Builder.py b/src/engine/SCons/Builder.py index e3fb396..caa0568 100644 --- a/src/engine/SCons/Builder.py +++ b/src/engine/SCons/Builder.py @@ -230,7 +230,7 @@ class OverrideWarner(collections.UserDict): def warn(self): if self.already_warned: return - for k in list(self.keys()): + for k in self.keys(): if k in misleading_keywords: alt = misleading_keywords[k] msg = "Did you mean to use `%s' instead of `%s'?" % (alt, k) diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 3e23196..18badc0 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -1854,7 +1854,7 @@ class Base(SubstitutionEnvironment): uniq = {} for executor in [n.get_executor() for n in nodes]: uniq[executor] = 1 - for executor in list(uniq.keys()): + for executor in uniq.keys(): executor.add_pre_action(action) return nodes @@ -1864,7 +1864,7 @@ class Base(SubstitutionEnvironment): uniq = {} for executor in [n.get_executor() for n in nodes]: uniq[executor] = 1 - for executor in list(uniq.keys()): + for executor in uniq.keys(): executor.add_post_action(action) return nodes diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index e1d6f68..6f16256 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -1612,7 +1612,7 @@ class Dir(Base): This clears any cached information that is invalidated by changing the repository.""" - for node in list(self.entries.values()): + for node in self.entries.values(): if node != self.dir: if node != self and isinstance(node, Dir): node.__clearRepositoryCache(duplicate) @@ -1623,7 +1623,7 @@ class Dir(Base): except AttributeError: pass if duplicate is not None: - node.duplicate=duplicate + node.duplicate = duplicate def __resetDuplicate(self, node): if node != self: diff --git a/src/engine/SCons/SConf.py b/src/engine/SCons/SConf.py index e706dae..988362e 100644 --- a/src/engine/SCons/SConf.py +++ b/src/engine/SCons/SConf.py @@ -132,8 +132,8 @@ def CreateConfigHBuilder(env): _stringConfigH) sconfigHBld = SCons.Builder.Builder(action=action) env.Append( BUILDERS={'SConfigHBuilder':sconfigHBld} ) - for k in list(_ac_config_hs.keys()): - env.SConfigHBuilder(k, env.Value(_ac_config_hs[k])) + for k, v in _ac_config_hs.items(): + env.SConfigHBuilder(k, env.Value(v)) class SConfWarning(SCons.Warnings.Warning): @@ -703,7 +703,7 @@ class SConfBase(object): """Adds all the tests given in the tests dictionary to this SConf instance """ - for name in list(tests.keys()): + for name in tests.keys(): self.AddTest(name, tests[name]) def _createDir( self, node ): diff --git a/src/engine/SCons/Script/Interactive.py b/src/engine/SCons/Script/Interactive.py index cc4f23c..59299f1 100644 --- a/src/engine/SCons/Script/Interactive.py +++ b/src/engine/SCons/Script/Interactive.py @@ -247,7 +247,7 @@ version Prints SCons version information. while n: n = walker.get_next() - for node in list(seen_nodes.keys()): + for node in seen_nodes.keys(): # Call node.clear() to clear most of the state node.clear() # node.clear() doesn't reset node.state, so call diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py index f9c8384..a0d7f4c 100644 --- a/src/engine/SCons/Script/Main.py +++ b/src/engine/SCons/Script/Main.py @@ -743,9 +743,9 @@ def _load_site_scons_dir(topdir, site_dir_name=None): modname = os.path.basename(pathname)[:-len(sfx)] site_m = {"__file__": pathname, "__name__": modname, "__doc__": None} re_special = re.compile("__[^_]+__") - for k in list(m.__dict__.keys()): + for k, v in m.__dict__.items(): if not re_special.match(k): - site_m[k] = m.__dict__[k] + site_m[k] = v # This is the magic. exec(compile(fp.read(), fp.name, 'exec'), site_m) diff --git a/src/engine/SCons/Tool/MSCommon/common.py b/src/engine/SCons/Tool/MSCommon/common.py index 386f445..4ce605b 100644 --- a/src/engine/SCons/Tool/MSCommon/common.py +++ b/src/engine/SCons/Tool/MSCommon/common.py @@ -152,8 +152,8 @@ def normalize_env(env, keys, force=False): Note: the environment is copied.""" normenv = {} if env: - for k in list(env.keys()): - normenv[k] = copy.deepcopy(env[k]) + for k, v in env.items(): + normenv[k] = copy.deepcopy(v) for k in keys: if k in os.environ and (force or k not in normenv): diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py index 99a958c..76a0913 100644 --- a/src/engine/SCons/Tool/__init__.py +++ b/src/engine/SCons/Tool/__init__.py @@ -1130,7 +1130,7 @@ class ToolInitializer(object): so we no longer copy and re-bind them when the construction environment gets cloned. """ - for method in list(self.methods.values()): + for method in self.methods.values(): env.RemoveMethod(method) def apply_tools(self, env): diff --git a/src/engine/SCons/Tool/intelc.py b/src/engine/SCons/Tool/intelc.py index 5a101b4..778cba1 100644 --- a/src/engine/SCons/Tool/intelc.py +++ b/src/engine/SCons/Tool/intelc.py @@ -495,15 +495,15 @@ def generate(env, version=None, abi=None, topdir=None, verbose=0): 'LIB' : libdir, 'PATH' : bindir, 'LD_LIBRARY_PATH' : libdir} - for p in list(paths.keys()): - env.PrependENVPath(p, os.path.join(topdir, paths[p])) + for p, v in paths.items(): + env.PrependENVPath(p, os.path.join(topdir, v)) if is_mac: paths={'INCLUDE' : 'include', 'LIB' : libdir, 'PATH' : bindir, 'LD_LIBRARY_PATH' : libdir} - for p in list(paths.keys()): - env.PrependENVPath(p, os.path.join(topdir, paths[p])) + for p, v in paths.items(): + env.PrependENVPath(p, os.path.join(topdir, v)) if is_windows: # env key reg valname default subdir of top paths=(('INCLUDE', 'IncludeDir', 'Include'), diff --git a/src/engine/SCons/Tool/msvs.py b/src/engine/SCons/Tool/msvs.py index 929e558..d923d3d 100644 --- a/src/engine/SCons/Tool/msvs.py +++ b/src/engine/SCons/Tool/msvs.py @@ -220,7 +220,7 @@ class _UserGenerator(object): for var, src in dbg_settings.items(): # Update only expected keys trg = {} - for key in [k for k in list(self.usrdebg.keys()) if k in src]: + for key in [k for k in self.usrdebg.keys() if k in src]: trg[key] = str(src[key]) self.configs[var].debug = trg @@ -578,11 +578,8 @@ class _DSPGenerator(object): for i in range(len(variants)): AddConfig(self, variants[i], buildtarget[i], outdir[i], runfile[i], cmdargs[i], cppdefines[i], cpppaths[i]) - self.platforms = [] - for key in list(self.configs.keys()): - platform = self.configs[key].platform - if platform not in self.platforms: - self.platforms.append(platform) + self.platforms = {p.platform for p in self.configs.values()} + def Build(self): pass @@ -702,7 +699,7 @@ class _GenerateV6DSP(_DSPGenerator): 'Resource Files': 'r|rc|ico|cur|bmp|dlg|rc2|rct|bin|cnt|rtf|gif|jpg|jpeg|jpe', 'Other Files': ''} - for kind in sorted(list(categories.keys()), key=lambda a: a.lower()): + for kind in sorted(categories.keys(), key=lambda a: a.lower()): if not self.sources[kind]: continue # skip empty groups @@ -1003,7 +1000,7 @@ class _GenerateV7DSP(_DSPGenerator, _GenerateV7User): self.file.write('\t\n') - cats = sorted([k for k in list(categories.keys()) if self.sources[k]], + cats = sorted([k for k in categories.keys() if self.sources[k]], key=lambda a: a.lower()) for kind in cats: if len(cats) > 1: @@ -1348,7 +1345,7 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): 'Resource Files': 'r;rc;ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe', 'Other Files': ''} - cats = sorted([k for k in list(categories.keys()) if self.sources[k]], + cats = sorted([k for k in categories.keys() if self.sources[k]], key = lambda a: a.lower()) # print vcxproj.filters file first @@ -1505,11 +1502,7 @@ class _GenerateV7DSW(_DSWGenerator): for variant in env['variant']: AddConfig(self, variant) - self.platforms = [] - for key in list(self.configs.keys()): - platform = self.configs[key].platform - if platform not in self.platforms: - self.platforms.append(platform) + self.platforms = {p.platform for p in self.configs.values()} def GenerateProjectFilesInfo(self): for dspfile in self.dspfiles: diff --git a/src/engine/SCons/Tool/msvsTests.py b/src/engine/SCons/Tool/msvsTests.py index cc4f717..c2b5f0e 100644 --- a/src/engine/SCons/Tool/msvsTests.py +++ b/src/engine/SCons/Tool/msvsTests.py @@ -771,8 +771,8 @@ class msvsTestCase(unittest.TestCase): # Check expected result self.assertListEqual(list(genDSP.configs.keys()), list(expected_configs.keys())) - for key in list(genDSP.configs.keys()): - self.assertDictEqual(genDSP.configs[key].__dict__, expected_configs[key]) + for key, v in genDSP.configs.items(): + self.assertDictEqual(v.__dict__, expected_configs[key]) genDSP.Build() diff --git a/src/engine/SCons/Tool/packaging/ipk.py b/src/engine/SCons/Tool/packaging/ipk.py index fe3f49b..ac8b992 100644 --- a/src/engine/SCons/Tool/packaging/ipk.py +++ b/src/engine/SCons/Tool/packaging/ipk.py @@ -173,7 +173,7 @@ Description: $X_IPK_DESCRIPTION # # close all opened files - for f in list(opened_files.values()): + for f in opened_files.values(): f.close() # call a user specified function diff --git a/src/engine/SCons/Tool/packaging/rpm.py b/src/engine/SCons/Tool/packaging/rpm.py index ebaa701..db8ae24 100644 --- a/src/engine/SCons/Tool/packaging/rpm.py +++ b/src/engine/SCons/Tool/packaging/rpm.py @@ -284,7 +284,7 @@ def build_specfile_filesection(spec, files): for file in files: # build the tagset tags = {} - for k in list(supported_tags.keys()): + for k in supported_tags.keys(): try: v = file.GetTag(k) if v: diff --git a/src/engine/SCons/cpp.py b/src/engine/SCons/cpp.py index 5b35390..0c20c94 100644 --- a/src/engine/SCons/cpp.py +++ b/src/engine/SCons/cpp.py @@ -89,7 +89,7 @@ del op_list override = { 'if' : 'if(?!n?def)', } -l = [override.get(x, x) for x in list(Table.keys())] +l = [override.get(x, x) for x in Table.keys()] # Turn the list of expressions into one big honkin' regular expression @@ -268,7 +268,7 @@ class PreProcessor(object): d = { 'scons_current_file' : self.scons_current_file } - for op in list(Table.keys()): + for op in Table.keys(): d[op] = getattr(self, 'do_' + op) self.default_table = d diff --git a/src/test_interrupts.py b/src/test_interrupts.py index de18a54..8e1b379 100644 --- a/src/test_interrupts.py +++ b/src/test_interrupts.py @@ -105,7 +105,7 @@ for f in files: indent_list.append( (line_num, match.group('try_or_except') ) ) try_except_lines[match.group('indent')] = indent_list uncaught_this_file = [] - for indent in list(try_except_lines.keys()): + for indent in try_except_lines.keys(): exc_keyboardint_seen = 0 exc_all_seen = 0 for (l,statement) in try_except_lines[indent] + [(-1,indent + 'try')]: -- cgit v0.12 From ec2af8b9bb82bcdea24bbe966675db900ce71223 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Thu, 16 Jan 2020 13:24:43 -0700 Subject: [PR #3528] preserve order on two changes Per review comment - with extra caution, use an order-preserving technique rather than a non-preserving one, in case it matters. Signed-off-by: Mats Wichmann --- src/engine/SCons/Tool/msvs.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/engine/SCons/Tool/msvs.py b/src/engine/SCons/Tool/msvs.py index d923d3d..0ef4a97 100644 --- a/src/engine/SCons/Tool/msvs.py +++ b/src/engine/SCons/Tool/msvs.py @@ -578,7 +578,9 @@ class _DSPGenerator(object): for i in range(len(variants)): AddConfig(self, variants[i], buildtarget[i], outdir[i], runfile[i], cmdargs[i], cppdefines[i], cpppaths[i]) - self.platforms = {p.platform for p in self.configs.values()} + seen = set() + self.platforms = [p.platform for p in self.configs.values() + if not (p.platform in seen or seen.add(p.platform))] def Build(self): @@ -1502,7 +1504,9 @@ class _GenerateV7DSW(_DSWGenerator): for variant in env['variant']: AddConfig(self, variant) - self.platforms = {p.platform for p in self.configs.values()} + seen = set() + self.platforms = [p.platform for p in self.configs.values() + if not (p.platform in seen or seen.add(p.platform))] def GenerateProjectFilesInfo(self): for dspfile in self.dspfiles: -- cgit v0.12 From 0f83b8b27d87232e610175e1f21bee292e285456 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 21 Jan 2020 17:12:06 -0500 Subject: Add base files for new test --- test/Configure/issue-3469/fixture/SConstruct | 25 ++++++++++++++++++++++++ test/Configure/issue-3469/fixture/SConstruct.2 | 0 test/Configure/issue-3469/fixture/sconstest.skip | 0 3 files changed, 25 insertions(+) create mode 100644 test/Configure/issue-3469/fixture/SConstruct create mode 100644 test/Configure/issue-3469/fixture/SConstruct.2 create mode 100644 test/Configure/issue-3469/fixture/sconstest.skip diff --git a/test/Configure/issue-3469/fixture/SConstruct b/test/Configure/issue-3469/fixture/SConstruct new file mode 100644 index 0000000..4b5bedc --- /dev/null +++ b/test/Configure/issue-3469/fixture/SConstruct @@ -0,0 +1,25 @@ +""" +This tests if we add/remove a test in between other tests if a rerun will properly cache the results. +Github issue #3469 +""" + +DefaultEnvironment(tools=[]) + +vars = Variables() +vars.Add(BoolVariable('SKIP', 'Skip Middle Conf test', 0)) +env = Environment(variables=vars) + +conf = Configure(env) +if not conf.CheckCHeader('math.h'): + print('Math.h must be installed!') + Exit(1) + +if not env['SKIP'] and not conf.CheckCHeader('stdlib.h'): + print('stdlib.h must be installed!') + Exit(1) + +if not conf.CheckCHeader('stdio.h'): + print('stdio.h must be installed!') + Exit(1) + +env = conf.Finish() diff --git a/test/Configure/issue-3469/fixture/SConstruct.2 b/test/Configure/issue-3469/fixture/SConstruct.2 new file mode 100644 index 0000000..e69de29 diff --git a/test/Configure/issue-3469/fixture/sconstest.skip b/test/Configure/issue-3469/fixture/sconstest.skip new file mode 100644 index 0000000..e69de29 -- cgit v0.12 From 076a09f263916279c2e99e60f083bc398024d5f9 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 21 Jan 2020 17:12:15 -0500 Subject: PEP8 --- src/engine/SCons/SConf.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/engine/SCons/SConf.py b/src/engine/SCons/SConf.py index 7e35e98..624af1d 100644 --- a/src/engine/SCons/SConf.py +++ b/src/engine/SCons/SConf.py @@ -162,11 +162,14 @@ class ConfigureCacheError(SConfError): def __init__(self,target): SConfError.__init__(self, '"%s" is not yet built and cache is forced.' % str(target)) + # define actions for building text files -def _createSource( target, source, env ): +def _createSource(target, source, env): fd = open(str(target[0]), "w") fd.write(source[0].get_contents().decode()) fd.close() + + def _stringSource( target, source, env ): return (str(target[0]) + ' <-\n |' + source[0].get_contents().decode().replace( '\n', "\n |" ) ) -- cgit v0.12 From d73f92f83c78022cb35d3af4d8471afe9422c0dd Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 21 Jan 2020 17:12:56 -0500 Subject: possible second test for issue --- test/Configure/issue-3469/fixture/SConstruct.2 | 44 ++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/test/Configure/issue-3469/fixture/SConstruct.2 b/test/Configure/issue-3469/fixture/SConstruct.2 index e69de29..df07993 100644 --- a/test/Configure/issue-3469/fixture/SConstruct.2 +++ b/test/Configure/issue-3469/fixture/SConstruct.2 @@ -0,0 +1,44 @@ +""" +This tests if we add/remove a test in between other tests if a rerun will properly cache the results. +Github issue #3469 + +MongoDB's problem is on 3rd run, a check which expects it's objectfile to have a main doesn't. +This means +This one does the following. +CheckLink +CheckHeader + +""" +import textwrap + +# DefaultEnvironment(tools=[]) + +vars = Variables() +vars.Add(BoolVariable('SKIP', 'Skip Middle Conf test', 0)) +env = Environment(variables=vars) + +print("SKIP:%s" % env['SKIP']) + + +conf = Configure(env, conf_dir='conf2') + +if not env['SKIP']: + int_size = conf.CheckTypeSize('unsigned int') + print("Size:%d"%int_size) + + +if env['SKIP'] and not conf.CheckCXXHeader('math.h'): + print('Math.h must be installed!') + Exit(1) + + +# +# if not conf.CheckCHeader('stdlib.h'): +# print('stdlib.h must be installed!') +# Exit(1) +# +# if not conf.CheckCHeader('stdio.h'): +# print('stdio.h must be installed!') +# Exit(1) + +env = conf.Finish() -- cgit v0.12 From 0b2fe7e90bb21be2370cc58b6fc86aa239627a28 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 21 Jan 2020 17:13:19 -0500 Subject: PEP8 --- testing/framework/TestSCons.py | 290 +++++++++++++++++++++-------------------- 1 file changed, 148 insertions(+), 142 deletions(-) diff --git a/testing/framework/TestSCons.py b/testing/framework/TestSCons.py index a633617..ca2660c 100644 --- a/testing/framework/TestSCons.py +++ b/testing/framework/TestSCons.py @@ -49,23 +49,23 @@ if SConsVersion == '__' + 'VERSION' + '__': SConsVersion = default_version __all__.extend([ - 'TestSCons', - 'machine', - 'python', - '_exe', - '_obj', - '_shobj', - 'shobj_', - 'lib_', - '_lib', - 'dll_', - '_dll' - ]) + 'TestSCons', + 'machine', + 'python', + '_exe', + '_obj', + '_shobj', + 'shobj_', + 'lib_', + '_lib', + 'dll_', + '_dll' +]) machine_map = { - 'i686' : 'i386', - 'i586' : 'i386', - 'i486' : 'i386', + 'i686': 'i386', + 'i586': 'i386', + 'i486': 'i386', } try: @@ -88,7 +88,6 @@ lib_ = lib_prefix _dll = dll_suffix dll_ = dll_prefix - if sys.platform == 'cygwin': # On Cygwin, os.path.normcase() lies, so just report back the # fact that the underlying Win32 OS is case-insensitive. @@ -98,16 +97,17 @@ else: def case_sensitive_suffixes(s1, s2): return (os.path.normcase(s1) != os.path.normcase(s2)) - file_expr = r"""File "[^"]*", line \d+, in [^\n]+ """ + # re.escape escapes too much. def re_escape(str): - for c in '\\.[]()*+?': # Not an exhaustive list. + for c in '\\.[]()*+?': # Not an exhaustive list. str = str.replace(c, '\\' + c) return str + # # Helper functions that we use as a replacement to the default re.match # when searching for special strings in stdout/stderr. @@ -122,6 +122,7 @@ def search_re(out, l): return None + def search_re_in_list(out, l): """ Search the regular expression 'l' in each line of the given string list 'out' and return the line's index @@ -134,21 +135,26 @@ def search_re_in_list(out, l): return None + # # Helpers for handling Python version numbers # def python_version_string(): return sys.version.split()[0] + def python_minor_version_string(): return sys.version[:3] + def unsupported_python_version(version=sys.version_info): return version < python_version_unsupported + def deprecated_python_version(version=sys.version_info): return version < python_version_deprecated + if deprecated_python_version(): msg = r""" scons: warning: Support for pre-2.7.0 Python version (%s) is deprecated. @@ -187,6 +193,7 @@ def initialize_sconsflags(ignore_python_version): os.environ['SCONSFLAGS'] = ' '.join(sconsflags) return save_sconsflags + def restore_sconsflags(sconsflags): if sconsflags is None: del os.environ['SCONSFLAGS'] @@ -247,7 +254,7 @@ class TestSCons(TestCommon): elif not self.external and not os.path.isabs(kw['program']): kw['program'] = os.path.join(self.orig_cwd, kw['program']) if 'interpreter' not in kw and not os.environ.get('SCONS_EXEC'): - kw['interpreter'] = [python,] + kw['interpreter'] = [python, ] if sys.version_info[0] < 3: kw['interpreter'].append('-tt') if 'match' not in kw: @@ -365,12 +372,12 @@ class TestSCons(TestCommon): return None - def wrap_stdout(self, build_str = "", read_str = "", error = 0, cleaning = 0): + def wrap_stdout(self, build_str="", read_str="", error=0, cleaning=0): """Wraps standard output string(s) in the normal "Reading ... done" and "Building ... done" strings """ - cap,lc = [ ('Build','build'), - ('Clean','clean') ][cleaning] + cap, lc = [('Build', 'build'), + ('Clean', 'clean')][cleaning] if error: term = "scons: %sing terminated because of errors.\n" % lc else: @@ -393,30 +400,30 @@ class TestSCons(TestCommon): finally: restore_sconsflags(sconsflags) -# Modifying the options should work and ought to be simpler, but this -# class is used for more than just running 'scons' itself. If there's -# an automated way of determining whether it's running 'scons' or -# something else, this code should be resurected. -# options = kw.get('options') -# if options: -# options = [options] -# else: -# options = [] -# if self.ignore_python_version and deprecated_python_version(): -# options.append('--warn=no-python-version') -# # Provide a way to suppress or provide alternate flags for -# # TestSCons purposes by setting TESTSCONS_SCONSFLAGS. -# # (The intended use case is to set it to null when running -# # timing tests of earlier versions of SCons which don't -# # support the --warn=no-visual-c-missing warning.) -# visual_c = os.environ.get('TESTSCONS_SCONSFLAGS', -# '--warn=no-visual-c-missing') -# if visual_c: -# options.append(visual_c) -# kw['options'] = ' '.join(options) -# TestCommon.run(self, *args, **kw) - - def up_to_date(self, arguments = '.', read_str = "", **kw): + # Modifying the options should work and ought to be simpler, but this + # class is used for more than just running 'scons' itself. If there's + # an automated way of determining whether it's running 'scons' or + # something else, this code should be resurected. + # options = kw.get('options') + # if options: + # options = [options] + # else: + # options = [] + # if self.ignore_python_version and deprecated_python_version(): + # options.append('--warn=no-python-version') + # # Provide a way to suppress or provide alternate flags for + # # TestSCons purposes by setting TESTSCONS_SCONSFLAGS. + # # (The intended use case is to set it to null when running + # # timing tests of earlier versions of SCons which don't + # # support the --warn=no-visual-c-missing warning.) + # visual_c = os.environ.get('TESTSCONS_SCONSFLAGS', + # '--warn=no-visual-c-missing') + # if visual_c: + # options.append(visual_c) + # kw['options'] = ' '.join(options) + # TestCommon.run(self, *args, **kw) + + def up_to_date(self, arguments='.', read_str="", **kw): """Asserts that all of the targets listed in arguments is up to date, but does not make any assumptions on other targets. This function is most useful in conjunction with the -n option. @@ -425,14 +432,14 @@ class TestSCons(TestCommon): for arg in arguments.split(): s = s + "scons: `%s' is up to date.\n" % arg kw['arguments'] = arguments - stdout = self.wrap_stdout(read_str = read_str, build_str = s) + stdout = self.wrap_stdout(read_str=read_str, build_str=s) # Append '.*' so that timing output that comes after the # up-to-date output is okay. kw['stdout'] = re.escape(stdout) + '.*' kw['match'] = self.match_re_dotall self.run(**kw) - def not_up_to_date(self, arguments = '.', **kw): + def not_up_to_date(self, arguments='.', **kw): """Asserts that none of the targets listed in arguments is up to date, but does not make any assumptions on other targets. This function is most useful in conjunction with the -n option. @@ -440,7 +447,7 @@ class TestSCons(TestCommon): s = "" for arg in arguments.split(): s = s + "(?!scons: `%s' is up to date.)" % re.escape(arg) - s = '('+s+'[^\n]*\n)*' + s = '(' + s + '[^\n]*\n)*' kw['arguments'] = arguments stdout = re.escape(self.wrap_stdout(build_str='ARGUMENTSGOHERE')) kw['stdout'] = stdout.replace('ARGUMENTSGOHERE', s) @@ -495,22 +502,22 @@ class TestSCons(TestCommon): # no option, should get one of nothing, warning, or error warning = self.deprecated_wrap(msg) - self.run(arguments = '.', stderr = None) + self.run(arguments='.', stderr=None) stderr = self.stderr() if stderr: # most common case done first if match_re_dotall(stderr, warning): - # expected output - pass + # expected output + pass elif match_re_dotall(stderr, err_out()): - # now a fatal error; skip the rest of the tests - self.pass_test() + # now a fatal error; skip the rest of the tests + self.pass_test() else: - # test failed; have to do this by hand... - print(self.banner('STDOUT ')) - print(self.stdout()) - print(self.diff(warning, stderr, 'STDERR ')) - self.fail_test() + # test failed; have to do this by hand... + print(self.banner('STDOUT ')) + print(self.stdout()) + print(self.diff(warning, stderr, 'STDERR ')) + self.fail_test() return warning @@ -529,14 +536,14 @@ class TestSCons(TestCommon): def RunPair(option, expected): # run the same test with the option on the command line and # then with the option passed via SetOption(). - self.run(options = '--warn=' + option, - arguments = '.', - stderr = expected, - match = match_re_dotall) - self.run(options = 'WARN=' + option, - arguments = '.', - stderr = expected, - match = match_re_dotall) + self.run(options='--warn=' + option, + arguments='.', + stderr=expected, + match=match_re_dotall) + self.run(options='WARN=' + option, + arguments='.', + stderr=expected, + match=match_re_dotall) # all warnings off, should get no output RunPair('no-deprecated', '') @@ -557,8 +564,8 @@ class TestSCons(TestCommon): return "Actual did not match expect at char %d:\n" \ " Expect: %s\n" \ " Actual: %s\n" \ - % (i, repr(expect[i-prelen:i+postlen]), - repr(actual[i-prelen:i+postlen])) + % (i, repr(expect[i - prelen:i + postlen]), + repr(actual[i - prelen:i + postlen])) i = i + 1 return "Actual matched the expected output???" @@ -579,14 +586,14 @@ class TestSCons(TestCommon): # traceback seems to be stable, so let's just format # an appropriate string # - #exec('import traceback; x = traceback.format_stack()[-1]') + # exec('import traceback; x = traceback.format_stack()[-1]') # import traceback # x = traceback.format_stack() # x = # XXX: .lstrip() # x = x.replace('', file) # x = x.replace('line 1,', 'line %s,' % line) # x="\n".join(x) - x='File "%s", line %s, in \n'%(file,line) + x = 'File "%s", line %s, in \n' % (file, line) return x def normalize_ps(self, s): @@ -613,13 +620,13 @@ class TestSCons(TestCommon): def normalize_pdf(self, s): s = self.to_bytes_re_sub(r'/(Creation|Mod)Date \(D:[^)]*\)', - r'/\1Date (D:XXXX)', s) + r'/\1Date (D:XXXX)', s) s = self.to_bytes_re_sub(r'/ID \[<[0-9a-fA-F]*> <[0-9a-fA-F]*>\]', - r'/ID [ ]', s) + r'/ID [ ]', s) s = self.to_bytes_re_sub(r'/(BaseFont|FontName) /[A-Z]{6}', - r'/\1 /XXXXXX', s) + r'/\1 /XXXXXX', s) s = self.to_bytes_re_sub(r'/Length \d+ *\n/Filter /FlateDecode\n', - r'/Length XXXX\n/Filter /FlateDecode\n', s) + r'/Length XXXX\n/Filter /FlateDecode\n', s) try: import zlib @@ -643,11 +650,11 @@ class TestSCons(TestCommon): r.append(s[x:b]) d = zlib.decompress(s[b:e]) d = self.to_bytes_re_sub(r'%%CreationDate: [^\n]*\n', - r'%%CreationDate: 1970 Jan 01 00:00:00\n', d) + r'%%CreationDate: 1970 Jan 01 00:00:00\n', d) d = self.to_bytes_re_sub(r'%DVIPSSource: TeX output \d\d\d\d\.\d\d\.\d\d:\d\d\d\d', - r'%DVIPSSource: TeX output 1970.01.01:0000', d) + r'%DVIPSSource: TeX output 1970.01.01:0000', d) d = self.to_bytes_re_sub(r'/(BaseFont|FontName) /[A-Z]{6}', - r'/\1 /XXXXXX', d) + r'/\1 /XXXXXX', d) r.append(d) x = e r.append(s[x:]) @@ -655,14 +662,14 @@ class TestSCons(TestCommon): return s - def paths(self,patterns): + def paths(self, patterns): import glob result = [] for p in patterns: result.extend(sorted(glob.glob(p))) return result - def unlink_sconsignfile(self,name='.sconsign.dblite'): + def unlink_sconsignfile(self, name='.sconsign.dblite'): """ Delete sconsign file. Note on python it seems to append .p3 to the file name so we take care of that @@ -728,7 +735,7 @@ class TestSCons(TestCommon): return None - def java_where_includes(self,version=None): + def java_where_includes(self, version=None): """ Find include path needed for compiling java jni code. @@ -740,30 +747,30 @@ class TestSCons(TestCommon): result = [] if sys.platform[:6] == 'darwin': java_home = self.java_where_java_home(version) - jni_path = os.path.join(java_home,'include','jni.h') + jni_path = os.path.join(java_home, 'include', 'jni.h') if os.path.exists(jni_path): result.append(os.path.dirname(jni_path)) if not version: - version='' + version = '' jni_dirs = ['/System/Library/Frameworks/JavaVM.framework/Headers/jni.h', '/usr/lib/jvm/default-java/include/jni.h', '/usr/lib/jvm/java-*-oracle/include/jni.h'] else: - jni_dirs = ['/System/Library/Frameworks/JavaVM.framework/Versions/%s*/Headers/jni.h'%version] - jni_dirs.extend(['/usr/lib/jvm/java-*-sun-%s*/include/jni.h'%version, - '/usr/lib/jvm/java-%s*-openjdk*/include/jni.h'%version, - '/usr/java/jdk%s*/include/jni.h'%version]) + jni_dirs = ['/System/Library/Frameworks/JavaVM.framework/Versions/%s*/Headers/jni.h' % version] + jni_dirs.extend(['/usr/lib/jvm/java-*-sun-%s*/include/jni.h' % version, + '/usr/lib/jvm/java-%s*-openjdk*/include/jni.h' % version, + '/usr/java/jdk%s*/include/jni.h' % version]) dirs = self.paths(jni_dirs) if not dirs: return None - d=os.path.dirname(self.paths(jni_dirs)[0]) + d = os.path.dirname(self.paths(jni_dirs)[0]) result.append(d) if sys.platform == 'win32': - result.append(os.path.join(d,'win32')) + result.append(os.path.join(d, 'win32')) elif sys.platform.startswith('linux'): - result.append(os.path.join(d,'linux')) + result.append(os.path.join(d, 'linux')) return result def java_where_java_home(self, version=None): @@ -788,14 +795,14 @@ class TestSCons(TestCommon): return java_home else: homes = ['/System/Library/Frameworks/JavaVM.framework/Home', - # osx 10.10 + # osx 10.10 '/System/Library/Frameworks/JavaVM.framework/Versions/Current/Home'] for home in homes: if os.path.exists(home): return home else: - if java_home.find('jdk%s'%version) != -1: + if java_home.find('jdk%s' % version) != -1: return java_home else: home = '/System/Library/Frameworks/JavaVM.framework/Versions/%s/Home' % version @@ -804,7 +811,7 @@ class TestSCons(TestCommon): home = '/System/Library/Frameworks/JavaVM.framework/Versions/Current/' else: jar = self.java_where_jar(version) - home = os.path.normpath('%s/..'%jar) + home = os.path.normpath('%s/..' % jar) if os.path.isdir(home): return home print("Could not determine JAVA_HOME: %s is not a directory" % home) @@ -873,8 +880,8 @@ class TestSCons(TestCommon): elif sys.platform == "darwin": self.java_mac_check(where_javac, 'javac') - self.run(program = where_javac, - arguments = '-version', + self.run(program=where_javac, + arguments='-version', stderr=None, status=None) # Note recent versions output version info to stdout instead of stderr @@ -893,7 +900,7 @@ class TestSCons(TestCommon): version = m.group(1) self.javac_is_gcj = False elif self.stderr().find('gcj') != -1: - version='1.2' + version = '1.2' self.javac_is_gcj = True else: version = None @@ -936,7 +943,6 @@ class TestSCons(TestCommon): self.skip_test("Could not find Java rmic, skipping non-simulated test(s).\n") return where_rmic - def java_get_class_files(self, dir): result = [] for dirpath, dirnames, filenames in os.walk(dir): @@ -945,7 +951,6 @@ class TestSCons(TestCommon): result.append(os.path.join(dirpath, fname)) return sorted(result) - def Qt_dummy_installation(self, dir='qt'): # create a dummy qt installation @@ -1016,7 +1021,7 @@ with open(outfile, 'w') as ofp, open(source, 'r') as ifp: else: ofp.write('#include "my_qobject.h"\\n' + ifp.read() + " Q_OBJECT \\n") sys.exit(0) -""" ) +""") self.write([dir, 'include', 'my_qobject.h'], r""" #define Q_OBJECT ; @@ -1040,10 +1045,10 @@ else: env.SharedLibrary('myqt', 'my_qobject.cpp') """) - self.run(chdir = self.workpath(dir, 'lib'), - arguments = '.', - stderr = noisy_ar, - match = self.match_re_dotall) + self.run(chdir=self.workpath(dir, 'lib'), + arguments='.', + stderr=noisy_ar, + match=self.match_re_dotall) self.QT = self.workpath(dir) self.QT_LIB = 'myqt' @@ -1083,11 +1088,10 @@ Export("env dup") SConscript(sconscript) """ % (self.QT, self.QT_LIB, self.QT_MOC, self.QT_UIC)) - - NCR = 0 # non-cached rebuild - CR = 1 # cached rebuild (up to date) - NCF = 2 # non-cached build failure - CF = 3 # cached build failure + NCR = 0 # non-cached rebuild + CR = 1 # cached rebuild (up to date) + NCF = 2 # non-cached build failure + CF = 3 # cached build failure if sys.platform == 'win32': Configure_lib = 'msvcrt' @@ -1095,7 +1099,7 @@ SConscript(sconscript) Configure_lib = 'm' # to use cygwin compilers on cmd.exe -> uncomment following line - #Configure_lib = 'm' + # Configure_lib = 'm' def coverage_run(self): """ Check if the the tests are being run under coverage. @@ -1205,7 +1209,7 @@ SConscript(sconscript) # sys.stderr.write("LOGFILE[%s]:%s"%(type(logfile),logfile)) if (doCheckLog and - logfile.find("scons: warning: The stored build information has an unexpected class.") >= 0): + logfile.find("scons: warning: The stored build information has an unexpected class.") >= 0): self.fail_test() sconf_dir = sconf_dir @@ -1221,53 +1225,53 @@ SConscript(sconscript) rdstr = "" cnt = 0 - for check,result,cache_desc in zip(checks, results, cached): - log = re.escape("scons: Configure: " + check) + ls + for check, result, cache_desc in zip(checks, results, cached): + log = re.escape("scons: Configure: " + check) + ls if doCheckLog: lastEnd = matchPart(log, logfile, lastEnd) log = "" result_cached = 1 - for bld_desc in cache_desc: # each TryXXX - for ext, flag in bld_desc: # each file in TryBuild - file = os.path.join(sconf_dir,"conftest_%d%s" % (cnt, ext)) + for bld_desc in cache_desc: # each TryXXX + for ext, flag in bld_desc: # each file in TryBuild + conf_filename = os.path.join(sconf_dir, "conftest_%d%s" % (cnt, ext)) if flag == self.NCR: # NCR = Non Cached Rebuild # rebuild will pass if ext in ['.c', '.cpp']: - log=log + re.escape(file + " <-") + ls - log=log + r"( \|" + nols + "*" + ls + ")+?" + log = log + re.escape(conf_filename + " <-") + ls + log = log + r"( \|" + nols + "*" + ls + ")+?" else: - log=log + "(" + nols + "*" + ls +")*?" + log = log + "(" + nols + "*" + ls + ")*?" result_cached = 0 if flag == self.CR: # CR = cached rebuild (up to date)s # up to date - log=log + \ - re.escape("scons: Configure: \"%s\" is up to date." - % file) + ls - log=log+re.escape("scons: Configure: The original builder " - "output was:") + ls - log=log+r"( \|.*"+ls+")+" + log = log + \ + re.escape("scons: Configure: \"%s\" is up to date." + % conf_filename) + ls + log = log + re.escape("scons: Configure: The original builder " + "output was:") + ls + log = log + r"( \|.*" + ls + ")+" if flag == self.NCF: # non-cached rebuild failure - log=log + "(" + nols + "*" + ls + ")*?" + log = log + "(" + nols + "*" + ls + ")*?" result_cached = 0 if flag == self.CF: # cached rebuild failure - log=log + \ - re.escape("scons: Configure: Building \"%s\" failed " - "in a previous run and all its sources are" - " up to date." % file) + ls - log=log+re.escape("scons: Configure: The original builder " - "output was:") + ls - log=log+r"( \|.*"+ls+")+" + log = log + \ + re.escape("scons: Configure: Building \"%s\" failed " + "in a previous run and all its sources are" + " up to date." % conf_filename) + ls + log = log + re.escape("scons: Configure: The original builder " + "output was:") + ls + log = log + r"( \|.*" + ls + ")+" cnt = cnt + 1 if result_cached: result = "(cached) " + result rdstr = rdstr + re.escape(check) + re.escape(result) + "\n" - log=log + re.escape("scons: Configure: " + result) + ls + ls + log = log + re.escape("scons: Configure: " + result) + ls + ls if doCheckLog: lastEnd = matchPart(log, logfile, lastEnd) @@ -1435,7 +1439,7 @@ else: files with .C and .c as different files or not in which case they are instructed to use .cpp instead of .C """ - if not case_sensitive_suffixes('.c','.C'): + if not case_sensitive_suffixes('.c', '.C'): alt_cpp_suffix = '.cpp' else: alt_cpp_suffix = '.C' @@ -1457,6 +1461,7 @@ class Stat: self.expression = re.compile(expression) self.convert = convert + StatList = [ Stat('memory-initial', 'kbytes', r'Memory before reading SConscript files:\s+(\d+)', @@ -1481,6 +1486,7 @@ StatList = [ class TimeSCons(TestSCons): """Class for timing SCons.""" + def __init__(self, *args, **kw): """ In addition to normal TestSCons.TestSCons intialization, @@ -1563,7 +1569,7 @@ class TimeSCons(TestSCons): fmt = "TRACE: graph=%s name=%s value=%s units=%s" line = fmt % (graph, name, value, units) if sort is not None: - line = line + (' sort=%s' % sort) + line = line + (' sort=%s' % sort) line = line + '\n' sys.stdout.write(line) sys.stdout.flush() @@ -1585,9 +1591,9 @@ class TimeSCons(TestSCons): else: avg1, avg5, avg15 = fp.readline().split(" ")[:3] fp.close() - self.trace('load-average', 'average1', avg1, 'processes') - self.trace('load-average', 'average5', avg5, 'processes') - self.trace('load-average', 'average15', avg15, 'processes') + self.trace('load-average', 'average1', avg1, 'processes') + self.trace('load-average', 'average5', avg5, 'processes') + self.trace('load-average', 'average15', avg15, 'processes') def collect_stats(self, input): result = {} @@ -1598,7 +1604,7 @@ class TimeSCons(TestSCons): # The dict keys match the keyword= arguments # of the trace() method above so they can be # applied directly to that call. - result[stat.name] = {'value':value, 'units':stat.units} + result[stat.name] = {'value': value, 'units': stat.units} return result def add_timing_options(self, kw, additional=None): @@ -1713,8 +1719,8 @@ class TimeSCons(TestSCons): for root, dirs, files in os.walk(source_dir): if '.svn' in dirs: dirs.remove('.svn') - dirs = [ d for d in dirs if not d.startswith('TimeSCons-') ] - files = [ f for f in files if not f.startswith('TimeSCons-') ] + dirs = [d for d in dirs if not d.startswith('TimeSCons-')] + files = [f for f in files if not f.startswith('TimeSCons-')] for dirname in dirs: source = os.path.join(root, dirname) destination = source.replace(source_dir, dest_dir) @@ -1736,7 +1742,7 @@ class TimeSCons(TestSCons): # " messages to be successful executions of the test (see # test/AR.py for sample usage). -noisy_ar=r'(ar: creating( archive)? \S+\n?)*' +noisy_ar = r'(ar: creating( archive)? \S+\n?)*' # Local Variables: # tab-width:4 -- cgit v0.12 From 0e7769d0eaa72c471cb3ca76ec57841956f9bdfe Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 22 Jan 2020 15:18:41 -0500 Subject: Updated TestSCons and test/Configure/option--config.py to work with new configure temporary file naming via content and action hash --- src/engine/SCons/SConf.py | 2 +- test/Configure/option--config.py | 125 +++++++++++++++-------- testing/framework/TestSCons.py | 214 ++++++++++++++++++++++++++++++++++----- 3 files changed, 272 insertions(+), 69 deletions(-) diff --git a/src/engine/SCons/SConf.py b/src/engine/SCons/SConf.py index 624af1d..b2a6357 100644 --- a/src/engine/SCons/SConf.py +++ b/src/engine/SCons/SConf.py @@ -616,7 +616,7 @@ class SConfBase(object): target = None action = builder.builder.action.get_contents(target=target, source=[source], env=self.env) - actionsig = str(SCons.Util.MD5signature(action)) + actionsig = SCons.Util.MD5signature(action) f = "_".join([f, actionsig]) pref = self.env.subst( builder.builder.prefix ) diff --git a/test/Configure/option--config.py b/test/Configure/option--config.py index 838409d..412720d 100644 --- a/test/Configure/option--config.py +++ b/test/Configure/option--config.py @@ -30,11 +30,10 @@ Verify use of the --config= option. import os.path -import TestSCons +from TestSCons import TestSCons, ConfigCheckInfo, _obj -_obj = TestSCons._obj - -test = TestSCons.TestSCons() +test = TestSCons() +# test.verbose_set(1) test.subdir('include') @@ -59,7 +58,8 @@ test.write(['include', 'non_system_header0.h'], """ /* A header */ """) -conftest_0_c = os.path.join(".sconf_temp", "conftest_0.c") +file_hash = 'cda36b76729ffb03bf36a48d13b2d98d' +conftest_0_c = os.path.join(".sconf_temp", "conftest_%s_0.c"%file_hash) SConstruct_file_line = test.python_file_line(SConstruct_path, 6)[:-1] expect = """ @@ -70,36 +70,63 @@ scons: *** "%(conftest_0_c)s" is not yet built and cache is forced. test.run(arguments='--config=cache', status=2, stderr=expect) test.run(arguments='--config=auto') -test.checkLogAndStdout(["Checking for C header file non_system_header0.h... ", - "Checking for C header file non_system_header1.h... "], - ["yes", "no"], - [[((".c", NCR), (_obj, NCR))], - [((".c", NCR), (_obj, NCF))]], - "config.log", ".sconf_temp", "SConstruct") +test.checkConfigureLogAndStdout(checks=[ + ConfigCheckInfo("Checking for C header file non_system_header0.h... ", + 'yes', [((".c", NCR), (_obj, NCR))], + 'conftest_cda36b76729ffb03bf36a48d13b2d98d_0%s' + ), + ConfigCheckInfo("Checking for C header file non_system_header1.h... ", + 'no', [((".c", NCR), (_obj, NCF))], + 'conftest_acc476a565a3f6d5d67ddc21f187d062_0%s')] +) test.run(arguments='--config=auto') -test.checkLogAndStdout(["Checking for C header file non_system_header0.h... ", - "Checking for C header file non_system_header1.h... "], - ["yes", "no"], - [[((".c", CR), (_obj, CR))], - [((".c", CR), (_obj, CF))]], - "config.log", ".sconf_temp", "SConstruct") +test.checkConfigureLogAndStdout(checks=[ + ConfigCheckInfo("Checking for C header file non_system_header0.h... ", + 'yes', + [((".c", CR), + ('_9b191e4c46e9d6ba17c8cd4d730900cf'+_obj, CR))], + 'conftest_cda36b76729ffb03bf36a48d13b2d98d_0%s' + ), + ConfigCheckInfo("Checking for C header file non_system_header1.h... ", + 'no', + [((".c", CR), + ('_b9da1a844a8707269188b28a62c0d83e'+_obj, CF))], + 'conftest_acc476a565a3f6d5d67ddc21f187d062_0%s')] +) + test.run(arguments='--config=force') -test.checkLogAndStdout(["Checking for C header file non_system_header0.h... ", - "Checking for C header file non_system_header1.h... "], - ["yes", "no"], - [[((".c", NCR), (_obj, NCR))], - [((".c", NCR), (_obj, NCF))]], - "config.log", ".sconf_temp", "SConstruct") +test.checkConfigureLogAndStdout(checks=[ + ConfigCheckInfo("Checking for C header file non_system_header0.h... ", + 'yes', + [((".c", NCR), + ('_9b191e4c46e9d6ba17c8cd4d730900cf'+_obj, NCR))], + 'conftest_cda36b76729ffb03bf36a48d13b2d98d_0%s' + ), + ConfigCheckInfo("Checking for C header file non_system_header1.h... ", + 'no', + [((".c", NCR), + ('_b9da1a844a8707269188b28a62c0d83e'+_obj, NCF))], + 'conftest_acc476a565a3f6d5d67ddc21f187d062_0%s')] +) + test.run(arguments='--config=cache') -test.checkLogAndStdout(["Checking for C header file non_system_header0.h... ", - "Checking for C header file non_system_header1.h... "], - ["yes", "no"], - [[((".c", CR), (_obj, CR))], - [((".c", CR), (_obj, CF))]], - "config.log", ".sconf_temp", "SConstruct") +test.checkConfigureLogAndStdout(checks=[ + ConfigCheckInfo("Checking for C header file non_system_header0.h... ", + 'yes', + [((".c", CR), + ('_9b191e4c46e9d6ba17c8cd4d730900cf'+_obj, CR))], + 'conftest_cda36b76729ffb03bf36a48d13b2d98d_0%s' + ), + ConfigCheckInfo("Checking for C header file non_system_header1.h... ", + 'no', + [((".c", CR), + ('_b9da1a844a8707269188b28a62c0d83e'+_obj, CF))], + 'conftest_acc476a565a3f6d5d67ddc21f187d062_0%s')] +) + test.write(['include', 'non_system_header1.h'], """ /* Another header */ @@ -107,21 +134,35 @@ test.write(['include', 'non_system_header1.h'], """ test.unlink(['include', 'non_system_header0.h']) test.run(arguments='--config=cache') -test.checkLogAndStdout(["Checking for C header file non_system_header0.h... ", - "Checking for C header file non_system_header1.h... "], - ["yes", "no"], - [[((".c", CR), (_obj, CR))], - [((".c", CR), (_obj, CF))]], - "config.log", ".sconf_temp", "SConstruct") -test.run(arguments='--config=auto') -test.checkLogAndStdout(["Checking for C header file non_system_header0.h... ", - "Checking for C header file non_system_header1.h... "], - ["no", "yes"], - [[((".c", CR), (_obj, NCF))], - [((".c", CR), (_obj, NCR))]], - "config.log", ".sconf_temp", "SConstruct") +test.checkConfigureLogAndStdout(checks=[ + ConfigCheckInfo("Checking for C header file non_system_header0.h... ", + 'yes', + [((".c", CR), + ('_9b191e4c46e9d6ba17c8cd4d730900cf'+_obj, CR))], + 'conftest_cda36b76729ffb03bf36a48d13b2d98d_0%s' + ), + ConfigCheckInfo("Checking for C header file non_system_header1.h... ", + 'no', + [((".c", CR), + ('_b9da1a844a8707269188b28a62c0d83e'+_obj, CF))], + 'conftest_acc476a565a3f6d5d67ddc21f187d062_0%s')] +) +test.run(arguments='--config=auto') +test.checkConfigureLogAndStdout(checks=[ + ConfigCheckInfo("Checking for C header file non_system_header0.h... ", + 'no', + [((".c", CR), + ('_9b191e4c46e9d6ba17c8cd4d730900cf'+_obj, NCF))], + 'conftest_cda36b76729ffb03bf36a48d13b2d98d_0%s' + ), + ConfigCheckInfo("Checking for C header file non_system_header1.h... ", + 'yes', + [((".c", CR), + ('_b9da1a844a8707269188b28a62c0d83e'+_obj, NCR))], + 'conftest_acc476a565a3f6d5d67ddc21f187d062_0%s')] +) test.file_fixture('test_main.c') diff --git a/testing/framework/TestSCons.py b/testing/framework/TestSCons.py index ca2660c..e3f4f47 100644 --- a/testing/framework/TestSCons.py +++ b/testing/framework/TestSCons.py @@ -23,6 +23,7 @@ import shutil import sys import time import subprocess +from collections import namedtuple from TestCommon import * from TestCommon import __all__ @@ -201,6 +202,34 @@ def restore_sconsflags(sconsflags): os.environ['SCONSFLAGS'] = sconsflags +# Helpers for Configure()'s config.log processing +ConfigCheckInfo = namedtuple('ConfigCheckInfo', + ['check_string', 'result', 'cached', 'temp_filename']) +# check_string: the string output to for this checker +# results : The expected results for each check +# cached : If the corresponding check is expected to be cached +# temp_filename : The name of the generated tempfile for this check + + +class NoMatch(Exception): + """ + Exception for matchPart to indicate there was no match found in the passed logfile + """ + def __init__(self, p): + self.pos = p + + +def match_part_of_configlog(log, logfile, lastEnd, NoMatch=NoMatch): + """ + Match part of the logfile + """ + print("Match:\n%s\n==============\n%s" % (log , logfile[lastEnd:])) + m = re.match(log, logfile[lastEnd:]) + if not m: + raise NoMatch(lastEnd) + return m.end() + lastEnd + + class TestSCons(TestCommon): """Class for testing SCons. @@ -1129,6 +1158,145 @@ SConscript(sconscript) except: pass + def checkConfigureLogAndStdout(self, checks, + logfile='config.log', + sconf_dir='.sconf_temp', + sconstruct="SConstruct", + doCheckLog=True, doCheckStdout=True): + """ + Used to verify the expected output from using Configure() + via the contents of one or both of stdout or config.log file. + The checks, results, cached parameters all are zipped together + for use in comparing results. + + TODO: Perhaps a better API makes sense? + + Parameters + ---------- + checks : list of ConfigCheckInfo tuples which specify + logfile : Name of the config log + sconf_dir : Name of the sconf dir + sconstruct : SConstruct file name + doCheckLog : check specified log file, defaults to true + doCheckStdout : Check stdout, defaults to true + + Returns + ------- + + """ + + + try: + ls = '\n' + nols = '([^\n])' + lastEnd = 0 + + # Read the whole logfile + logfile = self.read(self.workpath(logfile), mode='r') + + # Some debug code to keep around.. + # sys.stderr.write("LOGFILE[%s]:%s"%(type(logfile),logfile)) + + if (doCheckLog and + logfile.find("scons: warning: The stored build information has an unexpected class.") >= 0): + self.fail_test() + + log = r'file\ \S*%s\,line \d+:' % re.escape(sconstruct) + ls + if doCheckLog: + lastEnd = match_part_of_configlog(log, logfile, lastEnd) + + log = "\t" + re.escape("Configure(confdir = %s)" % sconf_dir) + ls + if doCheckLog: + lastEnd = match_part_of_configlog(log, logfile, lastEnd) + + rdstr = "" + + for check_info in checks: + log = re.escape("scons: Configure: " + check_info.check_string) + ls + + if doCheckLog: + lastEnd = match_part_of_configlog(log, logfile, lastEnd) + + log = "" + result_cached = 1 + for bld_desc in check_info.cached: # each TryXXX + for ext, flag in bld_desc: # each file in TryBuild + conf_filename = re.escape(os.path.join(sconf_dir, check_info.temp_filename%ext)) + + if flag == self.NCR: + # NCR = Non Cached Rebuild + # rebuild will pass + if ext in ['.c', '.cpp']: + log = log + conf_filename + re.escape(" <-") + ls + log = log + r"( \|" + nols + "*" + ls + ")+?" + else: + log = log + "(" + nols + "*" + ls + ")*?" + result_cached = 0 + if flag == self.CR: + # CR = cached rebuild (up to date)s + # up to date + log = log + \ + re.escape("scons: Configure: \"") + \ + conf_filename + \ + re.escape("\" is up to date.") + ls + log = log + re.escape("scons: Configure: The original builder " + "output was:") + ls + log = log + r"( \|.*" + ls + ")+" + if flag == self.NCF: + # non-cached rebuild failure + log = log + "(" + nols + "*" + ls + ")*?" + result_cached = 0 + if flag == self.CF: + # cached rebuild failure + log = log + \ + re.escape("scons: Configure: Building \"") + \ + conf_filename + \ + re.escape("\" failed in a previous run and all its sources are up to date.") + ls + log = log + re.escape("scons: Configure: The original builder output was:") + ls + log = log + r"( \|.*" + ls + ")+" + if result_cached: + result = "(cached) " + check_info.result + else: + result = check_info.result + rdstr = rdstr + re.escape(check_info.check_string) + re.escape(result) + "\n" + + log = log + re.escape("scons: Configure: " + result) + ls + ls + + if doCheckLog: + lastEnd = match_part_of_configlog(log, logfile, lastEnd) + + log = "" + if doCheckLog: + lastEnd = match_part_of_configlog(ls, logfile, lastEnd) + + if doCheckLog and lastEnd != len(logfile): + raise NoMatch(lastEnd) + + except NoMatch as m: + print("Cannot match log file against log regexp.") + print("log file: ") + print("------------------------------------------------------") + print(logfile[m.pos:]) + print("------------------------------------------------------") + print("log regexp: ") + print("------------------------------------------------------") + print(log) + print("------------------------------------------------------") + self.fail_test() + + if doCheckStdout: + exp_stdout = self.wrap_stdout(".*", rdstr) + if not self.match_re_dotall(self.stdout(), exp_stdout): + print("Unexpected stdout: ") + print("-----------------------------------------------------") + print(repr(self.stdout())) + print("-----------------------------------------------------") + print(repr(exp_stdout)) + print("-----------------------------------------------------") + self.fail_test() + + + def checkLogAndStdout(self, checks, results, cached, logfile, sconf_dir, sconstruct, doCheckLog=True, doCheckStdout=True): @@ -1163,18 +1331,6 @@ SConscript(sconscript) """ - class NoMatch(Exception): - def __init__(self, p): - self.pos = p - - def matchPart(log, logfile, lastEnd, NoMatch=NoMatch): - """ - Match part of the logfile - """ - m = re.match(log, logfile[lastEnd:]) - if not m: - raise NoMatch(lastEnd) - return m.end() + lastEnd try: @@ -1217,30 +1373,33 @@ SConscript(sconscript) log = r'file\ \S*%s\,line \d+:' % re.escape(sconstruct) + ls if doCheckLog: - lastEnd = matchPart(log, logfile, lastEnd) + lastEnd = match_part_of_configlog(log, logfile, lastEnd) log = "\t" + re.escape("Configure(confdir = %s)" % sconf_dir) + ls if doCheckLog: - lastEnd = matchPart(log, logfile, lastEnd) + lastEnd = match_part_of_configlog(log, logfile, lastEnd) rdstr = "" + cnt = 0 for check, result, cache_desc in zip(checks, results, cached): log = re.escape("scons: Configure: " + check) + ls if doCheckLog: - lastEnd = matchPart(log, logfile, lastEnd) + lastEnd = match_part_of_configlog(log, logfile, lastEnd) log = "" result_cached = 1 for bld_desc in cache_desc: # each TryXXX for ext, flag in bld_desc: # each file in TryBuild - conf_filename = os.path.join(sconf_dir, "conftest_%d%s" % (cnt, ext)) + conf_filename = re.escape(os.path.join(sconf_dir, "conftest")) +\ + r'_[a-z0-9]{32}_%d' % cnt + re.escape(ext) + if flag == self.NCR: # NCR = Non Cached Rebuild # rebuild will pass if ext in ['.c', '.cpp']: - log = log + re.escape(conf_filename + " <-") + ls + log = log + conf_filename + re.escape(" <-") + ls log = log + r"( \|" + nols + "*" + ls + ")+?" else: log = log + "(" + nols + "*" + ls + ")*?" @@ -1249,8 +1408,9 @@ SConscript(sconscript) # CR = cached rebuild (up to date)s # up to date log = log + \ - re.escape("scons: Configure: \"%s\" is up to date." - % conf_filename) + ls + re.escape("scons: Configure: \"") + \ + conf_filename + \ + re.escape("\" is up to date.") + ls log = log + re.escape("scons: Configure: The original builder " "output was:") + ls log = log + r"( \|.*" + ls + ")+" @@ -1261,23 +1421,25 @@ SConscript(sconscript) if flag == self.CF: # cached rebuild failure log = log + \ - re.escape("scons: Configure: Building \"%s\" failed " - "in a previous run and all its sources are" - " up to date." % conf_filename) + ls - log = log + re.escape("scons: Configure: The original builder " - "output was:") + ls + re.escape("scons: Configure: Building \"") + \ + conf_filename + \ + re.escape("\" failed in a previous run and all its sources are up to date.") + ls + log = log + re.escape("scons: Configure: The original builder output was:") + ls log = log + r"( \|.*" + ls + ")+" cnt = cnt + 1 if result_cached: result = "(cached) " + result rdstr = rdstr + re.escape(check) + re.escape(result) + "\n" + log = log + re.escape("scons: Configure: " + result) + ls + ls if doCheckLog: - lastEnd = matchPart(log, logfile, lastEnd) + lastEnd = match_part_of_configlog(log, logfile, lastEnd) log = "" - if doCheckLog: lastEnd = matchPart(ls, logfile, lastEnd) + if doCheckLog: + lastEnd = match_part_of_configlog(ls, logfile, lastEnd) + if doCheckLog and lastEnd != len(logfile): raise NoMatch(lastEnd) -- cgit v0.12 From f05685d70f12fa192c8cdeb8f4752b6af55beb24 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 22 Jan 2020 16:25:32 -0500 Subject: updates to make tests pass on windows --- test/Configure/option--config.py | 69 +++++++++++++++++++++++++--------------- testing/framework/TestSCons.py | 2 +- 2 files changed, 44 insertions(+), 27 deletions(-) diff --git a/test/Configure/option--config.py b/test/Configure/option--config.py index 412720d..8b23496 100644 --- a/test/Configure/option--config.py +++ b/test/Configure/option--config.py @@ -31,6 +31,7 @@ Verify use of the --config= option. import os.path from TestSCons import TestSCons, ConfigCheckInfo, _obj +from TestCmd import IS_WINDOWS test = TestSCons() # test.verbose_set(1) @@ -58,8 +59,20 @@ test.write(['include', 'non_system_header0.h'], """ /* A header */ """) -file_hash = 'cda36b76729ffb03bf36a48d13b2d98d' -conftest_0_c = os.path.join(".sconf_temp", "conftest_%s_0.c"%file_hash) +conftest_0_c_hash = 'cda36b76729ffb03bf36a48d13b2d98d' +conftest_1_c_hash = 'acc476a565a3f6d5d67ddc21f187d062' + +if IS_WINDOWS: + conftest_0_obj_suffix = '_213c72f9eb682c6f27f2eb78ed8bd57a'+_obj + conftest_1_obj_suffix = '_7c505229a64dccfea6e7cfdffe76bd2a'+_obj +else: + conftest_0_obj_suffix = '_9b191e4c46e9d6ba17c8cd4d730900cf'+_obj + conftest_1_obj_suffix = '_b9da1a844a8707269188b28a62c0d83e'+_obj + +conftest_0_base = os.path.join(".sconf_temp", "conftest_%s_0%%s"%conftest_0_c_hash) +conftest_0_c = conftest_0_base%'.c' +conftest_1_base = os.path.join(".sconf_temp", "conftest_%s_0%%s"%conftest_1_c_hash) + SConstruct_file_line = test.python_file_line(SConstruct_path, 6)[:-1] expect = """ @@ -72,12 +85,16 @@ test.run(arguments='--config=cache', status=2, stderr=expect) test.run(arguments='--config=auto') test.checkConfigureLogAndStdout(checks=[ ConfigCheckInfo("Checking for C header file non_system_header0.h... ", - 'yes', [((".c", NCR), (_obj, NCR))], - 'conftest_cda36b76729ffb03bf36a48d13b2d98d_0%s' + 'yes', + [((".c", NCR), + (_obj, NCR))], + conftest_0_base ), ConfigCheckInfo("Checking for C header file non_system_header1.h... ", - 'no', [((".c", NCR), (_obj, NCF))], - 'conftest_acc476a565a3f6d5d67ddc21f187d062_0%s')] + 'no', + [((".c", NCR), + (_obj, NCF))], + conftest_1_base)] ) test.run(arguments='--config=auto') @@ -85,14 +102,14 @@ test.checkConfigureLogAndStdout(checks=[ ConfigCheckInfo("Checking for C header file non_system_header0.h... ", 'yes', [((".c", CR), - ('_9b191e4c46e9d6ba17c8cd4d730900cf'+_obj, CR))], - 'conftest_cda36b76729ffb03bf36a48d13b2d98d_0%s' + (conftest_0_obj_suffix, CR))], + conftest_0_base, ), ConfigCheckInfo("Checking for C header file non_system_header1.h... ", 'no', [((".c", CR), - ('_b9da1a844a8707269188b28a62c0d83e'+_obj, CF))], - 'conftest_acc476a565a3f6d5d67ddc21f187d062_0%s')] + (conftest_1_obj_suffix, CF))], + conftest_1_base)] ) @@ -101,14 +118,14 @@ test.checkConfigureLogAndStdout(checks=[ ConfigCheckInfo("Checking for C header file non_system_header0.h... ", 'yes', [((".c", NCR), - ('_9b191e4c46e9d6ba17c8cd4d730900cf'+_obj, NCR))], - 'conftest_cda36b76729ffb03bf36a48d13b2d98d_0%s' + (conftest_0_obj_suffix, NCR))], + conftest_0_base, ), ConfigCheckInfo("Checking for C header file non_system_header1.h... ", 'no', [((".c", NCR), - ('_b9da1a844a8707269188b28a62c0d83e'+_obj, NCF))], - 'conftest_acc476a565a3f6d5d67ddc21f187d062_0%s')] + (conftest_1_obj_suffix, NCF))], + conftest_1_base)] ) @@ -117,14 +134,14 @@ test.checkConfigureLogAndStdout(checks=[ ConfigCheckInfo("Checking for C header file non_system_header0.h... ", 'yes', [((".c", CR), - ('_9b191e4c46e9d6ba17c8cd4d730900cf'+_obj, CR))], - 'conftest_cda36b76729ffb03bf36a48d13b2d98d_0%s' + (conftest_0_obj_suffix, CR))], + conftest_0_base, ), ConfigCheckInfo("Checking for C header file non_system_header1.h... ", 'no', [((".c", CR), - ('_b9da1a844a8707269188b28a62c0d83e'+_obj, CF))], - 'conftest_acc476a565a3f6d5d67ddc21f187d062_0%s')] + (conftest_1_obj_suffix, CF))], + conftest_1_base)] ) @@ -139,14 +156,14 @@ test.checkConfigureLogAndStdout(checks=[ ConfigCheckInfo("Checking for C header file non_system_header0.h... ", 'yes', [((".c", CR), - ('_9b191e4c46e9d6ba17c8cd4d730900cf'+_obj, CR))], - 'conftest_cda36b76729ffb03bf36a48d13b2d98d_0%s' + (conftest_0_obj_suffix, CR))], + conftest_0_base, ), ConfigCheckInfo("Checking for C header file non_system_header1.h... ", 'no', [((".c", CR), - ('_b9da1a844a8707269188b28a62c0d83e'+_obj, CF))], - 'conftest_acc476a565a3f6d5d67ddc21f187d062_0%s')] + (conftest_1_obj_suffix, CF))], + conftest_1_base)] ) test.run(arguments='--config=auto') @@ -154,14 +171,14 @@ test.checkConfigureLogAndStdout(checks=[ ConfigCheckInfo("Checking for C header file non_system_header0.h... ", 'no', [((".c", CR), - ('_9b191e4c46e9d6ba17c8cd4d730900cf'+_obj, NCF))], - 'conftest_cda36b76729ffb03bf36a48d13b2d98d_0%s' + (conftest_0_obj_suffix, NCF))], + conftest_0_base, ), ConfigCheckInfo("Checking for C header file non_system_header1.h... ", 'yes', [((".c", CR), - ('_b9da1a844a8707269188b28a62c0d83e'+_obj, NCR))], - 'conftest_acc476a565a3f6d5d67ddc21f187d062_0%s')] + (conftest_1_obj_suffix, NCR))], + conftest_1_base)] ) test.file_fixture('test_main.c') diff --git a/testing/framework/TestSCons.py b/testing/framework/TestSCons.py index e3f4f47..59a739a 100644 --- a/testing/framework/TestSCons.py +++ b/testing/framework/TestSCons.py @@ -1221,7 +1221,7 @@ SConscript(sconscript) result_cached = 1 for bld_desc in check_info.cached: # each TryXXX for ext, flag in bld_desc: # each file in TryBuild - conf_filename = re.escape(os.path.join(sconf_dir, check_info.temp_filename%ext)) + conf_filename = re.escape(check_info.temp_filename%ext) if flag == self.NCR: # NCR = Non Cached Rebuild -- cgit v0.12 From c35a2cdf0306e0cbc6a5215f9d77ac49debb1ece Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Thu, 23 Jan 2020 12:19:46 -0700 Subject: Fix some pyflakes warnings These are of the kind that would not be fixed by a code reformat (Black). These should all be trivial. They're nearly all in unit tests (all but two), since I haven't cleaned up as many there in the past. Signed-off-by: Mats Wichmann --- src/engine/SCons/BuilderTests.py | 14 +++++++------- src/engine/SCons/EnvironmentTests.py | 8 ++++---- src/engine/SCons/Node/AliasTests.py | 2 +- src/engine/SCons/Node/FSTests.py | 20 ++++++++++---------- src/engine/SCons/Node/NodeTests.py | 2 +- src/engine/SCons/PathListTests.py | 2 +- src/engine/SCons/Platform/__init__.py | 2 +- src/engine/SCons/SConsignTests.py | 2 +- src/engine/SCons/Scanner/RCTests.py | 2 +- src/engine/SCons/TaskmasterTests.py | 10 +++++----- src/engine/SCons/Tool/msvs.py | 2 +- src/engine/SCons/Tool/msvsTests.py | 10 +++++----- src/engine/SCons/Variables/ListVariableTests.py | 2 +- src/engine/SCons/Variables/PackageVariableTests.py | 4 ++-- 14 files changed, 41 insertions(+), 41 deletions(-) diff --git a/src/engine/SCons/BuilderTests.py b/src/engine/SCons/BuilderTests.py index f28e201..b4286fd 100644 --- a/src/engine/SCons/BuilderTests.py +++ b/src/engine/SCons/BuilderTests.py @@ -173,7 +173,7 @@ class MyNode_without_target_from_source(object): def builder_set(self, builder): self.builder = builder def has_builder(self): - return not self.builder is None + return self.builder is not None def set_explicit(self, is_explicit): self.is_explicit = is_explicit def has_explicit_builder(self): @@ -205,7 +205,7 @@ class BuilderTestCase(unittest.TestCase): """Test simple Builder creation """ builder = SCons.Builder.Builder(action="foo") - assert not builder is None, builder + assert builder is not None, builder builder = SCons.Builder.Builder(action="foo", OVERRIDE='x') x = builder.overrides['OVERRIDE'] assert x == 'x', x @@ -429,7 +429,7 @@ class BuilderTestCase(unittest.TestCase): return Foo(target) builder = SCons.Builder.Builder(target_factory = FooFactory) assert builder.target_factory is FooFactory - assert not builder.source_factory is FooFactory + assert builder.source_factory is not FooFactory def test_source_factory(self): """Test a Builder that creates source nodes of a specified class @@ -440,7 +440,7 @@ class BuilderTestCase(unittest.TestCase): global Foo return Foo(source) builder = SCons.Builder.Builder(source_factory = FooFactory) - assert not builder.target_factory is FooFactory + assert builder.target_factory is not FooFactory assert builder.source_factory is FooFactory def test_splitext(self): @@ -737,7 +737,7 @@ class BuilderTestCase(unittest.TestCase): with open(str(t), 'w') as f: f.write("function2\n") for t in tlist: - if not t in list(map(str, target)): + if t not in list(map(str, target)): with open(t, 'w') as f: f.write("function2\n") return 1 @@ -768,7 +768,7 @@ class BuilderTestCase(unittest.TestCase): with open(str(t), 'w') as f: f.write("function3\n") for t in tlist: - if not t in list(map(str, target)): + if t not in list(map(str, target)): with open(t, 'w') as f: f.write("function3\n") return 1 @@ -821,7 +821,7 @@ class BuilderTestCase(unittest.TestCase): assert s == ['aaa.bar'], s builder3 = SCons.Builder.Builder(action='bld3') - assert not builder3.src_builder is builder1.src_builder + assert builder3.src_builder is not builder1.src_builder builder4 = SCons.Builder.Builder(action='bld4', src_suffix='.i', diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index 0cb8418..01baba3 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -236,7 +236,7 @@ class SubstitutionTestCase(unittest.TestCase): """ env = SubstitutionEnvironment(XXX = 'x') assert 'XXX' in env - assert not 'YYY' in env + assert 'YYY' not in env def test_items(self): """Test the SubstitutionEnvironment items() method @@ -1759,7 +1759,7 @@ def exists(env): env2.Dictionary('ZZZ')[5] = 6 assert env1.Dictionary('XXX') is env2.Dictionary('XXX') assert 4 in env2.Dictionary('YYY') - assert not 4 in env1.Dictionary('YYY') + assert 4 not in env1.Dictionary('YYY') assert 5 in env2.Dictionary('ZZZ') assert 5 not in env1.Dictionary('ZZZ') @@ -3551,8 +3551,8 @@ class OverrideEnvironmentTestCase(unittest.TestCase,TestEnvironmentFixture): assert 'YYY' in env assert 'YYY' in env2 assert 'YYY' in env3 - assert not 'ZZZ' in env - assert not 'ZZZ' in env2 + assert 'ZZZ' not in env + assert 'ZZZ' not in env2 assert 'ZZZ' in env3 def test_items(self): diff --git a/src/engine/SCons/Node/AliasTests.py b/src/engine/SCons/Node/AliasTests.py index 5d9c799..27b75b3 100644 --- a/src/engine/SCons/Node/AliasTests.py +++ b/src/engine/SCons/Node/AliasTests.py @@ -93,7 +93,7 @@ class AliasTestCase(unittest.TestCase): a2 = SCons.Node.Alias.Alias('a') assert a2.name == 'a', a2.name - assert not a1 is a2 + assert a1 is not a2 assert a1.name == a2.name class AliasNodeInfoTestCase(unittest.TestCase): diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index 9c19481..bbfdd1b 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -3066,12 +3066,12 @@ class RepositoryTestCase(_tempdirTestCase): assert r is d1, r r = d2.rentry() - assert not r is d2, r + assert r is not d2, r r = str(r) assert r == os.path.join(self.rep1, 'd2'), r r = d3.rentry() - assert not r is d3, r + assert r is not d3, r r = str(r) assert r == os.path.join(self.rep2, 'd3'), r @@ -3079,12 +3079,12 @@ class RepositoryTestCase(_tempdirTestCase): assert r is e1, r r = e2.rentry() - assert not r is e2, r + assert r is not e2, r r = str(r) assert r == os.path.join(self.rep1, 'e2'), r r = e3.rentry() - assert not r is e3, r + assert r is not e3, r r = str(r) assert r == os.path.join(self.rep2, 'e3'), r @@ -3092,12 +3092,12 @@ class RepositoryTestCase(_tempdirTestCase): assert r is f1, r r = f2.rentry() - assert not r is f2, r + assert r is not f2, r r = str(r) assert r == os.path.join(self.rep1, 'f2'), r r = f3.rentry() - assert not r is f3, r + assert r is not f3, r r = str(r) assert r == os.path.join(self.rep2, 'f3'), r @@ -3127,12 +3127,12 @@ class RepositoryTestCase(_tempdirTestCase): assert r is d1, r r = d2.rdir() - assert not r is d2, r + assert r is not d2, r r = str(r) assert r == os.path.join(self.rep1, 'd2'), r r = d3.rdir() - assert not r is d3, r + assert r is not d3, r r = str(r) assert r == os.path.join(self.rep3, 'd3'), r @@ -3183,12 +3183,12 @@ class RepositoryTestCase(_tempdirTestCase): assert r is f1, r r = f2.rfile() - assert not r is f2, r + assert r is not f2, r r = str(r) assert r == os.path.join(self.rep1, 'f2'), r r = f3.rfile() - assert not r is f3, r + assert r is not f3, r r = f3.rstr() assert r == os.path.join(self.rep3, 'f3'), r diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py index d8179ff..8d9d3a9 100644 --- a/src/engine/SCons/Node/NodeTests.py +++ b/src/engine/SCons/Node/NodeTests.py @@ -1104,7 +1104,7 @@ class NodeTestCase(unittest.TestCase): for kid in [n1, n3, n4, n6, n7, n9, n10, n12]: assert kid in kids, kid for kid in [n2, n5, n8, n11]: - assert not kid in kids, kid + assert kid not in kids, kid def test_all_children(self): """Test fetching all the "children" of a Node. diff --git a/src/engine/SCons/PathListTests.py b/src/engine/SCons/PathListTests.py index 104be73..09b1132 100644 --- a/src/engine/SCons/PathListTests.py +++ b/src/engine/SCons/PathListTests.py @@ -185,7 +185,7 @@ class PathListTestCase(unittest.TestCase): x3 = SCons.PathList.PathList('x') - assert not x1 is x3, (x1, x3) + assert x1 is not x3, (x1, x3) if __name__ == "__main__": diff --git a/src/engine/SCons/Platform/__init__.py b/src/engine/SCons/Platform/__init__.py index 058241d..5e9a358 100644 --- a/src/engine/SCons/Platform/__init__.py +++ b/src/engine/SCons/Platform/__init__.py @@ -195,7 +195,7 @@ class TempFileMunge(object): # Default to the .lnk suffix for the benefit of the Phar Lap # linkloc linker, which likes to append an .lnk suffix if # none is given. - if env.has_key('TEMPFILESUFFIX'): + if 'TEMPFILESUFFIX' in env: suffix = env.subst('$TEMPFILESUFFIX') else: suffix = '.lnk' diff --git a/src/engine/SCons/SConsignTests.py b/src/engine/SCons/SConsignTests.py index d40a7b6..782072d 100644 --- a/src/engine/SCons/SConsignTests.py +++ b/src/engine/SCons/SConsignTests.py @@ -337,7 +337,7 @@ class SConsignFileTestCase(SConsignTestCase): SCons.SConsign.ForDirectory(DummyNode(test.workpath('dir'))) - assert not SCons.SConsign.DataBase is None, SCons.SConsign.DataBase + assert SCons.SConsign.DataBase is not None, SCons.SConsign.DataBase assert fake_dbm.name == file, fake_dbm.name assert fake_dbm.mode == "c", fake_dbm.mode diff --git a/src/engine/SCons/Scanner/RCTests.py b/src/engine/SCons/Scanner/RCTests.py index 551e613..347149c 100644 --- a/src/engine/SCons/Scanner/RCTests.py +++ b/src/engine/SCons/Scanner/RCTests.py @@ -82,7 +82,7 @@ class DummyEnvironment(collections.UserDict): def Dictionary(self, *args): return self.data - def subst(self, arg, target=None, source=None, conv=None): + def subst(self, strSubst, target=None, source=None, conv=None): if strSubst[0] == '$': return self.data[strSubst[1:]] return strSubst diff --git a/src/engine/SCons/TaskmasterTests.py b/src/engine/SCons/TaskmasterTests.py index c0c77b0..f23afd1 100644 --- a/src/engine/SCons/TaskmasterTests.py +++ b/src/engine/SCons/TaskmasterTests.py @@ -146,7 +146,7 @@ class Node(object): pass def has_builder(self): - return not self.builder is None + return self.builder is not None def is_derived(self): return self.has_builder or self.side_effect @@ -935,7 +935,7 @@ class TaskmasterTestCase(unittest.TestCase): except SCons.Errors.UserError: pass else: - raise TestFailed("did not catch expected UserError") + raise AssertionError("did not catch expected UserError") def raise_BuildError(): raise SCons.Errors.BuildError @@ -948,7 +948,7 @@ class TaskmasterTestCase(unittest.TestCase): except SCons.Errors.BuildError: pass else: - raise TestFailed("did not catch expected BuildError") + raise AssertionError("did not catch expected BuildError") # On a generic (non-BuildError) exception from a Builder, # the target should throw a BuildError exception with the @@ -968,7 +968,7 @@ class TaskmasterTestCase(unittest.TestCase): exc_traceback = sys.exc_info()[2] assert isinstance(e.exc_info[2], type(exc_traceback)), e.exc_info[2] else: - raise TestFailed("did not catch expected BuildError") + raise AssertionError("did not catch expected BuildError") built_text = None cache_text = [] @@ -1049,7 +1049,7 @@ class TaskmasterTestCase(unittest.TestCase): assert cache_text == ["n1 retrieved"], cache_text # If no binfo exists anymore, something has gone wrong... has_binfo = hasattr(n1, 'binfo') - assert has_binfo == True, has_binfo + assert has_binfo, has_binfo def test_exception(self): """Test generic Taskmaster exception handling diff --git a/src/engine/SCons/Tool/msvs.py b/src/engine/SCons/Tool/msvs.py index 0ef4a97..9952ccc 100644 --- a/src/engine/SCons/Tool/msvs.py +++ b/src/engine/SCons/Tool/msvs.py @@ -544,7 +544,7 @@ class _DSPGenerator(object): if t[1] in self.env: if SCons.Util.is_List(self.env[t[1]]): for i in self.env[t[1]]: - if not i in self.sources[t[0]]: + if i not in self.sources[t[0]]: self.sources[t[0]].append(i) else: if not self.env[t[1]] in self.sources[t[0]]: diff --git a/src/engine/SCons/Tool/msvsTests.py b/src/engine/SCons/Tool/msvsTests.py index c2b5f0e..38a100f 100644 --- a/src/engine/SCons/Tool/msvsTests.py +++ b/src/engine/SCons/Tool/msvsTests.py @@ -405,20 +405,20 @@ class DummyEnv(object): return self.dict return self.dict[key] - def __setitem__(self,key,value): + def __setitem__(self, key, value): self.dict[key] = value - def __getitem__(self,key): + def __getitem__(self, key): return self.dict[key] - def __contains__(self,key): + def __contains__(self, key): return key in self.dict - def has_key(self,name): + def has_key(self, name): return name in self.dict def get(self, name, value=None): - if self.has_key(name): + if name in self.dict: return self.dict[name] else: return value diff --git a/src/engine/SCons/Variables/ListVariableTests.py b/src/engine/SCons/Variables/ListVariableTests.py index ef4832c..8f79e07 100644 --- a/src/engine/SCons/Variables/ListVariableTests.py +++ b/src/engine/SCons/Variables/ListVariableTests.py @@ -42,7 +42,7 @@ class ListVariableTestCase(unittest.TestCase): assert o.help == 'test option help\n (all|none|comma-separated list of names)\n allowed names: one two three', repr(o.help) assert o.default == 'all', o.default assert o.validator is None, o.validator - assert not o.converter is None, o.converter + assert o.converter is not None, o.converter opts = SCons.Variables.Variables() opts.Add(SCons.Variables.ListVariable('test2', 'test2 help', diff --git a/src/engine/SCons/Variables/PackageVariableTests.py b/src/engine/SCons/Variables/PackageVariableTests.py index cda3a4a..a7e6b0d 100644 --- a/src/engine/SCons/Variables/PackageVariableTests.py +++ b/src/engine/SCons/Variables/PackageVariableTests.py @@ -80,10 +80,10 @@ class PackageVariableTestCase(unittest.TestCase): # False when we give it str(False). This assures consistent operation # through a cycle of Variables.Save() -> Variables(). x = o.converter(str(True)) - assert x == True, "converter returned a string when given str(True)" + assert x, "converter returned a string when given str(True)" x = o.converter(str(False)) - assert x == False, "converter returned a string when given str(False)" + assert not x, "converter returned a string when given str(False)" def test_validator(self): """Test the PackageVariable validator""" -- cgit v0.12 From 4d8892aff67876ac76031d72d8441da8ac46f342 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Thu, 23 Jan 2020 13:01:00 -0700 Subject: [PR #3531] fix TestFailed usage another way Per review, the replacement for (deprecated/removed) raising TestFailed is to call self.fail - updated to this. Signed-off-by: Mats Wichmann --- src/engine/SCons/TaskmasterTests.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/engine/SCons/TaskmasterTests.py b/src/engine/SCons/TaskmasterTests.py index f23afd1..1a47230 100644 --- a/src/engine/SCons/TaskmasterTests.py +++ b/src/engine/SCons/TaskmasterTests.py @@ -935,7 +935,7 @@ class TaskmasterTestCase(unittest.TestCase): except SCons.Errors.UserError: pass else: - raise AssertionError("did not catch expected UserError") + self.fail("did not catch expected UserError") def raise_BuildError(): raise SCons.Errors.BuildError @@ -948,7 +948,7 @@ class TaskmasterTestCase(unittest.TestCase): except SCons.Errors.BuildError: pass else: - raise AssertionError("did not catch expected BuildError") + self.fail("did not catch expected BuildError") # On a generic (non-BuildError) exception from a Builder, # the target should throw a BuildError exception with the @@ -968,7 +968,7 @@ class TaskmasterTestCase(unittest.TestCase): exc_traceback = sys.exc_info()[2] assert isinstance(e.exc_info[2], type(exc_traceback)), e.exc_info[2] else: - raise AssertionError("did not catch expected BuildError") + self.fail("did not catch expected BuildError") built_text = None cache_text = [] -- cgit v0.12 From 9b35a2175b460d820baec6e0343961f0e4912237 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 24 Jan 2020 09:26:01 -0700 Subject: Another round of user guide fiddling [ci skip] Some markup changes, a few werding additions. Signed-off-by: Mats Wichmann --- doc/user/build-install.xml | 50 +++++++++++++++++++++++++-------- doc/user/builders-writing.xml | 2 ++ doc/user/environments.xml | 49 +++++++++++++++++--------------- doc/user/install.xml | 18 ++++++++++-- doc/user/less-simple.xml | 6 ++-- doc/user/misc.xml | 15 +++++----- doc/user/nodes.xml | 4 +-- doc/user/output.xml | 30 ++++++++++---------- doc/user/simple.xml | 65 ++++++++++++++++++++++++------------------- 9 files changed, 148 insertions(+), 91 deletions(-) diff --git a/doc/user/build-install.xml b/doc/user/build-install.xml index fbb14e5..f343c02 100644 --- a/doc/user/build-install.xml +++ b/doc/user/build-install.xml @@ -110,29 +110,37 @@ Python 3.7.1 - In a cmd shell or PowerShell on a Windows system - (note PoweShell needs it spelled "python.exe" rather than "python"): + Note to Windows users: there are many different ways Python + can get installed or invoked on Windows, it is beyond the scope + of this guide to unravel all of them. Try using the + Python launcher (see + PEP 397) + by using the name py instead of + python, if that is not available drop + back to trying python. -C:\>python -V +C:\>py -V Python 3.7.1 If Python is not installed on your system, + or is not findable in the current search path, you will see an error message stating something like "command not found" (on UNIX or Linux) or "'python' is not recognized as an internal or external command, operable progam or batch file" - (on Windows). + (on Windows cmd). In that case, you need to install Python + (or fix the search path) before you can install &SCons;. - The standard location for information + The canoncical location for information about downloading and installing Python is http://www.python.org/download/. See that page and associated links to get started. @@ -141,16 +149,18 @@ Python 3.7.1 For Linux systems, Python is almost certainly available as a supported package, possibly - installed by default; this is often preferred to installing + installed by default; this is often preferred over installing by other means, and is easier than installing from source code. Many such systems have separate packages for - Python 2 and Python 3. Building from source may still be a + Python 2 and Python 3 - make sure the Python 3 package is + installed, as &SCons; requires it. + Building from source may still be a useful option if you need a version that is not offered by the distribution you are using. - &SCons; will work with Python 2.7.x or with Python 3.5 or later. + &SCons; will work with Python 3.5 or later. If you need to install Python and have a choice, we recommend using the most recent Python version available. Newer Pythons have significant improvements @@ -182,13 +192,31 @@ Python 3.7.1 - &SCons; comes pre-packaged for installation on many Linux systems + For those users using Anaconda or Miniconda, use the + conda installer instead, so the &scons; + install location will match the version of Python that + system will be using: + + + +% conda install -c conda-forge scons + + + + &SCons; comes pre-packaged for installation on many Linux systems. Check your package installation system to see if there is an &SCons; package available. Many people prefer to install distribution-native packages if available, as they provide a central point for management and updating. - Some distributions have two &SCons; packages available, one which - uses Python 2 and one which uses Python 3. If you need a specific + During the still-ongoing Python 2 to 3 transition, + some distributions may still have two &SCons; packages available, + one which uses Python 2 and one which uses Python 3. Since + latest &scons; only runs on Python 3, to get the current version + you should choose the Python 3 package. + + + + If you need a specific version of &SCons; that is different from the package available, pip has a version option or you can follow the instructions in the next section. diff --git a/doc/user/builders-writing.xml b/doc/user/builders-writing.xml index 76fa794..d9a155f 100644 --- a/doc/user/builders-writing.xml +++ b/doc/user/builders-writing.xml @@ -558,6 +558,8 @@ file.input &SCons; Builder objects can create an action "on the fly" by using a function called a &generator;. + (Note: this is not the same thing as a Python generator function + described in PEP 255) This provides a great deal of flexibility to construct just the right list of commands to build your target. diff --git a/doc/user/environments.xml b/doc/user/environments.xml index d3e5d6d..0a5722b 100644 --- a/doc/user/environments.xml +++ b/doc/user/environments.xml @@ -2,7 +2,7 @@ %scons; - + %builders-mod; @@ -90,8 +90,8 @@ no further substitutions can be made: The string: "The string says: %STRING" expands to: "The string says: The result is: final value" -If a construction variable is not defined in an environment, then the -null string is substituted: +If a construction variable is not defined in an environment, then an +empty string is substituted: Construction variables: FOO => 'value1', @@ -348,7 +348,7 @@ environment, of directory names, suffixes, etc. - An environment + An environment is a collection of values that can affect how a program executes. &SCons; distinguishes between three @@ -367,7 +367,7 @@ environment, of directory names, suffixes, etc. - The external environment + The external environment is the set of variables in the user's environment at the time the user runs &SCons;. These variables are available within the &SConscript; files @@ -384,7 +384,7 @@ environment, of directory names, suffixes, etc. - A &consenv; + A &consenv; is a distinct object created within a &SConscript; file and which contains values that @@ -408,13 +408,13 @@ environment, of directory names, suffixes, etc. - An execution environment + An execution environment is the values that &SCons; sets when executing an external command (such as a compiler or linker) to build one or more targets. Note that this is not the same as - the external environment + the external environment (see above). See , below. @@ -473,7 +473,7 @@ environment, of directory names, suffixes, etc. - The external environment + The external environment variable settings that the user has in force when executing &SCons; @@ -596,7 +596,7 @@ int main() { } construction variable values, except that the user has explicitly specified use of the GNU C compiler &gcc;, - and further specifies that the -O2 + and further specifies that the (optimization level two) flag should be used when compiling the object file. In other words, the explicit initializations of @@ -627,7 +627,7 @@ int main() { } env = Environment() -print("CC is: %s"%env['CC']) +print("CC is: %s" % env['CC']) @@ -811,7 +811,7 @@ scons: `.' is up to date. If a problem occurs when expanding a construction variable, by default it is expanded to '' - (a null string), and will not cause scons to fail. + (an empty string), and will not cause scons to fail. @@ -996,8 +996,8 @@ env = DefaultEnvironment(tools=['gcc', 'gnulink'], each tailored to a different way to build some piece of software or other file. If, for example, we need to build - one program with the -O2 flag - and another with the -g (debug) flag, + one program with the flag + and another with the (debug) flag, we would do this like so: @@ -1063,9 +1063,9 @@ int main() { } each implicitly told &SCons; to generate an object file named foo.o, one with a &cv-link-CCFLAGS; value of - -O2 + and one with a &cv-link-CCFLAGS; value of - -g. + . &SCons; can't just decide that one of them should take precedence over the other, so it generates the error. @@ -1279,7 +1279,7 @@ int main() { } actually occurs relative to when the targets get built becomes apparent - if we run &scons; without the -Q + if we run &scons; without the option: @@ -1625,7 +1625,9 @@ env['ENV']['PATH'] = ['/usr/local/bin', '/bin', '/usr/bin'] Note that &SCons; does allow you to define the directories in the &PATH; in a string, separated by the pathname-separator character - for your system (':' on POSIX systems, ';' on Windows): + for your system (':' on POSIX systems, ';' on Windows + or use os.pathsep for portability). + @@ -1761,10 +1763,11 @@ env.AppendENVPath('LIB', '/usr/local/lib') Note that the added values are strings, and if you want to add multiple directories to a variable like $PATH, - you must include the path separate character + you must include the path separator character + in the string (: on Linux or POSIX, - ; on Windows) - in the string. + ; on Windows, or use + os.pathsep for portability). @@ -1782,8 +1785,8 @@ env.AppendENVPath('LIB', '/usr/local/lib') Normally when using a tool from the construction environment, several different search locations are checked by default. - This includes the Scons/Tools/ directory - inbuilt to scons and the directory site_scons/site_tools + This includes the Scons/Tools/ directory + inbuilt to scons and the directory site_scons/site_tools relative to the root SConstruct file. diff --git a/doc/user/install.xml b/doc/user/install.xml index db87521..d5ea4d8 100644 --- a/doc/user/install.xml +++ b/doc/user/install.xml @@ -92,8 +92,11 @@ int main() { printf("Hello, world!\n"); } It can, however, be cumbersome to remember (and type) the specific destination directory - in which the program (or any other file) - should be installed. + in which the program (or other file) + should be installed. A call to &Default; can be used to + add the directory to the list of default targets, + removing the need to type it, + but sometimes you don't want to install on every build. This is an area where the &Alias; function comes in handy, allowing you, for example, @@ -118,7 +121,8 @@ int main() { printf("Hello, world!\n"); } This then yields the more natural ability to install the program - in its destination as follows: + in its destination as a separate + invocation, as follows: @@ -328,6 +332,14 @@ int call_foo() { --> + + On systems which expect a shared library to be installed both with + a name that indicates the version, for run-time resolution, + and as a plain name, for link-time resolution, the + &InstallVersionedLib; function can be used. Symbolic links + appropriate to the type of system will be generated based on + symlinks of the source library. + diff --git a/doc/user/less-simple.xml b/doc/user/less-simple.xml index 1a32492..10f0c1a 100644 --- a/doc/user/less-simple.xml +++ b/doc/user/less-simple.xml @@ -100,7 +100,9 @@ int main() { printf("Hello, world!\n"); } so that the order mimics that of an assignment statement in most programming languages, including Python: - "program = source files".) + "target = source files". For an + alternative way to supply this information, see + ). @@ -453,7 +455,7 @@ Program('program', src_files) -
+
Keyword Arguments diff --git a/doc/user/misc.xml b/doc/user/misc.xml index a595e59..b093629 100644 --- a/doc/user/misc.xml +++ b/doc/user/misc.xml @@ -654,21 +654,22 @@ env.Command('directory_build_info', - This issue may be overcome by using --enable-virtualenv + This issue may be overcome by using the + option. The option automatically imports virtualenv-related environment variables to all created construction environment env['ENV'], and modifies SCons PATH appropriately to prefer virtualenv's executables. - Setting environment variable SCONS_ENABLE_VIRTUALENV=1 + Setting environment variable SCONS_ENABLE_VIRTUALENV=1 will have same effect. If virtualenv support is enabled system-vide - by the environment variable, it may be suppressed with - --ignore-virtualenv option. + by the environment variable, it may be suppressed with the + option. - Inside of SConscript, a global function Virtualenv is + Inside of &SConscript;, a global function Virtualenv is available. It returns a path to virtualenv's home directory, or - None if SCons is not running from virtualenv. Note, - that this function returns a path even if SCons is run from an + None if &scons; is not running from virtualenv. Note + that this function returns a path even if &scons; is run from an unactivated virtualenv. diff --git a/doc/user/nodes.xml b/doc/user/nodes.xml index 7d36a65..29f2270 100644 --- a/doc/user/nodes.xml +++ b/doc/user/nodes.xml @@ -2,7 +2,7 @@ %scons; - + %builders-mod; @@ -299,7 +299,7 @@ int main() { printf("Hello, world!\n"); } the object_list[0] extracts an actual Node object from the list, - and the Python print statement + and the Python print function converts the object to a string for printing. diff --git a/doc/user/output.xml b/doc/user/output.xml index d1082a9..bae018a 100644 --- a/doc/user/output.xml +++ b/doc/user/output.xml @@ -2,7 +2,7 @@ %scons; - + %builders-mod; @@ -109,7 +109,7 @@ Type: 'scons program' to build the production program, When the &SConstruct; or &SConscript; files contain such a call to the &Help; function, the specified help text will be displayed in response to - the &SCons; -h option: + the &SCons; option: @@ -191,7 +191,7 @@ if env['PLATFORM'] == 'win32': standard list that describes the &SCons; command-line options. This list is also always displayed whenever - the -H option is used. + the option is used. @@ -325,7 +325,7 @@ foo.c By only setting the appropriate $*COMSTR variables if the user specifies - VERBOSE=1 + VERBOSE=1 on the command line, the user has control over how &SCons; @@ -422,7 +422,7 @@ f2.c Note that the &Progress; function does not arrange for a newline to be printed automatically at the end of the string (as does the Python - print statement), + print function), and we must specify the \n that we want printed at the end of the configured string. @@ -468,15 +468,15 @@ Program('f2.c') Note that we also specified the - overwrite=True argument + overwrite=True argument to the &Progress; function, which causes &SCons; to "wipe out" the previous string with space characters before printing the next &Progress; string. Without the - overwrite=True argument, + overwrite=True argument, a shorter file name would not overwrite - all of the charactes in a longer file name that + all of the charactes in a longer file name that precedes it, making it difficult to tell what the actual file name is on the output. @@ -523,11 +523,11 @@ Program('f2.c') Note that here we have also used the - interval= + interval= keyword argument to have &SCons; only print a new "spinner" string once every five evaluated nodes. - Using an interval= count, + Using an interval= count, even with strings that use $TARGET like our examples above, can be a good way to lessen the @@ -621,7 +621,7 @@ Progress(progress_function) you can use in a python atexit function to get a list of objects describing the actions that failed while attempting to build targets. There can be more - than one if you're using -j. Here's a + than one if you're using . Here's a simple example: @@ -647,7 +647,7 @@ atexit.register(print_build_failures) it calls &GetBuildFailures; to fetch the list of failed objects. See the man page for the detailed contents of the returned objects; - some of the more useful attributes are + some of the more useful attributes are .node, .errstr, .filename, and @@ -655,7 +655,7 @@ atexit.register(print_build_failures) The filename is not necessarily the same file as the node; the node is the target that was - being built when the error occurred, while the + being built when the error occurred, while the filenameis the file or dir that actually caused the error. Note: only call &GetBuildFailures; at the end of the @@ -663,7 +663,7 @@ atexit.register(print_build_failures) - + Here is a more complete example showing how to turn each element of &GetBuildFailures; into a string: @@ -722,7 +722,7 @@ atexit.register(display_build_status) - + When this runs, you'll see the appropriate output: diff --git a/doc/user/simple.xml b/doc/user/simple.xml index acc438b..138ff54 100644 --- a/doc/user/simple.xml +++ b/doc/user/simple.xml @@ -2,7 +2,7 @@ %scons; - + %builders-mod; @@ -76,7 +76,8 @@ main() And here's how to build it using &SCons;. - Enter the following into a file named &SConstruct;: + Save the code above into hello.c, + and enter the following into a file named &SConstruct;: @@ -98,7 +99,7 @@ int main() { printf("Hello, world!\n"); } and the input file from which you want it built (the hello.c file). - &b-link-Program; is a builder_method, + &b-link-Program; is a &builder_method;, a Python call that tells &SCons; that you want to build an executable program. @@ -142,10 +143,8 @@ int main() { printf("Hello, world!\n"); } Second, notice that the same input &SConstruct; file, without any changes, generates the correct output file names on both systems: - hello.o and hello - on POSIX systems, - hello.obj and hello.exe - on Windows systems. + &hello_o; and &hello; on POSIX systems, + &hello_obj; and &hello_exe; on Windows systems. This is a simple example of how &SCons; makes it extremely easy to write portable software builds. @@ -274,7 +273,7 @@ public class Example1 When using &SCons;, it is unnecessary to add special commands or target names to clean up after a build. Instead, you simply use the - -c or --clean + or option when you invoke &SCons;, and &SCons; removes the appropriate built files. So if we build our example above @@ -388,8 +387,8 @@ Program('hello.c') # "hello.c" is the source file. does not affect the order in which &SCons; actually builds the programs and object files - you want it to build. - In programming parlance, + you want it to build + In programming parlance, the &SConstruct; file is declarative, meaning you tell &SCons; what you want done @@ -398,22 +397,20 @@ Program('hello.c') # "hello.c" is the source file. where you specify explicitly the order in which to do things. - + . In other words, when you call the &b-link-Program; builder (or any other builder method), you're not telling &SCons; to build - the program at the instant the builder method is called. - Instead, you're telling &SCons; to build the program - that you want, for example, - a program built from a file named &hello_c;, - and it's up to &SCons; to build that program - (and any other files) whenever it's necessary. - (We'll learn more about how - &SCons; decides when building or rebuilding a file - is necessary in , below.) - + the program at that moment. + Instead, you're telling &SCons; what you want accomplished, + and it's up to &SCons; to figure out how to do that, and to + take those steps if/when it's necessary. + We'll learn more about how + &SCons; decides when building or rebuilding a target + is necessary in , below. + - + &SCons; reflects this distinction between @@ -433,9 +430,9 @@ Program('hello.c') # "hello.c" is the source file. Let's clarify this with an example. - Python has a print statement that + Python has a print function that prints a string of characters to the screen. - If we put print statements around + If we put print calls around our calls to the &b-Program; builder method: @@ -459,8 +456,8 @@ int main() { printf("Goodbye, world!\n"); } Then when we execute &SCons;, - we see the output from the print - statements in between the messages about + we see the output from calling the print + function in between the messages about reading the &SConscript; files, indicating that that is when the Python statements are being executed: @@ -473,13 +470,25 @@ int main() { printf("Goodbye, world!\n"); } - Notice also that &SCons; built the &goodbye; program first, + Notice that &SCons; built the &goodbye; program first, even though the "reading &SConscript;" output - shows that we called Program('hello.c') + shows that we called Program('hello.c') first in the &SConstruct; file. + + + Notice also that &SCons; was able to infer a lot of information + from the two &Program; calls. Because + &hello_c; and goodbye.c + were recognized as C-language source files, it knew to build + the intermediate target files &hello_o; and &goodbye_o; + and the final files &hello; and &goodbye; + It was not necessary to program &scons; beyond just calling &Program;. + + +
-- cgit v0.12 From 90a1af05075436bd38cc32a169d2c202739eb809 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sat, 25 Jan 2020 12:11:18 -0700 Subject: More manpage fiddling [ci skip] Add 2020 year. Use entities in more places where such are already defined. Change more instances of option formatting so the line break is between and Commented out options (not implemented) are not inside a block. A few other markup bits and indentations. Most of this does not show in the built manpage. Also amplified a few descriptions. Signed-off-by: Mats Wichmann --- doc/man/scons.xml | 508 ++++++++++++++++++++++++++---------------------------- 1 file changed, 247 insertions(+), 261 deletions(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index 9dccf11..6aa42a3 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -54,10 +54,10 @@ Steven Knight and the SCons Development Team - 2004 - 2019 + 2004 - 2020 - 2004 - 2019 + 2004 - 2020 The SCons Foundation @@ -488,67 +488,61 @@ supports the same command-line options as GNU and many of those supported by cons.
+ + + -b -Ignored for compatibility with non-GNU versions of -make. - +Ignored for compatibility with non-GNU versions of &Make; + -c, --clean, --remove Clean up by removing all target files for which a construction command is specified. Also remove any files or directories associated to the construction command -using the -Clean() -function. -Will not remove any targets specified by the -NoClean() -function. - +using the &Clean; function. +Will not remove any targets specified by the &NoClean; function. + --cache-debug=file -Print debug information about the -CacheDir() -derived-file caching -to the specified +Print debug information about the &CacheDir; +derived-file caching to the specified file. If file is - (a hyphen), -the debug information are printed to the standard output. -The printed messages describe what signature file names are -being looked for in, retrieved from, or written to the -CacheDir() -directory tree. - +the debug information is printed to the standard output. +The printed messages describe what signature-file names +are being looked for in, retrieved from, or written to the +&CacheDir; directory tree. + --cache-disable, --no-cache Disable the derived-file caching specified by -CacheDir(). +&CacheDir;. scons will neither retrieve files from the cache nor copy files to the cache. - + --cache-force, --cache-populate -When using -CacheDir(), +When using &CacheDir;, populate a cache by copying any already-existing, up-to-date derived files to the cache, in addition to files built by this invocation. @@ -558,23 +552,22 @@ or to add to the cache any derived files recently built with caching disabled via the option. - - + + --cache-readonly Use the cache (if enabled) for reading, but do not not update the cache with changed files. - + --cache-show -When using -CacheDir() +When using &CacheDir; and retrieving a derived file from the cache, show the command that would have been executed to build the file, @@ -583,21 +576,20 @@ instead of the usual report, This will produce consistent output for build logs, regardless of whether a target file was rebuilt or retrieved from the cache. - + --config=mode -This specifies how the -Configure +This specifies how the &Configure; call should use or generate the results of configuration tests. The option should be specified from -among the following choices: - +among the following choices. + --config=auto @@ -609,9 +601,9 @@ but will overlook changes in system header files or external commands (such as compilers) if you don't specify those dependecies explicitly. This is the default behavior. - + --config=force @@ -623,9 +615,9 @@ This can be used to explicitly force the configuration tests to be updated in response to an otherwise unconfigured change in a system header file or compiler. - + --config=cache @@ -636,9 +628,9 @@ Note that scons will still consider it an error if --config=cache is specified and a necessary test does not yet have any results in the cache. - + -C directory, --directory=directory @@ -653,7 +645,7 @@ That is, change directory before searching for the &Sconstruct.py; or &sconstruct.py; -file, or doing anything else. +file or doing anything else. When multiple options are given, each subsequent non-absolute @@ -730,18 +722,18 @@ have been compiled with optimization (that is, when executing from *.pyo files). - + --debug=duplicate Print a line for each unlink/relink (or copy) of a variant file from its source file. Includes debugging info for unlinking stale variant files, as well as unlinking old targets before building them. - + --debug=explain @@ -752,9 +744,9 @@ is deciding to (re-)build any targets. for targets that are not rebuilt.) - + --debug=findlibs @@ -762,9 +754,9 @@ rebuilt.) to print a message about each potential library name it is searching for, and about the actual libraries it finds. - + --debug=includes @@ -778,6 +770,7 @@ $ scons --debug=includes foo.o + --debug=memoizer @@ -785,35 +778,35 @@ $ scons --debug=includes foo.o an internal subsystem that counts how often SCons uses cached values in memory instead of recomputing them each time they're needed. - + --debug=memory Prints how much memory SCons uses before and after reading the SConscript files and before and after building targets. - + --debug=objects Prints a list of the various objects of the various classes used internally by SCons. - + --debug=pdb Re-run SCons under the control of the -pdb +pdb Python debugger. - + --debug=prepare @@ -826,9 +819,9 @@ This can help debug problems with targets that aren't being built; it shows whether scons is at least considering them or not. - + --debug=presub @@ -836,50 +829,51 @@ is at least considering them or not. before the construction environment variables are substituted. Also shows which targets are being built by this command. Output looks something like this: + $ scons --debug=presub Building myprog.o with action(s): $SHCC $SHCFLAGS $SHCCFLAGS $CPPFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES ... - + --debug=stacktrace Prints an internal Python stack trace when encountering an otherwise unexplained error. - + --debug=time Prints various time profiling information: - - + + The time spent executing each individual build command - - + + The total build time (time SCons ran from beginning to end) - - + + The total time spent reading and executing SConscript files - - -The total time spent SCons itself spend running + + +The total time SCons itself spent running (that is, not counting reading and executing SConscript files) - - + + The total time spent executing all build commands - + The elapsed wall-clock time spent executing those build commands - - + + The time spent processing each file passed to the SConscript() function - - + + (When scons @@ -950,9 +944,9 @@ or of not handling errors gracefully found in SCCS or RCS, for example, or if a file really does exist where the SCons configuration expects a directory). - + --duplicate=ORDER @@ -971,22 +965,23 @@ or copy. SCons will attempt to duplicate files using the mechanisms in the specified order. + + - - --enable-virtualenv Import virtualenv-related variables to SCons. + - -f file, --file=file, --makefile=file, --sconstruct=file + -f file, --file=file, --makefile=file, --sconstruct=file Use file @@ -997,29 +992,29 @@ options may be specified, in which case scons will read all of the specified files. - + -h, --help Print a local help message for this build, if one is defined in -the SConscript file(s), plus a line that describes the +the SConscript files, plus a line that describes the option for command-line option help. If no local help message is defined, prints the standard help message about command-line options. Exits after displaying the appropriate message. - + -H, --help-options Print the standard help message about command-line options and exit. - + -i, --ignore-errors @@ -1027,6 +1022,7 @@ exit. + -I directory, --include-dir=directory @@ -1037,15 +1033,16 @@ imported Python modules. If several options are used, the directories are searched in the order specified. - - - --ignore-virtualenv - + + + --ignore-virtualenv + Suppress importing virtualenv-related variables to SCons. - - + + + --implicit-cache @@ -1057,9 +1054,6 @@ from the last time it was run instead of scanning the files for implicit dependencies. This can significantly speed up SCons, but with the following limitations: - - - scons will not detect changes to implicit dependency search paths @@ -1075,17 +1069,18 @@ dependency is added earlier in the implicit dependency search path (e.g. CPPPATH, LIBPATH) than a current implicit dependency with the same name. + + - --implicit-deps-changed Forces SCons to ignore the cached implicit dependencies. This causes the implicit dependencies to be rescanned and recached. This implies . - + --implicit-deps-unchanged @@ -1093,7 +1088,6 @@ implicit dependencies to be rescanned and recached. This implies This causes cached implicit dependencies to always be used. This implies . - @@ -1157,7 +1151,6 @@ command: --taskmastertrace=FILE --tree=OPTIONS - @@ -1182,9 +1175,9 @@ with the specified options. is a synonym. This command is itself a synonym for build --clean - + exit @@ -1192,9 +1185,9 @@ This command is itself a synonym for You can also exit by terminating input (CTRL+D on UNIX or Linux systems, CTRL+Z on Windows systems). - + help[COMMAND] @@ -1207,9 +1200,9 @@ is specified, and ? are synonyms. - + shell[COMMANDLINE] @@ -1232,9 +1225,9 @@ environment variable and ! are synonyms. - + version @@ -1276,15 +1269,17 @@ option, the last one is effective. - + -k, --keep-going Continue as much as possible after an error. The target that failed and those that depend on it will not be remade, but other targets specified on the command line will still be processed. + + @@ -1294,7 +1289,6 @@ targets specified on the command line will still be processed. - @@ -1316,16 +1310,13 @@ targets specified on the command line will still be processed. - - -m -Ignored for compatibility with non-GNU versions of -make. - +Ignored for compatibility with non-GNU versions of &Make;. + --max-drift=SECONDS @@ -1343,9 +1334,9 @@ A negative value means to never cache the content signature and to ignore the cached value if there already is one. A value of 0 means to always use the cached signature, no matter how old the file is. - + --md5-chunksize=KILOBYTES @@ -1359,29 +1350,31 @@ small block-size slows down the build considerably. The default value is to use a chunk size of 64 kilobytes, which should be appropriate for most uses. - + -n, --just-print, --dry-run, --recon No execute. Print the commands that would be executed to build any out-of-date target files, but do not execute the commands. - + --no-site-dir Prevents the automatic addition of the standard site_scons dirs to -sys.path. +sys.path. Also prevents loading the -site_scons/site_init.py +site_scons/site_init.py modules if they exist, and prevents adding their -site_scons/site_tools +site_scons/site_tools dirs to the toolpath. + + @@ -1395,6 +1388,7 @@ dirs to the toolpath. + @@ -1413,8 +1407,6 @@ dirs to the toolpath. - - --profile=file @@ -1423,9 +1415,9 @@ and save the results in the specified file. The results may be analyzed using the Python pstats module. - + -q, --question @@ -1434,6 +1426,7 @@ status that is zero if the specified targets are already up to date, non-zero otherwise. + -Q @@ -1443,14 +1436,14 @@ building targets and entering directories. Commands that are executed to rebuild target files are still printed. + + - - --random @@ -1458,37 +1451,37 @@ to rebuild target files are still printed. building multiple trees simultaneously with caching enabled, to prevent multiple builds from simultaneously trying to build or retrieve the same target files. - + -s, --silent, --quiet Silent. Do not print commands that are executed to rebuild target files. Also suppresses SCons status messages. - + -S, --no-keep-going, --stop Ignored for compatibility with GNU make. - + - --site-dir=dir + --site-dir=dir -Uses the named dir as the site dir rather than the default +Uses the named dir as the site dir rather than the default site_scons dirs. This dir will get prepended to -sys.path, +sys.path, the module -dir/site_init.py +dir/site_init.py will get loaded if it exists, and -dir/site_tools +dir/site_tools will get added to the default toolpath. The default set of @@ -1497,18 +1490,15 @@ dirs used when is not specified depends on the system platform, as follows. Note that the directories are examined in the order given, from most -generic to most specific, so the last-executed site_init.py file is +generic to most specific, so the last-executed site_init.py file is the most specific one (which gives it the chance to override everything else), and the dirs are prepended to the paths, again so the last dir examined comes first in the resulting path. - - - - - - Windows: - + + + Windows: + %ALLUSERSPROFILE/Application Data/scons/site_scons %USERPROFILE%/Local Settings/Application Data/scons/site_scons @@ -1516,11 +1506,12 @@ the last dir examined comes first in the resulting path. %HOME%/.scons/site_scons ./site_scons - - - - Mac OS X: - + + + + + Mac OS X: + /Library/Application Support/SCons/site_scons /opt/local/share/scons/site_scons (for MacPorts) @@ -1529,32 +1520,36 @@ $HOME/Library/Application Support/SCons/site_scons $HOME/.scons/site_scons ./site_scons - - - - Solaris: - + + + + + Solaris: + /opt/sfw/scons/site_scons /usr/share/scons/site_scons $HOME/.scons/site_scons ./site_scons - - - - Linux, HPUX, and other Posix-like systems: - + + + + + Linux, HPUX, and other Posix-like systems: + /usr/share/scons/site_scons $HOME/.scons/site_scons ./site_scons + + + - - + --stack-size=KILOBYTES @@ -1575,9 +1570,9 @@ build process. The default value is to use a stack size of 256 kilobytes, which should be appropriate for most uses. You should not need to increase this value unless you encounter stack overflow errors. - + -t, --touch @@ -1586,9 +1581,9 @@ unless you encounter stack overflow errors. (Touching a file to make it appear up-to-date is unnecessary when using scons.) - + --taskmastertrace=file @@ -1599,9 +1594,9 @@ evaluates and controls the order in which Nodes are built. A file name of - may be used to specify the standard output. - + -tree=options @@ -1612,9 +1607,9 @@ in various formats, depending on the options specified: - + --tree=all @@ -1622,24 +1617,24 @@ specified: after each top-level target is built. This prints out the complete dependency tree, including implicit dependencies and ignored dependencies. - + --tree=derived Restricts the tree output to only derived (target) files, not source files. - + --tree=status Prints status information for each displayed node. - + --tree=prune @@ -1651,7 +1646,6 @@ will have its name printed in as an indication that the dependencies for that node can be found by searching for the relevant output higher up in the tree. - @@ -1673,21 +1667,16 @@ scons --tree=all,prune,status target -u, --up, --search-up Walks up the directory structure until an -SConstruct , -Sconstruct , -sconstruct , -SConstruct.py -Sconstruct.py -or -sconstruct.py +&SConstruct;, &Sconstruct;, &sconstruct;, &SConstruct.py;, +&Sconstruct.py; or &sconstruct.py; file is found, and uses that as the top of the directory tree. If no targets are specified on the command line, only targets at or below the current directory will be built. - + -U @@ -1698,9 +1687,9 @@ When this option is used and no targets are specified on the command line, all default targets that are defined in the SConscript(s) in the current directory are built, regardless of what directory the resultant targets end up in. - + -v, --version @@ -1709,40 +1698,40 @@ up in. version, copyright information, list of authors, and any other relevant information. Then exit. - + -w, --print-directory Print a message containing the working directory before and after other processing. - + --no-print-directory Turn off -w, even if it was turned on implicitly. - + --warn=type, --warn=no-type Enable or disable warnings. type specifies the type of warnings to be enabled or disabled: - + --warn=all, --warn=no-all Enables or disables all warnings. - + --warn=cache-version, --warn=no-cache-version @@ -1750,9 +1739,9 @@ specifies the type of warnings to be enabled or disabled: the latest configuration information CacheDir(). These warnings are enabled by default. - + --warn=cache-write-error, --warn=no-cache-write-error @@ -1760,9 +1749,9 @@ These warnings are enabled by default. write a copy of a built file to a specified CacheDir(). These warnings are disabled by default. - + --warn=corrupt-sconsign, --warn=no-corrupt-sconsign @@ -1770,17 +1759,17 @@ These warnings are disabled by default. .sconsign files. These warnings are enabled by default. - + --warn=dependency, --warn=no-dependency Enables or disables warnings about dependencies. These warnings are disabled by default. - + --warn=deprecated, --warn=no-deprecated @@ -1797,9 +1786,9 @@ before they are officially no longer supported by SCons. Warnings for some specific deprecated features may be enabled or disabled individually; see below. - + --warn=duplicate-environment, --warn=no-duplicate-environment @@ -1807,18 +1796,18 @@ see below. of a target with two different construction environments that use the same action. These warnings are enabled by default. - + --warn=fortran-cxx-mix, --warn=no-fortran-cxx-mix Enables or disables the specific warning about linking Fortran and C++ object files in a single executable, which can yield unpredictable behavior with some compilers. - + --warn=future-deprecated, --warn=no-future-deprecated @@ -1831,16 +1820,16 @@ SCons configurations for other users to build, so that the project can be warned as soon as possible about to-be-deprecated features that may require changes to the configuration. - + --warn=link, --warn=no-link Enables or disables warnings about link steps. - + --warn=misleading-keywords, --warn=no-misleading-keywords @@ -1856,17 +1845,17 @@ characters, the correct spellings are and source.) These warnings are enabled by default. - + --warn=missing-sconscript, --warn=no-missing-sconscript Enables or disables warnings about missing SConscript files. These warnings are enabled by default. - + --warn=no-object-count, --warn=no-no-object-count @@ -1877,9 +1866,9 @@ feature not working when is run with the Python option or from optimized Python (.pyo) modules. - + --warn=no-parallel-support, --warn=no-no-parallel-support @@ -1888,18 +1877,18 @@ not being able to support parallel builds when the option is used. These warnings are enabled by default. - + --warn=python-version, --warn=no-python-version Enables or disables the warning about running SCons with a deprecated version of Python. These warnings are enabled by default. - + --warn=reserved-variable, --warn=no-reserved-variable @@ -1915,15 +1904,29 @@ reserved construction variable names or UNCHANGED_TARGETS. These warnings are disabled by default. - + --warn=stack-size, --warn=no-stack-size Enables or disables warnings about requests to set the stack size that could not be honored. These warnings are enabled by default. + + + + + --warn=target_not_build, --warn=no-target_not_built + +Enables or disables warnings about a build rule not building the + expected targets. These warnings are not currently enabled by default. + + + + + + @@ -1943,20 +1946,6 @@ These warnings are enabled by default. - - - - - - - - --warn=target_not_build, --warn=no-target_not_built - -Enables or disables warnings about a build rule not building the - expected targets. These warnings are not currently enabled by default. - - - -Y repository, --repository=repository, --srcdir=repository @@ -1965,9 +1954,9 @@ files not found in the local directory hierarchy. Multiple options may be specified, in which case the repositories are searched in the order specified. - + @@ -1976,10 +1965,10 @@ repositories are searched in the order specified. Construction Environments -A construction environment is the basic means by which the SConscript +A &ConsEnv; is the basic means by which the SConscript files communicate build information to scons. -A new construction environment is created using the +A new &consenv; is created using the Environment function: @@ -1988,27 +1977,26 @@ env = Environment() Variables, called -construction -variables, -may be set in a construction environment +&ConsVars; +may be set in a &consenv; either by specifying them as keywords when the object is created or by assigning them a value after the object is created: -env = Environment(FOO = 'foo') +env = Environment(FOO='foo') env['BAR'] = 'bar' As a convenience, -construction variables may also be set or modified by the -parse_flags +&consvars; may also be set or modified by the +parse_flags keyword argument, which applies the &f-link-env-MergeFlags; method (described below) to the argument value after all other processing is completed. This is useful either if the exact content of the flags is unknown (for example, read from a control file) -or if the flags are distributed to a number of construction variables. +or if the flags are distributed to a number of &consvars;. env = Environment(parse_flags='-Iinclude -DEBUG -lm') @@ -2021,9 +2009,9 @@ env = Environment(parse_flags='-Iinclude -DEBUG -lm') and 'm' to LIBS. -By default, a new construction environment is +By default, a new &consenv; is initialized with a set of builder methods -and construction variables that are appropriate +and &consvars; that are appropriate for the current platform. An optional platform keyword argument may be used to specify that an environment should @@ -2037,7 +2025,7 @@ env = Environment(platform = 'win32') Specifying a platform initializes the appropriate -construction variables in the environment +&consvars; in the environment to use and generate file names with prefixes and suffixes appropriate for the platform. @@ -2328,8 +2316,8 @@ path strings: if the string begins with the # character it is top-relative - it works like a relative path but the search follows down from the directory containing the top-level -SConstruct rather than -from the current directory (the # is allowed +&SConstruct; rather than +from the current directory (the # is allowed to be followed by a pathname separator, which is ignored if found in that position). Top-relative paths only work in places where &scons; will @@ -2636,14 +2624,14 @@ construction variables like $TARGET and $SOURCE -when using the chdir +when using the chdir keyword argument--that is, the expanded file names will still be relative to -the top-level SConstruct directory, +the top-level directory where &SConstruct; was found, and consequently incorrect relative to the chdir directory. -If you use the chdir keyword argument, +If you use the chdir keyword argument, you will typically need to supply a different command line using expansions like @@ -2654,7 +2642,7 @@ to use just the filename portion of the targets and source. scons -predefined the following builder methods. +predefines the following builder methods. Depending on the setup of a particular &consenv; and on the type and software installation status of the underlying system, @@ -2745,7 +2733,8 @@ object. -Methods and Functions to Do Things + +Methods and Functions To Do Things In addition to Builder methods, scons provides a number of other construction environment methods @@ -2754,41 +2743,30 @@ manipulate the build configuration. Usually, a construction environment method and global function with the same name both exist -so that you don't have to remember whether -to a specific bit of functionality -must be called with or without a construction environment. -In the following list, -if you call something as a global function -it looks like: +for convenience. +In the following list, the global function +is documented like: Function(arguments) -and if you call something through a construction -environment it looks like: +and the construction environment method looks like: env.Function(arguments) -If you can call the functionality in both ways, +If you can call the function in both ways, then both forms are listed. -Global functions may be called from custom Python modules that you -import into an SConscript file by adding the following -to the Python module: - - -from SCons.Script import * - - -Except where otherwise noted, -the same-named +The global function and same-named construction environment method -and global function -provide the exact same functionality. -The only difference is that, -where appropriate, +provide almost identical functionality, with a couple of exceptions. +First, many of the construction environment methods affect only that +construction environment, while the global function has a +global effect. Second, where appropriate, calling the functionality through a construction environment will substitute construction variables into -any supplied strings. +any supplied strings, while the global function doesn't have the +context of a construction environment to pick variables from, +so it cannot perform the substitution. For example: @@ -2814,6 +2792,14 @@ For more on construction variable expansion, see the next section on construction variables. +Global functions may be called from custom Python modules that you +import into an SConscript file by adding the following import +to the Python module: + + +from SCons.Script import * + + Construction environment methods and global functions supported by scons @@ -2937,9 +2923,10 @@ else: scons will actually try to build, regardless of whether they were specified on -the command line or via the -Default() -function or method. +the command line or via the &Default; +function or method +(but empty if neither +command line targets or &Default; calls are present). The elements of this list may be strings or nodes, so you should run the list through the Python @@ -2949,8 +2936,7 @@ are converted to strings. Because this list may be taken from the list of targets specified using the -Default() -function or method, +&Default; function or method, the contents of the list may change on each successive call to Default(). @@ -2973,7 +2959,7 @@ if 'special/program' in BUILD_TARGETS: Note that the BUILD_TARGETS -list only contains targets expected listed +list only contains targets listed on the command line or via calls to the Default() function or method. @@ -3991,9 +3977,9 @@ opt.AddVariables( 'notset', validator, None), ) - + Update(env, [args]) @@ -4015,13 +4001,12 @@ the Environment() function: env = Environment(variables=vars) - The text file(s) that were specified -when the Variables object was created +when the &Variables; object was created are executed as Python scripts, and the values of (global) Python variables set in the file are added to the construction environment. @@ -4405,9 +4390,7 @@ in SConscript files: of the given file or directory. This path is relative to the top-level directory -(where the -SConstruct -file is found). +(where the &SConstruct; file is found). The build path is the same as the source path if variant_dir is not being used. @@ -5095,14 +5078,14 @@ construction variables like $TARGET and $SOURCE -when using the chdir +when using the chdir keyword argument--that is, the expanded file names will still be relative to -the top-level SConstruct directory, +the top-level directory containing the &SConstruct; file, and consequently incorrect relative to the chdir directory. -Builders created using chdir keyword argument, +Builders created using chdir keyword argument, will need to use construction variable expansions like ${TARGET.file} @@ -5433,14 +5416,14 @@ construction variables like $TARGET and $SOURCE -when using the chdir +when using the chdir keyword argument--that is, the expanded file names will still be relative to -the top-level SConstruct directory, +the top-level directory containing the &SConstruct; file, and consequently incorrect relative to the chdir directory. -Builders created using chdir keyword argument, +Builders created using chdir keyword argument, will need to use construction variable expansions like ${TARGET.file} @@ -7052,7 +7035,7 @@ prefix and suffix for the current platform Customizing construction variables from the command line. The following would allow the C compiler to be specified on the command -line or in the file custom.py. +line or in the file custom.py. vars = Variables('custom.py') @@ -7067,7 +7050,7 @@ Help(vars.GenerateHelpText(env)) scons "CC=my_cc" -or in the custom.py file: +or in the custom.py file: CC = 'my_cc' @@ -7171,7 +7154,10 @@ However the following variables are imported by SCONS_LIB_DIR Specifies the directory that contains the &scons; -Python module directory (for example, +Python module directory. Normally &scons; can deduce this, +but in some circumstances, such as working with a source +release, it may be necessary to specify +(for example, /home/aroach/scons-src-0.01/src/engine). @@ -7211,7 +7197,7 @@ Remove the cache file in case of problems with this. &scons; will ignore failures reading or writing the file and will silently revert to non-cached behavior in such cases. -Since &scons; 3.1. +Since &scons; 3.1 (experimental). -- cgit v0.12 From fef866618b5b93bebbc44b58b317aa9bb891313e Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 27 Jan 2020 07:35:33 -0800 Subject: [skip appveyor] update .travis.yml to try to fix broken build --- .travis.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 985a544..99d6802 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,13 +19,6 @@ install: # do the rest of the image setup - ./.travis/install.sh -# pypy is not passing atm, but still report build success for now -# allow coverage to fail, so we can still do testing for all platforms -matrix: - allow_failures: - - python: pypy3 - - stage: Coverage - # run coverage first as its still useful to collect stages: - Coverage @@ -43,6 +36,12 @@ stages: # apparently not guaranteed. jobs: + + # pypy is not passing atm, but still report build success for now + # allow coverage to fail, so we can still do testing for all platforms + allow_failures: + - python: pypy3 + - stage: Coverage include: - &test_job stage: Test -- cgit v0.12 From bb7c5827d957a85f71093412b64571cbb5061514 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 27 Jan 2020 07:43:21 -0800 Subject: [skip appveyor] update .travis.yml to try to fix warning build --- .travis.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 99d6802..b941f4c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -52,29 +52,24 @@ jobs: env: - PYVER=pypy3 - PYTHON=pypy3 - sudo: required - - <<: *test_job python: 3.5 env: - PYVER=35 - PYTHON=3.5 - sudo: required - <<: *test_job python: 3.6 env: - PYVER=36 - PYTHON=3.6 - sudo: required - <<: *test_job python: 3.7 env: - PYVER=37 - PYTHON=3.7 - sudo: required dist: xenial # required for Python >= 3.7 - <<: *test_job @@ -82,7 +77,6 @@ jobs: env: - PYVER=38 - PYTHON=3.8 - sudo: required dist: bionic # required for Python >= 3.8 -- cgit v0.12 From 68c7c2e6c22cab4301213ecada1516caea7c05ae Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Tue, 28 Jan 2020 07:26:46 -0700 Subject: Restore test syntax after earlier change dropped it. Signed-off-by: Mats Wichmann --- test/srcchange.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/srcchange.py b/test/srcchange.py index c2356b6..3c23737 100644 --- a/test/srcchange.py +++ b/test/srcchange.py @@ -62,7 +62,7 @@ SubRevision = Action(subrevision) env=Environment() content_env=env.Clone() -content_env.Command('revision.in', [], '%(_python_)s getrevision > $TARGET') +content_env.Command('revision.in', [], r'%(_python_)s getrevision > $TARGET') content_env.AlwaysBuild('revision.in') env.Precious('main.c') env.Command('main.c', 'revision.in', SubRevision) -- cgit v0.12 From f61e0f79acb17b182d3c509eceb6f8d2d1f42939 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Wed, 29 Jan 2020 07:24:21 -0700 Subject: Fix regex from recent change The new Python scanner had a couple of regexes not specified as raw strings. Python 3.9a3 complains about invalid escape, causing the option/debug-count test to fail. Adding the 'r' fixes. Signed-off-by: Mats Wichmann --- src/CHANGES.txt | 2 +- src/engine/SCons/Scanner/Python.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 36537cf..3d8b114 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -43,7 +43,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Convert remaining uses of insecure/deprecated mktemp method. - Clean up some duplications in manpage. Clarify portion of manpage on Dir and File nodes. - Reduce needless list conversions. - + - Another Python regex syntax fix. RELEASE 3.1.2 - Mon, 17 Dec 2019 02:06:27 +0000 diff --git a/src/engine/SCons/Scanner/Python.py b/src/engine/SCons/Scanner/Python.py index 0ab3111..deb2241 100644 --- a/src/engine/SCons/Scanner/Python.py +++ b/src/engine/SCons/Scanner/Python.py @@ -42,8 +42,8 @@ import re import SCons.Scanner # Capture python "from a import b" and "import a" statements. -from_cre = re.compile('^\s*from\s+([^\s]+)\s+import\s+(.*)', re.M) -import_cre = re.compile('^\s*import\s+([^\s]+)', re.M) +from_cre = re.compile(r'^\s*from\s+([^\s]+)\s+import\s+(.*)', re.M) +import_cre = re.compile(r'^\s*import\s+([^\s]+)', re.M) def path_function(env, dir=None, target=None, source=None, argument=None): -- cgit v0.12 From eb9f9e4b73df82a7ab0cffc3f66bbc513c72618f Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Wed, 29 Jan 2020 12:03:47 -0700 Subject: Requested update to CHANGES.txt --- src/CHANGES.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 3d8b114..99184ed 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -43,7 +43,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Convert remaining uses of insecure/deprecated mktemp method. - Clean up some duplications in manpage. Clarify portion of manpage on Dir and File nodes. - Reduce needless list conversions. - - Another Python regex syntax fix. + - Fixed regex in Python scanner. RELEASE 3.1.2 - Mon, 17 Dec 2019 02:06:27 +0000 -- cgit v0.12 From 64cd9e82dfa5cbf5374cd1ffe2578930307a879e Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 30 Jan 2020 10:10:12 -0800 Subject: Updated to expected configure context temporary and generated files to match new scheme to add contents and action hash to file name to avoid mistakenly reusing the wrong temp file based on changing the order and/or number of the configure tests being run between successive runs --- src/engine/SCons/Builder.py | 2 ++ test/Configure/ConfigureDryRunError.py | 2 +- test/Configure/basic.py | 6 ++-- test/Configure/implicit-cache.py | 4 +-- test/Configure/issue-3469/fixture/SConstruct.2 | 1 + testing/framework/TestSCons.py | 43 ++++++++++++-------------- 6 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/engine/SCons/Builder.py b/src/engine/SCons/Builder.py index e3fb396..69bb19e 100644 --- a/src/engine/SCons/Builder.py +++ b/src/engine/SCons/Builder.py @@ -647,6 +647,8 @@ class BuilderBase(object): env_kw = kw else: env_kw = self.overrides + + # TODO if env_kw: then the following line. there's no purpose in calling if no overrides. env = env.Override(env_kw) return self._execute(env, target, source, OverrideWarner(kw), ekw) diff --git a/test/Configure/ConfigureDryRunError.py b/test/Configure/ConfigureDryRunError.py index 1b89b03..ad40ea4 100644 --- a/test/Configure/ConfigureDryRunError.py +++ b/test/Configure/ConfigureDryRunError.py @@ -67,7 +67,7 @@ test.run(arguments='-n', status=2, stderr=expect) test.must_not_exist('config.log') test.subdir('.sconf_temp') -conftest_0_c = os.path.join(".sconf_temp", "conftest_0.c") +conftest_0_c = os.path.join(".sconf_temp", "conftest_df286a1d2f67e69d030b4eff75ca7e12_0.c") SConstruct_file_line = test.python_file_line(SConstruct_path, 6)[:-1] expect = """ diff --git a/test/Configure/basic.py b/test/Configure/basic.py index 4038a45..253fa25 100644 --- a/test/Configure/basic.py +++ b/test/Configure/basic.py @@ -28,11 +28,11 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" Verify that basic builds work with Configure contexts. """ -import TestSCons +from TestSCons import TestSCons, ConfigCheckInfo, _obj +from TestCmd import IS_WINDOWS -_obj = TestSCons._obj -test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) +test = TestSCons(match = TestSCons.match_re_dotall) NCR = test.NCR # non-cached rebuild CR = test.CR # cached rebuild (up to date) diff --git a/test/Configure/implicit-cache.py b/test/Configure/implicit-cache.py index 1a9ff34..20bdebb 100644 --- a/test/Configure/implicit-cache.py +++ b/test/Configure/implicit-cache.py @@ -77,7 +77,7 @@ test.write('foo.h', "#define FOO 1\n") test.run(arguments = '.') -test.run_sconsign('-d .sconf_temp -e conftest_0.c --raw .sconsign.dblite') +test.run_sconsign('-d .sconf_temp -e conftest_5a3fa36d51dd2a28d521d6cc0e2e1d04_0.c --raw .sconsign.dblite') old_sconsign_dblite = test.stdout() # Second run: Have the configure subsystem also look for foo.h, so @@ -90,7 +90,7 @@ old_sconsign_dblite = test.stdout() test.run(arguments = '--implicit-cache USE_FOO=1 .') -test.run_sconsign('-d .sconf_temp -e conftest_0.c --raw .sconsign.dblite') +test.run_sconsign('-d .sconf_temp -e conftest_5a3fa36d51dd2a28d521d6cc0e2e1d04_0.c --raw .sconsign.dblite') new_sconsign_dblite = test.stdout() if old_sconsign_dblite != new_sconsign_dblite: diff --git a/test/Configure/issue-3469/fixture/SConstruct.2 b/test/Configure/issue-3469/fixture/SConstruct.2 index df07993..171dc39 100644 --- a/test/Configure/issue-3469/fixture/SConstruct.2 +++ b/test/Configure/issue-3469/fixture/SConstruct.2 @@ -32,6 +32,7 @@ if env['SKIP'] and not conf.CheckCXXHeader('math.h'): Exit(1) + # # if not conf.CheckCHeader('stdlib.h'): # print('stdlib.h must be installed!') diff --git a/testing/framework/TestSCons.py b/testing/framework/TestSCons.py index 59a739a..3e6943b 100644 --- a/testing/framework/TestSCons.py +++ b/testing/framework/TestSCons.py @@ -1334,26 +1334,6 @@ SConscript(sconscript) try: - # Build regexp for a character which is not - # a linesep, and in the case of CR/LF - # build it with both CR and CR/LF - # TODO: Not sure why this is a good idea. A static string - # could do the same since we only have two variations - # to do with? - # ls = os.linesep - # nols = "(" - # for i in range(len(ls)): - # nols = nols + "(" - # for j in range(i): - # nols = nols + ls[j] - # nols = nols + "[^" + ls[i] + "])" - # if i < len(ls)-1: - # nols = nols + "|" - # nols = nols + ")" - # - # Replaced above logic with \n as we're reading the file - # using non-binary read. Python will translate \r\n -> \n - # For us. ls = '\n' nols = '([^\n])' lastEnd = 0 @@ -1392,8 +1372,25 @@ SConscript(sconscript) result_cached = 1 for bld_desc in cache_desc: # each TryXXX for ext, flag in bld_desc: # each file in TryBuild - conf_filename = re.escape(os.path.join(sconf_dir, "conftest")) +\ - r'_[a-z0-9]{32}_%d' % cnt + re.escape(ext) + if ext in ['.c','.cpp']: + conf_filename = re.escape(os.path.join(sconf_dir, "conftest")) +\ + r'_[a-z0-9]{32}_\d+%s' % re.escape(ext) + elif ext == '': + conf_filename = re.escape(os.path.join(sconf_dir, "conftest")) +\ + r'_[a-z0-9]{32}(_\d+_[a-z0-9]{32})?' + + else: + # We allow the second hash group to be optional because + # TryLink() will create a c file, then compile to obj, then link that + # The intermediate object file will not get the action hash + # But TryCompile()'s where the product is the .o will get the + # action hash. Rather than add a ton of complications to this logic + # this shortcut should be sufficient. + # TODO: perhaps revisit and/or fix file naming for intermediate files in + # Configure context logic + conf_filename = re.escape(os.path.join(sconf_dir, "conftest")) +\ + r'_[a-z0-9]{32}_\d+(_[a-z0-9]{32})?%s' % re.escape(ext) + if flag == self.NCR: # NCR = Non Cached Rebuild @@ -1426,7 +1423,7 @@ SConscript(sconscript) re.escape("\" failed in a previous run and all its sources are up to date.") + ls log = log + re.escape("scons: Configure: The original builder output was:") + ls log = log + r"( \|.*" + ls + ")+" - cnt = cnt + 1 + # cnt = cnt + 1 if result_cached: result = "(cached) " + result rdstr = rdstr + re.escape(check) + re.escape(result) + "\n" -- cgit v0.12 From fa04d252813955e777be37b672be56fa6d2cfd76 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 30 Jan 2020 11:56:29 -0800 Subject: Improve debug output when configure test fails stdout check --- testing/framework/TestSCons.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/testing/framework/TestSCons.py b/testing/framework/TestSCons.py index 3e6943b..2f20950 100644 --- a/testing/framework/TestSCons.py +++ b/testing/framework/TestSCons.py @@ -223,7 +223,7 @@ def match_part_of_configlog(log, logfile, lastEnd, NoMatch=NoMatch): """ Match part of the logfile """ - print("Match:\n%s\n==============\n%s" % (log , logfile[lastEnd:])) + # print("Match:\n%s\n==============\n%s" % (log , logfile[lastEnd:])) m = re.match(log, logfile[lastEnd:]) if not m: raise NoMatch(lastEnd) @@ -1330,8 +1330,6 @@ SConscript(sconscript) ------- """ - - try: ls = '\n' @@ -1372,7 +1370,7 @@ SConscript(sconscript) result_cached = 1 for bld_desc in cache_desc: # each TryXXX for ext, flag in bld_desc: # each file in TryBuild - if ext in ['.c','.cpp']: + if ext in ['.c', '.cpp']: conf_filename = re.escape(os.path.join(sconf_dir, "conftest")) +\ r'_[a-z0-9]{32}_\d+%s' % re.escape(ext) elif ext == '': @@ -1391,7 +1389,6 @@ SConscript(sconscript) conf_filename = re.escape(os.path.join(sconf_dir, "conftest")) +\ r'_[a-z0-9]{32}_\d+(_[a-z0-9]{32})?%s' % re.escape(ext) - if flag == self.NCR: # NCR = Non Cached Rebuild # rebuild will pass @@ -1426,6 +1423,7 @@ SConscript(sconscript) # cnt = cnt + 1 if result_cached: result = "(cached) " + result + rdstr = rdstr + re.escape(check) + re.escape(result) + "\n" log = log + re.escape("scons: Configure: " + result) + ls + ls @@ -1456,9 +1454,9 @@ SConscript(sconscript) exp_stdout = self.wrap_stdout(".*", rdstr) if not self.match_re_dotall(self.stdout(), exp_stdout): print("Unexpected stdout: ") - print("-----------------------------------------------------") + print("----Actual-------------------------------------------") print(repr(self.stdout())) - print("-----------------------------------------------------") + print("----Expected-----------------------------------------") print(repr(exp_stdout)) print("-----------------------------------------------------") self.fail_test() -- cgit v0.12 From d5c96ca94fcd8498d480c620b6319d9c13b8aeff Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 30 Jan 2020 11:57:09 -0800 Subject: New test. Fixes Issue #3469 --- test/Configure/issue-3469/issue-3469.py | 94 +++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 test/Configure/issue-3469/issue-3469.py diff --git a/test/Configure/issue-3469/issue-3469.py b/test/Configure/issue-3469/issue-3469.py new file mode 100644 index 0000000..a2fd7c2 --- /dev/null +++ b/test/Configure/issue-3469/issue-3469.py @@ -0,0 +1,94 @@ +#!/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 changing the order and/or number of config tests does not reuse +incorrect temporary test files on successive runs. +This addresses Issue 3469: +https://github.com/SCons/scons/issues/3469 +""" + +import TestSCons + +_exe = TestSCons._exe +_obj = TestSCons._obj +_python_ = TestSCons._python_ + +test = TestSCons.TestSCons() +test.verbose_set(1) + +NCR = test.NCR # non-cached rebuild +CR = test.CR # cached rebuild (up to date) +NCF = test.NCF # non-cached build failure +CF = test.CF # cached build failure + +test.file_fixture('./fixture/SConstruct') + +test.run() + +# First run all tests should build +test.checkLogAndStdout(["Checking for C header file math.h... ", + "Checking for C header file stdlib.h... ", + "Checking for C header file stdio.h... "], + ["yes", "yes", "yes"], + [[(('.c', NCR), (_obj, NCR))], + [(('.c', NCR), (_obj, NCR))], + [(('.c', NCR), (_obj, NCR))]], + "config.log", ".sconf_temp", "SConstruct") + + +# Second run, this will skip middle check. First and third (now second) checks should +# reuse cached +test.run('SKIP=1') +test.checkLogAndStdout(["Checking for C header file math.h... ", + # "Checking for C header file stdlib.h... ", + "Checking for C header file stdio.h... "], + ["yes", "yes", "yes"], + [[(('.c', CR), (_obj, CR))], + # [(('.c', CR), (_obj, CR))], + [(('.c', CR), (_obj, CR))]], + "config.log", ".sconf_temp", "SConstruct") + +# Third run. We're re-adding the middle test, all tests should reuse cached. +test.run('SKIP=0') +test.checkLogAndStdout(["Checking for C header file math.h... ", + "Checking for C header file stdlib.h... ", + "Checking for C header file stdio.h... "], + ["yes", "yes", "yes"], + [[(('.c', CR), (_obj, CR))], + [(('.c', CR), (_obj, CR))], + [(('.c', CR), (_obj, CR))]], + "config.log", ".sconf_temp", "SConstruct") + + + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: -- cgit v0.12 From 337906cbc01693f4daff40bb22028b8a39f0bc6d Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 30 Jan 2020 12:08:43 -0800 Subject: Add blurb to src/CHANGES.txt --- src/CHANGES.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 44b478f..ad936e4 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -16,6 +16,18 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER is a reasonable default and also aligns with changes in Appveyor's VS2019 image. - Drop support for Python 2.7. SCons will be Python 3.5+ going forward. + From Andrew Morrow: + - Fix Issue #3469 - Fixed improper reuse of temporary and compiled files by Configure when changing + the order and/or number of tests. This is done by using the hash of the generated temporary files + content and (For the target files) the hash of the action. + So where previously files would be named: + - config_1.c, config_1.o, config_1 + The will now be named (For example) + - conftest_68b375d16e812c43e6d72d6e93401e7c_0.c, + conftest_68b375d16e812c43e6d72d6e93401e7c_0_5713f09fc605f46b2ab2f7950455f187.o + or + conftest_68b375d16e812c43e6d72d6e93401e7c_0.o + conftest_68b375d16e812c43e6d72d6e93401e7c_0_5713f09fc605f46b2ab2f7950455f187 (for executable) From Mathew Robinson: - Improve performance of Subst by preventing unnecessary frame -- cgit v0.12 From 209d73e6c78978371915f14384bb8fff1902e386 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 30 Jan 2020 14:49:54 -0800 Subject: Fix unit test's mocked builder to have mocked action as the new logic requires an action to call get_contents() to create hash for file naming --- src/engine/SCons/SConfTests.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/engine/SCons/SConfTests.py b/src/engine/SCons/SConfTests.py index c5d1fbd..99927a5 100644 --- a/src/engine/SCons/SConfTests.py +++ b/src/engine/SCons/SConfTests.py @@ -169,10 +169,18 @@ class SConfTestCase(unittest.TestCase): log_file=self.test.workpath('config.log')) import SCons.Builder import SCons.Node + + class MyAction(object): + def get_contents(self, target, source, env): + return 'MyBuilder-MyAction $SOURCE $TARGET' + class MyBuilder(SCons.Builder.BuilderBase): def __init__(self): self.prefix = '' self.suffix = '' + # need action because temporary file name uses has of actions get_contents() + self.action = MyAction() + def __call__(self, env, target, source): class MyNode(object): def __init__(self, name): -- cgit v0.12 From 0d4c31c7adc62f215e6a73d2efa7c2787bee6c83 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 30 Jan 2020 15:03:02 -0800 Subject: Fix tests broken by Configure temp file naming changes --- test/option-n.py | 56 +++++++++++++++++++-------------------- test/question/Configure.py | 4 +-- test/sconsign/script/Configure.py | 6 ++--- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/test/option-n.py b/test/option-n.py index 2ec3fdc..e647b8e 100644 --- a/test/option-n.py +++ b/test/option-n.py @@ -91,27 +91,27 @@ test.fail_test(not os.path.exists(test.workpath('f2.out'))) test.unlink('f1.out') test.unlink('f2.out') -test.run(arguments = '-n ' + args, stdout = expect) +test.run(arguments='-n ' + args, stdout=expect) test.fail_test(os.path.exists(test.workpath('f1.out'))) test.fail_test(os.path.exists(test.workpath('f2.out'))) -test.run(arguments = '--no-exec ' + args, stdout = expect) +test.run(arguments='--no-exec ' + args, stdout=expect) test.fail_test(os.path.exists(test.workpath('f1.out'))) test.fail_test(os.path.exists(test.workpath('f2.out'))) -test.run(arguments = '--just-print ' + args, stdout = expect) +test.run(arguments='--just-print ' + args, stdout=expect) test.fail_test(os.path.exists(test.workpath('f1.out'))) test.fail_test(os.path.exists(test.workpath('f2.out'))) -test.run(arguments = '--dry-run ' + args, stdout = expect) +test.run(arguments='--dry-run ' + args, stdout=expect) test.fail_test(os.path.exists(test.workpath('f1.out'))) test.fail_test(os.path.exists(test.workpath('f2.out'))) -test.run(arguments = '--recon ' + args, stdout = expect) +test.run(arguments='--recon ' + args, stdout=expect) test.fail_test(os.path.exists(test.workpath('f1.out'))) test.fail_test(os.path.exists(test.workpath('f2.out'))) -test.run(arguments = args) +test.run(arguments=args) test.fail_test(not os.path.exists(test.workpath('f1.out'))) # Test that SCons does not write a modified .sconsign when -n is used. @@ -120,14 +120,14 @@ expect = test.wrap_stdout("""\ """ % locals()) test.unlink('.sconsign.dblite') test.write('f1.out', "X1.out\n") -test.run(arguments = '-n f1.out', stdout = expect) -test.run(arguments = '-n f1.out', stdout = expect) +test.run(arguments='-n f1.out', stdout=expect) +test.run(arguments='-n f1.out', stdout=expect) expect = test.wrap_stdout("Removed f1.out\nRemoved f2.out\n", cleaning=1) -test.run(arguments = '-n -c ' + args, stdout = expect) +test.run(arguments='-n -c ' + args, stdout=expect) -test.run(arguments = '-c -n ' + args, stdout = expect) +test.run(arguments='-c -n ' + args, stdout=expect) test.fail_test(not os.path.exists(test.workpath('f1.out'))) test.fail_test(not os.path.exists(test.workpath('f2.out'))) @@ -136,15 +136,15 @@ test.fail_test(not os.path.exists(test.workpath('f2.out'))) install_f3_in = os.path.join('install', 'f3.in') expect = test.wrap_stdout('Install file: "f3.in" as "%s"\n' % install_f3_in) -test.run(arguments = '-n install', stdout = expect) +test.run(arguments='-n install', stdout=expect) test.fail_test(os.path.exists(test.workpath('install', 'f3.in'))) -test.run(arguments = 'install', stdout = expect) +test.run(arguments='install', stdout=expect) test.fail_test(not os.path.exists(test.workpath('install', 'f3.in'))) test.write('f3.in', "f3.in again\n") -test.run(arguments = '-n install', stdout = expect) +test.run(arguments='-n install', stdout=expect) test.fail_test(not os.path.exists(test.workpath('install', 'f3.in'))) # Make sure duplicate source files in a VariantDir aren't created @@ -159,11 +159,11 @@ test.fail_test(not os.path.exists(test.workpath('install', 'f3.in'))) # method on that node, which may happen via other processing. # Therefore add this conditional removal to ensure a clean setting # before running this test. - + if os.path.exists(test.workpath('build', 'f4.in')): test.unlink(test.workpath('build', 'f4.in')) -test.run(arguments = '-n build') +test.run(arguments='-n build') test.fail_test(os.path.exists(test.workpath('build', 'f4.in'))) # test Configure-calls in conjunction with -n @@ -195,11 +195,11 @@ else: env = conf.Finish() """) # test that conf_dir isn't created and an error is raised -stderr=r""" +stderr = r""" scons: \*\*\* Cannot create configure directory "config\.test" within a dry-run\. File \S+, line \S+, in \S+ """ -test.run(arguments="-n",stderr=stderr,status=2, +test.run(arguments="-n", stderr=stderr, status=2, chdir=test.workpath("configure")) test.fail_test(os.path.exists(test.workpath("configure", "config.test"))) test.fail_test(os.path.exists(test.workpath("configure", "config.log"))) @@ -207,12 +207,12 @@ test.fail_test(os.path.exists(test.workpath("configure", "config.log"))) # test that targets are not built, if conf_dir exists. # verify that .cache and config.log are not created. # an error should be raised -stderr=r""" +stderr = r""" scons: \*\*\* Cannot update configure test "%s" within a dry-run\. File \S+, line \S+, in \S+ -""" % re.escape(os.path.join("config.test", "conftest_0.in")) -test.subdir(['configure','config.test']) -test.run(arguments="-n",stderr=stderr,status=2, +""" % re.escape(os.path.join("config.test", "conftest_b10a8db164e0754105b7a99be72e3fe5_0.in")) +test.subdir(['configure', 'config.test']) +test.run(arguments="-n", stderr=stderr, status=2, chdir=test.workpath("configure")) test.fail_test(os.path.exists(test.workpath("configure", "config.test", ".cache"))) @@ -224,15 +224,15 @@ test.fail_test(os.path.exists(test.workpath("configure", "config.log"))) # test that no error is raised, if all targets are up-to-date. In this # case .cache and config.log shouldn't be created -stdout=test.wrap_stdout(build_str="scons: `.' is up to date.\n", - read_str=r"""Executing Custom Test ... \(cached\) yes +stdout = test.wrap_stdout(build_str="scons: `.' is up to date.\n", + read_str=r"""Executing Custom Test ... \(cached\) yes """) -test.run(status=0,chdir=test.workpath("configure")) -log1_mtime = os.path.getmtime(test.workpath("configure","config.log")) -test.run(stdout=stdout,arguments="-n",status=0, +test.run(status=0, chdir=test.workpath("configure")) +log1_mtime = os.path.getmtime(test.workpath("configure", "config.log")) +test.run(stdout=stdout, arguments="-n", status=0, chdir=test.workpath("configure")) -log2_mtime = os.path.getmtime(test.workpath("configure","config.log")) -test.fail_test( log1_mtime != log2_mtime ) +log2_mtime = os.path.getmtime(test.workpath("configure", "config.log")) +test.fail_test(log1_mtime != log2_mtime) test.pass_test() diff --git a/test/question/Configure.py b/test/question/Configure.py index 88b0784..7df29f5 100644 --- a/test/question/Configure.py +++ b/test/question/Configure.py @@ -86,7 +86,7 @@ test.must_not_exist(test.workpath("config.log")) stderr=r""" scons: \*\*\* Cannot update configure test "%s" within a dry-run\. File \S+, line \S+, in \S+ -""" % re.escape(os.path.join("config.test", "conftest_0.in")) +""" % re.escape(os.path.join("config.test", "conftest_b10a8db164e0754105b7a99be72e3fe5_0.in")) test.subdir('config.test') @@ -94,7 +94,7 @@ test.run(arguments="-q aaa.out",stderr=stderr,status=2) test.must_not_exist(test.workpath("config.test", ".cache")) test.must_not_exist(test.workpath("config.test", "conftest_0")) -test.must_not_exist(test.workpath("config.test", "conftest_0.in")) +test.must_not_exist(test.workpath("config.test", "conftest_b10a8db164e0754105b7a99be72e3fe5_0.in")) test.must_not_exist(test.workpath("config.log")) # test that no error is raised, if all targets are up-to-date. In this diff --git a/test/sconsign/script/Configure.py b/test/sconsign/script/Configure.py index 679f084..125022d 100644 --- a/test/sconsign/script/Configure.py +++ b/test/sconsign/script/Configure.py @@ -55,7 +55,6 @@ CC_file = re.escape(CC_file) # in the expected output because paths in the .sconsign files are # canonicalized to use / as the separator. -_sconf_temp_conftest_0_c = '.sconf_temp/conftest_0.c' test.write('SConstruct', """ import os @@ -69,6 +68,7 @@ test.run(arguments = '.') sig_re = r'[0-9a-fA-F]{32}' date_re = r'\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' +_sconf_temp_conftest_0_c = '.sconf_temp/conftest_%(sig_re)s_0.c'%locals() # Note: There's a space at the end of the '.*': line, because the # Value node being printed actually begins with a newline. It would @@ -76,13 +76,13 @@ date_re = r'\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' expect = r"""=== .: SConstruct: None \d+ \d+ === .sconf_temp: -conftest_0.c: +conftest_%(sig_re)s_0.c: '.*': #include "math.h" %(sig_re)s \[.*\] -conftest_0%(_obj)s: +conftest_%(sig_re)s_0_%(sig_re)s%(_obj)s: %(_sconf_temp_conftest_0_c)s: %(sig_re)s \d+ \d+ %(CC)s: %(sig_re)s \d+ \d+ %(sig_re)s \[.*\] -- cgit v0.12 From 461eec6eb3510d4995c6ef445f2555f35fcf18c1 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sun, 26 Jan 2020 12:15:37 -0700 Subject: Add support for VS2017 Express Needed some new logic to accomodate that tools are not in the expected place (if real host is amd64, Express still uses Hostx86 as the tools dir, not Hostx64). Also needed a hack to run vcvarsall.bat with the correct argument. We now derive the "argument" by finding the appropriate host_target vcvars script, which has the argument to vcvarsall embedded, which we then run instead of calling vcvarsall directly. This allows us to deal with the pseudo target that Express has always used - we derive this part of the script name by using an existing lookup table. arm targets were also added (untested). Added some pithy comments (oh, no, the Piths ran away!) Signed-off-by: Mats Wichmann --- src/CHANGES.txt | 3 ++ src/engine/SCons/Tool/MSCommon/vc.py | 99 +++++++++++++++++++++++++++--------- src/engine/SCons/Tool/MSCommon/vs.py | 18 ++++++- 3 files changed, 93 insertions(+), 27 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 99184ed..85a4c97 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -44,6 +44,9 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Clean up some duplications in manpage. Clarify portion of manpage on Dir and File nodes. - Reduce needless list conversions. - Fixed regex in Python scanner. + - Accomodate VS 2017 Express - it's got a more liberal license then VS + Community, so some people prefer it (from 2019, no more Express) + vswhere call should also now work even if programs aren't on the C: drive. RELEASE 3.1.2 - Mon, 17 Dec 2019 02:06:27 +0000 diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py index 6f9bd12..be1fd4d 100644 --- a/src/engine/SCons/Tool/MSCommon/vc.py +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -95,6 +95,9 @@ _ARCH_TO_CANONICAL = { "aarch64" : "arm64", } +# Starting with 14.1 (aka VS2017), the tools are organized by host directory. +# with a target subdir. They are now in .../VC/Auxuiliary/Build. +# Special case: 2017 Express uses Hostx86 even if it's on 64-bit Windows. _HOST_TARGET_TO_CL_DIR_GREATER_THAN_14 = { ("amd64","amd64") : ("Hostx64","x64"), ("amd64","x86") : ("Hostx64","x86"), @@ -106,8 +109,9 @@ _HOST_TARGET_TO_CL_DIR_GREATER_THAN_14 = { ("x86","arm64") : ("Hostx86","arm64"), } -# get path to the cl.exe dir for older VS versions -# based off a tuple of (host, target) platforms +# For older compilers, the original x86 tools are in the tools dir, +# any others are in a subdir named by the host/target pair, +# or just a single word if host==target _HOST_TARGET_TO_CL_DIR = { ("amd64","amd64") : "amd64", ("amd64","x86") : "amd64_x86", @@ -117,23 +121,31 @@ _HOST_TARGET_TO_CL_DIR = { ("x86","x86") : "", ("x86","arm") : "x86_arm", ("x86","arm64") : "x86_arm64", + ("arm","arm") : "arm", } -# Given a (host, target) tuple, return the argument for the bat file. -# Both host and targets should be canonalized. +# Given a (host, target) tuple, return the argument for the bat file; +# For 14.1+ compilers we use this to compose the name of the bat file instead. +# Both host and targets should be canoncalized. +# If the target already looks like a pair, return it - these are +# pseudo targets (mainly used by Express versions) _HOST_TARGET_ARCH_TO_BAT_ARCH = { ("x86", "x86"): "x86", ("x86", "amd64"): "x86_amd64", ("x86", "x86_amd64"): "x86_amd64", - ("amd64", "x86_amd64"): "x86_amd64", # This is present in (at least) VS2012 express + ("amd64", "x86_amd64"): "x86_amd64", ("amd64", "amd64"): "amd64", ("amd64", "x86"): "x86", - ("x86", "ia64"): "x86_ia64", # gone since 14.0 - ("arm", "arm"): "arm", # since 14.0, maybe gone 14.1? - ("x86", "arm"): "x86_arm", # since 14.0 - ("x86", "arm64"): "x86_arm64", # since 14.1 - ("amd64", "arm"): "amd64_arm", # since 14.0 - ("amd64", "arm64"): "amd64_arm64", # since 14.1 + ("x86", "ia64"): "x86_ia64", # gone since 14.0 + ("arm", "arm"): "arm", # since 14.0, maybe gone 14.1? + ("x86", "arm"): "x86_arm", # since 14.0 + ("x86", "arm64"): "x86_arm64", # since 14.1 + ("x86", "x86_arm"): "x86_arm", # since 14.0 + ("x86", "x86_arm64"): "x86_arm64", # since 14.1 + ("amd64", "arm"): "amd64_arm", # since 14.0 + ("amd64", "arm64"): "amd64_arm64", # since 14.1 + ("amd64", "x86_arm"): "x86_arm", # since 14.0 + ("amd64", "x86_arm64"): "x86_arm64", # since 14.1 } _CL_EXE_NAME = 'cl.exe' @@ -403,6 +415,11 @@ def find_batch_file(env,msvc_version,host_arch,target_arch): """ Find the location of the batch script which should set up the compiler for any TARGET_ARCH whose compilers were installed by Visual Studio/VCExpress + + In newer (2017+) compilers, make use of the fact there are vcvars + scripts named with a host_target pair that calls vcvarsall.bat properly, + so use that and return an indication we don't need the argument + we would have computed to run the batch file. """ pdir = find_vc_pdir(msvc_version) if pdir is None: @@ -412,6 +429,7 @@ def find_batch_file(env,msvc_version,host_arch,target_arch): # filter out e.g. "Exp" from the version name msvc_ver_numeric = get_msvc_version_numeric(msvc_version) + use_arg = True vernum = float(msvc_ver_numeric) if 7 <= vernum < 8: pdir = os.path.join(pdir, os.pardir, "Common7", "Tools") @@ -422,7 +440,10 @@ def find_batch_file(env,msvc_version,host_arch,target_arch): elif 8 <= vernum <= 14: batfilename = os.path.join(pdir, "vcvarsall.bat") else: # vernum >= 14.1 VS2017 and above - batfilename = os.path.join(pdir, "Auxiliary", "Build", "vcvarsall.bat") + batfiledir = os.path.join(pdir, "Auxiliary", "Build") + targ = _HOST_TARGET_ARCH_TO_BAT_ARCH[(host_arch, target_arch)] + batfilename = os.path.join(batfiledir, "vcvars%s.bat" % targ) + use_arg = False if not os.path.exists(batfilename): debug("Not found: %s" % batfilename) @@ -437,8 +458,8 @@ def find_batch_file(env,msvc_version,host_arch,target_arch): sdk_bat_file_path = os.path.join(pdir,sdk_bat_file) if os.path.exists(sdk_bat_file_path): debug('find_batch_file() sdk_bat_file_path:%s'%sdk_bat_file_path) - return (batfilename, sdk_bat_file_path) - return (batfilename, None) + return (batfilename, use_arg, sdk_bat_file_path) + return (batfilename, use_arg, None) __INSTALLED_VCS_RUN = None @@ -484,7 +505,8 @@ def _check_cl_exists_in_vc_dir(env, vc_dir, msvc_version): # make sure the cl.exe exists meaning the tool is installed if ver_num > 14: - # 2017 and newer allowed multiple versions of the VC toolset to be installed at the same time. + # 2017 and newer allowed multiple versions of the VC toolset to be + # installed at the same time. This changes the layout. # Just get the default tool version for now #TODO: support setting a specific minor VC version default_toolset_file = os.path.join(vc_dir, _VC_TOOLS_VERSION_FILE) @@ -509,6 +531,20 @@ def _check_cl_exists_in_vc_dir(env, vc_dir, msvc_version): debug('_check_cl_exists_in_vc_dir(): found ' + _CL_EXE_NAME + '!') return True + elif host_platform == "amd64" and host_trgt_dir[0] == "Hostx64": + # Special case: fallback to Hostx86 if Hostx64 was tried + # and failed. We should key this off the "x86_amd64" and + # related pseudo targets, but we don't see them in this function. + # This is because VS 2017 Express running on amd64 will look + # to our probe like the host dir should be Hostx64, but it uses + # Hostx86 anyway. + host_trgt_dir = ("Hostx86", host_trgt_dir[1]) + cl_path = os.path.join(vc_dir, 'Tools','MSVC', vc_specific_version, 'bin', host_trgt_dir[0], host_trgt_dir[1], _CL_EXE_NAME) + debug('_check_cl_exists_in_vc_dir(): checking for ' + _CL_EXE_NAME + ' at ' + cl_path) + if os.path.exists(cl_path): + debug('_check_cl_exists_in_vc_dir(): found ' + _CL_EXE_NAME + '!') + return True + elif 14 >= ver_num >= 8: # Set default value to be -1 as "" which is the value for x86/x86 yields true when tested @@ -705,17 +741,27 @@ def msvc_find_valid_batch_script(env, version): host_platform, target_platform, req_target_platform = platforms try_target_archs = [target_platform] - # VS2012 has a "cross compile" environment to build 64 bit + # Express versions have a "cross compile" environment to build 64 bit # with x86_amd64 as the argument to the batch setup script + # For 2015/2017 Express, this could extend to arm and arm64 targets. if req_target_platform in ('amd64', 'x86_64'): try_target_archs.append('x86_amd64') - elif not req_target_platform and target_platform in ['amd64', 'x86_64']: - # There may not be "native" amd64, but maybe "cross" x86_amd64 tools - try_target_archs.append('x86_amd64') - # If the user hasn't specifically requested a TARGET_ARCH, and - # The TARGET_ARCH is amd64 then also try 32 bits if there are no viable - # 64 bit tools installed - try_target_archs.append('x86') + elif req_target_platform in ('arm',): + try_target_archs.append('x86_arm') + elif req_target_platform in ('arm64',): + try_target_archs.append('x86_arm64') + elif not req_target_platform: + if target_platform in ('amd64', 'x86_64'): + # There may not be "native" amd64, but maybe cross x86_amd64 tools + try_target_archs.append('x86_amd64') + # If the user hasn't specifically requested a TARGET_ARCH, + # and the TARGET_ARCH is amd64 then also try 32 bits + # if there are no viable 64 bit tools installed + try_target_archs.append('x86') + elif target_platform in ('arm',): + try_target_archs.append('x86_arm') + elif target_platform in ('arm64',): + try_target_archs.append('x86_arm64') debug("msvs_find_valid_batch_script(): host_platform: %s try_target_archs:%s"%(host_platform, try_target_archs)) @@ -742,7 +788,7 @@ def msvc_find_valid_batch_script(env, version): # Try to locate a batch file for this host/target platform combo try: - (vc_script, sdk_script) = find_batch_file(env, version, host_platform, tp) + (vc_script, use_arg, sdk_script) = find_batch_file(env, version, host_platform, tp) debug('msvc_find_valid_batch_script() vc_script:%s sdk_script:%s'%(vc_script,sdk_script)) except VisualCException as e: msg = str(e) @@ -758,6 +804,8 @@ def msvc_find_valid_batch_script(env, version): debug('msvc_find_valid_batch_script() use_script 2 %s, args:%s' % (repr(vc_script), arg)) found = None if vc_script: + if not use_arg: + arg = None try: d = script_env(vc_script, args=arg) found = vc_script @@ -823,12 +871,13 @@ def msvc_setup_env(env): return None for k, v in d.items(): - debug('msvc_setup_env() env:%s -> %s'%(k,v)) env.PrependENVPath(k, v, delete_existing=True) + debug("msvc_setup_env() env['ENV']['%s'] = %s" % (k, env['ENV'][k])) # final check to issue a warning if the compiler is not present msvc_cl = find_program_path(env, 'cl') if not msvc_cl: + debug("msvc_setup_env() did not find 'cl'") SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, "Could not find MSVC compiler 'cl', it may need to be installed separately with Visual Studio") diff --git a/src/engine/SCons/Tool/MSCommon/vs.py b/src/engine/SCons/Tool/MSCommon/vs.py index bac35d8..e13f52f 100644 --- a/src/engine/SCons/Tool/MSCommon/vs.py +++ b/src/engine/SCons/Tool/MSCommon/vs.py @@ -205,7 +205,8 @@ SupportedVSList = [ hkeys=[], common_tools_var='VS160COMNTOOLS', executable_path=r'Common7\IDE\devenv.com', - batch_file_path=r'VC\Auxiliary\Build\vsvars32.bat', + # should be a fallback, prefer use vswhere installationPath + batch_file_path=r'Common7\Tools\VsDevCmd.bat', supported_arch=['x86', 'amd64', "arm"], ), @@ -216,10 +217,23 @@ SupportedVSList = [ hkeys=[], common_tools_var='VS150COMNTOOLS', executable_path=r'Common7\IDE\devenv.com', - batch_file_path=r'VC\Auxiliary\Build\vsvars32.bat', + # should be a fallback, prefer use vswhere installationPath + batch_file_path=r'Common7\Tools\VsDevCmd.bat', supported_arch=['x86', 'amd64', "arm"], ), + # Visual C++ 2017 Express Edition (for Desktop) + VisualStudio('14.1Exp', + vc_version='14.1', + sdk_version='10.0A', + hkeys=[], + common_tools_var='VS150COMNTOOLS', + executable_path=r'Common7\IDE\WDExpress.exe', + # should be a fallback, prefer use vswhere installationPath + batch_file_path=r'Common7\Tools\VsDevCmd.bat', + supported_arch=['x86', 'amd64', "arm"], + ), + # Visual Studio 2015 VisualStudio('14.0', vc_version='14.0', -- cgit v0.12 From 1478929815f7934bd8163d511dbc31936bfb3eb7 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Mon, 27 Jan 2020 07:55:18 -0700 Subject: [PR #3538] change way native->native found VS 14.1+ looks for a host/target batch file, except those didn't exist in that form if host=target. add the ability to find those (vcvars32.bat and vcvars64.bat) Signed-off-by: Mats Wichmann --- src/engine/SCons/Tool/MSCommon/vc.py | 65 ++++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 22 deletions(-) diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py index be1fd4d..2832db7 100644 --- a/src/engine/SCons/Tool/MSCommon/vc.py +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -109,7 +109,7 @@ _HOST_TARGET_TO_CL_DIR_GREATER_THAN_14 = { ("x86","arm64") : ("Hostx86","arm64"), } -# For older compilers, the original x86 tools are in the tools dir, +# before 14.1 (VS2017): the original x86 tools are in the tools dir, # any others are in a subdir named by the host/target pair, # or just a single word if host==target _HOST_TARGET_TO_CL_DIR = { @@ -124,8 +124,30 @@ _HOST_TARGET_TO_CL_DIR = { ("arm","arm") : "arm", } +# 14.1 (VS2017) and later: +# Given a (host, target) tuple, return the batch file to look for. +# We can't return an arg for vcvarsall.bat, because that script +# runs anyway, even if given a host/targ pair that isn't installed. +# Targets that already looks like a pair are pseudo targets. +_HOST_TARGET_TO_BAT_ARCH_GT14 = { + ("amd64", "amd64"): "vcvars64.bat", + ("amd64", "x86"): "vcvarsamd64_x86.bat", + ("amd64", "x86_amd64"): "vcvarsx86_amd64.bat", + ("amd64", "arm"): "vcvarsamd64_arm.bat", + ("amd64", "x86_arm"): "vcvarsx86_arm.bat", + ("amd64", "arm64"): "vcvarsamd64_arm64.bat", + ("amd64", "x86_arm64"): "vcvarsx86_arm64.bat", + ("x86", "x86"): "vcvars32.bat", + ("x86", "amd64"): "vcvarsx86_amd64.bat", + ("x86", "x86_amd64"): "vcvarsx86_amd64.bat", + ("x86", "arm"): "vcvarsx86_arm.bat", + ("x86", "x86_arm"): "vcvarsx86_arm.bat", + ("x86", "arm64"): "vcvarsx86_arm64.bat", + ("x86", "x86_arm64"): "vcvarsx86_arm64.bat", +} + +# before 14.1 (VS2017): # Given a (host, target) tuple, return the argument for the bat file; -# For 14.1+ compilers we use this to compose the name of the bat file instead. # Both host and targets should be canoncalized. # If the target already looks like a pair, return it - these are # pseudo targets (mainly used by Express versions) @@ -133,17 +155,16 @@ _HOST_TARGET_ARCH_TO_BAT_ARCH = { ("x86", "x86"): "x86", ("x86", "amd64"): "x86_amd64", ("x86", "x86_amd64"): "x86_amd64", - ("amd64", "x86_amd64"): "x86_amd64", + ("amd64", "x86_amd64"): "x86_amd64", # This is present in (at least) VS2012 express ("amd64", "amd64"): "amd64", ("amd64", "x86"): "x86", - ("x86", "ia64"): "x86_ia64", # gone since 14.0 - ("arm", "arm"): "arm", # since 14.0, maybe gone 14.1? - ("x86", "arm"): "x86_arm", # since 14.0 - ("x86", "arm64"): "x86_arm64", # since 14.1 - ("x86", "x86_arm"): "x86_arm", # since 14.0 - ("x86", "x86_arm64"): "x86_arm64", # since 14.1 - ("amd64", "arm"): "amd64_arm", # since 14.0 - ("amd64", "arm64"): "amd64_arm64", # since 14.1 + ("x86", "ia64"): "x86_ia64", # gone since 14.0 + ("x86", "arm"): "x86_arm", # since 14.0 + ("x86", "arm64"): "x86_arm64", # since 14.1 + ("amd64", "arm"): "amd64_arm", # since 14.0 + ("amd64", "arm64"): "amd64_arm64", # since 14.1 + ("x86", "x86_arm"): "x86_arm", # since 14.0 + ("x86", "x86_arm64"): "x86_arm64", # since 14.1 ("amd64", "x86_arm"): "x86_arm", # since 14.0 ("amd64", "x86_arm64"): "x86_arm64", # since 14.1 } @@ -441,8 +462,8 @@ def find_batch_file(env,msvc_version,host_arch,target_arch): batfilename = os.path.join(pdir, "vcvarsall.bat") else: # vernum >= 14.1 VS2017 and above batfiledir = os.path.join(pdir, "Auxiliary", "Build") - targ = _HOST_TARGET_ARCH_TO_BAT_ARCH[(host_arch, target_arch)] - batfilename = os.path.join(batfiledir, "vcvars%s.bat" % targ) + targ = _HOST_TARGET_TO_BAT_ARCH_GT14[(host_arch, target_arch)] + batfilename = os.path.join(batfiledir, targ) use_arg = False if not os.path.exists(batfilename): @@ -778,14 +799,6 @@ def msvc_find_valid_batch_script(env, version): SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, warn_msg) arg = _HOST_TARGET_ARCH_TO_BAT_ARCH[host_target] - # Get just version numbers - maj, min = msvc_version_to_maj_min(version) - # VS2015+ - if maj >= 14: - if env.get('MSVC_UWP_APP') == '1': - # Initialize environment variables with store/universal paths - arg += ' store' - # Try to locate a batch file for this host/target platform combo try: (vc_script, use_arg, sdk_script) = find_batch_file(env, version, host_platform, tp) @@ -805,7 +818,15 @@ def msvc_find_valid_batch_script(env, version): found = None if vc_script: if not use_arg: - arg = None + arg = '' # bat file will supply platform type + # Get just version numbers + maj, min = msvc_version_to_maj_min(version) + # VS2015+ + if maj >= 14: + if env.get('MSVC_UWP_APP') == '1': + # Initialize environment variables with store/UWP paths + arg = (arg + ' store').lstrip() + try: d = script_env(vc_script, args=arg) found = vc_script -- cgit v0.12 From 384e93561fad65b4bf75771648174593a515528c Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Mon, 27 Jan 2020 10:12:07 -0700 Subject: [PR #3538] fix CHANGES.txt typo/sider complaint [appveyor skip] Signed-off-by: Mats Wichmann --- src/CHANGES.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 85a4c97..72e20fb 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -44,7 +44,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Clean up some duplications in manpage. Clarify portion of manpage on Dir and File nodes. - Reduce needless list conversions. - Fixed regex in Python scanner. - - Accomodate VS 2017 Express - it's got a more liberal license then VS + - Accommodate VS 2017 Express - it's got a more liberal license then VS Community, so some people prefer it (from 2019, no more Express) vswhere call should also now work even if programs aren't on the C: drive. -- cgit v0.12 From 3485896f915dc39e7e385fb72ec7e0321f5e5c58 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 31 Jan 2020 10:32:22 -0700 Subject: [PR #3538] detect vswhere even if not in C: Some changes in vswhere detection - not specific to 2017 Express, but came up in testing so fixing at same time: use the Windows variables for where programs are installed, rather than hardcoding C:. [fixes #3542] Since py2 support is dropped, use the more modern subprocess.run to call vswhere instead of fidlling with a Popen object (change is minimal, but this eliminates the commented aside about Py2 not supporting a context manager on Popen instances, as run() is a complete implementation of setup-call-wait-teardown). Signed-off-by: Mats Wichmann --- src/engine/SCons/Tool/MSCommon/vc.py | 38 +++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py index 2832db7..105c499 100644 --- a/src/engine/SCons/Tool/MSCommon/vc.py +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -41,7 +41,9 @@ import subprocess import os import platform import sys +from contextlib import suppress from string import digits as string_digits +#TODO: Python 2 cleanup if sys.version_info[0] == 2: import collections @@ -332,21 +334,24 @@ def find_vc_pdir_vswhere(msvc_version): debug("Unknown version of MSVC: %s" % msvc_version) raise UnsupportedVersion("Unknown version %s" % msvc_version) - # For bug 3333 - support default location of vswhere for both 64 and 32 bit windows - # installs. - for pf in ['Program Files (x86)', 'Program Files']: + # For bug 3333: support default location of vswhere for both + # 64 and 32 bit windows installs. + # For bug 3542: also accommodate not being on C: drive. + pfpaths = [os.environ["ProgramFiles"]] + with suppress(KeyError): + # 64-bit Windows only, try it first + pfpaths.insert(0, os.environ["ProgramFiles(x86)"]) + for pf in pfpaths: vswhere_path = os.path.join( - 'C:\\', pf, 'Microsoft Visual Studio', 'Installer', 'vswhere.exe' ) if os.path.exists(vswhere_path): - # If we found vswhere, then use it. break else: - # No vswhere on system, no install info available + # No vswhere on system, no install info available this way return None vswhere_cmd = [vswhere_path, @@ -354,22 +359,19 @@ def find_vc_pdir_vswhere(msvc_version): '-version', vswhere_version, '-property', 'installationPath'] - #TODO PY27 cannot use Popen as context manager - # try putting it back to the old way for now - sp = subprocess.Popen(vswhere_cmd, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - vsdir, err = sp.communicate() - if vsdir: - vsdir = vsdir.decode("mbcs").splitlines() + cp = subprocess.run(vswhere_cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + if cp.stdout: + lines = cp.stdout.decode("mbcs").splitlines() # vswhere could easily return multiple lines # we could define a way to pick the one we prefer, but since # this data is currently only used to make a check for existence, # returning the first hit should be good enough for now. - vc_pdir = os.path.join(vsdir[0], 'VC') + vc_pdir = os.path.join(lines[0], 'VC') return vc_pdir else: - # No vswhere on system, no install info available + # We found vswhere, but no install info available for this version return None @@ -661,7 +663,7 @@ def reset_installed_vcs(): # within the same scons run. Windows builds on the CI system were split # into chunks to get around single-build time limits. # With VS2019 it got even slower and an optional persistent cache file -# was introduced. The cache now also stores only the parsed vars, +# was introduced. The cache now also stores only the parsed vars, # not the entire output of running the batch file - saves a bit # of time not parsing every time. @@ -703,7 +705,7 @@ def script_env(script, args=None): return data cache_data = convert(cache_data) - + return cache_data def get_default_version(env): -- cgit v0.12 From 4b410b9b4ea9eb750c66562db49297dfc02a4b3b Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 31 Jan 2020 18:51:51 -0700 Subject: [PR #3538] detect msvc case where target arch is set For Express 2017, no 64-bit tools. When that was fixed to retry with 32-bit tools, the case where a 64-bit target was specified failed. Signed-off-by: Mats Wichmann --- src/CHANGES.txt | 2 +- src/engine/SCons/Tool/MSCommon/vc.py | 43 ++++++++++++++++++++++++------------ 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 72e20fb..047bde1 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -46,7 +46,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Fixed regex in Python scanner. - Accommodate VS 2017 Express - it's got a more liberal license then VS Community, so some people prefer it (from 2019, no more Express) - vswhere call should also now work even if programs aren't on the C: drive. + - vswhere call should also now work even if programs aren't on the C: drive. RELEASE 3.1.2 - Mon, 17 Dec 2019 02:06:27 +0000 diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py index 105c499..f0731b3 100644 --- a/src/engine/SCons/Tool/MSCommon/vc.py +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -135,6 +135,7 @@ _HOST_TARGET_TO_BAT_ARCH_GT14 = { ("amd64", "amd64"): "vcvars64.bat", ("amd64", "x86"): "vcvarsamd64_x86.bat", ("amd64", "x86_amd64"): "vcvarsx86_amd64.bat", + ("amd64", "x86_x86"): "vcvars32.bat", ("amd64", "arm"): "vcvarsamd64_arm.bat", ("amd64", "x86_arm"): "vcvarsx86_arm.bat", ("amd64", "arm64"): "vcvarsamd64_arm64.bat", @@ -160,6 +161,7 @@ _HOST_TARGET_ARCH_TO_BAT_ARCH = { ("amd64", "x86_amd64"): "x86_amd64", # This is present in (at least) VS2012 express ("amd64", "amd64"): "amd64", ("amd64", "x86"): "x86", + ("amd64", "x86_x86"): "x86", ("x86", "ia64"): "x86_ia64", # gone since 14.0 ("x86", "arm"): "x86_arm", # since 14.0 ("x86", "arm64"): "x86_arm64", # since 14.1 @@ -755,43 +757,56 @@ def msvc_setup_env_once(env): env["MSVC_SETUP_RUN"] = True def msvc_find_valid_batch_script(env, version): - debug('msvc_find_valid_batch_script()') - # Find the host platform, target platform, and if present the requested - # target platform + """Find and execute appropriate batch script to set up build env. + + The MSVC build environment depends heavily on having the shell + environment set. SCons does not inherit that, and does not count + on that being set up correctly anyway, so it tries to find the right + MSVC batch script, or the right arguments to the generic batch script + vcvarsall.bat, and run that, so we have a valid environment to build in. + There are dragons here: the batch scripts don't fail (see comments + elsewhere), they just leave you with a bad setup, so try hard to + get it right. + """ + + # Find the host, target, and if present the requested target: platforms = get_host_target(env) debug(" msvs_find_valid_batch_script(): host_platform %s, target_platform %s req_target_platform:%s" % platforms) - host_platform, target_platform, req_target_platform = platforms - try_target_archs = [target_platform] - # Express versions have a "cross compile" environment to build 64 bit - # with x86_amd64 as the argument to the batch setup script - # For 2015/2017 Express, this could extend to arm and arm64 targets. + # Most combinations of host + target are straightforward. + # While all MSVC / Visual Studio tools are pysically 32-bit, they + # make it look like there are 64-bit tools if the host is 64-bit, + # so you can invoke the environment batch script to set up to build, + # say, amd64 host -> x86 target. Express versions are an exception: + # they always look 32-bit, so the batch scripts with 64-bit + # host parts are absent. We try to fix that up in a couple of ways. + # One is here: we make a table of "targets" to try, with the extra + # targets being tags that tell us to try a different "host" instead + # of the deduced host. + try_target_archs = [target_platform] if req_target_platform in ('amd64', 'x86_64'): try_target_archs.append('x86_amd64') + elif req_target_platform in ('x86',): + try_target_archs.append('x86_x86') elif req_target_platform in ('arm',): try_target_archs.append('x86_arm') elif req_target_platform in ('arm64',): try_target_archs.append('x86_arm64') elif not req_target_platform: if target_platform in ('amd64', 'x86_64'): - # There may not be "native" amd64, but maybe cross x86_amd64 tools try_target_archs.append('x86_amd64') # If the user hasn't specifically requested a TARGET_ARCH, # and the TARGET_ARCH is amd64 then also try 32 bits # if there are no viable 64 bit tools installed try_target_archs.append('x86') - elif target_platform in ('arm',): - try_target_archs.append('x86_arm') - elif target_platform in ('arm64',): - try_target_archs.append('x86_arm64') debug("msvs_find_valid_batch_script(): host_platform: %s try_target_archs:%s"%(host_platform, try_target_archs)) d = None for tp in try_target_archs: # Set to current arch. - env['TARGET_ARCH']=tp + env['TARGET_ARCH'] = tp debug("msvc_find_valid_batch_script() trying target_platform:%s"%tp) host_target = (host_platform, tp) -- cgit v0.12 From 4f44de0e7816213b181cb00794bb0fc2b79798b9 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sat, 1 Feb 2020 07:42:53 -0700 Subject: [PR #3538] unbreak msvc tests on non-Windows Make tests still pass when run from a non-Windows platform, was breaking in CI on Linux hosts. Fiddle some more with comments. Add 14.1Exp in more places, including docs. Signed-off-by: Mats Wichmann --- src/engine/SCons/Tool/MSCommon/vc.py | 88 +++++++++++++++++++----------------- src/engine/SCons/Tool/msvc.xml | 1 + 2 files changed, 48 insertions(+), 41 deletions(-) diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py index f0731b3..d955668 100644 --- a/src/engine/SCons/Tool/MSCommon/vc.py +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -98,8 +98,9 @@ _ARCH_TO_CANONICAL = { } # Starting with 14.1 (aka VS2017), the tools are organized by host directory. -# with a target subdir. They are now in .../VC/Auxuiliary/Build. -# Special case: 2017 Express uses Hostx86 even if it's on 64-bit Windows. +# subdirs for each target. They are now in .../VC/Auxuiliary/Build. +# Note 2017 Express uses Hostx86 even if it's on 64-bit Windows, +# not reflected in this table. _HOST_TARGET_TO_CL_DIR_GREATER_THAN_14 = { ("amd64","amd64") : ("Hostx64","x64"), ("amd64","x86") : ("Hostx64","x86"), @@ -128,9 +129,10 @@ _HOST_TARGET_TO_CL_DIR = { # 14.1 (VS2017) and later: # Given a (host, target) tuple, return the batch file to look for. -# We can't return an arg for vcvarsall.bat, because that script -# runs anyway, even if given a host/targ pair that isn't installed. -# Targets that already looks like a pair are pseudo targets. +# We can't rely on returning an arg to use for vcvarsall.bat, +# because that script will run even if given a pair that isn't installed. +# Targets that already look like a pair are pseudo targets that +# effectively mean to skip whatever the host was specified as. _HOST_TARGET_TO_BAT_ARCH_GT14 = { ("amd64", "amd64"): "vcvars64.bat", ("amd64", "x86"): "vcvarsamd64_x86.bat", @@ -151,7 +153,7 @@ _HOST_TARGET_TO_BAT_ARCH_GT14 = { # before 14.1 (VS2017): # Given a (host, target) tuple, return the argument for the bat file; -# Both host and targets should be canoncalized. +# Both host and target should be canoncalized. # If the target already looks like a pair, return it - these are # pseudo targets (mainly used by Express versions) _HOST_TARGET_ARCH_TO_BAT_ARCH = { @@ -231,7 +233,7 @@ def get_host_target(env): # If you update this, update SupportedVSList in Tool/MSCommon/vs.py, and the # MSVC_VERSION documentation in Tool/msvc.xml. -_VCVER = ["14.2", "14.1", "14.0", "14.0Exp", "12.0", "12.0Exp", "11.0", "11.0Exp", "10.0", "10.0Exp", "9.0", "9.0Exp","8.0", "8.0Exp","7.1", "7.0", "6.0"] +_VCVER = ["14.2", "14.1", "14.1Exp", "14.0", "14.0Exp", "12.0", "12.0Exp", "11.0", "11.0Exp", "10.0", "10.0Exp", "9.0", "9.0Exp","8.0", "8.0Exp","7.1", "7.0", "6.0"] # if using vswhere, a further mapping is needed _VCVER_TO_VSWHERE_VER = { @@ -241,9 +243,11 @@ _VCVER_TO_VSWHERE_VER = { _VCVER_TO_PRODUCT_DIR = { '14.2' : [ - (SCons.Util.HKEY_LOCAL_MACHINE, r'')], # VS 2019 doesn't set this key + (SCons.Util.HKEY_LOCAL_MACHINE, r'')], # not set by this version '14.1' : [ - (SCons.Util.HKEY_LOCAL_MACHINE, r'')], # VS 2017 doesn't set this key + (SCons.Util.HKEY_LOCAL_MACHINE, r'')], # not set by this version + '14.1Exp' : [ + (SCons.Util.HKEY_LOCAL_MACHINE, r'')], # not set by this version '14.0' : [ (SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VisualStudio\14.0\Setup\VC\ProductDir')], '14.0Exp' : [ @@ -339,16 +343,17 @@ def find_vc_pdir_vswhere(msvc_version): # For bug 3333: support default location of vswhere for both # 64 and 32 bit windows installs. # For bug 3542: also accommodate not being on C: drive. - pfpaths = [os.environ["ProgramFiles"]] + # NB: this gets called from testsuite on non-Windows platforms. + # Whether that makes sense or not, don't break it for those. + pfpaths = [] with suppress(KeyError): # 64-bit Windows only, try it first - pfpaths.insert(0, os.environ["ProgramFiles(x86)"]) + pfpaths.append(os.environ["ProgramFiles(x86)"]) + with suppress(KeyError): + pfpaths.append(os.environ["ProgramFiles"]) for pf in pfpaths: vswhere_path = os.path.join( - pf, - 'Microsoft Visual Studio', - 'Installer', - 'vswhere.exe' + pf, "Microsoft Visual Studio", "Installer", "vswhere.exe" ) if os.path.exists(vswhere_path): break @@ -356,22 +361,22 @@ def find_vc_pdir_vswhere(msvc_version): # No vswhere on system, no install info available this way return None - vswhere_cmd = [vswhere_path, - '-products', '*', - '-version', vswhere_version, - '-property', 'installationPath'] + vswhere_cmd = [ + vswhere_path, + "-products", "*", + "-version", '[15.0, 16.0)', # vswhere_version, + "-property", "installationPath", + ] - cp = subprocess.run(vswhere_cmd, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) + cp = subprocess.run(vswhere_cmd, capture_output=True) if cp.stdout: - lines = cp.stdout.decode("mbcs").splitlines() - # vswhere could easily return multiple lines - # we could define a way to pick the one we prefer, but since + # vswhere could return multiple lines, e.g. if Build Tools + # and {Community,Professional,Enterprise} are both installed. + # We could define a way to pick the one we prefer, but since # this data is currently only used to make a check for existence, - # returning the first hit should be good enough for now. - vc_pdir = os.path.join(lines[0], 'VC') - return vc_pdir + # returning the first hit should be good enough. + lines = cp.stdout.decode("mbcs").splitlines() + return os.path.join(lines[0], 'VC') else: # We found vswhere, but no install info available for this version return None @@ -444,12 +449,11 @@ def find_batch_file(env,msvc_version,host_arch,target_arch): In newer (2017+) compilers, make use of the fact there are vcvars scripts named with a host_target pair that calls vcvarsall.bat properly, so use that and return an indication we don't need the argument - we would have computed to run the batch file. + we would have computed to run vcvarsall.bat. """ pdir = find_vc_pdir(msvc_version) if pdir is None: raise NoVersionFound("No version of Visual Studio found") - debug('find_batch_file() in {}'.format(pdir)) # filter out e.g. "Exp" from the version name @@ -492,10 +496,12 @@ _VC_TOOLS_VERSION_FILE_PATH = ['Auxiliary', 'Build', 'Microsoft.VCToolsVersion.d _VC_TOOLS_VERSION_FILE = os.sep.join(_VC_TOOLS_VERSION_FILE_PATH) def _check_cl_exists_in_vc_dir(env, vc_dir, msvc_version): - """Find the cl.exe on the filesystem in the vc_dir depending on - TARGET_ARCH, HOST_ARCH and the msvc version. TARGET_ARCH and - HOST_ARCH can be extracted from the passed env, unless its None, - which then the native platform is assumed the host and target. + """Return status of finding a cl.exe to use. + + Locates cl in the vc_dir depending on TARGET_ARCH, HOST_ARCH and the + msvc version. TARGET_ARCH and HOST_ARCH can be extracted from the + passed env, unless it is None, in which case the native platform is + assumed for both host and target. Args: env: Environment @@ -558,11 +564,11 @@ def _check_cl_exists_in_vc_dir(env, vc_dir, msvc_version): elif host_platform == "amd64" and host_trgt_dir[0] == "Hostx64": # Special case: fallback to Hostx86 if Hostx64 was tried - # and failed. We should key this off the "x86_amd64" and - # related pseudo targets, but we don't see them in this function. - # This is because VS 2017 Express running on amd64 will look - # to our probe like the host dir should be Hostx64, but it uses - # Hostx86 anyway. + # and failed. This is because VS 2017 Express running on amd64 + # will look to our probe like the host dir should be Hostx64, + # but Express uses Hostx86 anyway. + # We should key this off the "x86_amd64" and related pseudo + # targets, but we don't see those in this function. host_trgt_dir = ("Hostx86", host_trgt_dir[1]) cl_path = os.path.join(vc_dir, 'Tools','MSVC', vc_specific_version, 'bin', host_trgt_dir[0], host_trgt_dir[1], _CL_EXE_NAME) debug('_check_cl_exists_in_vc_dir(): checking for ' + _CL_EXE_NAME + ' at ' + cl_path) @@ -572,8 +578,8 @@ def _check_cl_exists_in_vc_dir(env, vc_dir, msvc_version): elif 14 >= ver_num >= 8: - # Set default value to be -1 as "" which is the value for x86/x86 yields true when tested - # if not host_trgt_dir + # Set default value to be -1 as "" which is the value for x86/x86 + # yields true when tested if not host_trgt_dir host_trgt_dir = _HOST_TARGET_TO_CL_DIR.get((host_platform, target_platform), None) if host_trgt_dir is None: debug('_check_cl_exists_in_vc_dir(): unsupported host/target platform combo') diff --git a/src/engine/SCons/Tool/msvc.xml b/src/engine/SCons/Tool/msvc.xml index dcac6cc..100c84c 100644 --- a/src/engine/SCons/Tool/msvc.xml +++ b/src/engine/SCons/Tool/msvc.xml @@ -355,6 +355,7 @@ constructor; setting it later has no effect. Valid values for Windows are 14.2, 14.1, +14.1Exp, 14.0, 14.0Exp, 12.0, -- cgit v0.12 From 98e032097907d9c21fc5080456b5870892ac971b Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sat, 1 Feb 2020 16:42:44 -0700 Subject: [PR #3538] roll back use of a too-new Py3 feature subprocess.run kw arg capture_output actually doesn't appear until Python 3.7; drop back to individually setting stdout/stderr. Signed-off-by: Mats Wichmann --- src/engine/SCons/Tool/MSCommon/vc.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py index d955668..2d6fad1 100644 --- a/src/engine/SCons/Tool/MSCommon/vc.py +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -43,6 +43,7 @@ import platform import sys from contextlib import suppress from string import digits as string_digits +from subprocess import PIPE #TODO: Python 2 cleanup if sys.version_info[0] == 2: import collections @@ -368,7 +369,9 @@ def find_vc_pdir_vswhere(msvc_version): "-property", "installationPath", ] - cp = subprocess.run(vswhere_cmd, capture_output=True) + #cp = subprocess.run(vswhere_cmd, capture_output=True) # 3.7+ only + cp = subprocess.run(vswhere_cmd, stdout=PIPE, stderr=PIPE) + if cp.stdout: # vswhere could return multiple lines, e.g. if Build Tools # and {Community,Professional,Enterprise} are both installed. -- cgit v0.12 From 2961f860b169052f6ce780404b2f7161987767a5 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sun, 2 Feb 2020 10:18:58 -0700 Subject: [PR #3538] fix wshwere invoke error During debugging, the call to vswhere which uses a derived version from the table was replaced by a fixed range, and this was unfortunately committed to git. Restoring. Signed-off-by: Mats Wichmann --- src/engine/SCons/Tool/MSCommon/vc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py index 2d6fad1..d22aa9b 100644 --- a/src/engine/SCons/Tool/MSCommon/vc.py +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -365,7 +365,7 @@ def find_vc_pdir_vswhere(msvc_version): vswhere_cmd = [ vswhere_path, "-products", "*", - "-version", '[15.0, 16.0)', # vswhere_version, + "-version", vswhere_version, "-property", "installationPath", ] -- cgit v0.12 From c23b5ad29c14e686aff08da4d76992e06ecfa8c5 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sun, 2 Feb 2020 11:03:11 -0700 Subject: [PR #3538] MSVC UWP test was never updated for 14.2 Has been reporting skipped because not supported due to lookup logic in the testcase. Adding. Signed-off-by: Mats Wichmann --- test/MSVC/MSVC_UWP_APP.py | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/test/MSVC/MSVC_UWP_APP.py b/test/MSVC/MSVC_UWP_APP.py index 861edcd..0f33dda 100644 --- a/test/MSVC/MSVC_UWP_APP.py +++ b/test/MSVC/MSVC_UWP_APP.py @@ -83,23 +83,23 @@ test = TestSCons.TestSCons() test.skip_if_not_msvc() installed_msvc_versions = msvc.cached_get_installed_vcs() -# MSVC guaranteed to be at least one version on the system or else skip_if_not_msvc() function -# would have skipped the test +# MSVC guaranteed to be at least one version on the system or else +# skip_if_not_msvc() function would have skipped the test msvc_140 = '14.0' in installed_msvc_versions msvc_141 = '14.1' in installed_msvc_versions +msvc_142 = '14.2' in installed_msvc_versions -if not (msvc_140 or msvc_141): - test.skip_test("Available MSVC doesn't support App store") +if not any((msvc_140, msvc_141, msvc_142)): + test.skip_test("Available MSVC doesn't support App store\n") if msvc_140: - - test.write('SConstruct', """ + test.write('SConstruct', """\ if ARGUMENTS.get('MSVC_UWP_APP'): help_vars = Variables() help_vars.Add(EnumVariable( 'MSVC_UWP_APP', - 'Build for a Universal Windows Platform (UWP) Application', + 'Build a Universal Windows Platform (UWP) Application', '0', allowed_values=('0', '1'))) else: @@ -128,14 +128,31 @@ print('env[MSVC_VERSION]=%s' % env.get('MSVC_VERSION')) test.fail_test((vclibstore_path_present is True) or (vclibstorerefs_path_present is True), message='VC Store LIBPATHs present when MSVC_UWP_APP not set (msvc_version=%s)' % msvc_version) -if msvc_141: - - test.write('SConstruct', """ +if msvc_141 or msvc_142: + if msvc_142: + test.write('SConstruct', """\ +if ARGUMENTS.get('MSVC_UWP_APP'): + help_vars = Variables() + help_vars.Add(EnumVariable( + 'MSVC_UWP_APP', + 'Build a Universal Windows Platform (UWP) Application', + '0', + allowed_values=('0', '1'))) +else: + help_vars = None +env = Environment(tools=['default', 'msvc'], variables=help_vars, MSVC_VERSION='14.2') +# Print the ENV LIBPATH to stdout +print('env[ENV][LIBPATH]=%s' % env.get('ENV').get('LIBPATH')) +print('env[MSVC_VERSION]=%s' % env.get('MSVC_VERSION')) +print('env[ENV][VSCMD_ARG_app_plat]=%s' % env.get('ENV').get('VSCMD_ARG_app_plat')) +""") + elif msvc_141: + test.write('SConstruct', """\ if ARGUMENTS.get('MSVC_UWP_APP'): help_vars = Variables() help_vars.Add(EnumVariable( 'MSVC_UWP_APP', - 'Build for a Universal Windows Platform (UWP) Application', + 'Build a Universal Windows Platform (UWP) Application', '0', allowed_values=('0', '1'))) else: -- cgit v0.12 From 83f7ea77ddfb5af259821e7437b51e856a004840 Mon Sep 17 00:00:00 2001 From: Konstantin Gonchar Date: Mon, 3 Feb 2020 11:25:29 +0200 Subject: Site downloads section moved --- README-local | 2 +- doc/user/build-install.xml | 2 +- src/README.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README-local b/README-local index 314d735..db855ea 100644 --- a/README-local +++ b/README-local @@ -38,7 +38,7 @@ LATEST VERSION Before going further, you can check for the latest version of the scons-local package, or any SCons package, at the SCons download page: - http://www.scons.org/download.html + https://scons.org/pages/download.html EXECUTION REQUIREMENTS diff --git a/doc/user/build-install.xml b/doc/user/build-install.xml index fbb14e5..105c6df 100644 --- a/doc/user/build-install.xml +++ b/doc/user/build-install.xml @@ -211,7 +211,7 @@ Python 3.7.1 scons-&buildversion;.tar.gz or scons-&buildversion;.zip, which are available from the SCons download page at - http://www.scons.org/download.html. + https://scons.org/pages/download.html. diff --git a/src/README.txt b/src/README.txt index 40d7217..55b71ff 100644 --- a/src/README.txt +++ b/src/README.txt @@ -22,7 +22,7 @@ LATEST VERSION Before going further, you can check that this package you have is the latest version by checking the SCons download page at: - http://www.scons.org/download.html + https://scons.org/pages/download.html EXECUTION REQUIREMENTS -- cgit v0.12 From ae586e9d850b030cad7c2a5bad9ed79547d7f707 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Mon, 3 Feb 2020 16:51:03 -0700 Subject: [PR #3538] vswhere lookup: add choco path Chocolatey install path is now checked. The paths to try use a different method of getting the Windows vars - os.path.expandvars, that avoids the use of a try block or os.environ.get. Signed-off-by: Mats Wichmann --- src/engine/SCons/Tool/MSCommon/vc.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py index d22aa9b..a18a1a7 100644 --- a/src/engine/SCons/Tool/MSCommon/vc.py +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -346,16 +346,15 @@ def find_vc_pdir_vswhere(msvc_version): # For bug 3542: also accommodate not being on C: drive. # NB: this gets called from testsuite on non-Windows platforms. # Whether that makes sense or not, don't break it for those. - pfpaths = [] - with suppress(KeyError): - # 64-bit Windows only, try it first - pfpaths.append(os.environ["ProgramFiles(x86)"]) - with suppress(KeyError): - pfpaths.append(os.environ["ProgramFiles"]) + # TODO: requested to add a user-specified path to vswhere + # and have this routine set the same var if it finds it. + pfpaths = [ + os.path.expandvars(r"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer"), + os.path.expandvars(r"%ProgramFiles%\Microsoft Visual Studio\Installer"), + os.path.expandvars(r"%ChocolateyInstall%\bin"), + ] for pf in pfpaths: - vswhere_path = os.path.join( - pf, "Microsoft Visual Studio", "Installer", "vswhere.exe" - ) + vswhere_path = os.path.join(pf, "vswhere.exe") if os.path.exists(vswhere_path): break else: -- cgit v0.12 From da43aa67f88f7afb64a0aafc03e5464a6c54fe12 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 4 Feb 2020 16:19:26 -0800 Subject: Remove unused fixture SConsctruct.2 --- test/Configure/issue-3469/fixture/SConstruct.2 | 45 -------------------------- 1 file changed, 45 deletions(-) delete mode 100644 test/Configure/issue-3469/fixture/SConstruct.2 diff --git a/test/Configure/issue-3469/fixture/SConstruct.2 b/test/Configure/issue-3469/fixture/SConstruct.2 deleted file mode 100644 index 171dc39..0000000 --- a/test/Configure/issue-3469/fixture/SConstruct.2 +++ /dev/null @@ -1,45 +0,0 @@ -""" -This tests if we add/remove a test in between other tests if a rerun will properly cache the results. -Github issue #3469 - -MongoDB's problem is on 3rd run, a check which expects it's objectfile to have a main doesn't. -This means -This one does the following. -CheckLink -CheckHeader - -""" -import textwrap - -# DefaultEnvironment(tools=[]) - -vars = Variables() -vars.Add(BoolVariable('SKIP', 'Skip Middle Conf test', 0)) -env = Environment(variables=vars) - -print("SKIP:%s" % env['SKIP']) - - -conf = Configure(env, conf_dir='conf2') - -if not env['SKIP']: - int_size = conf.CheckTypeSize('unsigned int') - print("Size:%d"%int_size) - - -if env['SKIP'] and not conf.CheckCXXHeader('math.h'): - print('Math.h must be installed!') - Exit(1) - - - -# -# if not conf.CheckCHeader('stdlib.h'): -# print('stdlib.h must be installed!') -# Exit(1) -# -# if not conf.CheckCHeader('stdio.h'): -# print('stdio.h must be installed!') -# Exit(1) - -env = conf.Finish() -- cgit v0.12 From 8eb485d98dd03df4767766d3e203d602b36e4b2d Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 4 Feb 2020 16:22:20 -0800 Subject: [ci skip] Fix typo --- src/engine/SCons/SConfTests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/SCons/SConfTests.py b/src/engine/SCons/SConfTests.py index 99927a5..40cd69d 100644 --- a/src/engine/SCons/SConfTests.py +++ b/src/engine/SCons/SConfTests.py @@ -178,7 +178,7 @@ class SConfTestCase(unittest.TestCase): def __init__(self): self.prefix = '' self.suffix = '' - # need action because temporary file name uses has of actions get_contents() + # need action because temporary file name uses hash of actions get_contents() self.action = MyAction() def __call__(self, env, target, source): -- cgit v0.12 From cbcfcf4533890dff1a39c7632af58bf6f1e42f85 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Tue, 4 Feb 2020 18:20:20 -0700 Subject: [PR #3533] fix typo [ci skip] Signed-off-by: Mats Wichmann --- doc/user/build-install.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/user/build-install.xml b/doc/user/build-install.xml index f343c02..3463cfb 100644 --- a/doc/user/build-install.xml +++ b/doc/user/build-install.xml @@ -140,7 +140,7 @@ Python 3.7.1 - The canoncical location for information + The canonical location for information about downloading and installing Python is http://www.python.org/download/. See that page and associated links to get started. -- cgit v0.12 From f94e7f2a7dafe32faa2e3892ebabfcf8e75e981d Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 4 Feb 2020 17:31:09 -0800 Subject: [ci skip] Update copyright date. Add Mats to list of contributors. Remove tigris announce list reference --- README.rst | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/README.rst b/README.rst index 2954904..e77d2d2 100755 --- a/README.rst +++ b/README.rst @@ -707,11 +707,6 @@ Subscription to the developer's mailing list is by approval. In practice, no one is refused list membership, but we reserve the right to limit membership in the future and/or weed out lurkers. -There is also a low-volume mailing list available for announcements about -SCons. Subscribe by sending email to: - - announce-subscribe@scons.tigris.org - There are other mailing lists available for SCons users, for notification of SCons code changes, and for notification of updated bug reports and project documents. Please see our mailing lists page for details. @@ -757,8 +752,9 @@ many contributors, including but not at all limited to: - Anatoly Techtonik - Christoph Wiedemann - Russel Winder +- Mats Wichmann \... and many others. -Copyright (c) 2001 - 2019 The SCons Foundation +Copyright (c) 2001 - 2020 The SCons Foundation -- cgit v0.12 From 5003b93da23de2c93a50f0af7dd73f06600c2189 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 4 Feb 2020 17:33:06 -0800 Subject: [ci skip] Update copyright date. Add Mats to list of contributors. Remove tigris announce list reference --- README-SF.rst | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/README-SF.rst b/README-SF.rst index 0c66bb3..d8da15d 100755 --- a/README-SF.rst +++ b/README-SF.rst @@ -683,11 +683,6 @@ Subscription to the developer's mailing list is by approval. In practice, no one is refused list membership, but we reserve the right to limit membership in the future and/or weed out lurkers. -There is also a low-volume mailing list available for announcements about -SCons. Subscribe by sending email to: - - announce-subscribe@scons.tigris.org - There are other mailing lists available for SCons users, for notification of SCons code changes, and for notification of updated bug reports and project documents. Please see our mailing lists page for details. @@ -733,8 +728,9 @@ many contributors, including but not at all limited to: - Anatoly Techtonik - Christoph Wiedemann - Russel Winder +- Mats Wichmann \... and many others. -Copyright (c) 2001 - 2019 The SCons Foundation +Copyright (c) 2001 - 2020 The SCons Foundation -- cgit v0.12 From 66298c456c69287b7e0152eece424440400c35a7 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 4 Feb 2020 17:33:57 -0800 Subject: [ci skip] Update copyright date. Add Mats to list of contributors. Remove tigris announce list reference --- README-local | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/README-local b/README-local index db855ea..3be108c 100644 --- a/README-local +++ b/README-local @@ -202,11 +202,6 @@ Subscription to the developer's mailing list is by approval. In practice, no one is refused list membership, but we reserve the right to limit membership in the future and/or weed out lurkers. -There is also a low-volume mailing list available for announcements about -SCons. Subscribe by sending email to: - - announce-subscribe@scons.tigris.org - There are other mailing lists available for SCons users, for notification of SCons code changes, and for notification of updated bug reports and project documents. Please see our mailing lists page for details. @@ -221,18 +216,28 @@ Check the SCons web site at: http://www.scons.org/ -AUTHOR INFO +Author Info =========== -Steven Knight -knight at baldmt dot com -http://www.baldmt.com/~knight/ - -With plenty of help from the SCons Development team: - Chad Austin - Charles Crain - Steve Leblanc - Anthony Roach - Terrel Shumway - - +SCons was originally written by Steven Knight, knight at baldmt dot com. +Since around 2010 it has been maintained by the SCons +development team, co-managed by Bill Deegan and Gary Oberbrunner, with +many contributors, including but not at all limited to: + +- Chad Austin +- Dirk Baechle +- Charles Crain +- William Deegan +- Steve Leblanc +- Rob Managan +- Greg Noel +- Gary Oberbrunner +- Anthony Roach +- Greg Spencer +- Tom Tanner +- Anatoly Techtonik +- Christoph Wiedemann +- Russel Winder +- Mats Wichmann + +\... and many others. \ No newline at end of file -- cgit v0.12 From 0467a4ab4385dce62b29cf201417d0752e61e898 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 4 Feb 2020 17:34:40 -0800 Subject: [ci skip] Update copyright date. --- LICENSE | 2 +- ReleaseConfig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/LICENSE b/LICENSE index 67e0e2f..9a7749b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2001 - 2019 The SCons Foundation +Copyright (c) 2001 - 2020 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/ReleaseConfig b/ReleaseConfig index 818b405..6532bb1 100755 --- a/ReleaseConfig +++ b/ReleaseConfig @@ -51,7 +51,7 @@ deprecated_python_version = (2, 7, 0) #month_year = 'December 2012' # If copyright years is not given, the release year is used as the end. -copyright_years = '2001 - 2019' +copyright_years = '2001 - 2020' # Local Variables: # tab-width:4 -- cgit v0.12 From 921d33704cae5fe5934a222b7f0f8a49703c0056 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 4 Feb 2020 17:36:38 -0800 Subject: [ci skip] add more instructions to CHANGES.txt on what/how to add your change info to file --- src/CHANGES.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 3acd034..a2319a7 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -5,6 +5,8 @@ Change Log NOTE: The 4.0.0 Release of SCons will drop Python 2.7 Support +NOTE: Please add your name below in alphabetical order by last name. +NOTE: Please include a reference to any Issues resolved by your changes in the bullet(s) you add RELEASE VERSION/DATE TO BE FILLED IN LATER -- cgit v0.12 From 4ec535b19a8fd0192e009dbba0c2a2563cc2eaaf Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 4 Feb 2020 17:44:24 -0800 Subject: [ci skip] Added Discord server info to issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 1 + .github/ISSUE_TEMPLATE/feature_request.md | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index e249a70..41c04f7 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -9,6 +9,7 @@ assignees: '' ## Please bring your issue to the SCons users mailing list before filing an issue here ## See: https://scons.org/bugs.html +## or join our Discord server : https://discord.gg/bXVpWAy **Describe the bug** diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 14f8e7e..5db5bea 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -9,6 +9,7 @@ assignees: '' ## Please bring your feature request to the SCons users mailing list before filing an issue here ## See: https://scons.org/bugs.html +## or join our Discord server : https://discord.gg/bXVpWAy **Describe the Feature** -- cgit v0.12 From 17c5f8270e590432fd781133df681ae7529c4981 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 4 Feb 2020 17:44:56 -0800 Subject: [ci skip] remove py 2.7*. Remove announce mailing list. Add mwichmann to list of developers --- src/README.txt | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/README.txt b/src/README.txt index 55b71ff..01ef436 100644 --- a/src/README.txt +++ b/src/README.txt @@ -28,7 +28,7 @@ the latest version by checking the SCons download page at: EXECUTION REQUIREMENTS ====================== -Running SCons requires Python version 2.7.* or 3.5.* and above. There should be +Running SCons requires Python 3.5.* and above. There should be no other dependencies or requirements to run SCons. (There is, however, an additional requirement to *install* SCons from this particular package; see the next section.) @@ -193,10 +193,6 @@ You may subscribe to the mailing list by sending email to: scons-users-join@scons.org -There is also a low-volume mailing list available for announcements -about SCons. Subscribe by sending email to: - - announce-subscribe@scons.tigris.org There are other mailing lists available for SCons developers, for notification of SCons code changes, and for notification of updated @@ -243,7 +239,8 @@ many contributors, including but not at all limited to: - Anatoly Techtonik - Christoph Wiedemann - Russel Winder +- Mats Wichmann \... and many others. -Copyright (c) 2001 - 2019 The SCons Foundation +Copyright (c) 2001 - 2020 The SCons Foundation -- cgit v0.12 From 0f6204727a4b41d1d60192f1c50c64a8791af158 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 5 Feb 2020 14:00:30 -0800 Subject: [ci skip] Fix SConsRevision.py to properly use with open as f instead of open, which was throwing warnings when run with newer pythons --- site_scons/SConsRevision.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/site_scons/SConsRevision.py b/site_scons/SConsRevision.py index 11de670..f6f7a71 100644 --- a/site_scons/SConsRevision.py +++ b/site_scons/SConsRevision.py @@ -29,12 +29,14 @@ def SCons_revision(target, source, env): contents = contents.replace('__REVISION' + '__', env['REVISION']) contents = contents.replace('__VERSION' + '__', env['VERSION']) contents = contents.replace('__NULL' + '__', '') - open(t, 'w').write(contents) + + with open(t,'w') as of: + of.write(contents) except UnicodeDecodeError as e: print("Error decoding file:%s just copying no revision edit") - with open(s, 'rb') as fp: + with open(s, 'rb') as fp, open(t, 'wb') as of: contents = fp.read() - open(t, 'wb').write(contents) + of.write(contents) os.chmod(t, os.stat(s)[0]) \ No newline at end of file -- cgit v0.12 From ef011014b343288919292560fa24e108874c059a Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 5 Feb 2020 17:19:22 -0800 Subject: [ci skip] update to create #.#.#.devMMYYHHmmss as version string for devel builds. Pypi won't accept the format we had previously with .alpha.#### --- bin/update-release-info.py | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/bin/update-release-info.py b/bin/update-release-info.py index fa7a5f8..f794093 100644 --- a/bin/update-release-info.py +++ b/bin/update-release-info.py @@ -9,7 +9,7 @@ It takes one parameter that says what the mode of update should be, which may be one of 'develop', 'release', or 'post'. In 'develop' mode, which is what someone would use as part of their own -development practices, the release type is forced to be 'alpha' and the +development practices, the release type is forced to be 'dev' and the patch level is the string 'yyyymmdd'. Otherwise, it's the same as the 'release' mode. @@ -30,7 +30,7 @@ in various files: In 'post' mode, files are prepared for the next release cycle: - In ReleaseConfig, the version tuple is updated for the next release by incrementing the release number (either minor or micro, depending - on the branch) and resetting release type to 'alpha'. + on the branch) and resetting release type to 'dev'. - A blank template replaces src/RELEASE.txt. - A new section to accumulate changes is added to src/CHANGES.txt and src/Announce.txt. @@ -110,30 +110,33 @@ else: sys.exit(1) if DEBUG: print('release date', release_date) -if mode == 'develop' and version_tuple[3] != 'alpha': - version_tuple == version_tuple[:3] + ('alpha', 0) + +yyyy,mm,dd,h,m,s = release_date +date_string = "".join(["%.2d"%d for d in time.localtime()[:6]]) + + +if mode == 'develop' and version_tuple[3] != 'dev': + version_tuple == version_tuple[:3] + ('dev', 0) if len(version_tuple) > 3 and version_tuple[3] != 'final': - if mode == 'develop': - version_tuple = version_tuple[:4] + ('yyyymmdd',) - else: - yyyy,mm,dd,_,_,_ = release_date - version_tuple = version_tuple[:4] + ((yyyy*100 + mm)*100 + dd,) -version_string = '.'.join(map(str, version_tuple)) + version_tuple = version_tuple[:4] + ((yyyy*100 + mm)*100 + dd,) + +version_string = '.'.join(map(str, version_tuple[:4])) + date_string + if len(version_tuple) > 3: version_type = version_tuple[3] else: version_type = 'final' if DEBUG: print('version string', version_string) -if version_type not in ['alpha', 'beta', 'candidate', 'final']: +if version_type not in ['dev', 'beta', 'candidate', 'final']: print(("""ERROR: `%s' is not a valid release type in version tuple; -\tit must be one of alpha, beta, candidate, or final""" % version_type)) +\tit must be one of dev, beta, candidate, or final""" % version_type)) sys.exit(1) try: month_year = config['month_year'] except KeyError: - if version_type == 'alpha': + if version_type == 'dev': month_year = 'MONTH YEAR' else: month_year = time.strftime('%B %Y', release_date + (0,0,0)) @@ -176,7 +179,7 @@ class UpdateFile(object): # Determine the pattern to match a version - _rel_types = r'(alpha|beta|candidate|final)' + _rel_types = r'(dev|beta|candidate|final)' match_pat = r'\d+\.\d+\.\d+\.' + _rel_types + r'\.(\d+|yyyymmdd)' match_rel = re.compile(match_pat) @@ -224,7 +227,7 @@ if mode == 'post': # minor release, increment minor value minor = version_tuple[1] + 1 micro = 0 - new_tuple = (version_tuple[0], minor, micro, 'alpha', 0) + new_tuple = (version_tuple[0], minor, micro, 'dev', 0) new_version = '.'.join(map(str, new_tuple[:4])) + '.yyyymmdd' # Update ReleaseConfig -- cgit v0.12 From e8e8d71df80b9b690ef9f2d5b83378f23677e30f Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 7 Feb 2020 11:52:53 -0700 Subject: Stop calling os.system in tests. This converts the remaining tests that called os.system themselves to use subprocess instead. Signed-off-by: Mats Wichmann --- test/AS/as-live.py | 4 ++-- test/Actions/actions.py | 10 ++++++---- test/CC/CCVERSION-fixture/versioned.py | 4 ++-- test/CXX/CXXVERSION.py | 8 +++----- test/DVIPDF/DVIPDF.py | 5 +++-- test/DVIPDF/DVIPDFFLAGS.py | 5 +++-- test/DVIPS/DVIPS.py | 4 ++-- test/DVIPS/DVIPSFLAGS.py | 7 ++++--- test/Ghostscript/GS.py | 5 ++--- test/LINK/LINKFLAGS.py | 6 +++--- test/LINK/SHLINKFLAGS.py | 6 +++--- test/SPAWN.py | 8 +++++--- test/TEX/biber_biblatex.py | 7 ++++--- test/TEX/biber_biblatex2.py | 7 ++++--- test/TEX/biblatex.py | 7 ++++--- test/TEX/biblatex_plain.py | 7 ++++--- test/TEX/clean.py | 7 ++++--- test/TEX/glossaries.py | 7 ++++--- test/TEX/glossary.py | 7 ++++--- test/TEX/lstinputlisting.py | 7 ++++--- test/TEX/multibib.py | 7 ++++--- test/TEX/newglossary.py | 7 ++++--- test/TEX/nomencl.py | 7 ++++--- test/TEX/recursive_scanner_dependencies_import.py | 7 ++++--- test/TEX/variant_dir_bibunit.py | 7 ++++--- test/TEX/variant_dir_newglossary.py | 7 ++++--- test/packaging/use-builddir.py | 15 ++++++--------- 27 files changed, 100 insertions(+), 85 deletions(-) diff --git a/test/AS/as-live.py b/test/AS/as-live.py index b781caf..676b537 100644 --- a/test/AS/as-live.py +++ b/test/AS/as-live.py @@ -56,12 +56,12 @@ if sys.platform == "win32": testccc = "" test.write("wrapper.py", """\ -import os +import subprocess import sys with open('%s', 'wb') as f: f.write(("wrapper.py: %%s\\n" %% sys.argv[-1]).encode()) cmd = " ".join(sys.argv[1:]) -os.system(cmd) +subprocess.run(cmd, shell=True) """ % test.workpath('wrapper.out').replace('\\', '\\\\')) test.write('SConstruct', """\ diff --git a/test/Actions/actions.py b/test/Actions/actions.py index f1bb6fe..cf5890d 100644 --- a/test/Actions/actions.py +++ b/test/Actions/actions.py @@ -65,12 +65,13 @@ test.must_match('foo.out', '2\nfoo.in\n') test.up_to_date(arguments = '.') test.write('SConstruct', """ -import os +import subprocess def func(env, target, source): cmd = r'%(_python_)s build.py %%s 3 %%s' %% (' '.join(map(str, target)), ' '.join(map(str, source))) print(cmd) - return os.system(cmd) + cp = subprocess.run(cmd, shell=True) + return cp.returncode B = Builder(action = func) env = Environment(BUILDERS = { 'B' : B }) env.B(target = 'foo.out', source = 'foo.in') @@ -83,7 +84,7 @@ test.must_match('foo.out', '3\nfoo.in\n') test.up_to_date(arguments = '.') test.write('SConstruct', """ -import os +import subprocess assert 'string' not in globals() class bld(object): def __init__(self): @@ -91,7 +92,8 @@ class bld(object): def __call__(self, env, target, source): cmd = self.get_contents(env, target, source) print(cmd) - return os.system(cmd) + cp = subprocess.run(cmd, shell=True) + return cp.returncode def get_contents(self, env, target, source): return self.cmd %% (' '.join(map(str, target)), ' '.join(map(str, source))) diff --git a/test/CC/CCVERSION-fixture/versioned.py b/test/CC/CCVERSION-fixture/versioned.py index d6c7ae8..33dc574 100644 --- a/test/CC/CCVERSION-fixture/versioned.py +++ b/test/CC/CCVERSION-fixture/versioned.py @@ -1,4 +1,4 @@ -import os +import subprocess import sys if '-dumpversion' in sys.argv: print('3.9.9') @@ -9,4 +9,4 @@ if '--version' in sys.argv: if sys.argv[1] not in [ '2.9.9', '3.9.9' ]: print('wrong version', sys.argv[1], 'when wrapping', sys.argv[2]) sys.exit(1) -os.system(" ".join(sys.argv[2:])) +subprocess.run(" ".join(sys.argv[2:]), shell=True) diff --git a/test/CXX/CXXVERSION.py b/test/CXX/CXXVERSION.py index abe6ce0..50ff8f8 100644 --- a/test/CXX/CXXVERSION.py +++ b/test/CXX/CXXVERSION.py @@ -24,7 +24,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" -import os import sys import TestSCons @@ -37,9 +36,8 @@ if sys.platform == 'win32': test.skip_test('CXXVERSION not set with MSVC, skipping test.') -test.write("versioned.py", -"""from __future__ import print_function -import os +test.write("versioned.py", """\ +import subprocess import sys if '-dumpversion' in sys.argv: print('3.9.9') @@ -50,7 +48,7 @@ if '--version' in sys.argv: if sys.argv[1] not in [ '2.9.9', '3.9.9' ]: print('wrong version', sys.argv[1], 'when wrapping', sys.argv[2]) sys.exit(1) -os.system(" ".join(sys.argv[2:])) +subprocess.run(" ".join(sys.argv[2:]), shell=True) """) test.write('SConstruct', """ diff --git a/test/DVIPDF/DVIPDF.py b/test/DVIPDF/DVIPDF.py index 87f4012..1c017a9 100644 --- a/test/DVIPDF/DVIPDF.py +++ b/test/DVIPDF/DVIPDF.py @@ -107,11 +107,12 @@ tex = test.where_is('tex') if dvipdf and tex: - test.write("wrapper.py", """import os + test.write("wrapper.py", """\ +import subprocess import sys cmd = " ".join(sys.argv[1:]) open('%s', 'a').write("%%s\\n" %% cmd) -os.system(cmd) +subprocess.run(cmd, shell=True) """ % test.workpath('wrapper.out').replace('\\', '\\\\')) test.write('SConstruct', """ diff --git a/test/DVIPDF/DVIPDFFLAGS.py b/test/DVIPDF/DVIPDFFLAGS.py index 30d0e4f..9ecb736 100644 --- a/test/DVIPDF/DVIPDFFLAGS.py +++ b/test/DVIPDF/DVIPDFFLAGS.py @@ -111,11 +111,12 @@ tex = test.where_is('tex') if dvipdf and tex: - test.write("wrapper.py", """import os + test.write("wrapper.py", """\ +import subprocess import sys cmd = " ".join(sys.argv[1:]) open('%s', 'a').write("%%s\\n" %% cmd) -os.system(cmd) +subprocess.run(cmd, shell=True) """ % test.workpath('wrapper.out').replace('\\', '\\\\')) test.write('SConstruct', """ diff --git a/test/DVIPS/DVIPS.py b/test/DVIPS/DVIPS.py index df7811a..3cfd730 100644 --- a/test/DVIPS/DVIPS.py +++ b/test/DVIPS/DVIPS.py @@ -123,11 +123,11 @@ if not dvips: test.skip_test("Could not find 'dvips'; skipping test(s).\n") test.write("wrapper.py", """ -import os +import subprocess import sys cmd = " ".join(sys.argv[1:]) open('%s', 'a').write("%%s\\n" %% cmd) -os.system(cmd) +subprocess.run(cmd, shell=True) """ % test.workpath('wrapper.out').replace('\\', '\\\\')) test.write('SConstruct', """ diff --git a/test/DVIPS/DVIPSFLAGS.py b/test/DVIPS/DVIPSFLAGS.py index b6625d7..f2e6ba9 100644 --- a/test/DVIPS/DVIPSFLAGS.py +++ b/test/DVIPS/DVIPSFLAGS.py @@ -126,11 +126,12 @@ dvips = test.where_is('dvips') if dvips: test.write("wrapper.py", """ -import os +import subprocess import sys cmd = " ".join(sys.argv[1:]) -open('%s', 'a').write("%%s\\n" %% cmd) -os.system(cmd) +with open('%s', 'a') as f: + f.write("%%s\\n" %% cmd) +subprocess.run(cmd, shell=True) """ % test.workpath('wrapper.out').replace('\\', '\\\\')) test.write('SConstruct', """ diff --git a/test/Ghostscript/GS.py b/test/Ghostscript/GS.py index 3f5aa58..68f7427 100644 --- a/test/Ghostscript/GS.py +++ b/test/Ghostscript/GS.py @@ -74,13 +74,12 @@ else: gs = test.where_is(gs_executable) if gs: - test.write("wrapper.py", """\ -import os +import subprocess import sys cmd = " ".join(sys.argv[1:]) open('%s', 'a').write("%%s\\n" %% cmd) -os.system(cmd) +subprocess.run(cmd, shell=True) """ % test.workpath('wrapper.out').replace('\\', '\\\\')) test.write('SConstruct', """\ diff --git a/test/LINK/LINKFLAGS.py b/test/LINK/LINKFLAGS.py index 1642459..749e369 100644 --- a/test/LINK/LINKFLAGS.py +++ b/test/LINK/LINKFLAGS.py @@ -33,13 +33,13 @@ _exe = TestSCons._exe test = TestSCons.TestSCons() -test.write("wrapper.py", -"""import os +test.write("wrapper.py", """\ +import subprocess import sys with open('%s', 'wb') as f: f.write(("wrapper.py\\n").encode()) args = [s for s in sys.argv[1:] if s != 'fake_link_flag'] -os.system(" ".join(args)) +subprocess.run(" ".join(args), shell=True) """ % test.workpath('wrapper.out').replace('\\', '\\\\')) test.write('SConstruct', """ diff --git a/test/LINK/SHLINKFLAGS.py b/test/LINK/SHLINKFLAGS.py index ab90ece..af5bdbb 100644 --- a/test/LINK/SHLINKFLAGS.py +++ b/test/LINK/SHLINKFLAGS.py @@ -34,13 +34,13 @@ _shlib = TestSCons._dll test = TestSCons.TestSCons() -test.write("wrapper.py", -"""import os +test.write("wrapper.py", """ +import subprocess import sys with open('%s', 'wb') as f: f.write(("wrapper.py\\n").encode()) args = [s for s in sys.argv[1:] if s != 'fake_shlink_flag'] -os.system(" ".join(args)) +subprocess.run(" ".join(args), shell=True) """ % test.workpath('wrapper.out').replace('\\', '\\\\')) test.write('SConstruct', """ diff --git a/test/SPAWN.py b/test/SPAWN.py index fba21d5..1949eb6 100644 --- a/test/SPAWN.py +++ b/test/SPAWN.py @@ -43,18 +43,20 @@ with open(sys.argv[1], 'wb') as ofp: """) test.write('SConstruct', """ -import os +import subprocess import sys def my_spawn1(sh, escape, cmd, args, env): s = " ".join(args + ['extra1.txt']) if sys.platform in ['win32']: s = '"' + s + '"' - os.system(s) + cp = subprocess.run(s, shell=True) + return cp.returncode def my_spawn2(sh, escape, cmd, args, env): s = " ".join(args + ['extra2.txt']) if sys.platform in ['win32']: s = '"' + s + '"' - os.system(s) + cp = subprocess.run(s, shell=True) + return cp.returncode env = Environment(MY_SPAWN1 = my_spawn1, MY_SPAWN2 = my_spawn2, COMMAND = r'%(_python_)s cat.py $TARGET $SOURCES') diff --git a/test/TEX/biber_biblatex.py b/test/TEX/biber_biblatex.py index 6ee8121..10c75af 100755 --- a/test/TEX/biber_biblatex.py +++ b/test/TEX/biber_biblatex.py @@ -30,8 +30,9 @@ Test creation of a Tex document that uses the multibib oackage Test courtesy Rob Managan. """ +import subprocess + import TestSCons -import os test = TestSCons.TestSCons() @@ -43,8 +44,8 @@ biber = test.where_is('biber') if not biber: test.skip_test("Could not find 'biber'; skipping test.\n") -gloss = os.system('kpsewhich biblatex.sty') -if not gloss==0: +cp = subprocess.run('kpsewhich biblatex.sty', shell=True) +if cp.returncode: test.skip_test("biblatex.sty not installed; skipping test(s).\n") diff --git a/test/TEX/biber_biblatex2.py b/test/TEX/biber_biblatex2.py index 61fafcf..92c7ea9 100644 --- a/test/TEX/biber_biblatex2.py +++ b/test/TEX/biber_biblatex2.py @@ -32,8 +32,9 @@ Require both be installed Test courtesy Rob Managan. """ +import subprocess + import TestSCons -import os test = TestSCons.TestSCons() @@ -49,8 +50,8 @@ bibtex = test.where_is('bibtex') if not bibtex: test.skip_test("Could not find 'bibtex'; skipping test.\n") -biblatex = os.system('kpsewhich biblatex.sty') -if not biblatex==0: +cp = subprocess.run('kpsewhich biblatex.sty', shell=True) +if cp.returncode: test.skip_test("biblatex.sty not installed; skipping test(s).\n") diff --git a/test/TEX/biblatex.py b/test/TEX/biblatex.py index bb88aaa..1e605cf 100755 --- a/test/TEX/biblatex.py +++ b/test/TEX/biblatex.py @@ -30,8 +30,9 @@ Test creation of a Tex document that uses the biblatex package Test courtesy Rob Managan. """ +import subprocess + import TestSCons -import os test = TestSCons.TestSCons() @@ -39,8 +40,8 @@ latex = test.where_is('pdflatex') if not latex: test.skip_test("Could not find 'pdflatex'; skipping test.\n") -biblatex = os.system('kpsewhich biblatex.sty') -if not biblatex==0: +cp = subprocess.run('kpsewhich biblatex.sty', shell=True) +if cp.returncode: test.skip_test("biblatex.sty not installed; skipping test(s).\n") diff --git a/test/TEX/biblatex_plain.py b/test/TEX/biblatex_plain.py index 5cad924..0fe15f8 100644 --- a/test/TEX/biblatex_plain.py +++ b/test/TEX/biblatex_plain.py @@ -30,8 +30,9 @@ Test creation of a Tex document that uses the biblatex package Test courtesy Rob Managan. """ +import subprocess + import TestSCons -import os test = TestSCons.TestSCons() @@ -39,8 +40,8 @@ latex = test.where_is('pdflatex') if not latex: test.skip_test("Could not find 'pdflatex'; skipping test.\n") -biblatex = os.system('kpsewhich biblatex.sty') -if not biblatex==0: +cp = subprocess.run('kpsewhich biblatex.sty', shell=True) +if cp.returncode: test.skip_test("biblatex.sty not installed; skipping test(s).\n") diff --git a/test/TEX/clean.py b/test/TEX/clean.py index 781caa1..4cae61d 100644 --- a/test/TEX/clean.py +++ b/test/TEX/clean.py @@ -28,7 +28,8 @@ r""" Check that all auxilary files created by LaTeX are properly cleaned by scons -c. """ -import os +import subprocess + import TestSCons test = TestSCons.TestSCons() @@ -38,8 +39,8 @@ latex = test.where_is('latex') if not latex: test.skip_test("Could not find 'latex'; skipping test(s).\n") -comment = os.system('kpsewhich comment.sty') -if not comment==0: +cp = subprocess.run('kpsewhich comment.sty', shell=True) +if cp.returncode: test.skip_test("comment.sty not installed; skipping test(s).\n") # package hyperref generates foo.out diff --git a/test/TEX/glossaries.py b/test/TEX/glossaries.py index cbb6964..a9fd1dc 100644 --- a/test/TEX/glossaries.py +++ b/test/TEX/glossaries.py @@ -31,7 +31,8 @@ be aware of the necessary created glossary files. Test configuration contributed by Robert Managan. """ -import os +import subprocess + import TestSCons test = TestSCons.TestSCons() @@ -41,8 +42,8 @@ latex = test.where_is('latex') if not latex: test.skip_test("Could not find 'latex'; skipping test(s).\n") -gloss = os.system('kpsewhich glossaries.sty') -if not gloss==0: +cp = subprocess.run('kpsewhich glossaries.sty', shell=True) +if cp.returncode: test.skip_test("glossaries.sty not installed; skipping test(s).\n") test.write('SConstruct', """\ diff --git a/test/TEX/glossary.py b/test/TEX/glossary.py index ef13ca1..d4ab579 100644 --- a/test/TEX/glossary.py +++ b/test/TEX/glossary.py @@ -31,7 +31,8 @@ be aware of the necessary created glossary files. Test configuration contributed by Robert Managan. """ -import os +import subprocess + import TestSCons test = TestSCons.TestSCons() @@ -41,8 +42,8 @@ latex = test.where_is('latex') if not latex: test.skip_test("Could not find 'latex'; skipping test(s).\n") -gloss = os.system('kpsewhich glossary.sty') -if not gloss==0: +cp = subprocess.run('kpsewhich glossary.sty', shell=True) +if cp.returncode: test.skip_test("glossary.sty not installed; skipping test(s).\n") test.write('SConstruct', """\ diff --git a/test/TEX/lstinputlisting.py b/test/TEX/lstinputlisting.py index 1f5020b..40f935b 100644 --- a/test/TEX/lstinputlisting.py +++ b/test/TEX/lstinputlisting.py @@ -31,8 +31,9 @@ changes. Thanks to Stefan Hepp for the patch that fixed this. """ +import subprocess + import TestSCons -import os test = TestSCons.TestSCons() @@ -41,8 +42,8 @@ pdflatex = test.where_is('pdflatex') if not pdflatex: test.skip_test("Could not find 'pdflatex'; skipping test(s).\n") -listings = os.system('kpsewhich listings.sty') -if not listings==0: +cp = subprocess.run('kpsewhich listings.sty', shell=True) +if cp.returncode: test.skip_test("listings.sty not installed; skipping test(s).\n") test.write(['SConstruct'], """\ diff --git a/test/TEX/multibib.py b/test/TEX/multibib.py index 114ade6..f80384a 100644 --- a/test/TEX/multibib.py +++ b/test/TEX/multibib.py @@ -30,8 +30,9 @@ Test creation of a Tex document that uses the multibib oackage Test courtesy Rob Managan. """ +import subprocess + import TestSCons -import os test = TestSCons.TestSCons() @@ -39,8 +40,8 @@ latex = test.where_is('latex') if not latex: test.skip_test("Could not find 'latex'; skipping test.\n") -multibib = os.system('kpsewhich multibib.sty') -if not multibib==0: +cp = subprocess.run('kpsewhich multibib.sty', shell=True) +if cp.returncode: test.skip_test("multibib.sty not installed; skipping test(s).\n") test.subdir(['src']) diff --git a/test/TEX/newglossary.py b/test/TEX/newglossary.py index 5d868a8..70296cf 100644 --- a/test/TEX/newglossary.py +++ b/test/TEX/newglossary.py @@ -31,7 +31,8 @@ be aware of the necessary created glossary files. Test configuration contributed by Robert Managan. """ -import os +import subprocess + import TestSCons test = TestSCons.TestSCons() @@ -41,8 +42,8 @@ latex = test.where_is('latex') if not latex: test.skip_test("Could not find 'latex'; skipping test(s).\n") -gloss = os.system('kpsewhich glossaries.sty') -if not gloss==0: +cp = subprocess.run('kpsewhich glossaries.sty', shell=True) +if cp.returncode: test.skip_test("glossaries.sty not installed; skipping test(s).\n") test.write('SConstruct', """\ diff --git a/test/TEX/nomencl.py b/test/TEX/nomencl.py index 0eb0b84..9cbced7 100644 --- a/test/TEX/nomencl.py +++ b/test/TEX/nomencl.py @@ -31,7 +31,8 @@ be aware of the necessary created glossary files. Test configuration contributed by Robert Managan. """ -import os +import subprocess + import TestSCons test = TestSCons.TestSCons() @@ -41,8 +42,8 @@ latex = test.where_is('latex') if not latex: test.skip_test("Could not find 'latex'; skipping test(s).\n") -nomencl = os.system('kpsewhich nomencl.sty') -if not nomencl==0: +cp = subprocess.run('kpsewhich nomencl.sty', shell=True) +if cp.returncode: test.skip_test("nomencl.sty not installed; skipping test(s).\n") test.write('SConstruct', """\ diff --git a/test/TEX/recursive_scanner_dependencies_import.py b/test/TEX/recursive_scanner_dependencies_import.py index a7b5e4a..7b6cb65 100644 --- a/test/TEX/recursive_scanner_dependencies_import.py +++ b/test/TEX/recursive_scanner_dependencies_import.py @@ -34,7 +34,8 @@ recursive_scanner_dependencies_input.py test because \input and dependencies are found only by the scanner. """ -import os +import subprocess + import TestSCons test = TestSCons.TestSCons() @@ -44,8 +45,8 @@ pdflatex = test.where_is('pdflatex') if not pdflatex: test.skip_test("Could not find 'pdflatex'; skipping test(s).\n") -latex_import = os.system('kpsewhich import.sty') -if latex_import != 0: +cp = subprocess.run('kpsewhich import.sty', shell=True) +if cp.returncode: test.skip_test("import.sty not installed; skipping test(s).\n") test.subdir('subdir') diff --git a/test/TEX/variant_dir_bibunit.py b/test/TEX/variant_dir_bibunit.py index e127a76..2a669ba 100644 --- a/test/TEX/variant_dir_bibunit.py +++ b/test/TEX/variant_dir_bibunit.py @@ -34,8 +34,9 @@ Latex produces by default. Test courtesy Rob Managan. """ +import subprocess + import TestSCons -import os test = TestSCons.TestSCons() @@ -44,8 +45,8 @@ bibtex = test.where_is('bibtex') if not all((latex, bibtex)): test.skip_test("Could not find 'latex' and/or 'bibtex'; skipping test.\n") -bibunits = os.system('kpsewhich bibunits.sty') -if not bibunits==0: +cp = subprocess.run('kpsewhich bibunits.sty', shell=True) +if cp.returncode: test.skip_test("bibunits.sty not installed; skipping test(s).\n") test.subdir(['src']) diff --git a/test/TEX/variant_dir_newglossary.py b/test/TEX/variant_dir_newglossary.py index 5e4d10d..ae865aa 100644 --- a/test/TEX/variant_dir_newglossary.py +++ b/test/TEX/variant_dir_newglossary.py @@ -31,7 +31,8 @@ with variant_dir. Test configuration contributed by Kendrick Boyd. """ -import os +import subprocess + import TestSCons test = TestSCons.TestSCons() @@ -41,8 +42,8 @@ latex = test.where_is('latex') if not latex: test.skip_test("Could not find 'latex'; skipping test(s).\n") -gloss = os.system('kpsewhich glossaries.sty') -if gloss!=0: +cp = subprocess.run('kpsewhich glossaries.sty', shell=True) +if cp.returncode: test.skip_test("glossaries.sty not installed; skipping test(s).\n") diff --git a/test/packaging/use-builddir.py b/test/packaging/use-builddir.py index 2395a8e..86a8219 100644 --- a/test/packaging/use-builddir.py +++ b/test/packaging/use-builddir.py @@ -28,13 +28,13 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" Test the ability to use the archiver in combination with builddir. """ -import os +import subprocess + import TestSCons python = TestSCons.python test = TestSCons.TestSCons() -test.verbose_set(3) tar = test.detect("TAR", "tar") if not tar: @@ -48,9 +48,7 @@ test.subdir("build") test.write("src/main.c", "") -test.write( - "SConstruct", - """ +test.write("SConstruct", """\ VariantDir('build', 'src') DefaultEnvironment(tools=[]) env=Environment(tools=['packaging', 'filesystem', 'zip']) @@ -76,9 +74,7 @@ test.subdir("temp") test.write("src/main.c", "") -test.write( - "SConstruct", - """ +test.write("SConstruct", """\ DefaultEnvironment(tools=[]) VariantDir('build', 'src') env=Environment(tools=['packaging', 'filesystem', 'tar']) @@ -93,7 +89,8 @@ test.run(stderr=None) test.must_exist("libfoo-1.2.3.tar.gz") -os.system('%s -C temp -xzf %s'%(tar, test.workpath('libfoo-1.2.3.tar.gz') )) +testdir = test.workpath('libfoo-1.2.3.tar.gz') +subprocess.run('%s -C temp -xzf %s' % (tar, testdir), shell=True) test.must_exist("temp/libfoo-1.2.3/src/main.c") test.must_exist("temp/libfoo-1.2.3/SConstruct") -- cgit v0.12 From 14fb32fe61d4cdb15f7ae699b55eaf60bc18ff5b Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 7 Feb 2020 14:35:23 -0700 Subject: Fix a couple of tests After a change to the tool itself, the update-release-info test needed an update to match. This doesn't seem to be sufficient yet. The SPAWN test was updated for this PR, but broke on Windows because apparently too much quoting for calling via subprocess. Dropped the special-case windows quoting in the test itself. Signed-off-by: Mats Wichmann --- test/SPAWN.py | 7 +++---- test/update-release-info/update-release-info.py | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/test/SPAWN.py b/test/SPAWN.py index 1949eb6..ca9d344 100644 --- a/test/SPAWN.py +++ b/test/SPAWN.py @@ -45,18 +45,17 @@ with open(sys.argv[1], 'wb') as ofp: test.write('SConstruct', """ import subprocess import sys + def my_spawn1(sh, escape, cmd, args, env): s = " ".join(args + ['extra1.txt']) - if sys.platform in ['win32']: - s = '"' + s + '"' cp = subprocess.run(s, shell=True) return cp.returncode + def my_spawn2(sh, escape, cmd, args, env): s = " ".join(args + ['extra2.txt']) - if sys.platform in ['win32']: - s = '"' + s + '"' cp = subprocess.run(s, shell=True) return cp.returncode + env = Environment(MY_SPAWN1 = my_spawn1, MY_SPAWN2 = my_spawn2, COMMAND = r'%(_python_)s cat.py $TARGET $SOURCES') diff --git a/test/update-release-info/update-release-info.py b/test/update-release-info/update-release-info.py index d0242a8..0a7f08f 100644 --- a/test/update-release-info/update-release-info.py +++ b/test/update-release-info/update-release-info.py @@ -110,7 +110,7 @@ combo_fail(0, 2) combo_fail(1, 2) combo_fail(0, 1, 2, stdout = """ERROR: `bad' is not a valid release type in version tuple; -\tit must be one of alpha, beta, candidate, or final +\tit must be one of dev, beta, candidate, or final """) # We won't need this entry again, so put in a default -- cgit v0.12 From 95312158803afd4648a83359840a263dc18dd0a2 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 10 Feb 2020 10:17:58 -0800 Subject: Updates work for develop mode --- ReleaseConfig | 2 +- bin/update-release-info.py | 452 ++++++++++++++++++++++++--------------------- 2 files changed, 246 insertions(+), 208 deletions(-) diff --git a/ReleaseConfig b/ReleaseConfig index 6532bb1..64de640 100755 --- a/ReleaseConfig +++ b/ReleaseConfig @@ -32,7 +32,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" # 'final', the patchlevel is set to the release date. This value is # mandatory and must be present in this file. #version_tuple = (2, 2, 0, 'final', 0) -version_tuple = (3, 1, 3, 'alpha', 0) +version_tuple = (3, 1, 3, 'dev', 0) # Python versions prior to unsupported_python_version cause a fatal error # when that version is used. Python versions prior to deprecate_python_version diff --git a/bin/update-release-info.py b/bin/update-release-info.py index f794093..e4d404b 100644 --- a/bin/update-release-info.py +++ b/bin/update-release-info.py @@ -56,103 +56,142 @@ In 'post' mode, files are prepared for the next release cycle: # 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. -from __future__ import print_function - __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import os import sys import time import re +import argparse DEBUG = os.environ.get('DEBUG', 0) -# Evaluate parameter -if len(sys.argv) < 2: - mode = 'develop' -else: - mode = sys.argv[1] - if mode not in ['develop', 'release', 'post']: - print(("""ERROR: `%s' as a parameter is invalid; it must be one of -\tdevelop, release, or post. The default is develop.""" % mode)) - sys.exit(1) - -# Get configuration information - -config = dict() -with open('ReleaseConfig') as f: - releaseconfig = f.read() -exec(releaseconfig, globals(), config) - - -try: - version_tuple = config['version_tuple'] - unsupported_version = config['unsupported_python_version'] - deprecated_version = config['deprecated_python_version'] -except KeyError: - print('''ERROR: Config file must contain at least version_tuple, -\tunsupported_python_version, and deprecated_python_version.''') - sys.exit(1) -if DEBUG: print('version tuple', version_tuple) -if DEBUG: print('unsupported Python version', unsupported_version) -if DEBUG: print('deprecated Python version', deprecated_version) - -try: - release_date = config['release_date'] -except KeyError: - release_date = time.localtime()[:6] -else: - if len(release_date) == 3: - release_date = release_date + time.localtime()[3:6] - if len(release_date) != 6: - print('''ERROR: Invalid release date''', release_date) - sys.exit(1) -if DEBUG: print('release date', release_date) - - -yyyy,mm,dd,h,m,s = release_date -date_string = "".join(["%.2d"%d for d in time.localtime()[:6]]) - - -if mode == 'develop' and version_tuple[3] != 'dev': - version_tuple == version_tuple[:3] + ('dev', 0) -if len(version_tuple) > 3 and version_tuple[3] != 'final': - version_tuple = version_tuple[:4] + ((yyyy*100 + mm)*100 + dd,) - -version_string = '.'.join(map(str, version_tuple[:4])) + date_string - -if len(version_tuple) > 3: - version_type = version_tuple[3] -else: - version_type = 'final' -if DEBUG: print('version string', version_string) - -if version_type not in ['dev', 'beta', 'candidate', 'final']: - print(("""ERROR: `%s' is not a valid release type in version tuple; -\tit must be one of dev, beta, candidate, or final""" % version_type)) - sys.exit(1) - -try: - month_year = config['month_year'] -except KeyError: - if version_type == 'dev': - month_year = 'MONTH YEAR' - else: - month_year = time.strftime('%B %Y', release_date + (0,0,0)) -if DEBUG: print('month year', month_year) - -try: - copyright_years = config['copyright_years'] -except KeyError: - copyright_years = '2001 - %d'%(release_date[0] + 1) -if DEBUG: print('copyright years', copyright_years) +class ReleaseInfo(object): + def __init__(self, args): + self.config = {} + self.args = args + self.release_date = time.localtime()[:6] + self.unsupported_version = None + self.deprecated_version = None + + # version_tuple = (3, 1, 3, 'alpha', 0) + self.version_tuple = (-1, -1, -1, 'not_set', -1) + + self.version_string = "UNSET" + self.version_type = 'UNSET' + self.month_year = 'UNSET' + self.copyright_years = 'UNSET' + self.new_date = 'NEW DATE WILL BE INSERTED HERE' + + self.read_config() + self.process_config() + self.set_new_date() + + def read_config(self): + # Get configuration information + + config = dict() + with open('ReleaseConfig') as f: + release_config = f.read() + exec(release_config, globals(), config) + + self.config = config + + def process_config(self): + """ + Process and validate the config info loaded from ReleaseConfig file + """ + + try: + self.version_tuple = self.config['version_tuple'] + self.unsupported_version = self.config['unsupported_python_version'] + self.deprecated_version = self.config['deprecated_python_version'] + except KeyError: + print('''ERROR: Config file must contain at least version_tuple, + \tunsupported_python_version, and deprecated_python_version.''') + sys.exit(1) + + if 'release_date' in self.config: + self.release_date = self.config['release_date'] + if len(self.release_date) == 3: + self.release_date = self.release_date + time.localtime()[3:6] + if len(self.release_date) != 6: + print('''ERROR: Invalid release date''', self.release_date) + sys.exit(1) + + yyyy, mm, dd, h, m, s = self.release_date + date_string = "".join(["%.2d" % d for d in self.release_date]) + + if self.args.mode == 'develop' and self.version_tuple[3] != 'dev': + self.version_tuple == self.version_tuple[:3] + ('dev', 0) + if len(self.version_tuple) > 3 and self.version_tuple[3] != 'final': + self.version_tuple = self.version_tuple[:4] + ((yyyy * 100 + mm) * 100 + dd,) + + self.version_string = '.'.join(map(str, self.version_tuple[:4])) + date_string + + if len(self.version_tuple) > 3: + self.version_type = self.version_tuple[3] + else: + self.version_type = 'final' + + if self.version_type not in ['dev', 'beta', 'candidate', 'final']: + print(("""ERROR: `%s' is not a valid release type in version tuple; + \tit must be one of dev, beta, candidate, or final""" % self.version_type)) + sys.exit(1) + + try: + self.month_year = self.config['month_year'] + except KeyError: + self.month_year = time.strftime('%B %Y', self.release_date + (0, 0, 0)) + + try: + self.copyright_years = self.config['copyright_years'] + except KeyError: + self.copyright_years = '2001 - %d' % (self.release_date[0] + 1) + + if DEBUG: + print('version tuple', self.version_tuple) + print('unsupported Python version', self.unsupported_version) + print('deprecated Python version', self.deprecated_version) + print('release date', self.release_date) + print('version string', self.version_string) + print('month year', self.month_year) + print('copyright years', self.copyright_years) + + def set_new_date(self): + """ + Determine the release date and the pattern to match a date + Mon, 05 Jun 2010 21:17:15 -0700 + NEW DATE WILL BE INSERTED HERE + """ + min = (time.daylight and time.altzone or time.timezone) // 60 + hr = min // 60 + min = -(min % 60 + hr * 100) + self.new_date = (time.strftime('%a, %d %b %Y %X', self.release_date + (0, 0, 0)) + + ' %+.4d' % min) + class UpdateFile(object): """ XXX """ - def __init__(self, file, orig = None): - if orig is None: orig = file + rel_info = None + mode = 'develop' + _days = r'(Sun|Mon|Tue|Wed|Thu|Fri|Sat)' + _months = r'(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oce|Nov|Dec)' + match_date = r''.join([_days, r', \d\d ', _months, r' \d\d\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d']) + match_date = re.compile(match_date) + + # Determine the pattern to match a version + + _rel_types = r'(dev|beta|candidate|final)' + match_pat = r'\d+\.\d+\.\d+\.' + _rel_types + r'\.(\d+|yyyymmdd)' + match_rel = re.compile(match_pat) + + def __init__(self, file, orig=None): + if orig is None: + orig = file + try: with open(orig, 'r') as f: self.content = f.read() @@ -169,45 +208,21 @@ class UpdateFile(object): # pretend file changed self.orig = '' - def sub(self, pattern, replacement, count = 1): + def sub(self, pattern, replacement, count=1): """ XXX """ self.content = re.sub(pattern, replacement, self.content, count) - def replace_assign(self, name, replacement, count = 1): + def replace_assign(self, name, replacement, count=1): """ XXX """ self.sub('\n' + name + ' = .*', '\n' + name + ' = ' + replacement) - # Determine the pattern to match a version - - _rel_types = r'(dev|beta|candidate|final)' - match_pat = r'\d+\.\d+\.\d+\.' + _rel_types + r'\.(\d+|yyyymmdd)' - match_rel = re.compile(match_pat) - - def replace_version(self, replacement = version_string, count = 1): + def replace_version(self, count=1): """ XXX """ - self.content = self.match_rel.sub(replacement, self.content, count) - - # Determine the release date and the pattern to match a date - # Mon, 05 Jun 2010 21:17:15 -0700 - # NEW DATE WILL BE INSERTED HERE - - if mode == 'develop': - new_date = 'NEW DATE WILL BE INSERTED HERE' - else: - min = (time.daylight and time.altzone or time.timezone)//60 - hr = min // 60 - min = -(min % 60 + hr * 100) - new_date = (time.strftime('%a, %d %b %Y %X', release_date + (0,0,0)) - + ' %+.4d' % min) - - _days = r'(Sun|Mon|Tue|Wed|Thu|Fri|Sat)' - _months = r'(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oce|Nov|Dec)' - match_date = r''.join([_days, r', \d\d ', _months, r' \d\d\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d']) - match_date = re.compile(match_date) + self.content = self.match_rel.sub(rel_info.version_string, self.content, count) - def replace_date(self, replacement = new_date, count = 1): + def replace_date(self, count=1): """ XXX """ - self.content = self.match_date.sub(replacement, self.content, count) + self.content = self.match_date.sub(rel_info.new_date, self.content, count) def __del__(self): """ XXX """ @@ -216,135 +231,158 @@ class UpdateFile(object): with open(self.file, 'w') as f: f.write(self.content) -if mode == 'post': - # Set up for the next release series. - - if version_tuple[2]: - # micro release, increment micro value - minor = version_tuple[1] - micro = version_tuple[2] + 1 - else: - # minor release, increment minor value - minor = version_tuple[1] + 1 - micro = 0 - new_tuple = (version_tuple[0], minor, micro, 'dev', 0) - new_version = '.'.join(map(str, new_tuple[:4])) + '.yyyymmdd' - # Update ReleaseConfig +def main(args, rel_info): + if args.mode == 'post': + # Set up for the next release series. - t = UpdateFile('ReleaseConfig') - if DEBUG: t.file = '/tmp/ReleaseConfig' - t.replace_assign('version_tuple', str(new_tuple)) + if rel_info.version_tuple[2]: + # micro release, increment micro value + minor = rel_info.version_tuple[1] + micro = rel_info.version_tuple[2] + 1 + else: + # minor release, increment minor value + minor = rel_info.version_tuple[1] + 1 + micro = 0 + new_tuple = (rel_info.version_tuple[0], minor, micro, 'dev', 0) + new_version = '.'.join(map(str, new_tuple[:4])) + '.yyyymmdd' + + # Update ReleaseConfig + + t = UpdateFile('ReleaseConfig') + if DEBUG: t.file = '/tmp/ReleaseConfig' + t.replace_assign('version_tuple', str(new_tuple)) + + # Update src/CHANGES.txt + + t = UpdateFile(os.path.join('src', 'CHANGES.txt')) + if DEBUG: t.file = '/tmp/CHANGES.txt' + t.sub('(\nRELEASE .*)', r"""\nRELEASE VERSION/DATE TO BE FILLED IN LATER\n + From John Doe:\n + - Whatever John Doe did.\n + \1""") + + # Update src/RELEASE.txt + + t = UpdateFile(os.path.join('src', 'RELEASE.txt'), + os.path.join('template', 'RELEASE.txt')) + if DEBUG: t.file = '/tmp/RELEASE.txt' + t.replace_version(new_version) + + # Update src/Announce.txt + + t = UpdateFile(os.path.join('src', 'Announce.txt')) + if DEBUG: t.file = '/tmp/Announce.txt' + t.sub('\nRELEASE .*', '\nRELEASE VERSION/DATE TO BE FILLED IN LATER') + announce_pattern = """( + Please note the following important changes scheduled for the next + release: + )""" + announce_replace = (r"""\1 + -- FEATURE THAT WILL CHANGE\n + Please note the following important changes since release """ + + '.'.join(map(str, rel_info.version_tuple[:3])) + ':\n') + t.sub(announce_pattern, announce_replace) + + # Write out the last update and exit + + t = None + sys.exit() # Update src/CHANGES.txt t = UpdateFile(os.path.join('src', 'CHANGES.txt')) if DEBUG: t.file = '/tmp/CHANGES.txt' - t.sub('(\nRELEASE .*)', r"""\nRELEASE VERSION/DATE TO BE FILLED IN LATER\n - From John Doe:\n - - Whatever John Doe did.\n -\1""") + t.sub('\nRELEASE .*', '\nRELEASE ' + rel_info.version_string + ' - ' + rel_info.new_date) # Update src/RELEASE.txt - t = UpdateFile(os.path.join('src', 'RELEASE.txt'), - os.path.join('template', 'RELEASE.txt')) + t = UpdateFile(os.path.join('src', 'RELEASE.txt')) if DEBUG: t.file = '/tmp/RELEASE.txt' - t.replace_version(new_version) + t.replace_version() # Update src/Announce.txt t = UpdateFile(os.path.join('src', 'Announce.txt')) if DEBUG: t.file = '/tmp/Announce.txt' - t.sub('\nRELEASE .*', '\nRELEASE VERSION/DATE TO BE FILLED IN LATER') - announce_pattern = """( - Please note the following important changes scheduled for the next - release: -)""" - announce_replace = (r"""\1 - -- FEATURE THAT WILL CHANGE\n - Please note the following important changes since release """ - + '.'.join(map(str, version_tuple[:3])) + ':\n') - t.sub(announce_pattern, announce_replace) - - # Write out the last update and exit + t.sub('\nRELEASE .*', '\nRELEASE ' + rel_info.version_string + ' - ' + rel_info.new_date) - t = None - sys.exit() + # Update SConstruct -# Update src/CHANGES.txt + t = UpdateFile('SConstruct') + if DEBUG: t.file = '/tmp/SConstruct' + t.replace_assign('month_year', repr(rel_info.month_year)) + t.replace_assign('copyright_years', repr(rel_info.copyright_years)) + t.replace_assign('default_version', repr(rel_info.version_string)) -t = UpdateFile(os.path.join('src', 'CHANGES.txt')) -if DEBUG: t.file = '/tmp/CHANGES.txt' -t.sub('\nRELEASE .*', '\nRELEASE ' + version_string + ' - ' + t.new_date) + # Update README -# Update src/RELEASE.txt + t = UpdateFile('README.rst') + if DEBUG: t.file = '/tmp/README.rst' + t.sub('-' + t.match_pat + r'\.', '-' + rel_info.version_string + '.', count=0) + for suf in ['tar', 'win32', 'zip', 'rpm', 'exe', 'deb']: + t.sub(r'-(\d+\.\d+\.\d+)\.%s' % suf, + '-%s.%s' % (rel_info.version_string, suf), + count=0) -t = UpdateFile(os.path.join('src', 'RELEASE.txt')) -if DEBUG: t.file = '/tmp/RELEASE.txt' -t.replace_version() + # Update testing/framework/TestSCons.py -# Update src/Announce.txt + t = UpdateFile(os.path.join('testing', 'framework', 'TestSCons.py')) + if DEBUG: t.file = '/tmp/TestSCons.py' + t.replace_assign('copyright_years', repr(rel_info.copyright_years)) + t.replace_assign('default_version', repr(rel_info.version_string)) + # ??? t.replace_assign('SConsVersion', repr(version_string)) + t.replace_assign('python_version_unsupported', str(rel_info.unsupported_version)) + t.replace_assign('python_version_deprecated', str(rel_info.deprecated_version)) -t = UpdateFile(os.path.join('src', 'Announce.txt')) -if DEBUG: t.file = '/tmp/Announce.txt' -t.sub('\nRELEASE .*', '\nRELEASE ' + version_string + ' - ' + t.new_date) + # Update Script/Main.py + t = UpdateFile(os.path.join('src', 'engine', 'SCons', 'Script', 'Main.py')) + if DEBUG: t.file = '/tmp/Main.py' + t.replace_assign('unsupported_python_version', str(rel_info.unsupported_version)) + t.replace_assign('deprecated_python_version', str(rel_info.deprecated_version)) -# Update SConstruct + # Update doc/user/main.{in,xml} -t = UpdateFile('SConstruct') -if DEBUG: t.file = '/tmp/SConstruct' -t.replace_assign('month_year', repr(month_year)) -t.replace_assign('copyright_years', repr(copyright_years)) -t.replace_assign('default_version', repr(version_string)) + docyears = '2004 - %d' % rel_info.release_date[0] + if os.path.exists(os.path.join('doc', 'user', 'main.in')): + # this is no longer used as of Dec 2013 + t = UpdateFile(os.path.join('doc', 'user', 'main.in')) + if DEBUG: t.file = '/tmp/main.in' + ## TODO debug these + # t.sub('[^<]*', '' + docyears + '') + # t.sub('[^<]*', '' + docyears + '') -# Update README + t = UpdateFile(os.path.join('doc', 'user', 'main.xml')) + if DEBUG: t.file = '/tmp/main.xml' + t.sub('[^<]*', '' + docyears + '') + t.sub('[^<]*', '' + docyears + '') -t = UpdateFile('README.rst') -if DEBUG: t.file = '/tmp/README.rst' -t.sub('-' + t.match_pat + r'\.', '-' + version_string + '.', count = 0) -for suf in ['tar', 'win32', 'zip', 'rpm', 'exe', 'deb']: - t.sub(r'-(\d+\.\d+\.\d+)\.%s' % suf, - '-%s.%s' % (version_string, suf), - count = 0) + # Write out the last update -# Update testing/framework/TestSCons.py - -t = UpdateFile(os.path.join('testing','framework', 'TestSCons.py')) -if DEBUG: t.file = '/tmp/TestSCons.py' -t.replace_assign('copyright_years', repr(copyright_years)) -t.replace_assign('default_version', repr(version_string)) -#??? t.replace_assign('SConsVersion', repr(version_string)) -t.replace_assign('python_version_unsupported', str(unsupported_version)) -t.replace_assign('python_version_deprecated', str(deprecated_version)) - -# Update Script/Main.py + t = None -t = UpdateFile(os.path.join('src', 'engine', 'SCons', 'Script', 'Main.py')) -if DEBUG: t.file = '/tmp/Main.py' -t.replace_assign('unsupported_python_version', str(unsupported_version)) -t.replace_assign('deprecated_python_version', str(deprecated_version)) -# Update doc/user/main.{in,xml} +def parse_arguments(): + """ + Create ArgumentParser object and processs arguments + """ -docyears = '2004 - %d' % release_date[0] -if os.path.exists(os.path.join('doc', 'user', 'main.in')): - # this is no longer used as of Dec 2013 - t = UpdateFile(os.path.join('doc', 'user', 'main.in')) - if DEBUG: t.file = '/tmp/main.in' - ## TODO debug these - #t.sub('[^<]*', '' + docyears + '') - #t.sub('[^<]*', '' + docyears + '') + parser = argparse.ArgumentParser(prog='update-release-info.py') + parser.add_argument('mode', choices=['develop', 'release', 'post'], default='develop') + parser.add_argument('--verbose', dest='verbose', action='store_true', help='Enable verbose logging') + parser.add_argument('--timestamp', dest='timestamp', help='Override the default current timestamp', + default=time.localtime()[:6]) -t = UpdateFile(os.path.join('doc', 'user', 'main.xml')) -if DEBUG: t.file = '/tmp/main.xml' -t.sub('[^<]*', '' + docyears + '') -t.sub('[^<]*', '' + docyears + '') + args = parser.parse_args() + return args -# Write out the last update -t = None +if __name__ == "__main__": + options = parse_arguments() + rel_info = ReleaseInfo(options) + UpdateFile.rel_info = rel_info + main(options, rel_info) # Local Variables: # tab-width:4 -- cgit v0.12 From a3e66db3f093c947ae4a080e1890cbfd831a6c83 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 10 Feb 2020 11:40:45 -0800 Subject: fixed tests and some code to be testable --- bin/update-release-info.py | 25 ++-- test/update-release-info/update-release-info.py | 184 ++++++++++++------------ 2 files changed, 110 insertions(+), 99 deletions(-) diff --git a/bin/update-release-info.py b/bin/update-release-info.py index e4d404b..1c83506 100644 --- a/bin/update-release-info.py +++ b/bin/update-release-info.py @@ -72,6 +72,7 @@ class ReleaseInfo(object): self.config = {} self.args = args self.release_date = time.localtime()[:6] + self.unsupported_version = None self.deprecated_version = None @@ -86,7 +87,8 @@ class ReleaseInfo(object): self.read_config() self.process_config() - self.set_new_date() + if not self.args.timestamp: + self.set_new_date() def read_config(self): # Get configuration information @@ -109,7 +111,7 @@ class ReleaseInfo(object): self.deprecated_version = self.config['deprecated_python_version'] except KeyError: print('''ERROR: Config file must contain at least version_tuple, - \tunsupported_python_version, and deprecated_python_version.''') +\tunsupported_python_version, and deprecated_python_version.''') sys.exit(1) if 'release_date' in self.config: @@ -123,10 +125,14 @@ class ReleaseInfo(object): yyyy, mm, dd, h, m, s = self.release_date date_string = "".join(["%.2d" % d for d in self.release_date]) + if self.args.timestamp: + date_string = self.args.timestamp + if self.args.mode == 'develop' and self.version_tuple[3] != 'dev': self.version_tuple == self.version_tuple[:3] + ('dev', 0) + if len(self.version_tuple) > 3 and self.version_tuple[3] != 'final': - self.version_tuple = self.version_tuple[:4] + ((yyyy * 100 + mm) * 100 + dd,) + self.version_tuple = self.version_tuple[:4] + (date_string,) self.version_string = '.'.join(map(str, self.version_tuple[:4])) + date_string @@ -137,13 +143,16 @@ class ReleaseInfo(object): if self.version_type not in ['dev', 'beta', 'candidate', 'final']: print(("""ERROR: `%s' is not a valid release type in version tuple; - \tit must be one of dev, beta, candidate, or final""" % self.version_type)) +\tit must be one of dev, beta, candidate, or final""" % self.version_type)) sys.exit(1) try: self.month_year = self.config['month_year'] except KeyError: - self.month_year = time.strftime('%B %Y', self.release_date + (0, 0, 0)) + if self.args.timestamp: + self.month_year = "MONTH YEAR" + else: + self.month_year = time.strftime('%B %Y', self.release_date + (0, 0, 0)) try: self.copyright_years = self.config['copyright_years'] @@ -369,10 +378,10 @@ def parse_arguments(): """ parser = argparse.ArgumentParser(prog='update-release-info.py') - parser.add_argument('mode', choices=['develop', 'release', 'post'], default='develop') + parser.add_argument('mode', nargs='?', choices=['develop', 'release', 'post'], default='develop') parser.add_argument('--verbose', dest='verbose', action='store_true', help='Enable verbose logging') - parser.add_argument('--timestamp', dest='timestamp', help='Override the default current timestamp', - default=time.localtime()[:6]) + + parser.add_argument('--timestamp', dest='timestamp', help='Override the default current timestamp') args = parser.parse_args() return args diff --git a/test/update-release-info/update-release-info.py b/test/update-release-info/update-release-info.py index d0242a8..a6ce5b4 100644 --- a/test/update-release-info/update-release-info.py +++ b/test/update-release-info/update-release-info.py @@ -32,65 +32,63 @@ import os, sys, time import TestRuntest # Needed to ensure we're using the correct year -this_year=time.localtime()[0] - -TestSCons = 'testing/framework/TestSCons.py' .split('/') -README = 'README.rst' .split('/') -ReleaseConfig = 'ReleaseConfig' .split('/') -SConstruct = 'SConstruct' .split('/') -Announce = 'src/Announce.txt' .split('/') -CHANGES = 'src/CHANGES.txt' .split('/') -RELEASE = 'src/RELEASE.txt' .split('/') -Main = 'src/engine/SCons/Script/Main.py' .split('/') -main_in = 'doc/user/main.in' .split('/') -main_xml = 'doc/user/main.xml' .split('/') +this_year = time.localtime()[0] + +TestSCons = 'testing/framework/TestSCons.py'.split('/') +README = 'README.rst'.split('/') +ReleaseConfig = 'ReleaseConfig'.split('/') +SConstruct = 'SConstruct'.split('/') +Announce = 'src/Announce.txt'.split('/') +CHANGES = 'src/CHANGES.txt'.split('/') +RELEASE = 'src/RELEASE.txt'.split('/') +Main = 'src/engine/SCons/Script/Main.py'.split('/') +main_in = 'doc/user/main.in'.split('/') +main_xml = 'doc/user/main.xml'.split('/') test = TestRuntest.TestRuntest( - program = os.path.join('bin', 'update-release-info.py'), - things_to_copy = ['bin'] - ) + program=os.path.join('bin', 'update-release-info.py'), + things_to_copy=['bin'] +) +# test.verbose_set(1) if not os.path.exists(test.program): test.skip_test("update-release-info.py is not distributed in this package\n") -test.run(arguments = 'bad', status = 1) +expected_stderr = """usage: update-release-info.py [-h] [--verbose] [--timestamp TIMESTAMP] + [{develop,release,post}] +update-release-info.py: error: argument mode: invalid choice: 'bad' (choose from 'develop', 'release', 'post') +""" +test.run(arguments='bad', stderr=expected_stderr, status=2) # Strings to go in ReleaseConfig combo_strings = [ -# Index 0: version tuple with bad release level -"""version_tuple = (2, 0, 0, 'bad', 0) -""", -# Index 1: Python version tuple -"""unsupported_python_version = (2, 6) -""", -# Index 2: Python version tuple -"""deprecated_python_version = (2, 7) -""", -# Index 3: alpha version tuple -"""version_tuple = (2, 0, 0, 'alpha', 0) -""", -# Index 4: final version tuple -"""version_tuple = (2, 0, 0, 'final', 0) -""", -# Index 5: bad release date -"""release_date = (%d, 12) -"""%this_year, -# Index 6: release date (hhhh, mm, dd) -"""release_date = (%d, 12, 21) -"""%this_year, -# Index 7: release date (hhhh, mm, dd, hh, mm, ss) -"""release_date = (%d, 12, 21, 12, 21, 12) -"""%this_year, + # Index 0: version tuple with bad release level + """version_tuple = (2, 0, 0, 'bad', 0)\n""", + # Index 1: Python version tuple + """unsupported_python_version = (2, 6)\n""", + # Index 2: Python version tuple + """deprecated_python_version = (2, 7)\n""", + # Index 3: alpha version tuple + """version_tuple = (2, 0, 0, 'dev', 0)\n""", + # Index 4: final version tuple + """version_tuple = (2, 0, 0, 'final', 0)\n""", + # Index 5: bad release date + """release_date = (%d, 12)\n""" % this_year, + # Index 6: release date (hhhh, mm, dd) + """release_date = (%d, 12, 21)\n""" % this_year, + # Index 7: release date (hhhh, mm, dd, hh, mm, ss) + """release_date = (%d, 12, 21, 12, 21, 12)\n""" % this_year, ] combo_error = \ -"""ERROR: Config file must contain at least version_tuple, -\tunsupported_python_version, and deprecated_python_version. -""" + """ERROR: Config file must contain at least version_tuple, +\tunsupported_python_version, and deprecated_python_version.\n""" + def combo_fail(*args, **kw): kw.setdefault('status', 1) combo_run(*args, **kw) + def combo_run(*args, **kw): t = '\n' for a in args: @@ -101,6 +99,7 @@ def combo_run(*args, **kw): kw.setdefault('stdout', combo_error) test.run(**kw) + combo_fail() combo_fail(0) combo_fail(1) @@ -108,17 +107,17 @@ combo_fail(2) combo_fail(0, 1) combo_fail(0, 2) combo_fail(1, 2) -combo_fail(0, 1, 2, stdout = +combo_fail(0, 1, 2, stdout= """ERROR: `bad' is not a valid release type in version tuple; -\tit must be one of alpha, beta, candidate, or final -""") +\tit must be one of dev, beta, candidate, or final\n""") # We won't need this entry again, so put in a default combo_strings[0] = combo_strings[1] + combo_strings[2] + combo_strings[3] -combo_fail(0, 5, stdout = +combo_fail(0, 5, stdout= """ERROR: Invalid release date (%d, 12) -"""%this_year ) +""" % this_year) + def pave(path): path = path[:-1] @@ -127,10 +126,12 @@ def pave(path): pave(path) test.subdir(path) + def pave_write(file, contents): pave(file) test.write(file, contents) + pave_write(CHANGES, """ RELEASE It doesn't matter what goes here... """) @@ -180,80 +181,81 @@ pave_write(main_xml, """ TODO """) + def updating_run(*args): stdout = '' for file in args: stdout += 'Updating %s...\n' % os.path.join(*file) - combo_run(0, 7, stdout = stdout) + combo_run(0, 7, stdout=stdout, arguments=['--timestamp=yyyymmdd']) + updating_run(CHANGES, RELEASE, Announce, SConstruct, README, TestSCons, Main) test.must_match(CHANGES, """ -RELEASE 2.0.0.alpha.yyyymmdd - NEW DATE WILL BE INSERTED HERE -""", mode = 'r') +RELEASE 2.0.0.devyyyymmdd - NEW DATE WILL BE INSERTED HERE +""", mode='r') test.must_match(RELEASE, """ -This file has a 2.0.0.alpha.yyyymmdd version string in it -""", mode = 'r') +This file has a 2.0.0.devyyyymmdd version string in it +""", mode='r') test.must_match(Announce, """ -RELEASE 2.0.0.alpha.yyyymmdd - NEW DATE WILL BE INSERTED HERE -""", mode = 'r') - +RELEASE 2.0.0.devyyyymmdd - NEW DATE WILL BE INSERTED HERE +""", mode='r') -years = '2001 - %d'%(this_year + 1) +years = '2001 - %d' % (this_year + 1) test.must_match(SConstruct, """ month_year = 'MONTH YEAR' copyright_years = %s -default_version = '2.0.0.alpha.yyyymmdd' -""" % repr(years), mode = 'r') +default_version = '2.0.0.devyyyymmdd' +""" % repr(years), mode='r') test.must_match(README, """ These files are a part of 33.22.11: - scons-2.0.0.alpha.yyyymmdd.tar.gz - scons-2.0.0.alpha.yyyymmdd.win32.exe - scons-2.0.0.alpha.yyyymmdd.zip - scons-2.0.0.alpha.yyyymmdd.rpm - scons-2.0.0.alpha.yyyymmdd.deb + scons-2.0.0.devyyyymmdd.tar.gz + scons-2.0.0.devyyyymmdd.win32.exe + scons-2.0.0.devyyyymmdd.zip + scons-2.0.0.devyyyymmdd.rpm + scons-2.0.0.devyyyymmdd.deb - scons-2.0.0.alpha.yyyymmdd.suffix -""", mode = 'r') + scons-2.0.0.devyyyymmdd.suffix +""", mode='r') # should get Python floors from TestSCons module. test.must_match(TestSCons, """ copyright_years = '%s' -default_version = '2.0.0.alpha.yyyymmdd' +default_version = '2.0.0.devyyyymmdd' python_version_unsupported = (2, 6) python_version_deprecated = (2, 7) -"""%years, mode = 'r') +""" % years, mode='r') # should get Python floors from TestSCons module. test.must_match(Main, """ unsupported_python_version = (2, 6) deprecated_python_version = (2, 7) -""", mode = 'r') - -#TODO: Release option -#TODO: ============== -#TODO: -#TODO: Dates in beta/candidate flow -#TODO: -#TODO: Dates in final flow -#TODO: -#TODO: Post option -#TODO: =========== -#TODO: -#TODO: Dates in post flow -#TODO: -#TODO: Update minor or micro version -#TODO: -#TODO: ReleaseConfig - new version tuple -#TODO: -#TODO: CHANGES - new section -#TODO: -#TODO: RELEASE - new template -#TODO: -#TODO: Announce - new section +""", mode='r') + +# TODO: Release option +# TODO: ============== +# TODO: +# TODO: Dates in beta/candidate flow +# TODO: +# TODO: Dates in final flow +# TODO: +# TODO: Post option +# TODO: =========== +# TODO: +# TODO: Dates in post flow +# TODO: +# TODO: Update minor or micro version +# TODO: +# TODO: ReleaseConfig - new version tuple +# TODO: +# TODO: CHANGES - new section +# TODO: +# TODO: RELEASE - new template +# TODO: +# TODO: Announce - new section test.pass_test() -- cgit v0.12 From 0b77413d3c1e19477446d58f41a4093316753ef9 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 10 Feb 2020 18:14:01 -0800 Subject: Fixed post release mode --- bin/update-release-info.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/bin/update-release-info.py b/bin/update-release-info.py index 1c83506..9c8efdd 100644 --- a/bin/update-release-info.py +++ b/bin/update-release-info.py @@ -194,7 +194,7 @@ class UpdateFile(object): # Determine the pattern to match a version _rel_types = r'(dev|beta|candidate|final)' - match_pat = r'\d+\.\d+\.\d+\.' + _rel_types + r'\.(\d+|yyyymmdd)' + match_pat = r'\d+\.\d+\.\d+\.' + _rel_types + r'\.?(\d+|yyyymmdd)' match_rel = re.compile(match_pat) def __init__(self, file, orig=None): @@ -254,7 +254,9 @@ def main(args, rel_info): minor = rel_info.version_tuple[1] + 1 micro = 0 new_tuple = (rel_info.version_tuple[0], minor, micro, 'dev', 0) - new_version = '.'.join(map(str, new_tuple[:4])) + '.yyyymmdd' + new_version = '.'.join(map(str, new_tuple[:4])) + 'yyyymmdd' + + rel_info.version_string = new_version # Update ReleaseConfig @@ -276,7 +278,7 @@ def main(args, rel_info): t = UpdateFile(os.path.join('src', 'RELEASE.txt'), os.path.join('template', 'RELEASE.txt')) if DEBUG: t.file = '/tmp/RELEASE.txt' - t.replace_version(new_version) + t.replace_version() # Update src/Announce.txt -- cgit v0.12 From 538c068dda7a762e6c4cf4465ddb10f8844387b8 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 10 Feb 2020 18:23:33 -0800 Subject: Fix sider found spelling error --- bin/update-release-info.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/update-release-info.py b/bin/update-release-info.py index 9c8efdd..3fcdf72 100644 --- a/bin/update-release-info.py +++ b/bin/update-release-info.py @@ -376,7 +376,7 @@ def main(args, rel_info): def parse_arguments(): """ - Create ArgumentParser object and processs arguments + Create ArgumentParser object and process arguments """ parser = argparse.ArgumentParser(prog='update-release-info.py') -- cgit v0.12 From c187c71f9a1dc867bf68e6837232975499146375 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 11 Feb 2020 10:10:40 -0800 Subject: Move testfile.py to testfile/ and have it use file_fixture() for SConstructs --- src/engine/SCons/Tool/textfile.py | 1 + test/textfile.py | 174 ------------------------------------- test/textfile/fixture/SConstruct | 20 +++++ test/textfile/fixture/SConstruct.2 | 24 +++++ test/textfile/textfile.py | 133 ++++++++++++++++++++++++++++ 5 files changed, 178 insertions(+), 174 deletions(-) delete mode 100644 test/textfile.py create mode 100644 test/textfile/fixture/SConstruct create mode 100644 test/textfile/fixture/SConstruct.2 create mode 100644 test/textfile/textfile.py diff --git a/src/engine/SCons/Tool/textfile.py b/src/engine/SCons/Tool/textfile.py index 48a2904..7ec9c78 100644 --- a/src/engine/SCons/Tool/textfile.py +++ b/src/engine/SCons/Tool/textfile.py @@ -71,6 +71,7 @@ def _do_subst(node, subs): contents = node.get_text_contents() if subs: for (k, val) in subs: + # contents = contents.replace(k, val) contents = re.sub(k, val, contents) if 'b' in TEXTFILE_FILE_WRITE_MODE: diff --git a/test/textfile.py b/test/textfile.py deleted file mode 100644 index 1d5b3c7..0000000 --- a/test/textfile.py +++ /dev/null @@ -1,174 +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 - -import os - -test = TestSCons.TestSCons() - -foo1 = test.workpath('foo1.txt') -#foo2 = test.workpath('foo2.txt') -#foo1a = test.workpath('foo1a.txt') -#foo2a = test.workpath('foo2a.txt') - -match_mode = 'r' - -test.write('SConstruct', """ -env = Environment(tools=['textfile']) -data0 = ['Goethe', 'Schiller'] -data = ['lalala', 42, data0, 'tanteratei'] - -env.Textfile('foo1', data) -env.Textfile('foo2', data, LINESEPARATOR='|*') -env.Textfile('foo1a.txt', data + ['']) -env.Textfile('foo2a.txt', data + [''], LINESEPARATOR='|*') - -# recreate the list with the data wrapped in Value() -data0 = list(map(Value, data0)) -data = list(map(Value, data)) -data[2] = data0 - -env.Substfile('bar1', data) -env.Substfile('bar2', data, LINESEPARATOR='|*') -data.append(Value('')) -env.Substfile('bar1a.txt', data) -env.Substfile('bar2a.txt', data, LINESEPARATOR='|*') -""", mode='w') - -test.run(arguments='.') - -linesep = '\n' - -textparts = ['lalala', '42', - 'Goethe', 'Schiller', - 'tanteratei'] -foo1Text = linesep.join(textparts) -foo2Text = '|*'.join(textparts) -foo1aText = foo1Text + linesep -foo2aText = foo2Text + '|*' - -test.up_to_date(arguments='.') - -files = list(map(test.workpath, ( - 'foo1.txt', 'foo2.txt', 'foo1a.txt', 'foo2a.txt', - 'bar1', 'bar2', 'bar1a.txt', 'bar2a.txt', -))) - - -def check_times(): - """ - make sure the files didn't get rewritten, because nothing changed: - """ - before = list(map(os.path.getmtime, files)) - # introduce a small delay, to make the test valid - test.sleep() - # should still be up-to-date - test.up_to_date(arguments='.') - after = list(map(os.path.getmtime, files)) - test.fail_test(before != after) - - -# make sure that the file content is as expected -test.must_match('foo1.txt', foo1Text, mode=match_mode) -test.must_match('bar1', foo1Text, mode=match_mode) -test.must_match('foo2.txt', foo2Text, mode=match_mode) -test.must_match('bar2', foo2Text, mode=match_mode) -test.must_match('foo1a.txt', foo1aText, mode=match_mode) -test.must_match('bar1a.txt', foo1aText, mode=match_mode) -test.must_match('foo2a.txt', foo2aText, mode=match_mode) -test.must_match('bar2a.txt', foo2aText, mode=match_mode) -check_times() - -# write the contents and make sure the files -# didn't get rewritten, because nothing changed: -test.write('foo1.txt', foo1Text) -test.write('bar1', foo1Text) -test.write('foo2.txt', foo2Text) -test.write('bar2', foo2Text) -test.write('foo1a.txt', foo1aText) -test.write('bar1a.txt', foo1aText) -test.write('foo2a.txt', foo2aText) -test.write('bar2a.txt', foo2aText) -check_times() - -# now that textfile is part of default tool list, run one testcase -# without adding it explicitly as a tool to make sure. -test.write('SConstruct', """ -textlist = ['This line has no substitutions', - 'This line has @subst@ substitutions', - 'This line has %subst% substitutions', - ] - -sub1 = { '@subst@' : 'most' } -sub2 = { '%subst%' : 'many' } -sub3 = { '@subst@' : 'most' , '%subst%' : 'many' } - -env = Environment() - -t = env.Textfile('text', textlist) -# no substitutions -s = env.Substfile('sub1', t) -# one substitution -s = env.Substfile('sub2', s, SUBST_DICT = sub1) -# the other substution -s = env.Substfile('sub3', s, SUBST_DICT = sub2) -# the reverse direction -s = env.Substfile('sub4', t, SUBST_DICT = sub2) -s = env.Substfile('sub5', s, SUBST_DICT = sub1) -# both -s = env.Substfile('sub6', t, SUBST_DICT = sub3) -""", mode='w') - -test.run(arguments='.') - -line1 = 'This line has no substitutions' -line2a = 'This line has @subst@ substitutions' -line2b = 'This line has most substitutions' -line3a = 'This line has %subst% substitutions' -line3b = 'This line has many substitutions' - - -def matchem(match_file, lines): - """ - Join all the lines with correct line separator, - then compare - """ - lines = linesep.join(lines) - test.must_match(match_file, lines, mode=match_mode, message="Expected:\n%s\n"%lines) - - -matchem('text.txt', [line1, line2a, line3a]) -matchem('sub1', [line1, line2a, line3a]) -matchem('sub2', [line1, line2b, line3a]) -matchem('sub3', [line1, line2b, line3b]) -matchem('sub4', [line1, line2a, line3b]) -matchem('sub5', [line1, line2b, line3b]) -matchem('sub6', [line1, line2b, line3b]) - -test.up_to_date(arguments='.') - -test.pass_test() diff --git a/test/textfile/fixture/SConstruct b/test/textfile/fixture/SConstruct new file mode 100644 index 0000000..df64106 --- /dev/null +++ b/test/textfile/fixture/SConstruct @@ -0,0 +1,20 @@ + +env = Environment(tools=['textfile']) +data0 = ['Goethe', 'Schiller'] +data = ['lalala', 42, data0, 'tanteratei'] + +env.Textfile('foo1', data) +env.Textfile('foo2', data, LINESEPARATOR='|*') +env.Textfile('foo1a.txt', data + ['']) +env.Textfile('foo2a.txt', data + [''], LINESEPARATOR='|*') + +# recreate the list with the data wrapped in Value() +data0 = list(map(Value, data0)) +data = list(map(Value, data)) +data[2] = data0 + +env.Substfile('bar1', data) +env.Substfile('bar2', data, LINESEPARATOR='|*') +data.append(Value('')) +env.Substfile('bar1a.txt', data) +env.Substfile('bar2a.txt', data, LINESEPARATOR='|*') diff --git a/test/textfile/fixture/SConstruct.2 b/test/textfile/fixture/SConstruct.2 new file mode 100644 index 0000000..32fd767 --- /dev/null +++ b/test/textfile/fixture/SConstruct.2 @@ -0,0 +1,24 @@ + +textlist = ['This line has no substitutions', + 'This line has @subst@ substitutions', + 'This line has %subst% substitutions', + ] + +sub1 = { '@subst@' : 'most' } +sub2 = { '%subst%' : 'many' } +sub3 = { '@subst@' : 'most' , '%subst%' : 'many' } + +env = Environment() + +t = env.Textfile('text', textlist) +# no substitutions +s = env.Substfile('sub1', t) +# one substitution +s = env.Substfile('sub2', s, SUBST_DICT = sub1) +# the other substution +s = env.Substfile('sub3', s, SUBST_DICT = sub2) +# the reverse direction +s = env.Substfile('sub4', t, SUBST_DICT = sub2) +s = env.Substfile('sub5', s, SUBST_DICT = sub1) +# both +s = env.Substfile('sub6', t, SUBST_DICT = sub3) diff --git a/test/textfile/textfile.py b/test/textfile/textfile.py new file mode 100644 index 0000000..7b542e0 --- /dev/null +++ b/test/textfile/textfile.py @@ -0,0 +1,133 @@ +#!/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 + +import os + +test = TestSCons.TestSCons() + +test.verbose_set(1) + +foo1 = test.workpath('foo1.txt') +#foo2 = test.workpath('foo2.txt') +#foo1a = test.workpath('foo1a.txt') +#foo2a = test.workpath('foo2a.txt') + +match_mode = 'r' + +test.file_fixture('fixture/SConstruct','SConstruct') + +test.run(arguments='.') + +linesep = '\n' + +textparts = ['lalala', '42', + 'Goethe', 'Schiller', + 'tanteratei'] +foo1Text = linesep.join(textparts) +foo2Text = '|*'.join(textparts) +foo1aText = foo1Text + linesep +foo2aText = foo2Text + '|*' + +test.up_to_date(arguments='.') + +files = list(map(test.workpath, ( + 'foo1.txt', 'foo2.txt', 'foo1a.txt', 'foo2a.txt', + 'bar1', 'bar2', 'bar1a.txt', 'bar2a.txt', +))) + + +def check_times(): + """ + make sure the files didn't get rewritten, because nothing changed: + """ + before = list(map(os.path.getmtime, files)) + # introduce a small delay, to make the test valid + test.sleep() + # should still be up-to-date + test.up_to_date(arguments='.') + after = list(map(os.path.getmtime, files)) + test.fail_test(before != after) + + +# make sure that the file content is as expected +test.must_match('foo1.txt', foo1Text, mode=match_mode) +test.must_match('bar1', foo1Text, mode=match_mode) +test.must_match('foo2.txt', foo2Text, mode=match_mode) +test.must_match('bar2', foo2Text, mode=match_mode) +test.must_match('foo1a.txt', foo1aText, mode=match_mode) +test.must_match('bar1a.txt', foo1aText, mode=match_mode) +test.must_match('foo2a.txt', foo2aText, mode=match_mode) +test.must_match('bar2a.txt', foo2aText, mode=match_mode) +check_times() + +# write the contents and make sure the files +# didn't get rewritten, because nothing changed: +test.write('foo1.txt', foo1Text) +test.write('bar1', foo1Text) +test.write('foo2.txt', foo2Text) +test.write('bar2', foo2Text) +test.write('foo1a.txt', foo1aText) +test.write('bar1a.txt', foo1aText) +test.write('foo2a.txt', foo2aText) +test.write('bar2a.txt', foo2aText) +check_times() + +# now that textfile is part of default tool list, run one testcase +# without adding it explicitly as a tool to make sure. +test.file_fixture('fixture/SConstruct.2','SConstruct.2') + + +test.run(options='-f SConstruct.2', arguments='.') + +line1 = 'This line has no substitutions' +line2a = 'This line has @subst@ substitutions' +line2b = 'This line has most substitutions' +line3a = 'This line has %subst% substitutions' +line3b = 'This line has many substitutions' + + +def matchem(match_file, lines): + """ + Join all the lines with correct line separator, + then compare + """ + lines = linesep.join(lines) + test.must_match(match_file, lines, mode=match_mode, message="Expected:\n%s\n"%lines) + + +matchem('text.txt', [line1, line2a, line3a]) +matchem('sub1', [line1, line2a, line3a]) +matchem('sub2', [line1, line2b, line3a]) +matchem('sub3', [line1, line2b, line3b]) +matchem('sub4', [line1, line2a, line3b]) +matchem('sub5', [line1, line2b, line3b]) +matchem('sub6', [line1, line2b, line3b]) + +test.up_to_date(options='-f SConstruct.2', arguments='.') + +test.pass_test() -- cgit v0.12 From 8662e7c190559fa4249fdf4aee38dbe08dd7847a Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Thu, 6 Feb 2020 09:37:19 -0700 Subject: Add a warning if msvc config cache may be outdated. If we didn't find cl.exe in the final check in msvc_setup_env(), issue a different warning if config caching is enabled. If it is, there's a decent chance we've found cl.exe in the past, meaning the cache is probably out of date - entries are indexed by path to the bat file+arg, whereas an msvc update may bump a version number in the path and the old path won't be valid: a cached path entry could look like this: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.24.28314\\bin\\HostX64\\x64", and the .28314 could be changed in an update. Signed-off-by: Mats Wichmann --- src/CHANGES.txt | 1 + src/engine/SCons/Tool/MSCommon/vc.py | 23 ++++++++++++----------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 407a83b..b320aaf 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -62,6 +62,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Accommodate VS 2017 Express - it's got a more liberal license then VS Community, so some people prefer it (from 2019, no more Express) - vswhere call should also now work even if programs aren't on the C: drive. + - Add a specific warning msg if msvc config cache may be out of date. RELEASE 3.1.2 - Mon, 17 Dec 2019 02:06:27 +0000 diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py index a18a1a7..ed713d0 100644 --- a/src/engine/SCons/Tool/MSCommon/vc.py +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -22,6 +22,9 @@ # # TODO: +# * gather all the information from a single vswhere call instead +# of calling repeatedly (use json format?) +# * support passing/setting location for vswhere in env. # * supported arch for versions: for old versions of batch file without # argument, giving bogus argument cannot be detected, so we have to hardcode # this here @@ -41,7 +44,6 @@ import subprocess import os import platform import sys -from contextlib import suppress from string import digits as string_digits from subprocess import PIPE #TODO: Python 2 cleanup @@ -52,12 +54,8 @@ import SCons.Warnings from SCons.Tool import find_program_path from . import common - -debug = common.debug - -from . import sdk - -get_installed_sdks = sdk.get_installed_sdks +from .common import CONFIG_CACHE, debug +from .sdk import get_installed_sdks class VisualCException(Exception): @@ -921,11 +919,14 @@ def msvc_setup_env(env): debug("msvc_setup_env() env['ENV']['%s'] = %s" % (k, env['ENV'][k])) # final check to issue a warning if the compiler is not present - msvc_cl = find_program_path(env, 'cl') - if not msvc_cl: + if not find_program_path(env, 'cl'): debug("msvc_setup_env() did not find 'cl'") - SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, - "Could not find MSVC compiler 'cl', it may need to be installed separately with Visual Studio") + if CONFIG_CACHE: + propose = "SCONS_CACHE_MSVC_CONFIG caching enabled, remove cache file {} if out of date.".format(CONFIG_CACHE) + else: + propose = "It may need to be installed separately with Visual Studio." + warn_msg = "Could not find MSVC compiler 'cl'. {}".format(propose) + SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, warn_msg) def msvc_exists(env=None, version=None): vcs = cached_get_installed_vcs(env) -- cgit v0.12 From f1ea7d0237fad19ba58da847f04fbf3a9b6061a9 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Tue, 11 Feb 2020 11:41:33 -0700 Subject: [PR #3546] update CHANGES.txt per review [ci skip] Be more clear about the msvc config-cache issue being fixed. Signed-off-by: Mats Wichmann --- src/CHANGES.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index b320aaf..c4523a7 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -62,7 +62,9 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Accommodate VS 2017 Express - it's got a more liberal license then VS Community, so some people prefer it (from 2019, no more Express) - vswhere call should also now work even if programs aren't on the C: drive. - - Add a specific warning msg if msvc config cache may be out of date. + - Add an alternate warning message cl.exe is not found and msvc config + cache is in use (SCONS_CACHE_MSVC_CONFIG was given) - config cache + may be out of date. RELEASE 3.1.2 - Mon, 17 Dec 2019 02:06:27 +0000 -- cgit v0.12 From 89c21459719a5069b0e804cfc7241f02455f4c90 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 11 Feb 2020 11:05:28 -0800 Subject: Add tests for issue 3550 --- test/textfile/fixture/SConstruct | 4 ++- test/textfile/fixture/SConstruct.2 | 21 ++++++------- test/textfile/fixture/SConstruct.issue-3550 | 12 ++++++++ test/textfile/fixture/foo-3550.in | 1 + test/textfile/issue-3550.py | 46 +++++++++++++++++++++++++++++ test/textfile/textfile.py | 33 ++++++++++----------- 6 files changed, 88 insertions(+), 29 deletions(-) create mode 100644 test/textfile/fixture/SConstruct.issue-3550 create mode 100644 test/textfile/fixture/foo-3550.in create mode 100644 test/textfile/issue-3550.py diff --git a/test/textfile/fixture/SConstruct b/test/textfile/fixture/SConstruct index df64106..8cfe909 100644 --- a/test/textfile/fixture/SConstruct +++ b/test/textfile/fixture/SConstruct @@ -1,7 +1,9 @@ +DefaultEnvironment(tools=[]) + env = Environment(tools=['textfile']) data0 = ['Goethe', 'Schiller'] -data = ['lalala', 42, data0, 'tanteratei'] +data = ['lalala', 42, data0, 'tanteratei'] env.Textfile('foo1', data) env.Textfile('foo2', data, LINESEPARATOR='|*') diff --git a/test/textfile/fixture/SConstruct.2 b/test/textfile/fixture/SConstruct.2 index 32fd767..b7e63a1 100644 --- a/test/textfile/fixture/SConstruct.2 +++ b/test/textfile/fixture/SConstruct.2 @@ -1,24 +1,25 @@ +DefaultEnvironment(tools=[]) textlist = ['This line has no substitutions', 'This line has @subst@ substitutions', 'This line has %subst% substitutions', - ] + ] -sub1 = { '@subst@' : 'most' } -sub2 = { '%subst%' : 'many' } -sub3 = { '@subst@' : 'most' , '%subst%' : 'many' } +sub1 = {'@subst@': 'most'} +sub2 = {'%subst%': 'many'} +sub3 = {'@subst@': 'most', '%subst%': 'many'} -env = Environment() +env = Environment(tools=['textfile']) t = env.Textfile('text', textlist) # no substitutions s = env.Substfile('sub1', t) # one substitution -s = env.Substfile('sub2', s, SUBST_DICT = sub1) +s = env.Substfile('sub2', s, SUBST_DICT=sub1) # the other substution -s = env.Substfile('sub3', s, SUBST_DICT = sub2) +s = env.Substfile('sub3', s, SUBST_DICT=sub2) # the reverse direction -s = env.Substfile('sub4', t, SUBST_DICT = sub2) -s = env.Substfile('sub5', s, SUBST_DICT = sub1) +s = env.Substfile('sub4', t, SUBST_DICT=sub2) +s = env.Substfile('sub5', s, SUBST_DICT=sub1) # both -s = env.Substfile('sub6', t, SUBST_DICT = sub3) +s = env.Substfile('sub6', t, SUBST_DICT=sub3) diff --git a/test/textfile/fixture/SConstruct.issue-3550 b/test/textfile/fixture/SConstruct.issue-3550 new file mode 100644 index 0000000..8502717 --- /dev/null +++ b/test/textfile/fixture/SConstruct.issue-3550 @@ -0,0 +1,12 @@ +DefaultEnvironment(tools=[]) +env = Environment(tools=['textfile']) + +env['FOO_PATH'] = r'Z:\mongo\build\install\bin' + +foo = env.Substfile( + target="foo", + source="foo-3550.in", + SUBST_DICT={ + "@foo_path@": "$FOO_PATH", + } +) diff --git a/test/textfile/fixture/foo-3550.in b/test/textfile/fixture/foo-3550.in new file mode 100644 index 0000000..c806a04 --- /dev/null +++ b/test/textfile/fixture/foo-3550.in @@ -0,0 +1 @@ +foo_path: @foo_path@ diff --git a/test/textfile/issue-3550.py b/test/textfile/issue-3550.py new file mode 100644 index 0000000..3c9425a --- /dev/null +++ b/test/textfile/issue-3550.py @@ -0,0 +1,46 @@ +#!/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 + +import os + +test = TestSCons.TestSCons() + +test.verbose_set(1) + +match_mode = 'r' + +test.file_fixture('fixture/SConstruct.issue-3550', 'SConstruct') +test.file_fixture('fixture/foo-3550.in', 'foo-3550.in') + +test.run(arguments='.') + +test.must_match('foo', + r'''foo_path: Z:\mongo\build\install\bin +''', mode=match_mode) + +test.pass_test() diff --git a/test/textfile/textfile.py b/test/textfile/textfile.py index 7b542e0..0f2e18e 100644 --- a/test/textfile/textfile.py +++ b/test/textfile/textfile.py @@ -30,16 +30,14 @@ import os test = TestSCons.TestSCons() -test.verbose_set(1) - foo1 = test.workpath('foo1.txt') -#foo2 = test.workpath('foo2.txt') -#foo1a = test.workpath('foo1a.txt') -#foo2a = test.workpath('foo2a.txt') +# foo2 = test.workpath('foo2.txt') +# foo1a = test.workpath('foo1a.txt') +# foo2a = test.workpath('foo2a.txt') match_mode = 'r' -test.file_fixture('fixture/SConstruct','SConstruct') +test.file_fixture('fixture/SConstruct', 'SConstruct') test.run(arguments='.') @@ -57,7 +55,7 @@ test.up_to_date(arguments='.') files = list(map(test.workpath, ( 'foo1.txt', 'foo2.txt', 'foo1a.txt', 'foo2a.txt', - 'bar1', 'bar2', 'bar1a.txt', 'bar2a.txt', + 'bar1', 'bar2', 'bar1a.txt', 'bar2a.txt', ))) @@ -75,10 +73,10 @@ def check_times(): # make sure that the file content is as expected -test.must_match('foo1.txt', foo1Text, mode=match_mode) -test.must_match('bar1', foo1Text, mode=match_mode) -test.must_match('foo2.txt', foo2Text, mode=match_mode) -test.must_match('bar2', foo2Text, mode=match_mode) +test.must_match('foo1.txt', foo1Text, mode=match_mode) +test.must_match('bar1', foo1Text, mode=match_mode) +test.must_match('foo2.txt', foo2Text, mode=match_mode) +test.must_match('bar2', foo2Text, mode=match_mode) test.must_match('foo1a.txt', foo1aText, mode=match_mode) test.must_match('bar1a.txt', foo1aText, mode=match_mode) test.must_match('foo2a.txt', foo2aText, mode=match_mode) @@ -87,10 +85,10 @@ check_times() # write the contents and make sure the files # didn't get rewritten, because nothing changed: -test.write('foo1.txt', foo1Text) -test.write('bar1', foo1Text) -test.write('foo2.txt', foo2Text) -test.write('bar2', foo2Text) +test.write('foo1.txt', foo1Text) +test.write('bar1', foo1Text) +test.write('foo2.txt', foo2Text) +test.write('bar2', foo2Text) test.write('foo1a.txt', foo1aText) test.write('bar1a.txt', foo1aText) test.write('foo2a.txt', foo2aText) @@ -99,8 +97,7 @@ check_times() # now that textfile is part of default tool list, run one testcase # without adding it explicitly as a tool to make sure. -test.file_fixture('fixture/SConstruct.2','SConstruct.2') - +test.file_fixture('fixture/SConstruct.2', 'SConstruct.2') test.run(options='-f SConstruct.2', arguments='.') @@ -117,7 +114,7 @@ def matchem(match_file, lines): then compare """ lines = linesep.join(lines) - test.must_match(match_file, lines, mode=match_mode, message="Expected:\n%s\n"%lines) + test.must_match(match_file, lines, mode=match_mode, message="Expected:\n%s\n" % lines) matchem('text.txt', [line1, line2a, line3a]) -- cgit v0.12 From c40509ba4e1b466dd03f8984e8169448c6cfa20a Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 11 Feb 2020 11:06:33 -0800 Subject: Fix issue #3550 - Substfile() can fail/crash when using windows paths as \'s are interpreted instead of simply used to replace text. Switch to using str.replace() --- src/engine/SCons/Tool/textfile.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/engine/SCons/Tool/textfile.py b/src/engine/SCons/Tool/textfile.py index 7ec9c78..c233658 100644 --- a/src/engine/SCons/Tool/textfile.py +++ b/src/engine/SCons/Tool/textfile.py @@ -71,8 +71,7 @@ def _do_subst(node, subs): contents = node.get_text_contents() if subs: for (k, val) in subs: - # contents = contents.replace(k, val) - contents = re.sub(k, val, contents) + contents = contents.replace(k, val) if 'b' in TEXTFILE_FILE_WRITE_MODE: try: -- cgit v0.12 From 7d80f0ca5f9e752118141bd9c7de9350cd6b8597 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 11 Feb 2020 11:08:56 -0800 Subject: [ci skip] Update CHANGES.txt --- src/CHANGES.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 407a83b..b1cc831 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -18,6 +18,9 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER is a reasonable default and also aligns with changes in Appveyor's VS2019 image. - Drop support for Python 2.7. SCons will be Python 3.5+ going forward. - Change SCons.Node.ValueWithMemo to consider any name passed when memoizing Value() nodes + - Fix Github Issue #3550 - When using Substfile() with a value like Z:\mongo\build\install\bin + the implementation using re.sub() would end up interpreting the string and finding regex escape + characters where it should have been simply replacing existing text. Switched to use string.replace(). From Jeremy Elson: - Updated design doc to use the correct syntax for Depends() -- cgit v0.12 From 74ac8dce11d14c2e33932b11ff88404f45ad3b08 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 11 Feb 2020 11:15:36 -0800 Subject: Resolve sider complaint --- test/textfile/issue-3550.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/textfile/issue-3550.py b/test/textfile/issue-3550.py index 3c9425a..60430ed 100644 --- a/test/textfile/issue-3550.py +++ b/test/textfile/issue-3550.py @@ -26,8 +26,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import TestSCons -import os - test = TestSCons.TestSCons() test.verbose_set(1) -- cgit v0.12 From d6e7dc914ecaeca971e66af8041b40dd7f255d7b Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 11 Feb 2020 16:46:30 -0800 Subject: [ci skip] Added mwichman as a developer so github sponsors can contribute to him --- .github/FUNDING.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 9daae32..ba16f86 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,5 +1,5 @@ # These are supported funding model platforms -github: bdbaddog +github: bdbaddog mwichmann patreon: bdbaddog -- cgit v0.12 From a25e470e46afe7867e77a52a23c54997bb01f7c6 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 11 Feb 2020 16:49:16 -0800 Subject: [ci skip] Added mwichman as a developer so github sponsors can contribute to him --- .github/FUNDING.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index ba16f86..486f170 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,5 +1,5 @@ # These are supported funding model platforms -github: bdbaddog mwichmann +github: [bdbaddog, mwichmann] patreon: bdbaddog -- cgit v0.12