From 395e09a4d28d25ae030c50cf82a0729f6c4c3bee Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Fri, 26 Jan 2018 19:20:14 +0200 Subject: New conditional C Scanner; Improvements for virtual C Pre-Processor --- src/CHANGES.txt | 11 +++++ src/engine/SCons/Scanner/C.py | 42 ++++++++++++------- src/engine/SCons/Scanner/CTests.py | 68 +++++++++++++++++++++++++++--- src/engine/SCons/cpp.py | 85 ++++++++++++++++++++++++++------------ src/engine/SCons/cppTests.py | 37 +++++++++++++---- 5 files changed, 186 insertions(+), 57 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index c02bb36..c13e3de 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -33,6 +33,17 @@ RELEASE 3.1.0.alpha.yyyymmdd - NEW DATE WILL BE INSERTED HERE - Updated manpage scons.xml to fix a nested list problem - Updated doc terminionly: use prepend instead of append as appropriate + From Ivan Kravets, PlatformIO + - New conditional C Scanner (`SCons.Scanner.C.CConditionalScanner()`) + which interprets C/C Preprocessor conditional syntax (#ifdef, #if, #else, + #elif, #define, etc.) + - Improvements for virtual C Pre-Processor: + * Handle UNSIGNED LONG and LONG numeric constants in DEC (keep support for HEX) + * Skip unrecognized directives, such as `#if( defined ...)` + * Ignore `#include DYNAMIC_INCLUDE` directive that depends on a dynamic + macro which is not located in a state TABLE. + * Cleanup CPP expressions before evaluating (strip comments, carriage returns) + RELEASE 3.0.1 - Mon, 12 Nov 2017 15:31:33 -0700 From Daniel Moody: diff --git a/src/engine/SCons/Scanner/C.py b/src/engine/SCons/Scanner/C.py index c2e50a6..db7463f 100644 --- a/src/engine/SCons/Scanner/C.py +++ b/src/engine/SCons/Scanner/C.py @@ -1,6 +1,6 @@ """SCons.Scanner.C -This module implements the dependency scanner for C/C++ code. +This module implements the dependency scanner for C/C++ code. """ @@ -72,7 +72,11 @@ def dictify_CPPDEFINES(env): result = {} for c in cppdefines: if SCons.Util.is_Sequence(c): - result[c[0]] = c[1] + # handle tuple with 1 item (e.g. tuple("DEFINE", )) + if len(c) > 1: + result[c[0]] = c[1] + else: + result[c[0]] = None else: result[c] = None return result @@ -108,21 +112,27 @@ class SConsCPPScannerWrapper(object): def select(self, node): return self + +def CConditionalScanner(): + """ + Return an advanced conditional Scanner instance for scanning source files + + Interprets C/C++ Preprocessor conditional syntax + (#ifdef, #if, defined, #else, #elif, etc.). + """ + return SConsCPPScannerWrapper("CScanner", "CPPPATH") + + def CScanner(): - """Return a prototype Scanner instance for scanning source files - that use the C pre-processor""" - - # Here's how we would (or might) use the CPP scanner code above that - # knows how to evaluate #if/#ifdef/#else/#elif lines when searching - # for #includes. This is commented out for now until we add the - # right configurability to let users pick between the scanners. - #return SConsCPPScannerWrapper("CScanner", "CPPPATH") - - cs = SCons.Scanner.ClassicCPP("CScanner", - "$CPPSUFFIXES", - "CPPPATH", - '^[ \t]*#[ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")') - return cs + """Return a simplified classic Scanner instance for scanning source files + + Takes into account the type of bracketing used to include the file, and + uses classic CPP rules for searching for the files based on the bracketing. + """ + return SCons.Scanner.ClassicCPP( + "CScanner", "$CPPSUFFIXES", "CPPPATH", + '^[ \t]*#[ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")') + # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Scanner/CTests.py b/src/engine/SCons/Scanner/CTests.py index 9c7df12..94d3dbf 100644 --- a/src/engine/SCons/Scanner/CTests.py +++ b/src/engine/SCons/Scanner/CTests.py @@ -27,7 +27,6 @@ import SCons.compat import collections import os -import sys import unittest import TestCmd @@ -45,8 +44,11 @@ os.chdir(test.workpath('')) # create some source files and headers: test.write('f1.cpp',""" -#include \"f1.h\" +#ifdef INCLUDE_F2 /* multi-line comment */ #include +#else +#include \"f1.h\" +#endif int main() { @@ -56,8 +58,15 @@ int main() test.write('f2.cpp',""" #include \"d1/f1.h\" -#include + +#if 5UL < 10 && !defined(DUMMY_MACRO) // some comment + #if NESTED_CONDITION + #include + #endif +#else #include \"f1.h\" +#endif + #import int main() @@ -261,7 +270,7 @@ class CScannerTestCase4(unittest.TestCase): deps = s(env.File('f2.cpp'), env, path) headers = ['d1/f1.h', 'f1.h', 'd1/d2/f1.h', 'd1/d2/f4.h'] deps_match(self, deps, headers) - + class CScannerTestCase5(unittest.TestCase): def runTest(self): """Make sure files in repositories will get scanned""" @@ -282,7 +291,7 @@ class CScannerTestCase5(unittest.TestCase): # Make sure rexists() got called on the file node being # scanned, essential for cooperation with VariantDir functionality. assert n.GetTag('rexists_called') - + headers = ['f1.h', 'f2.h', 'f3-test.h', 'd1/f1.h', 'd1/f2.h', 'd1/f3-test.h'] deps_match(self, deps, headers) @@ -340,7 +349,7 @@ class CScannerTestCase9(unittest.TestCase): # Did we catch the warning associated with not finding fb.h? assert to.out - + deps_match(self, deps, [ 'fa.h' ]) test.unlink('fa.h') @@ -440,6 +449,50 @@ class CScannerTestCase15(unittest.TestCase): assert suffix in s.get_skeys(env), "%s not in skeys" % suffix +class CConditionalScannerTestCase1(unittest.TestCase): + def runTest(self): + """Find local files with no CPPPATH""" + env = DummyEnvironment(CPPPATH=[]) + s = SCons.Scanner.C.CConditionalScanner() + path = s.path(env) + deps = s(env.File('f1.cpp'), env, path) + headers = ['f1.h'] + deps_match(self, deps, headers) + + +class CConditionalScannerTestCase2(unittest.TestCase): + def runTest(self): + """Find local files with no CPPPATH based on #ifdef""" + env = DummyEnvironment(CPPPATH=[], CPPDEFINES=["INCLUDE_F2"]) + s = SCons.Scanner.C.CConditionalScanner() + path = s.path(env) + deps = s(env.File('f1.cpp'), env, path) + headers = ['f2.h', 'fi.h'] + deps_match(self, deps, headers) + + +class CConditionalScannerTestCase3(unittest.TestCase): + def runTest(self): + """Find files in explicit subdirectories, ignore missing file""" + env = DummyEnvironment( + CPPPATH=[test.workpath("d1")], + CPPDEFINES=[("NESTED_CONDITION", 1)] + ) + s = SCons.Scanner.C.CConditionalScanner() + deps = s(env.File('f2.cpp'), env, s.path(env)) + headers = ['d1/f1.h', 'd1/d2/f1.h'] + deps_match(self, deps, headers) + + # disable nested conditions + env = DummyEnvironment( + CPPPATH=[test.workpath("d1")], + CPPDEFINES=[("NESTED_CONDITION", 0)] + ) + s = SCons.Scanner.C.CConditionalScanner() + deps = s(env.File('f2.cpp'), env, s.path(env)) + headers = ['d1/f1.h'] + deps_match(self, deps, headers) + def suite(): suite = unittest.TestSuite() @@ -457,6 +510,9 @@ def suite(): suite.addTest(CScannerTestCase13()) suite.addTest(CScannerTestCase14()) suite.addTest(CScannerTestCase15()) + suite.addTest(CConditionalScannerTestCase1()) + suite.addTest(CConditionalScannerTestCase2()) + suite.addTest(CConditionalScannerTestCase3()) return suite if __name__ == "__main__": diff --git a/src/engine/SCons/cpp.py b/src/engine/SCons/cpp.py index 161f070..42693b9 100644 --- a/src/engine/SCons/cpp.py +++ b/src/engine/SCons/cpp.py @@ -99,8 +99,19 @@ e = '^\s*#\s*(' + '|'.join(l) + ')(.*)$' # And last but not least, compile the expression. CPP_Expression = re.compile(e, re.M) +# A list with RE to cleanup CPP Expressions (tuples) +# We should remove all comments and carriage returns (\r) before evaluating +CPP_Expression_Cleaner_List = [ + "/\*.*\*/", + "/\*.*", + "//.*", + "\r" +] +CPP_Expression_Cleaner_RE = re.compile( + "\s*(" + "|".join(CPP_Expression_Cleaner_List) + ")") - +def Cleanup_CPP_Expressions(ts): + return [(t[0], CPP_Expression_Cleaner_RE.sub("", t[1])) for t in ts] # # Second "subsystem" of regular expressions that we set up: @@ -118,7 +129,6 @@ CPP_to_Python_Ops_Dict = { '||' : ' or ', '?' : ' and ', ':' : ' or ', - '\r' : '', } CPP_to_Python_Ops_Sub = lambda m: CPP_to_Python_Ops_Dict[m.group(0)] @@ -141,12 +151,10 @@ CPP_to_Python_Ops_Expression = re.compile(expr) # A separate list of expressions to be evaluated and substituted # sequentially, not all at once. CPP_to_Python_Eval_List = [ - ['defined\s+(\w+)', '"\\1" in __dict__'], - ['defined\s*\((\w+)\)', '"\\1" in __dict__'], - ['/\*.*\*/', ''], - ['/\*.*', ''], - ['//.*', ''], - ['(0x[0-9A-Fa-f]*)[UL]+', '\\1'], + ['defined\s+(\w+)', '"\\1" in __dict__'], + ['defined\s*\((\w+)\)', '"\\1" in __dict__'], + ['(0x[0-9A-Fa-f]+)(?:L|UL)?', '\\1'], + ['(\d+)(?:L|UL)?', '\\1'], ] # Replace the string representations of the regular expressions in the @@ -284,7 +292,13 @@ class PreProcessor(object): global CPP_Expression, Table contents = line_continuations.sub('', contents) cpp_tuples = CPP_Expression.findall(contents) - return [(m[0],) + Table[m[0]].match(m[1]).groups() for m in cpp_tuples] + cpp_tuples = Cleanup_CPP_Expressions(cpp_tuples) + result = [] + for t in cpp_tuples: + m = Table[t[0]].match(t[1]) + if m: + result.append((t[0],) + m.groups()) + return result def __call__(self, file): """ @@ -354,8 +368,10 @@ class PreProcessor(object): track #define values. """ t = CPP_to_Python(' '.join(t[1:])) - try: return eval(t, self.cpp_namespace) - except (NameError, TypeError): return 0 + try: + return eval(t, self.cpp_namespace) + except (NameError, TypeError, SyntaxError): + return 0 def initialize_result(self, fname): self.result = [fname] @@ -482,7 +498,11 @@ class PreProcessor(object): try: expansion = int(expansion) except (TypeError, ValueError): - pass + # handle "defined" chain "! (defined (A) || defined (B)" ... + if "defined " in expansion: + self.cpp_namespace[name] = self.eval_expression(t[2:]) + return + if args: evaluator = FunctionEvaluator(name, args[1:-1], expansion) self.cpp_namespace[name] = evaluator @@ -508,15 +528,21 @@ class PreProcessor(object): Default handling of a #include line. """ t = self.resolve_include(t) + if not t: + return include_file = self.find_include_file(t) - if include_file: - #print("include_file =", include_file) - self.result.append(include_file) - contents = self.read_file(include_file) - new_tuples = [('scons_current_file', include_file)] + \ - self.tupleize(contents) + \ - [('scons_current_file', self.current_file)] - self.tuples[:] = new_tuples + self.tuples + if not include_file: + return + # print("include_file =", include_file) + self.result.append(include_file) + # handle infinite recursion + for t in self.tuples: + if t[0] == 'scons_current_file' and t[1] == include_file: + return + new_tuples = [('scons_current_file', include_file)] + \ + self.tupleize(self.read_file(include_file)) + \ + [('scons_current_file', self.current_file)] + self.tuples[:] = new_tuples + self.tuples # Date: Tue, 22 Nov 2005 20:26:09 -0500 # From: Stefan Seefeld @@ -542,18 +568,25 @@ class PreProcessor(object): This handles recursive expansion of values without "" or <> surrounding the name until an initial " or < is found, to handle - #include FILE - - where FILE is a #define somewhere else.""" - - s = t[1] + where FILE is a #define somewhere else. + """ + s = t[1].strip() while not s[0] in '<"': - #print("s =", s) try: s = self.cpp_namespace[s] except KeyError: m = function_name.search(s) + + # Date: Mon, 28 Nov 2016 17:47:13 UTC + # From: Ivan Kravets + # + # Ignore `#include` directive that depends on dynamic macro + # which is not located in state TABLE + # For example, `#include MYCONFIG_FILE` + if not m: + return None + s = self.cpp_namespace[m.group(1)] if callable(s): args = function_arg_separator.split(m.group(2)) diff --git a/src/engine/SCons/cppTests.py b/src/engine/SCons/cppTests.py index 40236e4..1447a7b 100644 --- a/src/engine/SCons/cppTests.py +++ b/src/engine/SCons/cppTests.py @@ -26,7 +26,6 @@ from __future__ import absolute_import __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import atexit -import sys import unittest import TestUnit @@ -67,7 +66,7 @@ substitution_input = """ ifdef_input = """ #define DEFINED 0 -#ifdef DEFINED +#ifdef DEFINED /* multi-line comment */ #include "file7-yes" #else #include "file7-no" @@ -82,7 +81,7 @@ ifdef_input = """ if_boolean_input = """ -#define ZERO 0 +#define ZERO 0 // single-line comment #define ONE 1 #if ZERO @@ -132,27 +131,35 @@ if_boolean_input = """ if_defined_input = """ -#define DEFINED 0 +#define DEFINED_A 0 +#define DEFINED_B 0 -#if defined(DEFINED) +#if defined(DEFINED_A) #include "file15-yes" #endif -#if ! defined(DEFINED) +#if ! defined(DEFINED_A) #include #else #include #endif -#if defined DEFINED +#if defined DEFINED_A #include "file17-yes" #endif -#if ! defined DEFINED +#if ! defined DEFINED_A #include #else #include #endif + +#if ! (defined (DEFINED_A) || defined (DEFINED_B) +#include +#else +#include +#endif + """ @@ -226,11 +233,17 @@ expression_input = """ #include "file29-yes" #endif -#if ! (ONE != ONE) +#if ! (ONE != ONE) #include #else #include #endif + +#if 123456789UL || 0x13L +#include +#else +#include +#endif """ @@ -466,6 +479,7 @@ class PreProcessorTestCase(cppAllTestCase): ('include', '<', 'file16-yes'), ('include', '"', 'file17-yes'), ('include', '<', 'file18-yes'), + ('include', '<', 'file19-yes'), ] expression_expect = [ @@ -481,6 +495,7 @@ class PreProcessorTestCase(cppAllTestCase): ('include', '<', 'file28-yes'), ('include', '"', 'file29-yes'), ('include', '<', 'file30-yes'), + ('include', '<', 'file301-yes'), ] undef_expect = [ @@ -561,6 +576,8 @@ class DumbPreProcessorTestCase(cppAllTestCase): ('include', '"', 'file17-yes'), ('include', '<', 'file18-no'), ('include', '<', 'file18-yes'), + ('include', '<', 'file19-no'), + ('include', '<', 'file19-yes'), ] expression_expect = [ @@ -588,6 +605,8 @@ class DumbPreProcessorTestCase(cppAllTestCase): ('include', '"', 'file29-yes'), ('include', '<', 'file30-yes'), ('include', '<', 'file30-no'), + ('include', '<', 'file301-yes'), + ('include', '<', 'file301-no'), ] undef_expect = [ -- cgit v0.12 From 5fcdb300cbe1a64488c7686a2a71cd20aafd146d Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 8 Mar 2018 12:40:17 +0200 Subject: Avoid infinite recursion for conditional PreProcessor --- src/engine/SCons/cpp.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/engine/SCons/cpp.py b/src/engine/SCons/cpp.py index 42693b9..35b8799 100644 --- a/src/engine/SCons/cpp.py +++ b/src/engine/SCons/cpp.py @@ -531,14 +531,10 @@ class PreProcessor(object): if not t: return include_file = self.find_include_file(t) - if not include_file: + # avoid infinite recursion + if not include_file or include_file in self.result: return - # print("include_file =", include_file) self.result.append(include_file) - # handle infinite recursion - for t in self.tuples: - if t[0] == 'scons_current_file' and t[1] == include_file: - return new_tuples = [('scons_current_file', include_file)] + \ self.tupleize(self.read_file(include_file)) + \ [('scons_current_file', self.current_file)] -- cgit v0.12 From 080d987d57bb3d0fe5a6a5f879cdb8b35cd8c576 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 8 Mar 2018 14:03:33 +0200 Subject: Implement CPP tuples caching per a file --- src/engine/SCons/cpp.py | 88 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 58 insertions(+), 30 deletions(-) diff --git a/src/engine/SCons/cpp.py b/src/engine/SCons/cpp.py index 35b8799..72018c5 100644 --- a/src/engine/SCons/cpp.py +++ b/src/engine/SCons/cpp.py @@ -239,6 +239,9 @@ function_arg_separator = re.compile(',\s*') class PreProcessor(object): + + FILE_TUPLES_CACHE = None + """ The main workhorse class for handling C pre-processing. """ @@ -277,57 +280,81 @@ class PreProcessor(object): d[op] = getattr(self, 'do_' + op) self.default_table = d - # Controlling methods. - - def tupleize(self, contents): + def __call__(self, file): """ - Turns the contents of a file into a list of easily-processed - tuples describing the CPP lines in the file. + Pre-processes a file. - The first element of each tuple is the line's preprocessor - directive (#if, #include, #define, etc., minus the initial '#'). - The remaining elements are specific to the type of directive, as - pulled apart by the regular expression. + This is the main public entry point. """ - global CPP_Expression, Table - contents = line_continuations.sub('', contents) - cpp_tuples = CPP_Expression.findall(contents) - cpp_tuples = Cleanup_CPP_Expressions(cpp_tuples) - result = [] - for t in cpp_tuples: - m = Table[t[0]].match(t[1]) - if m: - result.append((t[0],) + m.groups()) - return result + self.current_file = file + return self.process_file(file) - def __call__(self, file): + def process_file(self, file): """ Pre-processes a file. - This is the main public entry point. + This is the main internal entry point. """ - self.current_file = file - return self.process_contents(self.read_file(file), file) + return self._process_tuples(self.tupleize_file(file), file) - def process_contents(self, contents, fname=None): + def process_contents(self, contents): """ Pre-processes a file contents. - This is the main internal entry point. + Is used by tests """ + return self._process_tuples(self.tupleize(contents)) + + def _process_tuples(self, tuples, file=None): self.stack = [] self.dispatch_table = self.default_table.copy() - self.current_file = fname - self.tuples = self.tupleize(contents) + self.current_file = file + self.tuples = tuples - self.initialize_result(fname) + self.initialize_result(file) while self.tuples: t = self.tuples.pop(0) # Uncomment to see the list of tuples being processed (e.g., # to validate the CPP lines are being translated correctly). - #print(t) + # print(t) self.dispatch_table[t[0]](t) - return self.finalize_result(fname) + return self.finalize_result(file) + + def tupleize_file(self, file): + if not PreProcessor.FILE_TUPLES_CACHE: + PreProcessor.FILE_TUPLES_CACHE = {} + file_tuples = PreProcessor.FILE_TUPLES_CACHE.get(file) + if not file_tuples: + file_tuples = self._parse_tuples(self.read_file(file)) + PreProcessor.FILE_TUPLES_CACHE[file] = file_tuples + return self._match_tuples(file_tuples) + + def tupleize(self, contents): + """ + Turns the contents of a file into a list of easily-processed + tuples describing the CPP lines in the file. + + The first element of each tuple is the line's preprocessor + directive (#if, #include, #define, etc., minus the initial '#'). + The remaining elements are specific to the type of directive, as + pulled apart by the regular expression. + """ + return self._match_tuples(self._parse_tuples(contents)) + + def _parse_tuples(self, contents): + global CPP_Expression + contents = line_continuations.sub('', contents) + tuples = CPP_Expression.findall(contents) + return Cleanup_CPP_Expressions(tuples) + + def _match_tuples(self, tuples): + global Table + result = [] + for t in tuples: + m = Table[t[0]].match(t[1]) + if m: + result.append((t[0],) + m.groups()) + return result # Dispatch table stack manipulation methods. @@ -535,6 +562,7 @@ class PreProcessor(object): if not include_file or include_file in self.result: return self.result.append(include_file) + # print include_file, len(self.tuples) new_tuples = [('scons_current_file', include_file)] + \ self.tupleize(self.read_file(include_file)) + \ [('scons_current_file', self.current_file)] -- cgit v0.12 From 80e62ede63890d52fb7395c7588758bc07f8fba6 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 8 Mar 2018 14:28:51 +0200 Subject: Restore support for "all" option for Conditional PreProcessor --- src/engine/SCons/Scanner/C.py | 5 +++-- src/engine/SCons/cpp.py | 14 +++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/engine/SCons/Scanner/C.py b/src/engine/SCons/Scanner/C.py index db7463f..0d18879 100644 --- a/src/engine/SCons/Scanner/C.py +++ b/src/engine/SCons/Scanner/C.py @@ -96,10 +96,11 @@ class SConsCPPScannerWrapper(object): def __init__(self, name, variable): self.name = name self.path = SCons.Scanner.FindPathDirs(variable) - def __call__(self, node, env, path = ()): + def __call__(self, node, env, path = (), all=False): cpp = SConsCPPScanner(current = node.get_dir(), cpppath = path, - dict = dictify_CPPDEFINES(env)) + dict = dictify_CPPDEFINES(env), + all = all) result = cpp(node) for included, includer in cpp.missing: fmt = "No dependency generated for file: %s (included from: %s) -- file not found" diff --git a/src/engine/SCons/cpp.py b/src/engine/SCons/cpp.py index 72018c5..22b7a7b 100644 --- a/src/engine/SCons/cpp.py +++ b/src/engine/SCons/cpp.py @@ -245,7 +245,7 @@ class PreProcessor(object): """ The main workhorse class for handling C pre-processing. """ - def __init__(self, current=os.curdir, cpppath=(), dict={}, all=0): + def __init__(self, current=os.curdir, cpppath=(), dict={}, all=False): global Table cpppath = tuple(cpppath) @@ -263,8 +263,8 @@ class PreProcessor(object): self.cpp_namespace = dict.copy() self.cpp_namespace['__dict__'] = self.cpp_namespace - if all: - self.do_include = self.all_include + # IF all=True, return all found includes without nested parsing + self.all = all # For efficiency, a dispatch table maps each C preprocessor # directive (#if, #define, etc.) to the method that should be @@ -563,6 +563,10 @@ class PreProcessor(object): return self.result.append(include_file) # print include_file, len(self.tuples) + + if self.all: + return + new_tuples = [('scons_current_file', include_file)] + \ self.tupleize(self.read_file(include_file)) + \ [('scons_current_file', self.current_file)] @@ -619,10 +623,6 @@ class PreProcessor(object): return None return (t[0], s[0], s[1:-1]) - def all_include(self, t): - """ - """ - self.result.append(self.resolve_include(t)) class DumbPreProcessor(PreProcessor): """A preprocessor that ignores all #if/#elif/#else/#endif directives -- cgit v0.12 From e2312b8dfb4b993e8abbb1cf1043906d4bf31b14 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 8 Mar 2018 16:25:09 +0200 Subject: Allow to control maximum depth of nested includes for conditional PreProcessor --- src/engine/SCons/Scanner/C.py | 4 ++-- src/engine/SCons/cpp.py | 28 +++++++++++++++++++++++----- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/engine/SCons/Scanner/C.py b/src/engine/SCons/Scanner/C.py index 0d18879..bd75bc9 100644 --- a/src/engine/SCons/Scanner/C.py +++ b/src/engine/SCons/Scanner/C.py @@ -96,11 +96,11 @@ class SConsCPPScannerWrapper(object): def __init__(self, name, variable): self.name = name self.path = SCons.Scanner.FindPathDirs(variable) - def __call__(self, node, env, path = (), all=False): + def __call__(self, node, env, path = (), depth=-1): cpp = SConsCPPScanner(current = node.get_dir(), cpppath = path, dict = dictify_CPPDEFINES(env), - all = all) + depth = depth) result = cpp(node) for included, includer in cpp.missing: fmt = "No dependency generated for file: %s (included from: %s) -- file not found" diff --git a/src/engine/SCons/cpp.py b/src/engine/SCons/cpp.py index 22b7a7b..cfff053 100644 --- a/src/engine/SCons/cpp.py +++ b/src/engine/SCons/cpp.py @@ -245,7 +245,7 @@ class PreProcessor(object): """ The main workhorse class for handling C pre-processing. """ - def __init__(self, current=os.curdir, cpppath=(), dict={}, all=False): + def __init__(self, current=os.curdir, cpppath=(), dict={}, all=0, depth=-1): global Table cpppath = tuple(cpppath) @@ -263,8 +263,15 @@ class PreProcessor(object): self.cpp_namespace = dict.copy() self.cpp_namespace['__dict__'] = self.cpp_namespace - # IF all=True, return all found includes without nested parsing - self.all = all + # Return all includes without resolving + if all: + self.do_include = self.all_include + + # Max depth of nested includes: + # -1 = unlimited + # 0 - disabled nesting + # >0 - number of allowed nested includes + self.depth = depth # For efficiency, a dispatch table maps each C preprocessor # directive (#if, #define, etc.) to the method that should be @@ -564,8 +571,14 @@ class PreProcessor(object): self.result.append(include_file) # print include_file, len(self.tuples) - if self.all: - return + # Handle maximum depth of nested includes + if self.depth != -1: + current_depth = 0 + for t in self.tuples: + if t[0] != "scons_current_file": + current_depth += 1 + if current_depth >= self.depth: + return new_tuples = [('scons_current_file', include_file)] + \ self.tupleize(self.read_file(include_file)) + \ @@ -623,6 +636,11 @@ class PreProcessor(object): return None return (t[0], s[0], s[1:-1]) + def all_include(self, t): + """ + """ + self.result.append(self.resolve_include(t)) + class DumbPreProcessor(PreProcessor): """A preprocessor that ignores all #if/#elif/#else/#endif directives -- cgit v0.12 From 1ec74bcc6f5a17217cfa7067a18d172ed224b876 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Mon, 19 Nov 2018 21:55:31 +0200 Subject: Remember known CPPPATH for dependencies --- src/engine/SCons/Scanner/C.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/engine/SCons/Scanner/C.py b/src/engine/SCons/Scanner/C.py index bd75bc9..ede74b9 100644 --- a/src/engine/SCons/Scanner/C.py +++ b/src/engine/SCons/Scanner/C.py @@ -29,6 +29,7 @@ This module implements the dependency scanner for C/C++ code. __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + import SCons.Node.FS import SCons.Scanner import SCons.Util @@ -46,16 +47,25 @@ class SConsCPPScanner(SCons.cpp.PreProcessor): def __init__(self, *args, **kw): SCons.cpp.PreProcessor.__init__(self, *args, **kw) self.missing = [] + self._known_paths = tuple() + def initialize_result(self, fname): self.result = SCons.Util.UniqueList([fname]) - def finalize_result(self, fname): - return self.result[1:] + def find_include_file(self, t): keyword, quote, fname = t - result = SCons.Node.FS.find_file(fname, self.searchpath[quote]) - if not result: + result = SCons.Node.FS.find_file( + fname, self._known_paths + self.searchpath[quote]) + if result: + result_path = result.get_abspath() + for p in self.searchpath[quote]: + if result_path.startswith(p.get_abspath()): + self._known_paths.add(p) + break + else: self.missing.append((fname, self.current_file)) return result + def read_file(self, file): try: with open(str(file.rfile())) as fp: -- cgit v0.12 From 037c8733cf74d9404a73d8ef6c5549a1d7684f25 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Tue, 20 Nov 2018 01:21:45 +0200 Subject: Handle CWD when searching for a file --- src/engine/SCons/Scanner/C.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/engine/SCons/Scanner/C.py b/src/engine/SCons/Scanner/C.py index ede74b9..37bf244 100644 --- a/src/engine/SCons/Scanner/C.py +++ b/src/engine/SCons/Scanner/C.py @@ -29,7 +29,6 @@ This module implements the dependency scanner for C/C++ code. __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - import SCons.Node.FS import SCons.Scanner import SCons.Util @@ -47,20 +46,22 @@ class SConsCPPScanner(SCons.cpp.PreProcessor): def __init__(self, *args, **kw): SCons.cpp.PreProcessor.__init__(self, *args, **kw) self.missing = [] - self._known_paths = tuple() + self._known_paths = [] def initialize_result(self, fname): self.result = SCons.Util.UniqueList([fname]) def find_include_file(self, t): keyword, quote, fname = t - result = SCons.Node.FS.find_file( - fname, self._known_paths + self.searchpath[quote]) + paths = tuple(self._known_paths) + self.searchpath[quote] + if quote == '"': + paths = (self.current_file.dir, ) + paths + result = SCons.Node.FS.find_file(fname, paths) if result: result_path = result.get_abspath() for p in self.searchpath[quote]: if result_path.startswith(p.get_abspath()): - self._known_paths.add(p) + self._known_paths.append(p) break else: self.missing.append((fname, self.current_file)) -- cgit v0.12 From 04bf778cb8749845cf1f21b6f06a742dac01b6ad Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Wed, 21 Nov 2018 00:43:40 +0200 Subject: Stop handling "define" and "undef" when condition fails --- src/engine/SCons/cpp.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/engine/SCons/cpp.py b/src/engine/SCons/cpp.py index e5f7345..4b921e4 100644 --- a/src/engine/SCons/cpp.py +++ b/src/engine/SCons/cpp.py @@ -447,7 +447,7 @@ class PreProcessor(object): d = self.dispatch_table p = self.stack[-1] if self.stack else self.default_table - for k in ('import', 'include', 'include_next'): + for k in ('import', 'include', 'include_next', 'define', 'undef'): d[k] = p[k] def stop_handling_includes(self, t=None): @@ -463,6 +463,8 @@ class PreProcessor(object): d['import'] = self.do_nothing d['include'] = self.do_nothing d['include_next'] = self.do_nothing + d['define'] = self.do_nothing + d['undef'] = self.do_nothing # Default methods for handling all of the preprocessor directives. # (Note that what actually gets called for a given directive at any -- cgit v0.12 From fa2df78952debfb465515235ff9d0227aa140316 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Mon, 26 Aug 2019 21:09:15 +0300 Subject: Fix incorrect calculation of includes depth --- src/engine/SCons/cpp.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/engine/SCons/cpp.py b/src/engine/SCons/cpp.py index 40d4a0c..7535dbb 100644 --- a/src/engine/SCons/cpp.py +++ b/src/engine/SCons/cpp.py @@ -218,7 +218,7 @@ class FunctionEvaluator(object): parts = [] for s in self.expansion: - if not s in self.args: + if s not in self.args: s = repr(s) parts.append(s) statement = ' + '.join(parts) @@ -580,13 +580,13 @@ class PreProcessor(object): if self.depth != -1: current_depth = 0 for t in self.tuples: - if t[0] != "scons_current_file": + if t[0] == "scons_current_file": current_depth += 1 if current_depth >= self.depth: return new_tuples = [('scons_current_file', include_file)] + \ - self.tupleize(self.read_file(include_file)) + \ + self.tupleize_file(include_file) + \ [('scons_current_file', self.current_file)] self.tuples[:] = new_tuples + self.tuples -- cgit v0.12 From b9b4a8f887868aeb4242816d1a88dc07f9435c20 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Mon, 26 Aug 2019 21:46:09 +0300 Subject: Remove tuples caching, save memory --- src/engine/SCons/cpp.py | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/src/engine/SCons/cpp.py b/src/engine/SCons/cpp.py index 7535dbb..f55ea21 100644 --- a/src/engine/SCons/cpp.py +++ b/src/engine/SCons/cpp.py @@ -243,8 +243,6 @@ function_arg_separator = re.compile(r',\s*') class PreProcessor(object): - FILE_TUPLES_CACHE = None - """ The main workhorse class for handling C pre-processing. """ @@ -305,7 +303,7 @@ class PreProcessor(object): This is the main internal entry point. """ - return self._process_tuples(self.tupleize_file(file), file) + return self._process_tuples(self.tupleize(self.read_file(file)), file) def process_contents(self, contents): """ @@ -330,15 +328,6 @@ class PreProcessor(object): self.dispatch_table[t[0]](t) return self.finalize_result(file) - def tupleize_file(self, file): - if not PreProcessor.FILE_TUPLES_CACHE: - PreProcessor.FILE_TUPLES_CACHE = {} - file_tuples = PreProcessor.FILE_TUPLES_CACHE.get(file) - if not file_tuples: - file_tuples = self._parse_tuples(self.read_file(file)) - PreProcessor.FILE_TUPLES_CACHE[file] = file_tuples - return self._match_tuples(file_tuples) - def tupleize(self, contents): """ Turns the contents of a file into a list of easily-processed @@ -586,7 +575,7 @@ class PreProcessor(object): return new_tuples = [('scons_current_file', include_file)] + \ - self.tupleize_file(include_file) + \ + self.tupleize(self.read_file(include_file)) + \ [('scons_current_file', self.current_file)] self.tuples[:] = new_tuples + self.tuples -- cgit v0.12 From 709bbe03fc4ba1cd12d6f51c79a2bc06b7f790f3 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Thu, 29 Aug 2019 11:43:01 -0600 Subject: CmdStringHolder should not fail in Subst Pass 1: test case showing the failure. This is WIP - need to add the fix, but want a CI build to show the fail. Closes issues #3248 Signed-off-by: Mats Wichmann --- test/Subst/bug3428.py | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 test/Subst/bug3428.py diff --git a/test/Subst/bug3428.py b/test/Subst/bug3428.py new file mode 100644 index 0000000..00587e6 --- /dev/null +++ b/test/Subst/bug3428.py @@ -0,0 +1,55 @@ +#!/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 CmdStringHolder doesn't trip in Subst on doing +a string-only operation that does not work on UserString class. +Issue: https://github.com/SCons/scons/issues/3428 +""" + +import TestSCons + +test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) + + +test.write('SConstruct', """\ +env = Environment() +env.Append(LIBPATH=["path1/sub1","path1/sub2"]) +lst = env.Flatten(env.subst_list("$LIBPATH")) +for i in lst: + env.Dir(i) +""") + +test.run(status=0) + + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: -- cgit v0.12 From 581a6912938f3143b2c31dcb78ecc9928da124df Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sun, 8 Sep 2019 06:17:29 -0600 Subject: [PR #3434] apply subst fix from #3428 Signed-off-by: Mats Wichmann --- src/CHANGES.txt | 1 + src/engine/SCons/Subst.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 87f4e28..e3d057e 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -15,6 +15,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER From Mats Wichmann - Replace instances of string find method with "in" checks where the index from find() was not used. + - CmdStringHolder fix from issue #3428 RELEASE 3.1.1 - Mon, 07 Aug 2019 20:09:12 -0500 diff --git a/src/engine/SCons/Subst.py b/src/engine/SCons/Subst.py index 6f62198..2de64c5 100644 --- a/src/engine/SCons/Subst.py +++ b/src/engine/SCons/Subst.py @@ -409,7 +409,7 @@ def scons_subst(strSubst, env, mode=SUBST_RAW, target=None, source=None, gvars={ handles separating command lines into lists of arguments, so see that function if that's what you're looking for. """ - if isinstance(strSubst, str) and strSubst.find('$') < 0: + if (isinstance(strSubst, str) and '$' not in strSubst) or isinstance(strSubst, CmdStringHolder): return strSubst class StringSubber(object): -- cgit v0.12 From b907ebd61c3898061412207c2c314107caa3a59b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Kul=C3=ADk?= Date: Fri, 27 Sep 2019 09:47:16 +0200 Subject: Fix bytes not being decoded in suncxx.py --- src/engine/SCons/Tool/suncxx.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/engine/SCons/Tool/suncxx.py b/src/engine/SCons/Tool/suncxx.py index 9ac8d32..090df7d 100644 --- a/src/engine/SCons/Tool/suncxx.py +++ b/src/engine/SCons/Tool/suncxx.py @@ -74,7 +74,7 @@ def get_package_info(package_name, pkginfo, pkgchk): except EnvironmentError: pass else: - pkginfo_contents = p.communicate()[0] + pkginfo_contents = p.communicate()[0].decode() version_re = re.compile(r'^ *VERSION:\s*(.*)$', re.M) version_match = version_re.search(pkginfo_contents) if version_match: @@ -88,7 +88,7 @@ def get_package_info(package_name, pkginfo, pkgchk): except EnvironmentError: pass else: - pkgchk_contents = p.communicate()[0] + pkgchk_contents = p.communicate()[0].decode() pathname_re = re.compile(r'^Pathname:\s*(.*/bin/CC)$', re.M) pathname_match = pathname_re.search(pkgchk_contents) if pathname_match: -- cgit v0.12 From 2cc64514e0b17d9f678b5bddb8ffe00789abdba8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Kul=C3=ADk?= Date: Fri, 27 Sep 2019 09:58:05 +0200 Subject: Modify CHANGES.txt --- src/CHANGES.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 4078669..ac9239f 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -18,6 +18,9 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Turn previously deprecated debug options into failures: --debug=tree, --debug=dtree, --debug=stree, --debug=nomemoizer. + From Jakub Kulik + - Fix subprocess result bytes not being decoded in SunOS/Solaris related tools. + RELEASE 3.1.1 - Mon, 07 Aug 2019 20:09:12 -0500 -- cgit v0.12 From 7193bf3b65b1f9fe47cde3772a1649af72c5cf3e Mon Sep 17 00:00:00 2001 From: Edoardo Bezzeccheri Date: Tue, 1 Oct 2019 13:47:02 +0200 Subject: Added debug option "timestamp", modify CHANGES.txt --- src/CHANGES.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 4078669..3ea2249 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -18,6 +18,9 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Turn previously deprecated debug options into failures: --debug=tree, --debug=dtree, --debug=stree, --debug=nomemoizer. + From Edoardo Bezzeccheri + - Added debug option "timestamp" which outputs to stdout the absolute start and end time for each target. + RELEASE 3.1.1 - Mon, 07 Aug 2019 20:09:12 -0500 -- cgit v0.12 From 8173acb3d3b69144ba90d931e110ee5b8e2801d0 Mon Sep 17 00:00:00 2001 From: Edoardo Bezzeccheri Date: Tue, 1 Oct 2019 13:47:17 +0200 Subject: Added debug option "timestamp", add test --- test/option/debug-timestamp.py | 234 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 234 insertions(+) create mode 100644 test/option/debug-timestamp.py diff --git a/test/option/debug-timestamp.py b/test/option/debug-timestamp.py new file mode 100644 index 0000000..3e7c682 --- /dev/null +++ b/test/option/debug-timestamp.py @@ -0,0 +1,234 @@ +#!/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. +from __future__ import division, print_function + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import TestSCons +import re +import time + +_python_ = TestSCons._python_ + +test = TestSCons.TestSCons() + +test.write('sleep_cat.py', """\ +import sys +import time +time.sleep(int(sys.argv[1])) +with open(sys.argv[2], 'wb') as fp: + for arg in sys.argv[3:]: + with open(arg, 'rb') as infp: + fp.write(infp.read()) +sys.exit(0) +""") + +test.write('SConstruct', """ +DefaultEnvironment(tools=[]) +env = Environment(tools=[], + PYTHON = r'%(_python_)s', + SLEEP_CAT = r'sleep_cat.py', + CATCOM = '$PYTHON $SLEEP_CAT $SECONDS $TARGET $SOURCES', + SECONDS = ARGUMENTS.get('SLEEP', '0')) +f1 = env.Command('f1.out', 'f1.in', '$CATCOM') +f2 = env.Command('f2.out', 'f2.in', '$CATCOM') +f3 = env.Command('f3.out', 'f3.in', '$CATCOM') +f4 = env.Command('f4.out', 'f4.in', '$CATCOM') +env.Command('output', [f1, f2, f3, f4], '$CATCOM') +""" % locals()) + +test.write('f1.in', "f1.in\n") +test.write('f2.in', "f2.in\n") +test.write('f3.in', "f3.in\n") +test.write('f4.in', "f4.in\n") + +expected_targets = ['f1.out', 'f2.out', 'f3.out', 'f4.out', 'output', '.'] + +# Before anything else, make sure we get valid --debug=timestamp results +# when just running the help option. +test.run(arguments = "-h --debug=timestamp") + + + +def num(s, match): + return float(re.search(match, s).group(1)) + +def within_tolerance(expected, actual, tolerance): + return abs((expected-actual)/actual) <= tolerance + +def get_total_time(stdout): + return num(stdout, r'Total build time: (\d+\.\d+) seconds') + +def get_sconscript_time(stdout): + return num(stdout, r'Total SConscript file execution time: (\d+\.\d+) seconds') + +def get_scons_time(stdout): + return num(stdout, r'Total SCons execution time: (\d+\.\d+) seconds') + +def get_command_time(stdout): + return num(stdout, r'Total command execution time: (\d+\.\d+) seconds') + + +# Try to make our results a little more accurate and repeatable by +# measuring Python overhead executing a minimal file, and reading the +# scons.py script itself from disk so that it's already been cached. +test.write('pass.py', "pass\n") +test.read(test.program) + +start_time = time.time() +test.run(program=TestSCons.python, arguments=test.workpath('pass.py')) +overhead = time.time() - start_time + + + +start_time = time.time() +test.run(arguments = "-j1 --debug=timestamp . SLEEP=0") +complete_time = time.time() - start_time + + + +expected_total_time = complete_time - overhead + +def get_times_and_targets(pattern): + targets = [] + times = [] + for target,time in re.findall(pattern, test.stdout()): + targets.append(target) + times.append(float(time)) + return targets, times + +duration_targets, durations = get_times_and_targets(r'Command execution time: (.*): (\d+\.\d+) seconds') +start_targets, start_times = get_times_and_targets(r'Command execution start time: (.*): (\d+\.\d+) seconds') +stop_targets, stop_times = get_times_and_targets(r'Command execution stop time: (.*): (\d+\.\d+) seconds') + +expected_command_time = 0.0 +for t in durations: + expected_command_time += t + + +stdout = test.stdout() + +total_time = get_total_time(stdout) +sconscript_time = get_sconscript_time(stdout) +scons_time = get_scons_time(stdout) +command_time = get_command_time(stdout) + +failures = [] +warnings = [] + + +def check_targets(targets): + if targets != expected_targets: + failures.append("""\ + Scons reported the targets of timing information as %(targets)s, + but the actual targets should have been %(expected_targets)s. + """.format(targets=targets, expected_targets=expected_targets)) + +check_targets(duration_targets) +check_targets(start_targets) +check_targets(stop_targets) + +if not within_tolerance(expected_command_time, command_time, 0.01): + failures.append("""\ +SCons -j1 reported a total command execution time of %(command_time)s, +but command execution times really totalled %(expected_command_time)s, +outside of the 1%% tolerance. +""" % locals()) + +added_times = sconscript_time+scons_time+command_time +if not within_tolerance(total_time, added_times, 0.01): + failures.append("""\ +SCons -j1 reported a total build time of %(total_time)s, +but the various execution times actually totalled %(added_times)s, +outside of the 1%% tolerance. +""" % locals()) + +if not within_tolerance(total_time, expected_total_time, 0.20): + # This tolerance check seems empirically to work fine if there's + # a light load on the system, but on a heavily loaded system the + # timings get screwy and it can fail frequently. Some obvious + # attempts to work around the problem didn't, so just treat it as + # a warning for now. + warnings.append("""\ +Warning: SCons -j1 reported total build time of %(total_time)s, +but the actual measured build time was %(expected_total_time)s +(end-to-end time of %(complete_time)s less Python overhead of %(overhead)s), +outside of the 15%% tolerance. +""" % locals()) + +if failures or warnings: + print('\n'.join([test.stdout()] + failures + warnings)) +if failures: + test.fail_test(1) + +test.run(arguments = "--debug=timestamp . SLEEP=0") + +command_time = get_command_time(test.stdout()) +if command_time != 0.0: + print("Up-to-date run received non-zero command time of %s" % command_time) + test.fail_test() + + + +test.run(arguments = "-c") + +test.run(arguments = "-j4 --debug=timestamp . SLEEP=1") + + + +stdout = test.stdout() + +total_time = get_total_time(stdout) +sconscript_time = get_sconscript_time(stdout) +scons_time = get_scons_time(stdout) +command_time = get_command_time(stdout) + +failures = [] + +added_times = sconscript_time+scons_time+command_time +if not within_tolerance(total_time, added_times, 0.01): + failures.append("""\ +SCons -j4 reported a total build time of %(total_time)s, +but the various execution times actually totalled %(added_times)s, +outside of the 1%% tolerance. +""" % locals()) + +if failures: + print('\n'.join([test.stdout()] + failures)) + test.fail_test(1) + +test.run(arguments = "-j4 --debug=timestamp . SLEEP=1") + +command_time = get_command_time(test.stdout()) +if command_time != 0.0: + print("Up-to-date run received non-zero command time of %s" % command_time) + test.fail_test() + + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: \ No newline at end of file -- cgit v0.12 From 0d2a82fe128c403bf4fa4f5deec23ead8fd24a91 Mon Sep 17 00:00:00 2001 From: Edoardo Bezzeccheri Date: Tue, 1 Oct 2019 13:47:32 +0200 Subject: Added debug option "timestamp", implementation --- src/engine/SCons/Script/Main.py | 10 +++++++++- src/engine/SCons/Script/SConsOptions.py | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py index acc8678..e5b7f94 100644 --- a/src/engine/SCons/Script/Main.py +++ b/src/engine/SCons/Script/Main.py @@ -75,6 +75,7 @@ print_objects = 0 print_memoizer = 0 print_stacktrace = 0 print_time = 0 +print_timestamp = 0 sconscript_time = 0 cumulative_command_time = 0 exit_status = 0 # final exit status, assume success by default @@ -209,7 +210,11 @@ class BuildTask(SCons.Taskmaster.OutOfDateTask): finish_time = time.time() last_command_end = finish_time cumulative_command_time = cumulative_command_time+finish_time-start_time + if print_timestamp: + sys.stdout.write("Command execution start time: %s: %f seconds\n"%(str(self.node), start_time)) sys.stdout.write("Command execution time: %s: %f seconds\n"%(str(self.node), finish_time-start_time)) + if print_timestamp: + sys.stdout.write("Command execution stop time: %s: %f seconds\n"%(str(self.node), finish_time)) def do_failed(self, status=2): _BuildFailures.append(self.exception[1]) @@ -636,7 +641,7 @@ def _SConstruct_exists(dirname='', repositories=[], filelist=None): return None def _set_debug_values(options): - global print_memoizer, print_objects, print_stacktrace, print_time + global print_memoizer, print_objects, print_stacktrace, print_time, print_timestamp debug_values = options.debug @@ -674,6 +679,9 @@ def _set_debug_values(options): options.tree_printers.append(TreePrinter(status=True)) if "time" in debug_values: print_time = 1 + if "timestamp" in debug_values: + print_time = 1 + print_timestamp = 1 if "tree" in debug_values: options.tree_printers.append(TreePrinter()) if "prepare" in debug_values: diff --git a/src/engine/SCons/Script/SConsOptions.py b/src/engine/SCons/Script/SConsOptions.py index add1150..6baccc3 100644 --- a/src/engine/SCons/Script/SConsOptions.py +++ b/src/engine/SCons/Script/SConsOptions.py @@ -622,7 +622,7 @@ def Parser(version): debug_options = ["count", "duplicate", "explain", "findlibs", "includes", "memoizer", "memory", "objects", "pdb", "prepare", "presub", "stacktrace", - "time"] + "time", "timestamp"] def opt_debug(option, opt, value__, parser, debug_options=debug_options, -- cgit v0.12 From dee0266dd236dd1aa1ff1298f45c99d034d565c9 Mon Sep 17 00:00:00 2001 From: Edoardo Bezzeccheri Date: Tue, 1 Oct 2019 15:00:07 +0200 Subject: Added debug option "timestamp", documentation --- doc/man/scons.xml | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index 9af3f3e..7bd0ce8 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -890,9 +890,43 @@ since multiple build commands and intervening SCons processing should take place in parallel.) - + + + --debug=timestamp + + Prints additional 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 +(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 absolute start and end wall-clock time spent executing those build commands + + + The time spent processing each file passed to the SConscript() function + + + + + --diskcheck=types -- cgit v0.12 From 24bb5363c588cca55826f4da37752a79943728a8 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Tue, 1 Oct 2019 07:18:31 -0600 Subject: Add doc for *EMITTER consvars [ci skip] Three *EMITTER construction variables had documentation of "TODO". A fourth, LDMODULEEMITTER, was not mentioned at all. Signed-off-by: Mats Wichmann --- src/engine/SCons/Tool/__init__.xml | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/engine/SCons/Tool/__init__.xml b/src/engine/SCons/Tool/__init__.xml index 69cc597..b6e5a43 100644 --- a/src/engine/SCons/Tool/__init__.xml +++ b/src/engine/SCons/Tool/__init__.xml @@ -468,7 +468,7 @@ as C++ files. Used to override &cv-link-SHLIBVERSION;/&cv-link-LDMODULEVERSION; when generating versioned import library for a shared library/loadable module. If undefined, the &cv-link-SHLIBVERSION;/&cv-link-LDMODULEVERSION; is used to -determine the version of versioned import library. +determine the version of versioned import library. @@ -476,7 +476,10 @@ determine the version of versioned import library. -TODO +Contains the emitter specification for the +&b-link-StaticLibrary; builder. +The manpage section "Builder Objects" contains +general information on specifying emitters. @@ -494,10 +497,24 @@ format as &cv-link-SHLIBVERSION;. + + + +Contains the emitter specification for the +&b-link-LoadableModule; builder. +The manpage section "Builder Objects" contains +general information on specifying emitters. + + + + -TODO +Contains the emitter specification for the +&b-link-SharedLibrary; builder. +The manpage section "Builder Objects" contains +general information on specifying emitters. @@ -505,7 +522,10 @@ TODO -TODO +Contains the emitter specification for the +&b-link-Program; builder. +The manpage section "Builder Objects" contains +general information on specifying emitters. @@ -514,7 +534,7 @@ TODO When this construction variable is defined, a versioned shared library -is created by &b-link-SharedLibrary; builder. This activates the +is created by the &b-link-SharedLibrary; builder. This activates the &cv-link-_SHLIBVERSIONFLAGS; and thus modifies the &cv-link-SHLINKCOM; as required, adds the version number to the library name, and creates the symlinks that are needed. &cv-link-SHLIBVERSION; versions should exist as alpha-numeric, -- cgit v0.12 From 16a9225e26489ab611af03f022eafe6d264bfcc4 Mon Sep 17 00:00:00 2001 From: jw0k Date: Fri, 4 Oct 2019 17:14:47 +0200 Subject: fix CheckFunc detection code for MSVC --- src/engine/SCons/Conftest.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/engine/SCons/Conftest.py b/src/engine/SCons/Conftest.py index 1163aa3..c24adf8 100644 --- a/src/engine/SCons/Conftest.py +++ b/src/engine/SCons/Conftest.py @@ -290,6 +290,10 @@ char %s();""" % function_name #include %(hdr)s +#if _MSC_VER && !__INTEL_COMPILER + #pragma function(%(name)s) +#endif + int main(void) { #if defined (__stub_%(name)s) || defined (__stub___%(name)s) fail fail fail -- cgit v0.12 From 68b8d043051761e72b304073aeac002abc1ad732 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sat, 5 Oct 2019 09:14:32 -0600 Subject: fix typo: missing quote in a manpage example [ci skip] Signed-off-by: Mats Wichmann --- doc/man/scons.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index 9af3f3e..9065f25 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -4572,7 +4572,7 @@ incl = Dir('include') f = incl.File('header.h') # Get a Node for a subdirectory within a directory -dist = Dir('project-3.2.1) +dist = Dir('project-3.2.1') src = dist.Dir('src') # Get a Node for a file in the same directory -- cgit v0.12 From 5f22daa0bd88e39071860b54678f8c516badf1f1 Mon Sep 17 00:00:00 2001 From: Jacek Kuczera Date: Sun, 6 Oct 2019 21:57:32 +0200 Subject: test whether CheckFunc properly detects memmove --- test/Configure/config-h.py | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/test/Configure/config-h.py b/test/Configure/config-h.py index a5c1998..405f259 100644 --- a/test/Configure/config-h.py +++ b/test/Configure/config-h.py @@ -46,25 +46,27 @@ env.AppendENVPath('PATH', os.environ['PATH']) conf = Configure(env, config_h = 'config.h') r1 = conf.CheckFunc('printf') r2 = conf.CheckFunc('noFunctionCall') -r3 = conf.CheckType('int') -r4 = conf.CheckType('noType') -r5 = conf.CheckCHeader('stdio.h', '<>') -r6 = conf.CheckCHeader('hopefullynoc-header.h') -r7 = conf.CheckCXXHeader('vector', '<>') -r8 = conf.CheckCXXHeader('hopefullynocxx-header.h') +r3 = conf.CheckFunc('memmove') +r4 = conf.CheckType('int') +r5 = conf.CheckType('noType') +r6 = conf.CheckCHeader('stdio.h', '<>') +r7 = conf.CheckCHeader('hopefullynoc-header.h') +r8 = conf.CheckCXXHeader('vector', '<>') +r9 = conf.CheckCXXHeader('hopefullynocxx-header.h') env = conf.Finish() conf = Configure(env, config_h = 'config.h') -r9 = conf.CheckLib('%(lib)s', 'sin') -r10 = conf.CheckLib('hopefullynolib', 'sin') -r11 = conf.CheckLibWithHeader('%(lib)s', 'math.h', 'c') -r12 = conf.CheckLibWithHeader('%(lib)s', 'hopefullynoheader2.h', 'c') -r13 = conf.CheckLibWithHeader('hopefullynolib2', 'math.h', 'c') +r10 = conf.CheckLib('%(lib)s', 'sin') +r11 = conf.CheckLib('hopefullynolib', 'sin') +r12 = conf.CheckLibWithHeader('%(lib)s', 'math.h', 'c') +r13 = conf.CheckLibWithHeader('%(lib)s', 'hopefullynoheader2.h', 'c') +r14 = conf.CheckLibWithHeader('hopefullynolib2', 'math.h', 'c') env = conf.Finish() """ % locals()) expected_read_str = """\ Checking for C function printf()... yes Checking for C function noFunctionCall()... no +Checking for C function memmove()... yes Checking for C type int... yes Checking for C type noType... no Checking for C header file stdio.h... yes @@ -96,6 +98,9 @@ expected_config_h = ("""\ /* Define to 1 if the system has the function `noFunctionCall'. */ /* #undef HAVE_NOFUNCTIONCALL */ +/* Define to 1 if the system has the function `memmove'. */ +#define HAVE_MEMMOVE 1 + /* Define to 1 if the system has the type `int'. */ #define HAVE_INT 1 -- cgit v0.12 From 671aed7eb090d1501a4097b34909db7ec336e68e Mon Sep 17 00:00:00 2001 From: Jacek Kuczera Date: Sun, 6 Oct 2019 22:11:54 +0200 Subject: describe CheckFunc fix --- src/CHANGES.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 4078669..96c8643 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -18,6 +18,9 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Turn previously deprecated debug options into failures: --debug=tree, --debug=dtree, --debug=stree, --debug=nomemoizer. + From Jacek Kuczera: + - Fix CheckFunc detection code for Visual 2019. Some functions + (e.g. memmove) were incorrectly recognized as not available. RELEASE 3.1.1 - Mon, 07 Aug 2019 20:09:12 -0500 -- cgit v0.12 From 2a72809ab9d83d999caf6a9f7b4618dbd00920f9 Mon Sep 17 00:00:00 2001 From: Edoardo Bezzeccheri Date: Wed, 9 Oct 2019 10:37:43 +0200 Subject: Added debug option "timestamp", fix shadowing internal fnc --- test/option/debug-timestamp.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/option/debug-timestamp.py b/test/option/debug-timestamp.py index 3e7c682..458974e 100644 --- a/test/option/debug-timestamp.py +++ b/test/option/debug-timestamp.py @@ -112,9 +112,9 @@ expected_total_time = complete_time - overhead def get_times_and_targets(pattern): targets = [] times = [] - for target,time in re.findall(pattern, test.stdout()): + for target, target_time in re.findall(pattern, test.stdout()): targets.append(target) - times.append(float(time)) + times.append(float(target_time)) return targets, times duration_targets, durations = get_times_and_targets(r'Command execution time: (.*): (\d+\.\d+) seconds') -- cgit v0.12 From ea6b79d2374143fd53f3e94d6026365b636c49af Mon Sep 17 00:00:00 2001 From: Edoardo Bezzeccheri Date: Wed, 9 Oct 2019 10:39:56 +0200 Subject: Added debug option "timestamp", rename test file --- test/option/debug-action-timestamps.py | 234 +++++++++++++++++++++++++++++++++ test/option/debug-timestamp.py | 234 --------------------------------- 2 files changed, 234 insertions(+), 234 deletions(-) create mode 100644 test/option/debug-action-timestamps.py delete mode 100644 test/option/debug-timestamp.py diff --git a/test/option/debug-action-timestamps.py b/test/option/debug-action-timestamps.py new file mode 100644 index 0000000..458974e --- /dev/null +++ b/test/option/debug-action-timestamps.py @@ -0,0 +1,234 @@ +#!/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. +from __future__ import division, print_function + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import TestSCons +import re +import time + +_python_ = TestSCons._python_ + +test = TestSCons.TestSCons() + +test.write('sleep_cat.py', """\ +import sys +import time +time.sleep(int(sys.argv[1])) +with open(sys.argv[2], 'wb') as fp: + for arg in sys.argv[3:]: + with open(arg, 'rb') as infp: + fp.write(infp.read()) +sys.exit(0) +""") + +test.write('SConstruct', """ +DefaultEnvironment(tools=[]) +env = Environment(tools=[], + PYTHON = r'%(_python_)s', + SLEEP_CAT = r'sleep_cat.py', + CATCOM = '$PYTHON $SLEEP_CAT $SECONDS $TARGET $SOURCES', + SECONDS = ARGUMENTS.get('SLEEP', '0')) +f1 = env.Command('f1.out', 'f1.in', '$CATCOM') +f2 = env.Command('f2.out', 'f2.in', '$CATCOM') +f3 = env.Command('f3.out', 'f3.in', '$CATCOM') +f4 = env.Command('f4.out', 'f4.in', '$CATCOM') +env.Command('output', [f1, f2, f3, f4], '$CATCOM') +""" % locals()) + +test.write('f1.in', "f1.in\n") +test.write('f2.in', "f2.in\n") +test.write('f3.in', "f3.in\n") +test.write('f4.in', "f4.in\n") + +expected_targets = ['f1.out', 'f2.out', 'f3.out', 'f4.out', 'output', '.'] + +# Before anything else, make sure we get valid --debug=timestamp results +# when just running the help option. +test.run(arguments = "-h --debug=timestamp") + + + +def num(s, match): + return float(re.search(match, s).group(1)) + +def within_tolerance(expected, actual, tolerance): + return abs((expected-actual)/actual) <= tolerance + +def get_total_time(stdout): + return num(stdout, r'Total build time: (\d+\.\d+) seconds') + +def get_sconscript_time(stdout): + return num(stdout, r'Total SConscript file execution time: (\d+\.\d+) seconds') + +def get_scons_time(stdout): + return num(stdout, r'Total SCons execution time: (\d+\.\d+) seconds') + +def get_command_time(stdout): + return num(stdout, r'Total command execution time: (\d+\.\d+) seconds') + + +# Try to make our results a little more accurate and repeatable by +# measuring Python overhead executing a minimal file, and reading the +# scons.py script itself from disk so that it's already been cached. +test.write('pass.py', "pass\n") +test.read(test.program) + +start_time = time.time() +test.run(program=TestSCons.python, arguments=test.workpath('pass.py')) +overhead = time.time() - start_time + + + +start_time = time.time() +test.run(arguments = "-j1 --debug=timestamp . SLEEP=0") +complete_time = time.time() - start_time + + + +expected_total_time = complete_time - overhead + +def get_times_and_targets(pattern): + targets = [] + times = [] + for target, target_time in re.findall(pattern, test.stdout()): + targets.append(target) + times.append(float(target_time)) + return targets, times + +duration_targets, durations = get_times_and_targets(r'Command execution time: (.*): (\d+\.\d+) seconds') +start_targets, start_times = get_times_and_targets(r'Command execution start time: (.*): (\d+\.\d+) seconds') +stop_targets, stop_times = get_times_and_targets(r'Command execution stop time: (.*): (\d+\.\d+) seconds') + +expected_command_time = 0.0 +for t in durations: + expected_command_time += t + + +stdout = test.stdout() + +total_time = get_total_time(stdout) +sconscript_time = get_sconscript_time(stdout) +scons_time = get_scons_time(stdout) +command_time = get_command_time(stdout) + +failures = [] +warnings = [] + + +def check_targets(targets): + if targets != expected_targets: + failures.append("""\ + Scons reported the targets of timing information as %(targets)s, + but the actual targets should have been %(expected_targets)s. + """.format(targets=targets, expected_targets=expected_targets)) + +check_targets(duration_targets) +check_targets(start_targets) +check_targets(stop_targets) + +if not within_tolerance(expected_command_time, command_time, 0.01): + failures.append("""\ +SCons -j1 reported a total command execution time of %(command_time)s, +but command execution times really totalled %(expected_command_time)s, +outside of the 1%% tolerance. +""" % locals()) + +added_times = sconscript_time+scons_time+command_time +if not within_tolerance(total_time, added_times, 0.01): + failures.append("""\ +SCons -j1 reported a total build time of %(total_time)s, +but the various execution times actually totalled %(added_times)s, +outside of the 1%% tolerance. +""" % locals()) + +if not within_tolerance(total_time, expected_total_time, 0.20): + # This tolerance check seems empirically to work fine if there's + # a light load on the system, but on a heavily loaded system the + # timings get screwy and it can fail frequently. Some obvious + # attempts to work around the problem didn't, so just treat it as + # a warning for now. + warnings.append("""\ +Warning: SCons -j1 reported total build time of %(total_time)s, +but the actual measured build time was %(expected_total_time)s +(end-to-end time of %(complete_time)s less Python overhead of %(overhead)s), +outside of the 15%% tolerance. +""" % locals()) + +if failures or warnings: + print('\n'.join([test.stdout()] + failures + warnings)) +if failures: + test.fail_test(1) + +test.run(arguments = "--debug=timestamp . SLEEP=0") + +command_time = get_command_time(test.stdout()) +if command_time != 0.0: + print("Up-to-date run received non-zero command time of %s" % command_time) + test.fail_test() + + + +test.run(arguments = "-c") + +test.run(arguments = "-j4 --debug=timestamp . SLEEP=1") + + + +stdout = test.stdout() + +total_time = get_total_time(stdout) +sconscript_time = get_sconscript_time(stdout) +scons_time = get_scons_time(stdout) +command_time = get_command_time(stdout) + +failures = [] + +added_times = sconscript_time+scons_time+command_time +if not within_tolerance(total_time, added_times, 0.01): + failures.append("""\ +SCons -j4 reported a total build time of %(total_time)s, +but the various execution times actually totalled %(added_times)s, +outside of the 1%% tolerance. +""" % locals()) + +if failures: + print('\n'.join([test.stdout()] + failures)) + test.fail_test(1) + +test.run(arguments = "-j4 --debug=timestamp . SLEEP=1") + +command_time = get_command_time(test.stdout()) +if command_time != 0.0: + print("Up-to-date run received non-zero command time of %s" % command_time) + test.fail_test() + + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: \ No newline at end of file diff --git a/test/option/debug-timestamp.py b/test/option/debug-timestamp.py deleted file mode 100644 index 458974e..0000000 --- a/test/option/debug-timestamp.py +++ /dev/null @@ -1,234 +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. -from __future__ import division, print_function - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - -import TestSCons -import re -import time - -_python_ = TestSCons._python_ - -test = TestSCons.TestSCons() - -test.write('sleep_cat.py', """\ -import sys -import time -time.sleep(int(sys.argv[1])) -with open(sys.argv[2], 'wb') as fp: - for arg in sys.argv[3:]: - with open(arg, 'rb') as infp: - fp.write(infp.read()) -sys.exit(0) -""") - -test.write('SConstruct', """ -DefaultEnvironment(tools=[]) -env = Environment(tools=[], - PYTHON = r'%(_python_)s', - SLEEP_CAT = r'sleep_cat.py', - CATCOM = '$PYTHON $SLEEP_CAT $SECONDS $TARGET $SOURCES', - SECONDS = ARGUMENTS.get('SLEEP', '0')) -f1 = env.Command('f1.out', 'f1.in', '$CATCOM') -f2 = env.Command('f2.out', 'f2.in', '$CATCOM') -f3 = env.Command('f3.out', 'f3.in', '$CATCOM') -f4 = env.Command('f4.out', 'f4.in', '$CATCOM') -env.Command('output', [f1, f2, f3, f4], '$CATCOM') -""" % locals()) - -test.write('f1.in', "f1.in\n") -test.write('f2.in', "f2.in\n") -test.write('f3.in', "f3.in\n") -test.write('f4.in', "f4.in\n") - -expected_targets = ['f1.out', 'f2.out', 'f3.out', 'f4.out', 'output', '.'] - -# Before anything else, make sure we get valid --debug=timestamp results -# when just running the help option. -test.run(arguments = "-h --debug=timestamp") - - - -def num(s, match): - return float(re.search(match, s).group(1)) - -def within_tolerance(expected, actual, tolerance): - return abs((expected-actual)/actual) <= tolerance - -def get_total_time(stdout): - return num(stdout, r'Total build time: (\d+\.\d+) seconds') - -def get_sconscript_time(stdout): - return num(stdout, r'Total SConscript file execution time: (\d+\.\d+) seconds') - -def get_scons_time(stdout): - return num(stdout, r'Total SCons execution time: (\d+\.\d+) seconds') - -def get_command_time(stdout): - return num(stdout, r'Total command execution time: (\d+\.\d+) seconds') - - -# Try to make our results a little more accurate and repeatable by -# measuring Python overhead executing a minimal file, and reading the -# scons.py script itself from disk so that it's already been cached. -test.write('pass.py', "pass\n") -test.read(test.program) - -start_time = time.time() -test.run(program=TestSCons.python, arguments=test.workpath('pass.py')) -overhead = time.time() - start_time - - - -start_time = time.time() -test.run(arguments = "-j1 --debug=timestamp . SLEEP=0") -complete_time = time.time() - start_time - - - -expected_total_time = complete_time - overhead - -def get_times_and_targets(pattern): - targets = [] - times = [] - for target, target_time in re.findall(pattern, test.stdout()): - targets.append(target) - times.append(float(target_time)) - return targets, times - -duration_targets, durations = get_times_and_targets(r'Command execution time: (.*): (\d+\.\d+) seconds') -start_targets, start_times = get_times_and_targets(r'Command execution start time: (.*): (\d+\.\d+) seconds') -stop_targets, stop_times = get_times_and_targets(r'Command execution stop time: (.*): (\d+\.\d+) seconds') - -expected_command_time = 0.0 -for t in durations: - expected_command_time += t - - -stdout = test.stdout() - -total_time = get_total_time(stdout) -sconscript_time = get_sconscript_time(stdout) -scons_time = get_scons_time(stdout) -command_time = get_command_time(stdout) - -failures = [] -warnings = [] - - -def check_targets(targets): - if targets != expected_targets: - failures.append("""\ - Scons reported the targets of timing information as %(targets)s, - but the actual targets should have been %(expected_targets)s. - """.format(targets=targets, expected_targets=expected_targets)) - -check_targets(duration_targets) -check_targets(start_targets) -check_targets(stop_targets) - -if not within_tolerance(expected_command_time, command_time, 0.01): - failures.append("""\ -SCons -j1 reported a total command execution time of %(command_time)s, -but command execution times really totalled %(expected_command_time)s, -outside of the 1%% tolerance. -""" % locals()) - -added_times = sconscript_time+scons_time+command_time -if not within_tolerance(total_time, added_times, 0.01): - failures.append("""\ -SCons -j1 reported a total build time of %(total_time)s, -but the various execution times actually totalled %(added_times)s, -outside of the 1%% tolerance. -""" % locals()) - -if not within_tolerance(total_time, expected_total_time, 0.20): - # This tolerance check seems empirically to work fine if there's - # a light load on the system, but on a heavily loaded system the - # timings get screwy and it can fail frequently. Some obvious - # attempts to work around the problem didn't, so just treat it as - # a warning for now. - warnings.append("""\ -Warning: SCons -j1 reported total build time of %(total_time)s, -but the actual measured build time was %(expected_total_time)s -(end-to-end time of %(complete_time)s less Python overhead of %(overhead)s), -outside of the 15%% tolerance. -""" % locals()) - -if failures or warnings: - print('\n'.join([test.stdout()] + failures + warnings)) -if failures: - test.fail_test(1) - -test.run(arguments = "--debug=timestamp . SLEEP=0") - -command_time = get_command_time(test.stdout()) -if command_time != 0.0: - print("Up-to-date run received non-zero command time of %s" % command_time) - test.fail_test() - - - -test.run(arguments = "-c") - -test.run(arguments = "-j4 --debug=timestamp . SLEEP=1") - - - -stdout = test.stdout() - -total_time = get_total_time(stdout) -sconscript_time = get_sconscript_time(stdout) -scons_time = get_scons_time(stdout) -command_time = get_command_time(stdout) - -failures = [] - -added_times = sconscript_time+scons_time+command_time -if not within_tolerance(total_time, added_times, 0.01): - failures.append("""\ -SCons -j4 reported a total build time of %(total_time)s, -but the various execution times actually totalled %(added_times)s, -outside of the 1%% tolerance. -""" % locals()) - -if failures: - print('\n'.join([test.stdout()] + failures)) - test.fail_test(1) - -test.run(arguments = "-j4 --debug=timestamp . SLEEP=1") - -command_time = get_command_time(test.stdout()) -if command_time != 0.0: - print("Up-to-date run received non-zero command time of %s" % command_time) - test.fail_test() - - -test.pass_test() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: \ No newline at end of file -- cgit v0.12 From e00c5893fa11a155286521f11fac82a0eb9c8d15 Mon Sep 17 00:00:00 2001 From: Edoardo Bezzeccheri Date: Wed, 9 Oct 2019 10:54:24 +0200 Subject: Added debug option "timestamp", changed option "timestamp" to "action_timestamps" As per PR review --- doc/man/scons.xml | 2 +- src/CHANGES.txt | 2 +- src/engine/SCons/Script/Main.py | 12 ++++++------ src/engine/SCons/Script/SConsOptions.py | 2 +- test/option/debug-action-timestamps.py | 12 ++++++------ 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index 7bd0ce8..78f71e7 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -894,7 +894,7 @@ should take place in parallel.) - --debug=timestamp + --debug=action_timestamps Prints additional time profiling information: diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 3ea2249..f1f6e53 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -19,7 +19,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER --debug=tree, --debug=dtree, --debug=stree, --debug=nomemoizer. From Edoardo Bezzeccheri - - Added debug option "timestamp" which outputs to stdout the absolute start and end time for each target. + - Added debug option "action_timestamps" which outputs to stdout the absolute start and end time for each target. RELEASE 3.1.1 - Mon, 07 Aug 2019 20:09:12 -0500 diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py index e5b7f94..58dbf64 100644 --- a/src/engine/SCons/Script/Main.py +++ b/src/engine/SCons/Script/Main.py @@ -75,7 +75,7 @@ print_objects = 0 print_memoizer = 0 print_stacktrace = 0 print_time = 0 -print_timestamp = 0 +print_action_timestamps = 0 sconscript_time = 0 cumulative_command_time = 0 exit_status = 0 # final exit status, assume success by default @@ -210,10 +210,10 @@ class BuildTask(SCons.Taskmaster.OutOfDateTask): finish_time = time.time() last_command_end = finish_time cumulative_command_time = cumulative_command_time+finish_time-start_time - if print_timestamp: + if print_action_timestamps: sys.stdout.write("Command execution start time: %s: %f seconds\n"%(str(self.node), start_time)) sys.stdout.write("Command execution time: %s: %f seconds\n"%(str(self.node), finish_time-start_time)) - if print_timestamp: + if print_action_timestamps: sys.stdout.write("Command execution stop time: %s: %f seconds\n"%(str(self.node), finish_time)) def do_failed(self, status=2): @@ -641,7 +641,7 @@ def _SConstruct_exists(dirname='', repositories=[], filelist=None): return None def _set_debug_values(options): - global print_memoizer, print_objects, print_stacktrace, print_time, print_timestamp + global print_memoizer, print_objects, print_stacktrace, print_time, print_action_timestamps debug_values = options.debug @@ -679,9 +679,9 @@ def _set_debug_values(options): options.tree_printers.append(TreePrinter(status=True)) if "time" in debug_values: print_time = 1 - if "timestamp" in debug_values: + if "action_timestamps" in debug_values: print_time = 1 - print_timestamp = 1 + print_action_timestamps = 1 if "tree" in debug_values: options.tree_printers.append(TreePrinter()) if "prepare" in debug_values: diff --git a/src/engine/SCons/Script/SConsOptions.py b/src/engine/SCons/Script/SConsOptions.py index 6baccc3..7b5d523 100644 --- a/src/engine/SCons/Script/SConsOptions.py +++ b/src/engine/SCons/Script/SConsOptions.py @@ -622,7 +622,7 @@ def Parser(version): debug_options = ["count", "duplicate", "explain", "findlibs", "includes", "memoizer", "memory", "objects", "pdb", "prepare", "presub", "stacktrace", - "time", "timestamp"] + "time", "action_timestamps"] def opt_debug(option, opt, value__, parser, debug_options=debug_options, diff --git a/test/option/debug-action-timestamps.py b/test/option/debug-action-timestamps.py index 458974e..c021117 100644 --- a/test/option/debug-action-timestamps.py +++ b/test/option/debug-action-timestamps.py @@ -64,9 +64,9 @@ test.write('f4.in', "f4.in\n") expected_targets = ['f1.out', 'f2.out', 'f3.out', 'f4.out', 'output', '.'] -# Before anything else, make sure we get valid --debug=timestamp results +# Before anything else, make sure we get valid --debug=action_timestamps results # when just running the help option. -test.run(arguments = "-h --debug=timestamp") +test.run(arguments = "-h --debug=action_timestamps") @@ -102,7 +102,7 @@ overhead = time.time() - start_time start_time = time.time() -test.run(arguments = "-j1 --debug=timestamp . SLEEP=0") +test.run(arguments = "-j1 --debug=action_timestamps . SLEEP=0") complete_time = time.time() - start_time @@ -181,7 +181,7 @@ if failures or warnings: if failures: test.fail_test(1) -test.run(arguments = "--debug=timestamp . SLEEP=0") +test.run(arguments = "--debug=action_timestamps . SLEEP=0") command_time = get_command_time(test.stdout()) if command_time != 0.0: @@ -192,7 +192,7 @@ if command_time != 0.0: test.run(arguments = "-c") -test.run(arguments = "-j4 --debug=timestamp . SLEEP=1") +test.run(arguments = "-j4 --debug=action_timestamps . SLEEP=1") @@ -217,7 +217,7 @@ if failures: print('\n'.join([test.stdout()] + failures)) test.fail_test(1) -test.run(arguments = "-j4 --debug=timestamp . SLEEP=1") +test.run(arguments = "-j4 --debug=action_timestamps . SLEEP=1") command_time = get_command_time(test.stdout()) if command_time != 0.0: -- cgit v0.12 From e3d197bdd67088b163b66da9ffa985992c36d184 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Wed, 9 Oct 2019 18:55:41 -0600 Subject: [WIP] enable persistent caching of vcvars on win32 Setting env var SCONS_CACHE_MSVC_CONFIG enables a filesystem cache of vcvars results, making them persistent across scons runs. On test runs (notably our CI system) this helps a lot; in normal usage where you run one scons invocation at a time instead of many hundreds in a test run it will make things a little more responsive (esp on vs2019) but the impact will be much smaller. Signed-off-by: Mats Wichmann --- .appveyor.yml | 1 + src/CHANGES.txt | 4 ++ src/engine/SCons/Tool/MSCommon/common.py | 35 +++++++++++-- src/engine/SCons/Tool/MSCommon/sdk.py | 30 +++++------ src/engine/SCons/Tool/MSCommon/vc.py | 90 +++++++++++++++++++------------- src/engine/SCons/Tool/MSCommon/vs.py | 4 +- 6 files changed, 107 insertions(+), 57 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index a18f295..09cd996 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -25,6 +25,7 @@ install: - cmd: set STATIC_DEPS=true & C:\\%WINPYTHON%\\python.exe -m pip install -U --progress-bar off lxml # install 3rd party tools to test with - cmd: choco install --allow-empty-checksums dmd ldc swig vswhere xsltproc winflexbison + - cmd: set SCONS_CACHE_MSVC_CONFIG=true - cmd: set ### LINUX ### diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 015622e..c45e86d 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -17,6 +17,10 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER the index from find() was not used. - Turn previously deprecated debug options into failures: --debug=tree, --debug=dtree, --debug=stree, --debug=nomemoizer. + - If SCONS_CACHE_MSVC_CONFIG env var is set, scons will cache the + results of past calls to vcvarsall.bat to a file; integrates with + existing memoizing of such vars. On vs2019 saves 5+ seconds per + scons invocation, which really helps test suite runs. From Jacek Kuczera: - Fix CheckFunc detection code for Visual 2019. Some functions diff --git a/src/engine/SCons/Tool/MSCommon/common.py b/src/engine/SCons/Tool/MSCommon/common.py index c3ba8e5..0a7e0ef 100644 --- a/src/engine/SCons/Tool/MSCommon/common.py +++ b/src/engine/SCons/Tool/MSCommon/common.py @@ -28,6 +28,7 @@ from __future__ import print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import copy +import json import os import subprocess import re @@ -44,12 +45,39 @@ elif LOGFILE: except ImportError: debug = lambda message: open(LOGFILE, 'a').write(message + '\n') else: - logging.basicConfig(filename=LOGFILE, level=logging.DEBUG) + logging.basicConfig( + format='%(relativeCreated)05dms:pid%(process)05d:MSCommon/%(filename)s:%(message)s', + filename=LOGFILE, + level=logging.DEBUG) debug = logging.getLogger(name=__name__).debug else: debug = lambda x: None +CONFIG_CACHE = os.environ.get('SCONS_CACHE_MSVC_CONFIG', None) +CONFIG_FILE = os.path.join(os.path.expanduser('~'), '.scons_msvc_cache') + + +def read_script_env_cache(): + """ fetch cached env vars if requested, else return empty dict """ + envcache = {} + if CONFIG_CACHE: + try: + with open(CONFIG_FILE, 'r') as f: + envcache = json.load(f) + except FileNotFoundError: + pass + return envcache + + +def write_script_env_cache(cache): + """ write out cach of env vars if requested """ + if CONFIG_CACHE: + with open(CONFIG_FILE, 'w') as f: + #TODO: clean up if it fails + json.dump(cache, f, indent=2) + + _is_win64 = None def is_win64(): @@ -207,14 +235,15 @@ def get_output(vcbat, args = None, env = None): output = stdout.decode("mbcs") return output -def parse_output(output, keep=("INCLUDE", "LIB", "LIBPATH", "PATH", 'VSCMD_ARG_app_plat')): +KEEPLIST = ("INCLUDE", "LIB", "LIBPATH", "PATH", 'VSCMD_ARG_app_plat') +def parse_output(output, keep=KEEPLIST): """ Parse output from running visual c++/studios vcvarsall.bat and running set To capture the values listed in keep """ # dkeep is a dict associating key: path_list, where key is one item from - # keep, and pat_list the associated list of paths + # keep, and path_list the associated list of paths dkeep = dict([(i, []) for i in keep]) # rdk will keep the regex to match the .bat file output line starts diff --git a/src/engine/SCons/Tool/MSCommon/sdk.py b/src/engine/SCons/Tool/MSCommon/sdk.py index ad57865..281c1e3 100644 --- a/src/engine/SCons/Tool/MSCommon/sdk.py +++ b/src/engine/SCons/Tool/MSCommon/sdk.py @@ -118,11 +118,11 @@ class SDKDefinition(object): if (host_arch != target_arch): arch_string='%s_%s'%(host_arch,target_arch) - debug("sdk.py: get_sdk_vc_script():arch_string:%s host_arch:%s target_arch:%s"%(arch_string, + debug("get_sdk_vc_script():arch_string:%s host_arch:%s target_arch:%s"%(arch_string, host_arch, target_arch)) file=self.vc_setup_scripts.get(arch_string,None) - debug("sdk.py: get_sdk_vc_script():file:%s"%file) + debug("get_sdk_vc_script():file:%s"%file) return file class WindowsSDK(SDKDefinition): @@ -286,14 +286,14 @@ InstalledSDKMap = None def get_installed_sdks(): global InstalledSDKList global InstalledSDKMap - debug('sdk.py:get_installed_sdks()') + debug('get_installed_sdks()') if InstalledSDKList is None: InstalledSDKList = [] InstalledSDKMap = {} for sdk in SupportedSDKList: - debug('MSCommon/sdk.py: trying to find SDK %s' % sdk.version) + debug('trying to find SDK %s' % sdk.version) if sdk.get_sdk_dir(): - debug('MSCommon/sdk.py:found SDK %s' % sdk.version) + debug('found SDK %s' % sdk.version) InstalledSDKList.append(sdk) InstalledSDKMap[sdk.version] = sdk return InstalledSDKList @@ -346,13 +346,13 @@ def get_default_sdk(): return InstalledSDKList[0] def mssdk_setup_env(env): - debug('sdk.py:mssdk_setup_env()') + debug('mssdk_setup_env()') if 'MSSDK_DIR' in env: sdk_dir = env['MSSDK_DIR'] if sdk_dir is None: return sdk_dir = env.subst(sdk_dir) - debug('sdk.py:mssdk_setup_env: Using MSSDK_DIR:{}'.format(sdk_dir)) + debug('mssdk_setup_env: Using MSSDK_DIR:{}'.format(sdk_dir)) elif 'MSSDK_VERSION' in env: sdk_version = env['MSSDK_VERSION'] if sdk_version is None: @@ -364,22 +364,22 @@ def mssdk_setup_env(env): msg = "SDK version %s is not installed" % sdk_version raise SCons.Errors.UserError(msg) sdk_dir = mssdk.get_sdk_dir() - debug('sdk.py:mssdk_setup_env: Using MSSDK_VERSION:%s'%sdk_dir) + debug('mssdk_setup_env: Using MSSDK_VERSION:%s'%sdk_dir) elif 'MSVS_VERSION' in env: msvs_version = env['MSVS_VERSION'] - debug('sdk.py:mssdk_setup_env:Getting MSVS_VERSION from env:%s'%msvs_version) + debug('mssdk_setup_env:Getting MSVS_VERSION from env:%s'%msvs_version) if msvs_version is None: - debug('sdk.py:mssdk_setup_env thinks msvs_version is None') + debug('mssdk_setup_env thinks msvs_version is None') return msvs_version = env.subst(msvs_version) from . import vs msvs = vs.get_vs_by_version(msvs_version) - debug('sdk.py:mssdk_setup_env:msvs is :%s'%msvs) + debug('mssdk_setup_env:msvs is :%s'%msvs) if not msvs: - debug('sdk.py:mssdk_setup_env: no VS version detected, bailingout:%s'%msvs) + debug('mssdk_setup_env: no VS version detected, bailingout:%s'%msvs) return sdk_version = msvs.sdk_version - debug('sdk.py:msvs.sdk_version is %s'%sdk_version) + debug('msvs.sdk_version is %s'%sdk_version) if not sdk_version: return mssdk = get_sdk_by_version(sdk_version) @@ -388,13 +388,13 @@ def mssdk_setup_env(env): if not mssdk: return sdk_dir = mssdk.get_sdk_dir() - debug('sdk.py:mssdk_setup_env: Using MSVS_VERSION:%s'%sdk_dir) + debug('mssdk_setup_env: Using MSVS_VERSION:%s'%sdk_dir) else: mssdk = get_default_sdk() if not mssdk: return sdk_dir = mssdk.get_sdk_dir() - debug('sdk.py:mssdk_setup_env: not using any env values. sdk_dir:%s'%sdk_dir) + debug('mssdk_setup_env: not using any env values. sdk_dir:%s'%sdk_dir) set_sdk_by_directory(env, sdk_dir) diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py index 0e4ef15..019d608 100644 --- a/src/engine/SCons/Tool/MSCommon/vc.py +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -152,7 +152,7 @@ def get_msvc_version_numeric(msvc_version): return ''.join([x for x in msvc_version if x in string_digits + '.']) def get_host_target(env): - debug('vc.py:get_host_target()') + debug('get_host_target()') host_platform = env.get('HOST_ARCH') if not host_platform: @@ -165,7 +165,7 @@ def get_host_target(env): # Retain user requested TARGET_ARCH req_target_platform = env.get('TARGET_ARCH') - debug('vc.py:get_host_target() req_target_platform:%s'%req_target_platform) + debug('get_host_target() req_target_platform:%s'%req_target_platform) if req_target_platform: # If user requested a specific platform then only try that one. @@ -403,7 +403,7 @@ def find_batch_file(env,msvc_version,host_arch,target_arch): if pdir is None: raise NoVersionFound("No version of Visual Studio found") - debug('vc.py: find_batch_file() in {}'.format(pdir)) + debug('find_batch_file() in {}'.format(pdir)) # filter out e.g. "Exp" from the version name msvc_ver_numeric = get_msvc_version_numeric(msvc_version) @@ -423,17 +423,17 @@ def find_batch_file(env,msvc_version,host_arch,target_arch): debug("Not found: %s" % batfilename) batfilename = None - installed_sdks=get_installed_sdks() + installed_sdks = get_installed_sdks() for _sdk in installed_sdks: sdk_bat_file = _sdk.get_sdk_vc_script(host_arch,target_arch) if not sdk_bat_file: - debug("vc.py:find_batch_file() not found:%s"%_sdk) + debug("find_batch_file() not found:%s"%_sdk) else: sdk_bat_file_path = os.path.join(pdir,sdk_bat_file) if os.path.exists(sdk_bat_file_path): - debug('vc.py:find_batch_file() sdk_bat_file_path:%s'%sdk_bat_file_path) - return (batfilename,sdk_bat_file_path) - return (batfilename,None) + debug('find_batch_file() sdk_bat_file_path:%s'%sdk_bat_file_path) + return (batfilename, sdk_bat_file_path) + return (batfilename, None) __INSTALLED_VCS_RUN = None @@ -592,21 +592,37 @@ def reset_installed_vcs(): # env2 = Environment(tools='msvs') # we can greatly improve the speed of the second and subsequent Environment # (or Clone) calls by memoizing the environment variables set by vcvars*.bat. -script_env_stdout_cache = {} +# +# Updated: by 2018, vcvarsall.bat had gotten so expensive it was breaking +# CI builds because the test suite starts scons so many times and the existing +# memo logic only helped with repeated calls within the same scons run; +# with VS2019 it got even slower and an optional cache file 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. + +script_env_cache = None + def script_env(script, args=None): - cache_key = (script, args) - stdout = script_env_stdout_cache.get(cache_key, None) - if stdout is None: + global script_env_cache + + if script_env_cache is None: + script_env_cache = common.read_script_env_cache() + cache_key = "{}--{}".format(script, args) + cache_data = script_env_cache.get(cache_key, None) + if cache_data is None: stdout = common.get_output(script, args) - script_env_stdout_cache[cache_key] = stdout - # Stupid batch files do not set return code: we take a look at the - # beginning of the output for an error message instead - olines = stdout.splitlines() - if olines[0].startswith("The specified configuration type is missing"): - raise BatchFileExecutionError("\n".join(olines[:2])) + # Stupid batch files do not set return code: we take a look at the + # beginning of the output for an error message instead + olines = stdout.splitlines() + if olines[0].startswith("The specified configuration type is missing"): + raise BatchFileExecutionError("\n".join(olines[:2])) - return common.parse_output(stdout) + cache_data = common.parse_output(stdout) + script_env_cache[cache_key] = cache_data + # once we updated cache, give a chance to write out if user wanted + common.write_script_env_cache(script_env_cache) + return cache_data def get_default_version(env): debug('get_default_version()') @@ -635,12 +651,12 @@ def get_default_version(env): debug('installed_vcs:%s' % installed_vcs) if not installed_vcs: #msg = 'No installed VCs' - #debug('msv %s\n' % repr(msg)) + #debug('msv %s' % repr(msg)) #SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, msg) debug('msvc_setup_env: No installed VCs') return None msvc_version = installed_vcs[0] - debug('msvc_setup_env: using default installed MSVC version %s\n' % repr(msvc_version)) + debug('msvc_setup_env: using default installed MSVC version %s' % repr(msvc_version)) return msvc_version @@ -654,12 +670,12 @@ def msvc_setup_env_once(env): msvc_setup_env(env) env["MSVC_SETUP_RUN"] = True -def msvc_find_valid_batch_script(env,version): - debug('vc.py:msvc_find_valid_batch_script()') +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 platforms = get_host_target(env) - debug("vc.py: msvs_find_valid_batch_script(): host_platform %s, target_platform %s req_target_platform:%s" % platforms) + 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] @@ -683,7 +699,7 @@ def msvc_find_valid_batch_script(env,version): # Set to current arch. env['TARGET_ARCH']=tp - debug("vc.py:msvc_find_valid_batch_script() trying target_platform:%s"%tp) + debug("msvc_find_valid_batch_script() trying target_platform:%s"%tp) host_target = (host_platform, tp) if not is_host_target_supported(host_target, version): warn_msg = "host, target = %s not supported for MSVC version %s" % \ @@ -701,8 +717,8 @@ 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) - debug('vc.py:msvc_find_valid_batch_script() vc_script:%s sdk_script:%s'%(vc_script,sdk_script)) + (vc_script, 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) debug('Caught exception while looking for batch file (%s)' % msg) @@ -714,29 +730,29 @@ def msvc_find_valid_batch_script(env,version): continue # Try to use the located batch file for this host/target platform combo - debug('vc.py:msvc_find_valid_batch_script() use_script 2 %s, args:%s\n' % (repr(vc_script), arg)) + debug('msvc_find_valid_batch_script() use_script 2 %s, args:%s' % (repr(vc_script), arg)) found = None if vc_script: try: d = script_env(vc_script, args=arg) found = vc_script except BatchFileExecutionError as e: - debug('vc.py:msvc_find_valid_batch_script() use_script 3: failed running VC script %s: %s: Error:%s'%(repr(vc_script),arg,e)) + debug('msvc_find_valid_batch_script() use_script 3: failed running VC script %s: %s: Error:%s'%(repr(vc_script),arg,e)) vc_script=None continue if not vc_script and sdk_script: - debug('vc.py: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('vc.py: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('vc.py:msvc_find_valid_batch_script() use_script 6: Neither VC script nor SDK script found') + debug('msvc_find_valid_batch_script() use_script 6: Neither VC script nor SDK script found') continue - debug("vc.py:msvc_find_valid_batch_script() Found a working script/target: %s/%s"%(repr(found),arg)) + debug("msvc_find_valid_batch_script() Found a working script/target: %s/%s"%(repr(found),arg)) break # We've found a working target_platform, so stop looking # If we cannot find a viable installed compiler, reset the TARGET_ARCH @@ -756,7 +772,7 @@ def msvc_setup_env(env): "compilers most likely not set correctly" SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, warn_msg) return None - debug('msvc_setup_env: using specified MSVC version %s\n' % repr(version)) + debug('msvc_setup_env: using specified MSVC version %s' % repr(version)) # XXX: we set-up both MSVS version for backward # compatibility with the msvs tool @@ -767,11 +783,11 @@ def msvc_setup_env(env): use_script = env.get('MSVC_USE_SCRIPT', True) if SCons.Util.is_String(use_script): - debug('vc.py:msvc_setup_env() use_script 1 %s\n' % repr(use_script)) + debug('msvc_setup_env() use_script 1 %s' % repr(use_script)) d = script_env(use_script) elif use_script: d = msvc_find_valid_batch_script(env,version) - debug('vc.py:msvc_setup_env() use_script 2 %s\n' % d) + debug('msvc_setup_env() use_script 2 %s' % d) if not d: return d else: @@ -782,7 +798,7 @@ def msvc_setup_env(env): return None for k, v in d.items(): - debug('vc.py:msvc_setup_env() env:%s -> %s'%(k,v)) + debug('msvc_setup_env() env:%s -> %s'%(k,v)) env.PrependENVPath(k, v, delete_existing=True) # final check to issue a warning if the compiler is not present diff --git a/src/engine/SCons/Tool/MSCommon/vs.py b/src/engine/SCons/Tool/MSCommon/vs.py index dfca48d..bac35d8 100644 --- a/src/engine/SCons/Tool/MSCommon/vs.py +++ b/src/engine/SCons/Tool/MSCommon/vs.py @@ -465,14 +465,14 @@ def get_vs_by_version(msvs): global InstalledVSMap global SupportedVSMap - debug('vs.py:get_vs_by_version()') + debug('get_vs_by_version()') if msvs not in SupportedVSMap: msg = "Visual Studio version %s is not supported" % repr(msvs) raise SCons.Errors.UserError(msg) get_installed_visual_studios() vs = InstalledVSMap.get(msvs) debug('InstalledVSMap:%s'%InstalledVSMap) - debug('vs.py:get_vs_by_version: found vs:%s'%vs) + debug('get_vs_by_version: found vs:%s'%vs) # Some check like this would let us provide a useful error message # if they try to set a Visual Studio version that's not installed. # However, we also want to be able to run tests (like the unit -- cgit v0.12 From f2a1d6936c961e8d6f059b74b667dd62be211be1 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Thu, 10 Oct 2019 08:04:57 -0600 Subject: [PR 3462] env-var-cache: fix exception to be 2.7 compatible msvc env-var cache-read function use 'except IOError' since 'FileNotFoundError' did not exist on Py2.7/win32. try to handle error if caceh write fails. add SCONS_CACHE_MSVC_CONFIG to manpage. SCONS_CACHE_MSVC_CONFIG can take a pathname to specify the cache file to use, or it can use the default. slightly simplified logging setup - logging is stdlib since py2.3, no need for try block on import. Signed-off-by: Mats Wichmann --- doc/man/scons.xml | 50 +++++++++++++++++++++++--------- src/CHANGES.txt | 9 +++--- src/engine/SCons/Tool/MSCommon/common.py | 45 +++++++++++++++------------- 3 files changed, 67 insertions(+), 37 deletions(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index 9065f25..c406b76 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -7189,22 +7189,45 @@ env.Program('MyApp', ['Foo.cpp', 'Bar.cpp']) ENVIRONMENT + +In general, &scons; is not controlled by environment +variables set shell used to invoke it, leaving it +up to the SConscript file author to import those if desired. +However the following variables are imported by +&scons; itself if set: + + - SCONS_LIB_DIR - -Specifies the directory that contains the SCons Python module directory -(e.g. /home/aroach/scons-src-0.01/src/engine). - - + SCONS_LIB_DIR + +Specifies the directory that contains the &scons; +Python module directory (for example, +/home/aroach/scons-src-0.01/src/engine). + + - SCONSFLAGS - -A string of options that will be used by scons in addition to those passed -on the command line. + SCONSFLAGS + +A string of options that will be used by &scons; +in addition to those passed on the command line. + + - + + SCONS_CACHE_MSVC_CONFIG + +If set, save the shell environment variables generated +in setting up the Microsoft Visual C++ compiler (and/or Build Tools), +to give these settings (expensive to generate) persistence +between runs of &scons;. +If set to a True-like value (1, +true or +True) will cache to a file named +.scons_msvc_cache in the user's home directory. +If set to a pathname, will use that pathname for the cache. + @@ -7220,8 +7243,9 @@ source code. AUTHORS -Originally: Steven Knight <knight@baldmt.com> and Anthony Roach <aroach@electriceyeball.com> -Since 2010: The SCons Development Team <scons-dev@scons.org> +Originally: Steven Knight knight@baldmt.com +and Anthony Roach aroach@electriceyeball.com. +Since 2010: The SCons Development Team scons-dev@scons.org. diff --git a/src/CHANGES.txt b/src/CHANGES.txt index c45e86d..61f31b2 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -17,10 +17,11 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER the index from find() was not used. - Turn previously deprecated debug options into failures: --debug=tree, --debug=dtree, --debug=stree, --debug=nomemoizer. - - If SCONS_CACHE_MSVC_CONFIG env var is set, scons will cache the - results of past calls to vcvarsall.bat to a file; integrates with - existing memoizing of such vars. On vs2019 saves 5+ seconds per - scons invocation, which really helps test suite runs. + - If SCONS_CACHE_MSVC_CONFIG shell environment variable is set, + scons will cache the results of past calls to vcvarsall.bat to + a file; integrates with existing memoizing of such vars. + On vs2019 saves 5+ seconds per scons invocation, which really + helps test suite runs. From Jacek Kuczera: - Fix CheckFunc detection code for Visual 2019. Some functions diff --git a/src/engine/SCons/Tool/MSCommon/common.py b/src/engine/SCons/Tool/MSCommon/common.py index 0a7e0ef..d4997eb 100644 --- a/src/engine/SCons/Tool/MSCommon/common.py +++ b/src/engine/SCons/Tool/MSCommon/common.py @@ -35,47 +35,52 @@ import re import SCons.Util +# internal-use so undocumented: +# set to '-' to print to console, else set to filename to log to LOGFILE = os.environ.get('SCONS_MSCOMMON_DEBUG') if LOGFILE == '-': def debug(message): print(message) elif LOGFILE: - try: - import logging - except ImportError: - debug = lambda message: open(LOGFILE, 'a').write(message + '\n') - else: - logging.basicConfig( - format='%(relativeCreated)05dms:pid%(process)05d:MSCommon/%(filename)s:%(message)s', - filename=LOGFILE, - level=logging.DEBUG) - debug = logging.getLogger(name=__name__).debug + import logging + logging.basicConfig( + format='%(relativeCreated)05dms:pid%(process)05d:MSCommon/%(filename)s:%(message)s', + filename=LOGFILE, + level=logging.DEBUG) + debug = logging.getLogger(name=__name__).debug else: debug = lambda x: None -CONFIG_CACHE = os.environ.get('SCONS_CACHE_MSVC_CONFIG', None) -CONFIG_FILE = os.path.join(os.path.expanduser('~'), '.scons_msvc_cache') - +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 env vars if requested, else return empty dict """ + """ fetch cached msvc env vars if requested, else return empty dict """ envcache = {} if CONFIG_CACHE: try: - with open(CONFIG_FILE, 'r') as f: + with open(CONFIG_CACHE, 'r') as f: envcache = json.load(f) - except FileNotFoundError: + #TODO can use more specific FileNotFoundError when py2 dropped + except IOError: pass return envcache def write_script_env_cache(cache): - """ write out cach of env vars if requested """ + """ write out cache of msvc env vars if requested """ if CONFIG_CACHE: - with open(CONFIG_FILE, 'w') as f: - #TODO: clean up if it fails - json.dump(cache, f, indent=2) + try: + with open(CONFIG_CACHE, 'w') as f: + json.dump(cache, f, indent=2) + except TypeError: + # data can't serialize to json, don't leave partial file + os.remove(CONFIG_CACHE) + except IOError: + # can't write the file, just skip + pass _is_win64 = None -- cgit v0.12 From f39f01c44bfb52fbb09ee57e8d678e03086b9a83 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Thu, 10 Oct 2019 09:52:23 -0600 Subject: [PR 3462] quote appveyor setting of cache val Python 2.7 suffered some problems in subprocess. Signed-off-by: Mats Wichmann --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index 09cd996..ea6ad36 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -25,7 +25,7 @@ install: - cmd: set STATIC_DEPS=true & C:\\%WINPYTHON%\\python.exe -m pip install -U --progress-bar off lxml # install 3rd party tools to test with - cmd: choco install --allow-empty-checksums dmd ldc swig vswhere xsltproc winflexbison - - cmd: set SCONS_CACHE_MSVC_CONFIG=true + - cmd: set SCONS_CACHE_MSVC_CONFIG="true" - cmd: set ### LINUX ### -- cgit v0.12 From 98e5afec3e9727d7ab462aca3fa4681ca3b5b016 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Thu, 10 Oct 2019 19:40:46 -0600 Subject: [PR 3462] python two handle the json reading the cache from the json file got us unicode when running python2, and this broke certain tests when calling subprocess.Popen: TypeError, because all the environment wasn't strings, some was unicode. Signed-off-by: Mats Wichmann --- .appveyor.yml | 2 +- doc/man/scons.xml | 23 +++++++++++++++++------ src/engine/SCons/Tool/MSCommon/common.py | 14 +++++++++++++- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index ea6ad36..09cd996 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -25,7 +25,7 @@ install: - cmd: set STATIC_DEPS=true & C:\\%WINPYTHON%\\python.exe -m pip install -U --progress-bar off lxml # install 3rd party tools to test with - cmd: choco install --allow-empty-checksums dmd ldc swig vswhere xsltproc winflexbison - - cmd: set SCONS_CACHE_MSVC_CONFIG="true" + - cmd: set SCONS_CACHE_MSVC_CONFIG=true - cmd: set ### LINUX ### diff --git a/doc/man/scons.xml b/doc/man/scons.xml index c406b76..e210e76 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -7191,7 +7191,7 @@ env.Program('MyApp', ['Foo.cpp', 'Bar.cpp']) ENVIRONMENT In general, &scons; is not controlled by environment -variables set shell used to invoke it, leaving it +variables set in the shell used to invoke it, leaving it up to the SConscript file author to import those if desired. However the following variables are imported by &scons; itself if set: @@ -7220,13 +7220,24 @@ in addition to those passed on the command line. If set, save the shell environment variables generated in setting up the Microsoft Visual C++ compiler (and/or Build Tools), -to give these settings (expensive to generate) persistence -between runs of &scons;. -If set to a True-like value (1, -true or -True) will cache to a file named +to give these settings, which are expensive to generate, persistence +across &scons; invocations. +If set to a True-like value ("1", +"true" or +"True") will cache to a file named .scons_msvc_cache in the user's home directory. If set to a pathname, will use that pathname for the cache. + +Note: this behavior is not enabled by default because it +might be somewhat fragile: while each major tool version +(e.g. Visual Studio 2018 vs 2019) will get separate +entries, if toolset updates cause a change +to settings within a given release series, &scons; will not +detect this and will fetch old settings. +In case of problems, just remove the cache file. +Use of this option is primarily intended to aid performance +for tightly controlled Continuous Integration setups. + diff --git a/src/engine/SCons/Tool/MSCommon/common.py b/src/engine/SCons/Tool/MSCommon/common.py index d4997eb..eaf57f9 100644 --- a/src/engine/SCons/Tool/MSCommon/common.py +++ b/src/engine/SCons/Tool/MSCommon/common.py @@ -32,6 +32,8 @@ import json import os import subprocess import re +import subprocess +import sys import SCons.Util @@ -56,13 +58,23 @@ 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') +# !@$#@$? Python2 +if sys.version_info[0] == 2: + def str_hook(obj): + return {k.encode('utf-8') if isinstance(k, unicode) else k : + v.encode('utf-8') if isinstance(v, unicode) else v + for k,v in obj} + def read_script_env_cache(): """ fetch cached msvc env vars if requested, else return empty dict """ envcache = {} if CONFIG_CACHE: try: with open(CONFIG_CACHE, 'r') as f: - envcache = json.load(f) + if sys.version_info[0] == 2: + envcache = json.load(f, object_pairs_hook=str_hook) + else: + envcache = json.load(f) #TODO can use more specific FileNotFoundError when py2 dropped except IOError: pass -- cgit v0.12 From 722228995b223b4507ebb686b48f94b9f7a8380c Mon Sep 17 00:00:00 2001 From: Edoardo Bezzeccheri Date: Fri, 11 Oct 2019 16:53:33 +0200 Subject: Added debug option "timestamp", completely overhauled test Started from scratch, removing copy of debug-time.py test. --- test/option/debug-action-timestamps.py | 263 +++++++++------------------------ 1 file changed, 67 insertions(+), 196 deletions(-) diff --git a/test/option/debug-action-timestamps.py b/test/option/debug-action-timestamps.py index c021117..11a4bf5 100644 --- a/test/option/debug-action-timestamps.py +++ b/test/option/debug-action-timestamps.py @@ -26,209 +26,80 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import TestSCons import re -import time _python_ = TestSCons._python_ -test = TestSCons.TestSCons() - -test.write('sleep_cat.py', """\ -import sys -import time -time.sleep(int(sys.argv[1])) -with open(sys.argv[2], 'wb') as fp: - for arg in sys.argv[3:]: - with open(arg, 'rb') as infp: - fp.write(infp.read()) -sys.exit(0) -""") - -test.write('SConstruct', """ +def setup_fixtures(): + test.file_fixture('../fixture/test_main.c', 'main.c') + test.write('SConstruct', """ DefaultEnvironment(tools=[]) -env = Environment(tools=[], - PYTHON = r'%(_python_)s', - SLEEP_CAT = r'sleep_cat.py', - CATCOM = '$PYTHON $SLEEP_CAT $SECONDS $TARGET $SOURCES', - SECONDS = ARGUMENTS.get('SLEEP', '0')) -f1 = env.Command('f1.out', 'f1.in', '$CATCOM') -f2 = env.Command('f2.out', 'f2.in', '$CATCOM') -f3 = env.Command('f3.out', 'f3.in', '$CATCOM') -f4 = env.Command('f4.out', 'f4.in', '$CATCOM') -env.Command('output', [f1, f2, f3, f4], '$CATCOM') -""" % locals()) - -test.write('f1.in', "f1.in\n") -test.write('f2.in', "f2.in\n") -test.write('f3.in', "f3.in\n") -test.write('f4.in', "f4.in\n") - -expected_targets = ['f1.out', 'f2.out', 'f3.out', 'f4.out', 'output', '.'] - -# Before anything else, make sure we get valid --debug=action_timestamps results -# when just running the help option. -test.run(arguments = "-h --debug=action_timestamps") - - - -def num(s, match): - return float(re.search(match, s).group(1)) - -def within_tolerance(expected, actual, tolerance): - return abs((expected-actual)/actual) <= tolerance - -def get_total_time(stdout): - return num(stdout, r'Total build time: (\d+\.\d+) seconds') - -def get_sconscript_time(stdout): - return num(stdout, r'Total SConscript file execution time: (\d+\.\d+) seconds') - -def get_scons_time(stdout): - return num(stdout, r'Total SCons execution time: (\d+\.\d+) seconds') - -def get_command_time(stdout): - return num(stdout, r'Total command execution time: (\d+\.\d+) seconds') - - -# Try to make our results a little more accurate and repeatable by -# measuring Python overhead executing a minimal file, and reading the -# scons.py script itself from disk so that it's already been cached. -test.write('pass.py', "pass\n") -test.read(test.program) - -start_time = time.time() -test.run(program=TestSCons.python, arguments=test.workpath('pass.py')) -overhead = time.time() - start_time - - - -start_time = time.time() -test.run(arguments = "-j1 --debug=action_timestamps . SLEEP=0") -complete_time = time.time() - start_time - - - -expected_total_time = complete_time - overhead - -def get_times_and_targets(pattern): - targets = [] - times = [] - for target, target_time in re.findall(pattern, test.stdout()): - targets.append(target) - times.append(float(target_time)) - return targets, times - -duration_targets, durations = get_times_and_targets(r'Command execution time: (.*): (\d+\.\d+) seconds') -start_targets, start_times = get_times_and_targets(r'Command execution start time: (.*): (\d+\.\d+) seconds') -stop_targets, stop_times = get_times_and_targets(r'Command execution stop time: (.*): (\d+\.\d+) seconds') - -expected_command_time = 0.0 -for t in durations: - expected_command_time += t - - -stdout = test.stdout() - -total_time = get_total_time(stdout) -sconscript_time = get_sconscript_time(stdout) -scons_time = get_scons_time(stdout) -command_time = get_command_time(stdout) - -failures = [] -warnings = [] - - -def check_targets(targets): - if targets != expected_targets: - failures.append("""\ - Scons reported the targets of timing information as %(targets)s, - but the actual targets should have been %(expected_targets)s. - """.format(targets=targets, expected_targets=expected_targets)) - -check_targets(duration_targets) -check_targets(start_targets) -check_targets(stop_targets) - -if not within_tolerance(expected_command_time, command_time, 0.01): - failures.append("""\ -SCons -j1 reported a total command execution time of %(command_time)s, -but command execution times really totalled %(expected_command_time)s, -outside of the 1%% tolerance. -""" % locals()) - -added_times = sconscript_time+scons_time+command_time -if not within_tolerance(total_time, added_times, 0.01): - failures.append("""\ -SCons -j1 reported a total build time of %(total_time)s, -but the various execution times actually totalled %(added_times)s, -outside of the 1%% tolerance. -""" % locals()) - -if not within_tolerance(total_time, expected_total_time, 0.20): - # This tolerance check seems empirically to work fine if there's - # a light load on the system, but on a heavily loaded system the - # timings get screwy and it can fail frequently. Some obvious - # attempts to work around the problem didn't, so just treat it as - # a warning for now. - warnings.append("""\ -Warning: SCons -j1 reported total build time of %(total_time)s, -but the actual measured build time was %(expected_total_time)s -(end-to-end time of %(complete_time)s less Python overhead of %(overhead)s), -outside of the 15%% tolerance. -""" % locals()) - -if failures or warnings: - print('\n'.join([test.stdout()] + failures + warnings)) -if failures: - test.fail_test(1) - -test.run(arguments = "--debug=action_timestamps . SLEEP=0") - -command_time = get_command_time(test.stdout()) -if command_time != 0.0: - print("Up-to-date run received non-zero command time of %s" % command_time) - test.fail_test() - - - -test.run(arguments = "-c") - -test.run(arguments = "-j4 --debug=action_timestamps . SLEEP=1") - - - -stdout = test.stdout() - -total_time = get_total_time(stdout) -sconscript_time = get_sconscript_time(stdout) -scons_time = get_scons_time(stdout) -command_time = get_command_time(stdout) - -failures = [] - -added_times = sconscript_time+scons_time+command_time -if not within_tolerance(total_time, added_times, 0.01): - failures.append("""\ -SCons -j4 reported a total build time of %(total_time)s, -but the various execution times actually totalled %(added_times)s, -outside of the 1%% tolerance. -""" % locals()) +env = Environment() +env.Program('main.exe', ['main.c']) +""") -if failures: - print('\n'.join([test.stdout()] + failures)) - test.fail_test(1) +def test_help_function(): + # Before anything else, make sure we get valid --debug=action_timestamps results + # when just running the help option. + test.run(arguments = "-h --debug=action_timestamps") + +def build(): + # Execute build + test.run(arguments='--debug=action_timestamps') + build_output = test.stdout() + return build_output + +def get_matches_from_output(build_output): + return [re.findall(pattern, build_output) for pattern in debug_time_patterns] + +def test_presence_of_debug_time_strings(build_output): + # Check presence of duration and timestamps + if None in get_matches_from_output(build_output): + print("One or more of the time debug strings were not found in the build output") + test.fail_test(1) + +def test_equal_number_of_debug_time_strings(build_output): + matches = get_matches_from_output(build_output) + num_of_matches = [len(match) for match in matches] + + # Check that the number of matches for each pattern is the same + if num_of_matches.count(num_of_matches[0]) != len(num_of_matches): + print("Debug time strings differs in quantity") + test.fail_test(2) + +def test_correctness_of_timestamps(build_output): + # Check if difference between timestamps is equal to duration + matches = get_matches_from_output(build_output) + + def match_to_float(m): + return float(m[1][1]) + + execution_time = match_to_float(matches[0]) + start_time = match_to_float(matches[1]) + stop_time = match_to_float(matches[2]) + delta_time = stop_time - start_time + + def within_tolerance(expected, actual, tolerance): + return abs((expected-actual)/actual) <= tolerance + + if not within_tolerance(execution_time, delta_time, 0.001): + print("Difference of timestamps differ from action duration") + print("Execution time = {}. Start time = {}. Stop time = {}. Delta time = {}".format(execution_time, start_time, stop_time, delta_time)) + test.fail_test(3) + +debug_time_patterns = [ + r'Command execution time: (.*): (\d+\.\d+) seconds', + r'Command execution start time: (.*): (\d+\.\d+) seconds', + r'Command execution stop time: (.*): (\d+\.\d+) seconds' +] -test.run(arguments = "-j4 --debug=action_timestamps . SLEEP=1") +test = TestSCons.TestSCons() +setup_fixtures() -command_time = get_command_time(test.stdout()) -if command_time != 0.0: - print("Up-to-date run received non-zero command time of %s" % command_time) - test.fail_test() +test_help_function() +build_output = build() +test_presence_of_debug_time_strings(build_output) +test_equal_number_of_debug_time_strings(build_output) +test_correctness_of_timestamps(build_output) test.pass_test() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: \ No newline at end of file -- cgit v0.12 From 883886b594fbf92d3b21adf49dc78aed13349209 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 11 Oct 2019 12:05:07 -0400 Subject: Move SConstruct from test to file fixture --- test/fixture/SConstruct_test_main.py | 3 +++ test/option/debug-action-timestamps.py | 6 +----- 2 files changed, 4 insertions(+), 5 deletions(-) create mode 100644 test/fixture/SConstruct_test_main.py diff --git a/test/fixture/SConstruct_test_main.py b/test/fixture/SConstruct_test_main.py new file mode 100644 index 0000000..8d2d2b0 --- /dev/null +++ b/test/fixture/SConstruct_test_main.py @@ -0,0 +1,3 @@ +DefaultEnvironment(tools=[]) +env = Environment() +env.Program('main.exe', ['main.c']) diff --git a/test/option/debug-action-timestamps.py b/test/option/debug-action-timestamps.py index 11a4bf5..0277516 100644 --- a/test/option/debug-action-timestamps.py +++ b/test/option/debug-action-timestamps.py @@ -31,11 +31,7 @@ _python_ = TestSCons._python_ def setup_fixtures(): test.file_fixture('../fixture/test_main.c', 'main.c') - test.write('SConstruct', """ -DefaultEnvironment(tools=[]) -env = Environment() -env.Program('main.exe', ['main.c']) -""") + test.file_fixture('../fixture/SConstruct_test_main.py', 'SConstruct') def test_help_function(): # Before anything else, make sure we get valid --debug=action_timestamps results -- cgit v0.12 From c135fd6842219561918366ec3b34d092eed0092e Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 11 Oct 2019 12:52:05 -0600 Subject: [PR 3462] convert json cache better way for py2 there was still a path through without fully converted data, where env['ENV'] could contain unicode, so convert the cache hit instead. This is a little slower but only for Py2 which is going away anyway. added the vs2019 exec test (vs-14.2-exec) which is just a copy of 14.0, 14.1 with the required version changed - this had never been added. Signed-off-by: Mats Wichmann --- src/engine/SCons/Tool/MSCommon/common.py | 14 +--- src/engine/SCons/Tool/MSCommon/vc.py | 23 +++++-- test/MSVS/vs-14.2-exec.py | 114 +++++++++++++++++++++++++++++++ 3 files changed, 133 insertions(+), 18 deletions(-) create mode 100644 test/MSVS/vs-14.2-exec.py diff --git a/src/engine/SCons/Tool/MSCommon/common.py b/src/engine/SCons/Tool/MSCommon/common.py index eaf57f9..ad371e9 100644 --- a/src/engine/SCons/Tool/MSCommon/common.py +++ b/src/engine/SCons/Tool/MSCommon/common.py @@ -30,7 +30,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import copy import json import os -import subprocess import re import subprocess import sys @@ -58,23 +57,13 @@ 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') -# !@$#@$? Python2 -if sys.version_info[0] == 2: - def str_hook(obj): - return {k.encode('utf-8') if isinstance(k, unicode) else k : - v.encode('utf-8') if isinstance(v, unicode) else v - for k,v in obj} - def read_script_env_cache(): """ fetch cached msvc env vars if requested, else return empty dict """ envcache = {} if CONFIG_CACHE: try: with open(CONFIG_CACHE, 'r') as f: - if sys.version_info[0] == 2: - envcache = json.load(f, object_pairs_hook=str_hook) - else: - envcache = json.load(f) + envcache = json.load(f) #TODO can use more specific FileNotFoundError when py2 dropped except IOError: pass @@ -244,7 +233,6 @@ def get_output(vcbat, args = None, env = None): if stderr: # TODO: find something better to do with stderr; # this at least prevents errors from getting swallowed. - import sys sys.stderr.write(stderr) if popen.wait() != 0: raise IOError(stderr.decode("mbcs")) diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py index 019d608..d321f43 100644 --- a/src/engine/SCons/Tool/MSCommon/vc.py +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -40,7 +40,10 @@ import SCons.Util import subprocess import os import platform +import sys from string import digits as string_digits +if sys.version_info[0] == 2: + import collections import SCons.Warnings from SCons.Tool import find_program_path @@ -157,11 +160,6 @@ def get_host_target(env): host_platform = env.get('HOST_ARCH') if not host_platform: host_platform = platform.machine() - # TODO(2.5): the native Python platform.machine() function returns - # '' on all Python versions before 2.6, after which it also uses - # PROCESSOR_ARCHITECTURE. - if not host_platform: - host_platform = os.environ.get('PROCESSOR_ARCHITECTURE', '') # Retain user requested TARGET_ARCH req_target_platform = env.get('TARGET_ARCH') @@ -622,6 +620,21 @@ def script_env(script, args=None): script_env_cache[cache_key] = cache_data # once we updated cache, give a chance to write out if user wanted common.write_script_env_cache(script_env_cache) + else: + # if we "hit" data from the json file, we have a Py2 problem: + # keys & values will be unicode. don't detect, just convert. + if sys.version_info[0] == 2: + def convert(data): + if isinstance(data, basestring): + return str(data) + elif isinstance(data, collections.Mapping): + return dict(map(convert, data.iteritems())) + elif isinstance(data, collections.Iterable): + return type(data)(map(convert, data)) + else: + return data + + cache_data = convert(cache_data) return cache_data def get_default_version(env): diff --git a/test/MSVS/vs-14.2-exec.py b/test/MSVS/vs-14.2-exec.py new file mode 100644 index 0000000..1894031 --- /dev/null +++ b/test/MSVS/vs-14.2-exec.py @@ -0,0 +1,114 @@ +#!/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__" + +""" +Test that we can actually build a simple program using our generated +Visual Studio 14.0 project (.vcxproj) and solution (.sln) files +using Visual Studio 14.2 +""" + +import os +import sys + +import TestSConsMSVS + +test = TestSConsMSVS.TestSConsMSVS() + +if sys.platform != 'win32': + msg = "Skipping Visual Studio test on non-Windows platform '%s'\n" % sys.platform + test.skip_test(msg) + +msvs_version = '14.2' + +if not msvs_version in test.msvs_versions(): + msg = "Visual Studio %s not installed; skipping test.\n" % msvs_version + test.skip_test(msg) + + + +# Let SCons figure out the Visual Studio environment variables for us and +# print out a statement that we can exec to suck them into our external +# environment so we can execute devenv and really try to build something. + +test.run(arguments = '-n -q -Q -f -', stdin = """\ +env = Environment(tools = ['msvc'], MSVS_VERSION='%(msvs_version)s') +if env.WhereIs('cl'): + print("os.environ.update(%%s)" %% repr(env['ENV'])) +""" % locals()) + +if(test.stdout() == ""): + msg = "Visual Studio %s missing cl.exe; skipping test.\n" % msvs_version + test.skip_test(msg) + +exec(test.stdout()) + + + +test.subdir('sub dir') + +test.write(['sub dir', 'SConstruct'], """\ +env=Environment(MSVS_VERSION = '%(msvs_version)s') + +env.MSVSProject(target = 'foo.vcxproj', + srcs = ['foo.c'], + buildtarget = 'foo.exe', + variant = 'Release', + DebugSettings = {'LocalDebuggerCommandArguments':'echo "" > output.txt'}) +env.Program('foo.c') +""" % locals()) + +test.write(['sub dir', 'foo.c'], r""" +int +main(int argc, char *argv) +{ + printf("foo.c\n"); + exit (0); +} +""") + +test.run(chdir='sub dir', arguments='.') + +test.vcproj_sys_path(test.workpath('sub dir', 'foo.vcxproj')) + +import SCons.Platform.win32 +system_dll_path = os.path.join( SCons.Platform.win32.get_system_root(), 'System32' ) +os.environ['PATH'] = os.environ['PATH'] + os.pathsep + system_dll_path + +test.run(chdir='sub dir', + program=[test.get_msvs_executable(msvs_version)], + arguments=['foo.sln', '/build', 'Release']) + +test.run(program=test.workpath('sub dir', 'foo'), stdout="foo.c\n") +test.validate_msvs_file(test.workpath('sub dir', 'foo.vcxproj.user')) + + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: -- cgit v0.12 From 17e907f1bdb5ee2b26ec3ff5c9a4361c48213062 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sat, 12 Oct 2019 11:51:46 -0600 Subject: [PR 3462] update doc/comments for msvc-env-cache Signed-off-by: Mats Wichmann --- doc/man/scons.xml | 34 +++++++++++++++++++------------- src/engine/SCons/Tool/MSCommon/common.py | 4 +++- src/engine/SCons/Tool/MSCommon/vc.py | 19 +++++++++++------- 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index e210e76..1b8ee43 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -7218,26 +7218,32 @@ in addition to those passed on the command line. SCONS_CACHE_MSVC_CONFIG -If set, save the shell environment variables generated -in setting up the Microsoft Visual C++ compiler (and/or Build Tools), -to give these settings, which are expensive to generate, persistence +(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, +which are expensive to generate, persistence across &scons; invocations. -If set to a True-like value ("1", +Use of this option is primarily intended to aid performance +in tightly controlled Continuous Integration setups. + +If set to a True-like value ("1", "true" or "True") will cache to a file named .scons_msvc_cache in the user's home directory. If set to a pathname, will use that pathname for the cache. - -Note: this behavior is not enabled by default because it -might be somewhat fragile: while each major tool version -(e.g. Visual Studio 2018 vs 2019) will get separate -entries, if toolset updates cause a change + +Note: use this cache with caution as it +might be somewhat fragile: while each major toolset version +(e.g. Visual Studio 2017 vs 2019) and architecture pair will get separate +cache entries, if toolset updates cause a change to settings within a given release series, &scons; will not -detect this and will fetch old settings. -In case of problems, just remove the cache file. -Use of this option is primarily intended to aid performance -for tightly controlled Continuous Integration setups. - +detect the change and will reuse old settings. +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. + diff --git a/src/engine/SCons/Tool/MSCommon/common.py b/src/engine/SCons/Tool/MSCommon/common.py index ad371e9..bbccf61 100644 --- a/src/engine/SCons/Tool/MSCommon/common.py +++ b/src/engine/SCons/Tool/MSCommon/common.py @@ -36,7 +36,7 @@ import sys import SCons.Util -# internal-use so undocumented: +# SCONS_MSCOMMON_DEBUG is internal-use so undocumented: # set to '-' to print to console, else set to filename to log to LOGFILE = os.environ.get('SCONS_MSCOMMON_DEBUG') if LOGFILE == '-': @@ -53,6 +53,7 @@ else: debug = lambda x: None +# SCONS_CACHE_MSVC_CONFIG is public, and is documented. 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') @@ -66,6 +67,7 @@ def read_script_env_cache(): envcache = json.load(f) #TODO can use more specific FileNotFoundError when py2 dropped except IOError: + # don't fail if no cache file, just proceed without it pass return envcache diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py index d321f43..4f6048d 100644 --- a/src/engine/SCons/Tool/MSCommon/vc.py +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -591,12 +591,15 @@ def reset_installed_vcs(): # we can greatly improve the speed of the second and subsequent Environment # (or Clone) calls by memoizing the environment variables set by vcvars*.bat. # -# Updated: by 2018, vcvarsall.bat had gotten so expensive it was breaking -# CI builds because the test suite starts scons so many times and the existing -# memo logic only helped with repeated calls within the same scons run; -# with VS2019 it got even slower and an optional cache file 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. +# Updated: by 2018, vcvarsall.bat had gotten so expensive (vs2017 era) +# it was breaking CI builds because the test suite starts scons so many +# times and the existing memo logic only helped with repeated calls +# 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, +# not the entire output of running the batch file - saves a bit +# of time not parsing every time. script_env_cache = None @@ -621,7 +624,8 @@ def script_env(script, args=None): # once we updated cache, give a chance to write out if user wanted common.write_script_env_cache(script_env_cache) else: - # if we "hit" data from the json file, we have a Py2 problem: + #TODO: Python 2 cleanup + # If we "hit" data from the json file, we have a Py2 problem: # keys & values will be unicode. don't detect, just convert. if sys.version_info[0] == 2: def convert(data): @@ -635,6 +639,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 8ec5aba156f070c89609ed8c99e7b3cc4973efa2 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 12 Oct 2019 15:28:09 -0700 Subject: Changed wording on MSVC caching to indicate it's currently experimental feature [CI Skip] --- src/CHANGES.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 7ce224e..df8fb0d 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -18,10 +18,11 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - CmdStringHolder fix from issue #3428 - Turn previously deprecated debug options into failures: --debug=tree, --debug=dtree, --debug=stree, --debug=nomemoizer. - - If SCONS_CACHE_MSVC_CONFIG shell environment variable is set, - scons will cache the results of past calls to vcvarsall.bat to + - Experimental New Feature: Enable caching MSVC configuration + If SCONS_CACHE_MSVC_CONFIG shell environment variable is set, + SCons will cache the results of past calls to vcvarsall.bat to a file; integrates with existing memoizing of such vars. - On vs2019 saves 5+ seconds per scons invocation, which really + On vs2019 saves 5+ seconds per SCons invocation, which really helps test suite runs. From Jacek Kuczera: -- cgit v0.12 From 9c4e6c7a303047e4b26e58af749508f7e254ae89 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sun, 20 Oct 2019 10:13:32 -0600 Subject: Remove deprecated {Source,Target}Signatures These two have been deprecated since 2010 (about SCons 2.0), commit 935e6985. Methods are removed, setoption for setting them removed, doc is removed, tests are migrated to test/Removed/*/Old with a sconstest.skip file so they don't run, and two new tests are added to confirm that using the functions and setoptions generate exceptions. Signed-off-by: Mats Wichmann --- doc/man/scons.xml | 21 -- doc/scons.mod | 3 - doc/user/depends.xml | 178 --------------- src/CHANGES.txt | 1 + src/engine/SCons/Environment.py | 59 +---- src/engine/SCons/Environment.xml | 252 --------------------- src/engine/SCons/EnvironmentTests.py | 91 -------- src/engine/SCons/Script/__init__.py | 2 - src/engine/SCons/Warnings.py | 6 - test/Deprecated/CacheDir/timestamp-content.py | 68 ------ test/Deprecated/CacheDir/timestamp-timestamp.py | 68 ------ test/Deprecated/SourceSignatures/basic.py | 131 ----------- test/Deprecated/SourceSignatures/env.py | 109 --------- test/Deprecated/SourceSignatures/implicit-cache.py | 105 --------- test/Deprecated/SourceSignatures/no-csigs.py | 81 ------- test/Deprecated/SourceSignatures/overrides.py | 68 ------ test/Deprecated/SourceSignatures/switch-rebuild.py | 96 -------- test/Deprecated/TargetSignatures/build-content.py | 142 ------------ test/Deprecated/TargetSignatures/content.py | 95 -------- test/Deprecated/TargetSignatures/overrides.py | 64 ------ test/Removed/CacheDir/Old/sconstest.skip | 0 test/Removed/CacheDir/Old/timestamp-content.py | 68 ++++++ test/Removed/CacheDir/Old/timestamp-timestamp.py | 68 ++++++ test/Removed/CacheDir/README.md | 4 + test/Removed/SourceSignatures/Old/basic.py | 131 +++++++++++ test/Removed/SourceSignatures/Old/env.py | 109 +++++++++ .../Removed/SourceSignatures/Old/implicit-cache.py | 105 +++++++++ test/Removed/SourceSignatures/Old/no-csigs.py | 81 +++++++ test/Removed/SourceSignatures/Old/overrides.py | 68 ++++++ test/Removed/SourceSignatures/Old/sconstest.skip | 0 .../Removed/SourceSignatures/Old/switch-rebuild.py | 96 ++++++++ test/Removed/SourceSignatures/README.md | 6 + test/Removed/SourceSignatures/SConstruct.method | 1 + test/Removed/SourceSignatures/SConstruct.setopt | 1 + test/Removed/SourceSignatures/SourceSignatures.py | 52 +++++ test/Removed/TargetSignatures/Old/build-content.py | 142 ++++++++++++ test/Removed/TargetSignatures/Old/content.py | 95 ++++++++ test/Removed/TargetSignatures/Old/overrides.py | 64 ++++++ test/Removed/TargetSignatures/Old/sconstest.skip | 0 test/Removed/TargetSignatures/README.md | 6 + test/Removed/TargetSignatures/SConstruct.method | 1 + test/Removed/TargetSignatures/SConstruct.setopt | 1 + test/Removed/TargetSignatures/TargetSignatures.py | 52 +++++ test/implicit-cache/basic.py | 7 +- test/sconsign/script/Signatures.py | 3 - test/srcchange.py | 5 +- test/subdivide.py | 5 +- 47 files changed, 1165 insertions(+), 1646 deletions(-) delete mode 100644 test/Deprecated/CacheDir/timestamp-content.py delete mode 100644 test/Deprecated/CacheDir/timestamp-timestamp.py delete mode 100644 test/Deprecated/SourceSignatures/basic.py delete mode 100644 test/Deprecated/SourceSignatures/env.py delete mode 100644 test/Deprecated/SourceSignatures/implicit-cache.py delete mode 100644 test/Deprecated/SourceSignatures/no-csigs.py delete mode 100644 test/Deprecated/SourceSignatures/overrides.py delete mode 100644 test/Deprecated/SourceSignatures/switch-rebuild.py delete mode 100644 test/Deprecated/TargetSignatures/build-content.py delete mode 100644 test/Deprecated/TargetSignatures/content.py delete mode 100644 test/Deprecated/TargetSignatures/overrides.py create mode 100644 test/Removed/CacheDir/Old/sconstest.skip create mode 100644 test/Removed/CacheDir/Old/timestamp-content.py create mode 100644 test/Removed/CacheDir/Old/timestamp-timestamp.py create mode 100644 test/Removed/CacheDir/README.md create mode 100644 test/Removed/SourceSignatures/Old/basic.py create mode 100644 test/Removed/SourceSignatures/Old/env.py create mode 100644 test/Removed/SourceSignatures/Old/implicit-cache.py create mode 100644 test/Removed/SourceSignatures/Old/no-csigs.py create mode 100644 test/Removed/SourceSignatures/Old/overrides.py create mode 100644 test/Removed/SourceSignatures/Old/sconstest.skip create mode 100644 test/Removed/SourceSignatures/Old/switch-rebuild.py create mode 100644 test/Removed/SourceSignatures/README.md create mode 100644 test/Removed/SourceSignatures/SConstruct.method create mode 100644 test/Removed/SourceSignatures/SConstruct.setopt create mode 100644 test/Removed/SourceSignatures/SourceSignatures.py create mode 100644 test/Removed/TargetSignatures/Old/build-content.py create mode 100644 test/Removed/TargetSignatures/Old/content.py create mode 100644 test/Removed/TargetSignatures/Old/overrides.py create mode 100644 test/Removed/TargetSignatures/Old/sconstest.skip create mode 100644 test/Removed/TargetSignatures/README.md create mode 100644 test/Removed/TargetSignatures/SConstruct.method create mode 100644 test/Removed/TargetSignatures/SConstruct.setopt create mode 100644 test/Removed/TargetSignatures/TargetSignatures.py diff --git a/doc/man/scons.xml b/doc/man/scons.xml index 95278e6..a9e0dd7 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -1827,27 +1827,6 @@ method. - - --warn=deprecated-source-signatures, --warn=no-deprecated-source-signatures - -Enables or disables warnings about use of the deprecated -SourceSignatures() -function or -env.SourceSignatures() -method. - - - - - --warn=deprecated-target-signatures, --warn=no-deprecated-target-signatures - -Enables or disables warnings about use of the deprecated -TargetSignatures() -function or -env.TargetSignatures() -method. - - diff --git a/doc/scons.mod b/doc/scons.mod index 71e996d..3e843a0 100644 --- a/doc/scons.mod +++ b/doc/scons.mod @@ -260,11 +260,8 @@ SetDefault"> SetOption"> SideEffect"> -SourceSignature"> -SourceSignatures"> Split"> Tag"> -TargetSignatures"> Task"> Touch"> UnknownOptions"> diff --git a/doc/user/depends.xml b/doc/user/depends.xml index 7947900..5a78eb5 100644 --- a/doc/user/depends.xml +++ b/doc/user/depends.xml @@ -765,184 +765,6 @@ int main() { printf("Hello, world!\n"); } -
- The &SourceSignatures; Function - - - - The &SourceSignatures; function is fairly straightforward, - and supports two different argument values - to configure whether source file changes should be decided - using MD5 signatures: - - - - -Program('hello.c') -SourceSignatures('MD5') - - - - - Or using time stamps: - - - - -Program('hello.c') -SourceSignatures('timestamp') - - - - - These are roughly equivalent to specifying - Decider('MD5') - or - Decider('timestamp-match'), - respectively, - although it only affects how SCons makes - decisions about dependencies on - source files--that is, - files that are not built from any other files. - - - -
- -
- The &TargetSignatures; Function - - - - The &TargetSignatures; function - specifies how &SCons; decides - when a target file has changed - when it is used as a - dependency of (input to) another target--that is, - the &TargetSignatures; function configures - how the signatures of "intermediate" target files - are used when deciding if a "downstream" target file - must be rebuilt. - - This easily-overlooked distinction between - how &SCons; decides if the target itself must be rebuilt - and how the target is then used to decide if a different - target must be rebuilt is one of the confusing - things that has led to the &TargetSignatures; - and &SourceSignatures; functions being - replaced by the simpler &Decider; function. - - - - - - - The &TargetSignatures; function supports the same - 'MD5' and 'timestamp' - argument values that are supported by the &SourceSignatures;, - with the same meanings, but applied to target files. - That is, in the example: - - - - -Program('hello.c') -TargetSignatures('MD5') - - - - - The MD5 checksum of the &hello_o; target file - will be used to decide if it has changed since the last - time the "downstream" &hello; target file was built. - And in the example: - - - - -Program('hello.c') -TargetSignatures('timestamp') - - - - - The modification time of the &hello_o; target file - will be used to decide if it has changed since the last - time the "downstream" &hello; target file was built. - - - - - - The &TargetSignatures; function supports - two additional argument values: - 'source' and 'build'. - The 'source' argument - specifies that decisions involving - whether target files have changed - since a previous build - should use the same behavior - for the decisions configured for source files - (using the &SourceSignatures; function). - So in the example: - - - - -Program('hello.c') -TargetSignatures('source') -SourceSignatures('timestamp') - - - - - All files, both targets and sources, - will use modification times - when deciding if an input file - has changed since the last - time a target was built. - - - - - - Lastly, the 'build' argument - specifies that &SCons; should examine - the build status of a target file - and always rebuild a "downstream" target - if the target file was itself rebuilt, - without re-examining the contents or timestamp - of the newly-built target file. - If the target file was not rebuilt during - this &scons; invocation, - then the target file will be examined - the same way as configured by - the &SourceSignature; call - to decide if it has changed. - - - - - - This mimics the behavior of - build signatures - in earlier versions of &SCons;. - A &buildsignature; re-combined - signatures of all the input files - that went into making the target file, - so that the target file itself - did not need to have its contents read - to compute an MD5 signature. - This can improve performance for some configurations, - but is generally not as effective as using - Decider('MD5-timestamp'). - - - -
- - -
Implicit Dependencies: The &cv-CPPPATH; Construction Variable diff --git a/src/CHANGES.txt b/src/CHANGES.txt index df8fb0d..af448d5 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -24,6 +24,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER a file; integrates with existing memoizing of such vars. On vs2019 saves 5+ seconds per SCons invocation, which really helps test suite runs. + - Remove deprecated SourceSignatures, TargetSignatures From Jacek Kuczera: - Fix CheckFunc detection code for Visual 2019. Some functions diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 08104c5..0e1102e 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -46,7 +46,7 @@ import SCons.Builder import SCons.Debug from SCons.Debug import logInstanceCreation import SCons.Defaults -import SCons.Errors +from SCons.Errors import UserError, BuildError import SCons.Memoize import SCons.Node import SCons.Node.Alias @@ -75,11 +75,6 @@ CalculatorArgs = {} semi_deepcopy = SCons.Util.semi_deepcopy semi_deepcopy_dict = SCons.Util.semi_deepcopy_dict -# Pull UserError into the global name space for the benefit of -# Environment().SourceSignatures(), which has some import statements -# which seem to mess up its ability to reference SCons directly. -UserError = SCons.Errors.UserError - def alias_builder(env, target, source): pass @@ -154,7 +149,7 @@ def _set_BUILDERS(env, key, value): env._dict[key] = bd for k, v in value.items(): if not SCons.Builder.is_a_Builder(v): - raise SCons.Errors.UserError('%s is not a Builder.' % repr(v)) + raise UserError('%s is not a Builder.' % repr(v)) bd.update(value) def _del_SCANNERS(env, key): @@ -431,7 +426,7 @@ class SubstitutionEnvironment(object): # efficient than calling another function or a method. if key not in self._dict \ and not _is_valid_var.match(key): - raise SCons.Errors.UserError("Illegal construction variable `%s'" % key) + raise UserError("Illegal construction variable `%s'" % key) self._dict[key] = value def get(self, key, default=None): @@ -1621,7 +1616,7 @@ class Base(SubstitutionEnvironment): for td in tdlist: targets.extend(td[0]) if len(targets) > 1: - raise SCons.Errors.UserError( + raise UserError( "More than one dependency target found in `%s': %s" % (filename, targets)) for target, depends in tdlist: @@ -2060,7 +2055,7 @@ class Base(SubstitutionEnvironment): """ action = self.Action(action, *args, **kw) result = action([], [], self) - if isinstance(result, SCons.Errors.BuildError): + if isinstance(result, BuildError): errstr = result.errstr if result.filename: errstr = result.filename + ': ' + errstr @@ -2180,7 +2175,7 @@ class Base(SubstitutionEnvironment): for side_effect in side_effects: if side_effect.multiple_side_effect_has_builder(): - raise SCons.Errors.UserError("Multiple ways to build the same target were specified for: %s" % str(side_effect)) + raise UserError("Multiple ways to build the same target were specified for: %s" % str(side_effect)) side_effect.add_source(targets) side_effect.side_effect = 1 self.Precious(side_effect) @@ -2198,24 +2193,6 @@ class Base(SubstitutionEnvironment): entry.set_src_builder(builder) return entries - def SourceSignatures(self, type): - global _warn_source_signatures_deprecated - if _warn_source_signatures_deprecated: - msg = "The env.SourceSignatures() method is deprecated;\n" + \ - "\tconvert your build to use the env.Decider() method instead." - SCons.Warnings.warn(SCons.Warnings.DeprecatedSourceSignaturesWarning, msg) - _warn_source_signatures_deprecated = False - type = self.subst(type) - self.src_sig_type = type - if type == 'MD5': - if not SCons.Util.md5: - raise UserError("MD5 signatures are not available in this version of Python.") - self.decide_source = self._changed_content - elif type == 'timestamp': - self.decide_source = self._changed_timestamp_match - else: - raise UserError("Unknown source signature type '%s'" % type) - def Split(self, arg): """This function converts a string or list into a list of strings or Nodes. This makes things easier for users by allowing files to @@ -2237,28 +2214,6 @@ class Base(SubstitutionEnvironment): else: return [self.subst(arg)] - def TargetSignatures(self, type): - global _warn_target_signatures_deprecated - if _warn_target_signatures_deprecated: - msg = "The env.TargetSignatures() method is deprecated;\n" + \ - "\tconvert your build to use the env.Decider() method instead." - SCons.Warnings.warn(SCons.Warnings.DeprecatedTargetSignaturesWarning, msg) - _warn_target_signatures_deprecated = False - type = self.subst(type) - self.tgt_sig_type = type - if type in ('MD5', 'content'): - if not SCons.Util.md5: - raise UserError("MD5 signatures are not available in this version of Python.") - self.decide_target = self._changed_content - elif type == 'timestamp': - self.decide_target = self._changed_timestamp_match - elif type == 'build': - self.decide_target = self._changed_build - elif type == 'source': - self.decide_target = self._changed_source - else: - raise UserError("Unknown target signature type '%s'"%type) - def Value(self, value, built_value=None): """ """ @@ -2355,7 +2310,7 @@ class OverrideEnvironment(Base): return self.__dict__['__subject'].__getitem__(key) def __setitem__(self, key, value): if not is_valid_construction_var(key): - raise SCons.Errors.UserError("Illegal construction variable `%s'" % key) + raise UserError("Illegal construction variable `%s'" % key) self.__dict__['overrides'][key] = value def __delitem__(self, key): try: diff --git a/src/engine/SCons/Environment.xml b/src/engine/SCons/Environment.xml index a635108..829bf12 100644 --- a/src/engine/SCons/Environment.xml +++ b/src/engine/SCons/Environment.xml @@ -2987,105 +2987,6 @@ env.SourceCode('no_source.c', None)
- - -(type) - - - -Note: Although it is not yet officially deprecated, -use of this function is discouraged. -See the -&f-link-Decider; -function for a more flexible and straightforward way -to configure SCons' decision-making. - - - -The -&f-SourceSignatures; -function tells -&scons; -how to decide if a source file -(a file that is not built from any other files) -has changed since the last time it -was used to build a particular target file. -Legal values are -MD5 -or -timestamp. - - - -If the environment method is used, -the specified type of source signature -is only used when deciding whether targets -built with that environment are up-to-date or must be rebuilt. -If the global function is used, -the specified type of source signature becomes the default -used for all decisions -about whether targets are up-to-date. - - - -MD5 -means -&scons; -decides that a source file has changed -if the MD5 checksum of its contents has changed since -the last time it was used to rebuild a particular target file. - - - -timestamp -means -&scons; -decides that a source file has changed -if its timestamp (modification time) has changed since -the last time it was used to rebuild a particular target file. -(Note that although this is similar to the behavior of Make, -by default it will also rebuild if the dependency is -older -than the last time it was used to rebuild the target file.) - - - -There is no different between the two behaviors -for Python -&f-Value; -node objects. - - - -MD5 -signatures take longer to compute, -but are more accurate than -timestamp -signatures. -The default value is -MD5. - - - -Note that the default -&f-link-TargetSignatures; -setting (see below) -is to use this -&f-SourceSignatures; -setting for any target files that are used -to build other target files. -Consequently, changing the value of -&f-SourceSignatures; -will, by default, -affect the up-to-date decision for all files in the build -(or all files built with a specific construction environment -when -&f-env-SourceSignatures; -is used). - - - - (arg) @@ -3229,159 +3130,6 @@ source_nodes = env.subst('$EXPAND_TO_NODELIST', - - -(type) - - - -Note: Although it is not yet officially deprecated, -use of this function is discouraged. -See the -&f-link-Decider; -function for a more flexible and straightforward way -to configure SCons' decision-making. - - - -The -&f-TargetSignatures; -function tells -&scons; -how to decide if a target file -(a file that -is -built from any other files) -has changed since the last time it -was used to build some other target file. -Legal values are -"build"; -"content" -(or its synonym -"MD5"); -"timestamp"; -or -"source". - - - -If the environment method is used, -the specified type of target signature is only used -for targets built with that environment. -If the global function is used, -the specified type of signature becomes the default -used for all target files that -don't have an explicit target signature type -specified for their environments. - - - -"content" -(or its synonym -"MD5") -means -&scons; -decides that a target file has changed -if the MD5 checksum of its contents has changed since -the last time it was used to rebuild some other target file. -This means -&scons; -will open up -MD5 sum the contents -of target files after they're built, -and may decide that it does not need to rebuild -"downstream" target files if a file was -rebuilt with exactly the same contents as the last time. - - - -"timestamp" -means -&scons; -decides that a target file has changed -if its timestamp (modification time) has changed since -the last time it was used to rebuild some other target file. -(Note that although this is similar to the behavior of Make, -by default it will also rebuild if the dependency is -older -than the last time it was used to rebuild the target file.) - - - -"source" -means -&scons; -decides that a target file has changed -as specified by the corresponding -&f-SourceSignatures; -setting -("MD5" -or -"timestamp"). -This means that -&scons; -will treat all input files to a target the same way, -regardless of whether they are source files -or have been built from other files. - - - -"build" -means -&scons; -decides that a target file has changed -if it has been rebuilt in this invocation -or if its content or timestamp have changed -as specified by the corresponding -&f-SourceSignatures; -setting. -This "propagates" the status of a rebuilt file -so that other "downstream" target files -will always be rebuilt, -even if the contents or the timestamp -have not changed. - - - -"build" -signatures are fastest because -"content" -(or -"MD5") -signatures take longer to compute, -but are more accurate than -"timestamp" -signatures, -and can prevent unnecessary "downstream" rebuilds -when a target file is rebuilt to the exact same contents -as the previous build. -The -"source" -setting provides the most consistent behavior -when other target files may be rebuilt from -both source and target input files. -The default value is -"source". - - - -Because the default setting is -"source", -using -&f-SourceSignatures; -is generally preferable to -&f-TargetSignatures;, -so that the up-to-date decision -will be consistent for all files -(or all files built with a specific construction environment). -Use of -&f-TargetSignatures; -provides specific control for how built target files -affect their "downstream" dependencies. - - - - (string, [toolpath, **kw]) diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index 70e1a37..f016f22 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -3284,44 +3284,6 @@ def generate(env): s = e.src_builder() assert s is None, s - def test_SourceSignatures(self): - """Test the SourceSignatures() method""" - import SCons.Errors - - env = self.TestEnvironment(M = 'MD5', T = 'timestamp') - - exc_caught = None - try: - env.SourceSignatures('invalid_type') - except SCons.Errors.UserError: - exc_caught = 1 - assert exc_caught, "did not catch expected UserError" - - env.SourceSignatures('MD5') - assert env.src_sig_type == 'MD5', env.src_sig_type - - env.SourceSignatures('$M') - assert env.src_sig_type == 'MD5', env.src_sig_type - - env.SourceSignatures('timestamp') - assert env.src_sig_type == 'timestamp', env.src_sig_type - - env.SourceSignatures('$T') - assert env.src_sig_type == 'timestamp', env.src_sig_type - - try: - import SCons.Util - save_md5 = SCons.Util.md5 - SCons.Util.md5 = None - try: - env.SourceSignatures('MD5') - except SCons.Errors.UserError: - pass - else: - self.fail('Did not catch expected UserError') - finally: - SCons.Util.md5 = save_md5 - def test_Split(self): """Test the Split() method""" env = self.TestEnvironment(FOO = 'fff', BAR = 'bbb') @@ -3338,56 +3300,6 @@ def generate(env): s = env.Split("$FOO$BAR") assert s == ["fffbbb"], s - def test_TargetSignatures(self): - """Test the TargetSignatures() method""" - import SCons.Errors - - env = self.TestEnvironment(B='build', C='content') - - exc_caught = None - try: - env.TargetSignatures('invalid_type') - except SCons.Errors.UserError: - exc_caught = 1 - assert exc_caught, "did not catch expected UserError" - assert not hasattr(env, '_build_signature') - - env.TargetSignatures('build') - assert env.tgt_sig_type == 'build', env.tgt_sig_type - - env.TargetSignatures('$B') - assert env.tgt_sig_type == 'build', env.tgt_sig_type - - env.TargetSignatures('content') - assert env.tgt_sig_type == 'content', env.tgt_sig_type - - env.TargetSignatures('$C') - assert env.tgt_sig_type == 'content', env.tgt_sig_type - - env.TargetSignatures('MD5') - assert env.tgt_sig_type == 'MD5', env.tgt_sig_type - - env.TargetSignatures('timestamp') - assert env.tgt_sig_type == 'timestamp', env.tgt_sig_type - - try: - import SCons.Util - save_md5 = SCons.Util.md5 - SCons.Util.md5 = None - try: - env.TargetSignatures('MD5') - except SCons.Errors.UserError: - pass - else: - self.fail('Did not catch expected UserError') - try: - env.TargetSignatures('content') - except SCons.Errors.UserError: - pass - else: - self.fail('Did not catch expected UserError') - finally: - SCons.Util.md5 = save_md5 def test_Value(self): """Test creating a Value() object @@ -3408,7 +3320,6 @@ def generate(env): assert v3.value == 'c', v3.value - def test_Environment_global_variable(self): """Test setting Environment variable to an Environment.Base subclass""" class MyEnv(SCons.Environment.Base): @@ -3750,8 +3661,6 @@ class OverrideEnvironmentTestCase(unittest.TestCase,TestEnvironmentFixture): # Environment() # FindFile() # Scanner() - # SourceSignatures() - # TargetSignatures() # It's unlikely Clone() will ever be called this way, so let the # other methods test that handling overridden values works. diff --git a/src/engine/SCons/Script/__init__.py b/src/engine/SCons/Script/__init__.py index 007eb0d..24af73e 100644 --- a/src/engine/SCons/Script/__init__.py +++ b/src/engine/SCons/Script/__init__.py @@ -346,10 +346,8 @@ GlobalDefaultEnvironmentFunctions = [ 'SConsignFile', 'SideEffect', 'SourceCode', - 'SourceSignatures', 'Split', 'Tag', - 'TargetSignatures', 'Value', 'VariantDir', ] diff --git a/src/engine/SCons/Warnings.py b/src/engine/SCons/Warnings.py index a5b257b..718b3d5 100644 --- a/src/engine/SCons/Warnings.py +++ b/src/engine/SCons/Warnings.py @@ -132,12 +132,6 @@ class DeprecatedCopyWarning(MandatoryDeprecatedWarning): class DeprecatedOptionsWarning(MandatoryDeprecatedWarning): pass -class DeprecatedSourceSignaturesWarning(MandatoryDeprecatedWarning): - pass - -class DeprecatedTargetSignaturesWarning(MandatoryDeprecatedWarning): - pass - class DeprecatedDebugOptionsWarning(MandatoryDeprecatedWarning): pass diff --git a/test/Deprecated/CacheDir/timestamp-content.py b/test/Deprecated/CacheDir/timestamp-content.py deleted file mode 100644 index 860d0f3..0000000 --- a/test/Deprecated/CacheDir/timestamp-content.py +++ /dev/null @@ -1,68 +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 CacheDir() works when using SourceSignatures('timestamp') -and TargetSignatures 'content'. -""" - -import TestSCons - -test = TestSCons.TestSCons() - -test.write('SConstruct', """ -SetOption('warn', 'no-deprecated') -SourceSignatures('timestamp') -TargetSignatures('content') -CacheDir('cache') -Command('file.out', 'file.in', Copy('$TARGET', '$SOURCE')) -""") - -test.write('file.in', "file.in\n") - -test.run(arguments = '.') - -test.must_match('file.out', "file.in\n") - -test.up_to_date(options = '--cache-show --debug=explain', arguments = '.') - -test.sleep() - -test.touch('file.in') - -test.not_up_to_date(options = '--cache-show --debug=explain', arguments = '.') - -test.up_to_date(options = '--cache-show --debug=explain', arguments = '.') - -test.up_to_date(options = '--cache-show --debug=explain', 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/Deprecated/CacheDir/timestamp-timestamp.py b/test/Deprecated/CacheDir/timestamp-timestamp.py deleted file mode 100644 index eec70b5..0000000 --- a/test/Deprecated/CacheDir/timestamp-timestamp.py +++ /dev/null @@ -1,68 +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 CacheDir() works when using both SourceSignatures() -and TargetSignatures values of 'timestamp'. -""" - -import TestSCons - -test = TestSCons.TestSCons() - -test.write(['SConstruct'], """\ -SetOption('warn', 'no-deprecated') -SourceSignatures('timestamp') -TargetSignatures('timestamp') -CacheDir('cache') -Command('file.out', 'file.in', Copy('$TARGET', '$SOURCE')) -""") - -test.write('file.in', "file.in\n") - -test.run(arguments = '--cache-show --debug=explain .') - -test.must_match('file.out', "file.in\n") - -test.up_to_date(options = '--cache-show --debug=explain', arguments = '.') - -test.sleep() - -test.touch('file.in') - -test.not_up_to_date(options = '--cache-show --debug=explain', arguments = '.') - -test.up_to_date(options = '--cache-show --debug=explain', arguments = '.') - -test.up_to_date(options = '--cache-show --debug=explain', 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/Deprecated/SourceSignatures/basic.py b/test/Deprecated/SourceSignatures/basic.py deleted file mode 100644 index 7951dbd..0000000 --- a/test/Deprecated/SourceSignatures/basic.py +++ /dev/null @@ -1,131 +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 os -import re - -import TestSCons - -test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) - - -base_sconstruct_contents = """\ -SetOption('warn', 'deprecated-source-signatures') -def build(env, target, source): - with open(str(target[0]), 'wt') as ofp, open(str(source[0]), 'rt') as ifp: - ofp.write(ifp.read()) -B = Builder(action = build) -env = Environment(BUILDERS = { 'B' : B }) -env.B(target = 'f1.out', source = 'f1.in') -env.B(target = 'f2.out', source = 'f2.in') -env.B(target = 'f3.out', source = 'f3.in') -env.B(target = 'f4.out', source = 'f4.in') -""" - -def write_SConstruct(test, sigtype): - contents = base_sconstruct_contents - if sigtype: - contents = contents + ("\nSourceSignatures('%s')\n" % sigtype) - test.write('SConstruct', contents) - - -expect = TestSCons.re_escape(""" -scons: warning: The env.SourceSignatures() method is deprecated; -\tconvert your build to use the env.Decider() method instead. -""") + TestSCons.file_expr - -write_SConstruct(test, 'timestamp') - -test.write('f1.in', "f1.in\n") -test.write('f2.in', "f2.in\n") -test.write('f3.in', "f3.in\n") -test.write('f4.in', "f4.in\n") - -test.run(arguments = 'f1.out f3.out', stderr = expect) - -test.run(arguments = 'f1.out f2.out f3.out f4.out', - stdout = re.escape(test.wrap_stdout("""\ -scons: `f1.out' is up to date. -build(["f2.out"], ["f2.in"]) -scons: `f3.out' is up to date. -build(["f4.out"], ["f4.in"]) -""")), - stderr = expect) - - -os.utime(test.workpath('f1.in'), - (os.path.getatime(test.workpath('f1.in')), - os.path.getmtime(test.workpath('f1.in'))+10)) -os.utime(test.workpath('f3.in'), - (os.path.getatime(test.workpath('f3.in')), - os.path.getmtime(test.workpath('f3.in'))+10)) - -test.run(arguments = 'f1.out f2.out f3.out f4.out', - stdout = re.escape(test.wrap_stdout("""\ -build(["f1.out"], ["f1.in"]) -scons: `f2.out' is up to date. -build(["f3.out"], ["f3.in"]) -scons: `f4.out' is up to date. -""")), - stderr = expect) - - -# Switching to content signatures from timestamps should rebuild, -# because we didn't record the content signatures last time. - -write_SConstruct(test, 'MD5') - -test.not_up_to_date(arguments = 'f1.out f2.out f3.out f4.out', stderr = expect) - - -test.sleep() - -test.write('f1.in', "f1.in\n") -test.write('f2.in', "f2.in\n") -test.write('f3.in', "f3.in\n") -test.write('f4.in', "f4.in\n") - -test.up_to_date(arguments = 'f1.out f2.out f3.out f4.out', stderr = None) - - -test.touch('f1.in', os.path.getmtime(test.workpath('f1.in'))+10) -test.touch('f3.in', os.path.getmtime(test.workpath('f3.in'))+10) - -test.up_to_date(arguments = 'f1.out f2.out f3.out f4.out', stderr = None) - - -write_SConstruct(test, None) - -test.up_to_date(arguments = 'f1.out f2.out f3.out f4.out', stderr = None) - - -test.pass_test() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Deprecated/SourceSignatures/env.py b/test/Deprecated/SourceSignatures/env.py deleted file mode 100644 index c63b176..0000000 --- a/test/Deprecated/SourceSignatures/env.py +++ /dev/null @@ -1,109 +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__" - -""" -Test that use of env.SourceSignatures() correctly overrides the -default behavior. -""" - -import os -import re - -import TestSCons - -test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) - -base_sconstruct_contents = """\ -SetOption('warn', 'deprecated-source-signatures') -def build(env, target, source): - with open(str(target[0]), 'wt') as ofp, open(str(source[0]), 'rt') as ifp: - ofp.write(ifp.read()) -B = Builder(action = build) -env = Environment(BUILDERS = { 'B' : B }) -env2 = env.Clone() -env2.SourceSignatures('%s') -env.B(target = 'f1.out', source = 'f1.in') -env.B(target = 'f2.out', source = 'f2.in') -env2.B(target = 'f3.out', source = 'f3.in') -env2.B(target = 'f4.out', source = 'f4.in') - -SourceSignatures('%s') -""" - -def write_SConstruct(test, env_sigtype, default_sigtype): - contents = base_sconstruct_contents % (env_sigtype, default_sigtype) - test.write('SConstruct', contents) - - -expect = TestSCons.re_escape(""" -scons: warning: The env.SourceSignatures() method is deprecated; -\tconvert your build to use the env.Decider() method instead. -""") + TestSCons.file_expr - - -write_SConstruct(test, 'MD5', 'timestamp') - -test.write('f1.in', "f1.in\n") -test.write('f2.in', "f2.in\n") -test.write('f3.in', "f3.in\n") -test.write('f4.in', "f4.in\n") - -test.run(arguments = 'f1.out f3.out', stderr = expect) - -test.run(arguments = 'f1.out f2.out f3.out f4.out', - stdout = re.escape(test.wrap_stdout("""\ -scons: `f1.out' is up to date. -build(["f2.out"], ["f2.in"]) -scons: `f3.out' is up to date. -build(["f4.out"], ["f4.in"]) -""")), - stderr = expect) - - -test.sleep() - -test.touch('f1.in') -test.touch('f3.in') - -test.run(arguments = 'f1.out f2.out f3.out f4.out', - stdout = re.escape(test.wrap_stdout("""\ -build(["f1.out"], ["f1.in"]) -scons: `f2.out' is up to date. -scons: `f3.out' is up to date. -scons: `f4.out' is up to date. -""")), - stderr = expect) - -test.up_to_date(arguments = 'f1.out f2.out f3.out f4.out', stderr = None) - - -test.pass_test() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Deprecated/SourceSignatures/implicit-cache.py b/test/Deprecated/SourceSignatures/implicit-cache.py deleted file mode 100644 index a4bdc78..0000000 --- a/test/Deprecated/SourceSignatures/implicit-cache.py +++ /dev/null @@ -1,105 +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__" - -""" -Test the simultaneous use of implicit_cache and -SourceSignatures('timestamp') -""" - -import re - -import TestSCons - -test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) - -test.write('SConstruct', """\ -SetOption('warn', 'deprecated-source-signatures') -SetOption('implicit_cache', 1) -SourceSignatures('timestamp') - -def build(env, target, source): - with open(str(target[0]), 'wt') as ofp, open(str(source[0]), 'rt') as ifp: - ofp.write(ifp.read()) -B = Builder(action = build) -env = Environment(BUILDERS = { 'B' : B }) -env.B(target = 'both.out', source = 'both.in') -""") - - -expect = TestSCons.re_escape(""" -scons: warning: The env.SourceSignatures() method is deprecated; -\tconvert your build to use the env.Decider() method instead. -""") + TestSCons.file_expr - - -both_out_both_in = re.escape(test.wrap_stdout('build(["both.out"], ["both.in"])\n')) - -test.write('both.in', "both.in 1\n") - -test.run(arguments = 'both.out', - stdout = both_out_both_in, - stderr = expect) - - -test.sleep(2) - -test.write('both.in', "both.in 2\n") - -test.run(arguments = 'both.out', - stdout = both_out_both_in, - stderr = expect) - - -test.sleep(2) - -test.write('both.in', "both.in 3\n") - -test.run(arguments = 'both.out', - stdout = both_out_both_in, - stderr = expect) - - -test.sleep(2) - -test.write('both.in', "both.in 4\n") - -test.run(arguments = 'both.out', - stdout = both_out_both_in, - stderr = expect) - - -test.sleep(2) - -test.up_to_date(arguments = 'both.out', stderr = None) - - -test.pass_test() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Deprecated/SourceSignatures/no-csigs.py b/test/Deprecated/SourceSignatures/no-csigs.py deleted file mode 100644 index c4f2a78..0000000 --- a/test/Deprecated/SourceSignatures/no-csigs.py +++ /dev/null @@ -1,81 +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 os - -import TestSCons -import TestSConsign - -test = TestSConsign.TestSConsign(match = TestSConsign.match_re) - - -test.write('SConstruct', """\ -SetOption('warn', 'deprecated-source-signatures') -def build(env, target, source): - with open(str(target[0]), 'wt') as ofp, open(str(source[0]), 'rt') as ifp: - ofp.write(ifp.read()) -B = Builder(action = build) -env = Environment(BUILDERS = { 'B' : B }) -env.B(target = 'f1.out', source = 'f1.in') -env.B(target = 'f2.out', source = 'f2.in') -SourceSignatures('timestamp') -""") - -test.write('f1.in', "f1.in\n") -test.write('f2.in', "f2.in\n") - -expect = TestSCons.re_escape(""" -scons: warning: The env.SourceSignatures() method is deprecated; -\tconvert your build to use the env.Decider() method instead. -""") + TestSCons.file_expr - -test.run(arguments = '.', stderr = expect) - - -expect = r"""=== .: -SConstruct: None \d+ \d+ -f1.in: None \d+ \d+ -f1.out: \S+ \d+ \d+ - f1.in: None \d+ \d+ - \S+ \[build\(target, source, env\)\] -f2.in: None \d+ \d+ -f2.out: \S+ \d+ \d+ - f2.in: None \d+ \d+ - \S+ \[build\(target, source, env\)\] -""" - -test.run_sconsign(arguments = test.workpath('.sconsign'), - stdout = expect) - - -test.pass_test() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Deprecated/SourceSignatures/overrides.py b/test/Deprecated/SourceSignatures/overrides.py deleted file mode 100644 index 4303c0e..0000000 --- a/test/Deprecated/SourceSignatures/overrides.py +++ /dev/null @@ -1,68 +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__" - -""" -Make sure that SourceSignatures() works when overrides are used on a -Builder call. (Previous implementations used methods that would stay -bound to the underlying construction environment, which in this case -meant ignoring the 'timestamp' setting and still using the underlying -content signature.) -""" - -import TestSCons - -test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) - -expect = TestSCons.re_escape(""" -scons: warning: The env.SourceSignatures() method is deprecated; -\tconvert your build to use the env.Decider() method instead. -""") + TestSCons.file_expr - -test.write('SConstruct', """\ -SetOption('warn', 'deprecated-source-signatures') -DefaultEnvironment().SourceSignatures('MD5') -env = Environment() -env.SourceSignatures('timestamp') -env.Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'), FOO=1) -""") - -test.write('foo.in', "foo.in 1\n") - -test.run(arguments = 'foo.out', stderr = expect) - -test.sleep() - -test.write('foo.in', "foo.in 1\n") - -test.not_up_to_date(arguments = 'foo.out', stderr = expect) - -test.pass_test() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Deprecated/SourceSignatures/switch-rebuild.py b/test/Deprecated/SourceSignatures/switch-rebuild.py deleted file mode 100644 index b9cc3d5..0000000 --- a/test/Deprecated/SourceSignatures/switch-rebuild.py +++ /dev/null @@ -1,96 +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__" - -""" -Test that switching SourceSignature() types no longer causes rebuilds. -""" - -import re - -import TestSCons - -test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) - -expect = TestSCons.re_escape(""" -scons: warning: The env.SourceSignatures() method is deprecated; -\tconvert your build to use the env.Decider() method instead. -""") + TestSCons.file_expr - - -base_sconstruct_contents = """\ -SetOption('warn', 'deprecated-source-signatures') -SourceSignatures('%s') - -def build(env, target, source): - with open(str(target[0]), 'wt') as ofp, open(str(source[0]), 'rt') as ifp: - ofp.write(ifp.read()) -B = Builder(action = build) -env = Environment(BUILDERS = { 'B' : B }) -env.B(target = 'switch.out', source = 'switch.in') -""" - -def write_SConstruct(test, sig_type): - contents = base_sconstruct_contents % sig_type - test.write('SConstruct', contents) - - -write_SConstruct(test, 'MD5') - -test.write('switch.in', "switch.in\n") - -switch_out_switch_in = re.escape(test.wrap_stdout('build(["switch.out"], ["switch.in"])\n')) - -test.run(arguments = 'switch.out', - stdout = switch_out_switch_in, - stderr = expect) - -test.up_to_date(arguments = 'switch.out', stderr = None) - - -write_SConstruct(test, 'timestamp') - -test.up_to_date(arguments = 'switch.out', stderr = None) - - -write_SConstruct(test, 'MD5') - -test.not_up_to_date(arguments = 'switch.out', stderr = None) - - -test.write('switch.in', "switch.in 2\n") - -test.run(arguments = 'switch.out', - stdout = switch_out_switch_in, - stderr = expect) - - -test.pass_test() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Deprecated/TargetSignatures/build-content.py b/test/Deprecated/TargetSignatures/build-content.py deleted file mode 100644 index efdaaee..0000000 --- a/test/Deprecated/TargetSignatures/build-content.py +++ /dev/null @@ -1,142 +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 basic interaction of the historic TargetSignatures('build') -and TargetSignatures('content') settings, overriding one with -the other in specific construction environments. -""" - -import re - -import TestSCons - -test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) - -expect = TestSCons.re_escape(""" -scons: warning: The env.TargetSignatures() method is deprecated; -\tconvert your build to use the env.Decider() method instead. -""") + TestSCons.file_expr - - -sconstruct_contents = """\ -SetOption('warn', 'deprecated-target-signatures') -env = Environment() - -def copy1(env, source, target): - with open(str(target[0]), 'wb') as fo, open(str(source[0]), 'rb') as fi: - fo.write(fi.read()) - -def copy2(env, source, target): - %s - return copy1(env, source, target) - -env['BUILDERS']['Copy1'] = Builder(action=copy1) -env['BUILDERS']['Copy2'] = Builder(action=copy2) - -env.Copy2('foo.mid', 'foo.in') -env.Copy1('foo.out', 'foo.mid') - -env2 = env.Clone() -env2.TargetSignatures('%s') -env2.Copy2('bar.mid', 'bar.in') -env2.Copy1('bar.out', 'bar.mid') - -TargetSignatures('%s') -""" - -def write_SConstruct(test, *args): - contents = sconstruct_contents % args - test.write('SConstruct', contents) - - - -write_SConstruct(test, '', 'build', 'content') - -test.write('foo.in', 'foo.in') -test.write('bar.in', 'bar.in') - -test.run(arguments="bar.out foo.out", - stdout=re.escape(test.wrap_stdout("""\ -copy2(["bar.mid"], ["bar.in"]) -copy1(["bar.out"], ["bar.mid"]) -copy2(["foo.mid"], ["foo.in"]) -copy1(["foo.out"], ["foo.mid"]) -""")), - stderr = expect) - -test.up_to_date(arguments='bar.out foo.out', stderr=None) - - - -# Change the code in the the copy2() function, which should change -# its content and trigger a rebuild of the targets built with it. - -write_SConstruct(test, 'x = 2 # added this line', 'build', 'content') - -test.run(arguments="bar.out foo.out", - stdout=re.escape(test.wrap_stdout("""\ -copy2(["bar.mid"], ["bar.in"]) -copy1(["bar.out"], ["bar.mid"]) -copy2(["foo.mid"], ["foo.in"]) -scons: `foo.out' is up to date. -""")), - stderr = expect) - - - -# Swapping content and build signatures no longer causes a rebuild -# because we record the right underlying information regardless. - -write_SConstruct(test, 'x = 2 # added this line', 'content', 'build') - -test.up_to_date(arguments="bar.out foo.out", stderr=None) - - - -# Change the code in the the copy2() function back again, which should -# trigger another rebuild of the targets built with it. - -write_SConstruct(test, '', 'content', 'build') - -test.run(arguments='bar.out foo.out', - stdout=re.escape(test.wrap_stdout("""\ -copy2(["bar.mid"], ["bar.in"]) -scons: `bar.out' is up to date. -copy2(["foo.mid"], ["foo.in"]) -copy1(["foo.out"], ["foo.mid"]) -""")), - stderr = expect) - - - -test.pass_test() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Deprecated/TargetSignatures/content.py b/test/Deprecated/TargetSignatures/content.py deleted file mode 100644 index aca63f3..0000000 --- a/test/Deprecated/TargetSignatures/content.py +++ /dev/null @@ -1,95 +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 use of the TargetSignatures('content') setting to override -SourceSignatures('timestamp') settings. -""" - -import TestSCons - -test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) - -expect = TestSCons.re_escape(""" -scons: warning: The env.SourceSignatures() method is deprecated; -\tconvert your build to use the env.Decider() method instead. -""") + TestSCons.file_expr + TestSCons.re_escape(""" -scons: warning: The env.TargetSignatures() method is deprecated; -\tconvert your build to use the env.Decider() method instead. -""") + TestSCons.file_expr - - -test.write('SConstruct', """\ -SetOption('warn', 'deprecated-source-signatures') -SetOption('warn', 'deprecated-target-signatures') -env = Environment() - -def copy(env, source, target): - with open(str(target[0]), 'wb') as ofp: - for s in source: - with open(str(s), 'rb') as ifp: - ofp.write(ifp.read()) - -copyAction = Action(copy, "Copying $TARGET") - -SourceSignatures('timestamp') - -env['BUILDERS']['Copy'] = Builder(action=copyAction) - -env.Copy('foo.out', 'foo.in') - -env2 = env.Clone() -env2.TargetSignatures('content') -env2.Copy('bar.out', 'bar.in') -AlwaysBuild('bar.out') - -env.Copy('final', ['foo.out', 'bar.out', 'extra.in']) -env.Ignore('final', 'extra.in') -""") - -test.write('foo.in', "foo.in\n") -test.write('bar.in', "bar.in\n") -test.write('extra.in', "extra.in 1\n") - -test.run(stderr = expect) - -test.must_match('final', "foo.in\nbar.in\nextra.in 1\n") - -test.sleep() -test.write('extra.in', "extra.in 2\n") - -test.run(stderr = expect) - -test.must_match('final', "foo.in\nbar.in\nextra.in 1\n") - - -test.pass_test() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Deprecated/TargetSignatures/overrides.py b/test/Deprecated/TargetSignatures/overrides.py deleted file mode 100644 index 54a66d4..0000000 --- a/test/Deprecated/TargetSignatures/overrides.py +++ /dev/null @@ -1,64 +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__" - -""" -Make sure that TargetSignatures() works when overrides are used on a -Builder call. Previous implementations used methods that would stay -bound to the underlying construction environment and cause weird -behavior like infinite recursion. -""" - -import TestSCons - -test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) - -test.write('SConstruct', """\ -SetOption('warn', 'deprecated-target-signatures') -env = Environment() -env.TargetSignatures('content') -env.Command('foo.out', 'foo.mid', Copy('$TARGET', '$SOURCE'), FOO=1) -env.Command('foo.mid', 'foo.in', Copy('$TARGET', '$SOURCE'), FOO=2) -""") - -test.write('foo.in', "foo.in\n") - -expect = TestSCons.re_escape(""" -scons: warning: The env.TargetSignatures() method is deprecated; -\tconvert your build to use the env.Decider() method instead. -""") + TestSCons.file_expr - -test.run(arguments = '.', stderr = expect) - -test.must_match('foo.mid', "foo.in\n") -test.must_match('foo.out', "foo.in\n") - -test.pass_test() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Removed/CacheDir/Old/sconstest.skip b/test/Removed/CacheDir/Old/sconstest.skip new file mode 100644 index 0000000..e69de29 diff --git a/test/Removed/CacheDir/Old/timestamp-content.py b/test/Removed/CacheDir/Old/timestamp-content.py new file mode 100644 index 0000000..860d0f3 --- /dev/null +++ b/test/Removed/CacheDir/Old/timestamp-content.py @@ -0,0 +1,68 @@ +#!/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 CacheDir() works when using SourceSignatures('timestamp') +and TargetSignatures 'content'. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """ +SetOption('warn', 'no-deprecated') +SourceSignatures('timestamp') +TargetSignatures('content') +CacheDir('cache') +Command('file.out', 'file.in', Copy('$TARGET', '$SOURCE')) +""") + +test.write('file.in', "file.in\n") + +test.run(arguments = '.') + +test.must_match('file.out', "file.in\n") + +test.up_to_date(options = '--cache-show --debug=explain', arguments = '.') + +test.sleep() + +test.touch('file.in') + +test.not_up_to_date(options = '--cache-show --debug=explain', arguments = '.') + +test.up_to_date(options = '--cache-show --debug=explain', arguments = '.') + +test.up_to_date(options = '--cache-show --debug=explain', 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/Removed/CacheDir/Old/timestamp-timestamp.py b/test/Removed/CacheDir/Old/timestamp-timestamp.py new file mode 100644 index 0000000..eec70b5 --- /dev/null +++ b/test/Removed/CacheDir/Old/timestamp-timestamp.py @@ -0,0 +1,68 @@ +#!/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 CacheDir() works when using both SourceSignatures() +and TargetSignatures values of 'timestamp'. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write(['SConstruct'], """\ +SetOption('warn', 'no-deprecated') +SourceSignatures('timestamp') +TargetSignatures('timestamp') +CacheDir('cache') +Command('file.out', 'file.in', Copy('$TARGET', '$SOURCE')) +""") + +test.write('file.in', "file.in\n") + +test.run(arguments = '--cache-show --debug=explain .') + +test.must_match('file.out', "file.in\n") + +test.up_to_date(options = '--cache-show --debug=explain', arguments = '.') + +test.sleep() + +test.touch('file.in') + +test.not_up_to_date(options = '--cache-show --debug=explain', arguments = '.') + +test.up_to_date(options = '--cache-show --debug=explain', arguments = '.') + +test.up_to_date(options = '--cache-show --debug=explain', 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/Removed/CacheDir/README.md b/test/Removed/CacheDir/README.md new file mode 100644 index 0000000..c5b75bf --- /dev/null +++ b/test/Removed/CacheDir/README.md @@ -0,0 +1,4 @@ +CacheDir/Old contains old tests of CacheDir which used the now removed +SourceSignatures and TargetSignatures methods, preserved here for +reference; the presence of an scontest.skip file means they are never +executed. diff --git a/test/Removed/SourceSignatures/Old/basic.py b/test/Removed/SourceSignatures/Old/basic.py new file mode 100644 index 0000000..7951dbd --- /dev/null +++ b/test/Removed/SourceSignatures/Old/basic.py @@ -0,0 +1,131 @@ +#!/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 os +import re + +import TestSCons + +test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) + + +base_sconstruct_contents = """\ +SetOption('warn', 'deprecated-source-signatures') +def build(env, target, source): + with open(str(target[0]), 'wt') as ofp, open(str(source[0]), 'rt') as ifp: + ofp.write(ifp.read()) +B = Builder(action = build) +env = Environment(BUILDERS = { 'B' : B }) +env.B(target = 'f1.out', source = 'f1.in') +env.B(target = 'f2.out', source = 'f2.in') +env.B(target = 'f3.out', source = 'f3.in') +env.B(target = 'f4.out', source = 'f4.in') +""" + +def write_SConstruct(test, sigtype): + contents = base_sconstruct_contents + if sigtype: + contents = contents + ("\nSourceSignatures('%s')\n" % sigtype) + test.write('SConstruct', contents) + + +expect = TestSCons.re_escape(""" +scons: warning: The env.SourceSignatures() method is deprecated; +\tconvert your build to use the env.Decider() method instead. +""") + TestSCons.file_expr + +write_SConstruct(test, 'timestamp') + +test.write('f1.in', "f1.in\n") +test.write('f2.in', "f2.in\n") +test.write('f3.in', "f3.in\n") +test.write('f4.in', "f4.in\n") + +test.run(arguments = 'f1.out f3.out', stderr = expect) + +test.run(arguments = 'f1.out f2.out f3.out f4.out', + stdout = re.escape(test.wrap_stdout("""\ +scons: `f1.out' is up to date. +build(["f2.out"], ["f2.in"]) +scons: `f3.out' is up to date. +build(["f4.out"], ["f4.in"]) +""")), + stderr = expect) + + +os.utime(test.workpath('f1.in'), + (os.path.getatime(test.workpath('f1.in')), + os.path.getmtime(test.workpath('f1.in'))+10)) +os.utime(test.workpath('f3.in'), + (os.path.getatime(test.workpath('f3.in')), + os.path.getmtime(test.workpath('f3.in'))+10)) + +test.run(arguments = 'f1.out f2.out f3.out f4.out', + stdout = re.escape(test.wrap_stdout("""\ +build(["f1.out"], ["f1.in"]) +scons: `f2.out' is up to date. +build(["f3.out"], ["f3.in"]) +scons: `f4.out' is up to date. +""")), + stderr = expect) + + +# Switching to content signatures from timestamps should rebuild, +# because we didn't record the content signatures last time. + +write_SConstruct(test, 'MD5') + +test.not_up_to_date(arguments = 'f1.out f2.out f3.out f4.out', stderr = expect) + + +test.sleep() + +test.write('f1.in', "f1.in\n") +test.write('f2.in', "f2.in\n") +test.write('f3.in', "f3.in\n") +test.write('f4.in', "f4.in\n") + +test.up_to_date(arguments = 'f1.out f2.out f3.out f4.out', stderr = None) + + +test.touch('f1.in', os.path.getmtime(test.workpath('f1.in'))+10) +test.touch('f3.in', os.path.getmtime(test.workpath('f3.in'))+10) + +test.up_to_date(arguments = 'f1.out f2.out f3.out f4.out', stderr = None) + + +write_SConstruct(test, None) + +test.up_to_date(arguments = 'f1.out f2.out f3.out f4.out', stderr = None) + + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Removed/SourceSignatures/Old/env.py b/test/Removed/SourceSignatures/Old/env.py new file mode 100644 index 0000000..c63b176 --- /dev/null +++ b/test/Removed/SourceSignatures/Old/env.py @@ -0,0 +1,109 @@ +#!/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__" + +""" +Test that use of env.SourceSignatures() correctly overrides the +default behavior. +""" + +import os +import re + +import TestSCons + +test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) + +base_sconstruct_contents = """\ +SetOption('warn', 'deprecated-source-signatures') +def build(env, target, source): + with open(str(target[0]), 'wt') as ofp, open(str(source[0]), 'rt') as ifp: + ofp.write(ifp.read()) +B = Builder(action = build) +env = Environment(BUILDERS = { 'B' : B }) +env2 = env.Clone() +env2.SourceSignatures('%s') +env.B(target = 'f1.out', source = 'f1.in') +env.B(target = 'f2.out', source = 'f2.in') +env2.B(target = 'f3.out', source = 'f3.in') +env2.B(target = 'f4.out', source = 'f4.in') + +SourceSignatures('%s') +""" + +def write_SConstruct(test, env_sigtype, default_sigtype): + contents = base_sconstruct_contents % (env_sigtype, default_sigtype) + test.write('SConstruct', contents) + + +expect = TestSCons.re_escape(""" +scons: warning: The env.SourceSignatures() method is deprecated; +\tconvert your build to use the env.Decider() method instead. +""") + TestSCons.file_expr + + +write_SConstruct(test, 'MD5', 'timestamp') + +test.write('f1.in', "f1.in\n") +test.write('f2.in', "f2.in\n") +test.write('f3.in', "f3.in\n") +test.write('f4.in', "f4.in\n") + +test.run(arguments = 'f1.out f3.out', stderr = expect) + +test.run(arguments = 'f1.out f2.out f3.out f4.out', + stdout = re.escape(test.wrap_stdout("""\ +scons: `f1.out' is up to date. +build(["f2.out"], ["f2.in"]) +scons: `f3.out' is up to date. +build(["f4.out"], ["f4.in"]) +""")), + stderr = expect) + + +test.sleep() + +test.touch('f1.in') +test.touch('f3.in') + +test.run(arguments = 'f1.out f2.out f3.out f4.out', + stdout = re.escape(test.wrap_stdout("""\ +build(["f1.out"], ["f1.in"]) +scons: `f2.out' is up to date. +scons: `f3.out' is up to date. +scons: `f4.out' is up to date. +""")), + stderr = expect) + +test.up_to_date(arguments = 'f1.out f2.out f3.out f4.out', stderr = None) + + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Removed/SourceSignatures/Old/implicit-cache.py b/test/Removed/SourceSignatures/Old/implicit-cache.py new file mode 100644 index 0000000..a4bdc78 --- /dev/null +++ b/test/Removed/SourceSignatures/Old/implicit-cache.py @@ -0,0 +1,105 @@ +#!/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__" + +""" +Test the simultaneous use of implicit_cache and +SourceSignatures('timestamp') +""" + +import re + +import TestSCons + +test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) + +test.write('SConstruct', """\ +SetOption('warn', 'deprecated-source-signatures') +SetOption('implicit_cache', 1) +SourceSignatures('timestamp') + +def build(env, target, source): + with open(str(target[0]), 'wt') as ofp, open(str(source[0]), 'rt') as ifp: + ofp.write(ifp.read()) +B = Builder(action = build) +env = Environment(BUILDERS = { 'B' : B }) +env.B(target = 'both.out', source = 'both.in') +""") + + +expect = TestSCons.re_escape(""" +scons: warning: The env.SourceSignatures() method is deprecated; +\tconvert your build to use the env.Decider() method instead. +""") + TestSCons.file_expr + + +both_out_both_in = re.escape(test.wrap_stdout('build(["both.out"], ["both.in"])\n')) + +test.write('both.in', "both.in 1\n") + +test.run(arguments = 'both.out', + stdout = both_out_both_in, + stderr = expect) + + +test.sleep(2) + +test.write('both.in', "both.in 2\n") + +test.run(arguments = 'both.out', + stdout = both_out_both_in, + stderr = expect) + + +test.sleep(2) + +test.write('both.in', "both.in 3\n") + +test.run(arguments = 'both.out', + stdout = both_out_both_in, + stderr = expect) + + +test.sleep(2) + +test.write('both.in', "both.in 4\n") + +test.run(arguments = 'both.out', + stdout = both_out_both_in, + stderr = expect) + + +test.sleep(2) + +test.up_to_date(arguments = 'both.out', stderr = None) + + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Removed/SourceSignatures/Old/no-csigs.py b/test/Removed/SourceSignatures/Old/no-csigs.py new file mode 100644 index 0000000..c4f2a78 --- /dev/null +++ b/test/Removed/SourceSignatures/Old/no-csigs.py @@ -0,0 +1,81 @@ + +#!/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 os + +import TestSCons +import TestSConsign + +test = TestSConsign.TestSConsign(match = TestSConsign.match_re) + + +test.write('SConstruct', """\ +SetOption('warn', 'deprecated-source-signatures') +def build(env, target, source): + with open(str(target[0]), 'wt') as ofp, open(str(source[0]), 'rt') as ifp: + ofp.write(ifp.read()) +B = Builder(action = build) +env = Environment(BUILDERS = { 'B' : B }) +env.B(target = 'f1.out', source = 'f1.in') +env.B(target = 'f2.out', source = 'f2.in') +SourceSignatures('timestamp') +""") + +test.write('f1.in', "f1.in\n") +test.write('f2.in', "f2.in\n") + +expect = TestSCons.re_escape(""" +scons: warning: The env.SourceSignatures() method is deprecated; +\tconvert your build to use the env.Decider() method instead. +""") + TestSCons.file_expr + +test.run(arguments = '.', stderr = expect) + + +expect = r"""=== .: +SConstruct: None \d+ \d+ +f1.in: None \d+ \d+ +f1.out: \S+ \d+ \d+ + f1.in: None \d+ \d+ + \S+ \[build\(target, source, env\)\] +f2.in: None \d+ \d+ +f2.out: \S+ \d+ \d+ + f2.in: None \d+ \d+ + \S+ \[build\(target, source, env\)\] +""" + +test.run_sconsign(arguments = test.workpath('.sconsign'), + stdout = expect) + + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Removed/SourceSignatures/Old/overrides.py b/test/Removed/SourceSignatures/Old/overrides.py new file mode 100644 index 0000000..4303c0e --- /dev/null +++ b/test/Removed/SourceSignatures/Old/overrides.py @@ -0,0 +1,68 @@ +#!/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__" + +""" +Make sure that SourceSignatures() works when overrides are used on a +Builder call. (Previous implementations used methods that would stay +bound to the underlying construction environment, which in this case +meant ignoring the 'timestamp' setting and still using the underlying +content signature.) +""" + +import TestSCons + +test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) + +expect = TestSCons.re_escape(""" +scons: warning: The env.SourceSignatures() method is deprecated; +\tconvert your build to use the env.Decider() method instead. +""") + TestSCons.file_expr + +test.write('SConstruct', """\ +SetOption('warn', 'deprecated-source-signatures') +DefaultEnvironment().SourceSignatures('MD5') +env = Environment() +env.SourceSignatures('timestamp') +env.Command('foo.out', 'foo.in', Copy('$TARGET', '$SOURCE'), FOO=1) +""") + +test.write('foo.in', "foo.in 1\n") + +test.run(arguments = 'foo.out', stderr = expect) + +test.sleep() + +test.write('foo.in', "foo.in 1\n") + +test.not_up_to_date(arguments = 'foo.out', stderr = expect) + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Removed/SourceSignatures/Old/sconstest.skip b/test/Removed/SourceSignatures/Old/sconstest.skip new file mode 100644 index 0000000..e69de29 diff --git a/test/Removed/SourceSignatures/Old/switch-rebuild.py b/test/Removed/SourceSignatures/Old/switch-rebuild.py new file mode 100644 index 0000000..b9cc3d5 --- /dev/null +++ b/test/Removed/SourceSignatures/Old/switch-rebuild.py @@ -0,0 +1,96 @@ +#!/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__" + +""" +Test that switching SourceSignature() types no longer causes rebuilds. +""" + +import re + +import TestSCons + +test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) + +expect = TestSCons.re_escape(""" +scons: warning: The env.SourceSignatures() method is deprecated; +\tconvert your build to use the env.Decider() method instead. +""") + TestSCons.file_expr + + +base_sconstruct_contents = """\ +SetOption('warn', 'deprecated-source-signatures') +SourceSignatures('%s') + +def build(env, target, source): + with open(str(target[0]), 'wt') as ofp, open(str(source[0]), 'rt') as ifp: + ofp.write(ifp.read()) +B = Builder(action = build) +env = Environment(BUILDERS = { 'B' : B }) +env.B(target = 'switch.out', source = 'switch.in') +""" + +def write_SConstruct(test, sig_type): + contents = base_sconstruct_contents % sig_type + test.write('SConstruct', contents) + + +write_SConstruct(test, 'MD5') + +test.write('switch.in', "switch.in\n") + +switch_out_switch_in = re.escape(test.wrap_stdout('build(["switch.out"], ["switch.in"])\n')) + +test.run(arguments = 'switch.out', + stdout = switch_out_switch_in, + stderr = expect) + +test.up_to_date(arguments = 'switch.out', stderr = None) + + +write_SConstruct(test, 'timestamp') + +test.up_to_date(arguments = 'switch.out', stderr = None) + + +write_SConstruct(test, 'MD5') + +test.not_up_to_date(arguments = 'switch.out', stderr = None) + + +test.write('switch.in', "switch.in 2\n") + +test.run(arguments = 'switch.out', + stdout = switch_out_switch_in, + stderr = expect) + + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Removed/SourceSignatures/README.md b/test/Removed/SourceSignatures/README.md new file mode 100644 index 0000000..05d8d05 --- /dev/null +++ b/test/Removed/SourceSignatures/README.md @@ -0,0 +1,6 @@ +SourceSignatures.py is the "new" test, only makes sure scons actually +fails in the presence of the method or setoption call. + +The Old directory is the former tests from the deprecated state, +preserved here for reference; the presence of an scontest.skip file +means they are never executed. diff --git a/test/Removed/SourceSignatures/SConstruct.method b/test/Removed/SourceSignatures/SConstruct.method new file mode 100644 index 0000000..e68d6bf --- /dev/null +++ b/test/Removed/SourceSignatures/SConstruct.method @@ -0,0 +1 @@ +SourceSignatures('MD5') diff --git a/test/Removed/SourceSignatures/SConstruct.setopt b/test/Removed/SourceSignatures/SConstruct.setopt new file mode 100644 index 0000000..6e1161f --- /dev/null +++ b/test/Removed/SourceSignatures/SConstruct.setopt @@ -0,0 +1 @@ +SetOption('warn', 'deprecated-source-signatures') diff --git a/test/Removed/SourceSignatures/SourceSignatures.py b/test/Removed/SourceSignatures/SourceSignatures.py new file mode 100644 index 0000000..fcc5e43 --- /dev/null +++ b/test/Removed/SourceSignatures/SourceSignatures.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__" + +""" +Test that SourceSignatures and its associated warning flag +are definitely gone. +""" + +import TestSCons + +test = TestSCons.TestSCons(match=TestSCons.match_re_dotall) + +test.file_fixture('SConstruct.method', 'SConstruct') +test.run(arguments='-Q -s', status=2, stdout=None, + stderr="""\ +NameError: name 'SourceSignatures' is not defined: + File ".+SConstruct", line 1: + SourceSignatures('MD5') +""") + +test.file_fixture('SConstruct.setopt', 'SConstruct') +test.run(arguments='-Q -s', status=0, stdout=None, + stderr="""\ +No warning type: 'deprecated-source-signatures' +No warning type: 'deprecated-source-signatures' +""") + +test.pass_test() + diff --git a/test/Removed/TargetSignatures/Old/build-content.py b/test/Removed/TargetSignatures/Old/build-content.py new file mode 100644 index 0000000..efdaaee --- /dev/null +++ b/test/Removed/TargetSignatures/Old/build-content.py @@ -0,0 +1,142 @@ +#!/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 basic interaction of the historic TargetSignatures('build') +and TargetSignatures('content') settings, overriding one with +the other in specific construction environments. +""" + +import re + +import TestSCons + +test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) + +expect = TestSCons.re_escape(""" +scons: warning: The env.TargetSignatures() method is deprecated; +\tconvert your build to use the env.Decider() method instead. +""") + TestSCons.file_expr + + +sconstruct_contents = """\ +SetOption('warn', 'deprecated-target-signatures') +env = Environment() + +def copy1(env, source, target): + with open(str(target[0]), 'wb') as fo, open(str(source[0]), 'rb') as fi: + fo.write(fi.read()) + +def copy2(env, source, target): + %s + return copy1(env, source, target) + +env['BUILDERS']['Copy1'] = Builder(action=copy1) +env['BUILDERS']['Copy2'] = Builder(action=copy2) + +env.Copy2('foo.mid', 'foo.in') +env.Copy1('foo.out', 'foo.mid') + +env2 = env.Clone() +env2.TargetSignatures('%s') +env2.Copy2('bar.mid', 'bar.in') +env2.Copy1('bar.out', 'bar.mid') + +TargetSignatures('%s') +""" + +def write_SConstruct(test, *args): + contents = sconstruct_contents % args + test.write('SConstruct', contents) + + + +write_SConstruct(test, '', 'build', 'content') + +test.write('foo.in', 'foo.in') +test.write('bar.in', 'bar.in') + +test.run(arguments="bar.out foo.out", + stdout=re.escape(test.wrap_stdout("""\ +copy2(["bar.mid"], ["bar.in"]) +copy1(["bar.out"], ["bar.mid"]) +copy2(["foo.mid"], ["foo.in"]) +copy1(["foo.out"], ["foo.mid"]) +""")), + stderr = expect) + +test.up_to_date(arguments='bar.out foo.out', stderr=None) + + + +# Change the code in the the copy2() function, which should change +# its content and trigger a rebuild of the targets built with it. + +write_SConstruct(test, 'x = 2 # added this line', 'build', 'content') + +test.run(arguments="bar.out foo.out", + stdout=re.escape(test.wrap_stdout("""\ +copy2(["bar.mid"], ["bar.in"]) +copy1(["bar.out"], ["bar.mid"]) +copy2(["foo.mid"], ["foo.in"]) +scons: `foo.out' is up to date. +""")), + stderr = expect) + + + +# Swapping content and build signatures no longer causes a rebuild +# because we record the right underlying information regardless. + +write_SConstruct(test, 'x = 2 # added this line', 'content', 'build') + +test.up_to_date(arguments="bar.out foo.out", stderr=None) + + + +# Change the code in the the copy2() function back again, which should +# trigger another rebuild of the targets built with it. + +write_SConstruct(test, '', 'content', 'build') + +test.run(arguments='bar.out foo.out', + stdout=re.escape(test.wrap_stdout("""\ +copy2(["bar.mid"], ["bar.in"]) +scons: `bar.out' is up to date. +copy2(["foo.mid"], ["foo.in"]) +copy1(["foo.out"], ["foo.mid"]) +""")), + stderr = expect) + + + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Removed/TargetSignatures/Old/content.py b/test/Removed/TargetSignatures/Old/content.py new file mode 100644 index 0000000..aca63f3 --- /dev/null +++ b/test/Removed/TargetSignatures/Old/content.py @@ -0,0 +1,95 @@ +#!/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 use of the TargetSignatures('content') setting to override +SourceSignatures('timestamp') settings. +""" + +import TestSCons + +test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) + +expect = TestSCons.re_escape(""" +scons: warning: The env.SourceSignatures() method is deprecated; +\tconvert your build to use the env.Decider() method instead. +""") + TestSCons.file_expr + TestSCons.re_escape(""" +scons: warning: The env.TargetSignatures() method is deprecated; +\tconvert your build to use the env.Decider() method instead. +""") + TestSCons.file_expr + + +test.write('SConstruct', """\ +SetOption('warn', 'deprecated-source-signatures') +SetOption('warn', 'deprecated-target-signatures') +env = Environment() + +def copy(env, source, target): + with open(str(target[0]), 'wb') as ofp: + for s in source: + with open(str(s), 'rb') as ifp: + ofp.write(ifp.read()) + +copyAction = Action(copy, "Copying $TARGET") + +SourceSignatures('timestamp') + +env['BUILDERS']['Copy'] = Builder(action=copyAction) + +env.Copy('foo.out', 'foo.in') + +env2 = env.Clone() +env2.TargetSignatures('content') +env2.Copy('bar.out', 'bar.in') +AlwaysBuild('bar.out') + +env.Copy('final', ['foo.out', 'bar.out', 'extra.in']) +env.Ignore('final', 'extra.in') +""") + +test.write('foo.in', "foo.in\n") +test.write('bar.in', "bar.in\n") +test.write('extra.in', "extra.in 1\n") + +test.run(stderr = expect) + +test.must_match('final', "foo.in\nbar.in\nextra.in 1\n") + +test.sleep() +test.write('extra.in', "extra.in 2\n") + +test.run(stderr = expect) + +test.must_match('final', "foo.in\nbar.in\nextra.in 1\n") + + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Removed/TargetSignatures/Old/overrides.py b/test/Removed/TargetSignatures/Old/overrides.py new file mode 100644 index 0000000..54a66d4 --- /dev/null +++ b/test/Removed/TargetSignatures/Old/overrides.py @@ -0,0 +1,64 @@ +#!/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__" + +""" +Make sure that TargetSignatures() works when overrides are used on a +Builder call. Previous implementations used methods that would stay +bound to the underlying construction environment and cause weird +behavior like infinite recursion. +""" + +import TestSCons + +test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) + +test.write('SConstruct', """\ +SetOption('warn', 'deprecated-target-signatures') +env = Environment() +env.TargetSignatures('content') +env.Command('foo.out', 'foo.mid', Copy('$TARGET', '$SOURCE'), FOO=1) +env.Command('foo.mid', 'foo.in', Copy('$TARGET', '$SOURCE'), FOO=2) +""") + +test.write('foo.in', "foo.in\n") + +expect = TestSCons.re_escape(""" +scons: warning: The env.TargetSignatures() method is deprecated; +\tconvert your build to use the env.Decider() method instead. +""") + TestSCons.file_expr + +test.run(arguments = '.', stderr = expect) + +test.must_match('foo.mid', "foo.in\n") +test.must_match('foo.out', "foo.in\n") + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Removed/TargetSignatures/Old/sconstest.skip b/test/Removed/TargetSignatures/Old/sconstest.skip new file mode 100644 index 0000000..e69de29 diff --git a/test/Removed/TargetSignatures/README.md b/test/Removed/TargetSignatures/README.md new file mode 100644 index 0000000..00a8b6b --- /dev/null +++ b/test/Removed/TargetSignatures/README.md @@ -0,0 +1,6 @@ +TargetSignatures.py is the "new" test, only makes sure scons actually +fails in the presence of the method or setoption call. + +The Old directory is the former tests from the deprecated state, +preserved here for reference; the presence of an scontest.skip file +means they are never executed. diff --git a/test/Removed/TargetSignatures/SConstruct.method b/test/Removed/TargetSignatures/SConstruct.method new file mode 100644 index 0000000..5e974b6 --- /dev/null +++ b/test/Removed/TargetSignatures/SConstruct.method @@ -0,0 +1 @@ +TargetSignatures('MD5') diff --git a/test/Removed/TargetSignatures/SConstruct.setopt b/test/Removed/TargetSignatures/SConstruct.setopt new file mode 100644 index 0000000..c887ce4 --- /dev/null +++ b/test/Removed/TargetSignatures/SConstruct.setopt @@ -0,0 +1 @@ +SetOption('warn', 'deprecated-target-signatures') diff --git a/test/Removed/TargetSignatures/TargetSignatures.py b/test/Removed/TargetSignatures/TargetSignatures.py new file mode 100644 index 0000000..0b3a37b --- /dev/null +++ b/test/Removed/TargetSignatures/TargetSignatures.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__" + +""" +Test that TargetSignatures and its associated warning flag +are definitely gone. +""" + +import TestSCons + +test = TestSCons.TestSCons(match=TestSCons.match_re_dotall) + +test.file_fixture('SConstruct.method', 'SConstruct') +test.run(arguments='-Q -s', status=2, stdout=None, + stderr="""\ +NameError: name 'TargetSignatures' is not defined: + File ".+SConstruct", line 1: + TargetSignatures('MD5') +""") + +test.file_fixture('SConstruct.setopt', 'SConstruct') +test.run(arguments="-Q -s", status=0, stdout=None, + stderr="""\ +No warning type: 'deprecated-target-signatures' +No warning type: 'deprecated-target-signatures' +""") + +test.pass_test() + diff --git a/test/implicit-cache/basic.py b/test/implicit-cache/basic.py index c03a320..7eece88 100644 --- a/test/implicit-cache/basic.py +++ b/test/implicit-cache/basic.py @@ -27,11 +27,8 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" """ Verify basic interactions of the --implicit-cache-* options. -This test used to set TargetSignatures('build') because we were -relying on the old behavior of non-essential changes in .h files -propagate to cause a rebuilt executable. We now just rely on -the default Decider('content') behavior and only check for the -rebuild of the object file itself when necessary. +We rely on the default Decider('content') behavior and only +check for the rebuild of the object file itself when necessary. """ import os.path diff --git a/test/sconsign/script/Signatures.py b/test/sconsign/script/Signatures.py index 24ffaf7..34737d5 100644 --- a/test/sconsign/script/Signatures.py +++ b/test/sconsign/script/Signatures.py @@ -28,9 +28,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" Verify that the sconsign script works when using a .sconsign file in each subdirectory (SConsignFile(None)) written with the non-default value of Decider('timestamp-newer'). - -This used to test the non-default combination of -SourceSignatures('timestamp') with TargetSignatures('content'). """ import TestSCons diff --git a/test/srcchange.py b/test/srcchange.py index f1f67c1..c2356b6 100644 --- a/test/srcchange.py +++ b/test/srcchange.py @@ -29,9 +29,8 @@ Test changing the C source files based on an always-executed revision extraction and substitution. This makes sure we evaluate the content of intermediate files as -expected. We used to configure this explicitly using -TargetSignatures('content') but we now rely on the default behavior -being the equivalent of Decider('content'). +expected. This relies on the default behavior being the equivalent +of Decider('content'). """ import os.path diff --git a/test/subdivide.py b/test/subdivide.py index a4a128e..9461d4b 100644 --- a/test/subdivide.py +++ b/test/subdivide.py @@ -29,9 +29,8 @@ Verify that rebuilds do not occur when SConsignFile(None) is used to put a .sconsign file in each directory and we subdvide the dependency tree with subsidiary *SConstruct* files in various subdirectories. -This depends on using content signatures for evaluation of intermediate -Nodes. We used to configure this explicitly using -TargetSignatures('content'), but we now rely on the default behavior +This depends on using content signatures for evaluation of +intermediate Nodes. This relies on the default behavior being the equivalent of Decider('content'). """ -- cgit v0.12 From 9c900844191f129d899dd48cc2fa96f9539d4ff6 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Mon, 21 Oct 2019 13:42:39 -0600 Subject: [PR 3464] rework new tests so they match stderr The re.DOTALL match function somehow wasn't matching the SConstruct error path, so build it up from known information instead. Signed-off-by: Mats Wichmann --- test/Removed/SourceSignatures/SourceSignatures.py | 15 ++++++++++----- test/Removed/TargetSignatures/TargetSignatures.py | 15 ++++++++++----- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/test/Removed/SourceSignatures/SourceSignatures.py b/test/Removed/SourceSignatures/SourceSignatures.py index fcc5e43..014c163 100644 --- a/test/Removed/SourceSignatures/SourceSignatures.py +++ b/test/Removed/SourceSignatures/SourceSignatures.py @@ -31,15 +31,15 @@ are definitely gone. import TestSCons -test = TestSCons.TestSCons(match=TestSCons.match_re_dotall) +test = TestSCons.TestSCons() test.file_fixture('SConstruct.method', 'SConstruct') -test.run(arguments='-Q -s', status=2, stdout=None, - stderr="""\ +expect = """\ NameError: name 'SourceSignatures' is not defined: - File ".+SConstruct", line 1: + File "{}", line 1: SourceSignatures('MD5') -""") +""".format(test.workpath('SConstruct')) +test.run(arguments='-Q -s', status=2, stdout=None, stderr=expect) test.file_fixture('SConstruct.setopt', 'SConstruct') test.run(arguments='-Q -s', status=0, stdout=None, @@ -50,3 +50,8 @@ No warning type: 'deprecated-source-signatures' test.pass_test() +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Removed/TargetSignatures/TargetSignatures.py b/test/Removed/TargetSignatures/TargetSignatures.py index 0b3a37b..889f992 100644 --- a/test/Removed/TargetSignatures/TargetSignatures.py +++ b/test/Removed/TargetSignatures/TargetSignatures.py @@ -31,15 +31,15 @@ are definitely gone. import TestSCons -test = TestSCons.TestSCons(match=TestSCons.match_re_dotall) +test = TestSCons.TestSCons() test.file_fixture('SConstruct.method', 'SConstruct') -test.run(arguments='-Q -s', status=2, stdout=None, - stderr="""\ +expect = """\ NameError: name 'TargetSignatures' is not defined: - File ".+SConstruct", line 1: + File "{}", line 1: TargetSignatures('MD5') -""") +""".format(test.workpath('SConstruct')) +test.run(arguments='-Q -s', status=2, stdout=None, stderr=expect) test.file_fixture('SConstruct.setopt', 'SConstruct') test.run(arguments="-Q -s", status=0, stdout=None, @@ -50,3 +50,8 @@ No warning type: 'deprecated-target-signatures' test.pass_test() +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: -- cgit v0.12 From 88387d1ebd5e7ee4c18f32a331ff5ad9d419dd9d Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Mon, 21 Oct 2019 14:01:34 -0600 Subject: [PR 3464] quiet sider complaints unused imports in a pair of tests that were moved and thus "touched". Signed-off-by: Mats Wichmann --- test/Removed/SourceSignatures/Old/env.py | 1 - test/Removed/SourceSignatures/Old/no-csigs.py | 2 -- 2 files changed, 3 deletions(-) diff --git a/test/Removed/SourceSignatures/Old/env.py b/test/Removed/SourceSignatures/Old/env.py index c63b176..bf86d4d 100644 --- a/test/Removed/SourceSignatures/Old/env.py +++ b/test/Removed/SourceSignatures/Old/env.py @@ -29,7 +29,6 @@ Test that use of env.SourceSignatures() correctly overrides the default behavior. """ -import os import re import TestSCons diff --git a/test/Removed/SourceSignatures/Old/no-csigs.py b/test/Removed/SourceSignatures/Old/no-csigs.py index c4f2a78..60c0460 100644 --- a/test/Removed/SourceSignatures/Old/no-csigs.py +++ b/test/Removed/SourceSignatures/Old/no-csigs.py @@ -25,8 +25,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" -import os - import TestSCons import TestSConsign -- cgit v0.12 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 69eb89f5055875a0af1b8329144eb61c04481105 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Mon, 16 Sep 2019 07:58:26 -0600 Subject: Remove deprecated Builder keywords overrides= and scanner= have been deprecated for over a decade. Signed-off-by: Mats Wichmann --- doc/man/scons.xml | 3 ++- src/CHANGES.txt | 2 ++ src/engine/SCons/Builder.py | 15 ++++++--------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index a9e0dd7..ae54e2e 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -4960,7 +4960,8 @@ the same target file(s). The default is 0, which means the builder can not be called multiple times for the same target file(s). Calling a builder multiple times for the same target simply adds additional source files to the target; it is not allowed to change the environment associated -with the target, specify addition environment overrides, or associate a different +with the target, specify additional environment overrides, +or associate a different builder with the target.
diff --git a/src/CHANGES.txt b/src/CHANGES.txt index af448d5..af05d35 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -25,6 +25,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER On vs2019 saves 5+ seconds per SCons invocation, which really helps test suite runs. - Remove deprecated SourceSignatures, TargetSignatures + - Remove deprecated Builder keywords: overrides and scanner From Jacek Kuczera: - Fix CheckFunc detection code for Visual 2019. Some functions @@ -36,6 +37,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER From Edoardo Bezzeccheri - Added debug option "action_timestamps" which outputs to stdout the absolute start and end time for each target. + RELEASE 3.1.1 - Mon, 07 Aug 2019 20:09:12 -0500 From William Deegan: diff --git a/src/engine/SCons/Builder.py b/src/engine/SCons/Builder.py index 4352d7a..e3fb396 100644 --- a/src/engine/SCons/Builder.py +++ b/src/engine/SCons/Builder.py @@ -396,16 +396,13 @@ class BuilderBase(object): self.env = env self.single_source = single_source if 'overrides' in overrides: - SCons.Warnings.warn(SCons.Warnings.DeprecatedBuilderKeywordsWarning, - "The \"overrides\" keyword to Builder() creation has been deprecated;\n" +\ - "\tspecify the items as keyword arguments to the Builder() call instead.") - overrides.update(overrides['overrides']) - del overrides['overrides'] + msg = "The \"overrides\" keyword to Builder() creation has been removed;\n" +\ + "\tspecify the items as keyword arguments to the Builder() call instead." + raise TypeError(msg) if 'scanner' in overrides: - SCons.Warnings.warn(SCons.Warnings.DeprecatedBuilderKeywordsWarning, - "The \"scanner\" keyword to Builder() creation has been deprecated;\n" - "\tuse: source_scanner or target_scanner as appropriate.") - del overrides['scanner'] + msg = "The \"scanner\" keyword to Builder() creation has been removed;\n" +\ + "\tuse: source_scanner or target_scanner as appropriate." + raise TypeError(msg) self.overrides = overrides self.set_suffix(suffix) -- 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 2e2ba90baa24a9919000edbf688c306e2c428fb6 Mon Sep 17 00:00:00 2001 From: Jakub Kulik Date: Fri, 1 Nov 2019 08:32:23 +0100 Subject: Fix incorrect testing assumptions for Solaris --- src/engine/SCons/ActionTests.py | 4 ---- src/engine/SCons/Tool/MSCommon/vc.py | 9 ++++++++- test/Clang/clang_shared_library.py | 2 +- test/Clang/clangxx_shared_library.py | 3 +++ test/Errors/execute-a-directory.py | 6 +----- test/Errors/non-executable-file.py | 6 +----- test/LINK/VersionedLib.py | 12 ++++++------ test/SWIG/recursive-includes-cpp.py | 2 ++ testing/framework/TestCommon.py | 4 ++-- 9 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/engine/SCons/ActionTests.py b/src/engine/SCons/ActionTests.py index 3054368..3303750 100644 --- a/src/engine/SCons/ActionTests.py +++ b/src/engine/SCons/ActionTests.py @@ -1208,10 +1208,6 @@ class CommandActionTestCase(unittest.TestCase): # Newer cygwin seems to return 126 for following expect_nonexecutable_file = 126 expect_nonexecutable_dir = 127 - elif sys.platform.find('sunos') != -1: - expect_nonexistent = 1 - expect_nonexecutable_file = 1 - expect_nonexecutable_dir = 1 else: expect_nonexistent = 127 expect_nonexecutable_file = 126 diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py index 4f6048d..86bdbe0 100644 --- a/src/engine/SCons/Tool/MSCommon/vc.py +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -161,11 +161,18 @@ def get_host_target(env): if not host_platform: host_platform = platform.machine() + # Solaris returns i86pc for both 32 and 64 bit architectures + if host_platform == "i86pc": + if platform.architecture()[0] == "64bit": + host_platform = "amd64" + else: + host_platform = "x86" + # Retain user requested TARGET_ARCH req_target_platform = env.get('TARGET_ARCH') debug('get_host_target() req_target_platform:%s'%req_target_platform) - if req_target_platform: + if req_target_platform: # If user requested a specific platform then only try that one. target_platform = req_target_platform else: diff --git a/test/Clang/clang_shared_library.py b/test/Clang/clang_shared_library.py index 9af3770..83fa4dd 100644 --- a/test/Clang/clang_shared_library.py +++ b/test/Clang/clang_shared_library.py @@ -35,7 +35,7 @@ if not test.where_is('clang'): base = Base() platform = base['PLATFORM'] -if platform == 'posix': +if platform in ['posix', 'sunos']: filename_options = ['foo.os'] libraryname = 'libfoo.so' elif platform == 'darwin': diff --git a/test/Clang/clangxx_shared_library.py b/test/Clang/clangxx_shared_library.py index 6240299..a16be6b 100644 --- a/test/Clang/clangxx_shared_library.py +++ b/test/Clang/clangxx_shared_library.py @@ -44,6 +44,9 @@ elif platform == 'darwin': elif platform == 'win32': filename_options = ['foo.obj','foo.os'] libraryname = 'foo.dll' +elif platform == 'sunos': + filename_options = ['foo.pic.o'] + libraryname = 'libfoo.so' else: test.fail_test() diff --git a/test/Errors/execute-a-directory.py b/test/Errors/execute-a-directory.py index 95fa7b6..8b6d13b 100644 --- a/test/Errors/execute-a-directory.py +++ b/test/Errors/execute-a-directory.py @@ -65,7 +65,7 @@ scons: \\*\\*\\* \\[%s\\] Error 1 """ cannot_execute = """\ -(sh: )*.+: cannot execute +(sh: )*.+: cannot execute( \\[Is a directory\\])? scons: \\*\\*\\* \\[%s\\] Error %s """ @@ -93,10 +93,6 @@ if os.name == 'nt': konnte_nicht_gefunden_werden % ('f3', 1), unspecified % 'f3' ] -elif sys.platform.find('sunos') != -1: - errs = [ - cannot_execute % ('f3', 1), - ] else: errs = [ cannot_execute % ('f3', 126), diff --git a/test/Errors/non-executable-file.py b/test/Errors/non-executable-file.py index 0e00c77..64c75c6 100644 --- a/test/Errors/non-executable-file.py +++ b/test/Errors/non-executable-file.py @@ -54,7 +54,7 @@ scons: \\*\\*\\* \\[%s\\] Error 1 """ cannot_execute = """\ -(sh: )*.+: cannot execute +(sh: )*.+: cannot execute( \\[Permission denied\\])? scons: \\*\\*\\* \\[%s\\] Error %s """ @@ -88,10 +88,6 @@ if os.name == 'nt': konnte_nicht_gefunden_werden % ('f1', 1), unspecified % 'f1' ] -elif sys.platform.find('sunos') != -1: - errs = [ - cannot_execute % ('f1', 1), - ] else: errs = [ cannot_execute % ('f1', 126), diff --git a/test/LINK/VersionedLib.py b/test/LINK/VersionedLib.py index 468e3e5..64f9b90 100644 --- a/test/LINK/VersionedLib.py +++ b/test/LINK/VersionedLib.py @@ -138,37 +138,37 @@ elif 'sunlink' in tool_list: test_plan = [ { 'libversion' : '2', - 'files' : [ 'libtest.so', 'libtest.so.2', 'so_test.os' ], + 'files' : [ 'libtest.so', 'libtest.so.2', 'test.pic.o' ], 'instfiles' : [ 'libtest.so', 'libtest.so.2' ], 'symlinks' : [ ('libtest.so', 'libtest.so.2') ], }, { 'libversion' : '2.5', - 'files' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5', 'so_test.os' ], + 'files' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5', 'test.pic.o' ], 'instfiles' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5' ], 'symlinks' : [ ('libtest.so', 'libtest.so.2.5'), ('libtest.so.2', 'libtest.so.2.5') ], }, { 'libversion' : '2.5.4', - 'files' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5.4', 'so_test.os' ], + 'files' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5.4', 'test.pic.o' ], 'instfiles' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5.4' ], 'symlinks' : [ ('libtest.so', 'libtest.so.2.5.4'), ('libtest.so.2', 'libtest.so.2.5.4') ], }, { 'libversion' : '2.5.4.7.8', - 'files' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5.4.7.8', 'so_test.os' ], + 'files' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5.4.7.8', 'test.pic.o' ], 'instfiles' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.5.4.7.8' ], 'symlinks' : [ ('libtest.so', 'libtest.so.2.5.4.7.8'), ('libtest.so.2', 'libtest.so.2.5.4.7.8') ], }, { 'libversion' : 'aabf114f', - 'files' : [ 'libtest.so', 'libtest.so.aabf114f', 'so_test.os' ], + 'files' : [ 'libtest.so', 'libtest.so.aabf114f', 'test.pic.o' ], 'instfiles' : [ 'libtest.so', 'libtest.so.aabf114f' ], 'symlinks' : [ ('libtest.so', 'libtest.so.aabf114f') ], }, { 'libversion' : '2.dfffa11', - 'files' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.dfffa11', 'so_test.os' ], + 'files' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.dfffa11', 'test.pic.o' ], 'instfiles' : [ 'libtest.so', 'libtest.so.2', 'libtest.so.2.dfffa11' ], 'symlinks' : [ ('libtest.so', 'libtest.so.2.dfffa11'), ('libtest.so.2', 'libtest.so.2.dfffa11') ], }, diff --git a/test/SWIG/recursive-includes-cpp.py b/test/SWIG/recursive-includes-cpp.py index 3999cc3..dcd9d05 100644 --- a/test/SWIG/recursive-includes-cpp.py +++ b/test/SWIG/recursive-includes-cpp.py @@ -115,6 +115,8 @@ env.SharedLibrary( if sys.platform == 'win32': object_suffix = ".obj" +elif sys.platform == 'sunos5': + object_suffix = ".pic.o" else: object_suffix = ".os" diff --git a/testing/framework/TestCommon.py b/testing/framework/TestCommon.py index ca4a147..8e6cc8e 100644 --- a/testing/framework/TestCommon.py +++ b/testing/framework/TestCommon.py @@ -165,8 +165,8 @@ elif sys.platform.find('darwin') != -1: elif sys.platform.find('sunos') != -1: exe_suffix = '' obj_suffix = '.o' - shobj_suffix = '.o' - shobj_prefix = 'so_' + shobj_suffix = '.pic.o' + shobj_prefix = '' lib_prefix = 'lib' lib_suffix = '.a' dll_prefix = 'lib' -- cgit v0.12 From 0951e5d691487033bae283d98c45ccbcf3ae822d Mon Sep 17 00:00:00 2001 From: maiphi Date: Fri, 1 Nov 2019 14:11:10 +0100 Subject: Tex builder: avoid error when reading non-utf-8 log files Python 3 throws a UnicodeDecodeError when reading a non-utf-8 file in text mode with default (utf-8) encoding. This happens when T1 fontenc is used in Latex and a warning in the log file contains e.g. umlauts. Invalid characters are now replaced. --- src/engine/SCons/Tool/tex.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/engine/SCons/Tool/tex.py b/src/engine/SCons/Tool/tex.py index 64b9d3b..5cf7bca 100644 --- a/src/engine/SCons/Tool/tex.py +++ b/src/engine/SCons/Tool/tex.py @@ -297,8 +297,8 @@ def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None logfilename = targetbase + '.log' logContent = '' if os.path.isfile(logfilename): - with open(logfilename, "r") as f: - logContent = f.read() + with open(logfilename, "rb") as f: + logContent = f.read().decode(errors='replace') # Read the fls file to find all .aux files -- cgit v0.12 From 6f35570377e7e7b5003dd6f069b65e95f9ae6efb Mon Sep 17 00:00:00 2001 From: maiphi Date: Fri, 1 Nov 2019 14:22:31 +0100 Subject: Add test case with Latin-1 encoded Latex log file. Required fix in the test framework. In order to make the test work, it was necessary to handle the encoding issue also in the test framework. Otherwise, though the Latex builder can handle the case, the test framework chokes on it. --- test/TEX/LATEX.py | 16 ++++++++++++++++ testing/framework/TestCmd.py | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/test/TEX/LATEX.py b/test/TEX/LATEX.py index 553313e..592bbb7 100644 --- a/test/TEX/LATEX.py +++ b/test/TEX/LATEX.py @@ -193,6 +193,22 @@ This is the include file. mod %s test.must_not_exist('latexi.ilg') + test.write('SConstruct', """ +env = Environment() +env.PostScript('latin1log.tex') +""") + + test.write('latin1log.tex', r""" +\documentclass[12pt,a4paper]{article} +\usepackage[T1]{fontenc} +\begin{document} +\"oxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +\end{document} +""") + + test.run(arguments = 'latin1log.dvi', stderr = None) + test.must_exist('latin1log.dvi') + test.pass_test() # Local Variables: diff --git a/testing/framework/TestCmd.py b/testing/framework/TestCmd.py index 81e03f3..9218f60 100644 --- a/testing/framework/TestCmd.py +++ b/testing/framework/TestCmd.py @@ -1528,7 +1528,7 @@ class TestCmd(object): # TODO: Run full tests on both platforms and see if this fixes failures # It seems that py3.6 still sets text mode if you set encoding. elif sys.version_info[0] == 3: # TODO and sys.version_info[1] < 6: - stream = stream.decode('utf-8') + stream = stream.decode('utf-8', errors='replace') stream = stream.replace('\r\n', '\n') elif sys.version_info[0] == 2: stream = stream.replace('\r\n', '\n') -- cgit v0.12 From 0a41c542db4a29bb2d84f68d853d6f7709476a86 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Fri, 1 Nov 2019 15:36:57 +0200 Subject: Parse GCC -imacros option https://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html --- src/engine/SCons/Environment.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 0e1102e..66912de 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -707,6 +707,9 @@ class SubstitutionEnvironment(object): elif append_next_arg_to == '-include': t = ('-include', self.fs.File(arg)) dict['CCFLAGS'].append(t) + elif append_next_arg_to == '-imacros': + t = ('-imacros', self.fs.File(arg)) + dict['CCFLAGS'].append(t) elif append_next_arg_to == '-isysroot': t = ('-isysroot', arg) dict['CCFLAGS'].append(t) @@ -793,7 +796,7 @@ class SubstitutionEnvironment(object): elif arg[0] == '+': dict['CCFLAGS'].append(arg) dict['LINKFLAGS'].append(arg) - elif arg in ['-include', '-isysroot', '-isystem', '-iquote', '-idirafter', '-arch']: + elif arg in ['-include', '-imacros', '-isysroot', '-isystem', '-iquote', '-idirafter', '-arch']: append_next_arg_to = arg else: dict['CCFLAGS'].append(arg) -- cgit v0.12 From 477ffd82d67ebd4820d33be760c1594fd82c09f0 Mon Sep 17 00:00:00 2001 From: maiphi Date: Fri, 1 Nov 2019 14:40:56 +0100 Subject: Added note about Latex Latin-1/UTF-8 issue to CHANGES.log --- src/CHANGES.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index af448d5..c6312b7 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -6,6 +6,10 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER + 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) is read. + From Mathew Robinson: - Improved threading performance by ensuring NodeInfo is shared -- cgit v0.12 From 8906411a79dfd9d5eaeb354f0feeebcc25cfc296 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Fri, 1 Nov 2019 15:43:41 +0200 Subject: Parse GCC "-imacros" option in ParseFlags --- src/CHANGES.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index af448d5..d768247 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -35,6 +35,9 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER From Edoardo Bezzeccheri - Added debug option "action_timestamps" which outputs to stdout the absolute start and end time for each target. + + From Ivan Kravets + - Parse GCC "-imacros" option in ParseFlags RELEASE 3.1.1 - Mon, 07 Aug 2019 20:09:12 -0500 -- cgit v0.12 From 44be58d63189400b1105300c1508243777b45c2e Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Fri, 1 Nov 2019 18:20:56 +0200 Subject: Parse "-imacros" option in ParseFlags --- src/CHANGES.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index d768247..ddc777c 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -37,7 +37,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Added debug option "action_timestamps" which outputs to stdout the absolute start and end time for each target. From Ivan Kravets - - Parse GCC "-imacros" option in ParseFlags + - Parse "-imacros" option in ParseFlags RELEASE 3.1.1 - Mon, 07 Aug 2019 20:09:12 -0500 -- cgit v0.12 From 30f8d95881195eb977825f4210d48fc571f9d37c Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Wed, 6 Nov 2019 12:49:48 +0200 Subject: Added support for "-imacros" to ParseFlags --- doc/generated/functions.gen | 11 +++---- src/CHANGES.txt | 6 ++-- src/engine/SCons/Environment.py | 56 ++++++++++++++++++------------------ src/engine/SCons/Environment.xml | 1 + src/engine/SCons/EnvironmentTests.py | 2 ++ 5 files changed, 40 insertions(+), 36 deletions(-) diff --git a/doc/generated/functions.gen b/doc/generated/functions.gen index e55799c..f3f2a0c 100644 --- a/doc/generated/functions.gen +++ b/doc/generated/functions.gen @@ -2505,16 +2505,16 @@ This specifies help text to be printed if the argument is given to scons. -If +If 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 Help -is called. With append set to False, any +is called. With append set to False, any Help -text generated with +text generated with AddOption is clobbered. If append is True, the AddOption help is prepended to the help -string, thus preserving the +string, thus preserving the message. @@ -2955,6 +2955,7 @@ and added to the following construction variables: -fmerge-all-constants CCFLAGS, LINKFLAGS -fopenmp CCFLAGS, LINKFLAGS -include CCFLAGS +-imacros CCFLAGS -isysroot CCFLAGS, LINKFLAGS -isystem CCFLAGS -iquote CCFLAGS diff --git a/src/CHANGES.txt b/src/CHANGES.txt index ddc777c..092c2c8 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -32,12 +32,12 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER From Jakub Kulik - Fix subprocess result bytes not being decoded in SunOS/Solaris related tools. - + From Edoardo Bezzeccheri - Added debug option "action_timestamps" which outputs to stdout the absolute start and end time for each target. - + From Ivan Kravets - - Parse "-imacros" option in ParseFlags + - Added support for "-imacros" to ParseFlags RELEASE 3.1.1 - Mon, 07 Aug 2019 20:09:12 -0500 diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 66912de..1296f54 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -702,34 +702,34 @@ class SubstitutionEnvironment(object): append_next_arg_to = None # for multi-word args for arg in params: if append_next_arg_to: - if append_next_arg_to == 'CPPDEFINES': - append_define(arg) - elif append_next_arg_to == '-include': - t = ('-include', self.fs.File(arg)) - dict['CCFLAGS'].append(t) - elif append_next_arg_to == '-imacros': - t = ('-imacros', self.fs.File(arg)) - dict['CCFLAGS'].append(t) - elif append_next_arg_to == '-isysroot': - t = ('-isysroot', arg) - dict['CCFLAGS'].append(t) - dict['LINKFLAGS'].append(t) - elif append_next_arg_to == '-isystem': - t = ('-isystem', arg) - dict['CCFLAGS'].append(t) - elif append_next_arg_to == '-iquote': - t = ('-iquote', arg) - dict['CCFLAGS'].append(t) - elif append_next_arg_to == '-idirafter': - t = ('-idirafter', arg) - dict['CCFLAGS'].append(t) - elif append_next_arg_to == '-arch': - t = ('-arch', arg) - dict['CCFLAGS'].append(t) - dict['LINKFLAGS'].append(t) - else: - dict[append_next_arg_to].append(arg) - append_next_arg_to = None + if append_next_arg_to == 'CPPDEFINES': + append_define(arg) + elif append_next_arg_to == '-include': + t = ('-include', self.fs.File(arg)) + dict['CCFLAGS'].append(t) + elif append_next_arg_to == '-imacros': + t = ('-imacros', self.fs.File(arg)) + dict['CCFLAGS'].append(t) + elif append_next_arg_to == '-isysroot': + t = ('-isysroot', arg) + dict['CCFLAGS'].append(t) + dict['LINKFLAGS'].append(t) + elif append_next_arg_to == '-isystem': + t = ('-isystem', arg) + dict['CCFLAGS'].append(t) + elif append_next_arg_to == '-iquote': + t = ('-iquote', arg) + dict['CCFLAGS'].append(t) + elif append_next_arg_to == '-idirafter': + t = ('-idirafter', arg) + dict['CCFLAGS'].append(t) + elif append_next_arg_to == '-arch': + t = ('-arch', arg) + dict['CCFLAGS'].append(t) + dict['LINKFLAGS'].append(t) + else: + dict[append_next_arg_to].append(arg) + append_next_arg_to = None elif not arg[0] in ['-', '+']: dict['LIBS'].append(self.fs.File(arg)) elif arg == '-dylib_file': diff --git a/src/engine/SCons/Environment.xml b/src/engine/SCons/Environment.xml index 829bf12..516505c 100644 --- a/src/engine/SCons/Environment.xml +++ b/src/engine/SCons/Environment.xml @@ -2324,6 +2324,7 @@ and added to the following construction variables: -fmerge-all-constants CCFLAGS, LINKFLAGS -fopenmp CCFLAGS, LINKFLAGS -include CCFLAGS +-imacros CCFLAGS -isysroot CCFLAGS, LINKFLAGS -isystem CCFLAGS -iquote CCFLAGS diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index f016f22..0957361 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -804,6 +804,7 @@ sys.exit(0) "-iquote /usr/include/foo1 " + \ "-isystem /usr/include/foo2 " + \ "-idirafter /usr/include/foo3 " + \ + "-imacros /usr/include/foo4 " + \ "+DD64 " + \ "-DFOO -DBAR=value -D BAZ " @@ -818,6 +819,7 @@ sys.exit(0) ('-iquote', '/usr/include/foo1'), ('-isystem', '/usr/include/foo2'), ('-idirafter', '/usr/include/foo3'), + ('-imacros', env.fs.File('/usr/include/foo4')), '+DD64'], repr(d['CCFLAGS']) assert d['CXXFLAGS'] == ['-std=c++0x'], repr(d['CXXFLAGS']) assert d['CPPDEFINES'] == ['FOO', ['BAR', 'value'], 'BAZ'], d['CPPDEFINES'] -- cgit v0.12 From e2e147378027376f42043f798e47d93353237fec Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Wed, 6 Nov 2019 08:37:49 -0700 Subject: [3.9] change tests not to expect bare scriptname Python 3.9 changes to give an absolute path in sys.argv[0]. Some tests expected to see just a simple path ('myyacc.py'); these now either do a test.must_contain instead of must_match, or change to do "if 'mypass.py' in sys.argv[0]' instead of the former "if sys.argv[0] == 'mypass.py'". Signed-off-by: Mats Wichmann --- test/GetBuildFailures/option-k.py | 4 ++-- test/GetBuildFailures/parallel.py | 4 ++-- test/GetBuildFailures/serial.py | 4 ++-- test/Rpcgen/RPCGEN.py | 8 ++++---- test/Rpcgen/RPCGENCLIENTFLAGS.py | 8 ++++---- test/Rpcgen/RPCGENFLAGS.py | 8 ++++---- test/Rpcgen/RPCGENHEADERFLAGS.py | 8 ++++---- test/Rpcgen/RPCGENSERVICEFLAGS.py | 8 ++++---- test/Rpcgen/RPCGENXDRFLAGS.py | 8 ++++---- test/YACC/YACCHFILESUFFIX.py | 4 ++-- test/YACC/YACCHXXFILESUFFIX.py | 2 +- test/YACC/YACCVCGFILESUFFIX.py | 2 +- 12 files changed, 34 insertions(+), 34 deletions(-) diff --git a/test/GetBuildFailures/option-k.py b/test/GetBuildFailures/option-k.py index 92a9db8..039ad50 100644 --- a/test/GetBuildFailures/option-k.py +++ b/test/GetBuildFailures/option-k.py @@ -45,11 +45,11 @@ test = TestSCons.TestSCons() contents = r"""\ import sys -if sys.argv[0] == 'mypass.py': +if 'mypass.py' in sys.argv[0]: with open(sys.argv[3], 'wb') as ofp, open(sys.argv[4], 'rb') as ifp: ofp.write(ifp.read()) exit_value = 0 -elif sys.argv[0] == 'myfail.py': +elif 'myfail.py' in sys.argv[0]: exit_value = 1 sys.exit(exit_value) """ diff --git a/test/GetBuildFailures/parallel.py b/test/GetBuildFailures/parallel.py index 5387e4a..63125ad 100644 --- a/test/GetBuildFailures/parallel.py +++ b/test/GetBuildFailures/parallel.py @@ -59,11 +59,11 @@ write_marker = sys.argv[2] + '.marker' if wait_marker != '-.marker': while not os.path.exists(wait_marker): time.sleep(1) -if sys.argv[0] == 'mypass.py': +if 'mypass.py' in sys.argv[0]: with open(sys.argv[3], 'wb') as ofp, open(sys.argv[4], 'rb') as ifp: ofp.write(ifp.read()) exit_value = 0 -elif sys.argv[0] == 'myfail.py': +elif 'myfail.py' in sys.argv[0]: exit_value = 1 if write_marker != '-.marker': os.mkdir(write_marker) diff --git a/test/GetBuildFailures/serial.py b/test/GetBuildFailures/serial.py index 7557dd5..4aecc12 100644 --- a/test/GetBuildFailures/serial.py +++ b/test/GetBuildFailures/serial.py @@ -48,11 +48,11 @@ test = TestSCons.TestSCons() contents = r"""\ import sys -if sys.argv[0] == 'mypass.py': +if 'mypass.py' in sys.argv[0]: with open(sys.argv[3], 'wb') as ofp, open(sys.argv[4], 'rb') as ifp: ofp.write(ifp.read()) exit_value = 0 -elif sys.argv[0] == 'myfail.py': +elif 'myfail.py' in sys.argv[0]: exit_value = 1 sys.exit(exit_value) """ diff --git a/test/Rpcgen/RPCGEN.py b/test/Rpcgen/RPCGEN.py index eaa4e16..86cdd71 100644 --- a/test/Rpcgen/RPCGEN.py +++ b/test/Rpcgen/RPCGEN.py @@ -69,10 +69,10 @@ expect_h = output % ('-h', test.workpath('rpcif.h')) expect_svc = output % ('-m', test.workpath('rpcif_svc.c')) expect_xdr = output % ('-c', test.workpath('rpcif_xdr.c')) -test.must_match('rpcif_clnt.c', expect_clnt, mode='r') -test.must_match('rpcif.h', expect_h, mode='r') -test.must_match('rpcif_svc.c', expect_svc, mode='r') -test.must_match('rpcif_xdr.c', expect_xdr, mode='r') +test.must_contain('rpcif_clnt.c', expect_clnt, mode='r') +test.must_contain('rpcif.h', expect_h, mode='r') +test.must_contain('rpcif_svc.c', expect_svc, mode='r') +test.must_contain('rpcif_xdr.c', expect_xdr, mode='r') diff --git a/test/Rpcgen/RPCGENCLIENTFLAGS.py b/test/Rpcgen/RPCGENCLIENTFLAGS.py index a298ebd..1143227 100644 --- a/test/Rpcgen/RPCGENCLIENTFLAGS.py +++ b/test/Rpcgen/RPCGENCLIENTFLAGS.py @@ -72,10 +72,10 @@ expect_h = output % ('-h', test.workpath('rpcif.h')) expect_svc = output % ('-m', test.workpath('rpcif_svc.c')) expect_xdr = output % ('-c', test.workpath('rpcif_xdr.c')) -test.must_match('rpcif_clnt.c', expect_clnt, mode='r') -test.must_match('rpcif.h', expect_h, mode='r') -test.must_match('rpcif_svc.c', expect_svc, mode='r') -test.must_match('rpcif_xdr.c', expect_xdr, mode='r') +test.must_contain('rpcif_clnt.c', expect_clnt, mode='r') +test.must_contain('rpcif.h', expect_h, mode='r') +test.must_contain('rpcif_svc.c', expect_svc, mode='r') +test.must_contain('rpcif_xdr.c', expect_xdr, mode='r') diff --git a/test/Rpcgen/RPCGENFLAGS.py b/test/Rpcgen/RPCGENFLAGS.py index c254ed0..3673a23 100644 --- a/test/Rpcgen/RPCGENFLAGS.py +++ b/test/Rpcgen/RPCGENFLAGS.py @@ -71,10 +71,10 @@ expect_h = output % ('-h', test.workpath('rpcif.h')) expect_svc = output % ('-m', test.workpath('rpcif_svc.c')) expect_xdr = output % ('-c', test.workpath('rpcif_xdr.c')) -test.must_match('rpcif_clnt.c', expect_clnt, mode='r') -test.must_match('rpcif.h', expect_h, mode='r') -test.must_match('rpcif_svc.c', expect_svc, mode='r') -test.must_match('rpcif_xdr.c', expect_xdr, mode='r') +test.must_contain('rpcif_clnt.c', expect_clnt, mode='r') +test.must_contain('rpcif.h', expect_h, mode='r') +test.must_contain('rpcif_svc.c', expect_svc, mode='r') +test.must_contain('rpcif_xdr.c', expect_xdr, mode='r') diff --git a/test/Rpcgen/RPCGENHEADERFLAGS.py b/test/Rpcgen/RPCGENHEADERFLAGS.py index 8e40ad7..6223ba3 100644 --- a/test/Rpcgen/RPCGENHEADERFLAGS.py +++ b/test/Rpcgen/RPCGENHEADERFLAGS.py @@ -72,10 +72,10 @@ expect_h = output_h % ('-h', test.workpath('rpcif.h')) expect_svc = output % ('-m', test.workpath('rpcif_svc.c')) expect_xdr = output % ('-c', test.workpath('rpcif_xdr.c')) -test.must_match('rpcif_clnt.c', expect_clnt, mode='r') -test.must_match('rpcif.h', expect_h, mode='r') -test.must_match('rpcif_svc.c', expect_svc, mode='r') -test.must_match('rpcif_xdr.c', expect_xdr, mode='r') +test.must_contain('rpcif_clnt.c', expect_clnt, mode='r') +test.must_contain('rpcif.h', expect_h, mode='r') +test.must_contain('rpcif_svc.c', expect_svc, mode='r') +test.must_contain('rpcif_xdr.c', expect_xdr, mode='r') diff --git a/test/Rpcgen/RPCGENSERVICEFLAGS.py b/test/Rpcgen/RPCGENSERVICEFLAGS.py index 2edc77c..7cdf430 100644 --- a/test/Rpcgen/RPCGENSERVICEFLAGS.py +++ b/test/Rpcgen/RPCGENSERVICEFLAGS.py @@ -72,10 +72,10 @@ expect_h = output % ('-h', test.workpath('rpcif.h')) expect_svc = output_svc % ('-m', test.workpath('rpcif_svc.c')) expect_xdr = output % ('-c', test.workpath('rpcif_xdr.c')) -test.must_match('rpcif_clnt.c', expect_clnt, mode='r') -test.must_match('rpcif.h', expect_h, mode='r') -test.must_match('rpcif_svc.c', expect_svc, mode='r') -test.must_match('rpcif_xdr.c', expect_xdr, mode='r') +test.must_contain('rpcif_clnt.c', expect_clnt, mode='r') +test.must_contain('rpcif.h', expect_h, mode='r') +test.must_contain('rpcif_svc.c', expect_svc, mode='r') +test.must_contain('rpcif_xdr.c', expect_xdr, mode='r') diff --git a/test/Rpcgen/RPCGENXDRFLAGS.py b/test/Rpcgen/RPCGENXDRFLAGS.py index 2d1ca96..2f6d8d9 100644 --- a/test/Rpcgen/RPCGENXDRFLAGS.py +++ b/test/Rpcgen/RPCGENXDRFLAGS.py @@ -72,10 +72,10 @@ expect_h = output % ('-h', test.workpath('rpcif.h')) expect_svc = output % ('-m', test.workpath('rpcif_svc.c')) expect_xdr = output_xdr % ('-c', test.workpath('rpcif_xdr.c')) -test.must_match('rpcif_clnt.c', expect_clnt, mode='r') -test.must_match('rpcif.h', expect_h, mode='r') -test.must_match('rpcif_svc.c', expect_svc, mode='r') -test.must_match('rpcif_xdr.c', expect_xdr, mode='r') +test.must_contain('rpcif_clnt.c', expect_clnt, mode='r') +test.must_contain('rpcif.h', expect_h, mode='r') +test.must_contain('rpcif_svc.c', expect_svc, mode='r') +test.must_contain('rpcif_xdr.c', expect_xdr, mode='r') diff --git a/test/YACC/YACCHFILESUFFIX.py b/test/YACC/YACCHFILESUFFIX.py index 6c34db1..da3416c 100644 --- a/test/YACC/YACCHFILESUFFIX.py +++ b/test/YACC/YACCHFILESUFFIX.py @@ -71,9 +71,9 @@ test.write('bbb.yacc', "bbb.yacc\n/*yacc*/\n") test.run(arguments = '.') test.must_match('aaa.c', "aaa.y\n") -test.must_match('aaa.hsuffix', "myyacc.py -d -o aaa.c aaa.y\n") +test.must_contain('aaa.hsuffix', "myyacc.py -d -o aaa.c aaa.y\n") test.must_match('bbb.c', "bbb.yacc\n") -test.must_match('bbb.hsuffix', "myyacc.py -d -o bbb.c bbb.yacc\n") +test.must_contain('bbb.hsuffix', "myyacc.py -d -o bbb.c bbb.yacc\n") test.up_to_date(arguments = '.') diff --git a/test/YACC/YACCHXXFILESUFFIX.py b/test/YACC/YACCHXXFILESUFFIX.py index 63a5358..3ee70ee 100644 --- a/test/YACC/YACCHXXFILESUFFIX.py +++ b/test/YACC/YACCHXXFILESUFFIX.py @@ -69,7 +69,7 @@ test.write('aaa.yy', "aaa.yy\n/*yacc*/\n") test.run(arguments = '.') test.must_match('aaa.cc', "aaa.yy\n") -test.must_match('aaa.hxxsuffix', "myyacc.py -d -o aaa.cc aaa.yy\n") +test.must_contain('aaa.hxxsuffix', "myyacc.py -d -o aaa.cc aaa.yy\n") test.up_to_date(arguments = '.') diff --git a/test/YACC/YACCVCGFILESUFFIX.py b/test/YACC/YACCVCGFILESUFFIX.py index aee3265..32c3440 100644 --- a/test/YACC/YACCVCGFILESUFFIX.py +++ b/test/YACC/YACCVCGFILESUFFIX.py @@ -78,7 +78,7 @@ test.must_not_exist('aaa.vcgsuffix') test.must_match('bbb.cc', "bbb.yy\n") test.must_not_exist('bbb.vcg') -test.must_match('bbb.vcgsuffix', "myyacc.py -g -o bbb.cc bbb.yy\n") +test.must_contain('bbb.vcgsuffix', "myyacc.py -g -o bbb.cc bbb.yy\n") test.up_to_date(arguments = '.') -- cgit v0.12 From 10d57a7c5cb108a4fa707560c0e72ccfd3793b76 Mon Sep 17 00:00:00 2001 From: maiphi Date: Thu, 7 Nov 2019 21:22:01 +0100 Subject: Latin-1 log test case: compile to DVI, not PostScript; add comment --- test/TEX/LATEX.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/TEX/LATEX.py b/test/TEX/LATEX.py index 592bbb7..dabe8b1 100644 --- a/test/TEX/LATEX.py +++ b/test/TEX/LATEX.py @@ -28,6 +28,8 @@ r""" Validate that we can set the LATEX string to our own utility, that the produced .dvi, .aux and .log files get removed by the -c option, and that we can use this to wrap calls to the real latex utility. +Check that a log file with a warning encoded in non-UTF-8 (here: Latin-1) +is read without throwing an error. """ import TestSCons @@ -195,9 +197,11 @@ This is the include file. mod %s test.write('SConstruct', """ env = Environment() -env.PostScript('latin1log.tex') +env.DVI('latin1log.tex') """) + # This will trigger an overfull hbox warning in the log file, + # containing the umlaut "o in Latin-1 ("T1 fontenc") encoding. test.write('latin1log.tex', r""" \documentclass[12pt,a4paper]{article} \usepackage[T1]{fontenc} -- cgit v0.12 From b41aedfbe1c00b1fef9072c987803d3af7efac9a Mon Sep 17 00:00:00 2001 From: maiphi Date: Thu, 7 Nov 2019 21:23:03 +0100 Subject: Changelog: add details about fix of Latex log encoding issue --- src/CHANGES.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index c6312b7..5d2bd1a 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -8,7 +8,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER 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) is read. + non-UTF-8 encoding (e.g. containing umlauts in Latin-1 encoding when + the fontenc package is included with \usepackage[T1]{fontenc}) is read. From Mathew Robinson: -- cgit v0.12 From eb73aacd6c0beeb77a9e07c17dfbaef7fb54c42a Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 8 Nov 2019 11:36:15 -0500 Subject: [skip ci] make scons_dev_master.py have proper shebang and also set executable --- bin/scons_dev_master.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 bin/scons_dev_master.py diff --git a/bin/scons_dev_master.py b/bin/scons_dev_master.py old mode 100644 new mode 100755 index 4b1160f..cdbd68e --- a/bin/scons_dev_master.py +++ b/bin/scons_dev_master.py @@ -1,4 +1,4 @@ -#!/bin/sh +#!/usr/bin/python # # A script for turning a generic Ubuntu system into a master for -- cgit v0.12 From d9eb207f308fe902dfce03b019bdacfde4edbaf5 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 9 Nov 2019 20:36:05 -0500 Subject: Create FUNDING.yml --- .github/FUNDING.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..9daae32 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,5 @@ +# These are supported funding model platforms + +github: bdbaddog +patreon: bdbaddog + -- cgit v0.12 From 406d528b20ce0f70186af066b80e14ebf25cafc3 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 9 Nov 2019 20:45:18 -0500 Subject: [ci skip] indicating to github linguist which files to ignore when detecting the main programming language for this repo --- .gitattributes | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..4b5f3dc --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +doc/* linguist-documentation +src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1 linguist-vendored +*.xml linguist-documentation +*.gen linguist-documentation + -- cgit v0.12 From ad0bbd693fde6157323ab461a5e637f237fb59e1 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 9 Nov 2019 20:47:46 -0500 Subject: [ci skip] updates --- .gitattributes | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitattributes b/.gitattributes index 4b5f3dc..089d31b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,6 @@ doc/* linguist-documentation src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1 linguist-vendored *.xml linguist-documentation +*.xsl linguist-documentation *.gen linguist-documentation -- cgit v0.12 From 83d5fe4d674aefd8bdd8b2eebd966173fef4911b Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Wed, 13 Nov 2019 07:42:02 -0700 Subject: Document that AddOpt has limitations [ci skip] Manpage describes that using spaces between AddOption'd option and its argument is undefined. Use Guide goes into more detail, including workarounds. :: these are not a solution, but do at least reduce the surprise factor. (multiple github issues) Fix tag mismatch in depends.xml introduced by a previous deletion. Signed-off-by: Mats Wichmann --- doc/user/command-line.xml | 34 ++++++++++++++++++++++++++++++++++ doc/user/depends.xml | 1 + src/engine/SCons/Script/Main.xml | 15 +++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/doc/user/command-line.xml b/doc/user/command-line.xml index d129d2e..8b8949a 100644 --- a/doc/user/command-line.xml +++ b/doc/user/command-line.xml @@ -608,6 +608,7 @@ foo.in of the optparse.OptionParser. + Once you have added a custom command-line option with the &AddOption; function, the value of the option (if any) is immediately available @@ -678,6 +679,39 @@ foo.in scons -Q -n --prefix=/tmp/install + + + Long options and option-arguments separated by a space, rather than + by =, are ambiguous. + While --input=ARG + has a clear meaning, for --input ARG it is not + possible to tell without instructions whether + ARG is an argument belonging to the + input option or a positional argument + (that is, an argument that does not start with a single or double dash). + In scons, positional arguments are treated as either + command-line build options or command-line targets + (see the immediately following sections for details), + which are made available for use in the &SConscript;. + This means they have to be collected before &SConscript; processing + takes place. Since &AddOption; calls, which provide + the necessary processing instructions, happen in the &SConscript;, + scons cannot resolve the ambiguity in time + for options added this way, and unexpected things will happen. + As a result, this usage style should be avoided when invoking + scons. For single-argument + options, use the --input=ARG style on the + command line. For multiple-argument options + (nargs greater than one), + set nargs to one in + &AddOption; and combine the option-arguments into one word + with a separator, and parse the result in your own code. + See the built-in --debug option, which + allows specifying multiple arguments as a single comma-separated + word, for an example of such usage. + + + diff --git a/doc/user/depends.xml b/doc/user/depends.xml index 5a78eb5..cd5094a 100644 --- a/doc/user/depends.xml +++ b/doc/user/depends.xml @@ -764,6 +764,7 @@ int main() { printf("Hello, world!\n"); } encounter them in older &SConscript; files. +
Implicit Dependencies: The &cv-CPPPATH; Construction Variable diff --git a/src/engine/SCons/Script/Main.xml b/src/engine/SCons/Script/Main.xml index e95afbc..13ad336 100644 --- a/src/engine/SCons/Script/Main.xml +++ b/src/engine/SCons/Script/Main.xml @@ -133,6 +133,21 @@ AddOption('--prefix', help='installation prefix') env = Environment(PREFIX = GetOption('prefix')) + + + +While &AddOption; behaves like +optparse.add_option, +the behavior of options added by &AddOption; +which take arguments is underfined in +scons if a space +(rather than = sign) is used as +the separator on the command line when +the option is invoked. +Such usage should be avoided. + + + -- cgit v0.12 From 0be4c7daa8d983be0faa53907f52aee9217f3704 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 15 Nov 2019 12:30:45 -0700 Subject: [PR 3475] add repeated-args suggestion for AddOpt [ci skip] Signed-off-by: Mats Wichmann --- doc/user/command-line.xml | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/doc/user/command-line.xml b/doc/user/command-line.xml index 8b8949a..f8f6a66 100644 --- a/doc/user/command-line.xml +++ b/doc/user/command-line.xml @@ -2,7 +2,7 @@ %scons; - + %builders-mod; @@ -89,7 +89,7 @@ all of the command-line variable settings, the ability to apply command-line variable settings to construction environments, - and functions for configuring + and functions for configuring specific types of variables (Boolean values, path names, etc.) with automatic validation of the user's specified values. @@ -681,36 +681,43 @@ foo.in - Long options and option-arguments separated by a space, rather than + Long options and option-arguments separated by space, rather than by =, are ambiguous. While --input=ARG has a clear meaning, for --input ARG it is not possible to tell without instructions whether ARG is an argument belonging to the - input option or a positional argument - (that is, an argument that does not start with a single or double dash). - In scons, positional arguments are treated as either + input option or a positional argument. + scons treats positional arguments as either command-line build options or command-line targets (see the immediately following sections for details), which are made available for use in the &SConscript;. - This means they have to be collected before &SConscript; processing + Thus, they must be collected before &SConscript; processing takes place. Since &AddOption; calls, which provide - the necessary processing instructions, happen in the &SConscript;, - scons cannot resolve the ambiguity in time - for options added this way, and unexpected things will happen. + the processing instructions to resolve the ambiguity, + happen in the &SConscript;, + scons does not know in time + for options added this way, and unexpected things will happen, + such as option-arguments assigned as targets and/or exceptions + due to missing option-arguments. + + As a result, this usage style should be avoided when invoking scons. For single-argument - options, use the --input=ARG style on the - command line. For multiple-argument options + options, use the --input=ARG form on the + command line. For multiple-argument options (nargs greater than one), set nargs to one in - &AddOption; and combine the option-arguments into one word - with a separator, and parse the result in your own code. - See the built-in --debug option, which + &AddOption; calls and either: combine the option-arguments into one word + with a separator, and parse the result in your own code + (see the built-in --debug option, which allows specifying multiple arguments as a single comma-separated - word, for an example of such usage. + word, for an example of such usage); or allow the option to + be specified multiple times by setting + action='append'. Both methods can be + supported at the same time. - +
@@ -1166,12 +1173,12 @@ vars = Variables('custom.py', ARGUMENTS) - + where values in the option file &custom_py; get overwritten by the ones specified on the command line. - +
-- cgit v0.12 From 24b5dfae51cbb67b9274899ff42a5f9f8edd87f2 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 15 Nov 2019 13:10:56 -0700 Subject: [PR 3475] fix another xml tag error that was lurking [ci skip] docs validate again after this Signed-off-by: Mats Wichmann --- doc/man/scons.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index ae54e2e..7ee3453 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -2278,10 +2278,10 @@ env.SomeTool(targets, sources) Builder Methods -You tell scons what to build +You tell scons what to build by calling Builders, functions which know to take a particular action when given files of a particular type -to produce a particular result type. scons +to produce a particular result type. scons defines a number of builders, and you can also write your own. Builders are attached to a &consenv; as methods, and the available builder methods are listed as -- cgit v0.12 From 8822795f5e37be2e0cd694523217693fac680d55 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 15 Nov 2019 14:20:14 -0700 Subject: [PR 3475] review edit: space -> whitespace [ci skip] Signed-off-by: Mats Wichmann --- doc/user/command-line.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/user/command-line.xml b/doc/user/command-line.xml index f8f6a66..62d0558 100644 --- a/doc/user/command-line.xml +++ b/doc/user/command-line.xml @@ -681,8 +681,8 @@ foo.in - Long options and option-arguments separated by space, rather than - by =, are ambiguous. + Long options and option-arguments separated by whitespace, + rather than by =, are ambiguous. While --input=ARG has a clear meaning, for --input ARG it is not possible to tell without instructions whether -- cgit v0.12 From e4b0d2da4679582c1108ceef67d88e6415ce029b Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Sat, 16 Nov 2019 21:34:43 +1100 Subject: Fix simple typo: whos -> whose --- src/engine/SCons/Tool/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py index c8fb389..f255b21 100644 --- a/src/engine/SCons/Tool/__init__.py +++ b/src/engine/SCons/Tool/__init__.py @@ -99,7 +99,7 @@ for suffix in LaTeXSuffixes: SourceFileScanner.add_scanner(suffix, LaTeXScanner) SourceFileScanner.add_scanner(suffix, PDFLaTeXScanner) -# Tool aliases are needed for those tools whos module names also +# Tool aliases are needed for those tools whose module names also # occur in the python standard library. This causes module shadowing and # can break using python library functions under python3 TOOL_ALIASES = { -- cgit v0.12 From c3f7bb42338d5008ff908c2f4ee85c07de9fffcb Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sat, 16 Nov 2019 07:22:14 -0700 Subject: [PR 3475] update docs/generated [ci skip] There's debated about whether the generated should be checked in at all; without an answer to that, they've fallen far enough out of sync that it becomes harder to use "git diff" as a spot-check that nothing strange is happening due to any given doc change. This should resync them to current. Signed-off-by: Mats Wichmann --- doc/generated/builders.gen | 30 +++- doc/generated/functions.gen | 376 +++++++++------------------------------ doc/generated/functions.mod | 8 - doc/generated/variables.gen | 120 ++++++++----- doc/generated/variables.mod | 2 + src/engine/SCons/Script/Main.xml | 4 +- 6 files changed, 183 insertions(+), 357 deletions(-) diff --git a/doc/generated/builders.gen b/doc/generated/builders.gen index 54c7aaa..59d2dca 100644 --- a/doc/generated/builders.gen +++ b/doc/generated/builders.gen @@ -48,11 +48,15 @@ env.CFile(target = 'bar', source = 'bar.y') -The Command "Builder" is actually implemented -as a function that looks like a Builder, -but actually takes an additional argument of the action -from which the Builder should be made. -See the Command function description +The Command "Builder" is actually +a function that looks like a Builder, +but takes a required third argument, which is the +action to take to construct the target +from the source, used for "one-off" builds +where a full builder is not needed. +Thus it does not follow the builder +calling rules described at the start of this section. +See instead the Command function description for the calling syntax and details. @@ -465,6 +469,22 @@ a builder. env.Install('/usr/local/bin', source = ['foo', 'bar']) + + +If the command line +option is given, the target directory will be prefixed +by the directory path specified. +This is useful to test installs without installing to +a "live" location in the system. + + + +See also FindInstalledFiles. +For more thoughts on installation, see the User Guide +(particularly the section on Command-Line Targets +and the chapters on Installing Files and on Alias Targets). + + diff --git a/doc/generated/functions.gen b/doc/generated/functions.gen index e55799c..60e733f 100644 --- a/doc/generated/functions.gen +++ b/doc/generated/functions.gen @@ -25,8 +25,8 @@ Creates an Action object for the specified action. -See the section "Action Objects," -below, for a complete explanation of the arguments and behavior. +See the manpage section "Action Objects" +for a complete explanation of the arguments and behavior. @@ -221,6 +221,21 @@ AddOption('--prefix', help='installation prefix') env = Environment(PREFIX = GetOption('prefix')) + + + +While AddOption behaves like +optparse.add_option, +the behavior of options added by AddOption +which take arguments is underfined in +scons if whitespace +(rather than = sign) is used as +the separator on the command line when +the option is invoked. +Such usage should be avoided. + + + @@ -241,7 +256,8 @@ has been built. The specified action(s) may be an Action object, or anything that can be converted into an Action object -(see below). +See the manpage section "Action Objects" +for a complete explanation. @@ -270,7 +286,8 @@ is built. The specified action(s) may be an Action object, or anything that can be converted into an Action object -(see below). +See the manpage section "Action Objects" +for a complete explanation. @@ -444,7 +461,7 @@ Otherwise, the construction variable and the value of the keyword argument are both coerced to lists, and the lists are added together. -(See also the Prepend method, below.) +(See also the Prepend method). @@ -568,8 +585,8 @@ or Creates a Builder object for the specified action. -See the section "Builder Objects," -below, for a complete explanation of the arguments and behavior. +See the manpage section "Builder Objects" +for a complete explanation of the arguments and behavior. @@ -873,7 +890,7 @@ same-named existing construction variables. An action can be an external command, specified as a string, or a callable Python object; -see "Action Objects," below, +see the manpage section "Action Objects" for more complete information. Also note that a string specifying an external command may be preceded by an @@ -897,7 +914,7 @@ env.Command('foo.out', 'foo.in', env.Command('bar.out', 'bar.in', ["rm -f $TARGET", "$BAR_BUILD < $SOURCES > $TARGET"], - ENV = {'PATH' : '/usr/local/bin/'}) + ENV={'PATH': '/usr/local/bin/'}) def rename(env, target, source): import os @@ -905,7 +922,7 @@ def rename(env, target, source): env.Command('baz.out', 'baz.in', ["$BAZ_BUILD < $SOURCES > .tmp", - rename ]) + rename]) @@ -914,14 +931,14 @@ Note that the function will usually assume, by default, that the specified targets and/or sources are Files, if no other part of the configuration -identifies what type of entry it is. +identifies what type of entries they are. If necessary, you can explicitly specify that targets or source nodes should -be treated as directoriese +be treated as directories by using the Dir or -env.Dir() +env.Dir functions. @@ -937,9 +954,9 @@ env.Command(env.Dir('$DISTDIR')), None, make_distdir) -(Also note that SCons will usually +Also note that SCons will usually automatically create any directory necessary to hold a target file, -so you normally don't need to create directories by hand.) +so you normally don't need to create directories by hand. @@ -954,8 +971,8 @@ so you normally don't need to create directories by hand.) Creates a Configure object for integrated functionality similar to GNU autoconf. -See the section "Configure Contexts," -below, for a complete explanation of the arguments and behavior. +See the manpage section "Configure Contexts" +for a complete explanation of the arguments and behavior. @@ -1385,7 +1402,8 @@ would supply a string as a directory name to a Builder method or function. Directory Nodes have attributes and methods that are useful in many situations; -see "File and Directory Nodes," below. +see manpage section "File and Directory Nodes" +for more information. @@ -1528,8 +1546,8 @@ Executes an Action object. The specified action may be an Action object -(see the section "Action Objects," -below, for a complete explanation of the arguments and behavior), +(see manpage section "Action Objects" +for a complete explanation of the arguments and behavior), or it may be a command-line string, list of commands, or executable Python function, @@ -1686,7 +1704,8 @@ would supply a string as a file name to a Builder method or function. File Nodes have attributes and methods that are useful in many situations; -see "File and Directory Nodes," below. +see manpage section "File and Directory Nodes" +for more information. @@ -2836,7 +2855,7 @@ and the construction variables they affect are as specified for the env.ParseFlags method (which this method calls). -See that method's description, below, +See that method's description for a table of options and construction variables. @@ -3539,8 +3558,8 @@ Return('val1 val2') Creates a Scanner object for the specified function. -See the section "Scanner Objects," -below, for a complete explanation of the arguments and behavior. +See manpage section "Scanner Objects" +for a complete explanation of the arguments and behavior. @@ -4229,107 +4248,6 @@ env.SourceCode('no_source.c', None) - - - SourceSignatures(type) - - - env.SourceSignatures(type) - - - -Note: Although it is not yet officially deprecated, -use of this function is discouraged. -See the -Decider -function for a more flexible and straightforward way -to configure SCons' decision-making. - - - -The -SourceSignatures -function tells -scons -how to decide if a source file -(a file that is not built from any other files) -has changed since the last time it -was used to build a particular target file. -Legal values are -MD5 -or -timestamp. - - - -If the environment method is used, -the specified type of source signature -is only used when deciding whether targets -built with that environment are up-to-date or must be rebuilt. -If the global function is used, -the specified type of source signature becomes the default -used for all decisions -about whether targets are up-to-date. - - - -MD5 -means -scons -decides that a source file has changed -if the MD5 checksum of its contents has changed since -the last time it was used to rebuild a particular target file. - - - -timestamp -means -scons -decides that a source file has changed -if its timestamp (modification time) has changed since -the last time it was used to rebuild a particular target file. -(Note that although this is similar to the behavior of Make, -by default it will also rebuild if the dependency is -older -than the last time it was used to rebuild the target file.) - - - -There is no different between the two behaviors -for Python -Value -node objects. - - - -MD5 -signatures take longer to compute, -but are more accurate than -timestamp -signatures. -The default value is -MD5. - - - -Note that the default -TargetSignatures -setting (see below) -is to use this -SourceSignatures -setting for any target files that are used -to build other target files. -Consequently, changing the value of -SourceSignatures -will, by default, -affect the up-to-date decision for all files in the build -(or all files built with a specific construction environment -when -env.SourceSignatures -is used). - - - Split(arg) @@ -4501,161 +4419,6 @@ Tag( 'file2.txt', DOC ) - - - TargetSignatures(type) - - - env.TargetSignatures(type) - - - -Note: Although it is not yet officially deprecated, -use of this function is discouraged. -See the -Decider -function for a more flexible and straightforward way -to configure SCons' decision-making. - - - -The -TargetSignatures -function tells -scons -how to decide if a target file -(a file that -is -built from any other files) -has changed since the last time it -was used to build some other target file. -Legal values are -"build"; -"content" -(or its synonym -"MD5"); -"timestamp"; -or -"source". - - - -If the environment method is used, -the specified type of target signature is only used -for targets built with that environment. -If the global function is used, -the specified type of signature becomes the default -used for all target files that -don't have an explicit target signature type -specified for their environments. - - - -"content" -(or its synonym -"MD5") -means -scons -decides that a target file has changed -if the MD5 checksum of its contents has changed since -the last time it was used to rebuild some other target file. -This means -scons -will open up -MD5 sum the contents -of target files after they're built, -and may decide that it does not need to rebuild -"downstream" target files if a file was -rebuilt with exactly the same contents as the last time. - - - -"timestamp" -means -scons -decides that a target file has changed -if its timestamp (modification time) has changed since -the last time it was used to rebuild some other target file. -(Note that although this is similar to the behavior of Make, -by default it will also rebuild if the dependency is -older -than the last time it was used to rebuild the target file.) - - - -"source" -means -scons -decides that a target file has changed -as specified by the corresponding -SourceSignatures -setting -("MD5" -or -"timestamp"). -This means that -scons -will treat all input files to a target the same way, -regardless of whether they are source files -or have been built from other files. - - - -"build" -means -scons -decides that a target file has changed -if it has been rebuilt in this invocation -or if its content or timestamp have changed -as specified by the corresponding -SourceSignatures -setting. -This "propagates" the status of a rebuilt file -so that other "downstream" target files -will always be rebuilt, -even if the contents or the timestamp -have not changed. - - - -"build" -signatures are fastest because -"content" -(or -"MD5") -signatures take longer to compute, -but are more accurate than -"timestamp" -signatures, -and can prevent unnecessary "downstream" rebuilds -when a target file is rebuilt to the exact same contents -as the previous build. -The -"source" -setting provides the most consistent behavior -when other target files may be rebuilt from -both source and target input files. -The default value is -"source". - - - -Because the default setting is -"source", -using -SourceSignatures -is generally preferable to -TargetSignatures, -so that the up-to-date decision -will be consistent for all files -(or all files built with a specific construction environment). -Use of -TargetSignatures -provides specific control for how built target files -affect their "downstream" dependencies. - - - Tool(string, [toolpath, **kw]) @@ -4949,30 +4712,51 @@ SConscript(dirs='doc', variant_dir='build/doc', duplicate=0) Searches for the specified executable program, returning the full path name to the program -if it is found, -and returning None if not. -Searches the specified -path, -the value of the calling environment's PATH -(env['ENV']['PATH']), -or the user's current external PATH -(os.environ['PATH']) -by default. +if it is found, else None. +Searches the value of the +path keyword argument, +or if None (the default) +the value of the calling environment's PATH +(env['ENV']['PATH']). +If path is None and +the env['ENV']['PATH'] key does not exist, +the user's current external PATH +(os.environ['PATH']) is used as fallback. + + On Windows systems, searches for executable -programs with any of the file extensions -listed in the specified -pathext, -the calling environment's PATHEXT -(env['ENV']['PATHEXT']) -or the user's current PATHEXT +programs with any of the file extensions listed in the +pathext keyword argument, +or if None (the default) +the calling environment's PATHEXT +(env['ENV']['PATHEXT']). +The user's current external PATHEXT (os.environ['PATHEXT']) -by default. +is used as a fallback if pathext is +None +and the key env['ENV']['PATHEXT'] +does not exist. + + Will not select any path name or names in the specified reject list, if any. + + +If you would prefer to search +the user's current external PATH +(os.environ['PATH']) +by default, +consider using the function SCons.Util.WhereIs instead. +Note that SCons.Util.WhereIs +does not expand environment variables automatically +(no implicit env.subst for its arguments). + + + diff --git a/doc/generated/functions.mod b/doc/generated/functions.mod index e460aaf..91710a3 100644 --- a/doc/generated/functions.mod +++ b/doc/generated/functions.mod @@ -82,11 +82,9 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. SetOption"> SideEffect"> SourceCode"> -SourceSignatures"> Split"> subst"> Tag"> -TargetSignatures"> Tool"> Value"> VariantDir"> @@ -166,11 +164,9 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. env.SetOption"> env.SideEffect"> env.SourceCode"> -env.SourceSignatures"> env.Split"> env.subst"> env.Tag"> -env.TargetSignatures"> env.Tool"> env.Value"> env.VariantDir"> @@ -260,11 +256,9 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. SetOption"> SideEffect"> SourceCode"> -SourceSignatures"> Split"> subst"> Tag"> -TargetSignatures"> Tool"> Value"> VariantDir"> @@ -344,11 +338,9 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. env.SetOption"> env.SideEffect"> env.SourceCode"> -env.SourceSignatures"> env.Split"> env.subst"> env.Tag"> -env.TargetSignatures"> env.Tool"> env.Value"> env.VariantDir"> diff --git a/doc/generated/variables.gen b/doc/generated/variables.gen index 8f09512..cf54aab 100644 --- a/doc/generated/variables.gen +++ b/doc/generated/variables.gen @@ -488,7 +488,8 @@ after the SCons template for the file has been written. A reserved variable name that may not be set or used in a construction environment. -(See "Variable Substitution," below.) +(See the manpage section "Variable Substitution" +for more information). @@ -498,7 +499,8 @@ that may not be set or used in a construction environment. A reserved variable name that may not be set or used in a construction environment. -(See "Variable Substitution," below.) +(See the manpage section "Variable Substitution" +for more information). @@ -2804,15 +2806,6 @@ is -dNOPAUSE -dBATCH -sDEVICE=pdfwrite HOST_ARCH - The name of the host hardware architecture used to create the Environment. - If a platform is specified when creating the Environment, then - that Platform's logic will handle setting this value. - This value is immutable, and should not be changed by the user after - the Environment is initialized. - Currently only set for Win32. - - - Sets the host architecture for Visual Studio compiler. If not set, default to the detected host architecture: note that this may depend on the python you are using. @@ -2828,7 +2821,16 @@ Valid values are the same as for This is currently only used on Windows, but in the future it will be used on other OSes as well. - + + + The name of the host hardware architecture used to create the Environment. + If a platform is specified when creating the Environment, then + that Platform's logic will handle setting this value. + This value is immutable, and should not be changed by the user after + the Environment is initialized. + Currently only set for Win32. + + HOST_OS @@ -2900,7 +2902,7 @@ to '.dll'. Used to override $SHLIBVERSION/$LDMODULEVERSION when generating versioned import library for a shared library/loadable module. If undefined, the $SHLIBVERSION/$LDMODULEVERSION is used to -determine the version of versioned import library. +determine the version of versioned import library. @@ -3070,7 +3072,7 @@ 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 $JARCOM (the command line) is displayed. +If this is not set, then $JARCOM (the command line) is displayed. @@ -3080,7 +3082,7 @@ env = Environment(JARCOMSTR = "JARchiving $SOURCES into $TARGET") The string displayed when the Java archive tool is called -If this is not set, then $JARCOM (the command line) is displayed. +If this is not set, then $JARCOM (the command line) is displayed. @@ -3446,6 +3448,17 @@ 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 @@ -3618,7 +3631,10 @@ when the $_LIBDIRFLAGS va LIBEMITTER -TODO +Contains the emitter specification for the +StaticLibrary builder. +The manpage section "Builder Objects" contains +general information on specifying emitters. @@ -5108,7 +5124,10 @@ for example. PROGEMITTER -TODO +Contains the emitter specification for the +Program builder. +The manpage section "Builder Objects" contains +general information on specifying emitters. @@ -5803,9 +5822,9 @@ appending to this list, although the more flexible approach is to associate scanners with a specific Builder. -See the sections "Builder Objects" -and "Scanner Objects," -below, for more information. +See the manpage sections "Builder Objects" +and "Scanner Objects" +for more information. @@ -6465,7 +6484,10 @@ If this is not set, then -TODO +Contains the emitter specification for the +SharedLibrary builder. +The manpage section "Builder Objects" contains +general information on specifying emitters. @@ -6509,7 +6531,7 @@ The suffix used for shared library file names. When this construction variable is defined, a versioned shared library -is created by SharedLibrary builder. This activates the +is created by the SharedLibrary builder. This activates the $_SHLIBVERSIONFLAGS and thus modifies the $SHLINKCOM as required, adds the version number to the library name, and creates the symlinks that are needed. $SHLIBVERSION versions should exist as alpha-numeric, @@ -6518,6 +6540,16 @@ Example + + SHLIBVERSIONFLAGS + + +Extra flags added to $SHLINKCOM when building versioned +SharedLibrary. These flags are only used when $SHLIBVERSION is +set. + + + _SHLIBVERSIONFLAGS @@ -6531,16 +6563,6 @@ and some extra dynamically generated options (such as - - SHLIBVERSIONFLAGS - - -Extra flags added to $SHLINKCOM when building versioned -SharedLibrary. These flags are only used when $SHLIBVERSION is -set. - - - SHLINK @@ -6629,7 +6651,8 @@ The variable is used, for example, by A reserved variable name that may not be set or used in a construction environment. -(See "Variable Substitution," below.) +(See the manpage section "Variable Substitution" +for more information). @@ -6652,7 +6675,8 @@ field in the controlling information for Ipkg and RPM packages. A reserved variable name that may not be set or used in a construction environment. -(See "Variable Substitution," below.) +(See the manpage section "Variable Substitution" +for more information). @@ -6996,7 +7020,8 @@ General options passed to the tar archiver. A reserved variable name that may not be set or used in a construction environment. -(See "Variable Substitution," below.) +(See the manpage section "Variable Substitution" +for more information). @@ -7004,13 +7029,6 @@ that may not be set or used in a construction environment. TARGET_ARCH - The name of the target hardware architecture for the compiled objects - created by this Environment. - This defaults to the value of HOST_ARCH, and the user can override it. - Currently only set for Win32. - - - Sets the target architecture for Visual Studio compiler (i.e. the arch of the binaries generated by the compiler). If not set, default to $HOST_ARCH, or, if that is unset, to the architecture of the @@ -7041,7 +7059,14 @@ and ia64 (Itanium). For example, if you want to compile 64-bit binaries, you would set TARGET_ARCH='x86_64' in your SCons environment. - + + + The name of the target hardware architecture for the compiled objects + created by this Environment. + This defaults to the value of HOST_ARCH, and the user can override it. + Currently only set for Win32. + + TARGET_OS @@ -7060,7 +7085,8 @@ For example, if you want to compile 64-bit binaries, you would set A reserved variable name that may not be set or used in a construction environment. -(See "Variable Substitution," below.) +(See the manpage section "Variable Substitution" +for more information). @@ -7193,7 +7219,8 @@ that are part of this construction environment. A reserved variable name that may not be set or used in a construction environment. -(See "Variable Substitution," below.) +(See the manpage section "Variable Substitution" +for more information). @@ -7203,7 +7230,8 @@ that may not be set or used in a construction environment. A reserved variable name that may not be set or used in a construction environment. -(See "Variable Substitution," below.) +(See the manpage section "Variable Substitution" +for more information). diff --git a/doc/generated/variables.mod b/doc/generated/variables.mod index 372a15f..1a5bc97 100644 --- a/doc/generated/variables.mod +++ b/doc/generated/variables.mod @@ -251,6 +251,7 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $LDMODULE"> $LDMODULECOM"> $LDMODULECOMSTR"> +$LDMODULEEMITTER"> $LDMODULEFLAGS"> $LDMODULENOVERSIONSYMLINKS"> $LDMODULEPREFIX"> @@ -891,6 +892,7 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $LDMODULE"> $LDMODULECOM"> $LDMODULECOMSTR"> +$LDMODULEEMITTER"> $LDMODULEFLAGS"> $LDMODULENOVERSIONSYMLINKS"> $LDMODULEPREFIX"> diff --git a/src/engine/SCons/Script/Main.xml b/src/engine/SCons/Script/Main.xml index 13ad336..514c1ae 100644 --- a/src/engine/SCons/Script/Main.xml +++ b/src/engine/SCons/Script/Main.xml @@ -138,9 +138,9 @@ env = Environment(PREFIX = GetOption('prefix')) While &AddOption; behaves like optparse.add_option, -the behavior of options added by &AddOption; +the behavior of options added by &AddOption; which take arguments is underfined in -scons if a space +scons if whitespace (rather than = sign) is used as the separator on the command line when the option is invoked. -- cgit v0.12 From d2e7ec3dcc8d0c2c401eefc9c36d91a19c9bbb2b Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Sun, 17 Nov 2019 17:28:46 +1100 Subject: Update CHANGES.txt --- src/CHANGES.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 617b3d0..be0c6b8 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -42,6 +42,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER From Edoardo Bezzeccheri - Added debug option "action_timestamps" which outputs to stdout the absolute start and end time for each target. + From Tim Gates + - Resolved a typo in engine.SCons.Tool RELEASE 3.1.1 - Mon, 07 Aug 2019 20:09:12 -0500 -- cgit v0.12 From edaee69677e2a07b2d515e821acb4d58cc5c8196 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Thu, 21 Nov 2019 08:58:05 -0700 Subject: [PR 3475] further wording tweaks on AddOption [ci skip] Reword some parts. Add note to manpage that AddOption does not support matching "abbreviations" for long option names. Add note to manpage and user guide that you can't SetOption on options added via AddOption. (as noted in issue #2105) Signed-off-by: Mats Wichmann --- doc/user/command-line.xml | 30 ++++++++++++++++++------------ src/engine/SCons/Script/Main.xml | 26 ++++++++++++++++++++------ 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/doc/user/command-line.xml b/doc/user/command-line.xml index 62d0558..d8f9fff 100644 --- a/doc/user/command-line.xml +++ b/doc/user/command-line.xml @@ -599,25 +599,30 @@ foo.in &SCons; also allows you to define your own command-line options with the &AddOption; function. The &AddOption; function takes the same arguments - as the optparse.add_option function - from the standard Python library. + as the add_option method + from the standard Python library module optparse. The &AddOption; function is, in fact, implemented using a subclass - of the optparse.OptionParser. + of optparse.OptionParser. + + Once you have added a custom command-line option with the &AddOption; function, the value of the option (if any) is immediately available using the standard &GetOption; function. + + &SetOption; is not currently supported for + options added with &AddOption;. @@ -681,21 +686,22 @@ foo.in - Long options and option-arguments separated by whitespace, - rather than by =, are ambiguous. + Option-arguments separated from long options by whitespace, + rather than by an =, cannot be correctly + resolved by scons. While --input=ARG - has a clear meaning, for --input ARG it is not - possible to tell without instructions whether + is clearly opt followed by arg, for --input ARG + it is not possible to tell without instructions whether ARG is an argument belonging to the input option or a positional argument. scons treats positional arguments as either command-line build options or command-line targets - (see the immediately following sections for details), - which are made available for use in the &SConscript;. + which are made available for use in an &SConscript; + (see the immediately following sections for details). Thus, they must be collected before &SConscript; processing takes place. Since &AddOption; calls, which provide - the processing instructions to resolve the ambiguity, - happen in the &SConscript;, + the processing instructions to resolve any ambiguity, + happen in an &SConscript;, scons does not know in time for options added this way, and unexpected things will happen, such as option-arguments assigned as targets and/or exceptions diff --git a/src/engine/SCons/Script/Main.xml b/src/engine/SCons/Script/Main.xml index 514c1ae..f518422 100644 --- a/src/engine/SCons/Script/Main.xml +++ b/src/engine/SCons/Script/Main.xml @@ -33,11 +33,11 @@ See its __doc__ string for a discussion of the format. This function adds a new command-line option to be recognized. The specified arguments -are the same as supported by the standard Python -optparse.add_option() -method (with a few additional capabilities noted below); +are the same as supported by the add_option +method in the standard Python library module optparse, +with a few additional capabilities noted below; see the documentation for -optparse +optparse for a thorough discussion of its option-processing capabities. @@ -78,12 +78,22 @@ the option will have a default value of +Unlike regular optparse, option names +added via AddOption must be matched +exactly, the automatic matching of abbreviations on the +command line for long options is not supported. +To allow specific abbreviations, +include them in the &f-AddOption; call. + + + Once a new command-line option has been added with &f-AddOption;, the option value may be accessed using &f-GetOption; or env.GetOption(). + +&f-SetOption; is not currently supported for +options added with &f-AddOption;. @@ -137,11 +150,12 @@ env = Environment(PREFIX = GetOption('prefix')) While &AddOption; behaves like -optparse.add_option, +add_option, +from the optparse module, the behavior of options added by &AddOption; which take arguments is underfined in scons if whitespace -(rather than = sign) is used as +(rather than an = sign) is used as the separator on the command line when the option is invoked. Such usage should be avoided. -- 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 7c34a7d12cccd0448670323297ee12e4575ef749 Mon Sep 17 00:00:00 2001 From: Rob Boehne Date: Tue, 26 Nov 2019 11:48:17 -0600 Subject: Fix a problem under Solaris when using Python 3, while maintaining support for Python 2.7. subproces.Popen() produces bytes without the encoding argument in 3, which is not recognized by 2.7, and doesn't need to be decoded. --- src/engine/SCons/Tool/suncxx.py | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/src/engine/SCons/Tool/suncxx.py b/src/engine/SCons/Tool/suncxx.py index 090df7d..d38c2cf 100644 --- a/src/engine/SCons/Tool/suncxx.py +++ b/src/engine/SCons/Tool/suncxx.py @@ -39,12 +39,14 @@ import os import re import subprocess +from SCons.Util import PY3 import SCons.Tool.cxx cplusplus = SCons.Tool.cxx -#cplusplus = __import__('c++', globals(), locals(), []) +# cplusplus = __import__('c++', globals(), locals(), []) package_info = {} + def get_package_info(package_name, pkginfo, pkgchk): try: return package_info[package_name] @@ -52,7 +54,7 @@ def get_package_info(package_name, pkginfo, pkgchk): version = None pathname = None try: - from subprocess import DEVNULL # py3k + from subprocess import DEVNULL # py3k except ImportError: DEVNULL = open(os.devnull, 'wb') @@ -68,13 +70,18 @@ def get_package_info(package_name, pkginfo, pkgchk): pathname = os.path.dirname(sadm_match.group(1)) try: + popen_args = {'stdout': subprocess.PIPE, + 'stderr': DEVNULL} + if PY3: + popen_args['encoding'] = 'utf-8' p = subprocess.Popen([pkginfo, '-l', package_name], - stdout=subprocess.PIPE, - stderr=DEVNULL) + **popen_args) except EnvironmentError: pass else: - pkginfo_contents = p.communicate()[0].decode() + pkginfo_contents = p.communicate()[0] + if not PY3: + pkginfo_contents.decode() version_re = re.compile(r'^ *VERSION:\s*(.*)$', re.M) version_match = version_re.search(pkginfo_contents) if version_match: @@ -82,13 +89,18 @@ def get_package_info(package_name, pkginfo, pkgchk): if pathname is None: try: + popen_args = {'stdout': subprocess.PIPE, + 'stderr': DEVNULL} + if PY3: + popen_args['encoding'] = 'utf-8' p = subprocess.Popen([pkgchk, '-l', package_name], - stdout=subprocess.PIPE, - stderr=DEVNULL) + **popen_args) except EnvironmentError: pass else: - pkgchk_contents = p.communicate()[0].decode() + pkgchk_contents = p.communicate()[0] + if not PY3: + pkgchk_contents.decode() pathname_re = re.compile(r'^Pathname:\s*(.*/bin/CC)$', re.M) pathname_match = pathname_re.search(pkgchk_contents) if pathname_match: @@ -97,7 +109,8 @@ def get_package_info(package_name, pkginfo, pkgchk): package_info[package_name] = (pathname, version) return package_info[package_name] -# use the package installer tool lslpp to figure out where cppc and what + +# use the package installer tool "pkg" to figure out where cppc and what # version of it is installed def get_cppc(env): cxx = env.subst('$CXX') @@ -119,6 +132,7 @@ def get_cppc(env): return (cppcPath, 'CC', 'CC', cppcVersion) + def generate(env): """Add Builders and construction variables for SunPRO C++.""" path, cxx, shcxx, version = get_cppc(env) @@ -131,10 +145,11 @@ def generate(env): env['CXX'] = cxx env['SHCXX'] = shcxx env['CXXVERSION'] = version - env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS -KPIC') - env['SHOBJPREFIX'] = 'so_' - env['SHOBJSUFFIX'] = '.o' - + env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS -KPIC') + env['SHOBJPREFIX'] = 'so_' + env['SHOBJSUFFIX'] = '.o' + + def exists(env): path, cxx, shcxx, version = get_cppc(env) if path and cxx: -- cgit v0.12 From 5bf4eabac323a728788120f5c3752a9643e6c35c Mon Sep 17 00:00:00 2001 From: Rob Boehne Date: Tue, 26 Nov 2019 14:57:19 -0600 Subject: try a different approach that should work on python 3.5. --- src/engine/SCons/Tool/suncxx.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/engine/SCons/Tool/suncxx.py b/src/engine/SCons/Tool/suncxx.py index d38c2cf..c155484 100644 --- a/src/engine/SCons/Tool/suncxx.py +++ b/src/engine/SCons/Tool/suncxx.py @@ -73,7 +73,7 @@ def get_package_info(package_name, pkginfo, pkgchk): popen_args = {'stdout': subprocess.PIPE, 'stderr': DEVNULL} if PY3: - popen_args['encoding'] = 'utf-8' + popen_args['universal_newlines'] = True p = subprocess.Popen([pkginfo, '-l', package_name], **popen_args) except EnvironmentError: @@ -92,7 +92,7 @@ def get_package_info(package_name, pkginfo, pkgchk): popen_args = {'stdout': subprocess.PIPE, 'stderr': DEVNULL} if PY3: - popen_args['encoding'] = 'utf-8' + popen_args['universal_newlines'] = True p = subprocess.Popen([pkgchk, '-l', package_name], **popen_args) except EnvironmentError: -- 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 83303e4e9f655d0f3af5e7c369f84ec57daa756b Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 27 Nov 2019 12:02:41 -0800 Subject: [ci skip] Add to CHANGES.txt for PR #3481 --- src/CHANGES.txt | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index db0a5f2..e24555d 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -6,13 +6,32 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER + From Edoardo Bezzeccheri + - Added debug option "action_timestamps" which outputs to stdout the absolute start and end time for each target. + + From Rob Boehne + - Fix suncxx tool (Oracle Studio compiler) when using Python 3. Previously would throw an exception. + Resolved by properly handling tool version string output as unicode. + + From Tim Gates + - Resolved a typo in engine.SCons.Tool + + From Ivan Kravets + - Added support for "-imacros" to ParseFlags + + From Jacek Kuczera: + - Fix CheckFunc detection code for Visual 2019. Some functions + (e.g. memmove) were incorrectly recognized as not available. + + From Jakub Kulik + - Fix subprocess result bytes not being decoded in SunOS/Solaris related tools. + 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 the fontenc package is included with \usepackage[T1]{fontenc}) is read. From Mathew Robinson: - - Improved threading performance by ensuring NodeInfo is shared across threads. Results in ~13% improvement for parallel builds (-j# > 1) with many shared nodes. @@ -32,21 +51,6 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Remove deprecated SourceSignatures, TargetSignatures - Remove deprecated Builder keywords: overrides and scanner - From Jacek Kuczera: - - Fix CheckFunc detection code for Visual 2019. Some functions - (e.g. memmove) were incorrectly recognized as not available. - - From Jakub Kulik - - Fix subprocess result bytes not being decoded in SunOS/Solaris related tools. - - From Edoardo Bezzeccheri - - Added debug option "action_timestamps" which outputs to stdout the absolute start and end time for each target. - - From Ivan Kravets - - Added support for "-imacros" to ParseFlags - - From Tim Gates - - Resolved a typo in engine.SCons.Tool RELEASE 3.1.1 - Mon, 07 Aug 2019 20:09:12 -0500 -- 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 7d89e07d3de486dcc8052663a7b0a37bd486efae Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Fri, 25 Oct 2019 12:15:39 -0400 Subject: Add support for scanning multiple entries in an action string This change adds support for scanning multiple entries in an action string in order to better support the following use cases: 1. A file is provided in an action string and should be taken as a dependency. For example, an action string "$PERL somefile.pl". 2. An action string actually has two actions separated by &&. For example, "cd && $ZIP ". Adding support for #1 actually allows us to fix the test IMPLICIT_COMMAND_DEPENDENCIES.py on Windows, which was previously treating a Python file as executable even on Windows. This was causing tests to repeatedly open the default handler of Python files, which if set to Visual Studio causes DDE hangs. This test is fixed because now we can have the action string specify python as the first command and still take an implicit dependency on the script, which is now the second command. --- src/CHANGES.txt | 4 ++ src/engine/SCons/Action.py | 35 ++++++++++++--- test/implicit/IMPLICIT_COMMAND_DEPENDENCIES.py | 62 ++++++++++++++------------ 3 files changed, 66 insertions(+), 35 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index e24555d..8c658f6 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -16,6 +16,10 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER From Tim Gates - Resolved a typo in engine.SCons.Tool + From Adam Gross: + - Added support for scanning multiple entries in an action string if + implicit command dependency scanning is enabled. + From Ivan Kravets - Added support for "-imacros" to ParseFlags diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index c6fc575..ccd5c17 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -853,6 +853,16 @@ class CommandAction(_ActionAction): "a single command") self.cmd_list = cmd + # Regex meant to parse a file path in the following cases: + # /path/to/file + # '/path/to/file' + # "C:\path\to\file" + # Does not allow for stripping off an optional @ before the parameter. + # We don't need to support detecting temp files generated by + # TempFileMunge because in signature mode (which is what is used during + # action scanning) TempFileMunge doesn't modify the command string. + self.command_strip = re.compile('^[\'"]?([^\'"]*)[\'"]?$') + def __str__(self): if is_List(self.cmd_list): return ' '.join(map(str, self.cmd_list)) @@ -987,15 +997,26 @@ class CommandAction(_ActionAction): else: cmd_list = env.subst_list(self.cmd_list, SUBST_SIG, target, source) res = [] + + # Avoid circular dependencies by ignoring any paths to targets. + targets_norm = set() + for t in target: + targets_norm.add(os.path.normcase(t.abspath)) + targets_norm.add(os.path.normcase(str(t))) + for cmd_line in cmd_list: if cmd_line: - d = str(cmd_line[0]) - m = strip_quotes.match(d) - if m: - d = m.group(1) - d = env.WhereIs(d) - if d: - res.append(env.fs.File(d)) + for entry in cmd_line: + d = str(entry) + if not d.startswith(('&', '-', '/') if os.name == 'nt' + else ('&', '-')): + m = self.command_strip.match(d) + if m: + d = m.group(1) + # For now, only match files, not directories. + d = d if os.path.isfile(d) else env.WhereIs(d) + if d and os.path.normcase(d) not in targets_norm: + res.append(env.fs.File(d)) return res diff --git a/test/implicit/IMPLICIT_COMMAND_DEPENDENCIES.py b/test/implicit/IMPLICIT_COMMAND_DEPENDENCIES.py index 2431a61..c7ce0b5 100644 --- a/test/implicit/IMPLICIT_COMMAND_DEPENDENCIES.py +++ b/test/implicit/IMPLICIT_COMMAND_DEPENDENCIES.py @@ -40,6 +40,8 @@ _python_ = TestSCons._python_ test = TestSCons.TestSCons() +test.write('file.in', "file.in\n") + generate_build_py_py_contents = """\ #!%(python)s import os @@ -61,17 +63,17 @@ os.chmod(sys.argv[1], 0o755) """ -extra = '' -test.write('generate_build_py.py', generate_build_py_py_contents % locals()) - +workpath = test.workpath() test.write('SConstruct', """ DefaultEnvironment(tools=[]) generate = Builder(action = r'%(_python_)s $GENERATE $TARGET') -build = Builder(action = r'$BUILD_PY $TARGET $SOURCES') +build = Builder(action = r'%(_python_)s $BUILD_PY $TARGET $SOURCES') +cd_and_build = Builder(action = r'cd %(workpath)s && %(_python_)s $BUILD_PY $TARGET $SOURCES') env = Environment(tools=[], BUILDERS = { 'GenerateBuild' : generate, 'BuildFile' : build, + 'CdAndBuildFile': cd_and_build, }, GENERATE = 'generate_build_py.py', BUILD_PY = 'build.py', @@ -94,40 +96,44 @@ envNone.BuildFile('fileNone.out', 'file.in') envFalse.BuildFile('fileFalse.out', 'file.in') envTrue.BuildFile('fileTrue.out', 'file.in') envTrue.BuildFile('fileQuote.out', 'file.in', BUILD_PY='"build.py"') -""" % locals()) +env.CdAndBuildFile('cd_file.out', 'file.in') +""" % locals()) -test.write('file.in', "file.in\n") - -test.run(arguments = '--tree=all .') - -expect_none = 'build.py %s file.in\nfile.in\n' -test.must_match('file.out', expect_none % 'file.out', mode='r') -test.must_match('file0.out', expect_none % 'file0.out', mode='r') -test.must_match('file1.out', expect_none % 'file1.out', mode='r') -test.must_match('fileNone.out', expect_none % 'fileNone.out', mode='r') -test.must_match('fileFalse.out', expect_none % 'fileFalse.out', mode='r') -test.must_match('fileTrue.out', expect_none % 'fileTrue.out', mode='r') -test.must_match('fileQuote.out', expect_none % 'fileQuote.out', mode='r') +def run_test(extra, python, _python_): + # Write the generate_build_py.py file. This uses the contents of the + # variable "extra" while writing build.py. + test.write('generate_build_py.py', + generate_build_py_py_contents % locals()) + # Run the SConscript file. + test.run(arguments = '--tree=all .') + # Generate some expected data, which depends on the value of "extra". + expect_none = 'build.py %s file.in\nfile.in\n' + expect_extra = (expect_none if not extra else + 'build.py %s file.in\n{}file.in\n'.format( + extra.replace('\\\\n', '\n'))) + expect_extra_abs = '{} %s file.in\n{}file.in\n'.format( + test.workpath('build.py'), + extra.replace('\\\\n', '\n')) -extra = 'xyzzy\\\\n' -test.write('generate_build_py.py', generate_build_py_py_contents % locals()) + # Verify that the output matches what is expected. + test.must_match('file.out', expect_extra % 'file.out', mode='r') + test.must_match('file0.out', expect_none % 'file0.out', mode='r') + test.must_match('file1.out', expect_extra % 'file1.out', mode='r') + test.must_match('fileNone.out', expect_none % 'fileNone.out', mode='r') + test.must_match('fileFalse.out', expect_none % 'fileFalse.out', mode='r') + test.must_match('fileTrue.out', expect_extra % 'fileTrue.out', mode='r') + test.must_match('fileQuote.out', expect_extra % 'fileQuote.out', mode='r') + test.must_match('cd_file.out', expect_extra % 'cd_file.out', mode='r') -test.run(arguments = '--tree=all .') -expect_extra = 'build.py %s file.in\nxyzzy\nfile.in\n' +run_test('', python, _python_) +run_test('xyzzy\\\\n', python, _python_) -test.must_match('file.out', expect_extra % 'file.out', mode='r') -test.must_match('file0.out', expect_none % 'file0.out', mode='r') -test.must_match('file1.out', expect_extra % 'file1.out', mode='r') -test.must_match('fileNone.out', expect_none % 'fileNone.out', mode='r') -test.must_match('fileFalse.out', expect_none % 'fileFalse.out', mode='r') -test.must_match('fileTrue.out', expect_extra % 'fileTrue.out', mode='r') -test.must_match('fileQuote.out', expect_extra % 'fileQuote.out', mode='r') test.pass_test() -- cgit v0.12 From 3363b244c7682a32a2a642d92e26d150c288abb5 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sun, 10 Nov 2019 11:01:41 -0700 Subject: Typo in testing document [ci skip] lack of a consistent indent confused ReST readers: System Message: WARNING/2 (/home/mats/github/scons/testing/framework/test-framework.rst, line 32) Block quote ends without a blank line; unexpected unindent. Signed-off-by: Mats Wichmann --- testing/framework/test-framework.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/framework/test-framework.rst b/testing/framework/test-framework.rst index cb6b8e1..24240ac 100644 --- a/testing/framework/test-framework.rst +++ b/testing/framework/test-framework.rst @@ -29,7 +29,7 @@ There are three types of SCons tests: ``src/engine/`` subdirectory and are the same base name as the module to be tests, with ``Tests`` appended before the ``.py``. For example, the unit tests for the ``Builder.py`` module are in the - ``BuilderTests.py`` script. Unit tests tend to be based on assertions. + ``BuilderTests.py`` script. Unit tests tend to be based on assertions. *External Tests* For the support of external Tools (in the form of packages, preferably), -- cgit v0.12 From b4f7dace38719ebb9a0f00c44a69f00d3caa5cfe Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sat, 30 Nov 2019 07:30:17 -0700 Subject: fix more Python escape complaints Write as raw strings: Two are docstrings that contain a backslash; the third is an odd expression parenthesized for no good reason and containing backslashes. Signed-off-by: Mats Wichmann --- src/engine/SCons/Tool/intelc.py | 4 ++-- src/engine/SCons/Tool/packaging/msi.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/engine/SCons/Tool/intelc.py b/src/engine/SCons/Tool/intelc.py index 1f3fcea..7550c34 100644 --- a/src/engine/SCons/Tool/intelc.py +++ b/src/engine/SCons/Tool/intelc.py @@ -387,7 +387,7 @@ def get_intel_compiler_top(version, abi): def generate(env, version=None, abi=None, topdir=None, verbose=0): - """Add Builders and construction variables for Intel C/C++ compiler + r"""Add Builders and construction variables for Intel C/C++ compiler to an Environment. args: version: (string) compiler version to use, like "80" @@ -551,7 +551,7 @@ def generate(env, version=None, abi=None, topdir=None, verbose=0): # Look for license file dir # in system environment, registry, and default location. envlicdir = os.environ.get("INTEL_LICENSE_FILE", '') - K = ('SOFTWARE\Intel\Licenses') + K = r'SOFTWARE\Intel\Licenses' try: k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE, K) reglicdir = SCons.Util.RegQueryValueEx(k, "w_cpp")[0] diff --git a/src/engine/SCons/Tool/packaging/msi.py b/src/engine/SCons/Tool/packaging/msi.py index 0ef18ec..34e4f0f 100644 --- a/src/engine/SCons/Tool/packaging/msi.py +++ b/src/engine/SCons/Tool/packaging/msi.py @@ -224,7 +224,7 @@ def build_wxsfile(target, source, env): # setup function # def create_default_directory_layout(root, NAME, VERSION, VENDOR, filename_set): - """ Create the wix default target directory layout and return the innermost + r""" Create the wix default target directory layout and return the innermost directory. We assume that the XML tree delivered in the root argument already contains -- cgit v0.12 From 5711640410fa2b4a4dc3deb02e262021f230778b Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Mon, 2 Dec 2019 17:05:57 -0500 Subject: Various improvements to the change --- src/engine/SCons/Action.py | 50 +++++++++++++++++++++--------------------- test/Batch/CHANGED_SOURCES.py | 5 ++++- test/Batch/action-changed.py | 12 +++++++--- test/Depends/Depends.py | 6 ++++- test/ParseDepends.py | 5 ++++- test/Repository/link-object.py | 6 +++++ test/explain/basic.py | 38 ++++++++++++++++++++++---------- 7 files changed, 79 insertions(+), 43 deletions(-) diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index ccd5c17..2dea8cc 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -853,16 +853,6 @@ class CommandAction(_ActionAction): "a single command") self.cmd_list = cmd - # Regex meant to parse a file path in the following cases: - # /path/to/file - # '/path/to/file' - # "C:\path\to\file" - # Does not allow for stripping off an optional @ before the parameter. - # We don't need to support detecting temp files generated by - # TempFileMunge because in signature mode (which is what is used during - # action scanning) TempFileMunge doesn't modify the command string. - self.command_strip = re.compile('^[\'"]?([^\'"]*)[\'"]?$') - def __str__(self): if is_List(self.cmd_list): return ' '.join(map(str, self.cmd_list)) @@ -992,17 +982,12 @@ class CommandAction(_ActionAction): if not icd or icd in ('0', 'None'): return [] from SCons.Subst import SUBST_SIG - if executor: - cmd_list = env.subst_list(self.cmd_list, SUBST_SIG, executor=executor) - else: - cmd_list = env.subst_list(self.cmd_list, SUBST_SIG, target, source) - res = [] - # Avoid circular dependencies by ignoring any paths to targets. - targets_norm = set() - for t in target: - targets_norm.add(os.path.normcase(t.abspath)) - targets_norm.add(os.path.normcase(str(t))) + # Avoid circular and duplicate dependencies by not provide source and + # target to subst_list. This causes references to $SOURCES, $TARGETS, + # and all related variables to disappear. + cmd_list = env.subst_list(self.cmd_list, SUBST_SIG, [], []) + res = [] for cmd_line in cmd_list: if cmd_line: @@ -1010,13 +995,28 @@ class CommandAction(_ActionAction): d = str(entry) if not d.startswith(('&', '-', '/') if os.name == 'nt' else ('&', '-')): - m = self.command_strip.match(d) + m = strip_quotes.match(d) if m: d = m.group(1) - # For now, only match files, not directories. - d = d if os.path.isfile(d) else env.WhereIs(d) - if d and os.path.normcase(d) not in targets_norm: - res.append(env.fs.File(d)) + + # For now, only match files, not directories. + p = os.path.abspath(d) if os.path.isfile(d) else \ + env.WhereIs(d) + if p: + res.append(env.fs.File(p)) + else: + # Try to find the dependency in any source + # repositories. + # + # TODO: I want to enumerate get_all_rdirs() and am + # not sure whether I want to enumerate + # srcdir_list(). srcdir_find_file() does both. Is + # that bad? Should we instead change env.WhereIs() + # to search in repositories too? + n, _ = env.fs.Top.srcdir_find_file(d) + if n and n not in target and n not in source: + res.append(n) + return res diff --git a/test/Batch/CHANGED_SOURCES.py b/test/Batch/CHANGED_SOURCES.py index 477869f..b54bd2e 100644 --- a/test/Batch/CHANGED_SOURCES.py +++ b/test/Batch/CHANGED_SOURCES.py @@ -48,8 +48,11 @@ for infile in sys.argv[2:]: sys.exit(0) """) +# Disable IMPLICIT_COMMAND_DEPENDENCIES because otherwise it renders them less +# effective. They count on paths provided at the end of the command string only +# being counted as dependencies if Depends() is used. test.write('SConstruct', """ -env = Environment() +env = Environment(IMPLICIT_COMMAND_DEPENDENCIES=False) env['BATCH_BUILD'] = 'batch_build.py' env['BATCHCOM'] = r'%(_python_)s $BATCH_BUILD ${TARGET.dir} $CHANGED_SOURCES' bb = Action('$BATCHCOM', batch_key=True, targets='CHANGED_TARGETS') diff --git a/test/Batch/action-changed.py b/test/Batch/action-changed.py index b2b1673..33c026e 100644 --- a/test/Batch/action-changed.py +++ b/test/Batch/action-changed.py @@ -33,7 +33,11 @@ import os import TestSCons -python = TestSCons.python +# swap slashes because on py3 on win32 inside the generated build.py +# the backslashes are getting interpretted as unicode which is +# invalid. +python = TestSCons.python.replace('\\','//') +_python_ = TestSCons._python_ test = TestSCons.TestSCons() @@ -53,17 +57,19 @@ sys.exit(0) test.write('build.py', build_py_contents % (python, 'one')) os.chmod(test.workpath('build.py'), 0o755) +build_py_workpath = test.workpath('build.py') + test.write('SConstruct', """ env = Environment() env.PrependENVPath('PATHEXT', '.PY') -bb = Action(r'"%s" $CHANGED_TARGETS -- $CHANGED_SOURCES', +bb = Action(r'%(_python_)s "%(build_py_workpath)s" $CHANGED_TARGETS -- $CHANGED_SOURCES', batch_key=True, targets='CHANGED_TARGETS') env['BUILDERS']['Batch'] = Builder(action=bb) env.Batch('f1.out', 'f1.in') env.Batch('f2.out', 'f2.in') env.Batch('f3.out', 'f3.in') -""" % test.workpath('build.py')) +""" % locals()) test.write('f1.in', "f1.in\n") test.write('f2.in', "f2.in\n") diff --git a/test/Depends/Depends.py b/test/Depends/Depends.py index 3ed9e12..51737a7 100644 --- a/test/Depends/Depends.py +++ b/test/Depends/Depends.py @@ -50,11 +50,15 @@ sys.exit(0) SUBDIR_foo_dep = os.path.join('$SUBDIR', 'foo.dep') SUBDIR_f3_out = os.path.join('$SUBDIR', 'f3.out') +# Disable IMPLICIT_COMMAND_DEPENDENCIES because otherwise it renders them less +# effective. They count on paths provided at the end of the command string only +# being counted as dependencies if Depends() is used. test.write('SConstruct', """ DefaultEnvironment(tools=[]) Foo = Builder(action = r'%(_python_)s build.py $TARGET $SOURCES subdir/foo.dep') Bar = Builder(action = r'%(_python_)s build.py $TARGET $SOURCES subdir/bar.dep') -env = Environment(tools=[], BUILDERS = { 'Foo' : Foo, 'Bar' : Bar }, SUBDIR='subdir') +env = Environment(tools=[], BUILDERS = { 'Foo' : Foo, 'Bar' : Bar }, SUBDIR='subdir', + IMPLICIT_COMMAND_DEPENDENCIES=False) env.Depends(target = ['f1.out', 'f2.out'], dependency = r'%(SUBDIR_foo_dep)s') env.Depends(target = r'%(SUBDIR_f3_out)s', dependency = 'subdir/bar.dep') env.Foo(target = 'f1.out', source = 'f1.in') diff --git a/test/ParseDepends.py b/test/ParseDepends.py index 2de2105..aa15fc9 100644 --- a/test/ParseDepends.py +++ b/test/ParseDepends.py @@ -40,10 +40,13 @@ with open(sys.argv[1], 'wb') as f, open(sys.argv[2], 'rb') as afp2, open(sys.arg f.write(afp2.read() + afp3.read()) """) +# Pass IMPLICIT_COMMAND_DEPENDENCIES=False because the test depends on us not +# taking a dependency on the last file in the action string. test.write('SConstruct', """ Foo = Builder(action = r'%(_python_)s build.py $TARGET $SOURCES subdir/foo.dep') Bar = Builder(action = r'%(_python_)s build.py $TARGET $SOURCES subdir/bar.dep') -env = Environment(BUILDERS = { 'Foo' : Foo, 'Bar' : Bar }, SUBDIR='subdir') +env = Environment(BUILDERS = { 'Foo' : Foo, 'Bar' : Bar }, SUBDIR='subdir', + IMPLICIT_COMMAND_DEPENDENCIES=False) env.ParseDepends('foo.d') env.ParseDepends('bar.d') env.Foo(target = 'f1.out', source = 'f1.in') diff --git a/test/Repository/link-object.py b/test/Repository/link-object.py index 78add90..f5bf783 100644 --- a/test/Repository/link-object.py +++ b/test/Repository/link-object.py @@ -44,7 +44,13 @@ workpath_repository = test.workpath('repository') repository_foo = test.workpath('repository', 'foo' + _exe) work_foo = test.workpath('work', 'foo' + _exe) +# Don't take implicit command dependencies because otherwise the program will +# be unexpectedly recompiled the first time we use chdir="work". The reason is +# that we take .obj files as implicit dependencies but when we move the current +# directory, those .obj files are no longer around. # +# TODO: Should this test pass as-is without disabling implicit command +# dependencies? test.write(['repository', 'SConstruct'], """ Repository(r'%s') env = Environment() diff --git a/test/explain/basic.py b/test/explain/basic.py index 46ce6bc..2d57d35 100644 --- a/test/explain/basic.py +++ b/test/explain/basic.py @@ -335,6 +335,7 @@ scons: rebuilding `file3' because: ->Depends ->Implicit Old:%(_python_)s New:%(_python_)s + Old:%(cat_py)s New:%(cat_py)s %(_python_)s %(cat_py)s file3 zzz yyy xxx """ % locals()) @@ -354,12 +355,21 @@ env.AddPostAction(f3, r'%(_python_)s %(cat_py)s ${TARGET}.yyy $SOURCES yyy') env.AddPreAction(f3, r'%(_python_)s %(cat_py)s ${TARGET}.alt $SOURCES') """ % locals()) +# Because Action.get_implicit_deps() scans the entire action string, we do take +# the additional "yyy" as a dependency. It already was a source, so it now is +# considered to be a dependency ordering change. expect = test.wrap_stdout("""\ -scons: rebuilding `file3' because the build action changed: - old: %(python)s %(cat_py)s $TARGET $SOURCES - new: %(_python_)s %(cat_py)s ${TARGET}.alt $SOURCES - %(python)s %(cat_py)s $TARGET $SOURCES - %(_python_)s %(cat_py)s ${TARGET}.yyy $SOURCES yyy +scons: rebuilding `file3' because: + the dependency order changed: + ->Sources + Old:zzz New:zzz + Old:yyy New:yyy + Old:xxx New:xxx + ->Depends + ->Implicit + Old:%(_python_)s New:%(_python_)s + Old:%(cat_py)s New:%(cat_py)s + Old:None New:yyy %(_python_)s %(cat_py)s file3.alt zzz yyy xxx %(_python_)s %(cat_py)s file3 zzz yyy xxx %(_python_)s %(cat_py)s file3.yyy zzz yyy xxx yyy @@ -384,13 +394,17 @@ env.AddPreAction(f3, r'%(_python_)s %(cat_py)s ${TARGET}.alt $SOURCES') """ % locals()) expect = test.wrap_stdout("""\ -scons: rebuilding `file3' because the build action changed: - old: %(_python_)s %(cat_py)s ${TARGET}.alt $SOURCES - %(python)s %(cat_py)s $TARGET $SOURCES - %(_python_)s %(cat_py)s ${TARGET}.yyy $SOURCES yyy - new: %(_python_)s %(cat_py)s ${TARGET}.alt $SOURCES - %(python)s %(cat_py)s $TARGET $SOURCES - %(_python_)s %(cat_py)s ${TARGET}.yyy $SOURCES xxx +scons: rebuilding `file3' because: + the dependency order changed: + ->Sources + Old:zzz New:zzz + Old:yyy New:yyy + Old:xxx New:xxx + ->Depends + ->Implicit + Old:%(_python_)s New:%(_python_)s + Old:%(cat_py)s New:%(cat_py)s + Old:yyy New:xxx %(_python_)s %(cat_py)s file3.alt zzz yyy xxx %(_python_)s %(cat_py)s file3 zzz yyy xxx %(_python_)s %(cat_py)s file3.yyy zzz yyy xxx xxx -- cgit v0.12 From 9d07ea27a4dda3ff51a67a7dd2af029fea3da0bc Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Tue, 3 Dec 2019 11:37:51 -0500 Subject: Fix some tests --- src/engine/SCons/Action.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index 2dea8cc..14a5a83 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -979,14 +979,23 @@ class CommandAction(_ActionAction): icd = env.get('IMPLICIT_COMMAND_DEPENDENCIES', True) if is_String(icd) and icd[:1] == '$': icd = env.subst(icd) + + # Several tests depend upon this function disambiguating the source and + # target lists. + # TODO: Is this a bad idea? + for s in source: + s.disambiguate() + for t in target: + t.disambiguate() + if not icd or icd in ('0', 'None'): return [] - from SCons.Subst import SUBST_SIG - # Avoid circular and duplicate dependencies by not provide source and - # target to subst_list. This causes references to $SOURCES, $TARGETS, - # and all related variables to disappear. - cmd_list = env.subst_list(self.cmd_list, SUBST_SIG, [], []) + # Avoid circular and duplicate dependencies by not provide source, + # target, or executor to subst_list. This causes references to + # $SOURCES, $TARGETS, and all related variables to disappear. + from SCons.Subst import SUBST_SIG + cmd_list = env.subst_list(self.cmd_list, SUBST_SIG) res = [] for cmd_line in cmd_list: -- cgit v0.12 From 20e42843dd1266e13f7bc5c9a89b08541e98d64c Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Tue, 3 Dec 2019 16:51:55 -0500 Subject: Switch heavyweight scanning to be opt-in --- src/engine/SCons/Action.py | 36 +++++++++++++++++++------- test/implicit/IMPLICIT_COMMAND_DEPENDENCIES.py | 13 ++++++---- 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index 14a5a83..ef99a4d 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -980,18 +980,36 @@ class CommandAction(_ActionAction): if is_String(icd) and icd[:1] == '$': icd = env.subst(icd) - # Several tests depend upon this function disambiguating the source and - # target lists. - # TODO: Is this a bad idea? - for s in source: - s.disambiguate() - for t in target: - t.disambiguate() - if not icd or icd in ('0', 'None'): return [] - # Avoid circular and duplicate dependencies by not provide source, + if icd in ['2', 2]: + return self._get_implicit_deps_heavyweight(target, source, env, executor) + else: + # Everything else (usually 1 or True) means that we want + # lightweight dependency scanning. + return self._get_implicit_deps_lightweight(target, source, env, executor) + + def _get_implicit_deps_lightweight(self, target, source, env, executor): + from SCons.Subst import SUBST_SIG + if executor: + cmd_list = env.subst_list(self.cmd_list, SUBST_SIG, executor=executor) + else: + cmd_list = env.subst_list(self.cmd_list, SUBST_SIG, target, source) + res = [] + for cmd_line in cmd_list: + if cmd_line: + d = str(cmd_line[0]) + m = strip_quotes.match(d) + if m: + d = m.group(1) + d = env.WhereIs(d) + if d: + res.append(env.fs.File(d)) + return res + + def _get_implicit_deps_heavyweight(self, target, source, env, executor): + # Avoid circular and duplicate dependencies by not providing source, # target, or executor to subst_list. This causes references to # $SOURCES, $TARGETS, and all related variables to disappear. from SCons.Subst import SUBST_SIG diff --git a/test/implicit/IMPLICIT_COMMAND_DEPENDENCIES.py b/test/implicit/IMPLICIT_COMMAND_DEPENDENCIES.py index c7ce0b5..bec9223 100644 --- a/test/implicit/IMPLICIT_COMMAND_DEPENDENCIES.py +++ b/test/implicit/IMPLICIT_COMMAND_DEPENDENCIES.py @@ -82,6 +82,7 @@ env.PrependENVPath('PATH', '.') env.PrependENVPath('PATHEXT', '.PY') env0 = env.Clone(IMPLICIT_COMMAND_DEPENDENCIES = 0) env1 = env.Clone(IMPLICIT_COMMAND_DEPENDENCIES = 1) +env2 = env.Clone(IMPLICIT_COMMAND_DEPENDENCIES = 2) envNone = env.Clone(IMPLICIT_COMMAND_DEPENDENCIES = None) envFalse = env.Clone(IMPLICIT_COMMAND_DEPENDENCIES = False) envTrue = env.Clone(IMPLICIT_COMMAND_DEPENDENCIES = True) @@ -92,12 +93,13 @@ AlwaysBuild(build_py) env.BuildFile('file.out', 'file.in') env0.BuildFile('file0.out', 'file.in') env1.BuildFile('file1.out', 'file.in') +env2.BuildFile('file2.out', 'file.in') envNone.BuildFile('fileNone.out', 'file.in') envFalse.BuildFile('fileFalse.out', 'file.in') envTrue.BuildFile('fileTrue.out', 'file.in') envTrue.BuildFile('fileQuote.out', 'file.in', BUILD_PY='"build.py"') -env.CdAndBuildFile('cd_file.out', 'file.in') +env2.CdAndBuildFile('cd_file.out', 'file.in') """ % locals()) @@ -121,13 +123,14 @@ def run_test(extra, python, _python_): extra.replace('\\\\n', '\n')) # Verify that the output matches what is expected. - test.must_match('file.out', expect_extra % 'file.out', mode='r') + test.must_match('file.out', expect_none % 'file.out', mode='r') test.must_match('file0.out', expect_none % 'file0.out', mode='r') - test.must_match('file1.out', expect_extra % 'file1.out', mode='r') + test.must_match('file1.out', expect_none % 'file1.out', mode='r') + test.must_match('file2.out', expect_extra % 'file2.out', mode='r') test.must_match('fileNone.out', expect_none % 'fileNone.out', mode='r') test.must_match('fileFalse.out', expect_none % 'fileFalse.out', mode='r') - test.must_match('fileTrue.out', expect_extra % 'fileTrue.out', mode='r') - test.must_match('fileQuote.out', expect_extra % 'fileQuote.out', mode='r') + test.must_match('fileTrue.out', expect_none % 'fileTrue.out', mode='r') + test.must_match('fileQuote.out', expect_none % 'fileQuote.out', mode='r') test.must_match('cd_file.out', expect_extra % 'cd_file.out', mode='r') -- cgit v0.12 From b2866a6821ba0575535e259a6a74e911c0d7c735 Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Tue, 3 Dec 2019 17:40:09 -0500 Subject: Fix some more tests Reverts some of the changes I made previously in my diff. --- test/Batch/action-changed.py | 4 +++- test/explain/basic.py | 38 ++++++++++++-------------------------- 2 files changed, 15 insertions(+), 27 deletions(-) diff --git a/test/Batch/action-changed.py b/test/Batch/action-changed.py index 33c026e..da5115e 100644 --- a/test/Batch/action-changed.py +++ b/test/Batch/action-changed.py @@ -59,8 +59,10 @@ os.chmod(test.workpath('build.py'), 0o755) build_py_workpath = test.workpath('build.py') +# Provide IMPLICIT_COMMAND_DEPENDENCIES=2 so we take a dependency on build.py. +# Without that, we only scan the first entry in the action string. test.write('SConstruct', """ -env = Environment() +env = Environment(IMPLICIT_COMMAND_DEPENDENCIES=2) env.PrependENVPath('PATHEXT', '.PY') bb = Action(r'%(_python_)s "%(build_py_workpath)s" $CHANGED_TARGETS -- $CHANGED_SOURCES', batch_key=True, diff --git a/test/explain/basic.py b/test/explain/basic.py index 2d57d35..46ce6bc 100644 --- a/test/explain/basic.py +++ b/test/explain/basic.py @@ -335,7 +335,6 @@ scons: rebuilding `file3' because: ->Depends ->Implicit Old:%(_python_)s New:%(_python_)s - Old:%(cat_py)s New:%(cat_py)s %(_python_)s %(cat_py)s file3 zzz yyy xxx """ % locals()) @@ -355,21 +354,12 @@ env.AddPostAction(f3, r'%(_python_)s %(cat_py)s ${TARGET}.yyy $SOURCES yyy') env.AddPreAction(f3, r'%(_python_)s %(cat_py)s ${TARGET}.alt $SOURCES') """ % locals()) -# Because Action.get_implicit_deps() scans the entire action string, we do take -# the additional "yyy" as a dependency. It already was a source, so it now is -# considered to be a dependency ordering change. expect = test.wrap_stdout("""\ -scons: rebuilding `file3' because: - the dependency order changed: - ->Sources - Old:zzz New:zzz - Old:yyy New:yyy - Old:xxx New:xxx - ->Depends - ->Implicit - Old:%(_python_)s New:%(_python_)s - Old:%(cat_py)s New:%(cat_py)s - Old:None New:yyy +scons: rebuilding `file3' because the build action changed: + old: %(python)s %(cat_py)s $TARGET $SOURCES + new: %(_python_)s %(cat_py)s ${TARGET}.alt $SOURCES + %(python)s %(cat_py)s $TARGET $SOURCES + %(_python_)s %(cat_py)s ${TARGET}.yyy $SOURCES yyy %(_python_)s %(cat_py)s file3.alt zzz yyy xxx %(_python_)s %(cat_py)s file3 zzz yyy xxx %(_python_)s %(cat_py)s file3.yyy zzz yyy xxx yyy @@ -394,17 +384,13 @@ env.AddPreAction(f3, r'%(_python_)s %(cat_py)s ${TARGET}.alt $SOURCES') """ % locals()) expect = test.wrap_stdout("""\ -scons: rebuilding `file3' because: - the dependency order changed: - ->Sources - Old:zzz New:zzz - Old:yyy New:yyy - Old:xxx New:xxx - ->Depends - ->Implicit - Old:%(_python_)s New:%(_python_)s - Old:%(cat_py)s New:%(cat_py)s - Old:yyy New:xxx +scons: rebuilding `file3' because the build action changed: + old: %(_python_)s %(cat_py)s ${TARGET}.alt $SOURCES + %(python)s %(cat_py)s $TARGET $SOURCES + %(_python_)s %(cat_py)s ${TARGET}.yyy $SOURCES yyy + new: %(_python_)s %(cat_py)s ${TARGET}.alt $SOURCES + %(python)s %(cat_py)s $TARGET $SOURCES + %(_python_)s %(cat_py)s ${TARGET}.yyy $SOURCES xxx %(_python_)s %(cat_py)s file3.alt zzz yyy xxx %(_python_)s %(cat_py)s file3 zzz yyy xxx %(_python_)s %(cat_py)s file3.yyy zzz yyy xxx xxx -- cgit v0.12 From 5df60c3f82a68acbc7f51769822a715259a9210d Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Tue, 3 Dec 2019 20:43:46 -0500 Subject: Add repository-related test coverage of the new code That was missing in the codecov report. --- test/Repository/Program.py | 195 +++++++++++++++++++-------------------- test/Repository/StaticLibrary.py | 165 +++++++++++++++++---------------- 2 files changed, 180 insertions(+), 180 deletions(-) diff --git a/test/Repository/Program.py b/test/Repository/Program.py index 1eb18d8..9260ae9 100644 --- a/test/Repository/Program.py +++ b/test/Repository/Program.py @@ -32,25 +32,22 @@ if sys.platform == 'win32': else: _exe = '' -test = TestSCons.TestSCons() - - - -# First, test a single repository. -test.subdir('repository', 'work1') - -repository = test.workpath('repository') -repository_foo_c = test.workpath('repository', 'foo.c') -work1_foo = test.workpath('work1', 'foo' + _exe) -work1_foo_c = test.workpath('work1', 'foo.c') - -test.write(['work1', 'SConstruct'], r""" +for implicit_deps in ['0', '1', '2']: + # First, test a single repository. + test = TestSCons.TestSCons() + test.subdir('repository', 'work1') + repository = test.workpath('repository') + repository_foo_c = test.workpath('repository', 'foo.c') + work1_foo = test.workpath('work1', 'foo' + _exe) + work1_foo_c = test.workpath('work1', 'foo.c') + + test.write(['work1', 'SConstruct'], r""" Repository(r'%s') -env = Environment() +env = Environment(IMPLICIT_COMMAND_DEPENDENCIES=%s) env.Program(target= 'foo', source = Split('aaa.c bbb.c foo.c')) -""" % repository) +""" % (repository, implicit_deps)) -test.write(['repository', 'aaa.c'], r""" + test.write(['repository', 'aaa.c'], r""" #include void aaa(void) @@ -59,7 +56,7 @@ aaa(void) } """) -test.write(['repository', 'bbb.c'], r""" + test.write(['repository', 'bbb.c'], r""" #include void bbb(void) @@ -68,7 +65,7 @@ bbb(void) } """) -test.write(['repository', 'foo.c'], r""" + test.write(['repository', 'foo.c'], r""" #include #include @@ -85,21 +82,21 @@ main(int argc, char *argv[]) } """) -# Make the entire repository non-writable, so we'll detect -# if we try to write into it accidentally. -test.writable('repository', 0) + # Make the entire repository non-writable, so we'll detect + # if we try to write into it accidentally. + test.writable('repository', 0) -test.run(chdir = 'work1', arguments = '.') + test.run(chdir = 'work1', arguments = '.') -test.run(program = work1_foo, stdout = """repository/aaa.c + test.run(program = work1_foo, stdout = """repository/aaa.c repository/bbb.c repository/foo.c """) -test.up_to_date(chdir = 'work1', arguments = '.') + test.up_to_date(chdir = 'work1', arguments = '.') -# -test.write(['work1', 'bbb.c'], r""" + # + test.write(['work1', 'bbb.c'], r""" #include void bbb(void) @@ -108,17 +105,17 @@ bbb(void) } """) -test.run(chdir = 'work1', arguments = '.') + test.run(chdir = 'work1', arguments = '.') -test.run(program = work1_foo, stdout = """repository/aaa.c + test.run(program = work1_foo, stdout = """repository/aaa.c work1/bbb.c repository/foo.c """) -test.up_to_date(chdir = 'work1', arguments = '.') + test.up_to_date(chdir = 'work1', arguments = '.') -# -test.write(['work1', 'aaa.c'], r""" + # + test.write(['work1', 'aaa.c'], r""" #include void aaa(void) @@ -127,7 +124,7 @@ aaa(void) } """) -test.write(['work1', 'foo.c'], r""" + test.write(['work1', 'foo.c'], r""" #include #include extern void aaa(void); @@ -143,57 +140,57 @@ main(int argc, char *argv[]) } """) -test.run(chdir = 'work1', arguments = '.') + test.run(chdir = 'work1', arguments = '.') -test.run(program = work1_foo, stdout = """work1/aaa.c + test.run(program = work1_foo, stdout = """work1/aaa.c work1/bbb.c work1/foo.c """) -test.up_to_date(chdir = 'work1', arguments = '.') + test.up_to_date(chdir = 'work1', arguments = '.') -# -test.unlink(['work1', 'aaa.c']) + # + test.unlink(['work1', 'aaa.c']) -test.run(chdir = 'work1', arguments = '.') + test.run(chdir = 'work1', arguments = '.') -test.run(program = work1_foo, stdout = """repository/aaa.c + test.run(program = work1_foo, stdout = """repository/aaa.c work1/bbb.c work1/foo.c """) -test.up_to_date(chdir = 'work1', arguments = '.') + test.up_to_date(chdir = 'work1', arguments = '.') -# -test.unlink(['work1', 'bbb.c']) -test.unlink(['work1', 'foo.c']) + # + test.unlink(['work1', 'bbb.c']) + test.unlink(['work1', 'foo.c']) -test.run(chdir = 'work1', arguments = '.') + test.run(chdir = 'work1', arguments = '.') -test.run(program = work1_foo, stdout = """repository/aaa.c + test.run(program = work1_foo, stdout = """repository/aaa.c repository/bbb.c repository/foo.c """) -test.up_to_date(chdir = 'work1', arguments = '.') + test.up_to_date(chdir = 'work1', arguments = '.') -# Now, test multiple repositories. -test.subdir('repository.new', 'repository.old', 'work2') + # Now, test multiple repositories. + test.subdir('repository.new', 'repository.old', 'work2') -repository_new = test.workpath('repository.new') -repository_old = test.workpath('repository.old') -work2_foo = test.workpath('work2', 'foo' + _exe) + repository_new = test.workpath('repository.new') + repository_old = test.workpath('repository.old') + work2_foo = test.workpath('work2', 'foo' + _exe) -test.write(['work2', 'SConstruct'], r""" + test.write(['work2', 'SConstruct'], r""" Repository(r'%s') Repository(r'%s') env = Environment() env.Program(target= 'foo', source = Split('aaa.c bbb.c foo.c')) """ % (repository_new, repository_old)) -test.write(['repository.old', 'aaa.c'], r""" + test.write(['repository.old', 'aaa.c'], r""" #include void aaa(void) @@ -202,7 +199,7 @@ aaa(void) } """) -test.write(['repository.old', 'bbb.c'], r""" + test.write(['repository.old', 'bbb.c'], r""" #include void bbb(void) @@ -211,7 +208,7 @@ bbb(void) } """) -test.write(['repository.old', 'foo.c'], r""" + test.write(['repository.old', 'foo.c'], r""" #include #include extern void aaa(void); @@ -227,24 +224,24 @@ main(int argc, char *argv[]) } """) -# Make both repositories non-writable, so we'll detect -# if we try to write into it accidentally. -test.writable('repository.new', 0) -test.writable('repository.old', 0) + # Make both repositories non-writable, so we'll detect + # if we try to write into it accidentally. + test.writable('repository.new', 0) + test.writable('repository.old', 0) -test.run(chdir = 'work2', arguments = '.') + test.run(chdir = 'work2', arguments = '.') -test.run(program = work2_foo, stdout = """repository.old/aaa.c + test.run(program = work2_foo, stdout = """repository.old/aaa.c repository.old/bbb.c repository.old/foo.c """) -test.up_to_date(chdir = 'work2', arguments = '.') + test.up_to_date(chdir = 'work2', arguments = '.') -# -test.writable('repository.new', 1) + # + test.writable('repository.new', 1) -test.write(['repository.new', 'aaa.c'], r""" + test.write(['repository.new', 'aaa.c'], r""" #include #include void @@ -254,7 +251,7 @@ aaa(void) } """) -test.write(['work2', 'bbb.c'], r""" + test.write(['work2', 'bbb.c'], r""" #include #include void @@ -264,20 +261,20 @@ bbb(void) } """) -# -test.writable('repository.new', 0) + # + test.writable('repository.new', 0) -test.run(chdir = 'work2', arguments = '.') + test.run(chdir = 'work2', arguments = '.') -test.run(program = work2_foo, stdout = """repository.new/aaa.c + test.run(program = work2_foo, stdout = """repository.new/aaa.c work2/bbb.c repository.old/foo.c """) -test.up_to_date(chdir = 'work2', arguments = '.') + test.up_to_date(chdir = 'work2', arguments = '.') -# -test.write(['work2', 'aaa.c'], r""" + # + test.write(['work2', 'aaa.c'], r""" #include #include void @@ -287,7 +284,7 @@ aaa(void) } """) -test.write(['work2', 'foo.c'], r""" + test.write(['work2', 'foo.c'], r""" #include #include extern void aaa(void); @@ -303,59 +300,59 @@ main(int argc, char *argv[]) } """) -# -test.run(chdir = 'work2', arguments = '.') + # + test.run(chdir = 'work2', arguments = '.') -test.run(program = work2_foo, stdout = """work2/aaa.c + test.run(program = work2_foo, stdout = """work2/aaa.c work2/bbb.c work2/foo.c """) -test.up_to_date(chdir = 'work2', arguments = '.') + test.up_to_date(chdir = 'work2', arguments = '.') -# -test.unlink(['work2', 'aaa.c']) -test.unlink(['work2', 'bbb.c']) + # + test.unlink(['work2', 'aaa.c']) + test.unlink(['work2', 'bbb.c']) -# -test.run(chdir = 'work2', arguments = '.') + # + test.run(chdir = 'work2', arguments = '.') -test.run(program = work2_foo, stdout = """repository.new/aaa.c + test.run(program = work2_foo, stdout = """repository.new/aaa.c repository.old/bbb.c work2/foo.c """) -test.up_to_date(chdir = 'work2', arguments = '.') + test.up_to_date(chdir = 'work2', arguments = '.') -# -test.unlink(['work2', 'foo.c']) + # + test.unlink(['work2', 'foo.c']) -# -test.run(chdir = 'work2', arguments = '.') + # + test.run(chdir = 'work2', arguments = '.') -test.run(program = work2_foo, stdout = """repository.new/aaa.c + test.run(program = work2_foo, stdout = """repository.new/aaa.c repository.old/bbb.c repository.old/foo.c """) -test.up_to_date(chdir = 'work2', arguments = '.') + test.up_to_date(chdir = 'work2', arguments = '.') -# -test.writable('repository.new', 1) + # + test.writable('repository.new', 1) -test.unlink(['repository.new', 'aaa.c']) + test.unlink(['repository.new', 'aaa.c']) -test.writable('repository.new', 0) + test.writable('repository.new', 0) -# -test.run(chdir = 'work2', arguments = '.') + # + test.run(chdir = 'work2', arguments = '.') -test.run(program = work2_foo, stdout = """repository.old/aaa.c + test.run(program = work2_foo, stdout = """repository.old/aaa.c repository.old/bbb.c repository.old/foo.c """) -test.up_to_date(chdir = 'work2', arguments = '.') + test.up_to_date(chdir = 'work2', arguments = '.') # diff --git a/test/Repository/StaticLibrary.py b/test/Repository/StaticLibrary.py index 4f8160c..d619bb3 100644 --- a/test/Repository/StaticLibrary.py +++ b/test/Repository/StaticLibrary.py @@ -30,35 +30,37 @@ import TestSCons _obj = TestSCons._obj _exe = TestSCons._exe -test = TestSCons.TestSCons() - -# -test.subdir('repository', 'work1', 'work2', 'work3') - -# -workpath_repository = test.workpath('repository') -repository_aaa_obj = test.workpath('repository', 'aaa' + _obj) -repository_bbb_obj = test.workpath('repository', 'bbb' + _obj) -repository_foo_obj = test.workpath('repository', 'foo' + _obj) -repository_foo = test.workpath('repository', 'foo' + _exe) -work1_foo = test.workpath('work1', 'foo' + _exe) -work2_aaa_obj = test.workpath('work2', 'aaa' + _obj) -work2_foo_obj = test.workpath('work2', 'foo' + _obj) -work2_foo = test.workpath('work2', 'foo' + _exe) -work3_aaa_obj = test.workpath('work3', 'aaa' + _obj) -work3_bbb_obj = test.workpath('work3', 'bbb' + _obj) -work3_foo = test.workpath('work3', 'foo' + _exe) - -opts = '-Y ' + workpath_repository - -# -test.write(['repository', 'SConstruct'], """ -env = Environment(LIBS = ['xxx'], LIBPATH = '.') +for implicit_deps in ['0', '1', '2']: + test = TestSCons.TestSCons() + + # + test.subdir('repository', 'work1', 'work2', 'work3') + + # + workpath_repository = test.workpath('repository') + repository_aaa_obj = test.workpath('repository', 'aaa' + _obj) + repository_bbb_obj = test.workpath('repository', 'bbb' + _obj) + repository_foo_obj = test.workpath('repository', 'foo' + _obj) + repository_foo = test.workpath('repository', 'foo' + _exe) + work1_foo = test.workpath('work1', 'foo' + _exe) + work2_aaa_obj = test.workpath('work2', 'aaa' + _obj) + work2_foo_obj = test.workpath('work2', 'foo' + _obj) + work2_foo = test.workpath('work2', 'foo' + _exe) + work3_aaa_obj = test.workpath('work3', 'aaa' + _obj) + work3_bbb_obj = test.workpath('work3', 'bbb' + _obj) + work3_foo = test.workpath('work3', 'foo' + _exe) + + opts = '-Y ' + workpath_repository + + # + test.write(['repository', 'SConstruct'], """ +env = Environment(LIBS = ['xxx'], LIBPATH = '.', + IMPLICIT_COMMAND_DEPENDENCIES=%s) env.Library(target = 'xxx', source = ['aaa.c', 'bbb.c']) env.Program(target = 'foo', source = 'foo.c') -""") +""" % implicit_deps) -test.write(['repository', 'aaa.c'], r""" + test.write(['repository', 'aaa.c'], r""" #include #include void @@ -68,7 +70,7 @@ aaa(void) } """) -test.write(['repository', 'bbb.c'], r""" + test.write(['repository', 'bbb.c'], r""" #include #include void @@ -78,7 +80,7 @@ bbb(void) } """) -test.write(['repository', 'foo.c'], r""" + test.write(['repository', 'foo.c'], r""" #include #include extern void aaa(void); @@ -94,29 +96,29 @@ main(int argc, char *argv[]) } """) -# Make the repository non-writable, -# so we'll detect if we try to write into it accidentally. -test.writable('repository', 0) + # Make the repository non-writable, + # so we'll detect if we try to write into it accidentally. + test.writable('repository', 0) -# -test.run(chdir = 'work1', options = opts, arguments = ".", - stderr=TestSCons.noisy_ar, - match=TestSCons.match_re_dotall) + # + test.run(chdir = 'work1', options = opts, arguments = ".", + stderr=TestSCons.noisy_ar, + match=TestSCons.match_re_dotall) -test.run(program = work1_foo, stdout = + test.run(program = work1_foo, stdout = """repository/aaa.c repository/bbb.c repository/foo.c """) -test.fail_test(os.path.exists(repository_aaa_obj)) -test.fail_test(os.path.exists(repository_bbb_obj)) -test.fail_test(os.path.exists(repository_foo_obj)) -test.fail_test(os.path.exists(repository_foo)) + test.fail_test(os.path.exists(repository_aaa_obj)) + test.fail_test(os.path.exists(repository_bbb_obj)) + test.fail_test(os.path.exists(repository_foo_obj)) + test.fail_test(os.path.exists(repository_foo)) -test.up_to_date(chdir = 'work1', options = opts, arguments = ".") + test.up_to_date(chdir = 'work1', options = opts, arguments = ".") -test.write(['work1', 'bbb.c'], r""" + test.write(['work1', 'bbb.c'], r""" #include #include void @@ -126,49 +128,49 @@ bbb(void) } """) -test.run(chdir = 'work1', options = opts, arguments = ".", - stderr=TestSCons.noisy_ar, - match=TestSCons.match_re_dotall) + test.run(chdir = 'work1', options = opts, arguments = ".", + stderr=TestSCons.noisy_ar, + match=TestSCons.match_re_dotall) -test.run(program = work1_foo, stdout = + test.run(program = work1_foo, stdout = """repository/aaa.c work1/bbb.c repository/foo.c """) -test.fail_test(os.path.exists(repository_aaa_obj)) -test.fail_test(os.path.exists(repository_bbb_obj)) -test.fail_test(os.path.exists(repository_foo_obj)) -test.fail_test(os.path.exists(repository_foo)) + test.fail_test(os.path.exists(repository_aaa_obj)) + test.fail_test(os.path.exists(repository_bbb_obj)) + test.fail_test(os.path.exists(repository_foo_obj)) + test.fail_test(os.path.exists(repository_foo)) -test.up_to_date(chdir = 'work1', options = opts, arguments = ".") + test.up_to_date(chdir = 'work1', options = opts, arguments = ".") -# -test.writable('repository', 1) + # + test.writable('repository', 1) -test.run(chdir = 'repository', options = opts, arguments = ".", - stderr=TestSCons.noisy_ar, - match=TestSCons.match_re_dotall) + test.run(chdir = 'repository', options = opts, arguments = ".", + stderr=TestSCons.noisy_ar, + match=TestSCons.match_re_dotall) -test.run(program = repository_foo, stdout = + test.run(program = repository_foo, stdout = """repository/aaa.c repository/bbb.c repository/foo.c """) -test.fail_test(not os.path.exists(repository_aaa_obj)) -test.fail_test(not os.path.exists(repository_bbb_obj)) -test.fail_test(not os.path.exists(repository_foo_obj)) + test.fail_test(not os.path.exists(repository_aaa_obj)) + test.fail_test(not os.path.exists(repository_bbb_obj)) + test.fail_test(not os.path.exists(repository_foo_obj)) -test.up_to_date(chdir = 'repository', options = opts, arguments = ".") + test.up_to_date(chdir = 'repository', options = opts, arguments = ".") -# -test.writable('repository', 0) + # + test.writable('repository', 0) -# -test.up_to_date(chdir = 'work2', options = opts, arguments = ".") + # + test.up_to_date(chdir = 'work2', options = opts, arguments = ".") -test.write(['work2', 'bbb.c'], r""" + test.write(['work2', 'bbb.c'], r""" #include #include void @@ -178,25 +180,25 @@ bbb(void) } """) -test.run(chdir = 'work2', options = opts, arguments = ".", - stderr=TestSCons.noisy_ar, - match=TestSCons.match_re_dotall) + test.run(chdir = 'work2', options = opts, arguments = ".", + stderr=TestSCons.noisy_ar, + match=TestSCons.match_re_dotall) -test.run(program = work2_foo, stdout = + test.run(program = work2_foo, stdout = """repository/aaa.c work2/bbb.c repository/foo.c """) -test.fail_test(os.path.exists(work2_aaa_obj)) -test.fail_test(os.path.exists(work2_foo_obj)) + test.fail_test(os.path.exists(work2_aaa_obj)) + test.fail_test(os.path.exists(work2_foo_obj)) -test.up_to_date(chdir = 'work2', options = opts, arguments = ".") + test.up_to_date(chdir = 'work2', options = opts, arguments = ".") -# -test.up_to_date(chdir = 'work3', options = opts, arguments = ".") + # + test.up_to_date(chdir = 'work3', options = opts, arguments = ".") -test.write(['work3', 'foo.c'], r""" + test.write(['work3', 'foo.c'], r""" #include #include extern void aaa(void); @@ -212,18 +214,19 @@ main(int argc, char *argv[]) } """) -test.run(chdir = 'work3', options = opts, arguments = ".") + test.run(chdir = 'work3', options = opts, arguments = ".") -test.run(program = work3_foo, stdout = + test.run(program = work3_foo, stdout = """repository/aaa.c repository/bbb.c work3/foo.c """) -test.fail_test(os.path.exists(work3_aaa_obj)) -test.fail_test(os.path.exists(work3_bbb_obj)) + test.fail_test(os.path.exists(work3_aaa_obj)) + test.fail_test(os.path.exists(work3_bbb_obj)) + + test.up_to_date(chdir = 'work3', options = opts, arguments = ".") -test.up_to_date(chdir = 'work3', options = opts, arguments = ".") # test.pass_test() -- cgit v0.12 From 3e039f1b101f7d52b333e1c5d7f75d3984ff0551 Mon Sep 17 00:00:00 2001 From: Jason Kenny Date: Wed, 4 Dec 2019 15:30:42 -0600 Subject: Allow Command to take more builder options add to change log add documentation update test --- src/CHANGES.txt | 3 +++ src/engine/SCons/Environment.py | 13 +++++++++++++ src/engine/SCons/Environment.xml | 22 +++++++++++++++------ test/Command.py | 42 +++++++++++++++++++++++++++++++++++++++- 4 files changed, 73 insertions(+), 7 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 617b3d0..b42dd0a 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -5,6 +5,9 @@ Change Log RELEASE VERSION/DATE TO BE FILLED IN LATER + From Jason Kenny + - Update Command() function to accept target_scanner, source_factory, and target_factory arguments. + This make Command act more like a one-off builder. From Philipp Maierhöfer: - Avoid crash with UnicodeDecodeError on Python 3 when a Latex log file in diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 0e1102e..17d3250 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -1984,9 +1984,22 @@ class Base(SubstitutionEnvironment): 'target_factory' : self.fs.Entry, 'source_factory' : self.fs.Entry, } + # source scanner try: bkw['source_scanner'] = kw['source_scanner'] except KeyError: pass else: del kw['source_scanner'] + #target scanner + try: bkw['target_scanner'] = kw['target_scanner'] + except KeyError: pass + else: del kw['target_scanner'] + #source factory + try: bkw['source_factory'] = kw['source_factory'] + except KeyError: pass + else: del kw['source_factory'] + #target factory + try: bkw['target_factory'] = kw['target_factory'] + except KeyError: pass + else: del kw['target_factory'] bld = SCons.Builder.Builder(**bkw) return bld(self, target, source, **kw) diff --git a/src/engine/SCons/Environment.xml b/src/engine/SCons/Environment.xml index 829bf12..a32d43d 100644 --- a/src/engine/SCons/Environment.xml +++ b/src/engine/SCons/Environment.xml @@ -937,19 +937,29 @@ for a single special-case build. -As a special case, the -source_scanner -keyword argument can +&b-Command; builder accepts +source_scanner, +target_scanner, +source_factory, and +target_factory +keyword arguments. The *_scanner args can be used to specify a Scanner object -that will be used to scan the sources. -(The global +that will be used to apply a custom +scanner for a source or target. +For example, the global DirScanner object can be used if any of the sources will be directories that must be scanned on-disk for changes to files that aren't -already specified in other Builder of function calls.) +already specified in other Builder of function calls. +The *_factory args take a factory function that the +Command will use to turn any sources or targets +specified as strings into SCons Nodes. +See the sections "Builder Objects" +below, for more information about how these +args work in a Builder. diff --git a/test/Command.py b/test/Command.py index 09a8daa..380c171 100644 --- a/test/Command.py +++ b/test/Command.py @@ -44,6 +44,7 @@ test.write(['expand_chdir_sub', 'subbuild.py'], build_py) test.write('SConstruct', """ import os +import sys def buildIt(env, target, source): with open(str(target[0]), 'w') as f, open(str(source[0]), 'r') as infp: @@ -62,6 +63,19 @@ def sub(env, target, source): t.write(s.read()) return 0 +def source_scanner(node, env, path, builder): + print("Source scanner node=", node, "builder =", builder,file=sys.stderr) + return [] + + +def target_scanner(node, env, path, builder): + print("Target scanner node=", node, "builder =", builder,file=sys.stderr) + return [] + +def factory(node,*lst,**kw): + print("factory called on:",node,file=sys.stderr) + return env.File(node) + env = Environment(COPY_THROUGH_TEMP = r'%(_python_)s build.py .tmp $SOURCE' + '\\n' + r'%(_python_)s build.py $TARGET .tmp', EXPAND = '$COPY_THROUGH_TEMP') env.Command(target = 'f1.out', source = 'f1.in', @@ -82,6 +96,19 @@ env.Command(target = 'f7.out', source = 'f7.in', action = r'%(_python_)s build.py $TARGET $SOURCE') Command(target = 'f8.out', source = 'f8.in', action = r'%(_python_)s build.py $TARGET $SOURCE') +env.Command(target = 'f7s.out', source = 'f7.in', + action = r'%(_python_)s build.py $TARGET $SOURCE', + target_scanner=Scanner(lambda node, env, path: target_scanner(node, env, path, "w-env")), + source_scanner=Scanner(lambda node, env, path: source_scanner(node, env, path, "w-env"))) +Command(target = 'f8s.out', source = 'f8.in', + action = r'%(_python_)s build.py $TARGET $SOURCE', + target_scanner=Scanner(lambda node, env, path: target_scanner(node, env, path, "wo-env")), + source_scanner=Scanner(lambda node, env, path: source_scanner(node, env, path, "wo-env"))) +Command(target = 'f8f.out', source = 'f8.in', + action = r'%(_python_)s build.py $TARGET $SOURCE', + target_factory=factory, + source_factory=factory + ) env.Command(target = 'f9.out', source = 'f9.in', action = r'$EXPAND') env.Command(target = '${F10}.out', source = '${F10}.in', @@ -108,7 +135,18 @@ test.write('f9.in', "f9.in\n") test.write('f10.in', "f10.in\n") test.write(['expand_chdir_sub', 'f11.in'], "expand_chdir_sub/f11.in\n") -test.run(arguments = '.') +test_str = r'''factory called on: f8.in +factory called on: f8f.out +Source scanner node= f7.in builder = w-env +Target scanner node= f7s.out builder = w-env +Source scanner node= f8.in builder = wo-env +Target scanner node= f8s.out builder = wo-env +''' + +out = test.run(arguments = '.', + stderr = test_str, + match=TestSCons.match_re_dotall) + test.must_match('f1.out', "f1.in\n", mode='r') test.must_match('f2.out', "f2.in\n", mode='r') @@ -118,6 +156,8 @@ test.must_match('f5.out', "XYZZY is set\nf5.in\n", mode='r') test.must_match('f6.out', "f6.in\n", mode='r') test.must_match('f7.out', "f7.in\n", mode='r') test.must_match('f8.out', "f8.in\n", mode='r') +test.must_match('f7s.out', "f7.in\n", mode='r') +test.must_match('f8s.out', "f8.in\n", mode='r') test.must_match('f9.out', "f9.in\n", mode='r') test.must_match('f10.out', "f10.in\n", mode='r') test.must_match(['expand_chdir_sub', 'f11.out'], "expand_chdir_sub/f11.in\n", mode='r') -- cgit v0.12 From d4eaa1986cfffdb11eee0aa5240fa44bef370fb1 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Tue, 25 Jun 2019 10:56:43 -0600 Subject: Improve building of docs using Py3 [ci skip] * context managers on file r/w + use shutil.copy where it makes sense. * lxml wants (demands?) that xml files be processed as bytes * for the phase where we gen the entity files, read as text anyway * Need to solve a problem where the generated xml is putting the \n in literally, not evaluating it. * Fix some examples broken for py3 * Fix more octal constant instances * Cleanups suggested by PyCharm: staticmethods, two blanks before class definition, others. This addresses issues called out in #3300, but is not a complete solution because the actual doc build step still fails with the epydoc failures (which aren't directly because of Py3; epydoc build doesn't work any better on my system with Py3, even with the forked version with patches). Signed-off-by: Mats Wichmann --- bin/SConsDoc.py | 211 ++++++++++++++++----------- bin/SConsExamples.py | 76 +++++----- bin/docs-update-generated.py | 17 ++- bin/scons-proc.py | 14 +- doc/generated/examples/factories_Chmod_1.xml | 2 +- doc/generated/functions.gen | 10 +- doc/man/scons.xml | 4 +- doc/user/README | 2 +- doc/user/builders-writing.xml | 12 +- doc/user/environments.xml | 2 +- doc/user/factories.xml | 10 +- doc/user/file-removal.xml | 2 +- doc/user/mergeflags.xml | 8 +- doc/user/parseconfig.xml | 4 +- doc/user/parseflags.xml | 12 +- doc/user/sideeffect.xml | 2 +- doc/user/troubleshoot.xml | 4 +- src/engine/SCons/Action.xml | 2 +- src/engine/SCons/Defaults.xml | 2 +- src/engine/SCons/Environment.xml | 8 +- src/engine/SCons/Platform/__init__.xml | 2 +- src/engine/SCons/Platform/posix.xml | 2 +- src/engine/SCons/Platform/sunos.xml | 2 +- src/engine/SCons/Platform/win32.xml | 2 +- src/engine/SCons/Scanner/__init__.xml | 2 +- src/engine/SCons/Script/Main.xml | 2 +- src/engine/SCons/Script/SConscript.xml | 2 +- src/engine/SCons/Subst.xml | 2 +- src/engine/SCons/Tool/386asm.xml | 2 +- src/engine/SCons/Tool/DCommon.xml | 2 +- src/engine/SCons/Tool/__init__.xml | 2 +- src/engine/SCons/Tool/aixc++.xml | 2 +- src/engine/SCons/Tool/aixcc.xml | 2 +- src/engine/SCons/Tool/aixf77.xml | 2 +- src/engine/SCons/Tool/aixlink.xml | 2 +- src/engine/SCons/Tool/applelink.xml | 2 +- src/engine/SCons/Tool/ar.xml | 2 +- src/engine/SCons/Tool/as.xml | 2 +- src/engine/SCons/Tool/bcc32.xml | 2 +- src/engine/SCons/Tool/c++.xml | 2 +- src/engine/SCons/Tool/cc.xml | 2 +- src/engine/SCons/Tool/clang.xml | 2 +- src/engine/SCons/Tool/clangxx.xml | 2 +- src/engine/SCons/Tool/cvf.xml | 2 +- src/engine/SCons/Tool/cyglink.xml | 2 +- src/engine/SCons/Tool/default.xml | 2 +- src/engine/SCons/Tool/dmd.xml | 2 +- src/engine/SCons/Tool/docbook/__init__.xml | 2 +- src/engine/SCons/Tool/dvi.xml | 2 +- src/engine/SCons/Tool/dvipdf.xml | 2 +- src/engine/SCons/Tool/dvips.xml | 2 +- src/engine/SCons/Tool/f03.xml | 2 +- src/engine/SCons/Tool/f08.xml | 2 +- src/engine/SCons/Tool/f77.xml | 2 +- src/engine/SCons/Tool/f90.xml | 2 +- src/engine/SCons/Tool/f95.xml | 2 +- src/engine/SCons/Tool/fortran.xml | 2 +- src/engine/SCons/Tool/g++.xml | 2 +- src/engine/SCons/Tool/g77.xml | 2 +- src/engine/SCons/Tool/gas.xml | 2 +- src/engine/SCons/Tool/gcc.xml | 2 +- src/engine/SCons/Tool/gdc.xml | 2 +- src/engine/SCons/Tool/gettext.xml | 2 +- src/engine/SCons/Tool/gfortran.xml | 2 +- src/engine/SCons/Tool/gnulink.xml | 2 +- src/engine/SCons/Tool/gs.xml | 2 +- src/engine/SCons/Tool/hpc++.xml | 2 +- src/engine/SCons/Tool/hpcc.xml | 2 +- src/engine/SCons/Tool/hplink.xml | 2 +- src/engine/SCons/Tool/icc.xml | 2 +- src/engine/SCons/Tool/icl.xml | 2 +- src/engine/SCons/Tool/ifl.xml | 2 +- src/engine/SCons/Tool/ifort.xml | 2 +- src/engine/SCons/Tool/ilink.xml | 2 +- src/engine/SCons/Tool/ilink32.xml | 2 +- src/engine/SCons/Tool/install.xml | 2 +- src/engine/SCons/Tool/intelc.xml | 2 +- src/engine/SCons/Tool/jar.xml | 2 +- src/engine/SCons/Tool/javac.xml | 2 +- src/engine/SCons/Tool/javah.xml | 2 +- src/engine/SCons/Tool/latex.xml | 2 +- src/engine/SCons/Tool/ldc.xml | 2 +- src/engine/SCons/Tool/lex.xml | 2 +- src/engine/SCons/Tool/link.xml | 2 +- src/engine/SCons/Tool/linkloc.xml | 2 +- src/engine/SCons/Tool/m4.xml | 2 +- src/engine/SCons/Tool/masm.xml | 2 +- src/engine/SCons/Tool/midl.xml | 2 +- src/engine/SCons/Tool/mingw.xml | 2 +- src/engine/SCons/Tool/msgfmt.xml | 2 +- src/engine/SCons/Tool/msginit.xml | 2 +- src/engine/SCons/Tool/msgmerge.xml | 2 +- src/engine/SCons/Tool/mslib.xml | 2 +- src/engine/SCons/Tool/mslink.xml | 2 +- src/engine/SCons/Tool/mssdk.xml | 2 +- src/engine/SCons/Tool/msvc.xml | 2 +- src/engine/SCons/Tool/msvs.xml | 2 +- src/engine/SCons/Tool/mwcc.xml | 2 +- src/engine/SCons/Tool/mwld.xml | 2 +- src/engine/SCons/Tool/nasm.xml | 2 +- src/engine/SCons/Tool/packaging.xml | 2 +- src/engine/SCons/Tool/packaging/__init__.xml | 6 +- src/engine/SCons/Tool/pdf.xml | 2 +- src/engine/SCons/Tool/pdflatex.xml | 2 +- src/engine/SCons/Tool/pdftex.xml | 2 +- src/engine/SCons/Tool/qt.xml | 2 +- src/engine/SCons/Tool/rmic.xml | 2 +- src/engine/SCons/Tool/rpcgen.xml | 2 +- src/engine/SCons/Tool/sgiar.xml | 2 +- src/engine/SCons/Tool/sgic++.xml | 2 +- src/engine/SCons/Tool/sgicc.xml | 2 +- src/engine/SCons/Tool/sgilink.xml | 2 +- src/engine/SCons/Tool/sunar.xml | 2 +- src/engine/SCons/Tool/sunc++.xml | 2 +- src/engine/SCons/Tool/suncc.xml | 2 +- src/engine/SCons/Tool/sunf77.xml | 2 +- src/engine/SCons/Tool/sunf90.xml | 2 +- src/engine/SCons/Tool/sunf95.xml | 2 +- src/engine/SCons/Tool/sunlink.xml | 2 +- src/engine/SCons/Tool/swig.xml | 2 +- src/engine/SCons/Tool/tar.xml | 2 +- src/engine/SCons/Tool/tex.xml | 2 +- src/engine/SCons/Tool/textfile.xml | 2 +- src/engine/SCons/Tool/tlib.xml | 2 +- src/engine/SCons/Tool/xgettext.xml | 2 +- src/engine/SCons/Tool/yacc.xml | 2 +- src/engine/SCons/Tool/zip.xml | 2 +- test/Fortran/FORTRANFILESUFFIXES2.py | 2 +- test/MSVC/query_vcbat.py | 2 +- test/packaging/rpm/tagging.py | 4 +- test/sconsign/script/Signatures.py | 2 +- test/sconsign/script/no-SConsignFile.py | 2 +- test/subdivide.py | 2 +- 133 files changed, 348 insertions(+), 288 deletions(-) diff --git a/bin/SConsDoc.py b/bin/SConsDoc.py index 5fd5f00..d200f8b 100644 --- a/bin/SConsDoc.py +++ b/bin/SConsDoc.py @@ -26,7 +26,8 @@ # from __future__ import print_function -__doc__ = """ + +__doc__ = r""" This module parses home-brew XML files that document various things in SCons. Right now, it handles Builders, functions, construction variables, and Tools, but we expect it to get extended in the future. @@ -117,16 +118,18 @@ import re import sys import copy +PY2 = sys.version_info[0] == 2 + # Do we have libxml2/libxslt/lxml? has_libxml2 = True try: import libxml2 import libxslt -except: +except ImportError: has_libxml2 = False try: import lxml - except: + except ImportError: raise ImportError("Failed to import either libxml2/libxslt or lxml") has_etree = False @@ -155,13 +158,16 @@ if not has_etree: except ImportError: raise ImportError("Failed to import ElementTree from any known place") -re_entity = re.compile(r"\&([^;]+);") +# patterns to help trim XML passed in as strings +re_entity = re.compile(r"&([^;]+);") re_entity_header = re.compile(r"") # Namespace for the SCons Docbook XSD -dbxsd="http://www.scons.org/dbxsd/v1.0" +dbxsd = "http://www.scons.org/dbxsd/v1.0" +# Namsespace pattern to help identify an scons-xml file read as bytes +dbxsdpat = b'xmlns="%s"' % dbxsd.encode('utf-8') # Namespace map identifier for the SCons Docbook XSD -dbxid="dbx" +dbxid = "dbx" # Namespace for schema instances xsi = "http://www.w3.org/2001/XMLSchema-instance" @@ -170,19 +176,22 @@ copyright_comment = """ __COPYRIGHT__ This file is processed by the bin/SConsDoc.py module. -See its __doc__ string for a discussion of the format. +See its docstring for a discussion of the format. """ def isSConsXml(fpath): - """ Check whether the given file is a SCons XML file, i.e. it - contains the default target namespace definition. + """ Check whether the given file is an SCons XML file. + + It is SCons XML if it contains the default target namespace definition + described by dbxsdpat + """ try: - with open(fpath,'r') as f: + with open(fpath, 'rb') as f: content = f.read() - if content.find('xmlns="%s"' % dbxsd) >= 0: + if content.find(dbxsdpat) >= 0: return True - except: + except Exception: pass return False @@ -195,10 +204,11 @@ def remove_entities(content): return content -default_xsd = os.path.join('doc','xsd','scons.xsd') +default_xsd = os.path.join('doc', 'xsd', 'scons.xsd') ARG = "dbscons" + class Libxml2ValidityHandler: def __init__(self): @@ -224,10 +234,11 @@ class DoctypeEntity: def getEntityString(self): txt = """ %(perc)s%(name)s; -""" % {'perc' : perc, 'name' : self.name, 'uri' : self.uri} +""" % {'perc': perc, 'name': self.name, 'uri': self.uri} return txt + class DoctypeDeclaration: def __init__(self, name_=None): self.name = name_ @@ -253,14 +264,16 @@ class DoctypeDeclaration: return content if not has_libxml2: - class TreeFactory: + class TreeFactory(object): def __init__(self): pass - def newNode(self, tag): + @staticmethod + def newNode(tag): return etree.Element(tag) - def newEtreeNode(self, tag, init_ns=False): + @staticmethod + def newEtreeNode(tag, init_ns=False): if init_ns: NSMAP = {None: dbxsd, 'xsi' : xsi} @@ -268,47 +281,60 @@ if not has_libxml2: return etree.Element(tag) - def copyNode(self, node): + @staticmethod + def copyNode(node): return copy.deepcopy(node) - def appendNode(self, parent, child): + @staticmethod + def appendNode(parent, child): parent.append(child) - def hasAttribute(self, node, att): + @staticmethod + def hasAttribute(node, att): return att in node.attrib - def getAttribute(self, node, att): + @staticmethod + def getAttribute(node, att): return node.attrib[att] - def setAttribute(self, node, att, value): + @staticmethod + def setAttribute(node, att, value): node.attrib[att] = value - def getText(self, root): + @staticmethod + def getText(root): return root.text - def setText(self, root, txt): + @staticmethod + def setText(root, txt): root.text = txt - def writeGenTree(self, root, fp): + @staticmethod + def writeGenTree(root, fp): dt = DoctypeDeclaration() - fp.write(etree.tostring(root, xml_declaration=True, - encoding="UTF-8", pretty_print=True, + encfun = unicode if PY2 else str + fp.write(etree.tostring(root, encoding=encfun, + pretty_print=True, doctype=dt.createDoctype())) - def writeTree(self, root, fpath): - with open(fpath, 'w') as fp: - fp.write(etree.tostring(root, xml_declaration=True, - encoding="UTF-8", pretty_print=True)) + @staticmethod + def writeTree(root, fpath): + encfun = unicode if PY2 else None + with open(fpath, 'wb') as fp: + fp.write(etree.tostring(root, encoding=encfun, + pretty_print=True)) - def prettyPrintFile(self, fpath): - with open(fpath,'r') as fin: + @staticmethod + def prettyPrintFile(fpath): + with open(fpath,'rb') as fin: tree = etree.parse(fin) pretty_content = etree.tostring(tree, pretty_print=True) - with open(fpath,'w') as fout: + with open(fpath,'wb') as fout: fout.write(pretty_content) - def decorateWithHeader(self, root): + @staticmethod + def decorateWithHeader(root): root.attrib["{"+xsi+"}schemaLocation"] = "%s %s/scons.xsd" % (dbxsd, dbxsd) return root @@ -316,12 +342,12 @@ if not has_libxml2: """ Return a XML file tree with the correct namespaces set, the element root as top entry and the given header comment. """ - NSMAP = {None: dbxsd, - 'xsi' : xsi} + NSMAP = {None: dbxsd, 'xsi' : xsi} t = etree.Element(root, nsmap=NSMAP) return self.decorateWithHeader(t) - def validateXml(self, fpath, xmlschema_context): + @staticmethod + def validateXml(fpath, xmlschema_context): # Use lxml xmlschema = etree.XMLSchema(xmlschema_context) try: @@ -339,19 +365,22 @@ if not has_libxml2: return False return True - def findAll(self, root, tag, ns=None, xp_ctxt=None, nsmap=None): + @staticmethod + def findAll(root, tag, ns=None, xp_ctxt=None, nsmap=None): expression = ".//{%s}%s" % (nsmap[ns], tag) if not ns or not nsmap: expression = ".//%s" % tag return root.findall(expression) - def findAllChildrenOf(self, root, tag, ns=None, xp_ctxt=None, nsmap=None): + @staticmethod + def findAllChildrenOf(root, tag, ns=None, xp_ctxt=None, nsmap=None): expression = "./{%s}%s/*" % (nsmap[ns], tag) if not ns or not nsmap: expression = "./%s/*" % tag return root.findall(expression) - def convertElementTree(self, root): + @staticmethod + def convertElementTree(root): """ Convert the given tree of etree.Element entries to a list of tree nodes for the current XML toolkit. @@ -359,53 +388,63 @@ if not has_libxml2: return [root] else: - class TreeFactory: + class TreeFactory(object): def __init__(self): pass - def newNode(self, tag): + @staticmethod + def newNode(tag): return libxml2.newNode(tag) - def newEtreeNode(self, tag, init_ns=False): + @staticmethod + def newEtreeNode(tag, init_ns=False): return etree.Element(tag) - def copyNode(self, node): + @staticmethod + def copyNode(node): return node.copyNode(1) - def appendNode(self, parent, child): + @staticmethod + def appendNode(parent, child): if hasattr(parent, 'addChild'): parent.addChild(child) else: parent.append(child) - def hasAttribute(self, node, att): + @staticmethod + def hasAttribute(node, att): if hasattr(node, 'hasProp'): return node.hasProp(att) return att in node.attrib - def getAttribute(self, node, att): + @staticmethod + def getAttribute(node, att): if hasattr(node, 'prop'): return node.prop(att) return node.attrib[att] - def setAttribute(self, node, att, value): + @staticmethod + def setAttribute(node, att, value): if hasattr(node, 'setProp'): node.setProp(att, value) else: node.attrib[att] = value - def getText(self, root): + @staticmethod + def getText(root): if hasattr(root, 'getContent'): return root.getContent() return root.text - def setText(self, root, txt): + @staticmethod + def setText(root, txt): if hasattr(root, 'setContent'): root.setContent(txt) else: root.text = txt - def writeGenTree(self, root, fp): + @staticmethod + def writeGenTree(root, fp): doc = libxml2.newDoc('1.0') dtd = doc.newDtd("sconsdoc", None, None) doc.addChild(dtd) @@ -420,23 +459,26 @@ else: fp.write(content) doc.freeDoc() - def writeTree(self, root, fpath): - with open(fpath, 'w') as fp: + @staticmethod + def writeTree(root, fpath): + with open(fpath, 'wb') as fp: doc = libxml2.newDoc('1.0') doc.setRootElement(root) fp.write(doc.serialize("UTF-8", 1)) doc.freeDoc() - def prettyPrintFile(self, fpath): + @staticmethod + def prettyPrintFile(fpath): # Read file and resolve entities doc = libxml2.readFile(fpath, None, libxml2d.XML_PARSE_NOENT) - with open(fpath, 'w') as fp: + with open(fpath, 'wb') as fp: # Prettyprint fp.write(doc.serialize("UTF-8", 1)) # Cleanup doc.freeDoc() - def decorateWithHeader(self, root): + @staticmethod + def decorateWithHeader(root): # Register the namespaces ns = root.newNs(dbxsd, None) xi = root.newNs(xsi, 'xsi') @@ -453,7 +495,8 @@ else: t = libxml2.newNode(root) return self.decorateWithHeader(t) - def validateXml(self, fpath, xmlschema_context): + @staticmethod + def validateXml(fpath, xmlschema_context): retval = True # Create validation context @@ -479,7 +522,8 @@ else: return retval - def findAll(self, root, tag, ns=None, xpath_context=None, nsmap=None): + @staticmethod + def findAll(root, tag, ns=None, xpath_context=None, nsmap=None): if hasattr(root, 'xpathEval') and xpath_context: # Use the xpath context xpath_context.setContextNode(root) @@ -493,7 +537,8 @@ else: expression = ".//%s" % tag return root.findall(expression) - def findAllChildrenOf(self, root, tag, ns=None, xpath_context=None, nsmap=None): + @staticmethod + def findAllChildrenOf(root, tag, ns=None, xpath_context=None, nsmap=None): if hasattr(root, 'xpathEval') and xpath_context: # Use the xpath context xpath_context.setContextNode(root) @@ -562,20 +607,18 @@ else: tf = TreeFactory() -class SConsDocTree: +class SConsDocTree(object): def __init__(self): - self.nsmap = {'dbx' : dbxsd} + self.nsmap = {'dbx': dbxsd} self.doc = None self.root = None self.xpath_context = None def parseContent(self, content, include_entities=True): - """ Parses the given content as XML file. This method - is used when we generate the basic lists of entities - for the builders, tools and functions. - So we usually don't bother about namespaces and resolving - entities here...this is handled in parseXmlFile below - (step 2 of the overall process). + """ Parses the given text content as XML + + This is the setup portion, called from parseContent in + an SConsDocHandler instance - see the notes there. """ if not include_entities: content = remove_entities(content) @@ -583,7 +626,6 @@ class SConsDocTree: self.root = etree.fromstring(content) def parseXmlFile(self, fpath): - nsmap = {'dbx' : dbxsd} if not has_libxml2: # Create domtree from file domtree = etree.parse(fpath) @@ -604,7 +646,7 @@ class SConsDocTree: if self.xpath_context is not None: self.xpath_context.xpathFreeContext() -perc="%" +perc = "%" def validate_all_xml(dpaths, xsdfile=default_xsd): xmlschema_context = None @@ -620,7 +662,7 @@ def validate_all_xml(dpaths, xsdfile=default_xsd): fpaths = [] for dp in dpaths: if dp.endswith('.xml') and isSConsXml(dp): - path='.' + path = '.' fpaths.append(dp) else: for path, dirs, files in os.walk(dp): @@ -633,8 +675,8 @@ def validate_all_xml(dpaths, xsdfile=default_xsd): fails = [] for idx, fp in enumerate(fpaths): fpath = os.path.join(path, fp) - print("%.2f%s (%d/%d) %s" % (float(idx+1)*100.0/float(len(fpaths)), - perc, idx+1, len(fpaths),fp)) + print("%.2f%s (%d/%d) %s" % (float(idx + 1) * 100.0 /float(len(fpaths)), + perc, idx + 1, len(fpaths), fp)) if not tf.validateXml(fp, xmlschema_context): fails.append(fp) @@ -649,6 +691,7 @@ def validate_all_xml(dpaths, xsdfile=default_xsd): return True + class Item(object): def __init__(self, name): self.name = name @@ -668,21 +711,25 @@ class Item(object): def __lt__(self, other): return self.sort_name < other.sort_name + class Builder(Item): pass + class Function(Item): - def __init__(self, name): - super(Function, self).__init__(name) + pass + class Tool(Item): def __init__(self, name): Item.__init__(self, name) self.entity = self.name.replace('+', 'X') + class ConstructionVariable(Item): pass + class Arguments(object): def __init__(self, signature, body=None): if not body: @@ -692,7 +739,7 @@ class Arguments(object): def __str__(self): s = ''.join(self.body).strip() result = [] - for m in re.findall('([a-zA-Z/_]+|[^a-zA-Z/_]+)', s): + for m in re.findall(r'([a-zA-Z/_]+|[^a-zA-Z/_]+)', s): if ' ' in m: m = '"%s"' % m result.append(m) @@ -700,6 +747,7 @@ class Arguments(object): def append(self, data): self.body.append(data) + class SConsDocHandler(object): def __init__(self): self.builders = {} @@ -794,7 +842,7 @@ class SConsDocHandler(object): self.parseDomtree(t.root, t.xpath_context, t.nsmap) # lifted from Ka-Ping Yee's way cool pydoc module. -if sys.version_info[0] == 2: +if PY2: def importfile(path): """Import a Python source file or compiled file given its path.""" import imp @@ -817,11 +865,10 @@ if sys.version_info[0] == 2: else: # PY3 version, from newer pydoc def importfile(path): """Import a Python source file or compiled file given its path.""" - import importlib - from pydoc import ErrorDuringImport - magic = importlib.util.MAGIC_NUMBER + from importlib import MAGIC_NUMBER + import pydoc with open(path, 'rb') as ifp: - is_bytecode = magic == ifp.read(len(magic)) + is_bytecode = MAGIC_NUMBER == ifp.read(len(MAGIC_NUMBER)) filename = os.path.basename(path) name, ext = os.path.splitext(filename) if is_bytecode: @@ -832,7 +879,7 @@ else: # PY3 version, from newer pydoc spec = importlib.util.spec_from_file_location(name, path, loader=loader) try: return importlib._bootstrap._load(spec) - except: + except ImportError: raise ErrorDuringImport(path, sys.exc_info()) # Local Variables: diff --git a/bin/SConsExamples.py b/bin/SConsExamples.py index 501169e..8a264e4 100644 --- a/bin/SConsExamples.py +++ b/bin/SConsExamples.py @@ -92,6 +92,7 @@ import os import re import sys import time +import shutil import SConsDoc from SConsDoc import tf as stf @@ -287,9 +288,8 @@ def ensureExampleOutputsExist(dpath): fpath = os.path.join(generated_examples, key + '_' + r.name.replace("/", "_")) # Write file - f = open(fpath, 'w') - f.write("%s\n" % content) - f.close() + with open(fpath, 'w') as f: + f.write("%s\n" % content) perc = "%" @@ -324,9 +324,8 @@ def createAllExampleOutputs(dpath): fpath = os.path.join(generated_examples, key + '_' + r.name.replace("/", "_")) # Write file - f = open(fpath, 'w') - f.write("%s\n" % content) - f.close() + with open(fpath, 'w') as f: + f.write("%s\n" % content) idx += 1 def collectSConsExampleNames(fpath): @@ -458,6 +457,7 @@ import re import SCons.Action import SCons.Defaults import SCons.Node.FS +import shutil platform = '%(osname)s' @@ -540,30 +540,28 @@ def Null(target, source, env): def Cat(target, source, env): target = str(target[0]) - f = open(target, "wb") for src in map(str, source): - f.write(open(src, "rb").read()) - f.close() + shutil.copy(src, target) def CCCom(target, source, env): - target = str(target[0]) - fp = open(target, "wb") - def process(source_file, fp=fp): - for line in open(source_file, "rb").readlines(): - m = re.match(r'#include\s[<"]([^<"]+)[>"]', line) - if m: - include = m.group(1) - for d in [str(env.Dir('$CPPPATH')), '.']: - f = os.path.join(d, include) - if os.path.exists(f): - process(f) - break - elif line[:11] != "STRIP CCCOM": - fp.write(line) - for src in map(str, source): - process(src) - fp.write('debug = ' + ARGUMENTS.get('debug', '0') + '\\n') - fp.close() + def process(source_file, ofp): + with open(source_file, "r") as ifp: + for line in ifp.readlines(): + m = re.match(r'#include\s[<"]([^<"]+)[>"]', line) + if m: + include = m.group(1) + for d in [str(env.Dir('$CPPPATH')), '.']: + f = os.path.join(d, include) + if os.path.exists(f): + process(f, ofp) + break + elif line[:11] != "STRIP CCCOM": + ofp.write(line) + + with open(str(target[0]), "w") as fp: + for src in map(str, source): + process(src, fp) + fp.write('debug = ' + ARGUMENTS.get('debug', '0') + '\\n') public_class_re = re.compile('^public class (\S+)', re.MULTILINE) @@ -577,20 +575,23 @@ def JavaCCom(target, source, env): for t in tlist: not_copied[t] = 1 for src in map(str, source): - contents = open(src, "rb").read() + with open(src, "r") as f: + contents = f.read() classes = public_class_re.findall(contents) for c in classes: for t in [x for x in tlist if x.find(c) != -1]: - open(t, "wb").write(contents) + with open(t, "w") as f: + f.write(contents) del not_copied[t] for t in not_copied.keys(): - open(t, "wb").write("\\n") + with open(t, "w") as f: + f.write("\\n") def JavaHCom(target, source, env): tlist = map(str, target) slist = map(str, source) for t, s in zip(tlist, slist): - open(t, "wb").write(open(s, "rb").read()) + shutil.copy(s, t) def JarCom(target, source, env): target = str(target[0]) @@ -599,10 +600,8 @@ def JarCom(target, source, env): for dirpath, dirnames, filenames in os.walk(src): class_files.extend([ os.path.join(dirpath, f) for f in filenames if f.endswith('.class') ]) - f = open(target, "wb") for cf in class_files: - f.write(open(cf, "rb").read()) - f.close() + shutil.copy(cf, target) # XXX Adding COLOR, COLORS and PACKAGE to the 'cc' varlist(s) by hand # here is bogus. It's for the benefit of doc/user/command-line.in, which @@ -721,7 +720,8 @@ def command_touch(args, command, test, values): if not os.path.isabs(file): file = os.path.join(test.workpath('WORK'), file) if not os.path.exists(file): - open(file, 'wb') + with open(file, 'w'): + pass os.utime(file, times) return [] @@ -735,8 +735,8 @@ def command_edit(args, c, test, values): for file in args: if not os.path.isabs(file): file = os.path.join(test.workpath('WORK'), file) - contents = open(file, 'rb').read() - open(file, 'wb').write(contents + add_string) + with open(file, 'a') as f: + f.write(add_string) return [] def command_ls(args, c, test, values): @@ -825,7 +825,7 @@ def create_scons_output(e): t.write(path, content) if hasattr(f, 'chmod'): if len(f.chmod): - os.chmod(path, int(f.chmod, 0)) + os.chmod(path, int(f.chmod, base=8)) # Regular expressions for making the doc output consistent, # regardless of reported addresses or Python version. diff --git a/bin/docs-update-generated.py b/bin/docs-update-generated.py index c164baf..307f843 100644 --- a/bin/docs-update-generated.py +++ b/bin/docs-update-generated.py @@ -10,6 +10,8 @@ from __future__ import print_function import os import sys +import subprocess + import SConsDoc # Directory where all generated files are stored @@ -17,8 +19,8 @@ gen_folder = os.path.join('doc','generated') def argpair(key): """ Return the argument pair *.gen,*.mod for the given key. """ - arg = '%s,%s' % (os.path.join(gen_folder,'%s.gen' % key), - os.path.join(gen_folder,'%s.mod' % key)) + arg = '%s,%s' % (os.path.join(gen_folder, '%s.gen' % key), + os.path.join(gen_folder, '%s.mod' % key)) return arg @@ -43,10 +45,13 @@ def generate_all(): print("Couldn't create destination folder %s! Exiting..." % gen_folder) return # Call scons-proc.py - os.system('%s %s -b %s -f %s -t %s -v %s %s' % - (sys.executable, os.path.join('bin','scons-proc.py'), - argpair('builders'), argpair('functions'), - argpair('tools'), argpair('variables'), ' '.join(flist))) + rv = subprocess.call([sys.executable, + os.path.join('bin','scons-proc.py'), + '-b', argpair('builders'), + '-f', argpair('functions'), + '-t', argpair('tools'), + '-v', argpair('variables')] + flist, + shell=False) if __name__ == "__main__": diff --git a/bin/scons-proc.py b/bin/scons-proc.py index e09c853..d8b37df 100644 --- a/bin/scons-proc.py +++ b/bin/scons-proc.py @@ -32,8 +32,8 @@ Options: -t file(s) dump tool information to the specified file(s) -v file(s) dump variable information to the specified file(s) - Regard that each -[btv] argument is a pair of - comma-separated .gen,.mod file names. + The "files" argument following a -[bftv] argument is expected to + be a comma-separated pair of names like: foo.gen,foo.mod """ @@ -70,7 +70,9 @@ def parse_docs(args, include_entities=True): sys.stderr.write("error in %s\n" % f) raise else: - content = open(f).read() + # mode we read (text/bytes) has to match handling in SConsDoc + with open(f, 'r') as fp: + content = fp.read() if content: try: h.parseContent(content, include_entities) @@ -166,6 +168,7 @@ class SCons_XML(object): # Write file f = self.fopen(filename) stf.writeGenTree(root, f) + f.close() def write_mod(self, filename): try: @@ -212,6 +215,7 @@ class SCons_XML(object): v.tag, v.entityfunc(), v.tag)) f.write('\n') f.write(Warning) + f.close() class Proxy(object): def __init__(self, subject): @@ -348,7 +352,7 @@ processor_class = SCons_XML # Step 1: Creating entity files for builders, functions,... print("Generating entity files...") -h = parse_docs(args, False) +h = parse_docs(args, include_entities=False) write_output_files(h, buildersfiles, functionsfiles, toolsfiles, variablesfiles, SCons_XML.write_mod) @@ -362,7 +366,7 @@ else: # Step 3: Creating actual documentation snippets, using the # fully resolved and updated entities from the *.mod files. print("Updating documentation for builders, tools and functions...") -h = parse_docs(args, True) +h = parse_docs(args, include_entities=True) write_output_files(h, buildersfiles, functionsfiles, toolsfiles, variablesfiles, SCons_XML.write) print("Done") diff --git a/doc/generated/examples/factories_Chmod_1.xml b/doc/generated/examples/factories_Chmod_1.xml index a324ed4..59bba55 100644 --- a/doc/generated/examples/factories_Chmod_1.xml +++ b/doc/generated/examples/factories_Chmod_1.xml @@ -1,5 +1,5 @@ % scons -Q Copy("file.out", "file.in") -Chmod("file.out", 0755) +Chmod("file.out", 0o755) diff --git a/doc/generated/functions.gen b/doc/generated/functions.gen index f3f2a0c..d24eac3 100644 --- a/doc/generated/functions.gen +++ b/doc/generated/functions.gen @@ -1408,7 +1408,7 @@ This SConstruct: env=Environment() -print env.Dump('CCCOM') +print(env.Dump('CCCOM')) @@ -1425,7 +1425,7 @@ While this SConstruct: env=Environment() -print env.Dump() +print(env.Dump()) @@ -4463,7 +4463,7 @@ Example: -print env.subst("The C compiler is: $CC") +print(env.subst("The C compiler is: $CC")) def compile(target, source, env): sourceDir = env.subst("${SOURCE.srcdir}", @@ -4493,9 +4493,9 @@ Examples: -# makes sure the built library will be installed with 0644 file +# makes sure the built library will be installed with 0o644 file # access mode -Tag( Library( 'lib.c' ), UNIX_ATTR="0644" ) +Tag( Library( 'lib.c' ), UNIX_ATTR="0o644" ) # marks file2.txt to be a documentation file Tag( 'file2.txt', DOC ) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index ae54e2e..5aea45a 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -5721,11 +5721,11 @@ which can be octal or string, similar to the bash command. Examples: -Execute(Chmod('file', 0755)) +Execute(Chmod('file', 0o755)) env.Command('foo.out', 'foo.in', [Copy('$TARGET', '$SOURCE'), - Chmod('$TARGET', 0755)]) + Chmod('$TARGET', 0o755)]) Execute(Chmod('file', "ugo+w")) diff --git a/doc/user/README b/doc/user/README index 2d05359..f94632d 100644 --- a/doc/user/README +++ b/doc/user/README @@ -12,7 +12,7 @@ Writing examples: here's a simple template. env = Environment() - print env.Dump("CC") + print(env.Dump("CC")) diff --git a/doc/user/builders-writing.xml b/doc/user/builders-writing.xml index e20e99b..a906df8 100644 --- a/doc/user/builders-writing.xml +++ b/doc/user/builders-writing.xml @@ -196,7 +196,7 @@ env.Foo('file.foo', 'file.input') file.input - + cat @@ -309,7 +309,7 @@ file.input hello.c - + cat @@ -389,7 +389,7 @@ file1.input file2.input - + cat @@ -682,7 +682,7 @@ env.Foo('file') file.input - + cat @@ -766,7 +766,7 @@ file.input new_source - + cat @@ -840,7 +840,7 @@ modify1.input modify2.input - + cat diff --git a/doc/user/environments.xml b/doc/user/environments.xml index 0b246d2..43503a6 100644 --- a/doc/user/environments.xml +++ b/doc/user/environments.xml @@ -1652,7 +1652,7 @@ env['ENV']['PATH'] = '/usr/local/bin:/bin:/usr/bin' env = Environment() env.Command('foo', [], '__ROOT__/usr/bin/printenv.py') - + #!/usr/bin/env python import os import sys diff --git a/doc/user/factories.xml b/doc/user/factories.xml index c8480db..b68dfd9 100644 --- a/doc/user/factories.xml +++ b/doc/user/factories.xml @@ -161,7 +161,7 @@ env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() SConscript('S') file.in - + touch $* @@ -231,7 +231,7 @@ env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() SConscript('S') file.in - + touch $* @@ -325,7 +325,7 @@ env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() SConscript('S') file.in - + touch $* @@ -416,7 +416,7 @@ env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() SConscript('S') file.in - + touch $* @@ -452,7 +452,7 @@ touch $* Command("file.out", "file.in", [ Copy("$TARGET", "$SOURCE"), - Chmod("$TARGET", 0755), + Chmod("$TARGET", 0o755), ]) file.in diff --git a/doc/user/file-removal.xml b/doc/user/file-removal.xml index c6c695f..6c7c71a 100644 --- a/doc/user/file-removal.xml +++ b/doc/user/file-removal.xml @@ -214,7 +214,7 @@ foo.in foo.log - + cat $3 > $2 diff --git a/doc/user/mergeflags.xml b/doc/user/mergeflags.xml index 280eb82..879a7b2 100644 --- a/doc/user/mergeflags.xml +++ b/doc/user/mergeflags.xml @@ -77,7 +77,7 @@ env = Environment() env.Append(CCFLAGS = '-option -O3 -O1') flags = { 'CCFLAGS' : '-whatever -O3' } env.MergeFlags(flags) -print env['CCFLAGS'] +print(env['CCFLAGS']) @@ -104,7 +104,7 @@ env = Environment() env.Append(CPPPATH = ['/include', '/usr/local/include', '/usr/include']) flags = { 'CPPPATH' : ['/usr/opt/include', '/usr/local/include'] } env.MergeFlags(flags) -print env['CPPPATH'] +print(env['CPPPATH']) @@ -138,8 +138,8 @@ env = Environment() env.Append(CCFLAGS = '-option -O3 -O1') env.Append(CPPPATH = ['/include', '/usr/local/include', '/usr/include']) env.MergeFlags('-whatever -I/usr/opt/include -O3 -I/usr/local/include') -print env['CCFLAGS'] -print env['CPPPATH'] +print(env['CCFLAGS']) +print(env['CPPPATH']) diff --git a/doc/user/parseconfig.xml b/doc/user/parseconfig.xml index 1ddd42d..a07201a 100644 --- a/doc/user/parseconfig.xml +++ b/doc/user/parseconfig.xml @@ -87,7 +87,7 @@ env = Environment() env['CPPPATH'] = ['/lib/compat'] env.ParseConfig("pkg-config x11 --cflags --libs") -print env['CPPPATH'] +print(env['CPPPATH']) @@ -139,7 +139,7 @@ scons: `.' is up to date. env = Environment() env.ParseConfig("pkg-config x11 --cflags --libs") env.ParseConfig("pkg-config x11 --cflags --libs") -print env['CPPPATH'] +print(env['CPPPATH']) diff --git a/doc/user/parseflags.xml b/doc/user/parseflags.xml index 46d6866..836b7f2 100644 --- a/doc/user/parseflags.xml +++ b/doc/user/parseflags.xml @@ -80,11 +80,12 @@ +from __future__ import print_function env = Environment() d = env.ParseFlags("-I/opt/include -L/opt/lib -lfoo") for k,v in sorted(d.items()): if v: - print k, v + print(k, v) env.MergeFlags(d) env.Program('f1.c') @@ -119,11 +120,12 @@ int main() { return 0; } +from __future__ import print_function env = Environment() d = env.ParseFlags("-whatever") for k,v in sorted(d.items()): if v: - print k, v + print(k, v) env.MergeFlags(d) env.Program('f1.c') @@ -145,11 +147,12 @@ env.Program('f1.c') +from __future__ import print_function env = Environment() d = env.ParseFlags(["-I/opt/include", ["-L/opt/lib", "-lfoo"]]) for k,v in sorted(d.items()): if v: - print k, v + print(k, v) env.MergeFlags(d) env.Program('f1.c') @@ -172,11 +175,12 @@ int main() { return 0; } +from __future__ import print_function env = Environment() d = env.ParseFlags(["!echo -I/opt/include", "!echo -L/opt/lib", "-lfoo"]) for k,v in sorted(d.items()): if v: - print k, v + print(k, v) env.MergeFlags(d) env.Program('f1.c') diff --git a/doc/user/sideeffect.xml b/doc/user/sideeffect.xml index ffbfde7..6a10c3b 100644 --- a/doc/user/sideeffect.xml +++ b/doc/user/sideeffect.xml @@ -164,7 +164,7 @@ env.SideEffect('logfile.txt', f1 + f2) file1.in file2.in - + cat diff --git a/doc/user/troubleshoot.xml b/doc/user/troubleshoot.xml index feac970..80e0e24 100644 --- a/doc/user/troubleshoot.xml +++ b/doc/user/troubleshoot.xml @@ -289,7 +289,7 @@ file3.c env = Environment() -print env.Dump() +print(env.Dump()) @@ -349,7 +349,7 @@ print env.Dump() env = Environment() -print env.Dump('ENV') +print(env.Dump('ENV')) diff --git a/src/engine/SCons/Action.xml b/src/engine/SCons/Action.xml index ab42958..7a8194e 100644 --- a/src/engine/SCons/Action.xml +++ b/src/engine/SCons/Action.xml @@ -1,4 +1,4 @@ - + The subsidiary script(s) must use the -Import +Import function to import the variables. Examples: - + foo = SConscript('sub/SConscript', exports='env') SConscript('dir/SConscript', exports=['env', 'variable']) SConscript(dirs='subdir', exports='env variable') SConscript(dirs=['one', 'two', 'three'], exports='shared_info') - + If the optional variant_dir argument is present, it causes an effect equivalent to the -VariantDir +VariantDir method described below. (If variant_dir @@ -3668,14 +3603,14 @@ and arguments are interpreted relative to the directory of the calling --> argument is interpreted relative to the directory of the calling -SConscript +SConscript file. See the description of the -VariantDir +VariantDir function below for additional details and restrictions. - + If variant_dir is present, @@ -3685,46 +3620,46 @@ but is not, --> the source directory is the directory in which the -SConscript +SConscript file resides and the -SConscript +SConscript file is evaluated as if it were in the variant_dir directory: - + SConscript('src/SConscript', variant_dir = 'build') - + is equivalent to - + VariantDir('build', 'src') SConscript('build/SConscript') - + This later paradigm is often used when the sources are in the same directory as the -SConstruct: +SConstruct: - + SConscript('SConscript', variant_dir = 'build') - + is equivalent to - + VariantDir('build', '.') SConscript('build/SConscript') - + - + The optional must_exist argument, if true, causes an exception to be raised if a requested -SConscript file is not found. The current default is false, +SConscript file is not found. The current default is false, causing only a warning to be omitted, but this behavior is deprecated. For scripts which truly intend to be optional, transition to explicty supplying must_exist=False to the call. - + Here are some composite examples: - + # collect the configuration information and use it to build src and doc shared_info = SConscript('MyConfig.py') SConscript('src/SConscript', exports='shared_info') SConscript('doc/SConscript', exports='shared_info') - + # build debugging and production versions. SConscript # can use Dir('.').path to determine variant. SConscript('SConscript', variant_dir='debug', duplicate=0) SConscript('SConscript', variant_dir='prod', duplicate=0) - + # build debugging and production versions. SConscript # is passed flags to use. opts = { 'CPPDEFINES' : ['DEBUG'], 'CCFLAGS' : '-pgdb' } @@ -3795,7 +3730,7 @@ opts = { 'CPPDEFINES' : ['NODEBUG'], 'CCFLAGS' : '-O' } SConscript('SConscript', variant_dir='prod', duplicate=0, exports=opts) - + # build common documentation and compile for different architectures SConscript('doc/SConscript', variant_dir='build/doc', duplicate=0) SConscript('src/SConscript', variant_dir='build/x86', duplicate=0) @@ -3810,10 +3745,9 @@ SConscript('src/SConscript', variant_dir='build/ppc', duplicate=0) env.SConscriptChdir(value) - - + By default, -scons +scons changes its working directory to the directory in which each subsidiary SConscript file lives. @@ -3821,14 +3755,14 @@ This behavior may be disabled by specifying either: - + SConscriptChdir(0) env.SConscriptChdir(0) - + in which case -scons +scons will stay in the top-level directory while reading all SConscript files. (This may be necessary when building from repositories, @@ -3840,11 +3774,11 @@ SConscriptChdir() multiple times. - + Example: - + env = Environment() SConscriptChdir(0) SConscript('foo/SConscript') # will not chdir to foo @@ -3860,10 +3794,9 @@ SConscript('bar/SConscript') # will chdir to bar env.SConsignFile([file, dbm_module]) - - + This tells -scons +scons to store all file signatures in the specified database file. @@ -3880,17 +3813,17 @@ If file is not an absolute path name, the file is placed in the same directory as the top-level -SConstruct +SConstruct file. - + If file is None, then -scons +scons will store file signatures in a separate .sconsign @@ -3900,7 +3833,7 @@ not in one global database file. prior to SCons 0.96.91 and 0.97.) - + The optional dbm_module argument can be used to specify @@ -3912,11 +3845,11 @@ Python data structures, and which works on all Python versions. - + Examples: - + # Explicitly stores signatures in ".sconsign.dblite" # in the top-level SConstruct directory (the # default behavior). @@ -3939,14 +3872,13 @@ SConsignFile(None) env.SetDefault(key=val, [...]) - - + Sets construction variables to default values specified with the keyword arguments if (and only if) the variables are not already set. The following statements are equivalent: - + env.SetDefault(FOO = 'foo') if 'FOO' not in env: env['FOO'] = 'foo' @@ -3960,13 +3892,12 @@ if 'FOO' not in env: env['FOO'] = 'foo' env.SetOption(name, value) - - + This function provides a way to set a select subset of the scons command line options from a SConscript file. The options supported are: - + clean @@ -4051,17 +3982,17 @@ which corresponds to --stack-size. - + See the documentation for the corresponding command line object for information about each specific option. - + Example: - + SetOption('max_drift', 1) @@ -4073,8 +4004,7 @@ SetOption('max_drift', 1) env.SideEffect(side_effect, target) - - + Declares side_effect as a side effect of building @@ -4092,7 +4022,7 @@ files for a static library, and various log files are created updated as side effects of various TeX commands. If a target is a side effect of multiple build commands, -scons +scons will ensure that only one set of commands is executed at a time. Consequently, you only need to use this method @@ -4100,7 +4030,7 @@ for side-effect targets that are built as a result of multiple build commands. - + Because multiple build commands may update the same side effect file, by default the @@ -4124,9 +4054,9 @@ is cleaned whenever a specific is cleaned, you must specify this explicitly with the -Clean +Clean or -env.Clean +env.Clean function. @@ -4138,17 +4068,16 @@ function. env.SourceCode(entries, builder) - - + This function and its associate factory functions are deprecated. There is no replacement. The intended use was to keep a local tree in sync with an archive, but in actuality the function only causes the archive to be fetched on the first run. -Synchronizing with the archive is best done external to SCons. +Synchronizing with the archive is best done external to SCons. - + Arrange for non-existent source files to be fetched from a source code management system using the specified @@ -4161,30 +4090,30 @@ source files or directories in which source files can be found. - + For any non-existent source files, -scons +scons will search up the directory tree and use the first -SourceCode +SourceCode builder it finds. The specified builder may be None, in which case -scons +scons will not use a builder to fetch source files for the specified entries, even if a -SourceCode +SourceCode builder has been specified for a directory higher up the tree. - -scons + +scons will, by default, fetch files from SCCS or RCS subdirectories without explicit configuration. @@ -4196,11 +4125,11 @@ and speed up your build a little by disabling these searches as follows: - + env.SourceCode('.', None) - + Note that if the specified builder is one you create by hand, @@ -4209,8 +4138,8 @@ construction environment to use when fetching a source file. - -scons + +scons provides a set of canned factory functions that return appropriate Builders for various popular @@ -4218,119 +4147,18 @@ source code management systems. Canonical examples of invocation include: - + env.SourceCode('.', env.BitKeeper('/usr/local/BKsources')) env.SourceCode('src', env.CVS('/usr/local/CVSROOT')) env.SourceCode('/', env.RCS()) env.SourceCode(['f1.c', 'f2.c'], env.SCCS()) env.SourceCode('no_source.c', None) - + - - - SourceSignatures(type) - - - env.SourceSignatures(type) - - - -Note: Although it is not yet officially deprecated, -use of this function is discouraged. -See the -Decider -function for a more flexible and straightforward way -to configure SCons' decision-making. - - - -The -SourceSignatures -function tells -scons -how to decide if a source file -(a file that is not built from any other files) -has changed since the last time it -was used to build a particular target file. -Legal values are -MD5 -or -timestamp. - - - -If the environment method is used, -the specified type of source signature -is only used when deciding whether targets -built with that environment are up-to-date or must be rebuilt. -If the global function is used, -the specified type of source signature becomes the default -used for all decisions -about whether targets are up-to-date. - - - -MD5 -means -scons -decides that a source file has changed -if the MD5 checksum of its contents has changed since -the last time it was used to rebuild a particular target file. - - - -timestamp -means -scons -decides that a source file has changed -if its timestamp (modification time) has changed since -the last time it was used to rebuild a particular target file. -(Note that although this is similar to the behavior of Make, -by default it will also rebuild if the dependency is -older -than the last time it was used to rebuild the target file.) - - - -There is no different between the two behaviors -for Python -Value -node objects. - - - -MD5 -signatures take longer to compute, -but are more accurate than -timestamp -signatures. -The default value is -MD5. - - - -Note that the default -TargetSignatures -setting (see below) -is to use this -SourceSignatures -setting for any target files that are used -to build other target files. -Consequently, changing the value of -SourceSignatures -will, by default, -affect the up-to-date decision for all files in the build -(or all files built with a specific construction environment -when -env.SourceSignatures -is used). - - - Split(arg) @@ -4338,8 +4166,7 @@ is used). env.Split(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 @@ -4352,11 +4179,11 @@ 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(""" @@ -4371,14 +4198,13 @@ files = Split(""" env.subst(input, [raw, target, source, conv]) - - + Performs construction variable interpolation on the specified string or sequence argument input. - + By default, leading or trailing white space will be removed from the result. @@ -4410,7 +4236,7 @@ pairs (as is done for signature calculation). - + If the input is a sequence (list or tuple), the individual elements of @@ -4418,7 +4244,7 @@ the sequence will be expanded, and the results will be returned as a list. - + The optional target and @@ -4427,20 +4253,20 @@ keyword arguments must be set to lists of target and source nodes, respectively, if you want the -$TARGET, -$TARGETS, -$SOURCE +$TARGET, +$TARGETS, +$SOURCE and -$SOURCES +$SOURCES to be available for expansion. This is usually necessary if you are calling -env.subst +env.subst from within a Python function used as an SCons action. - + Returned string values or sequence elements are converted to their string representation by default. The optional @@ -4458,11 +4284,11 @@ idiom to pass in an unnamed function that simply returns its unconverted argument. - + Example: - + print(env.subst("The C compiler is: $CC")) def compile(target, source, env): @@ -4479,20 +4305,19 @@ source_nodes = env.subst('$EXPAND_TO_NODELIST', Tag(node, tags) - - + Annotates file or directory Nodes with information about how the -Package +Package Builder should package those files or directories. All tags are optional. - + Examples: - + # makes sure the built library will be installed with 0o644 file # access mode Tag( Library( 'lib.c' ), UNIX_ATTR="0o644" ) @@ -4502,161 +4327,6 @@ Tag( 'file2.txt', DOC ) - - - TargetSignatures(type) - - - env.TargetSignatures(type) - - - -Note: Although it is not yet officially deprecated, -use of this function is discouraged. -See the -Decider -function for a more flexible and straightforward way -to configure SCons' decision-making. - - - -The -TargetSignatures -function tells -scons -how to decide if a target file -(a file that -is -built from any other files) -has changed since the last time it -was used to build some other target file. -Legal values are -"build"; -"content" -(or its synonym -"MD5"); -"timestamp"; -or -"source". - - - -If the environment method is used, -the specified type of target signature is only used -for targets built with that environment. -If the global function is used, -the specified type of signature becomes the default -used for all target files that -don't have an explicit target signature type -specified for their environments. - - - -"content" -(or its synonym -"MD5") -means -scons -decides that a target file has changed -if the MD5 checksum of its contents has changed since -the last time it was used to rebuild some other target file. -This means -scons -will open up -MD5 sum the contents -of target files after they're built, -and may decide that it does not need to rebuild -"downstream" target files if a file was -rebuilt with exactly the same contents as the last time. - - - -"timestamp" -means -scons -decides that a target file has changed -if its timestamp (modification time) has changed since -the last time it was used to rebuild some other target file. -(Note that although this is similar to the behavior of Make, -by default it will also rebuild if the dependency is -older -than the last time it was used to rebuild the target file.) - - - -"source" -means -scons -decides that a target file has changed -as specified by the corresponding -SourceSignatures -setting -("MD5" -or -"timestamp"). -This means that -scons -will treat all input files to a target the same way, -regardless of whether they are source files -or have been built from other files. - - - -"build" -means -scons -decides that a target file has changed -if it has been rebuilt in this invocation -or if its content or timestamp have changed -as specified by the corresponding -SourceSignatures -setting. -This "propagates" the status of a rebuilt file -so that other "downstream" target files -will always be rebuilt, -even if the contents or the timestamp -have not changed. - - - -"build" -signatures are fastest because -"content" -(or -"MD5") -signatures take longer to compute, -but are more accurate than -"timestamp" -signatures, -and can prevent unnecessary "downstream" rebuilds -when a target file is rebuilt to the exact same contents -as the previous build. -The -"source" -setting provides the most consistent behavior -when other target files may be rebuilt from -both source and target input files. -The default value is -"source". - - - -Because the default setting is -"source", -using -SourceSignatures -is generally preferable to -TargetSignatures, -so that the up-to-date decision -will be consistent for all files -(or all files built with a specific construction environment). -Use of -TargetSignatures -provides specific control for how built target files -affect their "downstream" dependencies. - - - Tool(string, [toolpath, **kw]) @@ -4664,10 +4334,9 @@ affect their "downstream" dependencies. env.Tool(string, [toolpath, **kw]) - - + The -Tool +Tool form of the function returns a callable object that can be used to initialize @@ -4679,21 +4348,21 @@ in which case the object will add the necessary variables to the construction environment and the name of the tool will be added to the -$TOOLS +$TOOLS construction variable. - + Additional keyword arguments are passed to the tool's generate() method. - + Examples: - + env = Environment(tools = [ Tool('msvc') ]) env = Environment() @@ -4703,22 +4372,22 @@ u = Tool('opengl', toolpath = ['tools']) u(env) # adds 'opengl' to the TOOLS variable - + The -env.Tool +env.Tool form of the function applies the callable object for the specified tool string to the environment through which the method was called. - + Additional keyword arguments are passed to the tool's generate() method. - + env.Tool('gcc') env.Tool('opengl', toolpath = ['build/tools']) @@ -4731,8 +4400,7 @@ env.Tool('opengl', toolpath = ['build/tools']) env.Value(value, [built_value]) - - + Returns a Node object representing the specified Python value. Value Nodes can be used as dependencies of targets. If the result of calling @@ -4746,7 +4414,7 @@ When using timestamp source signatures, Value Nodes' timestamps are equal to the system time when the Node is created. - + The returned Value Node object has a write() method that can be used to "build" a Value Node @@ -4762,11 +4430,11 @@ There is a corresponding method that will return the built value of the Node. - + Examples: - + env = Environment() def create(target, source, env): @@ -4808,10 +4476,9 @@ env.UpdateValue(target = Value(output), source = Value(input)) env.VariantDir(variant_dir, src_dir, [duplicate]) - - + Use the -VariantDir +VariantDir function to create a copy of your sources in another location: if a name under variant_dir @@ -4824,8 +4491,8 @@ than the original sources by simply refering to the sources (and targets) within the variant tree. - -VariantDir + +VariantDir can be called multiple times with the same src_dir to set up multiple builds with different options @@ -4843,9 +4510,9 @@ TODO: src_dir = '.' works fine with a build dir under it. --> - + The default behavior is for -scons +scons to physically duplicate the source files in the variant tree. Thus, a build performed in the variant tree is guaranteed to be identical to a build performed in the source tree even if @@ -4856,7 +4523,7 @@ or individual compilers or other invoked tools are hard-coded to put derived files in the same directory as source files. - + If possible on the platform, the duplication is performed by linking rather than copying; see also the @@ -4867,14 +4534,14 @@ files and directories that are not used are not present in variant_dir. - + Duplicating the source tree may be disabled by setting the duplicate argument to 0 (zero). This will cause -scons +scons to invoke Builders using the path names of source files in src_dir and the path names of derived files within @@ -4885,9 +4552,9 @@ and is usually safe for most builds (but see above for cases that may cause problems). - + Note that -VariantDir +VariantDir works most naturally with a subsidiary SConscript file. However, you would then call the subsidiary SConscript file not in the source directory, but in the @@ -4895,11 +4562,11 @@ not in the source directory, but in the regardless of the value of duplicate. This is how you tell -scons +scons which variant of a source tree to build: - + # run src/SConscript in two variant directories VariantDir('build/variant1', 'src') SConscript('build/variant1/SConscript') @@ -4907,31 +4574,31 @@ VariantDir('build/variant2', 'src') SConscript('build/variant2/SConscript') - + See also the -SConscript +SConscript function, described above, for another way to specify a variant directory in conjunction with calling a subsidiary SConscript file. - + Examples: - + # use names in the build directory, not the source directory VariantDir('build', 'src', duplicate=0) Program('build/prog', 'build/source.c') - + # this builds both the source and docs in a separate subtree VariantDir('build', '.', duplicate=0) SConscript(dirs=['build/src','build/doc']) - + # same as previous example, but only uses SConscript SConscript(dirs='src', variant_dir='build/src', duplicate=0) SConscript(dirs='doc', variant_dir='build/doc', duplicate=0) @@ -4945,35 +4612,55 @@ SConscript(dirs='doc', variant_dir='build/doc', duplicate=0) env.WhereIs(program, [path, pathext, reject]) - - + Searches for the specified executable program, returning the full path name to the program -if it is found, -and returning None if not. -Searches the specified -path, -the value of the calling environment's PATH -(env['ENV']['PATH']), -or the user's current external PATH -(os.environ['PATH']) -by default. +if it is found, else None. +Searches the value of the +path keyword argument, +or if None (the default) +the value of the calling environment's PATH +(env['ENV']['PATH']). +If path is None and +the env['ENV']['PATH'] key does not exist, +the user's current external PATH +(os.environ['PATH']) is used as fallback. + + On Windows systems, searches for executable -programs with any of the file extensions -listed in the specified -pathext, -the calling environment's PATHEXT -(env['ENV']['PATHEXT']) -or the user's current PATHEXT +programs with any of the file extensions listed in the +pathext keyword argument, +or if None (the default) +the calling environment's PATHEXT +(env['ENV']['PATHEXT']). +The user's current external PATHEXT (os.environ['PATHEXT']) -by default. +is used as a fallback if pathext is +None +and the key env['ENV']['PATHEXT'] +does not exist. + + Will not select any path name or names in the specified reject list, if any. + + +If you would prefer to search +the user's current external PATH +(os.environ['PATH']) +by default, +consider using the function SCons.Util.WhereIs instead. +Note that SCons.Util.WhereIs +does not expand environment variables automatically +(no implicit env.subst for its arguments). + + + diff --git a/doc/generated/functions.mod b/doc/generated/functions.mod index e460aaf..91710a3 100644 --- a/doc/generated/functions.mod +++ b/doc/generated/functions.mod @@ -82,11 +82,9 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. SetOption"> SideEffect"> SourceCode"> -SourceSignatures"> Split"> subst"> Tag"> -TargetSignatures"> Tool"> Value"> VariantDir"> @@ -166,11 +164,9 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. env.SetOption"> env.SideEffect"> env.SourceCode"> -env.SourceSignatures"> env.Split"> env.subst"> env.Tag"> -env.TargetSignatures"> env.Tool"> env.Value"> env.VariantDir"> @@ -260,11 +256,9 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. SetOption"> SideEffect"> SourceCode"> -SourceSignatures"> Split"> subst"> Tag"> -TargetSignatures"> Tool"> Value"> VariantDir"> @@ -344,11 +338,9 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. env.SetOption"> env.SideEffect"> env.SourceCode"> -env.SourceSignatures"> env.Split"> env.subst"> env.Tag"> -env.TargetSignatures"> env.Tool"> env.Value"> env.VariantDir"> diff --git a/doc/generated/tools.gen b/doc/generated/tools.gen index 0d30f6f..bf6381c 100644 --- a/doc/generated/tools.gen +++ b/doc/generated/tools.gen @@ -1,4 +1,3 @@ - %scons; @@ -12,153 +11,137 @@ %variables-mod; ]> - + 386asm - - + Sets construction variables for the 386ASM assembler for the Phar Lap ETS embedded operating system. -Sets: &cv-link-AS;, &cv-link-ASCOM;, &cv-link-ASFLAGS;, &cv-link-ASPPCOM;, &cv-link-ASPPFLAGS;.Uses: &cv-link-CC;, &cv-link-CPPFLAGS;, &cv-link-_CPPDEFFLAGS;, &cv-link-_CPPINCFLAGS;. +Sets: &cv-link-AS;, &cv-link-ASCOM;, &cv-link-ASFLAGS;, &cv-link-ASPPCOM;, &cv-link-ASPPFLAGS;.Uses: &cv-link-CC;, &cv-link-CPPFLAGS;, &cv-link-_CPPDEFFLAGS;, &cv-link-_CPPINCFLAGS;. aixc++ - - + Sets construction variables for the IMB xlc / Visual Age C++ compiler. -Sets: &cv-link-CXX;, &cv-link-CXXVERSION;, &cv-link-SHCXX;, &cv-link-SHOBJSUFFIX;. +Sets: &cv-link-CXX;, &cv-link-CXXVERSION;, &cv-link-SHCXX;, &cv-link-SHOBJSUFFIX;. aixcc - - + Sets construction variables for the IBM xlc / Visual Age C compiler. -Sets: &cv-link-CC;, &cv-link-CCVERSION;, &cv-link-SHCC;. +Sets: &cv-link-CC;, &cv-link-CCVERSION;, &cv-link-SHCC;. aixf77 - - + Sets construction variables for the IBM Visual Age f77 Fortran compiler. -Sets: &cv-link-F77;, &cv-link-SHF77;. +Sets: &cv-link-F77;, &cv-link-SHF77;. aixlink - - + Sets construction variables for the IBM Visual Age linker. -Sets: &cv-link-LINKFLAGS;, &cv-link-SHLIBSUFFIX;, &cv-link-SHLINKFLAGS;. +Sets: &cv-link-LINKFLAGS;, &cv-link-SHLIBSUFFIX;, &cv-link-SHLINKFLAGS;. applelink - - + Sets construction variables for the Apple linker (similar to the GNU linker). - Sets: &cv-link-APPLELINK_COMPATIBILITY_VERSION;, &cv-link-APPLELINK_CURRENT_VERSION;, &cv-link-APPLELINK_NO_COMPATIBILITY_VERSION;, &cv-link-APPLELINK_NO_CURRENT_VERSION;, &cv-link-FRAMEWORKPATHPREFIX;, &cv-link-LDMODULECOM;, &cv-link-LDMODULEFLAGS;, &cv-link-LDMODULEPREFIX;, &cv-link-LDMODULESUFFIX;, &cv-link-LINKCOM;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;, &cv-link-_APPLELINK_COMPATIBILITY_VERSION;, &cv-link-_APPLELINK_CURRENT_VERSION;, &cv-link-_FRAMEWORKPATH;, &cv-link-_FRAMEWORKS;.Uses: &cv-link-FRAMEWORKSFLAGS;. + Sets: &cv-link-APPLELINK_COMPATIBILITY_VERSION;, &cv-link-APPLELINK_CURRENT_VERSION;, &cv-link-APPLELINK_NO_COMPATIBILITY_VERSION;, &cv-link-APPLELINK_NO_CURRENT_VERSION;, &cv-link-FRAMEWORKPATHPREFIX;, &cv-link-LDMODULECOM;, &cv-link-LDMODULEFLAGS;, &cv-link-LDMODULEPREFIX;, &cv-link-LDMODULESUFFIX;, &cv-link-LINKCOM;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;, &cv-link-_APPLELINK_COMPATIBILITY_VERSION;, &cv-link-_APPLELINK_CURRENT_VERSION;, &cv-link-_FRAMEWORKPATH;, &cv-link-_FRAMEWORKS;.Uses: &cv-link-FRAMEWORKSFLAGS;. ar - - -Sets construction variables for the ar library archiver. + +Sets construction variables for the ar library archiver. -Sets: &cv-link-AR;, &cv-link-ARCOM;, &cv-link-ARFLAGS;, &cv-link-LIBPREFIX;, &cv-link-LIBSUFFIX;, &cv-link-RANLIB;, &cv-link-RANLIBCOM;, &cv-link-RANLIBFLAGS;. +Sets: &cv-link-AR;, &cv-link-ARCOM;, &cv-link-ARFLAGS;, &cv-link-LIBPREFIX;, &cv-link-LIBSUFFIX;, &cv-link-RANLIB;, &cv-link-RANLIBCOM;, &cv-link-RANLIBFLAGS;. as - - -Sets construction variables for the as assembler. + +Sets construction variables for the as assembler. -Sets: &cv-link-AS;, &cv-link-ASCOM;, &cv-link-ASFLAGS;, &cv-link-ASPPCOM;, &cv-link-ASPPFLAGS;.Uses: &cv-link-CC;, &cv-link-CPPFLAGS;, &cv-link-_CPPDEFFLAGS;, &cv-link-_CPPINCFLAGS;. +Sets: &cv-link-AS;, &cv-link-ASCOM;, &cv-link-ASFLAGS;, &cv-link-ASPPCOM;, &cv-link-ASPPFLAGS;.Uses: &cv-link-CC;, &cv-link-CPPFLAGS;, &cv-link-_CPPDEFFLAGS;, &cv-link-_CPPINCFLAGS;. bcc32 - - + Sets construction variables for the bcc32 compiler. -Sets: &cv-link-CC;, &cv-link-CCCOM;, &cv-link-CCFLAGS;, &cv-link-CFILESUFFIX;, &cv-link-CFLAGS;, &cv-link-CPPDEFPREFIX;, &cv-link-CPPDEFSUFFIX;, &cv-link-INCPREFIX;, &cv-link-INCSUFFIX;, &cv-link-SHCC;, &cv-link-SHCCCOM;, &cv-link-SHCCFLAGS;, &cv-link-SHCFLAGS;, &cv-link-SHOBJSUFFIX;.Uses: &cv-link-_CPPDEFFLAGS;, &cv-link-_CPPINCFLAGS;. +Sets: &cv-link-CC;, &cv-link-CCCOM;, &cv-link-CCFLAGS;, &cv-link-CFILESUFFIX;, &cv-link-CFLAGS;, &cv-link-CPPDEFPREFIX;, &cv-link-CPPDEFSUFFIX;, &cv-link-INCPREFIX;, &cv-link-INCSUFFIX;, &cv-link-SHCC;, &cv-link-SHCCCOM;, &cv-link-SHCCFLAGS;, &cv-link-SHCFLAGS;, &cv-link-SHOBJSUFFIX;.Uses: &cv-link-_CPPDEFFLAGS;, &cv-link-_CPPINCFLAGS;. cc - - + Sets construction variables for generic POSIX C compilers. -Sets: &cv-link-CC;, &cv-link-CCCOM;, &cv-link-CCFLAGS;, &cv-link-CFILESUFFIX;, &cv-link-CFLAGS;, &cv-link-CPPDEFPREFIX;, &cv-link-CPPDEFSUFFIX;, &cv-link-FRAMEWORKPATH;, &cv-link-FRAMEWORKS;, &cv-link-INCPREFIX;, &cv-link-INCSUFFIX;, &cv-link-SHCC;, &cv-link-SHCCCOM;, &cv-link-SHCCFLAGS;, &cv-link-SHCFLAGS;, &cv-link-SHOBJSUFFIX;.Uses: &cv-link-PLATFORM;. +Sets: &cv-link-CC;, &cv-link-CCCOM;, &cv-link-CCFLAGS;, &cv-link-CFILESUFFIX;, &cv-link-CFLAGS;, &cv-link-CPPDEFPREFIX;, &cv-link-CPPDEFSUFFIX;, &cv-link-FRAMEWORKPATH;, &cv-link-FRAMEWORKS;, &cv-link-INCPREFIX;, &cv-link-INCSUFFIX;, &cv-link-SHCC;, &cv-link-SHCCCOM;, &cv-link-SHCCFLAGS;, &cv-link-SHCFLAGS;, &cv-link-SHOBJSUFFIX;.Uses: &cv-link-PLATFORM;. clang - - + Set construction variables for the Clang C compiler. -Sets: &cv-link-CC;, &cv-link-CCVERSION;, &cv-link-SHCCFLAGS;. +Sets: &cv-link-CC;, &cv-link-CCVERSION;, &cv-link-SHCCFLAGS;. clangxx - - + Set construction variables for the Clang C++ compiler. -Sets: &cv-link-CXX;, &cv-link-CXXVERSION;, &cv-link-SHCXXFLAGS;, &cv-link-SHOBJSUFFIX;, &cv-link-STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME;. +Sets: &cv-link-CXX;, &cv-link-CXXVERSION;, &cv-link-SHCXXFLAGS;, &cv-link-SHOBJSUFFIX;, &cv-link-STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME;. cvf - - + Sets construction variables for the Compaq Visual Fortran compiler. -Sets: &cv-link-FORTRAN;, &cv-link-FORTRANCOM;, &cv-link-FORTRANMODDIR;, &cv-link-FORTRANMODDIRPREFIX;, &cv-link-FORTRANMODDIRSUFFIX;, &cv-link-FORTRANPPCOM;, &cv-link-OBJSUFFIX;, &cv-link-SHFORTRANCOM;, &cv-link-SHFORTRANPPCOM;.Uses: &cv-link-CPPFLAGS;, &cv-link-FORTRANFLAGS;, &cv-link-SHFORTRANFLAGS;, &cv-link-_CPPDEFFLAGS;, &cv-link-_FORTRANINCFLAGS;, &cv-link-_FORTRANMODFLAG;. +Sets: &cv-link-FORTRAN;, &cv-link-FORTRANCOM;, &cv-link-FORTRANMODDIR;, &cv-link-FORTRANMODDIRPREFIX;, &cv-link-FORTRANMODDIRSUFFIX;, &cv-link-FORTRANPPCOM;, &cv-link-OBJSUFFIX;, &cv-link-SHFORTRANCOM;, &cv-link-SHFORTRANPPCOM;.Uses: &cv-link-CPPFLAGS;, &cv-link-FORTRANFLAGS;, &cv-link-SHFORTRANFLAGS;, &cv-link-_CPPDEFFLAGS;, &cv-link-_FORTRANINCFLAGS;, &cv-link-_FORTRANMODFLAG;. cXX - - + Sets construction variables for generic POSIX C++ compilers. -Sets: &cv-link-CPPDEFPREFIX;, &cv-link-CPPDEFSUFFIX;, &cv-link-CXX;, &cv-link-CXXCOM;, &cv-link-CXXFILESUFFIX;, &cv-link-CXXFLAGS;, &cv-link-INCPREFIX;, &cv-link-INCSUFFIX;, &cv-link-OBJSUFFIX;, &cv-link-SHCXX;, &cv-link-SHCXXCOM;, &cv-link-SHCXXFLAGS;, &cv-link-SHOBJSUFFIX;.Uses: &cv-link-CXXCOMSTR;. +Sets: &cv-link-CPPDEFPREFIX;, &cv-link-CPPDEFSUFFIX;, &cv-link-CXX;, &cv-link-CXXCOM;, &cv-link-CXXFILESUFFIX;, &cv-link-CXXFLAGS;, &cv-link-INCPREFIX;, &cv-link-INCSUFFIX;, &cv-link-OBJSUFFIX;, &cv-link-SHCXX;, &cv-link-SHCXXCOM;, &cv-link-SHCXXFLAGS;, &cv-link-SHOBJSUFFIX;.Uses: &cv-link-CXXCOMSTR;. cyglink - - + Set construction variables for cygwin linker/loader. -Sets: &cv-link-IMPLIBPREFIX;, &cv-link-IMPLIBSUFFIX;, &cv-link-LDMODULEVERSIONFLAGS;, &cv-link-LINKFLAGS;, &cv-link-RPATHPREFIX;, &cv-link-RPATHSUFFIX;, &cv-link-SHLIBPREFIX;, &cv-link-SHLIBSUFFIX;, &cv-link-SHLIBVERSIONFLAGS;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;, &cv-link-_LDMODULEVERSIONFLAGS;, &cv-link-_SHLIBVERSIONFLAGS;. +Sets: &cv-link-IMPLIBPREFIX;, &cv-link-IMPLIBSUFFIX;, &cv-link-LDMODULEVERSIONFLAGS;, &cv-link-LINKFLAGS;, &cv-link-RPATHPREFIX;, &cv-link-RPATHSUFFIX;, &cv-link-SHLIBPREFIX;, &cv-link-SHLIBSUFFIX;, &cv-link-SHLIBVERSIONFLAGS;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;, &cv-link-_LDMODULEVERSIONFLAGS;, &cv-link-_SHLIBVERSIONFLAGS;. default - - -Sets construction variables for a default list of Tool modules. + +Sets construction variables for a default list of Tool modules. Use default in the tools list to retain the original defaults, since the tools parameter is treated as a literal statement of the tools -to be made available in that construction environment, not an addition. +to be made available in that construction environment, not an addition. - + The list of tools selected by default is not static, but is dependent both on the platform and on the software installed on the platform. Some tools will not initialize if an underlying command is not found, and some tools are selected from a list of choices on a first-found basis. The finished tool list can be -examined by inspecting the TOOLS construction variable -in the construction environment. +examined by inspecting the TOOLS construction variable +in the construction environment. - + On all platforms, all tools from the following list are selected whose respective conditions are met: filesystem, wix, lex, yacc, rpcgen, swig, @@ -166,7 +149,7 @@ jar, javac, javah, rmic, dvipdf, dvips, gs, tex, latex, pdflatex, pdftex, tar, zip, textfile. - + On Linux systems, the default tools list selects (first-found): a C compiler from gcc, intelc, icc, cc; @@ -183,7 +166,7 @@ It also selects all found from the list m4, rpm. - + On Windows systems, the default tools list selects (first-found): a C compiler from msvc, mingw, gcc, intelc, icl, icc, cc, bcc32; @@ -201,7 +184,7 @@ It also selects all found from the list msvs, midl. - + On MacOS systems, the default tools list selects (first-found): a C compiler from gcc, cc; @@ -217,9 +200,9 @@ It also selects all found from the list m4, rpm. - + Default lists for other platforms can be found by -examining the scons +examining the scons source code (see SCons/Tool/__init__.py). @@ -228,16 +211,14 @@ source code (see dmd - - + Sets construction variables for D language compiler DMD. -Sets: &cv-link-DC;, &cv-link-DCOM;, &cv-link-DDEBUG;, &cv-link-DDEBUGPREFIX;, &cv-link-DDEBUGSUFFIX;, &cv-link-DFILESUFFIX;, &cv-link-DFLAGPREFIX;, &cv-link-DFLAGS;, &cv-link-DFLAGSUFFIX;, &cv-link-DINCPREFIX;, &cv-link-DINCSUFFIX;, &cv-link-DLIB;, &cv-link-DLIBCOM;, &cv-link-DLIBDIRPREFIX;, &cv-link-DLIBDIRSUFFIX;, &cv-link-DLIBFLAGPREFIX;, &cv-link-DLIBFLAGSUFFIX;, &cv-link-DLIBLINKPREFIX;, &cv-link-DLIBLINKSUFFIX;, &cv-link-DLINK;, &cv-link-DLINKCOM;, &cv-link-DLINKFLAGPREFIX;, &cv-link-DLINKFLAGS;, &cv-link-DLINKFLAGSUFFIX;, &cv-link-DPATH;, &cv-link-DRPATHPREFIX;, &cv-link-DRPATHSUFFIX;, &cv-link-DShLibSonameGenerator;, &cv-link-DVERPREFIX;, &cv-link-DVERSIONS;, &cv-link-DVERSUFFIX;, &cv-link-SHDC;, &cv-link-SHDCOM;, &cv-link-SHDLIBVERSION;, &cv-link-SHDLIBVERSIONFLAGS;, &cv-link-SHDLINK;, &cv-link-SHDLINKCOM;, &cv-link-SHDLINKFLAGS;. +Sets: &cv-link-DC;, &cv-link-DCOM;, &cv-link-DDEBUG;, &cv-link-DDEBUGPREFIX;, &cv-link-DDEBUGSUFFIX;, &cv-link-DFILESUFFIX;, &cv-link-DFLAGPREFIX;, &cv-link-DFLAGS;, &cv-link-DFLAGSUFFIX;, &cv-link-DINCPREFIX;, &cv-link-DINCSUFFIX;, &cv-link-DLIB;, &cv-link-DLIBCOM;, &cv-link-DLIBDIRPREFIX;, &cv-link-DLIBDIRSUFFIX;, &cv-link-DLIBFLAGPREFIX;, &cv-link-DLIBFLAGSUFFIX;, &cv-link-DLIBLINKPREFIX;, &cv-link-DLIBLINKSUFFIX;, &cv-link-DLINK;, &cv-link-DLINKCOM;, &cv-link-DLINKFLAGPREFIX;, &cv-link-DLINKFLAGS;, &cv-link-DLINKFLAGSUFFIX;, &cv-link-DPATH;, &cv-link-DRPATHPREFIX;, &cv-link-DRPATHSUFFIX;, &cv-link-DShLibSonameGenerator;, &cv-link-DVERPREFIX;, &cv-link-DVERSIONS;, &cv-link-DVERSUFFIX;, &cv-link-SHDC;, &cv-link-SHDCOM;, &cv-link-SHDLIBVERSION;, &cv-link-SHDLIBVERSIONFLAGS;, &cv-link-SHDLINK;, &cv-link-SHDLINKCOM;, &cv-link-SHDLINKFLAGS;. docbook - -This tool tries to make working with Docbook in SCons a little easier. + This tool tries to make working with Docbook in SCons a little easier. It provides several toolchains for creating different output formats, like HTML or PDF. Contained in the package is a distribution of the Docbook XSL stylesheets as of version 1.76.1. @@ -245,27 +226,27 @@ As long as you don't specify your own stylesheets for customization, these official versions are picked as default...which should reduce the inevitable setup hassles for you. -Implicit dependencies to images and XIncludes are detected automatically +Implicit dependencies to images and XIncludes are detected automatically if you meet the HTML requirements. The additional stylesheet utils/xmldepend.xsl by Paul DuBois is used for this purpose. -Note, that there is no support for XML catalog resolving offered! This tool calls +Note, that there is no support for XML catalog resolving offered! This tool calls the XSLT processors and PDF renderers with the stylesheets you specified, that's it. The rest lies in your hands and you still have to know what you're doing when resolving names via a catalog. -For activating the tool "docbook", you have to add its name to the Environment constructor, +For activating the tool "docbook", you have to add its name to the Environment constructor, like this -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) -On its startup, the Docbook tool tries to find a required xsltproc processor, and +On its startup, the Docbook tool tries to find a required xsltproc processor, and a PDF renderer, e.g. fop. So make sure that these are added to your system's environment PATH and can be called directly, without specifying their full path. -For the most basic processing of Docbook to HTML, you need to have installed +For the most basic processing of Docbook to HTML, you need to have installed -the Python lxml binding to libxml2, or +the Python lxml binding to libxml2, or the direct Python bindings for libxml2/libxslt, or @@ -276,49 +257,49 @@ and xalan. -Rendering to PDF requires you to have one of the applications +Rendering to PDF requires you to have one of the applications fop or xep installed. -Creating a HTML or PDF document is very simple and straightforward. Say +Creating a HTML or PDF document is very simple and straightforward. Say -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) env.DocbookHtml('manual.html', 'manual.xml') env.DocbookPdf('manual.pdf', 'manual.xml') -to get both outputs from your XML source manual.xml. As a shortcut, you can +to get both outputs from your XML source manual.xml. As a shortcut, you can give the stem of the filenames alone, like this: -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) env.DocbookHtml('manual') env.DocbookPdf('manual') -and get the same result. Target and source lists are also supported: +and get the same result. Target and source lists are also supported: -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) env.DocbookHtml(['manual.html','reference.html'], ['manual.xml','reference.xml']) -or even +or even -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) env.DocbookHtml(['manual','reference']) -Whenever you leave out the list of sources, you may not specify a file extension! The +Whenever you leave out the list of sources, you may not specify a file extension! The Tool uses the given names as file stems, and adds the suffixes for target and source files accordingly. -The rules given above are valid for the Builders DocbookHtml, -DocbookPdf, DocbookEpub, DocbookSlidesPdf and DocbookXInclude. For the -DocbookMan transformation you +The rules given above are valid for the Builders DocbookHtml, +DocbookPdf, DocbookEpub, DocbookSlidesPdf and DocbookXInclude. For the +DocbookMan transformation you can specify a target name, but the actual output names are automatically set from the refname entries in your XML source. -The Builders DocbookHtmlChunked, DocbookHtmlhelp and -DocbookSlidesHtml are special, in that: +The Builders DocbookHtmlChunked, DocbookHtmlhelp and +DocbookSlidesHtml are special, in that: -they create a large set of files, where the exact names and their number depend +they create a large set of files, where the exact names and their number depend on the content of the source file, and @@ -327,24 +308,24 @@ XSL transformation is not picked up by the stylesheets. -As a result, there is simply no use in specifying a target HTML name. +As a result, there is simply no use in specifying a target HTML name. So the basic syntax for these builders is always: -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) env.DocbookHtmlhelp('manual') -If you want to use a specific XSL file, you can set the +If you want to use a specific XSL file, you can set the additional xsl parameter to your Builder call as follows: -env.DocbookHtml('other.html', 'manual.xml', xsl='html.xsl') +env.DocbookHtml('other.html', 'manual.xml', xsl='html.xsl') -Since this may get tedious if you always use the same local naming for your customized XSL files, +Since this may get tedious if you always use the same local naming for your customized XSL files, e.g. html.xsl for HTML and pdf.xsl for PDF output, a set of variables for setting the default XSL name is provided. These are: -DOCBOOK_DEFAULT_XSL_HTML +DOCBOOK_DEFAULT_XSL_HTML DOCBOOK_DEFAULT_XSL_HTMLCHUNKED DOCBOOK_DEFAULT_XSL_HTMLHELP DOCBOOK_DEFAULT_XSL_PDF @@ -353,735 +334,656 @@ DOCBOOK_DEFAULT_XSL_MAN DOCBOOK_DEFAULT_XSL_SLIDESPDF DOCBOOK_DEFAULT_XSL_SLIDESHTML -and you can set them when constructing your environment: +and you can set them when constructing your environment: -env = Environment(tools=['docbook'], +env = Environment(tools=['docbook'], DOCBOOK_DEFAULT_XSL_HTML='html.xsl', DOCBOOK_DEFAULT_XSL_PDF='pdf.xsl') env.DocbookHtml('manual') # now uses html.xsl -Sets: &cv-link-DOCBOOK_DEFAULT_XSL_EPUB;, &cv-link-DOCBOOK_DEFAULT_XSL_HTML;, &cv-link-DOCBOOK_DEFAULT_XSL_HTMLCHUNKED;, &cv-link-DOCBOOK_DEFAULT_XSL_HTMLHELP;, &cv-link-DOCBOOK_DEFAULT_XSL_MAN;, &cv-link-DOCBOOK_DEFAULT_XSL_PDF;, &cv-link-DOCBOOK_DEFAULT_XSL_SLIDESHTML;, &cv-link-DOCBOOK_DEFAULT_XSL_SLIDESPDF;, &cv-link-DOCBOOK_FOP;, &cv-link-DOCBOOK_FOPCOM;, &cv-link-DOCBOOK_FOPFLAGS;, &cv-link-DOCBOOK_XMLLINT;, &cv-link-DOCBOOK_XMLLINTCOM;, &cv-link-DOCBOOK_XMLLINTFLAGS;, &cv-link-DOCBOOK_XSLTPROC;, &cv-link-DOCBOOK_XSLTPROCCOM;, &cv-link-DOCBOOK_XSLTPROCFLAGS;, &cv-link-DOCBOOK_XSLTPROCPARAMS;.Uses: &cv-link-DOCBOOK_FOPCOMSTR;, &cv-link-DOCBOOK_XMLLINTCOMSTR;, &cv-link-DOCBOOK_XSLTPROCCOMSTR;. +Sets: &cv-link-DOCBOOK_DEFAULT_XSL_EPUB;, &cv-link-DOCBOOK_DEFAULT_XSL_HTML;, &cv-link-DOCBOOK_DEFAULT_XSL_HTMLCHUNKED;, &cv-link-DOCBOOK_DEFAULT_XSL_HTMLHELP;, &cv-link-DOCBOOK_DEFAULT_XSL_MAN;, &cv-link-DOCBOOK_DEFAULT_XSL_PDF;, &cv-link-DOCBOOK_DEFAULT_XSL_SLIDESHTML;, &cv-link-DOCBOOK_DEFAULT_XSL_SLIDESPDF;, &cv-link-DOCBOOK_FOP;, &cv-link-DOCBOOK_FOPCOM;, &cv-link-DOCBOOK_FOPFLAGS;, &cv-link-DOCBOOK_XMLLINT;, &cv-link-DOCBOOK_XMLLINTCOM;, &cv-link-DOCBOOK_XMLLINTFLAGS;, &cv-link-DOCBOOK_XSLTPROC;, &cv-link-DOCBOOK_XSLTPROCCOM;, &cv-link-DOCBOOK_XSLTPROCFLAGS;, &cv-link-DOCBOOK_XSLTPROCPARAMS;.Uses: &cv-link-DOCBOOK_FOPCOMSTR;, &cv-link-DOCBOOK_XMLLINTCOMSTR;, &cv-link-DOCBOOK_XSLTPROCCOMSTR;. dvi - - -Attaches the DVI builder to the + +Attaches the DVI builder to the construction environment. dvipdf - - + Sets construction variables for the dvipdf utility. -Sets: &cv-link-DVIPDF;, &cv-link-DVIPDFCOM;, &cv-link-DVIPDFFLAGS;.Uses: &cv-link-DVIPDFCOMSTR;. +Sets: &cv-link-DVIPDF;, &cv-link-DVIPDFCOM;, &cv-link-DVIPDFFLAGS;.Uses: &cv-link-DVIPDFCOMSTR;. dvips - - + Sets construction variables for the dvips utility. -Sets: &cv-link-DVIPS;, &cv-link-DVIPSFLAGS;, &cv-link-PSCOM;, &cv-link-PSPREFIX;, &cv-link-PSSUFFIX;.Uses: &cv-link-PSCOMSTR;. +Sets: &cv-link-DVIPS;, &cv-link-DVIPSFLAGS;, &cv-link-PSCOM;, &cv-link-PSPREFIX;, &cv-link-PSSUFFIX;.Uses: &cv-link-PSCOMSTR;. f03 - - + Set construction variables for generic POSIX Fortran 03 compilers. -Sets: &cv-link-F03;, &cv-link-F03COM;, &cv-link-F03FLAGS;, &cv-link-F03PPCOM;, &cv-link-SHF03;, &cv-link-SHF03COM;, &cv-link-SHF03FLAGS;, &cv-link-SHF03PPCOM;, &cv-link-_F03INCFLAGS;.Uses: &cv-link-F03COMSTR;, &cv-link-F03PPCOMSTR;, &cv-link-SHF03COMSTR;, &cv-link-SHF03PPCOMSTR;. +Sets: &cv-link-F03;, &cv-link-F03COM;, &cv-link-F03FLAGS;, &cv-link-F03PPCOM;, &cv-link-SHF03;, &cv-link-SHF03COM;, &cv-link-SHF03FLAGS;, &cv-link-SHF03PPCOM;, &cv-link-_F03INCFLAGS;.Uses: &cv-link-F03COMSTR;, &cv-link-F03PPCOMSTR;, &cv-link-SHF03COMSTR;, &cv-link-SHF03PPCOMSTR;. f08 - - + Set construction variables for generic POSIX Fortran 08 compilers. -Sets: &cv-link-F08;, &cv-link-F08COM;, &cv-link-F08FLAGS;, &cv-link-F08PPCOM;, &cv-link-SHF08;, &cv-link-SHF08COM;, &cv-link-SHF08FLAGS;, &cv-link-SHF08PPCOM;, &cv-link-_F08INCFLAGS;.Uses: &cv-link-F08COMSTR;, &cv-link-F08PPCOMSTR;, &cv-link-SHF08COMSTR;, &cv-link-SHF08PPCOMSTR;. +Sets: &cv-link-F08;, &cv-link-F08COM;, &cv-link-F08FLAGS;, &cv-link-F08PPCOM;, &cv-link-SHF08;, &cv-link-SHF08COM;, &cv-link-SHF08FLAGS;, &cv-link-SHF08PPCOM;, &cv-link-_F08INCFLAGS;.Uses: &cv-link-F08COMSTR;, &cv-link-F08PPCOMSTR;, &cv-link-SHF08COMSTR;, &cv-link-SHF08PPCOMSTR;. f77 - - + Set construction variables for generic POSIX Fortran 77 compilers. -Sets: &cv-link-F77;, &cv-link-F77COM;, &cv-link-F77FILESUFFIXES;, &cv-link-F77FLAGS;, &cv-link-F77PPCOM;, &cv-link-F77PPFILESUFFIXES;, &cv-link-FORTRAN;, &cv-link-FORTRANCOM;, &cv-link-FORTRANFLAGS;, &cv-link-SHF77;, &cv-link-SHF77COM;, &cv-link-SHF77FLAGS;, &cv-link-SHF77PPCOM;, &cv-link-SHFORTRAN;, &cv-link-SHFORTRANCOM;, &cv-link-SHFORTRANFLAGS;, &cv-link-SHFORTRANPPCOM;, &cv-link-_F77INCFLAGS;.Uses: &cv-link-F77COMSTR;, &cv-link-F77PPCOMSTR;, &cv-link-FORTRANCOMSTR;, &cv-link-FORTRANPPCOMSTR;, &cv-link-SHF77COMSTR;, &cv-link-SHF77PPCOMSTR;, &cv-link-SHFORTRANCOMSTR;, &cv-link-SHFORTRANPPCOMSTR;. +Sets: &cv-link-F77;, &cv-link-F77COM;, &cv-link-F77FILESUFFIXES;, &cv-link-F77FLAGS;, &cv-link-F77PPCOM;, &cv-link-F77PPFILESUFFIXES;, &cv-link-FORTRAN;, &cv-link-FORTRANCOM;, &cv-link-FORTRANFLAGS;, &cv-link-SHF77;, &cv-link-SHF77COM;, &cv-link-SHF77FLAGS;, &cv-link-SHF77PPCOM;, &cv-link-SHFORTRAN;, &cv-link-SHFORTRANCOM;, &cv-link-SHFORTRANFLAGS;, &cv-link-SHFORTRANPPCOM;, &cv-link-_F77INCFLAGS;.Uses: &cv-link-F77COMSTR;, &cv-link-F77PPCOMSTR;, &cv-link-FORTRANCOMSTR;, &cv-link-FORTRANPPCOMSTR;, &cv-link-SHF77COMSTR;, &cv-link-SHF77PPCOMSTR;, &cv-link-SHFORTRANCOMSTR;, &cv-link-SHFORTRANPPCOMSTR;. f90 - - + Set construction variables for generic POSIX Fortran 90 compilers. -Sets: &cv-link-F90;, &cv-link-F90COM;, &cv-link-F90FLAGS;, &cv-link-F90PPCOM;, &cv-link-SHF90;, &cv-link-SHF90COM;, &cv-link-SHF90FLAGS;, &cv-link-SHF90PPCOM;, &cv-link-_F90INCFLAGS;.Uses: &cv-link-F90COMSTR;, &cv-link-F90PPCOMSTR;, &cv-link-SHF90COMSTR;, &cv-link-SHF90PPCOMSTR;. +Sets: &cv-link-F90;, &cv-link-F90COM;, &cv-link-F90FLAGS;, &cv-link-F90PPCOM;, &cv-link-SHF90;, &cv-link-SHF90COM;, &cv-link-SHF90FLAGS;, &cv-link-SHF90PPCOM;, &cv-link-_F90INCFLAGS;.Uses: &cv-link-F90COMSTR;, &cv-link-F90PPCOMSTR;, &cv-link-SHF90COMSTR;, &cv-link-SHF90PPCOMSTR;. f95 - - + Set construction variables for generic POSIX Fortran 95 compilers. -Sets: &cv-link-F95;, &cv-link-F95COM;, &cv-link-F95FLAGS;, &cv-link-F95PPCOM;, &cv-link-SHF95;, &cv-link-SHF95COM;, &cv-link-SHF95FLAGS;, &cv-link-SHF95PPCOM;, &cv-link-_F95INCFLAGS;.Uses: &cv-link-F95COMSTR;, &cv-link-F95PPCOMSTR;, &cv-link-SHF95COMSTR;, &cv-link-SHF95PPCOMSTR;. +Sets: &cv-link-F95;, &cv-link-F95COM;, &cv-link-F95FLAGS;, &cv-link-F95PPCOM;, &cv-link-SHF95;, &cv-link-SHF95COM;, &cv-link-SHF95FLAGS;, &cv-link-SHF95PPCOM;, &cv-link-_F95INCFLAGS;.Uses: &cv-link-F95COMSTR;, &cv-link-F95PPCOMSTR;, &cv-link-SHF95COMSTR;, &cv-link-SHF95PPCOMSTR;. fortran - - + Set construction variables for generic POSIX Fortran compilers. -Sets: &cv-link-FORTRAN;, &cv-link-FORTRANCOM;, &cv-link-FORTRANFLAGS;, &cv-link-SHFORTRAN;, &cv-link-SHFORTRANCOM;, &cv-link-SHFORTRANFLAGS;, &cv-link-SHFORTRANPPCOM;.Uses: &cv-link-FORTRANCOMSTR;, &cv-link-FORTRANPPCOMSTR;, &cv-link-SHFORTRANCOMSTR;, &cv-link-SHFORTRANPPCOMSTR;. +Sets: &cv-link-FORTRAN;, &cv-link-FORTRANCOM;, &cv-link-FORTRANFLAGS;, &cv-link-SHFORTRAN;, &cv-link-SHFORTRANCOM;, &cv-link-SHFORTRANFLAGS;, &cv-link-SHFORTRANPPCOM;.Uses: &cv-link-FORTRANCOMSTR;, &cv-link-FORTRANPPCOMSTR;, &cv-link-SHFORTRANCOMSTR;, &cv-link-SHFORTRANPPCOMSTR;. g++ - - -Set construction variables for the gXX C++ compiler. + +Set construction variables for the gXX C++ compiler. -Sets: &cv-link-CXX;, &cv-link-CXXVERSION;, &cv-link-SHCXXFLAGS;, &cv-link-SHOBJSUFFIX;. +Sets: &cv-link-CXX;, &cv-link-CXXVERSION;, &cv-link-SHCXXFLAGS;, &cv-link-SHOBJSUFFIX;. g77 - - -Set construction variables for the g77 Fortran compiler. -Calls the f77 Tool module + +Set construction variables for the g77 Fortran compiler. +Calls the f77 Tool module to set variables. gas - - -Sets construction variables for the gas assembler. -Calls the as module. + +Sets construction variables for the gas assembler. +Calls the as module. -Sets: &cv-link-AS;. +Sets: &cv-link-AS;. gcc - - -Set construction variables for the gcc C compiler. + +Set construction variables for the gcc C compiler. -Sets: &cv-link-CC;, &cv-link-CCVERSION;, &cv-link-SHCCFLAGS;. +Sets: &cv-link-CC;, &cv-link-CCVERSION;, &cv-link-SHCCFLAGS;. gdc - - + Sets construction variables for the D language compiler GDC. -Sets: &cv-link-DC;, &cv-link-DCOM;, &cv-link-DDEBUG;, &cv-link-DDEBUGPREFIX;, &cv-link-DDEBUGSUFFIX;, &cv-link-DFILESUFFIX;, &cv-link-DFLAGPREFIX;, &cv-link-DFLAGS;, &cv-link-DFLAGSUFFIX;, &cv-link-DINCPREFIX;, &cv-link-DINCSUFFIX;, &cv-link-DLIB;, &cv-link-DLIBCOM;, &cv-link-DLIBDIRPREFIX;, &cv-link-DLIBDIRSUFFIX;, &cv-link-DLIBFLAGPREFIX;, &cv-link-DLIBFLAGSUFFIX;, &cv-link-DLIBLINKPREFIX;, &cv-link-DLIBLINKSUFFIX;, &cv-link-DLINK;, &cv-link-DLINKCOM;, &cv-link-DLINKFLAGPREFIX;, &cv-link-DLINKFLAGS;, &cv-link-DLINKFLAGSUFFIX;, &cv-link-DPATH;, &cv-link-DRPATHPREFIX;, &cv-link-DRPATHSUFFIX;, &cv-link-DShLibSonameGenerator;, &cv-link-DVERPREFIX;, &cv-link-DVERSIONS;, &cv-link-DVERSUFFIX;, &cv-link-SHDC;, &cv-link-SHDCOM;, &cv-link-SHDLIBVERSION;, &cv-link-SHDLIBVERSIONFLAGS;, &cv-link-SHDLINK;, &cv-link-SHDLINKCOM;, &cv-link-SHDLINKFLAGS;. +Sets: &cv-link-DC;, &cv-link-DCOM;, &cv-link-DDEBUG;, &cv-link-DDEBUGPREFIX;, &cv-link-DDEBUGSUFFIX;, &cv-link-DFILESUFFIX;, &cv-link-DFLAGPREFIX;, &cv-link-DFLAGS;, &cv-link-DFLAGSUFFIX;, &cv-link-DINCPREFIX;, &cv-link-DINCSUFFIX;, &cv-link-DLIB;, &cv-link-DLIBCOM;, &cv-link-DLIBDIRPREFIX;, &cv-link-DLIBDIRSUFFIX;, &cv-link-DLIBFLAGPREFIX;, &cv-link-DLIBFLAGSUFFIX;, &cv-link-DLIBLINKPREFIX;, &cv-link-DLIBLINKSUFFIX;, &cv-link-DLINK;, &cv-link-DLINKCOM;, &cv-link-DLINKFLAGPREFIX;, &cv-link-DLINKFLAGS;, &cv-link-DLINKFLAGSUFFIX;, &cv-link-DPATH;, &cv-link-DRPATHPREFIX;, &cv-link-DRPATHSUFFIX;, &cv-link-DShLibSonameGenerator;, &cv-link-DVERPREFIX;, &cv-link-DVERSIONS;, &cv-link-DVERSUFFIX;, &cv-link-SHDC;, &cv-link-SHDCOM;, &cv-link-SHDLIBVERSION;, &cv-link-SHDLIBVERSIONFLAGS;, &cv-link-SHDLINK;, &cv-link-SHDLINKCOM;, &cv-link-SHDLINKFLAGS;. gettext - - + This is actually a toolset, which supports internationalization and localization of software being constructed with SCons. The toolset loads following tools: - + - xgettext - to extract internationalized messages from source code to + xgettext - to extract internationalized messages from source code to POT file(s), - msginit - may be optionally used to initialize PO + msginit - may be optionally used to initialize PO files, - msgmerge - to update PO files, that already contain + msgmerge - to update PO files, that already contain translated messages, - msgfmt - to compile textual PO file to binary + msgfmt - to compile textual PO file to binary installable MO file. - -When you enable gettext, it internally loads all abovementioned tools, + +When you enable gettext, it internally loads all abovementioned tools, so you're encouraged to see their individual documentation. - + Each of the above tools provides its own builder(s) which may be used to perform particular activities related to software internationalization. You may be however interested in top-level builder -Translate described few paragraphs later. +Translate described few paragraphs later. - -To use gettext tools add 'gettext' tool to your + +To use gettext tools add 'gettext' tool to your environment: - + env = Environment( tools = ['default', 'gettext'] ) gfortran - - + Sets construction variables for the GNU F95/F2003 GNU compiler. -Sets: &cv-link-F77;, &cv-link-F90;, &cv-link-F95;, &cv-link-FORTRAN;, &cv-link-SHF77;, &cv-link-SHF77FLAGS;, &cv-link-SHF90;, &cv-link-SHF90FLAGS;, &cv-link-SHF95;, &cv-link-SHF95FLAGS;, &cv-link-SHFORTRAN;, &cv-link-SHFORTRANFLAGS;. +Sets: &cv-link-F77;, &cv-link-F90;, &cv-link-F95;, &cv-link-FORTRAN;, &cv-link-SHF77;, &cv-link-SHF77FLAGS;, &cv-link-SHF90;, &cv-link-SHF90FLAGS;, &cv-link-SHF95;, &cv-link-SHF95FLAGS;, &cv-link-SHFORTRAN;, &cv-link-SHFORTRANFLAGS;. gnulink - - + Set construction variables for GNU linker/loader. -Sets: &cv-link-LDMODULEVERSIONFLAGS;, &cv-link-RPATHPREFIX;, &cv-link-RPATHSUFFIX;, &cv-link-SHLIBVERSIONFLAGS;, &cv-link-SHLINKFLAGS;, &cv-link-_LDMODULESONAME;, &cv-link-_SHLIBSONAME;. +Sets: &cv-link-LDMODULEVERSIONFLAGS;, &cv-link-RPATHPREFIX;, &cv-link-RPATHSUFFIX;, &cv-link-SHLIBVERSIONFLAGS;, &cv-link-SHLINKFLAGS;, &cv-link-_LDMODULESONAME;, &cv-link-_SHLIBSONAME;. gs - - + This Tool sets the required construction variables for working with the Ghostscript command. It also registers an appropriate Action -with the PDF Builder (PDF), such that the conversion from +with the PDF Builder (PDF), such that the conversion from PS/EPS to PDF happens automatically for the TeX/LaTeX toolchain. -Finally, it adds an explicit Ghostscript Builder (Gs) to the +Finally, it adds an explicit Ghostscript Builder (Gs) to the environment. -Sets: &cv-link-GS;, &cv-link-GSCOM;, &cv-link-GSFLAGS;.Uses: &cv-link-GSCOMSTR;. +Sets: &cv-link-GS;, &cv-link-GSCOM;, &cv-link-GSFLAGS;.Uses: &cv-link-GSCOMSTR;. hpc++ - - + Set construction variables for the compilers aCC on HP/UX systems. hpcc - - + Set construction variables for the aCC on HP/UX systems. -Calls the cXX tool for additional variables. +Calls the cXX tool for additional variables. -Sets: &cv-link-CXX;, &cv-link-CXXVERSION;, &cv-link-SHCXXFLAGS;. +Sets: &cv-link-CXX;, &cv-link-CXXVERSION;, &cv-link-SHCXXFLAGS;. hplink - - + Sets construction variables for the linker on HP/UX systems. -Sets: &cv-link-LINKFLAGS;, &cv-link-SHLIBSUFFIX;, &cv-link-SHLINKFLAGS;. +Sets: &cv-link-LINKFLAGS;, &cv-link-SHLIBSUFFIX;, &cv-link-SHLINKFLAGS;. icc - - + Sets construction variables for the icc compiler on OS/2 systems. -Sets: &cv-link-CC;, &cv-link-CCCOM;, &cv-link-CFILESUFFIX;, &cv-link-CPPDEFPREFIX;, &cv-link-CPPDEFSUFFIX;, &cv-link-CXXCOM;, &cv-link-CXXFILESUFFIX;, &cv-link-INCPREFIX;, &cv-link-INCSUFFIX;.Uses: &cv-link-CCFLAGS;, &cv-link-CFLAGS;, &cv-link-CPPFLAGS;, &cv-link-_CPPDEFFLAGS;, &cv-link-_CPPINCFLAGS;. +Sets: &cv-link-CC;, &cv-link-CCCOM;, &cv-link-CFILESUFFIX;, &cv-link-CPPDEFPREFIX;, &cv-link-CPPDEFSUFFIX;, &cv-link-CXXCOM;, &cv-link-CXXFILESUFFIX;, &cv-link-INCPREFIX;, &cv-link-INCSUFFIX;.Uses: &cv-link-CCFLAGS;, &cv-link-CFLAGS;, &cv-link-CPPFLAGS;, &cv-link-_CPPDEFFLAGS;, &cv-link-_CPPINCFLAGS;. icl - - + Sets construction variables for the Intel C/C++ compiler. -Calls the intelc Tool module to set its variables. +Calls the intelc Tool module to set its variables. ifl - - + Sets construction variables for the Intel Fortran compiler. -Sets: &cv-link-FORTRAN;, &cv-link-FORTRANCOM;, &cv-link-FORTRANPPCOM;, &cv-link-SHFORTRANCOM;, &cv-link-SHFORTRANPPCOM;.Uses: &cv-link-CPPFLAGS;, &cv-link-FORTRANFLAGS;, &cv-link-_CPPDEFFLAGS;, &cv-link-_FORTRANINCFLAGS;. +Sets: &cv-link-FORTRAN;, &cv-link-FORTRANCOM;, &cv-link-FORTRANPPCOM;, &cv-link-SHFORTRANCOM;, &cv-link-SHFORTRANPPCOM;.Uses: &cv-link-CPPFLAGS;, &cv-link-FORTRANFLAGS;, &cv-link-_CPPDEFFLAGS;, &cv-link-_FORTRANINCFLAGS;. ifort - - + Sets construction variables for newer versions of the Intel Fortran compiler for Linux. -Sets: &cv-link-F77;, &cv-link-F90;, &cv-link-F95;, &cv-link-FORTRAN;, &cv-link-SHF77;, &cv-link-SHF77FLAGS;, &cv-link-SHF90;, &cv-link-SHF90FLAGS;, &cv-link-SHF95;, &cv-link-SHF95FLAGS;, &cv-link-SHFORTRAN;, &cv-link-SHFORTRANFLAGS;. +Sets: &cv-link-F77;, &cv-link-F90;, &cv-link-F95;, &cv-link-FORTRAN;, &cv-link-SHF77;, &cv-link-SHF77FLAGS;, &cv-link-SHF90;, &cv-link-SHF90FLAGS;, &cv-link-SHF95;, &cv-link-SHF95FLAGS;, &cv-link-SHFORTRAN;, &cv-link-SHFORTRANFLAGS;. ilink - - + Sets construction variables for the ilink linker on OS/2 systems. -Sets: &cv-link-LIBDIRPREFIX;, &cv-link-LIBDIRSUFFIX;, &cv-link-LIBLINKPREFIX;, &cv-link-LIBLINKSUFFIX;, &cv-link-LINK;, &cv-link-LINKCOM;, &cv-link-LINKFLAGS;. +Sets: &cv-link-LIBDIRPREFIX;, &cv-link-LIBDIRSUFFIX;, &cv-link-LIBLINKPREFIX;, &cv-link-LIBLINKSUFFIX;, &cv-link-LINK;, &cv-link-LINKCOM;, &cv-link-LINKFLAGS;. ilink32 - - + Sets construction variables for the Borland ilink32 linker. -Sets: &cv-link-LIBDIRPREFIX;, &cv-link-LIBDIRSUFFIX;, &cv-link-LIBLINKPREFIX;, &cv-link-LIBLINKSUFFIX;, &cv-link-LINK;, &cv-link-LINKCOM;, &cv-link-LINKFLAGS;. +Sets: &cv-link-LIBDIRPREFIX;, &cv-link-LIBDIRSUFFIX;, &cv-link-LIBLINKPREFIX;, &cv-link-LIBLINKSUFFIX;, &cv-link-LINK;, &cv-link-LINKCOM;, &cv-link-LINKFLAGS;. install - - + Sets construction variables for file and directory installation. -Sets: &cv-link-INSTALL;, &cv-link-INSTALLSTR;. +Sets: &cv-link-INSTALL;, &cv-link-INSTALLSTR;. intelc - - + Sets construction variables for the Intel C/C++ compiler (Linux and Windows, version 7 and later). -Calls the gcc or msvc +Calls the gcc or msvc (on Linux and Windows, respectively) to set underlying variables. -Sets: &cv-link-AR;, &cv-link-CC;, &cv-link-CXX;, &cv-link-INTEL_C_COMPILER_VERSION;, &cv-link-LINK;. +Sets: &cv-link-AR;, &cv-link-CC;, &cv-link-CXX;, &cv-link-INTEL_C_COMPILER_VERSION;, &cv-link-LINK;. jar - - -Sets construction variables for the jar utility. + +Sets construction variables for the jar utility. -Sets: &cv-link-JAR;, &cv-link-JARCOM;, &cv-link-JARFLAGS;, &cv-link-JARSUFFIX;.Uses: &cv-link-JARCOMSTR;. +Sets: &cv-link-JAR;, &cv-link-JARCOM;, &cv-link-JARFLAGS;, &cv-link-JARSUFFIX;.Uses: &cv-link-JARCOMSTR;. javac - - - Sets construction variables for the javac compiler. + + Sets construction variables for the javac compiler. - Sets: &cv-link-JAVABOOTCLASSPATH;, &cv-link-JAVAC;, &cv-link-JAVACCOM;, &cv-link-JAVACFLAGS;, &cv-link-JAVACLASSPATH;, &cv-link-JAVACLASSSUFFIX;, &cv-link-JAVAINCLUDES;, &cv-link-JAVASOURCEPATH;, &cv-link-JAVASUFFIX;.Uses: &cv-link-JAVACCOMSTR;. + Sets: &cv-link-JAVABOOTCLASSPATH;, &cv-link-JAVAC;, &cv-link-JAVACCOM;, &cv-link-JAVACFLAGS;, &cv-link-JAVACLASSPATH;, &cv-link-JAVACLASSSUFFIX;, &cv-link-JAVAINCLUDES;, &cv-link-JAVASOURCEPATH;, &cv-link-JAVASUFFIX;.Uses: &cv-link-JAVACCOMSTR;. javah - - -Sets construction variables for the javah tool. + +Sets construction variables for the javah tool. -Sets: &cv-link-JAVACLASSSUFFIX;, &cv-link-JAVAH;, &cv-link-JAVAHCOM;, &cv-link-JAVAHFLAGS;.Uses: &cv-link-JAVACLASSPATH;, &cv-link-JAVAHCOMSTR;. +Sets: &cv-link-JAVACLASSSUFFIX;, &cv-link-JAVAH;, &cv-link-JAVAHCOM;, &cv-link-JAVAHFLAGS;.Uses: &cv-link-JAVACLASSPATH;, &cv-link-JAVAHCOMSTR;. latex - - -Sets construction variables for the latex utility. + +Sets construction variables for the latex utility. -Sets: &cv-link-LATEX;, &cv-link-LATEXCOM;, &cv-link-LATEXFLAGS;.Uses: &cv-link-LATEXCOMSTR;. +Sets: &cv-link-LATEX;, &cv-link-LATEXCOM;, &cv-link-LATEXFLAGS;.Uses: &cv-link-LATEXCOMSTR;. ldc - - + Sets construction variables for the D language compiler LDC2. -Sets: &cv-link-DC;, &cv-link-DCOM;, &cv-link-DDEBUG;, &cv-link-DDEBUGPREFIX;, &cv-link-DDEBUGSUFFIX;, &cv-link-DFILESUFFIX;, &cv-link-DFLAGPREFIX;, &cv-link-DFLAGS;, &cv-link-DFLAGSUFFIX;, &cv-link-DINCPREFIX;, &cv-link-DINCSUFFIX;, &cv-link-DLIB;, &cv-link-DLIBCOM;, &cv-link-DLIBDIRPREFIX;, &cv-link-DLIBDIRSUFFIX;, &cv-link-DLIBFLAGPREFIX;, &cv-link-DLIBFLAGSUFFIX;, &cv-link-DLIBLINKPREFIX;, &cv-link-DLIBLINKSUFFIX;, &cv-link-DLINK;, &cv-link-DLINKCOM;, &cv-link-DLINKFLAGPREFIX;, &cv-link-DLINKFLAGS;, &cv-link-DLINKFLAGSUFFIX;, &cv-link-DPATH;, &cv-link-DRPATHPREFIX;, &cv-link-DRPATHSUFFIX;, &cv-link-DShLibSonameGenerator;, &cv-link-DVERPREFIX;, &cv-link-DVERSIONS;, &cv-link-DVERSUFFIX;, &cv-link-SHDC;, &cv-link-SHDCOM;, &cv-link-SHDLIBVERSION;, &cv-link-SHDLIBVERSIONFLAGS;, &cv-link-SHDLINK;, &cv-link-SHDLINKCOM;, &cv-link-SHDLINKFLAGS;. +Sets: &cv-link-DC;, &cv-link-DCOM;, &cv-link-DDEBUG;, &cv-link-DDEBUGPREFIX;, &cv-link-DDEBUGSUFFIX;, &cv-link-DFILESUFFIX;, &cv-link-DFLAGPREFIX;, &cv-link-DFLAGS;, &cv-link-DFLAGSUFFIX;, &cv-link-DINCPREFIX;, &cv-link-DINCSUFFIX;, &cv-link-DLIB;, &cv-link-DLIBCOM;, &cv-link-DLIBDIRPREFIX;, &cv-link-DLIBDIRSUFFIX;, &cv-link-DLIBFLAGPREFIX;, &cv-link-DLIBFLAGSUFFIX;, &cv-link-DLIBLINKPREFIX;, &cv-link-DLIBLINKSUFFIX;, &cv-link-DLINK;, &cv-link-DLINKCOM;, &cv-link-DLINKFLAGPREFIX;, &cv-link-DLINKFLAGS;, &cv-link-DLINKFLAGSUFFIX;, &cv-link-DPATH;, &cv-link-DRPATHPREFIX;, &cv-link-DRPATHSUFFIX;, &cv-link-DShLibSonameGenerator;, &cv-link-DVERPREFIX;, &cv-link-DVERSIONS;, &cv-link-DVERSUFFIX;, &cv-link-SHDC;, &cv-link-SHDCOM;, &cv-link-SHDLIBVERSION;, &cv-link-SHDLIBVERSIONFLAGS;, &cv-link-SHDLINK;, &cv-link-SHDLINKCOM;, &cv-link-SHDLINKFLAGS;. lex - - -Sets construction variables for the lex lexical analyser. + +Sets construction variables for the lex lexical analyser. -Sets: &cv-link-LEX;, &cv-link-LEXCOM;, &cv-link-LEXFLAGS;, &cv-link-LEXUNISTD;.Uses: &cv-link-LEXCOMSTR;. +Sets: &cv-link-LEX;, &cv-link-LEXCOM;, &cv-link-LEXFLAGS;, &cv-link-LEXUNISTD;.Uses: &cv-link-LEXCOMSTR;. link - - + Sets construction variables for generic POSIX linkers. This is a "smart" linker tool which selects a compiler to complete the linking based on the types of source files. -Sets: &cv-link-LDMODULE;, &cv-link-LDMODULECOM;, &cv-link-LDMODULEFLAGS;, &cv-link-LDMODULENOVERSIONSYMLINKS;, &cv-link-LDMODULEPREFIX;, &cv-link-LDMODULESUFFIX;, &cv-link-LDMODULEVERSION;, &cv-link-LDMODULEVERSIONFLAGS;, &cv-link-LIBDIRPREFIX;, &cv-link-LIBDIRSUFFIX;, &cv-link-LIBLINKPREFIX;, &cv-link-LIBLINKSUFFIX;, &cv-link-LINK;, &cv-link-LINKCOM;, &cv-link-LINKFLAGS;, &cv-link-SHLIBSUFFIX;, &cv-link-SHLINK;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;, &cv-link-__LDMODULEVERSIONFLAGS;, &cv-link-__SHLIBVERSIONFLAGS;.Uses: &cv-link-LDMODULECOMSTR;, &cv-link-LINKCOMSTR;, &cv-link-SHLINKCOMSTR;. +Sets: &cv-link-LDMODULE;, &cv-link-LDMODULECOM;, &cv-link-LDMODULEFLAGS;, &cv-link-LDMODULENOVERSIONSYMLINKS;, &cv-link-LDMODULEPREFIX;, &cv-link-LDMODULESUFFIX;, &cv-link-LDMODULEVERSION;, &cv-link-LDMODULEVERSIONFLAGS;, &cv-link-LIBDIRPREFIX;, &cv-link-LIBDIRSUFFIX;, &cv-link-LIBLINKPREFIX;, &cv-link-LIBLINKSUFFIX;, &cv-link-LINK;, &cv-link-LINKCOM;, &cv-link-LINKFLAGS;, &cv-link-SHLIBSUFFIX;, &cv-link-SHLINK;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;, &cv-link-__LDMODULEVERSIONFLAGS;, &cv-link-__SHLIBVERSIONFLAGS;.Uses: &cv-link-LDMODULECOMSTR;, &cv-link-LINKCOMSTR;, &cv-link-SHLINKCOMSTR;. linkloc - - + Sets construction variables for the LinkLoc linker for the Phar Lap ETS embedded operating system. -Sets: &cv-link-LIBDIRPREFIX;, &cv-link-LIBDIRSUFFIX;, &cv-link-LIBLINKPREFIX;, &cv-link-LIBLINKSUFFIX;, &cv-link-LINK;, &cv-link-LINKCOM;, &cv-link-LINKFLAGS;, &cv-link-SHLINK;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;.Uses: &cv-link-LINKCOMSTR;, &cv-link-SHLINKCOMSTR;. +Sets: &cv-link-LIBDIRPREFIX;, &cv-link-LIBDIRSUFFIX;, &cv-link-LIBLINKPREFIX;, &cv-link-LIBLINKSUFFIX;, &cv-link-LINK;, &cv-link-LINKCOM;, &cv-link-LINKFLAGS;, &cv-link-SHLINK;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;.Uses: &cv-link-LINKCOMSTR;, &cv-link-SHLINKCOMSTR;. m4 - - -Sets construction variables for the m4 macro processor. + +Sets construction variables for the m4 macro processor. -Sets: &cv-link-M4;, &cv-link-M4COM;, &cv-link-M4FLAGS;.Uses: &cv-link-M4COMSTR;. +Sets: &cv-link-M4;, &cv-link-M4COM;, &cv-link-M4FLAGS;.Uses: &cv-link-M4COMSTR;. masm - - + Sets construction variables for the Microsoft assembler. -Sets: &cv-link-AS;, &cv-link-ASCOM;, &cv-link-ASFLAGS;, &cv-link-ASPPCOM;, &cv-link-ASPPFLAGS;.Uses: &cv-link-ASCOMSTR;, &cv-link-ASPPCOMSTR;, &cv-link-CPPFLAGS;, &cv-link-_CPPDEFFLAGS;, &cv-link-_CPPINCFLAGS;. +Sets: &cv-link-AS;, &cv-link-ASCOM;, &cv-link-ASFLAGS;, &cv-link-ASPPCOM;, &cv-link-ASPPFLAGS;.Uses: &cv-link-ASCOMSTR;, &cv-link-ASPPCOMSTR;, &cv-link-CPPFLAGS;, &cv-link-_CPPDEFFLAGS;, &cv-link-_CPPINCFLAGS;. midl - - + Sets construction variables for the Microsoft IDL compiler. -Sets: &cv-link-MIDL;, &cv-link-MIDLCOM;, &cv-link-MIDLFLAGS;.Uses: &cv-link-MIDLCOMSTR;. +Sets: &cv-link-MIDL;, &cv-link-MIDLCOM;, &cv-link-MIDLFLAGS;.Uses: &cv-link-MIDLCOMSTR;. mingw - - + Sets construction variables for MinGW (Minimal Gnu on Windows). -Sets: &cv-link-AS;, &cv-link-CC;, &cv-link-CXX;, &cv-link-LDMODULECOM;, &cv-link-LIBPREFIX;, &cv-link-LIBSUFFIX;, &cv-link-OBJSUFFIX;, &cv-link-RC;, &cv-link-RCCOM;, &cv-link-RCFLAGS;, &cv-link-RCINCFLAGS;, &cv-link-RCINCPREFIX;, &cv-link-RCINCSUFFIX;, &cv-link-SHCCFLAGS;, &cv-link-SHCXXFLAGS;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;, &cv-link-SHOBJSUFFIX;, &cv-link-WINDOWSDEFPREFIX;, &cv-link-WINDOWSDEFSUFFIX;.Uses: &cv-link-RCCOMSTR;, &cv-link-SHLINKCOMSTR;. +Sets: &cv-link-AS;, &cv-link-CC;, &cv-link-CXX;, &cv-link-LDMODULECOM;, &cv-link-LIBPREFIX;, &cv-link-LIBSUFFIX;, &cv-link-OBJSUFFIX;, &cv-link-RC;, &cv-link-RCCOM;, &cv-link-RCFLAGS;, &cv-link-RCINCFLAGS;, &cv-link-RCINCPREFIX;, &cv-link-RCINCSUFFIX;, &cv-link-SHCCFLAGS;, &cv-link-SHCXXFLAGS;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;, &cv-link-SHOBJSUFFIX;, &cv-link-WINDOWSDEFPREFIX;, &cv-link-WINDOWSDEFSUFFIX;.Uses: &cv-link-RCCOMSTR;, &cv-link-SHLINKCOMSTR;. msgfmt - - -This scons tool is a part of scons gettext toolset. It provides scons + +This scons tool is a part of scons gettext toolset. It provides scons interface to msgfmt(1) command, which generates binary message catalog (MO) from a textual translation description (PO). -Sets: &cv-link-MOSUFFIX;, &cv-link-MSGFMT;, &cv-link-MSGFMTCOM;, &cv-link-MSGFMTCOMSTR;, &cv-link-MSGFMTFLAGS;, &cv-link-POSUFFIX;.Uses: &cv-link-LINGUAS_FILE;. +Sets: &cv-link-MOSUFFIX;, &cv-link-MSGFMT;, &cv-link-MSGFMTCOM;, &cv-link-MSGFMTCOMSTR;, &cv-link-MSGFMTFLAGS;, &cv-link-POSUFFIX;.Uses: &cv-link-LINGUAS_FILE;. msginit - - -This scons tool is a part of scons gettext toolset. It provides + +This scons tool is a part of scons gettext toolset. It provides scons interface to msginit(1) program, which creates new PO file, initializing the meta information with values from user's environment (or options). -Sets: &cv-link-MSGINIT;, &cv-link-MSGINITCOM;, &cv-link-MSGINITCOMSTR;, &cv-link-MSGINITFLAGS;, &cv-link-POAUTOINIT;, &cv-link-POCREATE_ALIAS;, &cv-link-POSUFFIX;, &cv-link-POTSUFFIX;, &cv-link-_MSGINITLOCALE;.Uses: &cv-link-LINGUAS_FILE;, &cv-link-POAUTOINIT;, &cv-link-POTDOMAIN;. +Sets: &cv-link-MSGINIT;, &cv-link-MSGINITCOM;, &cv-link-MSGINITCOMSTR;, &cv-link-MSGINITFLAGS;, &cv-link-POAUTOINIT;, &cv-link-POCREATE_ALIAS;, &cv-link-POSUFFIX;, &cv-link-POTSUFFIX;, &cv-link-_MSGINITLOCALE;.Uses: &cv-link-LINGUAS_FILE;, &cv-link-POAUTOINIT;, &cv-link-POTDOMAIN;. msgmerge - - -This scons tool is a part of scons gettext toolset. It provides + +This scons tool is a part of scons gettext toolset. It provides scons interface to msgmerge(1) command, which merges two Uniform style .po files together. -Sets: &cv-link-MSGMERGE;, &cv-link-MSGMERGECOM;, &cv-link-MSGMERGECOMSTR;, &cv-link-MSGMERGEFLAGS;, &cv-link-POSUFFIX;, &cv-link-POTSUFFIX;, &cv-link-POUPDATE_ALIAS;.Uses: &cv-link-LINGUAS_FILE;, &cv-link-POAUTOINIT;, &cv-link-POTDOMAIN;. +Sets: &cv-link-MSGMERGE;, &cv-link-MSGMERGECOM;, &cv-link-MSGMERGECOMSTR;, &cv-link-MSGMERGEFLAGS;, &cv-link-POSUFFIX;, &cv-link-POTSUFFIX;, &cv-link-POUPDATE_ALIAS;.Uses: &cv-link-LINGUAS_FILE;, &cv-link-POAUTOINIT;, &cv-link-POTDOMAIN;. mslib - - + Sets construction variables for the Microsoft mslib library archiver. -Sets: &cv-link-AR;, &cv-link-ARCOM;, &cv-link-ARFLAGS;, &cv-link-LIBPREFIX;, &cv-link-LIBSUFFIX;.Uses: &cv-link-ARCOMSTR;. +Sets: &cv-link-AR;, &cv-link-ARCOM;, &cv-link-ARFLAGS;, &cv-link-LIBPREFIX;, &cv-link-LIBSUFFIX;.Uses: &cv-link-ARCOMSTR;. mslink - - + Sets construction variables for the Microsoft linker. -Sets: &cv-link-LDMODULE;, &cv-link-LDMODULECOM;, &cv-link-LDMODULEFLAGS;, &cv-link-LDMODULEPREFIX;, &cv-link-LDMODULESUFFIX;, &cv-link-LIBDIRPREFIX;, &cv-link-LIBDIRSUFFIX;, &cv-link-LIBLINKPREFIX;, &cv-link-LIBLINKSUFFIX;, &cv-link-LINK;, &cv-link-LINKCOM;, &cv-link-LINKFLAGS;, &cv-link-REGSVR;, &cv-link-REGSVRCOM;, &cv-link-REGSVRFLAGS;, &cv-link-SHLINK;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;, &cv-link-WIN32DEFPREFIX;, &cv-link-WIN32DEFSUFFIX;, &cv-link-WIN32EXPPREFIX;, &cv-link-WIN32EXPSUFFIX;, &cv-link-WINDOWSDEFPREFIX;, &cv-link-WINDOWSDEFSUFFIX;, &cv-link-WINDOWSEXPPREFIX;, &cv-link-WINDOWSEXPSUFFIX;, &cv-link-WINDOWSPROGMANIFESTPREFIX;, &cv-link-WINDOWSPROGMANIFESTSUFFIX;, &cv-link-WINDOWSSHLIBMANIFESTPREFIX;, &cv-link-WINDOWSSHLIBMANIFESTSUFFIX;, &cv-link-WINDOWS_INSERT_DEF;.Uses: &cv-link-LDMODULECOMSTR;, &cv-link-LINKCOMSTR;, &cv-link-REGSVRCOMSTR;, &cv-link-SHLINKCOMSTR;. +Sets: &cv-link-LDMODULE;, &cv-link-LDMODULECOM;, &cv-link-LDMODULEFLAGS;, &cv-link-LDMODULEPREFIX;, &cv-link-LDMODULESUFFIX;, &cv-link-LIBDIRPREFIX;, &cv-link-LIBDIRSUFFIX;, &cv-link-LIBLINKPREFIX;, &cv-link-LIBLINKSUFFIX;, &cv-link-LINK;, &cv-link-LINKCOM;, &cv-link-LINKFLAGS;, &cv-link-REGSVR;, &cv-link-REGSVRCOM;, &cv-link-REGSVRFLAGS;, &cv-link-SHLINK;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;, &cv-link-WIN32DEFPREFIX;, &cv-link-WIN32DEFSUFFIX;, &cv-link-WIN32EXPPREFIX;, &cv-link-WIN32EXPSUFFIX;, &cv-link-WINDOWSDEFPREFIX;, &cv-link-WINDOWSDEFSUFFIX;, &cv-link-WINDOWSEXPPREFIX;, &cv-link-WINDOWSEXPSUFFIX;, &cv-link-WINDOWSPROGMANIFESTPREFIX;, &cv-link-WINDOWSPROGMANIFESTSUFFIX;, &cv-link-WINDOWSSHLIBMANIFESTPREFIX;, &cv-link-WINDOWSSHLIBMANIFESTSUFFIX;, &cv-link-WINDOWS_INSERT_DEF;.Uses: &cv-link-LDMODULECOMSTR;, &cv-link-LINKCOMSTR;, &cv-link-REGSVRCOMSTR;, &cv-link-SHLINKCOMSTR;. mssdk - - + Sets variables for Microsoft Platform SDK and/or Windows SDK. Note that unlike most other Tool modules, mssdk does not set construction variables, but sets the environment variables -in the environment SCons uses to execute +in the environment SCons uses to execute the Microsoft toolchain: %INCLUDE%, %LIB%, %LIBPATH% and %PATH%. -Uses: &cv-link-MSSDK_DIR;, &cv-link-MSSDK_VERSION;, &cv-link-MSVS_VERSION;. +Uses: &cv-link-MSSDK_DIR;, &cv-link-MSSDK_VERSION;, &cv-link-MSVS_VERSION;. msvc - - + Sets construction variables for the Microsoft Visual C/C++ compiler. -Sets: &cv-link-BUILDERS;, &cv-link-CC;, &cv-link-CCCOM;, &cv-link-CCFLAGS;, &cv-link-CCPCHFLAGS;, &cv-link-CCPDBFLAGS;, &cv-link-CFILESUFFIX;, &cv-link-CFLAGS;, &cv-link-CPPDEFPREFIX;, &cv-link-CPPDEFSUFFIX;, &cv-link-CXX;, &cv-link-CXXCOM;, &cv-link-CXXFILESUFFIX;, &cv-link-CXXFLAGS;, &cv-link-INCPREFIX;, &cv-link-INCSUFFIX;, &cv-link-OBJPREFIX;, &cv-link-OBJSUFFIX;, &cv-link-PCHCOM;, &cv-link-PCHPDBFLAGS;, &cv-link-RC;, &cv-link-RCCOM;, &cv-link-RCFLAGS;, &cv-link-SHCC;, &cv-link-SHCCCOM;, &cv-link-SHCCFLAGS;, &cv-link-SHCFLAGS;, &cv-link-SHCXX;, &cv-link-SHCXXCOM;, &cv-link-SHCXXFLAGS;, &cv-link-SHOBJPREFIX;, &cv-link-SHOBJSUFFIX;.Uses: &cv-link-CCCOMSTR;, &cv-link-CXXCOMSTR;, &cv-link-PCH;, &cv-link-PCHSTOP;, &cv-link-PDB;, &cv-link-SHCCCOMSTR;, &cv-link-SHCXXCOMSTR;. +Sets: &cv-link-BUILDERS;, &cv-link-CC;, &cv-link-CCCOM;, &cv-link-CCFLAGS;, &cv-link-CCPCHFLAGS;, &cv-link-CCPDBFLAGS;, &cv-link-CFILESUFFIX;, &cv-link-CFLAGS;, &cv-link-CPPDEFPREFIX;, &cv-link-CPPDEFSUFFIX;, &cv-link-CXX;, &cv-link-CXXCOM;, &cv-link-CXXFILESUFFIX;, &cv-link-CXXFLAGS;, &cv-link-INCPREFIX;, &cv-link-INCSUFFIX;, &cv-link-OBJPREFIX;, &cv-link-OBJSUFFIX;, &cv-link-PCHCOM;, &cv-link-PCHPDBFLAGS;, &cv-link-RC;, &cv-link-RCCOM;, &cv-link-RCFLAGS;, &cv-link-SHCC;, &cv-link-SHCCCOM;, &cv-link-SHCCFLAGS;, &cv-link-SHCFLAGS;, &cv-link-SHCXX;, &cv-link-SHCXXCOM;, &cv-link-SHCXXFLAGS;, &cv-link-SHOBJPREFIX;, &cv-link-SHOBJSUFFIX;.Uses: &cv-link-CCCOMSTR;, &cv-link-CXXCOMSTR;, &cv-link-PCH;, &cv-link-PCHSTOP;, &cv-link-PDB;, &cv-link-SHCCCOMSTR;, &cv-link-SHCXXCOMSTR;. msvs - - Sets construction variables for Microsoft Visual Studio. - Sets: &cv-link-MSVSBUILDCOM;, &cv-link-MSVSCLEANCOM;, &cv-link-MSVSENCODING;, &cv-link-MSVSPROJECTCOM;, &cv-link-MSVSREBUILDCOM;, &cv-link-MSVSSCONS;, &cv-link-MSVSSCONSCOM;, &cv-link-MSVSSCONSCRIPT;, &cv-link-MSVSSCONSFLAGS;, &cv-link-MSVSSOLUTIONCOM;. + Sets construction variables for Microsoft Visual Studio. + Sets: &cv-link-MSVSBUILDCOM;, &cv-link-MSVSCLEANCOM;, &cv-link-MSVSENCODING;, &cv-link-MSVSPROJECTCOM;, &cv-link-MSVSREBUILDCOM;, &cv-link-MSVSSCONS;, &cv-link-MSVSSCONSCOM;, &cv-link-MSVSSCONSCRIPT;, &cv-link-MSVSSCONSFLAGS;, &cv-link-MSVSSOLUTIONCOM;. mwcc - - + Sets construction variables for the Metrowerks CodeWarrior compiler. -Sets: &cv-link-CC;, &cv-link-CCCOM;, &cv-link-CFILESUFFIX;, &cv-link-CPPDEFPREFIX;, &cv-link-CPPDEFSUFFIX;, &cv-link-CXX;, &cv-link-CXXCOM;, &cv-link-CXXFILESUFFIX;, &cv-link-INCPREFIX;, &cv-link-INCSUFFIX;, &cv-link-MWCW_VERSION;, &cv-link-MWCW_VERSIONS;, &cv-link-SHCC;, &cv-link-SHCCCOM;, &cv-link-SHCCFLAGS;, &cv-link-SHCFLAGS;, &cv-link-SHCXX;, &cv-link-SHCXXCOM;, &cv-link-SHCXXFLAGS;.Uses: &cv-link-CCCOMSTR;, &cv-link-CXXCOMSTR;, &cv-link-SHCCCOMSTR;, &cv-link-SHCXXCOMSTR;. +Sets: &cv-link-CC;, &cv-link-CCCOM;, &cv-link-CFILESUFFIX;, &cv-link-CPPDEFPREFIX;, &cv-link-CPPDEFSUFFIX;, &cv-link-CXX;, &cv-link-CXXCOM;, &cv-link-CXXFILESUFFIX;, &cv-link-INCPREFIX;, &cv-link-INCSUFFIX;, &cv-link-MWCW_VERSION;, &cv-link-MWCW_VERSIONS;, &cv-link-SHCC;, &cv-link-SHCCCOM;, &cv-link-SHCCFLAGS;, &cv-link-SHCFLAGS;, &cv-link-SHCXX;, &cv-link-SHCXXCOM;, &cv-link-SHCXXFLAGS;.Uses: &cv-link-CCCOMSTR;, &cv-link-CXXCOMSTR;, &cv-link-SHCCCOMSTR;, &cv-link-SHCXXCOMSTR;. mwld - - + Sets construction variables for the Metrowerks CodeWarrior linker. -Sets: &cv-link-AR;, &cv-link-ARCOM;, &cv-link-LIBDIRPREFIX;, &cv-link-LIBDIRSUFFIX;, &cv-link-LIBLINKPREFIX;, &cv-link-LIBLINKSUFFIX;, &cv-link-LINK;, &cv-link-LINKCOM;, &cv-link-SHLINK;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;. +Sets: &cv-link-AR;, &cv-link-ARCOM;, &cv-link-LIBDIRPREFIX;, &cv-link-LIBDIRSUFFIX;, &cv-link-LIBLINKPREFIX;, &cv-link-LIBLINKSUFFIX;, &cv-link-LINK;, &cv-link-LINKCOM;, &cv-link-SHLINK;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;. nasm - - + Sets construction variables for the nasm Netwide Assembler. -Sets: &cv-link-AS;, &cv-link-ASCOM;, &cv-link-ASFLAGS;, &cv-link-ASPPCOM;, &cv-link-ASPPFLAGS;.Uses: &cv-link-ASCOMSTR;, &cv-link-ASPPCOMSTR;. - - - Packaging - - -Sets construction variables for the Package Builder. - - +Sets: &cv-link-AS;, &cv-link-ASCOM;, &cv-link-ASFLAGS;, &cv-link-ASPPCOM;, &cv-link-ASPPFLAGS;.Uses: &cv-link-ASCOMSTR;, &cv-link-ASPPCOMSTR;. packaging - - + A framework for building binary and source packages. + + Packaging + +Sets construction variables for the Package Builder. + + + pdf - - + Sets construction variables for the Portable Document Format builder. -Sets: &cv-link-PDFPREFIX;, &cv-link-PDFSUFFIX;. +Sets: &cv-link-PDFPREFIX;, &cv-link-PDFSUFFIX;. pdflatex - - -Sets construction variables for the pdflatex utility. + +Sets construction variables for the pdflatex utility. -Sets: &cv-link-LATEXRETRIES;, &cv-link-PDFLATEX;, &cv-link-PDFLATEXCOM;, &cv-link-PDFLATEXFLAGS;.Uses: &cv-link-PDFLATEXCOMSTR;. +Sets: &cv-link-LATEXRETRIES;, &cv-link-PDFLATEX;, &cv-link-PDFLATEXCOM;, &cv-link-PDFLATEXFLAGS;.Uses: &cv-link-PDFLATEXCOMSTR;. pdftex - - -Sets construction variables for the pdftex utility. + +Sets construction variables for the pdftex utility. -Sets: &cv-link-LATEXRETRIES;, &cv-link-PDFLATEX;, &cv-link-PDFLATEXCOM;, &cv-link-PDFLATEXFLAGS;, &cv-link-PDFTEX;, &cv-link-PDFTEXCOM;, &cv-link-PDFTEXFLAGS;.Uses: &cv-link-PDFLATEXCOMSTR;, &cv-link-PDFTEXCOMSTR;. +Sets: &cv-link-LATEXRETRIES;, &cv-link-PDFLATEX;, &cv-link-PDFLATEXCOM;, &cv-link-PDFLATEXFLAGS;, &cv-link-PDFTEX;, &cv-link-PDFTEXCOM;, &cv-link-PDFTEXFLAGS;.Uses: &cv-link-PDFLATEXCOMSTR;, &cv-link-PDFTEXCOMSTR;. qt - - + Sets construction variables for building Qt applications. -Sets: &cv-link-QTDIR;, &cv-link-QT_AUTOSCAN;, &cv-link-QT_BINPATH;, &cv-link-QT_CPPPATH;, &cv-link-QT_LIB;, &cv-link-QT_LIBPATH;, &cv-link-QT_MOC;, &cv-link-QT_MOCCXXPREFIX;, &cv-link-QT_MOCCXXSUFFIX;, &cv-link-QT_MOCFROMCXXCOM;, &cv-link-QT_MOCFROMCXXFLAGS;, &cv-link-QT_MOCFROMHCOM;, &cv-link-QT_MOCFROMHFLAGS;, &cv-link-QT_MOCHPREFIX;, &cv-link-QT_MOCHSUFFIX;, &cv-link-QT_UIC;, &cv-link-QT_UICCOM;, &cv-link-QT_UICDECLFLAGS;, &cv-link-QT_UICDECLPREFIX;, &cv-link-QT_UICDECLSUFFIX;, &cv-link-QT_UICIMPLFLAGS;, &cv-link-QT_UICIMPLPREFIX;, &cv-link-QT_UICIMPLSUFFIX;, &cv-link-QT_UISUFFIX;. +Sets: &cv-link-QTDIR;, &cv-link-QT_AUTOSCAN;, &cv-link-QT_BINPATH;, &cv-link-QT_CPPPATH;, &cv-link-QT_LIB;, &cv-link-QT_LIBPATH;, &cv-link-QT_MOC;, &cv-link-QT_MOCCXXPREFIX;, &cv-link-QT_MOCCXXSUFFIX;, &cv-link-QT_MOCFROMCXXCOM;, &cv-link-QT_MOCFROMCXXFLAGS;, &cv-link-QT_MOCFROMHCOM;, &cv-link-QT_MOCFROMHFLAGS;, &cv-link-QT_MOCHPREFIX;, &cv-link-QT_MOCHSUFFIX;, &cv-link-QT_UIC;, &cv-link-QT_UICCOM;, &cv-link-QT_UICDECLFLAGS;, &cv-link-QT_UICDECLPREFIX;, &cv-link-QT_UICDECLSUFFIX;, &cv-link-QT_UICIMPLFLAGS;, &cv-link-QT_UICIMPLPREFIX;, &cv-link-QT_UICIMPLSUFFIX;, &cv-link-QT_UISUFFIX;. rmic - - -Sets construction variables for the rmic utility. + +Sets construction variables for the rmic utility. -Sets: &cv-link-JAVACLASSSUFFIX;, &cv-link-RMIC;, &cv-link-RMICCOM;, &cv-link-RMICFLAGS;.Uses: &cv-link-RMICCOMSTR;. +Sets: &cv-link-JAVACLASSSUFFIX;, &cv-link-RMIC;, &cv-link-RMICCOM;, &cv-link-RMICFLAGS;.Uses: &cv-link-RMICCOMSTR;. rpcgen - - + Sets construction variables for building with RPCGEN. -Sets: &cv-link-RPCGEN;, &cv-link-RPCGENCLIENTFLAGS;, &cv-link-RPCGENFLAGS;, &cv-link-RPCGENHEADERFLAGS;, &cv-link-RPCGENSERVICEFLAGS;, &cv-link-RPCGENXDRFLAGS;. +Sets: &cv-link-RPCGEN;, &cv-link-RPCGENCLIENTFLAGS;, &cv-link-RPCGENFLAGS;, &cv-link-RPCGENHEADERFLAGS;, &cv-link-RPCGENSERVICEFLAGS;, &cv-link-RPCGENXDRFLAGS;. sgiar - - + Sets construction variables for the SGI library archiver. -Sets: &cv-link-AR;, &cv-link-ARCOMSTR;, &cv-link-ARFLAGS;, &cv-link-LIBPREFIX;, &cv-link-LIBSUFFIX;, &cv-link-SHLINK;, &cv-link-SHLINKFLAGS;.Uses: &cv-link-ARCOMSTR;, &cv-link-SHLINKCOMSTR;. +Sets: &cv-link-AR;, &cv-link-ARCOMSTR;, &cv-link-ARFLAGS;, &cv-link-LIBPREFIX;, &cv-link-LIBSUFFIX;, &cv-link-SHLINK;, &cv-link-SHLINKFLAGS;.Uses: &cv-link-ARCOMSTR;, &cv-link-SHLINKCOMSTR;. sgic++ - - + Sets construction variables for the SGI C++ compiler. -Sets: &cv-link-CXX;, &cv-link-CXXFLAGS;, &cv-link-SHCXX;, &cv-link-SHOBJSUFFIX;. +Sets: &cv-link-CXX;, &cv-link-CXXFLAGS;, &cv-link-SHCXX;, &cv-link-SHOBJSUFFIX;. sgicc - - + Sets construction variables for the SGI C compiler. -Sets: &cv-link-CXX;, &cv-link-SHOBJSUFFIX;. +Sets: &cv-link-CXX;, &cv-link-SHOBJSUFFIX;. sgilink - - + Sets construction variables for the SGI linker. -Sets: &cv-link-LINK;, &cv-link-RPATHPREFIX;, &cv-link-RPATHSUFFIX;, &cv-link-SHLINKFLAGS;. +Sets: &cv-link-LINK;, &cv-link-RPATHPREFIX;, &cv-link-RPATHSUFFIX;, &cv-link-SHLINKFLAGS;. sunar - - + Sets construction variables for the Sun library archiver. -Sets: &cv-link-AR;, &cv-link-ARCOM;, &cv-link-ARFLAGS;, &cv-link-LIBPREFIX;, &cv-link-LIBSUFFIX;.Uses: &cv-link-ARCOMSTR;. +Sets: &cv-link-AR;, &cv-link-ARCOM;, &cv-link-ARFLAGS;, &cv-link-LIBPREFIX;, &cv-link-LIBSUFFIX;.Uses: &cv-link-ARCOMSTR;. sunc++ - - + Sets construction variables for the Sun C++ compiler. -Sets: &cv-link-CXX;, &cv-link-CXXVERSION;, &cv-link-SHCXX;, &cv-link-SHCXXFLAGS;, &cv-link-SHOBJPREFIX;, &cv-link-SHOBJSUFFIX;. +Sets: &cv-link-CXX;, &cv-link-CXXVERSION;, &cv-link-SHCXX;, &cv-link-SHCXXFLAGS;, &cv-link-SHOBJPREFIX;, &cv-link-SHOBJSUFFIX;. suncc - - + Sets construction variables for the Sun C compiler. -Sets: &cv-link-CXX;, &cv-link-SHCCFLAGS;, &cv-link-SHOBJPREFIX;, &cv-link-SHOBJSUFFIX;. +Sets: &cv-link-CXX;, &cv-link-SHCCFLAGS;, &cv-link-SHOBJPREFIX;, &cv-link-SHOBJSUFFIX;. sunf77 - - -Set construction variables for the Sun f77 Fortran compiler. + +Set construction variables for the Sun f77 Fortran compiler. -Sets: &cv-link-F77;, &cv-link-FORTRAN;, &cv-link-SHF77;, &cv-link-SHF77FLAGS;, &cv-link-SHFORTRAN;, &cv-link-SHFORTRANFLAGS;. +Sets: &cv-link-F77;, &cv-link-FORTRAN;, &cv-link-SHF77;, &cv-link-SHF77FLAGS;, &cv-link-SHFORTRAN;, &cv-link-SHFORTRANFLAGS;. sunf90 - - -Set construction variables for the Sun f90 Fortran compiler. + +Set construction variables for the Sun f90 Fortran compiler. -Sets: &cv-link-F90;, &cv-link-FORTRAN;, &cv-link-SHF90;, &cv-link-SHF90FLAGS;, &cv-link-SHFORTRAN;, &cv-link-SHFORTRANFLAGS;. +Sets: &cv-link-F90;, &cv-link-FORTRAN;, &cv-link-SHF90;, &cv-link-SHF90FLAGS;, &cv-link-SHFORTRAN;, &cv-link-SHFORTRANFLAGS;. sunf95 - - -Set construction variables for the Sun f95 Fortran compiler. + +Set construction variables for the Sun f95 Fortran compiler. -Sets: &cv-link-F95;, &cv-link-FORTRAN;, &cv-link-SHF95;, &cv-link-SHF95FLAGS;, &cv-link-SHFORTRAN;, &cv-link-SHFORTRANFLAGS;. +Sets: &cv-link-F95;, &cv-link-FORTRAN;, &cv-link-SHF95;, &cv-link-SHF95FLAGS;, &cv-link-SHFORTRAN;, &cv-link-SHFORTRANFLAGS;. sunlink - - + Sets construction variables for the Sun linker. -Sets: &cv-link-RPATHPREFIX;, &cv-link-RPATHSUFFIX;, &cv-link-SHLINKFLAGS;. +Sets: &cv-link-RPATHPREFIX;, &cv-link-RPATHSUFFIX;, &cv-link-SHLINKFLAGS;. swig - - + Sets construction variables for the SWIG interface generator. -Sets: &cv-link-SWIG;, &cv-link-SWIGCFILESUFFIX;, &cv-link-SWIGCOM;, &cv-link-SWIGCXXFILESUFFIX;, &cv-link-SWIGDIRECTORSUFFIX;, &cv-link-SWIGFLAGS;, &cv-link-SWIGINCPREFIX;, &cv-link-SWIGINCSUFFIX;, &cv-link-SWIGPATH;, &cv-link-SWIGVERSION;, &cv-link-_SWIGINCFLAGS;.Uses: &cv-link-SWIGCOMSTR;. +Sets: &cv-link-SWIG;, &cv-link-SWIGCFILESUFFIX;, &cv-link-SWIGCOM;, &cv-link-SWIGCXXFILESUFFIX;, &cv-link-SWIGDIRECTORSUFFIX;, &cv-link-SWIGFLAGS;, &cv-link-SWIGINCPREFIX;, &cv-link-SWIGINCSUFFIX;, &cv-link-SWIGPATH;, &cv-link-SWIGVERSION;, &cv-link-_SWIGINCFLAGS;.Uses: &cv-link-SWIGCOMSTR;. tar - - -Sets construction variables for the tar archiver. + +Sets construction variables for the tar archiver. -Sets: &cv-link-TAR;, &cv-link-TARCOM;, &cv-link-TARFLAGS;, &cv-link-TARSUFFIX;.Uses: &cv-link-TARCOMSTR;. +Sets: &cv-link-TAR;, &cv-link-TARCOM;, &cv-link-TARFLAGS;, &cv-link-TARSUFFIX;.Uses: &cv-link-TARCOMSTR;. tex - - + Sets construction variables for the TeX formatter and typesetter. -Sets: &cv-link-BIBTEX;, &cv-link-BIBTEXCOM;, &cv-link-BIBTEXFLAGS;, &cv-link-LATEX;, &cv-link-LATEXCOM;, &cv-link-LATEXFLAGS;, &cv-link-MAKEINDEX;, &cv-link-MAKEINDEXCOM;, &cv-link-MAKEINDEXFLAGS;, &cv-link-TEX;, &cv-link-TEXCOM;, &cv-link-TEXFLAGS;.Uses: &cv-link-BIBTEXCOMSTR;, &cv-link-LATEXCOMSTR;, &cv-link-MAKEINDEXCOMSTR;, &cv-link-TEXCOMSTR;. +Sets: &cv-link-BIBTEX;, &cv-link-BIBTEXCOM;, &cv-link-BIBTEXFLAGS;, &cv-link-LATEX;, &cv-link-LATEXCOM;, &cv-link-LATEXFLAGS;, &cv-link-MAKEINDEX;, &cv-link-MAKEINDEXCOM;, &cv-link-MAKEINDEXFLAGS;, &cv-link-TEX;, &cv-link-TEXCOM;, &cv-link-TEXFLAGS;.Uses: &cv-link-BIBTEXCOMSTR;, &cv-link-LATEXCOMSTR;, &cv-link-MAKEINDEXCOMSTR;, &cv-link-TEXCOMSTR;. textfile - - -Set construction variables for the Textfile and Substfile builders. + +Set construction variables for the Textfile and Substfile builders. -Sets: &cv-link-LINESEPARATOR;, &cv-link-SUBSTFILEPREFIX;, &cv-link-SUBSTFILESUFFIX;, &cv-link-TEXTFILEPREFIX;, &cv-link-TEXTFILESUFFIX;.Uses: &cv-link-SUBST_DICT;. +Sets: &cv-link-LINESEPARATOR;, &cv-link-SUBSTFILEPREFIX;, &cv-link-SUBSTFILESUFFIX;, &cv-link-TEXTFILEPREFIX;, &cv-link-TEXTFILESUFFIX;.Uses: &cv-link-SUBST_DICT;. tlib - - + Sets construction variables for the Borlan tib library archiver. -Sets: &cv-link-AR;, &cv-link-ARCOM;, &cv-link-ARFLAGS;, &cv-link-LIBPREFIX;, &cv-link-LIBSUFFIX;.Uses: &cv-link-ARCOMSTR;. +Sets: &cv-link-AR;, &cv-link-ARCOM;, &cv-link-ARFLAGS;, &cv-link-LIBPREFIX;, &cv-link-LIBSUFFIX;.Uses: &cv-link-ARCOMSTR;. xgettext - - -This scons tool is a part of scons gettext toolset. It provides + +This scons tool is a part of scons gettext toolset. It provides scons interface to xgettext(1) program, which extracts internationalized messages from source code. The tool -provides POTUpdate builder to make PO +provides POTUpdate builder to make PO Template files. -Sets: &cv-link-POTSUFFIX;, &cv-link-POTUPDATE_ALIAS;, &cv-link-XGETTEXTCOM;, &cv-link-XGETTEXTCOMSTR;, &cv-link-XGETTEXTFLAGS;, &cv-link-XGETTEXTFROM;, &cv-link-XGETTEXTFROMPREFIX;, &cv-link-XGETTEXTFROMSUFFIX;, &cv-link-XGETTEXTPATH;, &cv-link-XGETTEXTPATHPREFIX;, &cv-link-XGETTEXTPATHSUFFIX;, &cv-link-_XGETTEXTDOMAIN;, &cv-link-_XGETTEXTFROMFLAGS;, &cv-link-_XGETTEXTPATHFLAGS;.Uses: &cv-link-POTDOMAIN;. +Sets: &cv-link-POTSUFFIX;, &cv-link-POTUPDATE_ALIAS;, &cv-link-XGETTEXTCOM;, &cv-link-XGETTEXTCOMSTR;, &cv-link-XGETTEXTFLAGS;, &cv-link-XGETTEXTFROM;, &cv-link-XGETTEXTFROMPREFIX;, &cv-link-XGETTEXTFROMSUFFIX;, &cv-link-XGETTEXTPATH;, &cv-link-XGETTEXTPATHPREFIX;, &cv-link-XGETTEXTPATHSUFFIX;, &cv-link-_XGETTEXTDOMAIN;, &cv-link-_XGETTEXTFROMFLAGS;, &cv-link-_XGETTEXTPATHFLAGS;.Uses: &cv-link-POTDOMAIN;. yacc - - -Sets construction variables for the yacc parse generator. + +Sets construction variables for the yacc parse generator. -Sets: &cv-link-YACC;, &cv-link-YACCCOM;, &cv-link-YACCFLAGS;, &cv-link-YACCHFILESUFFIX;, &cv-link-YACCHXXFILESUFFIX;, &cv-link-YACCVCGFILESUFFIX;.Uses: &cv-link-YACCCOMSTR;. +Sets: &cv-link-YACC;, &cv-link-YACCCOM;, &cv-link-YACCFLAGS;, &cv-link-YACCHFILESUFFIX;, &cv-link-YACCHXXFILESUFFIX;, &cv-link-YACCVCGFILESUFFIX;.Uses: &cv-link-YACCCOMSTR;. zip - - -Sets construction variables for the zip archiver. + +Sets construction variables for the zip archiver. -Sets: &cv-link-ZIP;, &cv-link-ZIPCOM;, &cv-link-ZIPCOMPRESSION;, &cv-link-ZIPFLAGS;, &cv-link-ZIPSUFFIX;.Uses: &cv-link-ZIPCOMSTR;. +Sets: &cv-link-ZIP;, &cv-link-ZIPCOM;, &cv-link-ZIPCOMPRESSION;, &cv-link-ZIPFLAGS;, &cv-link-ZIPSUFFIX;.Uses: &cv-link-ZIPCOMSTR;. diff --git a/doc/generated/tools.mod b/doc/generated/tools.mod index 1209d74..f9bc1d7 100644 --- a/doc/generated/tools.mod +++ b/doc/generated/tools.mod @@ -78,8 +78,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. mwcc"> mwld"> nasm"> -Packaging"> packaging"> +Packaging"> pdf"> pdflatex"> pdftex"> @@ -186,8 +186,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. mwcc"> mwld"> nasm"> -Packaging"> packaging"> +Packaging"> pdf"> pdflatex"> pdftex"> diff --git a/doc/generated/variables.gen b/doc/generated/variables.gen index 8f09512..db4c416 100644 --- a/doc/generated/variables.gen +++ b/doc/generated/variables.gen @@ -1,4 +1,3 @@ - %scons; @@ -12,125 +11,115 @@ %variables-mod; ]> - + __LDMODULEVERSIONFLAGS - - -This construction variable automatically introduces $_LDMODULEVERSIONFLAGS -if $LDMODULEVERSION is set. Othervise it evaluates to an empty string. + +This construction variable automatically introduces $_LDMODULEVERSIONFLAGS +if $LDMODULEVERSION is set. Othervise it evaluates to an empty string. __SHLIBVERSIONFLAGS - - -This construction variable automatically introduces $_SHLIBVERSIONFLAGS -if $SHLIBVERSION is set. Othervise it evaluates to an empty string. + +This construction variable automatically introduces $_SHLIBVERSIONFLAGS +if $SHLIBVERSION is set. Othervise it evaluates to an empty string. - - _APPLELINK_COMPATIBILITY_VERSION - - - A macro (by default a generator function) used to create the linker flags to specify - apple's linker's -compatibility_version flag. - The default generator uses $APPLELINK_COMPATIBILITY_VERSION - and $APPLELINK_NO_COMPATIBILITY_VERSION and $SHLIBVERSION - to determine the correct flag. - - - APPLELINK_COMPATIBILITY_VERSION - - + On Mac OS X this is used to set the linker flag: -compatibility_version - + The value is specified as X[.Y[.Z]] where X is between 1 and 65535, Y can be omitted or between 1 and - 255, Z can be omitted or between 1 and 255. This value will be derived from $SHLIBVERSION if + 255, Z can be omitted or between 1 and 255. This value will be derived from $SHLIBVERSION if not specified. The lowest digit will be dropped and replaced by a 0. - - If the $APPLELINK_NO_COMPATIBILITY_VERSION is set then no -compatibility_version will be + + If the $APPLELINK_NO_COMPATIBILITY_VERSION is set then no -compatibility_version will be output. - See MacOS's ld manpage for more details + See MacOS's ld manpage for more details - - _APPLELINK_CURRENT_VERSION - - - A macro (by default a generator function) used to create the linker flags to specify apple's linker's - -current_version flag. The default generator uses $APPLELINK_CURRENT_VERSION and - $APPLELINK_NO_CURRENT_VERSION and $SHLIBVERSION to determine the correct flag. + + _APPLELINK_COMPATIBILITY_VERSION + + A macro (by default a generator function) used to create the linker flags to specify + apple's linker's -compatibility_version flag. + The default generator uses $APPLELINK_COMPATIBILITY_VERSION + and $APPLELINK_NO_COMPATIBILITY_VERSION and $SHLIBVERSION + to determine the correct flag. APPLELINK_CURRENT_VERSION - - + On Mac OS X this is used to set the linker flag: -current_version - + The value is specified as X[.Y[.Z]] where X is between 1 and 65535, Y can be omitted or between 1 and - 255, Z can be omitted or between 1 and 255. This value will be set to $SHLIBVERSION if not + 255, Z can be omitted or between 1 and 255. This value will be set to $SHLIBVERSION if not specified. - - If the $APPLELINK_NO_CURRENT_VERSION is set then no -current_version will be + + If the $APPLELINK_NO_CURRENT_VERSION is set then no -current_version will be output. - See MacOS's ld manpage for more details + See MacOS's ld manpage for more details + + _APPLELINK_CURRENT_VERSION + + A macro (by default a generator function) used to create the linker flags to specify apple's linker's + -current_version flag. The default generator uses $APPLELINK_CURRENT_VERSION and + $APPLELINK_NO_CURRENT_VERSION and $SHLIBVERSION to determine the correct flag. + + + APPLELINK_NO_COMPATIBILITY_VERSION - - + Set this to any True (1|True|non-empty string) value to disable adding -compatibility_version flag when generating versioned shared libraries. - - This overrides $APPLELINK_COMPATIBILITY_VERSION. + + This overrides $APPLELINK_COMPATIBILITY_VERSION. APPLELINK_NO_CURRENT_VERSION - - + Set this to any True (1|True|non-empty string) value to disable adding -current_version flag when generating versioned shared libraries. - - This overrides $APPLELINK_CURRENT_VERSION. + + This overrides $APPLELINK_CURRENT_VERSION. AR - - + The static library archiver. ARCHITECTURE - - + Specifies the system architecture for which the package is being built. The default is the system architecture @@ -147,46 +136,41 @@ as well as forming part of the name of a generated RPM package file. ARCOM - - + The command line used to generate a static library from object files. ARCOMSTR - - + The string displayed when an object file is generated from an assembly-language source file. -If this is not set, then $ARCOM (the command line) is displayed. +If this is not set, then $ARCOM (the command line) is displayed. - + env = Environment(ARCOMSTR = "Archiving $TARGET") ARFLAGS - - + General options passed to the static library archiver. AS - - + The assembler. ASCOM - - + The command line used to generate an object file from an assembly-language source file. @@ -194,69 +178,63 @@ from an assembly-language source file. ASCOMSTR - - + The string displayed when an object file is generated from an assembly-language source file. -If this is not set, then $ASCOM (the command line) is displayed. +If this is not set, then $ASCOM (the command line) is displayed. - + env = Environment(ASCOMSTR = "Assembling $TARGET") ASFLAGS - - + General options passed to the assembler. ASPPCOM - - + The command line used to assemble an assembly-language source file into an object file after first running the file through the C preprocessor. Any options specified -in the $ASFLAGS and $CPPFLAGS construction variables +in the $ASFLAGS and $CPPFLAGS construction variables are included on this command line. ASPPCOMSTR - - + The string displayed when an object file is generated from an assembly-language source file after first running the file through the C preprocessor. -If this is not set, then $ASPPCOM (the command line) is displayed. +If this is not set, then $ASPPCOM (the command line) is displayed. - + env = Environment(ASPPCOMSTR = "Assembling $TARGET") ASPPFLAGS - - + General options when an assembling an assembly-language source file into an object file after first running the file through the C preprocessor. -The default is to use the value of $ASFLAGS. +The default is to use the value of $ASFLAGS. BIBTEX - - + The bibliography generator for the TeX formatter and typesetter and the LaTeX structured formatter and typesetter. @@ -264,8 +242,7 @@ LaTeX structured formatter and typesetter. BIBTEXCOM - - + The command line used to call the bibliography generator for the TeX formatter and typesetter and the LaTeX structured formatter and typesetter. @@ -274,22 +251,20 @@ typesetter. BIBTEXCOMSTR - - + The string displayed when generating a bibliography for TeX or LaTeX. -If this is not set, then $BIBTEXCOM (the command line) is displayed. +If this is not set, then $BIBTEXCOM (the command line) is displayed. - + env = Environment(BIBTEXCOMSTR = "Generating bibliography $TARGET") BIBTEXFLAGS - - + General options passed to the bibliography generator for the TeX formatter and typesetter and the LaTeX structured formatter and typesetter. @@ -297,8 +272,7 @@ and typesetter and the LaTeX structured formatter and typesetter. BUILDERS - - + A dictionary mapping the names of the builders available through this environment to underlying Builder objects. @@ -309,26 +283,26 @@ If you initialize this variable when an Environment is created: - + env = Environment(BUILDERS = {'NewBuilder' : foo}) - + the default Builders will no longer be available. To use a new Builder object in addition to the default Builders, add your new Builder object like this: - + env = Environment() env.Append(BUILDERS = {'NewBuilder' : foo}) - + or this: - + env = Environment() env['BUILDERS']['NewBuilder'] = foo @@ -336,70 +310,64 @@ env['BUILDERS']['NewBuilder'] = foo CC - - + The C compiler. CCCOM - - + The command line used to compile a C source file to a (static) object -file. Any options specified in the $CFLAGS, $CCFLAGS and -$CPPFLAGS construction variables are included on this command +file. Any options specified in the $CFLAGS, $CCFLAGS and +$CPPFLAGS construction variables are included on this command line. CCCOMSTR - - + The string displayed when a C source file is compiled to a (static) object file. -If this is not set, then $CCCOM (the command line) is displayed. +If this is not set, then $CCCOM (the command line) is displayed. - + env = Environment(CCCOMSTR = "Compiling static object $TARGET") CCFLAGS - - + General options that are passed to the C and C++ compilers. CCPCHFLAGS - - + Options added to the compiler command line to support building with precompiled headers. The default value expands expands to the appropriate Microsoft Visual C++ command-line options -when the $PCH construction variable is set. +when the $PCH construction variable is set. CCPDBFLAGS - - + Options added to the compiler command line to support storing debugging information in a Microsoft Visual C++ PDB file. The default value expands expands to appropriate Microsoft Visual C++ command-line options -when the $PDB construction variable is set. +when the $PDB construction variable is set. - + The Visual C++ compiler option that SCons uses by default to generate PDB information is . This works correctly with parallel () builds @@ -412,31 +380,30 @@ link-time performance, although parallel builds will no longer work. - + You can generate PDB files with the -switch by overriding the default $CCPDBFLAGS variable as follows: +switch by overriding the default $CCPDBFLAGS variable as follows: - + env['CCPDBFLAGS'] = ['${(PDB and "/Zi /Fd%s" % File(PDB)) or ""}'] - + An alternative would be to use the to put the debugging information in a separate .pdb file for each object file by overriding -the $CCPDBFLAGS variable as follows: +the $CCPDBFLAGS variable as follows: - + env['CCPDBFLAGS'] = '/Zi /Fd${TARGET}.pdb' CCVERSION - - + The version number of the C compiler. This may or may not be set, depending on the specific C compiler being used. @@ -445,8 +412,7 @@ depending on the specific C compiler being used. CFILESUFFIX - - + The suffix for C source files. This is used by the internal CFile builder when generating C files from Lex (.l) or YACC (.y) input files. @@ -463,16 +429,14 @@ as C files. CFLAGS - - + General options that are passed to the C compiler (C only; not C++). CHANGE_SPECFILE - - + A hook for modifying the file that controls the packaging build (the .spec for RPM, the control for Ipkg, @@ -484,28 +448,27 @@ after the SCons template for the file has been written. CHANGED_SOURCES - - + A reserved variable name that may not be set or used in a construction environment. -(See "Variable Substitution," below.) +(See the manpage section "Variable Substitution" +for more information). CHANGED_TARGETS - - + A reserved variable name that may not be set or used in a construction environment. -(See "Variable Substitution," below.) +(See the manpage section "Variable Substitution" +for more information). CHANGELOG - - + The name of a file containing the change log text to be included in the package. This is included as the @@ -517,9 +480,8 @@ section of the RPM _concat - - -A function used to produce variables like $_CPPINCFLAGS. It takes + +A function used to produce variables like $_CPPINCFLAGS. It takes four or five arguments: a prefix to concatenate onto each element, a list of elements, a suffix to concatenate onto each element, an environment @@ -527,15 +489,14 @@ for variable interpolation, and an optional function that will be called to transform the list before concatenation. - + env['_CPPINCFLAGS'] = '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs)} $)', CONFIGUREDIR - - + The name of the directory in which Configure context test files are written. The default is @@ -549,8 +510,7 @@ file. CONFIGURELOG - - + The name of the Configure context log file. The default is config.log @@ -563,50 +523,48 @@ file. _CPPDEFFLAGS - - + An automatically-generated construction variable containing the C preprocessor command-line options to define values. -The value of $_CPPDEFFLAGS is created +The value of $_CPPDEFFLAGS is created by respectively prepending and appending -$CPPDEFPREFIX and $CPPDEFSUFFIX +$CPPDEFPREFIX and $CPPDEFSUFFIX to the beginning and end -of each definition in $CPPDEFINES. +of each definition in $CPPDEFINES. CPPDEFINES - - + A platform independent specification of C preprocessor definitions. The definitions will be added to command lines through the automatically-generated -$_CPPDEFFLAGS construction variable (see above), +$_CPPDEFFLAGS construction variable (see above), which is constructed according to -the type of value of $CPPDEFINES: +the type of value of $CPPDEFINES: - -If $CPPDEFINES is a string, + +If $CPPDEFINES is a string, the values of the -$CPPDEFPREFIX and $CPPDEFSUFFIX +$CPPDEFPREFIX and $CPPDEFSUFFIX construction variables will be respectively prepended and appended to the beginning and end -of each definition in $CPPDEFINES. +of each definition in $CPPDEFINES. - + # Will add -Dxyz to POSIX compiler command lines, # and /Dxyz to Microsoft Visual C++ command lines. env = Environment(CPPDEFINES='xyz') - -If $CPPDEFINES is a list, + +If $CPPDEFINES is a list, the values of the -$CPPDEFPREFIX and $CPPDEFSUFFIX +$CPPDEFPREFIX and $CPPDEFSUFFIX construction variables will be respectively prepended and appended to the beginning and end of each element in the list. @@ -615,16 +573,16 @@ then the first item is the name being defined and the second item is its value: - + # Will add -DB=2 -DA to POSIX compiler command lines, # and /DB=2 /DA to Microsoft Visual C++ command lines. env = Environment(CPPDEFINES=[('B', 2), 'A']) - -If $CPPDEFINES is a dictionary, + +If $CPPDEFINES is a dictionary, the values of the -$CPPDEFPREFIX and $CPPDEFSUFFIX +$CPPDEFPREFIX and $CPPDEFSUFFIX construction variables will be respectively prepended and appended to the beginning and end of each item from the dictionary. @@ -637,11 +595,11 @@ then the name is defined without an explicit value. Note that the resulting flags are sorted by keyword to ensure that the order of the options on the command line is consistent each time -scons +scons is run. - + # Will add -DA -DB=2 to POSIX compiler command lines, # and /DA /DB=2 to Microsoft Visual C++ command lines. env = Environment(CPPDEFINES={'B':2, 'A':None}) @@ -650,45 +608,42 @@ env = Environment(CPPDEFINES={'B':2, 'A':None}) CPPDEFPREFIX - - + The prefix used to specify preprocessor definitions on the C compiler command line. This will be prepended to the beginning of each definition -in the $CPPDEFINES construction variable -when the $_CPPDEFFLAGS variable is automatically generated. +in the $CPPDEFINES construction variable +when the $_CPPDEFFLAGS variable is automatically generated. CPPDEFSUFFIX - - + The suffix used to specify preprocessor definitions on the C compiler command line. This will be appended to the end of each definition -in the $CPPDEFINES construction variable -when the $_CPPDEFFLAGS variable is automatically generated. +in the $CPPDEFINES construction variable +when the $_CPPDEFFLAGS variable is automatically generated. CPPFLAGS - - + User-specified C preprocessor options. These will be included in any command that uses the C preprocessor, including not just compilation of C and C++ source files -via the $CCCOM, -$SHCCCOM, -$CXXCOM and -$SHCXXCOM command lines, -but also the $FORTRANPPCOM, -$SHFORTRANPPCOM, -$F77PPCOM and -$SHF77PPCOM command lines +via the $CCCOM, +$SHCCCOM, +$CXXCOM and +$SHCXXCOM command lines, +but also the $FORTRANPPCOM, +$SHFORTRANPPCOM, +$F77PPCOM and +$SHF77PPCOM command lines used to compile a Fortran source file, -and the $ASPPCOM command line +and the $ASPPCOM command line used to assemble an assembly language source file, after first running each file through the C preprocessor. Note that this variable does @@ -696,30 +651,28 @@ Note that this variable does contain (or similar) include search path options -that scons generates automatically from $CPPPATH. -See $_CPPINCFLAGS, below, +that scons generates automatically from $CPPPATH. +See $_CPPINCFLAGS, below, for the variable that expands to those options. _CPPINCFLAGS - - + An automatically-generated construction variable containing the C preprocessor command-line options for specifying directories to be searched for include files. -The value of $_CPPINCFLAGS is created -by respectively prepending and appending $INCPREFIX and $INCSUFFIX +The value of $_CPPINCFLAGS is created +by respectively prepending and appending $INCPREFIX and $INCSUFFIX to the beginning and end -of each directory in $CPPPATH. +of each directory in $CPPPATH. CPPPATH - - + The list of directories that the C preprocessor will search for include directories. The C/C++ implicit dependency scanner will search these directories for include files. Don't explicitly put include directory @@ -727,57 +680,56 @@ arguments in CCFLAGS or CXXFLAGS because the result will be non-portable and the directories will not be searched by the dependency scanner. Note: directory names in CPPPATH will be looked-up relative to the SConscript directory when they are used in a command. To force -scons +scons to look-up a directory relative to the root of the source tree use #: - + env = Environment(CPPPATH='#/include') - + The directory look-up can also be forced using the -Dir() +Dir() function: - + include = Dir('include') env = Environment(CPPPATH=include) - + The directory list will be added to command lines through the automatically-generated -$_CPPINCFLAGS +$_CPPINCFLAGS construction variable, which is constructed by respectively prepending and appending the value of the -$INCPREFIX and $INCSUFFIX +$INCPREFIX and $INCSUFFIX construction variables to the beginning and end -of each directory in $CPPPATH. +of each directory in $CPPPATH. Any command lines you define that need the CPPPATH directory list should -include $_CPPINCFLAGS: +include $_CPPINCFLAGS: - + env = Environment(CCCOM="my_compiler $_CPPINCFLAGS -c -o $TARGET $SOURCE") CPPSUFFIXES - - + The list of suffixes of files that will be scanned for C preprocessor implicit dependencies (#include lines). The default list is: - + [".c", ".C", ".cxx", ".cpp", ".c++", ".cc", ".h", ".H", ".hxx", ".hpp", ".hh", ".F", ".fpp", ".FPP", @@ -788,41 +740,37 @@ The default list is: CXX - - + The C++ compiler. CXXCOM - - + The command line used to compile a C++ source file to an object file. -Any options specified in the $CXXFLAGS and -$CPPFLAGS construction variables +Any options specified in the $CXXFLAGS and +$CPPFLAGS construction variables are included on this command line. CXXCOMSTR - - + The string displayed when a C++ source file is compiled to a (static) object file. -If this is not set, then $CXXCOM (the command line) is displayed. +If this is not set, then $CXXCOM (the command line) is displayed. - + env = Environment(CXXCOMSTR = "Compiling static object $TARGET") CXXFILESUFFIX - - + The suffix for C++ source files. This is used by the internal CXXFile builder when generating C++ files from Lex (.ll) or YACC (.yy) input files. @@ -848,20 +796,18 @@ as C++ files. CXXFLAGS - - + General options that are passed to the C++ compiler. -By default, this includes the value of $CCFLAGS, -so that setting $CCFLAGS affects both C and C++ compilation. +By default, this includes the value of $CCFLAGS, +so that setting $CCFLAGS affects both C and C++ compilation. If you want to add C++-specific flags, -you must set or override the value of $CXXFLAGS. +you must set or override the value of $CXXFLAGS. CXXVERSION - - + The version number of the C++ compiler. This may or may not be set, depending on the specific C++ compiler being used. @@ -870,50 +816,44 @@ depending on the specific C++ compiler being used. DC - - + The D compiler to use. DCOM - - + The command line used to compile a D file to an object file. -Any options specified in the $DFLAGS construction variable +Any options specified in the $DFLAGS construction variable is included on this command line. DDEBUG - - + List of debug tags to enable when compiling. DDEBUGPREFIX - - + DDEBUGPREFIX. DDEBUGSUFFIX - - + DDEBUGSUFFIX. DESCRIPTION - - + A long description of the project being packaged. This is included in the relevant section of the file that controls the packaging build. @@ -922,8 +862,7 @@ of the file that controls the packaging build. DESCRIPTION_lang - - + A language-specific long description for the specified lang. This is used to populate a @@ -935,61 +874,53 @@ section of an RPM DFILESUFFIX - - + DFILESUFFIX. DFLAGPREFIX - - + DFLAGPREFIX. DFLAGS - - + General options that are passed to the D compiler. DFLAGSUFFIX - - + DFLAGSUFFIX. DINCPREFIX - - + DINCPREFIX. DINCSUFFIX - - + DLIBFLAGSUFFIX. Dir - - + A function that converts a string into a Dir instance relative to the target being built. - - + A function that converts a string into a Dir instance relative to the target being built. @@ -997,8 +928,7 @@ into a Dir instance relative to the target being built. Dirs - - + A function that converts a list of strings into a list of Dir instances relative to the target being built. @@ -1006,184 +936,162 @@ into a list of Dir instances relative to the target being built. DLIB - - + Name of the lib tool to use for D codes. DLIBCOM - - + The command line to use when creating libraries. DLIBDIRPREFIX - - + DLIBLINKPREFIX. DLIBDIRSUFFIX - - + DLIBLINKSUFFIX. DLIBFLAGPREFIX - - + DLIBFLAGPREFIX. DLIBFLAGSUFFIX - - + DLIBFLAGSUFFIX. DLIBLINKPREFIX - - + DLIBLINKPREFIX. DLIBLINKSUFFIX - - + DLIBLINKSUFFIX. DLINK - - + Name of the linker to use for linking systems including D sources. DLINKCOM - - + The command line to use when linking systems including D sources. DLINKFLAGPREFIX - - + DLINKFLAGPREFIX. DLINKFLAGS - - + List of linker flags. DLINKFLAGSUFFIX - - + DLINKFLAGSUFFIX. DOCBOOK_DEFAULT_XSL_EPUB - - -The default XSLT file for the DocbookEpub builder within the + +The default XSLT file for the DocbookEpub builder within the current environment, if no other XSLT gets specified via keyword. DOCBOOK_DEFAULT_XSL_HTML - - -The default XSLT file for the DocbookHtml builder within the + +The default XSLT file for the DocbookHtml builder within the current environment, if no other XSLT gets specified via keyword. DOCBOOK_DEFAULT_XSL_HTMLCHUNKED - - -The default XSLT file for the DocbookHtmlChunked builder within the + +The default XSLT file for the DocbookHtmlChunked builder within the current environment, if no other XSLT gets specified via keyword. DOCBOOK_DEFAULT_XSL_HTMLHELP - - -The default XSLT file for the DocbookHtmlhelp builder within the + +The default XSLT file for the DocbookHtmlhelp builder within the current environment, if no other XSLT gets specified via keyword. DOCBOOK_DEFAULT_XSL_MAN - - -The default XSLT file for the DocbookMan builder within the + +The default XSLT file for the DocbookMan builder within the current environment, if no other XSLT gets specified via keyword. DOCBOOK_DEFAULT_XSL_PDF - - -The default XSLT file for the DocbookPdf builder within the + +The default XSLT file for the DocbookPdf builder within the current environment, if no other XSLT gets specified via keyword. DOCBOOK_DEFAULT_XSL_SLIDESHTML - - -The default XSLT file for the DocbookSlidesHtml builder within the + +The default XSLT file for the DocbookSlidesHtml builder within the current environment, if no other XSLT gets specified via keyword. DOCBOOK_DEFAULT_XSL_SLIDESPDF - - -The default XSLT file for the DocbookSlidesPdf builder within the + +The default XSLT file for the DocbookSlidesPdf builder within the current environment, if no other XSLT gets specified via keyword. DOCBOOK_FOP - - + The path to the PDF renderer fop or xep, if one of them is installed (fop gets checked first). @@ -1191,8 +1099,7 @@ if one of them is installed (fop gets checked first). DOCBOOK_FOPCOM - - + The full command-line for the PDF renderer fop or xep. @@ -1200,8 +1107,7 @@ PDF renderer fop or xep. DOCBOOK_FOPCOMSTR - - + The string displayed when a renderer like fop or xep is used to create PDF output from an XML file. @@ -1209,8 +1115,7 @@ The string displayed when a renderer like fop or DOCBOOK_FOPFLAGS - - + Additonal command-line flags for the PDF renderer fop or xep. @@ -1218,8 +1123,7 @@ PDF renderer fop or xep. DOCBOOK_XMLLINT - - + The path to the external executable xmllint, if it's installed. Note, that this is only used as last fallback for resolving XIncludes, if no libxml2 or lxml Python binding can be imported @@ -1229,8 +1133,7 @@ in the current system. DOCBOOK_XMLLINTCOM - - + The full command-line for the external executable xmllint. @@ -1238,8 +1141,7 @@ The full command-line for the external executable DOCBOOK_XMLLINTCOMSTR - - + The string displayed when xmllint is used to resolve XIncludes for a given XML file. @@ -1247,8 +1149,7 @@ XIncludes for a given XML file. DOCBOOK_XMLLINTFLAGS - - + Additonal command-line flags for the external executable xmllint. @@ -1256,8 +1157,7 @@ Additonal command-line flags for the external executable DOCBOOK_XSLTPROC - - + The path to the external executable xsltproc (or saxon, xalan), if one of them is installed. @@ -1268,8 +1168,7 @@ no libxml2 or lxml Python binding can be imported in the current system. DOCBOOK_XSLTPROCCOM - - + The full command-line for the external executable xsltproc (or saxon, xalan). @@ -1278,8 +1177,7 @@ The full command-line for the external executable DOCBOOK_XSLTPROCCOMSTR - - + The string displayed when xsltproc is used to transform an XML file via a given XSLT stylesheet. @@ -1287,8 +1185,7 @@ an XML file via a given XSLT stylesheet. DOCBOOK_XSLTPROCFLAGS - - + Additonal command-line flags for the external executable xsltproc (or saxon, xalan). @@ -1297,8 +1194,7 @@ Additonal command-line flags for the external executable DOCBOOK_XSLTPROCPARAMS - - + Additonal parameters that are not intended for the XSLT processor executable, but the XSL processing itself. By default, they get appended at the end of the command line for saxon and saxon-xslt, respectively. @@ -1307,149 +1203,134 @@ for saxon and saxon-xslt, respectively. DPATH - - + List of paths to search for import modules. DRPATHPREFIX - - + DRPATHPREFIX. DRPATHSUFFIX - - + DRPATHSUFFIX. DShLibSonameGenerator - - + DShLibSonameGenerator. DSUFFIXES - - + The list of suffixes of files that will be scanned for imported D package files. The default list is: - + ['.d'] DVERPREFIX - - + DVERPREFIX. DVERSIONS - - + List of version tags to enable when compiling. DVERSUFFIX - - + DVERSUFFIX. DVIPDF - - + The TeX DVI file to PDF file converter. DVIPDFCOM - - + The command line used to convert TeX DVI files into a PDF file. DVIPDFCOMSTR - - + The string displayed when a TeX DVI file is converted into a PDF file. -If this is not set, then $DVIPDFCOM (the command line) is displayed. +If this is not set, then $DVIPDFCOM (the command line) is displayed. DVIPDFFLAGS - - + General options passed to the TeX DVI file to PDF file converter. DVIPS - - + The TeX DVI file to PostScript converter. DVIPSFLAGS - - + General options passed to the TeX DVI file to PostScript converter. ENV - - + A dictionary of environment variables to use when invoking commands. When -$ENV is used in a command all list +$ENV is used in a command all list values will be joined using the path separator and any other non-string values will simply be coerced to a string. Note that, by default, -scons +scons does not propagate the environment in force when you execute -scons +scons to the commands used to build target files. This is so that builds will be guaranteed repeatable regardless of the environment variables set at the time -scons +scons is invoked. - + If you want to propagate your environment variables to the commands executed @@ -1457,12 +1338,12 @@ to build target files, you must do so explicitly: - + import os env = Environment(ENV = os.environ) - + Note that you can choose only to propagate certain environment variables. A common example is @@ -1470,12 +1351,12 @@ the system PATH environment variable, so that -scons +scons uses the same utilities as the invoking shell (or other process): - + import os env = Environment(ENV = {'PATH' : os.environ['PATH']}) @@ -1483,8 +1364,7 @@ env = Environment(ENV = {'PATH' : os.environ['PATH']}) ESCAPE - - + A function that will be called to escape shell special characters in command lines. The function should take one argument: the command line string to escape; and should return the escaped command line. @@ -1493,25 +1373,23 @@ string to escape; and should return the escaped command line. F03 - - + The Fortran 03 compiler. -You should normally set the $FORTRAN variable, +You should normally set the $FORTRAN variable, which specifies the default Fortran compiler for all Fortran versions. -You only need to set $F03 if you need to use a specific compiler +You only need to set $F03 if you need to use a specific compiler or compiler version for Fortran 03 files. F03COM - - + The command line used to compile a Fortran 03 source file to an object file. -You only need to set $F03COM if you need to use a specific +You only need to set $F03COM if you need to use a specific command line for Fortran 03 files. -You should normally set the $FORTRANCOM variable, +You should normally set the $FORTRANCOM variable, which specifies the default command line for all Fortran versions. @@ -1519,19 +1397,17 @@ for all Fortran versions. F03COMSTR - - + The string displayed when a Fortran 03 source file is compiled to an object file. -If this is not set, then $F03COM or $FORTRANCOM +If this is not set, then $F03COM or $FORTRANCOM (the command line) is displayed. F03FILESUFFIXES - - + The list of file extensions for which the F03 dialect will be used. By default, this is ['.f03'] @@ -1539,22 +1415,21 @@ default, this is ['.f03'] F03FLAGS - - + General user-specified options that are passed to the Fortran 03 compiler. Note that this variable does not contain (or similar) include search path options -that scons generates automatically from $F03PATH. +that scons generates automatically from $F03PATH. See -$_F03INCFLAGS +$_F03INCFLAGS below, for the variable that expands to those options. -You only need to set $F03FLAGS if you need to define specific +You only need to set $F03FLAGS if you need to define specific user options for Fortran 03 files. -You should normally set the $FORTRANFLAGS variable, +You should normally set the $FORTRANFLAGS variable, which specifies the user-specified options passed to the default Fortran compiler for all Fortran versions. @@ -1563,86 +1438,83 @@ for all Fortran versions. _F03INCFLAGS - - + An automatically-generated construction variable containing the Fortran 03 compiler command-line options for specifying directories to be searched for include files. -The value of $_F03INCFLAGS is created -by appending $INCPREFIX and $INCSUFFIX +The value of $_F03INCFLAGS is created +by appending $INCPREFIX and $INCSUFFIX to the beginning and end -of each directory in $F03PATH. +of each directory in $F03PATH. F03PATH - - + The list of directories that the Fortran 03 compiler will search for include directories. The implicit dependency scanner will search these directories for include files. Don't explicitly put include directory -arguments in $F03FLAGS because the result will be non-portable +arguments in $F03FLAGS because the result will be non-portable and the directories will not be searched by the dependency scanner. Note: -directory names in $F03PATH will be looked-up relative to the SConscript +directory names in $F03PATH will be looked-up relative to the SConscript directory when they are used in a command. To force -scons +scons to look-up a directory relative to the root of the source tree use #: -You only need to set $F03PATH if you need to define a specific +You only need to set $F03PATH if you need to define a specific include path for Fortran 03 files. -You should normally set the $FORTRANPATH variable, +You should normally set the $FORTRANPATH variable, which specifies the include path for the default Fortran compiler for all Fortran versions. - + env = Environment(F03PATH='#/include') - + The directory look-up can also be forced using the -Dir() +Dir() function: - + include = Dir('include') env = Environment(F03PATH=include) - + The directory list will be added to command lines through the automatically-generated -$_F03INCFLAGS +$_F03INCFLAGS construction variable, which is constructed by appending the values of the -$INCPREFIX and $INCSUFFIX +$INCPREFIX and $INCSUFFIX construction variables to the beginning and end -of each directory in $F03PATH. +of each directory in $F03PATH. Any command lines you define that need the F03PATH directory list should -include $_F03INCFLAGS: +include $_F03INCFLAGS: - + env = Environment(F03COM="my_compiler $_F03INCFLAGS -c -o $TARGET $SOURCE") F03PPCOM - - + The command line used to compile a Fortran 03 source file to an object file after first running the file through the C preprocessor. -Any options specified in the $F03FLAGS and $CPPFLAGS construction variables +Any options specified in the $F03FLAGS and $CPPFLAGS construction variables are included on this command line. -You only need to set $F03PPCOM if you need to use a specific +You only need to set $F03PPCOM if you need to use a specific C-preprocessor command line for Fortran 03 files. -You should normally set the $FORTRANPPCOM variable, +You should normally set the $FORTRANPPCOM variable, which specifies the default C-preprocessor command line for all Fortran versions. @@ -1650,20 +1522,18 @@ for all Fortran versions. F03PPCOMSTR - - + 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 $F03PPCOM or $FORTRANPPCOM +If this is not set, then $F03PPCOM or $FORTRANPPCOM (the command line) is displayed. F03PPFILESUFFIXES - - + The list of file extensions for which the compilation + preprocessor pass for F03 dialect will be used. By default, this is empty @@ -1671,25 +1541,23 @@ F03 dialect will be used. By default, this is empty F08 - - + The Fortran 08 compiler. -You should normally set the $FORTRAN variable, +You should normally set the $FORTRAN variable, which specifies the default Fortran compiler for all Fortran versions. -You only need to set $F08 if you need to use a specific compiler +You only need to set $F08 if you need to use a specific compiler or compiler version for Fortran 08 files. F08COM - - + The command line used to compile a Fortran 08 source file to an object file. -You only need to set $F08COM if you need to use a specific +You only need to set $F08COM if you need to use a specific command line for Fortran 08 files. -You should normally set the $FORTRANCOM variable, +You should normally set the $FORTRANCOM variable, which specifies the default command line for all Fortran versions. @@ -1697,19 +1565,17 @@ for all Fortran versions. F08COMSTR - - + The string displayed when a Fortran 08 source file is compiled to an object file. -If this is not set, then $F08COM or $FORTRANCOM +If this is not set, then $F08COM or $FORTRANCOM (the command line) is displayed. F08FILESUFFIXES - - + The list of file extensions for which the F08 dialect will be used. By default, this is ['.f08'] @@ -1717,22 +1583,21 @@ default, this is ['.f08'] F08FLAGS - - + General user-specified options that are passed to the Fortran 08 compiler. Note that this variable does not contain (or similar) include search path options -that scons generates automatically from $F08PATH. +that scons generates automatically from $F08PATH. See -$_F08INCFLAGS +$_F08INCFLAGS below, for the variable that expands to those options. -You only need to set $F08FLAGS if you need to define specific +You only need to set $F08FLAGS if you need to define specific user options for Fortran 08 files. -You should normally set the $FORTRANFLAGS variable, +You should normally set the $FORTRANFLAGS variable, which specifies the user-specified options passed to the default Fortran compiler for all Fortran versions. @@ -1741,86 +1606,83 @@ for all Fortran versions. _F08INCFLAGS - - + An automatically-generated construction variable containing the Fortran 08 compiler command-line options for specifying directories to be searched for include files. -The value of $_F08INCFLAGS is created -by appending $INCPREFIX and $INCSUFFIX +The value of $_F08INCFLAGS is created +by appending $INCPREFIX and $INCSUFFIX to the beginning and end -of each directory in $F08PATH. +of each directory in $F08PATH. F08PATH - - + The list of directories that the Fortran 08 compiler will search for include directories. The implicit dependency scanner will search these directories for include files. Don't explicitly put include directory -arguments in $F08FLAGS because the result will be non-portable +arguments in $F08FLAGS because the result will be non-portable and the directories will not be searched by the dependency scanner. Note: -directory names in $F08PATH will be looked-up relative to the SConscript +directory names in $F08PATH will be looked-up relative to the SConscript directory when they are used in a command. To force -scons +scons to look-up a directory relative to the root of the source tree use #: -You only need to set $F08PATH if you need to define a specific +You only need to set $F08PATH if you need to define a specific include path for Fortran 08 files. -You should normally set the $FORTRANPATH variable, +You should normally set the $FORTRANPATH variable, which specifies the include path for the default Fortran compiler for all Fortran versions. - + env = Environment(F08PATH='#/include') - + The directory look-up can also be forced using the -Dir() +Dir() function: - + include = Dir('include') env = Environment(F08PATH=include) - + The directory list will be added to command lines through the automatically-generated -$_F08INCFLAGS +$_F08INCFLAGS construction variable, which is constructed by appending the values of the -$INCPREFIX and $INCSUFFIX +$INCPREFIX and $INCSUFFIX construction variables to the beginning and end -of each directory in $F08PATH. +of each directory in $F08PATH. Any command lines you define that need the F08PATH directory list should -include $_F08INCFLAGS: +include $_F08INCFLAGS: - + env = Environment(F08COM="my_compiler $_F08INCFLAGS -c -o $TARGET $SOURCE") F08PPCOM - - + The command line used to compile a Fortran 08 source file to an object file after first running the file through the C preprocessor. -Any options specified in the $F08FLAGS and $CPPFLAGS construction variables +Any options specified in the $F08FLAGS and $CPPFLAGS construction variables are included on this command line. -You only need to set $F08PPCOM if you need to use a specific +You only need to set $F08PPCOM if you need to use a specific C-preprocessor command line for Fortran 08 files. -You should normally set the $FORTRANPPCOM variable, +You should normally set the $FORTRANPPCOM variable, which specifies the default C-preprocessor command line for all Fortran versions. @@ -1828,20 +1690,18 @@ for all Fortran versions. F08PPCOMSTR - - + 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 $F08PPCOM or $FORTRANPPCOM +If this is not set, then $F08PPCOM or $FORTRANPPCOM (the command line) is displayed. F08PPFILESUFFIXES - - + The list of file extensions for which the compilation + preprocessor pass for F08 dialect will be used. By default, this is empty @@ -1849,25 +1709,23 @@ F08 dialect will be used. By default, this is empty F77 - - + The Fortran 77 compiler. -You should normally set the $FORTRAN variable, +You should normally set the $FORTRAN variable, which specifies the default Fortran compiler for all Fortran versions. -You only need to set $F77 if you need to use a specific compiler +You only need to set $F77 if you need to use a specific compiler or compiler version for Fortran 77 files. F77COM - - + The command line used to compile a Fortran 77 source file to an object file. -You only need to set $F77COM if you need to use a specific +You only need to set $F77COM if you need to use a specific command line for Fortran 77 files. -You should normally set the $FORTRANCOM variable, +You should normally set the $FORTRANCOM variable, which specifies the default command line for all Fortran versions. @@ -1875,19 +1733,17 @@ for all Fortran versions. F77COMSTR - - + The string displayed when a Fortran 77 source file is compiled to an object file. -If this is not set, then $F77COM or $FORTRANCOM +If this is not set, then $F77COM or $FORTRANCOM (the command line) is displayed. F77FILESUFFIXES - - + The list of file extensions for which the F77 dialect will be used. By default, this is ['.f77'] @@ -1895,22 +1751,21 @@ default, this is ['.f77'] F77FLAGS - - + General user-specified options that are passed to the Fortran 77 compiler. Note that this variable does not contain (or similar) include search path options -that scons generates automatically from $F77PATH. +that scons generates automatically from $F77PATH. See -$_F77INCFLAGS +$_F77INCFLAGS below, for the variable that expands to those options. -You only need to set $F77FLAGS if you need to define specific +You only need to set $F77FLAGS if you need to define specific user options for Fortran 77 files. -You should normally set the $FORTRANFLAGS variable, +You should normally set the $FORTRANFLAGS variable, which specifies the user-specified options passed to the default Fortran compiler for all Fortran versions. @@ -1919,86 +1774,83 @@ for all Fortran versions. _F77INCFLAGS - - + An automatically-generated construction variable containing the Fortran 77 compiler command-line options for specifying directories to be searched for include files. -The value of $_F77INCFLAGS is created -by appending $INCPREFIX and $INCSUFFIX +The value of $_F77INCFLAGS is created +by appending $INCPREFIX and $INCSUFFIX to the beginning and end -of each directory in $F77PATH. +of each directory in $F77PATH. F77PATH - - + The list of directories that the Fortran 77 compiler will search for include directories. The implicit dependency scanner will search these directories for include files. Don't explicitly put include directory -arguments in $F77FLAGS because the result will be non-portable +arguments in $F77FLAGS because the result will be non-portable and the directories will not be searched by the dependency scanner. Note: -directory names in $F77PATH will be looked-up relative to the SConscript +directory names in $F77PATH will be looked-up relative to the SConscript directory when they are used in a command. To force -scons +scons to look-up a directory relative to the root of the source tree use #: -You only need to set $F77PATH if you need to define a specific +You only need to set $F77PATH if you need to define a specific include path for Fortran 77 files. -You should normally set the $FORTRANPATH variable, +You should normally set the $FORTRANPATH variable, which specifies the include path for the default Fortran compiler for all Fortran versions. - + env = Environment(F77PATH='#/include') - + The directory look-up can also be forced using the -Dir() +Dir() function: - + include = Dir('include') env = Environment(F77PATH=include) - + The directory list will be added to command lines through the automatically-generated -$_F77INCFLAGS +$_F77INCFLAGS construction variable, which is constructed by appending the values of the -$INCPREFIX and $INCSUFFIX +$INCPREFIX and $INCSUFFIX construction variables to the beginning and end -of each directory in $F77PATH. +of each directory in $F77PATH. Any command lines you define that need the F77PATH directory list should -include $_F77INCFLAGS: +include $_F77INCFLAGS: - + env = Environment(F77COM="my_compiler $_F77INCFLAGS -c -o $TARGET $SOURCE") F77PPCOM - - + The command line used to compile a Fortran 77 source file to an object file after first running the file through the C preprocessor. -Any options specified in the $F77FLAGS and $CPPFLAGS construction variables +Any options specified in the $F77FLAGS and $CPPFLAGS construction variables are included on this command line. -You only need to set $F77PPCOM if you need to use a specific +You only need to set $F77PPCOM if you need to use a specific C-preprocessor command line for Fortran 77 files. -You should normally set the $FORTRANPPCOM variable, +You should normally set the $FORTRANPPCOM variable, which specifies the default C-preprocessor command line for all Fortran versions. @@ -2006,20 +1858,18 @@ for all Fortran versions. F77PPCOMSTR - - + 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 $F77PPCOM or $FORTRANPPCOM +If this is not set, then $F77PPCOM or $FORTRANPPCOM (the command line) is displayed. F77PPFILESUFFIXES - - + The list of file extensions for which the compilation + preprocessor pass for F77 dialect will be used. By default, this is empty @@ -2027,25 +1877,23 @@ F77 dialect will be used. By default, this is empty F90 - - + The Fortran 90 compiler. -You should normally set the $FORTRAN variable, +You should normally set the $FORTRAN variable, which specifies the default Fortran compiler for all Fortran versions. -You only need to set $F90 if you need to use a specific compiler +You only need to set $F90 if you need to use a specific compiler or compiler version for Fortran 90 files. F90COM - - + The command line used to compile a Fortran 90 source file to an object file. -You only need to set $F90COM if you need to use a specific +You only need to set $F90COM if you need to use a specific command line for Fortran 90 files. -You should normally set the $FORTRANCOM variable, +You should normally set the $FORTRANCOM variable, which specifies the default command line for all Fortran versions. @@ -2053,19 +1901,17 @@ for all Fortran versions. F90COMSTR - - + The string displayed when a Fortran 90 source file is compiled to an object file. -If this is not set, then $F90COM or $FORTRANCOM +If this is not set, then $F90COM or $FORTRANCOM (the command line) is displayed. F90FILESUFFIXES - - + The list of file extensions for which the F90 dialect will be used. By default, this is ['.f90'] @@ -2073,22 +1919,21 @@ default, this is ['.f90'] F90FLAGS - - + General user-specified options that are passed to the Fortran 90 compiler. Note that this variable does not contain (or similar) include search path options -that scons generates automatically from $F90PATH. +that scons generates automatically from $F90PATH. See -$_F90INCFLAGS +$_F90INCFLAGS below, for the variable that expands to those options. -You only need to set $F90FLAGS if you need to define specific +You only need to set $F90FLAGS if you need to define specific user options for Fortran 90 files. -You should normally set the $FORTRANFLAGS variable, +You should normally set the $FORTRANFLAGS variable, which specifies the user-specified options passed to the default Fortran compiler for all Fortran versions. @@ -2097,86 +1942,83 @@ for all Fortran versions. _F90INCFLAGS - - + An automatically-generated construction variable containing the Fortran 90 compiler command-line options for specifying directories to be searched for include files. -The value of $_F90INCFLAGS is created -by appending $INCPREFIX and $INCSUFFIX +The value of $_F90INCFLAGS is created +by appending $INCPREFIX and $INCSUFFIX to the beginning and end -of each directory in $F90PATH. +of each directory in $F90PATH. F90PATH - - + The list of directories that the Fortran 90 compiler will search for include directories. The implicit dependency scanner will search these directories for include files. Don't explicitly put include directory -arguments in $F90FLAGS because the result will be non-portable +arguments in $F90FLAGS because the result will be non-portable and the directories will not be searched by the dependency scanner. Note: -directory names in $F90PATH will be looked-up relative to the SConscript +directory names in $F90PATH will be looked-up relative to the SConscript directory when they are used in a command. To force -scons +scons to look-up a directory relative to the root of the source tree use #: -You only need to set $F90PATH if you need to define a specific +You only need to set $F90PATH if you need to define a specific include path for Fortran 90 files. -You should normally set the $FORTRANPATH variable, +You should normally set the $FORTRANPATH variable, which specifies the include path for the default Fortran compiler for all Fortran versions. - + env = Environment(F90PATH='#/include') - + The directory look-up can also be forced using the -Dir() +Dir() function: - + include = Dir('include') env = Environment(F90PATH=include) - + The directory list will be added to command lines through the automatically-generated -$_F90INCFLAGS +$_F90INCFLAGS construction variable, which is constructed by appending the values of the -$INCPREFIX and $INCSUFFIX +$INCPREFIX and $INCSUFFIX construction variables to the beginning and end -of each directory in $F90PATH. +of each directory in $F90PATH. Any command lines you define that need the F90PATH directory list should -include $_F90INCFLAGS: +include $_F90INCFLAGS: - + env = Environment(F90COM="my_compiler $_F90INCFLAGS -c -o $TARGET $SOURCE") F90PPCOM - - + The command line used to compile a Fortran 90 source file to an object file after first running the file through the C preprocessor. -Any options specified in the $F90FLAGS and $CPPFLAGS construction variables +Any options specified in the $F90FLAGS and $CPPFLAGS construction variables are included on this command line. -You only need to set $F90PPCOM if you need to use a specific +You only need to set $F90PPCOM if you need to use a specific C-preprocessor command line for Fortran 90 files. -You should normally set the $FORTRANPPCOM variable, +You should normally set the $FORTRANPPCOM variable, which specifies the default C-preprocessor command line for all Fortran versions. @@ -2184,19 +2026,17 @@ for all Fortran versions. F90PPCOMSTR - - + 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 $F90PPCOM or $FORTRANPPCOM +If this is not set, then $F90PPCOM or $FORTRANPPCOM (the command line) is displayed. F90PPFILESUFFIXES - - + The list of file extensions for which the compilation + preprocessor pass for F90 dialect will be used. By default, this is empty @@ -2204,25 +2044,23 @@ F90 dialect will be used. By default, this is empty F95 - - + The Fortran 95 compiler. -You should normally set the $FORTRAN variable, +You should normally set the $FORTRAN variable, which specifies the default Fortran compiler for all Fortran versions. -You only need to set $F95 if you need to use a specific compiler +You only need to set $F95 if you need to use a specific compiler or compiler version for Fortran 95 files. F95COM - - + The command line used to compile a Fortran 95 source file to an object file. -You only need to set $F95COM if you need to use a specific +You only need to set $F95COM if you need to use a specific command line for Fortran 95 files. -You should normally set the $FORTRANCOM variable, +You should normally set the $FORTRANCOM variable, which specifies the default command line for all Fortran versions. @@ -2230,19 +2068,17 @@ for all Fortran versions. F95COMSTR - - + The string displayed when a Fortran 95 source file is compiled to an object file. -If this is not set, then $F95COM or $FORTRANCOM +If this is not set, then $F95COM or $FORTRANCOM (the command line) is displayed. F95FILESUFFIXES - - + The list of file extensions for which the F95 dialect will be used. By default, this is ['.f95'] @@ -2250,22 +2086,21 @@ default, this is ['.f95'] F95FLAGS - - + General user-specified options that are passed to the Fortran 95 compiler. Note that this variable does not contain (or similar) include search path options -that scons generates automatically from $F95PATH. +that scons generates automatically from $F95PATH. See -$_F95INCFLAGS +$_F95INCFLAGS below, for the variable that expands to those options. -You only need to set $F95FLAGS if you need to define specific +You only need to set $F95FLAGS if you need to define specific user options for Fortran 95 files. -You should normally set the $FORTRANFLAGS variable, +You should normally set the $FORTRANFLAGS variable, which specifies the user-specified options passed to the default Fortran compiler for all Fortran versions. @@ -2274,86 +2109,83 @@ for all Fortran versions. _F95INCFLAGS - - + An automatically-generated construction variable containing the Fortran 95 compiler command-line options for specifying directories to be searched for include files. -The value of $_F95INCFLAGS is created -by appending $INCPREFIX and $INCSUFFIX +The value of $_F95INCFLAGS is created +by appending $INCPREFIX and $INCSUFFIX to the beginning and end -of each directory in $F95PATH. +of each directory in $F95PATH. F95PATH - - + The list of directories that the Fortran 95 compiler will search for include directories. The implicit dependency scanner will search these directories for include files. Don't explicitly put include directory -arguments in $F95FLAGS because the result will be non-portable +arguments in $F95FLAGS because the result will be non-portable and the directories will not be searched by the dependency scanner. Note: -directory names in $F95PATH will be looked-up relative to the SConscript +directory names in $F95PATH will be looked-up relative to the SConscript directory when they are used in a command. To force -scons +scons to look-up a directory relative to the root of the source tree use #: -You only need to set $F95PATH if you need to define a specific +You only need to set $F95PATH if you need to define a specific include path for Fortran 95 files. -You should normally set the $FORTRANPATH variable, +You should normally set the $FORTRANPATH variable, which specifies the include path for the default Fortran compiler for all Fortran versions. - + env = Environment(F95PATH='#/include') - + The directory look-up can also be forced using the -Dir() +Dir() function: - + include = Dir('include') env = Environment(F95PATH=include) - + The directory list will be added to command lines through the automatically-generated -$_F95INCFLAGS +$_F95INCFLAGS construction variable, which is constructed by appending the values of the -$INCPREFIX and $INCSUFFIX +$INCPREFIX and $INCSUFFIX construction variables to the beginning and end -of each directory in $F95PATH. +of each directory in $F95PATH. Any command lines you define that need the F95PATH directory list should -include $_F95INCFLAGS: +include $_F95INCFLAGS: - + env = Environment(F95COM="my_compiler $_F95INCFLAGS -c -o $TARGET $SOURCE") F95PPCOM - - + The command line used to compile a Fortran 95 source file to an object file after first running the file through the C preprocessor. -Any options specified in the $F95FLAGS and $CPPFLAGS construction variables +Any options specified in the $F95FLAGS and $CPPFLAGS construction variables are included on this command line. -You only need to set $F95PPCOM if you need to use a specific +You only need to set $F95PPCOM if you need to use a specific C-preprocessor command line for Fortran 95 files. -You should normally set the $FORTRANPPCOM variable, +You should normally set the $FORTRANPPCOM variable, which specifies the default C-preprocessor command line for all Fortran versions. @@ -2361,20 +2193,18 @@ for all Fortran versions. F95PPCOMSTR - - + 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 $F95PPCOM or $FORTRANPPCOM +If this is not set, then $F95PPCOM or $FORTRANPPCOM (the command line) is displayed. F95PPFILESUFFIXES - - + The list of file extensions for which the compilation + preprocessor pass for F95 dialect will be used. By default, this is empty @@ -2382,13 +2212,11 @@ F95 dialect will be used. By default, this is empty File - - + A function that converts a string into a File instance relative to the target being built. - - + A function that converts a string into a File instance relative to the target being built. @@ -2396,8 +2224,7 @@ target being built. FORTRAN - - + The default Fortran compiler for all versions of Fortran. @@ -2405,34 +2232,31 @@ for all versions of Fortran. FORTRANCOM - - + The command line used to compile a Fortran source file to an object file. By default, any options specified -in the $FORTRANFLAGS, -$CPPFLAGS, -$_CPPDEFFLAGS, -$_FORTRANMODFLAG, and -$_FORTRANINCFLAGS construction variables +in the $FORTRANFLAGS, +$CPPFLAGS, +$_CPPDEFFLAGS, +$_FORTRANMODFLAG, and +$_FORTRANINCFLAGS construction variables are included on this command line. FORTRANCOMSTR - - + The string displayed when a Fortran source file is compiled to an object file. -If this is not set, then $FORTRANCOM +If this is not set, then $FORTRANCOM (the command line) is displayed. FORTRANFILESUFFIXES - - + The list of file extensions for which the FORTRAN dialect will be used. By default, this is ['.f', '.for', '.ftn'] @@ -2440,17 +2264,16 @@ default, this is ['.f', '.for', '.ftn'] FORTRANFLAGS - - + General user-specified options that are passed to the Fortran compiler. Note that this variable does not contain (or similar) include or module search path options -that scons generates automatically from $FORTRANPATH. +that scons generates automatically from $FORTRANPATH. See -$_FORTRANINCFLAGS and $_FORTRANMODFLAG, +$_FORTRANINCFLAGS and $_FORTRANMODFLAG, below, for the variables that expand those options. @@ -2458,24 +2281,22 @@ for the variables that expand those options. _FORTRANINCFLAGS - - + An automatically-generated construction variable containing the Fortran compiler command-line options for specifying directories to be searched for include files and module files. -The value of $_FORTRANINCFLAGS is created +The value of $_FORTRANINCFLAGS is created by respectively prepending and appending -$INCPREFIX and $INCSUFFIX +$INCPREFIX and $INCSUFFIX to the beginning and end -of each directory in $FORTRANPATH. +of each directory in $FORTRANPATH. FORTRANMODDIR - - + Directory location where the Fortran compiler should place any module files it generates. This variable is empty, by default. Some Fortran compilers will internally append this directory in the search path @@ -2485,48 +2306,44 @@ for module files, as well. FORTRANMODDIRPREFIX - - + The prefix used to specify a module directory on the Fortran compiler command line. This will be prepended to the beginning of the directory -in the $FORTRANMODDIR construction variables -when the $_FORTRANMODFLAG variables is automatically generated. +in the $FORTRANMODDIR construction variables +when the $_FORTRANMODFLAG variables is automatically generated. FORTRANMODDIRSUFFIX - - + The suffix used to specify a module directory on the Fortran compiler command line. This will be appended to the end of the directory -in the $FORTRANMODDIR construction variables -when the $_FORTRANMODFLAG variables is automatically generated. +in the $FORTRANMODDIR construction variables +when the $_FORTRANMODFLAG variables is automatically generated. _FORTRANMODFLAG - - + An automatically-generated construction variable containing the Fortran compiler command-line option for specifying the directory location where the Fortran compiler should place any module files that happen to get generated during compilation. -The value of $_FORTRANMODFLAG is created +The value of $_FORTRANMODFLAG is created by respectively prepending and appending -$FORTRANMODDIRPREFIX and $FORTRANMODDIRSUFFIX -to the beginning and end of the directory in $FORTRANMODDIR. +$FORTRANMODDIRPREFIX and $FORTRANMODDIRSUFFIX +to the beginning and end of the directory in $FORTRANMODDIR. FORTRANMODPREFIX - - + The module file prefix used by the Fortran compiler. SCons assumes that the Fortran compiler follows the quasi-standard naming convention for module files of @@ -2540,8 +2357,7 @@ module file name as scons attempts to resolve dependencies. FORTRANMODSUFFIX - - + The module file suffix used by the Fortran compiler. SCons assumes that the Fortran compiler follows the quasi-standard naming convention for module files of @@ -2555,8 +2371,7 @@ module file name as scons attempts to resolve dependencies. FORTRANPATH - - + The list of directories that the Fortran compiler will search for include files and (for some compilers) module files. The Fortran implicit dependency scanner will search these directories for include files (but @@ -2566,77 +2381,74 @@ include directory arguments in FORTRANFLAGS because the result will be non-portable and the directories will not be searched by the dependency scanner. Note: directory names in FORTRANPATH will be looked-up relative to the SConscript directory when they are used in a command. To force -scons +scons to look-up a directory relative to the root of the source tree use #: - + env = Environment(FORTRANPATH='#/include') - + The directory look-up can also be forced using the -Dir() +Dir() function: - + include = Dir('include') env = Environment(FORTRANPATH=include) - + The directory list will be added to command lines through the automatically-generated -$_FORTRANINCFLAGS +$_FORTRANINCFLAGS construction variable, which is constructed by respectively prepending and appending the values of the -$INCPREFIX and $INCSUFFIX +$INCPREFIX and $INCSUFFIX construction variables to the beginning and end -of each directory in $FORTRANPATH. +of each directory in $FORTRANPATH. Any command lines you define that need the FORTRANPATH directory list should -include $_FORTRANINCFLAGS: +include $_FORTRANINCFLAGS: - + env = Environment(FORTRANCOM="my_compiler $_FORTRANINCFLAGS -c -o $TARGET $SOURCE") FORTRANPPCOM - - + The command line used to compile a Fortran source file to an object file after first running the file through the C preprocessor. -By default, any options specified in the $FORTRANFLAGS, -$CPPFLAGS, -$_CPPDEFFLAGS, -$_FORTRANMODFLAG, and -$_FORTRANINCFLAGS +By default, any options specified in the $FORTRANFLAGS, +$CPPFLAGS, +$_CPPDEFFLAGS, +$_FORTRANMODFLAG, and +$_FORTRANINCFLAGS construction variables are included on this command line. FORTRANPPCOMSTR - - + 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 $FORTRANPPCOM +If this is not set, then $FORTRANPPCOM (the command line) is displayed. FORTRANPPFILESUFFIXES - - + The list of file extensions for which the compilation + preprocessor pass for FORTRAN dialect will be used. By default, this is ['.fpp', '.FPP'] @@ -2644,15 +2456,14 @@ FORTRAN dialect will be used. By default, this is ['.fpp', '.FPP'] FORTRANSUFFIXES - - + The list of suffixes of files that will be scanned for Fortran implicit dependencies (INCLUDE lines and USE statements). The default list is: - + [".f", ".F", ".for", ".FOR", ".ftn", ".FTN", ".fpp", ".FPP", ".f77", ".F77", ".f90", ".F90", ".f95", ".F95"] @@ -2660,50 +2471,47 @@ The default list is: FRAMEWORKPATH - - + On Mac OS X with gcc, a list containing the paths to search for frameworks. Used by the compiler to find framework-style includes like #include <Fmwk/Header.h>. Used by the linker to find user-specified frameworks when linking (see - $FRAMEWORKS). + $FRAMEWORKS). For example: - + env.AppendUnique(FRAMEWORKPATH='#myframeworkdir') - + will add - + ... -Fmyframeworkdir - + to the compiler and linker command lines. _FRAMEWORKPATH - - + On Mac OS X with gcc, an automatically-generated construction variable containing the linker command-line options corresponding to - $FRAMEWORKPATH. + $FRAMEWORKPATH. FRAMEWORKPATHPREFIX - - + On Mac OS X with gcc, the prefix to be used for the FRAMEWORKPATH entries. - (see $FRAMEWORKPATH). + (see $FRAMEWORKPATH). The default value is . @@ -2711,70 +2519,64 @@ The default list is: FRAMEWORKPREFIX - - + On Mac OS X with gcc, the prefix to be used for linking in frameworks - (see $FRAMEWORKS). + (see $FRAMEWORKS). The default value is . - - _FRAMEWORKS - - - On Mac OS X with gcc, - an automatically-generated construction variable - containing the linker command-line options - for linking with FRAMEWORKS. - - - FRAMEWORKS - - + On Mac OS X with gcc, a list of the framework names to be linked into a program or shared library or bundle. The default value is the empty list. For example: - + env.AppendUnique(FRAMEWORKS=Split('System Cocoa SystemConfiguration')) + + _FRAMEWORKS + + On Mac OS X with gcc, + an automatically-generated construction variable + containing the linker command-line options + for linking with FRAMEWORKS. + + + FRAMEWORKSFLAGS - - + On Mac OS X with gcc, general user-supplied frameworks options to be added at the end of a command line building a loadable module. (This has been largely superseded by - the $FRAMEWORKPATH, $FRAMEWORKPATHPREFIX, - $FRAMEWORKPREFIX and $FRAMEWORKS variables + the $FRAMEWORKPATH, $FRAMEWORKPATHPREFIX, + $FRAMEWORKPREFIX and $FRAMEWORKS variables described above.) GS - - + The Ghostscript program used, e.g. to convert PostScript to PDF files. GSCOM - - + The full Ghostscript command line used for the conversion process. Its default value is $GS $GSFLAGS -sOutputFile=$TARGET $SOURCES. @@ -2782,18 +2584,16 @@ value is $GS $GSFLAGS -sOutputFile=$TARGET $SOURCES GSCOMSTR - - + The string displayed when Ghostscript is called for the conversion process. -If this is not set (the default), then $GSCOM (the command line) is displayed. +If this is not set (the default), then $GSCOM (the command line) is displayed. GSFLAGS - - + General options passed to the Ghostscript program, when converting PostScript to PDF files for example. Its default value is -dNOPAUSE -dBATCH -sDEVICE=pdfwrite @@ -2802,17 +2602,7 @@ is -dNOPAUSE -dBATCH -sDEVICE=pdfwrite HOST_ARCH - - - The name of the host hardware architecture used to create the Environment. - If a platform is specified when creating the Environment, then - that Platform's logic will handle setting this value. - This value is immutable, and should not be changed by the user after - the Environment is initialized. - Currently only set for Win32. - - - + Sets the host architecture for Visual Studio compiler. If not set, default to the detected host architecture: note that this may depend on the python you are using. @@ -2820,20 +2610,27 @@ This variable must be passed as an argument to the Environment() constructor; setting it later has no effect. - -Valid values are the same as for $TARGET_ARCH. + +Valid values are the same as for $TARGET_ARCH. - + This is currently only used on Windows, but in the future it will be used on other OSes as well. - + + The name of the host hardware architecture used to create the Environment. + If a platform is specified when creating the Environment, then + that Platform's logic will handle setting this value. + This value is immutable, and should not be changed by the user after + the Environment is initialized. + Currently only set for Win32. + + HOST_OS - - + The name of the host operating system used to create the Environment. If a platform is specified when creating the Environment, then that Platform's logic will handle setting this value. @@ -2845,75 +2642,69 @@ used on other OSes as well. IDLSUFFIXES - - + The list of suffixes of files that will be scanned for IDL implicit dependencies (#include or import lines). The default list is: - + [".idl", ".IDL"] IMPLIBNOVERSIONSYMLINKS - - -Used to override $SHLIBNOVERSIONSYMLINKS/$LDMODULENOVERSIONSYMLINKS when + +Used to override $SHLIBNOVERSIONSYMLINKS/$LDMODULENOVERSIONSYMLINKS when creating versioned import library for a shared library/loadable module. If not defined, -then $SHLIBNOVERSIONSYMLINKS/$LDMODULENOVERSIONSYMLINKS is used to determine +then $SHLIBNOVERSIONSYMLINKS/$LDMODULENOVERSIONSYMLINKS is used to determine whether to disable symlink generation or not. IMPLIBPREFIX - - + The prefix used for import library names. For example, cygwin uses import libraries (libfoo.dll.a) in pair with dynamic libraries -(cygfoo.dll). The cyglink linker sets -$IMPLIBPREFIX to 'lib' and $SHLIBPREFIX +(cygfoo.dll). The cyglink linker sets +$IMPLIBPREFIX to 'lib' and $SHLIBPREFIX to 'cyg'. IMPLIBSUFFIX - - + The suffix used for import library names. For example, cygwin uses import libraries (libfoo.dll.a) in pair with dynamic libraries -(cygfoo.dll). The cyglink linker sets -$IMPLIBSUFFIX to '.dll.a' and $SHLIBSUFFIX +(cygfoo.dll). The cyglink linker sets +$IMPLIBSUFFIX to '.dll.a' and $SHLIBSUFFIX to '.dll'. IMPLIBVERSION - - -Used to override $SHLIBVERSION/$LDMODULEVERSION when + +Used to override $SHLIBVERSION/$LDMODULEVERSION when generating versioned import library for a shared library/loadable module. If -undefined, the $SHLIBVERSION/$LDMODULEVERSION is used to -determine the version of versioned import library. +undefined, the $SHLIBVERSION/$LDMODULEVERSION is used to +determine the version of versioned import library. IMPLICIT_COMMAND_DEPENDENCIES - - + Controls whether or not SCons will add implicit dependencies for the commands executed to build targets. - + By default, SCons will add to each target an implicit dependency on the command @@ -2927,9 +2718,9 @@ variable in the environment used to execute the command. - + If the construction variable -$IMPLICIT_COMMAND_DEPENDENCIES +$IMPLICIT_COMMAND_DEPENDENCIES is set to a false value (None, False, @@ -2940,41 +2731,38 @@ not be added to the targets built with that construction environment. - + env = Environment(IMPLICIT_COMMAND_DEPENDENCIES = 0) INCPREFIX - - + The prefix used to specify an include directory on the C compiler command line. This will be prepended to the beginning of each directory -in the $CPPPATH and $FORTRANPATH construction variables -when the $_CPPINCFLAGS and $_FORTRANINCFLAGS +in the $CPPPATH and $FORTRANPATH construction variables +when the $_CPPINCFLAGS and $_FORTRANINCFLAGS variables are automatically generated. INCSUFFIX - - + The suffix used to specify an include directory on the C compiler command line. This will be appended to the end of each directory -in the $CPPPATH and $FORTRANPATH construction variables -when the $_CPPINCFLAGS and $_FORTRANINCFLAGS +in the $CPPPATH and $FORTRANPATH construction variables +when the $_CPPINCFLAGS and $_FORTRANINCFLAGS variables are automatically generated. INSTALL - - + A function to be called to install a file into a destination file name. The default function copies the file into the destination @@ -2983,11 +2771,11 @@ to match the source file's). The function takes the following arguments: - + def install(dest, source, env): - + dest is the path name of the destination file. source @@ -3001,21 +2789,19 @@ in force for this file installation. INSTALLSTR - - + The string displayed when a file is installed into a destination file name. The default is: - + Install file: "$SOURCE" as "$TARGET" INTEL_C_COMPILER_VERSION - - + Set by the "intelc" Tool to the major version number of the Intel C compiler selected for use. @@ -3024,27 +2810,23 @@ selected for use. JAR - - + The Java archive tool. - - + The Java archive tool. JARCHDIR - - + The directory to which the Java archive tool should change (using the option). - - + The directory to which the Java archive tool should change (using the @@ -3054,44 +2836,39 @@ option). JARCOM - - + The command line used to call the Java archive tool. - - + The command line used to call the Java archive tool. JARCOMSTR - - + The string displayed when the Java archive tool is called -If this is not set, then $JARCOM (the command line) is displayed. +If this is not set, then $JARCOM (the command line) is displayed. - + env = Environment(JARCOMSTR = "JARchiving $SOURCES into $TARGET") - - + The string displayed when the Java archive tool is called -If this is not set, then $JARCOM (the command line) is displayed. +If this is not set, then $JARCOM (the command line) is displayed. - + env = Environment(JARCOMSTR = "JARchiving $SOURCES into $TARGET") JARFLAGS - - + General options passed to the Java archive tool. By default this is set to @@ -3099,8 +2876,7 @@ to create the necessary jar file. - - + General options passed to the Java archive tool. By default this is set to @@ -3112,14 +2888,12 @@ file. JARSUFFIX - - + The suffix for Java archives: .jar by default. - - + The suffix for Java archives: .jar by default. @@ -3128,11 +2902,10 @@ by default. JAVABOOTCLASSPATH - - + Specifies the list of directories that will be added to the - javac command line + javac command line via the option. The individual directory names will be separated by the operating system's path separate character @@ -3144,51 +2917,46 @@ by default. JAVAC - - + The Java compiler. JAVACCOM - - + The command line used to compile a directory tree containing Java source files to corresponding Java class files. - Any options specified in the $JAVACFLAGS construction variable + Any options specified in the $JAVACFLAGS construction variable are included on this command line. JAVACCOMSTR - - + The string displayed when compiling a directory tree of Java source files to corresponding Java class files. - If this is not set, then $JAVACCOM (the command line) is displayed. + If this is not set, then $JAVACCOM (the command line) is displayed. - + env = Environment(JAVACCOMSTR = "Compiling class files $TARGETS from $SOURCES") JAVACFLAGS - - + General options that are passed to the Java compiler. JAVACLASSDIR - - + The directory in which Java class files may be found. This is stripped from the beginning of any Java .class file names supplied to the @@ -3199,14 +2967,13 @@ by default. JAVACLASSPATH - - + Specifies the list of directories that will be searched for Java .class file. The directories in this list will be added to the - javac and javah command lines + javac and javah command lines via the option. The individual directory names will be separated by the operating system's path separate character @@ -3215,11 +2982,11 @@ by default. on Windows). - + Note that this currently just adds the specified directory via the option. - SCons does not currently search the - $JAVACLASSPATH directories for dependency + SCons does not currently search the + $JAVACLASSPATH directories for dependency .class files. @@ -3227,8 +2994,7 @@ by default. JAVACLASSSUFFIX - - + The suffix for Java class files; .class by default. @@ -3237,41 +3003,37 @@ by default. JAVAH - - + The Java generator for C header and stub files. JAVAHCOM - - + The command line used to generate C header and stub files from Java classes. -Any options specified in the $JAVAHFLAGS construction variable +Any options specified in the $JAVAHFLAGS construction variable are included on this command line. JAVAHCOMSTR - - + The string displayed when C header and stub files are generated from Java classes. -If this is not set, then $JAVAHCOM (the command line) is displayed. +If this is not set, then $JAVAHCOM (the command line) is displayed. - + env = Environment(JAVAHCOMSTR = "Generating header/stub file(s) $TARGETS from $SOURCES") JAVAHFLAGS - - + General options passed to the C header and stub file generator for Java classes. @@ -3279,22 +3041,20 @@ for Java classes. JAVAINCLUDES - - + Include path for Java header files (such as jni.h) JAVASOURCEPATH - - + Specifies the list of directories that will be searched for input .java file. The directories in this list will be added to the - javac command line + javac command line via the option. The individual directory names will be separated by the operating system's path separate character @@ -3303,11 +3063,11 @@ for Java classes. on Windows). - + Note that this currently just adds the specified directory via the option. - SCons does not currently search the - $JAVASOURCEPATH directories for dependency + SCons does not currently search the + $JAVASOURCEPATH directories for dependency .java files. @@ -3315,8 +3075,7 @@ for Java classes. JAVASUFFIX - - + The suffix for Java files; .java by default. @@ -3325,76 +3084,70 @@ for Java classes. JAVAVERSION - - - Specifies the Java version being used by the Java builder. + + Specifies the Java version being used by the Java builder. This is not currently used to select one version of the Java compiler vs. another. Instead, you should set this to specify the version of Java - supported by your javac compiler. + supported by your javac compiler. The default is 1.4. - + This is sometimes necessary because Java 1.5 changed the file names that are created for nested anonymous inner classes, which can cause a mismatch with the files - that SCons expects will be generated by the javac compiler. - Setting $JAVAVERSION to + that SCons expects will be generated by the javac compiler. + Setting $JAVAVERSION to 1.5 (or 1.6, as appropriate) - can make SCons realize that a Java 1.5 or 1.6 + can make SCons realize that a Java 1.5 or 1.6 build is actually up to date. LATEX - - + The LaTeX structured formatter and typesetter. LATEXCOM - - + The command line used to call the LaTeX structured formatter and typesetter. LATEXCOMSTR - - + The string displayed when calling the LaTeX structured formatter and typesetter. -If this is not set, then $LATEXCOM (the command line) is displayed. +If this is not set, then $LATEXCOM (the command line) is displayed. - + env = Environment(LATEXCOMSTR = "Building $TARGET from LaTeX input $SOURCES") LATEXFLAGS - - + General options passed to the LaTeX structured formatter and typesetter. LATEXRETRIES - - + The maximum number of times that LaTeX will be re-run if the .log -generated by the $LATEXCOM command +generated by the $LATEXCOM command indicates that there are undefined references. The default is to try to resolve undefined references by re-running LaTeX up to three times. @@ -3403,91 +3156,92 @@ by re-running LaTeX up to three times. LATEXSUFFIXES - - + The list of suffixes of files that will be scanned for LaTeX implicit dependencies (\include or \import files). The default list is: - + [".tex", ".ltx", ".latex"] LDMODULE - - + The linker for building loadable modules. -By default, this is the same as $SHLINK. +By default, this is the same as $SHLINK. LDMODULECOM - - + The command line for building loadable modules. -On Mac OS X, this uses the $LDMODULE, -$LDMODULEFLAGS and -$FRAMEWORKSFLAGS variables. -On other systems, this is the same as $SHLINK. +On Mac OS X, this uses the $LDMODULE, +$LDMODULEFLAGS and +$FRAMEWORKSFLAGS variables. +On other systems, this is the same as $SHLINK. LDMODULECOMSTR - - + The string displayed when building loadable modules. -If this is not set, then $LDMODULECOM (the command line) is displayed. +If this is not set, then $LDMODULECOM (the command line) is displayed. + + + + + LDMODULEEMITTER + +Contains the emitter specification for the +LoadableModule builder. +The manpage section "Builder Objects" contains +general information on specifying emitters. LDMODULEFLAGS - - + General user options passed to the linker for building loadable modules. LDMODULENOVERSIONSYMLINKS - - -Instructs the LoadableModule builder to not automatically create symlinks + +Instructs the LoadableModule builder to not automatically create symlinks for versioned modules. Defaults to $SHLIBNOVERSIONSYMLINKS LDMODULEPREFIX - - + The prefix used for loadable module file names. On Mac OS X, this is null; on other systems, this is -the same as $SHLIBPREFIX. +the same as $SHLIBPREFIX. _LDMODULESONAME - - + A macro that automatically generates loadable module's SONAME based on $TARGET, -$LDMODULEVERSION and $LDMODULESUFFIX. Used by LoadableModule builder -when the linker tool supports SONAME (e.g. gnulink). +$LDMODULEVERSION and $LDMODULESUFFIX. Used by LoadableModule builder +when the linker tool supports SONAME (e.g. gnulink). LDMODULESUFFIX - - + The suffix used for loadable module file names. On Mac OS X, this is null; on other systems, this is @@ -3497,52 +3251,47 @@ the same as $SHLIBSUFFIX. LDMODULEVERSION - - + When this construction variable is defined, a versioned loadable module -is created by LoadableModule builder. This activates the -$_LDMODULEVERSIONFLAGS and thus modifies the $LDMODULECOM as +is created by LoadableModule builder. This activates the +$_LDMODULEVERSIONFLAGS and thus modifies the $LDMODULECOM as required, adds the version number to the library name, and creates the symlinks -that are needed. $LDMODULEVERSION versions should exist in the same -format as $SHLIBVERSION. - - - - - LDMODULEVERSIONFLAGS - - -Extra flags added to $LDMODULECOM when building versioned -LoadableModule. These flags are only used when $LDMODULEVERSION is -set. +that are needed. $LDMODULEVERSION versions should exist in the same +format as $SHLIBVERSION. _LDMODULEVERSIONFLAGS - - -This macro automatically introduces extra flags to $LDMODULECOM when -building versioned LoadableModule (that is when -$LDMODULEVERSION is set). _LDMODULEVERSIONFLAGS -usually adds $SHLIBVERSIONFLAGS and some extra dynamically generated + +This macro automatically introduces extra flags to $LDMODULECOM when +building versioned LoadableModule (that is when +$LDMODULEVERSION is set). _LDMODULEVERSIONFLAGS +usually adds $SHLIBVERSIONFLAGS and some extra dynamically generated options (such as -Wl,-soname=$_LDMODULESONAME). It is unused by plain (unversioned) loadable modules. + + LDMODULEVERSIONFLAGS + +Extra flags added to $LDMODULECOM when building versioned +LoadableModule. These flags are only used when $LDMODULEVERSION is +set. + + + LEX - - + The lexical analyzer generator. LEXCOM - - + The command line used to call the lexical analyzer generator to generate a source file. @@ -3550,170 +3299,161 @@ to generate a source file. LEXCOMSTR - - + The string displayed when generating a source file using the lexical analyzer generator. -If this is not set, then $LEXCOM (the command line) is displayed. +If this is not set, then $LEXCOM (the command line) is displayed. - + env = Environment(LEXCOMSTR = "Lex'ing $TARGET from $SOURCES") LEXFLAGS - - + General options passed to the lexical analyzer generator. LEXUNISTD - - + Used only on windows environments to set a lex flag to prevent 'unistd.h' from being included. The default value is '--nounistd'. _LIBDIRFLAGS - - + An automatically-generated construction variable containing the linker command-line options for specifying directories to be searched for library. -The value of $_LIBDIRFLAGS is created -by respectively prepending and appending $LIBDIRPREFIX and $LIBDIRSUFFIX +The value of $_LIBDIRFLAGS is created +by respectively prepending and appending $LIBDIRPREFIX and $LIBDIRSUFFIX to the beginning and end -of each directory in $LIBPATH. +of each directory in $LIBPATH. LIBDIRPREFIX - - + The prefix used to specify a library directory on the linker command line. This will be prepended to the beginning of each directory -in the $LIBPATH construction variable -when the $_LIBDIRFLAGS variable is automatically generated. +in the $LIBPATH construction variable +when the $_LIBDIRFLAGS variable is automatically generated. LIBDIRSUFFIX - - + The suffix used to specify a library directory on the linker command line. This will be appended to the end of each directory -in the $LIBPATH construction variable -when the $_LIBDIRFLAGS variable is automatically generated. +in the $LIBPATH construction variable +when the $_LIBDIRFLAGS variable is automatically generated. LIBEMITTER - - -TODO + +Contains the emitter specification for the +StaticLibrary builder. +The manpage section "Builder Objects" contains +general information on specifying emitters. _LIBFLAGS - - + An automatically-generated construction variable containing the linker command-line options for specifying libraries to be linked with the resulting target. -The value of $_LIBFLAGS is created -by respectively prepending and appending $LIBLINKPREFIX and $LIBLINKSUFFIX +The value of $_LIBFLAGS is created +by respectively prepending and appending $LIBLINKPREFIX and $LIBLINKSUFFIX to the beginning and end -of each filename in $LIBS. +of each filename in $LIBS. LIBLINKPREFIX - - + The prefix used to specify a library to link on the linker command line. This will be prepended to the beginning of each library -in the $LIBS construction variable -when the $_LIBFLAGS variable is automatically generated. +in the $LIBS construction variable +when the $_LIBFLAGS variable is automatically generated. LIBLINKSUFFIX - - + The suffix used to specify a library to link on the linker command line. This will be appended to the end of each library -in the $LIBS construction variable -when the $_LIBFLAGS variable is automatically generated. +in the $LIBS construction variable +when the $_LIBFLAGS variable is automatically generated. LIBPATH - - + The list of directories that will be searched for libraries. The implicit dependency scanner will search these directories for include files. Don't explicitly put include directory -arguments in $LINKFLAGS or $SHLINKFLAGS +arguments in $LINKFLAGS or $SHLINKFLAGS because the result will be non-portable and the directories will not be searched by the dependency scanner. Note: directory names in LIBPATH will be looked-up relative to the SConscript directory when they are used in a command. To force -scons +scons to look-up a directory relative to the root of the source tree use #: - + env = Environment(LIBPATH='#/libs') - + The directory look-up can also be forced using the -Dir() +Dir() function: - + libs = Dir('libs') env = Environment(LIBPATH=libs) - + The directory list will be added to command lines through the automatically-generated -$_LIBDIRFLAGS +$_LIBDIRFLAGS construction variable, which is constructed by respectively prepending and appending the values of the -$LIBDIRPREFIX and $LIBDIRSUFFIX +$LIBDIRPREFIX and $LIBDIRSUFFIX construction variables to the beginning and end -of each directory in $LIBPATH. +of each directory in $LIBPATH. Any command lines you define that need the LIBPATH directory list should -include $_LIBDIRFLAGS: +include $_LIBDIRFLAGS: - + env = Environment(LINKCOM="my_linker $_LIBDIRFLAGS $_LIBFLAGS -o $TARGET $SOURCE") LIBPREFIX - - + The prefix used for (static) library file names. A default value is set for each platform (posix, win32, os2, etc.), @@ -3725,65 +3465,63 @@ to reflect the names of the libraries they create. LIBPREFIXES - - + A list of all legal prefixes for library file names. When searching for library dependencies, SCons will look for files with these prefixes, the base library name, -and suffixes in the $LIBSUFFIXES list. +and suffixes in the $LIBSUFFIXES list. LIBS - - + A list of one or more libraries that will be linked with any executable programs created by this environment. - + The library list will be added to command lines through the automatically-generated -$_LIBFLAGS +$_LIBFLAGS construction variable, which is constructed by respectively prepending and appending the values of the -$LIBLINKPREFIX and $LIBLINKSUFFIX +$LIBLINKPREFIX and $LIBLINKSUFFIX construction variables to the beginning and end -of each filename in $LIBS. +of each filename in $LIBS. Any command lines you define that need the LIBS library list should -include $_LIBFLAGS: +include $_LIBFLAGS: - + env = Environment(LINKCOM="my_linker $_LIBDIRFLAGS $_LIBFLAGS -o $TARGET $SOURCE") - + If you add a File object to the -$LIBS +$LIBS list, the name of that file will be added to -$_LIBFLAGS, +$_LIBFLAGS, and thus the link line, as is, without -$LIBLINKPREFIX +$LIBLINKPREFIX or -$LIBLINKSUFFIX. +$LIBLINKSUFFIX. For example: - + env.Append(LIBS=File('/tmp/mylib.so')) - + In all cases, scons will add dependencies from the executable program to all the libraries in this list. @@ -3791,8 +3529,7 @@ all the libraries in this list. LIBSUFFIX - - + The suffix used for (static) library file names. A default value is set for each platform (posix, win32, os2, etc.), @@ -3804,11 +3541,10 @@ to reflect the names of the libraries they create. LIBSUFFIXES - - + A list of all legal suffixes for library file names. When searching for library dependencies, -SCons will look for files with prefixes, in the $LIBPREFIXES list, +SCons will look for files with prefixes, in the $LIBPREFIXES list, the base library name, and these suffixes. @@ -3816,8 +3552,7 @@ and these suffixes. LICENSE - - + The abbreviated name, preferably the SPDX code, of the license under which this project is released (GPL-3.0, LGPL-2.1, BSD-2-Clause etc.). See http://www.opensource.org/licenses/alphabetical @@ -3827,9 +3562,8 @@ for a list of license names and SPDX codes. LINESEPARATOR - - -The separator used by the Substfile and Textfile builders. + +The separator used by the Substfile and Textfile builders. This value is used between sources when constructing the target. It defaults to the current system line separator. @@ -3837,13 +3571,12 @@ It defaults to the current system line separator. LINGUAS_FILE - - -The $LINGUAS_FILE defines file(s) containing list of additional linguas -to be processed by POInit, POUpdate or MOFiles -builders. It also affects Translate builder. If the variable contains -a string, it defines name of the list file. The $LINGUAS_FILE may be a -list of file names as well. If $LINGUAS_FILE is set to + +The $LINGUAS_FILE defines file(s) containing list of additional linguas +to be processed by POInit, POUpdate or MOFiles +builders. It also affects Translate builder. If the variable contains +a string, it defines name of the list file. The $LINGUAS_FILE may be a +list of file names as well. If $LINGUAS_FILE is set to True (or non-zero numeric value), the list will be read from default file named LINGUAS. @@ -3853,54 +3586,50 @@ default file named LINK - - + The linker. LINKCOM - - + The command line used to link object files into an executable. LINKCOMSTR - - + The string displayed when object files are linked into an executable. -If this is not set, then $LINKCOM (the command line) is displayed. +If this is not set, then $LINKCOM (the command line) is displayed. - + env = Environment(LINKCOMSTR = "Linking $TARGET") LINKFLAGS - - + General user options passed to the linker. Note that this variable should not contain -(or similar) options for linking with the libraries listed in $LIBS, +(or similar) options for linking with the libraries listed in $LIBS, nor (or similar) library search path options -that scons generates automatically from $LIBPATH. +that scons generates automatically from $LIBPATH. See -$_LIBFLAGS +$_LIBFLAGS above, for the variable that expands to library-link options, and -$_LIBDIRFLAGS +$_LIBDIRFLAGS above, for the variable that expands to library search path options. @@ -3908,42 +3637,37 @@ for the variable that expands to library search path options. M4 - - + The M4 macro preprocessor. M4COM - - + The command line used to pass files through the M4 macro preprocessor. M4COMSTR - - + The string displayed when a file is passed through the M4 macro preprocessor. -If this is not set, then $M4COM (the command line) is displayed. +If this is not set, then $M4COM (the command line) is displayed. M4FLAGS - - + General options passed to the M4 macro preprocessor. MAKEINDEX - - + The makeindex generator for the TeX formatter and typesetter and the LaTeX structured formatter and typesetter. @@ -3951,8 +3675,7 @@ LaTeX structured formatter and typesetter. MAKEINDEXCOM - - + The command line used to call the makeindex generator for the TeX formatter and typesetter and the LaTeX structured formatter and typesetter. @@ -3961,19 +3684,17 @@ typesetter. MAKEINDEXCOMSTR - - + The string displayed when calling the makeindex generator for the TeX formatter and typesetter and the LaTeX structured formatter and typesetter. -If this is not set, then $MAKEINDEXCOM (the command line) is displayed. +If this is not set, then $MAKEINDEXCOM (the command line) is displayed. MAKEINDEXFLAGS - - + General options passed to the makeindex generator for the TeX formatter and typesetter and the LaTeX structured formatter and typesetter. @@ -3981,8 +3702,7 @@ and typesetter and the LaTeX structured formatter and typesetter. MAXLINELENGTH - - + The maximum number of characters allowed on an external command line. On Win32 systems, link lines longer than this many characters @@ -3992,178 +3712,159 @@ are linked via a temporary file name. MIDL - - + The Microsoft IDL compiler. MIDLCOM - - + The command line used to pass files to the Microsoft IDL compiler. MIDLCOMSTR - - + The string displayed when the Microsoft IDL compiler is called. -If this is not set, then $MIDLCOM (the command line) is displayed. +If this is not set, then $MIDLCOM (the command line) is displayed. MIDLFLAGS - - + General options passed to the Microsoft IDL compiler. MOSUFFIX - - + Suffix used for MO files (default: '.mo'). -See msgfmt tool and MOFiles builder. +See msgfmt tool and MOFiles builder. MSGFMT - - + Absolute path to msgfmt(1) binary, found by Detect(). -See msgfmt tool and MOFiles builder. +See msgfmt tool and MOFiles builder. MSGFMTCOM - - + Complete command line to run msgfmt(1) program. -See msgfmt tool and MOFiles builder. +See msgfmt tool and MOFiles builder. MSGFMTCOMSTR - - + String to display when msgfmt(1) is invoked -(default: '', which means ``print $MSGFMTCOM''). -See msgfmt tool and MOFiles builder. +(default: '', which means ``print $MSGFMTCOM''). +See msgfmt tool and MOFiles builder. MSGFMTFLAGS - - + Additional flags to msgfmt(1). -See msgfmt tool and MOFiles builder. +See msgfmt tool and MOFiles builder. MSGINIT - - + Path to msginit(1) program (found via Detect()). -See msginit tool and POInit builder. +See msginit tool and POInit builder. MSGINITCOM - - + Complete command line to run msginit(1) program. -See msginit tool and POInit builder. +See msginit tool and POInit builder. MSGINITCOMSTR - - + String to display when msginit(1) is invoked -(default: '', which means ``print $MSGINITCOM''). -See msginit tool and POInit builder. +(default: '', which means ``print $MSGINITCOM''). +See msginit tool and POInit builder. MSGINITFLAGS - - + List of additional flags to msginit(1) (default: []). -See msginit tool and POInit builder. +See msginit tool and POInit builder. _MSGINITLOCALE - - + Internal ``macro''. Computes locale (language) name based on target filename (default: '${TARGET.filebase}' ). - -See msginit tool and POInit builder. + +See msginit tool and POInit builder. MSGMERGE - - + Absolute path to msgmerge(1) binary as found by Detect(). -See msgmerge tool and POUpdate builder. +See msgmerge tool and POUpdate builder. MSGMERGECOM - - + Complete command line to run msgmerge(1) command. -See msgmerge tool and POUpdate builder. +See msgmerge tool and POUpdate builder. MSGMERGECOMSTR - - + String to be displayed when msgmerge(1) is invoked -(default: '', which means ``print $MSGMERGECOM''). -See msgmerge tool and POUpdate builder. +(default: '', which means ``print $MSGMERGECOM''). +See msgmerge tool and POUpdate builder. MSGMERGEFLAGS - - + Additional flags to msgmerge(1) command. -See msgmerge tool and POUpdate builder. +See msgmerge tool and POUpdate builder. MSSDK_DIR - - + The directory containing the Microsoft SDK (either Platform SDK or Windows SDK) to be used for compilation. @@ -4172,8 +3873,7 @@ to be used for compilation. MSSDK_VERSION - - + The version string of the Microsoft SDK (either Platform SDK or Windows SDK) to be used for compilation. @@ -4189,8 +3889,7 @@ and MSVC_BATCH - - + When set to any true value, specifies that SCons should batch compilation of object files @@ -4201,7 +3900,7 @@ and were configured in SCons using the same construction environment will be built in a single call to the compiler. Only source files that have changed since their object files were built will be passed to each compiler invocation -(via the $CHANGED_SOURCES construction variable). +(via the $CHANGED_SOURCES construction variable). Any compilations where the object (target) file base name (minus the .obj) does not match the source file base name @@ -4211,13 +3910,12 @@ will be compiled separately. MSVC_USE_SCRIPT - - + Use a batch script to set up Microsoft Visual Studio compiler - -$MSVC_USE_SCRIPT overrides $MSVC_VERSION and $TARGET_ARCH. + +$MSVC_USE_SCRIPT overrides $MSVC_VERSION and $TARGET_ARCH. If set to the name of a Visual Studio .bat file (e.g. vcvars.bat), SCons will run that bat file and extract the relevant variables from the result (typically %INCLUDE%, %LIB%, and %PATH%). Setting @@ -4229,13 +3927,12 @@ window and importing the shell's environment variables. MSVC_UWP_APP - - + Build libraries for a Universal Windows Platform (UWP) Application. - -If $MSVC_UWP_APP is set, the Visual Studio environment will be set up to point + +If $MSVC_UWP_APP is set, the Visual Studio environment will be set up to point to the Windows Store compatible libraries and Visual Studio runtimes. In doing so, any libraries that are built will be able to be used in a UWP App and published to the Windows Store. @@ -4244,7 +3941,7 @@ This variable must be passed as an argument to the Environment() constructor; setting it later has no effect. - + Valid values are '1' or '0' @@ -4252,20 +3949,19 @@ Valid values are '1' or '0' MSVC_VERSION - - + Sets the preferred version of Microsoft Visual C/C++ to use. - -If $MSVC_VERSION is not set, SCons will (by default) select the + +If $MSVC_VERSION is not set, SCons will (by default) select the latest version of Visual C/C++ installed on your system. If the specified version isn't installed, tool initialization will fail. This variable must be passed as an argument to the Environment() constructor; setting it later has no effect. - + Valid values for Windows are 14.2, 14.1, @@ -4292,16 +3988,15 @@ Versions ending in Exp refer to "Express" or MSVS - - + When the Microsoft Visual Studio tools are initialized, they set up this dictionary with the following keys: - + VERSION the version of MSVS being used (can be set via - $MSVS_VERSION) + $MSVS_VERSION) VERSIONS @@ -4357,20 +4052,19 @@ Versions ending in Exp refer to "Express" or - If a value is not set, it was not available in the registry. + If a value is not set, it was not available in the registry. MSVS_ARCH - - Sets the architecture for which the generated project(s) should build. - + Sets the architecture for which the generated project(s) should build. + The default value is x86. - amd64 is also supported by SCons for + amd64 is also supported by SCons for most Visual Studio versions. Since Visual Studio 2015 arm is supported, and since Visual Studio 2017 arm64 is supported. - Trying to set $MSVS_ARCH + Trying to set $MSVS_ARCH to an architecture that's not supported for a given Visual Studio version will generate an error. @@ -4378,8 +4072,7 @@ Versions ending in Exp refer to "Express" or MSVS_PROJECT_GUID - - + The string placed in a generated Microsoft Visual Studio project file as the value of the ProjectGUID attribute. There is no default @@ -4391,8 +4084,7 @@ defined, a new GUID is generated. MSVS_SCC_AUX_PATH - - + The path name placed in a generated Microsoft Visual Studio project file as the value of the SccAuxPath attribute if the @@ -4405,8 +4097,7 @@ no default value. MSVS_SCC_CONNECTION_ROOT - - + The root path of projects in your SCC workspace, i.e the path under which all project and solution files will be generated. It is used as a reference path from which the @@ -4430,8 +4121,7 @@ no default value. MSVS_SCC_PROJECT_NAME - - + The project name placed in a generated Microsoft Visual Studio project file as the value of the SccProjectName attribute if the @@ -4446,8 +4136,7 @@ no default value. MSVS_SCC_PROVIDER - - + The string placed in a generated Microsoft Visual Studio project file as the value of the SccProvider attribute. The string is @@ -4460,10 +4149,9 @@ no default value. MSVS_VERSION - - Sets the preferred version of Microsoft Visual Studio to use. - - If $MSVS_VERSION is not set, SCons will (by default) + Sets the preferred version of Microsoft Visual Studio to use. + + If $MSVS_VERSION is not set, SCons will (by default) select the latest version of Visual Studio installed on your system. So, if you have version 6 and version 7 (MSVS .NET) installed, it will prefer version 7. You can override this by @@ -4472,19 +4160,18 @@ no default value. version ('6.0' or '7.0', for example). If the specified version isn't installed, tool initialization will fail. - - This is obsolete: use $MSVC_VERSION instead. If - $MSVS_VERSION is set and $MSVC_VERSION is - not, $MSVC_VERSION will be set automatically to - $MSVS_VERSION. If both are set to different values, + + This is obsolete: use $MSVC_VERSION instead. If + $MSVS_VERSION is set and $MSVC_VERSION is + not, $MSVC_VERSION will be set automatically to + $MSVS_VERSION. If both are set to different values, scons will raise an error. MSVSBUILDCOM - - + The build command line placed in a generated Microsoft Visual Studio project file. The default is to have Visual Studio invoke SCons with any specified build targets. @@ -4493,8 +4180,7 @@ no default value. MSVSCLEANCOM - - + The clean command line placed in a generated Microsoft Visual Studio project file. The default is to have Visual Studio invoke SCons with the -c option to remove any specified @@ -4504,8 +4190,7 @@ no default value. MSVSENCODING - - + The encoding string placed in a generated Microsoft Visual Studio project file. The default is encoding Windows-1252. @@ -4514,14 +4199,12 @@ no default value. MSVSPROJECTCOM - - The action used to generate Microsoft Visual Studio project files. + The action used to generate Microsoft Visual Studio project files. MSVSPROJECTSUFFIX - - + The suffix used for Microsoft Visual Studio project (DSP) files. The default value is .vcproj when using Visual Studio version 7.x (.NET) or later version, @@ -4532,8 +4215,7 @@ no default value. MSVSREBUILDCOM - - + The rebuild command line placed in a generated Microsoft Visual Studio project file. The default is to have Visual Studio invoke SCons with any specified rebuild targets. @@ -4543,8 +4225,7 @@ no default value. MSVSSCONS - - + The SCons used in generated Microsoft Visual Studio project files. The default is the version of SCons being used to generate the project file. @@ -4553,8 +4234,7 @@ no default value. MSVSSCONSCOM - - + The default SCons command used in generated Microsoft Visual Studio project files. @@ -4562,34 +4242,30 @@ no default value. MSVSSCONSCRIPT - - - The sconscript file (that is, SConstruct or SConscript + + The sconscript file (that is, SConstruct or SConscript file) that will be invoked by Visual Studio project files - (through the $MSVSSCONSCOM variable). The default + (through the $MSVSSCONSCOM variable). The default is the same sconscript file that contains the call to - MSVSProject to build the project file. + MSVSProject to build the project file. MSVSSCONSFLAGS - - + The SCons flags used in generated Microsoft Visual Studio project files. MSVSSOLUTIONCOM - - The action used to generate Microsoft Visual Studio solution files. + The action used to generate Microsoft Visual Studio solution files. MSVSSOLUTIONSUFFIX - - + The suffix used for Microsoft Visual Studio solution (DSW) files. The default value is .sln when using Visual Studio version 7.x (.NET), and @@ -4600,43 +4276,38 @@ no default value. MT - - + The program used on Windows systems to embed manifests into DLLs and EXEs. -See also $WINDOWS_EMBED_MANIFEST. +See also $WINDOWS_EMBED_MANIFEST. MTEXECOM - - + The Windows command line used to embed manifests into executables. -See also $MTSHLIBCOM. +See also $MTSHLIBCOM. MTFLAGS - - -Flags passed to the $MT manifest embedding program (Windows only). + +Flags passed to the $MT manifest embedding program (Windows only). MTSHLIBCOM - - + The Windows command line used to embed manifests into shared libraries (DLLs). -See also $MTEXECOM. +See also $MTEXECOM. MWCW_VERSION - - + The version number of the MetroWerks CodeWarrior C compiler to be used. @@ -4644,8 +4315,7 @@ to be used. MWCW_VERSIONS - - + A list of installed versions of the MetroWerks CodeWarrior C compiler on this system. @@ -4653,16 +4323,14 @@ on this system. NAME - - + Specfies the name of the project to package. no_import_lib - - + When set to non-zero, suppresses creation of a corresponding Windows static import lib by the SharedLibrary @@ -4676,24 +4344,21 @@ when using Microsoft Visual Studio. OBJPREFIX - - + The prefix used for (static) object file names. OBJSUFFIX - - + The suffix used for (static) object file names. PACKAGEROOT - - + Specifies the directory where all files in resulting archive will be placed if applicable. The default value is "$NAME-$VERSION". @@ -4701,12 +4366,11 @@ placed if applicable. The default value is "$NAME-$VERSION". PACKAGETYPE - - + Selects the package type to build. Currently these are available: - + * msi - Microsoft Installer * rpm - Redhat Package Manger * ipkg - Itsy Package Management System @@ -4718,15 +4382,14 @@ Selects the package type to build. Currently these are available: * src_zip - zip file source - + This may be overridden with the "package_type" command line option. PACKAGEVERSION - - + The version of the package (not the underlying project). This is currently only used by the rpm packager and should reflect changes in the packaging, @@ -4736,8 +4399,7 @@ not the underlying project code itself. PCH - - + The Microsoft Visual C++ precompiled header that will be used when compiling object files. This variable is ignored by tools other than Microsoft Visual C++. When this variable is @@ -4747,44 +4409,40 @@ dependencies for the PCH file. Example: - + env['PCH'] = 'StdAfx.pch' PCHCOM - - + The command line used by the -PCH +PCH builder to generated a precompiled header. PCHCOMSTR - - + The string displayed when generating a precompiled header. -If this is not set, then $PCHCOM (the command line) is displayed. +If this is not set, then $PCHCOM (the command line) is displayed. PCHPDBFLAGS - - + A construction variable that, when expanded, adds the /yD flag to the command line -only if the $PDB construction variable is set. +only if the $PDB construction variable is set. PCHSTOP - - + This variable specifies how much of a source file is precompiled. This variable is ignored by tools other than Microsoft Visual C++, or when the PCH variable is not being used. When this variable is define it @@ -4793,15 +4451,14 @@ is included at the end of the precompiled portion of the source files, or the empty string if the "#pragma hrdstop" construct is being used: - + env['PCHSTOP'] = 'StdAfx.h' PDB - - + The Microsoft Visual C++ PDB file that will store debugging information for object files, shared libraries, and programs. This variable is ignored by tools other than Microsoft Visual C++. @@ -4812,11 +4469,11 @@ dependencies for the PDB file. Example: - + env['PDB'] = 'hello.pdb' - + The Visual C++ compiler switch that SCons uses by default to generate PDB information is . This works correctly with parallel () builds @@ -4828,116 +4485,104 @@ Using the instead may yield improved link-time performance, although parallel builds will no longer work. You can generate PDB files with the -switch by overriding the default $CCPDBFLAGS variable; +switch by overriding the default $CCPDBFLAGS variable; see the entry for that variable for specific examples. PDFCOM - - -A deprecated synonym for $DVIPDFCOM. + +A deprecated synonym for $DVIPDFCOM. PDFLATEX - - -The pdflatex utility. + +The pdflatex utility. PDFLATEXCOM - - -The command line used to call the pdflatex utility. + +The command line used to call the pdflatex utility. PDFLATEXCOMSTR - - -The string displayed when calling the pdflatex utility. -If this is not set, then $PDFLATEXCOM (the command line) is displayed. + +The string displayed when calling the pdflatex utility. +If this is not set, then $PDFLATEXCOM (the command line) is displayed. - + env = Environment(PDFLATEX;COMSTR = "Building $TARGET from LaTeX input $SOURCES") PDFLATEXFLAGS - - -General options passed to the pdflatex utility. + +General options passed to the pdflatex utility. PDFPREFIX - - + The prefix used for PDF file names. PDFSUFFIX - - + The suffix used for PDF file names. PDFTEX - - -The pdftex utility. + +The pdftex utility. PDFTEXCOM - - -The command line used to call the pdftex utility. + +The command line used to call the pdftex utility. PDFTEXCOMSTR - - -The string displayed when calling the pdftex utility. -If this is not set, then $PDFTEXCOM (the command line) is displayed. + +The string displayed when calling the pdftex utility. +If this is not set, then $PDFTEXCOM (the command line) is displayed. - + env = Environment(PDFTEXCOMSTR = "Building $TARGET from TeX input $SOURCES") PDFTEXFLAGS - - -General options passed to the pdftex utility. + +General options passed to the pdftex utility. PKGCHK - - + On Solaris systems, the package-checking program that will -be used (along with $PKGINFO) +be used (along with $PKGINFO) to look for installed versions of the Sun PRO C++ compiler. The default is @@ -4947,11 +4592,10 @@ The default is PKGINFO - - + On Solaris systems, the package information program that will -be used (along with $PKGCHK) +be used (along with $PKGCHK) to look for installed versions of the Sun PRO C++ compiler. The default is @@ -4961,15 +4605,14 @@ The default is PLATFORM - - + The name of the platform used to create the Environment. If no platform is specified when the Environment is created, -scons +scons autodetects the platform. - + env = Environment(tools = []) if env['PLATFORM'] == 'cygwin': Tool('mingw')(env) @@ -4980,45 +4623,41 @@ else: POAUTOINIT - - -The $POAUTOINIT variable, if set to True (on non-zero -numeric value), let the msginit tool to automatically initialize + +The $POAUTOINIT variable, if set to True (on non-zero +numeric value), let the msginit tool to automatically initialize missing PO files with msginit(1). This applies to both, -POInit and POUpdate builders (and others that use any of +POInit and POUpdate builders (and others that use any of them). POCREATE_ALIAS - - -Common alias for all PO files created with POInit + +Common alias for all PO files created with POInit builder (default: 'po-create'). -See msginit tool and POInit builder. +See msginit tool and POInit builder. POSUFFIX - - + Suffix used for PO files (default: '.po') -See msginit tool and POInit builder. +See msginit tool and POInit builder. POTDOMAIN - - -The $POTDOMAIN defines default domain, used to generate -POT filename as $POTDOMAIN.pot when + +The $POTDOMAIN defines default domain, used to generate +POT filename as $POTDOMAIN.pot when no POT file name is provided by the user. This applies to -POTUpdate, POInit and POUpdate builders (and -builders, that use them, e.g. Translate). Normally (if $POTDOMAIN is +POTUpdate, POInit and POUpdate builders (and +builders, that use them, e.g. Translate). Normally (if $POTDOMAIN is not defined), the builders use messages.pot as default POT file name. @@ -5026,37 +4665,33 @@ not defined), the builders use messages.pot as default POTSUFFIX - - + Suffix used for PO Template files (default: '.pot'). -See xgettext tool and POTUpdate builder. +See xgettext tool and POTUpdate builder. POTUPDATE_ALIAS - - + Name of the common phony target for all PO Templates created with -POUpdate (default: 'pot-update'). -See xgettext tool and POTUpdate builder. +POUpdate (default: 'pot-update'). +See xgettext tool and POTUpdate builder. POUPDATE_ALIAS - - + Common alias for all PO files being defined with -POUpdate builder (default: 'po-update'). -See msgmerge tool and POUpdate builder. +POUpdate builder (default: 'po-update'). +See msgmerge tool and POUpdate builder. PRINT_CMD_LINE_FUNC - - + A Python function used to print the command lines as they are executed (assuming command printing is not disabled by the @@ -5074,20 +4709,20 @@ the source(s) used (file node, list, or string name(s)), and the environment being used. - + The function must do the printing itself. The default implementation, used if this variable is not set or is None, is: - + def print_cmd_line(s, target, source, env): sys.stdout.write(s + "\n") - + Here's an example of a more interesting function: - + def print_cmd_line(s, target, source, env): sys.stdout.write("Building %s -> %s...\n" % (' and '.join([str(x) for x in source]), @@ -5096,7 +4731,7 @@ env=Environment(PRINT_CMD_LINE_FUNC=print_cmd_line) env.Program('foo', 'foo.c') - + This just prints "Building targetname from sourcename..." instead of the actual commands. Such a function could also log the actual commands to a log file, @@ -5106,66 +4741,61 @@ for example. PROGEMITTER - - -TODO + +Contains the emitter specification for the +Program builder. +The manpage section "Builder Objects" contains +general information on specifying emitters. PROGPREFIX - - + The prefix used for executable file names. PROGSUFFIX - - + The suffix used for executable file names. PSCOM - - + The command line used to convert TeX DVI files into a PostScript file. PSCOMSTR - - + The string displayed when a TeX DVI file is converted into a PostScript file. -If this is not set, then $PSCOM (the command line) is displayed. +If this is not set, then $PSCOM (the command line) is displayed. PSPREFIX - - + The prefix used for PostScript file names. PSSUFFIX - - + The prefix used for PostScript file names. QT_AUTOSCAN - - + Turn off scanning for mocable files. Use the Moc Builder to explicitly specify files to run moc on. @@ -5173,74 +4803,66 @@ specify files to run moc on. QT_BINPATH - - + The path where the qt binaries are installed. -The default value is '$QTDIR/bin'. +The default value is '$QTDIR/bin'. QT_CPPPATH - - + The path where the qt header files are installed. -The default value is '$QTDIR/include'. +The default value is '$QTDIR/include'. Note: If you set this variable to None, -the tool won't change the $CPPPATH +the tool won't change the $CPPPATH construction variable. QT_DEBUG - - + Prints lots of debugging information while scanning for moc files. QT_LIB - - + Default value is 'qt'. You may want to set this to 'qt-mt'. Note: If you set -this variable to None, the tool won't change the $LIBS variable. +this variable to None, the tool won't change the $LIBS variable. QT_LIBPATH - - + The path where the qt libraries are installed. -The default value is '$QTDIR/lib'. +The default value is '$QTDIR/lib'. Note: If you set this variable to None, -the tool won't change the $LIBPATH +the tool won't change the $LIBPATH construction variable. QT_MOC - - -Default value is '$QT_BINPATH/moc'. + +Default value is '$QT_BINPATH/moc'. QT_MOCCXXPREFIX - - + Default value is ''. Prefix for moc output files, when source is a cxx file. QT_MOCCXXSUFFIX - - + Default value is '.moc'. Suffix for moc output files, when source is a cxx file. @@ -5248,25 +4870,22 @@ file. QT_MOCFROMCXXCOM - - + Command to generate a moc file from a cpp file. QT_MOCFROMCXXCOMSTR - - + The string displayed when generating a moc file from a cpp file. -If this is not set, then $QT_MOCFROMCXXCOM (the command line) is displayed. +If this is not set, then $QT_MOCFROMCXXCOM (the command line) is displayed. QT_MOCFROMCXXFLAGS - - + Default value is '-i'. These flags are passed to moc, when moccing a C++ file. @@ -5274,25 +4893,22 @@ C++ file. QT_MOCFROMHCOM - - + Command to generate a moc file from a header. QT_MOCFROMHCOMSTR - - + The string displayed when generating a moc file from a cpp file. -If this is not set, then $QT_MOCFROMHCOM (the command line) is displayed. +If this is not set, then $QT_MOCFROMHCOM (the command line) is displayed. QT_MOCFROMHFLAGS - - + Default value is ''. These flags are passed to moc, when moccing a header file. @@ -5300,50 +4916,44 @@ file. QT_MOCHPREFIX - - + Default value is 'moc_'. Prefix for moc output files, when source is a header. QT_MOCHSUFFIX - - -Default value is '$CXXFILESUFFIX'. Suffix for moc output files, when source is + +Default value is '$CXXFILESUFFIX'. Suffix for moc output files, when source is a header. QT_UIC - - -Default value is '$QT_BINPATH/uic'. + +Default value is '$QT_BINPATH/uic'. QT_UICCOM - - + Command to generate header files from .ui files. QT_UICCOMSTR - - + The string displayed when generating header files from .ui files. -If this is not set, then $QT_UICCOM (the command line) is displayed. +If this is not set, then $QT_UICCOM (the command line) is displayed. QT_UICDECLFLAGS - - + Default value is ''. These flags are passed to uic, when creating a a h file from a .ui file. @@ -5351,24 +4961,21 @@ file from a .ui file. QT_UICDECLPREFIX - - + Default value is ''. Prefix for uic generated header files. QT_UICDECLSUFFIX - - + Default value is '.h'. Suffix for uic generated header files. QT_UICIMPLFLAGS - - + Default value is ''. These flags are passed to uic, when creating a cxx file from a .ui file. @@ -5376,33 +4983,29 @@ file from a .ui file. QT_UICIMPLPREFIX - - + Default value is 'uic_'. Prefix for uic generated implementation files. QT_UICIMPLSUFFIX - - -Default value is '$CXXFILESUFFIX'. Suffix for uic generated implementation + +Default value is '$CXXFILESUFFIX'. Suffix for uic generated implementation files. QT_UISUFFIX - - + Default value is '.ui'. Suffix of designer input files. QTDIR - - + The qt tool tries to take this from os.environ. It also initializes all QT_* construction variables listed below. @@ -5411,24 +5014,24 @@ with python's os.path.join() method, but are listed here with the '/' separator for easier reading.) In addition, the construction environment -variables $CPPPATH, -$LIBPATH and -$LIBS may be modified +variables $CPPPATH, +$LIBPATH and +$LIBS may be modified and the variables -$PROGEMITTER, $SHLIBEMITTER and $LIBEMITTER +$PROGEMITTER, $SHLIBEMITTER and $LIBEMITTER are modified. Because the build-performance is affected when using this tool, you have to explicitly specify it at Environment creation: - + Environment(tools=['default','qt']) - + The qt tool supports the following operations: - + Automatic moc file generation from header files. You do not have to specify moc files explicitly, the tool does it for you. However, there are a few preconditions to do so: Your header file must have @@ -5436,11 +5039,11 @@ the same filebase as your implementation file and must stay in the same directory. It must have one of the suffixes .h, .hpp, .H, .hxx, .hh. You can turn off automatic moc file generation by setting QT_AUTOSCAN to 0. See also the corresponding -Moc() +Moc() builder method. - + Automatic moc file generation from cxx files. As stated in the qt documentation, include the moc file at the end of the cxx file. Note that you have to include the file, which is generated @@ -5449,11 +5052,11 @@ by the transformation ${QT_MOCCXXPREFIX}<basename>${QT_MOCCXXSUFFIX}, by d do not include the correct file. If you are using VariantDir, you may need to specify duplicate=1. You can turn off automatic moc file generation by setting QT_AUTOSCAN to 0. See also the corresponding -Moc +Moc builder method. - + Automatic handling of .ui files. The implementation files generated from .ui files are handled much the same as yacc or lex files. Each .ui file given as a source of Program, Library or @@ -5461,52 +5064,47 @@ SharedLibrary will generate three files, the declaration file, the implementation file and a moc file. Because there are also generated headers, you may need to specify duplicate=1 in calls to VariantDir. See also the corresponding -Uic +Uic builder method. RANLIB - - + The archive indexer. RANLIBCOM - - + The command line used to index a static library archive. RANLIBCOMSTR - - + The string displayed when a static library archive is indexed. -If this is not set, then $RANLIBCOM (the command line) is displayed. +If this is not set, then $RANLIBCOM (the command line) is displayed. - + env = Environment(RANLIBCOMSTR = "Indexing $TARGET") RANLIBFLAGS - - + General options passed to the archive indexer. RC - - + The resource compiler used to build a Microsoft Visual C++ resource file. @@ -5514,8 +5112,7 @@ a Microsoft Visual C++ resource file. RCCOM - - + The command line used to build a Microsoft Visual C++ resource file. @@ -5523,66 +5120,60 @@ a Microsoft Visual C++ resource file. RCCOMSTR - - + The string displayed when invoking the resource compiler to build a Microsoft Visual C++ resource file. -If this is not set, then $RCCOM (the command line) is displayed. +If this is not set, then $RCCOM (the command line) is displayed. RCFLAGS - - + The flags passed to the resource compiler by the RES builder. RCINCFLAGS - - + An automatically-generated construction variable containing the command-line options for specifying directories to be searched by the resource compiler. -The value of $RCINCFLAGS is created +The value of $RCINCFLAGS is created by respectively prepending and appending -$RCINCPREFIX and $RCINCSUFFIX +$RCINCPREFIX and $RCINCSUFFIX to the beginning and end -of each directory in $CPPPATH. +of each directory in $CPPPATH. RCINCPREFIX - - + The prefix (flag) used to specify an include directory on the resource compiler command line. This will be prepended to the beginning of each directory -in the $CPPPATH construction variable -when the $RCINCFLAGS variable is expanded. +in the $CPPPATH construction variable +when the $RCINCFLAGS variable is expanded. RCINCSUFFIX - - + The suffix used to specify an include directory on the resource compiler command line. This will be appended to the end of each directory -in the $CPPPATH construction variable -when the $RCINCFLAGS variable is expanded. +in the $CPPPATH construction variable +when the $RCINCFLAGS variable is expanded. RDirs - - + A function that converts a string into a list of Dir instances by searching the repositories. @@ -5590,39 +5181,35 @@ searching the repositories. REGSVR - - + The program used on Windows systems to register a newly-built DLL library -whenever the SharedLibrary builder +whenever the SharedLibrary builder is passed a keyword argument of register=1. REGSVRCOM - - + The command line used on Windows systems to register a newly-built DLL library -whenever the SharedLibrary builder +whenever the SharedLibrary builder is passed a keyword argument of register=1. REGSVRCOMSTR - - + The string displayed when registering a newly-built DLL file. -If this is not set, then $REGSVRCOM (the command line) is displayed. +If this is not set, then $REGSVRCOM (the command line) is displayed. REGSVRFLAGS - - + Flags passed to the DLL registration program on Windows systems when a newly-built DLL library is registered. By default, @@ -5634,232 +5221,212 @@ and requiring user attention. RMIC - - + The Java RMI stub compiler. RMICCOM - - + The command line used to compile stub and skeleton class files from Java classes that contain RMI implementations. -Any options specified in the $RMICFLAGS construction variable +Any options specified in the $RMICFLAGS construction variable are included on this command line. RMICCOMSTR - - + The string displayed when compiling stub and skeleton class files from Java classes that contain RMI implementations. -If this is not set, then $RMICCOM (the command line) is displayed. +If this is not set, then $RMICCOM (the command line) is displayed. - + env = Environment(RMICCOMSTR = "Generating stub/skeleton class files $TARGETS from $SOURCES") RMICFLAGS - - + General options passed to the Java RMI stub compiler. - - _RPATH - - -An automatically-generated construction variable -containing the rpath flags to be used when linking -a program with shared libraries. -The value of $_RPATH is created -by respectively prepending $RPATHPREFIX and appending $RPATHSUFFIX -to the beginning and end -of each directory in $RPATH. - - - RPATH - - + A list of paths to search for shared libraries when running programs. Currently only used in the GNU (gnulink), IRIX (sgilink) and Sun (sunlink) linkers. Ignored on platforms and toolchains that don't support it. Note that the paths added to RPATH are not transformed by -scons +scons in any way: if you want an absolute path, you must make it absolute yourself. + + _RPATH + +An automatically-generated construction variable +containing the rpath flags to be used when linking +a program with shared libraries. +The value of $_RPATH is created +by respectively prepending $RPATHPREFIX and appending $RPATHSUFFIX +to the beginning and end +of each directory in $RPATH. + + + RPATHPREFIX - - + The prefix used to specify a directory to be searched for shared libraries when running programs. This will be prepended to the beginning of each directory -in the $RPATH construction variable -when the $_RPATH variable is automatically generated. +in the $RPATH construction variable +when the $_RPATH variable is automatically generated. RPATHSUFFIX - - + The suffix used to specify a directory to be searched for shared libraries when running programs. This will be appended to the end of each directory -in the $RPATH construction variable -when the $_RPATH variable is automatically generated. +in the $RPATH construction variable +when the $_RPATH variable is automatically generated. RPCGEN - - + The RPC protocol compiler. RPCGENCLIENTFLAGS - - + Options passed to the RPC protocol compiler when generating client side stubs. These are in addition to any flags specified in the -$RPCGENFLAGS +$RPCGENFLAGS construction variable. RPCGENFLAGS - - + General options passed to the RPC protocol compiler. RPCGENHEADERFLAGS - - + Options passed to the RPC protocol compiler when generating a header file. These are in addition to any flags specified in the -$RPCGENFLAGS +$RPCGENFLAGS construction variable. RPCGENSERVICEFLAGS - - + Options passed to the RPC protocol compiler when generating server side stubs. These are in addition to any flags specified in the -$RPCGENFLAGS +$RPCGENFLAGS construction variable. RPCGENXDRFLAGS - - + Options passed to the RPC protocol compiler when generating XDR routines. These are in addition to any flags specified in the -$RPCGENFLAGS +$RPCGENFLAGS construction variable. SCANNERS - - + A list of the available implicit dependency scanners. New file scanners may be added by appending to this list, although the more flexible approach is to associate scanners with a specific Builder. -See the sections "Builder Objects" -and "Scanner Objects," -below, for more information. +See the manpage sections "Builder Objects" +and "Scanner Objects" +for more information. SCONS_HOME - - + The (optional) path to the SCons library directory, initialized from the external environment. If set, this is used to construct a shorter and more efficient search path in - the $MSVSSCONS command line executed from Microsoft + the $MSVSSCONS command line executed from Microsoft Visual Studio project files. SHCC - - + The C compiler used for generating shared-library objects. SHCCCOM - - + The command line used to compile a C source file to a shared-library object file. -Any options specified in the $SHCFLAGS, -$SHCCFLAGS and -$CPPFLAGS construction variables +Any options specified in the $SHCFLAGS, +$SHCCFLAGS and +$CPPFLAGS construction variables are included on this command line. SHCCCOMSTR - - + The string displayed when a C source file is compiled to a shared object file. -If this is not set, then $SHCCCOM (the command line) is displayed. +If this is not set, then $SHCCCOM (the command line) is displayed. - + env = Environment(SHCCCOMSTR = "Compiling shared object $TARGET") SHCCFLAGS - - + Options that are passed to the C and C++ compilers to generate shared-library objects. @@ -5867,8 +5434,7 @@ to generate shared-library objects. SHCFLAGS - - + Options that are passed to the C compiler (only; not C++) to generate shared-library objects. @@ -5876,42 +5442,38 @@ to generate shared-library objects. SHCXX - - + The C++ compiler used for generating shared-library objects. SHCXXCOM - - + The command line used to compile a C++ source file to a shared-library object file. -Any options specified in the $SHCXXFLAGS and -$CPPFLAGS construction variables +Any options specified in the $SHCXXFLAGS and +$CPPFLAGS construction variables are included on this command line. SHCXXCOMSTR - - + The string displayed when a C++ source file is compiled to a shared object file. -If this is not set, then $SHCXXCOM (the command line) is displayed. +If this is not set, then $SHCXXCOM (the command line) is displayed. - + env = Environment(SHCXXCOMSTR = "Compiling shared object $TARGET") SHCXXFLAGS - - + Options that are passed to the C++ compiler to generate shared-library objects. @@ -5919,8 +5481,7 @@ to generate shared-library objects. SHDC - - + The name of the compiler to use when compiling D source destined to be in a shared objects. @@ -5928,32 +5489,28 @@ destined to be in a shared objects. SHDCOM - - + The command line to use when compiling code to be part of shared objects. SHDLIBVERSION - - + SHDLIBVERSION. SHDLIBVERSIONFLAGS - - + SHDLIBVERSIONFLAGS. SHDLINK - - + The linker to use when creating shared objects for code bases include D sources. @@ -5961,55 +5518,50 @@ include D sources. SHDLINKCOM - - + The command line to use when generating shared objects. SHDLINKFLAGS - - + The list of flags to use when generating a shared object. SHELL - - + A string naming the shell program that will be passed to the -$SPAWN +$SPAWN function. See the -$SPAWN +$SPAWN construction variable for more information. SHF03 - - + The Fortran 03 compiler used for generating shared-library objects. -You should normally set the $SHFORTRAN variable, +You should normally set the $SHFORTRAN variable, which specifies the default Fortran compiler for all Fortran versions. -You only need to set $SHF03 if you need to use a specific compiler +You only need to set $SHF03 if you need to use a specific compiler or compiler version for Fortran 03 files. SHF03COM - - + The command line used to compile a Fortran 03 source file to a shared-library object file. -You only need to set $SHF03COM if you need to use a specific +You only need to set $SHF03COM if you need to use a specific command line for Fortran 03 files. -You should normally set the $SHFORTRANCOM variable, +You should normally set the $SHFORTRANCOM variable, which specifies the default command line for all Fortran versions. @@ -6017,24 +5569,22 @@ for all Fortran versions. SHF03COMSTR - - + The string displayed when a Fortran 03 source file is compiled to a shared-library object file. -If this is not set, then $SHF03COM or $SHFORTRANCOM +If this is not set, then $SHF03COM or $SHFORTRANCOM (the command line) is displayed. SHF03FLAGS - - + Options that are passed to the Fortran 03 compiler to generated shared-library objects. -You only need to set $SHF03FLAGS if you need to define specific +You only need to set $SHF03FLAGS if you need to define specific user options for Fortran 03 files. -You should normally set the $SHFORTRANFLAGS variable, +You should normally set the $SHFORTRANFLAGS variable, which specifies the user-specified options passed to the default Fortran compiler for all Fortran versions. @@ -6043,16 +5593,15 @@ for all Fortran versions. SHF03PPCOM - - + The command line used to compile a Fortran 03 source file to a shared-library object file after first running the file through the C preprocessor. -Any options specified in the $SHF03FLAGS and $CPPFLAGS construction variables +Any options specified in the $SHF03FLAGS and $CPPFLAGS construction variables are included on this command line. -You only need to set $SHF03PPCOM if you need to use a specific +You only need to set $SHF03PPCOM if you need to use a specific C-preprocessor command line for Fortran 03 files. -You should normally set the $SHFORTRANPPCOM variable, +You should normally set the $SHFORTRANPPCOM variable, which specifies the default C-preprocessor command line for all Fortran versions. @@ -6060,38 +5609,35 @@ for all Fortran versions. SHF03PPCOMSTR - - + 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 $SHF03PPCOM or $SHFORTRANPPCOM +If this is not set, then $SHF03PPCOM or $SHFORTRANPPCOM (the command line) is displayed. SHF08 - - + The Fortran 08 compiler used for generating shared-library objects. -You should normally set the $SHFORTRAN variable, +You should normally set the $SHFORTRAN variable, which specifies the default Fortran compiler for all Fortran versions. -You only need to set $SHF08 if you need to use a specific compiler +You only need to set $SHF08 if you need to use a specific compiler or compiler version for Fortran 08 files. SHF08COM - - + The command line used to compile a Fortran 08 source file to a shared-library object file. -You only need to set $SHF08COM if you need to use a specific +You only need to set $SHF08COM if you need to use a specific command line for Fortran 08 files. -You should normally set the $SHFORTRANCOM variable, +You should normally set the $SHFORTRANCOM variable, which specifies the default command line for all Fortran versions. @@ -6099,24 +5645,22 @@ for all Fortran versions. SHF08COMSTR - - + The string displayed when a Fortran 08 source file is compiled to a shared-library object file. -If this is not set, then $SHF08COM or $SHFORTRANCOM +If this is not set, then $SHF08COM or $SHFORTRANCOM (the command line) is displayed. SHF08FLAGS - - + Options that are passed to the Fortran 08 compiler to generated shared-library objects. -You only need to set $SHF08FLAGS if you need to define specific +You only need to set $SHF08FLAGS if you need to define specific user options for Fortran 08 files. -You should normally set the $SHFORTRANFLAGS variable, +You should normally set the $SHFORTRANFLAGS variable, which specifies the user-specified options passed to the default Fortran compiler for all Fortran versions. @@ -6125,16 +5669,15 @@ for all Fortran versions. SHF08PPCOM - - + The command line used to compile a Fortran 08 source file to a shared-library object file after first running the file through the C preprocessor. -Any options specified in the $SHF08FLAGS and $CPPFLAGS construction variables +Any options specified in the $SHF08FLAGS and $CPPFLAGS construction variables are included on this command line. -You only need to set $SHF08PPCOM if you need to use a specific +You only need to set $SHF08PPCOM if you need to use a specific C-preprocessor command line for Fortran 08 files. -You should normally set the $SHFORTRANPPCOM variable, +You should normally set the $SHFORTRANPPCOM variable, which specifies the default C-preprocessor command line for all Fortran versions. @@ -6142,38 +5685,35 @@ for all Fortran versions. SHF08PPCOMSTR - - + 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 $SHF08PPCOM or $SHFORTRANPPCOM +If this is not set, then $SHF08PPCOM or $SHFORTRANPPCOM (the command line) is displayed. SHF77 - - + The Fortran 77 compiler used for generating shared-library objects. -You should normally set the $SHFORTRAN variable, +You should normally set the $SHFORTRAN variable, which specifies the default Fortran compiler for all Fortran versions. -You only need to set $SHF77 if you need to use a specific compiler +You only need to set $SHF77 if you need to use a specific compiler or compiler version for Fortran 77 files. SHF77COM - - + The command line used to compile a Fortran 77 source file to a shared-library object file. -You only need to set $SHF77COM if you need to use a specific +You only need to set $SHF77COM if you need to use a specific command line for Fortran 77 files. -You should normally set the $SHFORTRANCOM variable, +You should normally set the $SHFORTRANCOM variable, which specifies the default command line for all Fortran versions. @@ -6181,24 +5721,22 @@ for all Fortran versions. SHF77COMSTR - - + The string displayed when a Fortran 77 source file is compiled to a shared-library object file. -If this is not set, then $SHF77COM or $SHFORTRANCOM +If this is not set, then $SHF77COM or $SHFORTRANCOM (the command line) is displayed. SHF77FLAGS - - + Options that are passed to the Fortran 77 compiler to generated shared-library objects. -You only need to set $SHF77FLAGS if you need to define specific +You only need to set $SHF77FLAGS if you need to define specific user options for Fortran 77 files. -You should normally set the $SHFORTRANFLAGS variable, +You should normally set the $SHFORTRANFLAGS variable, which specifies the user-specified options passed to the default Fortran compiler for all Fortran versions. @@ -6207,16 +5745,15 @@ for all Fortran versions. SHF77PPCOM - - + The command line used to compile a Fortran 77 source file to a shared-library object file after first running the file through the C preprocessor. -Any options specified in the $SHF77FLAGS and $CPPFLAGS construction variables +Any options specified in the $SHF77FLAGS and $CPPFLAGS construction variables are included on this command line. -You only need to set $SHF77PPCOM if you need to use a specific +You only need to set $SHF77PPCOM if you need to use a specific C-preprocessor command line for Fortran 77 files. -You should normally set the $SHFORTRANPPCOM variable, +You should normally set the $SHFORTRANPPCOM variable, which specifies the default C-preprocessor command line for all Fortran versions. @@ -6224,38 +5761,35 @@ for all Fortran versions. SHF77PPCOMSTR - - + 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 $SHF77PPCOM or $SHFORTRANPPCOM +If this is not set, then $SHF77PPCOM or $SHFORTRANPPCOM (the command line) is displayed. SHF90 - - + The Fortran 90 compiler used for generating shared-library objects. -You should normally set the $SHFORTRAN variable, +You should normally set the $SHFORTRAN variable, which specifies the default Fortran compiler for all Fortran versions. -You only need to set $SHF90 if you need to use a specific compiler +You only need to set $SHF90 if you need to use a specific compiler or compiler version for Fortran 90 files. SHF90COM - - + The command line used to compile a Fortran 90 source file to a shared-library object file. -You only need to set $SHF90COM if you need to use a specific +You only need to set $SHF90COM if you need to use a specific command line for Fortran 90 files. -You should normally set the $SHFORTRANCOM variable, +You should normally set the $SHFORTRANCOM variable, which specifies the default command line for all Fortran versions. @@ -6263,24 +5797,22 @@ for all Fortran versions. SHF90COMSTR - - + The string displayed when a Fortran 90 source file is compiled to a shared-library object file. -If this is not set, then $SHF90COM or $SHFORTRANCOM +If this is not set, then $SHF90COM or $SHFORTRANCOM (the command line) is displayed. SHF90FLAGS - - + Options that are passed to the Fortran 90 compiler to generated shared-library objects. -You only need to set $SHF90FLAGS if you need to define specific +You only need to set $SHF90FLAGS if you need to define specific user options for Fortran 90 files. -You should normally set the $SHFORTRANFLAGS variable, +You should normally set the $SHFORTRANFLAGS variable, which specifies the user-specified options passed to the default Fortran compiler for all Fortran versions. @@ -6289,16 +5821,15 @@ for all Fortran versions. SHF90PPCOM - - + The command line used to compile a Fortran 90 source file to a shared-library object file after first running the file through the C preprocessor. -Any options specified in the $SHF90FLAGS and $CPPFLAGS construction variables +Any options specified in the $SHF90FLAGS and $CPPFLAGS construction variables are included on this command line. -You only need to set $SHF90PPCOM if you need to use a specific +You only need to set $SHF90PPCOM if you need to use a specific C-preprocessor command line for Fortran 90 files. -You should normally set the $SHFORTRANPPCOM variable, +You should normally set the $SHFORTRANPPCOM variable, which specifies the default C-preprocessor command line for all Fortran versions. @@ -6306,38 +5837,35 @@ for all Fortran versions. SHF90PPCOMSTR - - + 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 $SHF90PPCOM or $SHFORTRANPPCOM +If this is not set, then $SHF90PPCOM or $SHFORTRANPPCOM (the command line) is displayed. SHF95 - - + The Fortran 95 compiler used for generating shared-library objects. -You should normally set the $SHFORTRAN variable, +You should normally set the $SHFORTRAN variable, which specifies the default Fortran compiler for all Fortran versions. -You only need to set $SHF95 if you need to use a specific compiler +You only need to set $SHF95 if you need to use a specific compiler or compiler version for Fortran 95 files. SHF95COM - - + The command line used to compile a Fortran 95 source file to a shared-library object file. -You only need to set $SHF95COM if you need to use a specific +You only need to set $SHF95COM if you need to use a specific command line for Fortran 95 files. -You should normally set the $SHFORTRANCOM variable, +You should normally set the $SHFORTRANCOM variable, which specifies the default command line for all Fortran versions. @@ -6345,24 +5873,22 @@ for all Fortran versions. SHF95COMSTR - - + The string displayed when a Fortran 95 source file is compiled to a shared-library object file. -If this is not set, then $SHF95COM or $SHFORTRANCOM +If this is not set, then $SHF95COM or $SHFORTRANCOM (the command line) is displayed. SHF95FLAGS - - + Options that are passed to the Fortran 95 compiler to generated shared-library objects. -You only need to set $SHF95FLAGS if you need to define specific +You only need to set $SHF95FLAGS if you need to define specific user options for Fortran 95 files. -You should normally set the $SHFORTRANFLAGS variable, +You should normally set the $SHFORTRANFLAGS variable, which specifies the user-specified options passed to the default Fortran compiler for all Fortran versions. @@ -6371,16 +5897,15 @@ for all Fortran versions. SHF95PPCOM - - + The command line used to compile a Fortran 95 source file to a shared-library object file after first running the file through the C preprocessor. -Any options specified in the $SHF95FLAGS and $CPPFLAGS construction variables +Any options specified in the $SHF95FLAGS and $CPPFLAGS construction variables are included on this command line. -You only need to set $SHF95PPCOM if you need to use a specific +You only need to set $SHF95PPCOM if you need to use a specific C-preprocessor command line for Fortran 95 files. -You should normally set the $SHFORTRANPPCOM variable, +You should normally set the $SHFORTRANPPCOM variable, which specifies the default C-preprocessor command line for all Fortran versions. @@ -6388,28 +5913,25 @@ for all Fortran versions. SHF95PPCOMSTR - - + 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 $SHF95PPCOM or $SHFORTRANPPCOM +If this is not set, then $SHF95PPCOM or $SHFORTRANPPCOM (the command line) is displayed. SHFORTRAN - - + The default Fortran compiler used for generating shared-library objects. SHFORTRANCOM - - + The command line used to compile a Fortran source file to a shared-library object file. @@ -6417,19 +5939,17 @@ to a shared-library object file. SHFORTRANCOMSTR - - + The string displayed when a Fortran source file is compiled to a shared-library object file. -If this is not set, then $SHFORTRANCOM +If this is not set, then $SHFORTRANCOM (the command line) is displayed. SHFORTRANFLAGS - - + Options that are passed to the Fortran compiler to generate shared-library objects. @@ -6437,94 +5957,88 @@ to generate shared-library objects. SHFORTRANPPCOM - - + The command line used to compile a Fortran source file to a shared-library object file after first running the file through the C preprocessor. Any options specified -in the $SHFORTRANFLAGS and -$CPPFLAGS construction variables +in the $SHFORTRANFLAGS and +$CPPFLAGS construction variables are included on this command line. SHFORTRANPPCOMSTR - - + 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 $SHFORTRANPPCOM +If this is not set, then $SHFORTRANPPCOM (the command line) is displayed. SHLIBEMITTER - - -TODO + +Contains the emitter specification for the +SharedLibrary builder. +The manpage section "Builder Objects" contains +general information on specifying emitters. SHLIBNOVERSIONSYMLINKS - - -Instructs the SharedLibrary builder to not create symlinks for versioned + +Instructs the SharedLibrary builder to not create symlinks for versioned shared libraries. SHLIBPREFIX - - + The prefix used for shared library file names. _SHLIBSONAME - - + A macro that automatically generates shared library's SONAME based on $TARGET, -$SHLIBVERSION and $SHLIBSUFFIX. Used by SharedLibrary builder when -the linker tool supports SONAME (e.g. gnulink). +$SHLIBVERSION and $SHLIBSUFFIX. Used by SharedLibrary builder when +the linker tool supports SONAME (e.g. gnulink). SHLIBSUFFIX - - + The suffix used for shared library file names. SHLIBVERSION - - + When this construction variable is defined, a versioned shared library -is created by SharedLibrary builder. This activates the -$_SHLIBVERSIONFLAGS and thus modifies the $SHLINKCOM as +is created by the SharedLibrary builder. This activates the +$_SHLIBVERSIONFLAGS and thus modifies the $SHLINKCOM as required, adds the version number to the library name, and creates the symlinks -that are needed. $SHLIBVERSION versions should exist as alpha-numeric, +that are needed. $SHLIBVERSION versions should exist as alpha-numeric, decimal-delimited values as defined by the regular expression "\w+[\.\w+]*". -Example $SHLIBVERSION values include '1', '1.2.3', and '1.2.gitaa412c8b'. +Example $SHLIBVERSION values include '1', '1.2.3', and '1.2.gitaa412c8b'. _SHLIBVERSIONFLAGS - - -This macro automatically introduces extra flags to $SHLINKCOM when -building versioned SharedLibrary (that is when $SHLIBVERSION -is set). _SHLIBVERSIONFLAGS usually adds $SHLIBVERSIONFLAGS + +This macro automatically introduces extra flags to $SHLINKCOM when +building versioned SharedLibrary (that is when $SHLIBVERSION +is set). _SHLIBVERSIONFLAGS usually adds $SHLIBVERSIONFLAGS and some extra dynamically generated options (such as -Wl,-soname=$_SHLIBSONAME. It is unused by "plain" (unversioned) shared libraries. @@ -6533,63 +6047,58 @@ and some extra dynamically generated options (such as SHLIBVERSIONFLAGS - - -Extra flags added to $SHLINKCOM when building versioned -SharedLibrary. These flags are only used when $SHLIBVERSION is + +Extra flags added to $SHLINKCOM when building versioned +SharedLibrary. These flags are only used when $SHLIBVERSION is set. SHLINK - - + The linker for programs that use shared libraries. SHLINKCOM - - + The command line used to link programs using shared libraries. SHLINKCOMSTR - - + The string displayed when programs using shared libraries are linked. -If this is not set, then $SHLINKCOM (the command line) is displayed. +If this is not set, then $SHLINKCOM (the command line) is displayed. - + env = Environment(SHLINKCOMSTR = "Linking shared $TARGET") SHLINKFLAGS - - + General user options passed to the linker for programs using shared libraries. Note that this variable should not contain -(or similar) options for linking with the libraries listed in $LIBS, +(or similar) options for linking with the libraries listed in $LIBS, nor (or similar) include search path options -that scons generates automatically from $LIBPATH. +that scons generates automatically from $LIBPATH. See -$_LIBFLAGS +$_LIBFLAGS above, for the variable that expands to library-link options, and -$_LIBDIRFLAGS +$_LIBDIRFLAGS above, for the variable that expands to library search path options. @@ -6597,46 +6106,42 @@ for the variable that expands to library search path options. SHOBJPREFIX - - + The prefix used for shared object file names. SHOBJSUFFIX - - + The suffix used for shared object file names. SONAME - - + Variable used to hard-code SONAME for versioned shared library/loadable module. env.SharedLibrary('test', 'test.c', SHLIBVERSION='0.1.2', SONAME='libtest.so.2') -The variable is used, for example, by gnulink linker tool. +The variable is used, for example, by gnulink linker tool. SOURCE - - + A reserved variable name that may not be set or used in a construction environment. -(See "Variable Substitution," below.) +(See the manpage section "Variable Substitution" +for more information). SOURCE_URL - - + The URL (web address) of the location from which the project was retrieved. @@ -6648,27 +6153,26 @@ field in the controlling information for Ipkg and RPM packages. SOURCES - - + A reserved variable name that may not be set or used in a construction environment. -(See "Variable Substitution," below.) +(See the manpage section "Variable Substitution" +for more information). SPAWN - - + A command interpreter function that will be called to execute command line strings. The function must expect the following arguments: - + def spawn(shell, escape, cmd, args, env): - + sh is a string naming the shell program to use. escape @@ -6686,17 +6190,15 @@ in which the command should be executed. STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME - - + When this variable is true, static objects and shared objects are assumed to be the same; that is, SCons does not check for linking static objects into a shared library. SUBST_DICT - - -The dictionary used by the Substfile or Textfile builders + +The dictionary used by the Substfile or Textfile builders for substitution values. It can be anything acceptable to the dict() constructor, so in addition to a dictionary, @@ -6706,26 +6208,23 @@ lists of tuples are also acceptable. SUBSTFILEPREFIX - - -The prefix used for Substfile file names, + +The prefix used for Substfile file names, the null string by default. SUBSTFILESUFFIX - - -The suffix used for Substfile file names, + +The suffix used for Substfile file names, the null string by default. SUMMARY - - + A short summary of what the project is about. This is used to fill in the Summary: @@ -6738,35 +6237,32 @@ field in MSI packages. SWIG - - + The scripting language wrapper and interface generator. SWIGCFILESUFFIX - - + The suffix that will be used for intermediate C source files generated by the scripting language wrapper and interface generator. The default value is -_wrap$CFILESUFFIX. +_wrap$CFILESUFFIX. By default, this value is used whenever the option is not specified as part of the -$SWIGFLAGS +$SWIGFLAGS construction variable. SWIGCOM - - + The command line used to call the scripting language wrapper and interface generator. @@ -6774,35 +6270,32 @@ the scripting language wrapper and interface generator. SWIGCOMSTR - - + The string displayed when calling the scripting language wrapper and interface generator. -If this is not set, then $SWIGCOM (the command line) is displayed. +If this is not set, then $SWIGCOM (the command line) is displayed. SWIGCXXFILESUFFIX - - + The suffix that will be used for intermediate C++ source files generated by the scripting language wrapper and interface generator. The default value is -_wrap$CFILESUFFIX. +_wrap$CFILESUFFIX. By default, this value is used whenever the -c++ option is specified as part of the -$SWIGFLAGS +$SWIGFLAGS construction variable. SWIGDIRECTORSUFFIX - - + The suffix that will be used for intermediate C++ header files generated by the scripting language wrapper and interface generator. These are only generated for C++ code when the SWIG 'directors' feature is @@ -6814,8 +6307,7 @@ The default value is SWIGFLAGS - - + General options passed to the scripting language wrapper and interface generator. This is where you should set @@ -6826,61 +6318,57 @@ or whatever other options you want to specify to SWIG. If you set the option in this variable, -scons +scons will, by default, generate a C++ intermediate source file with the extension that is specified as the -$CXXFILESUFFIX +$CXXFILESUFFIX variable. _SWIGINCFLAGS - - + An automatically-generated construction variable containing the SWIG command-line options for specifying directories to be searched for included files. -The value of $_SWIGINCFLAGS is created +The value of $_SWIGINCFLAGS is created by respectively prepending and appending -$SWIGINCPREFIX and $SWIGINCSUFFIX +$SWIGINCPREFIX and $SWIGINCSUFFIX to the beginning and end -of each directory in $SWIGPATH. +of each directory in $SWIGPATH. SWIGINCPREFIX - - + The prefix used to specify an include directory on the SWIG command line. This will be prepended to the beginning of each directory -in the $SWIGPATH construction variable -when the $_SWIGINCFLAGS variable is automatically generated. +in the $SWIGPATH construction variable +when the $_SWIGINCFLAGS variable is automatically generated. SWIGINCSUFFIX - - + The suffix used to specify an include directory on the SWIG command line. This will be appended to the end of each directory -in the $SWIGPATH construction variable -when the $_SWIGINCFLAGS variable is automatically generated. +in the $SWIGPATH construction variable +when the $_SWIGINCFLAGS variable is automatically generated. SWIGOUTDIR - - + Specifies the output directory in which the scripting language wrapper and interface generator should place generated language-specific files. This will be used by SCons to identify -the files that will be generated by the swig call, +the files that will be generated by the swig call, and translated into the swig -outdir option on the command line. @@ -6888,15 +6376,14 @@ and translated into the SWIGPATH - - + The list of directories that the scripting language wrapper and interface generate will search for included files. The SWIG implicit dependency scanner will search these directories for include files. The default value is an empty list. - + Don't explicitly put include directory arguments in SWIGFLAGS; the result will be non-portable @@ -6904,116 +6391,103 @@ and the directories will not be searched by the dependency scanner. Note: directory names in SWIGPATH will be looked-up relative to the SConscript directory when they are used in a command. To force -scons +scons to look-up a directory relative to the root of the source tree use #: - + env = Environment(SWIGPATH='#/include') - + The directory look-up can also be forced using the -Dir() +Dir() function: - + include = Dir('include') env = Environment(SWIGPATH=include) - + The directory list will be added to command lines through the automatically-generated -$_SWIGINCFLAGS +$_SWIGINCFLAGS construction variable, which is constructed by respectively prepending and appending the values of the -$SWIGINCPREFIX and $SWIGINCSUFFIX +$SWIGINCPREFIX and $SWIGINCSUFFIX construction variables to the beginning and end -of each directory in $SWIGPATH. +of each directory in $SWIGPATH. Any command lines you define that need the SWIGPATH directory list should -include $_SWIGINCFLAGS: +include $_SWIGINCFLAGS: - + env = Environment(SWIGCOM="my_swig -o $TARGET $_SWIGINCFLAGS $SOURCES") SWIGVERSION - - + The version number of the SWIG tool. TAR - - + The tar archiver. TARCOM - - + The command line used to call the tar archiver. TARCOMSTR - - + The string displayed when archiving files using the tar archiver. -If this is not set, then $TARCOM (the command line) is displayed. +If this is not set, then $TARCOM (the command line) is displayed. - + env = Environment(TARCOMSTR = "Archiving $TARGET") TARFLAGS - - + General options passed to the tar archiver. TARGET - - + A reserved variable name that may not be set or used in a construction environment. -(See "Variable Substitution," below.) +(See the manpage section "Variable Substitution" +for more information). TARGET_ARCH - - - The name of the target hardware architecture for the compiled objects - created by this Environment. - This defaults to the value of HOST_ARCH, and the user can override it. - Currently only set for Win32. - - - + Sets the target architecture for Visual Studio compiler (i.e. the arch of the binaries generated by the compiler). If not set, default to -$HOST_ARCH, or, if that is unset, to the architecture of the +$HOST_ARCH, or, if that is unset, to the architecture of the running machine's OS (note that the python build or architecture has no effect). This variable must be passed as an argument to the Environment() @@ -7025,7 +6499,7 @@ all installed MSVC's that support the TARGET_ARCH, selecting the latest version for use. - + Valid values for Windows are x86, arm, @@ -7041,12 +6515,17 @@ and ia64 (Itanium). For example, if you want to compile 64-bit binaries, you would set TARGET_ARCH='x86_64' in your SCons environment. - + + The name of the target hardware architecture for the compiled objects + created by this Environment. + This defaults to the value of HOST_ARCH, and the user can override it. + Currently only set for Win32. + + TARGET_OS - - + The name of the target operating system for the compiled objects created by this Environment. This defaults to the value of HOST_OS, and the user can override it. @@ -7056,27 +6535,25 @@ For example, if you want to compile 64-bit binaries, you would set TARGETS - - + A reserved variable name that may not be set or used in a construction environment. -(See "Variable Substitution," below.) +(See the manpage section "Variable Substitution" +for more information). TARSUFFIX - - + The suffix used for tar file names. TEMPFILEARGJOIN - - -The string (or character) to be used to join the arguments passed to TEMPFILE when command line exceeds the limit set by $MAXLINELENGTH. + +The string (or character) to be used to join the arguments passed to TEMPFILE when command line exceeds the limit set by $MAXLINELENGTH. The default value is a space. However for MSVC, MSLINK the default is a line seperator characters as defined by os.linesep. Note this value is used literally and not expanded by the subst logic. @@ -7084,8 +6561,7 @@ Note this value is used literally and not expanded by the subst logic. TEMPFILEPREFIX - - + The prefix for a temporary file used to store lines lines longer than $MAXLINELENGTH as operations which call out to a shell will fail @@ -7101,8 +6577,7 @@ or '-via' for ARM toolchain. TEMPFILESUFFIX - - + The suffix used for the temporary file name used for long command lines. The name should include the dot ('.') if one is wanted as @@ -7113,46 +6588,41 @@ The default is '.lnk'. TEX - - + The TeX formatter and typesetter. TEXCOM - - + The command line used to call the TeX formatter and typesetter. TEXCOMSTR - - + The string displayed when calling the TeX formatter and typesetter. -If this is not set, then $TEXCOM (the command line) is displayed. +If this is not set, then $TEXCOM (the command line) is displayed. - + env = Environment(TEXCOMSTR = "Building $TARGET from TeX input $SOURCES") TEXFLAGS - - + General options passed to the TeX formatter and typesetter. TEXINPUTS - - + List of directories that the LaTeX program will search for include directories. The LaTeX implicit dependency scanner will search these @@ -7162,26 +6632,23 @@ directories for \include and \import files. TEXTFILEPREFIX - - -The prefix used for Textfile file names, + +The prefix used for Textfile file names, the null string by default. TEXTFILESUFFIX - - -The suffix used for Textfile file names; + +The suffix used for Textfile file names; .txt by default. TOOLS - - + A list of the names of the Tool specifications that are part of this construction environment. @@ -7189,28 +6656,27 @@ that are part of this construction environment. UNCHANGED_SOURCES - - + A reserved variable name that may not be set or used in a construction environment. -(See "Variable Substitution," below.) +(See the manpage section "Variable Substitution" +for more information). UNCHANGED_TARGETS - - + A reserved variable name that may not be set or used in a construction environment. -(See "Variable Substitution," below.) +(See the manpage section "Variable Substitution" +for more information). VENDOR - - + The person or organization who supply the packaged software. This is used to fill in the Vendor: @@ -7223,68 +6689,60 @@ field in the controlling information for MSI packages. VERSION - - + The version of the project, specified as a string. WIN32_INSERT_DEF - - -A deprecated synonym for $WINDOWS_INSERT_DEF. + +A deprecated synonym for $WINDOWS_INSERT_DEF. WIN32DEFPREFIX - - -A deprecated synonym for $WINDOWSDEFPREFIX. + +A deprecated synonym for $WINDOWSDEFPREFIX. WIN32DEFSUFFIX - - -A deprecated synonym for $WINDOWSDEFSUFFIX. + +A deprecated synonym for $WINDOWSDEFSUFFIX. WIN32EXPPREFIX - - -A deprecated synonym for $WINDOWSEXPSUFFIX. + +A deprecated synonym for $WINDOWSEXPSUFFIX. WIN32EXPSUFFIX - - -A deprecated synonym for $WINDOWSEXPSUFFIX. + +A deprecated synonym for $WINDOWSEXPSUFFIX. WINDOWS_EMBED_MANIFEST - - + Set this variable to True or 1 to embed the compiler-generated manifest (normally ${TARGET}.manifest) into all Windows exes and DLLs built with this environment, as a resource during their link step. -This is done using $MT and $MTEXECOM and $MTSHLIBCOM. +This is done using $MT and $MTEXECOM and $MTSHLIBCOM. WINDOWS_INSERT_DEF - - + When this is set to true, a library build of a Windows shared library (.dll file) @@ -7298,10 +6756,9 @@ The default is 0 (do not build a .def file). WINDOWS_INSERT_MANIFEST - - + When this is set to true, -scons +scons will be aware of the .manifest files generated by Microsoft Visua C/C++ 8. @@ -7310,40 +6767,35 @@ files generated by Microsoft Visua C/C++ 8. WINDOWSDEFPREFIX - - + The prefix used for Windows .def file names. WINDOWSDEFSUFFIX - - + The suffix used for Windows .def file names. WINDOWSEXPPREFIX - - + The prefix used for Windows .exp file names. WINDOWSEXPSUFFIX - - + The suffix used for Windows .exp file names. WINDOWSPROGMANIFESTPREFIX - - + The prefix used for executable program .manifest files generated by Microsoft Visual C/C++. @@ -7351,8 +6803,7 @@ generated by Microsoft Visual C/C++. WINDOWSPROGMANIFESTSUFFIX - - + The suffix used for executable program .manifest files generated by Microsoft Visual C/C++. @@ -7360,8 +6811,7 @@ generated by Microsoft Visual C/C++. WINDOWSSHLIBMANIFESTPREFIX - - + The prefix used for shared library .manifest files generated by Microsoft Visual C/C++. @@ -7369,8 +6819,7 @@ generated by Microsoft Visual C/C++. WINDOWSSHLIBMANIFESTSUFFIX - - + The suffix used for shared library .manifest files generated by Microsoft Visual C/C++. @@ -7378,8 +6827,7 @@ generated by Microsoft Visual C/C++. X_IPK_DEPENDS - - + This is used to fill in the Depends: field in the controlling information for Ipkg packages. @@ -7388,8 +6836,7 @@ field in the controlling information for Ipkg packages. X_IPK_DESCRIPTION - - + This is used to fill in the Description: field in the controlling information for Ipkg packages. @@ -7400,8 +6847,7 @@ The default value is X_IPK_MAINTAINER - - + This is used to fill in the Maintainer: field in the controlling information for Ipkg packages. @@ -7410,8 +6856,7 @@ field in the controlling information for Ipkg packages. X_IPK_PRIORITY - - + This is used to fill in the Priority: field in the controlling information for Ipkg packages. @@ -7420,8 +6865,7 @@ field in the controlling information for Ipkg packages. X_IPK_SECTION - - + This is used to fill in the Section: field in the controlling information for Ipkg packages. @@ -7430,8 +6874,7 @@ field in the controlling information for Ipkg packages. X_MSI_LANGUAGE - - + This is used to fill in the Language: attribute in the controlling information for MSI packages. @@ -7440,8 +6883,7 @@ attribute in the controlling information for MSI packages. X_MSI_LICENSE_TEXT - - + The text of the software license in RTF format. Carriage return characters will be replaced with the RTF equivalent \\par. @@ -7450,16 +6892,14 @@ replaced with the RTF equivalent \\par. X_MSI_UPGRADE_CODE - - + TODO X_RPM_AUTOREQPROV - - + This is used to fill in the AutoReqProv: field in the RPM @@ -7469,16 +6909,14 @@ field in the RPM X_RPM_BUILD - - + internal, but overridable X_RPM_BUILDREQUIRES - - + This is used to fill in the BuildRequires: field in the RPM @@ -7489,24 +6927,21 @@ Note this should only be used on a host managed by rpm as the dependencies will X_RPM_BUILDROOT - - + internal, but overridable X_RPM_CLEAN - - + internal, but overridable X_RPM_CONFLICTS - - + This is used to fill in the Conflicts: field in the RPM @@ -7516,8 +6951,7 @@ field in the RPM X_RPM_DEFATTR - - + This value is used as the default attributes for the files in the RPM package. The default value is @@ -7527,8 +6961,7 @@ The default value is X_RPM_DISTRIBUTION - - + This is used to fill in the Distribution: field in the RPM @@ -7538,8 +6971,7 @@ field in the RPM X_RPM_EPOCH - - + This is used to fill in the Epoch: field in the RPM @@ -7549,8 +6981,7 @@ field in the RPM X_RPM_EXCLUDEARCH - - + This is used to fill in the ExcludeArch: field in the RPM @@ -7560,8 +6991,7 @@ field in the RPM X_RPM_EXLUSIVEARCH - - + This is used to fill in the ExclusiveArch: field in the RPM @@ -7571,8 +7001,7 @@ field in the RPM X_RPM_EXTRADEFS - - + A list used to supply extra defintions or flags to be added to the RPM .spec file. Each item is added as-is with a carriage return appended. @@ -7588,7 +7017,7 @@ list that does not include the default line. Added in version 3.1. - + env.Package( NAME = 'foo', ... @@ -7603,8 +7032,7 @@ env.Package( X_RPM_GROUP - - + This is used to fill in the Group: field in the RPM @@ -7614,8 +7042,7 @@ field in the RPM X_RPM_GROUP_lang - - + This is used to fill in the Group(lang): field in the RPM @@ -7630,8 +7057,7 @@ the appropriate language code. X_RPM_ICON - - + This is used to fill in the Icon: field in the RPM @@ -7641,16 +7067,14 @@ field in the RPM X_RPM_INSTALL - - + internal, but overridable X_RPM_PACKAGER - - + This is used to fill in the Packager: field in the RPM @@ -7660,8 +7084,7 @@ field in the RPM X_RPM_POSTINSTALL - - + This is used to fill in the %post: section in the RPM @@ -7671,8 +7094,7 @@ section in the RPM X_RPM_POSTUNINSTALL - - + This is used to fill in the %postun: section in the RPM @@ -7682,8 +7104,7 @@ section in the RPM X_RPM_PREFIX - - + This is used to fill in the Prefix: field in the RPM @@ -7693,8 +7114,7 @@ field in the RPM X_RPM_PREINSTALL - - + This is used to fill in the %pre: section in the RPM @@ -7704,16 +7124,14 @@ section in the RPM X_RPM_PREP - - + internal, but overridable X_RPM_PREUNINSTALL - - + This is used to fill in the %preun: section in the RPM @@ -7723,8 +7141,7 @@ section in the RPM X_RPM_PROVIDES - - + This is used to fill in the Provides: field in the RPM @@ -7734,8 +7151,7 @@ field in the RPM X_RPM_REQUIRES - - + This is used to fill in the Requires: field in the RPM @@ -7745,8 +7161,7 @@ field in the RPM X_RPM_SERIAL - - + This is used to fill in the Serial: field in the RPM @@ -7756,8 +7171,7 @@ field in the RPM X_RPM_URL - - + This is used to fill in the Url: field in the RPM @@ -7767,37 +7181,33 @@ field in the RPM XGETTEXT - - + Path to xgettext(1) program (found via Detect()). -See xgettext tool and POTUpdate builder. +See xgettext tool and POTUpdate builder. XGETTEXTCOM - - + Complete xgettext command line. -See xgettext tool and POTUpdate builder. +See xgettext tool and POTUpdate builder. XGETTEXTCOMSTR - - + A string that is shown when xgettext(1) command is invoked -(default: '', which means "print $XGETTEXTCOM"). -See xgettext tool and POTUpdate builder. +(default: '', which means "print $XGETTEXTCOM"). +See xgettext tool and POTUpdate builder. _XGETTEXTDOMAIN - - + Internal "macro". Generates xgettext domain name form source and target (default: '${TARGET.filebase}'). @@ -7805,40 +7215,36 @@ form source and target (default: '${TARGET.filebase}'). XGETTEXTFLAGS - - + Additional flags to xgettext(1). -See xgettext tool and POTUpdate builder. +See xgettext tool and POTUpdate builder. XGETTEXTFROM - - + Name of file containing list of xgettext(1)'s source files. Autotools' users know this as POTFILES.in so they will in most cases set XGETTEXTFROM="POTFILES.in" here. -The $XGETTEXTFROM files have same syntax and semantics as the well known +The $XGETTEXTFROM files have same syntax and semantics as the well known GNU POTFILES.in. -See xgettext tool and POTUpdate builder. +See xgettext tool and POTUpdate builder. _XGETTEXTFROMFLAGS - - + Internal "macro". Genrates list of -D<dir> flags -from the $XGETTEXTPATH list. +from the $XGETTEXTPATH list. XGETTEXTFROMPREFIX - - -This flag is used to add single $XGETTEXTFROM file to + +This flag is used to add single $XGETTEXTFROM file to xgettext(1)'s commandline (default: '-f'). @@ -7846,38 +7252,34 @@ This flag is used to add single XGETTEXTFROMSUFFIX - - + (default: '') XGETTEXTPATH - - + List of directories, there xgettext(1) will look for source files (default: []). -This variable works only together with $XGETTEXTFROM +This variable works only together with $XGETTEXTFROM -See also xgettext tool and POTUpdate builder. +See also xgettext tool and POTUpdate builder. _XGETTEXTPATHFLAGS - - + Internal "macro". Generates list of -f<file> flags -from $XGETTEXTFROM. +from $XGETTEXTFROM. XGETTEXTPATHPREFIX - - + This flag is used to add single search path to xgettext(1)'s commandline (default: '-D'). @@ -7886,24 +7288,21 @@ This flag is used to add single search path to XGETTEXTPATHSUFFIX - - + (default: '') YACC - - + The parser generator. YACCCOM - - + The command line used to call the parser generator to generate a source file. @@ -7911,24 +7310,22 @@ to generate a source file. YACCCOMSTR - - + The string displayed when generating a source file using the parser generator. -If this is not set, then $YACCCOM (the command line) is displayed. +If this is not set, then $YACCCOM (the command line) is displayed. - + env = Environment(YACCCOMSTR = "Yacc'ing $TARGET from $SOURCES") YACCFLAGS - - + General options passed to the parser generator. -If $YACCFLAGS contains a option, +If $YACCFLAGS contains a option, SCons assumes that the call will also create a .h file (if the yacc source file ends in a .y suffix) or a .hpp file @@ -7938,8 +7335,7 @@ or a .hpp file YACCHFILESUFFIX - - + The suffix of the C header file generated by the parser generator when the @@ -7957,8 +7353,7 @@ The default value is YACCHXXFILESUFFIX - - + The suffix of the C++ header file generated by the parser generator when the @@ -7974,7 +7369,7 @@ The default value is except on Mac OS X, where the default is ${TARGET.suffix}.h. -because the default bison parser generator just +because the default bison parser generator just appends .h to the name of the generated C++ file. @@ -7982,8 +7377,7 @@ to the name of the generated C++ file. YACCVCGFILESUFFIX - - + The suffix of the file containing the VCG grammar automaton definition when the @@ -8001,16 +7395,14 @@ The default value is ZIP - - + The zip compression and file packaging utility. ZIPCOM - - + The command line used to call the zip utility, or the internal Python function used to create a zip archive. @@ -8019,8 +7411,7 @@ zip archive. ZIPCOMPRESSION - - + The compression flag @@ -8040,42 +7431,39 @@ module is unavailable. ZIPCOMSTR - - + The string displayed when archiving files using the zip utility. -If this is not set, then $ZIPCOM +If this is not set, then $ZIPCOM (the command line or internal Python function) is displayed. - + env = Environment(ZIPCOMSTR = "Zipping $TARGET") ZIPFLAGS - - + General options passed to the zip utility. ZIPROOT - - + An optional zip root directory (default empty). The filenames stored in the zip file will be relative to this directory, if given. Otherwise the filenames are relative to the current directory of the command. For instance: - + env = Environment() env.Zip('foo.zip', 'subdir1/subdir2/file1', ZIPROOT='subdir1') - + will produce a zip file foo.zip containing a file with the name subdir2/file1 rather than @@ -8085,8 +7473,7 @@ containing a file with the name ZIPSUFFIX - - + The suffix used for zip file names. diff --git a/doc/generated/variables.mod b/doc/generated/variables.mod index 372a15f..b26a645 100644 --- a/doc/generated/variables.mod +++ b/doc/generated/variables.mod @@ -10,10 +10,10 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $__LDMODULEVERSIONFLAGS"> $__SHLIBVERSIONFLAGS"> -$_APPLELINK_COMPATIBILITY_VERSION"> $APPLELINK_COMPATIBILITY_VERSION"> -$_APPLELINK_CURRENT_VERSION"> +$_APPLELINK_COMPATIBILITY_VERSION"> $APPLELINK_CURRENT_VERSION"> +$_APPLELINK_CURRENT_VERSION"> $APPLELINK_NO_COMPATIBILITY_VERSION"> $APPLELINK_NO_CURRENT_VERSION"> $AR"> @@ -200,8 +200,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $_FRAMEWORKPATH"> $FRAMEWORKPATHPREFIX"> $FRAMEWORKPREFIX"> -$_FRAMEWORKS"> $FRAMEWORKS"> +$_FRAMEWORKS"> $FRAMEWORKSFLAGS"> $GS"> $GSCOM"> @@ -251,14 +251,15 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $LDMODULE"> $LDMODULECOM"> $LDMODULECOMSTR"> +$LDMODULEEMITTER"> $LDMODULEFLAGS"> $LDMODULENOVERSIONSYMLINKS"> $LDMODULEPREFIX"> $_LDMODULESONAME"> $LDMODULESUFFIX"> $LDMODULEVERSION"> -$LDMODULEVERSIONFLAGS"> $_LDMODULEVERSIONFLAGS"> +$LDMODULEVERSIONFLAGS"> $LEX"> $LEXCOM"> $LEXCOMSTR"> @@ -433,8 +434,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $RMICCOM"> $RMICCOMSTR"> $RMICFLAGS"> -$_RPATH"> $RPATH"> +$_RPATH"> $RPATHPREFIX"> $RPATHSUFFIX"> $RPCGEN"> @@ -504,8 +505,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $_SHLIBSONAME"> $SHLIBSUFFIX"> $SHLIBVERSION"> -$SHLIBVERSIONFLAGS"> $_SHLIBVERSIONFLAGS"> +$SHLIBVERSIONFLAGS"> $SHLINK"> $SHLINKCOM"> $SHLINKCOMSTR"> @@ -650,10 +651,10 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $__LDMODULEVERSIONFLAGS"> $__SHLIBVERSIONFLAGS"> -$_APPLELINK_COMPATIBILITY_VERSION"> $APPLELINK_COMPATIBILITY_VERSION"> -$_APPLELINK_CURRENT_VERSION"> +$_APPLELINK_COMPATIBILITY_VERSION"> $APPLELINK_CURRENT_VERSION"> +$_APPLELINK_CURRENT_VERSION"> $APPLELINK_NO_COMPATIBILITY_VERSION"> $APPLELINK_NO_CURRENT_VERSION"> $AR"> @@ -840,8 +841,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $_FRAMEWORKPATH"> $FRAMEWORKPATHPREFIX"> $FRAMEWORKPREFIX"> -$_FRAMEWORKS"> $FRAMEWORKS"> +$_FRAMEWORKS"> $FRAMEWORKSFLAGS"> $GS"> $GSCOM"> @@ -891,14 +892,15 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $LDMODULE"> $LDMODULECOM"> $LDMODULECOMSTR"> +$LDMODULEEMITTER"> $LDMODULEFLAGS"> $LDMODULENOVERSIONSYMLINKS"> $LDMODULEPREFIX"> $_LDMODULESONAME"> $LDMODULESUFFIX"> $LDMODULEVERSION"> -$LDMODULEVERSIONFLAGS"> $_LDMODULEVERSIONFLAGS"> +$LDMODULEVERSIONFLAGS"> $LEX"> $LEXCOM"> $LEXCOMSTR"> @@ -1073,8 +1075,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $RMICCOM"> $RMICCOMSTR"> $RMICFLAGS"> -$_RPATH"> $RPATH"> +$_RPATH"> $RPATHPREFIX"> $RPATHSUFFIX"> $RPCGEN"> @@ -1144,8 +1146,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $_SHLIBSONAME"> $SHLIBSUFFIX"> $SHLIBVERSION"> -$SHLIBVERSIONFLAGS"> $_SHLIBVERSIONFLAGS"> +$SHLIBVERSIONFLAGS"> $SHLINK"> $SHLINKCOM"> $SHLINKCOMSTR"> -- cgit v0.12 From 16f42198ba3afe2e40b21c5627274fec48c8611e Mon Sep 17 00:00:00 2001 From: Jason Kenny Date: Fri, 6 Dec 2019 11:00:25 -0600 Subject: add py3 compatible print() functions --- test/Command.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Command.py b/test/Command.py index 380c171..7189d06 100644 --- a/test/Command.py +++ b/test/Command.py @@ -21,7 +21,6 @@ # 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 @@ -43,6 +42,7 @@ test.write('build.py', build_py) test.write(['expand_chdir_sub', 'subbuild.py'], build_py) test.write('SConstruct', """ +from __future__ import print_function import os import sys -- cgit v0.12 From ed66f1338f029a63b7a93f7027f3149ab5376bdd Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Fri, 6 Dec 2019 16:43:52 -0500 Subject: Fix multithreaded Windows builds when a thread has a file open for write Python 2 enables handle inheritance by default for child processes. It wasn't until Python 3.4 that it was disabled. This causes problems because if a Python action is writing to a file and a child process is spawned at that exact moment, builds fail because of sharing issues. --- src/engine/SCons/Platform/win32.py | 59 ++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/src/engine/SCons/Platform/win32.py b/src/engine/SCons/Platform/win32.py index 0a3b199..c0cf03b 100644 --- a/src/engine/SCons/Platform/win32.py +++ b/src/engine/SCons/Platform/win32.py @@ -51,10 +51,6 @@ try: import msvcrt import win32api import win32con - - msvcrt.get_osfhandle - win32api.SetHandleInformation - win32con.HANDLE_FLAG_INHERIT except ImportError: parallel_msg = \ "you do not seem to have the pywin32 extensions installed;\n" + \ @@ -66,28 +62,41 @@ except AttributeError: else: parallel_msg = None - _builtin_open = open - - def _scons_open(*args, **kw): - fp = _builtin_open(*args, **kw) - win32api.SetHandleInformation(msvcrt.get_osfhandle(fp.fileno()), - win32con.HANDLE_FLAG_INHERIT, - 0) - return fp - - open = _scons_open - if sys.version_info.major == 2: - _builtin_file = file - class _scons_file(_builtin_file): - def __init__(self, *args, **kw): - _builtin_file.__init__(self, *args, **kw) - win32api.SetHandleInformation(msvcrt.get_osfhandle(self.fileno()), - win32con.HANDLE_FLAG_INHERIT, 0) - file = _scons_file - else: - # No longer needed for python 3.4 and above. Files are opened non sharable - pass + import __builtin__ + + _builtin_file = __builtin__.file + _builtin_open = __builtin__.open + + def _scons_fixup_mode(mode): + """Adjust 'mode' to mark handle as non-inheritable. + + SCons is multithreaded, so allowing handles to be inherited by + children opens us up to races, where (e.g.) processes spawned by + the Taskmaster may inherit and retain references to files opened + by other threads. This may lead to sharing violations and, + ultimately, build failures. + + By including 'N' as part of fopen's 'mode' parameter, all file + handles returned from these functions are atomically marked as + non-inheritable. + """ + if not mode: + # Python's default is 'r'. + # https://docs.python.org/2/library/functions.html#open + mode = 'rN' + elif 'N' not in mode: + mode += 'N' + return mode + + def _scons_file(name, mode=None, *args, **kwargs): + return _builtin_file(name, _scons_fixup_mode(mode), *args, **kwargs) + + def _scons_open(name, mode=None, *args, **kwargs): + return _builtin_open(name, _scons_fixup_mode(mode), *args, **kwargs) + + __builtin__.file = _scons_file + __builtin__.open = _scons_open -- cgit v0.12 From 3b9e2a859177952ecec8370e56a5ecfc29d307b1 Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Fri, 6 Dec 2019 16:55:16 -0500 Subject: Change src\CHANGES.txt --- src/CHANGES.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index e24555d..1c05960 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -16,6 +16,11 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER From Tim Gates - Resolved a typo in engine.SCons.Tool + From Adam Gross: + - Resolved a race condition in multithreaded Windows builds with Python 2 + in the case where a child process is spawned while a Python action has a + file open. + From Ivan Kravets - Added support for "-imacros" to ParseFlags -- cgit v0.12 From 3be99b7a05858fb00b99620ec1277a2fd967d415 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sat, 7 Dec 2019 08:46:20 -0700 Subject: Update debug=action-timestamps + Rename to action-timestamps (from action_timestamps) for consistency with other compound word options. + Put manpage entry in alphabetical order. + Describe what option does and shorten it (refers to debug=time instead of duplicating it) + Change prints a bit (and tests to match) + Show scons version where added. + Slight adjustment to manpage introduction to debug options. Along the way, fixes a lingering tag mismatch from an earlier documentation PR. Updates PR#3456 Signed-off-by: Mats Wichmann --- doc/man/scons.xml | 61 +++++++++++---------------------- doc/user/depends.xml | 1 + src/engine/SCons/Script/Main.py | 7 ++-- src/engine/SCons/Script/SConsOptions.py | 2 +- test/option/debug-action-timestamps.py | 10 +++--- 5 files changed, 30 insertions(+), 51 deletions(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index ae54e2e..e0f920d 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -686,19 +686,32 @@ option except for the way default targets are handled. When this option is used and no targets are specified on the command line, all default targets are built, whether or not they are below the current directory. - + - --debug=type + --debug=type[,type...] Debug the build process. -type[,type...] -specifies what type of debugging. Multiple types may be specified, -separated by commas. The following types are valid: +type +specifies the kind of debugging info to emit. +Multiple types may be specified, separated by commas. +The following entries show the recognized types: + + + + --debug=action-timestamps + +Prints additional time profiling information. For +each command, shows the absolute start and end times. +This may be useful in debugging parallel builds. +Implies the option. + +Since &scons; 3.1. + --debug=count @@ -893,40 +906,6 @@ should take place in parallel.) - - --debug=action_timestamps - - Prints additional 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 -(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 absolute start and end wall-clock time spent executing those build commands - - - The time spent processing each file passed to the SConscript() function - - - - - --diskcheck=types @@ -2278,10 +2257,10 @@ env.SomeTool(targets, sources) Builder Methods -You tell scons what to build +You tell scons what to build by calling Builders, functions which know to take a particular action when given files of a particular type -to produce a particular result type. scons +to produce a particular result type. scons defines a number of builders, and you can also write your own. Builders are attached to a &consenv; as methods, and the available builder methods are listed as diff --git a/doc/user/depends.xml b/doc/user/depends.xml index 5a78eb5..cd5094a 100644 --- a/doc/user/depends.xml +++ b/doc/user/depends.xml @@ -764,6 +764,7 @@ int main() { printf("Hello, world!\n"); } encounter them in older &SConscript; files. +
Implicit Dependencies: The &cv-CPPPATH; Construction Variable diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py index 58dbf64..238a828 100644 --- a/src/engine/SCons/Script/Main.py +++ b/src/engine/SCons/Script/Main.py @@ -211,10 +211,9 @@ class BuildTask(SCons.Taskmaster.OutOfDateTask): last_command_end = finish_time cumulative_command_time = cumulative_command_time+finish_time-start_time if print_action_timestamps: - sys.stdout.write("Command execution start time: %s: %f seconds\n"%(str(self.node), start_time)) + sys.stdout.write("Command execution start timestamp: %s: %f\n"%(str(self.node), start_time)) + sys.stdout.write("Command execution end timestamp: %s: %f\n"%(str(self.node), finish_time)) sys.stdout.write("Command execution time: %s: %f seconds\n"%(str(self.node), finish_time-start_time)) - if print_action_timestamps: - sys.stdout.write("Command execution stop time: %s: %f seconds\n"%(str(self.node), finish_time)) def do_failed(self, status=2): _BuildFailures.append(self.exception[1]) @@ -679,7 +678,7 @@ def _set_debug_values(options): options.tree_printers.append(TreePrinter(status=True)) if "time" in debug_values: print_time = 1 - if "action_timestamps" in debug_values: + if "action-timestamps" in debug_values: print_time = 1 print_action_timestamps = 1 if "tree" in debug_values: diff --git a/src/engine/SCons/Script/SConsOptions.py b/src/engine/SCons/Script/SConsOptions.py index 7b5d523..66c7239 100644 --- a/src/engine/SCons/Script/SConsOptions.py +++ b/src/engine/SCons/Script/SConsOptions.py @@ -622,7 +622,7 @@ def Parser(version): debug_options = ["count", "duplicate", "explain", "findlibs", "includes", "memoizer", "memory", "objects", "pdb", "prepare", "presub", "stacktrace", - "time", "action_timestamps"] + "time", "action-timestamps"] def opt_debug(option, opt, value__, parser, debug_options=debug_options, diff --git a/test/option/debug-action-timestamps.py b/test/option/debug-action-timestamps.py index 0277516..059cfdf 100644 --- a/test/option/debug-action-timestamps.py +++ b/test/option/debug-action-timestamps.py @@ -34,13 +34,13 @@ def setup_fixtures(): test.file_fixture('../fixture/SConstruct_test_main.py', 'SConstruct') def test_help_function(): - # Before anything else, make sure we get valid --debug=action_timestamps results + # Before anything else, make sure we get valid --debug=action-timestamps results # when just running the help option. - test.run(arguments = "-h --debug=action_timestamps") + test.run(arguments = "-h --debug=action-timestamps") def build(): # Execute build - test.run(arguments='--debug=action_timestamps') + test.run(arguments='--debug=action-timestamps') build_output = test.stdout() return build_output @@ -84,8 +84,8 @@ def test_correctness_of_timestamps(build_output): debug_time_patterns = [ r'Command execution time: (.*): (\d+\.\d+) seconds', - r'Command execution start time: (.*): (\d+\.\d+) seconds', - r'Command execution stop time: (.*): (\d+\.\d+) seconds' + r'Command execution start timestamp: (.*): (\d+\.\d+)', + r'Command execution end timestamp: (.*): (\d+\.\d+)' ] test = TestSCons.TestSCons() -- cgit v0.12 From b1ac9ecfe28437f7e3480cd31120f12bd43c968b Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 7 Dec 2019 23:02:14 -0500 Subject: Address GaryO's feedback on PR 3129. Also reformatted Command() PEP8 --- src/CHANGES.txt | 9 ++++--- src/engine/SCons/Environment.py | 52 +++++++++++++++++++++++++++-------------- test/Command.py | 1 - 3 files changed, 40 insertions(+), 22 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index a5a37b8..34c7b9b 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -4,10 +4,9 @@ Change Log +NOTE: Please add your name below (and your changes) alphabetically by last name. + RELEASE VERSION/DATE TO BE FILLED IN LATER - From Jason Kenny - - Update Command() function to accept target_scanner, source_factory, and target_factory arguments. - This make Command act more like a one-off builder. From Edoardo Bezzeccheri - Added debug option "action_timestamps" which outputs to stdout the absolute start and end time for each target. @@ -19,6 +18,10 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER From Tim Gates - Resolved a typo in engine.SCons.Tool + From Jason Kenny + - Update Command() function to accept target_scanner, source_factory, and target_factory arguments. + This makes Command act more like a one-off builder. + From Ivan Kravets - Added support for "-imacros" to ParseFlags diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 4a9cf11..916ebc4 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -1983,26 +1983,42 @@ class Base(SubstitutionEnvironment): be any type that the Builder constructor will accept for an action.""" bkw = { - 'action' : action, - 'target_factory' : self.fs.Entry, - 'source_factory' : self.fs.Entry, + 'action': action, + 'target_factory': self.fs.Entry, + 'source_factory': self.fs.Entry, } # source scanner - try: bkw['source_scanner'] = kw['source_scanner'] - except KeyError: pass - else: del kw['source_scanner'] - #target scanner - try: bkw['target_scanner'] = kw['target_scanner'] - except KeyError: pass - else: del kw['target_scanner'] - #source factory - try: bkw['source_factory'] = kw['source_factory'] - except KeyError: pass - else: del kw['source_factory'] - #target factory - try: bkw['target_factory'] = kw['target_factory'] - except KeyError: pass - else: del kw['target_factory'] + try: + bkw['source_scanner'] = kw['source_scanner'] + except KeyError: + pass + else: + del kw['source_scanner'] + + # target scanner + try: + bkw['target_scanner'] = kw['target_scanner'] + except KeyError: + pass + else: + del kw['target_scanner'] + + # source factory + try: + bkw['source_factory'] = kw['source_factory'] + except KeyError: + pass + else: + del kw['source_factory'] + + # target factory + try: + bkw['target_factory'] = kw['target_factory'] + except KeyError: + pass + else: + del kw['target_factory'] + bld = SCons.Builder.Builder(**bkw) return bld(self, target, source, **kw) diff --git a/test/Command.py b/test/Command.py index 7189d06..1eb5f77 100644 --- a/test/Command.py +++ b/test/Command.py @@ -67,7 +67,6 @@ def source_scanner(node, env, path, builder): print("Source scanner node=", node, "builder =", builder,file=sys.stderr) return [] - def target_scanner(node, env, path, builder): print("Target scanner node=", node, "builder =", builder,file=sys.stderr) return [] -- cgit v0.12 From a8e707d20e1a7d7d6a45510194b2acbdf9ca8c3d Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 7 Dec 2019 23:03:17 -0500 Subject: Reformat test/Command.py PEP8 --- test/Command.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/Command.py b/test/Command.py index 1eb5f77..d8ca86d 100644 --- a/test/Command.py +++ b/test/Command.py @@ -142,9 +142,9 @@ Source scanner node= f8.in builder = wo-env Target scanner node= f8s.out builder = wo-env ''' -out = test.run(arguments = '.', - stderr = test_str, - match=TestSCons.match_re_dotall) +out = test.run(arguments='.', + stderr=test_str, + match=TestSCons.match_re_dotall) test.must_match('f1.out', "f1.in\n", mode='r') @@ -159,7 +159,8 @@ test.must_match('f7s.out', "f7.in\n", mode='r') test.must_match('f8s.out', "f8.in\n", mode='r') test.must_match('f9.out', "f9.in\n", mode='r') test.must_match('f10.out', "f10.in\n", mode='r') -test.must_match(['expand_chdir_sub', 'f11.out'], "expand_chdir_sub/f11.in\n", mode='r') +test.must_match(['expand_chdir_sub', 'f11.out'], + "expand_chdir_sub/f11.in\n", mode='r') test.pass_test() -- cgit v0.12 From 82016c7b8f990391f8afdc120d89a9a1f0e0a5ad Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Sun, 8 Dec 2019 14:34:16 -0500 Subject: Fix SConsTests.py to actually clear out the file/open overrides This was breaking the tests because it was not clearing the overrides in a manner consistent with the new logic. --- src/engine/SCons/SConfTests.py | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/engine/SCons/SConfTests.py b/src/engine/SCons/SConfTests.py index f770450..787138e 100644 --- a/src/engine/SCons/SConfTests.py +++ b/src/engine/SCons/SConfTests.py @@ -56,6 +56,18 @@ class SConfTestCase(unittest.TestCase): os.chdir(self.save_cwd) def _resetSConfState(self): + if sys.platform in ['cygwin', 'win32'] and sys.version_info.major == 2: + # On Windows with Python2, SCons.Platform.win32 redefines the + # built-in file() and open() functions to disable handle + # inheritance. Because we are unloading all SCons modules other + # than SCons.Compat, SCons.Platform.win32 will lose the variables + # it needs. As a result, we should reset the file() and open() + # functions to their original built-in versions. + import __builtin__ + import SCons.Platform.win32 + __builtin__.file = SCons.Platform.win32._builtin_file + __builtin__.open = SCons.Platform.win32._builtin_open + # Ok, this is tricky, and i do not know, if everything is sane. # We try to reset scons' state (including all global variables) import SCons.SConsign @@ -90,22 +102,6 @@ class SConfTestCase(unittest.TestCase): global existing_lib existing_lib = 'm' - if sys.platform in ['cygwin', 'win32']: - # On Windows, SCons.Platform.win32 redefines the builtin - # file() and open() functions to close the file handles. - # This interferes with the unittest.py infrastructure in - # some way. Just sidestep the issue by restoring the - # original builtin functions whenever we have to reset - # all of our global state. - - import SCons.Platform.win32 - - try: - file = SCons.Platform.win32._builtin_file - open = SCons.Platform.win32._builtin_open - except AttributeError: - pass - def _baseTryXXX(self, TryFunc): # TryCompile and TryLink are much the same, so we can test them # in one method, we pass the function as a string ('TryCompile', -- cgit v0.12 From b18b21d1cb1a000fb6e59338cc6f48afdea7348c Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Sun, 8 Dec 2019 21:13:43 -0500 Subject: Convert our file replacement to be a class This hopefully will fix one unit test that validates that it's a class. --- src/engine/SCons/Platform/win32.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/engine/SCons/Platform/win32.py b/src/engine/SCons/Platform/win32.py index c0cf03b..77c048e 100644 --- a/src/engine/SCons/Platform/win32.py +++ b/src/engine/SCons/Platform/win32.py @@ -89,11 +89,14 @@ else: mode += 'N' return mode - def _scons_file(name, mode=None, *args, **kwargs): - return _builtin_file(name, _scons_fixup_mode(mode), *args, **kwargs) + class _scons_file(_builtin_file): + def __init__(self, name, mode=None, *args, **kwargs): + _builtin_file.__init__(self, name, _scons_fixup_mode(mode), + *args, **kwargs) def _scons_open(name, mode=None, *args, **kwargs): - return _builtin_open(name, _scons_fixup_mode(mode), *args, **kwargs) + return _builtin_open(name, _scons_fixup_mode(mode), + *args, **kwargs) __builtin__.file = _scons_file __builtin__.open = _scons_open -- cgit v0.12 From 46b24a5cc8094f81802bfa79534e496872fb97ab Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Mon, 9 Dec 2019 10:51:32 -0500 Subject: Update CHANGES.txt to indicate original author of patch --- src/CHANGES.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 2c239a2..47b63ee 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -21,7 +21,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER From Adam Gross: - Resolved a race condition in multithreaded Windows builds with Python 2 in the case where a child process is spawned while a Python action has a - file open. + file open. Original author: Ryan Beasley. From Jason Kenny - Update Command() function to accept target_scanner, source_factory, and target_factory arguments. -- cgit v0.12 From 93507d5535e68341ca93af7efbc05fe6af1025e6 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 11 Dec 2019 12:26:39 -0500 Subject: Fix looking for specific version of libSystem.B.dylib when running on macOS. Use regex of #.#.# instead --- test/LINK/applelink.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/test/LINK/applelink.py b/test/LINK/applelink.py index 86e0a4c..e1b2837 100644 --- a/test/LINK/applelink.py +++ b/test/LINK/applelink.py @@ -25,6 +25,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import sys +import re import TestSCons @@ -83,10 +84,14 @@ for SHLIBVERSION, APPLELINK_CURRENT_VERSION, APPLELINK_COMPATIBILITY_VERSION, sh # libfoo.1.2.3.dylib: # > libfoo.1.2.3.dylib (compatibility version 1.1.99, current version 9.9.9) # > /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.50.4) - otool_output = "libfoo.{SHLIBVERSION}.dylib:\n\tlibfoo.{SHLIBVERSION}.dylib (compatibility version {APPLELINK_COMPATIBILITY_VERSION}, current version {APPLELINK_CURRENT_VERSION})\n\t/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.50.4)\n".format( - **locals()) + # otool_output = "libfoo.{SHLIBVERSION}.dylib:\n\tlibfoo.{SHLIBVERSION}.dylib (compatibility version {APPLELINK_COMPATIBILITY_VERSION}, current version {APPLELINK_CURRENT_VERSION})\n\t/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.50.4)\n".format( + # **locals()) + otool_output = "libfoo.{SHLIBVERSION}.dylib:\n\tlibfoo.{SHLIBVERSION}.dylib (compatibility version {APPLELINK_COMPATIBILITY_VERSION}, current version {APPLELINK_CURRENT_VERSION})\n\t/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version REPLACEME)\n".format(**locals()) + otool_output = re.escape(otool_output) + otool_output = otool_output.replace('REPLACEME','\d+\.\d+\.\d+') + - test.run(program='/usr/bin/otool', arguments='-L libfoo.%s.dylib' % SHLIBVERSION, stdout=otool_output) + test.run(program='/usr/bin/otool', arguments='-L libfoo.%s.dylib' % SHLIBVERSION, stdout=otool_output, match=TestSCons.match_re_dotall) # Now test that None in APPLELINK_CURRENT_VERSION or APPLELINK_COMPATIBILITY_VERSION will skip # generating their relevant linker command line flag. @@ -135,15 +140,16 @@ for SHLIBVERSION, \ # We expect output such as this # libfoo.1.2.3.dylib: # > libfoo.1.2.3.dylib (compatibility version 1.1.99, current version 9.9.9) - # > /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.50.4) + # > /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version #.#.#) if APPLELINK_NO_CURRENT_VERSION: APPLELINK_CURRENT_VERSION = '0.0.0' if APPLELINK_NO_COMPATIBILITY_VERSION: APPLELINK_COMPATIBILITY_VERSION = '0.0.0' - otool_output = "libfoo.{SHLIBVERSION}.dylib:\n\tlibfoo.{SHLIBVERSION}.dylib (compatibility version {APPLELINK_COMPATIBILITY_VERSION}, current version {APPLELINK_CURRENT_VERSION})\n\t/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.50.4)\n".format( + otool_output = "libfoo.{SHLIBVERSION}.dylib:\n\tlibfoo.{SHLIBVERSION}.dylib (compatibility version {APPLELINK_COMPATIBILITY_VERSION}, current version {APPLELINK_CURRENT_VERSION})\n\t/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version REPLACEME)\n".format( **locals()) + otool_output = re.escape(otool_output).replace('REPLACEME','\d+\.\d+\.\d+') - test.run(program='/usr/bin/otool', arguments='-L libfoo.%s.dylib' % SHLIBVERSION, stdout=otool_output) + test.run(program='/usr/bin/otool', arguments='-L libfoo.%s.dylib' % SHLIBVERSION, stdout=otool_output, match=TestSCons.match_re_dotall) test.pass_test() -- cgit v0.12 From 57bb593e4f562e6c6d5f64631bec5962c719295e Mon Sep 17 00:00:00 2001 From: Mathew Robinson Date: Wed, 11 Dec 2019 18:43:01 -0500 Subject: Improve DAG walk performance by preventing unnecessary list manipulation --- src/CHANGES.txt | 2 ++ src/engine/SCons/Taskmaster.py | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 47b63ee..c837157 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -46,6 +46,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Improved threading performance by ensuring NodeInfo is shared across threads. Results in ~13% improvement for parallel builds (-j# > 1) with many shared nodes. + - Improved DAG walk performance by reducing unnecessary work when + there are no un-visited children. From Mats Wichmann - Replace instances of string find method with "in" checks where diff --git a/src/engine/SCons/Taskmaster.py b/src/engine/SCons/Taskmaster.py index 4892026..06fc94c 100644 --- a/src/engine/SCons/Taskmaster.py +++ b/src/engine/SCons/Taskmaster.py @@ -874,8 +874,10 @@ class Taskmaster(object): # These nodes have not even been visited yet. Add # them to the list so that on some next pass we can # take a stab at evaluating them (or their children). - children_not_visited.reverse() - self.candidates.extend(self.order(children_not_visited)) + if children_not_visited: + if len(children_not_visited) > 1: + children_not_visited.reverse() + self.candidates.extend(self.order(children_not_visited)) # if T and children_not_visited: # T.write(self.trace_message(' adding to candidates: %s' % map(str, children_not_visited))) -- cgit v0.12 From 6a3a10d130817a4418bdfee5e3c746dfa7f9d60f Mon Sep 17 00:00:00 2001 From: Mathew Robinson Date: Wed, 11 Dec 2019 19:07:10 -0500 Subject: Optimize for most common case in Entry.disambiguate() This removes many unnecessary os.stat and related FS IO calls. --- src/CHANGES.txt | 2 ++ src/engine/SCons/Node/FS.py | 10 +++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 47b63ee..f137598 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -46,6 +46,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Improved threading performance by ensuring NodeInfo is shared across threads. Results in ~13% improvement for parallel builds (-j# > 1) with many shared nodes. + - Improve performance of Entry.disambiguate() by making check for + most common case first, preventing unnecessary IO. From Mats Wichmann - Replace instances of string find method with "in" checks where diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index 6b0fe98..4c68358 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -963,14 +963,14 @@ class Entry(Base): def disambiguate(self, must_exist=None): """ - """ - if self.isdir(): - self.__class__ = Dir - self._morph() - elif self.isfile(): + """ + if self.isfile(): self.__class__ = File self._morph() self.clear() + elif self.isdir(): + self.__class__ = Dir + self._morph() else: # There was nothing on-disk at this location, so look in # the src directory. -- 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 d960416fc4caa6e799812357fe91c3f3e11a9174 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 13 Dec 2019 08:25:01 -0700 Subject: Tweak DefaultEnvironment descriptions (ci skip) Doc-only change to be more explicit about when the default construction environment is used, and what it means to call DefaultEnvironment() - only the first call instantiates it, later calls return the object. Fixes #2477 Signed-off-by: Mats Wichmann --- doc/user/environments.xml | 58 ++++++++++++++++++++----------------------- src/engine/SCons/Defaults.xml | 16 ++++++++---- 2 files changed, 38 insertions(+), 36 deletions(-) diff --git a/doc/user/environments.xml b/doc/user/environments.xml index 43503a6..d3e5d6d 100644 --- a/doc/user/environments.xml +++ b/doc/user/environments.xml @@ -886,33 +886,30 @@ print("value is: %s"%env.subst( '->${1 / 0}<-' )) All of the &Builder; functions that we've introduced so far, - like &Program; and &Library;, - actually use a default &consenv; - that contains settings - for the various compilers - and other tools that - &SCons; configures by default, - or otherwise knows about - and has discovered on your system. - The goal of the default construction environment - is to make many configurations to "just work" - to build software using - readily available tools + like &Program; and &Library;, use a &consenv; + that contains settings for the various compilers + and other tools that &SCons; configures by default, + or otherwise knows about and has discovered on your system. + If not invoked as methods of a specific &consenv;, + they use the default &consenv; + The goal of the default &consenv; + is to make many configurations "just work" + to build software using readily available tools with a minimum of configuration changes. - You can, however, control the settings - in the default construction environment + If needed, you can control the default &consenv; by using the &DefaultEnvironment; function - to initialize various settings: + to initialize various settings by passing + them as keyword arguments: -DefaultEnvironment(CC = '/usr/local/bin/gcc') +DefaultEnvironment(CC='/usr/local/bin/gcc') @@ -928,15 +925,15 @@ DefaultEnvironment(CC = '/usr/local/bin/gcc') - Note that the &DefaultEnvironment; function - returns the initialized - default construction environment object, - which can then be manipulated like any - other construction environment. - So the following - would be equivalent to the - previous example, - setting the &cv-CC; + The &DefaultEnvironment; function + returns the initialized default &consenv; object, + which can then be manipulated like any other &consenv; + (note that the default environment works like a singleton - + it can have only one instance - so the keyword arguments + are processed only on the first call. On any subsequent + call the existing object is returned). + So the following would be equivalent to the + previous example, setting the &cv-CC; variable to /usr/local/bin/gcc but as a separate step after the default construction environment has been initialized: @@ -971,8 +968,8 @@ env['CC'] = '/usr/local/bin/gcc' -env = DefaultEnvironment(tools = ['gcc', 'gnulink'], - CC = '/usr/local/bin/gcc') +env = DefaultEnvironment(tools=['gcc', 'gnulink'], + CC='/usr/local/bin/gcc') @@ -994,9 +991,8 @@ env = DefaultEnvironment(tools = ['gcc', 'gnulink'], - The real advantage of construction environments - is that you can create as many different construction - environments as you need, + The real advantage of &consenvs; + is that you can create as many different ones as you need, each tailored to a different way to build some piece of software or other file. If, for example, we need to build @@ -1029,7 +1025,7 @@ int main() { } - We can even use multiple construction environments to build + We can even use multiple &consenvs; to build multiple versions of a single program. If you do this by simply trying to use the &b-link-Program; builder with both environments, though, diff --git a/src/engine/SCons/Defaults.xml b/src/engine/SCons/Defaults.xml index f215f5a..5002411 100644 --- a/src/engine/SCons/Defaults.xml +++ b/src/engine/SCons/Defaults.xml @@ -572,15 +572,21 @@ searching the repositories. -([args]) +([**kwargs]) -Creates and returns a default construction environment object. -This construction environment is used internally by SCons -in order to execute many of the global functions in this list, -and to fetch source files transparently +Creates and returns a default &consenv; object. +The default &consenv; is used internally by SCons +in order to execute many of the global functions in this list +(i.e. those not called as methods of a specific +&consenv;), and to fetch source files transparently from source code management systems. +The default environment is a singleton, so the keyword +arguments affect it only on the first call, on subsequent +calls the already-constructed object is returned. +The default environment can be modified in the same way +as any &consenv;. -- cgit v0.12 From ddab0035a4ec1b2de1d105e26f82dcc7d153dc4b Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 13 Dec 2019 09:07:12 -0700 Subject: [PR #3493] fix review comment [ci skip] Signed-off-by: Mats Wichmann --- src/engine/SCons/Defaults.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine/SCons/Defaults.xml b/src/engine/SCons/Defaults.xml index 5002411..22f46fe 100644 --- a/src/engine/SCons/Defaults.xml +++ b/src/engine/SCons/Defaults.xml @@ -576,7 +576,7 @@ searching the repositories. -Creates and returns a default &consenv; object. +Creates and returns the default &consenv; object. The default &consenv; is used internally by SCons in order to execute many of the global functions in this list (i.e. those not called as methods of a specific -- cgit v0.12 From 7c69e892566d189d83760ebd0e56b44fa11165ce Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sat, 14 Dec 2019 09:49:02 -0700 Subject: Remove deprecated env.Copy() Method removed. Test moved to test/Removed/Copy-Method/Old, and new test added to ensure it takes an AttributeError. Deprecation warning no longer useful for this one, so removed. Signed-off-by: Mats Wichmann --- doc/man/scons.xml | 18 ++--------- src/CHANGES.txt | 2 ++ src/engine/SCons/Environment.py | 8 ----- src/engine/SCons/EnvironmentTests.py | 12 ------- src/engine/SCons/Warnings.py | 3 -- test/Clone-compatibility.py | 2 ++ test/Deprecated/Copy-Method.py | 50 ----------------------------- test/Removed/Copy-Method/Copy-Method.py | 49 ++++++++++++++++++++++++++++ test/Removed/Copy-Method/Old/Copy-Method.py | 50 +++++++++++++++++++++++++++++ test/Removed/Copy-Method/Old/sconstest.skip | 0 test/Removed/Copy-Method/README.md | 6 ++++ test/Removed/Copy-Method/SConstruct.method | 2 ++ 12 files changed, 113 insertions(+), 89 deletions(-) delete mode 100644 test/Deprecated/Copy-Method.py create mode 100644 test/Removed/Copy-Method/Copy-Method.py create mode 100644 test/Removed/Copy-Method/Old/Copy-Method.py create mode 100644 test/Removed/Copy-Method/Old/sconstest.skip create mode 100644 test/Removed/Copy-Method/README.md create mode 100644 test/Removed/Copy-Method/SConstruct.method diff --git a/doc/man/scons.xml b/doc/man/scons.xml index a7327ea..899669e 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -1795,20 +1795,6 @@ Warnings for some specific deprecated features may be enabled or disabled individually; see below. -
- - - --warn=deprecated-copy, --warn=no-deprecated-copy - -Enables or disables warnings about use of the deprecated -env.Copy() -method. - - - - -
- @@ -7038,7 +7024,7 @@ value each time we call the SConscript function. SConstruct: - env = Environment(LIBPATH = ['#libA', '#libB']) + env = Environment(LIBPATH=['#libA', '#libB']) Export('env') SConscript('libA/SConscript') SConscript('libB/SConscript') @@ -7057,7 +7043,7 @@ libB/SConscript: Main/SConscript: Import('env') - e = env.Copy(LIBS = ['a', 'b']) + e = env.Clone(LIBS=['a', 'b']) e.Program('foo', Split('m1.c m2.c m3.c')) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index c837157..862e083 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -63,6 +63,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER helps test suite runs. - Remove deprecated SourceSignatures, TargetSignatures - Remove deprecated Builder keywords: overrides and scanner + - Remove deprecated env.Copy + - A number of documentation improvements. RELEASE 3.1.1 - Mon, 07 Aug 2019 20:09:12 -0500 diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 916ebc4..4535be9 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -1428,14 +1428,6 @@ class Base(SubstitutionEnvironment): if SCons.Debug.track_instances: logInstanceCreation(self, 'Environment.EnvironmentClone') return clone - def Copy(self, *args, **kw): - global _warn_copy_deprecated - if _warn_copy_deprecated: - msg = "The env.Copy() method is deprecated; use the env.Clone() method instead." - SCons.Warnings.warn(SCons.Warnings.DeprecatedCopyWarning, msg) - _warn_copy_deprecated = False - return self.Clone(*args, **kw) - def _changed_build(self, dependency, target, prev_ni, repo_node=None): if dependency.changed_state(target, prev_ni, repo_node): return 1 diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index 0957361..b2f2bd5 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -1876,18 +1876,6 @@ def generate(env): assert ('BUILDERS' in env) is False env2 = env.Clone() - def test_Copy(self): - """Test copying using the old env.Copy() method""" - env1 = self.TestEnvironment(XXX = 'x', YYY = 'y') - env2 = env1.Copy() - env1copy = env1.Copy() - assert env1copy == env1copy - assert env2 == env2 - env2.Replace(YYY = 'yyy') - assert env2 == env2 - assert env1 != env2 - assert env1 == env1copy - def test_Detect(self): """Test Detect()ing tools""" test = TestCmd.TestCmd(workdir = '') diff --git a/src/engine/SCons/Warnings.py b/src/engine/SCons/Warnings.py index 718b3d5..cd24b7c 100644 --- a/src/engine/SCons/Warnings.py +++ b/src/engine/SCons/Warnings.py @@ -126,9 +126,6 @@ class DeprecatedBuildDirWarning(DeprecatedWarning): class TaskmasterNeedsExecuteWarning(DeprecatedWarning): pass -class DeprecatedCopyWarning(MandatoryDeprecatedWarning): - pass - class DeprecatedOptionsWarning(MandatoryDeprecatedWarning): pass diff --git a/test/Clone-compatibility.py b/test/Clone-compatibility.py index a2f6362..38cbeb3 100644 --- a/test/Clone-compatibility.py +++ b/test/Clone-compatibility.py @@ -39,6 +39,8 @@ test.write('SConstruct', """ # code as the correct pattern for maintaining the backwards compatibility # of SConstruct files to earlier release of SCons. Going forward, make # sure it still works (or at least doesn't blow up). +# Copy was removed for 3.1.2 but Clone will certainly be there - +# this test probably isn't needed any longer. import SCons.Environment try: SCons.Environment.Environment.Clone diff --git a/test/Deprecated/Copy-Method.py b/test/Deprecated/Copy-Method.py deleted file mode 100644 index 2714f64..0000000 --- a/test/Deprecated/Copy-Method.py +++ /dev/null @@ -1,50 +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 the message about the deprecated env.Copy() message, and the -ability to suppress it. -""" - -import TestSCons - -test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) - -test.write('SConscript', """ -env = Environment().Copy() -env.Copy() -""") - -msg = """The env.Copy() method is deprecated; use the env.Clone() method instead.""" -test.deprecated_warning('deprecated-copy', msg) - -test.pass_test() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Removed/Copy-Method/Copy-Method.py b/test/Removed/Copy-Method/Copy-Method.py new file mode 100644 index 0000000..e55ebc6 --- /dev/null +++ b/test/Removed/Copy-Method/Copy-Method.py @@ -0,0 +1,49 @@ +#!/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 env.Copy() fails as expected since its removal +""" + +import TestSCons + +test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) + +test.file_fixture('SConstruct.method', 'SConstruct') +expect = """\ +AttributeError: 'SConsEnvironment' object has no attribute 'Copy': + File "{}", line 2: + env.Copy() +""".format(test.workpath('SConstruct')) +test.run(arguments='-Q -s', status=2, stdout=None, stderr=expect) + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Removed/Copy-Method/Old/Copy-Method.py b/test/Removed/Copy-Method/Old/Copy-Method.py new file mode 100644 index 0000000..2714f64 --- /dev/null +++ b/test/Removed/Copy-Method/Old/Copy-Method.py @@ -0,0 +1,50 @@ +#!/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 the message about the deprecated env.Copy() message, and the +ability to suppress it. +""" + +import TestSCons + +test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) + +test.write('SConscript', """ +env = Environment().Copy() +env.Copy() +""") + +msg = """The env.Copy() method is deprecated; use the env.Clone() method instead.""" +test.deprecated_warning('deprecated-copy', msg) + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Removed/Copy-Method/Old/sconstest.skip b/test/Removed/Copy-Method/Old/sconstest.skip new file mode 100644 index 0000000..e69de29 diff --git a/test/Removed/Copy-Method/README.md b/test/Removed/Copy-Method/README.md new file mode 100644 index 0000000..609c6e4 --- /dev/null +++ b/test/Removed/Copy-Method/README.md @@ -0,0 +1,6 @@ +Copy-Method.py is the "new" test for env.Copy, making sure we +get an AttributeError. + +The Old directory is the former tests from the deprecated state, +preserved here for reference; the presence of an scontest.skip file +means they are never executed. diff --git a/test/Removed/Copy-Method/SConstruct.method b/test/Removed/Copy-Method/SConstruct.method new file mode 100644 index 0000000..99737e1 --- /dev/null +++ b/test/Removed/Copy-Method/SConstruct.method @@ -0,0 +1,2 @@ +env = Environment() +env.Copy() -- cgit v0.12 From f4137883a3967ce4a6f3a142c987f834d8694220 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 14 Dec 2019 18:29:11 -0500 Subject: fixed match function to be non-regex --- test/Removed/Copy-Method/Copy-Method.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Removed/Copy-Method/Copy-Method.py b/test/Removed/Copy-Method/Copy-Method.py index e55ebc6..bca10fe 100644 --- a/test/Removed/Copy-Method/Copy-Method.py +++ b/test/Removed/Copy-Method/Copy-Method.py @@ -38,7 +38,7 @@ AttributeError: 'SConsEnvironment' object has no attribute 'Copy': File "{}", line 2: env.Copy() """.format(test.workpath('SConstruct')) -test.run(arguments='-Q -s', status=2, stdout=None, stderr=expect) +test.run(arguments='-Q -s', status=2, stderr=expect, match=TestSCons.match_exact) test.pass_test() -- cgit v0.12 From ac61e3fead14db2d61ac449d458c04f4bba4053f Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sun, 15 Dec 2019 06:48:35 -0700 Subject: Remove deprecated BuildDir, build_dir Updates docs and code; moves tests to test/Removed/BuildDir/Old. New tests verify that these can no longer be used. Along the way a small cleanup in SConscript.py Signed-off-by: Mats Wichmann --- doc/user/separate.xml | 6 +- src/CHANGES.txt | 1 + src/engine/SCons/Environment.py | 8 - src/engine/SCons/Environment.xml | 22 -- src/engine/SCons/Script/SConscript.py | 24 +- src/engine/SCons/Script/__init__.py | 1 - src/engine/SCons/Warnings.py | 9 - test/Deprecated/BuildDir.py | 295 ---------------------- test/Deprecated/SConscript-build_dir.py | 291 --------------------- test/Removed/BuildDir/Old/BuildDir.py | 295 ++++++++++++++++++++++ test/Removed/BuildDir/Old/SConscript-build_dir.py | 291 +++++++++++++++++++++ test/Removed/BuildDir/README.md | 6 + test/Removed/BuildDir/SConstruct.global | 1 + test/Removed/BuildDir/SConstruct.kwarg | 1 + test/Removed/BuildDir/SConstruct.method | 3 + 15 files changed, 608 insertions(+), 646 deletions(-) delete mode 100644 test/Deprecated/BuildDir.py delete mode 100644 test/Deprecated/SConscript-build_dir.py create mode 100644 test/Removed/BuildDir/Old/BuildDir.py create mode 100644 test/Removed/BuildDir/Old/SConscript-build_dir.py create mode 100644 test/Removed/BuildDir/README.md create mode 100644 test/Removed/BuildDir/SConstruct.global create mode 100644 test/Removed/BuildDir/SConstruct.kwarg create mode 100644 test/Removed/BuildDir/SConstruct.method diff --git a/doc/user/separate.xml b/doc/user/separate.xml index c276545..748a124 100644 --- a/doc/user/separate.xml +++ b/doc/user/separate.xml @@ -149,10 +149,8 @@ program using the F path name. One historical note: the &VariantDir; function - used to be called &BuildDir;. - That name is still supported - but has been deprecated - because the &SCons; functionality + used to be called &BuildDir;, a name which was + removed because the &SCons; functionality differs from the model of a "build directory" implemented by other build systems like the GNU Autotools. diff --git a/src/CHANGES.txt b/src/CHANGES.txt index dade5e0..28a4b43 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -66,6 +66,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Remove deprecated SourceSignatures, TargetSignatures - Remove deprecated Builder keywords: overrides and scanner - Remove deprecated env.Copy + - Remove deprecated BuildDir plus SConscript keyword build_dir - A number of documentation improvements. diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 4535be9..27179c3 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -1929,14 +1929,6 @@ class Base(SubstitutionEnvironment): t.set_always_build() return tlist - def BuildDir(self, *args, **kw): - msg = """BuildDir() and the build_dir keyword have been deprecated;\n\tuse VariantDir() and the variant_dir keyword instead.""" - SCons.Warnings.warn(SCons.Warnings.DeprecatedBuildDirWarning, msg) - if 'build_dir' in kw: - kw['variant_dir'] = kw['build_dir'] - del kw['build_dir'] - return self.VariantDir(*args, **kw) - def Builder(self, **kw): nkw = self.subst_kw(kw) return SCons.Builder.Builder(**nkw) diff --git a/src/engine/SCons/Environment.xml b/src/engine/SCons/Environment.xml index 73c347e..6f263a4 100644 --- a/src/engine/SCons/Environment.xml +++ b/src/engine/SCons/Environment.xml @@ -613,28 +613,6 @@ env.AppendUnique(CCFLAGS = '-g', FOO = ['foo.yyy'])
- - -(build_dir, src_dir, [duplicate]) - - - -Deprecated synonyms for -&f-VariantDir; -and -env.VariantDir(). -The -build_dir -argument becomes the -variant_dir -argument of -&f-VariantDir; -or -env.VariantDir(). - - - - (action, [arguments]) diff --git a/src/engine/SCons/Script/SConscript.py b/src/engine/SCons/Script/SConscript.py index eabaddb..0298a69 100644 --- a/src/engine/SCons/Script/SConscript.py +++ b/src/engine/SCons/Script/SConscript.py @@ -42,7 +42,7 @@ import SCons.Platform import SCons.SConf import SCons.Script.Main import SCons.Tool -import SCons.Util +from SCons.Util import is_List, is_String, is_Dict, flatten from . import Main @@ -98,7 +98,7 @@ def compute_exports(exports): retval = {} try: for export in exports: - if SCons.Util.is_Dict(export): + if is_Dict(export): retval.update(export) else: try: @@ -133,7 +133,7 @@ call_stack = [] def Return(*vars, **kw): retval = [] try: - fvars = SCons.Util.flatten(vars) + fvars = flatten(vars) for var in fvars: for v in var.split(): retval.append(call_stack[-1].globals[v]) @@ -420,7 +420,7 @@ class SConsEnvironment(SCons.Environment.Base): except KeyError: raise SCons.Errors.UserError("Invalid SConscript usage - no parameters") - if not SCons.Util.is_List(dirs): + if not is_List(dirs): dirs = [ dirs ] dirs = list(map(str, dirs)) @@ -441,13 +441,13 @@ class SConsEnvironment(SCons.Environment.Base): raise SCons.Errors.UserError("Invalid SConscript() usage - too many arguments") - if not SCons.Util.is_List(files): + if not is_List(files): files = [ files ] if kw.get('exports'): exports.extend(self.Split(kw['exports'])) - variant_dir = kw.get('variant_dir') or kw.get('build_dir') + variant_dir = kw.get('variant_dir') if variant_dir: if len(files) != 1: raise SCons.Errors.UserError("Invalid SConscript() usage - can only specify one SConscript with a variant_dir") @@ -577,9 +577,6 @@ class SConsEnvironment(SCons.Environment.Base): UserError: a script is not found and such exceptions are enabled. """ - if 'build_dir' in kw: - msg = """The build_dir keyword has been deprecated; use the variant_dir keyword instead.""" - SCons.Warnings.warn(SCons.Warnings.DeprecatedBuildDirWarning, msg) def subst_element(x, subst=self.subst): if SCons.Util.is_List(x): x = list(map(subst, x)) @@ -589,15 +586,10 @@ class SConsEnvironment(SCons.Environment.Base): ls = list(map(subst_element, ls)) subst_kw = {} for key, val in kw.items(): - if SCons.Util.is_String(val): + if is_String(val): val = self.subst(val) elif SCons.Util.is_List(val): - result = [] - for v in val: - if SCons.Util.is_String(v): - v = self.subst(v) - result.append(v) - val = result + val = [self.subst(v) if is_String(v) else v for v in val] subst_kw[key] = val files, exports = self._get_SConscript_filenames(ls, subst_kw) diff --git a/src/engine/SCons/Script/__init__.py b/src/engine/SCons/Script/__init__.py index 24af73e..9947943 100644 --- a/src/engine/SCons/Script/__init__.py +++ b/src/engine/SCons/Script/__init__.py @@ -314,7 +314,6 @@ GlobalDefaultEnvironmentFunctions = [ 'AddPreAction', 'Alias', 'AlwaysBuild', - 'BuildDir', 'CacheDir', 'Clean', #The Command() method is handled separately, below. diff --git a/src/engine/SCons/Warnings.py b/src/engine/SCons/Warnings.py index cd24b7c..fcec963 100644 --- a/src/engine/SCons/Warnings.py +++ b/src/engine/SCons/Warnings.py @@ -120,9 +120,6 @@ class PythonVersionWarning(DeprecatedWarning): class DeprecatedSourceCodeWarning(FutureDeprecatedWarning): pass -class DeprecatedBuildDirWarning(DeprecatedWarning): - pass - class TaskmasterNeedsExecuteWarning(DeprecatedWarning): pass @@ -132,12 +129,6 @@ class DeprecatedOptionsWarning(MandatoryDeprecatedWarning): class DeprecatedDebugOptionsWarning(MandatoryDeprecatedWarning): pass -class DeprecatedSigModuleWarning(MandatoryDeprecatedWarning): - pass - -class DeprecatedBuilderKeywordsWarning(MandatoryDeprecatedWarning): - pass - class DeprecatedMissingSConscriptWarning(DeprecatedWarning): pass diff --git a/test/Deprecated/BuildDir.py b/test/Deprecated/BuildDir.py deleted file mode 100644 index 1a1ba02..0000000 --- a/test/Deprecated/BuildDir.py +++ /dev/null @@ -1,295 +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 the deprecated BuildDir() function and method still -work to create a variant directory tree (by calling VariantDir() -under the covers). -""" - -import TestSCons - -_exe = TestSCons._exe - -test = TestSCons.TestSCons() - -test.write('SConscript', """ -BuildDir('build', 'src') -""") - -msg = """BuildDir() and the build_dir keyword have been deprecated; -\tuse VariantDir() and the variant_dir keyword instead.""" -test.deprecated_warning('deprecated-build-dir', msg) - -warning = '\nscons: warning: ' + TestSCons.re_escape(msg) \ - + '\n' + TestSCons.file_expr - -foo11 = test.workpath('work1', 'build', 'var1', 'foo1' + _exe) -foo12 = test.workpath('work1', 'build', 'var1', 'foo2' + _exe) -foo21 = test.workpath('work1', 'build', 'var2', 'foo1' + _exe) -foo22 = test.workpath('work1', 'build', 'var2', 'foo2' + _exe) -foo31 = test.workpath('work1', 'build', 'var3', 'foo1' + _exe) -foo32 = test.workpath('work1', 'build', 'var3', 'foo2' + _exe) -foo41 = test.workpath('work1', 'build', 'var4', 'foo1' + _exe) -foo42 = test.workpath('work1', 'build', 'var4', 'foo2' + _exe) -foo51 = test.workpath('build', 'var5', 'foo1' + _exe) -foo52 = test.workpath('build', 'var5', 'foo2' + _exe) - -test.subdir('work1') - -test.write(['work1', 'SConstruct'], """ -SetOption('warn', 'deprecated-build-dir') -src = Dir('src') -var2 = Dir('build/var2') -var3 = Dir('build/var3') -var4 = Dir('build/var4') -var5 = Dir('../build/var5') -var6 = Dir('../build/var6') - -env = Environment(BUILD = 'build', SRC = 'src') - -BuildDir('build/var1', src) -BuildDir(var2, src) -BuildDir(var3, src, duplicate=0) -env.BuildDir("$BUILD/var4", "$SRC", duplicate=0) -BuildDir(var5, src, duplicate=0) -BuildDir(var6, src) - -env = Environment(CPPPATH='#src', FORTRANPATH='#src') -SConscript('build/var1/SConscript', "env") -SConscript('build/var2/SConscript', "env") - -env = Environment(CPPPATH=src, FORTRANPATH=src) -SConscript('build/var3/SConscript', "env") -SConscript(File('SConscript', var4), "env") - -env = Environment(CPPPATH='.', FORTRANPATH='.') -SConscript('../build/var5/SConscript', "env") -SConscript('../build/var6/SConscript', "env") -""") - -test.subdir(['work1', 'src']) -test.write(['work1', 'src', 'SConscript'], """ -import os.path - -def buildIt(target, source, env): - if not os.path.exists('build'): - os.mkdir('build') - with open(str(source[0]), 'r') as ifp, open(str(target[0]), 'w') as ofp: - ofp.write(ifp.read()) - return 0 -Import("env") -env.Command(target='f2.c', source='f2.in', action=buildIt) -env.Program(target='foo2', source='f2.c') -env.Program(target='foo1', source='f1.c') -env.Command(target='f3.h', source='f3h.in', action=buildIt) -env.Command(target='f4.h', source='f4h.in', action=buildIt) -env.Command(target='f4.c', source='f4.in', action=buildIt) - -env2=env.Clone(CPPPATH='.') -env2.Program(target='foo3', source='f3.c') -env2.Program(target='foo4', source='f4.c') -""") - -test.write(['work1', 'src', 'f1.c'], r""" -#include -#include - -#include "f1.h" - -int -main(int argc, char *argv[]) -{ - argv[argc++] = "--"; - printf(F1_STR); - exit (0); -} -""") - -test.write(['work1', 'src', 'f2.in'], r""" -#include -#include - -#include "f2.h" - -int -main(int argc, char *argv[]) -{ - argv[argc++] = "--"; - printf(F2_STR); - exit (0); -} -""") - -test.write(['work1', 'src', 'f3.c'], r""" -#include -#include - -#include "f3.h" - -int -main(int argc, char *argv[]) -{ - argv[argc++] = "--"; - printf(F3_STR); - exit (0); -} -""") - -test.write(['work1', 'src', 'f4.in'], r""" -#include -#include - -#include "f4.h" - -int -main(int argc, char *argv[]) -{ - argv[argc++] = "--"; - printf(F4_STR); - exit (0); -} -""") - -test.write(['work1', 'src', 'f1.h'], r""" -#define F1_STR "f1.c\n" -""") - -test.write(['work1', 'src', 'f2.h'], r""" -#define F2_STR "f2.c\n" -""") - -test.write(['work1', 'src', 'f3h.in'], r""" -#define F3_STR "f3.c\n" -""") - -test.write(['work1', 'src', 'f4h.in'], r""" -#define F4_STR "f4.c\n" -""") - -# Some releases of freeBSD seem to have library complaints about -# tempnam(). Filter out these annoying messages before checking for -# error output. -def filter_tempnam(err): - if not err: - return '' - msg = "warning: tempnam() possibly used unsafely" - return '\n'.join([l for l in err.splitlines() if l.find(msg) == -1]) - -test.run(chdir='work1', arguments = '. ../build', stderr=None) - -stderr = filter_tempnam(test.stderr()) -test.fail_test(TestSCons.match_re_dotall(stderr, 6*warning)) - -test.run(program = foo11, stdout = "f1.c\n") -test.run(program = foo12, stdout = "f2.c\n") -test.run(program = foo41, stdout = "f1.c\n") -test.run(program = foo42, stdout = "f2.c\n") - -test.run(chdir='work1', - arguments='. ../build', - stderr = None, - stdout=test.wrap_stdout("""\ -scons: `.' is up to date. -scons: `%s' is up to date. -""" % test.workpath('build'))) - -stderr = filter_tempnam(test.stderr()) -test.fail_test(TestSCons.match_re_dotall(stderr, 6*warning)) - -import os -import stat -def equal_stats(x,y): - x = os.stat(x) - y = os.stat(y) - return (stat.S_IMODE(x[stat.ST_MODE]) == stat.S_IMODE(y[stat.ST_MODE]) and - x[stat.ST_MTIME] == y[stat.ST_MTIME]) - -# Make sure we did duplicate the source files in build/var2, -# and that their stats are the same: -test.must_exist(['work1', 'build', 'var2', 'f1.c']) -test.must_exist(['work1', 'build', 'var2', 'f2.in']) -test.fail_test(not equal_stats(test.workpath('work1', 'build', 'var2', 'f1.c'), test.workpath('work1', 'src', 'f1.c'))) -test.fail_test(not equal_stats(test.workpath('work1', 'build', 'var2', 'f2.in'), test.workpath('work1', 'src', 'f2.in'))) - -# Make sure we didn't duplicate the source files in build/var3. -test.must_not_exist(['work1', 'build', 'var3', 'f1.c']) -test.must_not_exist(['work1', 'build', 'var3', 'f2.in']) -test.must_not_exist(['work1', 'build', 'var3', 'b1.f']) -test.must_not_exist(['work1', 'build', 'var3', 'b2.in']) - -# Make sure we didn't duplicate the source files in build/var4. -test.must_not_exist(['work1', 'build', 'var4', 'f1.c']) -test.must_not_exist(['work1', 'build', 'var4', 'f2.in']) -test.must_not_exist(['work1', 'build', 'var4', 'b1.f']) -test.must_not_exist(['work1', 'build', 'var4', 'b2.in']) - -# Make sure we didn't duplicate the source files in build/var5. -test.must_not_exist(['build', 'var5', 'f1.c']) -test.must_not_exist(['build', 'var5', 'f2.in']) -test.must_not_exist(['build', 'var5', 'b1.f']) -test.must_not_exist(['build', 'var5', 'b2.in']) - -# verify that header files in the source directory are scanned properly: -test.write(['work1', 'src', 'f1.h'], r""" -#define F1_STR "f1.c 2\n" -""") - -test.write(['work1', 'src', 'f3h.in'], r""" -#define F3_STR "f3.c 2\n" -""") - -test.write(['work1', 'src', 'f4h.in'], r""" -#define F4_STR "f4.c 2\n" -""") - -test.run(chdir='work1', arguments = '../build/var5', stderr=None) - -stderr = filter_tempnam(test.stderr()) -test.fail_test(TestSCons.match_re_dotall(stderr, 6*warning)) - -test.run(program = foo51, stdout = "f1.c 2\n") -test.run(program = test.workpath('build', 'var5', 'foo3' + _exe), - stdout = "f3.c 2\n") -test.run(program = test.workpath('build', 'var5', 'foo4' + _exe), - stdout = "f4.c 2\n") - -test.run(chdir='work1', - arguments='../build/var5', - stderr=None, - stdout=test.wrap_stdout("""\ -scons: `%s' is up to date. -""" % test.workpath('build', 'var5'))) - -stderr = filter_tempnam(test.stderr()) -test.fail_test(TestSCons.match_re_dotall(stderr, 6*warning)) - -test.pass_test() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Deprecated/SConscript-build_dir.py b/test/Deprecated/SConscript-build_dir.py deleted file mode 100644 index 0d1ba6a..0000000 --- a/test/Deprecated/SConscript-build_dir.py +++ /dev/null @@ -1,291 +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 specifying a build_dir argument to SConscript still works. -""" - -import TestSCons - -test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) - -test.write('SConscript', """ -SConscript('DummyScript', build_dir = 'build') -""") - -test.write('DummyScript', """ -""") - -msg = """The build_dir keyword has been deprecated; use the variant_dir keyword instead.""" -test.deprecated_warning('deprecated-build-dir', msg) - -warning = '\nscons: warning: ' + TestSCons.re_escape(msg) \ - + '\n' + TestSCons.file_expr - -all1 = test.workpath('test', 'build', 'var1', 'all') -all2 = test.workpath('test', 'build', 'var2', 'all') -all3 = test.workpath('test', 'build', 'var3', 'all') -all4 = test.workpath('test', 'build', 'var4', 'all') -all5 = test.workpath('build', 'var5', 'all') -all6 = test.workpath('build', 'var6', 'all') -all7 = test.workpath('build', 'var7', 'all') -all8 = test.workpath('build', 'var8', 'all') -all9 = test.workpath('test', 'build', 'var9', 'src', 'all') - -test.subdir('test') - -test.write(['test', 'SConstruct'], """ -SetOption('warn', 'deprecated-build-dir') -src = Dir('src') -alt = Dir('alt') -var1 = Dir('build/var1') -var2 = Dir('build/var2') -var3 = Dir('build/var3') -var4 = Dir('build/var4') -var5 = Dir('../build/var5') -var6 = Dir('../build/var6') -var7 = Dir('../build/var7') -var8 = Dir('../build/var8') -var9 = Dir('../build/var9') - -def cat(env, source, target): - target = str(target[0]) - with open(target, "wb") as ofp: - for src in source: - with open(str(src), "rb") as ifp: - ofp.write(ifp.read()) - -env = Environment(BUILDERS={'Cat':Builder(action=cat)}, - BUILD='build') - -Export("env") - -SConscript('src/SConscript', build_dir=var1) -SConscript('src/SConscript', build_dir='build/var2', src_dir=src) - -SConscript('src/SConscript', build_dir='build/var3', duplicate=0) - -#XXX We can't support var4 and var5 yet, because our VariantDir linkage -#XXX is to an entire source directory. We haven't yet generalized our -#XXX infrastructure to be able to take the SConscript file from one source -#XXX directory, but the rest of the files from a different one. -#XXX SConscript('src/SConscript', build_dir=var4, src_dir=alt, duplicate=0) - -#XXX SConscript('src/SConscript', build_dir='../build/var5', src_dir='alt') -SConscript('src/SConscript', build_dir=var6) - -SConscript('src/SConscript', build_dir=var7, src_dir=src, duplicate=0) -env.SConscript('src/SConscript', build_dir='../$BUILD/var8', duplicate=0) - -# This tests the fact that if you specify a src_dir that is above -# the dir a SConscript is in, that we do the intuitive thing, i.e., -# we set the path of the SConscript accordingly. The below is -# equivalent to saying: -# -# VariantDir('build/var9', '.') -# SConscript('build/var9/src/SConscript') -SConscript('src/SConscript', build_dir='build/var9', src_dir='.') -""") - -test.subdir(['test', 'src'], ['test', 'alt']) - -test.write(['test', 'src', 'SConscript'], """ -Import("env") -env.Cat('aaa.out', 'aaa.in') -env.Cat('bbb.out', 'bbb.in') -env.Cat('ccc.out', 'ccc.in') -env.Cat('all', ['aaa.out', 'bbb.out', 'ccc.out']) -""") - -test.write('test/src/aaa.in', "test/src/aaa.in\n") -test.write('test/src/bbb.in', "test/src/bbb.in\n") -test.write('test/src/ccc.in', "test/src/ccc.in\n") - -test.write('test/alt/aaa.in', "test/alt/aaa.in\n") -test.write('test/alt/bbb.in', "test/alt/bbb.in\n") -test.write('test/alt/ccc.in', "test/alt/ccc.in\n") - -test.run(chdir='test', arguments = '. ../build', stderr = 7*warning) - -all_src = "test/src/aaa.in\ntest/src/bbb.in\ntest/src/ccc.in\n" -all_alt = "test/alt/aaa.in\ntest/alt/bbb.in\ntest/alt/ccc.in\n" - -test.must_match(all1, all_src) -test.must_match(all2, all_src) -test.must_match(all3, all_src) -#XXX We can't support var4 and var5 yet, because our VariantDir linkage -#XXX is to an entire source directory. We haven't yet generalized our -#XXX infrastructure to be able to take the SConscript file from one source -#XXX directory, but the rest of the files from a different one. -#XXX test.must_match(all4, all_alt) -#XXX test.must_match(all5, all_alt) -test.must_match(all6, all_src) -test.must_match(all7, all_src) -test.must_match(all8, all_src) -test.must_match(all9, all_src) - -import os -import stat -def equal_stats(x,y): - x = os.stat(x) - y = os.stat(y) - return (stat.S_IMODE(x[stat.ST_MODE]) == stat.S_IMODE(y[stat.ST_MODE]) and - x[stat.ST_MTIME] == y[stat.ST_MTIME]) - -# Make sure we did duplicate the source files in build/var1, -# and that their stats are the same: -for file in ['aaa.in', 'bbb.in', 'ccc.in']: - test.must_exist(test.workpath('test', 'build', 'var1', file)) - test.fail_test(not equal_stats(test.workpath('test', 'build', 'var1', file), - test.workpath('test', 'src', file))) - -# Make sure we did duplicate the source files in build/var2, -# and that their stats are the same: -for file in ['aaa.in', 'bbb.in', 'ccc.in']: - test.must_exist(test.workpath('test', 'build', 'var2', file)) - test.fail_test(not equal_stats(test.workpath('test', 'build', 'var2', file), - test.workpath('test', 'src', file))) - -# Make sure we didn't duplicate the source files in build/var3. -test.must_not_exist(test.workpath('test', 'build', 'var3', 'aaa.in')) -test.must_not_exist(test.workpath('test', 'build', 'var3', 'bbb.in')) -test.must_not_exist(test.workpath('test', 'build', 'var3', 'ccc.in')) - -#XXX We can't support var4 and var5 yet, because our VariantDir linkage -#XXX is to an entire source directory. We haven't yet generalized our -#XXX infrastructure to be able to take the SConscript file from one source -#XXX directory, but the rest of the files from a different one. -#XXX Make sure we didn't duplicate the source files in build/var4. -#XXXtest.must_not_exist(test.workpath('test', 'build', 'var4', 'aaa.in')) -#XXXtest.must_not_exist(test.workpath('test', 'build', 'var4', 'bbb.in')) -#XXXtest.must_not_exist(test.workpath('test', 'build', 'var4', 'ccc.in')) - -#XXX We can't support var4 and var5 yet, because our VariantDir linkage -#XXX is to an entire source directory. We haven't yet generalized our -#XXX infrastructure to be able to take the SConscript file from one source -#XXX directory, but the rest of the files from a different one. -#XXX Make sure we did duplicate the source files in build/var5, -#XXX and that their stats are the same: -#XXXfor file in ['aaa.in', 'bbb.in', 'ccc.in']: -#XXX test.must_exist(test.workpath('build', 'var5', file)) -#XXX test.fail_test(not equal_stats(test.workpath('build', 'var5', file), -#XXX test.workpath('test', 'src', file))) - -# Make sure we did duplicate the source files in build/var6, -# and that their stats are the same: -for file in ['aaa.in', 'bbb.in', 'ccc.in']: - test.must_exist(test.workpath('build', 'var6', file)) - test.fail_test(not equal_stats(test.workpath('build', 'var6', file), - test.workpath('test', 'src', file))) - -# Make sure we didn't duplicate the source files in build/var7. -test.must_not_exist(test.workpath('build', 'var7', 'aaa.in')) -test.must_not_exist(test.workpath('build', 'var7', 'bbb.in')) -test.must_not_exist(test.workpath('build', 'var7', 'ccc.in')) - -# Make sure we didn't duplicate the source files in build/var8. -test.must_not_exist(test.workpath('build', 'var8', 'aaa.in')) -test.must_not_exist(test.workpath('build', 'var8', 'bbb.in')) -test.must_not_exist(test.workpath('build', 'var8', 'ccc.in')) - -################### -test.subdir('test2') - -test.write(['test2', 'SConstruct'], """\ -SConscript('SConscript', build_dir='Build', src_dir='.', duplicate=0) -""") - -test.write(['test2', 'SConscript'], """\ -env = Environment() -foo_obj = env.Object('foo.c') -env.Program('foo', [foo_obj, 'bar.c']) -""") - -test.write(['test2', 'bar.c'], r""" -#include -#include - -void -bar(void) { - printf("bar.c\n"); -} -""") - -test.write(['test2', 'foo.c'], r""" -#include -#include - -extern void -bar(void); - -int -main(int argc, char *argv[]) { - bar(); - printf("foo.c\n"); -} -""") - -test.run(chdir="test2", stderr = warning) - -_obj = TestSCons._obj - -test.must_not_exist(test.workpath('test2', 'foo' + _obj)) -test.must_not_exist(test.workpath('test2', 'bar' + _obj)) -test.must_exist(test.workpath('test2', 'Build', 'foo' + _obj)) -test.must_exist(test.workpath('test2', 'Build', 'bar' + _obj)) - -################### -# Make sure that directories for subsidiary SConscript() calls -# in a build_dir get created if they don't already exist. -test.subdir('test3') - -test.subdir(['test3', 'src'], ['test3', 'src', '_glscry']) - -test.write(['test3', 'SConstruct'], """\ -SConscript(dirs=['src'], build_dir='build', duplicate=0) -""") - -test.write(['test3', 'src', 'SConscript'], """\ -SConscript(dirs=['_glscry']) -""") - -test.write(['test3', 'src', '_glscry', 'SConscript'], """\ -""") - -test.write(['test3', 'src', 'file.in'], "file.in\n") - -test.write(['test3', 'src', '_glscry', 'file.in'], "file.in\n") - -test.run(chdir='test3', stderr = warning) - - -test.pass_test() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Removed/BuildDir/Old/BuildDir.py b/test/Removed/BuildDir/Old/BuildDir.py new file mode 100644 index 0000000..1a1ba02 --- /dev/null +++ b/test/Removed/BuildDir/Old/BuildDir.py @@ -0,0 +1,295 @@ +#!/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 the deprecated BuildDir() function and method still +work to create a variant directory tree (by calling VariantDir() +under the covers). +""" + +import TestSCons + +_exe = TestSCons._exe + +test = TestSCons.TestSCons() + +test.write('SConscript', """ +BuildDir('build', 'src') +""") + +msg = """BuildDir() and the build_dir keyword have been deprecated; +\tuse VariantDir() and the variant_dir keyword instead.""" +test.deprecated_warning('deprecated-build-dir', msg) + +warning = '\nscons: warning: ' + TestSCons.re_escape(msg) \ + + '\n' + TestSCons.file_expr + +foo11 = test.workpath('work1', 'build', 'var1', 'foo1' + _exe) +foo12 = test.workpath('work1', 'build', 'var1', 'foo2' + _exe) +foo21 = test.workpath('work1', 'build', 'var2', 'foo1' + _exe) +foo22 = test.workpath('work1', 'build', 'var2', 'foo2' + _exe) +foo31 = test.workpath('work1', 'build', 'var3', 'foo1' + _exe) +foo32 = test.workpath('work1', 'build', 'var3', 'foo2' + _exe) +foo41 = test.workpath('work1', 'build', 'var4', 'foo1' + _exe) +foo42 = test.workpath('work1', 'build', 'var4', 'foo2' + _exe) +foo51 = test.workpath('build', 'var5', 'foo1' + _exe) +foo52 = test.workpath('build', 'var5', 'foo2' + _exe) + +test.subdir('work1') + +test.write(['work1', 'SConstruct'], """ +SetOption('warn', 'deprecated-build-dir') +src = Dir('src') +var2 = Dir('build/var2') +var3 = Dir('build/var3') +var4 = Dir('build/var4') +var5 = Dir('../build/var5') +var6 = Dir('../build/var6') + +env = Environment(BUILD = 'build', SRC = 'src') + +BuildDir('build/var1', src) +BuildDir(var2, src) +BuildDir(var3, src, duplicate=0) +env.BuildDir("$BUILD/var4", "$SRC", duplicate=0) +BuildDir(var5, src, duplicate=0) +BuildDir(var6, src) + +env = Environment(CPPPATH='#src', FORTRANPATH='#src') +SConscript('build/var1/SConscript', "env") +SConscript('build/var2/SConscript', "env") + +env = Environment(CPPPATH=src, FORTRANPATH=src) +SConscript('build/var3/SConscript', "env") +SConscript(File('SConscript', var4), "env") + +env = Environment(CPPPATH='.', FORTRANPATH='.') +SConscript('../build/var5/SConscript', "env") +SConscript('../build/var6/SConscript', "env") +""") + +test.subdir(['work1', 'src']) +test.write(['work1', 'src', 'SConscript'], """ +import os.path + +def buildIt(target, source, env): + if not os.path.exists('build'): + os.mkdir('build') + with open(str(source[0]), 'r') as ifp, open(str(target[0]), 'w') as ofp: + ofp.write(ifp.read()) + return 0 +Import("env") +env.Command(target='f2.c', source='f2.in', action=buildIt) +env.Program(target='foo2', source='f2.c') +env.Program(target='foo1', source='f1.c') +env.Command(target='f3.h', source='f3h.in', action=buildIt) +env.Command(target='f4.h', source='f4h.in', action=buildIt) +env.Command(target='f4.c', source='f4.in', action=buildIt) + +env2=env.Clone(CPPPATH='.') +env2.Program(target='foo3', source='f3.c') +env2.Program(target='foo4', source='f4.c') +""") + +test.write(['work1', 'src', 'f1.c'], r""" +#include +#include + +#include "f1.h" + +int +main(int argc, char *argv[]) +{ + argv[argc++] = "--"; + printf(F1_STR); + exit (0); +} +""") + +test.write(['work1', 'src', 'f2.in'], r""" +#include +#include + +#include "f2.h" + +int +main(int argc, char *argv[]) +{ + argv[argc++] = "--"; + printf(F2_STR); + exit (0); +} +""") + +test.write(['work1', 'src', 'f3.c'], r""" +#include +#include + +#include "f3.h" + +int +main(int argc, char *argv[]) +{ + argv[argc++] = "--"; + printf(F3_STR); + exit (0); +} +""") + +test.write(['work1', 'src', 'f4.in'], r""" +#include +#include + +#include "f4.h" + +int +main(int argc, char *argv[]) +{ + argv[argc++] = "--"; + printf(F4_STR); + exit (0); +} +""") + +test.write(['work1', 'src', 'f1.h'], r""" +#define F1_STR "f1.c\n" +""") + +test.write(['work1', 'src', 'f2.h'], r""" +#define F2_STR "f2.c\n" +""") + +test.write(['work1', 'src', 'f3h.in'], r""" +#define F3_STR "f3.c\n" +""") + +test.write(['work1', 'src', 'f4h.in'], r""" +#define F4_STR "f4.c\n" +""") + +# Some releases of freeBSD seem to have library complaints about +# tempnam(). Filter out these annoying messages before checking for +# error output. +def filter_tempnam(err): + if not err: + return '' + msg = "warning: tempnam() possibly used unsafely" + return '\n'.join([l for l in err.splitlines() if l.find(msg) == -1]) + +test.run(chdir='work1', arguments = '. ../build', stderr=None) + +stderr = filter_tempnam(test.stderr()) +test.fail_test(TestSCons.match_re_dotall(stderr, 6*warning)) + +test.run(program = foo11, stdout = "f1.c\n") +test.run(program = foo12, stdout = "f2.c\n") +test.run(program = foo41, stdout = "f1.c\n") +test.run(program = foo42, stdout = "f2.c\n") + +test.run(chdir='work1', + arguments='. ../build', + stderr = None, + stdout=test.wrap_stdout("""\ +scons: `.' is up to date. +scons: `%s' is up to date. +""" % test.workpath('build'))) + +stderr = filter_tempnam(test.stderr()) +test.fail_test(TestSCons.match_re_dotall(stderr, 6*warning)) + +import os +import stat +def equal_stats(x,y): + x = os.stat(x) + y = os.stat(y) + return (stat.S_IMODE(x[stat.ST_MODE]) == stat.S_IMODE(y[stat.ST_MODE]) and + x[stat.ST_MTIME] == y[stat.ST_MTIME]) + +# Make sure we did duplicate the source files in build/var2, +# and that their stats are the same: +test.must_exist(['work1', 'build', 'var2', 'f1.c']) +test.must_exist(['work1', 'build', 'var2', 'f2.in']) +test.fail_test(not equal_stats(test.workpath('work1', 'build', 'var2', 'f1.c'), test.workpath('work1', 'src', 'f1.c'))) +test.fail_test(not equal_stats(test.workpath('work1', 'build', 'var2', 'f2.in'), test.workpath('work1', 'src', 'f2.in'))) + +# Make sure we didn't duplicate the source files in build/var3. +test.must_not_exist(['work1', 'build', 'var3', 'f1.c']) +test.must_not_exist(['work1', 'build', 'var3', 'f2.in']) +test.must_not_exist(['work1', 'build', 'var3', 'b1.f']) +test.must_not_exist(['work1', 'build', 'var3', 'b2.in']) + +# Make sure we didn't duplicate the source files in build/var4. +test.must_not_exist(['work1', 'build', 'var4', 'f1.c']) +test.must_not_exist(['work1', 'build', 'var4', 'f2.in']) +test.must_not_exist(['work1', 'build', 'var4', 'b1.f']) +test.must_not_exist(['work1', 'build', 'var4', 'b2.in']) + +# Make sure we didn't duplicate the source files in build/var5. +test.must_not_exist(['build', 'var5', 'f1.c']) +test.must_not_exist(['build', 'var5', 'f2.in']) +test.must_not_exist(['build', 'var5', 'b1.f']) +test.must_not_exist(['build', 'var5', 'b2.in']) + +# verify that header files in the source directory are scanned properly: +test.write(['work1', 'src', 'f1.h'], r""" +#define F1_STR "f1.c 2\n" +""") + +test.write(['work1', 'src', 'f3h.in'], r""" +#define F3_STR "f3.c 2\n" +""") + +test.write(['work1', 'src', 'f4h.in'], r""" +#define F4_STR "f4.c 2\n" +""") + +test.run(chdir='work1', arguments = '../build/var5', stderr=None) + +stderr = filter_tempnam(test.stderr()) +test.fail_test(TestSCons.match_re_dotall(stderr, 6*warning)) + +test.run(program = foo51, stdout = "f1.c 2\n") +test.run(program = test.workpath('build', 'var5', 'foo3' + _exe), + stdout = "f3.c 2\n") +test.run(program = test.workpath('build', 'var5', 'foo4' + _exe), + stdout = "f4.c 2\n") + +test.run(chdir='work1', + arguments='../build/var5', + stderr=None, + stdout=test.wrap_stdout("""\ +scons: `%s' is up to date. +""" % test.workpath('build', 'var5'))) + +stderr = filter_tempnam(test.stderr()) +test.fail_test(TestSCons.match_re_dotall(stderr, 6*warning)) + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Removed/BuildDir/Old/SConscript-build_dir.py b/test/Removed/BuildDir/Old/SConscript-build_dir.py new file mode 100644 index 0000000..0d1ba6a --- /dev/null +++ b/test/Removed/BuildDir/Old/SConscript-build_dir.py @@ -0,0 +1,291 @@ +#!/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 specifying a build_dir argument to SConscript still works. +""" + +import TestSCons + +test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) + +test.write('SConscript', """ +SConscript('DummyScript', build_dir = 'build') +""") + +test.write('DummyScript', """ +""") + +msg = """The build_dir keyword has been deprecated; use the variant_dir keyword instead.""" +test.deprecated_warning('deprecated-build-dir', msg) + +warning = '\nscons: warning: ' + TestSCons.re_escape(msg) \ + + '\n' + TestSCons.file_expr + +all1 = test.workpath('test', 'build', 'var1', 'all') +all2 = test.workpath('test', 'build', 'var2', 'all') +all3 = test.workpath('test', 'build', 'var3', 'all') +all4 = test.workpath('test', 'build', 'var4', 'all') +all5 = test.workpath('build', 'var5', 'all') +all6 = test.workpath('build', 'var6', 'all') +all7 = test.workpath('build', 'var7', 'all') +all8 = test.workpath('build', 'var8', 'all') +all9 = test.workpath('test', 'build', 'var9', 'src', 'all') + +test.subdir('test') + +test.write(['test', 'SConstruct'], """ +SetOption('warn', 'deprecated-build-dir') +src = Dir('src') +alt = Dir('alt') +var1 = Dir('build/var1') +var2 = Dir('build/var2') +var3 = Dir('build/var3') +var4 = Dir('build/var4') +var5 = Dir('../build/var5') +var6 = Dir('../build/var6') +var7 = Dir('../build/var7') +var8 = Dir('../build/var8') +var9 = Dir('../build/var9') + +def cat(env, source, target): + target = str(target[0]) + with open(target, "wb") as ofp: + for src in source: + with open(str(src), "rb") as ifp: + ofp.write(ifp.read()) + +env = Environment(BUILDERS={'Cat':Builder(action=cat)}, + BUILD='build') + +Export("env") + +SConscript('src/SConscript', build_dir=var1) +SConscript('src/SConscript', build_dir='build/var2', src_dir=src) + +SConscript('src/SConscript', build_dir='build/var3', duplicate=0) + +#XXX We can't support var4 and var5 yet, because our VariantDir linkage +#XXX is to an entire source directory. We haven't yet generalized our +#XXX infrastructure to be able to take the SConscript file from one source +#XXX directory, but the rest of the files from a different one. +#XXX SConscript('src/SConscript', build_dir=var4, src_dir=alt, duplicate=0) + +#XXX SConscript('src/SConscript', build_dir='../build/var5', src_dir='alt') +SConscript('src/SConscript', build_dir=var6) + +SConscript('src/SConscript', build_dir=var7, src_dir=src, duplicate=0) +env.SConscript('src/SConscript', build_dir='../$BUILD/var8', duplicate=0) + +# This tests the fact that if you specify a src_dir that is above +# the dir a SConscript is in, that we do the intuitive thing, i.e., +# we set the path of the SConscript accordingly. The below is +# equivalent to saying: +# +# VariantDir('build/var9', '.') +# SConscript('build/var9/src/SConscript') +SConscript('src/SConscript', build_dir='build/var9', src_dir='.') +""") + +test.subdir(['test', 'src'], ['test', 'alt']) + +test.write(['test', 'src', 'SConscript'], """ +Import("env") +env.Cat('aaa.out', 'aaa.in') +env.Cat('bbb.out', 'bbb.in') +env.Cat('ccc.out', 'ccc.in') +env.Cat('all', ['aaa.out', 'bbb.out', 'ccc.out']) +""") + +test.write('test/src/aaa.in', "test/src/aaa.in\n") +test.write('test/src/bbb.in', "test/src/bbb.in\n") +test.write('test/src/ccc.in', "test/src/ccc.in\n") + +test.write('test/alt/aaa.in', "test/alt/aaa.in\n") +test.write('test/alt/bbb.in', "test/alt/bbb.in\n") +test.write('test/alt/ccc.in', "test/alt/ccc.in\n") + +test.run(chdir='test', arguments = '. ../build', stderr = 7*warning) + +all_src = "test/src/aaa.in\ntest/src/bbb.in\ntest/src/ccc.in\n" +all_alt = "test/alt/aaa.in\ntest/alt/bbb.in\ntest/alt/ccc.in\n" + +test.must_match(all1, all_src) +test.must_match(all2, all_src) +test.must_match(all3, all_src) +#XXX We can't support var4 and var5 yet, because our VariantDir linkage +#XXX is to an entire source directory. We haven't yet generalized our +#XXX infrastructure to be able to take the SConscript file from one source +#XXX directory, but the rest of the files from a different one. +#XXX test.must_match(all4, all_alt) +#XXX test.must_match(all5, all_alt) +test.must_match(all6, all_src) +test.must_match(all7, all_src) +test.must_match(all8, all_src) +test.must_match(all9, all_src) + +import os +import stat +def equal_stats(x,y): + x = os.stat(x) + y = os.stat(y) + return (stat.S_IMODE(x[stat.ST_MODE]) == stat.S_IMODE(y[stat.ST_MODE]) and + x[stat.ST_MTIME] == y[stat.ST_MTIME]) + +# Make sure we did duplicate the source files in build/var1, +# and that their stats are the same: +for file in ['aaa.in', 'bbb.in', 'ccc.in']: + test.must_exist(test.workpath('test', 'build', 'var1', file)) + test.fail_test(not equal_stats(test.workpath('test', 'build', 'var1', file), + test.workpath('test', 'src', file))) + +# Make sure we did duplicate the source files in build/var2, +# and that their stats are the same: +for file in ['aaa.in', 'bbb.in', 'ccc.in']: + test.must_exist(test.workpath('test', 'build', 'var2', file)) + test.fail_test(not equal_stats(test.workpath('test', 'build', 'var2', file), + test.workpath('test', 'src', file))) + +# Make sure we didn't duplicate the source files in build/var3. +test.must_not_exist(test.workpath('test', 'build', 'var3', 'aaa.in')) +test.must_not_exist(test.workpath('test', 'build', 'var3', 'bbb.in')) +test.must_not_exist(test.workpath('test', 'build', 'var3', 'ccc.in')) + +#XXX We can't support var4 and var5 yet, because our VariantDir linkage +#XXX is to an entire source directory. We haven't yet generalized our +#XXX infrastructure to be able to take the SConscript file from one source +#XXX directory, but the rest of the files from a different one. +#XXX Make sure we didn't duplicate the source files in build/var4. +#XXXtest.must_not_exist(test.workpath('test', 'build', 'var4', 'aaa.in')) +#XXXtest.must_not_exist(test.workpath('test', 'build', 'var4', 'bbb.in')) +#XXXtest.must_not_exist(test.workpath('test', 'build', 'var4', 'ccc.in')) + +#XXX We can't support var4 and var5 yet, because our VariantDir linkage +#XXX is to an entire source directory. We haven't yet generalized our +#XXX infrastructure to be able to take the SConscript file from one source +#XXX directory, but the rest of the files from a different one. +#XXX Make sure we did duplicate the source files in build/var5, +#XXX and that their stats are the same: +#XXXfor file in ['aaa.in', 'bbb.in', 'ccc.in']: +#XXX test.must_exist(test.workpath('build', 'var5', file)) +#XXX test.fail_test(not equal_stats(test.workpath('build', 'var5', file), +#XXX test.workpath('test', 'src', file))) + +# Make sure we did duplicate the source files in build/var6, +# and that their stats are the same: +for file in ['aaa.in', 'bbb.in', 'ccc.in']: + test.must_exist(test.workpath('build', 'var6', file)) + test.fail_test(not equal_stats(test.workpath('build', 'var6', file), + test.workpath('test', 'src', file))) + +# Make sure we didn't duplicate the source files in build/var7. +test.must_not_exist(test.workpath('build', 'var7', 'aaa.in')) +test.must_not_exist(test.workpath('build', 'var7', 'bbb.in')) +test.must_not_exist(test.workpath('build', 'var7', 'ccc.in')) + +# Make sure we didn't duplicate the source files in build/var8. +test.must_not_exist(test.workpath('build', 'var8', 'aaa.in')) +test.must_not_exist(test.workpath('build', 'var8', 'bbb.in')) +test.must_not_exist(test.workpath('build', 'var8', 'ccc.in')) + +################### +test.subdir('test2') + +test.write(['test2', 'SConstruct'], """\ +SConscript('SConscript', build_dir='Build', src_dir='.', duplicate=0) +""") + +test.write(['test2', 'SConscript'], """\ +env = Environment() +foo_obj = env.Object('foo.c') +env.Program('foo', [foo_obj, 'bar.c']) +""") + +test.write(['test2', 'bar.c'], r""" +#include +#include + +void +bar(void) { + printf("bar.c\n"); +} +""") + +test.write(['test2', 'foo.c'], r""" +#include +#include + +extern void +bar(void); + +int +main(int argc, char *argv[]) { + bar(); + printf("foo.c\n"); +} +""") + +test.run(chdir="test2", stderr = warning) + +_obj = TestSCons._obj + +test.must_not_exist(test.workpath('test2', 'foo' + _obj)) +test.must_not_exist(test.workpath('test2', 'bar' + _obj)) +test.must_exist(test.workpath('test2', 'Build', 'foo' + _obj)) +test.must_exist(test.workpath('test2', 'Build', 'bar' + _obj)) + +################### +# Make sure that directories for subsidiary SConscript() calls +# in a build_dir get created if they don't already exist. +test.subdir('test3') + +test.subdir(['test3', 'src'], ['test3', 'src', '_glscry']) + +test.write(['test3', 'SConstruct'], """\ +SConscript(dirs=['src'], build_dir='build', duplicate=0) +""") + +test.write(['test3', 'src', 'SConscript'], """\ +SConscript(dirs=['_glscry']) +""") + +test.write(['test3', 'src', '_glscry', 'SConscript'], """\ +""") + +test.write(['test3', 'src', 'file.in'], "file.in\n") + +test.write(['test3', 'src', '_glscry', 'file.in'], "file.in\n") + +test.run(chdir='test3', stderr = warning) + + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Removed/BuildDir/README.md b/test/Removed/BuildDir/README.md new file mode 100644 index 0000000..c4fd879 --- /dev/null +++ b/test/Removed/BuildDir/README.md @@ -0,0 +1,6 @@ +BuildDir/Old contains old tests which used the now removed BuildDir +function, env.BuildDir method, and build_dir argument to SConscript, +preserved here for reference; the presence of an scontest.skip file +means they are never executed. + +The "new" tests verify failure using these symbols. diff --git a/test/Removed/BuildDir/SConstruct.global b/test/Removed/BuildDir/SConstruct.global new file mode 100644 index 0000000..086fbae --- /dev/null +++ b/test/Removed/BuildDir/SConstruct.global @@ -0,0 +1 @@ +BuildDir('build', 'src') diff --git a/test/Removed/BuildDir/SConstruct.kwarg b/test/Removed/BuildDir/SConstruct.kwarg new file mode 100644 index 0000000..a5c46fb --- /dev/null +++ b/test/Removed/BuildDir/SConstruct.kwarg @@ -0,0 +1 @@ +SConscript('src/SConscript', build_dir='build') diff --git a/test/Removed/BuildDir/SConstruct.method b/test/Removed/BuildDir/SConstruct.method new file mode 100644 index 0000000..afea459 --- /dev/null +++ b/test/Removed/BuildDir/SConstruct.method @@ -0,0 +1,3 @@ +env = Environment(BUILD='build', SRC='src') + +env.BuildDir('build', 'src') -- cgit v0.12 From 063a3281b4fe7f43a34c0e65dfd3a02446ba12f8 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sun, 15 Dec 2019 09:08:10 -0700 Subject: [PR #3497] add the missing testcases forgot to add these to the initial commit Signed-off-by: Mats Wichmann --- test/Removed/BuildDir/BuildDir.py | 61 +++++++++++++++++++++++++++ test/Removed/BuildDir/SConscript-build_dir.py | 54 ++++++++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 test/Removed/BuildDir/BuildDir.py create mode 100644 test/Removed/BuildDir/SConscript-build_dir.py diff --git a/test/Removed/BuildDir/BuildDir.py b/test/Removed/BuildDir/BuildDir.py new file mode 100644 index 0000000..43c8b8b --- /dev/null +++ b/test/Removed/BuildDir/BuildDir.py @@ -0,0 +1,61 @@ +#!/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 the BuildDir function and method no longer work. +""" + +import TestSCons + +_exe = TestSCons._exe + +test = TestSCons.TestSCons(match=TestSCons.match_exact) + +test.subdir('src') + +test.file_fixture('SConstruct.global', 'SConstruct') +expect = """\ +NameError: name 'BuildDir' is not defined: + File "{}", line 1: + BuildDir('build', 'src') +""".format(test.workpath('SConstruct')) +test.run(arguments='-Q -s', status=2, stderr=expect) + +test.file_fixture('SConstruct.method', 'SConstruct') +expect = """\ +AttributeError: 'SConsEnvironment' object has no attribute 'BuildDir': + File "{}", line 3: + env.BuildDir('build', 'src') +""".format(test.workpath('SConstruct')) +test.run(arguments='-Q -s', status=2, stderr=expect) + + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Removed/BuildDir/SConscript-build_dir.py b/test/Removed/BuildDir/SConscript-build_dir.py new file mode 100644 index 0000000..55be7b1 --- /dev/null +++ b/test/Removed/BuildDir/SConscript-build_dir.py @@ -0,0 +1,54 @@ +#!/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 specifying a build_dir argument to SConscript no longer works. +""" + +import TestSCons + +test = TestSCons.TestSCons(match = TestSCons.match_exact) + +test.file_fixture('SConstruct.kwarg', 'SConstruct') +test.subdir('src') +test.write(['src', 'SConscript'], """ +""") + +# this doesn't work yet +expect = """\ +TypeError: SConscript() got an unexpected keyword argument 'build_dir': + File "{}", line 1: + SConscript('src/SConscript', build_dir='build') +""".format(test.workpath('SConstruct')) +test.run(arguments='-Q -s', status=2, stderr=expect) + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: -- cgit v0.12 From 81142e5249452a32a6b167709299ec45a92f0717 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sun, 15 Dec 2019 12:23:36 -0700 Subject: [PR #3497] add missed sconstest.skip Signed-off-by: Mats Wichmann --- test/Removed/BuildDir/Old/sconstest.skip | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/Removed/BuildDir/Old/sconstest.skip diff --git a/test/Removed/BuildDir/Old/sconstest.skip b/test/Removed/BuildDir/Old/sconstest.skip new file mode 100644 index 0000000..e69de29 -- cgit v0.12 From 85b6c3efd79561dd9c9af71217ee8dff8b05c37a Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Mon, 16 Dec 2019 08:27:57 -0700 Subject: [PR #3497] skip test for build_dir kwarg Turns out cannot test for now-unknown build_dir arg because SConscript() doesn't error on such. Skip test for now, leaving a note (and and issue). Signed-off-by: Mats Wichmann --- test/Removed/BuildDir/SConscript-build_dir.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/Removed/BuildDir/SConscript-build_dir.py b/test/Removed/BuildDir/SConscript-build_dir.py index 55be7b1..5a8d1ca 100644 --- a/test/Removed/BuildDir/SConscript-build_dir.py +++ b/test/Removed/BuildDir/SConscript-build_dir.py @@ -32,6 +32,9 @@ import TestSCons test = TestSCons.TestSCons(match = TestSCons.match_exact) +#TODO: fix #3500 and restore test, or drop entirly +test.skip_test('SConscript() does not error on unknown kwargs, see Issue #3500, skipping test\n') + test.file_fixture('SConstruct.kwarg', 'SConstruct') test.subdir('src') test.write(['src', 'SConscript'], """ -- cgit v0.12 From 8383095df98ec6848a68c818a637acda40896972 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 17 Dec 2019 01:38:08 +0000 Subject: Regenerated docs for 3.1.2 release --- doc/generated/builders.gen | 858 ++--- doc/generated/examples/EnumVariable_map_1.xml | 3 +- doc/generated/examples/addmethod_ex1_1.xml | 3 +- doc/generated/examples/addmethod_ex2_1.xml | 3 +- doc/generated/examples/addmethod_ex2_2.xml | 3 +- doc/generated/examples/alias_ex1_1.xml | 3 +- doc/generated/examples/alias_ex2_1.xml | 3 +- doc/generated/examples/buildersbuiltin_ex1_1.xml | 3 +- doc/generated/examples/buildersbuiltin_ex2_1.xml | 3 +- doc/generated/examples/buildersbuiltin_ex3_1.xml | 3 +- doc/generated/examples/buildersbuiltin_ex4_1.xml | 3 +- doc/generated/examples/buildersbuiltin_libs_1.xml | 3 +- doc/generated/examples/buildersbuiltin_libs_2.xml | 3 +- doc/generated/examples/builderscommands_ex1_1.xml | 3 +- doc/generated/examples/builderscommands_ex2_1.xml | 3 +- .../examples/builderswriting_MY_EMITTER_1.xml | 3 +- doc/generated/examples/builderswriting_ex1_1.xml | 3 +- doc/generated/examples/builderswriting_ex2_1.xml | 3 +- doc/generated/examples/builderswriting_ex3_1.xml | 3 +- doc/generated/examples/builderswriting_ex4_1.xml | 3 +- doc/generated/examples/builderswriting_ex5_1.xml | 3 +- doc/generated/examples/builderswriting_ex6_1.xml | 3 +- doc/generated/examples/builderswriting_ex7_1.xml | 3 +- doc/generated/examples/caching_ex-random_1.xml | 9 +- doc/generated/examples/caching_ex1_1.xml | 3 +- doc/generated/examples/caching_ex1_2.xml | 3 +- doc/generated/examples/caching_ex1_4.xml | 3 +- doc/generated/examples/caching_ex1_5.xml | 3 +- doc/generated/examples/commandline_ARGLIST_1.xml | 3 +- doc/generated/examples/commandline_ARGUMENTS_1.xml | 3 +- doc/generated/examples/commandline_AddOption_1.xml | 3 +- doc/generated/examples/commandline_AddOption_2.xml | 3 +- .../examples/commandline_BUILD_TARGETS_1_1.xml | 3 +- .../examples/commandline_BoolVariable_1.xml | 3 +- .../examples/commandline_BoolVariable_2.xml | 3 +- .../examples/commandline_BoolVariable_3.xml | 3 +- .../examples/commandline_BoolVariable_4.xml | 3 +- .../examples/commandline_BoolVariable_5.xml | 3 +- .../commandline_COMMAND_LINE_TARGETS_1.xml | 3 +- .../examples/commandline_DEFAULT_TARGETS_1_1.xml | 3 +- .../examples/commandline_DEFAULT_TARGETS_2_1.xml | 3 +- doc/generated/examples/commandline_Default1_1.xml | 3 +- doc/generated/examples/commandline_Default1_2.xml | 3 +- doc/generated/examples/commandline_Default2_1.xml | 3 +- doc/generated/examples/commandline_Default3_1.xml | 3 +- doc/generated/examples/commandline_Default4_1.xml | 3 +- .../examples/commandline_EnumVariable_1.xml | 3 +- .../examples/commandline_EnumVariable_2.xml | 3 +- .../examples/commandline_EnumVariable_3.xml | 3 +- .../examples/commandline_EnumVariable_ic1_1.xml | 3 +- .../examples/commandline_EnumVariable_ic2_1.xml | 3 +- .../examples/commandline_ListVariable_1.xml | 3 +- .../examples/commandline_ListVariable_2.xml | 3 +- .../examples/commandline_ListVariable_3.xml | 3 +- .../examples/commandline_PackageVariable_1.xml | 3 +- .../examples/commandline_PathVariable_1.xml | 3 +- .../examples/commandline_PathVariable_2.xml | 3 +- .../examples/commandline_SCONSFLAGS_1.xml | 3 +- doc/generated/examples/commandline_SetOption_1.xml | 3 +- doc/generated/examples/commandline_SetOption_2.xml | 3 +- doc/generated/examples/commandline_SetOption_3.xml | 3 +- .../examples/commandline_UnknownVariables_1.xml | 5 +- .../examples/commandline_Variables1_1.xml | 3 +- .../examples/commandline_Variables_Help_1.xml | 3 +- .../commandline_Variables_custom_py_1_1.xml | 3 +- .../commandline_Variables_custom_py_2_1.xml | 3 +- doc/generated/examples/depends_AlwaysBuild_1.xml | 3 +- doc/generated/examples/depends_AlwaysBuild_2.xml | 3 +- doc/generated/examples/depends_Requires_1.xml | 3 +- doc/generated/examples/depends_ex1_1.xml | 3 +- doc/generated/examples/depends_ex1_2.xml | 3 +- doc/generated/examples/depends_ex1_3.xml | 3 +- doc/generated/examples/depends_ex1_4.xml | 3 +- doc/generated/examples/depends_ex1_5.xml | 3 +- doc/generated/examples/depends_ex1_6.xml | 3 +- doc/generated/examples/depends_ex1_7.xml | 3 +- doc/generated/examples/depends_ex1_8.xml | 3 +- doc/generated/examples/depends_ex5_1.xml | 3 +- doc/generated/examples/depends_ex5_2.xml | 3 +- .../examples/depends_ignore_explicit_1.xml | 3 +- doc/generated/examples/depends_include_1.xml | 3 +- doc/generated/examples/depends_macroinc_1.xml | 3 +- doc/generated/examples/depends_match_1.xml | 3 +- doc/generated/examples/depends_mixing_1.xml | 3 +- doc/generated/examples/depends_newer_1.xml | 3 +- doc/generated/examples/depends_no-Requires_1.xml | 3 +- doc/generated/examples/depends_parsedep_1.xml | 3 +- .../examples/environments_Append-nonexistent_1.xml | 3 +- .../environments_Prepend-nonexistent_1.xml | 3 +- .../environments_Replace-nonexistent_1.xml | 3 +- doc/generated/examples/environments_Replace1_1.xml | 3 +- doc/generated/examples/environments_Replace2_1.xml | 3 +- doc/generated/examples/environments_ex1_1.xml | 3 +- doc/generated/examples/environments_ex2_1.xml | 3 +- doc/generated/examples/environments_ex3_1.xml | 3 +- doc/generated/examples/environments_ex4_1.xml | 3 +- doc/generated/examples/environments_ex5_1.xml | 3 +- doc/generated/examples/environments_ex6_1.xml | 3 +- doc/generated/examples/environments_ex6b_1.xml | 3 +- doc/generated/examples/environments_ex6b_2.xml | 3 +- doc/generated/examples/environments_ex8_1.xml | 3 +- doc/generated/examples/environments_ex9_1.xml | 3 +- doc/generated/examples/environments_missing1_1.xml | 3 +- doc/generated/examples/environments_missing2_1.xml | 3 +- doc/generated/examples/environments_missing3_1.xml | 3 +- doc/generated/examples/factories_Chmod_1.xml | 3 +- doc/generated/examples/factories_Copy1_1.xml | 3 +- doc/generated/examples/factories_Copy2_1.xml | 3 +- doc/generated/examples/factories_Copy3_1.xml | 3 +- doc/generated/examples/factories_Delete1_1.xml | 3 +- doc/generated/examples/factories_Delete2_1.xml | 3 +- doc/generated/examples/factories_Execute_1.xml | 3 +- doc/generated/examples/factories_Mkdir_1.xml | 3 +- doc/generated/examples/factories_Move_1.xml | 3 +- doc/generated/examples/factories_Touch_1.xml | 3 +- doc/generated/examples/fileremoval_clean-ex1_1.xml | 3 +- .../examples/fileremoval_noclean-ex1_1.xml | 3 +- .../examples/fileremoval_precious-ex1_1.xml | 3 +- doc/generated/examples/hierarchy_Return_1.xml | 3 +- doc/generated/examples/hierarchy_ex1_1.xml | 3 +- doc/generated/examples/hierarchy_ex2_1.xml | 3 +- doc/generated/examples/hierarchy_ex3_1.xml | 3 +- doc/generated/examples/install_ex1_1.xml | 3 +- doc/generated/examples/install_ex2_1.xml | 3 +- doc/generated/examples/install_ex3_1.xml | 3 +- doc/generated/examples/install_ex4_1.xml | 3 +- doc/generated/examples/install_ex5_1.xml | 3 +- doc/generated/examples/java_JAVACLASSDIR_1.xml | 3 +- doc/generated/examples/java_RMIC_1.xml | 3 +- doc/generated/examples/java_jar1_1.xml | 3 +- doc/generated/examples/java_jar2_1.xml | 3 +- doc/generated/examples/java_java-classes_1.xml | 3 +- doc/generated/examples/java_java-classes_2.xml | 3 +- doc/generated/examples/java_java_1.xml | 3 +- doc/generated/examples/java_javah_1.xml | 3 +- doc/generated/examples/java_javah_file_1.xml | 3 +- doc/generated/examples/lesssimple_ex2_1.xml | 3 +- doc/generated/examples/lesssimple_ex3_1.xml | 3 +- doc/generated/examples/lesssimple_ex3_2.xml | 3 +- doc/generated/examples/lesssimple_ex4_1.xml | 3 +- doc/generated/examples/lesssimple_ex5_1.xml | 3 +- doc/generated/examples/lesssimple_target_1.xml | 3 +- doc/generated/examples/lesssimple_target_2.xml | 3 +- .../examples/libraries_SharedLibrary_1.xml | 3 +- .../examples/libraries_SharedLibrary_2.xml | 3 +- doc/generated/examples/libraries_ex1_1.xml | 3 +- doc/generated/examples/libraries_ex1_2.xml | 3 +- doc/generated/examples/libraries_ex2_1.xml | 3 +- doc/generated/examples/libraries_ex2_2.xml | 3 +- doc/generated/examples/libraries_ex3_1.xml | 3 +- doc/generated/examples/libraries_ex3_2.xml | 3 +- doc/generated/examples/libraries_objects_1.xml | 3 +- .../examples/mergeflags_MergeFlags1_1.xml | 3 +- .../examples/mergeflags_MergeFlags2_1.xml | 3 +- .../examples/mergeflags_MergeFlags3_1.xml | 3 +- doc/generated/examples/misc_Exit_1.xml | 3 +- doc/generated/examples/misc_FindFile1a_1.xml | 3 +- doc/generated/examples/misc_FindFile1b_1.xml | 3 +- doc/generated/examples/misc_FindFile1d_1.xml | 3 +- doc/generated/examples/misc_FindFile2_1.xml | 3 +- doc/generated/examples/misc_FindFile2_2.xml | 3 +- doc/generated/examples/misc_FindFile3_1.xml | 3 +- doc/generated/examples/misc_Flatten1_1.xml | 3 +- doc/generated/examples/misc_Flatten2_1.xml | 3 +- doc/generated/examples/nodes_GetBuildPath_1.xml | 3 +- doc/generated/examples/nodes_ex1_1.xml | 3 +- doc/generated/examples/nodes_ex1_2.xml | 3 +- doc/generated/examples/nodes_exists_1.xml | 3 +- doc/generated/examples/nodes_print_1.xml | 3 +- doc/generated/examples/nodes_print_2.xml | 3 +- .../examples/output_Progress-TARGET_1.xml | 3 +- doc/generated/examples/output_ex1_1.xml | 3 +- doc/generated/examples/output_ex2_1.xml | 3 +- doc/generated/examples/output_ex2_2.xml | 3 +- doc/generated/examples/output_gbf2_1.xml | 3 +- doc/generated/examples/parseflags_ex1_1.xml | 3 +- doc/generated/examples/parseflags_ex1_2.xml | 3 +- doc/generated/examples/parseflags_ex2_1.xml | 3 +- doc/generated/examples/parseflags_ex3_1.xml | 3 +- doc/generated/examples/parseflags_ex4_1.xml | 3 +- doc/generated/examples/repositories_CPPPATH3_1.xml | 3 +- doc/generated/examples/repositories_CPPPATH_1.xml | 3 +- doc/generated/examples/repositories_ex1_1.xml | 3 +- doc/generated/examples/repositories_ex2_1.xml | 3 +- doc/generated/examples/repositories_ex3_1.xml | 3 +- doc/generated/examples/repositories_ex4_1.xml | 3 +- doc/generated/examples/repositories_quote1_1.xml | 3 +- doc/generated/examples/separate_builddir_1.xml | 3 +- .../examples/separate_builddir_sconscript_1.xml | 3 +- doc/generated/examples/separate_duplicate0_1.xml | 3 +- doc/generated/examples/separate_ex1_1.xml | 3 +- .../separate_glob_builddir_sconscript_1.xml | 3 +- doc/generated/examples/sideeffect_parallel_1.xml | 3 +- doc/generated/examples/sideeffect_shared_1.xml | 3 +- doc/generated/examples/sideeffect_simple_1.xml | 3 +- doc/generated/examples/simple_Object_1.xml | 3 +- doc/generated/examples/simple_Object_2.xml | 3 +- doc/generated/examples/simple_clean_1.xml | 3 +- doc/generated/examples/simple_clean_2.xml | 3 +- doc/generated/examples/simple_declarative_1.xml | 3 +- doc/generated/examples/simple_ex1_1.xml | 3 +- doc/generated/examples/simple_ex1_2.xml | 3 +- doc/generated/examples/simple_ex1_3.xml | 3 +- doc/generated/examples/simple_ex1_4.xml | 3 +- doc/generated/examples/simple_java_1.xml | 3 +- doc/generated/examples/sourcecode_bitkeeper_1.xml | 3 +- doc/generated/examples/sourcecode_cvs_1.xml | 3 +- doc/generated/examples/sourcecode_rcs_1.xml | 3 +- doc/generated/examples/sourcecode_sccs_1.xml | 3 +- doc/generated/examples/tasks_ex1_1.xml | 3 +- doc/generated/examples/troubleshoot_Dump_1.xml | 18 +- doc/generated/examples/troubleshoot_Dump_2.xml | 34 +- doc/generated/examples/troubleshoot_Dump_ENV_1.xml | 5 +- doc/generated/examples/troubleshoot_Dump_ENV_2.xml | 3 +- doc/generated/examples/troubleshoot_explain1_1.xml | 3 +- doc/generated/examples/troubleshoot_explain1_2.xml | 3 +- doc/generated/examples/troubleshoot_explain1_3.xml | 5 +- doc/generated/examples/troubleshoot_explain2_1.xml | 3 +- doc/generated/examples/troubleshoot_explain3_1.xml | 3 +- doc/generated/examples/troubleshoot_findlibs_1.xml | 3 +- .../examples/troubleshoot_stacktrace_1.xml | 3 +- .../examples/troubleshoot_stacktrace_2.xml | 3 +- .../examples/troubleshoot_taskmastertrace_1.xml | 3 +- doc/generated/examples/troubleshoot_tree1_1.xml | 3 +- doc/generated/examples/troubleshoot_tree1_2.xml | 3 +- doc/generated/examples/troubleshoot_tree1_3.xml | 3 +- doc/generated/examples/troubleshoot_tree1_4.xml | 3 +- doc/generated/examples/troubleshoot_tree1_5.xml | 3 +- doc/generated/examples/troubleshoot_tree1_6.xml | 3 +- doc/generated/examples/troubleshoot_tree2_1.xml | 3 +- doc/generated/examples/troubleshoot_tree2_2.xml | 3 +- doc/generated/examples/variants_ex_1.xml | 3 +- doc/generated/examples/variants_ex_2.xml | 3 +- doc/generated/functions.gen | 1219 +++---- doc/generated/functions.mod | 4 - doc/generated/tools.gen | 664 ++-- doc/generated/tools.mod | 4 +- doc/generated/variables.gen | 3552 ++++++++++++-------- doc/generated/variables.mod | 20 +- 239 files changed, 4073 insertions(+), 3002 deletions(-) diff --git a/doc/generated/builders.gen b/doc/generated/builders.gen index 65201ea..59d2dca 100644 --- a/doc/generated/builders.gen +++ b/doc/generated/builders.gen @@ -1,3 +1,4 @@ + %scons; @@ -11,7 +12,7 @@ %variables-mod; ]> - + CFile() @@ -19,17 +20,18 @@ env.CFile() - + + Builds a C source file given a lex (.l) or yacc (.y) input file. -The suffix specified by the $CFILESUFFIX construction variable +The suffix specified by the $CFILESUFFIX construction variable (.c by default) is automatically added to the target if it is not already present. Example: - + # builds foo.c env.CFile(target = 'foo.c', source = 'foo.l') # builds bar.c @@ -66,18 +68,19 @@ for the calling syntax and details. env.CXXFile() - + + Builds a C++ source file given a lex (.ll) or yacc (.yy) input file. -The suffix specified by the $CXXFILESUFFIX construction variable +The suffix specified by the $CXXFILESUFFIX construction variable (.cc by default) is automatically added to the target if it is not already present. Example: - + # builds foo.cc env.CXXFile(target = 'foo.cc', source = 'foo.ll') # builds bar.cc @@ -92,19 +95,20 @@ env.CXXFile(target = 'bar', source = 'bar.yy') env.DocbookEpub() - + + A pseudo-Builder, providing a Docbook toolchain for EPUB output. -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) env.DocbookEpub('manual.epub', 'manual.xml') - + or simply -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) env.DocbookEpub('manual') @@ -117,16 +121,17 @@ env.DocbookEpub('manual') env.DocbookHtml() - + + A pseudo-Builder, providing a Docbook toolchain for HTML output. -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) env.DocbookHtml('manual.html', 'manual.xml') - + or simply -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) env.DocbookHtml('manual') @@ -138,34 +143,35 @@ env.DocbookHtml('manual') env.DocbookHtmlChunked() - + + A pseudo-Builder, providing a Docbook toolchain for chunked HTML output. It supports the base.dir parameter. The chunkfast.xsl file (requires "EXSLT") is used as the default stylesheet. Basic syntax: -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) env.DocbookHtmlChunked('manual') - + where manual.xml is the input file. -If you use the root.filename +If you use the root.filename parameter in your own stylesheets you have to specify the new target name. This ensures that the dependencies get correct, especially for the cleanup via scons -c: -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) env.DocbookHtmlChunked('mymanual.html', 'manual', xsl='htmlchunk.xsl') -Some basic support for the base.dir is provided. You +Some basic support for the base.dir is provided. You can add the base_dir keyword to your Builder call, and the given prefix gets prepended to all the created filenames: -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) env.DocbookHtmlChunked('manual', xsl='htmlchunk.xsl', base_dir='output/') -Make sure that you don't forget the trailing slash for the base folder, else +Make sure that you don't forget the trailing slash for the base folder, else your files get renamed only! @@ -177,34 +183,35 @@ your files get renamed only! env.DocbookHtmlhelp() - + + A pseudo-Builder, providing a Docbook toolchain for HTMLHELP output. Its basic syntax is: -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) env.DocbookHtmlhelp('manual') - + where manual.xml is the input file. -If you use the root.filename +If you use the root.filename parameter in your own stylesheets you have to specify the new target name. This ensures that the dependencies get correct, especially for the cleanup via scons -c: -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) env.DocbookHtmlhelp('mymanual.html', 'manual', xsl='htmlhelp.xsl') -Some basic support for the base.dir parameter +Some basic support for the base.dir parameter is provided. You can add the base_dir keyword to your Builder call, and the given prefix gets prepended to all the created filenames: -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) env.DocbookHtmlhelp('manual', xsl='htmlhelp.xsl', base_dir='output/') -Make sure that you don't forget the trailing slash for the base folder, else +Make sure that you don't forget the trailing slash for the base folder, else your files get renamed only! @@ -217,15 +224,16 @@ your files get renamed only! env.DocbookMan() - + + A pseudo-Builder, providing a Docbook toolchain for Man page output. Its basic syntax is: -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) env.DocbookMan('manual') - + where manual.xml is the input file. Note, that you can specify a target name, but the actual output names are automatically set from the refname entries in your XML source. @@ -239,19 +247,20 @@ set from the refname entries in your XML source. env.DocbookPdf() - + + A pseudo-Builder, providing a Docbook toolchain for PDF output. -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) env.DocbookPdf('manual.pdf', 'manual.xml') - + or simply -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) env.DocbookPdf('manual') @@ -264,32 +273,33 @@ env.DocbookPdf('manual') env.DocbookSlidesHtml() - + + A pseudo-Builder, providing a Docbook toolchain for HTML slides output. -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) env.DocbookSlidesHtml('manual') -If you use the titlefoil.html parameter in +If you use the titlefoil.html parameter in your own stylesheets you have to give the new target name. This ensures that the dependencies get correct, especially for the cleanup via scons -c: -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) env.DocbookSlidesHtml('mymanual.html','manual', xsl='slideshtml.xsl') -Some basic support for the base.dir parameter +Some basic support for the base.dir parameter is provided. You can add the base_dir keyword to your Builder call, and the given prefix gets prepended to all the created filenames: -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) env.DocbookSlidesHtml('manual', xsl='slideshtml.xsl', base_dir='output/') -Make sure that you don't forget the trailing slash for the base folder, else +Make sure that you don't forget the trailing slash for the base folder, else your files get renamed only! @@ -302,19 +312,20 @@ your files get renamed only! env.DocbookSlidesPdf() - + + A pseudo-Builder, providing a Docbook toolchain for PDF slides output. -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) env.DocbookSlidesPdf('manual.pdf', 'manual.xml') - + or simply -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) env.DocbookSlidesPdf('manual') @@ -326,11 +337,12 @@ env.DocbookSlidesPdf('manual') env.DocbookXInclude() - + + A pseudo-Builder, for resolving XIncludes in a separate processing step. -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) env.DocbookXInclude('manual_xincluded.xml', 'manual.xml') @@ -342,15 +354,16 @@ env.DocbookXInclude('manual_xincluded.xml', 'manual.xml') env.DocbookXslt() - + + A pseudo-Builder, applying a given XSL transformation to the input file. -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) env.DocbookXslt('manual_transformed.xml', 'manual.xml', xsl='transform.xslt') -Note, that this builder requires the xsl parameter +Note, that this builder requires the xsl parameter to be set. @@ -362,40 +375,41 @@ to be set. env.DVI() - + + Builds a .dvi file from a .tex, .ltx or .latex input file. If the source file suffix is .tex, -scons +scons will examine the contents of the file; if the string \documentclass or \documentstyle is found, the file is assumed to be a LaTeX file and -the target is built by invoking the $LATEXCOM command line; -otherwise, the $TEXCOM command line is used. +the target is built by invoking the $LATEXCOM command line; +otherwise, the $TEXCOM command line is used. If the file is a LaTeX file, the -DVI +DVI builder method will also examine the contents of the .aux -file and invoke the $BIBTEX command line +file and invoke the $BIBTEX command line if the string bibdata is found, -start $MAKEINDEX to generate an index if a +start $MAKEINDEX to generate an index if a .ind file is found and will examine the contents .log -file and re-run the $LATEXCOM command +file and re-run the $LATEXCOM command if the log file says it is necessary. - + The suffix .dvi (hard-coded within TeX itself) is automatically added to the target @@ -403,7 +417,7 @@ if it is not already present. Examples: - + # builds from aaa.tex env.DVI(target = 'aaa.dvi', source = 'aaa.tex') # builds bbb.dvi @@ -420,13 +434,14 @@ env.DVI(target = 'ccc.dvi', source = 'ccc.latex') env.Gs() - + + A Builder for explicitly calling the gs executable. Depending on the underlying OS, the different names gs, gsos2 and gswin32c are tried. -env = Environment(tools=['gs']) +env = Environment(tools=['gs']) env.Gs('cover.jpg','scons-scons.pdf', GSFLAGS='-dNOPAUSE -dBATCH -sDEVICE=jpeg -dFirstPage=1 -dLastPage=1 -q') ) @@ -440,7 +455,8 @@ env.Gs('cover.jpg','scons-scons.pdf', env.Install() - + + Installs one or more source files or directories in the specified target, which must be a directory. @@ -450,7 +466,7 @@ sources may be given as a string or as a node returned by a builder. - + env.Install('/usr/local/bin', source = ['foo', 'bar']) @@ -478,7 +494,8 @@ and the chapters on Installing Files and on Alias Targets). env.InstallAs() - + + Installs one or more source files or directories to specific names, allowing changing a file or directory name @@ -490,7 +507,7 @@ source 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'], @@ -506,12 +523,13 @@ env.InstallAs(target = ['../lib/libfoo.a', '../lib/libbar.a'], env.InstallVersionedLib() - + + Installs a versioned shared library. The symlinks appropriate to the architecture will be generated based on symlinks of the source library. - + env.InstallVersionedLib(target = '/usr/local/bin/foo', source = 'libxyz.1.5.2.so') @@ -524,40 +542,41 @@ env.InstallVersionedLib(target = '/usr/local/bin/foo', env.Jar() - + + Builds a Java archive (.jar) file from the specified list of sources. Any directories in the source list will be searched for .class files). Any .java files in the source list will be compiled to .class files -by calling the Java Builder. +by calling the Java Builder. - -If the $JARCHDIR value is set, the -jar + +If the $JARCHDIR value is set, the +jar command will change to the specified directory using the option. -If $JARCHDIR is not set explicitly, -SCons will use the top of any subdirectory tree +If $JARCHDIR is not set explicitly, +SCons will use the top of any subdirectory tree in which Java .class -were built by the Java Builder. +were built by the Java Builder. - + If the contents any of the source files begin with the string Manifest-Version, the file is assumed to be a manifest and is passed to the -jar +jar command with the option set. - + env.Jar(target = 'foo.jar', source = 'classes') env.Jar(target = 'bar.jar', @@ -572,7 +591,8 @@ env.Jar(target = 'bar.jar', env.Java() - + + Builds one or more Java class files. The sources may be any combination of explicit .java @@ -581,7 +601,7 @@ env.Jar(target = 'bar.jar', for .java files. - + SCons will parse each source .java file to find the classes (including inner classes) @@ -592,7 +612,7 @@ env.Jar(target = 'bar.jar', the specified target directory. - + SCons will also search each Java file for the Java package name, which it assumes can be found on a line @@ -615,17 +635,17 @@ env.Jar(target = 'bar.jar', class file. - + Examples: - + env.Java(target = 'classes', source = 'src') env.Java(target = 'classes', source = ['src1', 'src2']) env.Java(target = 'classes', source = ['File1.java', 'File2.java']) - + Java source files can use the native encoding for the underlying OS. Since SCons compiles in simple ASCII mode by default, the compiler will generate warnings about unmappable characters, @@ -638,7 +658,7 @@ env.Jar(target = 'bar.jar', with a different encoding. - + env = Environment() env['ENV']['LANG'] = 'en_GB.UTF-8' @@ -651,7 +671,8 @@ env.Jar(target = 'bar.jar', env.JavaH() - + + Builds C header and source files for implementing Java native methods. The target can be either a directory @@ -661,29 +682,29 @@ will contain all of the definitions. The source can be the names of .class files, the names of .java files to be compiled into .class files -by calling the Java builder method, +by calling the Java builder method, or the objects returned from the -Java +Java builder method. - + If the construction variable -$JAVACLASSDIR +$JAVACLASSDIR is set, either in the environment or in the call to the -JavaH +JavaH builder method itself, then the value of the variable will be stripped from the beginning of any .class file names. - + Examples: - + # builds java_native.h classes = env.Java(target = 'classdir', source = 'src') env.JavaH(target = 'java_native.h', source = classes) @@ -706,9 +727,10 @@ env.JavaH(target = 'export', env.Library() - + + A synonym for the -StaticLibrary +StaticLibrary builder method. @@ -720,10 +742,11 @@ builder method. env.LoadableModule() - + + On most systems, this is the same as -SharedLibrary. +SharedLibrary. On Mac OS X (Darwin) platforms, this creates a loadable module bundle. @@ -736,9 +759,10 @@ this creates a loadable module bundle. env.M4() - + + Builds an output file from an M4 input file. -This uses a default $M4FLAGS value of +This uses a default $M4FLAGS value of , which considers all warnings to be fatal and stops on the first warning @@ -746,7 +770,7 @@ when using the GNU version of m4. Example: - + env.M4(target = 'foo.c', source = 'foo.c.m4') @@ -758,14 +782,15 @@ env.M4(target = 'foo.c', source = 'foo.c.m4') env.Moc() - + + Builds an output file from a moc input file. Moc input files are either header files or cxx files. This builder is only available after using the -tool 'qt'. See the $QTDIR variable for more information. +tool 'qt'. See the $QTDIR variable for more information. Example: - + env.Moc('foo.h') # generates moc_foo.cc env.Moc('foo.cpp') # generates foo.moc @@ -778,47 +803,48 @@ env.Moc('foo.cpp') # generates foo.moc env.MOFiles() - -This builder belongs to msgfmt tool. The builder compiles + + +This builder belongs to msgfmt tool. The builder compiles PO files to MO files. - + Example 1. Create pl.mo and en.mo by compiling pl.po and en.po: - + # ... env.MOFiles(['pl', 'en']) - + Example 2. Compile files for languages defined in LINGUAS file: - + # ... env.MOFiles(LINGUAS_FILE = 1) - + Example 3. Create pl.mo and en.mo by compiling pl.po and en.po plus files for languages defined in LINGUAS file: - + # ... env.MOFiles(['pl', 'en'], LINGUAS_FILE = 1) - + Example 4. Compile files for languages defined in LINGUAS file (another version): - + # ... env['LINGUAS_FILE'] = 1 env.MOFiles() @@ -832,53 +858,54 @@ Compile files for languages defined in LINGUAS file env.MSVSProject() - + + Builds a Microsoft Visual Studio project file, and by default builds a solution file as well. - + This builds a Visual Studio project file, based on the version of Visual Studio that is configured (either the latest installed version, or the version specified by - $MSVS_VERSION in the Environment constructor). For + $MSVS_VERSION in the Environment constructor). For Visual Studio 6, it will generate a .dsp file. For Visual Studio 7, 8, and 9, it will generate a .vcproj file. For Visual Studio 10 and later, it will generate a .vcxproj file. - + By default, this also generates a solution file for the specified project, a .dsw file for Visual Studio 6 or a .sln file for Visual Studio 7 and later. This behavior may be disabled by specifying auto_build_solution=0 when you - call MSVSProject, in which case you presumably want to - build the solution file(s) by calling the MSVSSolution + call MSVSProject, in which case you presumably want to + build the solution file(s) by calling the MSVSSolution Builder (see below). - - The MSVSProject builder takes several lists of filenames + + The MSVSProject builder takes several lists of filenames to be placed into the project file. These are currently limited to srcs, incs, localincs, resources, and misc. These are pretty self-explanatory, but it should be noted that these lists are added to the - $SOURCES construction variable as strings, NOT as + $SOURCES construction variable as strings, NOT as SCons File Nodes. This is because they represent file names to be added to the project file, not the source files used to build the project file. - + The above filename lists are all optional, although at least one must be specified for the resulting project file to be non-empty. - + In addition to the above lists of values, the following values may be specified: - + target @@ -886,7 +913,7 @@ Compile files for languages defined in LINGUAS file The name of the target .dsp or .vcproj file. The correct suffix for the version of Visual Studio - must be used, but the $MSVSPROJECTSUFFIX + must be used, but the $MSVSPROJECTSUFFIX construction variable will be defined to the correct value (see example below). @@ -904,7 +931,7 @@ Compile files for languages defined in LINGUAS file separated from the variant name by a | (vertical pipe) character: Debug|Xbox. The default target platform is Win32. Multiple calls - to MSVSProject with different variants are allowed; + to MSVSProject with different variants are allowed; all variants will be added to the project file with their appropriate build targets and sources. @@ -980,20 +1007,20 @@ Compile files for languages defined in LINGUAS file - - Note that because SCons always executes its build commands - from the directory in which the SConstruct file is located, + + Note that because SCons always executes its build commands + from the directory in which the SConstruct file is located, if you generate a project file in a different directory - than the SConstruct directory, users will not be able to + than the SConstruct directory, users will not be able to double-click on the file name in compilation error messages displayed in the Visual Studio console output window. This can be remedied by adding the Visual C/C++ /FC - compiler option to the $CCFLAGS variable so that + compiler option to the $CCFLAGS variable so that the compiler will print the full path name of any files that cause compilation errors. - Example usage: - + Example usage: + barsrcs = ['bar.cpp'] barincs = ['bar.h'] barlocalincs = ['StdAfx.h'] @@ -1012,13 +1039,13 @@ env.MSVSProject(target='Bar' + env['MSVSPROJECTSUFFIX'], buildtarget=buildtarget, variant='Release') - + Starting with version 2.4 of SCons it is also possible to specify the optional argument DebugSettings, which creates files for debugging under Visual Studio: - + DebugSettings @@ -1034,7 +1061,7 @@ env.MSVSProject(target='Bar' + env['MSVSPROJECTSUFFIX'], - + Currently, only Visual Studio v9.0 and Visual Studio version v11 are implemented, for other versions no file is generated. To generate the user file, you just need to @@ -1043,11 +1070,11 @@ env.MSVSProject(target='Bar' + env['MSVSPROJECTSUFFIX'], the dictionary is empty, or does not contain any good value, no file will be generated. - + Following is a more contrived example, involving the setup of a project for variants and DebugSettings: - + # Assuming you store your defaults in a file vars = Variables('variables.py') msvcver = vars.args.get('vc', '9') @@ -1171,25 +1198,26 @@ env.MSVSProject(target='Bar' + env['MSVSPROJECTSUFFIX'], env.MSVSSolution() - Builds a Microsoft Visual Studio solution file. - + + Builds a Microsoft Visual Studio solution file. + This builds a Visual Studio solution file, based on the version of Visual Studio that is configured (either the latest installed version, or the version specified by - $MSVS_VERSION in the construction environment). For + $MSVS_VERSION in the construction environment). For Visual Studio 6, it will generate a .dsw file. For Visual Studio 7 (.NET), it will generate a .sln file. - The following values must be specified: - + The following values must be specified: + target The name of the target .dsw or .sln file. The correct suffix for the version of Visual Studio must be used, - but the value $MSVSSOLUTIONSUFFIX will be + but the value $MSVSSOLUTIONSUFFIX will be defined to the correct value (see example below). @@ -1208,7 +1236,7 @@ env.MSVSProject(target='Bar' + env['MSVSPROJECTSUFFIX'], projects A list of project file names, or Project nodes returned - by calls to the MSVSProject Builder, to be placed + by calls to the MSVSProject Builder, to be placed into the solution file. It should be noted that these file names are NOT added to the $SOURCES environment variable in form of files, but rather as strings. @@ -1219,8 +1247,8 @@ env.MSVSProject(target='Bar' + env['MSVSPROJECTSUFFIX'], - Example Usage: - + Example Usage: + env.MSVSSolution(target='Bar' + env['MSVSSOLUTIONSUFFIX'], projects=['bar' + env['MSVSPROJECTSUFFIX']], variant='Release') @@ -1232,9 +1260,10 @@ env.MSVSSolution(target='Bar' + env['MSVSSOLUTIONSUFFIX'], projects=['bar' + env env.Object() - + + A synonym for the -StaticObject +StaticObject builder method. @@ -1246,39 +1275,41 @@ builder method. env.Package() - + + Builds a Binary Package of the given source files. - + env.Package(source = FindInstalledFiles()) - + + Builds software distribution packages. Packages consist of files to install and packaging information. -The former may be specified with the source parameter and may be left out, -in which case the FindInstalledFiles function will collect -all files that have an Install or InstallAs Builder attached. -If the target is not specified +The former may be specified with the source parameter and may be left out, +in which case the FindInstalledFiles function will collect +all files that have an Install or InstallAs Builder attached. +If the target is not specified it will be deduced from additional information given to this Builder. - + The packaging information is specified with the help of construction variables documented below. This information is called a tag to stress that -some of them can also be attached to files with the Tag function. +some of them can also be attached to files with the Tag function. The mandatory ones will complain if they were not specified. They vary depending on chosen target packager. - + The target packager may be selected with the "PACKAGETYPE" command line -option or with the $PACKAGETYPE construction variable. Currently +option or with the $PACKAGETYPE construction variable. Currently the following packagers available: - + * msi - Microsoft Installer * rpm - RPM Package Manger * ipkg - Itsy Package Management System @@ -1292,11 +1323,11 @@ the following packagers available: * 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. - + env = Environment(tools=['default', 'packaging']) env.Install('/bin/', 'my_program') env.Package( NAME = 'foo', @@ -1319,7 +1350,8 @@ env.Package( NAME = 'foo', env.PCH() - + + Builds a Microsoft Visual C++ precompiled header. Calling this builder method returns a list of two targets: the PCH as the first element, and the object @@ -1331,7 +1363,7 @@ conjunction with the PCH construction variable to force object files to use the precompiled header: - + env['PCH'] = env.PCH('StdAfx.cpp')[0] @@ -1343,20 +1375,21 @@ env['PCH'] = env.PCH('StdAfx.cpp')[0] env.PDF() - + + Builds a .pdf file from a .dvi input file (or, by extension, a .tex, .ltx, or .latex input file). -The suffix specified by the $PDFSUFFIX construction variable +The suffix specified by the $PDFSUFFIX construction variable (.pdf by default) is added automatically to the target if it is not already present. Example: - + # builds from aaa.tex env.PDF(target = 'aaa.pdf', source = 'aaa.tex') # builds bbb.pdf from bbb.dvi @@ -1371,99 +1404,100 @@ env.PDF(target = 'bbb', source = 'bbb.dvi') env.POInit() - -This builder belongs to msginit tool. The builder initializes missing -PO file(s) if $POAUTOINIT is set. If -$POAUTOINIT is not set (default), POInit prints instruction for + + +This builder belongs to msginit tool. The builder initializes missing +PO file(s) if $POAUTOINIT is set. If +$POAUTOINIT is not set (default), POInit prints instruction for user (that is supposed to be a translator), telling how the PO file should be initialized. In normal projects -you should not use POInit and use POUpdate -instead. POUpdate chooses intelligently between -msgmerge(1) and msginit(1). POInit +you should not use POInit and use POUpdate +instead. POUpdate chooses intelligently between +msgmerge(1) and msginit(1). POInit always uses msginit(1) and should be regarded as builder for special purposes or for temporary use (e.g. for quick, one time initialization of a bunch of PO files) or for tests. - -Target nodes defined through POInit are not built by default (they're + +Target nodes defined through POInit are not built by default (they're Ignored from '.' node) but are added to special Alias ('po-create' by default). -The alias name may be changed through the $POCREATE_ALIAS +The alias name may be changed through the $POCREATE_ALIAS construction variable. All PO files defined through -POInit may be easily initialized by scons po-create. +POInit may be easily initialized by scons po-create. - + Example 1. Initialize en.po and pl.po from messages.pot: - + # ... env.POInit(['en', 'pl']) # messages.pot --> [en.po, pl.po] - + Example 2. Initialize en.po and pl.po from foo.pot: - + # ... env.POInit(['en', 'pl'], ['foo']) # foo.pot --> [en.po, pl.po] - + Example 3. Initialize en.po and pl.po from -foo.pot but using $POTDOMAIN construction +foo.pot but using $POTDOMAIN construction variable: - + # ... env.POInit(['en', 'pl'], POTDOMAIN='foo') # foo.pot --> [en.po, pl.po] - + Example 4. Initialize PO files for languages defined in LINGUAS file. The files will be initialized from template messages.pot: - + # ... env.POInit(LINGUAS_FILE = 1) # needs 'LINGUAS' file - + Example 5. Initialize en.po and pl.pl PO files plus files for languages defined in LINGUAS file. The files will be initialized from template messages.pot: - + # ... env.POInit(['en', 'pl'], LINGUAS_FILE = 1) - + Example 6. You may preconfigure your environment first, and then initialize PO files: - + # ... env['POAUTOINIT'] = 1 env['LINGUAS_FILE'] = 1 env['POTDOMAIN'] = 'foo' env.POInit() - + which has same efect as: - + # ... env.POInit(POAUTOINIT = 1, LINGUAS_FILE = 1, POTDOMAIN = 'foo') @@ -1476,20 +1510,21 @@ which has same efect as: env.PostScript() - + + Builds a .ps file from a .dvi input file (or, by extension, a .tex, .ltx, or .latex input file). -The suffix specified by the $PSSUFFIX construction variable +The suffix specified by the $PSSUFFIX construction variable (.ps by default) is added automatically to the target if it is not already present. Example: - + # builds from aaa.tex env.PostScript(target = 'aaa.ps', source = 'aaa.tex') # builds bbb.ps from bbb.dvi @@ -1504,23 +1539,24 @@ env.PostScript(target = 'bbb', source = 'bbb.dvi') env.POTUpdate() - -The builder belongs to xgettext tool. The builder updates target + + +The builder belongs to xgettext tool. The builder updates target POT file if exists or creates one if it doesn't. The node is not built by default (i.e. it is Ignored from '.'), but only on demand (i.e. when given POT file is required or when special alias is invoked). This builder adds its targe node (messages.pot, say) to a special alias (pot-update by default, see -$POTUPDATE_ALIAS) so you can update/create them easily with +$POTUPDATE_ALIAS) so you can update/create them easily with scons pot-update. The file is not written until there is no real change in internationalized messages (or in comments that enter POT file). - + You may see xgettext(1) being invoked by the -xgettext tool even if there is no real change in internationalized +xgettext tool even if there is no real change in internationalized messages (so the POT file is not being updated). This happens every time a source file has changed. In such case we invoke xgettext(1) and compare its output with the content of @@ -1528,38 +1564,38 @@ happens every time a source file has changed. In such case we invoke not. - + Example 1. Let's create po/ directory and place following SConstruct script there: - + # SConstruct in 'po/' subdir env = Environment( tools = ['default', 'xgettext'] ) env.POTUpdate(['foo'], ['../a.cpp', '../b.cpp']) env.POTUpdate(['bar'], ['../c.cpp', '../d.cpp']) - + Then invoke scons few times: - + user@host:$ scons # Does not create foo.pot nor bar.pot user@host:$ scons foo.pot # Updates or creates foo.pot user@host:$ scons pot-update # Updates or creates foo.pot and bar.pot user@host:$ scons -c # Does not clean foo.pot nor bar.pot. - + the results shall be as the comments above say. - + Example 2. -The POTUpdate builder may be used with no target specified, in which +The POTUpdate builder may be used with no target specified, in which case default target messages.pot will be used. The -default target may also be overridden by setting $POTDOMAIN construction -variable or providing it as an override to POTUpdate builder: +default target may also be overridden by setting $POTDOMAIN construction +variable or providing it as an override to POTUpdate builder: - + # SConstruct script env = Environment( tools = ['default', 'xgettext'] ) env['POTDOMAIN'] = "foo" @@ -1567,49 +1603,49 @@ variable or providing it as an override to POTUpdate builde env.POTUpdate(POTDOMAIN = "bar", source = ["c.cpp", "d.cpp"]) # and bar.pot - + Example 3. The sources may be specified within separate file, for example POTFILES.in: - + # POTFILES.in in 'po/' subdirectory ../a.cpp ../b.cpp # end of file - + The name of the file (POTFILES.in) containing the list of -sources is provided via $XGETTEXTFROM: +sources is provided via $XGETTEXTFROM: - + # SConstruct file in 'po/' subdirectory env = Environment( tools = ['default', 'xgettext'] ) env.POTUpdate(XGETTEXTFROM = 'POTFILES.in') - + Example 4. -You may use $XGETTEXTPATH to define source search path. Assume, for +You may use $XGETTEXTPATH to define source search path. Assume, for example, that you have files a.cpp, b.cpp, po/SConstruct, po/POTFILES.in. Then your POT-related files could look as below: - + # POTFILES.in in 'po/' subdirectory a.cpp b.cpp # end of file - + # SConstruct file in 'po/' subdirectory env = Environment( tools = ['default', 'xgettext'] ) env.POTUpdate(XGETTEXTFROM = 'POTFILES.in', XGETTEXTPATH='../') - + Example 5. Multiple search directories may be defined within a list, i.e. XGETTEXTPATH = ['dir1', 'dir2', ...]. The order in the list @@ -1617,48 +1653,48 @@ determines the search order of source files. The path to the first file found is used. - + Let's create 0/1/po/SConstruct script: - + # SConstruct file in '0/1/po/' subdirectory env = Environment( tools = ['default', 'xgettext'] ) env.POTUpdate(XGETTEXTFROM = 'POTFILES.in', XGETTEXTPATH=['../', '../../']) - + and 0/1/po/POTFILES.in: - + # POTFILES.in in '0/1/po/' subdirectory a.cpp # end of file - + Write two *.cpp files, the first one is 0/a.cpp: - + /* 0/a.cpp */ gettext("Hello from ../../a.cpp") - + and the second is 0/1/a.cpp: - + /* 0/1/a.cpp */ gettext("Hello from ../a.cpp") - + then run scons. You'll obtain 0/1/po/messages.pot with the message "Hello from ../a.cpp". When you reverse order in $XGETTEXTFOM, i.e. when you write SConscript as - + # SConstruct file in '0/1/po/' subdirectory env = Environment( tools = ['default', 'xgettext'] ) env.POTUpdate(XGETTEXTFROM = 'POTFILES.in', XGETTEXTPATH=['../../', '../']) - + then the messages.pot will contain msgid "Hello from ../../a.cpp" line and not msgid "Hello from ../a.cpp". @@ -1673,106 +1709,107 @@ then the messages.pot will contain env.POUpdate() - -The builder belongs to msgmerge tool. The builder updates + + +The builder belongs to msgmerge tool. The builder updates PO files with msgmerge(1), or initializes missing PO files as described in documentation of -msginit tool and POInit builder (see also -$POAUTOINIT). Note, that POUpdate does not add its -targets to po-create alias as POInit +msginit tool and POInit builder (see also +$POAUTOINIT). Note, that POUpdate does not add its +targets to po-create alias as POInit does. - -Target nodes defined through POUpdate are not built by default + +Target nodes defined through POUpdate are not built by default (they're Ignored from '.' node). Instead, they are added automatically to special Alias ('po-update' by default). The alias name may be changed -through the $POUPDATE_ALIAS construction variable. You can easily +through the $POUPDATE_ALIAS construction variable. You can easily update PO files in your project by scons po-update. - + Example 1. Update en.po and pl.po from -messages.pot template (see also $POTDOMAIN), +messages.pot template (see also $POTDOMAIN), assuming that the later one exists or there is rule to build it (see -POTUpdate): +POTUpdate): - + # ... env.POUpdate(['en','pl']) # messages.pot --> [en.po, pl.po] - + Example 2. Update en.po and pl.po from foo.pot template: - + # ... env.POUpdate(['en', 'pl'], ['foo']) # foo.pot --> [en.po, pl.pl] - + Example 3. Update en.po and pl.po from foo.pot (another version): - + # ... env.POUpdate(['en', 'pl'], POTDOMAIN='foo') # foo.pot -- > [en.po, pl.pl] - + Example 4. Update files for languages defined in LINGUAS file. The files are updated from messages.pot template: - + # ... env.POUpdate(LINGUAS_FILE = 1) # needs 'LINGUAS' file - + Example 5. Same as above, but update from foo.pot template: - + # ... env.POUpdate(LINGUAS_FILE = 1, source = ['foo']) - + Example 6. Update en.po and pl.po plus files for languages defined in LINGUAS file. The files are updated from messages.pot template: - + # produce 'en.po', 'pl.po' + files defined in 'LINGUAS': env.POUpdate(['en', 'pl' ], LINGUAS_FILE = 1) - + Example 7. -Use $POAUTOINIT to automatically initialize PO file +Use $POAUTOINIT to automatically initialize PO file if it doesn't exist: - + # ... env.POUpdate(LINGUAS_FILE = 1, POAUTOINIT = 1) - + Example 8. Update PO files for languages defined in LINGUAS file. The files are updated from foo.pot template. All necessary settings are pre-configured via environment. - + # ... env['POAUTOINIT'] = 1 env['LINGUAS_FILE'] = 1 @@ -1789,28 +1826,29 @@ pre-configured via environment. env.Program() - + + Builds an executable given one or more object files or C, C++, D, or Fortran source files. If any C, C++, D or Fortran source files are specified, then they will be automatically compiled to object files using the -Object +Object builder method; see that builder method's description for a list of legal source file suffixes and how they are interpreted. The target executable file prefix -(specified by the $PROGPREFIX construction variable; nothing by default) +(specified by the $PROGPREFIX construction variable; nothing by default) and suffix -(specified by the $PROGSUFFIX construction variable; +(specified by the $PROGSUFFIX construction variable; by default, .exe on Windows systems, nothing on POSIX systems) are automatically added to the target if not already present. Example: - + env.Program(target = 'foo', source = ['foo.o', 'bar.c', 'baz.f']) @@ -1822,22 +1860,23 @@ env.Program(target = 'foo', source = ['foo.o', 'bar.c', 'baz.f']) env.ProgramAllAtOnce() - + + Builds an executable from D sources without first creating individual objects for each file. - + D sources can be compiled file-by-file as C and C++ source are, and - D is integrated into the scons Object and Program builders for + D is integrated into the scons Object and Program builders for this model of build. D codes can though do whole source meta-programming (some of the testing frameworks do this). For this it is imperative that all sources are compiled and linked in a single call to the D compiler. This builder serves that purpose. - + env.ProgramAllAtOnce('executable', ['mod_a.d, mod_b.d', 'mod_c.d']) - + This command will compile the modules mod_a, mod_b, and mod_c in a single compilation process without first creating object files for the modules. Some of the D compilers will create executable.o others @@ -1852,7 +1891,8 @@ env.Program(target = 'foo', source = ['foo.o', 'bar.c', 'baz.f']) env.RES() - + + Builds a Microsoft Visual C++ resource file. This builder method is only provided when Microsoft Visual C++ or MinGW is being used as the compiler. The @@ -1865,7 +1905,7 @@ file is scanned for implicit dependencies as though it were a C file. Example: - + env.RES('resource.rc') @@ -1877,7 +1917,8 @@ env.RES('resource.rc') env.RMIC() - + + Builds stub and skeleton class files for remote objects from Java .class files. @@ -1886,16 +1927,16 @@ relative to which the stub and skeleton class files will be written. The source can be the names of .class files, or the objects return from the -Java +Java builder method. - + If the construction variable -$JAVACLASSDIR +$JAVACLASSDIR is set, either in the environment or in the call to the -RMIC +RMIC builder method itself, then the value of the variable will be stripped from the @@ -1903,7 +1944,7 @@ beginning of any .class file names. - + classes = env.Java(target = 'classdir', source = 'src') env.RMIC(target = 'outdir1', source = classes) @@ -1923,7 +1964,8 @@ env.RMIC(target = 'outdir3', env.RPCGenClient() - + + Generates an RPC client stub (_clnt.c) file from a specified RPC (.x) source file. Because rpcgen only builds output files @@ -1932,7 +1974,7 @@ the command will be executed in the source file's directory by default. - + # Builds src/rpcif_clnt.c env.RPCGenClient('src/rpcif.x') @@ -1945,7 +1987,8 @@ env.RPCGenClient('src/rpcif.x') env.RPCGenHeader() - + + Generates an RPC header (.h) file from a specified RPC (.x) source file. Because rpcgen only builds output files @@ -1954,7 +1997,7 @@ the command will be executed in the source file's directory by default. - + # Builds src/rpcif.h env.RPCGenHeader('src/rpcif.x') @@ -1967,7 +2010,8 @@ env.RPCGenHeader('src/rpcif.x') env.RPCGenService() - + + Generates an RPC server-skeleton (_svc.c) file from a specified RPC (.x) source file. Because rpcgen only builds output files @@ -1976,7 +2020,7 @@ the command will be executed in the source file's directory by default. - + # Builds src/rpcif_svc.c env.RPCGenClient('src/rpcif.x') @@ -1989,7 +2033,8 @@ env.RPCGenClient('src/rpcif.x') env.RPCGenXDR() - + + Generates an RPC XDR routine (_xdr.c) file from a specified RPC (.x) source file. Because rpcgen only builds output files @@ -1998,7 +2043,7 @@ the command will be executed in the source file's directory by default. - + # Builds src/rpcif_xdr.c env.RPCGenClient('src/rpcif.x') @@ -2011,7 +2056,8 @@ env.RPCGenClient('src/rpcif.x') env.SharedLibrary() - + + Builds a shared library (.so on a POSIX system, .dll on Windows) @@ -2023,24 +2069,24 @@ compiled to object files. The static library prefix and suffix (if any) are automatically added to the target. The target library file prefix -(specified by the $SHLIBPREFIX construction variable; +(specified by the $SHLIBPREFIX construction variable; by default, lib on POSIX systems, nothing on Windows systems) and suffix -(specified by the $SHLIBSUFFIX construction variable; +(specified by the $SHLIBSUFFIX construction variable; by default, .dll on Windows systems, .so on POSIX systems) are automatically added to the target if not already present. Example: - + env.SharedLibrary(target = 'bar', source = ['bar.c', 'foo.o']) - + On Windows systems, the -SharedLibrary +SharedLibrary builder method will always build an import (.lib) library in addition to the shared (.dll) library, @@ -2049,9 +2095,9 @@ if there is not already a .lib file explicitly listed in the targets. - + On Cygwin systems, the -SharedLibrary +SharedLibrary builder method will always build an import (.dll.a) library in addition to the shared (.dll) library, @@ -2060,36 +2106,36 @@ if there is not already a .dll.a file explicitly listed in the targets. - + Any object files listed in the source must have been built for a shared library (that is, using the -SharedObject +SharedObject builder method). -scons +scons will raise an error if there is any mismatch. - + On some platforms, there is a distinction between a shared library (loaded automatically by the system to resolve external references) and a loadable module (explicitly loaded by user action). -For maximum portability, use the LoadableModule builder for the latter. +For maximum portability, use the LoadableModule builder for the latter. - -When the $SHLIBVERSION construction variable is defined a versioned -shared library is created. This modifies the $SHLINKFLAGS as required, + +When the $SHLIBVERSION construction variable is defined a versioned +shared library is created. This modifies the $SHLINKFLAGS as required, adds the version number to the library name, and creates the symlinks that are needed. - + env.SharedLibrary(target = 'bar', source = ['bar.c', 'foo.o'], SHLIBVERSION='1.5.2') - + On a POSIX system, versions with a single token create exactly one symlink: libbar.so.6 would have symlinks libbar.so only. On a POSIX system, versions with two or more @@ -2098,28 +2144,28 @@ libbar.so and libbar.so.2; on a Darwin (OSX) system the library would be libbar.2.3.1.dylib and the link would be libbar.dylib. - + On Windows systems, specifying register=1 will cause the .dll to be registered after it is built using REGSVR32. The command that is run -("regsvr32" by default) is determined by $REGSVR construction -variable, and the flags passed are determined by $REGSVRFLAGS. By -default, $REGSVRFLAGS includes the option, +("regsvr32" by default) is determined by $REGSVR construction +variable, and the flags passed are determined by $REGSVRFLAGS. By +default, $REGSVRFLAGS includes the option, to prevent dialogs from popping up and requiring user attention when it is run. If you change -$REGSVRFLAGS, be sure to include the option. +$REGSVRFLAGS, be sure to include the option. For example, - + env.SharedLibrary(target = 'bar', source = ['bar.cxx', 'foo.obj'], register=1) - + will register bar.dll as a COM object when it is done linking it. @@ -2132,12 +2178,13 @@ when it is done linking it. env.SharedObject() - + + Builds an object file for inclusion in a shared library. Source files must have one of the same set of extensions specified above for the -StaticObject +StaticObject builder method. On some platforms building a shared object requires additional compiler option @@ -2152,21 +2199,21 @@ and shared objects to be linked into a shared library, and will use the same suffix for shared and normal (static) objects. The target object file prefix -(specified by the $SHOBJPREFIX construction variable; -by default, the same as $OBJPREFIX) +(specified by the $SHOBJPREFIX construction variable; +by default, the same as $OBJPREFIX) and suffix -(specified by the $SHOBJSUFFIX construction variable) +(specified by the $SHOBJSUFFIX construction variable) are automatically added to the target if not already present. Examples: - + env.SharedObject(target = 'ddd', source = 'ddd.c') env.SharedObject(target = 'eee.o', source = 'eee.cpp') env.SharedObject(target = 'fff.obj', source = 'fff.for') - + Note that the source files will be scanned according to the suffix mappings in the SourceFileScanner @@ -2183,7 +2230,8 @@ below, for more information. env.StaticLibrary() - + + Builds a static library given one or more object files or C, C++, D or Fortran source files. If any source files are given, @@ -2192,29 +2240,29 @@ compiled to object files. The static library prefix and suffix (if any) are automatically added to the target. The target library file prefix -(specified by the $LIBPREFIX construction variable; +(specified by the $LIBPREFIX construction variable; by default, lib on POSIX systems, nothing on Windows systems) and suffix -(specified by the $LIBSUFFIX construction variable; +(specified by the $LIBSUFFIX construction variable; by default, .lib on Windows systems, .a on POSIX systems) are automatically added to the target if not already present. Example: - + env.StaticLibrary(target = 'bar', source = ['bar.c', 'foo.o']) - + Any object files listed in the source must have been built for a static library (that is, using the -StaticObject +StaticObject builder method). -scons +scons will raise an error if there is any mismatch. @@ -2226,13 +2274,14 @@ will raise an error if there is any mismatch. env.StaticObject() - + + Builds a static object file from one or more C, C++, D, or Fortran source files. Source files must have one of the following extensions: - + .asm assembly language file .ASM assembly language file .c C file @@ -2263,24 +2312,24 @@ Source files must have one of the following extensions: .SPP assembly language file + C pre-processor - + The target object file prefix -(specified by the $OBJPREFIX construction variable; nothing by default) +(specified by the $OBJPREFIX construction variable; nothing by default) and suffix -(specified by the $OBJSUFFIX construction variable; +(specified by the $OBJSUFFIX construction variable; .obj on Windows systems, .o on POSIX systems) are automatically added to the target if not already present. Examples: - + env.StaticObject(target = 'aaa', source = 'aaa.c') env.StaticObject(target = 'bbb.o', source = 'bbb.c++') env.StaticObject(target = 'ccc.obj', source = 'ccc.f') - + Note that the source files will be scanned according to the suffix mappings in SourceFileScanner @@ -2297,27 +2346,28 @@ below, for more information. env.Substfile() - -The Substfile builder creates a single text file from another file or set of -files by concatenating them with $LINESEPARATOR and replacing text -using the $SUBST_DICT construction variable. Nested lists of source files -are flattened. See also Textfile. + + +The Substfile builder creates a single text file from another file or set of +files by concatenating them with $LINESEPARATOR and replacing text +using the $SUBST_DICT construction variable. Nested lists of source files +are flattened. See also Textfile. - + If a single source file is present with an .in suffix, the suffix is stripped and the remainder is used as the default target name. - -The prefix and suffix specified by the $SUBSTFILEPREFIX -and $SUBSTFILESUFFIX construction variables + +The prefix and suffix specified by the $SUBSTFILEPREFIX +and $SUBSTFILESUFFIX construction variables (the null string by default in both cases) are automatically added to the target if they are not already present. - -If a construction variable named $SUBST_DICT is present, + +If a construction variable named $SUBST_DICT is present, it may be either a Python dictionary or a sequence of (key,value) tuples. If it is a dictionary it is converted into a list of tuples in an arbitrary order, so if one key is a prefix of another key @@ -2325,7 +2375,7 @@ or if one substitution could be further expanded by another subsitition, it is unpredictable whether the expansion will occur. - + Any occurrences of a key in the source are replaced by the corresponding value, which may be a Python callable function or a string. @@ -2334,7 +2384,7 @@ Strings are subst-expanded and the result replaces the key. - + env = Environment(tools=['default']) env['prefix'] = '/usr/bin' @@ -2386,12 +2436,13 @@ subst.Substfile('pgm2.c', [Value('#include "@foo@.h"'), env.Tar() - + + Builds a tar archive of the specified files and/or directories. Unlike most builder methods, the -Tar +Tar builder method may be called multiple times for a given target; each additional call @@ -2401,11 +2452,11 @@ Any source directories will be scanned for changes to any on-disk files, regardless of whether or not -scons +scons knows about them from other Builder or function calls. - + env.Tar('src.tar', 'src') # Create the stuff.tar file. @@ -2431,28 +2482,29 @@ env.Tar('foo') env.Textfile() - -The Textfile builder generates a single text file. + + +The Textfile builder generates a single text file. The source strings constitute the lines; nested lists of sources are flattened. -$LINESEPARATOR is used to separate the strings. +$LINESEPARATOR is used to separate the strings. - -If present, the $SUBST_DICT construction variable + +If present, the $SUBST_DICT construction variable is used to modify the strings before they are written; -see the Substfile description for details. +see the Substfile description for details. - -The prefix and suffix specified by the $TEXTFILEPREFIX -and $TEXTFILESUFFIX construction variables + +The prefix and suffix specified by the $TEXTFILEPREFIX +and $TEXTFILESUFFIX construction variables (the null string and .txt by default, respectively) are automatically added to the target if they are not already present. Examples: - + # builds/writes foo.txt env.Textfile(target = 'foo.txt', source = ['Goethe', 42, 'Schiller']) @@ -2501,49 +2553,50 @@ blob.txt env.Translate() - -This pseudo-builder belongs to gettext toolset. The builder extracts + + +This pseudo-builder belongs to gettext toolset. The builder extracts internationalized messages from source files, updates POT template (if necessary) and then updates PO translations (if -necessary). If $POAUTOINIT is set, missing PO files +necessary). If $POAUTOINIT is set, missing PO files will be automatically created (i.e. without translator person intervention). -The variables $LINGUAS_FILE and $POTDOMAIN are taken into -acount too. All other construction variables used by POTUpdate, and -POUpdate work here too. +The variables $LINGUAS_FILE and $POTDOMAIN are taken into +acount too. All other construction variables used by POTUpdate, and +POUpdate work here too. - + Example 1. The simplest way is to specify input files and output languages inline in -a SCons script when invoking Translate +a SCons script when invoking Translate - + # SConscript in 'po/' directory env = Environment( tools = ["default", "gettext"] ) env['POAUTOINIT'] = 1 env.Translate(['en','pl'], ['../a.cpp','../b.cpp']) - + Example 2. If you wish, you may also stick to conventional style known from autotools, i.e. using POTFILES.in and LINGUAS files - + # LINGUAS en pl #end - + # POTFILES.in a.cpp b.cpp # end - + # SConscript env = Environment( tools = ["default", "gettext"] ) env['POAUTOINIT'] = 1 @@ -2551,7 +2604,7 @@ env['XGETTEXTPATH'] = ['../'] env.Translate(LINGUAS_FILE = 1, XGETTEXTFROM = 'POTFILES.in') - + The last approach is perhaps the recommended one. It allows easily split internationalization/localization onto separate SCons scripts, where a script in source tree is responsible for translations (from sources to @@ -2568,11 +2621,11 @@ so the source tree looks familiar to translators, and they may work with the project in their usual way. - + Example 3. Let's prepare a development tree as below - + project/ + SConstruct + build/ @@ -2583,11 +2636,11 @@ Let's prepare a development tree as below + POTFILES.in + LINGUAS - + with build being variant directory. Write the top-level SConstruct script as follows - + # SConstruct env = Environment( tools = ["default", "gettext"] ) VariantDir('build', 'src', duplicate = 0) @@ -2595,23 +2648,23 @@ with build being variant directory. Write the top-level SConscript('src/po/SConscript.i18n', exports = 'env') SConscript('build/po/SConscript', exports = 'env') - + the src/po/SConscript.i18n as - + # src/po/SConscript.i18n Import('env') env.Translate(LINGUAS_FILE=1, XGETTEXTFROM='POTFILES.in', XGETTEXTPATH=['../']) - + and the src/po/SConscript - + # src/po/SConscript Import('env') env.MOFiles(LINGUAS_FILE = 1) - + Such setup produces POT and PO files under source tree in src/po/ and binary MO files under variant tree in @@ -2621,7 +2674,7 @@ not be committed back to source repositories (e.g. MO files). - + In above example, the PO files are not updated, nor created automatically when you issue scons '.' command. The files must be updated (created) by hand via scons @@ -2638,7 +2691,8 @@ running scons '.'. env.TypeLibrary() - + + Builds a Windows type library (.tlb) file from an input IDL file (.idl). In addition, it will build the associated interface stub and @@ -2647,11 +2701,11 @@ naming them according to the base name of the .idl file. For example, - + env.TypeLibrary(source="foo.idl") - + Will create foo.tlb, foo.h, foo_i.c, @@ -2669,21 +2723,22 @@ files. env.Uic() - + + Builds a header file, an implementation file and a moc file from an ui file. and returns the corresponding nodes in the above order. This builder is only available after using the tool 'qt'. Note: you can specify .ui files directly as source -files to the Program, -Library and SharedLibrary builders +files to the Program, +Library and SharedLibrary builders without using this builder. Using this builder lets you override the standard naming conventions (be careful: prefixes are always prepended to names of built files; if you don't want prefixes, you may set them to ``). -See the $QTDIR variable for more information. +See the $QTDIR variable for more information. Example: - + env.Uic('foo.ui') # -> ['foo.h', 'uic_foo.cc', 'moc_foo.cc'] env.Uic(target = Split('include/foo.h gen/uicfoo.cc gen/mocfoo.cc'), source = 'foo.ui') # -> ['include/foo.h', 'gen/uicfoo.cc', 'gen/mocfoo.cc'] @@ -2697,12 +2752,13 @@ env.Uic(target = Split('include/foo.h gen/uicfoo.cc gen/mocfoo.cc'), env.Zip() - + + Builds a zip archive of the specified files and/or directories. Unlike most builder methods, the -Zip +Zip builder method may be called multiple times for a given target; each additional call @@ -2712,11 +2768,11 @@ Any source directories will be scanned for changes to any on-disk files, regardless of whether or not -scons +scons knows about them from other Builder or function calls. - + env.Zip('src.zip', 'src') # Create the stuff.zip file. diff --git a/doc/generated/examples/EnumVariable_map_1.xml b/doc/generated/examples/EnumVariable_map_1.xml index 856731e..4380be0 100644 --- a/doc/generated/examples/EnumVariable_map_1.xml +++ b/doc/generated/examples/EnumVariable_map_1.xml @@ -1,3 +1,4 @@ -% scons -Q COLOR=navy foo.o + +% scons -Q COLOR=navy foo.o cc -o foo.o -c -DCOLOR="blue" foo.c diff --git a/doc/generated/examples/addmethod_ex1_1.xml b/doc/generated/examples/addmethod_ex1_1.xml index 5cacf9d..84dfd20 100644 --- a/doc/generated/examples/addmethod_ex1_1.xml +++ b/doc/generated/examples/addmethod_ex1_1.xml @@ -1,4 +1,5 @@ -% scons -Q / + +% scons -Q / cc -o hello.o -c hello.c cc -o hello hello.o Install file: "hello" as "/usr/bin/hello" diff --git a/doc/generated/examples/addmethod_ex2_1.xml b/doc/generated/examples/addmethod_ex2_1.xml index 4d0cb44..3930341 100644 --- a/doc/generated/examples/addmethod_ex2_1.xml +++ b/doc/generated/examples/addmethod_ex2_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o test_stuff.o -c test_stuff.c cc -o tests/test_stuff test_stuff.o diff --git a/doc/generated/examples/addmethod_ex2_2.xml b/doc/generated/examples/addmethod_ex2_2.xml index 7ad282f..734da63 100644 --- a/doc/generated/examples/addmethod_ex2_2.xml +++ b/doc/generated/examples/addmethod_ex2_2.xml @@ -1,4 +1,5 @@ -C:\>scons -Q + +C:\>scons -Q rc /nologo /fores.res res.rc cl /Fotest_stuff.obj /c test_stuff.c /nologo link /nologo /OUT:tests\test_stuff.exe test_stuff.obj res.res diff --git a/doc/generated/examples/alias_ex1_1.xml b/doc/generated/examples/alias_ex1_1.xml index d0db114..3ee3f1b 100644 --- a/doc/generated/examples/alias_ex1_1.xml +++ b/doc/generated/examples/alias_ex1_1.xml @@ -1,4 +1,5 @@ -% scons -Q install + +% scons -Q install cc -o hello.o -c hello.c cc -o hello hello.o Install file: "hello" as "/usr/bin/hello" diff --git a/doc/generated/examples/alias_ex2_1.xml b/doc/generated/examples/alias_ex2_1.xml index 56cc365..3fa7dfd 100644 --- a/doc/generated/examples/alias_ex2_1.xml +++ b/doc/generated/examples/alias_ex2_1.xml @@ -1,4 +1,5 @@ -% scons -Q install-bin + +% scons -Q install-bin cc -o foo.o -c foo.c cc -o foo foo.o Install file: "foo" as "/usr/bin/foo" diff --git a/doc/generated/examples/buildersbuiltin_ex1_1.xml b/doc/generated/examples/buildersbuiltin_ex1_1.xml index 75b365d..74cc779 100644 --- a/doc/generated/examples/buildersbuiltin_ex1_1.xml +++ b/doc/generated/examples/buildersbuiltin_ex1_1.xml @@ -1,4 +1,5 @@ -% scons -Q . + +% scons -Q . tar -c -f out1.tar file1 file2 tar -c -f out2.tar directory diff --git a/doc/generated/examples/buildersbuiltin_ex2_1.xml b/doc/generated/examples/buildersbuiltin_ex2_1.xml index 88abed4..6c66d7b 100644 --- a/doc/generated/examples/buildersbuiltin_ex2_1.xml +++ b/doc/generated/examples/buildersbuiltin_ex2_1.xml @@ -1,3 +1,4 @@ -% scons -Q . + +% scons -Q . tar -c -z -f out.tar.gz directory diff --git a/doc/generated/examples/buildersbuiltin_ex3_1.xml b/doc/generated/examples/buildersbuiltin_ex3_1.xml index 5cb16d1..4d281e5 100644 --- a/doc/generated/examples/buildersbuiltin_ex3_1.xml +++ b/doc/generated/examples/buildersbuiltin_ex3_1.xml @@ -1,3 +1,4 @@ -% scons -Q . + +% scons -Q . tar -c -z -f out.tgz directory diff --git a/doc/generated/examples/buildersbuiltin_ex4_1.xml b/doc/generated/examples/buildersbuiltin_ex4_1.xml index e907422..856f024 100644 --- a/doc/generated/examples/buildersbuiltin_ex4_1.xml +++ b/doc/generated/examples/buildersbuiltin_ex4_1.xml @@ -1,3 +1,4 @@ -% scons -Q . + +% scons -Q . zip(["out.zip"], ["file1", "file2"]) diff --git a/doc/generated/examples/buildersbuiltin_libs_1.xml b/doc/generated/examples/buildersbuiltin_libs_1.xml index 5b7abd9..8e1ee49 100644 --- a/doc/generated/examples/buildersbuiltin_libs_1.xml +++ b/doc/generated/examples/buildersbuiltin_libs_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o goodbye.o -c goodbye.c cc -o hello.o -c hello.c cc -o hello hello.o goodbye.o -L/usr/dir1 -Ldir2 -lfoo1 -lfoo2 diff --git a/doc/generated/examples/buildersbuiltin_libs_2.xml b/doc/generated/examples/buildersbuiltin_libs_2.xml index 31f3a46..41a9c1e 100644 --- a/doc/generated/examples/buildersbuiltin_libs_2.xml +++ b/doc/generated/examples/buildersbuiltin_libs_2.xml @@ -1,4 +1,5 @@ -C:\>scons -Q + +C:\>scons -Q cl /Fogoodbye.obj /c goodbye.c /nologo cl /Fohello.obj /c hello.c /nologo link /nologo /OUT:hello.exe /LIBPATH:\usr\dir1 /LIBPATH:dir2 foo1.lib foo2.lib hello.obj goodbye.obj diff --git a/doc/generated/examples/builderscommands_ex1_1.xml b/doc/generated/examples/builderscommands_ex1_1.xml index 470b5a4..8782773 100644 --- a/doc/generated/examples/builderscommands_ex1_1.xml +++ b/doc/generated/examples/builderscommands_ex1_1.xml @@ -1,3 +1,4 @@ -% scons -Q + +% scons -Q sed 's/x/y/' < foo.in > foo.out diff --git a/doc/generated/examples/builderscommands_ex2_1.xml b/doc/generated/examples/builderscommands_ex2_1.xml index 1593352..3fc1dde 100644 --- a/doc/generated/examples/builderscommands_ex2_1.xml +++ b/doc/generated/examples/builderscommands_ex2_1.xml @@ -1,3 +1,4 @@ -% scons -Q + +% scons -Q build(["foo.out"], ["foo.in"]) diff --git a/doc/generated/examples/builderswriting_MY_EMITTER_1.xml b/doc/generated/examples/builderswriting_MY_EMITTER_1.xml index ef831e5..0c17d0e 100644 --- a/doc/generated/examples/builderswriting_MY_EMITTER_1.xml +++ b/doc/generated/examples/builderswriting_MY_EMITTER_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q ./my_command file1.input modify1.in > file1.foo ./my_command file2.input modify2.in > file2.foo diff --git a/doc/generated/examples/builderswriting_ex1_1.xml b/doc/generated/examples/builderswriting_ex1_1.xml index 1c6379a..cefcfa2 100644 --- a/doc/generated/examples/builderswriting_ex1_1.xml +++ b/doc/generated/examples/builderswriting_ex1_1.xml @@ -1,3 +1,4 @@ -% scons -Q + +% scons -Q foobuild < file.input > file.foo diff --git a/doc/generated/examples/builderswriting_ex2_1.xml b/doc/generated/examples/builderswriting_ex2_1.xml index e86ee7b..445dfb0 100644 --- a/doc/generated/examples/builderswriting_ex2_1.xml +++ b/doc/generated/examples/builderswriting_ex2_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q AttributeError: 'SConsEnvironment' object has no attribute 'Program': File "/home/my/project/SConstruct", line 4: env.Program('hello.c') diff --git a/doc/generated/examples/builderswriting_ex3_1.xml b/doc/generated/examples/builderswriting_ex3_1.xml index 8e107c8..2d8bcac 100644 --- a/doc/generated/examples/builderswriting_ex3_1.xml +++ b/doc/generated/examples/builderswriting_ex3_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q foobuild < file.input > file.foo cc -o hello.o -c hello.c cc -o hello hello.o diff --git a/doc/generated/examples/builderswriting_ex4_1.xml b/doc/generated/examples/builderswriting_ex4_1.xml index f3ecd43..cc71b19 100644 --- a/doc/generated/examples/builderswriting_ex4_1.xml +++ b/doc/generated/examples/builderswriting_ex4_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q foobuild < file1.input > file1.foo foobuild < file2.input > file2.foo diff --git a/doc/generated/examples/builderswriting_ex5_1.xml b/doc/generated/examples/builderswriting_ex5_1.xml index e7e9097..d0aa83b 100644 --- a/doc/generated/examples/builderswriting_ex5_1.xml +++ b/doc/generated/examples/builderswriting_ex5_1.xml @@ -1,3 +1,4 @@ -% scons -Q + +% scons -Q build_function(["file.foo"], ["file.input"]) diff --git a/doc/generated/examples/builderswriting_ex6_1.xml b/doc/generated/examples/builderswriting_ex6_1.xml index 1c6379a..cefcfa2 100644 --- a/doc/generated/examples/builderswriting_ex6_1.xml +++ b/doc/generated/examples/builderswriting_ex6_1.xml @@ -1,3 +1,4 @@ -% scons -Q + +% scons -Q foobuild < file.input > file.foo diff --git a/doc/generated/examples/builderswriting_ex7_1.xml b/doc/generated/examples/builderswriting_ex7_1.xml index 88284fe..f14d598 100644 --- a/doc/generated/examples/builderswriting_ex7_1.xml +++ b/doc/generated/examples/builderswriting_ex7_1.xml @@ -1,3 +1,4 @@ -% scons -Q + +% scons -Q foobuild file.foo new_target - file.input new_source diff --git a/doc/generated/examples/caching_ex-random_1.xml b/doc/generated/examples/caching_ex-random_1.xml index 52e7877..1c99727 100644 --- a/doc/generated/examples/caching_ex-random_1.xml +++ b/doc/generated/examples/caching_ex-random_1.xml @@ -1,8 +1,9 @@ -% scons -Q -cc -o f4.o -c f4.c -cc -o f5.o -c f5.c -cc -o f2.o -c f2.c + +% scons -Q cc -o f3.o -c f3.c +cc -o f4.o -c f4.c cc -o f1.o -c f1.c +cc -o f2.o -c f2.c +cc -o f5.o -c f5.c cc -o prog f1.o f2.o f3.o f4.o f5.o diff --git a/doc/generated/examples/caching_ex1_1.xml b/doc/generated/examples/caching_ex1_1.xml index 2d65d46..38eaf82 100644 --- a/doc/generated/examples/caching_ex1_1.xml +++ b/doc/generated/examples/caching_ex1_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o hello.o -c hello.c cc -o hello hello.o % scons -Q -c diff --git a/doc/generated/examples/caching_ex1_2.xml b/doc/generated/examples/caching_ex1_2.xml index 1b27272..2f0bcde 100644 --- a/doc/generated/examples/caching_ex1_2.xml +++ b/doc/generated/examples/caching_ex1_2.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o hello.o -c hello.c cc -o hello hello.o % scons -Q -c diff --git a/doc/generated/examples/caching_ex1_4.xml b/doc/generated/examples/caching_ex1_4.xml index c33dd9b..922f1b6 100644 --- a/doc/generated/examples/caching_ex1_4.xml +++ b/doc/generated/examples/caching_ex1_4.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o hello.o -c hello.c cc -o hello hello.o % scons -Q -c diff --git a/doc/generated/examples/caching_ex1_5.xml b/doc/generated/examples/caching_ex1_5.xml index b784319..968727f 100644 --- a/doc/generated/examples/caching_ex1_5.xml +++ b/doc/generated/examples/caching_ex1_5.xml @@ -1,4 +1,5 @@ -% scons -Q --cache-disable + +% scons -Q --cache-disable cc -o hello.o -c hello.c cc -o hello hello.o % scons -Q -c diff --git a/doc/generated/examples/commandline_ARGLIST_1.xml b/doc/generated/examples/commandline_ARGLIST_1.xml index af2d032..e094bc0 100644 --- a/doc/generated/examples/commandline_ARGLIST_1.xml +++ b/doc/generated/examples/commandline_ARGLIST_1.xml @@ -1,4 +1,5 @@ -% scons -Q define=FOO + +% scons -Q define=FOO cc -o prog.o -c -DFOO prog.c % scons -Q define=FOO define=BAR cc -o prog.o -c -DFOO -DBAR prog.c diff --git a/doc/generated/examples/commandline_ARGUMENTS_1.xml b/doc/generated/examples/commandline_ARGUMENTS_1.xml index cd76cfb..6aa4ed2 100644 --- a/doc/generated/examples/commandline_ARGUMENTS_1.xml +++ b/doc/generated/examples/commandline_ARGUMENTS_1.xml @@ -1,4 +1,5 @@ -% scons -Q debug=0 + +% scons -Q debug=0 cc -o prog.o -c prog.c cc -o prog prog.o % scons -Q debug=0 diff --git a/doc/generated/examples/commandline_AddOption_1.xml b/doc/generated/examples/commandline_AddOption_1.xml index 5877f6d..55df25a 100644 --- a/doc/generated/examples/commandline_AddOption_1.xml +++ b/doc/generated/examples/commandline_AddOption_1.xml @@ -1,3 +1,4 @@ -% scons -Q -n + +% scons -Q -n Install file: "foo.in" as "/usr/bin/foo.in" diff --git a/doc/generated/examples/commandline_AddOption_2.xml b/doc/generated/examples/commandline_AddOption_2.xml index 3000a43..7d0b978 100644 --- a/doc/generated/examples/commandline_AddOption_2.xml +++ b/doc/generated/examples/commandline_AddOption_2.xml @@ -1,3 +1,4 @@ -% scons -Q -n --prefix=/tmp/install + +% scons -Q -n --prefix=/tmp/install Install file: "foo.in" as "/tmp/install/usr/bin/foo.in" diff --git a/doc/generated/examples/commandline_BUILD_TARGETS_1_1.xml b/doc/generated/examples/commandline_BUILD_TARGETS_1_1.xml index be22abf..bd51961 100644 --- a/doc/generated/examples/commandline_BUILD_TARGETS_1_1.xml +++ b/doc/generated/examples/commandline_BUILD_TARGETS_1_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q BUILD_TARGETS is ['prog1'] cc -o prog1.o -c prog1.c cc -o prog1 prog1.o diff --git a/doc/generated/examples/commandline_BoolVariable_1.xml b/doc/generated/examples/commandline_BoolVariable_1.xml index 481c0a3..e4c1792 100644 --- a/doc/generated/examples/commandline_BoolVariable_1.xml +++ b/doc/generated/examples/commandline_BoolVariable_1.xml @@ -1,3 +1,4 @@ -% scons -Q RELEASE=yes foo.o + +% scons -Q RELEASE=yes foo.o cc -o foo.o -c -DRELEASE_BUILD=True foo.c diff --git a/doc/generated/examples/commandline_BoolVariable_2.xml b/doc/generated/examples/commandline_BoolVariable_2.xml index 69f8155..dc1e068 100644 --- a/doc/generated/examples/commandline_BoolVariable_2.xml +++ b/doc/generated/examples/commandline_BoolVariable_2.xml @@ -1,3 +1,4 @@ -% scons -Q RELEASE=t foo.o + +% scons -Q RELEASE=t foo.o cc -o foo.o -c -DRELEASE_BUILD=True foo.c diff --git a/doc/generated/examples/commandline_BoolVariable_3.xml b/doc/generated/examples/commandline_BoolVariable_3.xml index 8d635f7..0750fb5 100644 --- a/doc/generated/examples/commandline_BoolVariable_3.xml +++ b/doc/generated/examples/commandline_BoolVariable_3.xml @@ -1,3 +1,4 @@ -% scons -Q RELEASE=no foo.o + +% scons -Q RELEASE=no foo.o cc -o foo.o -c -DRELEASE_BUILD=False foo.c diff --git a/doc/generated/examples/commandline_BoolVariable_4.xml b/doc/generated/examples/commandline_BoolVariable_4.xml index c576eee..84e4639 100644 --- a/doc/generated/examples/commandline_BoolVariable_4.xml +++ b/doc/generated/examples/commandline_BoolVariable_4.xml @@ -1,3 +1,4 @@ -% scons -Q RELEASE=f foo.o + +% scons -Q RELEASE=f foo.o cc -o foo.o -c -DRELEASE_BUILD=False foo.c diff --git a/doc/generated/examples/commandline_BoolVariable_5.xml b/doc/generated/examples/commandline_BoolVariable_5.xml index 1384407..81f1d4e 100644 --- a/doc/generated/examples/commandline_BoolVariable_5.xml +++ b/doc/generated/examples/commandline_BoolVariable_5.xml @@ -1,4 +1,5 @@ -% scons -Q RELEASE=bad_value foo.o + +% scons -Q RELEASE=bad_value foo.o scons: *** Error converting option: RELEASE Invalid value for boolean option: bad_value diff --git a/doc/generated/examples/commandline_COMMAND_LINE_TARGETS_1.xml b/doc/generated/examples/commandline_COMMAND_LINE_TARGETS_1.xml index ba270b8..1812f74 100644 --- a/doc/generated/examples/commandline_COMMAND_LINE_TARGETS_1.xml +++ b/doc/generated/examples/commandline_COMMAND_LINE_TARGETS_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o foo.o -c foo.c cc -o foo foo.o % scons -Q bar diff --git a/doc/generated/examples/commandline_DEFAULT_TARGETS_1_1.xml b/doc/generated/examples/commandline_DEFAULT_TARGETS_1_1.xml index 3f9e0fe..f92f160 100644 --- a/doc/generated/examples/commandline_DEFAULT_TARGETS_1_1.xml +++ b/doc/generated/examples/commandline_DEFAULT_TARGETS_1_1.xml @@ -1,4 +1,5 @@ -% scons + +% scons scons: Reading SConscript files ... DEFAULT_TARGETS is ['prog1'] scons: done reading SConscript files. diff --git a/doc/generated/examples/commandline_DEFAULT_TARGETS_2_1.xml b/doc/generated/examples/commandline_DEFAULT_TARGETS_2_1.xml index c51626d..01e953b 100644 --- a/doc/generated/examples/commandline_DEFAULT_TARGETS_2_1.xml +++ b/doc/generated/examples/commandline_DEFAULT_TARGETS_2_1.xml @@ -1,4 +1,5 @@ -% scons + +% scons scons: Reading SConscript files ... DEFAULT_TARGETS is now ['prog1'] DEFAULT_TARGETS is now ['prog1', 'prog2'] diff --git a/doc/generated/examples/commandline_Default1_1.xml b/doc/generated/examples/commandline_Default1_1.xml index 8679e25..18008d8 100644 --- a/doc/generated/examples/commandline_Default1_1.xml +++ b/doc/generated/examples/commandline_Default1_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o hello.o -c hello.c cc -o hello hello.o % scons -Q diff --git a/doc/generated/examples/commandline_Default1_2.xml b/doc/generated/examples/commandline_Default1_2.xml index e40c298..0f1a93e 100644 --- a/doc/generated/examples/commandline_Default1_2.xml +++ b/doc/generated/examples/commandline_Default1_2.xml @@ -1,4 +1,5 @@ -% scons -Q . + +% scons -Q . cc -o goodbye.o -c goodbye.c cc -o goodbye goodbye.o cc -o hello.o -c hello.c diff --git a/doc/generated/examples/commandline_Default2_1.xml b/doc/generated/examples/commandline_Default2_1.xml index bb4cd0c..606ed67 100644 --- a/doc/generated/examples/commandline_Default2_1.xml +++ b/doc/generated/examples/commandline_Default2_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o prog1.o -c prog1.c cc -o prog1 prog1.o cc -o prog3.o -c prog3.c diff --git a/doc/generated/examples/commandline_Default3_1.xml b/doc/generated/examples/commandline_Default3_1.xml index de93fb6..d18575c 100644 --- a/doc/generated/examples/commandline_Default3_1.xml +++ b/doc/generated/examples/commandline_Default3_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o prog1/foo.o -c prog1/foo.c cc -o prog1/main.o -c prog1/main.c cc -o prog1/main prog1/main.o prog1/foo.o diff --git a/doc/generated/examples/commandline_Default4_1.xml b/doc/generated/examples/commandline_Default4_1.xml index 3c16091..35e0b10 100644 --- a/doc/generated/examples/commandline_Default4_1.xml +++ b/doc/generated/examples/commandline_Default4_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q scons: *** No targets specified and no Default() targets found. Stop. Found nothing to build % scons -Q . diff --git a/doc/generated/examples/commandline_EnumVariable_1.xml b/doc/generated/examples/commandline_EnumVariable_1.xml index 2178dba..d658f69 100644 --- a/doc/generated/examples/commandline_EnumVariable_1.xml +++ b/doc/generated/examples/commandline_EnumVariable_1.xml @@ -1,4 +1,5 @@ -% scons -Q COLOR=red foo.o + +% scons -Q COLOR=red foo.o cc -o foo.o -c -DCOLOR="red" foo.c % scons -Q COLOR=blue foo.o cc -o foo.o -c -DCOLOR="blue" foo.c diff --git a/doc/generated/examples/commandline_EnumVariable_2.xml b/doc/generated/examples/commandline_EnumVariable_2.xml index c41e679..a8a18df 100644 --- a/doc/generated/examples/commandline_EnumVariable_2.xml +++ b/doc/generated/examples/commandline_EnumVariable_2.xml @@ -1,4 +1,5 @@ -% scons -Q COLOR=magenta foo.o + +% scons -Q COLOR=magenta foo.o scons: *** Invalid value for option COLOR: magenta. Valid values are: ('red', 'green', 'blue') File "/home/my/project/SConstruct", line 5, in <module> diff --git a/doc/generated/examples/commandline_EnumVariable_3.xml b/doc/generated/examples/commandline_EnumVariable_3.xml index 638ddda..bb9a6d5 100644 --- a/doc/generated/examples/commandline_EnumVariable_3.xml +++ b/doc/generated/examples/commandline_EnumVariable_3.xml @@ -1,4 +1,5 @@ -% scons -Q COLOR=Red foo.o + +% scons -Q COLOR=Red foo.o scons: *** Invalid value for option COLOR: Red. Valid values are: ('red', 'green', 'blue') File "/home/my/project/SConstruct", line 5, in <module> diff --git a/doc/generated/examples/commandline_EnumVariable_ic1_1.xml b/doc/generated/examples/commandline_EnumVariable_ic1_1.xml index 33f668d..db786e5 100644 --- a/doc/generated/examples/commandline_EnumVariable_ic1_1.xml +++ b/doc/generated/examples/commandline_EnumVariable_ic1_1.xml @@ -1,4 +1,5 @@ -% scons -Q COLOR=Red foo.o + +% scons -Q COLOR=Red foo.o cc -o foo.o -c -DCOLOR="Red" foo.c % scons -Q COLOR=BLUE foo.o cc -o foo.o -c -DCOLOR="BLUE" foo.c diff --git a/doc/generated/examples/commandline_EnumVariable_ic2_1.xml b/doc/generated/examples/commandline_EnumVariable_ic2_1.xml index ef24936..5596608 100644 --- a/doc/generated/examples/commandline_EnumVariable_ic2_1.xml +++ b/doc/generated/examples/commandline_EnumVariable_ic2_1.xml @@ -1,4 +1,5 @@ -% scons -Q COLOR=Red foo.o + +% scons -Q COLOR=Red foo.o cc -o foo.o -c -DCOLOR="red" foo.c % scons -Q COLOR=nAvY foo.o cc -o foo.o -c -DCOLOR="blue" foo.c diff --git a/doc/generated/examples/commandline_ListVariable_1.xml b/doc/generated/examples/commandline_ListVariable_1.xml index f04d1f3..6e245a3 100644 --- a/doc/generated/examples/commandline_ListVariable_1.xml +++ b/doc/generated/examples/commandline_ListVariable_1.xml @@ -1,4 +1,5 @@ -% scons -Q COLORS=red,blue foo.o + +% scons -Q COLORS=red,blue foo.o cc -o foo.o -c -DCOLORS="red blue" foo.c % scons -Q COLORS=blue,green,red foo.o cc -o foo.o -c -DCOLORS="blue green red" foo.c diff --git a/doc/generated/examples/commandline_ListVariable_2.xml b/doc/generated/examples/commandline_ListVariable_2.xml index 50bc815..b964669 100644 --- a/doc/generated/examples/commandline_ListVariable_2.xml +++ b/doc/generated/examples/commandline_ListVariable_2.xml @@ -1,4 +1,5 @@ -% scons -Q COLORS=all foo.o + +% scons -Q COLORS=all foo.o cc -o foo.o -c -DCOLORS="red green blue" foo.c % scons -Q COLORS=none foo.o cc -o foo.o -c -DCOLORS="" foo.c diff --git a/doc/generated/examples/commandline_ListVariable_3.xml b/doc/generated/examples/commandline_ListVariable_3.xml index f697598..ae13d8b 100644 --- a/doc/generated/examples/commandline_ListVariable_3.xml +++ b/doc/generated/examples/commandline_ListVariable_3.xml @@ -1,4 +1,5 @@ -% scons -Q COLORS=magenta foo.o + +% scons -Q COLORS=magenta foo.o scons: *** Error converting option: COLORS Invalid value(s) for option: magenta diff --git a/doc/generated/examples/commandline_PackageVariable_1.xml b/doc/generated/examples/commandline_PackageVariable_1.xml index daaa696..b83fd80 100644 --- a/doc/generated/examples/commandline_PackageVariable_1.xml +++ b/doc/generated/examples/commandline_PackageVariable_1.xml @@ -1,4 +1,5 @@ -% scons -Q foo.o + +% scons -Q foo.o cc -o foo.o -c -DPACKAGE="/opt/location" foo.c % scons -Q PACKAGE=/usr/local/location foo.o cc -o foo.o -c -DPACKAGE="/usr/local/location" foo.c diff --git a/doc/generated/examples/commandline_PathVariable_1.xml b/doc/generated/examples/commandline_PathVariable_1.xml index e995a69..81693b9 100644 --- a/doc/generated/examples/commandline_PathVariable_1.xml +++ b/doc/generated/examples/commandline_PathVariable_1.xml @@ -1,4 +1,5 @@ -% scons -Q foo.o + +% scons -Q foo.o cc -o foo.o -c -DCONFIG_FILE="/etc/my_config" foo.c % scons -Q CONFIG=/usr/local/etc/other_config foo.o scons: `foo.o' is up to date. diff --git a/doc/generated/examples/commandline_PathVariable_2.xml b/doc/generated/examples/commandline_PathVariable_2.xml index 6d69288..7dde5b1 100644 --- a/doc/generated/examples/commandline_PathVariable_2.xml +++ b/doc/generated/examples/commandline_PathVariable_2.xml @@ -1,4 +1,5 @@ -% scons -Q CONFIG=/does/not/exist foo.o + +% scons -Q CONFIG=/does/not/exist foo.o scons: *** Path for option CONFIG does not exist: /does/not/exist File "/home/my/project/SConstruct", line 6, in <module> diff --git a/doc/generated/examples/commandline_SCONSFLAGS_1.xml b/doc/generated/examples/commandline_SCONSFLAGS_1.xml index fc54357..35e366c 100644 --- a/doc/generated/examples/commandline_SCONSFLAGS_1.xml +++ b/doc/generated/examples/commandline_SCONSFLAGS_1.xml @@ -1,4 +1,5 @@ -% scons + +% scons scons: Reading SConscript files ... scons: done reading SConscript files. scons: Building targets ... diff --git a/doc/generated/examples/commandline_SetOption_1.xml b/doc/generated/examples/commandline_SetOption_1.xml index 4aedc2e..bac0cf4 100644 --- a/doc/generated/examples/commandline_SetOption_1.xml +++ b/doc/generated/examples/commandline_SetOption_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q running with -j 2 scons: `.' is up to date. diff --git a/doc/generated/examples/commandline_SetOption_2.xml b/doc/generated/examples/commandline_SetOption_2.xml index 54e214f..b00e073 100644 --- a/doc/generated/examples/commandline_SetOption_2.xml +++ b/doc/generated/examples/commandline_SetOption_2.xml @@ -1,4 +1,5 @@ -% export NUM_CPU="4" + +% export NUM_CPU="4" % scons -Q running with -j 4 scons: `.' is up to date. diff --git a/doc/generated/examples/commandline_SetOption_3.xml b/doc/generated/examples/commandline_SetOption_3.xml index 2db0d62..df42ff0 100644 --- a/doc/generated/examples/commandline_SetOption_3.xml +++ b/doc/generated/examples/commandline_SetOption_3.xml @@ -1,4 +1,5 @@ -% scons -Q -j 7 + +% scons -Q -j 7 running with -j 7 scons: `.' is up to date. % export NUM_CPU="4" diff --git a/doc/generated/examples/commandline_UnknownVariables_1.xml b/doc/generated/examples/commandline_UnknownVariables_1.xml index ecca75f..272a954 100644 --- a/doc/generated/examples/commandline_UnknownVariables_1.xml +++ b/doc/generated/examples/commandline_UnknownVariables_1.xml @@ -1,3 +1,4 @@ -% scons -Q NOT_KNOWN=foo -Unknown variables: dict_keys(['NOT_KNOWN']) + +% scons -Q NOT_KNOWN=foo +Unknown variables: ['NOT_KNOWN'] diff --git a/doc/generated/examples/commandline_Variables1_1.xml b/doc/generated/examples/commandline_Variables1_1.xml index 2b6ecf8..512ae65 100644 --- a/doc/generated/examples/commandline_Variables1_1.xml +++ b/doc/generated/examples/commandline_Variables1_1.xml @@ -1,4 +1,5 @@ -% scons -Q RELEASE=1 + +% scons -Q RELEASE=1 cc -o bar.o -c -DRELEASE_BUILD=1 bar.c cc -o foo.o -c -DRELEASE_BUILD=1 foo.c cc -o foo foo.o bar.o diff --git a/doc/generated/examples/commandline_Variables_Help_1.xml b/doc/generated/examples/commandline_Variables_Help_1.xml index 9fe588e..db171eb 100644 --- a/doc/generated/examples/commandline_Variables_Help_1.xml +++ b/doc/generated/examples/commandline_Variables_Help_1.xml @@ -1,4 +1,5 @@ -% scons -Q -h + +% scons -Q -h RELEASE: Set to 1 to build for release default: 0 diff --git a/doc/generated/examples/commandline_Variables_custom_py_1_1.xml b/doc/generated/examples/commandline_Variables_custom_py_1_1.xml index bf31267..4ef4d48 100644 --- a/doc/generated/examples/commandline_Variables_custom_py_1_1.xml +++ b/doc/generated/examples/commandline_Variables_custom_py_1_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o bar.o -c -DRELEASE_BUILD=1 bar.c cc -o foo.o -c -DRELEASE_BUILD=1 foo.c cc -o foo foo.o bar.o diff --git a/doc/generated/examples/commandline_Variables_custom_py_2_1.xml b/doc/generated/examples/commandline_Variables_custom_py_2_1.xml index fc07260..5961d0a 100644 --- a/doc/generated/examples/commandline_Variables_custom_py_2_1.xml +++ b/doc/generated/examples/commandline_Variables_custom_py_2_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o bar.o -c -DRELEASE_BUILD=0 bar.c cc -o foo.o -c -DRELEASE_BUILD=0 foo.c cc -o foo foo.o bar.o diff --git a/doc/generated/examples/depends_AlwaysBuild_1.xml b/doc/generated/examples/depends_AlwaysBuild_1.xml index e8bafae..86700fe 100644 --- a/doc/generated/examples/depends_AlwaysBuild_1.xml +++ b/doc/generated/examples/depends_AlwaysBuild_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o hello.o -c hello.c cc -o hello hello.o % scons -Q diff --git a/doc/generated/examples/depends_AlwaysBuild_2.xml b/doc/generated/examples/depends_AlwaysBuild_2.xml index 501ffa1..d1bdd6d 100644 --- a/doc/generated/examples/depends_AlwaysBuild_2.xml +++ b/doc/generated/examples/depends_AlwaysBuild_2.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o hello.o -c hello.c cc -o hello hello.o % scons -Q hello.o diff --git a/doc/generated/examples/depends_Requires_1.xml b/doc/generated/examples/depends_Requires_1.xml index 0a07c01..04bfc35 100644 --- a/doc/generated/examples/depends_Requires_1.xml +++ b/doc/generated/examples/depends_Requires_1.xml @@ -1,4 +1,5 @@ -% scons -Q hello + +% scons -Q hello cc -o version.o -c version.c cc -o hello.o -c hello.c cc -o hello version.o hello.o diff --git a/doc/generated/examples/depends_ex1_1.xml b/doc/generated/examples/depends_ex1_1.xml index 1a94afc..25355c9 100644 --- a/doc/generated/examples/depends_ex1_1.xml +++ b/doc/generated/examples/depends_ex1_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o hello.o -c hello.c cc -o hello hello.o % scons -Q diff --git a/doc/generated/examples/depends_ex1_2.xml b/doc/generated/examples/depends_ex1_2.xml index 0fd2024..09ecc73 100644 --- a/doc/generated/examples/depends_ex1_2.xml +++ b/doc/generated/examples/depends_ex1_2.xml @@ -1,4 +1,5 @@ -% scons -Q hello + +% scons -Q hello cc -o hello.o -c hello.c cc -o hello hello.o % scons -Q hello diff --git a/doc/generated/examples/depends_ex1_3.xml b/doc/generated/examples/depends_ex1_3.xml index 6bfba52..20062df 100644 --- a/doc/generated/examples/depends_ex1_3.xml +++ b/doc/generated/examples/depends_ex1_3.xml @@ -1,4 +1,5 @@ -% scons -Q hello + +% scons -Q hello cc -o hello.o -c hello.c cc -o hello hello.o % touch hello.c diff --git a/doc/generated/examples/depends_ex1_4.xml b/doc/generated/examples/depends_ex1_4.xml index bae5bd7..31aa5bd 100644 --- a/doc/generated/examples/depends_ex1_4.xml +++ b/doc/generated/examples/depends_ex1_4.xml @@ -1,4 +1,5 @@ -% scons -Q hello + +% scons -Q hello cc -o hello.o -c hello.c cc -o hello hello.o % [CHANGE THE CONTENTS OF hello.c] diff --git a/doc/generated/examples/depends_ex1_5.xml b/doc/generated/examples/depends_ex1_5.xml index 358bf5b..776bda2 100644 --- a/doc/generated/examples/depends_ex1_5.xml +++ b/doc/generated/examples/depends_ex1_5.xml @@ -1,4 +1,5 @@ -% scons -Q hello + +% scons -Q hello cc -o hello.o -c hello.c cc -o hello hello.o % [CHANGE A COMMENT IN hello.c] diff --git a/doc/generated/examples/depends_ex1_6.xml b/doc/generated/examples/depends_ex1_6.xml index 8461234..7493627 100644 --- a/doc/generated/examples/depends_ex1_6.xml +++ b/doc/generated/examples/depends_ex1_6.xml @@ -1,4 +1,5 @@ -% scons -Q --implicit-cache hello + +% scons -Q --implicit-cache hello cc -o hello.o -c hello.c cc -o hello hello.o % scons -Q hello diff --git a/doc/generated/examples/depends_ex1_7.xml b/doc/generated/examples/depends_ex1_7.xml index ea9088a..22b56d3 100644 --- a/doc/generated/examples/depends_ex1_7.xml +++ b/doc/generated/examples/depends_ex1_7.xml @@ -1,4 +1,5 @@ -% scons -Q --implicit-deps-changed hello + +% scons -Q --implicit-deps-changed hello cc -o hello.o -c hello.c cc -o hello hello.o % scons -Q hello diff --git a/doc/generated/examples/depends_ex1_8.xml b/doc/generated/examples/depends_ex1_8.xml index cc4ee6c..d60db97 100644 --- a/doc/generated/examples/depends_ex1_8.xml +++ b/doc/generated/examples/depends_ex1_8.xml @@ -1,4 +1,5 @@ -% scons -Q --implicit-deps-unchanged hello + +% scons -Q --implicit-deps-unchanged hello cc -o hello.o -c hello.c cc -o hello hello.o % scons -Q hello diff --git a/doc/generated/examples/depends_ex5_1.xml b/doc/generated/examples/depends_ex5_1.xml index 37985df..e81cb0c 100644 --- a/doc/generated/examples/depends_ex5_1.xml +++ b/doc/generated/examples/depends_ex5_1.xml @@ -1,4 +1,5 @@ -% scons -Q hello + +% scons -Q hello cc -o hello.o -c -Iinclude -I/home/project/inc hello.c cc -o hello hello.o diff --git a/doc/generated/examples/depends_ex5_2.xml b/doc/generated/examples/depends_ex5_2.xml index 460d135..ea78590 100644 --- a/doc/generated/examples/depends_ex5_2.xml +++ b/doc/generated/examples/depends_ex5_2.xml @@ -1,4 +1,5 @@ -C:\>scons -Q hello.exe + +C:\>scons -Q hello.exe cl /Fohello.obj /c hello.c /nologo /Iinclude /I\home\project\inc link /nologo /OUT:hello.exe hello.obj embedManifestExeCheck(target, source, env) diff --git a/doc/generated/examples/depends_ignore_explicit_1.xml b/doc/generated/examples/depends_ignore_explicit_1.xml index 79ebca2..a45a852 100644 --- a/doc/generated/examples/depends_ignore_explicit_1.xml +++ b/doc/generated/examples/depends_ignore_explicit_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q scons: `.' is up to date. % scons -Q hello cc -o hello.o -c hello.c diff --git a/doc/generated/examples/depends_include_1.xml b/doc/generated/examples/depends_include_1.xml index 987fead..e22bd03 100644 --- a/doc/generated/examples/depends_include_1.xml +++ b/doc/generated/examples/depends_include_1.xml @@ -1,4 +1,5 @@ -% scons -Q hello + +% scons -Q hello cc -o hello.o -c -I. hello.c cc -o hello hello.o % scons -Q hello diff --git a/doc/generated/examples/depends_macroinc_1.xml b/doc/generated/examples/depends_macroinc_1.xml index d15f4ef..95d4e0b 100644 --- a/doc/generated/examples/depends_macroinc_1.xml +++ b/doc/generated/examples/depends_macroinc_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o hello.o -c -I. hello.c cc -o hello hello.o % [CHANGE CONTENTS OF foo.h] diff --git a/doc/generated/examples/depends_match_1.xml b/doc/generated/examples/depends_match_1.xml index cde65ca..7dc3831 100644 --- a/doc/generated/examples/depends_match_1.xml +++ b/doc/generated/examples/depends_match_1.xml @@ -1,4 +1,5 @@ -% scons -Q hello.o + +% scons -Q hello.o cc -o hello.o -c hello.c % touch -t 198901010000 hello.c % scons -Q hello.o diff --git a/doc/generated/examples/depends_mixing_1.xml b/doc/generated/examples/depends_mixing_1.xml index 30d2527..258dc90 100644 --- a/doc/generated/examples/depends_mixing_1.xml +++ b/doc/generated/examples/depends_mixing_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o program1.o -c -I. program1.c cc -o prog-MD5 program1.o cc -o program2.o -c -I. program2.c diff --git a/doc/generated/examples/depends_newer_1.xml b/doc/generated/examples/depends_newer_1.xml index b09d0d6..28cb427 100644 --- a/doc/generated/examples/depends_newer_1.xml +++ b/doc/generated/examples/depends_newer_1.xml @@ -1,4 +1,5 @@ -% scons -Q hello.o + +% scons -Q hello.o cc -o hello.o -c hello.c % touch hello.c % scons -Q hello.o diff --git a/doc/generated/examples/depends_no-Requires_1.xml b/doc/generated/examples/depends_no-Requires_1.xml index 8be3285..8e2729f 100644 --- a/doc/generated/examples/depends_no-Requires_1.xml +++ b/doc/generated/examples/depends_no-Requires_1.xml @@ -1,4 +1,5 @@ -% scons -Q hello + +% scons -Q hello cc -o hello.o -c hello.c cc -o version.o -c version.c cc -o hello hello.o version.o diff --git a/doc/generated/examples/depends_parsedep_1.xml b/doc/generated/examples/depends_parsedep_1.xml index e83eccf..910930b1 100644 --- a/doc/generated/examples/depends_parsedep_1.xml +++ b/doc/generated/examples/depends_parsedep_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o hello.o -c -MD -MF hello.d -I. hello.c cc -o hello hello.o % [CHANGE CONTENTS OF foo.h] diff --git a/doc/generated/examples/environments_Append-nonexistent_1.xml b/doc/generated/examples/environments_Append-nonexistent_1.xml index 43b6834..bb15965 100644 --- a/doc/generated/examples/environments_Append-nonexistent_1.xml +++ b/doc/generated/examples/environments_Append-nonexistent_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q NEW_VARIABLE = added scons: `.' is up to date. diff --git a/doc/generated/examples/environments_Prepend-nonexistent_1.xml b/doc/generated/examples/environments_Prepend-nonexistent_1.xml index 43b6834..bb15965 100644 --- a/doc/generated/examples/environments_Prepend-nonexistent_1.xml +++ b/doc/generated/examples/environments_Prepend-nonexistent_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q NEW_VARIABLE = added scons: `.' is up to date. diff --git a/doc/generated/examples/environments_Replace-nonexistent_1.xml b/doc/generated/examples/environments_Replace-nonexistent_1.xml index 2aba4c8..c4480b5 100644 --- a/doc/generated/examples/environments_Replace-nonexistent_1.xml +++ b/doc/generated/examples/environments_Replace-nonexistent_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q NEW_VARIABLE = xyzzy scons: `.' is up to date. diff --git a/doc/generated/examples/environments_Replace1_1.xml b/doc/generated/examples/environments_Replace1_1.xml index 6fedc45..54f4976 100644 --- a/doc/generated/examples/environments_Replace1_1.xml +++ b/doc/generated/examples/environments_Replace1_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o foo.o -c -DDEFINE2 foo.c cc -o foo foo.o diff --git a/doc/generated/examples/environments_Replace2_1.xml b/doc/generated/examples/environments_Replace2_1.xml index 61027c8..9ad257b 100644 --- a/doc/generated/examples/environments_Replace2_1.xml +++ b/doc/generated/examples/environments_Replace2_1.xml @@ -1,4 +1,5 @@ -% scons + +% scons scons: Reading SConscript files ... CCFLAGS = -DDEFINE1 CCFLAGS = -DDEFINE2 diff --git a/doc/generated/examples/environments_ex1_1.xml b/doc/generated/examples/environments_ex1_1.xml index 1c4da07..84d22b8 100644 --- a/doc/generated/examples/environments_ex1_1.xml +++ b/doc/generated/examples/environments_ex1_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q gcc -o foo.o -c -O2 foo.c gcc -o foo foo.o diff --git a/doc/generated/examples/environments_ex2_1.xml b/doc/generated/examples/environments_ex2_1.xml index acab07b..eb86c9e 100644 --- a/doc/generated/examples/environments_ex2_1.xml +++ b/doc/generated/examples/environments_ex2_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o bar.o -c -g bar.c cc -o bar bar.o cc -o foo.o -c -O2 foo.c diff --git a/doc/generated/examples/environments_ex3_1.xml b/doc/generated/examples/environments_ex3_1.xml index 1c7bce9..3262302 100644 --- a/doc/generated/examples/environments_ex3_1.xml +++ b/doc/generated/examples/environments_ex3_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q scons: *** Two environments with different actions were specified for the same target: foo.o File "/home/my/project/SConstruct", line 6, in <module> diff --git a/doc/generated/examples/environments_ex4_1.xml b/doc/generated/examples/environments_ex4_1.xml index 4eda402..286f46f 100644 --- a/doc/generated/examples/environments_ex4_1.xml +++ b/doc/generated/examples/environments_ex4_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o foo-dbg.o -c -g foo.c cc -o foo-dbg foo-dbg.o cc -o foo-opt.o -c -O2 foo.c diff --git a/doc/generated/examples/environments_ex5_1.xml b/doc/generated/examples/environments_ex5_1.xml index 7316a6c..d6f0094 100644 --- a/doc/generated/examples/environments_ex5_1.xml +++ b/doc/generated/examples/environments_ex5_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q gcc -o foo.o -c foo.c gcc -o foo foo.o gcc -o foo-dbg.o -c -g foo.c diff --git a/doc/generated/examples/environments_ex6_1.xml b/doc/generated/examples/environments_ex6_1.xml index f6aa4b6..af8667f 100644 --- a/doc/generated/examples/environments_ex6_1.xml +++ b/doc/generated/examples/environments_ex6_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q CC is: cc scons: `.' is up to date. diff --git a/doc/generated/examples/environments_ex6b_1.xml b/doc/generated/examples/environments_ex6b_1.xml index 0da8d90..47a499a 100644 --- a/doc/generated/examples/environments_ex6b_1.xml +++ b/doc/generated/examples/environments_ex6b_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q key = OBJSUFFIX, value = .o key = LIBSUFFIX, value = .a key = PROGSUFFIX, value = diff --git a/doc/generated/examples/environments_ex6b_2.xml b/doc/generated/examples/environments_ex6b_2.xml index d0f20e9..73a6d19 100644 --- a/doc/generated/examples/environments_ex6b_2.xml +++ b/doc/generated/examples/environments_ex6b_2.xml @@ -1,4 +1,5 @@ -C:\>scons -Q + +C:\>scons -Q key = OBJSUFFIX, value = .obj key = LIBSUFFIX, value = .lib key = PROGSUFFIX, value = .exe diff --git a/doc/generated/examples/environments_ex8_1.xml b/doc/generated/examples/environments_ex8_1.xml index fe3b464..68ebac4 100644 --- a/doc/generated/examples/environments_ex8_1.xml +++ b/doc/generated/examples/environments_ex8_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o foo.o -c -DMY_VALUE -DLAST foo.c cc -o foo foo.o diff --git a/doc/generated/examples/environments_ex9_1.xml b/doc/generated/examples/environments_ex9_1.xml index 4d7bfd8..3e31c3f 100644 --- a/doc/generated/examples/environments_ex9_1.xml +++ b/doc/generated/examples/environments_ex9_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o foo.o -c -DFIRST -DMY_VALUE foo.c cc -o foo foo.o diff --git a/doc/generated/examples/environments_missing1_1.xml b/doc/generated/examples/environments_missing1_1.xml index 56b0ff5..edf136f 100644 --- a/doc/generated/examples/environments_missing1_1.xml +++ b/doc/generated/examples/environments_missing1_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q value is: -><- scons: `.' is up to date. diff --git a/doc/generated/examples/environments_missing2_1.xml b/doc/generated/examples/environments_missing2_1.xml index 770c7df..ffb308c 100644 --- a/doc/generated/examples/environments_missing2_1.xml +++ b/doc/generated/examples/environments_missing2_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q scons: *** NameError `MISSING' trying to evaluate `$MISSING' File "/home/my/project/SConstruct", line 3, in <module> diff --git a/doc/generated/examples/environments_missing3_1.xml b/doc/generated/examples/environments_missing3_1.xml index 56b0ff5..edf136f 100644 --- a/doc/generated/examples/environments_missing3_1.xml +++ b/doc/generated/examples/environments_missing3_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q value is: -><- scons: `.' is up to date. diff --git a/doc/generated/examples/factories_Chmod_1.xml b/doc/generated/examples/factories_Chmod_1.xml index 04e543c..a324ed4 100644 --- a/doc/generated/examples/factories_Chmod_1.xml +++ b/doc/generated/examples/factories_Chmod_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q Copy("file.out", "file.in") Chmod("file.out", 0755) diff --git a/doc/generated/examples/factories_Copy1_1.xml b/doc/generated/examples/factories_Copy1_1.xml index 02941a2..852412f 100644 --- a/doc/generated/examples/factories_Copy1_1.xml +++ b/doc/generated/examples/factories_Copy1_1.xml @@ -1,3 +1,4 @@ -% scons -Q + +% scons -Q Copy("file.out", "file.in") diff --git a/doc/generated/examples/factories_Copy2_1.xml b/doc/generated/examples/factories_Copy2_1.xml index 02941a2..852412f 100644 --- a/doc/generated/examples/factories_Copy2_1.xml +++ b/doc/generated/examples/factories_Copy2_1.xml @@ -1,3 +1,4 @@ -% scons -Q + +% scons -Q Copy("file.out", "file.in") diff --git a/doc/generated/examples/factories_Copy3_1.xml b/doc/generated/examples/factories_Copy3_1.xml index 224ec79..bcb41ff 100644 --- a/doc/generated/examples/factories_Copy3_1.xml +++ b/doc/generated/examples/factories_Copy3_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q Copy("tempfile", "file.in") modify tempfile Copy("file.out", "tempfile") diff --git a/doc/generated/examples/factories_Delete1_1.xml b/doc/generated/examples/factories_Delete1_1.xml index 22b5070..e9a287e 100644 --- a/doc/generated/examples/factories_Delete1_1.xml +++ b/doc/generated/examples/factories_Delete1_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q Delete("tempfile") Copy("tempfile", "file.in") modify tempfile diff --git a/doc/generated/examples/factories_Delete2_1.xml b/doc/generated/examples/factories_Delete2_1.xml index 109ed2c..2be3c3a 100644 --- a/doc/generated/examples/factories_Delete2_1.xml +++ b/doc/generated/examples/factories_Delete2_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q Delete("file.out") Copy("file.out", "file.in") diff --git a/doc/generated/examples/factories_Execute_1.xml b/doc/generated/examples/factories_Execute_1.xml index 0481396..a7ae0c7 100644 --- a/doc/generated/examples/factories_Execute_1.xml +++ b/doc/generated/examples/factories_Execute_1.xml @@ -1,4 +1,5 @@ -% scons + +% scons scons: Reading SConscript files ... Mkdir("/tmp/my_temp_directory") scons: done reading SConscript files. diff --git a/doc/generated/examples/factories_Mkdir_1.xml b/doc/generated/examples/factories_Mkdir_1.xml index 37c601d..ea3d79d 100644 --- a/doc/generated/examples/factories_Mkdir_1.xml +++ b/doc/generated/examples/factories_Mkdir_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q Delete("tempdir") Mkdir("tempdir") Copy("tempdir/file.in", "file.in") diff --git a/doc/generated/examples/factories_Move_1.xml b/doc/generated/examples/factories_Move_1.xml index a49ecef..a5e4ccd 100644 --- a/doc/generated/examples/factories_Move_1.xml +++ b/doc/generated/examples/factories_Move_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q Copy("tempfile", "file.in") modify tempfile Move("file.out", "tempfile") diff --git a/doc/generated/examples/factories_Touch_1.xml b/doc/generated/examples/factories_Touch_1.xml index dbc256a..7417fa4 100644 --- a/doc/generated/examples/factories_Touch_1.xml +++ b/doc/generated/examples/factories_Touch_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q Copy("file.out", "file.in") Touch("file.out") diff --git a/doc/generated/examples/fileremoval_clean-ex1_1.xml b/doc/generated/examples/fileremoval_clean-ex1_1.xml index 0d79060..c76a7e5 100644 --- a/doc/generated/examples/fileremoval_clean-ex1_1.xml +++ b/doc/generated/examples/fileremoval_clean-ex1_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q build -o foo.out foo.in % scons -Q -c Removed foo.out diff --git a/doc/generated/examples/fileremoval_noclean-ex1_1.xml b/doc/generated/examples/fileremoval_noclean-ex1_1.xml index bf5e42f..45bd878 100644 --- a/doc/generated/examples/fileremoval_noclean-ex1_1.xml +++ b/doc/generated/examples/fileremoval_noclean-ex1_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o f1.o -c f1.c cc -o f2.o -c f2.c cc -o f3.o -c f3.c diff --git a/doc/generated/examples/fileremoval_precious-ex1_1.xml b/doc/generated/examples/fileremoval_precious-ex1_1.xml index 232703f..36e5a25 100644 --- a/doc/generated/examples/fileremoval_precious-ex1_1.xml +++ b/doc/generated/examples/fileremoval_precious-ex1_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o f1.o -c f1.c cc -o f2.o -c f2.c cc -o f3.o -c f3.c diff --git a/doc/generated/examples/hierarchy_Return_1.xml b/doc/generated/examples/hierarchy_Return_1.xml index 417780f..e5ab7f7 100644 --- a/doc/generated/examples/hierarchy_Return_1.xml +++ b/doc/generated/examples/hierarchy_Return_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o bar/bar.o -c bar/bar.c cc -o foo/foo.o -c foo/foo.c ar rc libprog.a foo/foo.o bar/bar.o diff --git a/doc/generated/examples/hierarchy_ex1_1.xml b/doc/generated/examples/hierarchy_ex1_1.xml index c043c4b..bb5cc7b 100644 --- a/doc/generated/examples/hierarchy_ex1_1.xml +++ b/doc/generated/examples/hierarchy_ex1_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o prog1/foo1.o -c prog1/foo1.c cc -o prog1/foo2.o -c prog1/foo2.c cc -o prog1/main.o -c prog1/main.c diff --git a/doc/generated/examples/hierarchy_ex2_1.xml b/doc/generated/examples/hierarchy_ex2_1.xml index c6c7401..800a921 100644 --- a/doc/generated/examples/hierarchy_ex2_1.xml +++ b/doc/generated/examples/hierarchy_ex2_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o lib/foo1.o -c lib/foo1.c cc -o src/prog/foo2.o -c src/prog/foo2.c cc -o src/prog/main.o -c src/prog/main.c diff --git a/doc/generated/examples/hierarchy_ex3_1.xml b/doc/generated/examples/hierarchy_ex3_1.xml index 8c13ee3..473c9f4 100644 --- a/doc/generated/examples/hierarchy_ex3_1.xml +++ b/doc/generated/examples/hierarchy_ex3_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o src/prog/foo2.o -c src/prog/foo2.c cc -o src/prog/main.o -c src/prog/main.c cc -o /usr/joe/lib/foo1.o -c /usr/joe/lib/foo1.c diff --git a/doc/generated/examples/install_ex1_1.xml b/doc/generated/examples/install_ex1_1.xml index 30613e2..776f7e8 100644 --- a/doc/generated/examples/install_ex1_1.xml +++ b/doc/generated/examples/install_ex1_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o hello.o -c hello.c cc -o hello hello.o % scons -Q /usr/bin diff --git a/doc/generated/examples/install_ex2_1.xml b/doc/generated/examples/install_ex2_1.xml index 2354878..98de9c4 100644 --- a/doc/generated/examples/install_ex2_1.xml +++ b/doc/generated/examples/install_ex2_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o hello.o -c hello.c cc -o hello hello.o % scons -Q install diff --git a/doc/generated/examples/install_ex3_1.xml b/doc/generated/examples/install_ex3_1.xml index 0396853..e306111 100644 --- a/doc/generated/examples/install_ex3_1.xml +++ b/doc/generated/examples/install_ex3_1.xml @@ -1,4 +1,5 @@ -% scons -Q install + +% scons -Q install cc -o goodbye.o -c goodbye.c cc -o goodbye goodbye.o Install file: "goodbye" as "/usr/bin/goodbye" diff --git a/doc/generated/examples/install_ex4_1.xml b/doc/generated/examples/install_ex4_1.xml index 1bbbf65..36cd90c 100644 --- a/doc/generated/examples/install_ex4_1.xml +++ b/doc/generated/examples/install_ex4_1.xml @@ -1,4 +1,5 @@ -% scons -Q install + +% scons -Q install cc -o hello.o -c hello.c cc -o hello hello.o Install file: "hello" as "/usr/bin/hello-new" diff --git a/doc/generated/examples/install_ex5_1.xml b/doc/generated/examples/install_ex5_1.xml index 22c6b01..89f7c56 100644 --- a/doc/generated/examples/install_ex5_1.xml +++ b/doc/generated/examples/install_ex5_1.xml @@ -1,4 +1,5 @@ -% scons -Q install + +% scons -Q install cc -o goodbye.o -c goodbye.c cc -o goodbye goodbye.o Install file: "goodbye" as "/usr/bin/goodbye-new" diff --git a/doc/generated/examples/java_JAVACLASSDIR_1.xml b/doc/generated/examples/java_JAVACLASSDIR_1.xml index 75e5f95..5e0709a 100644 --- a/doc/generated/examples/java_JAVACLASSDIR_1.xml +++ b/doc/generated/examples/java_JAVACLASSDIR_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q javac -d classes -sourcepath src/pkg/sub src/pkg/sub/Example1.java src/pkg/sub/Example2.java src/pkg/sub/Example3.java javah -d native -classpath classes pkg.sub.Example1 pkg.sub.Example2 pkg.sub.Example3 diff --git a/doc/generated/examples/java_RMIC_1.xml b/doc/generated/examples/java_RMIC_1.xml index 16297dc..4db895e 100644 --- a/doc/generated/examples/java_RMIC_1.xml +++ b/doc/generated/examples/java_RMIC_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q javac -d classes -sourcepath src/pkg/sub src/pkg/sub/Example1.java src/pkg/sub/Example2.java rmic -d outdir -classpath classes pkg.sub.Example1 pkg.sub.Example2 diff --git a/doc/generated/examples/java_jar1_1.xml b/doc/generated/examples/java_jar1_1.xml index a88c00a..de93227 100644 --- a/doc/generated/examples/java_jar1_1.xml +++ b/doc/generated/examples/java_jar1_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q javac -d classes -sourcepath src src/Example1.java src/Example2.java src/Example3.java jar cf test.jar classes diff --git a/doc/generated/examples/java_jar2_1.xml b/doc/generated/examples/java_jar2_1.xml index c696fbd..9e942e2 100644 --- a/doc/generated/examples/java_jar2_1.xml +++ b/doc/generated/examples/java_jar2_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q javac -d classes -sourcepath prog1 prog1/Example1.java prog1/Example2.java javac -d classes -sourcepath prog2 prog2/Example3.java prog2/Example4.java jar cf prog1.jar -C classes Example1.class -C classes Example2.class diff --git a/doc/generated/examples/java_java-classes_1.xml b/doc/generated/examples/java_java-classes_1.xml index ce3c9ef..6f02f5f 100644 --- a/doc/generated/examples/java_java-classes_1.xml +++ b/doc/generated/examples/java_java-classes_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q javac -d classes -sourcepath src src/Example1.java src/Example2.java src/Example3.java % scons -Q classes scons: `classes' is up to date. diff --git a/doc/generated/examples/java_java-classes_2.xml b/doc/generated/examples/java_java-classes_2.xml index b773402..31f6028 100644 --- a/doc/generated/examples/java_java-classes_2.xml +++ b/doc/generated/examples/java_java-classes_2.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q javac -d classes -sourcepath src src/Example1.java src/Example2.java src/Example3.java % scons -Q -c classes Removed classes/Example1.class diff --git a/doc/generated/examples/java_java_1.xml b/doc/generated/examples/java_java_1.xml index 13078eb..551a5d4 100644 --- a/doc/generated/examples/java_java_1.xml +++ b/doc/generated/examples/java_java_1.xml @@ -1,3 +1,4 @@ -% scons -Q + +% scons -Q javac -d classes -sourcepath src src/Example1.java src/Example2.java src/Example3.java diff --git a/doc/generated/examples/java_javah_1.xml b/doc/generated/examples/java_javah_1.xml index 75e5f95..5e0709a 100644 --- a/doc/generated/examples/java_javah_1.xml +++ b/doc/generated/examples/java_javah_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q javac -d classes -sourcepath src/pkg/sub src/pkg/sub/Example1.java src/pkg/sub/Example2.java src/pkg/sub/Example3.java javah -d native -classpath classes pkg.sub.Example1 pkg.sub.Example2 pkg.sub.Example3 diff --git a/doc/generated/examples/java_javah_file_1.xml b/doc/generated/examples/java_javah_file_1.xml index 018a964..163a53d 100644 --- a/doc/generated/examples/java_javah_file_1.xml +++ b/doc/generated/examples/java_javah_file_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q javac -d classes -sourcepath src/pkg/sub src/pkg/sub/Example1.java src/pkg/sub/Example2.java src/pkg/sub/Example3.java javah -o native.h -classpath classes pkg.sub.Example1 pkg.sub.Example2 pkg.sub.Example3 diff --git a/doc/generated/examples/lesssimple_ex2_1.xml b/doc/generated/examples/lesssimple_ex2_1.xml index d643101..6093f0c 100644 --- a/doc/generated/examples/lesssimple_ex2_1.xml +++ b/doc/generated/examples/lesssimple_ex2_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o file1.o -c file1.c cc -o file2.o -c file2.c cc -o prog.o -c prog.c diff --git a/doc/generated/examples/lesssimple_ex3_1.xml b/doc/generated/examples/lesssimple_ex3_1.xml index 5ff2046..b3ac2f0 100644 --- a/doc/generated/examples/lesssimple_ex3_1.xml +++ b/doc/generated/examples/lesssimple_ex3_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o file1.o -c file1.c cc -o file2.o -c file2.c cc -o prog.o -c prog.c diff --git a/doc/generated/examples/lesssimple_ex3_2.xml b/doc/generated/examples/lesssimple_ex3_2.xml index 753bf7f..835f048 100644 --- a/doc/generated/examples/lesssimple_ex3_2.xml +++ b/doc/generated/examples/lesssimple_ex3_2.xml @@ -1,4 +1,5 @@ -C:\>scons -Q + +C:\>scons -Q cl /Fofile1.obj /c file1.c /nologo cl /Fofile2.obj /c file2.c /nologo cl /Foprog.obj /c prog.c /nologo diff --git a/doc/generated/examples/lesssimple_ex4_1.xml b/doc/generated/examples/lesssimple_ex4_1.xml index 26d6167..87af41d 100644 --- a/doc/generated/examples/lesssimple_ex4_1.xml +++ b/doc/generated/examples/lesssimple_ex4_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o bar1.o -c bar1.c cc -o bar2.o -c bar2.c cc -o bar bar1.o bar2.o diff --git a/doc/generated/examples/lesssimple_ex5_1.xml b/doc/generated/examples/lesssimple_ex5_1.xml index ea9e0e5..0043e11 100644 --- a/doc/generated/examples/lesssimple_ex5_1.xml +++ b/doc/generated/examples/lesssimple_ex5_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o bar1.o -c bar1.c cc -o bar2.o -c bar2.c cc -o common1.o -c common1.c diff --git a/doc/generated/examples/lesssimple_target_1.xml b/doc/generated/examples/lesssimple_target_1.xml index 6280522..a958acb 100644 --- a/doc/generated/examples/lesssimple_target_1.xml +++ b/doc/generated/examples/lesssimple_target_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o hello.o -c hello.c cc -o new_hello hello.o diff --git a/doc/generated/examples/lesssimple_target_2.xml b/doc/generated/examples/lesssimple_target_2.xml index a438d35..ef7b241 100644 --- a/doc/generated/examples/lesssimple_target_2.xml +++ b/doc/generated/examples/lesssimple_target_2.xml @@ -1,4 +1,5 @@ -C:\>scons -Q + +C:\>scons -Q cl /Fohello.obj /c hello.c /nologo link /nologo /OUT:new_hello.exe hello.obj embedManifestExeCheck(target, source, env) diff --git a/doc/generated/examples/libraries_SharedLibrary_1.xml b/doc/generated/examples/libraries_SharedLibrary_1.xml index ed11d19..2300891 100644 --- a/doc/generated/examples/libraries_SharedLibrary_1.xml +++ b/doc/generated/examples/libraries_SharedLibrary_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o f1.os -c f1.c cc -o f2.os -c f2.c cc -o f3.os -c f3.c diff --git a/doc/generated/examples/libraries_SharedLibrary_2.xml b/doc/generated/examples/libraries_SharedLibrary_2.xml index 7b752d7..b6b484d 100644 --- a/doc/generated/examples/libraries_SharedLibrary_2.xml +++ b/doc/generated/examples/libraries_SharedLibrary_2.xml @@ -1,4 +1,5 @@ -C:\>scons -Q + +C:\>scons -Q cl /Fof1.obj /c f1.c /nologo cl /Fof2.obj /c f2.c /nologo cl /Fof3.obj /c f3.c /nologo diff --git a/doc/generated/examples/libraries_ex1_1.xml b/doc/generated/examples/libraries_ex1_1.xml index 4a14b5b..bfd69b4 100644 --- a/doc/generated/examples/libraries_ex1_1.xml +++ b/doc/generated/examples/libraries_ex1_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o f1.o -c f1.c cc -o f2.o -c f2.c cc -o f3.o -c f3.c diff --git a/doc/generated/examples/libraries_ex1_2.xml b/doc/generated/examples/libraries_ex1_2.xml index 75c4186..912e7ad 100644 --- a/doc/generated/examples/libraries_ex1_2.xml +++ b/doc/generated/examples/libraries_ex1_2.xml @@ -1,4 +1,5 @@ -C:\>scons -Q + +C:\>scons -Q cl /Fof1.obj /c f1.c /nologo cl /Fof2.obj /c f2.c /nologo cl /Fof3.obj /c f3.c /nologo diff --git a/doc/generated/examples/libraries_ex2_1.xml b/doc/generated/examples/libraries_ex2_1.xml index c59edf4..c43f7e9 100644 --- a/doc/generated/examples/libraries_ex2_1.xml +++ b/doc/generated/examples/libraries_ex2_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o f1.o -c f1.c cc -o f2.o -c f2.c cc -o f3.o -c f3.c diff --git a/doc/generated/examples/libraries_ex2_2.xml b/doc/generated/examples/libraries_ex2_2.xml index f590dc8..84b4d75 100644 --- a/doc/generated/examples/libraries_ex2_2.xml +++ b/doc/generated/examples/libraries_ex2_2.xml @@ -1,4 +1,5 @@ -C:\>scons -Q + +C:\>scons -Q cl /Fof1.obj /c f1.c /nologo cl /Fof2.obj /c f2.c /nologo cl /Fof3.obj /c f3.c /nologo diff --git a/doc/generated/examples/libraries_ex3_1.xml b/doc/generated/examples/libraries_ex3_1.xml index f5fd4c8..9dd6ca9 100644 --- a/doc/generated/examples/libraries_ex3_1.xml +++ b/doc/generated/examples/libraries_ex3_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o prog.o -c prog.c cc -o prog prog.o -L/usr/lib -L/usr/local/lib -lm diff --git a/doc/generated/examples/libraries_ex3_2.xml b/doc/generated/examples/libraries_ex3_2.xml index 433f7fb..e5ec4ce 100644 --- a/doc/generated/examples/libraries_ex3_2.xml +++ b/doc/generated/examples/libraries_ex3_2.xml @@ -1,4 +1,5 @@ -C:\>scons -Q + +C:\>scons -Q cl /Foprog.obj /c prog.c /nologo link /nologo /OUT:prog.exe /LIBPATH:\usr\lib /LIBPATH:\usr\local\lib m.lib prog.obj embedManifestExeCheck(target, source, env) diff --git a/doc/generated/examples/libraries_objects_1.xml b/doc/generated/examples/libraries_objects_1.xml index db5d88c..5d732da 100644 --- a/doc/generated/examples/libraries_objects_1.xml +++ b/doc/generated/examples/libraries_objects_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o f1.o -c f1.c cc -o f3.o -c f3.c ar rc libfoo.a f1.o f2.o f3.o f4.o diff --git a/doc/generated/examples/mergeflags_MergeFlags1_1.xml b/doc/generated/examples/mergeflags_MergeFlags1_1.xml index fafefd4..8f18fd8 100644 --- a/doc/generated/examples/mergeflags_MergeFlags1_1.xml +++ b/doc/generated/examples/mergeflags_MergeFlags1_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q ['-option', '-O1', '-whatever', '-O3'] scons: `.' is up to date. diff --git a/doc/generated/examples/mergeflags_MergeFlags2_1.xml b/doc/generated/examples/mergeflags_MergeFlags2_1.xml index 017158a..8cae827 100644 --- a/doc/generated/examples/mergeflags_MergeFlags2_1.xml +++ b/doc/generated/examples/mergeflags_MergeFlags2_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q ['/include', '/usr/local/include', '/usr/include', '/usr/opt/include'] scons: `.' is up to date. diff --git a/doc/generated/examples/mergeflags_MergeFlags3_1.xml b/doc/generated/examples/mergeflags_MergeFlags3_1.xml index 2173cf3..d4f23d4 100644 --- a/doc/generated/examples/mergeflags_MergeFlags3_1.xml +++ b/doc/generated/examples/mergeflags_MergeFlags3_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q ['-option', '-O1', '-whatever', '-O3'] ['/include', '/usr/local/include', '/usr/include', '/usr/opt/include'] scons: `.' is up to date. diff --git a/doc/generated/examples/misc_Exit_1.xml b/doc/generated/examples/misc_Exit_1.xml index 5a5e411..6af378f 100644 --- a/doc/generated/examples/misc_Exit_1.xml +++ b/doc/generated/examples/misc_Exit_1.xml @@ -1,4 +1,5 @@ -% scons -Q FUTURE=1 + +% scons -Q FUTURE=1 The FUTURE option is not supported yet! % scons -Q cc -o hello.o -c hello.c diff --git a/doc/generated/examples/misc_FindFile1a_1.xml b/doc/generated/examples/misc_FindFile1a_1.xml index efa6b7c..eca0328 100644 --- a/doc/generated/examples/misc_FindFile1a_1.xml +++ b/doc/generated/examples/misc_FindFile1a_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q None <class 'SCons.Node.FS.File'> exists scons: `.' is up to date. diff --git a/doc/generated/examples/misc_FindFile1b_1.xml b/doc/generated/examples/misc_FindFile1b_1.xml index 2ab6acb..4b194ce 100644 --- a/doc/generated/examples/misc_FindFile1b_1.xml +++ b/doc/generated/examples/misc_FindFile1b_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q nonesuch.h : None config.h : config.h private.h : src/include/private.h diff --git a/doc/generated/examples/misc_FindFile1d_1.xml b/doc/generated/examples/misc_FindFile1d_1.xml index 3312c42..5ab499f 100644 --- a/doc/generated/examples/misc_FindFile1d_1.xml +++ b/doc/generated/examples/misc_FindFile1d_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q sub1/multiple sub2/multiple sub3/multiple diff --git a/doc/generated/examples/misc_FindFile2_1.xml b/doc/generated/examples/misc_FindFile2_1.xml index 7302968..149c5d5 100644 --- a/doc/generated/examples/misc_FindFile2_1.xml +++ b/doc/generated/examples/misc_FindFile2_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q leaf derived cat > derived leaf diff --git a/doc/generated/examples/misc_FindFile2_2.xml b/doc/generated/examples/misc_FindFile2_2.xml index 7302968..149c5d5 100644 --- a/doc/generated/examples/misc_FindFile2_2.xml +++ b/doc/generated/examples/misc_FindFile2_2.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q leaf derived cat > derived leaf diff --git a/doc/generated/examples/misc_FindFile3_1.xml b/doc/generated/examples/misc_FindFile3_1.xml index 69cfacf..2c09fed 100644 --- a/doc/generated/examples/misc_FindFile3_1.xml +++ b/doc/generated/examples/misc_FindFile3_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q build/leaf scons: `.' is up to date. diff --git a/doc/generated/examples/misc_Flatten1_1.xml b/doc/generated/examples/misc_Flatten1_1.xml index db574ed..54720bb 100644 --- a/doc/generated/examples/misc_Flatten1_1.xml +++ b/doc/generated/examples/misc_Flatten1_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o prog1.o -c prog1.c cc -o prog2.o -c -DFOO prog2.c cc -o prog1 prog1.o prog2.o diff --git a/doc/generated/examples/misc_Flatten2_1.xml b/doc/generated/examples/misc_Flatten2_1.xml index 06b99c3..66161ec 100644 --- a/doc/generated/examples/misc_Flatten2_1.xml +++ b/doc/generated/examples/misc_Flatten2_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q AttributeError: 'NodeList' object has no attribute 'abspath': File "/home/my/project/SConstruct", line 8: print(object_file.abspath) diff --git a/doc/generated/examples/nodes_GetBuildPath_1.xml b/doc/generated/examples/nodes_GetBuildPath_1.xml index 50543ab..376f65e 100644 --- a/doc/generated/examples/nodes_GetBuildPath_1.xml +++ b/doc/generated/examples/nodes_GetBuildPath_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q ['foo.c', 'sub/dir/value'] scons: `.' is up to date. diff --git a/doc/generated/examples/nodes_ex1_1.xml b/doc/generated/examples/nodes_ex1_1.xml index f05281f..e7eb8c4 100644 --- a/doc/generated/examples/nodes_ex1_1.xml +++ b/doc/generated/examples/nodes_ex1_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o goodbye.o -c -DGOODBYE goodbye.c cc -o hello.o -c -DHELLO hello.c cc -o hello hello.o goodbye.o diff --git a/doc/generated/examples/nodes_ex1_2.xml b/doc/generated/examples/nodes_ex1_2.xml index 3648775..a1ed1fb 100644 --- a/doc/generated/examples/nodes_ex1_2.xml +++ b/doc/generated/examples/nodes_ex1_2.xml @@ -1,4 +1,5 @@ -C:\>scons -Q + +C:\>scons -Q cl /Fogoodbye.obj /c goodbye.c -DGOODBYE cl /Fohello.obj /c hello.c -DHELLO link /nologo /OUT:hello.exe hello.obj goodbye.obj diff --git a/doc/generated/examples/nodes_exists_1.xml b/doc/generated/examples/nodes_exists_1.xml index f9abc43..a290b1c 100644 --- a/doc/generated/examples/nodes_exists_1.xml +++ b/doc/generated/examples/nodes_exists_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q hello does not exist! cc -o hello.o -c hello.c cc -o hello hello.o diff --git a/doc/generated/examples/nodes_print_1.xml b/doc/generated/examples/nodes_print_1.xml index 0d07e97..11a3f45 100644 --- a/doc/generated/examples/nodes_print_1.xml +++ b/doc/generated/examples/nodes_print_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q The object file is: hello.o The program file is: hello cc -o hello.o -c hello.c diff --git a/doc/generated/examples/nodes_print_2.xml b/doc/generated/examples/nodes_print_2.xml index 3c66573..a62b522 100644 --- a/doc/generated/examples/nodes_print_2.xml +++ b/doc/generated/examples/nodes_print_2.xml @@ -1,4 +1,5 @@ -C:\>scons -Q + +C:\>scons -Q The object file is: hello.obj The program file is: hello.exe cl /Fohello.obj /c hello.c /nologo diff --git a/doc/generated/examples/output_Progress-TARGET_1.xml b/doc/generated/examples/output_Progress-TARGET_1.xml index 3408cdc..b233c6e 100644 --- a/doc/generated/examples/output_Progress-TARGET_1.xml +++ b/doc/generated/examples/output_Progress-TARGET_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q Evaluating SConstruct Evaluating f1.c Evaluating f1.o diff --git a/doc/generated/examples/output_ex1_1.xml b/doc/generated/examples/output_ex1_1.xml index bff25da..535960b 100644 --- a/doc/generated/examples/output_ex1_1.xml +++ b/doc/generated/examples/output_ex1_1.xml @@ -1,4 +1,5 @@ -% scons -h + +% scons -h scons: Reading SConscript files ... scons: done reading SConscript files. diff --git a/doc/generated/examples/output_ex2_1.xml b/doc/generated/examples/output_ex2_1.xml index 5d02707..e951c3a 100644 --- a/doc/generated/examples/output_ex2_1.xml +++ b/doc/generated/examples/output_ex2_1.xml @@ -1,4 +1,5 @@ -C:\>scons -h + +C:\>scons -h scons: Reading SConscript files ... scons: done reading SConscript files. diff --git a/doc/generated/examples/output_ex2_2.xml b/doc/generated/examples/output_ex2_2.xml index 5a25472..8dca6c3 100644 --- a/doc/generated/examples/output_ex2_2.xml +++ b/doc/generated/examples/output_ex2_2.xml @@ -1,4 +1,5 @@ -% scons -h + +% scons -h scons: Reading SConscript files ... scons: done reading SConscript files. diff --git a/doc/generated/examples/output_gbf2_1.xml b/doc/generated/examples/output_gbf2_1.xml index 267035e..c31b41a 100644 --- a/doc/generated/examples/output_gbf2_1.xml +++ b/doc/generated/examples/output_gbf2_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q scons: `.' is up to date. Build succeeded. % scons -Q fail=1 diff --git a/doc/generated/examples/parseflags_ex1_1.xml b/doc/generated/examples/parseflags_ex1_1.xml index bfa731f..d6e4d96 100644 --- a/doc/generated/examples/parseflags_ex1_1.xml +++ b/doc/generated/examples/parseflags_ex1_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q CPPPATH ['/opt/include'] LIBPATH ['/opt/lib'] LIBS ['foo'] diff --git a/doc/generated/examples/parseflags_ex1_2.xml b/doc/generated/examples/parseflags_ex1_2.xml index d9f00a5..4c115d0 100644 --- a/doc/generated/examples/parseflags_ex1_2.xml +++ b/doc/generated/examples/parseflags_ex1_2.xml @@ -1,4 +1,5 @@ -C:\>scons -Q + +C:\>scons -Q CPPPATH ['/opt/include'] LIBPATH ['/opt/lib'] LIBS ['foo'] diff --git a/doc/generated/examples/parseflags_ex2_1.xml b/doc/generated/examples/parseflags_ex2_1.xml index 0a35925..da84ee3 100644 --- a/doc/generated/examples/parseflags_ex2_1.xml +++ b/doc/generated/examples/parseflags_ex2_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q CCFLAGS -whatever cc -o f1.o -c -whatever f1.c cc -o f1 f1.o diff --git a/doc/generated/examples/parseflags_ex3_1.xml b/doc/generated/examples/parseflags_ex3_1.xml index bfa731f..d6e4d96 100644 --- a/doc/generated/examples/parseflags_ex3_1.xml +++ b/doc/generated/examples/parseflags_ex3_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q CPPPATH ['/opt/include'] LIBPATH ['/opt/lib'] LIBS ['foo'] diff --git a/doc/generated/examples/parseflags_ex4_1.xml b/doc/generated/examples/parseflags_ex4_1.xml index bfa731f..d6e4d96 100644 --- a/doc/generated/examples/parseflags_ex4_1.xml +++ b/doc/generated/examples/parseflags_ex4_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q CPPPATH ['/opt/include'] LIBPATH ['/opt/lib'] LIBS ['foo'] diff --git a/doc/generated/examples/repositories_CPPPATH3_1.xml b/doc/generated/examples/repositories_CPPPATH3_1.xml index f983d96..d53ffdb 100644 --- a/doc/generated/examples/repositories_CPPPATH3_1.xml +++ b/doc/generated/examples/repositories_CPPPATH3_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o hello.o -c -Idir1 -I/r1/dir1 -I/r2/dir1 -Idir2 -I/r1/dir2 -I/r2/dir2 -Idir3 -I/r1/dir3 -I/r2/dir3 hello.c cc -o hello hello.o diff --git a/doc/generated/examples/repositories_CPPPATH_1.xml b/doc/generated/examples/repositories_CPPPATH_1.xml index 30b5d75..6c5a2d1 100644 --- a/doc/generated/examples/repositories_CPPPATH_1.xml +++ b/doc/generated/examples/repositories_CPPPATH_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o hello.o -c -I. -I/usr/repository1 hello.c cc -o hello hello.o diff --git a/doc/generated/examples/repositories_ex1_1.xml b/doc/generated/examples/repositories_ex1_1.xml index efc6d5a..a21fdc8 100644 --- a/doc/generated/examples/repositories_ex1_1.xml +++ b/doc/generated/examples/repositories_ex1_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o hello.o -c hello.c cc -o hello hello.o diff --git a/doc/generated/examples/repositories_ex2_1.xml b/doc/generated/examples/repositories_ex2_1.xml index e773a8d..819c936 100644 --- a/doc/generated/examples/repositories_ex2_1.xml +++ b/doc/generated/examples/repositories_ex2_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o hello.o -c /usr/repository1/hello.c cc -o hello hello.o diff --git a/doc/generated/examples/repositories_ex3_1.xml b/doc/generated/examples/repositories_ex3_1.xml index c437bb7..76d69cd 100644 --- a/doc/generated/examples/repositories_ex3_1.xml +++ b/doc/generated/examples/repositories_ex3_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o hello.o -c /usr/repository2/hello.c cc -o hello hello.o diff --git a/doc/generated/examples/repositories_ex4_1.xml b/doc/generated/examples/repositories_ex4_1.xml index 47d9923..8911683 100644 --- a/doc/generated/examples/repositories_ex4_1.xml +++ b/doc/generated/examples/repositories_ex4_1.xml @@ -1,4 +1,5 @@ -% cd /usr/repository1 + +% cd /usr/repository1 % scons -Q cc -o file1.o -c file1.c cc -o file2.o -c file2.c diff --git a/doc/generated/examples/repositories_quote1_1.xml b/doc/generated/examples/repositories_quote1_1.xml index c503900..d2ba624 100644 --- a/doc/generated/examples/repositories_quote1_1.xml +++ b/doc/generated/examples/repositories_quote1_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o hello.o -c -I. -I/usr/repository1 /usr/repository1/hello.c cc -o hello hello.o diff --git a/doc/generated/examples/separate_builddir_1.xml b/doc/generated/examples/separate_builddir_1.xml index 36d4383..a763172 100644 --- a/doc/generated/examples/separate_builddir_1.xml +++ b/doc/generated/examples/separate_builddir_1.xml @@ -1,4 +1,5 @@ -% ls src + +% ls src hello.c % scons -Q cc -o build/hello.o -c build/hello.c diff --git a/doc/generated/examples/separate_builddir_sconscript_1.xml b/doc/generated/examples/separate_builddir_sconscript_1.xml index d719829..5694a56 100644 --- a/doc/generated/examples/separate_builddir_sconscript_1.xml +++ b/doc/generated/examples/separate_builddir_sconscript_1.xml @@ -1,4 +1,5 @@ -% ls src + +% ls src SConscript hello.c % scons -Q cc -o build/hello.o -c build/hello.c diff --git a/doc/generated/examples/separate_duplicate0_1.xml b/doc/generated/examples/separate_duplicate0_1.xml index 3c8b642..207c5d7 100644 --- a/doc/generated/examples/separate_duplicate0_1.xml +++ b/doc/generated/examples/separate_duplicate0_1.xml @@ -1,4 +1,5 @@ -% ls src + +% ls src hello.c % scons -Q cc -o build/hello.o -c src/hello.c diff --git a/doc/generated/examples/separate_ex1_1.xml b/doc/generated/examples/separate_ex1_1.xml index d719829..5694a56 100644 --- a/doc/generated/examples/separate_ex1_1.xml +++ b/doc/generated/examples/separate_ex1_1.xml @@ -1,4 +1,5 @@ -% ls src + +% ls src SConscript hello.c % scons -Q cc -o build/hello.o -c build/hello.c diff --git a/doc/generated/examples/separate_glob_builddir_sconscript_1.xml b/doc/generated/examples/separate_glob_builddir_sconscript_1.xml index 4ff49d5..7cdb420 100644 --- a/doc/generated/examples/separate_glob_builddir_sconscript_1.xml +++ b/doc/generated/examples/separate_glob_builddir_sconscript_1.xml @@ -1,4 +1,5 @@ -% ls src + +% ls src SConscript f1.c f2.c f2.h % scons -Q cc -o build/f1.o -c build/f1.c diff --git a/doc/generated/examples/sideeffect_parallel_1.xml b/doc/generated/examples/sideeffect_parallel_1.xml index 0152803..9478c52 100644 --- a/doc/generated/examples/sideeffect_parallel_1.xml +++ b/doc/generated/examples/sideeffect_parallel_1.xml @@ -1,4 +1,5 @@ -% scons -Q --jobs=2 + +% scons -Q --jobs=2 echo > file1.out data1 echo > file2.out data2 diff --git a/doc/generated/examples/sideeffect_shared_1.xml b/doc/generated/examples/sideeffect_shared_1.xml index 355578a..2abb806 100644 --- a/doc/generated/examples/sideeffect_shared_1.xml +++ b/doc/generated/examples/sideeffect_shared_1.xml @@ -1,4 +1,5 @@ -% scons -Q --jobs=2 + +% scons -Q --jobs=2 ./build --log logfile.txt file1.in file1.out ./build --log logfile.txt file2.in file2.out diff --git a/doc/generated/examples/sideeffect_simple_1.xml b/doc/generated/examples/sideeffect_simple_1.xml index ed97594..e88630c 100644 --- a/doc/generated/examples/sideeffect_simple_1.xml +++ b/doc/generated/examples/sideeffect_simple_1.xml @@ -1,4 +1,5 @@ -% scons -Q --jobs=2 + +% scons -Q --jobs=2 File "/home/my/project/SConstruct", line 4 'echo >$TARGET data1; echo >log updated file1')) diff --git a/doc/generated/examples/simple_Object_1.xml b/doc/generated/examples/simple_Object_1.xml index 0dfb85a..6d5c80d 100644 --- a/doc/generated/examples/simple_Object_1.xml +++ b/doc/generated/examples/simple_Object_1.xml @@ -1,4 +1,5 @@ -% scons + +% scons scons: Reading SConscript files ... scons: done reading SConscript files. scons: Building targets ... diff --git a/doc/generated/examples/simple_Object_2.xml b/doc/generated/examples/simple_Object_2.xml index b7dea0c..3686006 100644 --- a/doc/generated/examples/simple_Object_2.xml +++ b/doc/generated/examples/simple_Object_2.xml @@ -1,4 +1,5 @@ -C:\>scons + +C:\>scons scons: Reading SConscript files ... scons: done reading SConscript files. scons: Building targets ... diff --git a/doc/generated/examples/simple_clean_1.xml b/doc/generated/examples/simple_clean_1.xml index c15ec25..21adbe7 100644 --- a/doc/generated/examples/simple_clean_1.xml +++ b/doc/generated/examples/simple_clean_1.xml @@ -1,4 +1,5 @@ -% scons + +% scons scons: Reading SConscript files ... scons: done reading SConscript files. scons: Building targets ... diff --git a/doc/generated/examples/simple_clean_2.xml b/doc/generated/examples/simple_clean_2.xml index 7e3d564..26f3c37 100644 --- a/doc/generated/examples/simple_clean_2.xml +++ b/doc/generated/examples/simple_clean_2.xml @@ -1,4 +1,5 @@ -C:\>scons + +C:\>scons scons: Reading SConscript files ... scons: done reading SConscript files. scons: Building targets ... diff --git a/doc/generated/examples/simple_declarative_1.xml b/doc/generated/examples/simple_declarative_1.xml index da29097..01061cf 100644 --- a/doc/generated/examples/simple_declarative_1.xml +++ b/doc/generated/examples/simple_declarative_1.xml @@ -1,4 +1,5 @@ -% scons + +% scons scons: Reading SConscript files ... Calling Program('hello.c') Calling Program('goodbye.c') diff --git a/doc/generated/examples/simple_ex1_1.xml b/doc/generated/examples/simple_ex1_1.xml index f645a2a..5833ede 100644 --- a/doc/generated/examples/simple_ex1_1.xml +++ b/doc/generated/examples/simple_ex1_1.xml @@ -1,4 +1,5 @@ -% scons + +% scons scons: Reading SConscript files ... scons: done reading SConscript files. scons: Building targets ... diff --git a/doc/generated/examples/simple_ex1_2.xml b/doc/generated/examples/simple_ex1_2.xml index 518b437..f0e07a1 100644 --- a/doc/generated/examples/simple_ex1_2.xml +++ b/doc/generated/examples/simple_ex1_2.xml @@ -1,4 +1,5 @@ -C:\>scons + +C:\>scons scons: Reading SConscript files ... scons: done reading SConscript files. scons: Building targets ... diff --git a/doc/generated/examples/simple_ex1_3.xml b/doc/generated/examples/simple_ex1_3.xml index 518b437..f0e07a1 100644 --- a/doc/generated/examples/simple_ex1_3.xml +++ b/doc/generated/examples/simple_ex1_3.xml @@ -1,4 +1,5 @@ -C:\>scons + +C:\>scons scons: Reading SConscript files ... scons: done reading SConscript files. scons: Building targets ... diff --git a/doc/generated/examples/simple_ex1_4.xml b/doc/generated/examples/simple_ex1_4.xml index eb10a06..80c7b63 100644 --- a/doc/generated/examples/simple_ex1_4.xml +++ b/doc/generated/examples/simple_ex1_4.xml @@ -1,4 +1,5 @@ -C:\>scons -Q + +C:\>scons -Q cl /Fohello.obj /c hello.c /nologo link /nologo /OUT:hello.exe hello.obj embedManifestExeCheck(target, source, env) diff --git a/doc/generated/examples/simple_java_1.xml b/doc/generated/examples/simple_java_1.xml index decf1b5..75cc6cc 100644 --- a/doc/generated/examples/simple_java_1.xml +++ b/doc/generated/examples/simple_java_1.xml @@ -1,4 +1,5 @@ -% scons + +% scons scons: Reading SConscript files ... scons: done reading SConscript files. scons: Building targets ... diff --git a/doc/generated/examples/sourcecode_bitkeeper_1.xml b/doc/generated/examples/sourcecode_bitkeeper_1.xml index 6ff49fb..41af3a2 100644 --- a/doc/generated/examples/sourcecode_bitkeeper_1.xml +++ b/doc/generated/examples/sourcecode_bitkeeper_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q AttributeError: 'SConsEnvironment' object has no attribute 'BitKeeper': File "/home/my/project/SConstruct", line 2: env.SourceCode('.', env.BitKeeper()) diff --git a/doc/generated/examples/sourcecode_cvs_1.xml b/doc/generated/examples/sourcecode_cvs_1.xml index f813346..01ddb6b 100644 --- a/doc/generated/examples/sourcecode_cvs_1.xml +++ b/doc/generated/examples/sourcecode_cvs_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q AttributeError: 'SConsEnvironment' object has no attribute 'CVS': File "/home/my/project/SConstruct", line 2: env.SourceCode('.', env.CVS('/usr/local/CVS')) diff --git a/doc/generated/examples/sourcecode_rcs_1.xml b/doc/generated/examples/sourcecode_rcs_1.xml index 0a84b0a..e6b36dd 100644 --- a/doc/generated/examples/sourcecode_rcs_1.xml +++ b/doc/generated/examples/sourcecode_rcs_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q AttributeError: 'SConsEnvironment' object has no attribute 'RCS': File "/home/my/project/SConstruct", line 2: env.SourceCode('.', env.RCS()) diff --git a/doc/generated/examples/sourcecode_sccs_1.xml b/doc/generated/examples/sourcecode_sccs_1.xml index a1bad0d..e0699d1 100644 --- a/doc/generated/examples/sourcecode_sccs_1.xml +++ b/doc/generated/examples/sourcecode_sccs_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q AttributeError: 'SConsEnvironment' object has no attribute 'SCCS': File "/home/my/project/SConstruct", line 2: env.SourceCode('.', env.SCCS()) diff --git a/doc/generated/examples/tasks_ex1_1.xml b/doc/generated/examples/tasks_ex1_1.xml index 0bbbae1..4885fde 100644 --- a/doc/generated/examples/tasks_ex1_1.xml +++ b/doc/generated/examples/tasks_ex1_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cat < test.bar > test.h cc -o app main.cpp cat < foo.bar2 > foo.cpp diff --git a/doc/generated/examples/troubleshoot_Dump_1.xml b/doc/generated/examples/troubleshoot_Dump_1.xml index 513babe..1f6f250 100644 --- a/doc/generated/examples/troubleshoot_Dump_1.xml +++ b/doc/generated/examples/troubleshoot_Dump_1.xml @@ -1,8 +1,7 @@ -% scons + +% scons scons: Reading SConscript files ... -{ 'BUILDERS': { '_InternalInstall': <function InstallBuilderWrapper at 0x700000>, - '_InternalInstallAs': <function InstallAsBuilderWrapper at 0x700000>, - '_InternalInstallVersionedLib': <function InstallVersionedBuilderWrapper at 0x700000>}, +{ 'BUILDERS': {'_InternalInstall': <function InstallBuilderWrapper at 0x700000>, '_InternalInstallVersionedLib': <function InstallVersionedBuilderWrapper at 0x700000>, '_InternalInstallAs': <function InstallAsBuilderWrapper at 0x700000>}, 'CONFIGUREDIR': '#/.sconf_temp', 'CONFIGURELOG': '#/config.log', 'CPPSUFFIXES': [ '.c', @@ -28,7 +27,7 @@ scons: Reading SConscript files ... 'DSUFFIXES': ['.d'], 'Dir': <SCons.Defaults.Variable_Method_Caller object at 0x700000>, 'Dirs': <SCons.Defaults.Variable_Method_Caller object at 0x700000>, - 'ENV': {'PATH': '/usr/local/bin:/opt/bin:/bin:/usr/bin'}, + 'ENV': { 'PATH': '/usr/local/bin:/opt/bin:/bin:/usr/bin'}, 'ESCAPE': <function escape at 0x700000>, 'File': <SCons.Defaults.Variable_Method_Caller object at 0x700000>, 'HOST_ARCH': None, @@ -61,12 +60,9 @@ scons: Reading SConscript files ... 'TEMPFILEARGJOIN': ' ', 'TEMPFILEPREFIX': '@', 'TOOLS': ['install', 'install'], - '_CPPDEFFLAGS': '${_defines(CPPDEFPREFIX, CPPDEFINES, CPPDEFSUFFIX, ' - '__env__)}', - '_CPPINCFLAGS': '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs, ' - 'TARGET, SOURCE)} $)', - '_LIBDIRFLAGS': '$( ${_concat(LIBDIRPREFIX, LIBPATH, LIBDIRSUFFIX, __env__, ' - 'RDirs, TARGET, SOURCE)} $)', + '_CPPDEFFLAGS': '${_defines(CPPDEFPREFIX, CPPDEFINES, CPPDEFSUFFIX, __env__)}', + '_CPPINCFLAGS': '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)', + '_LIBDIRFLAGS': '$( ${_concat(LIBDIRPREFIX, LIBPATH, LIBDIRSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)', '_LIBFLAGS': '${_concat(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, __env__)}', '__DRPATH': '$_DRPATH', '__DSHLIBVERSIONFLAGS': '${__libversionflags(__env__,"DSHLIBVERSION","_DSHLIBVERSIONFLAGS")}', diff --git a/doc/generated/examples/troubleshoot_Dump_2.xml b/doc/generated/examples/troubleshoot_Dump_2.xml index 39cf4f6..4b8aa0b 100644 --- a/doc/generated/examples/troubleshoot_Dump_2.xml +++ b/doc/generated/examples/troubleshoot_Dump_2.xml @@ -1,18 +1,11 @@ -C:\>scons + +C:\>scons scons: Reading SConscript files ... -{ 'BUILDERS': { 'Object': <SCons.Builder.CompositeBuilder object at 0x700000>, - 'PCH': <SCons.Builder.BuilderBase object at 0x700000>, - 'RES': <SCons.Builder.BuilderBase object at 0x700000>, - 'SharedObject': <SCons.Builder.CompositeBuilder object at 0x700000>, - 'StaticObject': <SCons.Builder.CompositeBuilder object at 0x700000>, - '_InternalInstall': <function InstallBuilderWrapper at 0x700000>, - '_InternalInstallAs': <function InstallAsBuilderWrapper at 0x700000>, - '_InternalInstallVersionedLib': <function InstallVersionedBuilderWrapper at 0x700000>}, +{ 'BUILDERS': {'_InternalInstallVersionedLib': <function InstallVersionedBuilderWrapper at 0x700000>, '_InternalInstall': <function InstallBuilderWrapper at 0x700000>, 'Object': <SCons.Builder.CompositeBuilder object at 0x700000>, 'PCH': <SCons.Builder.BuilderBase object at 0x700000>, 'RES': <SCons.Builder.BuilderBase object at 0x700000>, 'SharedObject': <SCons.Builder.CompositeBuilder object at 0x700000>, 'StaticObject': <SCons.Builder.CompositeBuilder object at 0x700000>, '_InternalInstallAs': <function InstallAsBuilderWrapper at 0x700000>}, 'CC': 'cl', 'CCCOM': <SCons.Action.FunctionAction object at 0x700000>, 'CCFLAGS': ['/nologo'], - 'CCPCHFLAGS': [ '${(PCH and "/Yu%s \\"/Fp%s\\""%(PCHSTOP or "",File(PCH))) ' - 'or ""}'], + 'CCPCHFLAGS': ['${(PCH and "/Yu%s \\"/Fp%s\\""%(PCHSTOP or "",File(PCH))) or ""}'], 'CCPDBFLAGS': ['${(PDB and "/Z7") or ""}'], 'CFILESUFFIX': '.c', 'CFLAGS': [], @@ -41,8 +34,7 @@ scons: Reading SConscript files ... '.SPP', '.sx'], 'CXX': '$CC', - 'CXXCOM': '${TEMPFILE("$CXX $_MSVC_OUTPUT_FLAG /c $CHANGED_SOURCES $CXXFLAGS ' - '$CCFLAGS $_CCCOMCOM","$CXXCOMSTR")}', + 'CXXCOM': '${TEMPFILE("$CXX $_MSVC_OUTPUT_FLAG /c $CHANGED_SOURCES $CXXFLAGS $CCFLAGS $_CCCOMCOM","$CXXCOMSTR")}', 'CXXFILESUFFIX': '.cc', 'CXXFLAGS': ['$(', '/TP', '$)'], 'DSUFFIXES': ['.d'], @@ -69,9 +61,7 @@ scons: Reading SConscript files ... 'MSVC_SETUP_RUN': True, 'OBJPREFIX': '', 'OBJSUFFIX': '.obj', - 'PCHCOM': '$CXX /Fo${TARGETS[1]} $CXXFLAGS $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS ' - '$_CPPINCFLAGS /c $SOURCES /Yc$PCHSTOP /Fp${TARGETS[0]} ' - '$CCPDBFLAGS $PCHPDBFLAGS', + 'PCHCOM': '$CXX /Fo${TARGETS[1]} $CXXFLAGS $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Yc$PCHSTOP /Fp${TARGETS[0]} $CCPDBFLAGS $PCHPDBFLAGS', 'PCHPDBFLAGS': ['${(PDB and "/Yd") or ""}'], 'PLATFORM': 'win32', 'PROGPREFIX': '', @@ -88,8 +78,7 @@ scons: Reading SConscript files ... 'SHCCFLAGS': ['$CCFLAGS'], 'SHCFLAGS': ['$CFLAGS'], 'SHCXX': '$CXX', - 'SHCXXCOM': '${TEMPFILE("$SHCXX $_MSVC_OUTPUT_FLAG /c $CHANGED_SOURCES ' - '$SHCXXFLAGS $SHCCFLAGS $_CCCOMCOM","$SHCXXCOMSTR")}', + 'SHCXXCOM': '${TEMPFILE("$SHCXX $_MSVC_OUTPUT_FLAG /c $CHANGED_SOURCES $SHCXXFLAGS $SHCCFLAGS $_CCCOMCOM","$SHCXXCOMSTR")}', 'SHCXXFLAGS': ['$CXXFLAGS'], 'SHELL': None, 'SHLIBPREFIX': '', @@ -105,12 +94,9 @@ scons: Reading SConscript files ... 'TEMPFILEPREFIX': '@', 'TOOLS': ['msvc', 'install', 'install'], '_CCCOMCOM': '$CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS $CCPCHFLAGS $CCPDBFLAGS', - '_CPPDEFFLAGS': '${_defines(CPPDEFPREFIX, CPPDEFINES, CPPDEFSUFFIX, ' - '__env__)}', - '_CPPINCFLAGS': '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs, ' - 'TARGET, SOURCE)} $)', - '_LIBDIRFLAGS': '$( ${_concat(LIBDIRPREFIX, LIBPATH, LIBDIRSUFFIX, __env__, ' - 'RDirs, TARGET, SOURCE)} $)', + '_CPPDEFFLAGS': '${_defines(CPPDEFPREFIX, CPPDEFINES, CPPDEFSUFFIX, __env__)}', + '_CPPINCFLAGS': '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)', + '_LIBDIRFLAGS': '$( ${_concat(LIBDIRPREFIX, LIBPATH, LIBDIRSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)', '_LIBFLAGS': '${_concat(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, __env__)}', '_MSVC_OUTPUT_FLAG': <function msvc_output_flag at 0x700000>, '__DSHLIBVERSIONFLAGS': '${__libversionflags(__env__,"DSHLIBVERSION","_DSHLIBVERSIONFLAGS")}', diff --git a/doc/generated/examples/troubleshoot_Dump_ENV_1.xml b/doc/generated/examples/troubleshoot_Dump_ENV_1.xml index 7ed4d86..786491f 100644 --- a/doc/generated/examples/troubleshoot_Dump_ENV_1.xml +++ b/doc/generated/examples/troubleshoot_Dump_ENV_1.xml @@ -1,6 +1,7 @@ -% scons + +% scons scons: Reading SConscript files ... -{'PATH': '/usr/local/bin:/opt/bin:/bin:/usr/bin'} +{ 'PATH': '/usr/local/bin:/opt/bin:/bin:/usr/bin'} scons: done reading SConscript files. scons: Building targets ... scons: `.' is up to date. diff --git a/doc/generated/examples/troubleshoot_Dump_ENV_2.xml b/doc/generated/examples/troubleshoot_Dump_ENV_2.xml index e421f6a..b91c31c 100644 --- a/doc/generated/examples/troubleshoot_Dump_ENV_2.xml +++ b/doc/generated/examples/troubleshoot_Dump_ENV_2.xml @@ -1,4 +1,5 @@ -C:\>scons + +C:\>scons scons: Reading SConscript files ... { 'PATH': 'C:\\WINDOWS\\System32:/usr/bin', 'PATHEXT': '.COM;.EXE;.BAT;.CMD', diff --git a/doc/generated/examples/troubleshoot_explain1_1.xml b/doc/generated/examples/troubleshoot_explain1_1.xml index c73e5ac..2a9547d 100644 --- a/doc/generated/examples/troubleshoot_explain1_1.xml +++ b/doc/generated/examples/troubleshoot_explain1_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cp file.in file.oout % scons -Q cp file.in file.oout diff --git a/doc/generated/examples/troubleshoot_explain1_2.xml b/doc/generated/examples/troubleshoot_explain1_2.xml index 77eb88b..9864cd7 100644 --- a/doc/generated/examples/troubleshoot_explain1_2.xml +++ b/doc/generated/examples/troubleshoot_explain1_2.xml @@ -1,4 +1,5 @@ -% scons -Q --debug=explain + +% scons -Q --debug=explain scons: building `file.out' because it doesn't exist cp file.in file.oout diff --git a/doc/generated/examples/troubleshoot_explain1_3.xml b/doc/generated/examples/troubleshoot_explain1_3.xml index 4e7d5f8..ebc13f8 100644 --- a/doc/generated/examples/troubleshoot_explain1_3.xml +++ b/doc/generated/examples/troubleshoot_explain1_3.xml @@ -1,6 +1,7 @@ -% scons -Q --warn=target-not-built + +% scons -Q --warn=target-not-built cp file.in file.oout scons: warning: Cannot find target file.out after building -File "/Users/bdbaddog/devel/scons/git/scons/src/script/scons.py", line 204, in <module> +File "/home/bdeegan/devel/scons/git/as_scons/src/script/scons.py", line 204, in <module> diff --git a/doc/generated/examples/troubleshoot_explain2_1.xml b/doc/generated/examples/troubleshoot_explain2_1.xml index 80fefda..cd95a44 100644 --- a/doc/generated/examples/troubleshoot_explain2_1.xml +++ b/doc/generated/examples/troubleshoot_explain2_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o file1.o -c file1.c cc -o file2.o -c file2.c cc -o file3.o -c file3.c diff --git a/doc/generated/examples/troubleshoot_explain3_1.xml b/doc/generated/examples/troubleshoot_explain3_1.xml index 4fde5ac..bacb7e8 100644 --- a/doc/generated/examples/troubleshoot_explain3_1.xml +++ b/doc/generated/examples/troubleshoot_explain3_1.xml @@ -1,4 +1,5 @@ -% scons -Q + +% scons -Q cc -o file1.o -c -I. file1.c cc -o file2.o -c -I. file2.c cc -o file3.o -c -I. file3.c diff --git a/doc/generated/examples/troubleshoot_findlibs_1.xml b/doc/generated/examples/troubleshoot_findlibs_1.xml index 9fddc2b..8fc4e5f 100644 --- a/doc/generated/examples/troubleshoot_findlibs_1.xml +++ b/doc/generated/examples/troubleshoot_findlibs_1.xml @@ -1,4 +1,5 @@ -% scons -Q --debug=findlibs + +% scons -Q --debug=findlibs findlibs: looking for 'libfoo.a' in 'libs1' ... findlibs: ... FOUND 'libfoo.a' in 'libs1' findlibs: looking for 'libfoo.so' in 'libs1' ... diff --git a/doc/generated/examples/troubleshoot_stacktrace_1.xml b/doc/generated/examples/troubleshoot_stacktrace_1.xml index 464eca5..cc3ca7b 100644 --- a/doc/generated/examples/troubleshoot_stacktrace_1.xml +++ b/doc/generated/examples/troubleshoot_stacktrace_1.xml @@ -1,3 +1,4 @@ -% scons -Q + +% scons -Q scons: *** [prog.o] Source `prog.c' not found, needed by target `prog.o'. diff --git a/doc/generated/examples/troubleshoot_stacktrace_2.xml b/doc/generated/examples/troubleshoot_stacktrace_2.xml index a1f4872..70a429d 100644 --- a/doc/generated/examples/troubleshoot_stacktrace_2.xml +++ b/doc/generated/examples/troubleshoot_stacktrace_2.xml @@ -1,4 +1,5 @@ -% scons -Q --debug=stacktrace + +% scons -Q --debug=stacktrace scons: *** [prog.o] Source `prog.c' not found, needed by target `prog.o'. scons: internal stack trace: File "bootstrap/src/engine/SCons/Job.py", line 199, in start diff --git a/doc/generated/examples/troubleshoot_taskmastertrace_1.xml b/doc/generated/examples/troubleshoot_taskmastertrace_1.xml index cfa2c8b..578951d 100644 --- a/doc/generated/examples/troubleshoot_taskmastertrace_1.xml +++ b/doc/generated/examples/troubleshoot_taskmastertrace_1.xml @@ -1,4 +1,5 @@ -% scons -Q --taskmastertrace=- prog + +% scons -Q --taskmastertrace=- prog Taskmaster: Looking for a node to evaluate Taskmaster: Considering node <no_state 0 'prog'> and its children: diff --git a/doc/generated/examples/troubleshoot_tree1_1.xml b/doc/generated/examples/troubleshoot_tree1_1.xml index 0f3c3c8..4ccadc6 100644 --- a/doc/generated/examples/troubleshoot_tree1_1.xml +++ b/doc/generated/examples/troubleshoot_tree1_1.xml @@ -1,4 +1,5 @@ -% scons -Q --tree=all + +% scons -Q --tree=all cc -o f1.o -c -I. f1.c cc -o f2.o -c -I. f2.c cc -o f3.o -c -I. f3.c diff --git a/doc/generated/examples/troubleshoot_tree1_2.xml b/doc/generated/examples/troubleshoot_tree1_2.xml index 7f3789f..0bd4874 100644 --- a/doc/generated/examples/troubleshoot_tree1_2.xml +++ b/doc/generated/examples/troubleshoot_tree1_2.xml @@ -1,4 +1,5 @@ -% scons -Q --tree=all f2.o + +% scons -Q --tree=all f2.o cc -o f2.o -c -I. f2.c +-f2.o +-f2.c diff --git a/doc/generated/examples/troubleshoot_tree1_3.xml b/doc/generated/examples/troubleshoot_tree1_3.xml index bc0dbac..75fa841 100644 --- a/doc/generated/examples/troubleshoot_tree1_3.xml +++ b/doc/generated/examples/troubleshoot_tree1_3.xml @@ -1,4 +1,5 @@ -% scons -Q --tree=all f1.o f3.o + +% scons -Q --tree=all f1.o f3.o cc -o f1.o -c -I. f1.c +-f1.o +-f1.c diff --git a/doc/generated/examples/troubleshoot_tree1_4.xml b/doc/generated/examples/troubleshoot_tree1_4.xml index 687b1ba..409bce9 100644 --- a/doc/generated/examples/troubleshoot_tree1_4.xml +++ b/doc/generated/examples/troubleshoot_tree1_4.xml @@ -1,4 +1,5 @@ -% scons -Q --tree=status + +% scons -Q --tree=status cc -o f1.o -c -I. f1.c cc -o f2.o -c -I. f2.c cc -o f3.o -c -I. f3.c diff --git a/doc/generated/examples/troubleshoot_tree1_5.xml b/doc/generated/examples/troubleshoot_tree1_5.xml index 00b05ac..b852ab0 100644 --- a/doc/generated/examples/troubleshoot_tree1_5.xml +++ b/doc/generated/examples/troubleshoot_tree1_5.xml @@ -1,4 +1,5 @@ -% scons -Q --tree=derived + +% scons -Q --tree=derived cc -o f1.o -c -I. f1.c cc -o f2.o -c -I. f2.c cc -o f3.o -c -I. f3.c diff --git a/doc/generated/examples/troubleshoot_tree1_6.xml b/doc/generated/examples/troubleshoot_tree1_6.xml index 2b16556..a0d42d7 100644 --- a/doc/generated/examples/troubleshoot_tree1_6.xml +++ b/doc/generated/examples/troubleshoot_tree1_6.xml @@ -1,4 +1,5 @@ -% scons -Q --tree=derived,status + +% scons -Q --tree=derived,status cc -o f1.o -c -I. f1.c cc -o f2.o -c -I. f2.c cc -o f3.o -c -I. f3.c diff --git a/doc/generated/examples/troubleshoot_tree2_1.xml b/doc/generated/examples/troubleshoot_tree2_1.xml index e7e2d5d..85febf5 100644 --- a/doc/generated/examples/troubleshoot_tree2_1.xml +++ b/doc/generated/examples/troubleshoot_tree2_1.xml @@ -1,4 +1,5 @@ -% scons -Q --tree=all + +% scons -Q --tree=all cc -o f1.o -c -I. f1.c cc -o f2.o -c -I. f2.c cc -o f3.o -c -I. f3.c diff --git a/doc/generated/examples/troubleshoot_tree2_2.xml b/doc/generated/examples/troubleshoot_tree2_2.xml index c2f0e64..5380fad 100644 --- a/doc/generated/examples/troubleshoot_tree2_2.xml +++ b/doc/generated/examples/troubleshoot_tree2_2.xml @@ -1,4 +1,5 @@ -% scons -Q --tree=prune + +% scons -Q --tree=prune cc -o f1.o -c -I. f1.c cc -o f2.o -c -I. f2.c cc -o f3.o -c -I. f3.c diff --git a/doc/generated/examples/variants_ex_1.xml b/doc/generated/examples/variants_ex_1.xml index b51655c..12a14d6 100644 --- a/doc/generated/examples/variants_ex_1.xml +++ b/doc/generated/examples/variants_ex_1.xml @@ -1,4 +1,5 @@ -% scons -Q OS=linux + +% scons -Q OS=linux Install file: "build/linux/world/world.h" as "export/linux/include/world.h" cc -o build/linux/hello/hello.o -c -Iexport/linux/include build/linux/hello/hello.c cc -o build/linux/world/world.o -c -Iexport/linux/include build/linux/world/world.c diff --git a/doc/generated/examples/variants_ex_2.xml b/doc/generated/examples/variants_ex_2.xml index 22385e3..c129cc4 100644 --- a/doc/generated/examples/variants_ex_2.xml +++ b/doc/generated/examples/variants_ex_2.xml @@ -1,4 +1,5 @@ -C:\>scons -Q OS=windows + +C:\>scons -Q OS=windows Install file: "build/windows/world/world.h" as "export/windows/include/world.h" cl /Fobuild\windows\hello\hello.obj /c build\windows\hello\hello.c /nologo /Iexport\windows\include cl /Fobuild\windows\world\world.obj /c build\windows\world\world.c /nologo /Iexport\windows\include diff --git a/doc/generated/functions.gen b/doc/generated/functions.gen index 28160ba..d71387e 100644 --- a/doc/generated/functions.gen +++ b/doc/generated/functions.gen @@ -1,3 +1,4 @@ + %scons; @@ -11,7 +12,7 @@ %variables-mod; ]> - + Action(action, [cmd/str/fun, [var, ...]] [option=value, ...]) @@ -19,7 +20,8 @@ env.Action(action, [cmd/str/fun, [var, ...]] [option=value, ...]) - + + Creates an Action object for the specified action. @@ -27,7 +29,7 @@ See the manpage section "Action Objects" for a complete explanation of the arguments and behavior. - + Note that the env.Action() form of the invocation will expand @@ -54,7 +56,8 @@ until the Action object is actually used. env.AddMethod(function, [name]) - + + When called with the AddMethod() form, @@ -83,11 +86,11 @@ specified itself is used for the method name. - + Examples: - + # Note that the first argument to the function to # be attached as a method must be the object through # which the method will be called; the Python @@ -113,24 +116,25 @@ env.other_method_name('another arg') AddOption(arguments) - + + This function adds a new command-line option to be recognized. The specified arguments -are the same as supported by the standard Python -optparse.add_option() -method (with a few additional capabilities noted below); +are the same as supported by the add_option +method in the standard Python library module optparse, +with a few additional capabilities noted below; see the documentation for -optparse +optparse for a thorough discussion of its option-processing capabities. - + In addition to the arguments and values supported by the optparse.add_option() method, the SCons -AddOption +AddOption function allows you to set the nargs keyword value to @@ -142,7 +146,7 @@ argument. When nargs = '?' is passed to the -AddOption +AddOption function, the const keyword argument @@ -152,36 +156,49 @@ option is specified on the command line without an explicit argument. - + If no default= keyword argument is supplied when calling -AddOption, +AddOption, the option will have a default value of None. - + +Unlike regular optparse, option names +added via AddOption must be matched +exactly, the automatic matching of abbreviations on the +command line for long options is not supported. +To allow specific abbreviations, +include them in the AddOption call. + + + Once a new command-line option has been added with -AddOption, +AddOption, the option value may be accessed using -GetOption +GetOption or env.GetOption(). + +SetOption is not currently supported for +options added with AddOption. - + Any specified help= strings for the new option(s) @@ -193,22 +210,22 @@ options (the latter only if no other help text is specified in the SConscript files). The help text for the local options specified by -AddOption +AddOption will appear below the SCons options themselves, under a separate Local Options heading. The options will appear in the help text in the order in which the -AddOption +AddOption calls occur. - + Example: - + AddOption('--prefix', dest='prefix', nargs=1, type='string', @@ -221,11 +238,12 @@ env = Environment(PREFIX = GetOption('prefix')) While AddOption behaves like -optparse.add_option, +add_option, +from the optparse module, the behavior of options added by AddOption which take arguments is underfined in scons if whitespace -(rather than = sign) is used as +(rather than an = sign) is used as the separator on the command line when the option is invoked. Such usage should be avoided. @@ -241,7 +259,8 @@ Such usage should be avoided. env.AddPostAction(target, action) - + + Arranges for the specified action to be performed @@ -255,7 +274,7 @@ See the manpage section "Action Objects" for a complete explanation. - + When multiple targets are supplied, the action may be called multiple times, once after each action that generates @@ -270,7 +289,8 @@ one or more targets in the list. env.AddPreAction(target, action) - + + Arranges for the specified action to be performed @@ -284,14 +304,14 @@ See the manpage section "Action Objects" for a complete explanation. - + When multiple targets are specified, the action(s) may be called multiple times, once before each action that generates one or more targets in the list. - + Note that if any of the targets are built in multiple steps, the action will be invoked just before the "final" action that specifically @@ -302,16 +322,16 @@ from a specified source file via an intermediate object file: - + foo = Program('foo.c') AddPreAction(foo, 'pre_action') - + The specified pre_action would be executed before -scons +scons calls the link command that actually generates the executable program binary foo, @@ -328,7 +348,8 @@ file into an object file. env.Alias(alias, [targets, [action]]) - + + Creates one or more phony targets that expand to one or more other targets. An optional @@ -342,17 +363,17 @@ which exists outside of any file system. This Node object, or the alias name, may be used as a dependency of any other target, including another alias. -Alias +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. - + Examples: - + Alias('install') Alias('install', '/usr/bin') Alias(['install', 'install-lib'], '/usr/local/lib') @@ -368,7 +389,8 @@ env.Alias('update', ['file1', 'file2'], "update_database $SOURCES") AllowSubstExceptions([exception, ...]) - + + Specifies the exceptions that will be allowed when expanding construction variables. By default, @@ -384,19 +406,19 @@ will generate an error message and terminate processing. - + If -AllowSubstExceptions +AllowSubstExceptions is called multiple times, each call completely overwrites the previous list of allowed exceptions. - + Example: - + # Requires that all construction variable names exist. # (You may wish to do this if you want to enforce strictly # that all construction variables must be defined before use.) @@ -415,13 +437,14 @@ AllowSubstExceptions(IndexError, NameError, ZeroDivisionError) env.AlwaysBuild(target, ...) - + + Marks each given target so that it is always assumed to be out of date, and will always be rebuilt if needed. Note, however, that -AlwaysBuild +AlwaysBuild does not add its target(s) to the default target list, so the targets will only be built if they are specified on the command line, @@ -430,7 +453,7 @@ they will always be built if so specified. Multiple targets can be passed in to a single call to -AlwaysBuild. +AlwaysBuild. @@ -438,7 +461,8 @@ Multiple targets can be passed in to a single call to env.Append(key=val, [...]) - + + Appends the specified keyword arguments to the end of construction variables in the environment. If the Environment does not have @@ -454,11 +478,11 @@ and the lists are added together. (See also the Prepend method). - + Example: - + env.Append(CCFLAGS = ' -g', FOO = ['foo.yyy']) @@ -467,7 +491,8 @@ env.Append(CCFLAGS = ' -g', FOO = ['foo.yyy']) env.AppendENVPath(name, newpath, [envname, sep, delete_existing]) - + + This appends new path elements to the given path in the specified external environment (ENV @@ -485,18 +510,18 @@ case where the given old path variable is a list instead of a string, in which case a list will be returned instead of a string. - + If delete_existing is 0, then adding a path that already exists will not move it to the end; it will stay where it is in the list. - + Example: - + print 'before:',env['ENV']['INCLUDE'] include_path = '/foo/bar:/foo' env.AppendENVPath('INCLUDE', include_path) @@ -512,7 +537,8 @@ after: /biz:/foo/bar:/foo env.AppendUnique(key=val, [...], delete_existing=0) - + + Appends the specified keyword arguments to the end of construction variables in the environment. If the Environment does not have @@ -528,38 +554,15 @@ existing matching values are removed first, so existing values in the arg list move to the end of the list. - + Example: - + env.AppendUnique(CCFLAGS = '-g', FOO = ['foo.yyy']) - - - BuildDir(build_dir, src_dir, [duplicate]) - - - env.BuildDir(build_dir, src_dir, [duplicate]) - - -Deprecated synonyms for -VariantDir -and -env.VariantDir(). -The -build_dir -argument becomes the -variant_dir -argument of -VariantDir -or -env.VariantDir(). - - - Builder(action, [arguments]) @@ -567,7 +570,8 @@ or env.Builder(action, [arguments]) - + + Creates a Builder object for the specified action. @@ -575,7 +579,7 @@ See the manpage section "Builder Objects" for a complete explanation of the arguments and behavior. - + Note that the env.Builder() form of the invocation will expand @@ -590,7 +594,7 @@ construction environment through which env.Builder() was called. The -Builder +Builder form delays all variable expansion until after the Builder object is actually called. @@ -603,14 +607,15 @@ until after the Builder object is actually called. env.CacheDir(cache_dir) - + + Specifies that -scons +scons will maintain a cache of derived files in cache_dir. The derived files in the cache will be shared among all the builds using the same -CacheDir +CacheDir call. Specifying a cache_dir @@ -619,13 +624,13 @@ of disables derived file caching. - + Calling env.CacheDir() will only affect targets built through the specified construction environment. Calling -CacheDir +CacheDir sets a global default that will be used by all targets built through construction environments @@ -636,21 +641,21 @@ have an specified. - + When a CacheDir() is being used and -scons +scons finds a derived file that needs to be rebuilt, it will first look in the cache to see if a derived file has already been built from identical input files and an identical build action (as incorporated into the MD5 build signature). If so, -scons +scons will retrieve the file from the cache. If the derived file is not present in the cache, -scons +scons will rebuild it and then place a copy of the built file in the cache (identified by its MD5 build signature), @@ -659,20 +664,20 @@ builds that need to build the same derived file from identical inputs. - + Use of a specified -CacheDir +CacheDir may be disabled for any invocation by using the option. - + If the option is used, -scons +scons will place a copy of all derived files in the cache, @@ -680,17 +685,17 @@ even if they already existed and were not built by this invocation. This is useful to populate a cache the first time -CacheDir +CacheDir is added to a build, or after using the option. - + When using -CacheDir, -scons +CacheDir, +scons will report, "Retrieved `file' from cache," unless the @@ -699,7 +704,7 @@ option is being used. When the option is used, -scons +scons will print the action that would have been used to build the file, @@ -711,9 +716,9 @@ a given derived file has been built in-place or retrieved from the cache. - + The -NoCache +NoCache method can be used to disable caching of specific files. This can be useful if inputs and/or outputs of some tool are impossible to predict or prohibitively large. @@ -727,7 +732,8 @@ predict or prohibitively large. env.Clean(targets, files_or_dirs) - + + This specifies a list of files or directories which should be removed whenever the targets are specified with the @@ -735,28 +741,28 @@ command line option. The specified targets may be a list or an individual target. Multiple calls to -Clean +Clean are legal, and create new targets or add files and directories to the clean list for the specified targets. - + Multiple files or directories should be specified either as separate arguments to the -Clean +Clean method, or as a list. -Clean +Clean will also accept the return value of any of the construction environment Builder methods. Examples: - + The related -NoClean +NoClean function overrides calling -Clean +Clean for the same target, and any targets passed to both functions will not @@ -765,23 +771,23 @@ be removed by the option. - + Examples: - + Clean('foo', ['bar', 'baz']) Clean('dist', env.Program('hello', 'hello.c')) Clean(['foo', 'bar'], 'something_else_to_clean') - + In this example, installing the project creates a subdirectory for the documentation. This statement causes the subdirectory to be removed if the project is deinstalled. - + Clean(docdir, os.path.join(docdir, projectname)) @@ -790,7 +796,8 @@ Clean(docdir, os.path.join(docdir, projectname)) env.Clone([key=val, ...]) - + + Returns a separate copy of a construction environment. If there are any keyword arguments specified, they are added to the returned copy, @@ -798,34 +805,34 @@ overwriting any existing values for the keywords. - + Example: - + env2 = env.Clone() env3 = env.Clone(CCFLAGS = '-g') - + Additionally, a list of tools and a toolpath may be specified, as in the Environment constructor: - + def MyTool(env): env['FOO'] = 'bar' env4 = env.Clone(tools = ['msvc', MyTool]) - + The parse_flags keyword argument is also recognized to allow merging command-line style arguments into the appropriate construction -variables (see env.MergeFlags). +variables (see env.MergeFlags). - + # create an environment for compiling programs that use wxWidgets wx_env = env.Clone(parse_flags='!wx-config --cflags --cxxflags') @@ -838,7 +845,8 @@ wx_env = env.Clone(parse_flags='!wx-config --cflags --cxxflags') env.Command(target, source, action, [key=val, ...]) - + + Executes a specific action (or list of actions) to build a target file or files. @@ -847,28 +855,38 @@ than defining a separate Builder object for a single special-case build. - -As a special case, the -source_scanner -keyword argument can + +Command builder accepts +source_scanner, +target_scanner, +source_factory, and +target_factory +keyword arguments. The *_scanner args can be used to specify a Scanner object -that will be used to scan the sources. -(The global +that will be used to apply a custom +scanner for a source or target. +For example, the global DirScanner object can be used if any of the sources will be directories that must be scanned on-disk for changes to files that aren't -already specified in other Builder of function calls.) +already specified in other Builder of function calls. +The *_factory args take a factory function that the +Command will use to turn any sources or targets +specified as strings into SCons Nodes. +See the sections "Builder Objects" +below, for more information about how these +args work in a Builder. - + Any other keyword arguments specified override any same-named existing construction variables. - + An action can be an external command, specified as a string, or a callable Python object; @@ -885,11 +903,11 @@ or by a to ignore the exit status of the external command. - + Examples: - + env.Command('foo.out', 'foo.in', "$FOO_BUILD < $SOURCES > $TARGET") @@ -907,9 +925,9 @@ env.Command('baz.out', 'baz.in', rename]) - + Note that the -Command +Command function will usually assume, by default, that the specified targets and/or sources are Files, if no other part of the configuration @@ -918,24 +936,23 @@ If necessary, you can explicitly specify that targets or source nodes should be treated as directories by using the -Dir +Dir or env.Dir functions. - + Examples: - + env.Command('ddd.list', Dir('ddd'), 'ls -l $SOURCE > $TARGET') env['DISTDIR'] = 'destination/directory' env.Command(env.Dir('$DISTDIR')), None, make_distdir) - Also note that SCons will usually automatically create any directory necessary to hold a target file, @@ -950,7 +967,8 @@ so you normally don't need to create directories by hand. env.Configure([custom_tests, conf_dir, log_file, config_h]) - + + Creates a Configure object for integrated functionality similar to GNU autoconf. See the manpage section "Configure Contexts" @@ -962,7 +980,8 @@ for a complete explanation of the arguments and behavior. env.Copy([key=val, ...]) - + + A now-deprecated synonym for env.Clone(). @@ -975,7 +994,8 @@ A now-deprecated synonym for env.Decider(function) - + + Specifies that all up-to-date decisions for targets built through this construction environment will be handled by the specified @@ -987,7 +1007,7 @@ that specify the type of decision function to be performed: - + timestamp-newer @@ -1070,11 +1090,11 @@ all within a single second. - + Examples: - + # Use exact timestamp matches by default. Decider('timestamp-match') @@ -1083,7 +1103,7 @@ Decider('timestamp-match') env.Decider('content') - + In addition to the above already-available functions, the function @@ -1091,7 +1111,7 @@ argument may be an actual Python function that takes the following three arguments: - + dependency @@ -1150,7 +1170,7 @@ Use this node instead of the one specified by - + The function should return a @@ -1178,11 +1198,11 @@ Ignoring some or all of the function arguments is perfectly normal. - + Example: - + def my_decider(dependency, target, prev_ni, repo_node=None): return not os.path.exists(str(target)) @@ -1197,13 +1217,14 @@ env.Decider(my_decider) env.Default(targets) - + + This specifies a list of default targets, which will be built by -scons +scons if no explicit targets are given on the command line. Multiple calls to -Default +Default are legal, and add to the list of default targets. As noted above, both forms of this call affect the @@ -1212,43 +1233,43 @@ construction environment method applies construction variable expansion to the targets. - + Multiple targets should be specified as separate arguments to the -Default +Default method, or as a list. -Default +Default will also accept the Node returned by any of a construction environment's builder methods. - + Examples: - + Default('foo', 'bar', 'baz') env.Default(['a', 'b', 'c']) hello = env.Program('hello', 'hello.c') env.Default(hello) - + An argument to -Default +Default of None will clear all default targets. Later calls to -Default +Default will add to the (now empty) default-target list like normal. - + The current list of targets added using the -Default +Default function or method is available in the DEFAULT_TARGETS list; @@ -1258,14 +1279,21 @@ see below. - DefaultEnvironment([args]) + DefaultEnvironment([**kwargs]) - -Creates and returns a default construction environment object. -This construction environment is used internally by SCons -in order to execute many of the global functions in this list, -and to fetch source files transparently + + +Creates and returns the default construction environment object. +The default construction environment is used internally by SCons +in order to execute many of the global functions in this list +(i.e. those not called as methods of a specific +construction environment), and to fetch source files transparently from source code management systems. +The default environment is a singleton, so the keyword +arguments affect it only on the first call, on subsequent +calls the already-constructed object is returned. +The default environment can be modified in the same way +as any construction environment. @@ -1276,7 +1304,8 @@ from source code management systems. env.Depends(target, dependency) - + + Specifies an explicit dependency; the target @@ -1299,11 +1328,11 @@ is not caught by a Scanner for the file. - + Example: - + env.Depends('foo', 'other-input-file-for-foo') mylib = env.Library('mylib.c') @@ -1324,20 +1353,21 @@ env.Depends(bar, installed_lib) env.Dictionary([vars]) - + + Returns a dictionary object -containing the construction variables in the construction environment. +containing the construction variables in the construction environment. If there are any arguments specified, -the values of the specified construction variables +the values of the specified construction variables are returned as a string (if one argument) or as a list of strings. - + Example: - + cvars = env.Dictionary() cc_values = env.Dictionary('CC', 'CCFLAGS', 'CCCOM') @@ -1350,7 +1380,8 @@ cc_values = env.Dictionary('CC', 'CCFLAGS', 'CCCOM') env.Dir(name, [directory]) - + + This returns a Directory Node, an object that represents the specified directory name. @@ -1363,7 +1394,7 @@ If no is specified, the current script's directory is used as the parent. - + If name is a list, SCons returns a list of Dir nodes. @@ -1371,7 +1402,7 @@ Construction variables are expanded in name. - + Directory Nodes can be used anywhere you would supply a string as a directory name to a Builder method or function. @@ -1386,7 +1417,8 @@ for more information. env.Dump([key]) - + + Returns a pretty printable representation of the environment. key, if not @@ -1394,36 +1426,36 @@ if not should be a string containing the name of the variable of interest. - + This SConstruct: - + env=Environment() print(env.Dump('CCCOM')) - + will print: - + '$CC -c -o $TARGET $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS $SOURCES' - + While this SConstruct: - + env=Environment() print(env.Dump()) - + will print: - + { 'AR': 'ar', 'ARCOM': '$AR $ARFLAGS $TARGET $SOURCES\n$RANLIB $RANLIBFLAGS $TARGET', 'ARFLAGS': ['r'], @@ -1441,7 +1473,8 @@ will print: env.EnsurePythonVersion(major, minor) - + + Ensure that the Python version is at least major.minor. This function will @@ -1449,11 +1482,11 @@ print out an error message and exit SCons with a non-zero exit code if the actual Python version is not late enough. - + Example: - + EnsurePythonVersion(2,2) @@ -1465,7 +1498,8 @@ EnsurePythonVersion(2,2) env.EnsureSConsVersion(major, minor, [revision]) - + + Ensure that the SCons version is at least major.minor, or @@ -1478,11 +1512,11 @@ print out an error message and exit SCons with a non-zero exit code if the actual SCons version is not late enough. - + Examples: - + EnsureSConsVersion(0,14) EnsureSConsVersion(0,96,90) @@ -1496,7 +1530,8 @@ EnsureSConsVersion(0,96,90) env.Environment([key=value, ...]) - + + Return a new construction environment initialized with the specified key=value @@ -1511,7 +1546,8 @@ pairs. env.Execute(action, [strfunction, varlist]) - + + Executes an Action object. The specified action @@ -1529,14 +1565,14 @@ or return value of the Python function will be returned. - + Note that -scons +scons will print an error message if the executed action fails--that is, exits with or returns a non-zero value. -scons +scons will not, however, @@ -1545,12 +1581,12 @@ if the specified action fails. If you want the build to stop in response to a failed -Execute +Execute call, you must explicitly check for a non-zero return value: - + Execute(Copy('file.out', 'file.in')) if Execute("mkdir sub/dir/ectory"): @@ -1566,9 +1602,10 @@ if Execute("mkdir sub/dir/ectory"): env.Exit([value]) - + + This tells -scons +scons to exit immediately with the specified value. @@ -1586,28 +1623,29 @@ is used if no value is specified. env.Export(vars) - + + This tells -scons +scons to export a list of variables from the current SConscript file to all other SConscript files. The exported variables are kept in a global collection, so subsequent calls to -Export +Export will over-write previous exports that have the same name. Multiple variable names can be passed to -Export +Export as separate arguments or as a list. Keyword arguments can be used to provide names and their values. A dictionary can be used to map variables to a different name when exported. Both local variables and global variables can be exported. - + Examples: - + env = Environment() # Make env available for all SConscript files to Import(). Export("env") @@ -1626,15 +1664,15 @@ Export(debug = env) Export({"debug":env}) - + Note that the -SConscript +SConscript function supports an exports argument that makes it easier to to export a variable or set of variables to a single SConscript file. See the description of the -SConscript +SConscript function, below. @@ -1646,7 +1684,8 @@ function, below. env.File(name, [directory]) - + + This returns a File Node, an object that represents the specified file @@ -1657,7 +1696,7 @@ can be a relative or absolute path. is an optional directory that will be used as the parent directory. - + If name is a list, SCons returns a list of File nodes. @@ -1665,7 +1704,7 @@ Construction variables are expanded in name. - + File Nodes can be used anywhere you would supply a string as a file name to a Builder method or function. @@ -1683,7 +1722,8 @@ for more information. env.FindFile(file, dirs) - + + Search for file in the path specified by @@ -1695,11 +1735,11 @@ this function also searches for derived files that have not yet been built. - + Example: - + foo = env.FindFile('foo', ['dir1', 'dir2']) @@ -1711,24 +1751,25 @@ foo = env.FindFile('foo', ['dir1', 'dir2']) env.FindInstalledFiles() - + + Returns the list of targets set up by the -Install +Install or -InstallAs +InstallAs builders. - + This function serves as a convenient method to select the contents of a binary package. - + Example: - + Install( '/bin', [ 'executable_a', 'executable_b' ] ) # will return the file node list @@ -1747,7 +1788,8 @@ FindInstalledFiles() FindPathDirs(variable) - + + Returns a function (actually a callable Python object) intended to be used as the @@ -1759,14 +1801,14 @@ in a construction environment and treat the construction variable's value as a list of directory paths that should be searched (like -$CPPPATH, -$LIBPATH, +$CPPPATH, +$LIBPATH, etc.). - + Note that use of -FindPathDirs +FindPathDirs is generally preferable to writing your own path_function @@ -1774,11 +1816,11 @@ for the following reasons: 1) The returned list will contain all appropriate directories found in source trees (when -VariantDir +VariantDir is used) or in code repositories (when -Repository +Repository or the option are used). @@ -1790,11 +1832,11 @@ and avoid re-scanning the directories for files, when possible. - + Example: - + def my_scan(node, env, path, arg): # Code to scan file contents goes here... return include_files @@ -1812,7 +1854,8 @@ scanner = Scanner(name = 'myscanner', env.FindSourceFiles(node='"."') - + + Returns the list of nodes which serve as the source of the built files. It does so by inspecting the dependency tree starting at the optional argument @@ -1822,16 +1865,16 @@ which defaults to the '"."'-node. It will then return all leaves of These are all children which have no further children. - + This function is a convenient method to select the contents of a Source Package. - + Example: - + Program( 'src/main_a.c' ) Program( 'src/main_b.c' ) Program( 'main_c.c' ) @@ -1843,7 +1886,7 @@ FindSourceFiles() FindSourceFiles( 'src' ) - + As you can see build support files (SConstruct in the above example) will also be returned by this function. @@ -1856,7 +1899,8 @@ will also be returned by this function. env.Flatten(sequence) - + + Takes a sequence (that is, a Python list or tuple) that may contain nested sequences and returns a flattened list containing @@ -1869,11 +1913,11 @@ but direct Python manipulation of these lists does not. - + Examples: - + foo = Object('foo.c') bar = Object('bar.c') @@ -1896,7 +1940,8 @@ for object in Flatten(objects): GetBuildFailures() - + + Returns a list of exceptions for the actions that failed while attempting to build targets. @@ -1908,13 +1953,13 @@ that record various aspects of the build failure: - + .node The node that was being built when the build failure occurred. - + .status The numeric exit status returned by the command or Python function @@ -1922,7 +1967,7 @@ that failed when trying to build the specified Node. - + .errstr The SCons error string describing the build failure. @@ -1932,7 +1977,7 @@ to indicate that an executed command exited with a status of 2.) - + .filename The name of the file or directory that actually caused the failure. @@ -1955,7 +2000,7 @@ attribute will be sub/dir. - + .executor The SCons Executor object for the target Node @@ -1965,7 +2010,7 @@ the construction environment used for the failed action. - + .action The actual SCons Action object that failed. This will be one specific action @@ -1974,26 +2019,26 @@ actions that would have been executed to build the target. - + .command The actual expanded command that was executed and failed, after expansion of -$TARGET, -$SOURCE, +$TARGET, +$SOURCE, and other construction variables. - + Note that the -GetBuildFailures +GetBuildFailures function will always return an empty list until any build failure has occurred, which means that -GetBuildFailures +GetBuildFailures will always return an empty list while the -SConscript +SConscript files are being read. Its primary intended use is for functions that will be @@ -2005,7 +2050,7 @@ function. Example: - + import atexit def print_build_failures(): @@ -2024,9 +2069,10 @@ atexit.register(print_build_failures) env.GetBuildPath(file, [...]) - + + Returns the -scons +scons path name (or names) for the specified file (or files). @@ -2034,7 +2080,7 @@ The specified file or files may be -scons +scons Nodes or strings representing path names. @@ -2046,9 +2092,10 @@ Nodes or strings representing path names. env.GetLaunchDir() - + + Returns the absolute path name of the directory from which -scons +scons was initially invoked. This can be useful when using the , @@ -2057,7 +2104,7 @@ or options, which internally change to the directory in which the -SConstruct +SConstruct file is found. @@ -2069,16 +2116,17 @@ file is found. env.GetOption(name) - + + This function provides a way to query the value of SCons options set on scons command line (or set using the -SetOption +SetOption function). The options supported are: - + cache_debug @@ -2323,7 +2371,7 @@ which corresponds to --warn and --warning. - + See the documentation for the corresponding command line object for information about each specific option. @@ -2337,11 +2385,12 @@ option. env.Glob(pattern, [ondisk, source, strings, exclude]) - + + Returns Nodes (or strings) that match the specified pattern, relative to the directory of the current -SConscript +SConscript file. The env.Glob() @@ -2351,20 +2400,20 @@ and returns whatever matches the resulting expanded pattern. - + The specified pattern uses Unix shell style metacharacters for matching: - + * matches everything ? matches any single character [seq] matches any character in seq [!seq] matches any char not in seq - + If the first character of a filename is a dot, it must be matched explicitly. Character matches do @@ -2372,17 +2421,17 @@ Character matches do span directory separators. - + The -Glob +Glob knows about repositories (see the -Repository +Repository function) and source directories (see the -VariantDir +VariantDir function) and returns a Node (or string, if so configured) @@ -2392,7 +2441,7 @@ anywhere in a corresponding repository or source directory. - + The ondisk argument may be set to @@ -2406,7 +2455,7 @@ return corresponding Nodes for any on-disk matches found. - + The source argument may be set to @@ -2414,20 +2463,20 @@ argument may be set to (or any equivalent value) to specify that, when the local directory is a -VariantDir, +VariantDir, the returned Nodes should be from the corresponding source directory, not the local directory. - + The strings argument may be set to True (or any equivalent value) to have the -Glob +Glob function return strings, not Nodes, that represent the matched files or directories. The returned strings will be relative to @@ -2436,18 +2485,18 @@ the local (SConscript) directory. arbitrary manipulation of file names, but if the returned strings are passed to a different -SConscript +SConscript file, any Node translation will be relative to the other -SConscript +SConscript directory, not the original -SConscript +SConscript directory.) - + The exclude argument may be set to a pattern or a list of patterns @@ -2457,11 +2506,11 @@ Elements matching a least one pattern of this list will be excluded. - + Examples: - + Program('foo', Glob('*.c')) Zip('/tmp/everything', Glob('.??*') + Glob('*')) sources = Glob('*.cpp', exclude=['os_*_specific_*.cpp']) + Glob('os_%s_specific_*.cpp'%currentOS) @@ -2475,19 +2524,20 @@ sources = Glob('*.cpp', exclude=['os_*_specific_*.cpp']) + Glob('os_%s_specific_ env.Help(text, append=False) - + + This specifies help text to be printed if the argument is given to -scons. +scons. If -Help +Help is called multiple times, the text is appended together in the order that -Help +Help is called. With append set to False, any -Help +Help text generated with -AddOption +AddOption is clobbered. If append is True, the AddOption help is prepended to the help string, thus preserving the @@ -2502,33 +2552,34 @@ message. env.Ignore(target, dependency) - + + The specified dependency file(s) will be ignored when deciding if the target file(s) need to be rebuilt. - + You can also use -Ignore +Ignore to remove a target from the default build. In order to do this you must specify the directory the target will be built in as the target, and the file you want to skip building as the dependency. - + Note that this will only remove the dependencies listed from the files built by default. It will still be built if that dependency is needed by another object being built. See the third and forth examples below. - + Examples: - + env.Ignore('foo', 'foo.c') env.Ignore('bar', ['bar1.h', 'bar2.h']) env.Ignore('.','foobar.obj') @@ -2543,30 +2594,31 @@ env.Ignore('bar','bar/foobar.obj') env.Import(vars) - + + This tells -scons +scons to import a list of variables into the current SConscript file. This will import variables that were exported with -Export +Export or in the exports argument to -SConscript. +SConscript. Variables exported by -SConscript +SConscript have precedence. Multiple variable names can be passed to -Import +Import as separate arguments or as a list. The variable "*" can be used to import all variables. - + Examples: - + Import("env") Import("env", "variable") Import(["env", "variable"]) @@ -2581,7 +2633,8 @@ Import("*") env.Literal(string) - + + The specified string will be preserved as-is @@ -2596,7 +2649,8 @@ and not have construction variables expanded. env.Local(targets) - + + The specified targets will have copies made in the local tree, @@ -2610,7 +2664,8 @@ Returns a list of the target Node or Nodes. env.MergeFlags(arg, [unique]) - + + Merges the specified arg values to the construction environment's construction variables. @@ -2618,7 +2673,7 @@ If the arg argument is not a dictionary, it is converted to one by calling -env.ParseFlags +env.ParseFlags on the argument before the values are merged. Note that @@ -2627,10 +2682,10 @@ must be a single value, so multiple strings must be passed in as a list, not as separate arguments to -env.MergeFlags. +env.MergeFlags. - + By default, duplicate values are eliminated; you can, however, specify @@ -2646,11 +2701,11 @@ All other construction variables keep the right-most unique value. - + Examples: - + # Add an optimization flag to $CCFLAGS. env.MergeFlags('-O3') @@ -2673,38 +2728,39 @@ env.MergeFlags(['-O3', env.NoCache(target, ...) - + + Specifies a list of files which should not be cached whenever the -CacheDir +CacheDir method has been activated. The specified targets may be a list or an individual target. - + Multiple files should be specified either as separate arguments to the -NoCache +NoCache method, or as a list. -NoCache +NoCache will also accept the return value of any of the construction environment Builder methods. - + Calling -NoCache +NoCache on directories and other non-File Node types has no effect because only File Nodes are cached. - + Examples: - + NoCache('foo.elf') NoCache(env.Program('hello', 'hello.c')) @@ -2717,7 +2773,8 @@ NoCache(env.Program('hello', 'hello.c')) env.NoClean(target, ...) - + + Specifies a list of files or directories which should not be removed whenever the targets (or their dependencies) @@ -2727,7 +2784,7 @@ command line option. The specified targets may be a list or an individual target. Multiple calls to -NoClean +NoClean are legal, and prevent each specified target from being removed by calls to the @@ -2735,21 +2792,21 @@ from being removed by calls to the option. - + Multiple files or directories should be specified either as separate arguments to the -NoClean +NoClean method, or as a list. -NoClean +NoClean will also accept the return value of any of the construction environment Builder methods. - + Calling -NoClean +NoClean for a target overrides calling -Clean +Clean for the same target, and any targets passed to both functions will not @@ -2758,11 +2815,11 @@ be removed by the option. - + Examples: - + NoClean('foo.elf') NoClean(env.Program('hello', 'hello.c')) @@ -2772,7 +2829,8 @@ NoClean(env.Program('hello', 'hello.c')) env.ParseConfig(command, [function, unique]) - + + Calls the specified function to modify the environment as specified by the output of @@ -2780,7 +2838,7 @@ to modify the environment as specified by the output of The default function is -env.MergeFlags, +env.MergeFlags, which expects the output of a typical *-config command @@ -2797,11 +2855,11 @@ to allow duplicate values to be added. - + Interpreted options and the construction variables they affect are as specified for the -env.ParseFlags +env.ParseFlags method (which this method calls). See that method's description for a table of options and construction variables. @@ -2815,17 +2873,18 @@ for a table of options and construction variables. env.ParseDepends(filename, [must_exist, only_one]) - + + Parses the contents of the specified filename as a list of dependencies in the style of -Make +Make or mkdep, and explicitly establishes all of the listed dependencies. - + By default, it is not an error if the specified @@ -2841,7 +2900,7 @@ generate an error if the file does not exist, or is otherwise inaccessible. - + The optional only_one argument may be set to a non-zero @@ -2863,15 +2922,15 @@ one output file into a corresponding file. - + The filename and all of the files listed therein will be interpreted relative to the directory of the -SConscript +SConscript file which calls the -ParseDepends +ParseDepends function. @@ -2880,25 +2939,26 @@ function. env.ParseFlags(flags, ...) - + + Parses one or more strings containing typical command-line flags for GCC tool chains and returns a dictionary with the flag values separated into the appropriate SCons construction variables. This is intended as a companion to the -env.MergeFlags +env.MergeFlags method, but allows for the values in the returned dictionary to be modified, if necessary, before merging them into the construction environment. (Note that -env.MergeFlags +env.MergeFlags will call this method if its argument is not a dictionary, so it is usually not necessary to call -env.ParseFlags +env.ParseFlags directly unless you want to manipulate the values.) - + If the first character in any string is an exclamation mark (!), the rest of the string is executed as a command, @@ -2907,12 +2967,12 @@ parsed as GCC tool chain command-line flags and added to the resulting dictionary. - + Flag values are translated accordig to the prefix found, and added to the following construction variables: - + -arch CCFLAGS, LINKFLAGS -D CPPDEFINES -framework FRAMEWORKS @@ -2943,19 +3003,19 @@ and added to the following construction variables: + CCFLAGS, LINKFLAGS - + Any other strings not associated with options are assumed to be the names of libraries and added to the -$LIBS +$LIBS construction variable. - + Examples (all of which produce the same result): - + dict = env.ParseFlags('-O2 -Dfoo -Dbar=1') dict = env.ParseFlags('-O2', '-Dfoo', '-Dbar=1') dict = env.ParseFlags(['-O2', '-Dfoo -Dbar=1']) @@ -2967,38 +3027,39 @@ dict = env.ParseFlags('-O2', '!echo -Dfoo -Dbar=1') Platform(string) - + + The -Platform +Platform form returns a callable object that can be used to initialize a construction environment using the platform keyword of the -Environment +Environment function. - + Example: - + env = Environment(platform = Platform('win32')) - + The -env.Platform +env.Platform form applies the callable object for the specified platform string to the environment through which the method was called. - + env.Platform('posix') - + Note that the win32 platform adds the @@ -3007,7 +3068,7 @@ and SystemRoot variables from the user's external environment to the construction environment's -$ENV +$ENV dictionary. This is so that any executed commands that use sockets to connect with other systems @@ -3025,14 +3086,15 @@ will work on Windows systems. env.Precious(target, ...) - + + Marks each given target as precious so it is not deleted before it is rebuilt. Normally -scons +scons deletes a target before building it. Multiple targets can be passed in to a single call to -Precious. +Precious. @@ -3040,7 +3102,8 @@ Multiple targets can be passed in to a single call to env.Prepend(key=val, [...]) - + + Appends the specified keyword arguments to the beginning of construction variables in the environment. If the Environment does not have @@ -3056,11 +3119,11 @@ and the lists are added together. (See also the Append method, above.) - + Example: - + env.Prepend(CCFLAGS = '-g ', FOO = ['foo.yyy']) @@ -3069,10 +3132,11 @@ env.Prepend(CCFLAGS = '-g ', FOO = ['foo.yyy']) env.PrependENVPath(name, newpath, [envname, sep, delete_existing]) - + + This appends new path elements to the given path in the specified external environment -($ENV +($ENV by default). This will only add any particular path once (leaving the first one it encounters and @@ -3087,7 +3151,7 @@ case where the given old path variable is a list instead of a string, in which case a list will be returned instead of a string. - + If delete_existing is 0, then adding a path that already exists @@ -3095,22 +3159,22 @@ will not move it to the beginning; it will stay where it is in the list. - + Example: - + print 'before:',env['ENV']['INCLUDE'] include_path = '/foo/bar:/foo' env.PrependENVPath('INCLUDE', include_path) print 'after:',env['ENV']['INCLUDE'] - + The above example will print: - + before: /biz:/foo after: /foo/bar:/foo:/biz @@ -3120,7 +3184,8 @@ after: /foo/bar:/foo:/biz env.PrependUnique(key=val, delete_existing=0, [...]) - + + Appends the specified keyword arguments to the beginning of construction variables in the environment. If the Environment does not have @@ -3136,11 +3201,11 @@ existing matching values are removed first, so existing values in the arg list move to the front of the list. - + Example: - + env.PrependUnique(CCFLAGS = '-g', FOO = ['foo.yyy']) @@ -3155,13 +3220,14 @@ env.PrependUnique(CCFLAGS = '-g', FOO = ['foo.yyy']) Progress(list_of_strings, [interval, file, overwrite]) - + + Allows SCons to show progress made during the build by displaying a string or calling a function while evaluating Nodes (e.g. files). - + If the first specified argument is a Python callable (a function or an object that has a __call__() @@ -3183,19 +3249,19 @@ if SCons ever changes the interface to call the function with additional arguments in the future.) - + An example of a simple custom progress function that prints a string containing the Node name every 10 Nodes: - + def my_progress_function(node, *args, **kw): print('Evaluating node %s!' % node) Progress(my_progress_function, interval=10) - + A more complicated example of a custom progress display object that prints a string containing a count every 100 evaluated Nodes. @@ -3206,7 +3272,7 @@ at the end so that the string will overwrite itself on a display: - + import sys class ProgressCounter(object): count = 0 @@ -3216,9 +3282,9 @@ class ProgressCounter(object): Progress(ProgressCounter(), interval=100) - + If the first argument -Progress +Progress is a string, the string will be displayed every @@ -3234,14 +3300,14 @@ on the error output, one dot for every 100 evaluated Nodes: - + import sys Progress('.', interval=100, file=sys.stderr) - + If the string contains the verbatim substring -$TARGET, +$TARGET, it will be replaced with the Node. Note that, for performance reasons, this is not @@ -3259,14 +3325,14 @@ keyword argument to make sure the previously-printed file name is overwritten with blank spaces: - + import sys Progress('$TARGET\r', overwrite=True) - + If the first argument to -Progress +Progress is a list of strings, then each string in the list will be displayed in rotating fashion every @@ -3276,7 +3342,7 @@ This can be used to implement a "spinner" on the user's screen as follows: - + Progress(['-\r', '\\\r', '|\r', '/\r'], interval=5) @@ -3288,17 +3354,18 @@ Progress(['-\r', '\\\r', '|\r', '/\r'], interval=5) env.Pseudo(target, ...) - + + This indicates that each given target should not be created by the build rule, and if the target is created, an error will be generated. This is similar to the gnu make .PHONY target. However, in the vast majority of cases, an -Alias +Alias is more appropriate. Multiple targets can be passed in to a single call to -Pseudo. +Pseudo. @@ -3309,7 +3376,8 @@ Multiple targets can be passed in to a single call to env.PyPackageDir(modulename) - + + This returns a Directory Node similar to Dir. The python module / package is looked up and if located the directory is returned for the location. @@ -3317,7 +3385,7 @@ the directory is returned for the location. Is a named python package / module to lookup the directory for it's location. - + If modulename is a list, SCons returns a list of Dir nodes. @@ -3330,16 +3398,17 @@ Construction variables are expanded in env.Replace(key=val, [...]) - + + Replaces construction variables in the Environment with the specified keyword arguments. - + Example: - + env.Replace(CCFLAGS = '-g', FOO = 'foo.xxx') @@ -3351,20 +3420,21 @@ env.Replace(CCFLAGS = '-g', FOO = 'foo.xxx') env.Repository(directory) - + + Specifies that directory is a repository to be searched for files. Multiple calls to -Repository +Repository are legal, and each one adds to the list of repositories that will be searched. - + To -scons, +scons, a repository is a copy of the source tree, from the top-level directory on down, which may contain @@ -3375,26 +3445,26 @@ The canonical example would be an official source tree maintained by an integrator. If the repository contains derived files, then the derived files should have been built using -scons, +scons, so that the repository contains the necessary signature information to allow -scons +scons to figure out when it is appropriate to use the repository copy of a derived file, instead of building one locally. - + Note that if an up-to-date derived file already exists in a repository, -scons +scons will not make a copy in the local directory tree. In order to guarantee that a local copy will be made, use the -Local +Local method. @@ -3406,7 +3476,8 @@ method. env.Requires(target, prerequisite) - + + Specifies an order-only relationship between the specified target file(s) and the specified prerequisite file(s). @@ -3420,11 +3491,11 @@ and will not be rebuilt simply because the prerequisite file(s) change. - + Example: - + env.Requires('foo', 'file-that-must-be-built-before-foo') @@ -3433,7 +3504,8 @@ env.Requires('foo', 'file-that-must-be-built-before-foo') Return([vars..., stop=]) - + + By default, this stops processing the current SConscript file and returns to the calling SConscript file @@ -3441,32 +3513,32 @@ the values of the variables named in the vars string arguments. Multiple strings contaning variable names may be passed to -Return. +Return. Any strings that contain white space - + The optional stop= keyword argument may be set to a false value to continue processing the rest of the SConscript file after the -Return +Return call. This was the default behavior prior to SCons 0.98. However, the values returned are still the values of the variables in the named vars at the point -Return +Return is called. - + Examples: - + # Returns without returning a value. Return() @@ -3488,7 +3560,8 @@ Return('val1 val2') env.Scanner(function, [argument, keys, path_function, node_class, node_factory, scan_check, recursive]) - + + Creates a Scanner object for the specified function. @@ -3510,23 +3583,24 @@ for a complete explanation of the arguments and behavior. env.SConscript(dirs=subdirs, [name=script, exports, variant_dir, duplicate, must_exist]) - + + This tells -scons +scons to execute one or more subsidiary SConscript (configuration) files. Any variables returned by a called script using -Return +Return will be returned by the call to -SConscript. +SConscript. There are two ways to call the -SConscript +SConscript function. - + The first way you can call -SConscript +SConscript is to explicitly specify one or more scripts as the first argument. @@ -3534,45 +3608,45 @@ 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 -Split). +Split). Examples: - + SConscript('SConscript') # run SConscript in the current directory SConscript('src/SConscript') # run SConscript in the src directory SConscript(['src/SConscript', 'doc/SConscript']) config = SConscript('MyConfig.py') - + The second way you can call -SConscript +SConscript is to specify a list of (sub)directory names as a dirs=subdirs keyword argument. In this case, -scons +scons will, by default, execute a subsidiary configuration file named -SConscript +SConscript in each of the specified directories. You may specify a name other than -SConscript +SConscript by supplying an optional name=script keyword argument. The first three examples below have the same effect as the first three examples above: - + SConscript(dirs='.') # run SConscript in the current directory SConscript(dirs='src') # run SConscript in the src directory SConscript(dirs=['src', 'doc']) SConscript(dirs=['sub1', 'sub2'], name='MySConscript') - + The optional exports argument provides a list of variable names or a dictionary of @@ -3581,28 +3655,28 @@ named values to export to the These variables are locally exported only to the specified script(s), and do not affect the global pool of variables used by the -Export +Export function. The subsidiary script(s) must use the -Import +Import function to import the variables. Examples: - + foo = SConscript('sub/SConscript', exports='env') SConscript('dir/SConscript', exports=['env', 'variable']) SConscript(dirs='subdir', exports='env variable') SConscript(dirs=['one', 'two', 'three'], exports='shared_info') - + If the optional variant_dir argument is present, it causes an effect equivalent to the -VariantDir +VariantDir method described below. (If variant_dir @@ -3619,14 +3693,14 @@ and arguments are interpreted relative to the directory of the calling --> argument is interpreted relative to the directory of the calling -SConscript +SConscript file. See the description of the -VariantDir +VariantDir function below for additional details and restrictions. - + If variant_dir is present, @@ -3636,46 +3710,46 @@ but is not, --> the source directory is the directory in which the -SConscript +SConscript file resides and the -SConscript +SConscript file is evaluated as if it were in the variant_dir directory: - + SConscript('src/SConscript', variant_dir = 'build') - + is equivalent to - + VariantDir('build', 'src') SConscript('build/SConscript') - + This later paradigm is often used when the sources are in the same directory as the -SConstruct: +SConstruct: - + SConscript('SConscript', variant_dir = 'build') - + is equivalent to - + VariantDir('build', '.') SConscript('build/SConscript') - + - + The optional must_exist argument, if true, causes an exception to be raised if a requested -SConscript file is not found. The current default is false, +SConscript file is not found. The current default is false, causing only a warning to be omitted, but this behavior is deprecated. For scripts which truly intend to be optional, transition to explicty supplying must_exist=False to the call. - + Here are some composite examples: - + # collect the configuration information and use it to build src and doc shared_info = SConscript('MyConfig.py') SConscript('src/SConscript', exports='shared_info') SConscript('doc/SConscript', exports='shared_info') - + # build debugging and production versions. SConscript # can use Dir('.').path to determine variant. SConscript('SConscript', variant_dir='debug', duplicate=0) SConscript('SConscript', variant_dir='prod', duplicate=0) - + # build debugging and production versions. SConscript # is passed flags to use. opts = { 'CPPDEFINES' : ['DEBUG'], 'CCFLAGS' : '-pgdb' } @@ -3746,7 +3820,7 @@ opts = { 'CPPDEFINES' : ['NODEBUG'], 'CCFLAGS' : '-O' } SConscript('SConscript', variant_dir='prod', duplicate=0, exports=opts) - + # build common documentation and compile for different architectures SConscript('doc/SConscript', variant_dir='build/doc', duplicate=0) SConscript('src/SConscript', variant_dir='build/x86', duplicate=0) @@ -3761,9 +3835,10 @@ SConscript('src/SConscript', variant_dir='build/ppc', duplicate=0) env.SConscriptChdir(value) - + + By default, -scons +scons changes its working directory to the directory in which each subsidiary SConscript file lives. @@ -3771,14 +3846,14 @@ This behavior may be disabled by specifying either: - + SConscriptChdir(0) env.SConscriptChdir(0) - + in which case -scons +scons will stay in the top-level directory while reading all SConscript files. (This may be necessary when building from repositories, @@ -3790,11 +3865,11 @@ SConscriptChdir() multiple times. - + Example: - + env = Environment() SConscriptChdir(0) SConscript('foo/SConscript') # will not chdir to foo @@ -3810,9 +3885,10 @@ SConscript('bar/SConscript') # will chdir to bar env.SConsignFile([file, dbm_module]) - + + This tells -scons +scons to store all file signatures in the specified database file. @@ -3829,17 +3905,17 @@ If file is not an absolute path name, the file is placed in the same directory as the top-level -SConstruct +SConstruct file. - + If file is None, then -scons +scons will store file signatures in a separate .sconsign @@ -3849,7 +3925,7 @@ not in one global database file. prior to SCons 0.96.91 and 0.97.) - + The optional dbm_module argument can be used to specify @@ -3861,11 +3937,11 @@ Python data structures, and which works on all Python versions. - + Examples: - + # Explicitly stores signatures in ".sconsign.dblite" # in the top-level SConstruct directory (the # default behavior). @@ -3888,13 +3964,14 @@ SConsignFile(None) env.SetDefault(key=val, [...]) - + + Sets construction variables to default values specified with the keyword arguments if (and only if) the variables are not already set. The following statements are equivalent: - + env.SetDefault(FOO = 'foo') if 'FOO' not in env: env['FOO'] = 'foo' @@ -3908,12 +3985,13 @@ if 'FOO' not in env: env['FOO'] = 'foo' env.SetOption(name, value) - + + This function provides a way to set a select subset of the scons command line options from a SConscript file. The options supported are: - + clean @@ -3998,17 +4076,17 @@ which corresponds to --stack-size. - + See the documentation for the corresponding command line object for information about each specific option. - + Example: - + SetOption('max_drift', 1) @@ -4020,7 +4098,8 @@ SetOption('max_drift', 1) env.SideEffect(side_effect, target) - + + Declares side_effect as a side effect of building @@ -4038,7 +4117,7 @@ files for a static library, and various log files are created updated as side effects of various TeX commands. If a target is a side effect of multiple build commands, -scons +scons will ensure that only one set of commands is executed at a time. Consequently, you only need to use this method @@ -4046,7 +4125,7 @@ for side-effect targets that are built as a result of multiple build commands. - + Because multiple build commands may update the same side effect file, by default the @@ -4070,9 +4149,9 @@ is cleaned whenever a specific is cleaned, you must specify this explicitly with the -Clean +Clean or -env.Clean +env.Clean function. @@ -4084,16 +4163,17 @@ function. env.SourceCode(entries, builder) - + + This function and its associate factory functions are deprecated. There is no replacement. The intended use was to keep a local tree in sync with an archive, but in actuality the function only causes the archive to be fetched on the first run. -Synchronizing with the archive is best done external to SCons. +Synchronizing with the archive is best done external to SCons. - + Arrange for non-existent source files to be fetched from a source code management system using the specified @@ -4106,30 +4186,30 @@ source files or directories in which source files can be found. - + For any non-existent source files, -scons +scons will search up the directory tree and use the first -SourceCode +SourceCode builder it finds. The specified builder may be None, in which case -scons +scons will not use a builder to fetch source files for the specified entries, even if a -SourceCode +SourceCode builder has been specified for a directory higher up the tree. - -scons + +scons will, by default, fetch files from SCCS or RCS subdirectories without explicit configuration. @@ -4141,11 +4221,11 @@ and speed up your build a little by disabling these searches as follows: - + env.SourceCode('.', None) - + Note that if the specified builder is one you create by hand, @@ -4154,8 +4234,8 @@ construction environment to use when fetching a source file. - -scons + +scons provides a set of canned factory functions that return appropriate Builders for various popular @@ -4163,14 +4243,14 @@ source code management systems. Canonical examples of invocation include: - + env.SourceCode('.', env.BitKeeper('/usr/local/BKsources')) env.SourceCode('src', env.CVS('/usr/local/CVSROOT')) env.SourceCode('/', env.RCS()) env.SourceCode(['f1.c', 'f2.c'], env.SCCS()) env.SourceCode('no_source.c', None) - + @@ -4182,7 +4262,8 @@ env.SourceCode('no_source.c', None) env.Split(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 @@ -4195,11 +4276,11 @@ 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(""" @@ -4214,13 +4295,14 @@ files = Split(""" env.subst(input, [raw, target, source, conv]) - + + Performs construction variable interpolation on the specified string or sequence argument input. - + By default, leading or trailing white space will be removed from the result. @@ -4252,7 +4334,7 @@ pairs (as is done for signature calculation). - + If the input is a sequence (list or tuple), the individual elements of @@ -4260,7 +4342,7 @@ the sequence will be expanded, and the results will be returned as a list. - + The optional target and @@ -4269,20 +4351,20 @@ keyword arguments must be set to lists of target and source nodes, respectively, if you want the -$TARGET, -$TARGETS, -$SOURCE +$TARGET, +$TARGETS, +$SOURCE and -$SOURCES +$SOURCES to be available for expansion. This is usually necessary if you are calling -env.subst +env.subst from within a Python function used as an SCons action. - + Returned string values or sequence elements are converted to their string representation by default. The optional @@ -4300,11 +4382,11 @@ idiom to pass in an unnamed function that simply returns its unconverted argument. - + Example: - + print(env.subst("The C compiler is: $CC")) def compile(target, source, env): @@ -4321,19 +4403,20 @@ source_nodes = env.subst('$EXPAND_TO_NODELIST', Tag(node, tags) - + + Annotates file or directory Nodes with information about how the -Package +Package Builder should package those files or directories. All tags are optional. - + Examples: - + # makes sure the built library will be installed with 0o644 file # access mode Tag( Library( 'lib.c' ), UNIX_ATTR="0o644" ) @@ -4350,9 +4433,10 @@ Tag( 'file2.txt', DOC ) env.Tool(string, [toolpath, **kw]) - + + The -Tool +Tool form of the function returns a callable object that can be used to initialize @@ -4364,21 +4448,21 @@ in which case the object will add the necessary variables to the construction environment and the name of the tool will be added to the -$TOOLS +$TOOLS construction variable. - + Additional keyword arguments are passed to the tool's generate() method. - + Examples: - + env = Environment(tools = [ Tool('msvc') ]) env = Environment() @@ -4388,22 +4472,22 @@ u = Tool('opengl', toolpath = ['tools']) u(env) # adds 'opengl' to the TOOLS variable - + The -env.Tool +env.Tool form of the function applies the callable object for the specified tool string to the environment through which the method was called. - + Additional keyword arguments are passed to the tool's generate() method. - + env.Tool('gcc') env.Tool('opengl', toolpath = ['build/tools']) @@ -4416,7 +4500,8 @@ env.Tool('opengl', toolpath = ['build/tools']) env.Value(value, [built_value]) - + + Returns a Node object representing the specified Python value. Value Nodes can be used as dependencies of targets. If the result of calling @@ -4430,7 +4515,7 @@ When using timestamp source signatures, Value Nodes' timestamps are equal to the system time when the Node is created. - + The returned Value Node object has a write() method that can be used to "build" a Value Node @@ -4446,11 +4531,11 @@ There is a corresponding method that will return the built value of the Node. - + Examples: - + env = Environment() def create(target, source, env): @@ -4492,9 +4577,10 @@ env.UpdateValue(target = Value(output), source = Value(input)) env.VariantDir(variant_dir, src_dir, [duplicate]) - + + Use the -VariantDir +VariantDir function to create a copy of your sources in another location: if a name under variant_dir @@ -4507,8 +4593,8 @@ than the original sources by simply refering to the sources (and targets) within the variant tree. - -VariantDir + +VariantDir can be called multiple times with the same src_dir to set up multiple builds with different options @@ -4526,9 +4612,9 @@ TODO: src_dir = '.' works fine with a build dir under it. --> - + The default behavior is for -scons +scons to physically duplicate the source files in the variant tree. Thus, a build performed in the variant tree is guaranteed to be identical to a build performed in the source tree even if @@ -4539,7 +4625,7 @@ or individual compilers or other invoked tools are hard-coded to put derived files in the same directory as source files. - + If possible on the platform, the duplication is performed by linking rather than copying; see also the @@ -4550,14 +4636,14 @@ files and directories that are not used are not present in variant_dir. - + Duplicating the source tree may be disabled by setting the duplicate argument to 0 (zero). This will cause -scons +scons to invoke Builders using the path names of source files in src_dir and the path names of derived files within @@ -4568,9 +4654,9 @@ and is usually safe for most builds (but see above for cases that may cause problems). - + Note that -VariantDir +VariantDir works most naturally with a subsidiary SConscript file. However, you would then call the subsidiary SConscript file not in the source directory, but in the @@ -4578,11 +4664,11 @@ not in the source directory, but in the regardless of the value of duplicate. This is how you tell -scons +scons which variant of a source tree to build: - + # run src/SConscript in two variant directories VariantDir('build/variant1', 'src') SConscript('build/variant1/SConscript') @@ -4590,31 +4676,31 @@ VariantDir('build/variant2', 'src') SConscript('build/variant2/SConscript') - + See also the -SConscript +SConscript function, described above, for another way to specify a variant directory in conjunction with calling a subsidiary SConscript file. - + Examples: - + # use names in the build directory, not the source directory VariantDir('build', 'src', duplicate=0) Program('build/prog', 'build/source.c') - + # this builds both the source and docs in a separate subtree VariantDir('build', '.', duplicate=0) SConscript(dirs=['build/src','build/doc']) - + # same as previous example, but only uses SConscript SConscript(dirs='src', variant_dir='build/src', duplicate=0) SConscript(dirs='doc', variant_dir='build/doc', duplicate=0) @@ -4628,7 +4714,8 @@ SConscript(dirs='doc', variant_dir='build/doc', duplicate=0) env.WhereIs(program, [path, pathext, reject]) - + + Searches for the specified executable program, returning the full path name to the program diff --git a/doc/generated/functions.mod b/doc/generated/functions.mod index 91710a3..3d49229 100644 --- a/doc/generated/functions.mod +++ b/doc/generated/functions.mod @@ -19,7 +19,6 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. Append"> AppendENVPath"> AppendUnique"> -BuildDir"> Builder"> CacheDir"> Clean"> @@ -101,7 +100,6 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. env.Append"> env.AppendENVPath"> env.AppendUnique"> -env.BuildDir"> env.Builder"> env.CacheDir"> env.Clean"> @@ -193,7 +191,6 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. Append"> AppendENVPath"> AppendUnique"> -BuildDir"> Builder"> CacheDir"> Clean"> @@ -275,7 +272,6 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. env.Append"> env.AppendENVPath"> env.AppendUnique"> -env.BuildDir"> env.Builder"> env.CacheDir"> env.Clean"> diff --git a/doc/generated/tools.gen b/doc/generated/tools.gen index bf6381c..0d30f6f 100644 --- a/doc/generated/tools.gen +++ b/doc/generated/tools.gen @@ -1,3 +1,4 @@ + %scons; @@ -11,137 +12,153 @@ %variables-mod; ]> - + 386asm - + + Sets construction variables for the 386ASM assembler for the Phar Lap ETS embedded operating system. -Sets: &cv-link-AS;, &cv-link-ASCOM;, &cv-link-ASFLAGS;, &cv-link-ASPPCOM;, &cv-link-ASPPFLAGS;.Uses: &cv-link-CC;, &cv-link-CPPFLAGS;, &cv-link-_CPPDEFFLAGS;, &cv-link-_CPPINCFLAGS;. +Sets: &cv-link-AS;, &cv-link-ASCOM;, &cv-link-ASFLAGS;, &cv-link-ASPPCOM;, &cv-link-ASPPFLAGS;.Uses: &cv-link-CC;, &cv-link-CPPFLAGS;, &cv-link-_CPPDEFFLAGS;, &cv-link-_CPPINCFLAGS;. aixc++ - + + Sets construction variables for the IMB xlc / Visual Age C++ compiler. -Sets: &cv-link-CXX;, &cv-link-CXXVERSION;, &cv-link-SHCXX;, &cv-link-SHOBJSUFFIX;. +Sets: &cv-link-CXX;, &cv-link-CXXVERSION;, &cv-link-SHCXX;, &cv-link-SHOBJSUFFIX;. aixcc - + + Sets construction variables for the IBM xlc / Visual Age C compiler. -Sets: &cv-link-CC;, &cv-link-CCVERSION;, &cv-link-SHCC;. +Sets: &cv-link-CC;, &cv-link-CCVERSION;, &cv-link-SHCC;. aixf77 - + + Sets construction variables for the IBM Visual Age f77 Fortran compiler. -Sets: &cv-link-F77;, &cv-link-SHF77;. +Sets: &cv-link-F77;, &cv-link-SHF77;. aixlink - + + Sets construction variables for the IBM Visual Age linker. -Sets: &cv-link-LINKFLAGS;, &cv-link-SHLIBSUFFIX;, &cv-link-SHLINKFLAGS;. +Sets: &cv-link-LINKFLAGS;, &cv-link-SHLIBSUFFIX;, &cv-link-SHLINKFLAGS;. applelink - + + Sets construction variables for the Apple linker (similar to the GNU linker). - Sets: &cv-link-APPLELINK_COMPATIBILITY_VERSION;, &cv-link-APPLELINK_CURRENT_VERSION;, &cv-link-APPLELINK_NO_COMPATIBILITY_VERSION;, &cv-link-APPLELINK_NO_CURRENT_VERSION;, &cv-link-FRAMEWORKPATHPREFIX;, &cv-link-LDMODULECOM;, &cv-link-LDMODULEFLAGS;, &cv-link-LDMODULEPREFIX;, &cv-link-LDMODULESUFFIX;, &cv-link-LINKCOM;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;, &cv-link-_APPLELINK_COMPATIBILITY_VERSION;, &cv-link-_APPLELINK_CURRENT_VERSION;, &cv-link-_FRAMEWORKPATH;, &cv-link-_FRAMEWORKS;.Uses: &cv-link-FRAMEWORKSFLAGS;. + Sets: &cv-link-APPLELINK_COMPATIBILITY_VERSION;, &cv-link-APPLELINK_CURRENT_VERSION;, &cv-link-APPLELINK_NO_COMPATIBILITY_VERSION;, &cv-link-APPLELINK_NO_CURRENT_VERSION;, &cv-link-FRAMEWORKPATHPREFIX;, &cv-link-LDMODULECOM;, &cv-link-LDMODULEFLAGS;, &cv-link-LDMODULEPREFIX;, &cv-link-LDMODULESUFFIX;, &cv-link-LINKCOM;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;, &cv-link-_APPLELINK_COMPATIBILITY_VERSION;, &cv-link-_APPLELINK_CURRENT_VERSION;, &cv-link-_FRAMEWORKPATH;, &cv-link-_FRAMEWORKS;.Uses: &cv-link-FRAMEWORKSFLAGS;. ar - -Sets construction variables for the ar library archiver. + + +Sets construction variables for the ar library archiver. -Sets: &cv-link-AR;, &cv-link-ARCOM;, &cv-link-ARFLAGS;, &cv-link-LIBPREFIX;, &cv-link-LIBSUFFIX;, &cv-link-RANLIB;, &cv-link-RANLIBCOM;, &cv-link-RANLIBFLAGS;. +Sets: &cv-link-AR;, &cv-link-ARCOM;, &cv-link-ARFLAGS;, &cv-link-LIBPREFIX;, &cv-link-LIBSUFFIX;, &cv-link-RANLIB;, &cv-link-RANLIBCOM;, &cv-link-RANLIBFLAGS;. as - -Sets construction variables for the as assembler. + + +Sets construction variables for the as assembler. -Sets: &cv-link-AS;, &cv-link-ASCOM;, &cv-link-ASFLAGS;, &cv-link-ASPPCOM;, &cv-link-ASPPFLAGS;.Uses: &cv-link-CC;, &cv-link-CPPFLAGS;, &cv-link-_CPPDEFFLAGS;, &cv-link-_CPPINCFLAGS;. +Sets: &cv-link-AS;, &cv-link-ASCOM;, &cv-link-ASFLAGS;, &cv-link-ASPPCOM;, &cv-link-ASPPFLAGS;.Uses: &cv-link-CC;, &cv-link-CPPFLAGS;, &cv-link-_CPPDEFFLAGS;, &cv-link-_CPPINCFLAGS;. bcc32 - + + Sets construction variables for the bcc32 compiler. -Sets: &cv-link-CC;, &cv-link-CCCOM;, &cv-link-CCFLAGS;, &cv-link-CFILESUFFIX;, &cv-link-CFLAGS;, &cv-link-CPPDEFPREFIX;, &cv-link-CPPDEFSUFFIX;, &cv-link-INCPREFIX;, &cv-link-INCSUFFIX;, &cv-link-SHCC;, &cv-link-SHCCCOM;, &cv-link-SHCCFLAGS;, &cv-link-SHCFLAGS;, &cv-link-SHOBJSUFFIX;.Uses: &cv-link-_CPPDEFFLAGS;, &cv-link-_CPPINCFLAGS;. +Sets: &cv-link-CC;, &cv-link-CCCOM;, &cv-link-CCFLAGS;, &cv-link-CFILESUFFIX;, &cv-link-CFLAGS;, &cv-link-CPPDEFPREFIX;, &cv-link-CPPDEFSUFFIX;, &cv-link-INCPREFIX;, &cv-link-INCSUFFIX;, &cv-link-SHCC;, &cv-link-SHCCCOM;, &cv-link-SHCCFLAGS;, &cv-link-SHCFLAGS;, &cv-link-SHOBJSUFFIX;.Uses: &cv-link-_CPPDEFFLAGS;, &cv-link-_CPPINCFLAGS;. cc - + + Sets construction variables for generic POSIX C compilers. -Sets: &cv-link-CC;, &cv-link-CCCOM;, &cv-link-CCFLAGS;, &cv-link-CFILESUFFIX;, &cv-link-CFLAGS;, &cv-link-CPPDEFPREFIX;, &cv-link-CPPDEFSUFFIX;, &cv-link-FRAMEWORKPATH;, &cv-link-FRAMEWORKS;, &cv-link-INCPREFIX;, &cv-link-INCSUFFIX;, &cv-link-SHCC;, &cv-link-SHCCCOM;, &cv-link-SHCCFLAGS;, &cv-link-SHCFLAGS;, &cv-link-SHOBJSUFFIX;.Uses: &cv-link-PLATFORM;. +Sets: &cv-link-CC;, &cv-link-CCCOM;, &cv-link-CCFLAGS;, &cv-link-CFILESUFFIX;, &cv-link-CFLAGS;, &cv-link-CPPDEFPREFIX;, &cv-link-CPPDEFSUFFIX;, &cv-link-FRAMEWORKPATH;, &cv-link-FRAMEWORKS;, &cv-link-INCPREFIX;, &cv-link-INCSUFFIX;, &cv-link-SHCC;, &cv-link-SHCCCOM;, &cv-link-SHCCFLAGS;, &cv-link-SHCFLAGS;, &cv-link-SHOBJSUFFIX;.Uses: &cv-link-PLATFORM;. clang - + + Set construction variables for the Clang C compiler. -Sets: &cv-link-CC;, &cv-link-CCVERSION;, &cv-link-SHCCFLAGS;. +Sets: &cv-link-CC;, &cv-link-CCVERSION;, &cv-link-SHCCFLAGS;. clangxx - + + Set construction variables for the Clang C++ compiler. -Sets: &cv-link-CXX;, &cv-link-CXXVERSION;, &cv-link-SHCXXFLAGS;, &cv-link-SHOBJSUFFIX;, &cv-link-STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME;. +Sets: &cv-link-CXX;, &cv-link-CXXVERSION;, &cv-link-SHCXXFLAGS;, &cv-link-SHOBJSUFFIX;, &cv-link-STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME;. cvf - + + Sets construction variables for the Compaq Visual Fortran compiler. -Sets: &cv-link-FORTRAN;, &cv-link-FORTRANCOM;, &cv-link-FORTRANMODDIR;, &cv-link-FORTRANMODDIRPREFIX;, &cv-link-FORTRANMODDIRSUFFIX;, &cv-link-FORTRANPPCOM;, &cv-link-OBJSUFFIX;, &cv-link-SHFORTRANCOM;, &cv-link-SHFORTRANPPCOM;.Uses: &cv-link-CPPFLAGS;, &cv-link-FORTRANFLAGS;, &cv-link-SHFORTRANFLAGS;, &cv-link-_CPPDEFFLAGS;, &cv-link-_FORTRANINCFLAGS;, &cv-link-_FORTRANMODFLAG;. +Sets: &cv-link-FORTRAN;, &cv-link-FORTRANCOM;, &cv-link-FORTRANMODDIR;, &cv-link-FORTRANMODDIRPREFIX;, &cv-link-FORTRANMODDIRSUFFIX;, &cv-link-FORTRANPPCOM;, &cv-link-OBJSUFFIX;, &cv-link-SHFORTRANCOM;, &cv-link-SHFORTRANPPCOM;.Uses: &cv-link-CPPFLAGS;, &cv-link-FORTRANFLAGS;, &cv-link-SHFORTRANFLAGS;, &cv-link-_CPPDEFFLAGS;, &cv-link-_FORTRANINCFLAGS;, &cv-link-_FORTRANMODFLAG;. cXX - + + Sets construction variables for generic POSIX C++ compilers. -Sets: &cv-link-CPPDEFPREFIX;, &cv-link-CPPDEFSUFFIX;, &cv-link-CXX;, &cv-link-CXXCOM;, &cv-link-CXXFILESUFFIX;, &cv-link-CXXFLAGS;, &cv-link-INCPREFIX;, &cv-link-INCSUFFIX;, &cv-link-OBJSUFFIX;, &cv-link-SHCXX;, &cv-link-SHCXXCOM;, &cv-link-SHCXXFLAGS;, &cv-link-SHOBJSUFFIX;.Uses: &cv-link-CXXCOMSTR;. +Sets: &cv-link-CPPDEFPREFIX;, &cv-link-CPPDEFSUFFIX;, &cv-link-CXX;, &cv-link-CXXCOM;, &cv-link-CXXFILESUFFIX;, &cv-link-CXXFLAGS;, &cv-link-INCPREFIX;, &cv-link-INCSUFFIX;, &cv-link-OBJSUFFIX;, &cv-link-SHCXX;, &cv-link-SHCXXCOM;, &cv-link-SHCXXFLAGS;, &cv-link-SHOBJSUFFIX;.Uses: &cv-link-CXXCOMSTR;. cyglink - + + Set construction variables for cygwin linker/loader. -Sets: &cv-link-IMPLIBPREFIX;, &cv-link-IMPLIBSUFFIX;, &cv-link-LDMODULEVERSIONFLAGS;, &cv-link-LINKFLAGS;, &cv-link-RPATHPREFIX;, &cv-link-RPATHSUFFIX;, &cv-link-SHLIBPREFIX;, &cv-link-SHLIBSUFFIX;, &cv-link-SHLIBVERSIONFLAGS;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;, &cv-link-_LDMODULEVERSIONFLAGS;, &cv-link-_SHLIBVERSIONFLAGS;. +Sets: &cv-link-IMPLIBPREFIX;, &cv-link-IMPLIBSUFFIX;, &cv-link-LDMODULEVERSIONFLAGS;, &cv-link-LINKFLAGS;, &cv-link-RPATHPREFIX;, &cv-link-RPATHSUFFIX;, &cv-link-SHLIBPREFIX;, &cv-link-SHLIBSUFFIX;, &cv-link-SHLIBVERSIONFLAGS;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;, &cv-link-_LDMODULEVERSIONFLAGS;, &cv-link-_SHLIBVERSIONFLAGS;. default - -Sets construction variables for a default list of Tool modules. + + +Sets construction variables for a default list of Tool modules. Use default in the tools list to retain the original defaults, since the tools parameter is treated as a literal statement of the tools -to be made available in that construction environment, not an addition. +to be made available in that construction environment, not an addition. - + The list of tools selected by default is not static, but is dependent both on the platform and on the software installed on the platform. Some tools will not initialize if an underlying command is not found, and some tools are selected from a list of choices on a first-found basis. The finished tool list can be -examined by inspecting the TOOLS construction variable -in the construction environment. +examined by inspecting the TOOLS construction variable +in the construction environment. - + On all platforms, all tools from the following list are selected whose respective conditions are met: filesystem, wix, lex, yacc, rpcgen, swig, @@ -149,7 +166,7 @@ jar, javac, javah, rmic, dvipdf, dvips, gs, tex, latex, pdflatex, pdftex, tar, zip, textfile. - + On Linux systems, the default tools list selects (first-found): a C compiler from gcc, intelc, icc, cc; @@ -166,7 +183,7 @@ It also selects all found from the list m4, rpm. - + On Windows systems, the default tools list selects (first-found): a C compiler from msvc, mingw, gcc, intelc, icl, icc, cc, bcc32; @@ -184,7 +201,7 @@ It also selects all found from the list msvs, midl. - + On MacOS systems, the default tools list selects (first-found): a C compiler from gcc, cc; @@ -200,9 +217,9 @@ It also selects all found from the list m4, rpm. - + Default lists for other platforms can be found by -examining the scons +examining the scons source code (see SCons/Tool/__init__.py). @@ -211,14 +228,16 @@ source code (see dmd - + + Sets construction variables for D language compiler DMD. -Sets: &cv-link-DC;, &cv-link-DCOM;, &cv-link-DDEBUG;, &cv-link-DDEBUGPREFIX;, &cv-link-DDEBUGSUFFIX;, &cv-link-DFILESUFFIX;, &cv-link-DFLAGPREFIX;, &cv-link-DFLAGS;, &cv-link-DFLAGSUFFIX;, &cv-link-DINCPREFIX;, &cv-link-DINCSUFFIX;, &cv-link-DLIB;, &cv-link-DLIBCOM;, &cv-link-DLIBDIRPREFIX;, &cv-link-DLIBDIRSUFFIX;, &cv-link-DLIBFLAGPREFIX;, &cv-link-DLIBFLAGSUFFIX;, &cv-link-DLIBLINKPREFIX;, &cv-link-DLIBLINKSUFFIX;, &cv-link-DLINK;, &cv-link-DLINKCOM;, &cv-link-DLINKFLAGPREFIX;, &cv-link-DLINKFLAGS;, &cv-link-DLINKFLAGSUFFIX;, &cv-link-DPATH;, &cv-link-DRPATHPREFIX;, &cv-link-DRPATHSUFFIX;, &cv-link-DShLibSonameGenerator;, &cv-link-DVERPREFIX;, &cv-link-DVERSIONS;, &cv-link-DVERSUFFIX;, &cv-link-SHDC;, &cv-link-SHDCOM;, &cv-link-SHDLIBVERSION;, &cv-link-SHDLIBVERSIONFLAGS;, &cv-link-SHDLINK;, &cv-link-SHDLINKCOM;, &cv-link-SHDLINKFLAGS;. +Sets: &cv-link-DC;, &cv-link-DCOM;, &cv-link-DDEBUG;, &cv-link-DDEBUGPREFIX;, &cv-link-DDEBUGSUFFIX;, &cv-link-DFILESUFFIX;, &cv-link-DFLAGPREFIX;, &cv-link-DFLAGS;, &cv-link-DFLAGSUFFIX;, &cv-link-DINCPREFIX;, &cv-link-DINCSUFFIX;, &cv-link-DLIB;, &cv-link-DLIBCOM;, &cv-link-DLIBDIRPREFIX;, &cv-link-DLIBDIRSUFFIX;, &cv-link-DLIBFLAGPREFIX;, &cv-link-DLIBFLAGSUFFIX;, &cv-link-DLIBLINKPREFIX;, &cv-link-DLIBLINKSUFFIX;, &cv-link-DLINK;, &cv-link-DLINKCOM;, &cv-link-DLINKFLAGPREFIX;, &cv-link-DLINKFLAGS;, &cv-link-DLINKFLAGSUFFIX;, &cv-link-DPATH;, &cv-link-DRPATHPREFIX;, &cv-link-DRPATHSUFFIX;, &cv-link-DShLibSonameGenerator;, &cv-link-DVERPREFIX;, &cv-link-DVERSIONS;, &cv-link-DVERSUFFIX;, &cv-link-SHDC;, &cv-link-SHDCOM;, &cv-link-SHDLIBVERSION;, &cv-link-SHDLIBVERSIONFLAGS;, &cv-link-SHDLINK;, &cv-link-SHDLINKCOM;, &cv-link-SHDLINKFLAGS;. docbook - This tool tries to make working with Docbook in SCons a little easier. + +This tool tries to make working with Docbook in SCons a little easier. It provides several toolchains for creating different output formats, like HTML or PDF. Contained in the package is a distribution of the Docbook XSL stylesheets as of version 1.76.1. @@ -226,27 +245,27 @@ As long as you don't specify your own stylesheets for customization, these official versions are picked as default...which should reduce the inevitable setup hassles for you. -Implicit dependencies to images and XIncludes are detected automatically +Implicit dependencies to images and XIncludes are detected automatically if you meet the HTML requirements. The additional stylesheet utils/xmldepend.xsl by Paul DuBois is used for this purpose. -Note, that there is no support for XML catalog resolving offered! This tool calls +Note, that there is no support for XML catalog resolving offered! This tool calls the XSLT processors and PDF renderers with the stylesheets you specified, that's it. The rest lies in your hands and you still have to know what you're doing when resolving names via a catalog. -For activating the tool "docbook", you have to add its name to the Environment constructor, +For activating the tool "docbook", you have to add its name to the Environment constructor, like this -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) -On its startup, the Docbook tool tries to find a required xsltproc processor, and +On its startup, the Docbook tool tries to find a required xsltproc processor, and a PDF renderer, e.g. fop. So make sure that these are added to your system's environment PATH and can be called directly, without specifying their full path. -For the most basic processing of Docbook to HTML, you need to have installed +For the most basic processing of Docbook to HTML, you need to have installed -the Python lxml binding to libxml2, or +the Python lxml binding to libxml2, or the direct Python bindings for libxml2/libxslt, or @@ -257,49 +276,49 @@ and xalan. -Rendering to PDF requires you to have one of the applications +Rendering to PDF requires you to have one of the applications fop or xep installed. -Creating a HTML or PDF document is very simple and straightforward. Say +Creating a HTML or PDF document is very simple and straightforward. Say -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) env.DocbookHtml('manual.html', 'manual.xml') env.DocbookPdf('manual.pdf', 'manual.xml') -to get both outputs from your XML source manual.xml. As a shortcut, you can +to get both outputs from your XML source manual.xml. As a shortcut, you can give the stem of the filenames alone, like this: -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) env.DocbookHtml('manual') env.DocbookPdf('manual') -and get the same result. Target and source lists are also supported: +and get the same result. Target and source lists are also supported: -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) env.DocbookHtml(['manual.html','reference.html'], ['manual.xml','reference.xml']) -or even +or even -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) env.DocbookHtml(['manual','reference']) -Whenever you leave out the list of sources, you may not specify a file extension! The +Whenever you leave out the list of sources, you may not specify a file extension! The Tool uses the given names as file stems, and adds the suffixes for target and source files accordingly. -The rules given above are valid for the Builders DocbookHtml, -DocbookPdf, DocbookEpub, DocbookSlidesPdf and DocbookXInclude. For the -DocbookMan transformation you +The rules given above are valid for the Builders DocbookHtml, +DocbookPdf, DocbookEpub, DocbookSlidesPdf and DocbookXInclude. For the +DocbookMan transformation you can specify a target name, but the actual output names are automatically set from the refname entries in your XML source. -The Builders DocbookHtmlChunked, DocbookHtmlhelp and -DocbookSlidesHtml are special, in that: +The Builders DocbookHtmlChunked, DocbookHtmlhelp and +DocbookSlidesHtml are special, in that: -they create a large set of files, where the exact names and their number depend +they create a large set of files, where the exact names and their number depend on the content of the source file, and @@ -308,24 +327,24 @@ XSL transformation is not picked up by the stylesheets. -As a result, there is simply no use in specifying a target HTML name. +As a result, there is simply no use in specifying a target HTML name. So the basic syntax for these builders is always: -env = Environment(tools=['docbook']) +env = Environment(tools=['docbook']) env.DocbookHtmlhelp('manual') -If you want to use a specific XSL file, you can set the +If you want to use a specific XSL file, you can set the additional xsl parameter to your Builder call as follows: -env.DocbookHtml('other.html', 'manual.xml', xsl='html.xsl') +env.DocbookHtml('other.html', 'manual.xml', xsl='html.xsl') -Since this may get tedious if you always use the same local naming for your customized XSL files, +Since this may get tedious if you always use the same local naming for your customized XSL files, e.g. html.xsl for HTML and pdf.xsl for PDF output, a set of variables for setting the default XSL name is provided. These are: -DOCBOOK_DEFAULT_XSL_HTML +DOCBOOK_DEFAULT_XSL_HTML DOCBOOK_DEFAULT_XSL_HTMLCHUNKED DOCBOOK_DEFAULT_XSL_HTMLHELP DOCBOOK_DEFAULT_XSL_PDF @@ -334,656 +353,735 @@ DOCBOOK_DEFAULT_XSL_MAN DOCBOOK_DEFAULT_XSL_SLIDESPDF DOCBOOK_DEFAULT_XSL_SLIDESHTML -and you can set them when constructing your environment: +and you can set them when constructing your environment: -env = Environment(tools=['docbook'], +env = Environment(tools=['docbook'], DOCBOOK_DEFAULT_XSL_HTML='html.xsl', DOCBOOK_DEFAULT_XSL_PDF='pdf.xsl') env.DocbookHtml('manual') # now uses html.xsl -Sets: &cv-link-DOCBOOK_DEFAULT_XSL_EPUB;, &cv-link-DOCBOOK_DEFAULT_XSL_HTML;, &cv-link-DOCBOOK_DEFAULT_XSL_HTMLCHUNKED;, &cv-link-DOCBOOK_DEFAULT_XSL_HTMLHELP;, &cv-link-DOCBOOK_DEFAULT_XSL_MAN;, &cv-link-DOCBOOK_DEFAULT_XSL_PDF;, &cv-link-DOCBOOK_DEFAULT_XSL_SLIDESHTML;, &cv-link-DOCBOOK_DEFAULT_XSL_SLIDESPDF;, &cv-link-DOCBOOK_FOP;, &cv-link-DOCBOOK_FOPCOM;, &cv-link-DOCBOOK_FOPFLAGS;, &cv-link-DOCBOOK_XMLLINT;, &cv-link-DOCBOOK_XMLLINTCOM;, &cv-link-DOCBOOK_XMLLINTFLAGS;, &cv-link-DOCBOOK_XSLTPROC;, &cv-link-DOCBOOK_XSLTPROCCOM;, &cv-link-DOCBOOK_XSLTPROCFLAGS;, &cv-link-DOCBOOK_XSLTPROCPARAMS;.Uses: &cv-link-DOCBOOK_FOPCOMSTR;, &cv-link-DOCBOOK_XMLLINTCOMSTR;, &cv-link-DOCBOOK_XSLTPROCCOMSTR;. +Sets: &cv-link-DOCBOOK_DEFAULT_XSL_EPUB;, &cv-link-DOCBOOK_DEFAULT_XSL_HTML;, &cv-link-DOCBOOK_DEFAULT_XSL_HTMLCHUNKED;, &cv-link-DOCBOOK_DEFAULT_XSL_HTMLHELP;, &cv-link-DOCBOOK_DEFAULT_XSL_MAN;, &cv-link-DOCBOOK_DEFAULT_XSL_PDF;, &cv-link-DOCBOOK_DEFAULT_XSL_SLIDESHTML;, &cv-link-DOCBOOK_DEFAULT_XSL_SLIDESPDF;, &cv-link-DOCBOOK_FOP;, &cv-link-DOCBOOK_FOPCOM;, &cv-link-DOCBOOK_FOPFLAGS;, &cv-link-DOCBOOK_XMLLINT;, &cv-link-DOCBOOK_XMLLINTCOM;, &cv-link-DOCBOOK_XMLLINTFLAGS;, &cv-link-DOCBOOK_XSLTPROC;, &cv-link-DOCBOOK_XSLTPROCCOM;, &cv-link-DOCBOOK_XSLTPROCFLAGS;, &cv-link-DOCBOOK_XSLTPROCPARAMS;.Uses: &cv-link-DOCBOOK_FOPCOMSTR;, &cv-link-DOCBOOK_XMLLINTCOMSTR;, &cv-link-DOCBOOK_XSLTPROCCOMSTR;. dvi - -Attaches the DVI builder to the + + +Attaches the DVI builder to the construction environment. dvipdf - + + Sets construction variables for the dvipdf utility. -Sets: &cv-link-DVIPDF;, &cv-link-DVIPDFCOM;, &cv-link-DVIPDFFLAGS;.Uses: &cv-link-DVIPDFCOMSTR;. +Sets: &cv-link-DVIPDF;, &cv-link-DVIPDFCOM;, &cv-link-DVIPDFFLAGS;.Uses: &cv-link-DVIPDFCOMSTR;. dvips - + + Sets construction variables for the dvips utility. -Sets: &cv-link-DVIPS;, &cv-link-DVIPSFLAGS;, &cv-link-PSCOM;, &cv-link-PSPREFIX;, &cv-link-PSSUFFIX;.Uses: &cv-link-PSCOMSTR;. +Sets: &cv-link-DVIPS;, &cv-link-DVIPSFLAGS;, &cv-link-PSCOM;, &cv-link-PSPREFIX;, &cv-link-PSSUFFIX;.Uses: &cv-link-PSCOMSTR;. f03 - + + Set construction variables for generic POSIX Fortran 03 compilers. -Sets: &cv-link-F03;, &cv-link-F03COM;, &cv-link-F03FLAGS;, &cv-link-F03PPCOM;, &cv-link-SHF03;, &cv-link-SHF03COM;, &cv-link-SHF03FLAGS;, &cv-link-SHF03PPCOM;, &cv-link-_F03INCFLAGS;.Uses: &cv-link-F03COMSTR;, &cv-link-F03PPCOMSTR;, &cv-link-SHF03COMSTR;, &cv-link-SHF03PPCOMSTR;. +Sets: &cv-link-F03;, &cv-link-F03COM;, &cv-link-F03FLAGS;, &cv-link-F03PPCOM;, &cv-link-SHF03;, &cv-link-SHF03COM;, &cv-link-SHF03FLAGS;, &cv-link-SHF03PPCOM;, &cv-link-_F03INCFLAGS;.Uses: &cv-link-F03COMSTR;, &cv-link-F03PPCOMSTR;, &cv-link-SHF03COMSTR;, &cv-link-SHF03PPCOMSTR;. f08 - + + Set construction variables for generic POSIX Fortran 08 compilers. -Sets: &cv-link-F08;, &cv-link-F08COM;, &cv-link-F08FLAGS;, &cv-link-F08PPCOM;, &cv-link-SHF08;, &cv-link-SHF08COM;, &cv-link-SHF08FLAGS;, &cv-link-SHF08PPCOM;, &cv-link-_F08INCFLAGS;.Uses: &cv-link-F08COMSTR;, &cv-link-F08PPCOMSTR;, &cv-link-SHF08COMSTR;, &cv-link-SHF08PPCOMSTR;. +Sets: &cv-link-F08;, &cv-link-F08COM;, &cv-link-F08FLAGS;, &cv-link-F08PPCOM;, &cv-link-SHF08;, &cv-link-SHF08COM;, &cv-link-SHF08FLAGS;, &cv-link-SHF08PPCOM;, &cv-link-_F08INCFLAGS;.Uses: &cv-link-F08COMSTR;, &cv-link-F08PPCOMSTR;, &cv-link-SHF08COMSTR;, &cv-link-SHF08PPCOMSTR;. f77 - + + Set construction variables for generic POSIX Fortran 77 compilers. -Sets: &cv-link-F77;, &cv-link-F77COM;, &cv-link-F77FILESUFFIXES;, &cv-link-F77FLAGS;, &cv-link-F77PPCOM;, &cv-link-F77PPFILESUFFIXES;, &cv-link-FORTRAN;, &cv-link-FORTRANCOM;, &cv-link-FORTRANFLAGS;, &cv-link-SHF77;, &cv-link-SHF77COM;, &cv-link-SHF77FLAGS;, &cv-link-SHF77PPCOM;, &cv-link-SHFORTRAN;, &cv-link-SHFORTRANCOM;, &cv-link-SHFORTRANFLAGS;, &cv-link-SHFORTRANPPCOM;, &cv-link-_F77INCFLAGS;.Uses: &cv-link-F77COMSTR;, &cv-link-F77PPCOMSTR;, &cv-link-FORTRANCOMSTR;, &cv-link-FORTRANPPCOMSTR;, &cv-link-SHF77COMSTR;, &cv-link-SHF77PPCOMSTR;, &cv-link-SHFORTRANCOMSTR;, &cv-link-SHFORTRANPPCOMSTR;. +Sets: &cv-link-F77;, &cv-link-F77COM;, &cv-link-F77FILESUFFIXES;, &cv-link-F77FLAGS;, &cv-link-F77PPCOM;, &cv-link-F77PPFILESUFFIXES;, &cv-link-FORTRAN;, &cv-link-FORTRANCOM;, &cv-link-FORTRANFLAGS;, &cv-link-SHF77;, &cv-link-SHF77COM;, &cv-link-SHF77FLAGS;, &cv-link-SHF77PPCOM;, &cv-link-SHFORTRAN;, &cv-link-SHFORTRANCOM;, &cv-link-SHFORTRANFLAGS;, &cv-link-SHFORTRANPPCOM;, &cv-link-_F77INCFLAGS;.Uses: &cv-link-F77COMSTR;, &cv-link-F77PPCOMSTR;, &cv-link-FORTRANCOMSTR;, &cv-link-FORTRANPPCOMSTR;, &cv-link-SHF77COMSTR;, &cv-link-SHF77PPCOMSTR;, &cv-link-SHFORTRANCOMSTR;, &cv-link-SHFORTRANPPCOMSTR;. f90 - + + Set construction variables for generic POSIX Fortran 90 compilers. -Sets: &cv-link-F90;, &cv-link-F90COM;, &cv-link-F90FLAGS;, &cv-link-F90PPCOM;, &cv-link-SHF90;, &cv-link-SHF90COM;, &cv-link-SHF90FLAGS;, &cv-link-SHF90PPCOM;, &cv-link-_F90INCFLAGS;.Uses: &cv-link-F90COMSTR;, &cv-link-F90PPCOMSTR;, &cv-link-SHF90COMSTR;, &cv-link-SHF90PPCOMSTR;. +Sets: &cv-link-F90;, &cv-link-F90COM;, &cv-link-F90FLAGS;, &cv-link-F90PPCOM;, &cv-link-SHF90;, &cv-link-SHF90COM;, &cv-link-SHF90FLAGS;, &cv-link-SHF90PPCOM;, &cv-link-_F90INCFLAGS;.Uses: &cv-link-F90COMSTR;, &cv-link-F90PPCOMSTR;, &cv-link-SHF90COMSTR;, &cv-link-SHF90PPCOMSTR;. f95 - + + Set construction variables for generic POSIX Fortran 95 compilers. -Sets: &cv-link-F95;, &cv-link-F95COM;, &cv-link-F95FLAGS;, &cv-link-F95PPCOM;, &cv-link-SHF95;, &cv-link-SHF95COM;, &cv-link-SHF95FLAGS;, &cv-link-SHF95PPCOM;, &cv-link-_F95INCFLAGS;.Uses: &cv-link-F95COMSTR;, &cv-link-F95PPCOMSTR;, &cv-link-SHF95COMSTR;, &cv-link-SHF95PPCOMSTR;. +Sets: &cv-link-F95;, &cv-link-F95COM;, &cv-link-F95FLAGS;, &cv-link-F95PPCOM;, &cv-link-SHF95;, &cv-link-SHF95COM;, &cv-link-SHF95FLAGS;, &cv-link-SHF95PPCOM;, &cv-link-_F95INCFLAGS;.Uses: &cv-link-F95COMSTR;, &cv-link-F95PPCOMSTR;, &cv-link-SHF95COMSTR;, &cv-link-SHF95PPCOMSTR;. fortran - + + Set construction variables for generic POSIX Fortran compilers. -Sets: &cv-link-FORTRAN;, &cv-link-FORTRANCOM;, &cv-link-FORTRANFLAGS;, &cv-link-SHFORTRAN;, &cv-link-SHFORTRANCOM;, &cv-link-SHFORTRANFLAGS;, &cv-link-SHFORTRANPPCOM;.Uses: &cv-link-FORTRANCOMSTR;, &cv-link-FORTRANPPCOMSTR;, &cv-link-SHFORTRANCOMSTR;, &cv-link-SHFORTRANPPCOMSTR;. +Sets: &cv-link-FORTRAN;, &cv-link-FORTRANCOM;, &cv-link-FORTRANFLAGS;, &cv-link-SHFORTRAN;, &cv-link-SHFORTRANCOM;, &cv-link-SHFORTRANFLAGS;, &cv-link-SHFORTRANPPCOM;.Uses: &cv-link-FORTRANCOMSTR;, &cv-link-FORTRANPPCOMSTR;, &cv-link-SHFORTRANCOMSTR;, &cv-link-SHFORTRANPPCOMSTR;. g++ - -Set construction variables for the gXX C++ compiler. + + +Set construction variables for the gXX C++ compiler. -Sets: &cv-link-CXX;, &cv-link-CXXVERSION;, &cv-link-SHCXXFLAGS;, &cv-link-SHOBJSUFFIX;. +Sets: &cv-link-CXX;, &cv-link-CXXVERSION;, &cv-link-SHCXXFLAGS;, &cv-link-SHOBJSUFFIX;. g77 - -Set construction variables for the g77 Fortran compiler. -Calls the f77 Tool module + + +Set construction variables for the g77 Fortran compiler. +Calls the f77 Tool module to set variables. gas - -Sets construction variables for the gas assembler. -Calls the as module. + + +Sets construction variables for the gas assembler. +Calls the as module. -Sets: &cv-link-AS;. +Sets: &cv-link-AS;. gcc - -Set construction variables for the gcc C compiler. + + +Set construction variables for the gcc C compiler. -Sets: &cv-link-CC;, &cv-link-CCVERSION;, &cv-link-SHCCFLAGS;. +Sets: &cv-link-CC;, &cv-link-CCVERSION;, &cv-link-SHCCFLAGS;. gdc - + + Sets construction variables for the D language compiler GDC. -Sets: &cv-link-DC;, &cv-link-DCOM;, &cv-link-DDEBUG;, &cv-link-DDEBUGPREFIX;, &cv-link-DDEBUGSUFFIX;, &cv-link-DFILESUFFIX;, &cv-link-DFLAGPREFIX;, &cv-link-DFLAGS;, &cv-link-DFLAGSUFFIX;, &cv-link-DINCPREFIX;, &cv-link-DINCSUFFIX;, &cv-link-DLIB;, &cv-link-DLIBCOM;, &cv-link-DLIBDIRPREFIX;, &cv-link-DLIBDIRSUFFIX;, &cv-link-DLIBFLAGPREFIX;, &cv-link-DLIBFLAGSUFFIX;, &cv-link-DLIBLINKPREFIX;, &cv-link-DLIBLINKSUFFIX;, &cv-link-DLINK;, &cv-link-DLINKCOM;, &cv-link-DLINKFLAGPREFIX;, &cv-link-DLINKFLAGS;, &cv-link-DLINKFLAGSUFFIX;, &cv-link-DPATH;, &cv-link-DRPATHPREFIX;, &cv-link-DRPATHSUFFIX;, &cv-link-DShLibSonameGenerator;, &cv-link-DVERPREFIX;, &cv-link-DVERSIONS;, &cv-link-DVERSUFFIX;, &cv-link-SHDC;, &cv-link-SHDCOM;, &cv-link-SHDLIBVERSION;, &cv-link-SHDLIBVERSIONFLAGS;, &cv-link-SHDLINK;, &cv-link-SHDLINKCOM;, &cv-link-SHDLINKFLAGS;. +Sets: &cv-link-DC;, &cv-link-DCOM;, &cv-link-DDEBUG;, &cv-link-DDEBUGPREFIX;, &cv-link-DDEBUGSUFFIX;, &cv-link-DFILESUFFIX;, &cv-link-DFLAGPREFIX;, &cv-link-DFLAGS;, &cv-link-DFLAGSUFFIX;, &cv-link-DINCPREFIX;, &cv-link-DINCSUFFIX;, &cv-link-DLIB;, &cv-link-DLIBCOM;, &cv-link-DLIBDIRPREFIX;, &cv-link-DLIBDIRSUFFIX;, &cv-link-DLIBFLAGPREFIX;, &cv-link-DLIBFLAGSUFFIX;, &cv-link-DLIBLINKPREFIX;, &cv-link-DLIBLINKSUFFIX;, &cv-link-DLINK;, &cv-link-DLINKCOM;, &cv-link-DLINKFLAGPREFIX;, &cv-link-DLINKFLAGS;, &cv-link-DLINKFLAGSUFFIX;, &cv-link-DPATH;, &cv-link-DRPATHPREFIX;, &cv-link-DRPATHSUFFIX;, &cv-link-DShLibSonameGenerator;, &cv-link-DVERPREFIX;, &cv-link-DVERSIONS;, &cv-link-DVERSUFFIX;, &cv-link-SHDC;, &cv-link-SHDCOM;, &cv-link-SHDLIBVERSION;, &cv-link-SHDLIBVERSIONFLAGS;, &cv-link-SHDLINK;, &cv-link-SHDLINKCOM;, &cv-link-SHDLINKFLAGS;. gettext - + + This is actually a toolset, which supports internationalization and localization of software being constructed with SCons. The toolset loads following tools: - + - xgettext - to extract internationalized messages from source code to + xgettext - to extract internationalized messages from source code to POT file(s), - msginit - may be optionally used to initialize PO + msginit - may be optionally used to initialize PO files, - msgmerge - to update PO files, that already contain + msgmerge - to update PO files, that already contain translated messages, - msgfmt - to compile textual PO file to binary + msgfmt - to compile textual PO file to binary installable MO file. - -When you enable gettext, it internally loads all abovementioned tools, + +When you enable gettext, it internally loads all abovementioned tools, so you're encouraged to see their individual documentation. - + Each of the above tools provides its own builder(s) which may be used to perform particular activities related to software internationalization. You may be however interested in top-level builder -Translate described few paragraphs later. +Translate described few paragraphs later. - -To use gettext tools add 'gettext' tool to your + +To use gettext tools add 'gettext' tool to your environment: - + env = Environment( tools = ['default', 'gettext'] ) gfortran - + + Sets construction variables for the GNU F95/F2003 GNU compiler. -Sets: &cv-link-F77;, &cv-link-F90;, &cv-link-F95;, &cv-link-FORTRAN;, &cv-link-SHF77;, &cv-link-SHF77FLAGS;, &cv-link-SHF90;, &cv-link-SHF90FLAGS;, &cv-link-SHF95;, &cv-link-SHF95FLAGS;, &cv-link-SHFORTRAN;, &cv-link-SHFORTRANFLAGS;. +Sets: &cv-link-F77;, &cv-link-F90;, &cv-link-F95;, &cv-link-FORTRAN;, &cv-link-SHF77;, &cv-link-SHF77FLAGS;, &cv-link-SHF90;, &cv-link-SHF90FLAGS;, &cv-link-SHF95;, &cv-link-SHF95FLAGS;, &cv-link-SHFORTRAN;, &cv-link-SHFORTRANFLAGS;. gnulink - + + Set construction variables for GNU linker/loader. -Sets: &cv-link-LDMODULEVERSIONFLAGS;, &cv-link-RPATHPREFIX;, &cv-link-RPATHSUFFIX;, &cv-link-SHLIBVERSIONFLAGS;, &cv-link-SHLINKFLAGS;, &cv-link-_LDMODULESONAME;, &cv-link-_SHLIBSONAME;. +Sets: &cv-link-LDMODULEVERSIONFLAGS;, &cv-link-RPATHPREFIX;, &cv-link-RPATHSUFFIX;, &cv-link-SHLIBVERSIONFLAGS;, &cv-link-SHLINKFLAGS;, &cv-link-_LDMODULESONAME;, &cv-link-_SHLIBSONAME;. gs - + + This Tool sets the required construction variables for working with the Ghostscript command. It also registers an appropriate Action -with the PDF Builder (PDF), such that the conversion from +with the PDF Builder (PDF), such that the conversion from PS/EPS to PDF happens automatically for the TeX/LaTeX toolchain. -Finally, it adds an explicit Ghostscript Builder (Gs) to the +Finally, it adds an explicit Ghostscript Builder (Gs) to the environment. -Sets: &cv-link-GS;, &cv-link-GSCOM;, &cv-link-GSFLAGS;.Uses: &cv-link-GSCOMSTR;. +Sets: &cv-link-GS;, &cv-link-GSCOM;, &cv-link-GSFLAGS;.Uses: &cv-link-GSCOMSTR;. hpc++ - + + Set construction variables for the compilers aCC on HP/UX systems. hpcc - + + Set construction variables for the aCC on HP/UX systems. -Calls the cXX tool for additional variables. +Calls the cXX tool for additional variables. -Sets: &cv-link-CXX;, &cv-link-CXXVERSION;, &cv-link-SHCXXFLAGS;. +Sets: &cv-link-CXX;, &cv-link-CXXVERSION;, &cv-link-SHCXXFLAGS;. hplink - + + Sets construction variables for the linker on HP/UX systems. -Sets: &cv-link-LINKFLAGS;, &cv-link-SHLIBSUFFIX;, &cv-link-SHLINKFLAGS;. +Sets: &cv-link-LINKFLAGS;, &cv-link-SHLIBSUFFIX;, &cv-link-SHLINKFLAGS;. icc - + + Sets construction variables for the icc compiler on OS/2 systems. -Sets: &cv-link-CC;, &cv-link-CCCOM;, &cv-link-CFILESUFFIX;, &cv-link-CPPDEFPREFIX;, &cv-link-CPPDEFSUFFIX;, &cv-link-CXXCOM;, &cv-link-CXXFILESUFFIX;, &cv-link-INCPREFIX;, &cv-link-INCSUFFIX;.Uses: &cv-link-CCFLAGS;, &cv-link-CFLAGS;, &cv-link-CPPFLAGS;, &cv-link-_CPPDEFFLAGS;, &cv-link-_CPPINCFLAGS;. +Sets: &cv-link-CC;, &cv-link-CCCOM;, &cv-link-CFILESUFFIX;, &cv-link-CPPDEFPREFIX;, &cv-link-CPPDEFSUFFIX;, &cv-link-CXXCOM;, &cv-link-CXXFILESUFFIX;, &cv-link-INCPREFIX;, &cv-link-INCSUFFIX;.Uses: &cv-link-CCFLAGS;, &cv-link-CFLAGS;, &cv-link-CPPFLAGS;, &cv-link-_CPPDEFFLAGS;, &cv-link-_CPPINCFLAGS;. icl - + + Sets construction variables for the Intel C/C++ compiler. -Calls the intelc Tool module to set its variables. +Calls the intelc Tool module to set its variables. ifl - + + Sets construction variables for the Intel Fortran compiler. -Sets: &cv-link-FORTRAN;, &cv-link-FORTRANCOM;, &cv-link-FORTRANPPCOM;, &cv-link-SHFORTRANCOM;, &cv-link-SHFORTRANPPCOM;.Uses: &cv-link-CPPFLAGS;, &cv-link-FORTRANFLAGS;, &cv-link-_CPPDEFFLAGS;, &cv-link-_FORTRANINCFLAGS;. +Sets: &cv-link-FORTRAN;, &cv-link-FORTRANCOM;, &cv-link-FORTRANPPCOM;, &cv-link-SHFORTRANCOM;, &cv-link-SHFORTRANPPCOM;.Uses: &cv-link-CPPFLAGS;, &cv-link-FORTRANFLAGS;, &cv-link-_CPPDEFFLAGS;, &cv-link-_FORTRANINCFLAGS;. ifort - + + Sets construction variables for newer versions of the Intel Fortran compiler for Linux. -Sets: &cv-link-F77;, &cv-link-F90;, &cv-link-F95;, &cv-link-FORTRAN;, &cv-link-SHF77;, &cv-link-SHF77FLAGS;, &cv-link-SHF90;, &cv-link-SHF90FLAGS;, &cv-link-SHF95;, &cv-link-SHF95FLAGS;, &cv-link-SHFORTRAN;, &cv-link-SHFORTRANFLAGS;. +Sets: &cv-link-F77;, &cv-link-F90;, &cv-link-F95;, &cv-link-FORTRAN;, &cv-link-SHF77;, &cv-link-SHF77FLAGS;, &cv-link-SHF90;, &cv-link-SHF90FLAGS;, &cv-link-SHF95;, &cv-link-SHF95FLAGS;, &cv-link-SHFORTRAN;, &cv-link-SHFORTRANFLAGS;. ilink - + + Sets construction variables for the ilink linker on OS/2 systems. -Sets: &cv-link-LIBDIRPREFIX;, &cv-link-LIBDIRSUFFIX;, &cv-link-LIBLINKPREFIX;, &cv-link-LIBLINKSUFFIX;, &cv-link-LINK;, &cv-link-LINKCOM;, &cv-link-LINKFLAGS;. +Sets: &cv-link-LIBDIRPREFIX;, &cv-link-LIBDIRSUFFIX;, &cv-link-LIBLINKPREFIX;, &cv-link-LIBLINKSUFFIX;, &cv-link-LINK;, &cv-link-LINKCOM;, &cv-link-LINKFLAGS;. ilink32 - + + Sets construction variables for the Borland ilink32 linker. -Sets: &cv-link-LIBDIRPREFIX;, &cv-link-LIBDIRSUFFIX;, &cv-link-LIBLINKPREFIX;, &cv-link-LIBLINKSUFFIX;, &cv-link-LINK;, &cv-link-LINKCOM;, &cv-link-LINKFLAGS;. +Sets: &cv-link-LIBDIRPREFIX;, &cv-link-LIBDIRSUFFIX;, &cv-link-LIBLINKPREFIX;, &cv-link-LIBLINKSUFFIX;, &cv-link-LINK;, &cv-link-LINKCOM;, &cv-link-LINKFLAGS;. install - + + Sets construction variables for file and directory installation. -Sets: &cv-link-INSTALL;, &cv-link-INSTALLSTR;. +Sets: &cv-link-INSTALL;, &cv-link-INSTALLSTR;. intelc - + + Sets construction variables for the Intel C/C++ compiler (Linux and Windows, version 7 and later). -Calls the gcc or msvc +Calls the gcc or msvc (on Linux and Windows, respectively) to set underlying variables. -Sets: &cv-link-AR;, &cv-link-CC;, &cv-link-CXX;, &cv-link-INTEL_C_COMPILER_VERSION;, &cv-link-LINK;. +Sets: &cv-link-AR;, &cv-link-CC;, &cv-link-CXX;, &cv-link-INTEL_C_COMPILER_VERSION;, &cv-link-LINK;. jar - -Sets construction variables for the jar utility. + + +Sets construction variables for the jar utility. -Sets: &cv-link-JAR;, &cv-link-JARCOM;, &cv-link-JARFLAGS;, &cv-link-JARSUFFIX;.Uses: &cv-link-JARCOMSTR;. +Sets: &cv-link-JAR;, &cv-link-JARCOM;, &cv-link-JARFLAGS;, &cv-link-JARSUFFIX;.Uses: &cv-link-JARCOMSTR;. javac - - Sets construction variables for the javac compiler. + + + Sets construction variables for the javac compiler. - Sets: &cv-link-JAVABOOTCLASSPATH;, &cv-link-JAVAC;, &cv-link-JAVACCOM;, &cv-link-JAVACFLAGS;, &cv-link-JAVACLASSPATH;, &cv-link-JAVACLASSSUFFIX;, &cv-link-JAVAINCLUDES;, &cv-link-JAVASOURCEPATH;, &cv-link-JAVASUFFIX;.Uses: &cv-link-JAVACCOMSTR;. + Sets: &cv-link-JAVABOOTCLASSPATH;, &cv-link-JAVAC;, &cv-link-JAVACCOM;, &cv-link-JAVACFLAGS;, &cv-link-JAVACLASSPATH;, &cv-link-JAVACLASSSUFFIX;, &cv-link-JAVAINCLUDES;, &cv-link-JAVASOURCEPATH;, &cv-link-JAVASUFFIX;.Uses: &cv-link-JAVACCOMSTR;. javah - -Sets construction variables for the javah tool. + + +Sets construction variables for the javah tool. -Sets: &cv-link-JAVACLASSSUFFIX;, &cv-link-JAVAH;, &cv-link-JAVAHCOM;, &cv-link-JAVAHFLAGS;.Uses: &cv-link-JAVACLASSPATH;, &cv-link-JAVAHCOMSTR;. +Sets: &cv-link-JAVACLASSSUFFIX;, &cv-link-JAVAH;, &cv-link-JAVAHCOM;, &cv-link-JAVAHFLAGS;.Uses: &cv-link-JAVACLASSPATH;, &cv-link-JAVAHCOMSTR;. latex - -Sets construction variables for the latex utility. + + +Sets construction variables for the latex utility. -Sets: &cv-link-LATEX;, &cv-link-LATEXCOM;, &cv-link-LATEXFLAGS;.Uses: &cv-link-LATEXCOMSTR;. +Sets: &cv-link-LATEX;, &cv-link-LATEXCOM;, &cv-link-LATEXFLAGS;.Uses: &cv-link-LATEXCOMSTR;. ldc - + + Sets construction variables for the D language compiler LDC2. -Sets: &cv-link-DC;, &cv-link-DCOM;, &cv-link-DDEBUG;, &cv-link-DDEBUGPREFIX;, &cv-link-DDEBUGSUFFIX;, &cv-link-DFILESUFFIX;, &cv-link-DFLAGPREFIX;, &cv-link-DFLAGS;, &cv-link-DFLAGSUFFIX;, &cv-link-DINCPREFIX;, &cv-link-DINCSUFFIX;, &cv-link-DLIB;, &cv-link-DLIBCOM;, &cv-link-DLIBDIRPREFIX;, &cv-link-DLIBDIRSUFFIX;, &cv-link-DLIBFLAGPREFIX;, &cv-link-DLIBFLAGSUFFIX;, &cv-link-DLIBLINKPREFIX;, &cv-link-DLIBLINKSUFFIX;, &cv-link-DLINK;, &cv-link-DLINKCOM;, &cv-link-DLINKFLAGPREFIX;, &cv-link-DLINKFLAGS;, &cv-link-DLINKFLAGSUFFIX;, &cv-link-DPATH;, &cv-link-DRPATHPREFIX;, &cv-link-DRPATHSUFFIX;, &cv-link-DShLibSonameGenerator;, &cv-link-DVERPREFIX;, &cv-link-DVERSIONS;, &cv-link-DVERSUFFIX;, &cv-link-SHDC;, &cv-link-SHDCOM;, &cv-link-SHDLIBVERSION;, &cv-link-SHDLIBVERSIONFLAGS;, &cv-link-SHDLINK;, &cv-link-SHDLINKCOM;, &cv-link-SHDLINKFLAGS;. +Sets: &cv-link-DC;, &cv-link-DCOM;, &cv-link-DDEBUG;, &cv-link-DDEBUGPREFIX;, &cv-link-DDEBUGSUFFIX;, &cv-link-DFILESUFFIX;, &cv-link-DFLAGPREFIX;, &cv-link-DFLAGS;, &cv-link-DFLAGSUFFIX;, &cv-link-DINCPREFIX;, &cv-link-DINCSUFFIX;, &cv-link-DLIB;, &cv-link-DLIBCOM;, &cv-link-DLIBDIRPREFIX;, &cv-link-DLIBDIRSUFFIX;, &cv-link-DLIBFLAGPREFIX;, &cv-link-DLIBFLAGSUFFIX;, &cv-link-DLIBLINKPREFIX;, &cv-link-DLIBLINKSUFFIX;, &cv-link-DLINK;, &cv-link-DLINKCOM;, &cv-link-DLINKFLAGPREFIX;, &cv-link-DLINKFLAGS;, &cv-link-DLINKFLAGSUFFIX;, &cv-link-DPATH;, &cv-link-DRPATHPREFIX;, &cv-link-DRPATHSUFFIX;, &cv-link-DShLibSonameGenerator;, &cv-link-DVERPREFIX;, &cv-link-DVERSIONS;, &cv-link-DVERSUFFIX;, &cv-link-SHDC;, &cv-link-SHDCOM;, &cv-link-SHDLIBVERSION;, &cv-link-SHDLIBVERSIONFLAGS;, &cv-link-SHDLINK;, &cv-link-SHDLINKCOM;, &cv-link-SHDLINKFLAGS;. lex - -Sets construction variables for the lex lexical analyser. + + +Sets construction variables for the lex lexical analyser. -Sets: &cv-link-LEX;, &cv-link-LEXCOM;, &cv-link-LEXFLAGS;, &cv-link-LEXUNISTD;.Uses: &cv-link-LEXCOMSTR;. +Sets: &cv-link-LEX;, &cv-link-LEXCOM;, &cv-link-LEXFLAGS;, &cv-link-LEXUNISTD;.Uses: &cv-link-LEXCOMSTR;. link - + + Sets construction variables for generic POSIX linkers. This is a "smart" linker tool which selects a compiler to complete the linking based on the types of source files. -Sets: &cv-link-LDMODULE;, &cv-link-LDMODULECOM;, &cv-link-LDMODULEFLAGS;, &cv-link-LDMODULENOVERSIONSYMLINKS;, &cv-link-LDMODULEPREFIX;, &cv-link-LDMODULESUFFIX;, &cv-link-LDMODULEVERSION;, &cv-link-LDMODULEVERSIONFLAGS;, &cv-link-LIBDIRPREFIX;, &cv-link-LIBDIRSUFFIX;, &cv-link-LIBLINKPREFIX;, &cv-link-LIBLINKSUFFIX;, &cv-link-LINK;, &cv-link-LINKCOM;, &cv-link-LINKFLAGS;, &cv-link-SHLIBSUFFIX;, &cv-link-SHLINK;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;, &cv-link-__LDMODULEVERSIONFLAGS;, &cv-link-__SHLIBVERSIONFLAGS;.Uses: &cv-link-LDMODULECOMSTR;, &cv-link-LINKCOMSTR;, &cv-link-SHLINKCOMSTR;. +Sets: &cv-link-LDMODULE;, &cv-link-LDMODULECOM;, &cv-link-LDMODULEFLAGS;, &cv-link-LDMODULENOVERSIONSYMLINKS;, &cv-link-LDMODULEPREFIX;, &cv-link-LDMODULESUFFIX;, &cv-link-LDMODULEVERSION;, &cv-link-LDMODULEVERSIONFLAGS;, &cv-link-LIBDIRPREFIX;, &cv-link-LIBDIRSUFFIX;, &cv-link-LIBLINKPREFIX;, &cv-link-LIBLINKSUFFIX;, &cv-link-LINK;, &cv-link-LINKCOM;, &cv-link-LINKFLAGS;, &cv-link-SHLIBSUFFIX;, &cv-link-SHLINK;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;, &cv-link-__LDMODULEVERSIONFLAGS;, &cv-link-__SHLIBVERSIONFLAGS;.Uses: &cv-link-LDMODULECOMSTR;, &cv-link-LINKCOMSTR;, &cv-link-SHLINKCOMSTR;. linkloc - + + Sets construction variables for the LinkLoc linker for the Phar Lap ETS embedded operating system. -Sets: &cv-link-LIBDIRPREFIX;, &cv-link-LIBDIRSUFFIX;, &cv-link-LIBLINKPREFIX;, &cv-link-LIBLINKSUFFIX;, &cv-link-LINK;, &cv-link-LINKCOM;, &cv-link-LINKFLAGS;, &cv-link-SHLINK;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;.Uses: &cv-link-LINKCOMSTR;, &cv-link-SHLINKCOMSTR;. +Sets: &cv-link-LIBDIRPREFIX;, &cv-link-LIBDIRSUFFIX;, &cv-link-LIBLINKPREFIX;, &cv-link-LIBLINKSUFFIX;, &cv-link-LINK;, &cv-link-LINKCOM;, &cv-link-LINKFLAGS;, &cv-link-SHLINK;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;.Uses: &cv-link-LINKCOMSTR;, &cv-link-SHLINKCOMSTR;. m4 - -Sets construction variables for the m4 macro processor. + + +Sets construction variables for the m4 macro processor. -Sets: &cv-link-M4;, &cv-link-M4COM;, &cv-link-M4FLAGS;.Uses: &cv-link-M4COMSTR;. +Sets: &cv-link-M4;, &cv-link-M4COM;, &cv-link-M4FLAGS;.Uses: &cv-link-M4COMSTR;. masm - + + Sets construction variables for the Microsoft assembler. -Sets: &cv-link-AS;, &cv-link-ASCOM;, &cv-link-ASFLAGS;, &cv-link-ASPPCOM;, &cv-link-ASPPFLAGS;.Uses: &cv-link-ASCOMSTR;, &cv-link-ASPPCOMSTR;, &cv-link-CPPFLAGS;, &cv-link-_CPPDEFFLAGS;, &cv-link-_CPPINCFLAGS;. +Sets: &cv-link-AS;, &cv-link-ASCOM;, &cv-link-ASFLAGS;, &cv-link-ASPPCOM;, &cv-link-ASPPFLAGS;.Uses: &cv-link-ASCOMSTR;, &cv-link-ASPPCOMSTR;, &cv-link-CPPFLAGS;, &cv-link-_CPPDEFFLAGS;, &cv-link-_CPPINCFLAGS;. midl - + + Sets construction variables for the Microsoft IDL compiler. -Sets: &cv-link-MIDL;, &cv-link-MIDLCOM;, &cv-link-MIDLFLAGS;.Uses: &cv-link-MIDLCOMSTR;. +Sets: &cv-link-MIDL;, &cv-link-MIDLCOM;, &cv-link-MIDLFLAGS;.Uses: &cv-link-MIDLCOMSTR;. mingw - + + Sets construction variables for MinGW (Minimal Gnu on Windows). -Sets: &cv-link-AS;, &cv-link-CC;, &cv-link-CXX;, &cv-link-LDMODULECOM;, &cv-link-LIBPREFIX;, &cv-link-LIBSUFFIX;, &cv-link-OBJSUFFIX;, &cv-link-RC;, &cv-link-RCCOM;, &cv-link-RCFLAGS;, &cv-link-RCINCFLAGS;, &cv-link-RCINCPREFIX;, &cv-link-RCINCSUFFIX;, &cv-link-SHCCFLAGS;, &cv-link-SHCXXFLAGS;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;, &cv-link-SHOBJSUFFIX;, &cv-link-WINDOWSDEFPREFIX;, &cv-link-WINDOWSDEFSUFFIX;.Uses: &cv-link-RCCOMSTR;, &cv-link-SHLINKCOMSTR;. +Sets: &cv-link-AS;, &cv-link-CC;, &cv-link-CXX;, &cv-link-LDMODULECOM;, &cv-link-LIBPREFIX;, &cv-link-LIBSUFFIX;, &cv-link-OBJSUFFIX;, &cv-link-RC;, &cv-link-RCCOM;, &cv-link-RCFLAGS;, &cv-link-RCINCFLAGS;, &cv-link-RCINCPREFIX;, &cv-link-RCINCSUFFIX;, &cv-link-SHCCFLAGS;, &cv-link-SHCXXFLAGS;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;, &cv-link-SHOBJSUFFIX;, &cv-link-WINDOWSDEFPREFIX;, &cv-link-WINDOWSDEFSUFFIX;.Uses: &cv-link-RCCOMSTR;, &cv-link-SHLINKCOMSTR;. msgfmt - -This scons tool is a part of scons gettext toolset. It provides scons + + +This scons tool is a part of scons gettext toolset. It provides scons interface to msgfmt(1) command, which generates binary message catalog (MO) from a textual translation description (PO). -Sets: &cv-link-MOSUFFIX;, &cv-link-MSGFMT;, &cv-link-MSGFMTCOM;, &cv-link-MSGFMTCOMSTR;, &cv-link-MSGFMTFLAGS;, &cv-link-POSUFFIX;.Uses: &cv-link-LINGUAS_FILE;. +Sets: &cv-link-MOSUFFIX;, &cv-link-MSGFMT;, &cv-link-MSGFMTCOM;, &cv-link-MSGFMTCOMSTR;, &cv-link-MSGFMTFLAGS;, &cv-link-POSUFFIX;.Uses: &cv-link-LINGUAS_FILE;. msginit - -This scons tool is a part of scons gettext toolset. It provides + + +This scons tool is a part of scons gettext toolset. It provides scons interface to msginit(1) program, which creates new PO file, initializing the meta information with values from user's environment (or options). -Sets: &cv-link-MSGINIT;, &cv-link-MSGINITCOM;, &cv-link-MSGINITCOMSTR;, &cv-link-MSGINITFLAGS;, &cv-link-POAUTOINIT;, &cv-link-POCREATE_ALIAS;, &cv-link-POSUFFIX;, &cv-link-POTSUFFIX;, &cv-link-_MSGINITLOCALE;.Uses: &cv-link-LINGUAS_FILE;, &cv-link-POAUTOINIT;, &cv-link-POTDOMAIN;. +Sets: &cv-link-MSGINIT;, &cv-link-MSGINITCOM;, &cv-link-MSGINITCOMSTR;, &cv-link-MSGINITFLAGS;, &cv-link-POAUTOINIT;, &cv-link-POCREATE_ALIAS;, &cv-link-POSUFFIX;, &cv-link-POTSUFFIX;, &cv-link-_MSGINITLOCALE;.Uses: &cv-link-LINGUAS_FILE;, &cv-link-POAUTOINIT;, &cv-link-POTDOMAIN;. msgmerge - -This scons tool is a part of scons gettext toolset. It provides + + +This scons tool is a part of scons gettext toolset. It provides scons interface to msgmerge(1) command, which merges two Uniform style .po files together. -Sets: &cv-link-MSGMERGE;, &cv-link-MSGMERGECOM;, &cv-link-MSGMERGECOMSTR;, &cv-link-MSGMERGEFLAGS;, &cv-link-POSUFFIX;, &cv-link-POTSUFFIX;, &cv-link-POUPDATE_ALIAS;.Uses: &cv-link-LINGUAS_FILE;, &cv-link-POAUTOINIT;, &cv-link-POTDOMAIN;. +Sets: &cv-link-MSGMERGE;, &cv-link-MSGMERGECOM;, &cv-link-MSGMERGECOMSTR;, &cv-link-MSGMERGEFLAGS;, &cv-link-POSUFFIX;, &cv-link-POTSUFFIX;, &cv-link-POUPDATE_ALIAS;.Uses: &cv-link-LINGUAS_FILE;, &cv-link-POAUTOINIT;, &cv-link-POTDOMAIN;. mslib - + + Sets construction variables for the Microsoft mslib library archiver. -Sets: &cv-link-AR;, &cv-link-ARCOM;, &cv-link-ARFLAGS;, &cv-link-LIBPREFIX;, &cv-link-LIBSUFFIX;.Uses: &cv-link-ARCOMSTR;. +Sets: &cv-link-AR;, &cv-link-ARCOM;, &cv-link-ARFLAGS;, &cv-link-LIBPREFIX;, &cv-link-LIBSUFFIX;.Uses: &cv-link-ARCOMSTR;. mslink - + + Sets construction variables for the Microsoft linker. -Sets: &cv-link-LDMODULE;, &cv-link-LDMODULECOM;, &cv-link-LDMODULEFLAGS;, &cv-link-LDMODULEPREFIX;, &cv-link-LDMODULESUFFIX;, &cv-link-LIBDIRPREFIX;, &cv-link-LIBDIRSUFFIX;, &cv-link-LIBLINKPREFIX;, &cv-link-LIBLINKSUFFIX;, &cv-link-LINK;, &cv-link-LINKCOM;, &cv-link-LINKFLAGS;, &cv-link-REGSVR;, &cv-link-REGSVRCOM;, &cv-link-REGSVRFLAGS;, &cv-link-SHLINK;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;, &cv-link-WIN32DEFPREFIX;, &cv-link-WIN32DEFSUFFIX;, &cv-link-WIN32EXPPREFIX;, &cv-link-WIN32EXPSUFFIX;, &cv-link-WINDOWSDEFPREFIX;, &cv-link-WINDOWSDEFSUFFIX;, &cv-link-WINDOWSEXPPREFIX;, &cv-link-WINDOWSEXPSUFFIX;, &cv-link-WINDOWSPROGMANIFESTPREFIX;, &cv-link-WINDOWSPROGMANIFESTSUFFIX;, &cv-link-WINDOWSSHLIBMANIFESTPREFIX;, &cv-link-WINDOWSSHLIBMANIFESTSUFFIX;, &cv-link-WINDOWS_INSERT_DEF;.Uses: &cv-link-LDMODULECOMSTR;, &cv-link-LINKCOMSTR;, &cv-link-REGSVRCOMSTR;, &cv-link-SHLINKCOMSTR;. +Sets: &cv-link-LDMODULE;, &cv-link-LDMODULECOM;, &cv-link-LDMODULEFLAGS;, &cv-link-LDMODULEPREFIX;, &cv-link-LDMODULESUFFIX;, &cv-link-LIBDIRPREFIX;, &cv-link-LIBDIRSUFFIX;, &cv-link-LIBLINKPREFIX;, &cv-link-LIBLINKSUFFIX;, &cv-link-LINK;, &cv-link-LINKCOM;, &cv-link-LINKFLAGS;, &cv-link-REGSVR;, &cv-link-REGSVRCOM;, &cv-link-REGSVRFLAGS;, &cv-link-SHLINK;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;, &cv-link-WIN32DEFPREFIX;, &cv-link-WIN32DEFSUFFIX;, &cv-link-WIN32EXPPREFIX;, &cv-link-WIN32EXPSUFFIX;, &cv-link-WINDOWSDEFPREFIX;, &cv-link-WINDOWSDEFSUFFIX;, &cv-link-WINDOWSEXPPREFIX;, &cv-link-WINDOWSEXPSUFFIX;, &cv-link-WINDOWSPROGMANIFESTPREFIX;, &cv-link-WINDOWSPROGMANIFESTSUFFIX;, &cv-link-WINDOWSSHLIBMANIFESTPREFIX;, &cv-link-WINDOWSSHLIBMANIFESTSUFFIX;, &cv-link-WINDOWS_INSERT_DEF;.Uses: &cv-link-LDMODULECOMSTR;, &cv-link-LINKCOMSTR;, &cv-link-REGSVRCOMSTR;, &cv-link-SHLINKCOMSTR;. mssdk - + + Sets variables for Microsoft Platform SDK and/or Windows SDK. Note that unlike most other Tool modules, mssdk does not set construction variables, but sets the environment variables -in the environment SCons uses to execute +in the environment SCons uses to execute the Microsoft toolchain: %INCLUDE%, %LIB%, %LIBPATH% and %PATH%. -Uses: &cv-link-MSSDK_DIR;, &cv-link-MSSDK_VERSION;, &cv-link-MSVS_VERSION;. +Uses: &cv-link-MSSDK_DIR;, &cv-link-MSSDK_VERSION;, &cv-link-MSVS_VERSION;. msvc - + + Sets construction variables for the Microsoft Visual C/C++ compiler. -Sets: &cv-link-BUILDERS;, &cv-link-CC;, &cv-link-CCCOM;, &cv-link-CCFLAGS;, &cv-link-CCPCHFLAGS;, &cv-link-CCPDBFLAGS;, &cv-link-CFILESUFFIX;, &cv-link-CFLAGS;, &cv-link-CPPDEFPREFIX;, &cv-link-CPPDEFSUFFIX;, &cv-link-CXX;, &cv-link-CXXCOM;, &cv-link-CXXFILESUFFIX;, &cv-link-CXXFLAGS;, &cv-link-INCPREFIX;, &cv-link-INCSUFFIX;, &cv-link-OBJPREFIX;, &cv-link-OBJSUFFIX;, &cv-link-PCHCOM;, &cv-link-PCHPDBFLAGS;, &cv-link-RC;, &cv-link-RCCOM;, &cv-link-RCFLAGS;, &cv-link-SHCC;, &cv-link-SHCCCOM;, &cv-link-SHCCFLAGS;, &cv-link-SHCFLAGS;, &cv-link-SHCXX;, &cv-link-SHCXXCOM;, &cv-link-SHCXXFLAGS;, &cv-link-SHOBJPREFIX;, &cv-link-SHOBJSUFFIX;.Uses: &cv-link-CCCOMSTR;, &cv-link-CXXCOMSTR;, &cv-link-PCH;, &cv-link-PCHSTOP;, &cv-link-PDB;, &cv-link-SHCCCOMSTR;, &cv-link-SHCXXCOMSTR;. +Sets: &cv-link-BUILDERS;, &cv-link-CC;, &cv-link-CCCOM;, &cv-link-CCFLAGS;, &cv-link-CCPCHFLAGS;, &cv-link-CCPDBFLAGS;, &cv-link-CFILESUFFIX;, &cv-link-CFLAGS;, &cv-link-CPPDEFPREFIX;, &cv-link-CPPDEFSUFFIX;, &cv-link-CXX;, &cv-link-CXXCOM;, &cv-link-CXXFILESUFFIX;, &cv-link-CXXFLAGS;, &cv-link-INCPREFIX;, &cv-link-INCSUFFIX;, &cv-link-OBJPREFIX;, &cv-link-OBJSUFFIX;, &cv-link-PCHCOM;, &cv-link-PCHPDBFLAGS;, &cv-link-RC;, &cv-link-RCCOM;, &cv-link-RCFLAGS;, &cv-link-SHCC;, &cv-link-SHCCCOM;, &cv-link-SHCCFLAGS;, &cv-link-SHCFLAGS;, &cv-link-SHCXX;, &cv-link-SHCXXCOM;, &cv-link-SHCXXFLAGS;, &cv-link-SHOBJPREFIX;, &cv-link-SHOBJSUFFIX;.Uses: &cv-link-CCCOMSTR;, &cv-link-CXXCOMSTR;, &cv-link-PCH;, &cv-link-PCHSTOP;, &cv-link-PDB;, &cv-link-SHCCCOMSTR;, &cv-link-SHCXXCOMSTR;. msvs - Sets construction variables for Microsoft Visual Studio. - Sets: &cv-link-MSVSBUILDCOM;, &cv-link-MSVSCLEANCOM;, &cv-link-MSVSENCODING;, &cv-link-MSVSPROJECTCOM;, &cv-link-MSVSREBUILDCOM;, &cv-link-MSVSSCONS;, &cv-link-MSVSSCONSCOM;, &cv-link-MSVSSCONSCRIPT;, &cv-link-MSVSSCONSFLAGS;, &cv-link-MSVSSOLUTIONCOM;. + + Sets construction variables for Microsoft Visual Studio. + Sets: &cv-link-MSVSBUILDCOM;, &cv-link-MSVSCLEANCOM;, &cv-link-MSVSENCODING;, &cv-link-MSVSPROJECTCOM;, &cv-link-MSVSREBUILDCOM;, &cv-link-MSVSSCONS;, &cv-link-MSVSSCONSCOM;, &cv-link-MSVSSCONSCRIPT;, &cv-link-MSVSSCONSFLAGS;, &cv-link-MSVSSOLUTIONCOM;. mwcc - + + Sets construction variables for the Metrowerks CodeWarrior compiler. -Sets: &cv-link-CC;, &cv-link-CCCOM;, &cv-link-CFILESUFFIX;, &cv-link-CPPDEFPREFIX;, &cv-link-CPPDEFSUFFIX;, &cv-link-CXX;, &cv-link-CXXCOM;, &cv-link-CXXFILESUFFIX;, &cv-link-INCPREFIX;, &cv-link-INCSUFFIX;, &cv-link-MWCW_VERSION;, &cv-link-MWCW_VERSIONS;, &cv-link-SHCC;, &cv-link-SHCCCOM;, &cv-link-SHCCFLAGS;, &cv-link-SHCFLAGS;, &cv-link-SHCXX;, &cv-link-SHCXXCOM;, &cv-link-SHCXXFLAGS;.Uses: &cv-link-CCCOMSTR;, &cv-link-CXXCOMSTR;, &cv-link-SHCCCOMSTR;, &cv-link-SHCXXCOMSTR;. +Sets: &cv-link-CC;, &cv-link-CCCOM;, &cv-link-CFILESUFFIX;, &cv-link-CPPDEFPREFIX;, &cv-link-CPPDEFSUFFIX;, &cv-link-CXX;, &cv-link-CXXCOM;, &cv-link-CXXFILESUFFIX;, &cv-link-INCPREFIX;, &cv-link-INCSUFFIX;, &cv-link-MWCW_VERSION;, &cv-link-MWCW_VERSIONS;, &cv-link-SHCC;, &cv-link-SHCCCOM;, &cv-link-SHCCFLAGS;, &cv-link-SHCFLAGS;, &cv-link-SHCXX;, &cv-link-SHCXXCOM;, &cv-link-SHCXXFLAGS;.Uses: &cv-link-CCCOMSTR;, &cv-link-CXXCOMSTR;, &cv-link-SHCCCOMSTR;, &cv-link-SHCXXCOMSTR;. mwld - + + Sets construction variables for the Metrowerks CodeWarrior linker. -Sets: &cv-link-AR;, &cv-link-ARCOM;, &cv-link-LIBDIRPREFIX;, &cv-link-LIBDIRSUFFIX;, &cv-link-LIBLINKPREFIX;, &cv-link-LIBLINKSUFFIX;, &cv-link-LINK;, &cv-link-LINKCOM;, &cv-link-SHLINK;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;. +Sets: &cv-link-AR;, &cv-link-ARCOM;, &cv-link-LIBDIRPREFIX;, &cv-link-LIBDIRSUFFIX;, &cv-link-LIBLINKPREFIX;, &cv-link-LIBLINKSUFFIX;, &cv-link-LINK;, &cv-link-LINKCOM;, &cv-link-SHLINK;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;. nasm - + + Sets construction variables for the nasm Netwide Assembler. -Sets: &cv-link-AS;, &cv-link-ASCOM;, &cv-link-ASFLAGS;, &cv-link-ASPPCOM;, &cv-link-ASPPFLAGS;.Uses: &cv-link-ASCOMSTR;, &cv-link-ASPPCOMSTR;. +Sets: &cv-link-AS;, &cv-link-ASCOM;, &cv-link-ASFLAGS;, &cv-link-ASPPCOM;, &cv-link-ASPPFLAGS;.Uses: &cv-link-ASCOMSTR;, &cv-link-ASPPCOMSTR;. - - packaging - -A framework for building binary and source packages. + + Packaging + + +Sets construction variables for the Package Builder. - - Packaging - -Sets construction variables for the Package Builder. + + packaging + + +A framework for building binary and source packages. pdf - + + Sets construction variables for the Portable Document Format builder. -Sets: &cv-link-PDFPREFIX;, &cv-link-PDFSUFFIX;. +Sets: &cv-link-PDFPREFIX;, &cv-link-PDFSUFFIX;. pdflatex - -Sets construction variables for the pdflatex utility. + + +Sets construction variables for the pdflatex utility. -Sets: &cv-link-LATEXRETRIES;, &cv-link-PDFLATEX;, &cv-link-PDFLATEXCOM;, &cv-link-PDFLATEXFLAGS;.Uses: &cv-link-PDFLATEXCOMSTR;. +Sets: &cv-link-LATEXRETRIES;, &cv-link-PDFLATEX;, &cv-link-PDFLATEXCOM;, &cv-link-PDFLATEXFLAGS;.Uses: &cv-link-PDFLATEXCOMSTR;. pdftex - -Sets construction variables for the pdftex utility. + + +Sets construction variables for the pdftex utility. -Sets: &cv-link-LATEXRETRIES;, &cv-link-PDFLATEX;, &cv-link-PDFLATEXCOM;, &cv-link-PDFLATEXFLAGS;, &cv-link-PDFTEX;, &cv-link-PDFTEXCOM;, &cv-link-PDFTEXFLAGS;.Uses: &cv-link-PDFLATEXCOMSTR;, &cv-link-PDFTEXCOMSTR;. +Sets: &cv-link-LATEXRETRIES;, &cv-link-PDFLATEX;, &cv-link-PDFLATEXCOM;, &cv-link-PDFLATEXFLAGS;, &cv-link-PDFTEX;, &cv-link-PDFTEXCOM;, &cv-link-PDFTEXFLAGS;.Uses: &cv-link-PDFLATEXCOMSTR;, &cv-link-PDFTEXCOMSTR;. qt - + + Sets construction variables for building Qt applications. -Sets: &cv-link-QTDIR;, &cv-link-QT_AUTOSCAN;, &cv-link-QT_BINPATH;, &cv-link-QT_CPPPATH;, &cv-link-QT_LIB;, &cv-link-QT_LIBPATH;, &cv-link-QT_MOC;, &cv-link-QT_MOCCXXPREFIX;, &cv-link-QT_MOCCXXSUFFIX;, &cv-link-QT_MOCFROMCXXCOM;, &cv-link-QT_MOCFROMCXXFLAGS;, &cv-link-QT_MOCFROMHCOM;, &cv-link-QT_MOCFROMHFLAGS;, &cv-link-QT_MOCHPREFIX;, &cv-link-QT_MOCHSUFFIX;, &cv-link-QT_UIC;, &cv-link-QT_UICCOM;, &cv-link-QT_UICDECLFLAGS;, &cv-link-QT_UICDECLPREFIX;, &cv-link-QT_UICDECLSUFFIX;, &cv-link-QT_UICIMPLFLAGS;, &cv-link-QT_UICIMPLPREFIX;, &cv-link-QT_UICIMPLSUFFIX;, &cv-link-QT_UISUFFIX;. +Sets: &cv-link-QTDIR;, &cv-link-QT_AUTOSCAN;, &cv-link-QT_BINPATH;, &cv-link-QT_CPPPATH;, &cv-link-QT_LIB;, &cv-link-QT_LIBPATH;, &cv-link-QT_MOC;, &cv-link-QT_MOCCXXPREFIX;, &cv-link-QT_MOCCXXSUFFIX;, &cv-link-QT_MOCFROMCXXCOM;, &cv-link-QT_MOCFROMCXXFLAGS;, &cv-link-QT_MOCFROMHCOM;, &cv-link-QT_MOCFROMHFLAGS;, &cv-link-QT_MOCHPREFIX;, &cv-link-QT_MOCHSUFFIX;, &cv-link-QT_UIC;, &cv-link-QT_UICCOM;, &cv-link-QT_UICDECLFLAGS;, &cv-link-QT_UICDECLPREFIX;, &cv-link-QT_UICDECLSUFFIX;, &cv-link-QT_UICIMPLFLAGS;, &cv-link-QT_UICIMPLPREFIX;, &cv-link-QT_UICIMPLSUFFIX;, &cv-link-QT_UISUFFIX;. rmic - -Sets construction variables for the rmic utility. + + +Sets construction variables for the rmic utility. -Sets: &cv-link-JAVACLASSSUFFIX;, &cv-link-RMIC;, &cv-link-RMICCOM;, &cv-link-RMICFLAGS;.Uses: &cv-link-RMICCOMSTR;. +Sets: &cv-link-JAVACLASSSUFFIX;, &cv-link-RMIC;, &cv-link-RMICCOM;, &cv-link-RMICFLAGS;.Uses: &cv-link-RMICCOMSTR;. rpcgen - + + Sets construction variables for building with RPCGEN. -Sets: &cv-link-RPCGEN;, &cv-link-RPCGENCLIENTFLAGS;, &cv-link-RPCGENFLAGS;, &cv-link-RPCGENHEADERFLAGS;, &cv-link-RPCGENSERVICEFLAGS;, &cv-link-RPCGENXDRFLAGS;. +Sets: &cv-link-RPCGEN;, &cv-link-RPCGENCLIENTFLAGS;, &cv-link-RPCGENFLAGS;, &cv-link-RPCGENHEADERFLAGS;, &cv-link-RPCGENSERVICEFLAGS;, &cv-link-RPCGENXDRFLAGS;. sgiar - + + Sets construction variables for the SGI library archiver. -Sets: &cv-link-AR;, &cv-link-ARCOMSTR;, &cv-link-ARFLAGS;, &cv-link-LIBPREFIX;, &cv-link-LIBSUFFIX;, &cv-link-SHLINK;, &cv-link-SHLINKFLAGS;.Uses: &cv-link-ARCOMSTR;, &cv-link-SHLINKCOMSTR;. +Sets: &cv-link-AR;, &cv-link-ARCOMSTR;, &cv-link-ARFLAGS;, &cv-link-LIBPREFIX;, &cv-link-LIBSUFFIX;, &cv-link-SHLINK;, &cv-link-SHLINKFLAGS;.Uses: &cv-link-ARCOMSTR;, &cv-link-SHLINKCOMSTR;. sgic++ - + + Sets construction variables for the SGI C++ compiler. -Sets: &cv-link-CXX;, &cv-link-CXXFLAGS;, &cv-link-SHCXX;, &cv-link-SHOBJSUFFIX;. +Sets: &cv-link-CXX;, &cv-link-CXXFLAGS;, &cv-link-SHCXX;, &cv-link-SHOBJSUFFIX;. sgicc - + + Sets construction variables for the SGI C compiler. -Sets: &cv-link-CXX;, &cv-link-SHOBJSUFFIX;. +Sets: &cv-link-CXX;, &cv-link-SHOBJSUFFIX;. sgilink - + + Sets construction variables for the SGI linker. -Sets: &cv-link-LINK;, &cv-link-RPATHPREFIX;, &cv-link-RPATHSUFFIX;, &cv-link-SHLINKFLAGS;. +Sets: &cv-link-LINK;, &cv-link-RPATHPREFIX;, &cv-link-RPATHSUFFIX;, &cv-link-SHLINKFLAGS;. sunar - + + Sets construction variables for the Sun library archiver. -Sets: &cv-link-AR;, &cv-link-ARCOM;, &cv-link-ARFLAGS;, &cv-link-LIBPREFIX;, &cv-link-LIBSUFFIX;.Uses: &cv-link-ARCOMSTR;. +Sets: &cv-link-AR;, &cv-link-ARCOM;, &cv-link-ARFLAGS;, &cv-link-LIBPREFIX;, &cv-link-LIBSUFFIX;.Uses: &cv-link-ARCOMSTR;. sunc++ - + + Sets construction variables for the Sun C++ compiler. -Sets: &cv-link-CXX;, &cv-link-CXXVERSION;, &cv-link-SHCXX;, &cv-link-SHCXXFLAGS;, &cv-link-SHOBJPREFIX;, &cv-link-SHOBJSUFFIX;. +Sets: &cv-link-CXX;, &cv-link-CXXVERSION;, &cv-link-SHCXX;, &cv-link-SHCXXFLAGS;, &cv-link-SHOBJPREFIX;, &cv-link-SHOBJSUFFIX;. suncc - + + Sets construction variables for the Sun C compiler. -Sets: &cv-link-CXX;, &cv-link-SHCCFLAGS;, &cv-link-SHOBJPREFIX;, &cv-link-SHOBJSUFFIX;. +Sets: &cv-link-CXX;, &cv-link-SHCCFLAGS;, &cv-link-SHOBJPREFIX;, &cv-link-SHOBJSUFFIX;. sunf77 - -Set construction variables for the Sun f77 Fortran compiler. + + +Set construction variables for the Sun f77 Fortran compiler. -Sets: &cv-link-F77;, &cv-link-FORTRAN;, &cv-link-SHF77;, &cv-link-SHF77FLAGS;, &cv-link-SHFORTRAN;, &cv-link-SHFORTRANFLAGS;. +Sets: &cv-link-F77;, &cv-link-FORTRAN;, &cv-link-SHF77;, &cv-link-SHF77FLAGS;, &cv-link-SHFORTRAN;, &cv-link-SHFORTRANFLAGS;. sunf90 - -Set construction variables for the Sun f90 Fortran compiler. + + +Set construction variables for the Sun f90 Fortran compiler. -Sets: &cv-link-F90;, &cv-link-FORTRAN;, &cv-link-SHF90;, &cv-link-SHF90FLAGS;, &cv-link-SHFORTRAN;, &cv-link-SHFORTRANFLAGS;. +Sets: &cv-link-F90;, &cv-link-FORTRAN;, &cv-link-SHF90;, &cv-link-SHF90FLAGS;, &cv-link-SHFORTRAN;, &cv-link-SHFORTRANFLAGS;. sunf95 - -Set construction variables for the Sun f95 Fortran compiler. + + +Set construction variables for the Sun f95 Fortran compiler. -Sets: &cv-link-F95;, &cv-link-FORTRAN;, &cv-link-SHF95;, &cv-link-SHF95FLAGS;, &cv-link-SHFORTRAN;, &cv-link-SHFORTRANFLAGS;. +Sets: &cv-link-F95;, &cv-link-FORTRAN;, &cv-link-SHF95;, &cv-link-SHF95FLAGS;, &cv-link-SHFORTRAN;, &cv-link-SHFORTRANFLAGS;. sunlink - + + Sets construction variables for the Sun linker. -Sets: &cv-link-RPATHPREFIX;, &cv-link-RPATHSUFFIX;, &cv-link-SHLINKFLAGS;. +Sets: &cv-link-RPATHPREFIX;, &cv-link-RPATHSUFFIX;, &cv-link-SHLINKFLAGS;. swig - + + Sets construction variables for the SWIG interface generator. -Sets: &cv-link-SWIG;, &cv-link-SWIGCFILESUFFIX;, &cv-link-SWIGCOM;, &cv-link-SWIGCXXFILESUFFIX;, &cv-link-SWIGDIRECTORSUFFIX;, &cv-link-SWIGFLAGS;, &cv-link-SWIGINCPREFIX;, &cv-link-SWIGINCSUFFIX;, &cv-link-SWIGPATH;, &cv-link-SWIGVERSION;, &cv-link-_SWIGINCFLAGS;.Uses: &cv-link-SWIGCOMSTR;. +Sets: &cv-link-SWIG;, &cv-link-SWIGCFILESUFFIX;, &cv-link-SWIGCOM;, &cv-link-SWIGCXXFILESUFFIX;, &cv-link-SWIGDIRECTORSUFFIX;, &cv-link-SWIGFLAGS;, &cv-link-SWIGINCPREFIX;, &cv-link-SWIGINCSUFFIX;, &cv-link-SWIGPATH;, &cv-link-SWIGVERSION;, &cv-link-_SWIGINCFLAGS;.Uses: &cv-link-SWIGCOMSTR;. tar - -Sets construction variables for the tar archiver. + + +Sets construction variables for the tar archiver. -Sets: &cv-link-TAR;, &cv-link-TARCOM;, &cv-link-TARFLAGS;, &cv-link-TARSUFFIX;.Uses: &cv-link-TARCOMSTR;. +Sets: &cv-link-TAR;, &cv-link-TARCOM;, &cv-link-TARFLAGS;, &cv-link-TARSUFFIX;.Uses: &cv-link-TARCOMSTR;. tex - + + Sets construction variables for the TeX formatter and typesetter. -Sets: &cv-link-BIBTEX;, &cv-link-BIBTEXCOM;, &cv-link-BIBTEXFLAGS;, &cv-link-LATEX;, &cv-link-LATEXCOM;, &cv-link-LATEXFLAGS;, &cv-link-MAKEINDEX;, &cv-link-MAKEINDEXCOM;, &cv-link-MAKEINDEXFLAGS;, &cv-link-TEX;, &cv-link-TEXCOM;, &cv-link-TEXFLAGS;.Uses: &cv-link-BIBTEXCOMSTR;, &cv-link-LATEXCOMSTR;, &cv-link-MAKEINDEXCOMSTR;, &cv-link-TEXCOMSTR;. +Sets: &cv-link-BIBTEX;, &cv-link-BIBTEXCOM;, &cv-link-BIBTEXFLAGS;, &cv-link-LATEX;, &cv-link-LATEXCOM;, &cv-link-LATEXFLAGS;, &cv-link-MAKEINDEX;, &cv-link-MAKEINDEXCOM;, &cv-link-MAKEINDEXFLAGS;, &cv-link-TEX;, &cv-link-TEXCOM;, &cv-link-TEXFLAGS;.Uses: &cv-link-BIBTEXCOMSTR;, &cv-link-LATEXCOMSTR;, &cv-link-MAKEINDEXCOMSTR;, &cv-link-TEXCOMSTR;. textfile - -Set construction variables for the Textfile and Substfile builders. + + +Set construction variables for the Textfile and Substfile builders. -Sets: &cv-link-LINESEPARATOR;, &cv-link-SUBSTFILEPREFIX;, &cv-link-SUBSTFILESUFFIX;, &cv-link-TEXTFILEPREFIX;, &cv-link-TEXTFILESUFFIX;.Uses: &cv-link-SUBST_DICT;. +Sets: &cv-link-LINESEPARATOR;, &cv-link-SUBSTFILEPREFIX;, &cv-link-SUBSTFILESUFFIX;, &cv-link-TEXTFILEPREFIX;, &cv-link-TEXTFILESUFFIX;.Uses: &cv-link-SUBST_DICT;. tlib - + + Sets construction variables for the Borlan tib library archiver. -Sets: &cv-link-AR;, &cv-link-ARCOM;, &cv-link-ARFLAGS;, &cv-link-LIBPREFIX;, &cv-link-LIBSUFFIX;.Uses: &cv-link-ARCOMSTR;. +Sets: &cv-link-AR;, &cv-link-ARCOM;, &cv-link-ARFLAGS;, &cv-link-LIBPREFIX;, &cv-link-LIBSUFFIX;.Uses: &cv-link-ARCOMSTR;. xgettext - -This scons tool is a part of scons gettext toolset. It provides + + +This scons tool is a part of scons gettext toolset. It provides scons interface to xgettext(1) program, which extracts internationalized messages from source code. The tool -provides POTUpdate builder to make PO +provides POTUpdate builder to make PO Template files. -Sets: &cv-link-POTSUFFIX;, &cv-link-POTUPDATE_ALIAS;, &cv-link-XGETTEXTCOM;, &cv-link-XGETTEXTCOMSTR;, &cv-link-XGETTEXTFLAGS;, &cv-link-XGETTEXTFROM;, &cv-link-XGETTEXTFROMPREFIX;, &cv-link-XGETTEXTFROMSUFFIX;, &cv-link-XGETTEXTPATH;, &cv-link-XGETTEXTPATHPREFIX;, &cv-link-XGETTEXTPATHSUFFIX;, &cv-link-_XGETTEXTDOMAIN;, &cv-link-_XGETTEXTFROMFLAGS;, &cv-link-_XGETTEXTPATHFLAGS;.Uses: &cv-link-POTDOMAIN;. +Sets: &cv-link-POTSUFFIX;, &cv-link-POTUPDATE_ALIAS;, &cv-link-XGETTEXTCOM;, &cv-link-XGETTEXTCOMSTR;, &cv-link-XGETTEXTFLAGS;, &cv-link-XGETTEXTFROM;, &cv-link-XGETTEXTFROMPREFIX;, &cv-link-XGETTEXTFROMSUFFIX;, &cv-link-XGETTEXTPATH;, &cv-link-XGETTEXTPATHPREFIX;, &cv-link-XGETTEXTPATHSUFFIX;, &cv-link-_XGETTEXTDOMAIN;, &cv-link-_XGETTEXTFROMFLAGS;, &cv-link-_XGETTEXTPATHFLAGS;.Uses: &cv-link-POTDOMAIN;. yacc - -Sets construction variables for the yacc parse generator. + + +Sets construction variables for the yacc parse generator. -Sets: &cv-link-YACC;, &cv-link-YACCCOM;, &cv-link-YACCFLAGS;, &cv-link-YACCHFILESUFFIX;, &cv-link-YACCHXXFILESUFFIX;, &cv-link-YACCVCGFILESUFFIX;.Uses: &cv-link-YACCCOMSTR;. +Sets: &cv-link-YACC;, &cv-link-YACCCOM;, &cv-link-YACCFLAGS;, &cv-link-YACCHFILESUFFIX;, &cv-link-YACCHXXFILESUFFIX;, &cv-link-YACCVCGFILESUFFIX;.Uses: &cv-link-YACCCOMSTR;. zip - -Sets construction variables for the zip archiver. + + +Sets construction variables for the zip archiver. -Sets: &cv-link-ZIP;, &cv-link-ZIPCOM;, &cv-link-ZIPCOMPRESSION;, &cv-link-ZIPFLAGS;, &cv-link-ZIPSUFFIX;.Uses: &cv-link-ZIPCOMSTR;. +Sets: &cv-link-ZIP;, &cv-link-ZIPCOM;, &cv-link-ZIPCOMPRESSION;, &cv-link-ZIPFLAGS;, &cv-link-ZIPSUFFIX;.Uses: &cv-link-ZIPCOMSTR;. diff --git a/doc/generated/tools.mod b/doc/generated/tools.mod index f9bc1d7..1209d74 100644 --- a/doc/generated/tools.mod +++ b/doc/generated/tools.mod @@ -78,8 +78,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. mwcc"> mwld"> nasm"> -packaging"> Packaging"> +packaging"> pdf"> pdflatex"> pdftex"> @@ -186,8 +186,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. mwcc"> mwld"> nasm"> -packaging"> Packaging"> +packaging"> pdf"> pdflatex"> pdftex"> diff --git a/doc/generated/variables.gen b/doc/generated/variables.gen index 705bf5b..9050832 100644 --- a/doc/generated/variables.gen +++ b/doc/generated/variables.gen @@ -1,3 +1,4 @@ + %scons; @@ -11,115 +12,125 @@ %variables-mod; ]> - + __LDMODULEVERSIONFLAGS - -This construction variable automatically introduces $_LDMODULEVERSIONFLAGS -if $LDMODULEVERSION is set. Othervise it evaluates to an empty string. + + +This construction variable automatically introduces $_LDMODULEVERSIONFLAGS +if $LDMODULEVERSION is set. Othervise it evaluates to an empty string. __SHLIBVERSIONFLAGS - -This construction variable automatically introduces $_SHLIBVERSIONFLAGS -if $SHLIBVERSION is set. Othervise it evaluates to an empty string. + + +This construction variable automatically introduces $_SHLIBVERSIONFLAGS +if $SHLIBVERSION is set. Othervise it evaluates to an empty string. + + _APPLELINK_COMPATIBILITY_VERSION + + + A macro (by default a generator function) used to create the linker flags to specify + apple's linker's -compatibility_version flag. + The default generator uses $APPLELINK_COMPATIBILITY_VERSION + and $APPLELINK_NO_COMPATIBILITY_VERSION and $SHLIBVERSION + to determine the correct flag. + + + APPLELINK_COMPATIBILITY_VERSION - + + On Mac OS X this is used to set the linker flag: -compatibility_version - + The value is specified as X[.Y[.Z]] where X is between 1 and 65535, Y can be omitted or between 1 and - 255, Z can be omitted or between 1 and 255. This value will be derived from $SHLIBVERSION if + 255, Z can be omitted or between 1 and 255. This value will be derived from $SHLIBVERSION if not specified. The lowest digit will be dropped and replaced by a 0. - - If the $APPLELINK_NO_COMPATIBILITY_VERSION is set then no -compatibility_version will be + + If the $APPLELINK_NO_COMPATIBILITY_VERSION is set then no -compatibility_version will be output. - See MacOS's ld manpage for more details + See MacOS's ld manpage for more details - - _APPLELINK_COMPATIBILITY_VERSION - - A macro (by default a generator function) used to create the linker flags to specify - apple's linker's -compatibility_version flag. - The default generator uses $APPLELINK_COMPATIBILITY_VERSION - and $APPLELINK_NO_COMPATIBILITY_VERSION and $SHLIBVERSION - to determine the correct flag. + + _APPLELINK_CURRENT_VERSION + + + A macro (by default a generator function) used to create the linker flags to specify apple's linker's + -current_version flag. The default generator uses $APPLELINK_CURRENT_VERSION and + $APPLELINK_NO_CURRENT_VERSION and $SHLIBVERSION to determine the correct flag. APPLELINK_CURRENT_VERSION - + + On Mac OS X this is used to set the linker flag: -current_version - + The value is specified as X[.Y[.Z]] where X is between 1 and 65535, Y can be omitted or between 1 and - 255, Z can be omitted or between 1 and 255. This value will be set to $SHLIBVERSION if not + 255, Z can be omitted or between 1 and 255. This value will be set to $SHLIBVERSION if not specified. - - If the $APPLELINK_NO_CURRENT_VERSION is set then no -current_version will be + + If the $APPLELINK_NO_CURRENT_VERSION is set then no -current_version will be output. - See MacOS's ld manpage for more details + See MacOS's ld manpage for more details - - _APPLELINK_CURRENT_VERSION - - A macro (by default a generator function) used to create the linker flags to specify apple's linker's - -current_version flag. The default generator uses $APPLELINK_CURRENT_VERSION and - $APPLELINK_NO_CURRENT_VERSION and $SHLIBVERSION to determine the correct flag. - - - APPLELINK_NO_COMPATIBILITY_VERSION - + + Set this to any True (1|True|non-empty string) value to disable adding -compatibility_version flag when generating versioned shared libraries. - - This overrides $APPLELINK_COMPATIBILITY_VERSION. + + This overrides $APPLELINK_COMPATIBILITY_VERSION. APPLELINK_NO_CURRENT_VERSION - + + Set this to any True (1|True|non-empty string) value to disable adding -current_version flag when generating versioned shared libraries. - - This overrides $APPLELINK_CURRENT_VERSION. + + This overrides $APPLELINK_CURRENT_VERSION. AR - + + The static library archiver. ARCHITECTURE - + + Specifies the system architecture for which the package is being built. The default is the system architecture @@ -136,41 +147,46 @@ as well as forming part of the name of a generated RPM package file. ARCOM - + + The command line used to generate a static library from object files. ARCOMSTR - + + The string displayed when an object file is generated from an assembly-language source file. -If this is not set, then $ARCOM (the command line) is displayed. +If this is not set, then $ARCOM (the command line) is displayed. - + env = Environment(ARCOMSTR = "Archiving $TARGET") ARFLAGS - + + General options passed to the static library archiver. AS - + + The assembler. ASCOM - + + The command line used to generate an object file from an assembly-language source file. @@ -178,63 +194,69 @@ from an assembly-language source file. ASCOMSTR - + + The string displayed when an object file is generated from an assembly-language source file. -If this is not set, then $ASCOM (the command line) is displayed. +If this is not set, then $ASCOM (the command line) is displayed. - + env = Environment(ASCOMSTR = "Assembling $TARGET") ASFLAGS - + + General options passed to the assembler. ASPPCOM - + + The command line used to assemble an assembly-language source file into an object file after first running the file through the C preprocessor. Any options specified -in the $ASFLAGS and $CPPFLAGS construction variables +in the $ASFLAGS and $CPPFLAGS construction variables are included on this command line. ASPPCOMSTR - + + The string displayed when an object file is generated from an assembly-language source file after first running the file through the C preprocessor. -If this is not set, then $ASPPCOM (the command line) is displayed. +If this is not set, then $ASPPCOM (the command line) is displayed. - + env = Environment(ASPPCOMSTR = "Assembling $TARGET") ASPPFLAGS - + + General options when an assembling an assembly-language source file into an object file after first running the file through the C preprocessor. -The default is to use the value of $ASFLAGS. +The default is to use the value of $ASFLAGS. BIBTEX - + + The bibliography generator for the TeX formatter and typesetter and the LaTeX structured formatter and typesetter. @@ -242,7 +264,8 @@ LaTeX structured formatter and typesetter. BIBTEXCOM - + + The command line used to call the bibliography generator for the TeX formatter and typesetter and the LaTeX structured formatter and typesetter. @@ -251,20 +274,22 @@ typesetter. BIBTEXCOMSTR - + + The string displayed when generating a bibliography for TeX or LaTeX. -If this is not set, then $BIBTEXCOM (the command line) is displayed. +If this is not set, then $BIBTEXCOM (the command line) is displayed. - + env = Environment(BIBTEXCOMSTR = "Generating bibliography $TARGET") BIBTEXFLAGS - + + General options passed to the bibliography generator for the TeX formatter and typesetter and the LaTeX structured formatter and typesetter. @@ -272,7 +297,8 @@ and typesetter and the LaTeX structured formatter and typesetter. BUILDERS - + + A dictionary mapping the names of the builders available through this environment to underlying Builder objects. @@ -283,26 +309,26 @@ If you initialize this variable when an Environment is created: - + env = Environment(BUILDERS = {'NewBuilder' : foo}) - + the default Builders will no longer be available. To use a new Builder object in addition to the default Builders, add your new Builder object like this: - + env = Environment() env.Append(BUILDERS = {'NewBuilder' : foo}) - + or this: - + env = Environment() env['BUILDERS']['NewBuilder'] = foo @@ -310,64 +336,70 @@ env['BUILDERS']['NewBuilder'] = foo CC - + + The C compiler. CCCOM - + + The command line used to compile a C source file to a (static) object -file. Any options specified in the $CFLAGS, $CCFLAGS and -$CPPFLAGS construction variables are included on this command +file. Any options specified in the $CFLAGS, $CCFLAGS and +$CPPFLAGS construction variables are included on this command line. CCCOMSTR - + + The string displayed when a C source file is compiled to a (static) object file. -If this is not set, then $CCCOM (the command line) is displayed. +If this is not set, then $CCCOM (the command line) is displayed. - + env = Environment(CCCOMSTR = "Compiling static object $TARGET") CCFLAGS - + + General options that are passed to the C and C++ compilers. CCPCHFLAGS - + + Options added to the compiler command line to support building with precompiled headers. The default value expands expands to the appropriate Microsoft Visual C++ command-line options -when the $PCH construction variable is set. +when the $PCH construction variable is set. CCPDBFLAGS - + + Options added to the compiler command line to support storing debugging information in a Microsoft Visual C++ PDB file. The default value expands expands to appropriate Microsoft Visual C++ command-line options -when the $PDB construction variable is set. +when the $PDB construction variable is set. - + The Visual C++ compiler option that SCons uses by default to generate PDB information is . This works correctly with parallel () builds @@ -380,30 +412,31 @@ link-time performance, although parallel builds will no longer work. - + You can generate PDB files with the -switch by overriding the default $CCPDBFLAGS variable as follows: +switch by overriding the default $CCPDBFLAGS variable as follows: - + env['CCPDBFLAGS'] = ['${(PDB and "/Zi /Fd%s" % File(PDB)) or ""}'] - + An alternative would be to use the to put the debugging information in a separate .pdb file for each object file by overriding -the $CCPDBFLAGS variable as follows: +the $CCPDBFLAGS variable as follows: - + env['CCPDBFLAGS'] = '/Zi /Fd${TARGET}.pdb' CCVERSION - + + The version number of the C compiler. This may or may not be set, depending on the specific C compiler being used. @@ -412,7 +445,8 @@ depending on the specific C compiler being used. CFILESUFFIX - + + The suffix for C source files. This is used by the internal CFile builder when generating C files from Lex (.l) or YACC (.y) input files. @@ -429,14 +463,16 @@ as C files. CFLAGS - + + General options that are passed to the C compiler (C only; not C++). CHANGE_SPECFILE - + + A hook for modifying the file that controls the packaging build (the .spec for RPM, the control for Ipkg, @@ -448,7 +484,8 @@ after the SCons template for the file has been written. CHANGED_SOURCES - + + A reserved variable name that may not be set or used in a construction environment. (See the manpage section "Variable Substitution" @@ -458,7 +495,8 @@ for more information). CHANGED_TARGETS - + + A reserved variable name that may not be set or used in a construction environment. (See the manpage section "Variable Substitution" @@ -468,7 +506,8 @@ for more information). CHANGELOG - + + The name of a file containing the change log text to be included in the package. This is included as the @@ -480,8 +519,9 @@ section of the RPM _concat - -A function used to produce variables like $_CPPINCFLAGS. It takes + + +A function used to produce variables like $_CPPINCFLAGS. It takes four or five arguments: a prefix to concatenate onto each element, a list of elements, a suffix to concatenate onto each element, an environment @@ -489,14 +529,15 @@ for variable interpolation, and an optional function that will be called to transform the list before concatenation. - + env['_CPPINCFLAGS'] = '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs)} $)', CONFIGUREDIR - + + The name of the directory in which Configure context test files are written. The default is @@ -510,7 +551,8 @@ file. CONFIGURELOG - + + The name of the Configure context log file. The default is config.log @@ -523,48 +565,50 @@ file. _CPPDEFFLAGS - + + An automatically-generated construction variable containing the C preprocessor command-line options to define values. -The value of $_CPPDEFFLAGS is created +The value of $_CPPDEFFLAGS is created by respectively prepending and appending -$CPPDEFPREFIX and $CPPDEFSUFFIX +$CPPDEFPREFIX and $CPPDEFSUFFIX to the beginning and end -of each definition in $CPPDEFINES. +of each definition in $CPPDEFINES. CPPDEFINES - + + A platform independent specification of C preprocessor definitions. The definitions will be added to command lines through the automatically-generated -$_CPPDEFFLAGS construction variable (see above), +$_CPPDEFFLAGS construction variable (see above), which is constructed according to -the type of value of $CPPDEFINES: +the type of value of $CPPDEFINES: - -If $CPPDEFINES is a string, + +If $CPPDEFINES is a string, the values of the -$CPPDEFPREFIX and $CPPDEFSUFFIX +$CPPDEFPREFIX and $CPPDEFSUFFIX construction variables will be respectively prepended and appended to the beginning and end -of each definition in $CPPDEFINES. +of each definition in $CPPDEFINES. - + # Will add -Dxyz to POSIX compiler command lines, # and /Dxyz to Microsoft Visual C++ command lines. env = Environment(CPPDEFINES='xyz') - -If $CPPDEFINES is a list, + +If $CPPDEFINES is a list, the values of the -$CPPDEFPREFIX and $CPPDEFSUFFIX +$CPPDEFPREFIX and $CPPDEFSUFFIX construction variables will be respectively prepended and appended to the beginning and end of each element in the list. @@ -573,16 +617,16 @@ then the first item is the name being defined and the second item is its value: - + # Will add -DB=2 -DA to POSIX compiler command lines, # and /DB=2 /DA to Microsoft Visual C++ command lines. env = Environment(CPPDEFINES=[('B', 2), 'A']) - -If $CPPDEFINES is a dictionary, + +If $CPPDEFINES is a dictionary, the values of the -$CPPDEFPREFIX and $CPPDEFSUFFIX +$CPPDEFPREFIX and $CPPDEFSUFFIX construction variables will be respectively prepended and appended to the beginning and end of each item from the dictionary. @@ -595,11 +639,11 @@ then the name is defined without an explicit value. Note that the resulting flags are sorted by keyword to ensure that the order of the options on the command line is consistent each time -scons +scons is run. - + # Will add -DA -DB=2 to POSIX compiler command lines, # and /DA /DB=2 to Microsoft Visual C++ command lines. env = Environment(CPPDEFINES={'B':2, 'A':None}) @@ -608,42 +652,45 @@ env = Environment(CPPDEFINES={'B':2, 'A':None}) CPPDEFPREFIX - + + The prefix used to specify preprocessor definitions on the C compiler command line. This will be prepended to the beginning of each definition -in the $CPPDEFINES construction variable -when the $_CPPDEFFLAGS variable is automatically generated. +in the $CPPDEFINES construction variable +when the $_CPPDEFFLAGS variable is automatically generated. CPPDEFSUFFIX - + + The suffix used to specify preprocessor definitions on the C compiler command line. This will be appended to the end of each definition -in the $CPPDEFINES construction variable -when the $_CPPDEFFLAGS variable is automatically generated. +in the $CPPDEFINES construction variable +when the $_CPPDEFFLAGS variable is automatically generated. CPPFLAGS - + + User-specified C preprocessor options. These will be included in any command that uses the C preprocessor, including not just compilation of C and C++ source files -via the $CCCOM, -$SHCCCOM, -$CXXCOM and -$SHCXXCOM command lines, -but also the $FORTRANPPCOM, -$SHFORTRANPPCOM, -$F77PPCOM and -$SHF77PPCOM command lines +via the $CCCOM, +$SHCCCOM, +$CXXCOM and +$SHCXXCOM command lines, +but also the $FORTRANPPCOM, +$SHFORTRANPPCOM, +$F77PPCOM and +$SHF77PPCOM command lines used to compile a Fortran source file, -and the $ASPPCOM command line +and the $ASPPCOM command line used to assemble an assembly language source file, after first running each file through the C preprocessor. Note that this variable does @@ -651,28 +698,30 @@ Note that this variable does contain (or similar) include search path options -that scons generates automatically from $CPPPATH. -See $_CPPINCFLAGS, below, +that scons generates automatically from $CPPPATH. +See $_CPPINCFLAGS, below, for the variable that expands to those options. _CPPINCFLAGS - + + An automatically-generated construction variable containing the C preprocessor command-line options for specifying directories to be searched for include files. -The value of $_CPPINCFLAGS is created -by respectively prepending and appending $INCPREFIX and $INCSUFFIX +The value of $_CPPINCFLAGS is created +by respectively prepending and appending $INCPREFIX and $INCSUFFIX to the beginning and end -of each directory in $CPPPATH. +of each directory in $CPPPATH. CPPPATH - + + The list of directories that the C preprocessor will search for include directories. The C/C++ implicit dependency scanner will search these directories for include files. Don't explicitly put include directory @@ -680,56 +729,57 @@ arguments in CCFLAGS or CXXFLAGS because the result will be non-portable and the directories will not be searched by the dependency scanner. Note: directory names in CPPPATH will be looked-up relative to the SConscript directory when they are used in a command. To force -scons +scons to look-up a directory relative to the root of the source tree use #: - + env = Environment(CPPPATH='#/include') - + The directory look-up can also be forced using the -Dir() +Dir() function: - + include = Dir('include') env = Environment(CPPPATH=include) - + The directory list will be added to command lines through the automatically-generated -$_CPPINCFLAGS +$_CPPINCFLAGS construction variable, which is constructed by respectively prepending and appending the value of the -$INCPREFIX and $INCSUFFIX +$INCPREFIX and $INCSUFFIX construction variables to the beginning and end -of each directory in $CPPPATH. +of each directory in $CPPPATH. Any command lines you define that need the CPPPATH directory list should -include $_CPPINCFLAGS: +include $_CPPINCFLAGS: - + env = Environment(CCCOM="my_compiler $_CPPINCFLAGS -c -o $TARGET $SOURCE") CPPSUFFIXES - + + The list of suffixes of files that will be scanned for C preprocessor implicit dependencies (#include lines). The default list is: - + [".c", ".C", ".cxx", ".cpp", ".c++", ".cc", ".h", ".H", ".hxx", ".hpp", ".hh", ".F", ".fpp", ".FPP", @@ -740,37 +790,41 @@ The default list is: CXX - + + The C++ compiler. CXXCOM - + + The command line used to compile a C++ source file to an object file. -Any options specified in the $CXXFLAGS and -$CPPFLAGS construction variables +Any options specified in the $CXXFLAGS and +$CPPFLAGS construction variables are included on this command line. CXXCOMSTR - + + The string displayed when a C++ source file is compiled to a (static) object file. -If this is not set, then $CXXCOM (the command line) is displayed. +If this is not set, then $CXXCOM (the command line) is displayed. - + env = Environment(CXXCOMSTR = "Compiling static object $TARGET") CXXFILESUFFIX - + + The suffix for C++ source files. This is used by the internal CXXFile builder when generating C++ files from Lex (.ll) or YACC (.yy) input files. @@ -796,18 +850,20 @@ as C++ files. CXXFLAGS - + + General options that are passed to the C++ compiler. -By default, this includes the value of $CCFLAGS, -so that setting $CCFLAGS affects both C and C++ compilation. +By default, this includes the value of $CCFLAGS, +so that setting $CCFLAGS affects both C and C++ compilation. If you want to add C++-specific flags, -you must set or override the value of $CXXFLAGS. +you must set or override the value of $CXXFLAGS. CXXVERSION - + + The version number of the C++ compiler. This may or may not be set, depending on the specific C++ compiler being used. @@ -816,44 +872,50 @@ depending on the specific C++ compiler being used. DC - + + The D compiler to use. DCOM - + + The command line used to compile a D file to an object file. -Any options specified in the $DFLAGS construction variable +Any options specified in the $DFLAGS construction variable is included on this command line. DDEBUG - + + List of debug tags to enable when compiling. DDEBUGPREFIX - + + DDEBUGPREFIX. DDEBUGSUFFIX - + + DDEBUGSUFFIX. DESCRIPTION - + + A long description of the project being packaged. This is included in the relevant section of the file that controls the packaging build. @@ -862,7 +924,8 @@ of the file that controls the packaging build. DESCRIPTION_lang - + + A language-specific long description for the specified lang. This is used to populate a @@ -874,53 +937,61 @@ section of an RPM DFILESUFFIX - + + DFILESUFFIX. DFLAGPREFIX - + + DFLAGPREFIX. DFLAGS - + + General options that are passed to the D compiler. DFLAGSUFFIX - + + DFLAGSUFFIX. DINCPREFIX - + + DINCPREFIX. DINCSUFFIX - + + DLIBFLAGSUFFIX. Dir - + + A function that converts a string into a Dir instance relative to the target being built. - + + A function that converts a string into a Dir instance relative to the target being built. @@ -928,7 +999,8 @@ into a Dir instance relative to the target being built. Dirs - + + A function that converts a list of strings into a list of Dir instances relative to the target being built. @@ -936,162 +1008,184 @@ into a list of Dir instances relative to the target being built. DLIB - + + Name of the lib tool to use for D codes. DLIBCOM - + + The command line to use when creating libraries. DLIBDIRPREFIX - + + DLIBLINKPREFIX. DLIBDIRSUFFIX - + + DLIBLINKSUFFIX. DLIBFLAGPREFIX - + + DLIBFLAGPREFIX. DLIBFLAGSUFFIX - + + DLIBFLAGSUFFIX. DLIBLINKPREFIX - + + DLIBLINKPREFIX. DLIBLINKSUFFIX - + + DLIBLINKSUFFIX. DLINK - + + Name of the linker to use for linking systems including D sources. DLINKCOM - + + The command line to use when linking systems including D sources. DLINKFLAGPREFIX - + + DLINKFLAGPREFIX. DLINKFLAGS - + + List of linker flags. DLINKFLAGSUFFIX - + + DLINKFLAGSUFFIX. DOCBOOK_DEFAULT_XSL_EPUB - -The default XSLT file for the DocbookEpub builder within the + + +The default XSLT file for the DocbookEpub builder within the current environment, if no other XSLT gets specified via keyword. DOCBOOK_DEFAULT_XSL_HTML - -The default XSLT file for the DocbookHtml builder within the + + +The default XSLT file for the DocbookHtml builder within the current environment, if no other XSLT gets specified via keyword. DOCBOOK_DEFAULT_XSL_HTMLCHUNKED - -The default XSLT file for the DocbookHtmlChunked builder within the + + +The default XSLT file for the DocbookHtmlChunked builder within the current environment, if no other XSLT gets specified via keyword. DOCBOOK_DEFAULT_XSL_HTMLHELP - -The default XSLT file for the DocbookHtmlhelp builder within the + + +The default XSLT file for the DocbookHtmlhelp builder within the current environment, if no other XSLT gets specified via keyword. DOCBOOK_DEFAULT_XSL_MAN - -The default XSLT file for the DocbookMan builder within the + + +The default XSLT file for the DocbookMan builder within the current environment, if no other XSLT gets specified via keyword. DOCBOOK_DEFAULT_XSL_PDF - -The default XSLT file for the DocbookPdf builder within the + + +The default XSLT file for the DocbookPdf builder within the current environment, if no other XSLT gets specified via keyword. DOCBOOK_DEFAULT_XSL_SLIDESHTML - -The default XSLT file for the DocbookSlidesHtml builder within the + + +The default XSLT file for the DocbookSlidesHtml builder within the current environment, if no other XSLT gets specified via keyword. DOCBOOK_DEFAULT_XSL_SLIDESPDF - -The default XSLT file for the DocbookSlidesPdf builder within the + + +The default XSLT file for the DocbookSlidesPdf builder within the current environment, if no other XSLT gets specified via keyword. DOCBOOK_FOP - + + The path to the PDF renderer fop or xep, if one of them is installed (fop gets checked first). @@ -1099,7 +1193,8 @@ if one of them is installed (fop gets checked first). DOCBOOK_FOPCOM - + + The full command-line for the PDF renderer fop or xep. @@ -1107,7 +1202,8 @@ PDF renderer fop or xep. DOCBOOK_FOPCOMSTR - + + The string displayed when a renderer like fop or xep is used to create PDF output from an XML file. @@ -1115,7 +1211,8 @@ The string displayed when a renderer like fop or DOCBOOK_FOPFLAGS - + + Additonal command-line flags for the PDF renderer fop or xep. @@ -1123,7 +1220,8 @@ PDF renderer fop or xep. DOCBOOK_XMLLINT - + + The path to the external executable xmllint, if it's installed. Note, that this is only used as last fallback for resolving XIncludes, if no libxml2 or lxml Python binding can be imported @@ -1133,7 +1231,8 @@ in the current system. DOCBOOK_XMLLINTCOM - + + The full command-line for the external executable xmllint. @@ -1141,7 +1240,8 @@ The full command-line for the external executable DOCBOOK_XMLLINTCOMSTR - + + The string displayed when xmllint is used to resolve XIncludes for a given XML file. @@ -1149,7 +1249,8 @@ XIncludes for a given XML file. DOCBOOK_XMLLINTFLAGS - + + Additonal command-line flags for the external executable xmllint. @@ -1157,7 +1258,8 @@ Additonal command-line flags for the external executable DOCBOOK_XSLTPROC - + + The path to the external executable xsltproc (or saxon, xalan), if one of them is installed. @@ -1168,7 +1270,8 @@ no libxml2 or lxml Python binding can be imported in the current system. DOCBOOK_XSLTPROCCOM - + + The full command-line for the external executable xsltproc (or saxon, xalan). @@ -1177,15 +1280,17 @@ The full command-line for the external executable DOCBOOK_XSLTPROCCOMSTR - -The string displayed when xsltproc is used to transform + + +The string displayed when xsltproc is used to transform an XML file via a given XSLT stylesheet. DOCBOOK_XSLTPROCFLAGS - + + Additonal command-line flags for the external executable xsltproc (or saxon, xalan). @@ -1194,7 +1299,8 @@ Additonal command-line flags for the external executable DOCBOOK_XSLTPROCPARAMS - + + Additonal parameters that are not intended for the XSLT processor executable, but the XSL processing itself. By default, they get appended at the end of the command line for saxon and saxon-xslt, respectively. @@ -1203,134 +1309,149 @@ for saxon and saxon-xslt, respectively. DPATH - + + List of paths to search for import modules. DRPATHPREFIX - + + DRPATHPREFIX. DRPATHSUFFIX - + + DRPATHSUFFIX. DShLibSonameGenerator - + + DShLibSonameGenerator. DSUFFIXES - + + The list of suffixes of files that will be scanned for imported D package files. The default list is: - + ['.d'] DVERPREFIX - + + DVERPREFIX. DVERSIONS - + + List of version tags to enable when compiling. DVERSUFFIX - + + DVERSUFFIX. DVIPDF - + + The TeX DVI file to PDF file converter. DVIPDFCOM - + + The command line used to convert TeX DVI files into a PDF file. DVIPDFCOMSTR - + + The string displayed when a TeX DVI file is converted into a PDF file. -If this is not set, then $DVIPDFCOM (the command line) is displayed. +If this is not set, then $DVIPDFCOM (the command line) is displayed. DVIPDFFLAGS - + + General options passed to the TeX DVI file to PDF file converter. DVIPS - + + The TeX DVI file to PostScript converter. DVIPSFLAGS - + + General options passed to the TeX DVI file to PostScript converter. ENV - + + A dictionary of environment variables to use when invoking commands. When -$ENV is used in a command all list +$ENV is used in a command all list values will be joined using the path separator and any other non-string values will simply be coerced to a string. Note that, by default, -scons +scons does not propagate the environment in force when you execute -scons +scons to the commands used to build target files. This is so that builds will be guaranteed repeatable regardless of the environment variables set at the time -scons +scons is invoked. - + If you want to propagate your environment variables to the commands executed @@ -1338,12 +1459,12 @@ to build target files, you must do so explicitly: - + import os env = Environment(ENV = os.environ) - + Note that you can choose only to propagate certain environment variables. A common example is @@ -1351,12 +1472,12 @@ the system PATH environment variable, so that -scons +scons uses the same utilities as the invoking shell (or other process): - + import os env = Environment(ENV = {'PATH' : os.environ['PATH']}) @@ -1364,7 +1485,8 @@ env = Environment(ENV = {'PATH' : os.environ['PATH']}) ESCAPE - + + A function that will be called to escape shell special characters in command lines. The function should take one argument: the command line string to escape; and should return the escaped command line. @@ -1373,23 +1495,25 @@ string to escape; and should return the escaped command line. F03 - + + The Fortran 03 compiler. -You should normally set the $FORTRAN variable, +You should normally set the $FORTRAN variable, which specifies the default Fortran compiler for all Fortran versions. -You only need to set $F03 if you need to use a specific compiler +You only need to set $F03 if you need to use a specific compiler or compiler version for Fortran 03 files. F03COM - + + The command line used to compile a Fortran 03 source file to an object file. -You only need to set $F03COM if you need to use a specific +You only need to set $F03COM if you need to use a specific command line for Fortran 03 files. -You should normally set the $FORTRANCOM variable, +You should normally set the $FORTRANCOM variable, which specifies the default command line for all Fortran versions. @@ -1397,17 +1521,19 @@ for all Fortran versions. F03COMSTR - + + The string displayed when a Fortran 03 source file is compiled to an object file. -If this is not set, then $F03COM or $FORTRANCOM +If this is not set, then $F03COM or $FORTRANCOM (the command line) is displayed. F03FILESUFFIXES - + + The list of file extensions for which the F03 dialect will be used. By default, this is ['.f03'] @@ -1415,21 +1541,22 @@ default, this is ['.f03'] F03FLAGS - + + General user-specified options that are passed to the Fortran 03 compiler. Note that this variable does not contain (or similar) include search path options -that scons generates automatically from $F03PATH. +that scons generates automatically from $F03PATH. See -$_F03INCFLAGS +$_F03INCFLAGS below, for the variable that expands to those options. -You only need to set $F03FLAGS if you need to define specific +You only need to set $F03FLAGS if you need to define specific user options for Fortran 03 files. -You should normally set the $FORTRANFLAGS variable, +You should normally set the $FORTRANFLAGS variable, which specifies the user-specified options passed to the default Fortran compiler for all Fortran versions. @@ -1438,83 +1565,86 @@ for all Fortran versions. _F03INCFLAGS - + + An automatically-generated construction variable containing the Fortran 03 compiler command-line options for specifying directories to be searched for include files. -The value of $_F03INCFLAGS is created -by appending $INCPREFIX and $INCSUFFIX +The value of $_F03INCFLAGS is created +by appending $INCPREFIX and $INCSUFFIX to the beginning and end -of each directory in $F03PATH. +of each directory in $F03PATH. F03PATH - + + The list of directories that the Fortran 03 compiler will search for include directories. The implicit dependency scanner will search these directories for include files. Don't explicitly put include directory -arguments in $F03FLAGS because the result will be non-portable +arguments in $F03FLAGS because the result will be non-portable and the directories will not be searched by the dependency scanner. Note: -directory names in $F03PATH will be looked-up relative to the SConscript +directory names in $F03PATH will be looked-up relative to the SConscript directory when they are used in a command. To force -scons +scons to look-up a directory relative to the root of the source tree use #: -You only need to set $F03PATH if you need to define a specific +You only need to set $F03PATH if you need to define a specific include path for Fortran 03 files. -You should normally set the $FORTRANPATH variable, +You should normally set the $FORTRANPATH variable, which specifies the include path for the default Fortran compiler for all Fortran versions. - + env = Environment(F03PATH='#/include') - + The directory look-up can also be forced using the -Dir() +Dir() function: - + include = Dir('include') env = Environment(F03PATH=include) - + The directory list will be added to command lines through the automatically-generated -$_F03INCFLAGS +$_F03INCFLAGS construction variable, which is constructed by appending the values of the -$INCPREFIX and $INCSUFFIX +$INCPREFIX and $INCSUFFIX construction variables to the beginning and end -of each directory in $F03PATH. +of each directory in $F03PATH. Any command lines you define that need the F03PATH directory list should -include $_F03INCFLAGS: +include $_F03INCFLAGS: - + env = Environment(F03COM="my_compiler $_F03INCFLAGS -c -o $TARGET $SOURCE") F03PPCOM - + + The command line used to compile a Fortran 03 source file to an object file after first running the file through the C preprocessor. -Any options specified in the $F03FLAGS and $CPPFLAGS construction variables +Any options specified in the $F03FLAGS and $CPPFLAGS construction variables are included on this command line. -You only need to set $F03PPCOM if you need to use a specific +You only need to set $F03PPCOM if you need to use a specific C-preprocessor command line for Fortran 03 files. -You should normally set the $FORTRANPPCOM variable, +You should normally set the $FORTRANPPCOM variable, which specifies the default C-preprocessor command line for all Fortran versions. @@ -1522,18 +1652,20 @@ for all Fortran versions. F03PPCOMSTR - + + 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 $F03PPCOM or $FORTRANPPCOM +If this is not set, then $F03PPCOM or $FORTRANPPCOM (the command line) is displayed. F03PPFILESUFFIXES - + + The list of file extensions for which the compilation + preprocessor pass for F03 dialect will be used. By default, this is empty @@ -1541,23 +1673,25 @@ F03 dialect will be used. By default, this is empty F08 - + + The Fortran 08 compiler. -You should normally set the $FORTRAN variable, +You should normally set the $FORTRAN variable, which specifies the default Fortran compiler for all Fortran versions. -You only need to set $F08 if you need to use a specific compiler +You only need to set $F08 if you need to use a specific compiler or compiler version for Fortran 08 files. F08COM - + + The command line used to compile a Fortran 08 source file to an object file. -You only need to set $F08COM if you need to use a specific +You only need to set $F08COM if you need to use a specific command line for Fortran 08 files. -You should normally set the $FORTRANCOM variable, +You should normally set the $FORTRANCOM variable, which specifies the default command line for all Fortran versions. @@ -1565,17 +1699,19 @@ for all Fortran versions. F08COMSTR - + + The string displayed when a Fortran 08 source file is compiled to an object file. -If this is not set, then $F08COM or $FORTRANCOM +If this is not set, then $F08COM or $FORTRANCOM (the command line) is displayed. F08FILESUFFIXES - + + The list of file extensions for which the F08 dialect will be used. By default, this is ['.f08'] @@ -1583,21 +1719,22 @@ default, this is ['.f08'] F08FLAGS - + + General user-specified options that are passed to the Fortran 08 compiler. Note that this variable does not contain (or similar) include search path options -that scons generates automatically from $F08PATH. +that scons generates automatically from $F08PATH. See -$_F08INCFLAGS +$_F08INCFLAGS below, for the variable that expands to those options. -You only need to set $F08FLAGS if you need to define specific +You only need to set $F08FLAGS if you need to define specific user options for Fortran 08 files. -You should normally set the $FORTRANFLAGS variable, +You should normally set the $FORTRANFLAGS variable, which specifies the user-specified options passed to the default Fortran compiler for all Fortran versions. @@ -1606,83 +1743,86 @@ for all Fortran versions. _F08INCFLAGS - + + An automatically-generated construction variable containing the Fortran 08 compiler command-line options for specifying directories to be searched for include files. -The value of $_F08INCFLAGS is created -by appending $INCPREFIX and $INCSUFFIX +The value of $_F08INCFLAGS is created +by appending $INCPREFIX and $INCSUFFIX to the beginning and end -of each directory in $F08PATH. +of each directory in $F08PATH. F08PATH - + + The list of directories that the Fortran 08 compiler will search for include directories. The implicit dependency scanner will search these directories for include files. Don't explicitly put include directory -arguments in $F08FLAGS because the result will be non-portable +arguments in $F08FLAGS because the result will be non-portable and the directories will not be searched by the dependency scanner. Note: -directory names in $F08PATH will be looked-up relative to the SConscript +directory names in $F08PATH will be looked-up relative to the SConscript directory when they are used in a command. To force -scons +scons to look-up a directory relative to the root of the source tree use #: -You only need to set $F08PATH if you need to define a specific +You only need to set $F08PATH if you need to define a specific include path for Fortran 08 files. -You should normally set the $FORTRANPATH variable, +You should normally set the $FORTRANPATH variable, which specifies the include path for the default Fortran compiler for all Fortran versions. - + env = Environment(F08PATH='#/include') - + The directory look-up can also be forced using the -Dir() +Dir() function: - + include = Dir('include') env = Environment(F08PATH=include) - + The directory list will be added to command lines through the automatically-generated -$_F08INCFLAGS +$_F08INCFLAGS construction variable, which is constructed by appending the values of the -$INCPREFIX and $INCSUFFIX +$INCPREFIX and $INCSUFFIX construction variables to the beginning and end -of each directory in $F08PATH. +of each directory in $F08PATH. Any command lines you define that need the F08PATH directory list should -include $_F08INCFLAGS: +include $_F08INCFLAGS: - + env = Environment(F08COM="my_compiler $_F08INCFLAGS -c -o $TARGET $SOURCE") F08PPCOM - + + The command line used to compile a Fortran 08 source file to an object file after first running the file through the C preprocessor. -Any options specified in the $F08FLAGS and $CPPFLAGS construction variables +Any options specified in the $F08FLAGS and $CPPFLAGS construction variables are included on this command line. -You only need to set $F08PPCOM if you need to use a specific +You only need to set $F08PPCOM if you need to use a specific C-preprocessor command line for Fortran 08 files. -You should normally set the $FORTRANPPCOM variable, +You should normally set the $FORTRANPPCOM variable, which specifies the default C-preprocessor command line for all Fortran versions. @@ -1690,18 +1830,20 @@ for all Fortran versions. F08PPCOMSTR - + + 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 $F08PPCOM or $FORTRANPPCOM +If this is not set, then $F08PPCOM or $FORTRANPPCOM (the command line) is displayed. F08PPFILESUFFIXES - + + The list of file extensions for which the compilation + preprocessor pass for F08 dialect will be used. By default, this is empty @@ -1709,23 +1851,25 @@ F08 dialect will be used. By default, this is empty F77 - + + The Fortran 77 compiler. -You should normally set the $FORTRAN variable, +You should normally set the $FORTRAN variable, which specifies the default Fortran compiler for all Fortran versions. -You only need to set $F77 if you need to use a specific compiler +You only need to set $F77 if you need to use a specific compiler or compiler version for Fortran 77 files. F77COM - + + The command line used to compile a Fortran 77 source file to an object file. -You only need to set $F77COM if you need to use a specific +You only need to set $F77COM if you need to use a specific command line for Fortran 77 files. -You should normally set the $FORTRANCOM variable, +You should normally set the $FORTRANCOM variable, which specifies the default command line for all Fortran versions. @@ -1733,17 +1877,19 @@ for all Fortran versions. F77COMSTR - + + The string displayed when a Fortran 77 source file is compiled to an object file. -If this is not set, then $F77COM or $FORTRANCOM +If this is not set, then $F77COM or $FORTRANCOM (the command line) is displayed. F77FILESUFFIXES - + + The list of file extensions for which the F77 dialect will be used. By default, this is ['.f77'] @@ -1751,21 +1897,22 @@ default, this is ['.f77'] F77FLAGS - + + General user-specified options that are passed to the Fortran 77 compiler. Note that this variable does not contain (or similar) include search path options -that scons generates automatically from $F77PATH. +that scons generates automatically from $F77PATH. See -$_F77INCFLAGS +$_F77INCFLAGS below, for the variable that expands to those options. -You only need to set $F77FLAGS if you need to define specific +You only need to set $F77FLAGS if you need to define specific user options for Fortran 77 files. -You should normally set the $FORTRANFLAGS variable, +You should normally set the $FORTRANFLAGS variable, which specifies the user-specified options passed to the default Fortran compiler for all Fortran versions. @@ -1774,83 +1921,86 @@ for all Fortran versions. _F77INCFLAGS - + + An automatically-generated construction variable containing the Fortran 77 compiler command-line options for specifying directories to be searched for include files. -The value of $_F77INCFLAGS is created -by appending $INCPREFIX and $INCSUFFIX +The value of $_F77INCFLAGS is created +by appending $INCPREFIX and $INCSUFFIX to the beginning and end -of each directory in $F77PATH. +of each directory in $F77PATH. F77PATH - + + The list of directories that the Fortran 77 compiler will search for include directories. The implicit dependency scanner will search these directories for include files. Don't explicitly put include directory -arguments in $F77FLAGS because the result will be non-portable +arguments in $F77FLAGS because the result will be non-portable and the directories will not be searched by the dependency scanner. Note: -directory names in $F77PATH will be looked-up relative to the SConscript +directory names in $F77PATH will be looked-up relative to the SConscript directory when they are used in a command. To force -scons +scons to look-up a directory relative to the root of the source tree use #: -You only need to set $F77PATH if you need to define a specific +You only need to set $F77PATH if you need to define a specific include path for Fortran 77 files. -You should normally set the $FORTRANPATH variable, +You should normally set the $FORTRANPATH variable, which specifies the include path for the default Fortran compiler for all Fortran versions. - + env = Environment(F77PATH='#/include') - + The directory look-up can also be forced using the -Dir() +Dir() function: - + include = Dir('include') env = Environment(F77PATH=include) - + The directory list will be added to command lines through the automatically-generated -$_F77INCFLAGS +$_F77INCFLAGS construction variable, which is constructed by appending the values of the -$INCPREFIX and $INCSUFFIX +$INCPREFIX and $INCSUFFIX construction variables to the beginning and end -of each directory in $F77PATH. +of each directory in $F77PATH. Any command lines you define that need the F77PATH directory list should -include $_F77INCFLAGS: +include $_F77INCFLAGS: - + env = Environment(F77COM="my_compiler $_F77INCFLAGS -c -o $TARGET $SOURCE") F77PPCOM - + + The command line used to compile a Fortran 77 source file to an object file after first running the file through the C preprocessor. -Any options specified in the $F77FLAGS and $CPPFLAGS construction variables +Any options specified in the $F77FLAGS and $CPPFLAGS construction variables are included on this command line. -You only need to set $F77PPCOM if you need to use a specific +You only need to set $F77PPCOM if you need to use a specific C-preprocessor command line for Fortran 77 files. -You should normally set the $FORTRANPPCOM variable, +You should normally set the $FORTRANPPCOM variable, which specifies the default C-preprocessor command line for all Fortran versions. @@ -1858,18 +2008,20 @@ for all Fortran versions. F77PPCOMSTR - + + 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 $F77PPCOM or $FORTRANPPCOM +If this is not set, then $F77PPCOM or $FORTRANPPCOM (the command line) is displayed. F77PPFILESUFFIXES - + + The list of file extensions for which the compilation + preprocessor pass for F77 dialect will be used. By default, this is empty @@ -1877,23 +2029,25 @@ F77 dialect will be used. By default, this is empty F90 - + + The Fortran 90 compiler. -You should normally set the $FORTRAN variable, +You should normally set the $FORTRAN variable, which specifies the default Fortran compiler for all Fortran versions. -You only need to set $F90 if you need to use a specific compiler +You only need to set $F90 if you need to use a specific compiler or compiler version for Fortran 90 files. F90COM - + + The command line used to compile a Fortran 90 source file to an object file. -You only need to set $F90COM if you need to use a specific +You only need to set $F90COM if you need to use a specific command line for Fortran 90 files. -You should normally set the $FORTRANCOM variable, +You should normally set the $FORTRANCOM variable, which specifies the default command line for all Fortran versions. @@ -1901,17 +2055,19 @@ for all Fortran versions. F90COMSTR - + + The string displayed when a Fortran 90 source file is compiled to an object file. -If this is not set, then $F90COM or $FORTRANCOM +If this is not set, then $F90COM or $FORTRANCOM (the command line) is displayed. F90FILESUFFIXES - + + The list of file extensions for which the F90 dialect will be used. By default, this is ['.f90'] @@ -1919,21 +2075,22 @@ default, this is ['.f90'] F90FLAGS - + + General user-specified options that are passed to the Fortran 90 compiler. Note that this variable does not contain (or similar) include search path options -that scons generates automatically from $F90PATH. +that scons generates automatically from $F90PATH. See -$_F90INCFLAGS +$_F90INCFLAGS below, for the variable that expands to those options. -You only need to set $F90FLAGS if you need to define specific +You only need to set $F90FLAGS if you need to define specific user options for Fortran 90 files. -You should normally set the $FORTRANFLAGS variable, +You should normally set the $FORTRANFLAGS variable, which specifies the user-specified options passed to the default Fortran compiler for all Fortran versions. @@ -1942,83 +2099,86 @@ for all Fortran versions. _F90INCFLAGS - + + An automatically-generated construction variable containing the Fortran 90 compiler command-line options for specifying directories to be searched for include files. -The value of $_F90INCFLAGS is created -by appending $INCPREFIX and $INCSUFFIX +The value of $_F90INCFLAGS is created +by appending $INCPREFIX and $INCSUFFIX to the beginning and end -of each directory in $F90PATH. +of each directory in $F90PATH. F90PATH - + + The list of directories that the Fortran 90 compiler will search for include directories. The implicit dependency scanner will search these directories for include files. Don't explicitly put include directory -arguments in $F90FLAGS because the result will be non-portable +arguments in $F90FLAGS because the result will be non-portable and the directories will not be searched by the dependency scanner. Note: -directory names in $F90PATH will be looked-up relative to the SConscript +directory names in $F90PATH will be looked-up relative to the SConscript directory when they are used in a command. To force -scons +scons to look-up a directory relative to the root of the source tree use #: -You only need to set $F90PATH if you need to define a specific +You only need to set $F90PATH if you need to define a specific include path for Fortran 90 files. -You should normally set the $FORTRANPATH variable, +You should normally set the $FORTRANPATH variable, which specifies the include path for the default Fortran compiler for all Fortran versions. - + env = Environment(F90PATH='#/include') - + The directory look-up can also be forced using the -Dir() +Dir() function: - + include = Dir('include') env = Environment(F90PATH=include) - + The directory list will be added to command lines through the automatically-generated -$_F90INCFLAGS +$_F90INCFLAGS construction variable, which is constructed by appending the values of the -$INCPREFIX and $INCSUFFIX +$INCPREFIX and $INCSUFFIX construction variables to the beginning and end -of each directory in $F90PATH. +of each directory in $F90PATH. Any command lines you define that need the F90PATH directory list should -include $_F90INCFLAGS: +include $_F90INCFLAGS: - + env = Environment(F90COM="my_compiler $_F90INCFLAGS -c -o $TARGET $SOURCE") F90PPCOM - + + The command line used to compile a Fortran 90 source file to an object file after first running the file through the C preprocessor. -Any options specified in the $F90FLAGS and $CPPFLAGS construction variables +Any options specified in the $F90FLAGS and $CPPFLAGS construction variables are included on this command line. -You only need to set $F90PPCOM if you need to use a specific +You only need to set $F90PPCOM if you need to use a specific C-preprocessor command line for Fortran 90 files. -You should normally set the $FORTRANPPCOM variable, +You should normally set the $FORTRANPPCOM variable, which specifies the default C-preprocessor command line for all Fortran versions. @@ -2026,17 +2186,19 @@ for all Fortran versions. F90PPCOMSTR - + + 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 $F90PPCOM or $FORTRANPPCOM +If this is not set, then $F90PPCOM or $FORTRANPPCOM (the command line) is displayed. F90PPFILESUFFIXES - + + The list of file extensions for which the compilation + preprocessor pass for F90 dialect will be used. By default, this is empty @@ -2044,23 +2206,25 @@ F90 dialect will be used. By default, this is empty F95 - + + The Fortran 95 compiler. -You should normally set the $FORTRAN variable, +You should normally set the $FORTRAN variable, which specifies the default Fortran compiler for all Fortran versions. -You only need to set $F95 if you need to use a specific compiler +You only need to set $F95 if you need to use a specific compiler or compiler version for Fortran 95 files. F95COM - + + The command line used to compile a Fortran 95 source file to an object file. -You only need to set $F95COM if you need to use a specific +You only need to set $F95COM if you need to use a specific command line for Fortran 95 files. -You should normally set the $FORTRANCOM variable, +You should normally set the $FORTRANCOM variable, which specifies the default command line for all Fortran versions. @@ -2068,17 +2232,19 @@ for all Fortran versions. F95COMSTR - + + The string displayed when a Fortran 95 source file is compiled to an object file. -If this is not set, then $F95COM or $FORTRANCOM +If this is not set, then $F95COM or $FORTRANCOM (the command line) is displayed. F95FILESUFFIXES - + + The list of file extensions for which the F95 dialect will be used. By default, this is ['.f95'] @@ -2086,21 +2252,22 @@ default, this is ['.f95'] F95FLAGS - + + General user-specified options that are passed to the Fortran 95 compiler. Note that this variable does not contain (or similar) include search path options -that scons generates automatically from $F95PATH. +that scons generates automatically from $F95PATH. See -$_F95INCFLAGS +$_F95INCFLAGS below, for the variable that expands to those options. -You only need to set $F95FLAGS if you need to define specific +You only need to set $F95FLAGS if you need to define specific user options for Fortran 95 files. -You should normally set the $FORTRANFLAGS variable, +You should normally set the $FORTRANFLAGS variable, which specifies the user-specified options passed to the default Fortran compiler for all Fortran versions. @@ -2109,83 +2276,86 @@ for all Fortran versions. _F95INCFLAGS - + + An automatically-generated construction variable containing the Fortran 95 compiler command-line options for specifying directories to be searched for include files. -The value of $_F95INCFLAGS is created -by appending $INCPREFIX and $INCSUFFIX +The value of $_F95INCFLAGS is created +by appending $INCPREFIX and $INCSUFFIX to the beginning and end -of each directory in $F95PATH. +of each directory in $F95PATH. F95PATH - + + The list of directories that the Fortran 95 compiler will search for include directories. The implicit dependency scanner will search these directories for include files. Don't explicitly put include directory -arguments in $F95FLAGS because the result will be non-portable +arguments in $F95FLAGS because the result will be non-portable and the directories will not be searched by the dependency scanner. Note: -directory names in $F95PATH will be looked-up relative to the SConscript +directory names in $F95PATH will be looked-up relative to the SConscript directory when they are used in a command. To force -scons +scons to look-up a directory relative to the root of the source tree use #: -You only need to set $F95PATH if you need to define a specific +You only need to set $F95PATH if you need to define a specific include path for Fortran 95 files. -You should normally set the $FORTRANPATH variable, +You should normally set the $FORTRANPATH variable, which specifies the include path for the default Fortran compiler for all Fortran versions. - + env = Environment(F95PATH='#/include') - + The directory look-up can also be forced using the -Dir() +Dir() function: - + include = Dir('include') env = Environment(F95PATH=include) - + The directory list will be added to command lines through the automatically-generated -$_F95INCFLAGS +$_F95INCFLAGS construction variable, which is constructed by appending the values of the -$INCPREFIX and $INCSUFFIX +$INCPREFIX and $INCSUFFIX construction variables to the beginning and end -of each directory in $F95PATH. +of each directory in $F95PATH. Any command lines you define that need the F95PATH directory list should -include $_F95INCFLAGS: +include $_F95INCFLAGS: - + env = Environment(F95COM="my_compiler $_F95INCFLAGS -c -o $TARGET $SOURCE") F95PPCOM - + + The command line used to compile a Fortran 95 source file to an object file after first running the file through the C preprocessor. -Any options specified in the $F95FLAGS and $CPPFLAGS construction variables +Any options specified in the $F95FLAGS and $CPPFLAGS construction variables are included on this command line. -You only need to set $F95PPCOM if you need to use a specific +You only need to set $F95PPCOM if you need to use a specific C-preprocessor command line for Fortran 95 files. -You should normally set the $FORTRANPPCOM variable, +You should normally set the $FORTRANPPCOM variable, which specifies the default C-preprocessor command line for all Fortran versions. @@ -2193,18 +2363,20 @@ for all Fortran versions. F95PPCOMSTR - + + 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 $F95PPCOM or $FORTRANPPCOM +If this is not set, then $F95PPCOM or $FORTRANPPCOM (the command line) is displayed. F95PPFILESUFFIXES - + + The list of file extensions for which the compilation + preprocessor pass for F95 dialect will be used. By default, this is empty @@ -2212,11 +2384,13 @@ F95 dialect will be used. By default, this is empty File - + + A function that converts a string into a File instance relative to the target being built. - + + A function that converts a string into a File instance relative to the target being built. @@ -2224,7 +2398,8 @@ target being built. FORTRAN - + + The default Fortran compiler for all versions of Fortran. @@ -2232,31 +2407,34 @@ for all versions of Fortran. FORTRANCOM - + + The command line used to compile a Fortran source file to an object file. By default, any options specified -in the $FORTRANFLAGS, -$CPPFLAGS, -$_CPPDEFFLAGS, -$_FORTRANMODFLAG, and -$_FORTRANINCFLAGS construction variables +in the $FORTRANFLAGS, +$CPPFLAGS, +$_CPPDEFFLAGS, +$_FORTRANMODFLAG, and +$_FORTRANINCFLAGS construction variables are included on this command line. FORTRANCOMSTR - + + The string displayed when a Fortran source file is compiled to an object file. -If this is not set, then $FORTRANCOM +If this is not set, then $FORTRANCOM (the command line) is displayed. FORTRANFILESUFFIXES - + + The list of file extensions for which the FORTRAN dialect will be used. By default, this is ['.f', '.for', '.ftn'] @@ -2264,16 +2442,17 @@ default, this is ['.f', '.for', '.ftn'] FORTRANFLAGS - + + General user-specified options that are passed to the Fortran compiler. Note that this variable does not contain (or similar) include or module search path options -that scons generates automatically from $FORTRANPATH. +that scons generates automatically from $FORTRANPATH. See -$_FORTRANINCFLAGS and $_FORTRANMODFLAG, +$_FORTRANINCFLAGS and $_FORTRANMODFLAG, below, for the variables that expand those options. @@ -2281,22 +2460,24 @@ for the variables that expand those options. _FORTRANINCFLAGS - + + An automatically-generated construction variable containing the Fortran compiler command-line options for specifying directories to be searched for include files and module files. -The value of $_FORTRANINCFLAGS is created +The value of $_FORTRANINCFLAGS is created by respectively prepending and appending -$INCPREFIX and $INCSUFFIX +$INCPREFIX and $INCSUFFIX to the beginning and end -of each directory in $FORTRANPATH. +of each directory in $FORTRANPATH. FORTRANMODDIR - + + Directory location where the Fortran compiler should place any module files it generates. This variable is empty, by default. Some Fortran compilers will internally append this directory in the search path @@ -2306,44 +2487,48 @@ for module files, as well. FORTRANMODDIRPREFIX - + + The prefix used to specify a module directory on the Fortran compiler command line. This will be prepended to the beginning of the directory -in the $FORTRANMODDIR construction variables -when the $_FORTRANMODFLAG variables is automatically generated. +in the $FORTRANMODDIR construction variables +when the $_FORTRANMODFLAG variables is automatically generated. FORTRANMODDIRSUFFIX - + + The suffix used to specify a module directory on the Fortran compiler command line. This will be appended to the end of the directory -in the $FORTRANMODDIR construction variables -when the $_FORTRANMODFLAG variables is automatically generated. +in the $FORTRANMODDIR construction variables +when the $_FORTRANMODFLAG variables is automatically generated. _FORTRANMODFLAG - + + An automatically-generated construction variable containing the Fortran compiler command-line option for specifying the directory location where the Fortran compiler should place any module files that happen to get generated during compilation. -The value of $_FORTRANMODFLAG is created +The value of $_FORTRANMODFLAG is created by respectively prepending and appending -$FORTRANMODDIRPREFIX and $FORTRANMODDIRSUFFIX -to the beginning and end of the directory in $FORTRANMODDIR. +$FORTRANMODDIRPREFIX and $FORTRANMODDIRSUFFIX +to the beginning and end of the directory in $FORTRANMODDIR. FORTRANMODPREFIX - + + The module file prefix used by the Fortran compiler. SCons assumes that the Fortran compiler follows the quasi-standard naming convention for module files of @@ -2357,7 +2542,8 @@ module file name as scons attempts to resolve dependencies. FORTRANMODSUFFIX - + + The module file suffix used by the Fortran compiler. SCons assumes that the Fortran compiler follows the quasi-standard naming convention for module files of @@ -2371,7 +2557,8 @@ module file name as scons attempts to resolve dependencies. FORTRANPATH - + + The list of directories that the Fortran compiler will search for include files and (for some compilers) module files. The Fortran implicit dependency scanner will search these directories for include files (but @@ -2381,74 +2568,77 @@ include directory arguments in FORTRANFLAGS because the result will be non-portable and the directories will not be searched by the dependency scanner. Note: directory names in FORTRANPATH will be looked-up relative to the SConscript directory when they are used in a command. To force -scons +scons to look-up a directory relative to the root of the source tree use #: - + env = Environment(FORTRANPATH='#/include') - + The directory look-up can also be forced using the -Dir() +Dir() function: - + include = Dir('include') env = Environment(FORTRANPATH=include) - + The directory list will be added to command lines through the automatically-generated -$_FORTRANINCFLAGS +$_FORTRANINCFLAGS construction variable, which is constructed by respectively prepending and appending the values of the -$INCPREFIX and $INCSUFFIX +$INCPREFIX and $INCSUFFIX construction variables to the beginning and end -of each directory in $FORTRANPATH. +of each directory in $FORTRANPATH. Any command lines you define that need the FORTRANPATH directory list should -include $_FORTRANINCFLAGS: +include $_FORTRANINCFLAGS: - + env = Environment(FORTRANCOM="my_compiler $_FORTRANINCFLAGS -c -o $TARGET $SOURCE") FORTRANPPCOM - + + The command line used to compile a Fortran source file to an object file after first running the file through the C preprocessor. -By default, any options specified in the $FORTRANFLAGS, -$CPPFLAGS, -$_CPPDEFFLAGS, -$_FORTRANMODFLAG, and -$_FORTRANINCFLAGS +By default, any options specified in the $FORTRANFLAGS, +$CPPFLAGS, +$_CPPDEFFLAGS, +$_FORTRANMODFLAG, and +$_FORTRANINCFLAGS construction variables are included on this command line. FORTRANPPCOMSTR - + + 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 $FORTRANPPCOM +If this is not set, then $FORTRANPPCOM (the command line) is displayed. FORTRANPPFILESUFFIXES - + + The list of file extensions for which the compilation + preprocessor pass for FORTRAN dialect will be used. By default, this is ['.fpp', '.FPP'] @@ -2456,14 +2646,15 @@ FORTRAN dialect will be used. By default, this is ['.fpp', '.FPP'] FORTRANSUFFIXES - + + The list of suffixes of files that will be scanned for Fortran implicit dependencies (INCLUDE lines and USE statements). The default list is: - + [".f", ".F", ".for", ".FOR", ".ftn", ".FTN", ".fpp", ".FPP", ".f77", ".F77", ".f90", ".F90", ".f95", ".F95"] @@ -2471,47 +2662,50 @@ The default list is: FRAMEWORKPATH - + + On Mac OS X with gcc, a list containing the paths to search for frameworks. Used by the compiler to find framework-style includes like #include <Fmwk/Header.h>. Used by the linker to find user-specified frameworks when linking (see - $FRAMEWORKS). + $FRAMEWORKS). For example: - + env.AppendUnique(FRAMEWORKPATH='#myframeworkdir') - + will add - + ... -Fmyframeworkdir - + to the compiler and linker command lines. _FRAMEWORKPATH - + + On Mac OS X with gcc, an automatically-generated construction variable containing the linker command-line options corresponding to - $FRAMEWORKPATH. + $FRAMEWORKPATH. FRAMEWORKPATHPREFIX - + + On Mac OS X with gcc, the prefix to be used for the FRAMEWORKPATH entries. - (see $FRAMEWORKPATH). + (see $FRAMEWORKPATH). The default value is . @@ -2519,64 +2713,70 @@ The default list is: FRAMEWORKPREFIX - + + On Mac OS X with gcc, the prefix to be used for linking in frameworks - (see $FRAMEWORKS). + (see $FRAMEWORKS). The default value is . + + _FRAMEWORKS + + + On Mac OS X with gcc, + an automatically-generated construction variable + containing the linker command-line options + for linking with FRAMEWORKS. + + + FRAMEWORKS - + + On Mac OS X with gcc, a list of the framework names to be linked into a program or shared library or bundle. The default value is the empty list. For example: - + env.AppendUnique(FRAMEWORKS=Split('System Cocoa SystemConfiguration')) - - _FRAMEWORKS - - On Mac OS X with gcc, - an automatically-generated construction variable - containing the linker command-line options - for linking with FRAMEWORKS. - - - FRAMEWORKSFLAGS - + + On Mac OS X with gcc, general user-supplied frameworks options to be added at the end of a command line building a loadable module. (This has been largely superseded by - the $FRAMEWORKPATH, $FRAMEWORKPATHPREFIX, - $FRAMEWORKPREFIX and $FRAMEWORKS variables + the $FRAMEWORKPATH, $FRAMEWORKPATHPREFIX, + $FRAMEWORKPREFIX and $FRAMEWORKS variables described above.) GS - + + The Ghostscript program used, e.g. to convert PostScript to PDF files. GSCOM - + + The full Ghostscript command line used for the conversion process. Its default value is $GS $GSFLAGS -sOutputFile=$TARGET $SOURCES. @@ -2584,16 +2784,18 @@ value is $GS $GSFLAGS -sOutputFile=$TARGET $SOURCES GSCOMSTR - + + The string displayed when Ghostscript is called for the conversion process. -If this is not set (the default), then $GSCOM (the command line) is displayed. +If this is not set (the default), then $GSCOM (the command line) is displayed. GSFLAGS - + + General options passed to the Ghostscript program, when converting PostScript to PDF files for example. Its default value is -dNOPAUSE -dBATCH -sDEVICE=pdfwrite @@ -2604,6 +2806,15 @@ is -dNOPAUSE -dBATCH -sDEVICE=pdfwrite HOST_ARCH + The name of the host hardware architecture used to create the Environment. + If a platform is specified when creating the Environment, then + that Platform's logic will handle setting this value. + This value is immutable, and should not be changed by the user after + the Environment is initialized. + Currently only set for Win32. + + + Sets the host architecture for Visual Studio compiler. If not set, default to the detected host architecture: note that this may depend on the python you are using. @@ -2611,28 +2822,20 @@ This variable must be passed as an argument to the Environment() constructor; setting it later has no effect. - -Valid values are the same as for $TARGET_ARCH. + +Valid values are the same as for $TARGET_ARCH. - + This is currently only used on Windows, but in the future it will be used on other OSes as well. - - - The name of the host hardware architecture used to create the Environment. - If a platform is specified when creating the Environment, then - that Platform's logic will handle setting this value. - This value is immutable, and should not be changed by the user after - the Environment is initialized. - Currently only set for Win32. - - + HOST_OS - + + The name of the host operating system used to create the Environment. If a platform is specified when creating the Environment, then that Platform's logic will handle setting this value. @@ -2644,54 +2847,59 @@ used on other OSes as well. IDLSUFFIXES - + + The list of suffixes of files that will be scanned for IDL implicit dependencies (#include or import lines). The default list is: - + [".idl", ".IDL"] IMPLIBNOVERSIONSYMLINKS - -Used to override $SHLIBNOVERSIONSYMLINKS/$LDMODULENOVERSIONSYMLINKS when + + +Used to override $SHLIBNOVERSIONSYMLINKS/$LDMODULENOVERSIONSYMLINKS when creating versioned import library for a shared library/loadable module. If not defined, -then $SHLIBNOVERSIONSYMLINKS/$LDMODULENOVERSIONSYMLINKS is used to determine +then $SHLIBNOVERSIONSYMLINKS/$LDMODULENOVERSIONSYMLINKS is used to determine whether to disable symlink generation or not. IMPLIBPREFIX - + + The prefix used for import library names. For example, cygwin uses import libraries (libfoo.dll.a) in pair with dynamic libraries -(cygfoo.dll). The cyglink linker sets -$IMPLIBPREFIX to 'lib' and $SHLIBPREFIX +(cygfoo.dll). The cyglink linker sets +$IMPLIBPREFIX to 'lib' and $SHLIBPREFIX to 'cyg'. IMPLIBSUFFIX - + + The suffix used for import library names. For example, cygwin uses import libraries (libfoo.dll.a) in pair with dynamic libraries -(cygfoo.dll). The cyglink linker sets -$IMPLIBSUFFIX to '.dll.a' and $SHLIBSUFFIX +(cygfoo.dll). The cyglink linker sets +$IMPLIBSUFFIX to '.dll.a' and $SHLIBSUFFIX to '.dll'. IMPLIBVERSION - -Used to override $SHLIBVERSION/$LDMODULEVERSION when + + +Used to override $SHLIBVERSION/$LDMODULEVERSION when generating versioned import library for a shared library/loadable module. If undefined, the $SHLIBVERSION/$LDMODULEVERSION is used to determine the version of versioned import library. @@ -2700,13 +2908,14 @@ determine the version of versioned import library. IMPLICIT_COMMAND_DEPENDENCIES - + + Controls whether or not SCons will add implicit dependencies for the commands executed to build targets. - + By default, SCons will add to each target an implicit dependency on the command @@ -2720,9 +2929,9 @@ variable in the environment used to execute the command. - + If the construction variable -$IMPLICIT_COMMAND_DEPENDENCIES +$IMPLICIT_COMMAND_DEPENDENCIES is set to a false value (None, False, @@ -2733,38 +2942,41 @@ not be added to the targets built with that construction environment. - + env = Environment(IMPLICIT_COMMAND_DEPENDENCIES = 0) INCPREFIX - + + The prefix used to specify an include directory on the C compiler command line. This will be prepended to the beginning of each directory -in the $CPPPATH and $FORTRANPATH construction variables -when the $_CPPINCFLAGS and $_FORTRANINCFLAGS +in the $CPPPATH and $FORTRANPATH construction variables +when the $_CPPINCFLAGS and $_FORTRANINCFLAGS variables are automatically generated. INCSUFFIX - + + The suffix used to specify an include directory on the C compiler command line. This will be appended to the end of each directory -in the $CPPPATH and $FORTRANPATH construction variables -when the $_CPPINCFLAGS and $_FORTRANINCFLAGS +in the $CPPPATH and $FORTRANPATH construction variables +when the $_CPPINCFLAGS and $_FORTRANINCFLAGS variables are automatically generated. INSTALL - + + A function to be called to install a file into a destination file name. The default function copies the file into the destination @@ -2773,11 +2985,11 @@ to match the source file's). The function takes the following arguments: - + def install(dest, source, env): - + dest is the path name of the destination file. source @@ -2791,19 +3003,21 @@ in force for this file installation. INSTALLSTR - + + The string displayed when a file is installed into a destination file name. The default is: - + Install file: "$SOURCE" as "$TARGET" INTEL_C_COMPILER_VERSION - + + Set by the "intelc" Tool to the major version number of the Intel C compiler selected for use. @@ -2812,23 +3026,27 @@ selected for use. JAR - + + The Java archive tool. - + + The Java archive tool. JARCHDIR - + + The directory to which the Java archive tool should change (using the option). - + + The directory to which the Java archive tool should change (using the @@ -2838,39 +3056,44 @@ option). JARCOM - + + The command line used to call the Java archive tool. - + + The command line used to call the Java archive tool. JARCOMSTR - + + The string displayed when the Java archive tool is called If this is not set, then $JARCOM (the command line) is displayed. - + env = Environment(JARCOMSTR = "JARchiving $SOURCES into $TARGET") - + + The string displayed when the Java archive tool is called If this is not set, then $JARCOM (the command line) is displayed. - + env = Environment(JARCOMSTR = "JARchiving $SOURCES into $TARGET") JARFLAGS - + + General options passed to the Java archive tool. By default this is set to @@ -2878,7 +3101,8 @@ to create the necessary jar file. - + + General options passed to the Java archive tool. By default this is set to @@ -2890,12 +3114,14 @@ file. JARSUFFIX - + + The suffix for Java archives: .jar by default. - + + The suffix for Java archives: .jar by default. @@ -2904,10 +3130,11 @@ by default. JAVABOOTCLASSPATH - + + Specifies the list of directories that will be added to the - javac command line + javac command line via the option. The individual directory names will be separated by the operating system's path separate character @@ -2919,46 +3146,51 @@ by default. JAVAC - + + The Java compiler. JAVACCOM - + + The command line used to compile a directory tree containing Java source files to corresponding Java class files. - Any options specified in the $JAVACFLAGS construction variable + Any options specified in the $JAVACFLAGS construction variable are included on this command line. JAVACCOMSTR - + + The string displayed when compiling a directory tree of Java source files to corresponding Java class files. - If this is not set, then $JAVACCOM (the command line) is displayed. + If this is not set, then $JAVACCOM (the command line) is displayed. - + env = Environment(JAVACCOMSTR = "Compiling class files $TARGETS from $SOURCES") JAVACFLAGS - + + General options that are passed to the Java compiler. JAVACLASSDIR - + + The directory in which Java class files may be found. This is stripped from the beginning of any Java .class file names supplied to the @@ -2969,13 +3201,14 @@ by default. JAVACLASSPATH - + + Specifies the list of directories that will be searched for Java .class file. The directories in this list will be added to the - javac and javah command lines + javac and javah command lines via the option. The individual directory names will be separated by the operating system's path separate character @@ -2984,11 +3217,11 @@ by default. on Windows). - + Note that this currently just adds the specified directory via the option. - SCons does not currently search the - $JAVACLASSPATH directories for dependency + SCons does not currently search the + $JAVACLASSPATH directories for dependency .class files. @@ -2996,7 +3229,8 @@ by default. JAVACLASSSUFFIX - + + The suffix for Java class files; .class by default. @@ -3005,37 +3239,41 @@ by default. JAVAH - + + The Java generator for C header and stub files. JAVAHCOM - + + The command line used to generate C header and stub files from Java classes. -Any options specified in the $JAVAHFLAGS construction variable +Any options specified in the $JAVAHFLAGS construction variable are included on this command line. JAVAHCOMSTR - + + The string displayed when C header and stub files are generated from Java classes. -If this is not set, then $JAVAHCOM (the command line) is displayed. +If this is not set, then $JAVAHCOM (the command line) is displayed. - + env = Environment(JAVAHCOMSTR = "Generating header/stub file(s) $TARGETS from $SOURCES") JAVAHFLAGS - + + General options passed to the C header and stub file generator for Java classes. @@ -3043,20 +3281,22 @@ for Java classes. JAVAINCLUDES - + + Include path for Java header files (such as jni.h) JAVASOURCEPATH - + + Specifies the list of directories that will be searched for input .java file. The directories in this list will be added to the - javac command line + javac command line via the option. The individual directory names will be separated by the operating system's path separate character @@ -3065,11 +3305,11 @@ for Java classes. on Windows). - + Note that this currently just adds the specified directory via the option. - SCons does not currently search the - $JAVASOURCEPATH directories for dependency + SCons does not currently search the + $JAVASOURCEPATH directories for dependency .java files. @@ -3077,7 +3317,8 @@ for Java classes. JAVASUFFIX - + + The suffix for Java files; .java by default. @@ -3086,70 +3327,76 @@ for Java classes. JAVAVERSION - - Specifies the Java version being used by the Java builder. + + + Specifies the Java version being used by the Java builder. This is not currently used to select one version of the Java compiler vs. another. Instead, you should set this to specify the version of Java - supported by your javac compiler. + supported by your javac compiler. The default is 1.4. - + This is sometimes necessary because Java 1.5 changed the file names that are created for nested anonymous inner classes, which can cause a mismatch with the files - that SCons expects will be generated by the javac compiler. - Setting $JAVAVERSION to + that SCons expects will be generated by the javac compiler. + Setting $JAVAVERSION to 1.5 (or 1.6, as appropriate) - can make SCons realize that a Java 1.5 or 1.6 + can make SCons realize that a Java 1.5 or 1.6 build is actually up to date. LATEX - + + The LaTeX structured formatter and typesetter. LATEXCOM - + + The command line used to call the LaTeX structured formatter and typesetter. LATEXCOMSTR - + + The string displayed when calling the LaTeX structured formatter and typesetter. -If this is not set, then $LATEXCOM (the command line) is displayed. +If this is not set, then $LATEXCOM (the command line) is displayed. - + env = Environment(LATEXCOMSTR = "Building $TARGET from LaTeX input $SOURCES") LATEXFLAGS - + + General options passed to the LaTeX structured formatter and typesetter. LATEXRETRIES - + + The maximum number of times that LaTeX will be re-run if the .log -generated by the $LATEXCOM command +generated by the $LATEXCOM command indicates that there are undefined references. The default is to try to resolve undefined references by re-running LaTeX up to three times. @@ -3158,52 +3405,46 @@ by re-running LaTeX up to three times. LATEXSUFFIXES - + + The list of suffixes of files that will be scanned for LaTeX implicit dependencies (\include or \import files). The default list is: - + [".tex", ".ltx", ".latex"] LDMODULE - + + The linker for building loadable modules. -By default, this is the same as $SHLINK. +By default, this is the same as $SHLINK. LDMODULECOM - + + The command line for building loadable modules. -On Mac OS X, this uses the $LDMODULE, -$LDMODULEFLAGS and -$FRAMEWORKSFLAGS variables. -On other systems, this is the same as $SHLINK. +On Mac OS X, this uses the $LDMODULE, +$LDMODULEFLAGS and +$FRAMEWORKSFLAGS variables. +On other systems, this is the same as $SHLINK. LDMODULECOMSTR - + + The string displayed when building loadable modules. -If this is not set, then $LDMODULECOM (the command line) is displayed. - - - - - LDMODULEEMITTER - -Contains the emitter specification for the -LoadableModule builder. -The manpage section "Builder Objects" contains -general information on specifying emitters. +If this is not set, then $LDMODULECOM (the command line) is displayed. @@ -3220,41 +3461,46 @@ general information on specifying emitters. LDMODULEFLAGS - + + General user options passed to the linker for building loadable modules. LDMODULENOVERSIONSYMLINKS - -Instructs the LoadableModule builder to not automatically create symlinks + + +Instructs the LoadableModule builder to not automatically create symlinks for versioned modules. Defaults to $SHLIBNOVERSIONSYMLINKS LDMODULEPREFIX - + + The prefix used for loadable module file names. On Mac OS X, this is null; on other systems, this is -the same as $SHLIBPREFIX. +the same as $SHLIBPREFIX. _LDMODULESONAME - + + A macro that automatically generates loadable module's SONAME based on $TARGET, -$LDMODULEVERSION and $LDMODULESUFFIX. Used by LoadableModule builder -when the linker tool supports SONAME (e.g. gnulink). +$LDMODULEVERSION and $LDMODULESUFFIX. Used by LoadableModule builder +when the linker tool supports SONAME (e.g. gnulink). LDMODULESUFFIX - + + The suffix used for loadable module file names. On Mac OS X, this is null; on other systems, this is @@ -3264,47 +3510,52 @@ the same as $SHLIBSUFFIX. LDMODULEVERSION - + + When this construction variable is defined, a versioned loadable module -is created by LoadableModule builder. This activates the -$_LDMODULEVERSIONFLAGS and thus modifies the $LDMODULECOM as +is created by LoadableModule builder. This activates the +$_LDMODULEVERSIONFLAGS and thus modifies the $LDMODULECOM as required, adds the version number to the library name, and creates the symlinks -that are needed. $LDMODULEVERSION versions should exist in the same -format as $SHLIBVERSION. +that are needed. $LDMODULEVERSION versions should exist in the same +format as $SHLIBVERSION. + + + + + LDMODULEVERSIONFLAGS + + +Extra flags added to $LDMODULECOM when building versioned +LoadableModule. These flags are only used when $LDMODULEVERSION is +set. _LDMODULEVERSIONFLAGS - -This macro automatically introduces extra flags to $LDMODULECOM when -building versioned LoadableModule (that is when -$LDMODULEVERSION is set). _LDMODULEVERSIONFLAGS -usually adds $SHLIBVERSIONFLAGS and some extra dynamically generated + + +This macro automatically introduces extra flags to $LDMODULECOM when +building versioned LoadableModule (that is when +$LDMODULEVERSION is set). _LDMODULEVERSIONFLAGS +usually adds $SHLIBVERSIONFLAGS and some extra dynamically generated options (such as -Wl,-soname=$_LDMODULESONAME). It is unused by plain (unversioned) loadable modules. - - LDMODULEVERSIONFLAGS - -Extra flags added to $LDMODULECOM when building versioned -LoadableModule. These flags are only used when $LDMODULEVERSION is -set. - - - LEX - + + The lexical analyzer generator. LEXCOM - + + The command line used to call the lexical analyzer generator to generate a source file. @@ -3312,61 +3563,67 @@ to generate a source file. LEXCOMSTR - + + The string displayed when generating a source file using the lexical analyzer generator. -If this is not set, then $LEXCOM (the command line) is displayed. +If this is not set, then $LEXCOM (the command line) is displayed. - + env = Environment(LEXCOMSTR = "Lex'ing $TARGET from $SOURCES") LEXFLAGS - + + General options passed to the lexical analyzer generator. LEXUNISTD - + + Used only on windows environments to set a lex flag to prevent 'unistd.h' from being included. The default value is '--nounistd'. _LIBDIRFLAGS - + + An automatically-generated construction variable containing the linker command-line options for specifying directories to be searched for library. -The value of $_LIBDIRFLAGS is created -by respectively prepending and appending $LIBDIRPREFIX and $LIBDIRSUFFIX +The value of $_LIBDIRFLAGS is created +by respectively prepending and appending $LIBDIRPREFIX and $LIBDIRSUFFIX to the beginning and end -of each directory in $LIBPATH. +of each directory in $LIBPATH. LIBDIRPREFIX - + + The prefix used to specify a library directory on the linker command line. This will be prepended to the beginning of each directory -in the $LIBPATH construction variable -when the $_LIBDIRFLAGS variable is automatically generated. +in the $LIBPATH construction variable +when the $_LIBDIRFLAGS variable is automatically generated. LIBDIRSUFFIX - + + The suffix used to specify a library directory on the linker command line. This will be appended to the end of each directory -in the $LIBPATH construction variable -when the $_LIBDIRFLAGS variable is automatically generated. +in the $LIBPATH construction variable +when the $_LIBDIRFLAGS variable is automatically generated. @@ -3383,91 +3640,96 @@ general information on specifying emitters. _LIBFLAGS - + + An automatically-generated construction variable containing the linker command-line options for specifying libraries to be linked with the resulting target. -The value of $_LIBFLAGS is created -by respectively prepending and appending $LIBLINKPREFIX and $LIBLINKSUFFIX +The value of $_LIBFLAGS is created +by respectively prepending and appending $LIBLINKPREFIX and $LIBLINKSUFFIX to the beginning and end -of each filename in $LIBS. +of each filename in $LIBS. LIBLINKPREFIX - + + The prefix used to specify a library to link on the linker command line. This will be prepended to the beginning of each library -in the $LIBS construction variable -when the $_LIBFLAGS variable is automatically generated. +in the $LIBS construction variable +when the $_LIBFLAGS variable is automatically generated. LIBLINKSUFFIX - + + The suffix used to specify a library to link on the linker command line. This will be appended to the end of each library -in the $LIBS construction variable -when the $_LIBFLAGS variable is automatically generated. +in the $LIBS construction variable +when the $_LIBFLAGS variable is automatically generated. LIBPATH - + + The list of directories that will be searched for libraries. The implicit dependency scanner will search these directories for include files. Don't explicitly put include directory -arguments in $LINKFLAGS or $SHLINKFLAGS +arguments in $LINKFLAGS or $SHLINKFLAGS because the result will be non-portable and the directories will not be searched by the dependency scanner. Note: directory names in LIBPATH will be looked-up relative to the SConscript directory when they are used in a command. To force -scons +scons to look-up a directory relative to the root of the source tree use #: - + env = Environment(LIBPATH='#/libs') - + The directory look-up can also be forced using the -Dir() +Dir() function: - + libs = Dir('libs') env = Environment(LIBPATH=libs) - + The directory list will be added to command lines through the automatically-generated -$_LIBDIRFLAGS +$_LIBDIRFLAGS construction variable, which is constructed by respectively prepending and appending the values of the -$LIBDIRPREFIX and $LIBDIRSUFFIX +$LIBDIRPREFIX and $LIBDIRSUFFIX construction variables to the beginning and end -of each directory in $LIBPATH. +of each directory in $LIBPATH. Any command lines you define that need the LIBPATH directory list should -include $_LIBDIRFLAGS: +include $_LIBDIRFLAGS: - + env = Environment(LINKCOM="my_linker $_LIBDIRFLAGS $_LIBFLAGS -o $TARGET $SOURCE") LIBPREFIX - + + The prefix used for (static) library file names. A default value is set for each platform (posix, win32, os2, etc.), @@ -3479,63 +3741,65 @@ to reflect the names of the libraries they create. LIBPREFIXES - + + A list of all legal prefixes for library file names. When searching for library dependencies, SCons will look for files with these prefixes, the base library name, -and suffixes in the $LIBSUFFIXES list. +and suffixes in the $LIBSUFFIXES list. LIBS - + + A list of one or more libraries that will be linked with any executable programs created by this environment. - + The library list will be added to command lines through the automatically-generated -$_LIBFLAGS +$_LIBFLAGS construction variable, which is constructed by respectively prepending and appending the values of the -$LIBLINKPREFIX and $LIBLINKSUFFIX +$LIBLINKPREFIX and $LIBLINKSUFFIX construction variables to the beginning and end -of each filename in $LIBS. +of each filename in $LIBS. Any command lines you define that need the LIBS library list should -include $_LIBFLAGS: +include $_LIBFLAGS: - + env = Environment(LINKCOM="my_linker $_LIBDIRFLAGS $_LIBFLAGS -o $TARGET $SOURCE") - + If you add a File object to the -$LIBS +$LIBS list, the name of that file will be added to -$_LIBFLAGS, +$_LIBFLAGS, and thus the link line, as is, without -$LIBLINKPREFIX +$LIBLINKPREFIX or -$LIBLINKSUFFIX. +$LIBLINKSUFFIX. For example: - + env.Append(LIBS=File('/tmp/mylib.so')) - + In all cases, scons will add dependencies from the executable program to all the libraries in this list. @@ -3543,7 +3807,8 @@ all the libraries in this list. LIBSUFFIX - + + The suffix used for (static) library file names. A default value is set for each platform (posix, win32, os2, etc.), @@ -3555,10 +3820,11 @@ to reflect the names of the libraries they create. LIBSUFFIXES - + + A list of all legal suffixes for library file names. When searching for library dependencies, -SCons will look for files with prefixes, in the $LIBPREFIXES list, +SCons will look for files with prefixes, in the $LIBPREFIXES list, the base library name, and these suffixes. @@ -3566,7 +3832,8 @@ and these suffixes. LICENSE - + + The abbreviated name, preferably the SPDX code, of the license under which this project is released (GPL-3.0, LGPL-2.1, BSD-2-Clause etc.). See http://www.opensource.org/licenses/alphabetical @@ -3576,8 +3843,9 @@ for a list of license names and SPDX codes. LINESEPARATOR - -The separator used by the Substfile and Textfile builders. + + +The separator used by the Substfile and Textfile builders. This value is used between sources when constructing the target. It defaults to the current system line separator. @@ -3585,12 +3853,13 @@ It defaults to the current system line separator. LINGUAS_FILE - -The $LINGUAS_FILE defines file(s) containing list of additional linguas -to be processed by POInit, POUpdate or MOFiles -builders. It also affects Translate builder. If the variable contains -a string, it defines name of the list file. The $LINGUAS_FILE may be a -list of file names as well. If $LINGUAS_FILE is set to + + +The $LINGUAS_FILE defines file(s) containing list of additional linguas +to be processed by POInit, POUpdate or MOFiles +builders. It also affects Translate builder. If the variable contains +a string, it defines name of the list file. The $LINGUAS_FILE may be a +list of file names as well. If $LINGUAS_FILE is set to True (or non-zero numeric value), the list will be read from default file named LINGUAS. @@ -3600,50 +3869,54 @@ default file named LINK - + + The linker. LINKCOM - + + The command line used to link object files into an executable. LINKCOMSTR - + + The string displayed when object files are linked into an executable. -If this is not set, then $LINKCOM (the command line) is displayed. +If this is not set, then $LINKCOM (the command line) is displayed. - + env = Environment(LINKCOMSTR = "Linking $TARGET") LINKFLAGS - + + General user options passed to the linker. Note that this variable should not contain -(or similar) options for linking with the libraries listed in $LIBS, +(or similar) options for linking with the libraries listed in $LIBS, nor (or similar) library search path options -that scons generates automatically from $LIBPATH. +that scons generates automatically from $LIBPATH. See -$_LIBFLAGS +$_LIBFLAGS above, for the variable that expands to library-link options, and -$_LIBDIRFLAGS +$_LIBDIRFLAGS above, for the variable that expands to library search path options. @@ -3651,37 +3924,42 @@ for the variable that expands to library search path options. M4 - + + The M4 macro preprocessor. M4COM - + + The command line used to pass files through the M4 macro preprocessor. M4COMSTR - + + The string displayed when a file is passed through the M4 macro preprocessor. -If this is not set, then $M4COM (the command line) is displayed. +If this is not set, then $M4COM (the command line) is displayed. M4FLAGS - + + General options passed to the M4 macro preprocessor. MAKEINDEX - + + The makeindex generator for the TeX formatter and typesetter and the LaTeX structured formatter and typesetter. @@ -3689,7 +3967,8 @@ LaTeX structured formatter and typesetter. MAKEINDEXCOM - + + The command line used to call the makeindex generator for the TeX formatter and typesetter and the LaTeX structured formatter and typesetter. @@ -3698,17 +3977,19 @@ typesetter. MAKEINDEXCOMSTR - + + The string displayed when calling the makeindex generator for the TeX formatter and typesetter and the LaTeX structured formatter and typesetter. -If this is not set, then $MAKEINDEXCOM (the command line) is displayed. +If this is not set, then $MAKEINDEXCOM (the command line) is displayed. MAKEINDEXFLAGS - + + General options passed to the makeindex generator for the TeX formatter and typesetter and the LaTeX structured formatter and typesetter. @@ -3716,7 +3997,8 @@ and typesetter and the LaTeX structured formatter and typesetter. MAXLINELENGTH - + + The maximum number of characters allowed on an external command line. On Win32 systems, link lines longer than this many characters @@ -3726,159 +4008,178 @@ are linked via a temporary file name. MIDL - + + The Microsoft IDL compiler. MIDLCOM - + + The command line used to pass files to the Microsoft IDL compiler. MIDLCOMSTR - + + The string displayed when the Microsoft IDL compiler is called. -If this is not set, then $MIDLCOM (the command line) is displayed. +If this is not set, then $MIDLCOM (the command line) is displayed. MIDLFLAGS - + + General options passed to the Microsoft IDL compiler. MOSUFFIX - + + Suffix used for MO files (default: '.mo'). -See msgfmt tool and MOFiles builder. +See msgfmt tool and MOFiles builder. MSGFMT - + + Absolute path to msgfmt(1) binary, found by Detect(). -See msgfmt tool and MOFiles builder. +See msgfmt tool and MOFiles builder. MSGFMTCOM - + + Complete command line to run msgfmt(1) program. -See msgfmt tool and MOFiles builder. +See msgfmt tool and MOFiles builder. MSGFMTCOMSTR - + + String to display when msgfmt(1) is invoked -(default: '', which means ``print $MSGFMTCOM''). -See msgfmt tool and MOFiles builder. +(default: '', which means ``print $MSGFMTCOM''). +See msgfmt tool and MOFiles builder. MSGFMTFLAGS - + + Additional flags to msgfmt(1). -See msgfmt tool and MOFiles builder. +See msgfmt tool and MOFiles builder. MSGINIT - + + Path to msginit(1) program (found via Detect()). -See msginit tool and POInit builder. +See msginit tool and POInit builder. MSGINITCOM - + + Complete command line to run msginit(1) program. -See msginit tool and POInit builder. +See msginit tool and POInit builder. MSGINITCOMSTR - + + String to display when msginit(1) is invoked -(default: '', which means ``print $MSGINITCOM''). -See msginit tool and POInit builder. +(default: '', which means ``print $MSGINITCOM''). +See msginit tool and POInit builder. MSGINITFLAGS - + + List of additional flags to msginit(1) (default: []). -See msginit tool and POInit builder. +See msginit tool and POInit builder. _MSGINITLOCALE - + + Internal ``macro''. Computes locale (language) name based on target filename (default: '${TARGET.filebase}' ). - -See msginit tool and POInit builder. + +See msginit tool and POInit builder. MSGMERGE - + + Absolute path to msgmerge(1) binary as found by Detect(). -See msgmerge tool and POUpdate builder. +See msgmerge tool and POUpdate builder. MSGMERGECOM - + + Complete command line to run msgmerge(1) command. -See msgmerge tool and POUpdate builder. +See msgmerge tool and POUpdate builder. MSGMERGECOMSTR - + + String to be displayed when msgmerge(1) is invoked -(default: '', which means ``print $MSGMERGECOM''). -See msgmerge tool and POUpdate builder. +(default: '', which means ``print $MSGMERGECOM''). +See msgmerge tool and POUpdate builder. MSGMERGEFLAGS - + + Additional flags to msgmerge(1) command. -See msgmerge tool and POUpdate builder. +See msgmerge tool and POUpdate builder. MSSDK_DIR - + + The directory containing the Microsoft SDK (either Platform SDK or Windows SDK) to be used for compilation. @@ -3887,7 +4188,8 @@ to be used for compilation. MSSDK_VERSION - + + The version string of the Microsoft SDK (either Platform SDK or Windows SDK) to be used for compilation. @@ -3903,7 +4205,8 @@ and MSVC_BATCH - + + When set to any true value, specifies that SCons should batch compilation of object files @@ -3914,7 +4217,7 @@ and were configured in SCons using the same construction environment will be built in a single call to the compiler. Only source files that have changed since their object files were built will be passed to each compiler invocation -(via the $CHANGED_SOURCES construction variable). +(via the $CHANGED_SOURCES construction variable). Any compilations where the object (target) file base name (minus the .obj) does not match the source file base name @@ -3924,12 +4227,13 @@ will be compiled separately. MSVC_USE_SCRIPT - + + Use a batch script to set up Microsoft Visual Studio compiler - -$MSVC_USE_SCRIPT overrides $MSVC_VERSION and $TARGET_ARCH. + +$MSVC_USE_SCRIPT overrides $MSVC_VERSION and $TARGET_ARCH. If set to the name of a Visual Studio .bat file (e.g. vcvars.bat), SCons will run that bat file and extract the relevant variables from the result (typically %INCLUDE%, %LIB%, and %PATH%). Setting @@ -3941,12 +4245,13 @@ window and importing the shell's environment variables. MSVC_UWP_APP - + + Build libraries for a Universal Windows Platform (UWP) Application. - -If $MSVC_UWP_APP is set, the Visual Studio environment will be set up to point + +If $MSVC_UWP_APP is set, the Visual Studio environment will be set up to point to the Windows Store compatible libraries and Visual Studio runtimes. In doing so, any libraries that are built will be able to be used in a UWP App and published to the Windows Store. @@ -3955,7 +4260,7 @@ This variable must be passed as an argument to the Environment() constructor; setting it later has no effect. - + Valid values are '1' or '0' @@ -3963,19 +4268,20 @@ Valid values are '1' or '0' MSVC_VERSION - + + Sets the preferred version of Microsoft Visual C/C++ to use. - -If $MSVC_VERSION is not set, SCons will (by default) select the + +If $MSVC_VERSION is not set, SCons will (by default) select the latest version of Visual C/C++ installed on your system. If the specified version isn't installed, tool initialization will fail. This variable must be passed as an argument to the Environment() constructor; setting it later has no effect. - + Valid values for Windows are 14.2, 14.1, @@ -4002,15 +4308,16 @@ Versions ending in Exp refer to "Express" or MSVS - + + When the Microsoft Visual Studio tools are initialized, they set up this dictionary with the following keys: - + VERSION the version of MSVS being used (can be set via - $MSVS_VERSION) + $MSVS_VERSION) VERSIONS @@ -4066,19 +4373,20 @@ Versions ending in Exp refer to "Express" or - If a value is not set, it was not available in the registry. + If a value is not set, it was not available in the registry. MSVS_ARCH - Sets the architecture for which the generated project(s) should build. - + + Sets the architecture for which the generated project(s) should build. + The default value is x86. - amd64 is also supported by SCons for + amd64 is also supported by SCons for most Visual Studio versions. Since Visual Studio 2015 arm is supported, and since Visual Studio 2017 arm64 is supported. - Trying to set $MSVS_ARCH + Trying to set $MSVS_ARCH to an architecture that's not supported for a given Visual Studio version will generate an error. @@ -4086,7 +4394,8 @@ Versions ending in Exp refer to "Express" or MSVS_PROJECT_GUID - + + The string placed in a generated Microsoft Visual Studio project file as the value of the ProjectGUID attribute. There is no default @@ -4098,7 +4407,8 @@ defined, a new GUID is generated. MSVS_SCC_AUX_PATH - + + The path name placed in a generated Microsoft Visual Studio project file as the value of the SccAuxPath attribute if the @@ -4111,7 +4421,8 @@ no default value. MSVS_SCC_CONNECTION_ROOT - + + The root path of projects in your SCC workspace, i.e the path under which all project and solution files will be generated. It is used as a reference path from which the @@ -4135,7 +4446,8 @@ no default value. MSVS_SCC_PROJECT_NAME - + + The project name placed in a generated Microsoft Visual Studio project file as the value of the SccProjectName attribute if the @@ -4150,7 +4462,8 @@ no default value. MSVS_SCC_PROVIDER - + + The string placed in a generated Microsoft Visual Studio project file as the value of the SccProvider attribute. The string is @@ -4163,9 +4476,10 @@ no default value. MSVS_VERSION - Sets the preferred version of Microsoft Visual Studio to use. - - If $MSVS_VERSION is not set, SCons will (by default) + + Sets the preferred version of Microsoft Visual Studio to use. + + If $MSVS_VERSION is not set, SCons will (by default) select the latest version of Visual Studio installed on your system. So, if you have version 6 and version 7 (MSVS .NET) installed, it will prefer version 7. You can override this by @@ -4174,18 +4488,19 @@ no default value. version ('6.0' or '7.0', for example). If the specified version isn't installed, tool initialization will fail. - - This is obsolete: use $MSVC_VERSION instead. If - $MSVS_VERSION is set and $MSVC_VERSION is - not, $MSVC_VERSION will be set automatically to - $MSVS_VERSION. If both are set to different values, + + This is obsolete: use $MSVC_VERSION instead. If + $MSVS_VERSION is set and $MSVC_VERSION is + not, $MSVC_VERSION will be set automatically to + $MSVS_VERSION. If both are set to different values, scons will raise an error. MSVSBUILDCOM - + + The build command line placed in a generated Microsoft Visual Studio project file. The default is to have Visual Studio invoke SCons with any specified build targets. @@ -4194,7 +4509,8 @@ no default value. MSVSCLEANCOM - + + The clean command line placed in a generated Microsoft Visual Studio project file. The default is to have Visual Studio invoke SCons with the -c option to remove any specified @@ -4204,7 +4520,8 @@ no default value. MSVSENCODING - + + The encoding string placed in a generated Microsoft Visual Studio project file. The default is encoding Windows-1252. @@ -4213,12 +4530,14 @@ no default value. MSVSPROJECTCOM - The action used to generate Microsoft Visual Studio project files. + + The action used to generate Microsoft Visual Studio project files. MSVSPROJECTSUFFIX - + + The suffix used for Microsoft Visual Studio project (DSP) files. The default value is .vcproj when using Visual Studio version 7.x (.NET) or later version, @@ -4229,7 +4548,8 @@ no default value. MSVSREBUILDCOM - + + The rebuild command line placed in a generated Microsoft Visual Studio project file. The default is to have Visual Studio invoke SCons with any specified rebuild targets. @@ -4239,7 +4559,8 @@ no default value. MSVSSCONS - + + The SCons used in generated Microsoft Visual Studio project files. The default is the version of SCons being used to generate the project file. @@ -4248,7 +4569,8 @@ no default value. MSVSSCONSCOM - + + The default SCons command used in generated Microsoft Visual Studio project files. @@ -4256,30 +4578,34 @@ no default value. MSVSSCONSCRIPT - - The sconscript file (that is, SConstruct or SConscript + + + The sconscript file (that is, SConstruct or SConscript file) that will be invoked by Visual Studio project files - (through the $MSVSSCONSCOM variable). The default + (through the $MSVSSCONSCOM variable). The default is the same sconscript file that contains the call to - MSVSProject to build the project file. + MSVSProject to build the project file. MSVSSCONSFLAGS - + + The SCons flags used in generated Microsoft Visual Studio project files. MSVSSOLUTIONCOM - The action used to generate Microsoft Visual Studio solution files. + + The action used to generate Microsoft Visual Studio solution files. MSVSSOLUTIONSUFFIX - + + The suffix used for Microsoft Visual Studio solution (DSW) files. The default value is .sln when using Visual Studio version 7.x (.NET), and @@ -4290,38 +4616,43 @@ no default value. MT - + + The program used on Windows systems to embed manifests into DLLs and EXEs. -See also $WINDOWS_EMBED_MANIFEST. +See also $WINDOWS_EMBED_MANIFEST. MTEXECOM - + + The Windows command line used to embed manifests into executables. -See also $MTSHLIBCOM. +See also $MTSHLIBCOM. MTFLAGS - -Flags passed to the $MT manifest embedding program (Windows only). + + +Flags passed to the $MT manifest embedding program (Windows only). MTSHLIBCOM - + + The Windows command line used to embed manifests into shared libraries (DLLs). -See also $MTEXECOM. +See also $MTEXECOM. MWCW_VERSION - + + The version number of the MetroWerks CodeWarrior C compiler to be used. @@ -4329,7 +4660,8 @@ to be used. MWCW_VERSIONS - + + A list of installed versions of the MetroWerks CodeWarrior C compiler on this system. @@ -4337,14 +4669,16 @@ on this system. NAME - + + Specfies the name of the project to package. no_import_lib - + + When set to non-zero, suppresses creation of a corresponding Windows static import lib by the SharedLibrary @@ -4358,21 +4692,24 @@ when using Microsoft Visual Studio. OBJPREFIX - + + The prefix used for (static) object file names. OBJSUFFIX - + + The suffix used for (static) object file names. PACKAGEROOT - + + Specifies the directory where all files in resulting archive will be placed if applicable. The default value is "$NAME-$VERSION". @@ -4380,11 +4717,12 @@ placed if applicable. The default value is "$NAME-$VERSION". PACKAGETYPE - + + Selects the package type to build. Currently these are available: - + * msi - Microsoft Installer * rpm - Redhat Package Manger * ipkg - Itsy Package Management System @@ -4396,14 +4734,15 @@ Selects the package type to build. Currently these are available: * src_zip - zip file source - + This may be overridden with the "package_type" command line option. PACKAGEVERSION - + + The version of the package (not the underlying project). This is currently only used by the rpm packager and should reflect changes in the packaging, @@ -4413,7 +4752,8 @@ not the underlying project code itself. PCH - + + The Microsoft Visual C++ precompiled header that will be used when compiling object files. This variable is ignored by tools other than Microsoft Visual C++. When this variable is @@ -4423,40 +4763,44 @@ dependencies for the PCH file. Example: - + env['PCH'] = 'StdAfx.pch' PCHCOM - + + The command line used by the -PCH +PCH builder to generated a precompiled header. PCHCOMSTR - + + The string displayed when generating a precompiled header. -If this is not set, then $PCHCOM (the command line) is displayed. +If this is not set, then $PCHCOM (the command line) is displayed. PCHPDBFLAGS - + + A construction variable that, when expanded, adds the /yD flag to the command line -only if the $PDB construction variable is set. +only if the $PDB construction variable is set. PCHSTOP - + + This variable specifies how much of a source file is precompiled. This variable is ignored by tools other than Microsoft Visual C++, or when the PCH variable is not being used. When this variable is define it @@ -4465,14 +4809,15 @@ is included at the end of the precompiled portion of the source files, or the empty string if the "#pragma hrdstop" construct is being used: - + env['PCHSTOP'] = 'StdAfx.h' PDB - + + The Microsoft Visual C++ PDB file that will store debugging information for object files, shared libraries, and programs. This variable is ignored by tools other than Microsoft Visual C++. @@ -4483,11 +4828,11 @@ dependencies for the PDB file. Example: - + env['PDB'] = 'hello.pdb' - + The Visual C++ compiler switch that SCons uses by default to generate PDB information is . This works correctly with parallel () builds @@ -4499,104 +4844,116 @@ Using the instead may yield improved link-time performance, although parallel builds will no longer work. You can generate PDB files with the -switch by overriding the default $CCPDBFLAGS variable; +switch by overriding the default $CCPDBFLAGS variable; see the entry for that variable for specific examples. PDFCOM - -A deprecated synonym for $DVIPDFCOM. + + +A deprecated synonym for $DVIPDFCOM. PDFLATEX - -The pdflatex utility. + + +The pdflatex utility. PDFLATEXCOM - -The command line used to call the pdflatex utility. + + +The command line used to call the pdflatex utility. PDFLATEXCOMSTR - -The string displayed when calling the pdflatex utility. -If this is not set, then $PDFLATEXCOM (the command line) is displayed. + + +The string displayed when calling the pdflatex utility. +If this is not set, then $PDFLATEXCOM (the command line) is displayed. - + env = Environment(PDFLATEX;COMSTR = "Building $TARGET from LaTeX input $SOURCES") PDFLATEXFLAGS - -General options passed to the pdflatex utility. + + +General options passed to the pdflatex utility. PDFPREFIX - + + The prefix used for PDF file names. PDFSUFFIX - + + The suffix used for PDF file names. PDFTEX - -The pdftex utility. + + +The pdftex utility. PDFTEXCOM - -The command line used to call the pdftex utility. + + +The command line used to call the pdftex utility. PDFTEXCOMSTR - -The string displayed when calling the pdftex utility. -If this is not set, then $PDFTEXCOM (the command line) is displayed. + + +The string displayed when calling the pdftex utility. +If this is not set, then $PDFTEXCOM (the command line) is displayed. - + env = Environment(PDFTEXCOMSTR = "Building $TARGET from TeX input $SOURCES") PDFTEXFLAGS - -General options passed to the pdftex utility. + + +General options passed to the pdftex utility. PKGCHK - + + On Solaris systems, the package-checking program that will -be used (along with $PKGINFO) +be used (along with $PKGINFO) to look for installed versions of the Sun PRO C++ compiler. The default is @@ -4606,10 +4963,11 @@ The default is PKGINFO - + + On Solaris systems, the package information program that will -be used (along with $PKGCHK) +be used (along with $PKGCHK) to look for installed versions of the Sun PRO C++ compiler. The default is @@ -4619,14 +4977,15 @@ The default is PLATFORM - + + The name of the platform used to create the Environment. If no platform is specified when the Environment is created, -scons +scons autodetects the platform. - + env = Environment(tools = []) if env['PLATFORM'] == 'cygwin': Tool('mingw')(env) @@ -4637,41 +4996,45 @@ else: POAUTOINIT - -The $POAUTOINIT variable, if set to True (on non-zero -numeric value), let the msginit tool to automatically initialize + + +The $POAUTOINIT variable, if set to True (on non-zero +numeric value), let the msginit tool to automatically initialize missing PO files with msginit(1). This applies to both, -POInit and POUpdate builders (and others that use any of +POInit and POUpdate builders (and others that use any of them). POCREATE_ALIAS - -Common alias for all PO files created with POInit + + +Common alias for all PO files created with POInit builder (default: 'po-create'). -See msginit tool and POInit builder. +See msginit tool and POInit builder. POSUFFIX - + + Suffix used for PO files (default: '.po') -See msginit tool and POInit builder. +See msginit tool and POInit builder. POTDOMAIN - -The $POTDOMAIN defines default domain, used to generate -POT filename as $POTDOMAIN.pot when + + +The $POTDOMAIN defines default domain, used to generate +POT filename as $POTDOMAIN.pot when no POT file name is provided by the user. This applies to -POTUpdate, POInit and POUpdate builders (and -builders, that use them, e.g. Translate). Normally (if $POTDOMAIN is +POTUpdate, POInit and POUpdate builders (and +builders, that use them, e.g. Translate). Normally (if $POTDOMAIN is not defined), the builders use messages.pot as default POT file name. @@ -4679,33 +5042,37 @@ not defined), the builders use messages.pot as default POTSUFFIX - + + Suffix used for PO Template files (default: '.pot'). -See xgettext tool and POTUpdate builder. +See xgettext tool and POTUpdate builder. POTUPDATE_ALIAS - + + Name of the common phony target for all PO Templates created with -POUpdate (default: 'pot-update'). -See xgettext tool and POTUpdate builder. +POUpdate (default: 'pot-update'). +See xgettext tool and POTUpdate builder. POUPDATE_ALIAS - + + Common alias for all PO files being defined with -POUpdate builder (default: 'po-update'). -See msgmerge tool and POUpdate builder. +POUpdate builder (default: 'po-update'). +See msgmerge tool and POUpdate builder. PRINT_CMD_LINE_FUNC - + + A Python function used to print the command lines as they are executed (assuming command printing is not disabled by the @@ -4723,20 +5090,20 @@ the source(s) used (file node, list, or string name(s)), and the environment being used. - + The function must do the printing itself. The default implementation, used if this variable is not set or is None, is: - + def print_cmd_line(s, target, source, env): sys.stdout.write(s + "\n") - + Here's an example of a more interesting function: - + def print_cmd_line(s, target, source, env): sys.stdout.write("Building %s -> %s...\n" % (' and '.join([str(x) for x in source]), @@ -4745,7 +5112,7 @@ env=Environment(PRINT_CMD_LINE_FUNC=print_cmd_line) env.Program('foo', 'foo.c') - + This just prints "Building targetname from sourcename..." instead of the actual commands. Such a function could also log the actual commands to a log file, @@ -4766,51 +5133,58 @@ general information on specifying emitters. PROGPREFIX - + + The prefix used for executable file names. PROGSUFFIX - + + The suffix used for executable file names. PSCOM - + + The command line used to convert TeX DVI files into a PostScript file. PSCOMSTR - + + The string displayed when a TeX DVI file is converted into a PostScript file. -If this is not set, then $PSCOM (the command line) is displayed. +If this is not set, then $PSCOM (the command line) is displayed. PSPREFIX - + + The prefix used for PostScript file names. PSSUFFIX - + + The prefix used for PostScript file names. QT_AUTOSCAN - + + Turn off scanning for mocable files. Use the Moc Builder to explicitly specify files to run moc on. @@ -4818,66 +5192,74 @@ specify files to run moc on. QT_BINPATH - + + The path where the qt binaries are installed. -The default value is '$QTDIR/bin'. +The default value is '$QTDIR/bin'. QT_CPPPATH - + + The path where the qt header files are installed. -The default value is '$QTDIR/include'. +The default value is '$QTDIR/include'. Note: If you set this variable to None, -the tool won't change the $CPPPATH +the tool won't change the $CPPPATH construction variable. QT_DEBUG - + + Prints lots of debugging information while scanning for moc files. QT_LIB - + + Default value is 'qt'. You may want to set this to 'qt-mt'. Note: If you set -this variable to None, the tool won't change the $LIBS variable. +this variable to None, the tool won't change the $LIBS variable. QT_LIBPATH - + + The path where the qt libraries are installed. -The default value is '$QTDIR/lib'. +The default value is '$QTDIR/lib'. Note: If you set this variable to None, -the tool won't change the $LIBPATH +the tool won't change the $LIBPATH construction variable. QT_MOC - -Default value is '$QT_BINPATH/moc'. + + +Default value is '$QT_BINPATH/moc'. QT_MOCCXXPREFIX - + + Default value is ''. Prefix for moc output files, when source is a cxx file. QT_MOCCXXSUFFIX - + + Default value is '.moc'. Suffix for moc output files, when source is a cxx file. @@ -4885,22 +5267,25 @@ file. QT_MOCFROMCXXCOM - + + Command to generate a moc file from a cpp file. QT_MOCFROMCXXCOMSTR - + + The string displayed when generating a moc file from a cpp file. -If this is not set, then $QT_MOCFROMCXXCOM (the command line) is displayed. +If this is not set, then $QT_MOCFROMCXXCOM (the command line) is displayed. QT_MOCFROMCXXFLAGS - + + Default value is '-i'. These flags are passed to moc, when moccing a C++ file. @@ -4908,22 +5293,25 @@ C++ file. QT_MOCFROMHCOM - + + Command to generate a moc file from a header. QT_MOCFROMHCOMSTR - + + The string displayed when generating a moc file from a cpp file. -If this is not set, then $QT_MOCFROMHCOM (the command line) is displayed. +If this is not set, then $QT_MOCFROMHCOM (the command line) is displayed. QT_MOCFROMHFLAGS - + + Default value is ''. These flags are passed to moc, when moccing a header file. @@ -4931,44 +5319,50 @@ file. QT_MOCHPREFIX - + + Default value is 'moc_'. Prefix for moc output files, when source is a header. QT_MOCHSUFFIX - -Default value is '$CXXFILESUFFIX'. Suffix for moc output files, when source is + + +Default value is '$CXXFILESUFFIX'. Suffix for moc output files, when source is a header. QT_UIC - -Default value is '$QT_BINPATH/uic'. + + +Default value is '$QT_BINPATH/uic'. QT_UICCOM - + + Command to generate header files from .ui files. QT_UICCOMSTR - + + The string displayed when generating header files from .ui files. -If this is not set, then $QT_UICCOM (the command line) is displayed. +If this is not set, then $QT_UICCOM (the command line) is displayed. QT_UICDECLFLAGS - + + Default value is ''. These flags are passed to uic, when creating a a h file from a .ui file. @@ -4976,21 +5370,24 @@ file from a .ui file. QT_UICDECLPREFIX - + + Default value is ''. Prefix for uic generated header files. QT_UICDECLSUFFIX - + + Default value is '.h'. Suffix for uic generated header files. QT_UICIMPLFLAGS - + + Default value is ''. These flags are passed to uic, when creating a cxx file from a .ui file. @@ -4998,29 +5395,33 @@ file from a .ui file. QT_UICIMPLPREFIX - + + Default value is 'uic_'. Prefix for uic generated implementation files. QT_UICIMPLSUFFIX - -Default value is '$CXXFILESUFFIX'. Suffix for uic generated implementation + + +Default value is '$CXXFILESUFFIX'. Suffix for uic generated implementation files. QT_UISUFFIX - + + Default value is '.ui'. Suffix of designer input files. QTDIR - + + The qt tool tries to take this from os.environ. It also initializes all QT_* construction variables listed below. @@ -5029,24 +5430,24 @@ with python's os.path.join() method, but are listed here with the '/' separator for easier reading.) In addition, the construction environment -variables $CPPPATH, -$LIBPATH and -$LIBS may be modified +variables $CPPPATH, +$LIBPATH and +$LIBS may be modified and the variables -$PROGEMITTER, $SHLIBEMITTER and $LIBEMITTER +$PROGEMITTER, $SHLIBEMITTER and $LIBEMITTER are modified. Because the build-performance is affected when using this tool, you have to explicitly specify it at Environment creation: - + Environment(tools=['default','qt']) - + The qt tool supports the following operations: - + Automatic moc file generation from header files. You do not have to specify moc files explicitly, the tool does it for you. However, there are a few preconditions to do so: Your header file must have @@ -5054,11 +5455,11 @@ the same filebase as your implementation file and must stay in the same directory. It must have one of the suffixes .h, .hpp, .H, .hxx, .hh. You can turn off automatic moc file generation by setting QT_AUTOSCAN to 0. See also the corresponding -Moc() +Moc() builder method. - + Automatic moc file generation from cxx files. As stated in the qt documentation, include the moc file at the end of the cxx file. Note that you have to include the file, which is generated @@ -5067,11 +5468,11 @@ by the transformation ${QT_MOCCXXPREFIX}<basename>${QT_MOCCXXSUFFIX}, by d do not include the correct file. If you are using VariantDir, you may need to specify duplicate=1. You can turn off automatic moc file generation by setting QT_AUTOSCAN to 0. See also the corresponding -Moc +Moc builder method. - + Automatic handling of .ui files. The implementation files generated from .ui files are handled much the same as yacc or lex files. Each .ui file given as a source of Program, Library or @@ -5079,47 +5480,52 @@ SharedLibrary will generate three files, the declaration file, the implementation file and a moc file. Because there are also generated headers, you may need to specify duplicate=1 in calls to VariantDir. See also the corresponding -Uic +Uic builder method. RANLIB - + + The archive indexer. RANLIBCOM - + + The command line used to index a static library archive. RANLIBCOMSTR - + + The string displayed when a static library archive is indexed. -If this is not set, then $RANLIBCOM (the command line) is displayed. +If this is not set, then $RANLIBCOM (the command line) is displayed. - + env = Environment(RANLIBCOMSTR = "Indexing $TARGET") RANLIBFLAGS - + + General options passed to the archive indexer. RC - + + The resource compiler used to build a Microsoft Visual C++ resource file. @@ -5127,7 +5533,8 @@ a Microsoft Visual C++ resource file. RCCOM - + + The command line used to build a Microsoft Visual C++ resource file. @@ -5135,60 +5542,66 @@ a Microsoft Visual C++ resource file. RCCOMSTR - + + The string displayed when invoking the resource compiler to build a Microsoft Visual C++ resource file. -If this is not set, then $RCCOM (the command line) is displayed. +If this is not set, then $RCCOM (the command line) is displayed. RCFLAGS - + + The flags passed to the resource compiler by the RES builder. RCINCFLAGS - + + An automatically-generated construction variable containing the command-line options for specifying directories to be searched by the resource compiler. -The value of $RCINCFLAGS is created +The value of $RCINCFLAGS is created by respectively prepending and appending -$RCINCPREFIX and $RCINCSUFFIX +$RCINCPREFIX and $RCINCSUFFIX to the beginning and end -of each directory in $CPPPATH. +of each directory in $CPPPATH. RCINCPREFIX - + + The prefix (flag) used to specify an include directory on the resource compiler command line. This will be prepended to the beginning of each directory -in the $CPPPATH construction variable -when the $RCINCFLAGS variable is expanded. +in the $CPPPATH construction variable +when the $RCINCFLAGS variable is expanded. RCINCSUFFIX - + + The suffix used to specify an include directory on the resource compiler command line. This will be appended to the end of each directory -in the $CPPPATH construction variable -when the $RCINCFLAGS variable is expanded. +in the $CPPPATH construction variable +when the $RCINCFLAGS variable is expanded. RDirs - + + A function that converts a string into a list of Dir instances by searching the repositories. @@ -5196,35 +5609,39 @@ searching the repositories. REGSVR - + + The program used on Windows systems to register a newly-built DLL library -whenever the SharedLibrary builder +whenever the SharedLibrary builder is passed a keyword argument of register=1. REGSVRCOM - + + The command line used on Windows systems to register a newly-built DLL library -whenever the SharedLibrary builder +whenever the SharedLibrary builder is passed a keyword argument of register=1. REGSVRCOMSTR - + + The string displayed when registering a newly-built DLL file. -If this is not set, then $REGSVRCOM (the command line) is displayed. +If this is not set, then $REGSVRCOM (the command line) is displayed. REGSVRFLAGS - + + Flags passed to the DLL registration program on Windows systems when a newly-built DLL library is registered. By default, @@ -5236,154 +5653,169 @@ and requiring user attention. RMIC - + + The Java RMI stub compiler. RMICCOM - + + The command line used to compile stub and skeleton class files from Java classes that contain RMI implementations. -Any options specified in the $RMICFLAGS construction variable +Any options specified in the $RMICFLAGS construction variable are included on this command line. RMICCOMSTR - + + The string displayed when compiling stub and skeleton class files from Java classes that contain RMI implementations. -If this is not set, then $RMICCOM (the command line) is displayed. +If this is not set, then $RMICCOM (the command line) is displayed. - + env = Environment(RMICCOMSTR = "Generating stub/skeleton class files $TARGETS from $SOURCES") RMICFLAGS - + + General options passed to the Java RMI stub compiler. + + _RPATH + + +An automatically-generated construction variable +containing the rpath flags to be used when linking +a program with shared libraries. +The value of $_RPATH is created +by respectively prepending $RPATHPREFIX and appending $RPATHSUFFIX +to the beginning and end +of each directory in $RPATH. + + + RPATH - + + A list of paths to search for shared libraries when running programs. Currently only used in the GNU (gnulink), IRIX (sgilink) and Sun (sunlink) linkers. Ignored on platforms and toolchains that don't support it. Note that the paths added to RPATH are not transformed by -scons +scons in any way: if you want an absolute path, you must make it absolute yourself. - - _RPATH - -An automatically-generated construction variable -containing the rpath flags to be used when linking -a program with shared libraries. -The value of $_RPATH is created -by respectively prepending $RPATHPREFIX and appending $RPATHSUFFIX -to the beginning and end -of each directory in $RPATH. - - - RPATHPREFIX - + + The prefix used to specify a directory to be searched for shared libraries when running programs. This will be prepended to the beginning of each directory -in the $RPATH construction variable -when the $_RPATH variable is automatically generated. +in the $RPATH construction variable +when the $_RPATH variable is automatically generated. RPATHSUFFIX - + + The suffix used to specify a directory to be searched for shared libraries when running programs. This will be appended to the end of each directory -in the $RPATH construction variable -when the $_RPATH variable is automatically generated. +in the $RPATH construction variable +when the $_RPATH variable is automatically generated. RPCGEN - + + The RPC protocol compiler. RPCGENCLIENTFLAGS - + + Options passed to the RPC protocol compiler when generating client side stubs. These are in addition to any flags specified in the -$RPCGENFLAGS +$RPCGENFLAGS construction variable. RPCGENFLAGS - + + General options passed to the RPC protocol compiler. RPCGENHEADERFLAGS - + + Options passed to the RPC protocol compiler when generating a header file. These are in addition to any flags specified in the -$RPCGENFLAGS +$RPCGENFLAGS construction variable. RPCGENSERVICEFLAGS - + + Options passed to the RPC protocol compiler when generating server side stubs. These are in addition to any flags specified in the -$RPCGENFLAGS +$RPCGENFLAGS construction variable. RPCGENXDRFLAGS - + + Options passed to the RPC protocol compiler when generating XDR routines. These are in addition to any flags specified in the -$RPCGENFLAGS +$RPCGENFLAGS construction variable. SCANNERS - + + A list of the available implicit dependency scanners. New file scanners may be added by appending to this list, @@ -5398,50 +5830,55 @@ for more information. SCONS_HOME - + + The (optional) path to the SCons library directory, initialized from the external environment. If set, this is used to construct a shorter and more efficient search path in - the $MSVSSCONS command line executed from Microsoft + the $MSVSSCONS command line executed from Microsoft Visual Studio project files. SHCC - + + The C compiler used for generating shared-library objects. SHCCCOM - + + The command line used to compile a C source file to a shared-library object file. -Any options specified in the $SHCFLAGS, -$SHCCFLAGS and -$CPPFLAGS construction variables +Any options specified in the $SHCFLAGS, +$SHCCFLAGS and +$CPPFLAGS construction variables are included on this command line. SHCCCOMSTR - + + The string displayed when a C source file is compiled to a shared object file. -If this is not set, then $SHCCCOM (the command line) is displayed. +If this is not set, then $SHCCCOM (the command line) is displayed. - + env = Environment(SHCCCOMSTR = "Compiling shared object $TARGET") SHCCFLAGS - + + Options that are passed to the C and C++ compilers to generate shared-library objects. @@ -5449,7 +5886,8 @@ to generate shared-library objects. SHCFLAGS - + + Options that are passed to the C compiler (only; not C++) to generate shared-library objects. @@ -5457,38 +5895,42 @@ to generate shared-library objects. SHCXX - + + The C++ compiler used for generating shared-library objects. SHCXXCOM - + + The command line used to compile a C++ source file to a shared-library object file. -Any options specified in the $SHCXXFLAGS and -$CPPFLAGS construction variables +Any options specified in the $SHCXXFLAGS and +$CPPFLAGS construction variables are included on this command line. SHCXXCOMSTR - + + The string displayed when a C++ source file is compiled to a shared object file. -If this is not set, then $SHCXXCOM (the command line) is displayed. +If this is not set, then $SHCXXCOM (the command line) is displayed. - + env = Environment(SHCXXCOMSTR = "Compiling shared object $TARGET") SHCXXFLAGS - + + Options that are passed to the C++ compiler to generate shared-library objects. @@ -5496,7 +5938,8 @@ to generate shared-library objects. SHDC - + + The name of the compiler to use when compiling D source destined to be in a shared objects. @@ -5504,28 +5947,32 @@ destined to be in a shared objects. SHDCOM - + + The command line to use when compiling code to be part of shared objects. SHDLIBVERSION - + + SHDLIBVERSION. SHDLIBVERSIONFLAGS - + + SHDLIBVERSIONFLAGS. SHDLINK - + + The linker to use when creating shared objects for code bases include D sources. @@ -5533,50 +5980,55 @@ include D sources. SHDLINKCOM - + + The command line to use when generating shared objects. SHDLINKFLAGS - + + The list of flags to use when generating a shared object. SHELL - + + A string naming the shell program that will be passed to the -$SPAWN +$SPAWN function. See the -$SPAWN +$SPAWN construction variable for more information. SHF03 - + + The Fortran 03 compiler used for generating shared-library objects. -You should normally set the $SHFORTRAN variable, +You should normally set the $SHFORTRAN variable, which specifies the default Fortran compiler for all Fortran versions. -You only need to set $SHF03 if you need to use a specific compiler +You only need to set $SHF03 if you need to use a specific compiler or compiler version for Fortran 03 files. SHF03COM - + + The command line used to compile a Fortran 03 source file to a shared-library object file. -You only need to set $SHF03COM if you need to use a specific +You only need to set $SHF03COM if you need to use a specific command line for Fortran 03 files. -You should normally set the $SHFORTRANCOM variable, +You should normally set the $SHFORTRANCOM variable, which specifies the default command line for all Fortran versions. @@ -5584,22 +6036,24 @@ for all Fortran versions. SHF03COMSTR - + + The string displayed when a Fortran 03 source file is compiled to a shared-library object file. -If this is not set, then $SHF03COM or $SHFORTRANCOM +If this is not set, then $SHF03COM or $SHFORTRANCOM (the command line) is displayed. SHF03FLAGS - + + Options that are passed to the Fortran 03 compiler to generated shared-library objects. -You only need to set $SHF03FLAGS if you need to define specific +You only need to set $SHF03FLAGS if you need to define specific user options for Fortran 03 files. -You should normally set the $SHFORTRANFLAGS variable, +You should normally set the $SHFORTRANFLAGS variable, which specifies the user-specified options passed to the default Fortran compiler for all Fortran versions. @@ -5608,15 +6062,16 @@ for all Fortran versions. SHF03PPCOM - + + The command line used to compile a Fortran 03 source file to a shared-library object file after first running the file through the C preprocessor. -Any options specified in the $SHF03FLAGS and $CPPFLAGS construction variables +Any options specified in the $SHF03FLAGS and $CPPFLAGS construction variables are included on this command line. -You only need to set $SHF03PPCOM if you need to use a specific +You only need to set $SHF03PPCOM if you need to use a specific C-preprocessor command line for Fortran 03 files. -You should normally set the $SHFORTRANPPCOM variable, +You should normally set the $SHFORTRANPPCOM variable, which specifies the default C-preprocessor command line for all Fortran versions. @@ -5624,35 +6079,38 @@ for all Fortran versions. SHF03PPCOMSTR - + + 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 $SHF03PPCOM or $SHFORTRANPPCOM +If this is not set, then $SHF03PPCOM or $SHFORTRANPPCOM (the command line) is displayed. SHF08 - + + The Fortran 08 compiler used for generating shared-library objects. -You should normally set the $SHFORTRAN variable, +You should normally set the $SHFORTRAN variable, which specifies the default Fortran compiler for all Fortran versions. -You only need to set $SHF08 if you need to use a specific compiler +You only need to set $SHF08 if you need to use a specific compiler or compiler version for Fortran 08 files. SHF08COM - + + The command line used to compile a Fortran 08 source file to a shared-library object file. -You only need to set $SHF08COM if you need to use a specific +You only need to set $SHF08COM if you need to use a specific command line for Fortran 08 files. -You should normally set the $SHFORTRANCOM variable, +You should normally set the $SHFORTRANCOM variable, which specifies the default command line for all Fortran versions. @@ -5660,22 +6118,24 @@ for all Fortran versions. SHF08COMSTR - + + The string displayed when a Fortran 08 source file is compiled to a shared-library object file. -If this is not set, then $SHF08COM or $SHFORTRANCOM +If this is not set, then $SHF08COM or $SHFORTRANCOM (the command line) is displayed. SHF08FLAGS - + + Options that are passed to the Fortran 08 compiler to generated shared-library objects. -You only need to set $SHF08FLAGS if you need to define specific +You only need to set $SHF08FLAGS if you need to define specific user options for Fortran 08 files. -You should normally set the $SHFORTRANFLAGS variable, +You should normally set the $SHFORTRANFLAGS variable, which specifies the user-specified options passed to the default Fortran compiler for all Fortran versions. @@ -5684,15 +6144,16 @@ for all Fortran versions. SHF08PPCOM - + + The command line used to compile a Fortran 08 source file to a shared-library object file after first running the file through the C preprocessor. -Any options specified in the $SHF08FLAGS and $CPPFLAGS construction variables +Any options specified in the $SHF08FLAGS and $CPPFLAGS construction variables are included on this command line. -You only need to set $SHF08PPCOM if you need to use a specific +You only need to set $SHF08PPCOM if you need to use a specific C-preprocessor command line for Fortran 08 files. -You should normally set the $SHFORTRANPPCOM variable, +You should normally set the $SHFORTRANPPCOM variable, which specifies the default C-preprocessor command line for all Fortran versions. @@ -5700,35 +6161,38 @@ for all Fortran versions. SHF08PPCOMSTR - + + 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 $SHF08PPCOM or $SHFORTRANPPCOM +If this is not set, then $SHF08PPCOM or $SHFORTRANPPCOM (the command line) is displayed. SHF77 - + + The Fortran 77 compiler used for generating shared-library objects. -You should normally set the $SHFORTRAN variable, +You should normally set the $SHFORTRAN variable, which specifies the default Fortran compiler for all Fortran versions. -You only need to set $SHF77 if you need to use a specific compiler +You only need to set $SHF77 if you need to use a specific compiler or compiler version for Fortran 77 files. SHF77COM - + + The command line used to compile a Fortran 77 source file to a shared-library object file. -You only need to set $SHF77COM if you need to use a specific +You only need to set $SHF77COM if you need to use a specific command line for Fortran 77 files. -You should normally set the $SHFORTRANCOM variable, +You should normally set the $SHFORTRANCOM variable, which specifies the default command line for all Fortran versions. @@ -5736,22 +6200,24 @@ for all Fortran versions. SHF77COMSTR - + + The string displayed when a Fortran 77 source file is compiled to a shared-library object file. -If this is not set, then $SHF77COM or $SHFORTRANCOM +If this is not set, then $SHF77COM or $SHFORTRANCOM (the command line) is displayed. SHF77FLAGS - + + Options that are passed to the Fortran 77 compiler to generated shared-library objects. -You only need to set $SHF77FLAGS if you need to define specific +You only need to set $SHF77FLAGS if you need to define specific user options for Fortran 77 files. -You should normally set the $SHFORTRANFLAGS variable, +You should normally set the $SHFORTRANFLAGS variable, which specifies the user-specified options passed to the default Fortran compiler for all Fortran versions. @@ -5760,15 +6226,16 @@ for all Fortran versions. SHF77PPCOM - + + The command line used to compile a Fortran 77 source file to a shared-library object file after first running the file through the C preprocessor. -Any options specified in the $SHF77FLAGS and $CPPFLAGS construction variables +Any options specified in the $SHF77FLAGS and $CPPFLAGS construction variables are included on this command line. -You only need to set $SHF77PPCOM if you need to use a specific +You only need to set $SHF77PPCOM if you need to use a specific C-preprocessor command line for Fortran 77 files. -You should normally set the $SHFORTRANPPCOM variable, +You should normally set the $SHFORTRANPPCOM variable, which specifies the default C-preprocessor command line for all Fortran versions. @@ -5776,35 +6243,38 @@ for all Fortran versions. SHF77PPCOMSTR - + + 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 $SHF77PPCOM or $SHFORTRANPPCOM +If this is not set, then $SHF77PPCOM or $SHFORTRANPPCOM (the command line) is displayed. SHF90 - + + The Fortran 90 compiler used for generating shared-library objects. -You should normally set the $SHFORTRAN variable, +You should normally set the $SHFORTRAN variable, which specifies the default Fortran compiler for all Fortran versions. -You only need to set $SHF90 if you need to use a specific compiler +You only need to set $SHF90 if you need to use a specific compiler or compiler version for Fortran 90 files. SHF90COM - + + The command line used to compile a Fortran 90 source file to a shared-library object file. -You only need to set $SHF90COM if you need to use a specific +You only need to set $SHF90COM if you need to use a specific command line for Fortran 90 files. -You should normally set the $SHFORTRANCOM variable, +You should normally set the $SHFORTRANCOM variable, which specifies the default command line for all Fortran versions. @@ -5812,22 +6282,24 @@ for all Fortran versions. SHF90COMSTR - + + The string displayed when a Fortran 90 source file is compiled to a shared-library object file. -If this is not set, then $SHF90COM or $SHFORTRANCOM +If this is not set, then $SHF90COM or $SHFORTRANCOM (the command line) is displayed. SHF90FLAGS - + + Options that are passed to the Fortran 90 compiler to generated shared-library objects. -You only need to set $SHF90FLAGS if you need to define specific +You only need to set $SHF90FLAGS if you need to define specific user options for Fortran 90 files. -You should normally set the $SHFORTRANFLAGS variable, +You should normally set the $SHFORTRANFLAGS variable, which specifies the user-specified options passed to the default Fortran compiler for all Fortran versions. @@ -5836,15 +6308,16 @@ for all Fortran versions. SHF90PPCOM - + + The command line used to compile a Fortran 90 source file to a shared-library object file after first running the file through the C preprocessor. -Any options specified in the $SHF90FLAGS and $CPPFLAGS construction variables +Any options specified in the $SHF90FLAGS and $CPPFLAGS construction variables are included on this command line. -You only need to set $SHF90PPCOM if you need to use a specific +You only need to set $SHF90PPCOM if you need to use a specific C-preprocessor command line for Fortran 90 files. -You should normally set the $SHFORTRANPPCOM variable, +You should normally set the $SHFORTRANPPCOM variable, which specifies the default C-preprocessor command line for all Fortran versions. @@ -5852,35 +6325,38 @@ for all Fortran versions. SHF90PPCOMSTR - + + 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 $SHF90PPCOM or $SHFORTRANPPCOM +If this is not set, then $SHF90PPCOM or $SHFORTRANPPCOM (the command line) is displayed. SHF95 - + + The Fortran 95 compiler used for generating shared-library objects. -You should normally set the $SHFORTRAN variable, +You should normally set the $SHFORTRAN variable, which specifies the default Fortran compiler for all Fortran versions. -You only need to set $SHF95 if you need to use a specific compiler +You only need to set $SHF95 if you need to use a specific compiler or compiler version for Fortran 95 files. SHF95COM - + + The command line used to compile a Fortran 95 source file to a shared-library object file. -You only need to set $SHF95COM if you need to use a specific +You only need to set $SHF95COM if you need to use a specific command line for Fortran 95 files. -You should normally set the $SHFORTRANCOM variable, +You should normally set the $SHFORTRANCOM variable, which specifies the default command line for all Fortran versions. @@ -5888,22 +6364,24 @@ for all Fortran versions. SHF95COMSTR - + + The string displayed when a Fortran 95 source file is compiled to a shared-library object file. -If this is not set, then $SHF95COM or $SHFORTRANCOM +If this is not set, then $SHF95COM or $SHFORTRANCOM (the command line) is displayed. SHF95FLAGS - + + Options that are passed to the Fortran 95 compiler to generated shared-library objects. -You only need to set $SHF95FLAGS if you need to define specific +You only need to set $SHF95FLAGS if you need to define specific user options for Fortran 95 files. -You should normally set the $SHFORTRANFLAGS variable, +You should normally set the $SHFORTRANFLAGS variable, which specifies the user-specified options passed to the default Fortran compiler for all Fortran versions. @@ -5912,15 +6390,16 @@ for all Fortran versions. SHF95PPCOM - + + The command line used to compile a Fortran 95 source file to a shared-library object file after first running the file through the C preprocessor. -Any options specified in the $SHF95FLAGS and $CPPFLAGS construction variables +Any options specified in the $SHF95FLAGS and $CPPFLAGS construction variables are included on this command line. -You only need to set $SHF95PPCOM if you need to use a specific +You only need to set $SHF95PPCOM if you need to use a specific C-preprocessor command line for Fortran 95 files. -You should normally set the $SHFORTRANPPCOM variable, +You should normally set the $SHFORTRANPPCOM variable, which specifies the default C-preprocessor command line for all Fortran versions. @@ -5928,25 +6407,28 @@ for all Fortran versions. SHF95PPCOMSTR - + + 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 $SHF95PPCOM or $SHFORTRANPPCOM +If this is not set, then $SHF95PPCOM or $SHFORTRANPPCOM (the command line) is displayed. SHFORTRAN - + + The default Fortran compiler used for generating shared-library objects. SHFORTRANCOM - + + The command line used to compile a Fortran source file to a shared-library object file. @@ -5954,17 +6436,19 @@ to a shared-library object file. SHFORTRANCOMSTR - + + The string displayed when a Fortran source file is compiled to a shared-library object file. -If this is not set, then $SHFORTRANCOM +If this is not set, then $SHFORTRANCOM (the command line) is displayed. SHFORTRANFLAGS - + + Options that are passed to the Fortran compiler to generate shared-library objects. @@ -5972,24 +6456,26 @@ to generate shared-library objects. SHFORTRANPPCOM - + + The command line used to compile a Fortran source file to a shared-library object file after first running the file through the C preprocessor. Any options specified -in the $SHFORTRANFLAGS and -$CPPFLAGS construction variables +in the $SHFORTRANFLAGS and +$CPPFLAGS construction variables are included on this command line. SHFORTRANPPCOMSTR - + + 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 $SHFORTRANPPCOM +If this is not set, then $SHFORTRANPPCOM (the command line) is displayed. @@ -6007,45 +6493,63 @@ general information on specifying emitters. SHLIBNOVERSIONSYMLINKS - -Instructs the SharedLibrary builder to not create symlinks for versioned + + +Instructs the SharedLibrary builder to not create symlinks for versioned shared libraries. SHLIBPREFIX - + + The prefix used for shared library file names. _SHLIBSONAME - + + A macro that automatically generates shared library's SONAME based on $TARGET, -$SHLIBVERSION and $SHLIBSUFFIX. Used by SharedLibrary builder when -the linker tool supports SONAME (e.g. gnulink). +$SHLIBVERSION and $SHLIBSUFFIX. Used by SharedLibrary builder when +the linker tool supports SONAME (e.g. gnulink). SHLIBSUFFIX - + + The suffix used for shared library file names. SHLIBVERSION - + + When this construction variable is defined, a versioned shared library is created by the SharedLibrary builder. This activates the $_SHLIBVERSIONFLAGS and thus modifies the $SHLINKCOM as required, adds the version number to the library name, and creates the symlinks -that are needed. $SHLIBVERSION versions should exist as alpha-numeric, +that are needed. $SHLIBVERSION versions should exist as alpha-numeric, decimal-delimited values as defined by the regular expression "\w+[\.\w+]*". -Example $SHLIBVERSION values include '1', '1.2.3', and '1.2.gitaa412c8b'. +Example $SHLIBVERSION values include '1', '1.2.3', and '1.2.gitaa412c8b'. + + + + + _SHLIBVERSIONFLAGS + + +This macro automatically introduces extra flags to $SHLINKCOM when +building versioned SharedLibrary (that is when $SHLIBVERSION +is set). _SHLIBVERSIONFLAGS usually adds $SHLIBVERSIONFLAGS +and some extra dynamically generated options (such as +-Wl,-soname=$_SHLIBSONAME. It is unused by "plain" +(unversioned) shared libraries. @@ -6059,63 +6563,55 @@ set. - - _SHLIBVERSIONFLAGS - -This macro automatically introduces extra flags to $SHLINKCOM when -building versioned SharedLibrary (that is when $SHLIBVERSION -is set). _SHLIBVERSIONFLAGS usually adds $SHLIBVERSIONFLAGS -and some extra dynamically generated options (such as --Wl,-soname=$_SHLIBSONAME. It is unused by "plain" -(unversioned) shared libraries. - - - SHLINK - + + The linker for programs that use shared libraries. SHLINKCOM - + + The command line used to link programs using shared libraries. SHLINKCOMSTR - + + The string displayed when programs using shared libraries are linked. -If this is not set, then $SHLINKCOM (the command line) is displayed. +If this is not set, then $SHLINKCOM (the command line) is displayed. - + env = Environment(SHLINKCOMSTR = "Linking shared $TARGET") SHLINKFLAGS - + + General user options passed to the linker for programs using shared libraries. Note that this variable should not contain -(or similar) options for linking with the libraries listed in $LIBS, +(or similar) options for linking with the libraries listed in $LIBS, nor (or similar) include search path options -that scons generates automatically from $LIBPATH. +that scons generates automatically from $LIBPATH. See -$_LIBFLAGS +$_LIBFLAGS above, for the variable that expands to library-link options, and -$_LIBDIRFLAGS +$_LIBDIRFLAGS above, for the variable that expands to library search path options. @@ -6123,32 +6619,36 @@ for the variable that expands to library search path options. SHOBJPREFIX - + + The prefix used for shared object file names. SHOBJSUFFIX - + + The suffix used for shared object file names. SONAME - + + Variable used to hard-code SONAME for versioned shared library/loadable module. env.SharedLibrary('test', 'test.c', SHLIBVERSION='0.1.2', SONAME='libtest.so.2') -The variable is used, for example, by gnulink linker tool. +The variable is used, for example, by gnulink linker tool. SOURCE - + + A reserved variable name that may not be set or used in a construction environment. (See the manpage section "Variable Substitution" @@ -6158,7 +6658,8 @@ for more information). SOURCE_URL - + + The URL (web address) of the location from which the project was retrieved. @@ -6170,7 +6671,8 @@ field in the controlling information for Ipkg and RPM packages. SOURCES - + + A reserved variable name that may not be set or used in a construction environment. (See the manpage section "Variable Substitution" @@ -6180,16 +6682,17 @@ for more information). SPAWN - + + A command interpreter function that will be called to execute command line strings. The function must expect the following arguments: - + def spawn(shell, escape, cmd, args, env): - + sh is a string naming the shell program to use. escape @@ -6207,15 +6710,17 @@ in which the command should be executed. STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME - + + When this variable is true, static objects and shared objects are assumed to be the same; that is, SCons does not check for linking static objects into a shared library. SUBST_DICT - -The dictionary used by the Substfile or Textfile builders + + +The dictionary used by the Substfile or Textfile builders for substitution values. It can be anything acceptable to the dict() constructor, so in addition to a dictionary, @@ -6225,23 +6730,26 @@ lists of tuples are also acceptable. SUBSTFILEPREFIX - -The prefix used for Substfile file names, + + +The prefix used for Substfile file names, the null string by default. SUBSTFILESUFFIX - -The suffix used for Substfile file names, + + +The suffix used for Substfile file names, the null string by default. SUMMARY - + + A short summary of what the project is about. This is used to fill in the Summary: @@ -6254,32 +6762,35 @@ field in MSI packages. SWIG - + + The scripting language wrapper and interface generator. SWIGCFILESUFFIX - + + The suffix that will be used for intermediate C source files generated by the scripting language wrapper and interface generator. The default value is -_wrap$CFILESUFFIX. +_wrap$CFILESUFFIX. By default, this value is used whenever the option is not specified as part of the -$SWIGFLAGS +$SWIGFLAGS construction variable. SWIGCOM - + + The command line used to call the scripting language wrapper and interface generator. @@ -6287,32 +6798,35 @@ the scripting language wrapper and interface generator. SWIGCOMSTR - + + The string displayed when calling the scripting language wrapper and interface generator. -If this is not set, then $SWIGCOM (the command line) is displayed. +If this is not set, then $SWIGCOM (the command line) is displayed. SWIGCXXFILESUFFIX - + + The suffix that will be used for intermediate C++ source files generated by the scripting language wrapper and interface generator. The default value is -_wrap$CFILESUFFIX. +_wrap$CFILESUFFIX. By default, this value is used whenever the -c++ option is specified as part of the -$SWIGFLAGS +$SWIGFLAGS construction variable. SWIGDIRECTORSUFFIX - + + The suffix that will be used for intermediate C++ header files generated by the scripting language wrapper and interface generator. These are only generated for C++ code when the SWIG 'directors' feature is @@ -6324,7 +6838,8 @@ The default value is SWIGFLAGS - + + General options passed to the scripting language wrapper and interface generator. This is where you should set @@ -6335,57 +6850,61 @@ or whatever other options you want to specify to SWIG. If you set the option in this variable, -scons +scons will, by default, generate a C++ intermediate source file with the extension that is specified as the -$CXXFILESUFFIX +$CXXFILESUFFIX variable. _SWIGINCFLAGS - + + An automatically-generated construction variable containing the SWIG command-line options for specifying directories to be searched for included files. -The value of $_SWIGINCFLAGS is created +The value of $_SWIGINCFLAGS is created by respectively prepending and appending -$SWIGINCPREFIX and $SWIGINCSUFFIX +$SWIGINCPREFIX and $SWIGINCSUFFIX to the beginning and end -of each directory in $SWIGPATH. +of each directory in $SWIGPATH. SWIGINCPREFIX - + + The prefix used to specify an include directory on the SWIG command line. This will be prepended to the beginning of each directory -in the $SWIGPATH construction variable -when the $_SWIGINCFLAGS variable is automatically generated. +in the $SWIGPATH construction variable +when the $_SWIGINCFLAGS variable is automatically generated. SWIGINCSUFFIX - + + The suffix used to specify an include directory on the SWIG command line. This will be appended to the end of each directory -in the $SWIGPATH construction variable -when the $_SWIGINCFLAGS variable is automatically generated. +in the $SWIGPATH construction variable +when the $_SWIGINCFLAGS variable is automatically generated. SWIGOUTDIR - + + Specifies the output directory in which the scripting language wrapper and interface generator should place generated language-specific files. This will be used by SCons to identify -the files that will be generated by the swig call, +the files that will be generated by the swig call, and translated into the swig -outdir option on the command line. @@ -6393,14 +6912,15 @@ and translated into the SWIGPATH - + + The list of directories that the scripting language wrapper and interface generate will search for included files. The SWIG implicit dependency scanner will search these directories for include files. The default value is an empty list. - + Don't explicitly put include directory arguments in SWIGFLAGS; the result will be non-portable @@ -6408,90 +6928,96 @@ and the directories will not be searched by the dependency scanner. Note: directory names in SWIGPATH will be looked-up relative to the SConscript directory when they are used in a command. To force -scons +scons to look-up a directory relative to the root of the source tree use #: - + env = Environment(SWIGPATH='#/include') - + The directory look-up can also be forced using the -Dir() +Dir() function: - + include = Dir('include') env = Environment(SWIGPATH=include) - + The directory list will be added to command lines through the automatically-generated -$_SWIGINCFLAGS +$_SWIGINCFLAGS construction variable, which is constructed by respectively prepending and appending the values of the -$SWIGINCPREFIX and $SWIGINCSUFFIX +$SWIGINCPREFIX and $SWIGINCSUFFIX construction variables to the beginning and end -of each directory in $SWIGPATH. +of each directory in $SWIGPATH. Any command lines you define that need the SWIGPATH directory list should -include $_SWIGINCFLAGS: +include $_SWIGINCFLAGS: - + env = Environment(SWIGCOM="my_swig -o $TARGET $_SWIGINCFLAGS $SOURCES") SWIGVERSION - + + The version number of the SWIG tool. TAR - + + The tar archiver. TARCOM - + + The command line used to call the tar archiver. TARCOMSTR - + + The string displayed when archiving files using the tar archiver. -If this is not set, then $TARCOM (the command line) is displayed. +If this is not set, then $TARCOM (the command line) is displayed. - + env = Environment(TARCOMSTR = "Archiving $TARGET") TARFLAGS - + + General options passed to the tar archiver. TARGET - + + A reserved variable name that may not be set or used in a construction environment. (See the manpage section "Variable Substitution" @@ -6503,9 +7029,16 @@ for more information). TARGET_ARCH + The name of the target hardware architecture for the compiled objects + created by this Environment. + This defaults to the value of HOST_ARCH, and the user can override it. + Currently only set for Win32. + + + Sets the target architecture for Visual Studio compiler (i.e. the arch of the binaries generated by the compiler). If not set, default to -$HOST_ARCH, or, if that is unset, to the architecture of the +$HOST_ARCH, or, if that is unset, to the architecture of the running machine's OS (note that the python build or architecture has no effect). This variable must be passed as an argument to the Environment() @@ -6517,7 +7050,7 @@ all installed MSVC's that support the TARGET_ARCH, selecting the latest version for use. - + Valid values for Windows are x86, arm, @@ -6533,18 +7066,12 @@ and ia64 (Itanium). For example, if you want to compile 64-bit binaries, you would set TARGET_ARCH='x86_64' in your SCons environment. - - - The name of the target hardware architecture for the compiled objects - created by this Environment. - This defaults to the value of HOST_ARCH, and the user can override it. - Currently only set for Win32. - - + TARGET_OS - + + The name of the target operating system for the compiled objects created by this Environment. This defaults to the value of HOST_OS, and the user can override it. @@ -6554,7 +7081,8 @@ For example, if you want to compile 64-bit binaries, you would set TARGETS - + + A reserved variable name that may not be set or used in a construction environment. (See the manpage section "Variable Substitution" @@ -6564,15 +7092,17 @@ for more information). TARSUFFIX - + + The suffix used for tar file names. TEMPFILEARGJOIN - -The string (or character) to be used to join the arguments passed to TEMPFILE when command line exceeds the limit set by $MAXLINELENGTH. + + +The string (or character) to be used to join the arguments passed to TEMPFILE when command line exceeds the limit set by $MAXLINELENGTH. The default value is a space. However for MSVC, MSLINK the default is a line seperator characters as defined by os.linesep. Note this value is used literally and not expanded by the subst logic. @@ -6580,7 +7110,8 @@ Note this value is used literally and not expanded by the subst logic. TEMPFILEPREFIX - + + The prefix for a temporary file used to store lines lines longer than $MAXLINELENGTH as operations which call out to a shell will fail @@ -6596,7 +7127,8 @@ or '-via' for ARM toolchain. TEMPFILESUFFIX - + + The suffix used for the temporary file name used for long command lines. The name should include the dot ('.') if one is wanted as @@ -6607,41 +7139,46 @@ The default is '.lnk'. TEX - + + The TeX formatter and typesetter. TEXCOM - + + The command line used to call the TeX formatter and typesetter. TEXCOMSTR - + + The string displayed when calling the TeX formatter and typesetter. -If this is not set, then $TEXCOM (the command line) is displayed. +If this is not set, then $TEXCOM (the command line) is displayed. - + env = Environment(TEXCOMSTR = "Building $TARGET from TeX input $SOURCES") TEXFLAGS - + + General options passed to the TeX formatter and typesetter. TEXINPUTS - + + List of directories that the LaTeX program will search for include directories. The LaTeX implicit dependency scanner will search these @@ -6651,23 +7188,26 @@ directories for \include and \import files. TEXTFILEPREFIX - -The prefix used for Textfile file names, + + +The prefix used for Textfile file names, the null string by default. TEXTFILESUFFIX - -The suffix used for Textfile file names; + + +The suffix used for Textfile file names; .txt by default. TOOLS - + + A list of the names of the Tool specifications that are part of this construction environment. @@ -6675,7 +7215,8 @@ that are part of this construction environment. UNCHANGED_SOURCES - + + A reserved variable name that may not be set or used in a construction environment. (See the manpage section "Variable Substitution" @@ -6685,7 +7226,8 @@ for more information). UNCHANGED_TARGETS - + + A reserved variable name that may not be set or used in a construction environment. (See the manpage section "Variable Substitution" @@ -6695,7 +7237,8 @@ for more information). VENDOR - + + The person or organization who supply the packaged software. This is used to fill in the Vendor: @@ -6708,60 +7251,68 @@ field in the controlling information for MSI packages. VERSION - + + The version of the project, specified as a string. WIN32_INSERT_DEF - -A deprecated synonym for $WINDOWS_INSERT_DEF. + + +A deprecated synonym for $WINDOWS_INSERT_DEF. WIN32DEFPREFIX - -A deprecated synonym for $WINDOWSDEFPREFIX. + + +A deprecated synonym for $WINDOWSDEFPREFIX. WIN32DEFSUFFIX - -A deprecated synonym for $WINDOWSDEFSUFFIX. + + +A deprecated synonym for $WINDOWSDEFSUFFIX. WIN32EXPPREFIX - -A deprecated synonym for $WINDOWSEXPSUFFIX. + + +A deprecated synonym for $WINDOWSEXPSUFFIX. WIN32EXPSUFFIX - -A deprecated synonym for $WINDOWSEXPSUFFIX. + + +A deprecated synonym for $WINDOWSEXPSUFFIX. WINDOWS_EMBED_MANIFEST - + + Set this variable to True or 1 to embed the compiler-generated manifest (normally ${TARGET}.manifest) into all Windows exes and DLLs built with this environment, as a resource during their link step. -This is done using $MT and $MTEXECOM and $MTSHLIBCOM. +This is done using $MT and $MTEXECOM and $MTSHLIBCOM. WINDOWS_INSERT_DEF - + + When this is set to true, a library build of a Windows shared library (.dll file) @@ -6775,9 +7326,10 @@ The default is 0 (do not build a .def file). WINDOWS_INSERT_MANIFEST - + + When this is set to true, -scons +scons will be aware of the .manifest files generated by Microsoft Visua C/C++ 8. @@ -6786,35 +7338,40 @@ files generated by Microsoft Visua C/C++ 8. WINDOWSDEFPREFIX - + + The prefix used for Windows .def file names. WINDOWSDEFSUFFIX - + + The suffix used for Windows .def file names. WINDOWSEXPPREFIX - + + The prefix used for Windows .exp file names. WINDOWSEXPSUFFIX - + + The suffix used for Windows .exp file names. WINDOWSPROGMANIFESTPREFIX - + + The prefix used for executable program .manifest files generated by Microsoft Visual C/C++. @@ -6822,7 +7379,8 @@ generated by Microsoft Visual C/C++. WINDOWSPROGMANIFESTSUFFIX - + + The suffix used for executable program .manifest files generated by Microsoft Visual C/C++. @@ -6830,7 +7388,8 @@ generated by Microsoft Visual C/C++. WINDOWSSHLIBMANIFESTPREFIX - + + The prefix used for shared library .manifest files generated by Microsoft Visual C/C++. @@ -6838,7 +7397,8 @@ generated by Microsoft Visual C/C++. WINDOWSSHLIBMANIFESTSUFFIX - + + The suffix used for shared library .manifest files generated by Microsoft Visual C/C++. @@ -6846,7 +7406,8 @@ generated by Microsoft Visual C/C++. X_IPK_DEPENDS - + + This is used to fill in the Depends: field in the controlling information for Ipkg packages. @@ -6855,7 +7416,8 @@ field in the controlling information for Ipkg packages. X_IPK_DESCRIPTION - + + This is used to fill in the Description: field in the controlling information for Ipkg packages. @@ -6866,7 +7428,8 @@ The default value is X_IPK_MAINTAINER - + + This is used to fill in the Maintainer: field in the controlling information for Ipkg packages. @@ -6875,7 +7438,8 @@ field in the controlling information for Ipkg packages. X_IPK_PRIORITY - + + This is used to fill in the Priority: field in the controlling information for Ipkg packages. @@ -6884,7 +7448,8 @@ field in the controlling information for Ipkg packages. X_IPK_SECTION - + + This is used to fill in the Section: field in the controlling information for Ipkg packages. @@ -6893,7 +7458,8 @@ field in the controlling information for Ipkg packages. X_MSI_LANGUAGE - + + This is used to fill in the Language: attribute in the controlling information for MSI packages. @@ -6902,7 +7468,8 @@ attribute in the controlling information for MSI packages. X_MSI_LICENSE_TEXT - + + The text of the software license in RTF format. Carriage return characters will be replaced with the RTF equivalent \\par. @@ -6911,14 +7478,16 @@ replaced with the RTF equivalent \\par. X_MSI_UPGRADE_CODE - + + TODO X_RPM_AUTOREQPROV - + + This is used to fill in the AutoReqProv: field in the RPM @@ -6928,14 +7497,16 @@ field in the RPM X_RPM_BUILD - + + internal, but overridable X_RPM_BUILDREQUIRES - + + This is used to fill in the BuildRequires: field in the RPM @@ -6946,21 +7517,24 @@ Note this should only be used on a host managed by rpm as the dependencies will X_RPM_BUILDROOT - + + internal, but overridable X_RPM_CLEAN - + + internal, but overridable X_RPM_CONFLICTS - + + This is used to fill in the Conflicts: field in the RPM @@ -6970,7 +7544,8 @@ field in the RPM X_RPM_DEFATTR - + + This value is used as the default attributes for the files in the RPM package. The default value is @@ -6980,7 +7555,8 @@ The default value is X_RPM_DISTRIBUTION - + + This is used to fill in the Distribution: field in the RPM @@ -6990,7 +7566,8 @@ field in the RPM X_RPM_EPOCH - + + This is used to fill in the Epoch: field in the RPM @@ -7000,7 +7577,8 @@ field in the RPM X_RPM_EXCLUDEARCH - + + This is used to fill in the ExcludeArch: field in the RPM @@ -7010,7 +7588,8 @@ field in the RPM X_RPM_EXLUSIVEARCH - + + This is used to fill in the ExclusiveArch: field in the RPM @@ -7020,7 +7599,8 @@ field in the RPM X_RPM_EXTRADEFS - + + A list used to supply extra defintions or flags to be added to the RPM .spec file. Each item is added as-is with a carriage return appended. @@ -7036,7 +7616,7 @@ list that does not include the default line. Added in version 3.1. - + env.Package( NAME = 'foo', ... @@ -7051,7 +7631,8 @@ env.Package( X_RPM_GROUP - + + This is used to fill in the Group: field in the RPM @@ -7061,7 +7642,8 @@ field in the RPM X_RPM_GROUP_lang - + + This is used to fill in the Group(lang): field in the RPM @@ -7076,7 +7658,8 @@ the appropriate language code. X_RPM_ICON - + + This is used to fill in the Icon: field in the RPM @@ -7086,14 +7669,16 @@ field in the RPM X_RPM_INSTALL - + + internal, but overridable X_RPM_PACKAGER - + + This is used to fill in the Packager: field in the RPM @@ -7103,7 +7688,8 @@ field in the RPM X_RPM_POSTINSTALL - + + This is used to fill in the %post: section in the RPM @@ -7113,7 +7699,8 @@ section in the RPM X_RPM_POSTUNINSTALL - + + This is used to fill in the %postun: section in the RPM @@ -7123,7 +7710,8 @@ section in the RPM X_RPM_PREFIX - + + This is used to fill in the Prefix: field in the RPM @@ -7133,7 +7721,8 @@ field in the RPM X_RPM_PREINSTALL - + + This is used to fill in the %pre: section in the RPM @@ -7143,14 +7732,16 @@ section in the RPM X_RPM_PREP - + + internal, but overridable X_RPM_PREUNINSTALL - + + This is used to fill in the %preun: section in the RPM @@ -7160,7 +7751,8 @@ section in the RPM X_RPM_PROVIDES - + + This is used to fill in the Provides: field in the RPM @@ -7170,7 +7762,8 @@ field in the RPM X_RPM_REQUIRES - + + This is used to fill in the Requires: field in the RPM @@ -7180,7 +7773,8 @@ field in the RPM X_RPM_SERIAL - + + This is used to fill in the Serial: field in the RPM @@ -7190,7 +7784,8 @@ field in the RPM X_RPM_URL - + + This is used to fill in the Url: field in the RPM @@ -7200,33 +7795,37 @@ field in the RPM XGETTEXT - + + Path to xgettext(1) program (found via Detect()). -See xgettext tool and POTUpdate builder. +See xgettext tool and POTUpdate builder. XGETTEXTCOM - + + Complete xgettext command line. -See xgettext tool and POTUpdate builder. +See xgettext tool and POTUpdate builder. XGETTEXTCOMSTR - + + A string that is shown when xgettext(1) command is invoked -(default: '', which means "print $XGETTEXTCOM"). -See xgettext tool and POTUpdate builder. +(default: '', which means "print $XGETTEXTCOM"). +See xgettext tool and POTUpdate builder. _XGETTEXTDOMAIN - + + Internal "macro". Generates xgettext domain name form source and target (default: '${TARGET.filebase}'). @@ -7234,36 +7833,40 @@ form source and target (default: '${TARGET.filebase}'). XGETTEXTFLAGS - + + Additional flags to xgettext(1). -See xgettext tool and POTUpdate builder. +See xgettext tool and POTUpdate builder. XGETTEXTFROM - + + Name of file containing list of xgettext(1)'s source files. Autotools' users know this as POTFILES.in so they will in most cases set XGETTEXTFROM="POTFILES.in" here. -The $XGETTEXTFROM files have same syntax and semantics as the well known +The $XGETTEXTFROM files have same syntax and semantics as the well known GNU POTFILES.in. -See xgettext tool and POTUpdate builder. +See xgettext tool and POTUpdate builder. _XGETTEXTFROMFLAGS - + + Internal "macro". Genrates list of -D<dir> flags -from the $XGETTEXTPATH list. +from the $XGETTEXTPATH list. XGETTEXTFROMPREFIX - -This flag is used to add single $XGETTEXTFROM file to + + +This flag is used to add single $XGETTEXTFROM file to xgettext(1)'s commandline (default: '-f'). @@ -7271,34 +7874,38 @@ This flag is used to add single $XGETTEXT XGETTEXTFROMSUFFIX - + + (default: '') XGETTEXTPATH - + + List of directories, there xgettext(1) will look for source files (default: []). -This variable works only together with $XGETTEXTFROM +This variable works only together with $XGETTEXTFROM -See also xgettext tool and POTUpdate builder. +See also xgettext tool and POTUpdate builder. _XGETTEXTPATHFLAGS - + + Internal "macro". Generates list of -f<file> flags -from $XGETTEXTFROM. +from $XGETTEXTFROM. XGETTEXTPATHPREFIX - + + This flag is used to add single search path to xgettext(1)'s commandline (default: '-D'). @@ -7307,21 +7914,24 @@ This flag is used to add single search path to XGETTEXTPATHSUFFIX - + + (default: '') YACC - + + The parser generator. YACCCOM - + + The command line used to call the parser generator to generate a source file. @@ -7329,22 +7939,24 @@ to generate a source file. YACCCOMSTR - + + The string displayed when generating a source file using the parser generator. -If this is not set, then $YACCCOM (the command line) is displayed. +If this is not set, then $YACCCOM (the command line) is displayed. - + env = Environment(YACCCOMSTR = "Yacc'ing $TARGET from $SOURCES") YACCFLAGS - + + General options passed to the parser generator. -If $YACCFLAGS contains a option, +If $YACCFLAGS contains a option, SCons assumes that the call will also create a .h file (if the yacc source file ends in a .y suffix) or a .hpp file @@ -7354,7 +7966,8 @@ or a .hpp file YACCHFILESUFFIX - + + The suffix of the C header file generated by the parser generator when the @@ -7372,7 +7985,8 @@ The default value is YACCHXXFILESUFFIX - + + The suffix of the C++ header file generated by the parser generator when the @@ -7388,7 +8002,7 @@ The default value is except on Mac OS X, where the default is ${TARGET.suffix}.h. -because the default bison parser generator just +because the default bison parser generator just appends .h to the name of the generated C++ file. @@ -7396,7 +8010,8 @@ to the name of the generated C++ file. YACCVCGFILESUFFIX - + + The suffix of the file containing the VCG grammar automaton definition when the @@ -7414,14 +8029,16 @@ The default value is ZIP - + + The zip compression and file packaging utility. ZIPCOM - + + The command line used to call the zip utility, or the internal Python function used to create a zip archive. @@ -7430,7 +8047,8 @@ zip archive. ZIPCOMPRESSION - + + The compression flag @@ -7450,39 +8068,42 @@ module is unavailable. ZIPCOMSTR - + + The string displayed when archiving files using the zip utility. -If this is not set, then $ZIPCOM +If this is not set, then $ZIPCOM (the command line or internal Python function) is displayed. - + env = Environment(ZIPCOMSTR = "Zipping $TARGET") ZIPFLAGS - + + General options passed to the zip utility. ZIPROOT - + + An optional zip root directory (default empty). The filenames stored in the zip file will be relative to this directory, if given. Otherwise the filenames are relative to the current directory of the command. For instance: - + env = Environment() env.Zip('foo.zip', 'subdir1/subdir2/file1', ZIPROOT='subdir1') - + will produce a zip file foo.zip containing a file with the name subdir2/file1 rather than @@ -7492,7 +8113,8 @@ containing a file with the name ZIPSUFFIX - + + The suffix used for zip file names. diff --git a/doc/generated/variables.mod b/doc/generated/variables.mod index b26a645..ba92aa9 100644 --- a/doc/generated/variables.mod +++ b/doc/generated/variables.mod @@ -10,10 +10,10 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $__LDMODULEVERSIONFLAGS"> $__SHLIBVERSIONFLAGS"> -$APPLELINK_COMPATIBILITY_VERSION"> $_APPLELINK_COMPATIBILITY_VERSION"> -$APPLELINK_CURRENT_VERSION"> +$APPLELINK_COMPATIBILITY_VERSION"> $_APPLELINK_CURRENT_VERSION"> +$APPLELINK_CURRENT_VERSION"> $APPLELINK_NO_COMPATIBILITY_VERSION"> $APPLELINK_NO_CURRENT_VERSION"> $AR"> @@ -200,8 +200,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $_FRAMEWORKPATH"> $FRAMEWORKPATHPREFIX"> $FRAMEWORKPREFIX"> -$FRAMEWORKS"> $_FRAMEWORKS"> +$FRAMEWORKS"> $FRAMEWORKSFLAGS"> $GS"> $GSCOM"> @@ -258,8 +258,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $_LDMODULESONAME"> $LDMODULESUFFIX"> $LDMODULEVERSION"> -$_LDMODULEVERSIONFLAGS"> $LDMODULEVERSIONFLAGS"> +$_LDMODULEVERSIONFLAGS"> $LEX"> $LEXCOM"> $LEXCOMSTR"> @@ -434,8 +434,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $RMICCOM"> $RMICCOMSTR"> $RMICFLAGS"> -$RPATH"> $_RPATH"> +$RPATH"> $RPATHPREFIX"> $RPATHSUFFIX"> $RPCGEN"> @@ -651,10 +651,10 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $__LDMODULEVERSIONFLAGS"> $__SHLIBVERSIONFLAGS"> -$APPLELINK_COMPATIBILITY_VERSION"> $_APPLELINK_COMPATIBILITY_VERSION"> -$APPLELINK_CURRENT_VERSION"> +$APPLELINK_COMPATIBILITY_VERSION"> $_APPLELINK_CURRENT_VERSION"> +$APPLELINK_CURRENT_VERSION"> $APPLELINK_NO_COMPATIBILITY_VERSION"> $APPLELINK_NO_CURRENT_VERSION"> $AR"> @@ -841,8 +841,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $_FRAMEWORKPATH"> $FRAMEWORKPATHPREFIX"> $FRAMEWORKPREFIX"> -$FRAMEWORKS"> $_FRAMEWORKS"> +$FRAMEWORKS"> $FRAMEWORKSFLAGS"> $GS"> $GSCOM"> @@ -899,8 +899,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $_LDMODULESONAME"> $LDMODULESUFFIX"> $LDMODULEVERSION"> -$_LDMODULEVERSIONFLAGS"> $LDMODULEVERSIONFLAGS"> +$_LDMODULEVERSIONFLAGS"> $LEX"> $LEXCOM"> $LEXCOMSTR"> @@ -1075,8 +1075,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $RMICCOM"> $RMICCOMSTR"> $RMICFLAGS"> -$RPATH"> $_RPATH"> +$RPATH"> $RPATHPREFIX"> $RPATHSUFFIX"> $RPCGEN"> -- cgit v0.12 From 6a187ca7f326be45bf522f114faa74e541dc3a73 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 17 Dec 2019 01:46:21 +0000 Subject: Add 3.1.1 release info to debian/changelog and src/Announce.txt --- debian/changelog | 6 ++++++ src/Announce.txt | 28 ++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/debian/changelog b/debian/changelog index 77ac165..204f605 100755 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +scons (3.1.1) unstable; urgency=low + + * Maintenance Release + + -- William Deegan Mon, 16 Dec 2019 15:04:42 -0700 + scons (3.1.0) unstable; urgency=low * Maintenance Release diff --git a/src/Announce.txt b/src/Announce.txt index 1359696..034f34e 100755 --- a/src/Announce.txt +++ b/src/Announce.txt @@ -24,6 +24,34 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER release and consult the CHANGES.txt file for complete a list of changes since last release. This announcement highlights only the important changes. + Please note the following important changes since release 3.1.1: + - Added debug option "action_timestamps" which outputs to stdout the absolute start and end time for each target. + - Update Command() function to accept target_scanner, source_factory, and target_factory arguments. + This makes Command act more like a one-off builder. + - Added support for "-imacros" to ParseFlags + - 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 + the fontenc package is included with \usepackage[T1]{fontenc}) is read. + - Improved threading performance by ensuring NodeInfo is shared + across threads. Results in ~13% improvement for parallel builds + (-j# > 1) with many shared nodes. + - Improve performance of Entry.disambiguate() by making check for + most common case first, preventing unnecessary IO. + - Improved DAG walk performance by reducing unnecessary work when + there are no un-visited children. + - Turn previously deprecated debug options into failures: + --debug=tree, --debug=dtree, --debug=stree, --debug=nomemoizer. + - Experimental New Feature: Enable caching MSVC configuration + If SCONS_CACHE_MSVC_CONFIG shell environment variable is set, + SCons will cache the results of past calls to vcvarsall.bat to + a file; integrates with existing memoizing of such vars. + On vs2019 saves 5+ seconds per SCons invocation, which really + helps test suite runs. + - Remove deprecated SourceSignatures, TargetSignatures + - Remove deprecated Builder keywords: overrides and scanner + - Remove deprecated env.Copy + - Remove deprecated BuildDir plus SConscript keyword build_dir + Please note the following important changes since release 3.0.4: - Change the default for AppendENVPath to delete_existing=0, so path order will not be changed, unless explicitly set (Issue #3276) -- cgit v0.12 From f6d28fda767e9b6dace8c63198381e2157a12b1f Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 17 Dec 2019 02:05:17 +0000 Subject: Update content in RELEASE.txt CHANGES.txt Announce.txt and bump the version in ReleaseConfig --- ReleaseConfig | 2 +- src/Announce.txt | 5 ++- src/CHANGES.txt | 4 +-- src/RELEASE.txt | 103 ++++++++++++++++++++++++++++++++----------------------- 4 files changed, 67 insertions(+), 47 deletions(-) diff --git a/ReleaseConfig b/ReleaseConfig index 69be328..3068687 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, 2, 'alpha', 0) +version_tuple = (3, 1, 2) # 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/src/Announce.txt b/src/Announce.txt index 034f34e..17b3093 100755 --- a/src/Announce.txt +++ b/src/Announce.txt @@ -24,7 +24,10 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER release and consult the CHANGES.txt file for complete a list of changes since last release. This announcement highlights only the important changes. - Please note the following important changes since release 3.1.1: + + NOTE: The 4.0.0 Release of SCons will drop Python 2.7 Support + + Please note the following important changes since release 3.1.1: - Added debug option "action_timestamps" which outputs to stdout the absolute start and end time for each target. - Update Command() function to accept target_scanner, source_factory, and target_factory arguments. This makes Command act more like a one-off builder. diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 28a4b43..96517c0 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -4,7 +4,7 @@ Change Log -NOTE: Please add your name below (and your changes) alphabetically by last name. +NOTE: The 4.0.0 Release of SCons will drop Python 2.7 Support RELEASE VERSION/DATE TO BE FILLED IN LATER @@ -35,7 +35,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER (e.g. memmove) were incorrectly recognized as not available. From Jakub Kulik - - Fix subprocess result bytes not being decoded in SunOS/Solaris related tools. + - Fix stacktrace when using SCons with Python 3.5+ and SunOS/Solaris related tools. From Philipp Maierhöfer: - Avoid crash with UnicodeDecodeError on Python 3 when a Latex log file in diff --git a/src/RELEASE.txt b/src/RELEASE.txt index 17e698f..cce5810 100755 --- a/src/RELEASE.txt +++ b/src/RELEASE.txt @@ -3,71 +3,88 @@ https://scons.org/pages/download.html - XXX The primary purpose of this release ... XXX + Here is a summary of the changes since 3.1.1: - A SCons "checkpoint release" is intended to provide early access to - new features so they can be tested in the field before being released - for adoption by other software distributions. - - Note that a checkpoint release is developed using the same test-driven - development methodology as all SCons releases. Existing SCons - functionality should all work as it does in previous releases (except - for any changes identified in the release notes) and early adopters - should be able to use a checkpoint release safely for production work - with existing SConscript files. If not, it represents not only a bug - in SCons but also a hole in the regression test suite, and we want to - hear about it. - - New features may be more lightly tested than in past releases, - especially as concerns their interaction with all of the other - functionality in SCons. We are especially interested in hearing bug - reports about new functionality. - - We do not recommend that downstream distributions (Debian, Fedora, - etc.) package a checkpoint release, mainly to avoid confusing the - "public" release numbering with the long checkpoint release names. - - Here is a summary of the changes since 1.3.0: + NOTE: The 4.0.0 Release of SCons will drop Python 2.7 Support NEW FUNCTIONALITY + - Added debug option "action_timestamps" which outputs to stdout the absolute start and end time for each target. - - List new features (presumably why a checkpoint is being released) + REMOVED FUNCTIONALITY + - Turn previously deprecated debug options into failures: + --debug=tree, --debug=dtree, --debug=stree, --debug=nomemoizer. + - Remove deprecated SourceSignatures, TargetSignatures + - Remove deprecated Builder keywords: overrides and scanner + - Remove deprecated env.Copy + - Remove deprecated BuildDir plus SConscript keyword build_dir - DEPRECATED FUNCTIONALITY - - - List anything that's been deprecated since the last release CHANGED/ENHANCED EXISTING FUNCTIONALITY - - - List modifications to existing features, where the previous behavior - wouldn't actually be considered a bug + - Update Command() function to accept target_scanner, source_factory, and target_factory arguments. + This makes Command act more like a one-off builder. + - Added support for "-imacros" to ParseFlags + - EXPERIMENTAL NEW FEATURE: Enable caching MSVC configuration + If SCONS_CACHE_MSVC_CONFIG shell environment variable is set, + SCons will cache the results of past calls to vcvarsall.bat to + a file; integrates with existing memoizing of such vars. + On vs2019 saves 5+ seconds per SCons invocation, which really + helps test suite runs. FIXES - - - List fixes of outright bugs + - Fix suncxx tool (Oracle Studio compiler) when using Python 3. Previously would throw an exception. + Resolved by properly handling tool version string output as unicode. + - Resolved a race condition in multithreaded Windows builds with Python 2 + in the case where a child process is spawned while a Python action has a + file open. Original author: Ryan Beasley. + - Fix CheckFunc detection code for Visual 2019. Some functions + (e.g. memmove) were incorrectly recognized as not available. + - Fix stacktrace when using SCons with Python 3.5+ and SunOS/Solaris related tools. + - Latex: 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 + the fontenc package is included with \usepackage[T1]{fontenc}) is read. + - CmdStringHolder fix from issue #3428 IMPROVEMENTS + - Improved threading performance by ensuring NodeInfo is shared + across threads. Results in ~13% improvement for parallel builds + (-j# > 1) with many shared nodes. + - Improve performance of Entry.disambiguate() by making check for + most common case first, preventing unnecessary IO. + - Improved DAG walk performance by reducing unnecessary work when + there are no un-visited children. - - List improvements that wouldn't be visible to the user in the - documentation: performance improvements (describe the circumstances - under which they would be observed), or major code cleanups PACKAGING - - List changes in the way SCons is packaged and/or released + - N/A DOCUMENTATION - - List any significant changes to the documentation (not individual - typo fixes, even if they're mentioned in src/CHANGES.txt to give - the contributor credit) + - N/A DEVELOPMENT - - List visible changes in the way SCons is developed + - N/A + + +Thanks to the following developers for their contributions to this release. +git shortlog --no-merges -ns 3.1.1..HEAD + 59 Mats Wichmann + 21 William Deegan + 8 Edoardo Bezzeccheri + 5 Adam Gross + 5 maiphi + 4 Ivan Kravets + 4 Mathew Robinson + 2 Jakub Kulík + 2 Jacek Kuczera + 2 Rob Boehne + 2 Jason Kenny + 2 Tim Gates + 1 Jakub Kulik + 1 Theogen Ratkin + 1 jw0k - Thanks to CURLY, LARRY, and MOE for their contributions to this release. - Contributors are listed alphabetically by their last name. __COPYRIGHT__ __FILE__ __REVISION__ __DATE__ __DEVELOPER__ -- cgit v0.12 From bee7caf9defd6e108fc2998a2520ddb36a967691 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 17 Dec 2019 02:06:47 +0000 Subject: Update version strings --- README.rst | 14 +++++++------- SConstruct | 4 ++-- src/Announce.txt | 2 +- src/CHANGES.txt | 2 +- src/RELEASE.txt | 2 +- testing/framework/TestSCons.py | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/README.rst b/README.rst index 9589df7..7b7c221 100755 --- a/README.rst +++ b/README.rst @@ -499,13 +499,13 @@ about `Executing SCons Without Installing`_):: Depending on the utilities installed on your system, any or all of the following packages will be built:: - build/dist/scons-3.1.1.tar.gz - build/dist/scons-3.1.1.zip - build/dist/scons-doc-3.1.1.tar.gz - build/dist/scons-local-3.1.1.tar.gz - build/dist/scons-local-3.1.1.zip - build/dist/scons-src-3.1.1.tar.gz - build/dist/scons-src-3.1.1.zip + build/dist/scons-3.1.2.tar.gz + build/dist/scons-3.1.2.zip + build/dist/scons-doc-3.1.2.tar.gz + build/dist/scons-local-3.1.2.tar.gz + build/dist/scons-local-3.1.2.zip + build/dist/scons-src-3.1.2.tar.gz + build/dist/scons-src-3.1.2.zip The SConstruct file is supposed to be smart enough to avoid trying to build packages for which you don't have the proper utilities installed. For diff --git a/SConstruct b/SConstruct index 8db1657..1adf714 100644 --- a/SConstruct +++ b/SConstruct @@ -8,7 +8,7 @@ from __future__ import print_function copyright_years = '2001 - 2019' # This gets inserted into the man pages to reflect the month of release. -month_year = 'August 2019' +month_year = 'December 2019' # # __COPYRIGHT__ @@ -49,7 +49,7 @@ import textwrap import bootstrap project = 'scons' -default_version = '3.1.1' +default_version = '3.1.2' copyright = "Copyright (c) %s The SCons Foundation" % copyright_years SConsignFile() diff --git a/src/Announce.txt b/src/Announce.txt index 17b3093..321496d 100755 --- a/src/Announce.txt +++ b/src/Announce.txt @@ -18,7 +18,7 @@ So that everyone using SCons can help each other learn how to use it more effectively, please go to http://scons.org/lists.html#users to sign up for the scons-users mailing list. -RELEASE VERSION/DATE TO BE FILLED IN LATER +RELEASE 3.1.2 - Mon, 17 Dec 2019 02:06:27 +0000 Please consult the RELEASE.txt file for a summary of changes since the last release and consult the CHANGES.txt file for complete a list of changes diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 96517c0..745bcba 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -6,7 +6,7 @@ NOTE: The 4.0.0 Release of SCons will drop Python 2.7 Support -RELEASE VERSION/DATE TO BE FILLED IN LATER +RELEASE 3.1.2 - Mon, 17 Dec 2019 02:06:27 +0000 From Edoardo Bezzeccheri - Added debug option "action_timestamps" which outputs to stdout the absolute start and end time for each target. diff --git a/src/RELEASE.txt b/src/RELEASE.txt index cce5810..0070c6a 100755 --- a/src/RELEASE.txt +++ b/src/RELEASE.txt @@ -1,4 +1,4 @@ - A new SCons checkpoint release, 3.1.2.alpha.yyyymmdd, is now available + A new SCons checkpoint release, 3.1.2, is now available on the SCons download page: https://scons.org/pages/download.html diff --git a/testing/framework/TestSCons.py b/testing/framework/TestSCons.py index 7dc9e74..d1aed28 100644 --- a/testing/framework/TestSCons.py +++ b/testing/framework/TestSCons.py @@ -35,7 +35,7 @@ from TestCmd import PIPE # here provides some independent verification that what we packaged # conforms to what we expect. -default_version = '3.1.1' +default_version = '3.1.2' python_version_unsupported = (2, 6, 0) python_version_deprecated = (2, 7, 0) -- cgit v0.12 From da2e57392ae9601e922b8b6f20f6faf1d708fc5a Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 17 Dec 2019 02:42:47 +0000 Subject: Updates for README and logic to upload it to Sourceforge as part of the normal upload script --- README-SF.rst | 740 ++++++++++++++++++++++++++++++++++++++++++++ README.rst | 23 +- bin/upload-release-files.sh | 6 + 3 files changed, 755 insertions(+), 14 deletions(-) create mode 100755 README-SF.rst diff --git a/README-SF.rst b/README-SF.rst new file mode 100755 index 0000000..67301d4 --- /dev/null +++ b/README-SF.rst @@ -0,0 +1,740 @@ +SCons - a software construction tool +#################################### + + +Welcome to the SCons development tree. The real purpose of this tree is to +package SCons for production distribution in a variety of formats, not just to +hack SCons code. + +If all you want to do is install and run SCons, it will be easier for you to +download and install the scons-{version}.tar.gz or scons-{version}.zip package +rather than to work with the packaging logic in this tree. + +To the extent that this tree is about building SCons packages, the *full* +development cycle is not just to test the code directly, but to package SCons, +unpack the package, "install" SCons in a test subdirectory, and then to run +the tests against the unpacked and installed software. This helps eliminate +problems caused by, for example, failure to update the list of files to be +packaged. + +For just working on making an individual change to the SCons source, however, +you don't actually need to build or install SCons; you *can* actually edit and +execute SCons in-place. See the following sections below for more +information: + + `Making Changes`_ + How to edit and execute SCons in-place. + + `Debugging`_ + Tips for debugging problems in SCons. + + `Testing`_ + How to use the automated regression tests. + + `Development Workflow`_ + An example of how to put the edit/execute/test pieces + together in a reasonable development workflow. + + +Latest Version +============== + +Before going further, you can check that this package you have is the latest +version at the SCons download page: + + http://www.scons.org/pages/download.html + + +Execution Requirements +====================== + +Running SCons requires either Python version 2.7.* or 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++ +compiler suite on WIN32 systems, and assumes a C compiler named 'cc', a C++ +compiler named 'c++', and a Fortran compiler named 'g77' (such as found in the +GNU C compiler suite) on any other type of system. You may, of course, +override these default values by appropriate configuration of Environment +construction variables. + +By default, SCons knows how to search for available programming tools on +various systems--see the SCons man page for details. You may, of course, +override the default SCons choices made by appropriate configuration of +Environment construction variables. + + +Installation Requirements +========================= + +Nothing special. + + +Executing SCons Without Installing +================================== + +You can execute the local SCons directly from the src/ subdirectory by first +setting the SCONS_LIB_DIR environment variable to the local src/engine +subdirectory, and then executing the local src/script/scons.py script to +populate the build/scons/ subdirectory. You would do this as follows on a +Linux or UNIX system (using sh or a derivative like bash or ksh):: + + $ setenv MYSCONS=`pwd`/src + $ python $MYSCONS/script/scons.py [arguments] + +Or on Windows:: + + C:\scons>set MYSCONS=%cd%\src + C:\scons>python %MYSCONS%\script\scons.py [arguments] + +An alternative approach is to skip the above and use:: + + $ python bootstrap.py [arguments] + +bootstrap.py keeps the src/ subdirectory free of compiled Python (\*.pyc or +\*.pyo) files by copying the necessary SCons files to a local bootstrap/ +subdirectory and executing it from there. + +You can use the -C option to have SCons change directory to another location +where you already have a build configuration set up:: + + $ python bootstrap.py -C /some/other/location [arguments] + +For simplicity in the following examples, we will only show the bootstrap.py +approach. + + +Installation +============ + + Note: You don't need to build SCons packages or install SCons if you just + want to work on developing a patch. See the sections about `Making + Changes`_ and `Testing`_ below if you just want to submit a bug fix or + some new functionality. See the sections below about `Building Packages`_ + and `Testing Packages`_ if your enhancement involves changing the way in + which SCons is packaged and/or installed on an end-user system. + +Assuming your system satisfies the installation requirements in the previous +section, install SCons from this package by first populating the build/scons/ +subdirectory. (For an easier way to install SCons, without having to populate +this directory, use the scons-{version}.tar.gz or scons-{version}.zip +package.) + +Populate build/scons/ using a pre-installed SCons +------------------------------------------------- + +If you already have an appropriate version of SCons installed on your system, +populate the build/scons/ directory by running:: + + $ scons build/scons + +Populate build/scons/ using the SCons source +-------------------------------------------- + +You can also use this version of SCons to populate its own build directory +by using a supplied bootstrap.py script (see the section above about +`Executing SCons Without Installing`_):: + + $ python bootstrap.py build/scons + +Install the built SCons files +----------------------------- + +Any of the above commands will populate the build/scons/ directory with the +necessary files and directory structure to use the Python-standard setup +script as follows on Linux or UNIX:: + + # cd build/scons + # python setup.py install + +Or on Windows:: + + C:\scons\>cd build\scons + C:\scons\build\scons>python setup.py install + +By default, the above commands will do the following: + +- Install the version-numbered "scons-3.1.2" and "sconsign-3.1.2" scripts in + the default system script directory (/usr/bin or C:\\Python\*\\Scripts, for + example). This can be disabled by specifying the "--no-version-script" + option on the command line. + +- Install scripts named "scons" and "sconsign" scripts in the default system + script directory (/usr/bin or C:\\Python\*\\Scripts, for example). This can be + disabled by specifying the "--no-scons-script" option on the command line, + which is useful if you want to install and experiment with a new version + before making it the default on your system. + + On UNIX or Linux systems, you can have the "scons" and "sconsign" scripts be + hard links or symbolic links to the "scons-3.1.2" and "sconsign-3.1.2" + scripts by specifying the "--hardlink-scons" or "--symlink-scons" options on + the command line. + +- Install "scons-3.1.2.bat" and "scons.bat" wrapper scripts in the Python + prefix directory on Windows (C:\\Python\*, for example). This can be disabled + by specifying the "--no-install-bat" option on the command line. + + On UNIX or Linux systems, the "--install-bat" option may be specified to + have "scons-3.1.2.bat" and "scons.bat" files installed in the default system + script directory, which is useful if you want to install SCons in a shared + file system directory that can be used to execute SCons from both UNIX/Linux + and Windows systems. + +- Install the SCons build engine (a Python module) in an appropriate + version-numbered SCons library directory (/usr/lib/scons-3.1.2 or + C:\\Python\*\\scons-3.1.2, for example). See below for more options related to + installing the build engine library. + +- Install the troff-format man pages in an appropriate directory on UNIX or + Linux systems (/usr/share/man/man1 or /usr/man/man1, for example). This can + be disabled by specifying the "--no-install-man" option on the command line. + The man pages can be installed on Windows systems by specifying the + "--install-man" option on the command line. + +Note that, by default, SCons does not install its build engine library in the +standard Python library directories. If you want to be able to use the SCons +library modules (the build engine) in other Python scripts, specify the +"--standard-lib" option on the command line, as follows:: + + # python setup.py install --standard-lib + +This will install the build engine in the standard Python library directory +(/usr/lib/python\*/site-packages or C:\\Python*\\Lib\\site-packages). + +Alternatively, you can have SCons install its build engine library in a +hard-coded standalone library directory, instead of the default +version-numbered directory, by specifying the "--standalone-lib" option on the +command line, as follows:: + + # python setup.py install --standalone-lib + +This is usually not recommended, however. + +Note that, to install SCons in any of the above system directories, you should +have system installation privileges (that is, "root" or "Administrator") when +running the setup.py script. If you don't have system installation +privileges, you can use the --prefix option to specify an alternate +installation location, such as your home directory:: + + $ python setup.py install --prefix=$HOME + +This will install SCons in the appropriate locations relative to $HOME--that +is, the scons script itself $HOME/bin and the associated library in +$HOME/lib/scons, for example. + + +Making Changes +============== + +Because SCons is implemented in a scripting language, you don't need to build +it in order to make changes and test them. + +Virtually all of the SCons functionality exists in the "build engine," the +src/engine/SCons subdirectory hierarchy that contains all of the modules that +make up SCons. The src/script/scons.py wrapper script exists mainly to find +the appropriate build engine library and then execute it. + +In order to make your own changes locally and test them by hand, simply edit +modules in the local src/engine/SCons subdirectory tree and use the local +bootstrap.py script (see the section above about `Executing SCons Without +Installing`_):: + + $ python bootstrap.py [arguments] + +If you want to be able to just execute your modified version of SCons from the +command line, you can make it executable and add its directory to your $PATH +like so:: + + $ chmod 755 src/script/scons.py + $ export PATH=$PATH:`pwd`/src/script + +You should then be able to run this version of SCons by just typing "scons.py" +at your UNIX or Linux command line. + +Note that the regular SCons development process makes heavy use of automated +testing. See the `Testing`_ and `Development Workflow`_ sections below for more +information about the automated regression tests and how they can be used in a +development cycle to validate that your changes don't break existing +functionality. + + +Debugging +========= + +Python comes with a good interactive debugger. When debugging changes by hand +(i.e., when not using the automated tests), you can invoke SCons under control +of the Python debugger by specifying the --debug=pdb option:: + + $ scons --debug=pdb [arguments] + > /home/knight/SCons/src/engine/SCons/Script/Main.py(927)_main() + -> default_warnings = [ SCons.Warnings.CorruptSConsignWarning, + (Pdb) + +Once in the debugger, you can set breakpoints at lines in files in the build +engine modules by providing the path name of the file relative to the +src/engine subdirectory (that is, including the SCons/ as the first directory +component):: + + (Pdb) b SCons/Tool/msvc.py:158 + +The debugger also supports single stepping, stepping into functions, printing +variables, etc. + +Trying to debug problems found by running the automated tests (see the +`Testing`_ section, below) is more difficult, because the test automation +harness re-invokes SCons and captures output. Consequently, there isn't an +easy way to invoke the Python debugger in a useful way on any particular SCons +call within a test script. + +The most effective technique for debugging problems that occur during an +automated test is to use the good old tried-and-true technique of adding +statements to print tracing information. But note that you can't just use +"print" statement, or even "sys.stdout.write()" because those change the +SCons output, and the automated tests usually look for matches of specific +output strings to decide if a given SCons invocations passes the test. + +To deal with this, SCons supports a Trace() function that (by default) will +print messages to your console screen ("/dev/tty" on UNIX or Linux, "con" on +Windows). By adding Trace() calls to the SCons source code:: + + def sample_method(self, value): + from SCons.Debug import Trace + Trace('called sample_method(%s, %s)\n' % (self, value)) + +You can then run automated tests that print any arbitrary information you wish +about what's going on inside SCons, without interfering with the test +automation. + +The Trace() function can also redirect its output to a file, rather than the +screen:: + + def sample_method(self, value): + from SCons.Debug import Trace + Trace('called sample_method(%s, %s)\n' % (self, value), + file='trace.out') + +Where the Trace() function sends its output is stateful: once you use the +"file=" argument, all subsequent calls to Trace() send their output to the +same file, until another call with a "file=" argument is reached. + + +Testing +======= + +Tests are run by the runtest.py script in this directory. + +There are two types of tests in this package: + +1. Unit tests for individual SCons modules live underneath the src/engine/ + subdirectory and are the same base name as the module with "Tests.py" + appended--for example, the unit test for the Builder.py module is the + BuilderTests.py script. + +2. End-to-end tests of SCons live in the test/ subdirectory. + +You may specifically list one or more tests to be run:: + + $ python runtest.py src/engine/SCons/BuilderTests.py + + $ python runtest.py test/option-j.py test/Program.py + +You also use the -f option to execute just the tests listed in a specified +text file:: + + $ cat testlist.txt + test/option-j.py + test/Program.py + $ python runtest.py -f testlist.txt + +One test must be listed per line, and any lines that begin with '#' will be +ignored (allowing you, for example, to comment out tests that are currently +passing and then uncomment all of the tests in the file for a final validation +run). + +The runtest.py script also takes a -a option that searches the tree for all of +the tests and runs them:: + + $ python runtest.py -a + +If more than one test is run, the runtest.py script prints a summary of how +many tests passed, failed, or yielded no result, and lists any unsuccessful +tests. + +The above invocations all test directly the files underneath the src/ +subdirectory, and do not require that a build be performed first. The +runtest.py script supports additional options to run tests against unpacked +packages in the build/test-\*/ subdirectories. See the `Testing Packages`_ +section below. + + +Development Workflow +==================== + + Caveat: The point of this section isn't to describe one dogmatic workflow. + Just running the test suite can be time-consuming, and getting a patch to + pass all of the tests can be more so. If you're genuinely blocked, it may + make more sense to submit a patch with a note about which tests still + fail, and how. Someone else may be able to take your "initial draft" and + figure out how to improve it to fix the rest of the tests. So there's + plenty of room for use of good judgement. + +The various techniques described in the above sections can be combined to +create simple and effective workflows that allow you to validate that patches +you submit to SCons don't break existing functionality and have adequate +testing, thereby increasing the speed with which they can be integrated. + +For example, suppose your project's SCons configuration is blocked by an SCons +bug, and you decide you want to fix it and submit the patch. Here's one +possible way to go about doing that (using UNIX/Linux as the development +platform, Windows users can translate as appropriate)): + +- Change to the top of your checked-out SCons tree. + +- Confirm that the bug still exists in this version of SCons by using the -C + option to run the broken build:: + + $ python bootstrap.py -C /home/me/broken_project . + +- Fix the bug in SCons by editing appropriate module files underneath + src/engine/SCons. + +- Confirm that you've fixed the bug affecting your project:: + + $ python bootstrap.py -C /home/me/broken_project . + +- Test to see if your fix had any unintended side effects that break existing + functionality:: + + $ python runtest.py -a -o test.log + + Be patient, there are more than 700 test scripts in the whole suite. If you + are on UNIX/Linux, you can use:: + + $ python runtest.py -a | tee test.log + + instead so you can monitor progress from your terminal. + + If any test scripts fail, they will be listed in a summary at the end of the + log file. Some test scripts may also report NO RESULT because (for example) + your local system is the wrong type or doesn't have some installed utilities + necessary to run the script. In general, you can ignore the NO RESULT list. + +- Cut-and-paste the list of failed tests into a file:: + + $ cat > failed.txt + test/failed-test-1.py + test/failed-test-2.py + test/failed-test-3.py + ^D + $ + +- Now debug the test failures and fix them, either by changing SCons, or by + making necessary changes to the tests (if, for example, you have a strong + reason to change functionality, or if you find that the bug really is in the + test script itself). After each change, use the runtest.py -f option to + examine the effects of the change on the subset of tests that originally + failed:: + + $ [edit] + $ python runtest.py -f failed.txt + + Repeat this until all of the tests that originally failed now pass. + +- Now you need to go back and validate that any changes you made while getting + the tests to pass didn't break the fix you originally put in, and didn't + introduce any *additional* unintended side effects that broke other tests:: + + $ python bootstrap.py -C /home/me/broken_project . + $ python runtest.py -a -o test.log + + If you find any newly-broken tests, add them to your "failed.txt" file and + go back to the previous step. + +Of course, the above is only one suggested workflow. In practice, there is a +lot of room for judgment and experience to make things go quicker. For +example, if you're making a change to just the Java support, you might start +looking for regressions by just running the test/Java/\*.py tests instead of +running all of "runtest.py -a". + + +Building Packages +================= + +We use SCons (version 3.1.2 or later) to build its own packages. If you +already have an appropriate version of SCons installed on your system, you can +build everything by simply running it:: + + $ scons + +If you don't have SCons already installed on your +system, you can use the supplied bootstrap.py script (see the section above +about `Executing SCons Without Installing`_):: + + $ python bootstrap.py build/scons + +Depending on the utilities installed on your system, any or all of the +following packages will be built:: + + build/dist/scons-3.1.2.tar.gz + build/dist/scons-3.1.2.zip + build/dist/scons-doc-3.1.2.tar.gz + build/dist/scons-local-3.1.2.tar.gz + build/dist/scons-local-3.1.2.zip + build/dist/scons-src-3.1.2.tar.gz + build/dist/scons-src-3.1.2.zip + +The SConstruct file is supposed to be smart enough to avoid trying to build +packages for which you don't have the proper utilities installed. For +example, if you don't have Debian packaging tools installed, it should just +not build the .deb package, not fail the build. + +If you receive a build error, please report it to the scons-devel mailing list +and open a bug report on the SCons bug tracker. + +Note that in addition to creating the above packages, the default build will +also unpack one or more of the packages for testing. + + +Testing Packages +================ + +A full build will unpack and/or install any .deb, .rpm., .local.tar.gz, +.local.zip, .src.tar.gz, .src.zip, .tar.gz, and .zip packages into separate +build/test-\*/ subdirectories. (Of course, if a package was not built on your +system, it should not try to install it.) The runtest.py script supports a -p +option that will run the specified tests (individually or collectively via +the -a option) against the unpacked build/test-/\* subdirectory:: + + $ python runtest.py -p local-tar-gz + + $ python runtest.py -p local-zip + + $ python runtest.py -p src-tar-gz + + $ python runtest.py -p src-zip + + $ python runtest.py -p tar-gz + + $ python runtest.py -p zip + +(The canonical invocation is to also use the runtest.py -a option so that all +tests are run against the specified package.) + + +Contents of this Package +======================== + +Not guaranteed to be up-to-date (but better than nothing): + +bench/ + A subdirectory for benchmarking scripts, used to perform timing tests + to decide what specific idioms are most efficient for various parts of + the code base. We check these in so they're available in case we have + to revisit any of these decisions in the future. + +bin/ + Miscellaneous utilities used in SCons development. Right now, + some of the stuff here includes: + + - a script that runs pychecker on our source tree; + + - a script that counts source and test files and numbers of lines in each; + + - a prototype script for capturing sample SCons output in xml files; + + - a script that can profile and time a packaging build of SCons itself; + + - a copy of xml_export, which can retrieve project data from SourceForge; + and + + - scripts and a Python module for translating the SCons home-brew XML + documentation tags into DocBook and man page format + + +bootstrap.py + Build script for running SCons from the current source code checkout. This + copies SCons files to bootstrap/ subdirectory, and then executes SCons + with the supplied command-line arguments. + +build/ + This doesn't exist yet if you're looking at a vanilla source tree. This + is generated as part of our build process, and it's where, believe it or + not, we *build* everything. + +debian/ + Files needed to construct a Debian package. The contents of this directory + are dictated by the Debian Policy Manual + (http://www.debian.org/doc/debian-policy). The package will not be + accepted into the Debian distribution unless the contents of this + directory satisfy the relevant Debian policies. + +doc/ + SCons documentation. A variety of things here, in various stages of + (in)completeness. + +gentoo/ + Stuff to generate files for Gentoo Linux. + +HOWTO/ + Documentation of SCons administrative procedures (making a change, + releasing a new version). Maybe other administrative stuff in the future. + +LICENSE + A copy of the copyright and terms under which SCons is distributed (the + Open Source Initiative-approved MIT license). + +LICENSE-local + A copy of the copyright and terms under which SCons is distributed for + inclusion in the scons-local-{version} packages. This is the same as + LICENSE with a preamble that specifies the licensing terms are for SCons + itself, not any other package that includes SCons. + +README.rst + What you're looking at right now. + +README-local + A README file for inclusion in the scons-local-{version} packages. + Similar to this file, but stripped down and modified for people looking at + including SCons in their shipped software. + +runtest.py + Script for running SCons tests. By default, this will run a test against + the code in the local src/ tree, so you don't have to do a build before + testing your changes. + +SConstruct + The file describing to SCons how to build the SCons distribution. + + (It has been pointed out that it's hard to find the SCons API in this + SConstruct file, and that it looks a lot more like a pure Python script + than a build configuration file. That's mainly because all of the magick + we have to perform to deal with all of the different packaging formats + requires a lot of pure Python manipulation. In other words, don't look at + this file for an example of how easy it is to use SCons to build "normal" + software.) + +src/ + Where the actual source code is kept, of course. + +test/ + End-to-end tests of the SCons utility itself. These are separate from the + individual module unit tests, which live side-by-side with the modules + under src/. + +testing/ + SCons testing framework. + +Documentation +============= + +See the src/RELEASE.txt file for notes about this specific release, including +known problems. See the src/CHANGES.txt file for a list of changes since the +previous release. + +The doc/man/scons.1 man page is included in this package, and contains a +section of small examples for getting started using SCons. + +Additional documentation for SCons is available at: + + http://www.scons.org/documentation.html + + +Licensing +========= + +SCons is distributed under the MIT license, a full copy of which is available +in the LICENSE file. + + +Reporting Bugs +============== + +The SCons project welcomes bug reports and feature requests. + +Please make sure you send email with the problem or feature request to +the SCons users mailing list, which you can join via the link below: + + http://two.pairlist.net/mailman/listinfo/scons-users + +Once you have discussed your issue on the users mailing list and the +community has confirmed that it is either a new bug or a duplicate of an +existing bug, then please follow the instructions the community provides +to file a new bug or to add yourself to the CC list for an existing bug + +You can explore the list of existing bugs, which may include workarounds +for the problem you've run into on GitHub Issues: + + https://github.com/SCons/scons/issues + + +Mailing Lists +============= + +An active mailing list for developers of SCons is available. You may +send questions or comments to the list at: + + scons-dev@scons.org + +You may subscribe to the developer's mailing list using form on this page: + + http://two.pairlist.net/mailman/listinfo/scons-dev + +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. + + +Donations +========= + +If you find SCons helpful, please consider making a donation (of cash, +software, or hardware) to support continued work on the project. Information +is available at: + + http://www.scons.org/donate.html + + +For More Information +==================== + +Check the SCons web site at: + + http://www.scons.org/ + + +Author Info +=========== + +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 + +\... and many others. + +Copyright (c) 2001 - 2019 The SCons Foundation + diff --git a/README.rst b/README.rst index 7b7c221..2fbefc5 100755 --- a/README.rst +++ b/README.rst @@ -178,7 +178,7 @@ Or on Windows:: By default, the above commands will do the following: -- Install the version-numbered "scons-3.1.0" and "sconsign-3.0.3" scripts in +- Install the version-numbered "scons-3.1.2" and "sconsign-3.1.2" scripts in the default system script directory (/usr/bin or C:\\Python\*\\Scripts, for example). This can be disabled by specifying the "--no-version-script" option on the command line. @@ -190,23 +190,23 @@ By default, the above commands will do the following: before making it the default on your system. On UNIX or Linux systems, you can have the "scons" and "sconsign" scripts be - hard links or symbolic links to the "scons-3.0.3" and "sconsign-3.0.3" + hard links or symbolic links to the "scons-3.1.2" and "sconsign-3.1.2" scripts by specifying the "--hardlink-scons" or "--symlink-scons" options on the command line. -- Install "scons-3.0.3.bat" and "scons.bat" wrapper scripts in the Python +- Install "scons-3.1.2.bat" and "scons.bat" wrapper scripts in the Python prefix directory on Windows (C:\\Python\*, for example). This can be disabled by specifying the "--no-install-bat" option on the command line. On UNIX or Linux systems, the "--install-bat" option may be specified to - have "scons-3.0.3.bat" and "scons.bat" files installed in the default system + have "scons-3.1.2.bat" and "scons.bat" files installed in the default system script directory, which is useful if you want to install SCons in a shared file system directory that can be used to execute SCons from both UNIX/Linux and Windows systems. - Install the SCons build engine (a Python module) in an appropriate - version-numbered SCons library directory (/usr/lib/scons-3.0.3 or - C:\\Python\*\\scons-3.0.3, for example). See below for more options related to + version-numbered SCons library directory (/usr/lib/scons-3.1.2 or + C:\\Python\*\\scons-3.1.2, for example). See below for more options related to installing the build engine library. - Install the troff-format man pages in an appropriate directory on UNIX or @@ -484,7 +484,7 @@ running all of "runtest.py -a". Building Packages ================= -We use SCons (version 3.0.3 or later) to build its own packages. If you +We use SCons (version 3.1.2 or later) to build its own packages. If you already have an appropriate version of SCons installed on your system, you can build everything by simply running it:: @@ -613,10 +613,6 @@ LICENSE-local LICENSE with a preamble that specifies the licensing terms are for SCons itself, not any other package that includes SCons. -QMTest/ - The Python modules we use for testing, some generic modules originating - elsewhere and some specific to SCons. - README.rst What you're looking at right now. @@ -625,9 +621,6 @@ README-local Similar to this file, but stripped down and modified for people looking at including SCons in their shipped software. -rpm/ - The .spec file for building our RPM packages. - runtest.py Script for running SCons tests. By default, this will run a test against the code in the local src/ tree, so you don't have to do a build before @@ -652,6 +645,8 @@ test/ individual module unit tests, which live side-by-side with the modules under src/. +testing/ + SCons testing framework. Documentation ============= diff --git a/bin/upload-release-files.sh b/bin/upload-release-files.sh index 577203e..b23b0a0 100755 --- a/bin/upload-release-files.sh +++ b/bin/upload-release-files.sh @@ -21,6 +21,12 @@ cp -f ../../src/CHANGES.txt ../../src/RELEASE.txt ../../src/Announce.txt ../../s set -x +# upload README +$RSYNC $RSYNCOPTS\ + README-SF.rst bdbaddog@frs.sourceforge.net:/home/frs/project/scons/ \ + $SF_USER@$SF_MACHINE:$SF_TOPDIR/scons/ + + # Upload main scons release files: $RSYNC $RSYNCOPTS \ scons-$VERSION.tar.gz \ -- cgit v0.12 From 06fecd6362d691d16d9ad8347dd85ca7726a4d71 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 17 Dec 2019 03:00:39 +0000 Subject: Revert code back to development mode --- ReleaseConfig | 2 +- src/Announce.txt | 2 +- src/CHANGES.txt | 7 ++++ src/RELEASE.txt | 105 +++++++++++++++++++++++-------------------------------- 4 files changed, 53 insertions(+), 63 deletions(-) diff --git a/ReleaseConfig b/ReleaseConfig index 3068687..818b405 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, 2) +version_tuple = (3, 1, 3, 'alpha', 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/src/Announce.txt b/src/Announce.txt index 321496d..17b3093 100755 --- a/src/Announce.txt +++ b/src/Announce.txt @@ -18,7 +18,7 @@ So that everyone using SCons can help each other learn how to use it more effectively, please go to http://scons.org/lists.html#users to sign up for the scons-users mailing list. -RELEASE 3.1.2 - Mon, 17 Dec 2019 02:06:27 +0000 +RELEASE VERSION/DATE TO BE FILLED IN LATER Please consult the RELEASE.txt file for a summary of changes since the last release and consult the CHANGES.txt file for complete a list of changes diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 745bcba..968a2c4 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -6,6 +6,13 @@ 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. + + RELEASE 3.1.2 - Mon, 17 Dec 2019 02:06:27 +0000 From Edoardo Bezzeccheri diff --git a/src/RELEASE.txt b/src/RELEASE.txt index 0070c6a..825122e 100755 --- a/src/RELEASE.txt +++ b/src/RELEASE.txt @@ -1,90 +1,73 @@ - A new SCons checkpoint release, 3.1.2, is now available + A new SCons checkpoint release, 3.1.3.alpha.yyyymmdd, is now available on the SCons download page: https://scons.org/pages/download.html - Here is a summary of the changes since 3.1.1: + XXX The primary purpose of this release ... XXX - NOTE: The 4.0.0 Release of SCons will drop Python 2.7 Support + A SCons "checkpoint release" is intended to provide early access to + new features so they can be tested in the field before being released + for adoption by other software distributions. + + Note that a checkpoint release is developed using the same test-driven + development methodology as all SCons releases. Existing SCons + functionality should all work as it does in previous releases (except + for any changes identified in the release notes) and early adopters + should be able to use a checkpoint release safely for production work + with existing SConscript files. If not, it represents not only a bug + in SCons but also a hole in the regression test suite, and we want to + hear about it. + + New features may be more lightly tested than in past releases, + especially as concerns their interaction with all of the other + functionality in SCons. We are especially interested in hearing bug + reports about new functionality. + + We do not recommend that downstream distributions (Debian, Fedora, + etc.) package a checkpoint release, mainly to avoid confusing the + "public" release numbering with the long checkpoint release names. + + Here is a summary of the changes since 1.3.0: NEW FUNCTIONALITY - - Added debug option "action_timestamps" which outputs to stdout the absolute start and end time for each target. - REMOVED FUNCTIONALITY - - Turn previously deprecated debug options into failures: - --debug=tree, --debug=dtree, --debug=stree, --debug=nomemoizer. - - Remove deprecated SourceSignatures, TargetSignatures - - Remove deprecated Builder keywords: overrides and scanner - - Remove deprecated env.Copy - - Remove deprecated BuildDir plus SConscript keyword build_dir + - List new features (presumably why a checkpoint is being released) + DEPRECATED FUNCTIONALITY + + - List anything that's been deprecated since the last release CHANGED/ENHANCED EXISTING FUNCTIONALITY - - Update Command() function to accept target_scanner, source_factory, and target_factory arguments. - This makes Command act more like a one-off builder. - - Added support for "-imacros" to ParseFlags - - EXPERIMENTAL NEW FEATURE: Enable caching MSVC configuration - If SCONS_CACHE_MSVC_CONFIG shell environment variable is set, - SCons will cache the results of past calls to vcvarsall.bat to - a file; integrates with existing memoizing of such vars. - On vs2019 saves 5+ seconds per SCons invocation, which really - helps test suite runs. + + - List modifications to existing features, where the previous behavior + wouldn't actually be considered a bug FIXES - - Fix suncxx tool (Oracle Studio compiler) when using Python 3. Previously would throw an exception. - Resolved by properly handling tool version string output as unicode. - - Resolved a race condition in multithreaded Windows builds with Python 2 - in the case where a child process is spawned while a Python action has a - file open. Original author: Ryan Beasley. - - Fix CheckFunc detection code for Visual 2019. Some functions - (e.g. memmove) were incorrectly recognized as not available. - - Fix stacktrace when using SCons with Python 3.5+ and SunOS/Solaris related tools. - - Latex: 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 - the fontenc package is included with \usepackage[T1]{fontenc}) is read. - - CmdStringHolder fix from issue #3428 + + - List fixes of outright bugs IMPROVEMENTS - - Improved threading performance by ensuring NodeInfo is shared - across threads. Results in ~13% improvement for parallel builds - (-j# > 1) with many shared nodes. - - Improve performance of Entry.disambiguate() by making check for - most common case first, preventing unnecessary IO. - - Improved DAG walk performance by reducing unnecessary work when - there are no un-visited children. + - List improvements that wouldn't be visible to the user in the + documentation: performance improvements (describe the circumstances + under which they would be observed), or major code cleanups PACKAGING - - N/A + - List changes in the way SCons is packaged and/or released DOCUMENTATION - - N/A + - List any significant changes to the documentation (not individual + typo fixes, even if they're mentioned in src/CHANGES.txt to give + the contributor credit) DEVELOPMENT - - N/A - - -Thanks to the following developers for their contributions to this release. -git shortlog --no-merges -ns 3.1.1..HEAD - 59 Mats Wichmann - 21 William Deegan - 8 Edoardo Bezzeccheri - 5 Adam Gross - 5 maiphi - 4 Ivan Kravets - 4 Mathew Robinson - 2 Jakub Kulík - 2 Jacek Kuczera - 2 Rob Boehne - 2 Jason Kenny - 2 Tim Gates - 1 Jakub Kulik - 1 Theogen Ratkin - 1 jw0k + - List visible changes in the way SCons is developed + Thanks to CURLY, LARRY, and MOE for their contributions to this release. + Contributors are listed alphabetically by their last name. __COPYRIGHT__ __FILE__ __REVISION__ __DATE__ __DEVELOPER__ -- 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 22a7b1eaaaa6a72f8ee301e45dc1bb72d876ff7a Mon Sep 17 00:00:00 2001 From: Mathew Robinson Date: Wed, 18 Dec 2019 10:27:33 -0500 Subject: Improve performance of Subst by preventing unnecessary frame allocations --- src/CHANGES.txt | 7 +- src/engine/SCons/Subst.py | 719 +++++++++++++++++++++++----------------------- 2 files changed, 365 insertions(+), 361 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 968a2c4..96465d6 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -8,9 +8,10 @@ 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 Mathew Robinson: + - Improve performance of Subst by preventing unnecessary frame + allocations by no longer defining the *Subber classes inside of their + respective function calls. RELEASE 3.1.2 - Mon, 17 Dec 2019 02:06:27 +0000 diff --git a/src/engine/SCons/Subst.py b/src/engine/SCons/Subst.py index 2de64c5..f3693a1 100644 --- a/src/engine/SCons/Subst.py +++ b/src/engine/SCons/Subst.py @@ -331,6 +331,366 @@ def subst_dict(target, source): return dict + +class StringSubber(object): + """A class to construct the results of a scons_subst() call. + + This binds a specific construction environment, mode, target and + source with two methods (substitute() and expand()) that handle + the expansion. + """ + def __init__(self, env, mode, conv, gvars): + self.env = env + self.mode = mode + self.conv = conv + self.gvars = gvars + + def expand(self, s, lvars): + """Expand a single "token" as necessary, returning an + appropriate string containing the expansion. + + This handles expanding different types of things (strings, + lists, callables) appropriately. It calls the wrapper + substitute() method to re-expand things as necessary, so that + the results of expansions of side-by-side strings still get + re-evaluated separately, not smushed together. + """ + if is_String(s): + try: + s0, s1 = s[:2] + except (IndexError, ValueError): + return s + if s0 != '$': + return s + if s1 == '$': + # In this case keep the double $'s which we'll later + # swap for a single dollar sign as we need to retain + # this information to properly avoid matching "$("" when + # the actual text was "$$("" (or "$)"" when "$$)"" ) + return '$$' + elif s1 in '()': + return s + else: + key = s[1:] + 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) + 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 '' + + # Before re-expanding the result, handle + # recursive expansion by copying the local + # variable dictionary and overwriting a null + # string for the value of the variable name + # we just expanded. + # + # This could potentially be optimized by only + # copying lvars when s contains more expansions, + # but lvars is usually supposed to be pretty + # small, and deeply nested variable expansions + # are probably more the exception than the norm, + # so it should be tolerable for now. + lv = lvars.copy() + var = key.split('.')[0] + lv[var] = '' + return self.substitute(s, lv) + elif is_Sequence(s): + def func(l, conv=self.conv, substitute=self.substitute, lvars=lvars): + return conv(substitute(l, lvars)) + return list(map(func, s)) + elif callable(s): + try: + s = s(target=lvars['TARGETS'], + source=lvars['SOURCES'], + env=self.env, + for_signature=(self.mode != SUBST_CMD)) + except TypeError: + # This probably indicates that it's a callable + # object that doesn't match our calling arguments + # (like an Action). + if self.mode == SUBST_RAW: + return s + s = self.conv(s) + return self.substitute(s, lvars) + elif s is None: + return '' + else: + return s + + def substitute(self, args, lvars): + """Substitute expansions in an argument or list of arguments. + + This serves as a wrapper for splitting up a string into + separate tokens. + """ + if is_String(args) and not isinstance(args, CmdStringHolder): + args = str(args) # In case it's a UserString. + try: + def sub_match(match): + return self.conv(self.expand(match.group(1), lvars)) + result = _dollar_exps.sub(sub_match, args) + except TypeError: + # If the internal conversion routine doesn't return + # strings (it could be overridden to return Nodes, for + # example), then the 1.5.2 re module will throw this + # exception. Back off to a slower, general-purpose + # algorithm that works for all data types. + args = _separate_args.findall(args) + result = [] + for a in args: + result.append(self.conv(self.expand(a, lvars))) + if len(result) == 1: + result = result[0] + else: + result = ''.join(map(str, result)) + return result + else: + return self.expand(args, lvars) + + +class ListSubber(collections.UserList): + """A class to construct the results of a scons_subst_list() call. + + Like StringSubber, this class binds a specific construction + environment, mode, target and source with two methods + (substitute() and expand()) that handle the expansion. + + In addition, however, this class is used to track the state of + the result(s) we're gathering so we can do the appropriate thing + whenever we have to append another word to the result--start a new + line, start a new word, append to the current word, etc. We do + this by setting the "append" attribute to the right method so + that our wrapper methods only need ever call ListSubber.append(), + and the rest of the object takes care of doing the right thing + internally. + """ + def __init__(self, env, mode, conv, gvars): + collections.UserList.__init__(self, []) + self.env = env + self.mode = mode + self.conv = conv + self.gvars = gvars + + if self.mode == SUBST_RAW: + self.add_strip = lambda x: self.append(x) + else: + self.add_strip = lambda x: None + self.in_strip = None + self.next_line() + + def expand(self, s, lvars, within_list): + """Expand a single "token" as necessary, appending the + expansion to the current result. + + This handles expanding different types of things (strings, + lists, callables) appropriately. It calls the wrapper + substitute() method to re-expand things as necessary, so that + the results of expansions of side-by-side strings still get + re-evaluated separately, not smushed together. + """ + + if is_String(s): + try: + s0, s1 = s[:2] + except (IndexError, ValueError): + self.append(s) + return + if s0 != '$': + self.append(s) + return + if s1 == '$': + self.append('$') + elif s1 == '(': + self.open_strip('$(') + elif s1 == ')': + self.close_strip('$)') + else: + key = s[1:] + 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) + 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 + + # Before re-expanding the result, handle + # recursive expansion by copying the local + # variable dictionary and overwriting a null + # string for the value of the variable name + # we just expanded. + lv = lvars.copy() + var = key.split('.')[0] + lv[var] = '' + self.substitute(s, lv, 0) + self.this_word() + elif is_Sequence(s): + for a in s: + self.substitute(a, lvars, 1) + self.next_word() + elif callable(s): + try: + s = s(target=lvars['TARGETS'], + source=lvars['SOURCES'], + env=self.env, + for_signature=(self.mode != SUBST_CMD)) + except TypeError: + # This probably indicates that it's a callable + # object that doesn't match our calling arguments + # (like an Action). + if self.mode == SUBST_RAW: + self.append(s) + return + s = self.conv(s) + self.substitute(s, lvars, within_list) + elif s is None: + self.this_word() + else: + self.append(s) + + def substitute(self, args, lvars, within_list): + """Substitute expansions in an argument or list of arguments. + + This serves as a wrapper for splitting up a string into + separate tokens. + """ + + if is_String(args) and not isinstance(args, CmdStringHolder): + args = str(args) # In case it's a UserString. + args = _separate_args.findall(args) + for a in args: + if a[0] in ' \t\n\r\f\v': + if '\n' in a: + self.next_line() + elif within_list: + self.append(a) + else: + self.next_word() + else: + self.expand(a, lvars, within_list) + else: + self.expand(args, lvars, within_list) + + def next_line(self): + """Arrange for the next word to start a new line. This + is like starting a new word, except that we have to append + another line to the result.""" + collections.UserList.append(self, []) + self.next_word() + + def this_word(self): + """Arrange for the next word to append to the end of the + current last word in the result.""" + self.append = self.add_to_current_word + + def next_word(self): + """Arrange for the next word to start a new word.""" + self.append = self.add_new_word + + def add_to_current_word(self, x): + """Append the string x to the end of the current last word + in the result. If that is not possible, then just add + it as a new word. Make sure the entire concatenated string + inherits the object attributes of x (in particular, the + escape function) by wrapping it as CmdStringHolder.""" + + if not self.in_strip or self.mode != SUBST_SIG: + try: + current_word = self[-1][-1] + except IndexError: + self.add_new_word(x) + else: + # All right, this is a hack and it should probably + # be refactored out of existence in the future. + # The issue is that we want to smoosh words together + # and make one file name that gets escaped if + # we're expanding something like foo$EXTENSION, + # but we don't want to smoosh them together if + # it's something like >$TARGET, because then we'll + # treat the '>' like it's part of the file name. + # So for now, just hard-code looking for the special + # command-line redirection characters... + try: + last_char = str(current_word)[-1] + except IndexError: + last_char = '\0' + if last_char in '<>|': + self.add_new_word(x) + else: + y = current_word + x + + # We used to treat a word appended to a literal + # as a literal itself, but this caused problems + # with interpreting quotes around space-separated + # targets on command lines. Removing this makes + # none of the "substantive" end-to-end tests fail, + # so we'll take this out but leave it commented + # for now in case there's a problem not covered + # by the test cases and we need to resurrect this. + #literal1 = self.literal(self[-1][-1]) + #literal2 = self.literal(x) + y = self.conv(y) + if is_String(y): + #y = CmdStringHolder(y, literal1 or literal2) + y = CmdStringHolder(y, None) + self[-1][-1] = y + + def add_new_word(self, x): + if not self.in_strip or self.mode != SUBST_SIG: + literal = self.literal(x) + x = self.conv(x) + if is_String(x): + x = CmdStringHolder(x, literal) + self[-1].append(x) + self.append = self.add_to_current_word + + def literal(self, x): + try: + l = x.is_literal + except AttributeError: + return None + else: + return l() + + def open_strip(self, x): + """Handle the "open strip" $( token.""" + self.add_strip(x) + self.in_strip = 1 + + def close_strip(self, x): + """Handle the "close strip" $) token.""" + self.add_strip(x) + self.in_strip = None + + # Constants for the "mode" parameter to scons_subst_list() and # scons_subst(). SUBST_RAW gives the raw command line. SUBST_CMD # gives a command line suitable for passing to a shell. SUBST_SIG @@ -412,136 +772,6 @@ def scons_subst(strSubst, env, mode=SUBST_RAW, target=None, source=None, gvars={ if (isinstance(strSubst, str) and '$' not in strSubst) or isinstance(strSubst, CmdStringHolder): return strSubst - class StringSubber(object): - """A class to construct the results of a scons_subst() call. - - This binds a specific construction environment, mode, target and - source with two methods (substitute() and expand()) that handle - the expansion. - """ - def __init__(self, env, mode, conv, gvars): - self.env = env - self.mode = mode - self.conv = conv - self.gvars = gvars - - def expand(self, s, lvars): - """Expand a single "token" as necessary, returning an - appropriate string containing the expansion. - - This handles expanding different types of things (strings, - lists, callables) appropriately. It calls the wrapper - substitute() method to re-expand things as necessary, so that - the results of expansions of side-by-side strings still get - re-evaluated separately, not smushed together. - """ - if is_String(s): - try: - s0, s1 = s[:2] - except (IndexError, ValueError): - return s - if s0 != '$': - return s - if s1 == '$': - # In this case keep the double $'s which we'll later - # swap for a single dollar sign as we need to retain - # this information to properly avoid matching "$("" when - # the actual text was "$$("" (or "$)"" when "$$)"" ) - return '$$' - elif s1 in '()': - return s - else: - key = s[1:] - 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) - 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 '' - - # Before re-expanding the result, handle - # recursive expansion by copying the local - # variable dictionary and overwriting a null - # string for the value of the variable name - # we just expanded. - # - # This could potentially be optimized by only - # copying lvars when s contains more expansions, - # but lvars is usually supposed to be pretty - # small, and deeply nested variable expansions - # are probably more the exception than the norm, - # so it should be tolerable for now. - lv = lvars.copy() - var = key.split('.')[0] - lv[var] = '' - return self.substitute(s, lv) - elif is_Sequence(s): - def func(l, conv=self.conv, substitute=self.substitute, lvars=lvars): - return conv(substitute(l, lvars)) - return list(map(func, s)) - elif callable(s): - try: - s = s(target=lvars['TARGETS'], - source=lvars['SOURCES'], - env=self.env, - for_signature=(self.mode != SUBST_CMD)) - except TypeError: - # This probably indicates that it's a callable - # object that doesn't match our calling arguments - # (like an Action). - if self.mode == SUBST_RAW: - return s - s = self.conv(s) - return self.substitute(s, lvars) - elif s is None: - return '' - else: - return s - - def substitute(self, args, lvars): - """Substitute expansions in an argument or list of arguments. - - This serves as a wrapper for splitting up a string into - separate tokens. - """ - if is_String(args) and not isinstance(args, CmdStringHolder): - args = str(args) # In case it's a UserString. - try: - def sub_match(match): - return self.conv(self.expand(match.group(1), lvars)) - result = _dollar_exps.sub(sub_match, args) - except TypeError: - # If the internal conversion routine doesn't return - # strings (it could be overridden to return Nodes, for - # example), then the 1.5.2 re module will throw this - # exception. Back off to a slower, general-purpose - # algorithm that works for all data types. - args = _separate_args.findall(args) - result = [] - for a in args: - result.append(self.conv(self.expand(a, lvars))) - if len(result) == 1: - result = result[0] - else: - result = ''.join(map(str, result)) - return result - else: - return self.expand(args, lvars) - if conv is None: conv = _strconv[mode] @@ -615,234 +845,7 @@ def scons_subst_list(strSubst, env, mode=SUBST_RAW, target=None, source=None, gv The companion scons_subst() function (above) handles basic substitutions within strings, so see that function instead if that's what you're looking for. - """ - class ListSubber(collections.UserList): - """A class to construct the results of a scons_subst_list() call. - - Like StringSubber, this class binds a specific construction - environment, mode, target and source with two methods - (substitute() and expand()) that handle the expansion. - - In addition, however, this class is used to track the state of - the result(s) we're gathering so we can do the appropriate thing - whenever we have to append another word to the result--start a new - line, start a new word, append to the current word, etc. We do - this by setting the "append" attribute to the right method so - that our wrapper methods only need ever call ListSubber.append(), - and the rest of the object takes care of doing the right thing - internally. - """ - def __init__(self, env, mode, conv, gvars): - collections.UserList.__init__(self, []) - self.env = env - self.mode = mode - self.conv = conv - self.gvars = gvars - - if self.mode == SUBST_RAW: - self.add_strip = lambda x: self.append(x) - else: - self.add_strip = lambda x: None - self.in_strip = None - self.next_line() - - def expand(self, s, lvars, within_list): - """Expand a single "token" as necessary, appending the - expansion to the current result. - - This handles expanding different types of things (strings, - lists, callables) appropriately. It calls the wrapper - substitute() method to re-expand things as necessary, so that - the results of expansions of side-by-side strings still get - re-evaluated separately, not smushed together. - """ - - if is_String(s): - try: - s0, s1 = s[:2] - except (IndexError, ValueError): - self.append(s) - return - if s0 != '$': - self.append(s) - return - if s1 == '$': - self.append('$') - elif s1 == '(': - self.open_strip('$(') - elif s1 == ')': - self.close_strip('$)') - else: - key = s[1:] - 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) - 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 - - # Before re-expanding the result, handle - # recursive expansion by copying the local - # variable dictionary and overwriting a null - # string for the value of the variable name - # we just expanded. - lv = lvars.copy() - var = key.split('.')[0] - lv[var] = '' - self.substitute(s, lv, 0) - self.this_word() - elif is_Sequence(s): - for a in s: - self.substitute(a, lvars, 1) - self.next_word() - elif callable(s): - try: - s = s(target=lvars['TARGETS'], - source=lvars['SOURCES'], - env=self.env, - for_signature=(self.mode != SUBST_CMD)) - except TypeError: - # This probably indicates that it's a callable - # object that doesn't match our calling arguments - # (like an Action). - if self.mode == SUBST_RAW: - self.append(s) - return - s = self.conv(s) - self.substitute(s, lvars, within_list) - elif s is None: - self.this_word() - else: - self.append(s) - - def substitute(self, args, lvars, within_list): - """Substitute expansions in an argument or list of arguments. - - This serves as a wrapper for splitting up a string into - separate tokens. - """ - - if is_String(args) and not isinstance(args, CmdStringHolder): - args = str(args) # In case it's a UserString. - args = _separate_args.findall(args) - for a in args: - if a[0] in ' \t\n\r\f\v': - if '\n' in a: - self.next_line() - elif within_list: - self.append(a) - else: - self.next_word() - else: - self.expand(a, lvars, within_list) - else: - self.expand(args, lvars, within_list) - - def next_line(self): - """Arrange for the next word to start a new line. This - is like starting a new word, except that we have to append - another line to the result.""" - collections.UserList.append(self, []) - self.next_word() - - def this_word(self): - """Arrange for the next word to append to the end of the - current last word in the result.""" - self.append = self.add_to_current_word - - def next_word(self): - """Arrange for the next word to start a new word.""" - self.append = self.add_new_word - - def add_to_current_word(self, x): - """Append the string x to the end of the current last word - in the result. If that is not possible, then just add - it as a new word. Make sure the entire concatenated string - inherits the object attributes of x (in particular, the - escape function) by wrapping it as CmdStringHolder.""" - - if not self.in_strip or self.mode != SUBST_SIG: - try: - current_word = self[-1][-1] - except IndexError: - self.add_new_word(x) - else: - # All right, this is a hack and it should probably - # be refactored out of existence in the future. - # The issue is that we want to smoosh words together - # and make one file name that gets escaped if - # we're expanding something like foo$EXTENSION, - # but we don't want to smoosh them together if - # it's something like >$TARGET, because then we'll - # treat the '>' like it's part of the file name. - # So for now, just hard-code looking for the special - # command-line redirection characters... - try: - last_char = str(current_word)[-1] - except IndexError: - last_char = '\0' - if last_char in '<>|': - self.add_new_word(x) - else: - y = current_word + x - - # We used to treat a word appended to a literal - # as a literal itself, but this caused problems - # with interpreting quotes around space-separated - # targets on command lines. Removing this makes - # none of the "substantive" end-to-end tests fail, - # so we'll take this out but leave it commented - # for now in case there's a problem not covered - # by the test cases and we need to resurrect this. - #literal1 = self.literal(self[-1][-1]) - #literal2 = self.literal(x) - y = self.conv(y) - if is_String(y): - #y = CmdStringHolder(y, literal1 or literal2) - y = CmdStringHolder(y, None) - self[-1][-1] = y - - def add_new_word(self, x): - if not self.in_strip or self.mode != SUBST_SIG: - literal = self.literal(x) - x = self.conv(x) - if is_String(x): - x = CmdStringHolder(x, literal) - self[-1].append(x) - self.append = self.add_to_current_word - - def literal(self, x): - try: - l = x.is_literal - except AttributeError: - return None - else: - return l() - - def open_strip(self, x): - """Handle the "open strip" $( token.""" - self.add_strip(x) - self.in_strip = 1 - - def close_strip(self, x): - """Handle the "close strip" $) token.""" - self.add_strip(x) - self.in_strip = None - + """ if conv is None: conv = _strconv[mode] -- 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 c13b879fa7014a7a3e195bdc845fbf5527cca6aa Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 20 Dec 2019 12:04:35 -0700 Subject: Remove deprecated SourceCode func/method Signed-off-by: Mats Wichmann --- doc/user/builders-writing.xml | 31 ----- doc/user/main.xml | 7 -- doc/user/sourcecode.xml | 185 ----------------------------- src/CHANGES.txt | 3 + src/engine/SCons/Environment.py | 31 ----- src/engine/SCons/Environment.xml | 131 -------------------- src/engine/SCons/EnvironmentTests.py | 19 --- src/engine/SCons/Script/__init__.py | 1 - test/Deprecated/SourceCode/SourceCode.py | 123 ------------------- test/Removed/SourceCode/Old/SourceCode.py | 123 +++++++++++++++++++ test/Removed/SourceCode/Old/sconstest.skip | 0 test/Removed/SourceCode/README.md | 6 + test/Removed/SourceCode/SConstruct.global | 2 + test/Removed/SourceCode/SConstruct.method | 3 + test/Removed/SourceCode/SourceCode.py | 73 ++++++++++++ 15 files changed, 210 insertions(+), 528 deletions(-) delete mode 100644 doc/user/sourcecode.xml delete mode 100644 test/Deprecated/SourceCode/SourceCode.py create mode 100644 test/Removed/SourceCode/Old/SourceCode.py create mode 100644 test/Removed/SourceCode/Old/sconstest.skip create mode 100644 test/Removed/SourceCode/README.md create mode 100644 test/Removed/SourceCode/SConstruct.global create mode 100644 test/Removed/SourceCode/SConstruct.method create mode 100644 test/Removed/SourceCode/SourceCode.py diff --git a/doc/user/builders-writing.xml b/doc/user/builders-writing.xml index a906df8..76fa794 100644 --- a/doc/user/builders-writing.xml +++ b/doc/user/builders-writing.xml @@ -1079,35 +1079,4 @@ from SCons.Script import *
- - - diff --git a/doc/user/main.xml b/doc/user/main.xml index 42724d1..85dcf00 100644 --- a/doc/user/main.xml +++ b/doc/user/main.xml @@ -147,13 +147,6 @@ - - - diff --git a/doc/user/sourcecode.xml b/doc/user/sourcecode.xml deleted file mode 100644 index 5905cc5..0000000 --- a/doc/user/sourcecode.xml +++ /dev/null @@ -1,185 +0,0 @@ - - - %scons; - - - %builders-mod; - - %functions-mod; - - %tools-mod; - - %variables-mod; -]> - - -Fetching Files From Source Code Management Systems - - - - - - - - XXX - - - -
- Fetching Source Code From BitKeeper - - - - XXX - - - - - -env = Environment() -env.SourceCode('.', env.BitKeeper()) -env.Program('hello.c') - - -s.hello.c - - - - - scons -Q - - -
- -
- Fetching Source Code From CVS - - - - XXX - - - - - -env = Environment() -env.SourceCode('.', env.CVS('/usr/local/CVS')) -env.Program('hello.c') - - - - - scons -Q - - -
- -
- Fetching Source Code From RCS - - - - XXX - - - - - -env = Environment() -env.SourceCode('.', env.RCS()) -env.Program('hello.c') - - -hello.c,v - - - - - scons -Q - - -
- -
- Fetching Source Code From SCCS - - - - XXX - - - - - -env = Environment() -env.SourceCode('.', env.SCCS()) -env.Program('hello.c') - - -s.hello.c - - - - - scons -Q - - -
- - - -
diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 96465d6..79a65fb 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -13,6 +13,9 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER allocations by no longer defining the *Subber classes inside of their respective function calls. + From Mats Wichmann: + - Remove deprecated SourceCode + RELEASE 3.1.2 - Mon, 17 Dec 2019 02:06:27 +0000 diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 27179c3..36b7c3d 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -2199,37 +2199,6 @@ class Base(SubstitutionEnvironment): target.side_effects.append(side_effect) return side_effects - def SourceCode(self, entry, builder): - """Arrange for a source code builder for (part of) a tree.""" - msg = """SourceCode() has been deprecated and there is no replacement. -\tIf you need this function, please contact scons-dev@scons.org""" - SCons.Warnings.warn(SCons.Warnings.DeprecatedSourceCodeWarning, msg) - entries = self.arg2nodes(entry, self.fs.Entry) - for entry in entries: - entry.set_src_builder(builder) - return entries - - def Split(self, arg): - """This function converts a string or list into a list of strings - or Nodes. This makes things easier for users by allowing files to - be specified as a white-space separated list to be split. - - The input rules are: - - A single string containing names separated by spaces. These will be - split apart at the spaces. - - A single Node instance - - A list containing either strings or Node instances. Any strings - in the list are not split at spaces. - - In all cases, the function returns a list of Nodes and strings.""" - - if SCons.Util.is_List(arg): - return list(map(self.subst, arg)) - elif SCons.Util.is_String(arg): - return self.subst(arg).split() - else: - return [self.subst(arg)] - def Value(self, value, built_value=None): """ """ diff --git a/src/engine/SCons/Environment.xml b/src/engine/SCons/Environment.xml index 6f263a4..b1c2039 100644 --- a/src/engine/SCons/Environment.xml +++ b/src/engine/SCons/Environment.xml @@ -2879,137 +2879,6 @@ function. - - -(entries, builder) - - - -This function and its associate factory functions are deprecated. -There is no replacement. -The intended use was to keep a local tree in sync with an archive, -but in actuality the function only causes the archive -to be fetched on the first run. -Synchronizing with the archive is best done external to &SCons;. - - - -Arrange for non-existent source files to -be fetched from a source code management system -using the specified -builder. -The specified -entries -may be a Node, string or list of both, -and may represent either individual -source files or directories in which -source files can be found. - - - -For any non-existent source files, -&scons; -will search up the directory tree -and use the first -&f-SourceCode; -builder it finds. -The specified -builder -may be -None, -in which case -&scons; -will not use a builder to fetch -source files for the specified -entries, -even if a -&f-SourceCode; -builder has been specified -for a directory higher up the tree. - - - -&scons; -will, by default, -fetch files from SCCS or RCS subdirectories -without explicit configuration. -This takes some extra processing time -to search for the necessary -source code management files on disk. -You can avoid these extra searches -and speed up your build a little -by disabling these searches as follows: - - - -env.SourceCode('.', None) - - - -Note that if the specified -builder -is one you create by hand, -it must have an associated -construction environment to use -when fetching a source file. - - - -&scons; -provides a set of canned factory -functions that return appropriate -Builders for various popular -source code management systems. -Canonical examples of invocation include: - - - -env.SourceCode('.', env.BitKeeper('/usr/local/BKsources')) -env.SourceCode('src', env.CVS('/usr/local/CVSROOT')) -env.SourceCode('/', env.RCS()) -env.SourceCode(['f1.c', 'f2.c'], env.SCCS()) -env.SourceCode('no_source.c', None) - - - - - - - - - -(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/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index b2f2bd5..52ab859 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -3255,25 +3255,6 @@ def generate(env): assert ggg.side_effects == [s], ggg.side_effects assert ccc.side_effects == [s], ccc.side_effects - def test_SourceCode(self): - """Test the SourceCode() method.""" - env = self.TestEnvironment(FOO='mmm', BAR='nnn') - e = env.SourceCode('foo', None)[0] - assert e.get_internal_path() == 'foo' - s = e.src_builder() - assert s is None, s - - b = Builder() - e = env.SourceCode(e, b)[0] - assert e.get_internal_path() == 'foo' - s = e.src_builder() - assert s is b, s - - e = env.SourceCode('$BAR$FOO', None)[0] - assert e.get_internal_path() == 'nnnmmm' - s = e.src_builder() - assert s is None, s - def test_Split(self): """Test the Split() method""" env = self.TestEnvironment(FOO = 'fff', BAR = 'bbb') diff --git a/src/engine/SCons/Script/__init__.py b/src/engine/SCons/Script/__init__.py index 9947943..8f526be 100644 --- a/src/engine/SCons/Script/__init__.py +++ b/src/engine/SCons/Script/__init__.py @@ -344,7 +344,6 @@ GlobalDefaultEnvironmentFunctions = [ 'Requires', 'SConsignFile', 'SideEffect', - 'SourceCode', 'Split', 'Tag', 'Value', diff --git a/test/Deprecated/SourceCode/SourceCode.py b/test/Deprecated/SourceCode/SourceCode.py deleted file mode 100644 index b7f1305..0000000 --- a/test/Deprecated/SourceCode/SourceCode.py +++ /dev/null @@ -1,123 +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__" - -""" -Test fetching source files using the SourceCode() method. -""" - -import os - -import TestSCons - -test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) - -test.write('SConscript', """ -SourceCode('.', None) -""") - -msg = """SourceCode() has been deprecated and there is no replacement. -\tIf you need this function, please contact scons-dev@scons.org""" -warning = test.deprecated_warning('deprecated-source-code', msg) - -test.subdir('sub', 'sub2') - -test.write('SConstruct', """\ -SetOption('warn', 'deprecated-source-code') -import os - -def cat(env, source, target): - target = str(target[0]) - with open(target, "wb") as ofp: - for src in source: - with open(str(src), "rb") as ifp: - ofp.write(ifp.read()) - -def sc_cat(env, source, target): - source = [] - for t in target: - head, tail = os.path.split(str(t)) - source.append(os.path.join(head, 'sc-' + tail)) - cat(env, source, target) - -env = Environment(BUILDERS={'Cat':Builder(action=cat)}, SUBDIR='sub') -env.SourceCode('$SUBDIR', Builder(action=sc_cat, env=env)) -env.Cat('aaa.out', 'sub/aaa.in') -bbb_in = File('sub/bbb.in') -bbb_in.is_derived() -env.Cat('bbb.out', bbb_in) -env.Cat('ccc.out', 'sub/ccc.in') -env.Cat('all', ['aaa.out', 'bbb.out', 'ccc.out']) -SConscript('sub/SConscript', "env") - -SourceCode('sub2', Builder(action=sc_cat, env=env)) -env.Cat('ddd.out', 'sub2/ddd.in') -""") - -test.write(['sub', 'sc-aaa.in'], "sub/sc-aaa.in\n") -test.write(['sub', 'sc-bbb.in'], "sub/sc-bbb.in\n") -test.write(['sub', 'sc-ccc.in'], "sub/sc-ccc.in\n") -test.write(['sub2', 'sc-ddd.in'], "sub2/sc-ddd.in\n") - -test.write(['sub', 'sc-SConscript'], "'sub/sc-SConscript'\n") - -read_str = """\ -sc_cat(["%s"], []) -""" % (os.path.join('sub', 'SConscript')) - -build_str = """\ -sc_cat(["%s"], []) -cat(["aaa.out"], ["%s"]) -sc_cat(["%s"], []) -cat(["bbb.out"], ["%s"]) -sc_cat(["%s"], []) -cat(["ccc.out"], ["%s"]) -cat(["all"], ["aaa.out", "bbb.out", "ccc.out"]) -sc_cat(["%s"], []) -cat(["ddd.out"], ["%s"]) -""" % (os.path.join('sub', 'aaa.in'), - os.path.join('sub', 'aaa.in'), - os.path.join('sub', 'bbb.in'), - os.path.join('sub', 'bbb.in'), - os.path.join('sub', 'ccc.in'), - os.path.join('sub', 'ccc.in'), - os.path.join('sub2', 'ddd.in'), - os.path.join('sub2', 'ddd.in')) - -stdout = TestSCons.re_escape(test.wrap_stdout(read_str = read_str, - build_str = build_str)) - -test.run(arguments = '.', stdout = stdout, stderr = 2*warning) - -test.must_match(['sub', 'SConscript'], "'sub/sc-SConscript'\n") -test.must_match('all', "sub/sc-aaa.in\nsub/sc-bbb.in\nsub/sc-ccc.in\n") -test.must_match('ddd.out', "sub2/sc-ddd.in\n") - -test.pass_test() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Removed/SourceCode/Old/SourceCode.py b/test/Removed/SourceCode/Old/SourceCode.py new file mode 100644 index 0000000..b7f1305 --- /dev/null +++ b/test/Removed/SourceCode/Old/SourceCode.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Test fetching source files using the SourceCode() method. +""" + +import os + +import TestSCons + +test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) + +test.write('SConscript', """ +SourceCode('.', None) +""") + +msg = """SourceCode() has been deprecated and there is no replacement. +\tIf you need this function, please contact scons-dev@scons.org""" +warning = test.deprecated_warning('deprecated-source-code', msg) + +test.subdir('sub', 'sub2') + +test.write('SConstruct', """\ +SetOption('warn', 'deprecated-source-code') +import os + +def cat(env, source, target): + target = str(target[0]) + with open(target, "wb") as ofp: + for src in source: + with open(str(src), "rb") as ifp: + ofp.write(ifp.read()) + +def sc_cat(env, source, target): + source = [] + for t in target: + head, tail = os.path.split(str(t)) + source.append(os.path.join(head, 'sc-' + tail)) + cat(env, source, target) + +env = Environment(BUILDERS={'Cat':Builder(action=cat)}, SUBDIR='sub') +env.SourceCode('$SUBDIR', Builder(action=sc_cat, env=env)) +env.Cat('aaa.out', 'sub/aaa.in') +bbb_in = File('sub/bbb.in') +bbb_in.is_derived() +env.Cat('bbb.out', bbb_in) +env.Cat('ccc.out', 'sub/ccc.in') +env.Cat('all', ['aaa.out', 'bbb.out', 'ccc.out']) +SConscript('sub/SConscript', "env") + +SourceCode('sub2', Builder(action=sc_cat, env=env)) +env.Cat('ddd.out', 'sub2/ddd.in') +""") + +test.write(['sub', 'sc-aaa.in'], "sub/sc-aaa.in\n") +test.write(['sub', 'sc-bbb.in'], "sub/sc-bbb.in\n") +test.write(['sub', 'sc-ccc.in'], "sub/sc-ccc.in\n") +test.write(['sub2', 'sc-ddd.in'], "sub2/sc-ddd.in\n") + +test.write(['sub', 'sc-SConscript'], "'sub/sc-SConscript'\n") + +read_str = """\ +sc_cat(["%s"], []) +""" % (os.path.join('sub', 'SConscript')) + +build_str = """\ +sc_cat(["%s"], []) +cat(["aaa.out"], ["%s"]) +sc_cat(["%s"], []) +cat(["bbb.out"], ["%s"]) +sc_cat(["%s"], []) +cat(["ccc.out"], ["%s"]) +cat(["all"], ["aaa.out", "bbb.out", "ccc.out"]) +sc_cat(["%s"], []) +cat(["ddd.out"], ["%s"]) +""" % (os.path.join('sub', 'aaa.in'), + os.path.join('sub', 'aaa.in'), + os.path.join('sub', 'bbb.in'), + os.path.join('sub', 'bbb.in'), + os.path.join('sub', 'ccc.in'), + os.path.join('sub', 'ccc.in'), + os.path.join('sub2', 'ddd.in'), + os.path.join('sub2', 'ddd.in')) + +stdout = TestSCons.re_escape(test.wrap_stdout(read_str = read_str, + build_str = build_str)) + +test.run(arguments = '.', stdout = stdout, stderr = 2*warning) + +test.must_match(['sub', 'SConscript'], "'sub/sc-SConscript'\n") +test.must_match('all', "sub/sc-aaa.in\nsub/sc-bbb.in\nsub/sc-ccc.in\n") +test.must_match('ddd.out', "sub2/sc-ddd.in\n") + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Removed/SourceCode/Old/sconstest.skip b/test/Removed/SourceCode/Old/sconstest.skip new file mode 100644 index 0000000..e69de29 diff --git a/test/Removed/SourceCode/README.md b/test/Removed/SourceCode/README.md new file mode 100644 index 0000000..c584dc9 --- /dev/null +++ b/test/Removed/SourceCode/README.md @@ -0,0 +1,6 @@ +SourceCode.py is the "new" test for SourceCode making sure we +get a NameError. + +The Old directory is the former tests from the deprecated state, +preserved here for reference; the presence of an scontest.skip file +means they are never executed. diff --git a/test/Removed/SourceCode/SConstruct.global b/test/Removed/SourceCode/SConstruct.global new file mode 100644 index 0000000..321fe7e --- /dev/null +++ b/test/Removed/SourceCode/SConstruct.global @@ -0,0 +1,2 @@ +DefaultEnvironment(tools=[]) +SourceCode('no_source.c', None) diff --git a/test/Removed/SourceCode/SConstruct.method b/test/Removed/SourceCode/SConstruct.method new file mode 100644 index 0000000..94a4916 --- /dev/null +++ b/test/Removed/SourceCode/SConstruct.method @@ -0,0 +1,3 @@ +DefaultEnvironment(tools=[]) +env = Environment(tools=["textfile"]) +env.SourceCode('no_source.c', None) diff --git a/test/Removed/SourceCode/SourceCode.py b/test/Removed/SourceCode/SourceCode.py new file mode 100644 index 0000000..30499af --- /dev/null +++ b/test/Removed/SourceCode/SourceCode.py @@ -0,0 +1,73 @@ +""" +NameError: name 'SourceCode' is not defined: + File "/tmp/testcmd.193317.nqan7rtg/SConstruct", line 4: + SConscript('SConscript') + File "/home/mats/github/scons/src/engine/SCons/Script/SConscript.py", line 660: + return method(*args, **kw) + File "/home/mats/github/scons/src/engine/SCons/Script/SConscript.py", line 597: + return _SConscript(self.fs, *files, **subst_kw) + File "/home/mats/github/scons/src/engine/SCons/Script/SConscript.py", line 286: + exec(compile(scriptdata, scriptname, 'exec'), call_stack[-1].globals) + File "/tmp/testcmd.193317.nqan7rtg/SConscript", line 2: + SourceCode('.', None) +""" +#!/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__" + +""" +Test the removed SourceCode() method errors out if used. +""" + +import os + +import TestSCons + +test = TestSCons.TestSCons(match=TestSCons.match_exact) + +test.subdir('src') + +test.file_fixture('SConstruct.global', 'SConstruct') +expect = """\ +NameError: name 'SourceCode' is not defined: + File "{}", line 2: + SourceCode('no_source.c', None) +""".format(test.workpath('SConstruct')) +test.run(arguments='-Q -s', status=2, stderr=expect) + +test.file_fixture('SConstruct.method', 'SConstruct') +expect = """\ +AttributeError: 'SConsEnvironment' object has no attribute 'SourceCode': + File "{}", line 3: + env.SourceCode('no_source.c', None) +""".format(test.workpath('SConstruct')) +test.run(arguments='-Q -s', status=2, stderr=expect) + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: -- cgit v0.12 From 1b177138a204de2000cc490a96050e54e4626166 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 20 Dec 2019 12:21:29 -0700 Subject: [PR #3506] fix sider complaint Signed-off-by: Mats Wichmann --- test/Removed/SourceCode/SourceCode.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/Removed/SourceCode/SourceCode.py b/test/Removed/SourceCode/SourceCode.py index 30499af..8ac54d4 100644 --- a/test/Removed/SourceCode/SourceCode.py +++ b/test/Removed/SourceCode/SourceCode.py @@ -40,8 +40,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" Test the removed SourceCode() method errors out if used. """ -import os - import TestSCons test = TestSCons.TestSCons(match=TestSCons.match_exact) -- cgit v0.12 From f6d44c83fc88a3feffa88f747c5cceb875453059 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 20 Dec 2019 12:52:01 -0700 Subject: [PR #3506] restore accidentally removed Split Oops! somehow removed an extra function block. Signed-off-by: Mats Wichmann --- src/engine/SCons/Environment.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 36b7c3d..2c80424 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -2199,6 +2199,27 @@ class Base(SubstitutionEnvironment): target.side_effects.append(side_effect) return side_effects + def Split(self, arg): + """This function converts a string or list into a list of strings + or Nodes. This makes things easier for users by allowing files to + be specified as a white-space separated list to be split. + + The input rules are: + - A single string containing names separated by spaces. These will be + split apart at the spaces. + - A single Node instance + - A list containing either strings or Node instances. Any strings + in the list are not split at spaces. + + In all cases, the function returns a list of Nodes and strings.""" + + if SCons.Util.is_List(arg): + return list(map(self.subst, arg)) + elif SCons.Util.is_String(arg): + return self.subst(arg).split() + else: + return [self.subst(arg)] + def Value(self, value, built_value=None): """ """ -- cgit v0.12 From c1d1e5492069b799a5e7a9689bf940d34b9a526a Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 20 Dec 2019 13:19:43 -0700 Subject: [PR #3506] fix remnamt docstring and speed up left a pasted traceback in the SourceCode.py test, got rid of. applied "standard" speedup of dropping tools in DefaultEnvironmment and Environment, speeds up windows a lot (individual Removed tests running in 1 sec instead of 15) Signed-off-by: Mats Wichmann --- test/Removed/BuildDir/BuildDir.py | 2 +- test/Removed/BuildDir/SConscript-build_dir.py | 2 +- test/Removed/BuildDir/SConstruct.global | 1 + test/Removed/BuildDir/SConstruct.kwarg | 1 + test/Removed/BuildDir/SConstruct.method | 4 ++-- test/Removed/Copy-Method/Copy-Method.py | 2 +- test/Removed/Copy-Method/SConstruct.method | 3 ++- test/Removed/SourceCode/SourceCode.py | 13 ------------- test/Removed/SourceSignatures/SConstruct.method | 1 + test/Removed/SourceSignatures/SConstruct.setopt | 1 + test/Removed/SourceSignatures/SourceSignatures.py | 2 +- test/Removed/TargetSignatures/SConstruct.method | 1 + test/Removed/TargetSignatures/SConstruct.setopt | 1 + test/Removed/TargetSignatures/TargetSignatures.py | 2 +- 14 files changed, 15 insertions(+), 21 deletions(-) diff --git a/test/Removed/BuildDir/BuildDir.py b/test/Removed/BuildDir/BuildDir.py index 43c8b8b..589b89a 100644 --- a/test/Removed/BuildDir/BuildDir.py +++ b/test/Removed/BuildDir/BuildDir.py @@ -38,7 +38,7 @@ test.subdir('src') test.file_fixture('SConstruct.global', 'SConstruct') expect = """\ NameError: name 'BuildDir' is not defined: - File "{}", line 1: + File "{}", line 2: BuildDir('build', 'src') """.format(test.workpath('SConstruct')) test.run(arguments='-Q -s', status=2, stderr=expect) diff --git a/test/Removed/BuildDir/SConscript-build_dir.py b/test/Removed/BuildDir/SConscript-build_dir.py index 5a8d1ca..77b6ee4 100644 --- a/test/Removed/BuildDir/SConscript-build_dir.py +++ b/test/Removed/BuildDir/SConscript-build_dir.py @@ -43,7 +43,7 @@ test.write(['src', 'SConscript'], """ # this doesn't work yet expect = """\ TypeError: SConscript() got an unexpected keyword argument 'build_dir': - File "{}", line 1: + File "{}", line 2: SConscript('src/SConscript', build_dir='build') """.format(test.workpath('SConstruct')) test.run(arguments='-Q -s', status=2, stderr=expect) diff --git a/test/Removed/BuildDir/SConstruct.global b/test/Removed/BuildDir/SConstruct.global index 086fbae..7dddf29 100644 --- a/test/Removed/BuildDir/SConstruct.global +++ b/test/Removed/BuildDir/SConstruct.global @@ -1 +1,2 @@ +DefaultEnvironment(tools=[]) BuildDir('build', 'src') diff --git a/test/Removed/BuildDir/SConstruct.kwarg b/test/Removed/BuildDir/SConstruct.kwarg index a5c46fb..2288669 100644 --- a/test/Removed/BuildDir/SConstruct.kwarg +++ b/test/Removed/BuildDir/SConstruct.kwarg @@ -1 +1,2 @@ +DefaultEnvironment(tools=[]) SConscript('src/SConscript', build_dir='build') diff --git a/test/Removed/BuildDir/SConstruct.method b/test/Removed/BuildDir/SConstruct.method index afea459..ddf2324 100644 --- a/test/Removed/BuildDir/SConstruct.method +++ b/test/Removed/BuildDir/SConstruct.method @@ -1,3 +1,3 @@ -env = Environment(BUILD='build', SRC='src') - +DefaultEnvironment(tools=[]) +env = Environment(BUILD='build', SRC='src', tools=[]) env.BuildDir('build', 'src') diff --git a/test/Removed/Copy-Method/Copy-Method.py b/test/Removed/Copy-Method/Copy-Method.py index bca10fe..4c7c386 100644 --- a/test/Removed/Copy-Method/Copy-Method.py +++ b/test/Removed/Copy-Method/Copy-Method.py @@ -35,7 +35,7 @@ test = TestSCons.TestSCons(match = TestSCons.match_re_dotall) test.file_fixture('SConstruct.method', 'SConstruct') expect = """\ AttributeError: 'SConsEnvironment' object has no attribute 'Copy': - File "{}", line 2: + File "{}", line 3: env.Copy() """.format(test.workpath('SConstruct')) test.run(arguments='-Q -s', status=2, stderr=expect, match=TestSCons.match_exact) diff --git a/test/Removed/Copy-Method/SConstruct.method b/test/Removed/Copy-Method/SConstruct.method index 99737e1..5a59bd6 100644 --- a/test/Removed/Copy-Method/SConstruct.method +++ b/test/Removed/Copy-Method/SConstruct.method @@ -1,2 +1,3 @@ -env = Environment() +DefaultEnvironment(tools=[]) +env = Environment(tools=["textfile"]) env.Copy() diff --git a/test/Removed/SourceCode/SourceCode.py b/test/Removed/SourceCode/SourceCode.py index 8ac54d4..f586ef6 100644 --- a/test/Removed/SourceCode/SourceCode.py +++ b/test/Removed/SourceCode/SourceCode.py @@ -1,16 +1,3 @@ -""" -NameError: name 'SourceCode' is not defined: - File "/tmp/testcmd.193317.nqan7rtg/SConstruct", line 4: - SConscript('SConscript') - File "/home/mats/github/scons/src/engine/SCons/Script/SConscript.py", line 660: - return method(*args, **kw) - File "/home/mats/github/scons/src/engine/SCons/Script/SConscript.py", line 597: - return _SConscript(self.fs, *files, **subst_kw) - File "/home/mats/github/scons/src/engine/SCons/Script/SConscript.py", line 286: - exec(compile(scriptdata, scriptname, 'exec'), call_stack[-1].globals) - File "/tmp/testcmd.193317.nqan7rtg/SConscript", line 2: - SourceCode('.', None) -""" #!/usr/bin/env python # # __COPYRIGHT__ diff --git a/test/Removed/SourceSignatures/SConstruct.method b/test/Removed/SourceSignatures/SConstruct.method index e68d6bf..99ef2d2 100644 --- a/test/Removed/SourceSignatures/SConstruct.method +++ b/test/Removed/SourceSignatures/SConstruct.method @@ -1 +1,2 @@ +DefaultEnvironment(tools=[]) SourceSignatures('MD5') diff --git a/test/Removed/SourceSignatures/SConstruct.setopt b/test/Removed/SourceSignatures/SConstruct.setopt index 6e1161f..f4b278e 100644 --- a/test/Removed/SourceSignatures/SConstruct.setopt +++ b/test/Removed/SourceSignatures/SConstruct.setopt @@ -1 +1,2 @@ +DefaultEnvironment(tools=[]) SetOption('warn', 'deprecated-source-signatures') diff --git a/test/Removed/SourceSignatures/SourceSignatures.py b/test/Removed/SourceSignatures/SourceSignatures.py index 014c163..04d2ed7 100644 --- a/test/Removed/SourceSignatures/SourceSignatures.py +++ b/test/Removed/SourceSignatures/SourceSignatures.py @@ -36,7 +36,7 @@ test = TestSCons.TestSCons() test.file_fixture('SConstruct.method', 'SConstruct') expect = """\ NameError: name 'SourceSignatures' is not defined: - File "{}", line 1: + File "{}", line 2: SourceSignatures('MD5') """.format(test.workpath('SConstruct')) test.run(arguments='-Q -s', status=2, stdout=None, stderr=expect) diff --git a/test/Removed/TargetSignatures/SConstruct.method b/test/Removed/TargetSignatures/SConstruct.method index 5e974b6..9f82f9b 100644 --- a/test/Removed/TargetSignatures/SConstruct.method +++ b/test/Removed/TargetSignatures/SConstruct.method @@ -1 +1,2 @@ +DefaultEnvironment(tools=[]) TargetSignatures('MD5') diff --git a/test/Removed/TargetSignatures/SConstruct.setopt b/test/Removed/TargetSignatures/SConstruct.setopt index c887ce4..5576ba8 100644 --- a/test/Removed/TargetSignatures/SConstruct.setopt +++ b/test/Removed/TargetSignatures/SConstruct.setopt @@ -1 +1,2 @@ +DefaultEnvironment(tools=[]) SetOption('warn', 'deprecated-target-signatures') diff --git a/test/Removed/TargetSignatures/TargetSignatures.py b/test/Removed/TargetSignatures/TargetSignatures.py index 889f992..edd60a2 100644 --- a/test/Removed/TargetSignatures/TargetSignatures.py +++ b/test/Removed/TargetSignatures/TargetSignatures.py @@ -36,7 +36,7 @@ test = TestSCons.TestSCons() test.file_fixture('SConstruct.method', 'SConstruct') expect = """\ NameError: name 'TargetSignatures' is not defined: - File "{}", line 1: + File "{}", line 2: TargetSignatures('MD5') """.format(test.workpath('SConstruct')) test.run(arguments='-Q -s', status=2, stdout=None, stderr=expect) -- 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 c73104adc3624503764ff4585b8ba22b62ee4c3b Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sat, 21 Dec 2019 07:12:38 -0700 Subject: Fix two small syntax errors in string formatting Signed-off-by: Mats Wichmann --- src/CHANGES.txt | 1 + src/engine/SCons/Tool/install.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 79a65fb..87980a8 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -15,6 +15,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER From Mats Wichmann: - Remove deprecated SourceCode + - str.format syntax errors fixed RELEASE 3.1.2 - Mon, 17 Dec 2019 02:06:27 +0000 diff --git a/src/engine/SCons/Tool/install.py b/src/engine/SCons/Tool/install.py index c0a193b..dcb3581 100644 --- a/src/engine/SCons/Tool/install.py +++ b/src/engine/SCons/Tool/install.py @@ -168,7 +168,7 @@ def installShlibLinks(dest, source, env): Verbose = False symlinks = listShlibLinksToInstall(dest, source, env) if Verbose: - print('installShlibLinks: symlinks={:r}'.format(SCons.Tool.StringizeLibSymlinks(symlinks))) + print('installShlibLinks: symlinks={!r}'.format(SCons.Tool.StringizeLibSymlinks(symlinks))) if symlinks: SCons.Tool.CreateLibSymlinks(env, symlinks) return @@ -244,7 +244,7 @@ def add_versioned_targets_to_INSTALLED_FILES(target, source, env): Verbose = False _INSTALLED_FILES.extend(target) if Verbose: - print("add_versioned_targets_to_INSTALLED_FILES: target={:r}".format(list(map(str, target)))) + print("add_versioned_targets_to_INSTALLED_FILES: target={!r}".format(list(map(str, target)))) symlinks = listShlibLinksToInstall(target[0], source, env) if symlinks: SCons.Tool.EmitLibSymlinks(env, symlinks, target[0]) -- 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 07590772d7a87fbfa29d77f64d23fd599b719485 Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Fri, 10 Jan 2020 12:32:15 -0500 Subject: Update scanning code to get it closer to desired state Changes: 1. Remove repository code. 2. Only use env.WhereIs() if it's the first entry in a group. 3. Avoid duplicate sources if they are in another variable (e.g. LIBS). --- src/engine/SCons/Action.py | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index ef99a4d..6edaa05 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -1013,11 +1013,12 @@ class CommandAction(_ActionAction): # target, or executor to subst_list. This causes references to # $SOURCES, $TARGETS, and all related variables to disappear. from SCons.Subst import SUBST_SIG - cmd_list = env.subst_list(self.cmd_list, SUBST_SIG) + cmd_list = env.subst_list(self.cmd_list, SUBST_SIG, conv=lambda x: x) res = [] for cmd_line in cmd_list: if cmd_line: + is_first_entry = True for entry in cmd_line: d = str(entry) if not d.startswith(('&', '-', '/') if os.name == 'nt' @@ -1026,25 +1027,27 @@ class CommandAction(_ActionAction): if m: d = m.group(1) - # For now, only match files, not directories. - p = os.path.abspath(d) if os.path.isfile(d) else \ - env.WhereIs(d) - if p: - res.append(env.fs.File(p)) - else: - # Try to find the dependency in any source - # repositories. - # - # TODO: I want to enumerate get_all_rdirs() and am - # not sure whether I want to enumerate - # srcdir_list(). srcdir_find_file() does both. Is - # that bad? Should we instead change env.WhereIs() - # to search in repositories too? - n, _ = env.fs.Top.srcdir_find_file(d) - if n and n not in target and n not in source: - res.append(n) + if d: + # Resolve the first entry in the command string using + # PATH, which env.WhereIs() looks in. + # For now, only match files, not directories. + p = os.path.abspath(d) if os.path.isfile(d) else None + if not p and is_first_entry: + p = env.WhereIs(d) - return res + if p: + res.append(env.fs.File(p)) + + is_first_entry = False + else: + is_first_entry = d == '&&' + + # Despite not providing source and target to env.subst() above, we + # can still end up with sources in this list. For example, files in + # LIBS will still resolve in env.subst(). This won't result in + # circular dependencies, but it causes problems with cache signatures + # changing between full and incremental builds. + return [r for r in res if r not in target and r not in source] class CommandGeneratorAction(ActionBase): -- 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 df23cffb83106a243f762258aa645edc86f05779 Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Sat, 11 Jan 2020 20:51:40 -0500 Subject: Address review feedback --- src/CHANGES.txt | 4 +++- src/engine/SCons/Action.xml | 21 +++++++++++++++++++++ test/Batch/CHANGED_SOURCES.py | 5 +---- test/Depends/Depends.py | 6 +----- test/ParseDepends.py | 5 +---- test/Repository/link-object.py | 6 ------ 6 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index d2453ab..53f4d48 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -18,7 +18,9 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER From Adam Gross: - Added support for scanning multiple entries in an action string if - implicit command dependency scanning is enabled. + IMPLICIT_COMMAND_DEPENDENCIES is set to 2. This opts into more thorough + action scanning where every string in the command is scanned to determine + if it is a non-source and non-target path. From Mathew Robinson: - Improve performance of Subst by preventing unnecessary frame diff --git a/src/engine/SCons/Action.xml b/src/engine/SCons/Action.xml index 7a8194e..f10bf03 100644 --- a/src/engine/SCons/Action.xml +++ b/src/engine/SCons/Action.xml @@ -58,6 +58,27 @@ not be added to the targets built with that construction environment. + +If the construction variable +&cv-IMPLICIT_COMMAND_DEPENDENCIES; +is set to 2, then +all entries in all command strings will be +scanned for relative or absolute paths. If +any are present, they will be added as +implicit dependencies to the targets built +with that construction environment. +not be added to the targets built with that +construction environment. The first command +in the action string and the first after any +&& entries will be found +by searching the PATH +variable in the ENV +environment used to execute the command. +All other commands will only be found if they +are absolute paths or valid paths relative +to the working directory. + + env = Environment(IMPLICIT_COMMAND_DEPENDENCIES = 0) diff --git a/test/Batch/CHANGED_SOURCES.py b/test/Batch/CHANGED_SOURCES.py index b54bd2e..477869f 100644 --- a/test/Batch/CHANGED_SOURCES.py +++ b/test/Batch/CHANGED_SOURCES.py @@ -48,11 +48,8 @@ for infile in sys.argv[2:]: sys.exit(0) """) -# Disable IMPLICIT_COMMAND_DEPENDENCIES because otherwise it renders them less -# effective. They count on paths provided at the end of the command string only -# being counted as dependencies if Depends() is used. test.write('SConstruct', """ -env = Environment(IMPLICIT_COMMAND_DEPENDENCIES=False) +env = Environment() env['BATCH_BUILD'] = 'batch_build.py' env['BATCHCOM'] = r'%(_python_)s $BATCH_BUILD ${TARGET.dir} $CHANGED_SOURCES' bb = Action('$BATCHCOM', batch_key=True, targets='CHANGED_TARGETS') diff --git a/test/Depends/Depends.py b/test/Depends/Depends.py index 51737a7..3ed9e12 100644 --- a/test/Depends/Depends.py +++ b/test/Depends/Depends.py @@ -50,15 +50,11 @@ sys.exit(0) SUBDIR_foo_dep = os.path.join('$SUBDIR', 'foo.dep') SUBDIR_f3_out = os.path.join('$SUBDIR', 'f3.out') -# Disable IMPLICIT_COMMAND_DEPENDENCIES because otherwise it renders them less -# effective. They count on paths provided at the end of the command string only -# being counted as dependencies if Depends() is used. test.write('SConstruct', """ DefaultEnvironment(tools=[]) Foo = Builder(action = r'%(_python_)s build.py $TARGET $SOURCES subdir/foo.dep') Bar = Builder(action = r'%(_python_)s build.py $TARGET $SOURCES subdir/bar.dep') -env = Environment(tools=[], BUILDERS = { 'Foo' : Foo, 'Bar' : Bar }, SUBDIR='subdir', - IMPLICIT_COMMAND_DEPENDENCIES=False) +env = Environment(tools=[], BUILDERS = { 'Foo' : Foo, 'Bar' : Bar }, SUBDIR='subdir') env.Depends(target = ['f1.out', 'f2.out'], dependency = r'%(SUBDIR_foo_dep)s') env.Depends(target = r'%(SUBDIR_f3_out)s', dependency = 'subdir/bar.dep') env.Foo(target = 'f1.out', source = 'f1.in') diff --git a/test/ParseDepends.py b/test/ParseDepends.py index aa15fc9..2de2105 100644 --- a/test/ParseDepends.py +++ b/test/ParseDepends.py @@ -40,13 +40,10 @@ with open(sys.argv[1], 'wb') as f, open(sys.argv[2], 'rb') as afp2, open(sys.arg f.write(afp2.read() + afp3.read()) """) -# Pass IMPLICIT_COMMAND_DEPENDENCIES=False because the test depends on us not -# taking a dependency on the last file in the action string. test.write('SConstruct', """ Foo = Builder(action = r'%(_python_)s build.py $TARGET $SOURCES subdir/foo.dep') Bar = Builder(action = r'%(_python_)s build.py $TARGET $SOURCES subdir/bar.dep') -env = Environment(BUILDERS = { 'Foo' : Foo, 'Bar' : Bar }, SUBDIR='subdir', - IMPLICIT_COMMAND_DEPENDENCIES=False) +env = Environment(BUILDERS = { 'Foo' : Foo, 'Bar' : Bar }, SUBDIR='subdir') env.ParseDepends('foo.d') env.ParseDepends('bar.d') env.Foo(target = 'f1.out', source = 'f1.in') diff --git a/test/Repository/link-object.py b/test/Repository/link-object.py index f5bf783..78add90 100644 --- a/test/Repository/link-object.py +++ b/test/Repository/link-object.py @@ -44,13 +44,7 @@ workpath_repository = test.workpath('repository') repository_foo = test.workpath('repository', 'foo' + _exe) work_foo = test.workpath('work', 'foo' + _exe) -# Don't take implicit command dependencies because otherwise the program will -# be unexpectedly recompiled the first time we use chdir="work". The reason is -# that we take .obj files as implicit dependencies but when we move the current -# directory, those .obj files are no longer around. # -# TODO: Should this test pass as-is without disabling implicit command -# dependencies? test.write(['repository', 'SConstruct'], """ Repository(r'%s') env = Environment() -- cgit v0.12 From 420f23129a3eb298e20e2250f97eb8eefdd923d4 Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Mon, 13 Jan 2020 13:41:28 -0500 Subject: Change IMPLICIT_COMMAND_DEPENDENCIES meaning as requested in PR --- src/engine/SCons/Action.py | 48 +++++++++++++++++++++----- src/engine/SCons/Action.xml | 20 ++++++++++- test/Repository/Program.py | 2 +- test/Repository/StaticLibrary.py | 2 +- test/implicit/IMPLICIT_COMMAND_DEPENDENCIES.py | 38 ++++++++++++-------- 5 files changed, 84 insertions(+), 26 deletions(-) diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index 6edaa05..3f5e4b8 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -976,6 +976,7 @@ class CommandAction(_ActionAction): return env.subst_target_source(cmd, SUBST_SIG, target, source) def get_implicit_deps(self, target, source, env, executor=None): + """Return the implicit dependencies of this action's command line.""" icd = env.get('IMPLICIT_COMMAND_DEPENDENCIES', True) if is_String(icd) and icd[:1] == '$': icd = env.subst(icd) @@ -983,14 +984,25 @@ class CommandAction(_ActionAction): if not icd or icd in ('0', 'None'): return [] - if icd in ['2', 2]: - return self._get_implicit_deps_heavyweight(target, source, env, executor) + try: + icd_int = int(icd) + except ValueError: + icd_int = None + + if (icd_int and icd_int > 1) or icd == 'all': + # An integer value greater than 1 specifies the number of entries + # to scan. "all" means to scan all. + return self._get_implicit_deps_heavyweight(target, source, env, executor, icd_int) else: # Everything else (usually 1 or True) means that we want # lightweight dependency scanning. return self._get_implicit_deps_lightweight(target, source, env, executor) def _get_implicit_deps_lightweight(self, target, source, env, executor): + """ + Lightweight dependency scanning involves only scanning the first entry + in an action string, even if it contains &&. + """ from SCons.Subst import SUBST_SIG if executor: cmd_list = env.subst_list(self.cmd_list, SUBST_SIG, executor=executor) @@ -1008,7 +1020,24 @@ class CommandAction(_ActionAction): res.append(env.fs.File(d)) return res - def _get_implicit_deps_heavyweight(self, target, source, env, executor): + def _get_implicit_deps_heavyweight(self, target, source, env, executor, + icd_int): + """ + Heavyweight dependency scanning involves scanning more than just the + first entry in an action string. The exact behavior depends on the + value of icd_int. Only files are taken as implicit dependencies; + directories are ignored. + + If icd_int is an integer value, it specifies the number of entries to + scan for implicit dependencies. Action strings are also scanned after + a &&. So for example, if icd_int=2 and the action string is + "cd && $PYTHON $SCRIPT_PATH ", the implicit + dependencies would be the path to the python binary and the path to the + script. + + If icd_int is None, all entries are scanned for implicit dependencies. + """ + # Avoid circular and duplicate dependencies by not providing source, # target, or executor to subst_list. This causes references to # $SOURCES, $TARGETS, and all related variables to disappear. @@ -1018,11 +1047,12 @@ class CommandAction(_ActionAction): for cmd_line in cmd_list: if cmd_line: - is_first_entry = True + entry_count = 0 for entry in cmd_line: d = str(entry) - if not d.startswith(('&', '-', '/') if os.name == 'nt' - else ('&', '-')): + if ((icd_int is None or entry_count < icd_int) and + not d.startswith(('&', '-', '/') if os.name == 'nt' + else ('&', '-'))): m = strip_quotes.match(d) if m: d = m.group(1) @@ -1032,15 +1062,15 @@ class CommandAction(_ActionAction): # PATH, which env.WhereIs() looks in. # For now, only match files, not directories. p = os.path.abspath(d) if os.path.isfile(d) else None - if not p and is_first_entry: + if not p and entry_count == 0: p = env.WhereIs(d) if p: res.append(env.fs.File(p)) - is_first_entry = False + entry_count = entry_count + 1 else: - is_first_entry = d == '&&' + entry_count = 0 if d == '&&' else entry_count + 1 # Despite not providing source and target to env.subst() above, we # can still end up with sources in this list. For example, files in diff --git a/src/engine/SCons/Action.xml b/src/engine/SCons/Action.xml index f10bf03..d85af3b 100644 --- a/src/engine/SCons/Action.xml +++ b/src/engine/SCons/Action.xml @@ -61,7 +61,25 @@ built with that construction environment. If the construction variable &cv-IMPLICIT_COMMAND_DEPENDENCIES; -is set to 2, then +is set to 2 or higher, +then that number of entries in the command +string will be scanned for relative or absolute +paths. The count will reset after any +&& entries are found. +The first command in the action string and +the first after any && +entries will be found by searching the +PATH variable in the +ENV environment used to +execute the command. All other commands will +only be found if they are absolute paths or +valid paths relative to the working directory. + + + +If the construction variable +&cv-IMPLICIT_COMMAND_DEPENDENCIES; +is set to all, then all entries in all command strings will be scanned for relative or absolute paths. If any are present, they will be added as diff --git a/test/Repository/Program.py b/test/Repository/Program.py index 9260ae9..9e8af77 100644 --- a/test/Repository/Program.py +++ b/test/Repository/Program.py @@ -32,7 +32,7 @@ if sys.platform == 'win32': else: _exe = '' -for implicit_deps in ['0', '1', '2']: +for implicit_deps in ['0', '1', '2', 'all']: # First, test a single repository. test = TestSCons.TestSCons() test.subdir('repository', 'work1') diff --git a/test/Repository/StaticLibrary.py b/test/Repository/StaticLibrary.py index d619bb3..acd4b83 100644 --- a/test/Repository/StaticLibrary.py +++ b/test/Repository/StaticLibrary.py @@ -30,7 +30,7 @@ import TestSCons _obj = TestSCons._obj _exe = TestSCons._exe -for implicit_deps in ['0', '1', '2']: +for implicit_deps in ['0', '1', '2', 'all']: test = TestSCons.TestSCons() # diff --git a/test/implicit/IMPLICIT_COMMAND_DEPENDENCIES.py b/test/implicit/IMPLICIT_COMMAND_DEPENDENCIES.py index bec9223..bec2255 100644 --- a/test/implicit/IMPLICIT_COMMAND_DEPENDENCIES.py +++ b/test/implicit/IMPLICIT_COMMAND_DEPENDENCIES.py @@ -83,6 +83,7 @@ env.PrependENVPath('PATHEXT', '.PY') env0 = env.Clone(IMPLICIT_COMMAND_DEPENDENCIES = 0) env1 = env.Clone(IMPLICIT_COMMAND_DEPENDENCIES = 1) env2 = env.Clone(IMPLICIT_COMMAND_DEPENDENCIES = 2) +envAll = env.Clone(IMPLICIT_COMMAND_DEPENDENCIES = 'all') envNone = env.Clone(IMPLICIT_COMMAND_DEPENDENCIES = None) envFalse = env.Clone(IMPLICIT_COMMAND_DEPENDENCIES = False) envTrue = env.Clone(IMPLICIT_COMMAND_DEPENDENCIES = True) @@ -94,12 +95,15 @@ env.BuildFile('file.out', 'file.in') env0.BuildFile('file0.out', 'file.in') env1.BuildFile('file1.out', 'file.in') env2.BuildFile('file2.out', 'file.in') +envAll.BuildFile('fileall.out', 'file.in') envNone.BuildFile('fileNone.out', 'file.in') envFalse.BuildFile('fileFalse.out', 'file.in') envTrue.BuildFile('fileTrue.out', 'file.in') envTrue.BuildFile('fileQuote.out', 'file.in', BUILD_PY='"build.py"') -env2.CdAndBuildFile('cd_file.out', 'file.in') +env1.CdAndBuildFile('cd_file1.out', 'file.in') +env2.CdAndBuildFile('cd_file2.out', 'file.in') +envAll.CdAndBuildFile('cd_fileall.out', 'file.in') """ % locals()) @@ -113,25 +117,31 @@ def run_test(extra, python, _python_): # Run the SConscript file. test.run(arguments = '--tree=all .') - # Generate some expected data, which depends on the value of "extra". - expect_none = 'build.py %s file.in\nfile.in\n' - expect_extra = (expect_none if not extra else + # Generate some expected data of actions involving build.py. This expected + # data depends on the value of "extra". + build_none = 'build.py %s file.in\nfile.in\n' + build_extra = (build_none if not extra else 'build.py %s file.in\n{}file.in\n'.format( extra.replace('\\\\n', '\n'))) - expect_extra_abs = '{} %s file.in\n{}file.in\n'.format( + build_extra_abs = '{} %s file.in\n{}file.in\n'.format( test.workpath('build.py'), extra.replace('\\\\n', '\n')) + empty_none = 'empty.py %s file.in\nfile.in\n' + # Verify that the output matches what is expected. - test.must_match('file.out', expect_none % 'file.out', mode='r') - test.must_match('file0.out', expect_none % 'file0.out', mode='r') - test.must_match('file1.out', expect_none % 'file1.out', mode='r') - test.must_match('file2.out', expect_extra % 'file2.out', mode='r') - test.must_match('fileNone.out', expect_none % 'fileNone.out', mode='r') - test.must_match('fileFalse.out', expect_none % 'fileFalse.out', mode='r') - test.must_match('fileTrue.out', expect_none % 'fileTrue.out', mode='r') - test.must_match('fileQuote.out', expect_none % 'fileQuote.out', mode='r') - test.must_match('cd_file.out', expect_extra % 'cd_file.out', mode='r') + test.must_match('file.out', build_none % 'file.out', mode='r') + test.must_match('file0.out', build_none % 'file0.out', mode='r') + test.must_match('file1.out', build_none % 'file1.out', mode='r') + test.must_match('file2.out', build_extra % 'file2.out', mode='r') + test.must_match('fileall.out', build_extra % 'fileall.out', mode='r') + test.must_match('fileNone.out', build_none % 'fileNone.out', mode='r') + test.must_match('fileFalse.out', build_none % 'fileFalse.out', mode='r') + test.must_match('fileTrue.out', build_none % 'fileTrue.out', mode='r') + test.must_match('fileQuote.out', build_none % 'fileQuote.out', mode='r') + test.must_match('cd_file1.out', build_none % 'cd_file1.out', mode='r') + test.must_match('cd_file2.out', build_extra % 'cd_file2.out', mode='r') + test.must_match('cd_fileall.out', build_extra % 'cd_fileall.out', mode='r') run_test('', python, _python_) -- 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 4f5bb72605c6163c1bb32c9ceceee5bd168728b8 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Tue, 11 Feb 2020 08:52:35 -0700 Subject: Update Script/Main.py so it uses importlib instead of deprecated imp module. import site_init.py file directly for Py3 Find spec for the site file by path rather than by fiddling sys.path to restrict the search. Py3: address the problem that we might get a "site_init.py" from somewhere else in sys.path. Clean up excess indentation / try nesting; adjust comment. Signed-off-by: Mats Wichmann --- src/CHANGES.txt | 3 + src/engine/SCons/Script/Main.py | 142 +++++++++++++++++++++++----------------- 2 files changed, 86 insertions(+), 59 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 407a83b..5093462 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -150,6 +150,9 @@ RELEASE 3.1.1 - Mon, 07 Aug 2019 20:09:12 -0500 - JSON encoding errors for CacheDir config - JSON decoding errors for CacheDir config + From Mats Wichmann: + - Script/Main.py now uses importlib in the PY3 case. + RELEASE 3.1.0 - Mon, 20 Jul 2019 16:59:23 -0700 diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py index a0d7f4c..24bb94d 100644 --- a/src/engine/SCons/Script/Main.py +++ b/src/engine/SCons/Script/Main.py @@ -64,8 +64,8 @@ import SCons.SConf import SCons.Script import SCons.Taskmaster import SCons.Util +from SCons.Util import PY3 import SCons.Warnings - import SCons.Script.Interactive # Global variables @@ -698,80 +698,104 @@ def _create_path(plist): return path def _load_site_scons_dir(topdir, site_dir_name=None): - """Load the site_scons dir under topdir. - Prepends site_scons to sys.path, imports site_scons/site_init.py, - and prepends site_scons/site_tools to default toolpath.""" + """Load the site directory under topdir. + + If a site dir name is supplied use it, else use default "site_scons" + Prepend site dir to sys.path. + If a "site_tools" subdir exists, prepend to toolpath. + Import "site_init.py" from site dir if it exists. + """ if site_dir_name: err_if_not_found = True # user specified: err if missing else: site_dir_name = "site_scons" - err_if_not_found = False - + err_if_not_found = False # scons default: okay to be missing site_dir = os.path.join(topdir, site_dir_name) + if not os.path.exists(site_dir): if err_if_not_found: - raise SCons.Errors.UserError("site dir %s not found."%site_dir) + raise SCons.Errors.UserError("site dir %s not found." % site_dir) return + sys.path.insert(0, os.path.abspath(site_dir)) site_init_filename = "site_init.py" site_init_modname = "site_init" site_tools_dirname = "site_tools" - # prepend to sys.path - sys.path = [os.path.abspath(site_dir)] + sys.path site_init_file = os.path.join(site_dir, site_init_filename) site_tools_dir = os.path.join(site_dir, site_tools_dirname) - if os.path.exists(site_init_file): - import imp, re - try: - try: - fp, pathname, description = imp.find_module(site_init_modname, - [site_dir]) - # Load the file into SCons.Script namespace. This is - # opaque and clever; m is the module object for the - # SCons.Script module, and the exec ... in call executes a - # file (or string containing code) in the context of the - # module's dictionary, so anything that code defines ends - # up adding to that module. This is really short, but all - # the error checking makes it longer. - try: - m = sys.modules['SCons.Script'] - except Exception as e: - fmt = 'cannot import site_init.py: missing SCons.Script module %s' - raise SCons.Errors.InternalError(fmt % repr(e)) - try: - sfx = description[0] - modname = os.path.basename(pathname)[:-len(sfx)] - site_m = {"__file__": pathname, "__name__": modname, "__doc__": None} - re_special = re.compile("__[^_]+__") - for k, v in m.__dict__.items(): - if not re_special.match(k): - site_m[k] = v - - # This is the magic. - exec(compile(fp.read(), fp.name, 'exec'), site_m) - except KeyboardInterrupt: - raise - except Exception as e: - fmt = '*** Error loading site_init file %s:\n' - sys.stderr.write(fmt % repr(site_init_file)) - raise - else: - for k in site_m: - if not re_special.match(k): - m.__dict__[k] = site_m[k] - except KeyboardInterrupt: - raise - except ImportError as e: - fmt = '*** cannot import site init file %s:\n' - sys.stderr.write(fmt % repr(site_init_file)) - raise - finally: - if fp: - fp.close() + if os.path.exists(site_tools_dir): - # prepend to DefaultToolpath SCons.Tool.DefaultToolpath.insert(0, os.path.abspath(site_tools_dir)) + if not os.path.exists(site_init_file): + return + + if PY3: + import importlib.util + else: + import imp + import re + + # "import" the site_init.py file into the SCons.Script namespace. + # This is a variant on the basic Python import flow in that the globals + # dict for the compile step is prepopulated from the SCons.Script + # module object; on success the SCons.Script globals are refilled + # from the site_init globals so it all appears in SCons.Script + # instead of as a separate module. + try: + try: + m = sys.modules['SCons.Script'] + except KeyError: + fmt = 'cannot import {}: missing SCons.Script module' + raise SCons.Errors.InternalError(fmt.format(site_init_file)) + + if PY3: + spec = importlib.util.spec_from_file_location(site_init_modname, + site_init_file) + fp = open(spec.origin, 'r') + site_m = {"__file__": spec.origin, + "__name__": spec.name, + "__doc__": None} + else: + fp, pathname, description = imp.find_module(site_init_modname, + [site_dir]) + sfx = description[0] + modname = os.path.basename(pathname)[:-len(sfx)] + site_m = {"__file__": pathname, + "__name__": modname, + "__doc__": None} + + re_dunder = re.compile(r"__[^_]+__") + for k, v in m.__dict__.items(): + if not re_dunder.match(k): + site_m[k] = v + + try: + codeobj = compile(fp.read(), fp.name, 'exec') + exec(codeobj, site_m) + except KeyboardInterrupt: + raise + except Exception: + fmt = '*** Error loading site_init file %s:\n' + sys.stderr.write(fmt % repr(site_init_file)) + raise + else: + for k, v in site_m.items(): + if not re_dunder.match(k): + m.__dict__[k] = v + + except KeyboardInterrupt: + raise + except Exception: + fmt = '*** cannot import site init file %s:\n' + sys.stderr.write(fmt % repr(site_init_file)) + raise + finally: + try: + fp.close() + except Exception: + pass + def _load_all_site_scons_dirs(topdir, verbose=None): """Load all of the predefined site_scons dir. Order is significant; we load them in order from most generic @@ -810,7 +834,7 @@ def _load_all_site_scons_dirs(topdir, verbose=None): sysdirs=['/usr/share/scons', homedir('.scons')] - dirs=sysdirs + [topdir] + dirs = sysdirs + [topdir] for d in dirs: if verbose: # this is used by unit tests. print("Loading site dir ", d) -- 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 82df07778ae85895266897bac7ea5f434183eb4f Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Tue, 11 Feb 2020 09:23:06 -0700 Subject: Drop Python2 support from Main.py site_dir code Also simplify cleanup a bit - we don't need to leave the site file open, can use a context manager to read the code and let it close there. Signed-off-by: Mats Wichmann --- src/CHANGES.txt | 4 +--- src/engine/SCons/Script/Main.py | 52 ++++++++++++++--------------------------- 2 files changed, 19 insertions(+), 37 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 5093462..d1c5f3b 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. + - Script/Main.py now uses importlib instead of imp module. RELEASE 3.1.2 - Mon, 17 Dec 2019 02:06:27 +0000 @@ -150,9 +151,6 @@ RELEASE 3.1.1 - Mon, 07 Aug 2019 20:09:12 -0500 - JSON encoding errors for CacheDir config - JSON decoding errors for CacheDir config - From Mats Wichmann: - - Script/Main.py now uses importlib in the PY3 case. - RELEASE 3.1.0 - Mon, 20 Jul 2019 16:59:23 -0700 diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py index 24bb94d..59401cc 100644 --- a/src/engine/SCons/Script/Main.py +++ b/src/engine/SCons/Script/Main.py @@ -43,7 +43,9 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import SCons.compat +import importlib.util import os +import re import sys import time import traceback @@ -64,7 +66,6 @@ import SCons.SConf import SCons.Script import SCons.Taskmaster import SCons.Util -from SCons.Util import PY3 import SCons.Warnings import SCons.Script.Interactive @@ -730,12 +731,6 @@ def _load_site_scons_dir(topdir, site_dir_name=None): if not os.path.exists(site_init_file): return - if PY3: - import importlib.util - else: - import imp - import re - # "import" the site_init.py file into the SCons.Script namespace. # This is a variant on the basic Python import flow in that the globals # dict for the compile step is prepopulated from the SCons.Script @@ -749,52 +744,41 @@ def _load_site_scons_dir(topdir, site_dir_name=None): fmt = 'cannot import {}: missing SCons.Script module' raise SCons.Errors.InternalError(fmt.format(site_init_file)) - if PY3: - spec = importlib.util.spec_from_file_location(site_init_modname, - site_init_file) - fp = open(spec.origin, 'r') - site_m = {"__file__": spec.origin, - "__name__": spec.name, - "__doc__": None} - else: - fp, pathname, description = imp.find_module(site_init_modname, - [site_dir]) - sfx = description[0] - modname = os.path.basename(pathname)[:-len(sfx)] - site_m = {"__file__": pathname, - "__name__": modname, - "__doc__": None} - + spec = importlib.util.spec_from_file_location(site_init_modname, site_init_file) + site_m = { + "__file__": spec.origin, + "__name__": spec.name, + "__doc__": None, + } re_dunder = re.compile(r"__[^_]+__") + # update site dict with all but magic (dunder) methods for k, v in m.__dict__.items(): if not re_dunder.match(k): site_m[k] = v + with open(spec.origin, 'r') as f: + code = f.read() try: - codeobj = compile(fp.read(), fp.name, 'exec') + codeobj = compile(code, spec.name, "exec") exec(codeobj, site_m) except KeyboardInterrupt: raise except Exception: - fmt = '*** Error loading site_init file %s:\n' - sys.stderr.write(fmt % repr(site_init_file)) + fmt = "*** Error loading site_init file {}:\n" + sys.stderr.write(fmt.format(site_init_file)) raise else: + # now refill globals with site_init's symbols for k, v in site_m.items(): if not re_dunder.match(k): m.__dict__[k] = v - except KeyboardInterrupt: raise except Exception: - fmt = '*** cannot import site init file %s:\n' - sys.stderr.write(fmt % repr(site_init_file)) + fmt = "*** cannot import site init file {}:\n" + sys.stderr.write(fmt.format(site_init_file)) raise - finally: - try: - fp.close() - except Exception: - pass + def _load_all_site_scons_dirs(topdir, verbose=None): """Load all of the predefined site_scons dir. -- 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 From 4814146dc3f69729e22f89078a5783a82e9df039 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Wed, 29 Jan 2020 12:37:08 -0700 Subject: test cleanups: use harness python In a few places, a command line was built to execute a wrapper script written in Python, but the Python used was not the one used to invoke the test run (which is made available by TestSCons), but the result of running test.where_is('python'). On a system which still has the thing named 'python' resolve to Python 2, this fails, through no fault of scons itself. The two fixture wrapper scripts used occasionally by the tests used subprocess.call; this is considered "old" though not marked as deprecated at this time. Switched to subprocess.run. See: https://docs.python.org/3/library/subprocess.html#older-high-level-api One of these scripts was doing unnecessary bytes-twiddling. Modernized the inline myswig.py script (in test/SWIG/SWIG.py). This script was reformatted using Black along the way. Signed-off-by: Mats Wichmann --- test/SWIG/SWIG.py | 42 +++++++++++++++++++------------------- test/SWIG/SWIGPATH.py | 13 ++++++------ test/SWIG/implicit-dependencies.py | 13 ++++++------ test/SWIG/noproxy.py | 2 ++ test/fixture/mycompile.py | 2 +- test/fixture/mylink.py | 12 +++++------ test/fixture/myrewrite.py | 2 +- test/fixture/wrapper.py | 6 +++--- test/fixture/wrapper_with_args.py | 2 +- 9 files changed, 47 insertions(+), 47 deletions(-) diff --git a/test/SWIG/SWIG.py b/test/SWIG/SWIG.py index 31bc7d7..625b5f1 100644 --- a/test/SWIG/SWIG.py +++ b/test/SWIG/SWIG.py @@ -35,19 +35,19 @@ _obj = TestSCons._obj test = TestSCons.TestSCons() -python = test.where_is('python') -if not python: - test.skip_test('Can not find installed "python", skipping test.\n') +_python_ = TestSCons._python_ - -test.write('myswig.py', r""" +test.write('myswig.py', """\ import getopt import sys -opts, args = getopt.getopt(sys.argv[1:], 'c:o:v:') + +opts, args = getopt.getopt(sys.argv[1:], "c:o:v:") for opt, arg in opts: - if opt == '-c': pass - elif opt == '-o': out = arg - elif opt == '-v' and arg == 'ersion': + if opt == "-c": + pass + elif opt == "-o": + out = arg + elif opt == "-v" and arg == "ersion": print("") print("SWIG Version 0.1.2") print("") @@ -55,23 +55,23 @@ for opt, arg in opts: print("") print("Configured options: +pcre") print("") - print("Please see http://www.swig.org for reporting bugs and further information") + print("Please see http://www.swig.org for reporting bugs " + "and further information") sys.exit(0) -infile = open(args[0], 'r') -outfile = open(out, 'w') -for l in infile.readlines(): - if l[:4] != 'swig': - outfile.write(l) + +with open(args[0], "r") as ifp, open(out, "w") as ofp: + for line in ifp: + if not line.startswith("swig"): + ofp.write(line) sys.exit(0) """) -test.write('SConstruct', """ -env = Environment(tools=['default', 'swig'], - SWIG = [r'%(python)s', 'myswig.py']) +test.write('SConstruct', """\ +env = Environment(tools=["default", "swig"], SWIG=[r"%(_python_)s", "myswig.py"]) print(env.subst("Using SWIG $SWIGVERSION")) -env.Program(target = 'test1', source = 'test1.i') -env.CFile(target = 'test2', source = 'test2.i') -env.Clone(SWIGFLAGS = '-c++').Program(target = 'test3', source = 'test3.i') +env.Program(target="test1", source="test1.i") +env.CFile(target="test2", source="test2.i") +env.Clone(SWIGFLAGS="-c++").Program(target="test3", source="test3.i") """ % locals()) test.write('test1.i', r""" diff --git a/test/SWIG/SWIGPATH.py b/test/SWIG/SWIGPATH.py index d516c0c..fcce4c2 100644 --- a/test/SWIG/SWIGPATH.py +++ b/test/SWIG/SWIGPATH.py @@ -35,13 +35,12 @@ test = TestSCons.TestSCons() swig = test.where_is('swig') if not swig: test.skip_test('Can not find installed "swig", skipping test.\n') +swig = swig.replace('\\','/') -python = test.where_is('python') -if not python: - test,skip_test('Can not find installed "python", skipping test.\n') +_python_ = TestSCons._python_ + +test.file_fixture('wrapper.py') -swig = swig.replace('\\','/') -python = python.replace('\\','/') test.subdir('inc1', 'inc2') test.write(['inc2', 'dependency.i'], """\ @@ -59,7 +58,7 @@ foo = Environment(SWIGFLAGS='-python', SWIG='%(swig)s', SWIGPATH=['inc1', 'inc2']) swig = foo.Dictionary('SWIG') -bar = foo.Clone(SWIG = [r'%(python)s', 'wrapper.py', swig]) +bar = foo.Clone(SWIG = [r'%(_python_)s', 'wrapper.py', swig]) foo.CFile(target = 'dependent', source = ['dependent.i']) """ % locals()) @@ -96,4 +95,4 @@ test.pass_test() # tab-width:4 # indent-tabs-mode:nil # End: -# vim: set expandtab tabstop=4 shiftwidth=4: \ No newline at end of file +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/SWIG/implicit-dependencies.py b/test/SWIG/implicit-dependencies.py index 8664bf6..d9eaa8e 100644 --- a/test/SWIG/implicit-dependencies.py +++ b/test/SWIG/implicit-dependencies.py @@ -35,13 +35,12 @@ test = TestSCons.TestSCons() swig = test.where_is('swig') if not swig: test.skip_test('Can not find installed "swig", skipping test.\n') +swig = swig.replace('\\','/') -python = test.where_is('python') -if not python: - test.skip_test('Can not find installed "python", skipping test.\n') +_python_ = TestSCons._python_ + +test.file_fixture('wrapper.py') -swig = swig.replace('\\','/') -python = python.replace('\\','/') test.write("dependency.i", """\ %module dependency """) @@ -55,7 +54,7 @@ test.write("dependent.i", """\ test.write('SConstruct', """ foo = Environment(SWIGFLAGS='-python', SWIG='%(swig)s') swig = foo.Dictionary('SWIG') -bar = foo.Clone(SWIG = [r'%(python)s', r'wrapper.py', swig]) +bar = foo.Clone(SWIG = [r'%(_python_)s', 'wrapper.py', swig]) foo.CFile(target = 'dependent', source = ['dependent.i']) """ % locals()) @@ -76,4 +75,4 @@ test.pass_test() # tab-width:4 # indent-tabs-mode:nil # End: -# vim: set expandtab tabstop=4 shiftwidth=4: \ No newline at end of file +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/SWIG/noproxy.py b/test/SWIG/noproxy.py index f94f553..e3dde61 100644 --- a/test/SWIG/noproxy.py +++ b/test/SWIG/noproxy.py @@ -52,6 +52,8 @@ python, python_include, python_libpath, python_lib = \ # handle testing on other platforms: ldmodule_prefix = '_' +test.file_fixture('wrapper.py') + test.write("dependency.i", """\ %module dependency """) diff --git a/test/fixture/mycompile.py b/test/fixture/mycompile.py index 27bf840..0f37d19 100644 --- a/test/fixture/mycompile.py +++ b/test/fixture/mycompile.py @@ -13,7 +13,7 @@ if __name__ == '__main__': with open(sys.argv[2], 'wb') as ofp: for f in sys.argv[3:]: with open(f, 'rb') as ifp: - lines = [ln for ln in ifp.readlines() if ln != line] + lines = [ln for ln in ifp if ln != line] for ln in lines: ofp.write(ln) sys.exit(0) diff --git a/test/fixture/mylink.py b/test/fixture/mylink.py index b567118..38d9846 100644 --- a/test/fixture/mylink.py +++ b/test/fixture/mylink.py @@ -23,9 +23,9 @@ if __name__ == '__main__': args = args[1:] if a[:5].lower() == '/out:': out = a[5:] with open(args[0], 'rb') as ifp, open(out, 'wb') as ofp: - for l in ifp.readlines(): - if not l.startswith(b'#link'): - ofp.write(l) + for line in ifp: + if not line.startswith(b'#link'): + ofp.write(line) sys.exit(0) else: import getopt @@ -33,7 +33,7 @@ if __name__ == '__main__': for opt, arg in opts: if opt == '-o': out = arg with open(args[0], 'rb') as ifp, open(out, 'wb') as ofp: - for l in ifp.readlines(): - if not l.startswith(b'#link'): - ofp.write(l) + for line in ifp: + if not line.startswith(b'#link'): + ofp.write(line) sys.exit(0) diff --git a/test/fixture/myrewrite.py b/test/fixture/myrewrite.py index ad46091..6914611 100644 --- a/test/fixture/myrewrite.py +++ b/test/fixture/myrewrite.py @@ -10,7 +10,7 @@ import sys if __name__ == '__main__': line = ('/*' + sys.argv[1] + '*/\n').encode() with open(sys.argv[2], 'rb') as ifp: - lines = [ln for ln in ifp.readlines() if ln != line] + lines = [ln for ln in ifp if ln != line] with open(sys.argv[2], 'wb') as ofp: for ln in lines: ofp.write(ln) diff --git a/test/fixture/wrapper.py b/test/fixture/wrapper.py index a023689..d9bcefe 100644 --- a/test/fixture/wrapper.py +++ b/test/fixture/wrapper.py @@ -5,6 +5,6 @@ import subprocess if __name__ == '__main__': path = os.path.join(os.path.dirname(os.path.relpath(__file__)), 'wrapper.out') if '--version' not in sys.argv and '-dumpversion' not in sys.argv: - with open(path, 'wb') as f: - f.write(b"wrapper.py\n") - subprocess.call(sys.argv[1:]) + with open(path, 'w') as f: + f.write("wrapper.py\n") + subprocess.run(sys.argv[1:]) diff --git a/test/fixture/wrapper_with_args.py b/test/fixture/wrapper_with_args.py index f9e4d22..b8d6ae5 100644 --- a/test/fixture/wrapper_with_args.py +++ b/test/fixture/wrapper_with_args.py @@ -6,4 +6,4 @@ if __name__ == '__main__': path = os.path.join(os.path.dirname(os.path.relpath(__file__)), 'wrapper.out') with open(path, 'a') as f: f.write("wrapper_with_args.py %s\n" % " ".join(sys.argv[1:])) - subprocess.call(sys.argv[1:]) + subprocess.run(sys.argv[1:]) -- cgit v0.12 From 8bc187941d5ea8a11200432c099802eefa7a2356 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Wed, 12 Feb 2020 22:01:05 +0200 Subject: Update changes with CConditionalScanner and improved virtual C Pre-Processor --- src/CHANGES.txt | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index b3a7422..6b6b7fd 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -11,17 +11,17 @@ NOTE: Please include a reference to any Issues resolved by your changes in the b RELEASE VERSION/DATE TO BE FILLED IN LATER From William Deegan: - - Fix broken clang + MSVC 2019 combination by using MSVC configuration logic to + - 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 + - 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 - 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() @@ -32,6 +32,17 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - 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 Ivan Kravets, PlatformIO + - New conditional C Scanner (`SCons.Scanner.C.CConditionalScanner()`) + which interprets C/C Preprocessor conditional syntax (#ifdef, #if, #else, + #elif, #define, etc.) + - Improvements for virtual C Pre-Processor: + * Handle UNSIGNED LONG and LONG numeric constants in DEC (keep support for HEX) + * Skip unrecognized directives, such as `#if( defined ...)` + * Ignore `#include DYNAMIC_INCLUDE` directive that depends on a dynamic + macro which is not located in a state TABLE. + * Cleanup CPP expressions before evaluating (strip comments, carriage returns) + 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 @@ -102,7 +113,7 @@ RELEASE 3.1.2 - Mon, 17 Dec 2019 02:06:27 +0000 (e.g. memmove) were incorrectly recognized as not available. From Jakub Kulik - - Fix stacktrace when using SCons with Python 3.5+ and SunOS/Solaris related tools. + - Fix stacktrace when using SCons with Python 3.5+ and SunOS/Solaris related tools. From Philipp Maierhöfer: - Avoid crash with UnicodeDecodeError on Python 3 when a Latex log file in -- cgit v0.12 From e51f211505aa5cdd81c2db6cbcb0b93a73c146e3 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Thu, 13 Feb 2020 06:57:16 -0700 Subject: [PR #3554] trim unused bits from swig tests Three files in the previous fix got an added call to pull in the wrapper.py fixture; it turns out they didn't actually use it - appeared in a dummy call to Clone but the cloned env was never used. Drop those bits. Signed-off-by: Mats Wichmann --- test/SWIG/SWIGPATH.py | 5 ----- test/SWIG/implicit-dependencies.py | 7 +------ test/SWIG/noproxy.py | 3 --- 3 files changed, 1 insertion(+), 14 deletions(-) diff --git a/test/SWIG/SWIGPATH.py b/test/SWIG/SWIGPATH.py index fcce4c2..ef4fb18 100644 --- a/test/SWIG/SWIGPATH.py +++ b/test/SWIG/SWIGPATH.py @@ -37,10 +37,6 @@ if not swig: test.skip_test('Can not find installed "swig", skipping test.\n') swig = swig.replace('\\','/') -_python_ = TestSCons._python_ - -test.file_fixture('wrapper.py') - test.subdir('inc1', 'inc2') test.write(['inc2', 'dependency.i'], """\ @@ -58,7 +54,6 @@ foo = Environment(SWIGFLAGS='-python', SWIG='%(swig)s', SWIGPATH=['inc1', 'inc2']) swig = foo.Dictionary('SWIG') -bar = foo.Clone(SWIG = [r'%(_python_)s', 'wrapper.py', swig]) foo.CFile(target = 'dependent', source = ['dependent.i']) """ % locals()) diff --git a/test/SWIG/implicit-dependencies.py b/test/SWIG/implicit-dependencies.py index d9eaa8e..311ecc3 100644 --- a/test/SWIG/implicit-dependencies.py +++ b/test/SWIG/implicit-dependencies.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/asr/bin/env python # # __COPYRIGHT__ # @@ -37,10 +37,6 @@ if not swig: test.skip_test('Can not find installed "swig", skipping test.\n') swig = swig.replace('\\','/') -_python_ = TestSCons._python_ - -test.file_fixture('wrapper.py') - test.write("dependency.i", """\ %module dependency """) @@ -54,7 +50,6 @@ test.write("dependent.i", """\ test.write('SConstruct', """ foo = Environment(SWIGFLAGS='-python', SWIG='%(swig)s') swig = foo.Dictionary('SWIG') -bar = foo.Clone(SWIG = [r'%(_python_)s', 'wrapper.py', swig]) foo.CFile(target = 'dependent', source = ['dependent.i']) """ % locals()) diff --git a/test/SWIG/noproxy.py b/test/SWIG/noproxy.py index e3dde61..deeaa3a 100644 --- a/test/SWIG/noproxy.py +++ b/test/SWIG/noproxy.py @@ -52,8 +52,6 @@ python, python_include, python_libpath, python_lib = \ # handle testing on other platforms: ldmodule_prefix = '_' -test.file_fixture('wrapper.py') - test.write("dependency.i", """\ %module dependency """) @@ -75,7 +73,6 @@ foo = Environment(SWIGFLAGS=['-python', '-noproxy'], ) swig = foo.Dictionary('SWIG') -bar = foo.Clone(SWIG = [r'%(python)s', 'wrapper.py', swig]) foo.CFile(target = 'dependent', source = ['dependent.i']) """ % locals()) -- cgit v0.12 From 2931eea70b0234cf284c88b9a2a31e1c63bcfcd6 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Thu, 13 Feb 2020 08:16:11 -0700 Subject: [PR #3554] restore wrapper.py for former state Changes didn't work on Windows. Signed-off-by: Mats Wichmann --- test/fixture/wrapper.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/fixture/wrapper.py b/test/fixture/wrapper.py index d9bcefe..112186e 100644 --- a/test/fixture/wrapper.py +++ b/test/fixture/wrapper.py @@ -5,6 +5,6 @@ import subprocess if __name__ == '__main__': path = os.path.join(os.path.dirname(os.path.relpath(__file__)), 'wrapper.out') if '--version' not in sys.argv and '-dumpversion' not in sys.argv: - with open(path, 'w') as f: - f.write("wrapper.py\n") + with open(path, 'wb') as f: + f.write(b"wrapper.py\n") subprocess.run(sys.argv[1:]) -- cgit v0.12 From fe2680ddd07a4bc7c6064e7193f4979060e178ba Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Thu, 13 Feb 2020 17:33:47 +0200 Subject: Isolate CConditionalScanner from CScanner --- src/engine/SCons/Scanner/C.py | 142 +++++++++++++++++++++++++++++++----------- 1 file changed, 107 insertions(+), 35 deletions(-) diff --git a/src/engine/SCons/Scanner/C.py b/src/engine/SCons/Scanner/C.py index 37bf244..29cc396 100644 --- a/src/engine/SCons/Scanner/C.py +++ b/src/engine/SCons/Scanner/C.py @@ -46,27 +46,16 @@ class SConsCPPScanner(SCons.cpp.PreProcessor): def __init__(self, *args, **kw): SCons.cpp.PreProcessor.__init__(self, *args, **kw) self.missing = [] - self._known_paths = [] - def initialize_result(self, fname): self.result = SCons.Util.UniqueList([fname]) - + def finalize_result(self, fname): + return self.result[1:] def find_include_file(self, t): keyword, quote, fname = t - paths = tuple(self._known_paths) + self.searchpath[quote] - if quote == '"': - paths = (self.current_file.dir, ) + paths - result = SCons.Node.FS.find_file(fname, paths) - if result: - result_path = result.get_abspath() - for p in self.searchpath[quote]: - if result_path.startswith(p.get_abspath()): - self._known_paths.append(p) - break - else: + result = SCons.Node.FS.find_file(fname, self.searchpath[quote]) + if not result: self.missing.append((fname, self.current_file)) return result - def read_file(self, file): try: with open(str(file.rfile())) as fp: @@ -83,11 +72,7 @@ def dictify_CPPDEFINES(env): result = {} for c in cppdefines: if SCons.Util.is_Sequence(c): - # handle tuple with 1 item (e.g. tuple("DEFINE", )) - if len(c) > 1: - result[c[0]] = c[1] - else: - result[c[0]] = None + result[c[0]] = c[1] else: result[c] = None return result @@ -107,11 +92,10 @@ class SConsCPPScannerWrapper(object): def __init__(self, name, variable): self.name = name self.path = SCons.Scanner.FindPathDirs(variable) - def __call__(self, node, env, path = (), depth=-1): + def __call__(self, node, env, path = ()): cpp = SConsCPPScanner(current = node.get_dir(), cpppath = path, - dict = dictify_CPPDEFINES(env), - depth = depth) + dict = dictify_CPPDEFINES(env)) result = cpp(node) for included, includer in cpp.missing: fmt = "No dependency generated for file: %s (included from: %s) -- file not found" @@ -124,26 +108,114 @@ class SConsCPPScannerWrapper(object): def select(self, node): return self +def CScanner(): + """Return a prototype Scanner instance for scanning source files + that use the C pre-processor""" + + # Here's how we would (or might) use the CPP scanner code above that + # knows how to evaluate #if/#ifdef/#else/#elif lines when searching + # for #includes. This is commented out for now until we add the + # right configurability to let users pick between the scanners. + #return SConsCPPScannerWrapper("CScanner", "CPPPATH") -def CConditionalScanner(): + cs = SCons.Scanner.ClassicCPP("CScanner", + "$CPPSUFFIXES", + "CPPPATH", + '^[ \t]*#[ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")') + return cs + + +# +# ConditionalScanner +# + + +class SConsCPPConditionalScanner(SCons.cpp.PreProcessor): """ - Return an advanced conditional Scanner instance for scanning source files + SCons-specific subclass of the cpp.py module's processing. - Interprets C/C++ Preprocessor conditional syntax - (#ifdef, #if, defined, #else, #elif, etc.). + We subclass this so that: 1) we can deal with files represented + by Nodes, not strings; 2) we can keep track of the files that are + missing. """ - return SConsCPPScannerWrapper("CScanner", "CPPPATH") + def __init__(self, *args, **kw): + SCons.cpp.PreProcessor.__init__(self, *args, **kw) + self.missing = [] + self._known_paths = [] + + def initialize_result(self, fname): + self.result = SCons.Util.UniqueList([fname]) -def CScanner(): - """Return a simplified classic Scanner instance for scanning source files + def find_include_file(self, t): + keyword, quote, fname = t + paths = tuple(self._known_paths) + self.searchpath[quote] + if quote == '"': + paths = (self.current_file.dir,) + paths + result = SCons.Node.FS.find_file(fname, paths) + if result: + result_path = result.get_abspath() + for p in self.searchpath[quote]: + if result_path.startswith(p.get_abspath()): + self._known_paths.append(p) + break + else: + self.missing.append((fname, self.current_file)) + return result + + def read_file(self, file): + try: + with open(str(file.rfile())) as fp: + return fp.read() + except EnvironmentError: + self.missing.append((file, self.current_file)) + return "" + + +class SConsCPPConditionalScannerWrapper(object): + """ + The SCons wrapper around a cpp.py scanner. + + This is the actual glue between the calling conventions of generic + SCons scanners, and the (subclass of) cpp.py class that knows how + to look for #include lines with reasonably real C-preprocessor-like + evaluation of #if/#ifdef/#else/#elif lines. + """ - Takes into account the type of bracketing used to include the file, and - uses classic CPP rules for searching for the files based on the bracketing. + def __init__(self, name, variable): + self.name = name + self.path = SCons.Scanner.FindPathDirs(variable) + + def __call__(self, node, env, path=(), depth=-1): + cpp = SConsCPPConditionalScanner( + current=node.get_dir(), + cpppath=path, + dict=dictify_CPPDEFINES(env), + depth=depth, + ) + result = cpp(node) + for included, includer in cpp.missing: + fmt = "No dependency generated for file: %s (included from: %s) -- file not found" + SCons.Warnings.warn( + SCons.Warnings.DependencyWarning, fmt % (included, includer) + ) + return result + + def recurse_nodes(self, nodes): + return nodes + + def select(self, node): + return self + + +def CConditionalScanner(): + """ + Return an advanced conditional Scanner instance for scanning source files + + Interprets C/C++ Preprocessor conditional syntax + (#ifdef, #if, defined, #else, #elif, etc.). """ - return SCons.Scanner.ClassicCPP( - "CScanner", "$CPPSUFFIXES", "CPPPATH", - '^[ \t]*#[ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")') + return SConsCPPConditionalScannerWrapper("CConditionalScanner", "CPPPATH") # Local Variables: -- cgit v0.12 From 348f8d81b6aa49d8798eac268700806d121c5f4f Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 13 Feb 2020 20:05:26 -0800 Subject: [ci skip] fix typo --- test/SWIG/implicit-dependencies.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/SWIG/implicit-dependencies.py b/test/SWIG/implicit-dependencies.py index 311ecc3..715db83 100644 --- a/test/SWIG/implicit-dependencies.py +++ b/test/SWIG/implicit-dependencies.py @@ -1,4 +1,4 @@ -#!/asr/bin/env python +#!/usr/bin/env python # # __COPYRIGHT__ # -- cgit v0.12 From 83304e49c44ec770bb5770d6ef6a6ece4dec92f8 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sat, 15 Feb 2020 09:01:36 -0700 Subject: Change errant TEXFTILESUFFIX to SUBSTFILESUFFIX In one location a copy-paste apparently didn't get fixed up, and the wrong construction var was used. Fixes #3540 Signed-off-by: Mats Wichmann --- src/CHANGES.txt | 1 + src/engine/SCons/Tool/textfile.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index b3a7422..4638bd6 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -68,6 +68,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - 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. + - Fix typo TEXTFILESUFFIX -> SUBSTFILESUFFIX (bug #3540) RELEASE 3.1.2 - Mon, 17 Dec 2019 02:06:27 +0000 diff --git a/src/engine/SCons/Tool/textfile.py b/src/engine/SCons/Tool/textfile.py index c233658..b404304 100644 --- a/src/engine/SCons/Tool/textfile.py +++ b/src/engine/SCons/Tool/textfile.py @@ -171,7 +171,7 @@ _text_builder = SCons.Builder.Builder( suffix='$TEXTFILESUFFIX', ) -_subst_varlist = _common_varlist + ['SUBSTFILEPREFIX', 'TEXTFILESUFFIX'] +_subst_varlist = _common_varlist + ['SUBSTFILEPREFIX', 'SUBSTFILESUFFIX'] _subst_builder = SCons.Builder.Builder( action=SCons.Action.Action(_action, _strfunc, varlist=_subst_varlist), source_factory=SCons.Node.FS.File, -- cgit v0.12 From 1a7f7caa2ecc2fdeaeb69c27a41d9986718de7ae Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 15 Feb 2020 16:50:34 -0800 Subject: Add testcase for GitHub Issue #3540. Update tests for 3550 to allow 3540 to use some of it's test files --- test/textfile/fixture/SConstruct.issue-3540 | 23 ++++++++++++++ test/textfile/fixture/SConstruct.issue-3550 | 4 +-- test/textfile/fixture/foo-3550.in | 1 - test/textfile/fixture/substfile.in | 1 + test/textfile/issue-3540.py | 48 +++++++++++++++++++++++++++++ test/textfile/issue-3550.py | 12 ++++++-- 6 files changed, 83 insertions(+), 6 deletions(-) create mode 100644 test/textfile/fixture/SConstruct.issue-3540 delete mode 100644 test/textfile/fixture/foo-3550.in create mode 100644 test/textfile/fixture/substfile.in create mode 100644 test/textfile/issue-3540.py diff --git a/test/textfile/fixture/SConstruct.issue-3540 b/test/textfile/fixture/SConstruct.issue-3540 new file mode 100644 index 0000000..021689a --- /dev/null +++ b/test/textfile/fixture/SConstruct.issue-3540 @@ -0,0 +1,23 @@ +""" +Test for GH Issue 3540 + +textfile()'s action is not sensitive to changes in TEXTFILESUFFIX (rather was sensitive to SUBSTFILESUFFIX) + +""" + +DefaultEnvironment(tools=[]) + +text_file_suffix = ARGUMENTS.get('text_file_suffix', 'DEFAULTSUFFIX') + +env = Environment(tools=['textfile'], + TEXTFILESUFFIX=text_file_suffix) + +env['FOO_PATH'] = "test-value-1" + +foo = env.Substfile( + target="substfile", + source="substfile.in", + SUBST_DICT={ + "@foo_path@": "$FOO_PATH", + } +) diff --git a/test/textfile/fixture/SConstruct.issue-3550 b/test/textfile/fixture/SConstruct.issue-3550 index 8502717..0239ade 100644 --- a/test/textfile/fixture/SConstruct.issue-3550 +++ b/test/textfile/fixture/SConstruct.issue-3550 @@ -4,8 +4,8 @@ env = Environment(tools=['textfile']) env['FOO_PATH'] = r'Z:\mongo\build\install\bin' foo = env.Substfile( - target="foo", - source="foo-3550.in", + target="substfile", + source="substfile.in", SUBST_DICT={ "@foo_path@": "$FOO_PATH", } diff --git a/test/textfile/fixture/foo-3550.in b/test/textfile/fixture/foo-3550.in deleted file mode 100644 index c806a04..0000000 --- a/test/textfile/fixture/foo-3550.in +++ /dev/null @@ -1 +0,0 @@ -foo_path: @foo_path@ diff --git a/test/textfile/fixture/substfile.in b/test/textfile/fixture/substfile.in new file mode 100644 index 0000000..c806a04 --- /dev/null +++ b/test/textfile/fixture/substfile.in @@ -0,0 +1 @@ +foo_path: @foo_path@ diff --git a/test/textfile/issue-3540.py b/test/textfile/issue-3540.py new file mode 100644 index 0000000..b53f06a --- /dev/null +++ b/test/textfile/issue-3540.py @@ -0,0 +1,48 @@ +#!/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__" +""" +Test for GH Issue 3540 + +textfile()'s action is not sensitive to changes in TEXTFILEPREFIX (rather was sensitive to SUBSTFILEPREFIX) + +""" + +import TestSCons + +test = TestSCons.TestSCons() + +# test.verbose_set(1) + +test.file_fixture('fixture/substfile.in', 'substfile.in') +test.file_fixture('fixture/SConstruct.issue-3540', 'SConstruct') + +test.run() +test.must_exist('substfile') + +test.up_to_date(options='text_file_suffix=BLAH') + + +test.pass_test() diff --git a/test/textfile/issue-3550.py b/test/textfile/issue-3550.py index 60430ed..5951d1b 100644 --- a/test/textfile/issue-3550.py +++ b/test/textfile/issue-3550.py @@ -23,21 +23,27 @@ # __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" +""" +Test for GH Issue 3550 + + You can't pass a Windows path in a value to be interpolated, + because SCons will try to pass it through re.sub which rejects certain character sequences. +""" import TestSCons test = TestSCons.TestSCons() -test.verbose_set(1) +# 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.file_fixture('fixture/substfile.in', 'substfile.in') test.run(arguments='.') -test.must_match('foo', +test.must_match('substfile', r'''foo_path: Z:\mongo\build\install\bin ''', mode=match_mode) -- cgit v0.12 From 03dbdfc91995b4b9bd3360eafa0dead73a7019d3 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 15 Feb 2020 20:36:39 -0800 Subject: Fix Issue #2904 - add useful error message when more than one Configure() contexts are opened --- src/engine/SCons/SConf.py | 3 +- test/Configure/fixture/SConstruct.issue-2906 | 5 ++ ...ssue-2906-useful-duplicate-configure-message.py | 57 ++++++++++++++++++++++ 3 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 test/Configure/fixture/SConstruct.issue-2906 create mode 100644 test/Configure/issue-2906-useful-duplicate-configure-message.py diff --git a/src/engine/SCons/SConf.py b/src/engine/SCons/SConf.py index 50a1329..a5e443e 100644 --- a/src/engine/SCons/SConf.py +++ b/src/engine/SCons/SConf.py @@ -430,7 +430,8 @@ class SConfBase(object): SConfFS = SCons.Node.FS.default_fs or \ SCons.Node.FS.FS(env.fs.pathTop) if sconf_global is not None: - raise SCons.Errors.UserError + raise SCons.Errors.UserError("""User Called Configure() when another Configure() exists. + Please call .Finish() before creating and second Configure() context""") if log_file is not None: log_file = SConfFS.File(env.subst(log_file)) diff --git a/test/Configure/fixture/SConstruct.issue-2906 b/test/Configure/fixture/SConstruct.issue-2906 new file mode 100644 index 0000000..7763653 --- /dev/null +++ b/test/Configure/fixture/SConstruct.issue-2906 @@ -0,0 +1,5 @@ +env = Environment() +conf1 = Configure(env) +env2 = Environment() +# Error right here. You can't have two configure contexts in flight at the same time. +conf2 = Configure(env2) \ No newline at end of file diff --git a/test/Configure/issue-2906-useful-duplicate-configure-message.py b/test/Configure/issue-2906-useful-duplicate-configure-message.py new file mode 100644 index 0000000..716cb33 --- /dev/null +++ b/test/Configure/issue-2906-useful-duplicate-configure-message.py @@ -0,0 +1,57 @@ +#!/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 useful error message when you create a second Configure context without +finalizing the previous one via conf.Finish() +This addresses Issue 2906: +https://github.com/SCons/scons/issues/2906 +""" + +import TestSCons + +test = TestSCons.TestSCons() +test.verbose_set(1) + +test.file_fixture('./fixture/SConstruct.issue-2906', 'SConstruct') + +test_SConstruct_path = test.workpath('SConstruct') + +expected_stdout = "scons: Reading SConscript files ...\n" + +expected_stderr = """ +scons: *** User Called Configure() when another Configure() exists. + Please call .Finish() before creating and second Configure() context +File "%s", line 5, in \n"""%test_SConstruct_path +test.run(stderr=expected_stderr, stdout=expected_stdout, status=2) + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: -- cgit v0.12 From 6363a46016bf9d834db3e1ab92b7303c070105ee Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 15 Feb 2020 20:38:18 -0800 Subject: Update CHANGES.txt --- src/CHANGES.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index b3a7422..8806179 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -21,6 +21,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - 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(). + - Fix Github Issue #2904 - Provide useful error message when more than one Configure Contexts are opened. + Only one open is allowed. You must call conf.Finish() to complete the currently open one before creating another From Jeremy Elson: - Updated design doc to use the correct syntax for Depends() -- cgit v0.12 From 283a1d3b52f3755733aa592eac99fab54feadd5b Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 16 Feb 2020 14:25:12 -0800 Subject: Updated error message per sugguestion by mwichmann --- src/engine/SCons/SConf.py | 2 +- test/Configure/issue-2906-useful-duplicate-configure-message.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/engine/SCons/SConf.py b/src/engine/SCons/SConf.py index a5e443e..685fa3e 100644 --- a/src/engine/SCons/SConf.py +++ b/src/engine/SCons/SConf.py @@ -430,7 +430,7 @@ class SConfBase(object): SConfFS = SCons.Node.FS.default_fs or \ SCons.Node.FS.FS(env.fs.pathTop) if sconf_global is not None: - raise SCons.Errors.UserError("""User Called Configure() when another Configure() exists. + raise SCons.Errors.UserError("""Configure() called while another Configure() exists. Please call .Finish() before creating and second Configure() context""") if log_file is not None: diff --git a/test/Configure/issue-2906-useful-duplicate-configure-message.py b/test/Configure/issue-2906-useful-duplicate-configure-message.py index 716cb33..c980bd3 100644 --- a/test/Configure/issue-2906-useful-duplicate-configure-message.py +++ b/test/Configure/issue-2906-useful-duplicate-configure-message.py @@ -43,7 +43,7 @@ test_SConstruct_path = test.workpath('SConstruct') expected_stdout = "scons: Reading SConscript files ...\n" expected_stderr = """ -scons: *** User Called Configure() when another Configure() exists. +scons: *** Configure() called while another Configure() exists. Please call .Finish() before creating and second Configure() context File "%s", line 5, in \n"""%test_SConstruct_path test.run(stderr=expected_stderr, stdout=expected_stdout, status=2) -- cgit v0.12 From 12a571916e7a09f36f987ca4a22f0d800e15a2cd Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 16 Feb 2020 18:40:43 -0800 Subject: Remove 'from __future__ import print_function' no longer needed as we're dropping < py 3.5 --- src/engine/SCons/BuilderTests.py | 2 -- src/engine/SCons/EnvironmentTests.py | 3 --- src/engine/SCons/Executor.py | 2 -- src/engine/SCons/Memoize.py | 2 -- src/engine/SCons/Node/FS.py | 2 -- src/engine/SCons/Node/FSTests.py | 2 -- src/engine/SCons/Node/__init__.py | 2 -- src/engine/SCons/Platform/__init__.py | 2 -- src/engine/SCons/SConf.py | 2 -- src/engine/SCons/SConsign.py | 3 --- src/engine/SCons/Script/Interactive.py | 2 -- src/engine/SCons/Script/Main.py | 3 --- src/engine/SCons/SubstTests.py | 2 -- src/engine/SCons/Taskmaster.py | 2 -- src/engine/SCons/Tool/DCommon.py | 2 -- src/engine/SCons/Tool/FortranCommon.py | 2 -- src/engine/SCons/Tool/MSCommon/common.py | 2 -- src/engine/SCons/Tool/cyglink.py | 2 +- src/engine/SCons/Tool/dmd.py | 2 -- .../SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/docbook.py | 2 -- .../SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/xslt.py | 2 -- src/engine/SCons/Tool/gdc.py | 2 -- src/engine/SCons/Tool/install.py | 2 -- src/engine/SCons/Tool/intelc.py | 2 -- src/engine/SCons/Tool/ldc.py | 2 -- src/engine/SCons/Tool/link.py | 2 -- src/engine/SCons/Tool/mslink.py | 2 -- src/engine/SCons/Tool/msvs.py | 3 --- src/engine/SCons/Tool/msvsTests.py | 2 -- src/engine/SCons/Tool/qt.py | 2 -- src/engine/SCons/Tool/rpmutils.py | 2 -- src/engine/SCons/Tool/swig.py | 2 -- src/engine/SCons/Tool/tex.py | 2 -- src/engine/SCons/dblite.py | 7 ++++--- src/script/scons-configure-cache.py | 1 - src/script/scons-time.py | 2 +- src/script/scons.py | 2 -- src/script/sconsign.py | 2 -- src/setup.py | 3 --- src/test_files.py | 2 -- src/test_interrupts.py | 2 -- src/test_pychecker.py | 2 -- src/test_setup.py | 2 -- src/test_strings.py | 2 -- 44 files changed, 6 insertions(+), 91 deletions(-) diff --git a/src/engine/SCons/BuilderTests.py b/src/engine/SCons/BuilderTests.py index b4286fd..acdc277 100644 --- a/src/engine/SCons/BuilderTests.py +++ b/src/engine/SCons/BuilderTests.py @@ -20,8 +20,6 @@ # 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 SCons.compat diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index 01baba3..3db6499 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -20,9 +20,6 @@ # 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 SCons.compat diff --git a/src/engine/SCons/Executor.py b/src/engine/SCons/Executor.py index 28bb6ad..fb2224f 100644 --- a/src/engine/SCons/Executor.py +++ b/src/engine/SCons/Executor.py @@ -26,8 +26,6 @@ Nodes. # 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 collections diff --git a/src/engine/SCons/Memoize.py b/src/engine/SCons/Memoize.py index 5bdcf42..0595fdf 100644 --- a/src/engine/SCons/Memoize.py +++ b/src/engine/SCons/Memoize.py @@ -20,8 +20,6 @@ # 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__" __doc__ = """Memoizer diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index 6f16256..423ba76 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -31,8 +31,6 @@ that can be used by scripts or modules looking for the canonical default. # 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 fnmatch diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index bbfdd1b..41d9381 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -20,8 +20,6 @@ # 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 division, print_function - __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import SCons.compat diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index 0b58282..c3565bf 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -19,8 +19,6 @@ be able to depend on any other type of "thing." """ -from __future__ import print_function - # # __COPYRIGHT__ # diff --git a/src/engine/SCons/Platform/__init__.py b/src/engine/SCons/Platform/__init__.py index 5e9a358..21e63b4 100644 --- a/src/engine/SCons/Platform/__init__.py +++ b/src/engine/SCons/Platform/__init__.py @@ -41,8 +41,6 @@ their own platform definition. # 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 SCons.compat diff --git a/src/engine/SCons/SConf.py b/src/engine/SCons/SConf.py index 685fa3e..e0e492b 100644 --- a/src/engine/SCons/SConf.py +++ b/src/engine/SCons/SConf.py @@ -33,8 +33,6 @@ libraries are installed, if some command line options are supported etc. # 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 SCons.compat diff --git a/src/engine/SCons/SConsign.py b/src/engine/SCons/SConsign.py index 1115f2a..a516e1f 100644 --- a/src/engine/SCons/SConsign.py +++ b/src/engine/SCons/SConsign.py @@ -26,9 +26,6 @@ Writing and reading information to the .sconsign file or files. # 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 SCons.compat diff --git a/src/engine/SCons/Script/Interactive.py b/src/engine/SCons/Script/Interactive.py index 59299f1..a414b4e 100644 --- a/src/engine/SCons/Script/Interactive.py +++ b/src/engine/SCons/Script/Interactive.py @@ -19,8 +19,6 @@ # 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__" __doc__ = """ diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py index a0d7f4c..f738503 100644 --- a/src/engine/SCons/Script/Main.py +++ b/src/engine/SCons/Script/Main.py @@ -10,9 +10,6 @@ some other module. If it's specific to the "scons" script invocation, it goes here. """ -from __future__ import print_function - - unsupported_python_version = (2, 6, 0) deprecated_python_version = (2, 7, 0) diff --git a/src/engine/SCons/SubstTests.py b/src/engine/SCons/SubstTests.py index c25b377..574e714 100644 --- a/src/engine/SCons/SubstTests.py +++ b/src/engine/SCons/SubstTests.py @@ -20,8 +20,6 @@ # 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 SCons.compat diff --git a/src/engine/SCons/Taskmaster.py b/src/engine/SCons/Taskmaster.py index 1e5776c..2bbb732 100644 --- a/src/engine/SCons/Taskmaster.py +++ b/src/engine/SCons/Taskmaster.py @@ -20,8 +20,6 @@ # 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 - import sys __doc__ = """ diff --git a/src/engine/SCons/Tool/DCommon.py b/src/engine/SCons/Tool/DCommon.py index 71c4d8d..d29db3a 100644 --- a/src/engine/SCons/Tool/DCommon.py +++ b/src/engine/SCons/Tool/DCommon.py @@ -1,5 +1,3 @@ -from __future__ import print_function - """SCons.Tool.DCommon Common code for the various D tools. diff --git a/src/engine/SCons/Tool/FortranCommon.py b/src/engine/SCons/Tool/FortranCommon.py index cbb9a03..bfa1c1c 100644 --- a/src/engine/SCons/Tool/FortranCommon.py +++ b/src/engine/SCons/Tool/FortranCommon.py @@ -26,8 +26,6 @@ Stuff for processing Fortran, common to all fortran dialects. # 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 re diff --git a/src/engine/SCons/Tool/MSCommon/common.py b/src/engine/SCons/Tool/MSCommon/common.py index 4ce605b..505136e 100644 --- a/src/engine/SCons/Tool/MSCommon/common.py +++ b/src/engine/SCons/Tool/MSCommon/common.py @@ -23,8 +23,6 @@ Common helper functions for working with the Microsoft tool chain. # 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 copy diff --git a/src/engine/SCons/Tool/cyglink.py b/src/engine/SCons/Tool/cyglink.py index c3d78de..f19614c 100644 --- a/src/engine/SCons/Tool/cyglink.py +++ b/src/engine/SCons/Tool/cyglink.py @@ -8,7 +8,7 @@ selection method. """ -from __future__ import absolute_import, print_function +from __future__ import absolute_import import re import os diff --git a/src/engine/SCons/Tool/dmd.py b/src/engine/SCons/Tool/dmd.py index 6a64a72..3cc4ed0 100644 --- a/src/engine/SCons/Tool/dmd.py +++ b/src/engine/SCons/Tool/dmd.py @@ -1,5 +1,3 @@ -from __future__ import print_function - """SCons.Tool.dmd Tool-specific initialization for the Digital Mars D compiler. 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 de1375d..7e6a81a 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 @@ -1,7 +1,5 @@ # docbook.py: extension module # $Id: docbook.py 8353 2009-03-17 16:57:50Z mzjn $ -from __future__ import print_function - import sys import string import libxml2 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 d5529b8..0a4ff92 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 @@ -1,7 +1,5 @@ #!/usr/bin/python -u # $Id: xslt.py 8353 2009-03-17 16:57:50Z mzjn $ -from __future__ import print_function - import sys import libxml2 import libxslt diff --git a/src/engine/SCons/Tool/gdc.py b/src/engine/SCons/Tool/gdc.py index 0c6a8ab..ecf4f3a 100644 --- a/src/engine/SCons/Tool/gdc.py +++ b/src/engine/SCons/Tool/gdc.py @@ -1,5 +1,3 @@ -from __future__ import print_function - """SCons.Tool.gdc Tool-specific initialization for the GDC compiler. diff --git a/src/engine/SCons/Tool/install.py b/src/engine/SCons/Tool/install.py index dcb3581..06f7902 100644 --- a/src/engine/SCons/Tool/install.py +++ b/src/engine/SCons/Tool/install.py @@ -29,8 +29,6 @@ selection method. # 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 diff --git a/src/engine/SCons/Tool/intelc.py b/src/engine/SCons/Tool/intelc.py index 778cba1..0880976 100644 --- a/src/engine/SCons/Tool/intelc.py +++ b/src/engine/SCons/Tool/intelc.py @@ -30,8 +30,6 @@ selection method. # 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 division, print_function - __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import math, sys, os.path, glob, string, re diff --git a/src/engine/SCons/Tool/ldc.py b/src/engine/SCons/Tool/ldc.py index 3e12199..f915569 100644 --- a/src/engine/SCons/Tool/ldc.py +++ b/src/engine/SCons/Tool/ldc.py @@ -1,5 +1,3 @@ -from __future__ import print_function - """SCons.Tool.ldc Tool-specific initialization for the LDC compiler. diff --git a/src/engine/SCons/Tool/link.py b/src/engine/SCons/Tool/link.py index 5d920fb..d52c90d 100644 --- a/src/engine/SCons/Tool/link.py +++ b/src/engine/SCons/Tool/link.py @@ -30,8 +30,6 @@ selection method. # 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 sys diff --git a/src/engine/SCons/Tool/mslink.py b/src/engine/SCons/Tool/mslink.py index fc5f009..bab78d8 100644 --- a/src/engine/SCons/Tool/mslink.py +++ b/src/engine/SCons/Tool/mslink.py @@ -30,8 +30,6 @@ selection method. # 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 diff --git a/src/engine/SCons/Tool/msvs.py b/src/engine/SCons/Tool/msvs.py index 9952ccc..7332b49 100644 --- a/src/engine/SCons/Tool/msvs.py +++ b/src/engine/SCons/Tool/msvs.py @@ -29,9 +29,6 @@ selection method. # 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 SCons.compat diff --git a/src/engine/SCons/Tool/msvsTests.py b/src/engine/SCons/Tool/msvsTests.py index 38a100f..b3373ea 100644 --- a/src/engine/SCons/Tool/msvsTests.py +++ b/src/engine/SCons/Tool/msvsTests.py @@ -20,8 +20,6 @@ # 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 diff --git a/src/engine/SCons/Tool/qt.py b/src/engine/SCons/Tool/qt.py index 0c471f9..3dc87c0 100644 --- a/src/engine/SCons/Tool/qt.py +++ b/src/engine/SCons/Tool/qt.py @@ -31,8 +31,6 @@ selection method. # 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.path diff --git a/src/engine/SCons/Tool/rpmutils.py b/src/engine/SCons/Tool/rpmutils.py index 566f8e1..2c4fb32 100644 --- a/src/engine/SCons/Tool/rpmutils.py +++ b/src/engine/SCons/Tool/rpmutils.py @@ -34,8 +34,6 @@ exact syntax. # 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__" diff --git a/src/engine/SCons/Tool/swig.py b/src/engine/SCons/Tool/swig.py index f139a09..4d98494 100644 --- a/src/engine/SCons/Tool/swig.py +++ b/src/engine/SCons/Tool/swig.py @@ -7,8 +7,6 @@ It will usually be imported through the generic SCons.Tool.Tool() selection method. """ -from __future__ import print_function - # # __COPYRIGHT__ # diff --git a/src/engine/SCons/Tool/tex.py b/src/engine/SCons/Tool/tex.py index fa18cf9..1d61e2d 100644 --- a/src/engine/SCons/Tool/tex.py +++ b/src/engine/SCons/Tool/tex.py @@ -31,8 +31,6 @@ selection method. # 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.path diff --git a/src/engine/SCons/dblite.py b/src/engine/SCons/dblite.py index 55254b3..8351017 100644 --- a/src/engine/SCons/dblite.py +++ b/src/engine/SCons/dblite.py @@ -1,6 +1,7 @@ -# dblite.py module contributed by Ralf W. Grosse-Kunstleve. -# Extended for Unicode by Steven Knight. -from __future__ import print_function +""" +dblite.py module contributed by Ralf W. Grosse-Kunstleve. +Extended for Unicode by Steven Knight. +""" import os import pickle diff --git a/src/script/scons-configure-cache.py b/src/script/scons-configure-cache.py index a687c9c..716315c 100644 --- a/src/script/scons-configure-cache.py +++ b/src/script/scons-configure-cache.py @@ -31,7 +31,6 @@ digits of the signature. The prefix length used for directory names can be changed by this script. """ -from __future__ import print_function import argparse import glob import json diff --git a/src/script/scons-time.py b/src/script/scons-time.py index 91a105b..0fcd1c4 100644 --- a/src/script/scons-time.py +++ b/src/script/scons-time.py @@ -29,7 +29,7 @@ # 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 division, print_function +from __future__ import division __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/src/script/scons.py b/src/script/scons.py index 2e76365..1e12898 100755 --- a/src/script/scons.py +++ b/src/script/scons.py @@ -23,8 +23,6 @@ # 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__" __version__ = "__VERSION__" diff --git a/src/script/sconsign.py b/src/script/sconsign.py index 5ea5ea5..726838c 100644 --- a/src/script/sconsign.py +++ b/src/script/sconsign.py @@ -23,8 +23,6 @@ # 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__" __version__ = "__VERSION__" diff --git a/src/setup.py b/src/setup.py index 0f9a672..261e2a4 100755 --- a/src/setup.py +++ b/src/setup.py @@ -20,9 +20,6 @@ # 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 - - import distutils.command.build_scripts import distutils.command.install_scripts import distutils.command.install_lib diff --git a/src/test_files.py b/src/test_files.py index 1eee11d..fcb2b4c 100644 --- a/src/test_files.py +++ b/src/test_files.py @@ -21,8 +21,6 @@ # 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__" """ diff --git a/src/test_interrupts.py b/src/test_interrupts.py index 8e1b379..1cac046 100644 --- a/src/test_interrupts.py +++ b/src/test_interrupts.py @@ -21,8 +21,6 @@ # 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__" """ diff --git a/src/test_pychecker.py b/src/test_pychecker.py index 56233c2..fdc8d20 100644 --- a/src/test_pychecker.py +++ b/src/test_pychecker.py @@ -20,8 +20,6 @@ # 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__" """ diff --git a/src/test_setup.py b/src/test_setup.py index d9fa5b5..8410be3 100644 --- a/src/test_setup.py +++ b/src/test_setup.py @@ -21,8 +21,6 @@ # 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__" """ diff --git a/src/test_strings.py b/src/test_strings.py index a8a5000..b43340f 100644 --- a/src/test_strings.py +++ b/src/test_strings.py @@ -21,8 +21,6 @@ # 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__" """ -- cgit v0.12 From ae0891eece6e36b9e261de807979fd4d35dcc4e2 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 17 Feb 2020 10:28:35 -0800 Subject: remove remaining from __future__ imports --- src/engine/SCons/Defaults.py | 2 -- src/engine/SCons/TaskmasterTests.py | 2 -- src/engine/SCons/Tool/cyglink.py | 2 -- src/engine/SCons/Tool/f08.py | 2 -- src/engine/SCons/cppTests.py | 3 --- 5 files changed, 11 deletions(-) diff --git a/src/engine/SCons/Defaults.py b/src/engine/SCons/Defaults.py index a69d8b0..2bac41e 100644 --- a/src/engine/SCons/Defaults.py +++ b/src/engine/SCons/Defaults.py @@ -31,8 +31,6 @@ from distutils.msvccompiler. # 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 division - __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/src/engine/SCons/TaskmasterTests.py b/src/engine/SCons/TaskmasterTests.py index 1a47230..58a31aa 100644 --- a/src/engine/SCons/TaskmasterTests.py +++ b/src/engine/SCons/TaskmasterTests.py @@ -20,8 +20,6 @@ # 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 division - __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import SCons.compat diff --git a/src/engine/SCons/Tool/cyglink.py b/src/engine/SCons/Tool/cyglink.py index f19614c..fbb6d24 100644 --- a/src/engine/SCons/Tool/cyglink.py +++ b/src/engine/SCons/Tool/cyglink.py @@ -8,8 +8,6 @@ selection method. """ -from __future__ import absolute_import - import re import os diff --git a/src/engine/SCons/Tool/f08.py b/src/engine/SCons/Tool/f08.py index 7fa5872..64bac8e 100644 --- a/src/engine/SCons/Tool/f08.py +++ b/src/engine/SCons/Tool/f08.py @@ -8,8 +8,6 @@ selection method. """ -from __future__ import absolute_import - # # __COPYRIGHT__ # diff --git a/src/engine/SCons/cppTests.py b/src/engine/SCons/cppTests.py index eff7715..eb9189d 100644 --- a/src/engine/SCons/cppTests.py +++ b/src/engine/SCons/cppTests.py @@ -20,9 +20,6 @@ # 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 absolute_import - __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import atexit -- cgit v0.12 From 0a6189cb492728a839d753d1a96e96d8a6cabcf9 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 17 Feb 2020 12:32:29 -0800 Subject: Clean up collections to switch to collections.abc where possible --- src/engine/SCons/ActionTests.py | 2 -- src/engine/SCons/Builder.py | 8 ++++---- src/engine/SCons/BuilderTests.py | 4 ++-- src/engine/SCons/DefaultsTests.py | 2 -- src/engine/SCons/Tool/MSCommon/vc.py | 19 ------------------- src/engine/SCons/Tool/__init__.py | 7 +------ src/engine/SCons/Util.py | 7 ++----- 7 files changed, 9 insertions(+), 40 deletions(-) diff --git a/src/engine/SCons/ActionTests.py b/src/engine/SCons/ActionTests.py index 3303750..c61a4c7 100644 --- a/src/engine/SCons/ActionTests.py +++ b/src/engine/SCons/ActionTests.py @@ -37,10 +37,8 @@ class GlobalActFunc(object): pass -import collections import io import os -import re import sys import types import unittest diff --git a/src/engine/SCons/Builder.py b/src/engine/SCons/Builder.py index 13949e5..3f0be63 100644 --- a/src/engine/SCons/Builder.py +++ b/src/engine/SCons/Builder.py @@ -100,7 +100,7 @@ There are the following methods for internal use within this module: __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" -import collections +from collections import UserDict, UserList import SCons.Action import SCons.Debug @@ -197,7 +197,7 @@ class DictEmitter(SCons.Util.Selector): target, source = emitter(target, source, env) return (target, source) -class ListEmitter(collections.UserList): +class ListEmitter(UserList): """A callable list of emitters that calls each in sequence, returning the result. """ @@ -215,7 +215,7 @@ misleading_keywords = { 'sources' : 'source', } -class OverrideWarner(collections.UserDict): +class OverrideWarner(UserDict): """A class for warning about keyword arguments that we use as overrides in a Builder call. @@ -224,7 +224,7 @@ class OverrideWarner(collections.UserDict): warnings once, no matter how many Builders are invoked. """ def __init__(self, dict): - collections.UserDict.__init__(self, dict) + UserDict.__init__(self, dict) if SCons.Debug.track_instances: logInstanceCreation(self, 'Builder.OverrideWarner') self.already_warned = None def warn(self): diff --git a/src/engine/SCons/BuilderTests.py b/src/engine/SCons/BuilderTests.py index acdc277..2f72832 100644 --- a/src/engine/SCons/BuilderTests.py +++ b/src/engine/SCons/BuilderTests.py @@ -31,7 +31,7 @@ import SCons.compat def Func(): pass -import collections +from collections import UserList import io import os.path import re @@ -254,7 +254,7 @@ class BuilderTestCase(unittest.TestCase): assert not hasattr(n2, 'env') l = [1] - ul = collections.UserList([2]) + ul = UserList([2]) try: l.extend(ul) except TypeError: diff --git a/src/engine/SCons/DefaultsTests.py b/src/engine/SCons/DefaultsTests.py index 2cbad70..34941bc 100644 --- a/src/engine/SCons/DefaultsTests.py +++ b/src/engine/SCons/DefaultsTests.py @@ -29,8 +29,6 @@ import os import sys import unittest -from collections import UserDict - import TestCmd import SCons.Errors diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py index ed713d0..82fb6b9 100644 --- a/src/engine/SCons/Tool/MSCommon/vc.py +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -46,9 +46,6 @@ import platform import sys from string import digits as string_digits from subprocess import PIPE -#TODO: Python 2 cleanup -if sys.version_info[0] == 2: - import collections import SCons.Warnings from SCons.Tool import find_program_path @@ -697,22 +694,6 @@ def script_env(script, args=None): script_env_cache[cache_key] = cache_data # once we updated cache, give a chance to write out if user wanted common.write_script_env_cache(script_env_cache) - else: - #TODO: Python 2 cleanup - # If we "hit" data from the json file, we have a Py2 problem: - # keys & values will be unicode. don't detect, just convert. - if sys.version_info[0] == 2: - def convert(data): - if isinstance(data, basestring): - return str(data) - elif isinstance(data, collections.Mapping): - return dict(map(convert, data.iteritems())) - elif isinstance(data, collections.Iterable): - return type(data)(map(convert, data)) - else: - return data - - cache_data = convert(cache_data) return cache_data diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py index 76a0913..7331a64 100644 --- a/src/engine/SCons/Tool/__init__.py +++ b/src/engine/SCons/Tool/__init__.py @@ -41,6 +41,7 @@ import sys import re import os import shutil +from collections.abc import Callable import SCons.Builder import SCons.Errors @@ -51,12 +52,6 @@ import SCons.Scanner.D import SCons.Scanner.LaTeX import SCons.Scanner.Prog import SCons.Scanner.SWIG -try: - # Python 3 - from collections.abc import Callable -except ImportError: - # Python 2.7 - from collections import Callable DefaultToolpath = [] diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index 130cc5e..d1baab2 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -34,15 +34,12 @@ import types import codecs import pprint import hashlib +from collections import UserDict, UserList, UserString, OrderedDict +from collections.abc import Iterable, MappingView PY3 = sys.version_info[0] == 3 PYPY = hasattr(sys, 'pypy_translation_info') - -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 # types module later to look for UnicodeType. -- cgit v0.12 From 83690c61e673b91b3e35cffdbc0a010296509e05 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 17 Feb 2020 12:45:45 -0800 Subject: Fix some py3.8 warnings in doc SConscript --- doc/SConscript | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/SConscript b/doc/SConscript index ff29a70..e43a27b 100644 --- a/doc/SConscript +++ b/doc/SConscript @@ -90,7 +90,8 @@ def writeVersionXml(verfile, date, ver, rev): os.makedirs(dir) except OSError: pass # okay if the directory already exists - open(verfile, "w").write(""" @@ -105,7 +106,7 @@ man_page_list = ['scons.1','scons-time.1','sconsign.1'] # Template for the MAN page texts when we can't properly # create them because the skip_doc flag is set (required # modules/tools aren't installed in the current system) -man_replace_tpl = """.TH "%(uctitle)s" "1" "%(today)s" "SCons %(version)s" "SCons %(version)s" +man_replace_tpl = r""".TH "%(uctitle)s" "1" "%(today)s" "SCons %(version)s" "SCons %(version)s" .ie \n(.g .ds Aq \(aq .el .ds Aq ' .nh -- cgit v0.12 From 7f77bd5474b7c154d029431ed1bb38c813f6c9fb Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 17 Feb 2020 15:34:03 -0800 Subject: Fix sider issue. Simplify code by removing py27 v py35+ --- src/engine/SCons/Util.py | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index d1baab2..fa6bc06 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -35,7 +35,7 @@ import codecs import pprint import hashlib from collections import UserDict, UserList, UserString, OrderedDict -from collections.abc import Iterable, MappingView +from collections.abc import MappingView PY3 = sys.version_info[0] == 3 PYPY = hasattr(sys, 'pypy_translation_info') @@ -356,27 +356,18 @@ def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited=None): DictTypes = (dict, UserDict) ListTypes = (list, UserList) -try: - # Handle getting dictionary views. - SequenceTypes = (list, tuple, UserList, MappingView) -except NameError: - SequenceTypes = (list, tuple, UserList) +# Handle getting dictionary views. +SequenceTypes = (list, tuple, UserList, MappingView) # Note that profiling data shows a speed-up when comparing # explicitly with str and unicode instead of simply comparing # with basestring. (at least on Python 2.5.1) -try: - StringTypes = (str, unicode, UserString) -except NameError: - StringTypes = (str, UserString) +StringTypes = (str, UserString) # Empirically, it is faster to check explicitly for str and # unicode than for basestring. -try: - BaseStringTypes = (str, unicode) -except NameError: - BaseStringTypes = str +BaseStringTypes = str def is_Dict(obj, isinstance=isinstance, DictTypes=DictTypes): return isinstance(obj, DictTypes) -- cgit v0.12 From 2298a1eeb3299f852af45e31c1829b9b3a35f4f1 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 17 Feb 2020 15:55:10 -0800 Subject: remove PY3 variable from SCons.Util No longer needed --- 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 fa6bc06..0f2a27a 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -37,7 +37,6 @@ import hashlib from collections import UserDict, UserList, UserString, OrderedDict from collections.abc import MappingView -PY3 = sys.version_info[0] == 3 PYPY = hasattr(sys, 'pypy_translation_info') # Don't "from types import ..." these because we need to get at the -- cgit v0.12 From a70cd70c45384f4482b90b950e2ad49e6e50a7b7 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 17 Feb 2020 16:22:02 -0800 Subject: replace dictionary initializations with simpler logic --- src/engine/SCons/Node/FS.py | 12 +++--------- src/engine/SCons/Node/FSTests.py | 5 +---- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index 423ba76..a268020 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -1547,9 +1547,7 @@ class Dir(Base): self.repositories = [] self.srcdir = None - self.entries = {} - self.entries['.'] = self - self.entries['..'] = self.dir + self.entries = {'.': self, '..': self.dir} self.cwd = self self.searched = 0 self._sconsign = None @@ -2304,10 +2302,8 @@ class RootDir(Dir): self._morph() self.duplicate = 0 - self._lookupDict = {} + self._lookupDict = {'': self, '/': self} - self._lookupDict[''] = self - self._lookupDict['/'] = self self.root = self # The // entry is necessary because os.path.normpath() # preserves double slashes at the beginning of a path on Posix @@ -2327,9 +2323,7 @@ class RootDir(Dir): self.repositories = [] self.srcdir = None - self.entries = {} - self.entries['.'] = self - self.entries['..'] = self.dir + self.entries = {'.': self, '..': self.dir} self.cwd = self self.searched = 0 self._sconsign = None diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index 41d9381..26c71b0 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -463,10 +463,7 @@ class VariantDirTestCase(unittest.TestCase): def __init__(self, duplicate, link, symlink, copy): self.duplicate = duplicate - self.have = {} - self.have['hard'] = link - self.have['soft'] = symlink - self.have['copy'] = copy + self.have = {'hard': link, 'soft': symlink, 'copy': copy} self.links_to_be_called = [] for link in self.duplicate.split('-'): -- cgit v0.12 From b22e98ed4f611eabc05aec9aa1c991f0f918967a Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 17 Feb 2020 16:26:53 -0800 Subject: more code cleanup found by pycharm --- .../SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/docbook.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 7e6a81a..3d53bf7 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 @@ -67,9 +67,9 @@ def adjustColumnWidths(ctx, nodeset): relPart = 0.0 absPart = 0.0 - starPos = string.find(width, "*") + starPos = width.find("*") if starPos >= 0: - relPart, absPart = string.split(width, "*", 2) + relPart, absPart = width.split("*", 2) relPart = float(relPart) relTotal = relTotal + float(relPart) else: @@ -111,7 +111,7 @@ def adjustColumnWidths(ctx, nodeset): widths = correctRoundingError(widths) else: pixelWidth = nominalWidth - if string.find(tableWidth, "%") < 0: + if '%' not in tableWidth: pixelWidth = convertLength(tableWidth) if pixelWidth <= absTotal: @@ -125,7 +125,7 @@ def adjustColumnWidths(ctx, nodeset): relParts[count] = rel + absParts[count] absTotal = absTotal + rel + absParts[count] - if string.find(tableWidth, "%") < 0: + if '%' not in tableWidth: for count in range(len(relParts)): if foStylesheet: pixels = relParts[count] -- cgit v0.12 From 155c43a058bcd6fa1bccd0ed89fb778eaa598958 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 17 Feb 2020 16:27:33 -0800 Subject: more code cleanup found by pycharm --- bin/import-test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/import-test.py b/bin/import-test.py index 65b6e79..6a71a37 100644 --- a/bin/import-test.py +++ b/bin/import-test.py @@ -82,7 +82,7 @@ def print_files(dir): for dirpath, dirnames, filenames in os.walk(directory): dir = lookup(dirpath) - for f in fnames: + for f in filenames: dir.entries[f] = None subdir_list = [] -- cgit v0.12 From 5b2f62cb7d8e7b91ab0dcf6fcda830df93d54221 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 17 Feb 2020 16:29:30 -0800 Subject: Fix reference to obsolete urllib.urlretrieve, now urllib.request.urlretrieve --- bin/install_scons.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/install_scons.py b/bin/install_scons.py index ac79fd3..ed919f8 100644 --- a/bin/install_scons.py +++ b/bin/install_scons.py @@ -25,7 +25,7 @@ import os import shutil import sys import tarfile -from urllib import urlretrieve +from urllib.request import urlretrieve from Command import CommandRunner, Usage -- cgit v0.12 From 5bc5aac03463900b731b352940459ca5270c7ac5 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 17 Feb 2020 16:34:32 -0800 Subject: remove unicode reference in ActionTests.py --- src/engine/SCons/ActionTests.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/engine/SCons/ActionTests.py b/src/engine/SCons/ActionTests.py index c61a4c7..4784abf 100644 --- a/src/engine/SCons/ActionTests.py +++ b/src/engine/SCons/ActionTests.py @@ -337,14 +337,6 @@ class ActionTestCase(unittest.TestCase): # a singleton list returns the contained action test_positional_args(cmd_action, ["string"]) - try: - unicode - except NameError: - pass - else: - a2 = eval("SCons.Action.Action(u'string')") - assert isinstance(a2, SCons.Action.CommandAction), a2 - def line_action(a): assert isinstance(a, SCons.Action.CommandAction), a assert a.cmd_list == ["explicit", "command", "line"], a.cmd_list -- cgit v0.12 From d741d87697bdd305335df0e2b76c1e61d70de663 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 17 Feb 2020 16:37:38 -0800 Subject: remove unicode from dblite.py --- src/engine/SCons/dblite.py | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/src/engine/SCons/dblite.py b/src/engine/SCons/dblite.py index 8351017..5ac77a5 100644 --- a/src/engine/SCons/dblite.py +++ b/src/engine/SCons/dblite.py @@ -18,26 +18,14 @@ def corruption_warning(filename): print("Warning: Discarding corrupt database:", filename) -try: - unicode -except NameError: - def is_string(s): - return isinstance(s, str) -else: - def is_string(s): - return type(s) in (str, unicode) +def is_string(s): + return isinstance(s, str) def is_bytes(s): return isinstance(s, bytes) -try: - unicode('a') -except NameError: - def unicode(s): - return s - dblite_suffix = '.dblite' # TODO: Does commenting this out break switching from py2/3? @@ -217,23 +205,17 @@ def _exercise(): assert len(db) == 0 db["foo"] = "bar" assert db["foo"] == "bar" - db[unicode("ufoo")] = unicode("ubar") - assert db[unicode("ufoo")] == unicode("ubar") db.sync() db = open("tmp", "c") assert len(db) == 2, len(db) assert db["foo"] == "bar" db["bar"] = "foo" assert db["bar"] == "foo" - db[unicode("ubar")] = unicode("ufoo") - assert db[unicode("ubar")] == unicode("ufoo") db.sync() db = open("tmp", "r") assert len(db) == 4, len(db) assert db["foo"] == "bar" assert db["bar"] == "foo" - assert db[unicode("ufoo")] == unicode("ubar") - assert db[unicode("ubar")] == unicode("ufoo") try: db.sync() except IOError as e: -- cgit v0.12 From d750da6bcc95931b0f492c318c6937b6016b73a4 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 17 Feb 2020 16:39:11 -0800 Subject: removing unicode from UtilTests.py --- src/engine/SCons/UtilTests.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/engine/SCons/UtilTests.py b/src/engine/SCons/UtilTests.py index ee07e61..4968a77 100644 --- a/src/engine/SCons/UtilTests.py +++ b/src/engine/SCons/UtilTests.py @@ -313,7 +313,7 @@ class UtilTestCase(unittest.TestCase): """ Test the to_Bytes method""" self.assertEqual(to_bytes('Hello'), bytearray('Hello', 'utf-8'), - "Check that to_bytes creates byte array when presented with unicode string.") + "Check that to_bytes creates byte array when presented with non byte string.") def test_to_String(self): """Test the to_String() method.""" @@ -761,9 +761,6 @@ bling def test_intern(self): s1 = silent_intern("spam") - # TODO: Python 3.x does not have a unicode() global function - if sys.version[0] == '2': - s2 = silent_intern(unicode("unicode spam")) s3 = silent_intern(42) s4 = silent_intern("spam") assert id(s1) == id(s4) -- cgit v0.12 From 31406d8059594246bff3f5cca945f82301cc8c32 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 17 Feb 2020 16:45:06 -0800 Subject: More unicode removal and cleanup --- src/engine/SCons/Util.py | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index 0f2a27a..22df6fa 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -39,9 +39,6 @@ from collections.abc import MappingView PYPY = hasattr(sys, 'pypy_translation_info') -# Don't "from types import ..." these because we need to get at the -# types module later to look for UnicodeType. - # Below not used? # InstanceType = types.InstanceType @@ -358,14 +355,13 @@ ListTypes = (list, UserList) # Handle getting dictionary views. SequenceTypes = (list, tuple, UserList, MappingView) - +# TODO: PY3 check this benchmarking is still correct. # Note that profiling data shows a speed-up when comparing -# explicitly with str and unicode instead of simply comparing +# explicitly with str instead of simply comparing # with basestring. (at least on Python 2.5.1) StringTypes = (str, UserString) -# Empirically, it is faster to check explicitly for str and -# unicode than for basestring. +# Empirically, it is faster to check explicitly for str than for basestring. BaseStringTypes = str def is_Dict(obj, isinstance=isinstance, DictTypes=DictTypes): @@ -434,24 +430,25 @@ def flatten_sequence(sequence, isinstance=isinstance, StringTypes=StringTypes, do_flatten(item, result) return result -# Generic convert-to-string functions that abstract away whether or -# not the Python we're executing has Unicode support. The wrapper +# Generic convert-to-string functions. The wrapper # to_String_for_signature() will use a for_signature() method if the # specified object has one. # + + def to_String(s, isinstance=isinstance, str=str, UserString=UserString, BaseStringTypes=BaseStringTypes): - if isinstance(s,BaseStringTypes): + if isinstance(s, BaseStringTypes): # Early out when already a string! return s elif isinstance(s, UserString): - # s.data can only be either a unicode or a regular - # string. Please see the UserString initializer. + # s.data can only be a regular string. Please see the UserString initializer. return s.data else: return str(s) + def to_String_for_subst(s, isinstance=isinstance, str=str, to_String=to_String, BaseStringTypes=BaseStringTypes, SequenceTypes=SequenceTypes, @@ -463,12 +460,12 @@ def to_String_for_subst(s, elif isinstance(s, SequenceTypes): return ' '.join([to_String_for_subst(e) for e in s]) elif isinstance(s, UserString): - # s.data can only be either a unicode or a regular - # string. Please see the UserString initializer. + # s.data can only a regular string. Please see the UserString initializer. return s.data else: return str(s) + def to_String_for_signature(obj, to_String_for_subst=to_String_for_subst, AttributeError=AttributeError): try: @@ -478,6 +475,7 @@ def to_String_for_signature(obj, to_String_for_subst=to_String_for_subst, # pprint will output dictionary in key sorted order # with py3.5 the order was randomized. In general depending on dictionary order # which was undefined until py3.6 (where it's by insertion order) was not wise. + # TODO: Change code when floor is raised to PY36 return pprint.pformat(obj, width=1000000) else: return to_String_for_subst(obj) @@ -1495,7 +1493,7 @@ def MD5collect(signatures): def silent_intern(x): """ Perform sys.intern() on the passed argument and return the result. - If the input is ineligible (e.g. a unicode string) the original argument is + If the input is ineligible the original argument is returned and no exception is thrown. """ try: -- cgit v0.12 From d447cda50da33619e221e49b8f62f8723483e312 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 17 Feb 2020 16:47:03 -0800 Subject: more unicode cleanup --- src/engine/SCons/BuilderTests.py | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/engine/SCons/BuilderTests.py b/src/engine/SCons/BuilderTests.py index 2f72832..d509219 100644 --- a/src/engine/SCons/BuilderTests.py +++ b/src/engine/SCons/BuilderTests.py @@ -306,22 +306,6 @@ class BuilderTestCase(unittest.TestCase): #be = target.get_build_env() #assert be['VAR'] == 'foo', be['VAR'] - try: unicode - except NameError: - uni = str - else: - uni = unicode - - target = builder(env, target = uni('n12 n13'), - source = [uni('n14 n15')])[0] - assert target.name == uni('n12 n13') - assert target.sources[0].name == uni('n14 n15') - - target = builder(env, target = [uni('n16 n17')], - source = uni('n18 n19'))[0] - assert target.name == uni('n16 n17') - assert target.sources[0].name == uni('n18 n19') - n20 = MyNode_without_target_from_source('n20') flag = 0 try: -- cgit v0.12 From 30394eb96f38142120beb4548918be4d5193f71e Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 17 Feb 2020 16:52:47 -0800 Subject: more unicode cleanup --- src/engine/SCons/Platform/win32.py | 3 --- src/engine/SCons/SConfTests.py | 10 +--------- src/engine/SCons/Scanner/ProgTests.py | 17 +---------------- 3 files changed, 2 insertions(+), 28 deletions(-) diff --git a/src/engine/SCons/Platform/win32.py b/src/engine/SCons/Platform/win32.py index bb1b46d..3258dfd 100644 --- a/src/engine/SCons/Platform/win32.py +++ b/src/engine/SCons/Platform/win32.py @@ -307,9 +307,6 @@ def get_system_root(): except: pass - # Ensure system root is a string and not unicode - # (This only matters for py27 were unicode in env passed to POpen fails) - val = str(val) _system_root = val return val diff --git a/src/engine/SCons/SConfTests.py b/src/engine/SCons/SConfTests.py index 40cd69d..63ec8f1 100644 --- a/src/engine/SCons/SConfTests.py +++ b/src/engine/SCons/SConfTests.py @@ -307,10 +307,6 @@ int main(void) { return None def actionFAIL(target, source, env): return 1 - def actionUnicode(target, source, env): - with open(str(target[0]), "wb") as f: - f.write('2\302\242\n') - return None self._resetSConfState() @@ -319,14 +315,10 @@ int main(void) { log_file=self.test.workpath('config.log')) try: (ret, output) = sconf.TryAction(action=actionOK) - assert ret and output.encode('utf-8') == bytearray("RUN OK"+os.linesep,'utf-8'), (ret, output) + assert ret and output.encode('utf-8') == bytearray("RUN OK"+os.linesep, 'utf-8'), (ret, output) (ret, output) = sconf.TryAction(action=actionFAIL) assert not ret and output == "", (ret, output) - if not TestCmd.IS_PY3: - # GH Issue #3141 - unicode text and py2.7 crashes. - (ret, output) = sconf.TryAction(action=actionUnicode) - assert ret and output == u'2\xa2\n', (ret, output) finally: sconf.Finish() diff --git a/src/engine/SCons/Scanner/ProgTests.py b/src/engine/SCons/Scanner/ProgTests.py index 45fdcb2..8981fd4 100644 --- a/src/engine/SCons/Scanner/ProgTests.py +++ b/src/engine/SCons/Scanner/ProgTests.py @@ -43,6 +43,7 @@ libs = [ 'l1.lib', 'd1/l2.lib', 'd1/d2/l3.lib', for h in libs: test.write(h, "\n") + # define some helpers: class DummyEnvironment(object): @@ -254,22 +255,6 @@ def suite(): suite.addTest(ProgramScannerTestCase8()) suite.addTest(ProgramScannerTestCase9()) suite.addTest(ProgramScannerTestCase10()) - try: unicode - except NameError: pass - else: - code = """if 1: - class ProgramScannerTestCase4(unittest.TestCase): - def runTest(self): - env = DummyEnvironment(LIBPATH=[test.workpath("d1/d2"), - test.workpath("d1")], - LIBS=u'l2 l3'.split()) - s = SCons.Scanner.Prog.ProgramScanner() - path = s.path(env) - deps = s(DummyNode('dummy'), env, path) - assert deps_match(deps, ['d1/l2.lib', 'd1/d2/l3.lib']), map(str, deps) - suite.addTest(ProgramScannerTestCase4()) - \n""" - exec(code) return suite if __name__ == "__main__": -- cgit v0.12 From 46fc8314b5956313f4f7a3f3cbaf970f6f8616f5 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 17 Feb 2020 16:57:44 -0800 Subject: more unicode cleanup --- src/engine/SCons/Action.py | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index c6fc575..b22de60 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -628,17 +628,9 @@ class _ActionAction(ActionBase): """ In python 3, and in some of our tests, sys.stdout is a String io object, and it takes unicode strings only - In other cases it's a regular Python 2.x file object - which takes strings (bytes), and if you pass those a - unicode object they try to decode with 'ascii' codec - which fails if the cmd line has any hi-bit-set chars. - This code assumes s is a regular string, but should - work if it's unicode too. + This code assumes s is a regular string. """ - try: - sys.stdout.write(s + u"\n") - except UnicodeDecodeError: - sys.stdout.write(s + "\n") + sys.stdout.write(s + "\n") def __call__(self, target, source, env, exitstatfunc=_null, -- cgit v0.12 From 8b939d89c0b3483ef1cc3e78eb6f58bd7f041fd6 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 17 Feb 2020 20:43:29 -0800 Subject: More post py27 cleanup. Remove no-op function calls. Fix _exercise() built in test to complete --- src/engine/SCons/dblite.py | 57 +++++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 26 deletions(-) diff --git a/src/engine/SCons/dblite.py b/src/engine/SCons/dblite.py index 5ac77a5..765516c 100644 --- a/src/engine/SCons/dblite.py +++ b/src/engine/SCons/dblite.py @@ -18,14 +18,6 @@ def corruption_warning(filename): print("Warning: Discarding corrupt database:", filename) -def is_string(s): - return isinstance(s, str) - - -def is_bytes(s): - return isinstance(s, bytes) - - dblite_suffix = '.dblite' # TODO: Does commenting this out break switching from py2/3? @@ -170,10 +162,13 @@ class dblite(object): def __setitem__(self, key, value): self._check_writable() - if not is_string(key): + + if not isinstance(key, str): raise TypeError("key `%s' must be a string but is %s" % (key, type(key))) - if not is_bytes(value): + + if not isinstance(value, bytes): raise TypeError("value `%s' must be a bytes but is %s" % (value, type(value))) + self._dict[key] = value self._needs_sync = 0o001 @@ -203,19 +198,21 @@ def open(file, flag=None, mode=0o666): def _exercise(): db = open("tmp", "n") assert len(db) == 0 - db["foo"] = "bar" - assert db["foo"] == "bar" + db["foo"] = b"bar" + assert db["foo"] == b"bar" db.sync() + db = open("tmp", "c") - assert len(db) == 2, len(db) - assert db["foo"] == "bar" - db["bar"] = "foo" - assert db["bar"] == "foo" + assert len(db) == 1, len(db) + assert db["foo"] == b"bar" + db["bar"] = b"foo" + assert db["bar"] == b"foo" db.sync() + db = open("tmp", "r") - assert len(db) == 4, len(db) - assert db["foo"] == "bar" - assert db["bar"] == "foo" + assert len(db) == 2, len(db) + assert db["foo"] == b"bar" + assert db["bar"] == b"foo" try: db.sync() except IOError as e: @@ -223,26 +220,31 @@ def _exercise(): else: raise RuntimeError("IOError expected.") db = open("tmp", "w") - assert len(db) == 4 - db["ping"] = "pong" + assert len(db) == 2, len(db) + db["ping"] = b"pong" db.sync() + try: db[(1, 2)] = "tuple" except TypeError as e: - assert str(e) == "key `(1, 2)' must be a string but is ", str(e) + assert str(e) == "key `(1, 2)' must be a string but is ", str(e) else: raise RuntimeError("TypeError exception expected") + try: db["list"] = [1, 2] except TypeError as e: - assert str(e) == "value `[1, 2]' must be a string but is ", str(e) + assert str(e) == "value `[1, 2]' must be a bytes but is ", str(e) else: raise RuntimeError("TypeError exception expected") + db = open("tmp", "r") - assert len(db) == 5 + assert len(db) == 3, len(db) + db = open("tmp", "n") - assert len(db) == 0 + assert len(db) == 0, len(db) dblite._open("tmp.dblite", "w") + db = open("tmp", "r") dblite._open("tmp.dblite", "w").write("x") try: @@ -251,10 +253,11 @@ def _exercise(): pass else: raise RuntimeError("pickle exception expected.") + global ignore_corrupt_dbfiles ignore_corrupt_dbfiles = 2 db = open("tmp", "r") - assert len(db) == 0 + assert len(db) == 0, len(db) os.unlink("tmp.dblite") try: db = open("tmp", "w") @@ -263,6 +266,8 @@ def _exercise(): else: raise RuntimeError("IOError expected.") + print("Completed _exercise()") + if __name__ == "__main__": _exercise() -- cgit v0.12 From 987f563b8cd16f146c2ee8b8f1617d8954aab810 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 17 Feb 2020 20:56:18 -0800 Subject: more post py27 cleanup --- src/engine/SCons/Node/FS.py | 21 ++--- src/engine/SCons/Platform/win32.py | 40 --------- src/engine/SCons/SConfTests.py | 12 --- src/engine/SCons/Taskmaster.py | 15 ++-- src/engine/SCons/Tool/__init__.py | 178 +++++++++++++++---------------------- 5 files changed, 84 insertions(+), 182 deletions(-) diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index a268020..1a5bd1b 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -42,6 +42,7 @@ import sys import time import codecs from itertools import chain +import importlib.util import SCons.Action import SCons.Debug @@ -1425,22 +1426,10 @@ class FS(LocalFS): This can be useful when we want to determine a toolpath based on a python module name""" dirpath = '' - if sys.version_info[0] < 3 or (sys.version_info[0] == 3 and sys.version_info[1] in (0,1,2,3,4)): - # Python2 Code - import imp - splitname = modulename.split('.') - srchpths = sys.path - for item in splitname: - file, path, desc = imp.find_module(item, srchpths) - if file is not None: - path = os.path.dirname(path) - srchpths = [path] - dirpath = path - else: - # Python3 Code - import importlib.util - modspec = importlib.util.find_spec(modulename) - dirpath = os.path.dirname(modspec.origin) + + # Python3 Code + modspec = importlib.util.find_spec(modulename) + dirpath = os.path.dirname(modspec.origin) return self._lookup(dirpath, None, Dir, True) diff --git a/src/engine/SCons/Platform/win32.py b/src/engine/SCons/Platform/win32.py index 3258dfd..afe2df9 100644 --- a/src/engine/SCons/Platform/win32.py +++ b/src/engine/SCons/Platform/win32.py @@ -62,46 +62,6 @@ except AttributeError: else: parallel_msg = None - if sys.version_info.major == 2: - import __builtin__ - - _builtin_file = __builtin__.file - _builtin_open = __builtin__.open - - def _scons_fixup_mode(mode): - """Adjust 'mode' to mark handle as non-inheritable. - - SCons is multithreaded, so allowing handles to be inherited by - children opens us up to races, where (e.g.) processes spawned by - the Taskmaster may inherit and retain references to files opened - by other threads. This may lead to sharing violations and, - ultimately, build failures. - - By including 'N' as part of fopen's 'mode' parameter, all file - handles returned from these functions are atomically marked as - non-inheritable. - """ - if not mode: - # Python's default is 'r'. - # https://docs.python.org/2/library/functions.html#open - mode = 'rN' - elif 'N' not in mode: - mode += 'N' - return mode - - class _scons_file(_builtin_file): - def __init__(self, name, mode=None, *args, **kwargs): - _builtin_file.__init__(self, name, _scons_fixup_mode(mode), - *args, **kwargs) - - def _scons_open(name, mode=None, *args, **kwargs): - return _builtin_open(name, _scons_fixup_mode(mode), - *args, **kwargs) - - __builtin__.file = _scons_file - __builtin__.open = _scons_open - - if False: # Now swap out shutil.filecopy and filecopy2 for win32 api native CopyFile diff --git a/src/engine/SCons/SConfTests.py b/src/engine/SCons/SConfTests.py index 63ec8f1..e2b9133 100644 --- a/src/engine/SCons/SConfTests.py +++ b/src/engine/SCons/SConfTests.py @@ -56,18 +56,6 @@ class SConfTestCase(unittest.TestCase): os.chdir(self.save_cwd) def _resetSConfState(self): - if sys.platform in ['cygwin', 'win32'] and sys.version_info.major == 2: - # On Windows with Python2, SCons.Platform.win32 redefines the - # built-in file() and open() functions to disable handle - # inheritance. Because we are unloading all SCons modules other - # than SCons.Compat, SCons.Platform.win32 will lose the variables - # it needs. As a result, we should reset the file() and open() - # functions to their original built-in versions. - import __builtin__ - import SCons.Platform.win32 - __builtin__.file = SCons.Platform.win32._builtin_file - __builtin__.open = SCons.Platform.win32._builtin_open - # Ok, this is tricky, and i do not know, if everything is sane. # We try to reset scons' state (including all global variables) import SCons.SConsign diff --git a/src/engine/SCons/Taskmaster.py b/src/engine/SCons/Taskmaster.py index 2bbb732..d04b585 100644 --- a/src/engine/SCons/Taskmaster.py +++ b/src/engine/SCons/Taskmaster.py @@ -553,15 +553,12 @@ class Task(object): exc_traceback = None # raise exc_type(exc_value).with_traceback(exc_traceback) - if sys.version_info[0] == 2: - exec("raise exc_type, exc_value, exc_traceback") - else: # sys.version_info[0] == 3: - if isinstance(exc_value, Exception): #hasattr(exc_value, 'with_traceback'): - # If exc_value is an exception, then just reraise - exec("raise exc_value.with_traceback(exc_traceback)") - else: - # else we'll create an exception using the value and raise that - exec("raise exc_type(exc_value).with_traceback(exc_traceback)") + if isinstance(exc_value, Exception): #hasattr(exc_value, 'with_traceback'): + # If exc_value is an exception, then just reraise + raise exc_value.with_traceback(exc_traceback) + else: + # else we'll create an exception using the value and raise that + raise exc_type(exc_value).with_traceback(exc_traceback) # raise e.__class__, e.__class__(e), sys.exc_info()[2] diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py index 7331a64..4cb77c0 100644 --- a/src/engine/SCons/Tool/__init__.py +++ b/src/engine/SCons/Tool/__init__.py @@ -38,10 +38,9 @@ tool definition. __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import sys -import re import os -import shutil from collections.abc import Callable +import importlib.util import SCons.Builder import SCons.Errors @@ -137,112 +136,81 @@ class Tool(object): sys.path = self.toolpath + sys.path # sys.stderr.write("Tool:%s\nPATH:%s\n"%(self.name,sys.path)) - if sys.version_info[0] < 3 or (sys.version_info[0] == 3 and sys.version_info[1] in (0, 1, 2, 3, 4)): - # Py 2 code - try: - try: - file = None - try: - mod, file = self._load_dotted_module_py2(self.name, self.name, self.toolpath) - return mod - finally: - if file: - file.close() - except ImportError as e: - splitname = self.name.split('.') - if str(e) != "No module named %s" % splitname[0]: - raise SCons.Errors.SConsEnvironmentError(e) - try: - import zipimport - except ImportError: - pass - else: - for aPath in self.toolpath: - try: - importer = zipimport.zipimporter(aPath) - return importer.load_module(self.name) - except ImportError as e: - pass - finally: - sys.path = oldpythonpath - elif sys.version_info[1] > 4: - # From: http://stackoverflow.com/questions/67631/how-to-import-a-module-given-the-full-path/67692#67692 - # import importlib.util - # spec = importlib.util.spec_from_file_location("module.name", "/path/to/file.py") - # foo = importlib.util.module_from_spec(spec) - # spec.loader.exec_module(foo) - # foo.MyClass() - # Py 3 code - - # import pdb; pdb.set_trace() - import importlib.util - - # sys.stderr.write("toolpath:%s\n" % self.toolpath) - # sys.stderr.write("SCONS.TOOL path:%s\n" % sys.modules['SCons.Tool'].__path__) - debug = False - spec = None - found_name = self.name - add_to_scons_tools_namespace = False - for path in self.toolpath: - sepname = self.name.replace('.', os.path.sep) - file_path = os.path.join(path, "%s.py" % sepname) - file_package = os.path.join(path, sepname) - - if debug: sys.stderr.write("Trying:%s %s\n" % (file_path, file_package)) - - if os.path.isfile(file_path): - spec = importlib.util.spec_from_file_location(self.name, file_path) - if debug: print("file_Path:%s FOUND" % file_path) - break - elif os.path.isdir(file_package): - file_package = os.path.join(file_package, '__init__.py') - spec = importlib.util.spec_from_file_location(self.name, file_package) - if debug: print("PACKAGE:%s Found" % file_package) - break - - else: - continue - - if spec is None: - if debug: sys.stderr.write("NO SPEC :%s\n" % self.name) - spec = importlib.util.find_spec("." + self.name, package='SCons.Tool') - if spec: - found_name = 'SCons.Tool.' + self.name - add_to_scons_tools_namespace = True - if debug: sys.stderr.write("Spec Found? .%s :%s\n" % (self.name, spec)) - - if spec is None: - error_string = "No module named %s" % self.name - raise SCons.Errors.SConsEnvironmentError(error_string) - - module = importlib.util.module_from_spec(spec) - if module is None: - if debug: print("MODULE IS NONE:%s" % self.name) - error_string = "No module named %s" % self.name - raise SCons.Errors.SConsEnvironmentError(error_string) - - # Don't reload a tool we already loaded. - sys_modules_value = sys.modules.get(found_name, False) - - found_module = None - if sys_modules_value and sys_modules_value.__file__ == spec.origin: - found_module = sys.modules[found_name] + # From: http://stackoverflow.com/questions/67631/how-to-import-a-module-given-the-full-path/67692#67692 + # import importlib.util + # spec = importlib.util.spec_from_file_location("module.name", "/path/to/file.py") + # foo = importlib.util.module_from_spec(spec) + # spec.loader.exec_module(foo) + # foo.MyClass() + # Py 3 code + + + # sys.stderr.write("toolpath:%s\n" % self.toolpath) + # sys.stderr.write("SCONS.TOOL path:%s\n" % sys.modules['SCons.Tool'].__path__) + debug = False + spec = None + found_name = self.name + add_to_scons_tools_namespace = False + for path in self.toolpath: + sepname = self.name.replace('.', os.path.sep) + file_path = os.path.join(path, "%s.py" % sepname) + file_package = os.path.join(path, sepname) + + if debug: sys.stderr.write("Trying:%s %s\n" % (file_path, file_package)) + + if os.path.isfile(file_path): + spec = importlib.util.spec_from_file_location(self.name, file_path) + if debug: print("file_Path:%s FOUND" % file_path) + break + elif os.path.isdir(file_package): + file_package = os.path.join(file_package, '__init__.py') + spec = importlib.util.spec_from_file_location(self.name, file_package) + if debug: print("PACKAGE:%s Found" % file_package) + break + else: - # Not sure what to do in the case that there already - # exists sys.modules[self.name] but the source file is - # different.. ? - module = spec.loader.load_module(spec.name) - - sys.modules[found_name] = module - if add_to_scons_tools_namespace: - # If we found it in SCons.Tool, then add it to the module - setattr(SCons.Tool, self.name, module) + continue + + if spec is None: + if debug: sys.stderr.write("NO SPEC :%s\n" % self.name) + spec = importlib.util.find_spec("." + self.name, package='SCons.Tool') + if spec: + found_name = 'SCons.Tool.' + self.name + add_to_scons_tools_namespace = True + if debug: sys.stderr.write("Spec Found? .%s :%s\n" % (self.name, spec)) + + if spec is None: + error_string = "No module named %s" % self.name + raise SCons.Errors.SConsEnvironmentError(error_string) + + module = importlib.util.module_from_spec(spec) + if module is None: + if debug: print("MODULE IS NONE:%s" % self.name) + error_string = "No module named %s" % self.name + raise SCons.Errors.SConsEnvironmentError(error_string) + + # Don't reload a tool we already loaded. + sys_modules_value = sys.modules.get(found_name, False) + + found_module = None + if sys_modules_value and sys_modules_value.__file__ == spec.origin: + found_module = sys.modules[found_name] + else: + # Not sure what to do in the case that there already + # exists sys.modules[self.name] but the source file is + # different.. ? + module = spec.loader.load_module(spec.name) + + sys.modules[found_name] = module + if add_to_scons_tools_namespace: + # If we found it in SCons.Tool, then add it to the module + setattr(SCons.Tool, self.name, module) - found_module = module + found_module = module - if found_module is not None: - sys.path = oldpythonpath - return found_module + if found_module is not None: + sys.path = oldpythonpath + return found_module sys.path = oldpythonpath -- cgit v0.12 From b3589ce0a14ca9cc3ac67ee5d1a2d6ff92d4c6b0 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 18 Feb 2020 10:32:23 -0800 Subject: Remove u' u" from strings. no longer needed --- src/engine/SCons/Action.py | 2 +- src/engine/SCons/Environment.py | 2 +- src/engine/SCons/EnvironmentTests.py | 5 ----- src/engine/SCons/JobTests.py | 4 ++-- src/engine/SCons/Node/FS.py | 2 +- src/engine/SCons/Node/FSTests.py | 22 +++++----------------- src/engine/SCons/Scanner/ScannerTests.py | 2 +- src/engine/SCons/Taskmaster.py | 24 ++++++++++++------------ src/engine/SCons/UtilTests.py | 2 +- 9 files changed, 24 insertions(+), 41 deletions(-) diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index b22de60..0b7282c 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -669,7 +669,7 @@ class _ActionAction(ActionBase): source = executor.get_all_sources() t = ' and '.join(map(str, target)) l = '\n '.join(self.presub_lines(env)) - out = u"Building %s with action:\n %s\n" % (t, l) + out = "Building %s with action:\n %s\n" % (t, l) sys.stdout.write(out) cmd = None if show and self.strfunction: diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 5e76e35..00379e1 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -584,7 +584,7 @@ class SubstitutionEnvironment(object): out,err = p.communicate() status = p.wait() if err: - sys.stderr.write(u"" + err) + sys.stderr.write("" + err) if status: raise OSError("'%s' exited %d" % (command, status)) return out diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index 3db6499..a9ec674 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -262,11 +262,6 @@ class SubstitutionTestCase(unittest.TestCase): assert isinstance(nodes[0], X) assert nodes[0].name == "Util.py UtilTests.py", nodes[0].name - nodes = env.arg2nodes(u"Util.py UtilTests.py", Factory) - assert len(nodes) == 1, nodes - assert isinstance(nodes[0], X) - assert nodes[0].name == u"Util.py UtilTests.py", nodes[0].name - nodes = env.arg2nodes(["Util.py", "UtilTests.py"], Factory) assert len(nodes) == 2, nodes assert isinstance(nodes[0], X) diff --git a/src/engine/SCons/JobTests.py b/src/engine/SCons/JobTests.py index 2e3af4f..9c9bb41 100644 --- a/src/engine/SCons/JobTests.py +++ b/src/engine/SCons/JobTests.py @@ -42,8 +42,8 @@ def get_cpu_nums(): ncpus = os.sysconf( "SC_NPROCESSORS_ONLN" ) if isinstance(ncpus, int) and ncpus > 0: return ncpus - else: # OSX: - return int( os.popen2( "sysctl -n hw.ncpu")[1].read() ) + else: # OSX: + 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"]) diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index 1a5bd1b..bb965db 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -3727,7 +3727,7 @@ class FileFinder(object): if verbose and not callable(verbose): if not SCons.Util.is_String(verbose): verbose = "find_file" - _verbose = u' %s: ' % verbose + _verbose = ' %s: ' % verbose verbose = lambda s: sys.stdout.write(_verbose + s) filedir, filename = os.path.split(filename) diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index 26c71b0..3f2cb0e 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -1342,11 +1342,10 @@ class FSTestCase(_tempdirTestCase): assert f1.get_contents() == bytearray("Foo\x1aBar", 'utf-8'), f1.get_contents() # This tests to make sure we can decode UTF-8 text files. - test_string = u"Foo\x1aBar" + test_string = "Foo\x1aBar" test.write("utf8_file", test_string.encode('utf-8')) f1 = fs.File(test.workpath("utf8_file")) - assert eval('f1.get_text_contents() == u"Foo\x1aBar"'), \ - f1.get_text_contents() + f1.get_text_contents() == "Foo\x1aBar", f1.get_text_contents() # Check for string which doesn't have BOM and isn't valid # ASCII @@ -1444,7 +1443,7 @@ class FSTestCase(_tempdirTestCase): c = e.get_text_contents() try: - eval('assert c == u"", c') + eval('assert c == "", c') except SyntaxError: assert c == "" @@ -1455,10 +1454,7 @@ class FSTestCase(_tempdirTestCase): assert e.__class__ == SCons.Node.FS.Entry, e.__class__ assert c == "", c c = e.get_text_contents() - try: - eval('assert c == u"", c') - except SyntaxError: - assert c == "", c + assert c == "", c test.write("tstamp", "tstamp\n") try: @@ -3311,15 +3307,7 @@ class RepositoryTestCase(_tempdirTestCase): # Use a test string that has a file terminator in it to make # sure we read the entire file, regardless of its contents. - try: - eval('test_string = u"Con\x1aTents\n"') - except SyntaxError: - import collections - class FakeUnicodeString(collections.UserString): - def encode(self, encoding): - return str(self) - - test_string = FakeUnicodeString("Con\x1aTents\n") + test_string = "Con\x1aTents\n" # Test with ASCII. test.write(["rep3", "contents"], test_string.encode('ascii')) diff --git a/src/engine/SCons/Scanner/ScannerTests.py b/src/engine/SCons/Scanner/ScannerTests.py index abe4042..6206af9 100644 --- a/src/engine/SCons/Scanner/ScannerTests.py +++ b/src/engine/SCons/Scanner/ScannerTests.py @@ -599,7 +599,7 @@ class ClassicCPPTestCase(unittest.TestCase): assert n == 'path/bbb', n assert i == 'bbb', i - n, i = s.find_include(('<', u'ccc'), 'foo', ('path',)) + n, i = s.find_include(('<', 'ccc'), 'foo', ('path',)) assert n == 'path/ccc', n assert i == 'ccc', i diff --git a/src/engine/SCons/Taskmaster.py b/src/engine/SCons/Taskmaster.py index d04b585..6ca0e03 100644 --- a/src/engine/SCons/Taskmaster.py +++ b/src/engine/SCons/Taskmaster.py @@ -169,7 +169,7 @@ class Task(object): """ global print_prepare T = self.tm.trace - if T: T.write(self.trace_message(u'Task.prepare()', self.node)) + if T: T.write(self.trace_message('Task.prepare()', self.node)) # Now that it's the appropriate time, give the TaskMaster a # chance to raise any exceptions it encountered while preparing @@ -231,7 +231,7 @@ class Task(object): prepare(), executed() or failed(). """ T = self.tm.trace - if T: T.write(self.trace_message(u'Task.execute()', self.node)) + if T: T.write(self.trace_message('Task.execute()', self.node)) try: cached_targets = [] @@ -397,7 +397,7 @@ class Task(object): """ global print_prepare T = self.tm.trace - if T: T.write(self.trace_message(u'Task.make_ready_current()', + if T: T.write(self.trace_message('Task.make_ready_current()', self.node)) self.out_of_date = [] @@ -445,7 +445,7 @@ class Task(object): that can be put back on the candidates list. """ T = self.tm.trace - if T: T.write(self.trace_message(u'Task.postprocess()', self.node)) + if T: T.write(self.trace_message('Task.postprocess()', self.node)) # We may have built multiple targets, some of which may have # common parents waiting for this build. Count up how many @@ -462,7 +462,7 @@ class Task(object): # A node can only be in the pending_children set if it has # some waiting_parents. if t.waiting_parents: - if T: T.write(self.trace_message(u'Task.postprocess()', + if T: T.write(self.trace_message('Task.postprocess()', t, 'removing')) pending_children.discard(t) @@ -491,7 +491,7 @@ class Task(object): for p, subtract in parents.items(): p.ref_count = p.ref_count - subtract - if T: T.write(self.trace_message(u'Task.postprocess()', + if T: T.write(self.trace_message('Task.postprocess()', p, 'adjusted parent ref count')) if p.ref_count == 0: @@ -792,7 +792,7 @@ class Taskmaster(object): while True: node = self.next_candidate() if node is None: - if T: T.write(self.trace_message('No candidate anymore.') + u'\n') + if T: T.write(self.trace_message('No candidate anymore.') + '\n') return None node = node.disambiguate() @@ -815,7 +815,7 @@ class Taskmaster(object): else: S = None - if T: T.write(self.trace_message(u' Considering node %s and its children:' % self.trace_node(node))) + if T: T.write(self.trace_message(' Considering node %s and its children:' % self.trace_node(node))) if state == NODE_NO_STATE: # Mark this node as being on the execution stack: @@ -823,7 +823,7 @@ class Taskmaster(object): elif state > NODE_PENDING: # Skip this node if it has already been evaluated: if S: S.already_handled = S.already_handled + 1 - if T: T.write(self.trace_message(u' already handled (executed)')) + if T: T.write(self.trace_message(' already handled (executed)')) continue executor = node.get_executor() @@ -854,7 +854,7 @@ class Taskmaster(object): for child in chain(executor.get_all_prerequisites(), children): childstate = child.get_state() - if T: T.write(self.trace_message(u' ' + self.trace_node(child))) + if T: T.write(self.trace_message(' ' + self.trace_node(child))) if childstate == NODE_NO_STATE: children_not_visited.append(child) @@ -915,7 +915,7 @@ class Taskmaster(object): # count so we can be put back on the list for # re-evaluation when they've all finished. node.ref_count = node.ref_count + child.add_to_waiting_parents(node) - if T: T.write(self.trace_message(u' adjusted ref count: %s, child %s' % + if T: T.write(self.trace_message(' adjusted ref count: %s, child %s' % (self.trace_node(node), repr(str(child))))) if T: @@ -941,7 +941,7 @@ class Taskmaster(object): # The default when we've gotten through all of the checks above: # this node is ready to be built. if S: S.build = S.build + 1 - if T: T.write(self.trace_message(u'Evaluating %s\n' % + if T: T.write(self.trace_message('Evaluating %s\n' % self.trace_node(node))) # For debugging only: diff --git a/src/engine/SCons/UtilTests.py b/src/engine/SCons/UtilTests.py index 4968a77..d96b63f 100644 --- a/src/engine/SCons/UtilTests.py +++ b/src/engine/SCons/UtilTests.py @@ -740,7 +740,7 @@ class UtilTestCase(unittest.TestCase): def test_LogicalLines(self): """Test the LogicalLines class""" - content = u""" + content = """ foo \\ bar \\ baz -- cgit v0.12 From e66f178d42d9d6f323be8884c8d1e80e3936d0a3 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 18 Feb 2020 10:36:54 -0800 Subject: more unicode cleanup post py27 --- testing/framework/TestCmd.py | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/testing/framework/TestCmd.py b/testing/framework/TestCmd.py index 6beed24..f29449f 100644 --- a/testing/framework/TestCmd.py +++ b/testing/framework/TestCmd.py @@ -358,14 +358,8 @@ def to_str(s): return str(s, 'utf-8') -try: - eval('unicode') -except NameError: - def is_String(e): - return isinstance(e, (str, UserString)) -else: - def is_String(e): - return isinstance(e, (str, unicode, UserString)) +def is_String(e): + return isinstance(e, (str, UserString)) testprefix = 'testcmd.' if os.name in ('posix', 'nt'): @@ -1094,7 +1088,7 @@ class TestCmd(object): condition = self.condition if self._preserve[condition]: for dir in self._dirlist: - print(u"Preserved directory " + dir) + print("Preserved directory " + dir) else: list = self._dirlist[:] list.reverse() @@ -1536,7 +1530,6 @@ class TestCmd(object): return stream - def finish(self, popen=None, **kw): """ Finishes and waits for the process being run under control of -- cgit v0.12 From 73a6eb497276e8ed8b8c81204d8b25a728ac84e9 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 18 Feb 2020 11:33:37 -0800 Subject: Update TestCommonTests.py to work with py35+ changes --- testing/framework/TestCommonTests.py | 48 +++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/testing/framework/TestCommonTests.py b/testing/framework/TestCommonTests.py index c54f33f..6377737 100644 --- a/testing/framework/TestCommonTests.py +++ b/testing/framework/TestCommonTests.py @@ -45,10 +45,9 @@ def lstrip(s): lines = [ l[spaces:] for l in lines ] return '\n'.join(lines) -if sys.version[:3] == '1.5': - expected_newline = '\\012' -else: - expected_newline = '\\n' + +expected_newline = '\\n' + def assert_display(expect, result, error=None): try: @@ -57,9 +56,9 @@ def assert_display(expect, result, error=None): pass result = [ '\n', - ('*'*80) + '\n', + 'EXPECTED'+('*'*80) + '\n', expect, - ('*'*80) + '\n', + 'GOT'+('*'*80) + '\n', result, ('*'*80) + '\n', ] @@ -353,14 +352,13 @@ class must_contain_TestCase(TestCommonTestCase): expect = lstrip("""\ File `file1' does not contain required string. Required string ================================================================ - 1 c + b'1 c' file1 contents ================================================================= - file1 does not match - + b'file1 does not match\\n' """) run_env.run(program=sys.executable, stdin=script) stdout = run_env.stdout() - assert stdout == expect, repr(stdout) + assert stdout == expect, "got:\n%s\nexpected:\n%s"%(stdout, expect) stderr = run_env.stderr() assert stderr.find("FAILED") != -1, stderr @@ -1294,7 +1292,7 @@ class must_not_contain_TestCase(TestCommonTestCase): from TestCommon import TestCommon tc = TestCommon(workdir='') tc.write('file1', "file1 contents\\n") - tc.must_not_contain('file1', "1 does not contain c") + tc.must_not_contain('file1', b"1 does not contain c") tc.pass_test() """) run_env.run(program=sys.executable, stdin=script) @@ -1327,20 +1325,20 @@ class must_not_contain_TestCase(TestCommonTestCase): from TestCommon import TestCommon tc = TestCommon(workdir='') tc.write('file1', "file1 does contain contents\\n") - tc.must_not_contain('file1', "1 does contain c") + tc.must_not_contain('file1', b"1 does contain c") tc.run() """) expect = lstrip("""\ File `file1' contains banned string. Banned string ================================================================== - 1 does contain c + b'1 does contain c' file1 contents ================================================================= - file1 does contain contents - + b'file1 does contain contents\\n' """) run_env.run(program=sys.executable, stdin=script) stdout = run_env.stdout() - assert stdout == expect, repr(stdout) + assert stdout == expect, "\ngot:\n%s\nexpected:\n%s" % (stdout, expect) + stderr = run_env.stderr() assert stderr.find("FAILED") != -1, stderr @@ -1352,20 +1350,20 @@ class must_not_contain_TestCase(TestCommonTestCase): from TestCommon import TestCommon tc = TestCommon(workdir='') tc.write('file1', "file1 does contain contents\\n") - tc.must_not_contain('file1', "file1 does") + tc.must_not_contain('file1', b"file1 does") tc.run() """) expect = lstrip("""\ File `file1' contains banned string. Banned string ================================================================== - file1 does + b'file1 does' file1 contents ================================================================= - file1 does contain contents - + b'file1 does contain contents\\n' """) run_env.run(program=sys.executable, stdin=script) stdout = run_env.stdout() - assert stdout == expect, repr(stdout) + assert stdout == expect, "\ngot:\n%s\nexpected:\n%s" % (stdout, expect) + stderr = run_env.stderr() assert stderr.find("FAILED") != -1, stderr @@ -1379,7 +1377,7 @@ class must_not_contain_TestCase(TestCommonTestCase): tc.write('file1', "file1 contents\\n", mode='w') tc.must_not_contain('file1', "1 does not contain c", mode='r') tc.write('file2', "file2 contents\\n", mode='wb') - tc.must_not_contain('file2', "2 does not contain c", mode='rb') + tc.must_not_contain('file2', b"2 does not contain c", mode='rb') tc.pass_test() """) run_env.run(program=sys.executable, stdin=script) @@ -1891,6 +1889,7 @@ class run_TestCase(TestCommonTestCase): expect_stdout = lstrip("""\ STDOUT ========================================================================= + None STDERR ========================================================================= """) @@ -1904,6 +1903,9 @@ class run_TestCase(TestCommonTestCase): .* File "[^"]+TestCommon.py", line \\d+, in start raise e + File "[^"]+TestCommon.py", line \\d+, in start + return TestCmd.start\\(self, program, interpreter, arguments, + File "", line \\d+, in raise_exception TypeError: forced TypeError """ % re.escape(repr(sys.executable))) expect_stderr = re.compile(expect_stderr, re.M) @@ -2172,7 +2174,7 @@ class run_TestCase(TestCommonTestCase): tc.run() """) - self.SIGTERM = signal.SIGTERM + self.SIGTERM = int(signal.SIGTERM) # Script returns the signal value as a negative number. expect_stdout = lstrip("""\ -- cgit v0.12 From 7528b23f63755ecb2bc60e25aeef0188179b7681 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 18 Feb 2020 11:42:57 -0800 Subject: Fix runtest.py to only run *Tests.py files under testing as well as under src (unittests) --- runtest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtest.py b/runtest.py index 554b4f6..fdbbe22 100755 --- a/runtest.py +++ b/runtest.py @@ -662,7 +662,7 @@ else: # sys.stderr.write("to:%s\n"%tp) for path in glob.glob(tp): if os.path.isdir(path): - if path.startswith('src'): + if path.startswith('src') or path.startswith('testing'): for p in find_Tests_py(path): unittests.append(p) elif path.startswith('test'): -- cgit v0.12 From ce3f96839ad51b98d73db74b4335c903e3ceef44 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 18 Feb 2020 21:33:51 -0500 Subject: post py27 --- bin/calibrate.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/calibrate.py b/bin/calibrate.py index be06a54..d18cfcd 100644 --- a/bin/calibrate.py +++ b/bin/calibrate.py @@ -20,8 +20,6 @@ # 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 division, print_function - import optparse import os import re @@ -31,6 +29,7 @@ import sys variable_re = re.compile(r'^VARIABLE: (.*)$', re.M) elapsed_re = re.compile(r'^ELAPSED: (.*)$', re.M) + def main(argv=None): if argv is None: argv = sys.argv @@ -84,5 +83,6 @@ def main(argv=None): return 0 + if __name__ == "__main__": sys.exit(main()) -- cgit v0.12 From 71389d9642877ffcb191b16f7b08ba3bf78da530 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Tue, 18 Feb 2020 08:24:13 -0700 Subject: rm-py2: Remove "from __future__" from more places A couple of minor reformats along the way, most prominently, in tests, if being edited anyway, make sure the docstring most tests have is actually the docstring (sometimes the __revision__ line came before, which makes the string not be the docstring). Snuck in some minor framework changes that were orphaned when another draft PR was not needed: this almost all docstring changes, the functional part is using casefold instead of lower in a match func - a slightly better approach which is now possible that Py2 compatibility is not needed. Signed-off-by: Mats Wichmann --- SConstruct | 2 - bootstrap.py | 20 +++++----- doc/SConscript | 2 - doc/user/parseflags.xml | 20 ++++------ runtest.py | 2 - src/script/scons-time.py | 1 - test/AddOption/help.py | 5 +-- test/Command.py | 3 +- test/Configure/ConfigureDryRunError.py | 6 +-- test/Configure/config-h.py | 6 +-- test/Configure/custom-tests.py | 7 +--- test/Configure/implicit-cache.py | 6 +-- test/ENV.py | 5 +-- test/GetBuildFailures/parallel.py | 2 - test/Glob/glob-libpath.py | 6 +-- test/Interactive/shell.py | 6 +-- test/Interactive/version.py | 5 +-- test/Java/multi-step.py | 6 +-- test/LINK/VersionedLib.py | 3 -- test/MSVC/mssdk.py | 6 +-- test/MSVC/msvc.py | 6 +-- test/QT/Tool.py | 7 +--- test/QT/copied-env.py | 5 +-- test/QT/qt_warnings.py | 6 +-- test/SCONS_LIB_DIR.py | 3 -- test/SWIG/build-dir.py | 6 +-- test/SWIG/live.py | 7 +--- test/TEMPFILEPREFIX.py | 6 +-- test/TEMPFILESUFFIX.py | 6 +-- test/TEX/TEX.py | 5 +-- test/Value.py | 2 - test/VariantDir/reflect.py | 8 +--- test/Win32/bad-drive.py | 2 - test/Win32/default-drive.py | 2 - test/builderrors.py | 2 - test/explain/basic.py | 6 +-- test/explain/save-info.py | 7 +--- test/gnutools.py | 6 +-- test/option--random.py | 6 +-- test/option-v.py | 2 - test/option/debug-action-timestamps.py | 1 - test/option/debug-count.py | 5 +-- test/option/debug-multiple.py | 6 +-- test/option/debug-time.py | 1 - test/option/help-options.py | 5 +-- .../convenience-functions/image/SConstruct | 2 - test/scons-time/run/config/python.py | 6 +-- test/scons-time/run/config/scons.py | 5 +-- test/site_scons/sysdirs.py | 11 ++---- test/srcchange.py | 6 +-- testing/framework/TestCmd.py | 43 ++++++++++++---------- testing/framework/TestCmdTests.py | 20 +++++----- testing/framework/TestCommon.py | 2 - testing/framework/TestCommonTests.py | 7 +--- testing/framework/TestSCons.py | 1 - testing/framework/TestSCons_time.py | 1 - testing/framework/TestSConsign.py | 1 - 57 files changed, 116 insertions(+), 226 deletions(-) diff --git a/SConstruct b/SConstruct index 1adf714..23797da 100644 --- a/SConstruct +++ b/SConstruct @@ -3,8 +3,6 @@ # # See the README.rst file for an overview of how SCons is built and tested. -from __future__ import print_function - copyright_years = '2001 - 2019' # This gets inserted into the man pages to reflect the month of release. diff --git a/bootstrap.py b/bootstrap.py index 4ade361..d47c966 100755 --- a/bootstrap.py +++ b/bootstrap.py @@ -20,18 +20,8 @@ # 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 - -import os -import os.path -import sys -import glob -import subprocess -import filecmp -import shutil -__doc__ = """bootstrap.py +"""bootstrap.py Execute SCons from this source tree. It copies Python scripts and modules from src/ subdirectory into a subdirectory named "bootstrap/" (by default), @@ -75,6 +65,14 @@ the following SCons options: "eaten" by the bootstrap.py script. """ +import os +import os.path +import sys +import glob +import subprocess +import filecmp +import shutil + def parseManifestLines(basedir, manifest): """ Scans a MANIFEST file, and returns the list of source files. diff --git a/doc/SConscript b/doc/SConscript index e43a27b..8f6d1cd 100644 --- a/doc/SConscript +++ b/doc/SConscript @@ -24,8 +24,6 @@ # 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 - import os.path import re import sys diff --git a/doc/user/parseflags.xml b/doc/user/parseflags.xml index 836b7f2..35c336e 100644 --- a/doc/user/parseflags.xml +++ b/doc/user/parseflags.xml @@ -80,14 +80,13 @@ -from __future__ import print_function env = Environment() d = env.ParseFlags("-I/opt/include -L/opt/lib -lfoo") -for k,v in sorted(d.items()): +for k, v in sorted(d.items()): if v: print(k, v) env.MergeFlags(d) -env.Program('f1.c') +env.Program("f1.c") int main() { return 0; } @@ -120,14 +119,13 @@ int main() { return 0; } -from __future__ import print_function env = Environment() d = env.ParseFlags("-whatever") -for k,v in sorted(d.items()): +for k, v in sorted(d.items()): if v: print(k, v) env.MergeFlags(d) -env.Program('f1.c') +env.Program("f1.c") int main() { return 0; } @@ -147,14 +145,13 @@ env.Program('f1.c') -from __future__ import print_function env = Environment() d = env.ParseFlags(["-I/opt/include", ["-L/opt/lib", "-lfoo"]]) -for k,v in sorted(d.items()): +for k, v in sorted(d.items()): if v: print(k, v) env.MergeFlags(d) -env.Program('f1.c') +env.Program("f1.c") int main() { return 0; } @@ -175,14 +172,13 @@ int main() { return 0; } -from __future__ import print_function env = Environment() d = env.ParseFlags(["!echo -I/opt/include", "!echo -L/opt/lib", "-lfoo"]) -for k,v in sorted(d.items()): +for k, v in sorted(d.items()): if v: print(k, v) env.MergeFlags(d) -env.Program('f1.c') +env.Program("f1.c") int main() { return 0; } diff --git a/runtest.py b/runtest.py index fdbbe22..57b4ba4 100755 --- a/runtest.py +++ b/runtest.py @@ -69,8 +69,6 @@ Environment Variables: TESTCMD_VERBOSE: turn on verbosity in TestCommand\ """ -from __future__ import print_function - import getopt import glob import os diff --git a/src/script/scons-time.py b/src/script/scons-time.py index 0fcd1c4..e4dd863 100644 --- a/src/script/scons-time.py +++ b/src/script/scons-time.py @@ -29,7 +29,6 @@ # 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 division __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/test/AddOption/help.py b/test/AddOption/help.py index 7b886cb..23e5bd1 100644 --- a/test/AddOption/help.py +++ b/test/AddOption/help.py @@ -20,15 +20,14 @@ # 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__" """ Verify the help text when the AddOption() function is used (and when it's not). """ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + import TestSCons test = TestSCons.TestSCons() diff --git a/test/Command.py b/test/Command.py index d8ca86d..5abdf16 100644 --- a/test/Command.py +++ b/test/Command.py @@ -20,7 +20,7 @@ # 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 @@ -42,7 +42,6 @@ test.write('build.py', build_py) test.write(['expand_chdir_sub', 'subbuild.py'], build_py) test.write('SConstruct', """ -from __future__ import print_function import os import sys diff --git a/test/Configure/ConfigureDryRunError.py b/test/Configure/ConfigureDryRunError.py index ad40ea4..3648518 100644 --- a/test/Configure/ConfigureDryRunError.py +++ b/test/Configure/ConfigureDryRunError.py @@ -20,15 +20,13 @@ # 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__" """ Verify the ConfigureDryRunError. """ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + import os import TestSCons diff --git a/test/Configure/config-h.py b/test/Configure/config-h.py index 405f259..0331b24 100644 --- a/test/Configure/config-h.py +++ b/test/Configure/config-h.py @@ -20,15 +20,13 @@ # 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__" """ Verify creation of a config.h file from a Configure context. """ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + import os import re diff --git a/test/Configure/custom-tests.py b/test/Configure/custom-tests.py index 1c6eac8..47b344a 100644 --- a/test/Configure/custom-tests.py +++ b/test/Configure/custom-tests.py @@ -20,14 +20,13 @@ # 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 execution of custom test cases. """ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + import TestSCons _exe = TestSCons._exe @@ -49,8 +48,6 @@ runOK = compileOK runFAIL = "int main(void) { return 1; }" test.write('pyAct.py', """\ -from __future__ import print_function - import sys print(sys.argv[1]) sys.exit(int(sys.argv[1])) diff --git a/test/Configure/implicit-cache.py b/test/Configure/implicit-cache.py index 20bdebb..f4f3e94 100644 --- a/test/Configure/implicit-cache.py +++ b/test/Configure/implicit-cache.py @@ -20,10 +20,6 @@ # 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__" """ Verify that use of --implicit-cache with the Python Value Nodes @@ -56,6 +52,8 @@ something else changed in the .sconf_temp directory), the string would get longer and longer until it blew out the users's memory. """ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + import TestSConsign test = TestSConsign.TestSConsign() diff --git a/test/ENV.py b/test/ENV.py index 0866cf5..0fc3f09 100644 --- a/test/ENV.py +++ b/test/ENV.py @@ -20,7 +20,6 @@ # 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__" @@ -70,9 +69,7 @@ env['ENV']['LIST'] = [foo, 'bar'] env['ENV']['FOO'] = foo """ % locals()) -test.write('build.py', -r""" -from __future__ import print_function +test.write('build.py', r""" import os print('LIST:', os.environ['LIST']) print('FOO:', os.environ['FOO']) diff --git a/test/GetBuildFailures/parallel.py b/test/GetBuildFailures/parallel.py index 63125ad..9b162d8 100644 --- a/test/GetBuildFailures/parallel.py +++ b/test/GetBuildFailures/parallel.py @@ -20,8 +20,6 @@ # 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 """ Verify that a failed build action with -j works as expected. diff --git a/test/Glob/glob-libpath.py b/test/Glob/glob-libpath.py index 0878090..b688b7e 100644 --- a/test/Glob/glob-libpath.py +++ b/test/Glob/glob-libpath.py @@ -20,10 +20,6 @@ # 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__" """ Verify that Glob() in a subdir doesn't corrupt LIBPATH. @@ -31,6 +27,8 @@ See bug #2184, "Glob pollutes LIBPATH" from Ian P. Cardenas. Test output should not contain -Lsrc/util. """ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + import TestSCons test = TestSCons.TestSCons() diff --git a/test/Interactive/shell.py b/test/Interactive/shell.py index dd13504..e839d6d 100644 --- a/test/Interactive/shell.py +++ b/test/Interactive/shell.py @@ -20,14 +20,14 @@ # 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 the ability of the "shell" command (and its "sh" and "!" aliases) to shell out of interactive mode. """ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + import sys import TestSCons @@ -40,8 +40,6 @@ shell_command_py = test.workpath('shell_command.py') _shell_command_py_ = '"%s"' % shell_command_py.replace('\\', '\\\\') test.write(shell_command_py, """\ -from __future__ import print_function - print('hello from shell_command.py') """) diff --git a/test/Interactive/version.py b/test/Interactive/version.py index 88416ad..6609ad7 100644 --- a/test/Interactive/version.py +++ b/test/Interactive/version.py @@ -20,14 +20,13 @@ # 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__" """ Verify the behavior of the "version" subcommand. """ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + import TestCmd import TestSCons diff --git a/test/Java/multi-step.py b/test/Java/multi-step.py index f5ee257..d0b3450 100644 --- a/test/Java/multi-step.py +++ b/test/Java/multi-step.py @@ -20,16 +20,14 @@ # 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__" """ Real-world test (courtesy Leanid Nazdrynau) of the multi-step capabilities of the various Java Builders. """ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + import os import TestSCons diff --git a/test/LINK/VersionedLib.py b/test/LINK/VersionedLib.py index 64f9b90..104f696 100644 --- a/test/LINK/VersionedLib.py +++ b/test/LINK/VersionedLib.py @@ -20,9 +20,6 @@ # 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__" diff --git a/test/MSVC/mssdk.py b/test/MSVC/mssdk.py index ba45346..8d1bb5c 100644 --- a/test/MSVC/mssdk.py +++ b/test/MSVC/mssdk.py @@ -20,15 +20,13 @@ # 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__" """ Simple test to make sure mssdk works. """ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + import time import TestSCons diff --git a/test/MSVC/msvc.py b/test/MSVC/msvc.py index 838922c..b92cf3a 100644 --- a/test/MSVC/msvc.py +++ b/test/MSVC/msvc.py @@ -20,16 +20,14 @@ # 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__" """ Verify basic invocation of Microsoft Visual C/C++, including use of a precompiled header with the $CCFLAGS variable. """ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + import time import TestSCons diff --git a/test/QT/Tool.py b/test/QT/Tool.py index 9e4a277..f684e91 100644 --- a/test/QT/Tool.py +++ b/test/QT/Tool.py @@ -20,11 +20,6 @@ # 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__" """ Verify that applying env.Tool('qt') after running Configure checks @@ -36,6 +31,8 @@ not completely minimal, but we're leaving it as-is since it represents a good real-world sanity check on the interaction of some key subsystems. """ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + import os import TestSCons diff --git a/test/QT/copied-env.py b/test/QT/copied-env.py index 3989143..be9f599 100644 --- a/test/QT/copied-env.py +++ b/test/QT/copied-env.py @@ -20,14 +20,13 @@ # 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__" """ Test Qt with a copied construction environment. """ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + import TestSCons test = TestSCons.TestSCons() diff --git a/test/QT/qt_warnings.py b/test/QT/qt_warnings.py index 020333e..2aa7940 100644 --- a/test/QT/qt_warnings.py +++ b/test/QT/qt_warnings.py @@ -20,15 +20,13 @@ # 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__" """ Test the Qt tool warnings. """ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + import os import re diff --git a/test/SCONS_LIB_DIR.py b/test/SCONS_LIB_DIR.py index 65ec3de..5691f61 100644 --- a/test/SCONS_LIB_DIR.py +++ b/test/SCONS_LIB_DIR.py @@ -20,7 +20,6 @@ # 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__" @@ -31,8 +30,6 @@ test = TestSCons.TestSCons() test.subdir('SCons') test.write(['SCons','Script.py'], """ -from __future__ import print_function - def main (): print("SCons.Script") """) diff --git a/test/SWIG/build-dir.py b/test/SWIG/build-dir.py index f70e6e1..372b052 100644 --- a/test/SWIG/build-dir.py +++ b/test/SWIG/build-dir.py @@ -21,14 +21,14 @@ # 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__" - """ Make sure SWIG works when a VariantDir (or variant_dir) is used. Test case courtesy Joe Maruszewski. """ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + import sys import TestSCons @@ -143,8 +143,6 @@ public: ## XXX: @ptomulik: looks like it was unused? ## test.write(['source', 'test.py'], """\ ## #!%(_python_)s -## from __future__ import print_function -## ## import linalg ## ## diff --git a/test/SWIG/live.py b/test/SWIG/live.py index e01597d..e7b2602 100644 --- a/test/SWIG/live.py +++ b/test/SWIG/live.py @@ -20,14 +20,13 @@ # 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__" """ Test SWIG behavior with a live, installed SWIG. """ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + import os import sys @@ -134,7 +133,6 @@ test.run(arguments = ldmodule_prefix+'foo' + _dll) test.must_not_exist(test.workpath('wrapper.out')) test.run(program = python, stdin = """\ -from __future__ import print_function import foo print(foo.foo_string()) """, stdout="""\ @@ -148,7 +146,6 @@ test.run(arguments = ldmodule_prefix+'bar' + _dll) test.must_match('wrapper.out', "wrapper.py\n") test.run(program = python, stdin = """\ -from __future__ import print_function import foo import bar print(foo.foo_string()) diff --git a/test/TEMPFILEPREFIX.py b/test/TEMPFILEPREFIX.py index f5093e1..4ccfd7d 100644 --- a/test/TEMPFILEPREFIX.py +++ b/test/TEMPFILEPREFIX.py @@ -20,9 +20,6 @@ # 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 setting the $TEMPFILEPREFIX variable will cause @@ -30,6 +27,8 @@ it to appear at the front of name of the generated tempfile used for long command lines. """ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + import os import stat @@ -38,7 +37,6 @@ import TestSCons test = TestSCons.TestSCons(match = TestSCons.match_re) test.write('echo.py', """\ -from __future__ import print_function import sys print(sys.argv) """) diff --git a/test/TEMPFILESUFFIX.py b/test/TEMPFILESUFFIX.py index aee1e2d..df546ac 100644 --- a/test/TEMPFILESUFFIX.py +++ b/test/TEMPFILESUFFIX.py @@ -20,9 +20,6 @@ # 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 setting the $TEMPFILESUFFIX variable will cause @@ -30,6 +27,8 @@ it to appear at the end of name of the generated tempfile used for long command lines. """ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + import os import stat @@ -38,7 +37,6 @@ import TestSCons test = TestSCons.TestSCons(match=TestSCons.match_re) test.write('echo.py', """\ -from __future__ import print_function import sys print(sys.argv) """) diff --git a/test/TEX/TEX.py b/test/TEX/TEX.py index f0d4043..4c4bd87 100644 --- a/test/TEX/TEX.py +++ b/test/TEX/TEX.py @@ -20,9 +20,6 @@ # 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__" r""" Validate that we can set the TEX string to our own utility, that @@ -30,6 +27,8 @@ the produced .dvi, .aux and .log files get removed by the -c option, and that we can use this to wrap calls to the real latex utility. """ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + import TestSCons _python_ = TestSCons._python_ diff --git a/test/Value.py b/test/Value.py index 8f6c7fe..eb04eb0 100644 --- a/test/Value.py +++ b/test/Value.py @@ -20,8 +20,6 @@ # 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__" diff --git a/test/VariantDir/reflect.py b/test/VariantDir/reflect.py index 72f3af7..56b0c18 100644 --- a/test/VariantDir/reflect.py +++ b/test/VariantDir/reflect.py @@ -20,9 +20,6 @@ # 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__" """ This test validates the correct operation of a VariantDir specification @@ -33,6 +30,8 @@ in the variant_dir as sources for that same build dir. Test based on bug #1055521 filed by Gary Oberbrunner. """ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + import os.path import re @@ -44,14 +43,11 @@ _python_ = TestSCons._python_ re_python = re.escape(TestSCons._python_) test.write("mycc.py", """ -from __future__ import print_function print('Compile') """) test.write("mylink.py", """ -from __future__ import print_function - print('Link') """) diff --git a/test/Win32/bad-drive.py b/test/Win32/bad-drive.py index 28d926b..cca5462 100644 --- a/test/Win32/bad-drive.py +++ b/test/Win32/bad-drive.py @@ -20,8 +20,6 @@ # 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 """ This test verifies (on Windows systems) that we fail gracefully and diff --git a/test/Win32/default-drive.py b/test/Win32/default-drive.py index 78db4be..7d19c57 100644 --- a/test/Win32/default-drive.py +++ b/test/Win32/default-drive.py @@ -20,8 +20,6 @@ # 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 """ This test verifies (on Windows systems) that specifying an diff --git a/test/builderrors.py b/test/builderrors.py index f5cbccf..635f448 100644 --- a/test/builderrors.py +++ b/test/builderrors.py @@ -20,7 +20,6 @@ # 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__" @@ -169,7 +168,6 @@ test.must_not_contain_any_line(test.stderr(), ['Exception', 'Traceback']) # Should not give traceback; the task error should get converted # to a BuildError. test.write('SConstruct', """ -from __future__ import print_function import atexit env = Environment() diff --git a/test/explain/basic.py b/test/explain/basic.py index 46ce6bc..6d41496 100644 --- a/test/explain/basic.py +++ b/test/explain/basic.py @@ -20,14 +20,13 @@ # 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 a lot of the basic operation of the --debug=explain option. """ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + import os import TestSCons @@ -52,7 +51,6 @@ inc_bbb_k = test.workpath('inc', 'bbb.k') test.write(cat_py, r""" -from __future__ import print_function import sys diff --git a/test/explain/save-info.py b/test/explain/save-info.py index 24ebb88..500bb55 100644 --- a/test/explain/save-info.py +++ b/test/explain/save-info.py @@ -20,14 +20,13 @@ # 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 the --debug=explain information gets saved by default. """ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + import TestSCons _python_ = TestSCons._python_ @@ -42,8 +41,6 @@ inc_ddd = test.workpath('inc', 'ddd') inc_eee = test.workpath('inc', 'eee') test.write(cat_py, r""" -from __future__ import print_function - import sys def process(outfp, infp): diff --git a/test/gnutools.py b/test/gnutools.py index 040de2a..eb0d847 100644 --- a/test/gnutools.py +++ b/test/gnutools.py @@ -20,15 +20,13 @@ # 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__" """ Testing the gnu tool chain, i.e. the tools 'gcc', 'g++' and 'gnulink'. """ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + import TestSCons import sys diff --git a/test/option--random.py b/test/option--random.py index 2944ad8..c25ec12 100644 --- a/test/option--random.py +++ b/test/option--random.py @@ -20,15 +20,13 @@ # 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__" """ Verify that we build correctly using the --random option. """ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + import os.path import TestSCons diff --git a/test/option-v.py b/test/option-v.py index ed8c4e5..ec20b20 100644 --- a/test/option-v.py +++ b/test/option-v.py @@ -20,8 +20,6 @@ # 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__" diff --git a/test/option/debug-action-timestamps.py b/test/option/debug-action-timestamps.py index 059cfdf..747d880 100644 --- a/test/option/debug-action-timestamps.py +++ b/test/option/debug-action-timestamps.py @@ -20,7 +20,6 @@ # 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 division, print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/test/option/debug-count.py b/test/option/debug-count.py index 0234bfa..f2fceb4 100644 --- a/test/option/debug-count.py +++ b/test/option/debug-count.py @@ -20,14 +20,13 @@ # 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__" """ Test that the --debug=count option works. """ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + import re import sys diff --git a/test/option/debug-multiple.py b/test/option/debug-multiple.py index 020aa85..124e033 100644 --- a/test/option/debug-multiple.py +++ b/test/option/debug-multiple.py @@ -21,14 +21,12 @@ # 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__" - """ Test that --debug can take multiple options """ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + import re import TestSCons diff --git a/test/option/debug-time.py b/test/option/debug-time.py index 3ed7555..7e95af3 100644 --- a/test/option/debug-time.py +++ b/test/option/debug-time.py @@ -20,7 +20,6 @@ # 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 division, print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/test/option/help-options.py b/test/option/help-options.py index 1835a62..2dac532 100644 --- a/test/option/help-options.py +++ b/test/option/help-options.py @@ -20,14 +20,13 @@ # 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__" """ Verify behavior of the -H and --help-options options. """ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + import re import TestSCons diff --git a/test/packaging/convenience-functions/image/SConstruct b/test/packaging/convenience-functions/image/SConstruct index f35c3e3..a424fd9 100644 --- a/test/packaging/convenience-functions/image/SConstruct +++ b/test/packaging/convenience-functions/image/SConstruct @@ -1,5 +1,3 @@ -from __future__ import print_function - env = Environment(tools=['default', 'packaging']) prog = env.Install( 'bin/', ["f1", "f2"] ) env.File( "f3" ) diff --git a/test/scons-time/run/config/python.py b/test/scons-time/run/config/python.py index c8842c1..bf873fa 100644 --- a/test/scons-time/run/config/python.py +++ b/test/scons-time/run/config/python.py @@ -20,14 +20,13 @@ # 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 specifying an alternate Python executable in a config file. """ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + import os import TestSCons_time @@ -46,7 +45,6 @@ python = r'%(my_python_py)s' test.write(my_python_py, """\ #!%(_python_)s -from __future__ import print_function import sys profile = '' for arg in sys.argv[1:]: diff --git a/test/scons-time/run/config/scons.py b/test/scons-time/run/config/scons.py index b782e83..168ee7a 100644 --- a/test/scons-time/run/config/scons.py +++ b/test/scons-time/run/config/scons.py @@ -20,14 +20,12 @@ # 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 specifying an alternate SCons through a config file. """ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import TestSCons_time @@ -42,7 +40,6 @@ scons = r'%(my_scons_py)s' """ % locals()) test.write(my_scons_py, """\ -from __future__ import print_function import sys profile = '' for arg in sys.argv[1:]: diff --git a/test/site_scons/sysdirs.py b/test/site_scons/sysdirs.py index 36a581e..61f9c02 100644 --- a/test/site_scons/sysdirs.py +++ b/test/site_scons/sysdirs.py @@ -20,13 +20,6 @@ # 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 TestSCons """ Verify site_scons system dirs are getting loaded. @@ -37,6 +30,10 @@ files from the system dirs, but the test harness can't put files in those dirs (which may not even exist on a build system). """ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import TestSCons + test = TestSCons.TestSCons() test.write('SConstruct', """ diff --git a/test/srcchange.py b/test/srcchange.py index 3c23737..30f6f20 100644 --- a/test/srcchange.py +++ b/test/srcchange.py @@ -20,9 +20,6 @@ # 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__" """ Test changing the C source files based on an always-executed revision @@ -33,6 +30,8 @@ expected. This relies on the default behavior being the equivalent of Decider('content'). """ +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + import os.path import TestSCons @@ -42,7 +41,6 @@ _python_ = TestSCons._python_ test = TestSCons.TestSCons() test.write('getrevision', r""" -from __future__ import print_function with open('revnum.in', 'r') as f: print(f.read().strip(), end='') """) diff --git a/testing/framework/TestCmd.py b/testing/framework/TestCmd.py index f29449f..ed8b4b4 100644 --- a/testing/framework/TestCmd.py +++ b/testing/framework/TestCmd.py @@ -285,7 +285,6 @@ version. # PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, # AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. -from __future__ import division, print_function __author__ = "Steven Knight " __revision__ = "TestCmd.py 1.3.D001 2010/06/03 12:58:27 knight" @@ -492,11 +491,9 @@ def match_caseinsensitive(lines=None, matches=None): """ Match function using case-insensitive matching. - Only a simplistic comparison is done, based on lowercasing the - strings. This has plenty of holes for unicode data using - non-English languages. - - TODO: casefold() is better than lower() if we don't need Py2 support. + Only a simplistic comparison is done, based on casefolding + the strings. This may still fail but is the suggestion of + the Unicode Standard. :param lines: data lines :type lines: str or list[str] @@ -512,7 +509,7 @@ def match_caseinsensitive(lines=None, matches=None): if len(lines) != len(matches): return None for line, match in zip(lines, matches): - if line.lower() != match.lower(): + if line.casefold() != match.casefold(): return None return 1 @@ -700,7 +697,7 @@ if sys.platform == 'win32': if is_String(pathext): pathext = pathext.split(os.pathsep) for ext in pathext: - if ext.lower() == file[-len(ext):].lower(): + if ext.casefold() == file[-len(ext):].casefold(): pathext = [''] break for dir in path: @@ -1504,13 +1501,13 @@ class TestCmd(object): @staticmethod def fix_binary_stream(stream): """ - Handle stdout/stderr from popen when we specify universal_newlines = False. + Handle stdout/stderr from popen when we specify not universal_newlines - This will read from the pipes in binary mode, not decode the output, - and not convert line endings to \n. + This will read from the pipes in binary mode, will not decode the + output, and will not convert line endings to \n. We do this because in py3 (3.5) with universal_newlines=True, it will choose the default system locale to decode the output, and this breaks unicode - output. Specifically breaking test/option--tree.py which outputs a unicode char. + output. Specifically test/option--tree.py which outputs a unicode char. py 3.6 allows us to pass an encoding param to popen thus not requiring the decode nor end of line handling, because we propagate universal_newlines as specified. @@ -1968,13 +1965,20 @@ class TestCmd(object): do_chmod(top) def write(self, file, content, mode='wb'): - """Writes the specified content text (second argument) to the - specified file name (first argument). The file name may be - a list, in which case the elements are concatenated with the - os.path.join() method. The file is created under the temporary - working directory. Any subdirectories in the path must already - exist. The I/O mode for the file may be specified; it must - begin with a 'w'. The default is 'wb' (binary write). + """Write data to file + + The file is created under the temporary working directory. + Any subdirectories in the path must already exist. The + write is converted to the required type rather than failing + if there is a str/bytes mistmatch. + + :param file: name of file to write to. If a list, treated + as components of a path and concatenated into a path. + :type file: str or list(str) + :param content: data to write. + :type content: str or bytes + :param mode: file mode, default is binary. + :type mode: str """ file = self.canonicalize(file) if mode[0] != 'w': @@ -1983,7 +1987,6 @@ class TestCmd(object): try: f.write(content) except TypeError as e: - # python 3 default strings are not bytes, but unicode f.write(bytes(content, 'utf-8')) # Local Variables: diff --git a/testing/framework/TestCmdTests.py b/testing/framework/TestCmdTests.py index 48eba1e..e8c2744 100644 --- a/testing/framework/TestCmdTests.py +++ b/testing/framework/TestCmdTests.py @@ -254,7 +254,7 @@ class cleanup_TestCase(TestCmdTestCase): def test_atexit(self): """Test cleanup() when atexit is used""" - self.popen_python("""from __future__ import print_function + self.popen_python("""\ import sys sys.path = ['%s'] + sys.path import atexit @@ -269,7 +269,7 @@ sys.exit(0) @unittest.skipIf(TestCmd.IS_PY3, "No sys.exitfunc in Python 3") def test_exitfunc(self): """Test cleanup() when sys.exitfunc is set""" - self.popen_python("""from __future__ import print_function + self.popen_python("""\ import sys sys.path = ['%s'] + sys.path def my_exitfunc(): @@ -609,7 +609,7 @@ sys.exit(0) def test_diff_stderr_not_affecting_diff_stdout(self): """Test diff_stderr() not affecting diff_stdout() behavior""" - self.popen_python(r"""from __future__ import print_function + self.popen_python(r""" import sys sys.path = ['%s'] + sys.path import TestCmd @@ -716,7 +716,7 @@ sys.exit(0) def test_diff_stdout_not_affecting_diff_stderr(self): """Test diff_stdout() not affecting diff_stderr() behavior""" - self.popen_python(r"""from __future__ import print_function + self.popen_python(r""" import sys sys.path = ['%s'] + sys.path import TestCmd @@ -2089,7 +2089,7 @@ sys.exit(0) def test_set_diff_function_stdout(self): """Test set_diff_function(): stdout""" - self.popen_python("""from __future__ import print_function + self.popen_python("""\ import sys sys.path = ['%s'] + sys.path import TestCmd @@ -2118,7 +2118,7 @@ diff_stdout: def test_set_diff_function_stderr(self): """Test set_diff_function(): stderr """ - self.popen_python("""from __future__ import print_function + self.popen_python("""\ import sys sys.path = ['%s'] + sys.path import TestCmd @@ -2693,7 +2693,7 @@ class stdin_TestCase(TestCmdTestCase): def test_stdin(self): """Test stdin()""" run_env = TestCmd.TestCmd(workdir = '') - run_env.write('run', """from __future__ import print_function + run_env.write('run', """\ import fileinput for line in fileinput.input(): print('Y'.join(line[:-1].split('X'))) @@ -3332,15 +3332,13 @@ class variables_TestCase(TestCmdTestCase): 'TestCmd', ] - script = "from __future__ import print_function\n" + \ - "import TestCmd\n" + \ + script = "import TestCmd\n" + \ '\n'.join([ "print(TestCmd.%s\n)" % v for v in variables ]) run_env.run(program=sys.executable, stdin=script) stderr = run_env.stderr() assert stderr == "", stderr - script = "from __future__ import print_function\n" + \ - "from TestCmd import *\n" + \ + script = "from TestCmd import *\n" + \ '\n'.join([ "print(%s)" % v for v in variables ]) run_env.run(program=sys.executable, stdin=script) stderr = run_env.stderr() diff --git a/testing/framework/TestCommon.py b/testing/framework/TestCommon.py index 8e6cc8e..1bd9f6b 100644 --- a/testing/framework/TestCommon.py +++ b/testing/framework/TestCommon.py @@ -93,8 +93,6 @@ The TestCommon module also provides the following variables # AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. -from __future__ import print_function - __author__ = "Steven Knight " __revision__ = "TestCommon.py 1.3.D001 2010/06/03 12:58:27 knight" __version__ = "1.3" diff --git a/testing/framework/TestCommonTests.py b/testing/framework/TestCommonTests.py index 6377737..01e9fe1 100644 --- a/testing/framework/TestCommonTests.py +++ b/testing/framework/TestCommonTests.py @@ -167,7 +167,6 @@ class __init__TestCase(TestCommonTestCase): os.chdir(run_env.workdir) script = lstrip("""\ - from __future__ import print_function from TestCommon import TestCommon tc = TestCommon(workdir='') import os @@ -2340,15 +2339,13 @@ class variables_TestCase(TestCommonTestCase): 'dll_suffix', ] - script = "from __future__ import print_function\n" + \ - "import TestCommon\n" + \ + script = "import TestCommon\n" + \ '\n'.join([ "print(TestCommon.%s)\n" % v for v in variables ]) run_env.run(program=sys.executable, stdin=script) stderr = run_env.stderr() assert stderr == "", stderr - script = "from __future__ import print_function\n" + \ - "from TestCommon import *\n" + \ + script = "from TestCommon import *\n" + \ '\n'.join([ "print(%s)" % v for v in variables ]) run_env.run(program=sys.executable, stdin=script) stderr = run_env.stderr() diff --git a/testing/framework/TestSCons.py b/testing/framework/TestSCons.py index 2f20950..8800c1b 100644 --- a/testing/framework/TestSCons.py +++ b/testing/framework/TestSCons.py @@ -13,7 +13,6 @@ attributes defined in this subclass. """ # __COPYRIGHT__ -from __future__ import division, print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" diff --git a/testing/framework/TestSCons_time.py b/testing/framework/TestSCons_time.py index f27e0e3..6f46e26 100644 --- a/testing/framework/TestSCons_time.py +++ b/testing/framework/TestSCons_time.py @@ -27,7 +27,6 @@ from TestSCons import search_re, search_re_in_list __all__.extend(['TestSCons_time',]) SConstruct = """\ -from __future__ import print_function import os print("SConstruct file directory:", os.getcwd()) """ diff --git a/testing/framework/TestSConsign.py b/testing/framework/TestSConsign.py index a48b648..665059c 100644 --- a/testing/framework/TestSConsign.py +++ b/testing/framework/TestSConsign.py @@ -1,5 +1,4 @@ # __COPYRIGHT__ -from __future__ import print_function __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" -- cgit v0.12 From 27e0fc09302264dca55f5b5c0215c485634c15c6 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Thu, 20 Feb 2020 16:22:15 -0700 Subject: Let test runner use new Dev. Mode Python Development Mode imposes more checks (since Python 3.7). Allow it to optionally be enabled while doing a test run. Signed-off-by: Mats Wichmann --- runtest.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/runtest.py b/runtest.py index 57b4ba4..ec27a68 100755 --- a/runtest.py +++ b/runtest.py @@ -23,6 +23,7 @@ Options: -b --baseline BASE Run test scripts against baseline BASE. --builddir DIR Directory in which packages were built. -d --debug Run test scripts under the Python debugger. + -D --devmode Run tests in Python's development mode (3.7+ only) -e --external Run the script in external mode (for external Tools) -f --file FILE Only run tests listed in FILE. -j --jobs JOBS Run tests in JOBS parallel jobs. @@ -89,6 +90,7 @@ cwd = os.getcwd() baseline = 0 builddir = os.path.join(cwd, 'build') external = 0 +devmode = False debug = '' execute_tests = 1 jobs = 1 @@ -151,9 +153,10 @@ parser.add_option('--xml', #print("args:", args) -opts, args = getopt.getopt(args, "b:def:hj:klnP:p:qsv:Xx:t", +opts, args = getopt.getopt(args, "b:dDef:hj:klnP:p:qsv:Xx:t", ['baseline=', 'builddir=', - 'debug', 'external', 'file=', 'help', 'no-progress', + 'debug', 'devmode', 'external', + 'file=', 'help', 'no-progress', 'jobs=', 'list', 'no-exec', 'nopipefiles', 'package=', 'passed', 'python=', @@ -176,6 +179,8 @@ for o, a in opts: if os.path.exists(pdb): debug = pdb break + elif o in ['-D', '--devmode']: + devmode = 1 elif o in ['-e', '--external']: external = 1 elif o in ['-f', '--file']: @@ -770,10 +775,10 @@ def log_result(t, io_lock=None): def run_test(t, io_lock=None, run_async=True): t.headline = "" command_args = [] - if sys.version_info[0] < 3: - command_args.append('-tt') if debug: command_args.append(debug) + if devmode and sys.version_info > (3, 7, 0): + command_args.append('-X dev') command_args.append(t.path) if options.runner and t.path in unittests: # For example --runner TestUnit.TAPTestRunner -- cgit v0.12 From e7821141cfa0b5b3b3fcc37fda5e2680435637af Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Thu, 20 Feb 2020 16:27:29 -0700 Subject: Change devmode check to not exclude 3.7.0 Signed-off-by: Mats Wichmann --- runtest.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtest.py b/runtest.py index ec27a68..6e4f58d 100755 --- a/runtest.py +++ b/runtest.py @@ -180,7 +180,7 @@ for o, a in opts: debug = pdb break elif o in ['-D', '--devmode']: - devmode = 1 + devmode = True elif o in ['-e', '--external']: external = 1 elif o in ['-f', '--file']: @@ -777,7 +777,7 @@ def run_test(t, io_lock=None, run_async=True): command_args = [] if debug: command_args.append(debug) - if devmode and sys.version_info > (3, 7, 0): + if devmode and sys.version_info >= (3, 7, 0): command_args.append('-X dev') command_args.append(t.path) if options.runner and t.path in unittests: -- cgit v0.12 From 02080bf85ef1ae7b75476a1fe7402937fbcd2626 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 23 Feb 2020 14:43:18 -0500 Subject: Reduce IMPLICIT_COMMAND_DEPENDENCIES's tried in test. No need to try all values, only new functionality. Full range is covered in other test --- test/Repository/Program.py | 5 ++++- test/Repository/StaticLibrary.py | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/test/Repository/Program.py b/test/Repository/Program.py index 9e8af77..75860a7 100644 --- a/test/Repository/Program.py +++ b/test/Repository/Program.py @@ -32,9 +32,10 @@ if sys.platform == 'win32': else: _exe = '' -for implicit_deps in ['0', '1', '2', 'all']: +for implicit_deps in ['0', '1', '"all"']: # First, test a single repository. test = TestSCons.TestSCons() + test.verbose_set(1) test.subdir('repository', 'work1') repository = test.workpath('repository') repository_foo_c = test.workpath('repository', 'foo.c') @@ -42,6 +43,7 @@ for implicit_deps in ['0', '1', '2', 'all']: work1_foo_c = test.workpath('work1', 'foo.c') test.write(['work1', 'SConstruct'], r""" +DefaultEnvironment(tools=[]) Repository(r'%s') env = Environment(IMPLICIT_COMMAND_DEPENDENCIES=%s) env.Program(target= 'foo', source = Split('aaa.c bbb.c foo.c')) @@ -184,6 +186,7 @@ repository/foo.c work2_foo = test.workpath('work2', 'foo' + _exe) test.write(['work2', 'SConstruct'], r""" +DefaultEnvironment(tools=[]) Repository(r'%s') Repository(r'%s') env = Environment() diff --git a/test/Repository/StaticLibrary.py b/test/Repository/StaticLibrary.py index acd4b83..29cb841 100644 --- a/test/Repository/StaticLibrary.py +++ b/test/Repository/StaticLibrary.py @@ -30,7 +30,7 @@ import TestSCons _obj = TestSCons._obj _exe = TestSCons._exe -for implicit_deps in ['0', '1', '2', 'all']: +for implicit_deps in ['1', '2']: test = TestSCons.TestSCons() # -- cgit v0.12 From 0d458ee9fad0f1003938f8d1612cd449c2ff53b8 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 23 Feb 2020 14:43:43 -0500 Subject: Update description of IMPLICIT_COMMAND_DEPENDENCIES's functional change --- src/CHANGES.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 574f64b..20b99c4 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -29,9 +29,10 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER From Adam Gross: - Added support for scanning multiple entries in an action string if - IMPLICIT_COMMAND_DEPENDENCIES is set to 2. This opts into more thorough - action scanning where every string in the command is scanned to determine - if it is a non-source and non-target path. + IMPLICIT_COMMAND_DEPENDENCIES is set to 2 or 'all'. This enables more thorough + action scanning where every item in each command line is scanned to determine + if it is a non-source and non-target path and added to the list of implicit dependencies + for the target. - Added support for taking instances of the Value class as implicit dependencies. - Added new module SCons.Scanner.Python to allow scanning .py files. -- cgit v0.12 From 5c969e525aec3323415626d001c3ab28bd8942e4 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Mon, 24 Feb 2020 09:03:13 -0700 Subject: Fix runtest no-exec mode Failure to default some values in class initializer caused a downstream problem if running no-exec mode, as one field was added only if running in execute mode. Signed-off-by: Mats Wichmann --- runtest.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/runtest.py b/runtest.py index 57b4ba4..70f1385 100755 --- a/runtest.py +++ b/runtest.py @@ -368,14 +368,17 @@ class RuntestBase(object): def __init__(self, path, num, spe=None): self.path = path self.num = num + self.stdout = self.stderr = self.status = None self.abspath = os.path.abspath(path) + self.command_args = [] + self.command_str = "" + self.test_time = self.total_time = 0 if spe: for dir in spe: f = os.path.join(dir, path) if os.path.isfile(f): self.abspath = f break - self.status = None class SystemExecutor(RuntestBase): -- cgit v0.12 From b4454c3f49ff814806b49bbf245f0a5262638d0c Mon Sep 17 00:00:00 2001 From: Rob Boehne Date: Mon, 24 Feb 2020 14:06:21 -0600 Subject: Specifiy encoding for Java files, as the default varies across platforms. --- src/engine/SCons/Tool/JavaCommon.py | 2 +- src/engine/SCons/Tool/JavaCommonTests.py | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/engine/SCons/Tool/JavaCommon.py b/src/engine/SCons/Tool/JavaCommon.py index 1711de1..c6c19ae 100644 --- a/src/engine/SCons/Tool/JavaCommon.py +++ b/src/engine/SCons/Tool/JavaCommon.py @@ -404,7 +404,7 @@ if java_parsing: def parse_java_file(fn, version=default_java_version): - with open(fn, 'r') as f: + with open(fn, 'r', encoding='utf-8') as f: data = f.read() return parse_java(data, version) diff --git a/src/engine/SCons/Tool/JavaCommonTests.py b/src/engine/SCons/Tool/JavaCommonTests.py index 9242624..b0a788e 100644 --- a/src/engine/SCons/Tool/JavaCommonTests.py +++ b/src/engine/SCons/Tool/JavaCommonTests.py @@ -68,6 +68,30 @@ public class Foo assert classes == ['Foo'], classes + def test_file_parser(self): + """Test the file parser""" + input = """\ +package com.sub.bar; + +public class Foo +{ + public static void main(String[] args) + { + /* This tests that unicde is handled . */ + String hello1 = new String("ఎత్తువెడల్పు"); + } +} +""" + file_name = 'test_file_parser.java' + with open(file_name, 'w', encoding='UTF-8') as jf: + print(input, file=jf) + + pkg_dir, classes = SCons.Tool.JavaCommon.parse_java_file(file_name) + if os.path.exists(file_name): + os.remove(file_name) + assert pkg_dir == os.path.join('com', 'sub', 'bar'), pkg_dir + assert classes == ['Foo'], classes + def test_dollar_sign(self): """Test class names with $ in them""" -- cgit v0.12 From 3f442c1d3f6a35df4572e9a3b123213356193df2 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Mon, 24 Feb 2020 08:41:49 -0700 Subject: rutest cleanups and subprocess update - Clean up some things suggested by checkers. - Add a few docsstrings. - Make RuntestBase an abstract class - Eliminate Py2 remnants. - Use subprocess.run for a slightly cleaner interface - don't have to separately do wait or communicate, don't need to set up context manager, and everything returns cleanly in a subprocess.CompletedProcess. Signed-off-by: Mats Wichmann --- runtest.py | 310 ++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 162 insertions(+), 148 deletions(-) diff --git a/runtest.py b/runtest.py index 70f1385..f13dde1 100755 --- a/runtest.py +++ b/runtest.py @@ -66,7 +66,7 @@ Options: Environment Variables: PRESERVE, PRESERVE_{PASS,FAIL,NO_RESULT}: preserve test subdirs - TESTCMD_VERBOSE: turn on verbosity in TestCommand\ + TESTCMD_VERBOSE: turn on verbosity in TestCommand """ import getopt @@ -74,36 +74,35 @@ import glob import os import re import stat +import subprocess import sys -import time - +import tempfile import threading -try: # python3 - from queue import Queue -except ImportError as e: # python2 - from Queue import Queue -import subprocess +import time +from abc import ABC, abstractmethod +from optparse import OptionParser, BadOptionError +from queue import Queue cwd = os.getcwd() -baseline = 0 +baseline = None builddir = os.path.join(cwd, 'build') -external = 0 +external = False debug = '' -execute_tests = 1 +execute_tests = True jobs = 1 -list_only = None -printcommand = 1 +list_only = False +printcommand = True package = None -print_passed_summary = None +print_passed_summary = False scons = None -scons_exec = None +scons_exec = False testlistfile = None version = '' -print_times = None +print_times = False python = None sp = [] -print_progress = 1 +print_progress = True catch_output = False suppress_output = False allow_pipe_files = True @@ -122,8 +121,6 @@ helpstr = usagestr + __doc__ # unknown options and lets them pile up in the leftover argument # list. Useful to gradually port getopt to optparse. -from optparse import OptionParser, BadOptionError - class PassThroughOptionParser(OptionParser): def _process_long_opt(self, rargs, values): try: @@ -137,31 +134,46 @@ class PassThroughOptionParser(OptionParser): self.largs.append(err.opt_str) parser = PassThroughOptionParser(add_help_option=False) -parser.add_option('-a', '--all', action='store_true', - help="Run all tests.") +parser.add_option('-a', '--all', action='store_true', help="Run all tests.") parser.add_option('-o', '--output', - help="Save the output from a test run to the log file.") + help="Save the output from a test run to the log file.") parser.add_option('--runner', metavar='class', - help="Test runner class for unit tests.") -parser.add_option('--xml', - help="Save results to file in SCons XML format.") + help="Test runner class for unit tests.") +parser.add_option('--xml', help="Save results to file in SCons XML format.") (options, args) = parser.parse_args() -#print("options:", options) -#print("args:", args) - - -opts, args = getopt.getopt(args, "b:def:hj:klnP:p:qsv:Xx:t", - ['baseline=', 'builddir=', - 'debug', 'external', 'file=', 'help', 'no-progress', - 'jobs=', - 'list', 'no-exec', 'nopipefiles', - 'package=', 'passed', 'python=', - 'quiet', - 'quit-on-failure', - 'short-progress', 'time', - 'version=', 'exec=', - 'verbose=', 'exclude-list=']) +# print("options:", options) +# print("args:", args) + + +opts, args = getopt.getopt( + args, + "b:def:hj:klnP:p:qsv:Xx:t", + [ + "baseline=", + "builddir=", + "debug", + "external", + "file=", + "help", + "no-progress", + "jobs=", + "list", + "no-exec", + "nopipefiles", + "package=", + "passed", + "python=", + "quiet", + "quit-on-failure", + "short-progress", + "time", + "version=", + "exec=", + "verbose=", + "exclude-list=", + ], +) for o, a in opts: if o in ['-b', '--baseline']: @@ -171,13 +183,13 @@ for o, a in opts: if not os.path.isabs(builddir): builddir = os.path.normpath(os.path.join(cwd, builddir)) elif o in ['-d', '--debug']: - for dir in sys.path: - pdb = os.path.join(dir, 'pdb.py') + for d in sys.path: + pdb = os.path.join(d, 'pdb.py') if os.path.exists(pdb): debug = pdb break elif o in ['-e', '--external']: - external = 1 + external = True elif o in ['-f', '--file']: if not os.path.isabs(a): a = os.path.join(cwd, a) @@ -191,46 +203,45 @@ for o, a in opts: # or outputs will interleave and be hard to read catch_output = True elif o in ['-k', '--no-progress']: - print_progress = 0 + print_progress = False elif o in ['-l', '--list']: - list_only = 1 + list_only = True elif o in ['-n', '--no-exec']: - execute_tests = None + execute_tests = False elif o in ['--nopipefiles']: allow_pipe_files = False elif o in ['-p', '--package']: package = a elif o in ['--passed']: - print_passed_summary = 1 + print_passed_summary = True elif o in ['-P', '--python']: python = a elif o in ['-q', '--quiet']: - printcommand = 0 + printcommand = False suppress_output = catch_output = True elif o in ['--quit-on-failure']: quit_on_failure = True elif o in ['-s', '--short-progress']: - print_progress = 1 + print_progress = True suppress_output = catch_output = True elif o in ['-t', '--time']: - print_times = 1 + print_times = True elif o in ['--verbose']: os.environ['TESTCMD_VERBOSE'] = a elif o in ['-v', '--version']: version = a elif o in ['-X']: - scons_exec = 1 + scons_exec = True elif o in ['-x', '--exec']: scons = a elif o in ['--exclude-list']: excludelistfile = a -# --- setup stdout/stderr --- -class Unbuffered(object): +class Unbuffered(): + """ class to arrange for stdout/stderr to be unbuffered """ def __init__(self, file): self.file = file - self.softspace = 0 ## backward compatibility; not supported in Py3k def write(self, arg): self.file.write(arg) self.file.flush() @@ -240,9 +251,12 @@ class Unbuffered(object): sys.stdout = Unbuffered(sys.stdout) sys.stderr = Unbuffered(sys.stderr) +# possible alternative: switch to using print, and: +# print = functools.partial(print, flush) + if options.output: logfile = open(options.output, 'w') - class Tee(object): + class Tee(): def __init__(self, openfile, stream): self.file = openfile self.stream = stream @@ -254,11 +268,10 @@ if options.output: # --- define helpers ---- if sys.platform in ('win32', 'cygwin'): - def whereis(file): pathext = [''] + os.environ['PATHEXT'].split(os.pathsep) - for dir in os.environ['PATH'].split(os.pathsep): - f = os.path.join(dir, file) + for d in os.environ['PATH'].split(os.pathsep): + f = os.path.join(d, file) for ext in pathext: fext = f + ext if os.path.isfile(fext): @@ -266,10 +279,9 @@ if sys.platform in ('win32', 'cygwin'): return None else: - def whereis(file): - for dir in os.environ['PATH'].split(os.pathsep): - f = os.path.join(dir, file) + for d in os.environ['PATH'].split(os.pathsep): + f = os.path.join(d, file) if os.path.isfile(f): try: st = os.stat(f) @@ -297,8 +309,8 @@ if not catch_output: # Without any output suppressed, we let the subprocess # write its stuff freely to stdout/stderr. def spawn_it(command_args): - p = subprocess.Popen(command_args, shell=False) - return (None, None, p.wait()) + cp = subprocess.run(command_args, shell=False) + return cp.stdout, cp.stderr, cp.returncode else: # Else, we catch the output of both pipes... if allow_pipe_files: @@ -315,16 +327,13 @@ else: # subprocess.PIPE. def spawn_it(command_args): # Create temporary files - import tempfile tmp_stdout = tempfile.TemporaryFile(mode='w+t') tmp_stderr = tempfile.TemporaryFile(mode='w+t') # Start subprocess... - p = subprocess.Popen(command_args, - stdout=tmp_stdout, - stderr=tmp_stderr, - shell=False) - # ... and wait for it to finish. - ret = p.wait() + cp = subprocess.run(command_args, + stdout=tmp_stdout, + stderr=tmp_stderr, + shell=False) try: # Rewind to start of files @@ -339,7 +348,7 @@ else: tmp_stderr.close() # Return values - return (spawned_stderr, spawned_stdout, ret) + return spawned_stderr, spawned_stdout, cp.returncode else: # We get here only if the user gave the '--nopipefiles' @@ -355,16 +364,15 @@ else: # Hence a deadlock. # Be dragons here! Better don't use this! def spawn_it(command_args): - p = subprocess.Popen(command_args, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - shell=False) - spawned_stdout = p.stdout.read() - spawned_stderr = p.stderr.read() - return (spawned_stderr, spawned_stdout, p.wait()) + cp = subprocess.run(command_args, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + shell=False) + return cp.stdout, cp.stderr, cp.returncode -class RuntestBase(object): +class RuntestBase(ABC): + """ Base class for tests """ def __init__(self, path, num, spe=None): self.path = path self.num = num @@ -374,14 +382,19 @@ class RuntestBase(object): self.command_str = "" self.test_time = self.total_time = 0 if spe: - for dir in spe: - f = os.path.join(dir, path) + for d in spe: + f = os.path.join(d, path) if os.path.isfile(f): self.abspath = f break + @abstractmethod + def execute(self): + pass + class SystemExecutor(RuntestBase): + """ Test class for tests executed with spawn_it() """ def execute(self): self.stderr, self.stdout, s = spawn_it(self.command_args) self.status = s @@ -390,22 +403,28 @@ class SystemExecutor(RuntestBase): class PopenExecutor(RuntestBase): + """ Test class for tests executed with Popen + + A bit of a misnomer as the Popen call is now wrapped + by calling subprocess.run (behind the covers uses Popen. + Very similar to SystemExecutor, but uses command_str + instead of command_args, and doesn't allow for not catching + the output. + """ # For an explanation of the following 'if ... else' # and the 'allow_pipe_files' option, please check out the # definition of spawn_it() above. if allow_pipe_files: def execute(self): # Create temporary files - import tempfile tmp_stdout = tempfile.TemporaryFile(mode='w+t') tmp_stderr = tempfile.TemporaryFile(mode='w+t') # Start subprocess... - p = subprocess.Popen(self.command_str.split(), - stdout=tmp_stdout, - stderr=tmp_stderr, - shell=False) - # ... and wait for it to finish. - self.status = p.wait() + cp = subprocess.run(self.command_str.split(), + stdout=tmp_stdout, + stderr=tmp_stderr, + shell=False) + self.status = cp.returncode try: # Rewind to start of files @@ -420,19 +439,20 @@ class PopenExecutor(RuntestBase): tmp_stderr.close() else: def execute(self): - p = subprocess.Popen(self.command_str.split(), - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - shell=False) - self.status = p.wait() - with p.stdout: - self.stdout = p.stdout.read() - with p.stderr: - self.stderr = p.stderr.read() + cp = subprocess.run(self.command_str.split(), + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + shell=False) + self.status = cp.returncode + self.stdout = cp.stdout + self.stderr = cp.stderr class XML(PopenExecutor): - def header(self, f): + """ Test class for tests that will output in scons xml """ + @staticmethod + def header(f): f.write(' \n') + def write(self, f): f.write(' \n') f.write(' %s\n' % self.path) @@ -442,6 +462,7 @@ class XML(PopenExecutor): f.write(' %s\n' % self.stderr) f.write(' \n' % self.test_time) f.write(' \n') + def footer(self, f): f.write(' \n' % self.total_time) f.write(' \n') @@ -454,7 +475,7 @@ else: # --- start processing --- if package: - dir = { + dirs = { 'deb' : 'usr', 'local-tar-gz' : None, 'local-zip' : None, @@ -471,13 +492,13 @@ if package: 'deb' : os.path.join('python2.1', 'site-packages') } - if package not in dir: + if package not in dirs: sys.stderr.write("Unknown package '%s'\n" % package) sys.exit(2) test_dir = os.path.join(builddir, 'test-%s' % package) - if dir[package] is None: + if dirs[package] is None: scons_script_dir = test_dir globs = glob.glob(os.path.join(test_dir, 'scons-local-*')) if not globs: @@ -486,13 +507,13 @@ if package: scons_lib_dir = None pythonpath_dir = globs[len(globs)-1] elif sys.platform == 'win32': - scons_script_dir = os.path.join(test_dir, dir[package], 'Scripts') - scons_lib_dir = os.path.join(test_dir, dir[package]) + scons_script_dir = os.path.join(test_dir, dirs[package], 'Scripts') + scons_lib_dir = os.path.join(test_dir, dirs[package]) pythonpath_dir = scons_lib_dir else: - scons_script_dir = os.path.join(test_dir, dir[package], 'bin') - l = lib.get(package, 'scons') - scons_lib_dir = os.path.join(test_dir, dir[package], 'lib', l) + scons_script_dir = os.path.join(test_dir, dirs[package], 'bin') + sconslib = lib.get(package, 'scons') + scons_lib_dir = os.path.join(test_dir, dirs[package], 'lib', sconslib) pythonpath_dir = scons_lib_dir scons_runtest_dir = builddir @@ -506,7 +527,7 @@ else: elif baseline == '-': url = None with os.popen("svn info 2>&1", "r") as p: - svn_info = p.read() + svn_info = p.read() match = re.search(r'URL: (.*)', svn_info) if match: url = match.group(1) @@ -514,7 +535,6 @@ else: sys.stderr.write('runtest.py: could not find a URL:\n') sys.stderr.write(svn_info) sys.exit(1) - import tempfile base = tempfile.mkdtemp(prefix='runtest-tmp-') command = 'cd %s && svn co -q %s' % (base, url) @@ -569,7 +589,7 @@ if '_JAVA_OPTIONS' in os.environ: # harness from $srcdir/etc. Those modules should be transfered # to testing/, in which case this manipulation of PYTHONPATH # should be able to go away. -pythonpaths = [ pythonpath_dir ] +pythonpaths = [pythonpath_dir] scriptpath = os.path.dirname(os.path.realpath(__file__)) @@ -593,7 +613,7 @@ unittests = [] endtests = [] -def find_Tests_py(directory): +def find_unit_tests(directory): """ Look for unit tests """ result = [] for dirpath, dirnames, filenames in os.walk(directory): @@ -606,7 +626,7 @@ def find_Tests_py(directory): return sorted(result) -def find_py(directory): +def find_e2e_tests(directory): """ Look for end-to-end tests """ result = [] @@ -631,8 +651,7 @@ if testlistfile: tests = [x for x in tests if x[0] != '#'] tests = [x[:-1] for x in tests] tests = [x.strip() for x in tests] - tests = [x for x in tests if len(x) > 0] - + tests = [x for x in tests if x] else: testpaths = [] @@ -664,10 +683,10 @@ else: for path in glob.glob(tp): if os.path.isdir(path): if path.startswith('src') or path.startswith('testing'): - for p in find_Tests_py(path): + for p in find_unit_tests(path): unittests.append(p) elif path.startswith('test'): - for p in find_py(path): + for p in find_e2e_tests(path): endtests.append(p) else: if path.endswith("Tests.py"): @@ -693,11 +712,11 @@ if excludelistfile: excludetests = [x for x in excludetests if x[0] != '#'] excludetests = [x[:-1] for x in excludetests] excludetests = [x.strip() for x in excludetests] - excludetests = [x for x in excludetests if len(x) > 0] + excludetests = [x for x in excludetests if x] # ---[ test processing ]----------------------------------- tests = [t for t in tests if t not in excludetests] -tests = [Test(t, n+1) for n, t in enumerate(tests)] +tests = [Test(t, n + 1) for n, t in enumerate(tests)] if list_only: for t in tests: @@ -711,24 +730,14 @@ if not python: python = sys.executable os.environ["python_executable"] = python -# time.clock() is the suggested interface for doing benchmarking timings, -# but time.time() does a better job on Linux systems, so let that be -# the non-Windows default. - -#TODO: clean up when py2 support is dropped -try: - time_func = time.perf_counter -except AttributeError: - if sys.platform == 'win32': - time_func = time.clock - else: - time_func = time.time - if print_times: - print_time_func = lambda fmt, time: sys.stdout.write(fmt % time) + def print_time(fmt, tm): + sys.stdout.write(fmt % tm) else: - print_time_func = lambda fmt, time: None + def print_time(fmt, tm): + pass +time_func = time.perf_counter total_start_time = time_func() total_num_tests = len(tests) @@ -759,7 +768,7 @@ def log_result(t, io_lock=None): print(t.stdout) if t.stderr: print(t.stderr) - print_time_func("Test execution time: %.1f seconds\n", t.test_time) + print_time("Test execution time: %.1f seconds\n", t.test_time) finally: if io_lock: io_lock.release() @@ -773,8 +782,6 @@ def log_result(t, io_lock=None): def run_test(t, io_lock=None, run_async=True): t.headline = "" command_args = [] - if sys.version_info[0] < 3: - command_args.append('-tt') if debug: command_args.append(debug) command_args.append(t.path) @@ -785,10 +792,13 @@ def run_test(t, io_lock=None, run_async=True): t.command_str = " ".join([escape(python)] + command_args) if printcommand: if print_progress: - t.headline += ("%d/%d (%.2f%s) %s\n" % (t.num, total_num_tests, - float(t.num)*100.0/float(total_num_tests), - '%', - t.command_str)) + t.headline += "%d/%d (%.2f%s) %s\n" % ( + t.num, + total_num_tests, + float(t.num) * 100.0 / float(total_num_tests), + "%", + t.command_str, + ) else: t.headline += t.command_str + "\n" if not suppress_output and not catch_output: @@ -810,6 +820,10 @@ def run_test(t, io_lock=None, run_async=True): class RunTest(threading.Thread): + """ Test Runner class + + One instance will be created for each job thread in multi-job mode + """ def __init__(self, queue=None, io_lock=None, group=None, target=None, name=None, args=(), kwargs=None): super(RunTest, self).__init__(group=group, target=target, name=name) @@ -823,25 +837,25 @@ class RunTest(threading.Thread): if jobs > 1: print("Running tests using %d jobs" % jobs) - queue = Queue() + testq = Queue() for t in tests: - queue.put(t) - io_lock = threading.Lock() + testq.put(t) + testlock = threading.Lock() # Start worker threads to consume the queue - threads = [RunTest(queue=queue, io_lock=io_lock) for _ in range(jobs)] + threads = [RunTest(queue=testq, io_lock=testlock) for _ in range(jobs)] for t in threads: t.daemon = True t.start() # wait on the queue rather than the individual threads - queue.join() + testq.join() else: for t in tests: run_test(t, io_lock=None, run_async=False) # --- all tests are complete by the time we get here --- -if len(tests) > 0: +if tests: tests[0].total_time = time_func() - total_start_time - print_time_func("Total execution time for all tests: %.1f seconds\n", tests[0].total_time) + print_time("Total execution time for all tests: %.1f seconds\n", tests[0].total_time) passed = [t for t in tests if t.status == 0] fail = [t for t in tests if t.status == 1] @@ -890,9 +904,9 @@ if options.output: if isinstance(sys.stderr, Tee): sys.stderr.file.close() -if len(fail): +if fail: sys.exit(1) -elif len(no_result): +elif no_result: sys.exit(2) else: sys.exit(0) -- cgit v0.12 From b6ec4db801b44fe067488f1eab4f7c98b8693d46 Mon Sep 17 00:00:00 2001 From: Robert Boehne Date: Mon, 24 Feb 2020 15:53:53 -0600 Subject: Add a blurb about specifining encoding when opening Java source files as text. --- src/CHANGES.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 20b99c4..7c5c9c2 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -10,6 +10,10 @@ NOTE: Please include a reference to any Issues resolved by your changes in the b RELEASE VERSION/DATE TO BE FILLED IN LATER +From Rob Boehne + - Specify UTF-8 encoding when opening Java source file as text. By default, encoding is the output + of locale.getpreferredencoding(False), and varies by platform. + 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 -- cgit v0.12 From 304245ce439fe49e788d7d2dab8690f4f67a56fd Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Mon, 2 Dec 2019 10:59:29 -0700 Subject: Fix some test fixture-handling nits. dir-fixture() did not concatenate a source list into a path as the testing doc says it should. fix-fixture() did not either, and the doc didn't say so; now it does (docstring and external testing doc). There was a way to slip through both dir_fixtures and file_fixture with the path invalid - if you have fixture dirs defined, and the dir/file is not found in them, you'll come out of the loop set to the last fixture dir and not try the current dir. This doesn't break anything, just leads to a somewhat misleading message if the fixture really isn't found - the traceback indicates the fixture was not found in whatever the last passed-in fixture dir was. Now it looks like it was not found in the source testing dir. The message can still be improved to be more descriptive. A couple of minor Py2 removals. Testing doc didn't mention FIXTURE_DIRS, so this was added. A bunch of other doc fiddling. Signed-off-by: Mats Wichmann --- testing/framework/TestCmd.py | 111 ++++++++++++------------- testing/framework/test-framework.rst | 152 ++++++++++++++++++++++++----------- 2 files changed, 156 insertions(+), 107 deletions(-) diff --git a/testing/framework/TestCmd.py b/testing/framework/TestCmd.py index ed8b4b4..9b5df8e 100644 --- a/testing/framework/TestCmd.py +++ b/testing/framework/TestCmd.py @@ -298,6 +298,7 @@ import re import shutil import signal import stat +import subprocess import sys import tempfile import threading @@ -306,7 +307,6 @@ import traceback 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') @@ -729,23 +729,6 @@ else: default_sleep_seconds = 1 -import subprocess - -try: - subprocess.Popen.terminate -except AttributeError: - if sys.platform == 'win32': - import win32process - - def terminate(self): - win32process.TerminateProcess(self._handle, 1) - else: - def terminate(self): - os.kill(self.pid, signal.SIGTERM) - method = types.MethodType(terminate, None, subprocess.Popen) - setattr(subprocess.Popen, 'terminate', method) - - # From Josiah Carlson, # ASPN : Python Cookbook : Module to allow Asynchronous subprocess use on Windows and Posix platforms # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/440554 @@ -1025,12 +1008,11 @@ class TestCmd(object): self.condition = 'no_result' self.workdir_set(workdir) self.subdir(subdir) - self.fixture_dirs = [] try: self.fixture_dirs = (os.environ['FIXTURE_DIRS']).split(os.pathsep) except KeyError: - pass + self.fixture_dirs = [] def __del__(self): @@ -1051,7 +1033,7 @@ class TestCmd(object): def canonicalize(self, path): if is_List(path): - path = os.path.join(*tuple(path)) + path = os.path.join(*path) if not os.path.isabs(path): path = os.path.join(self.workdir, path) return path @@ -1312,7 +1294,7 @@ class TestCmd(object): file = self.canonicalize(file) if mode[0] != 'r': raise ValueError("mode must begin with 'r'") - if IS_PY3 and 'b' not in mode: + if 'b' not in mode: with open(file, mode, newline=newline) as f: return f.read() else: @@ -1360,23 +1342,31 @@ class TestCmd(object): return result def dir_fixture(self, srcdir, dstdir=None): - """Copies the contents of the specified folder srcdir from - the directory of the called script, to the current - working directory. - - The srcdir name may be a list, in which case the elements are - concatenated with the os.path.join() method. The dstdir is - assumed to be under the temporary working directory, it gets - created automatically, if it does not already exist. + """ Copies the contents of the fixture dir to the test dir. + + If srcdir is an absolute path, it is tried directly, else + the fixture_dirs are prepended to it and tried in succession. + To tightly control the search order, the harness can be called + with FIXTURE_DIRS also including the test source directory + in the desired place, it will otherwise be tried last. + + srcdir may be a list, in which case the elements are first + joined into a pathname. + + If a dstdir is supplied, it is taken to be under the temporary + working dir. dstdir is created automatically if needed. """ + if is_List(srcdir): + srcdir = os.path.join(*srcdir) + spath = srcdir if srcdir and self.fixture_dirs and not os.path.isabs(srcdir): for dir in self.fixture_dirs: spath = os.path.join(dir, srcdir) if os.path.isdir(spath): break - else: - spath = srcdir + else: + spath = srcdir if dstdir: dstdir = self.canonicalize(dstdir) @@ -1403,23 +1393,33 @@ class TestCmd(object): shutil.copy(epath, dpath) def file_fixture(self, srcfile, dstfile=None): - """Copies the file srcfile from the directory of - the called script, to the current working directory. + """ Copies a fixture file to the test dir, optionally renaming. + + If srcfile is an absolute path, it is tried directly, else + the fixture_dirs are prepended to it and tried in succession. + To tightly control the search order, the harness can be called + with FIXTURE_DIRS also including the test source directory + in the desired place, it will otherwise be tried last. + + srcfile may be a list, in which case the elements are first + joined into a pathname. - The dstfile is assumed to be under the temporary working - directory unless it is an absolute path name. - If dstfile is specified its target directory gets created - automatically, if it does not already exist. + dstfile is assumed to be under the temporary working directory + unless it is an absolute path name. Any directory components + of dstfile are created automatically if needed. """ - srcpath, srctail = os.path.split(srcfile) + if is_List(srcfile): + srcdir = os.path.join(*srcfile) - if srcpath and (not self.fixture_dirs or os.path.isabs(srcpath)): - spath = srcfile - else: + srcpath, srctail = os.path.split(srcfile) + spath = srcfile + if srcfile and self.fixture_dirs and not os.path.isabs(srcfile): for dir in self.fixture_dirs: spath = os.path.join(dir, srcfile) if os.path.isfile(spath): break + else: + spath = srcfile if not dstfile: if srctail: @@ -1435,8 +1435,8 @@ class TestCmd(object): dstlist = dstlist[1:] for idx in range(len(dstlist)): self.subdir(dstlist[:idx + 1]) - dpath = os.path.join(self.workdir, dstfile) + shutil.copy(spath, dpath) def start(self, program=None, @@ -1445,8 +1445,7 @@ class TestCmd(object): universal_newlines=None, timeout=_Null, **kw): - """ - Starts a program or script for the test environment. + """ Starts a program or script for the test environment. The specified program will have the original directory prepended unless it is enclosed in a [list]. @@ -1478,7 +1477,7 @@ class TestCmd(object): self.timer = threading.Timer(float(timeout), self._timeout) self.timer.start() - if IS_PY3 and sys.platform == 'win32': + if sys.platform == 'win32': # Set this otherwist stdout/stderr pipes default to # windows default locale cp1252 which will throw exception # if using non-ascii characters. @@ -1517,15 +1516,10 @@ class TestCmd(object): if not stream: return stream - # TODO: Run full tests on both platforms and see if this fixes failures # It seems that py3.6 still sets text mode if you set encoding. - elif sys.version_info[0] == 3: # TODO and sys.version_info[1] < 6: - stream = stream.decode('utf-8', errors='replace') - stream = stream.replace('\r\n', '\n') - elif sys.version_info[0] == 2: - stream = stream.replace('\r\n', '\n') - - return stream + # was: if IS_PY3: # TODO and sys.version_info[1] < 6: + stream = stream.decode('utf-8', errors='replace') + return stream.replace('\r\n', '\n') def finish(self, popen=None, **kw): """ @@ -1587,7 +1581,8 @@ class TestCmd(object): if is_List(stdin): stdin = ''.join(stdin) - if stdin and IS_PY3:# and sys.version_info[1] < 6: + # TODO: was: if stdin and IS_PY3:# and sys.version_info[1] < 6: + if stdin: stdin = to_bytes(stdin) # TODO(sgk): figure out how to re-use the logic in the .finish() @@ -1687,7 +1682,7 @@ class TestCmd(object): if sub is None: continue if is_List(sub): - sub = os.path.join(*tuple(sub)) + sub = os.path.join(*sub) new = os.path.join(self.workdir, sub) try: os.mkdir(new) @@ -1786,7 +1781,7 @@ class TestCmd(object): """Find an executable file. """ if is_List(file): - file = os.path.join(*tuple(file)) + file = os.path.join(*file) if not os.path.isabs(file): file = where_is(file, path, pathext) return file @@ -1808,7 +1803,7 @@ class TestCmd(object): the temporary working directory name with the specified arguments using the os.path.join() method. """ - return os.path.join(self.workdir, *tuple(args)) + return os.path.join(self.workdir, *args) def readable(self, top, read=1): """Make the specified directory tree readable (read == 1) diff --git a/testing/framework/test-framework.rst b/testing/framework/test-framework.rst index a0fe861..965efd4 100644 --- a/testing/framework/test-framework.rst +++ b/testing/framework/test-framework.rst @@ -113,14 +113,14 @@ You may specifically list one or more tests to be run:: $ python runtest.py src/engine/SCons/BuilderTests.py $ python runtest.py test/option-j.py test/Program.py -Folder names are allowed arguments as well, so you can do:: +Folder names are allowed in the test list as well, so you can do:: $ python runtest.py test/SWIG to run all SWIG tests only. You can also use the ``-f`` option to execute just the tests listed in -a specified text file:: +a test list file:: $ cat testlist.txt test/option-j.py @@ -136,9 +136,11 @@ If more than one test is run, the ``runtest.py`` script prints a summary of how many tests passed, failed, or yielded no result, and lists any unsuccessful tests. -The above invocations all test directly the files underneath the ``src/`` -subdirectory, and do not require that a packaging build be performed -first. The ``runtest.py`` script supports additional options to run +The above invocations all test against the scons files underneath the ``src/`` +subdirectory, and do not require that a packaging build of SCons be performed +first. This is the most common mode: make some changes, and test in +place the effects. +The ``runtest.py`` script supports additional options to run tests against unpacked packages in the ``build/test-*/`` subdirectories. If you are testing a separate Tool outside of the SCons source tree, you @@ -149,26 +151,33 @@ have to call the ``runtest.py`` script in *external* (stand-alone) mode:: This ensures that the testing framework doesn't try to access SCons classes needed for some of the *internal* test cases. -Note, that the actual tests are carried out in a temporary folder each, -which gets deleted afterwards. This ensures that your source directories -don't get clobbered with temporary files from the test runs. It also -means that you can't simply change into a folder to "debug things" after -a test has gone wrong. For a way around this, check out the ``PRESERVE`` -environment variable. It can be seen in action in -`How to convert old tests`_ below. +Note that as each test is run, it is executed in a temporary directory +created just for that test, which is by default removed when the +test is complete. This ensures that your source directories +don't get clobbered with temporary files and changes from the test runs. +If the test itself needs to know the directory, it can be obtained +as ``test.workdir``, or more commonly by calling ``test.workpath``, +a function which takes a path-component argument and returns the path to +that path-component in the testing directory. + +The use of an ephemeral test directory means that you can't simply change +into a folder to "debug things" after a test has gone wrong. +For a way around this, check out the ``PRESERVE`` environment variable. +It can be seen in action in `How to Convert Old Tests to Use Fixures`_ below. Not Running Tests ================= If you simply want to check which tests would get executed, you can call -the ``runtest.py`` script with the ``-l`` option:: +the ``runtest.py`` script with the ``-l`` option combined with whichever +test finding options (see below) you intend to use. Example: - $ python runtest.py -l + $ python runtest.py -l test/scons-time -Then there is also the ``-n`` option, which prints the command line for -each single test, but doesn't actually execute them:: +``runtest.py`` also has ``-n`` option, which prints the command line for +each test which would have been run, but doesn't actually execute them:: - $ python runtest.py -n + $ python runtest.py -n -a Finding Tests ============= @@ -182,7 +191,7 @@ directory. It then dives into the ``src`` and ``test`` folders, where it tries to find filenames ``*Test.py`` - for the ``src`` directory + for the ``src`` folder ``*.py`` for the ``test`` folder @@ -216,6 +225,8 @@ a simple "Hello, world!" example:: """) test.write('hello.c', """\ + #include + int main(int argc, char *argv[]) { @@ -259,7 +270,7 @@ a simple "Hello, world!" example:: ``test.write('hello.c', ...)`` This lines creates an ``hello.c`` file in the temporary directory. - Note that we have to escape the ``\\n`` in the + Note that we have to escape the newline in the ``"Hello, world!\\n"`` string so that it ends up as a single backslash in the ``hello.c`` file on disk. @@ -282,7 +293,9 @@ a simple "Hello, world!" example:: non-zero, or there is any error output. ``test.pass_test()`` - This is always the last line in a test script. It prints ``PASSED`` + This is always the last line in a test script. If we get to + this line, it means we haven't bailed out on a failure or skip, + so the result was good. It prints ``PASSED`` on the screen and makes sure we exit with a ``0`` status to indicate the test passed. As a side effect of destroying the ``test`` object, the created temporary directory will be removed. @@ -295,14 +308,21 @@ on the fly by the test program. We give a filename to the ``TestSCons.write()`` method, and a string holding its contents, and it gets written to the test folder right before starting.. -This technique can still be seen throughout most of the end-to-end tests, -but there is a better way. To create a test, you need to create the -files that will be used, then when they work reasonably, they need to -be pasted into the script. The process repeats for maintenance. Once -a test gets more complex and/or grows many steps, the test script gets -harder to read. Why not keep the files as is? - -In testing parlance, a fixture is a repeatable test setup. The scons +This simple technique can be seen throughout most of the end-to-end +tests as it was the original technique provided to test developers, +but it is definitely not the preferred way to write a new test. +To develop this way, you first need to create the necessary files and +get them to work, then convert them to an embedded string form, which may +involve lots of extra escaping. These embedded files are then tricky +to maintain. As a test grows multiple steps, it becomes less easy to +read, since the embedded strings aren't quite the final files, and +the volume of test code obscures the flow of the testing steps. +Additionally, as SCons moves more to the use of code checkers and +formatters to detect problems and keep a standard coding style for +better readability, note that these techniques don't look inside +strings, so they're either left out or lots of manual work has to be done. + +In testing parlance, a fixture is a repeatable test setup. The SCons test harness allows the use of saved files or directories to be used 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 @@ -314,22 +334,28 @@ them, see instructions in the above section named "Finding Tests". Directory Fixtures ################## -The function ``dir_fixture(self, srcdir, dstdir=None)`` in the ``TestCmd`` -class copies the contents of the specified folder ``srcdir`` from +The test harness method ``dir_fixture(srcdir, [dstdir])`` +copies the contents of the specified folder ``srcdir`` from the directory of the called test script to the current temporary test directory. The ``srcdir`` name may be a list, in which case the elements are concatenated with the ``os.path.join()`` method. The ``dstdir`` is assumed to be under the temporary working directory, it gets created automatically, if it does not already exist. +If ``srcdir`` represents an absolute path, it is used as-is. Otherwise, +if the harness was invoked with the environment variable ``FIXTURE_DIRS`` +set, the test instance will present that list of directories to search +as ``self.fixture_dirs``, each of these are additionally searched for +a directory with the name of ``srcdir``. + A short syntax example:: test = TestSCons.TestSCons() test.dir_fixture('image') test.run() -would copy all files and subfolders from the local ``image`` folder, -to the temporary directory for the current test. +would copy all files and subfolders from the local ``image`` folder +to the temporary directory for the current test, then run it. To see a real example for this in action, refer to the test named ``test/packaging/convenience-functions/convenience-functions.py``. @@ -337,13 +363,17 @@ To see a real example for this in action, refer to the test named File Fixtures ############# -Like for directory fixtures, ``file_fixture(self, srcfile, dstfile=None)`` +Similarly, the method ``file_fixture(srcfile, [dstfile])`` copies the file ``srcfile`` from the directory of the called script, to the temporary test directory. The ``dstfile`` is assumed to be under the temporary working directory, unless it is an absolute path name. If ``dstfile`` is specified, its target directory gets created automatically if it doesn't already exist. +If ``srcfile`` represents an absolute path, it is used as-is. Otherwise, +any passed in fixture directories are used as additional places to +search, as for the ``dir_fixture`` case. + With the following code:: test = TestSCons.TestSCons() @@ -368,7 +398,7 @@ list of available Tools, though not all may have tests yet. How to Convert Old Tests to Use Fixures ####################################### -Tests using the inline ``TestSCons.write()`` method can easily be +Tests using the inline ``TestSCons.write()`` method can fairly easily be converted to the fixture based approach. For this, we need to get at the files as they are written to each temporary test folder. @@ -383,9 +413,9 @@ So, you should be able to give the commands:: assuming Linux and a bash-like shell. For a Windows ``cmd`` shell, use ``set PRESERVE=1`` (that will leave it set for the duration of the -``cmd`` session, unless manually deleted). +``cmd`` session, unless manually cleared). -The output should then look something like this:: +The output will then look something like this:: 1/1 (100.00%) /usr/bin/python -tt test/packaging/sandbox-test.py PASSED @@ -399,6 +429,19 @@ tedious ``TestSCons.write()`` statements and replace them by a single Finally, don't forget to clean up and remove the temporary test directory. ``;)`` +For more complex testing scenarios you can use ``file_fixture`` with +the option to rename (that is, supplying a second argument, which is +the name to give the fixture file being copied). For example some test +files write multiple ``SConstruct`` files across the full run. +These files can be given different names - perhaps using a sufffix - +and then sucessively copied to the final name as needed:: + + test.file_fixture('fixture/SConstruct.part1', 'SConstruct') + # more setup, then run test + test.file_fixture('fixture/SConstruct.part2', 'SConstruct') + # etc. + + When Not to Use a Fixture ######################### @@ -413,30 +456,33 @@ kind of usage that does not lend itself to a fixture:: test.write('SConstruct', """ cc = Environment().Dictionary('CC') - env = Environment(LINK = r'%(_python_)s mylink.py', - LINKFLAGS = [], - CC = r'%(_python_)s mycc.py', - CXX = cc, - CXXFLAGS = []) - env.Program(target = 'test1', source = 'test1.c') + env = Environment(LINK=r'%(_python_)s mylink.py', + LINKFLAGS=[], + CC=r'%(_python_)s mycc.py', + CXX=cc, + CXXFLAGS=[]) + env.Program(target='test1', source='test1.c') """ % locals()) Here the value of ``_python_`` is picked out of the script's -``locals`` dictionary and interpolated into the string that -will be written to ``SConstruct``. +``locals`` dictionary - which works because we've set it above - +and interpolated using a mapping key into the string that will +be written to ``SConstruct``. A fixture would be hard to use +here because we don't know the value of `_python_` until runtime. The other files created in this test may still be candidates for -use in a fixture, however. +use as fixture files, however. Debugging End-to-End Tests ========================== Most of the end to end tests have expectations for standard output -and error from the test runs. The expectation could be either +and error embedded in the tests. The expectation could be either that there is nothing on that stream, or that it will contain very specific text which the test matches against. So adding -``print()`` calls, or ``sys,stderr.write()`` or similar will -emit data that the tests do not expect, and cause further failures. +``print()`` calls, or ``sys.stderr.write()`` or similar will +emit data that the tests do not expect, and thus cause further +failures - possibly even obscuring the original error. Say you have three different tests in a script, and the third one is unexpectedly failing. You add some debug prints to the part of scons that is involved, and now the first test of the @@ -445,7 +491,15 @@ to the third test you were trying to debug. Still, there are some techniques to help debugging. -Probably the most effective technique is to use the internal +The first step should be to run the tests so the harness +emits more information, without forcing more information into +the test stdout/stderr which will confuse result evaulation. +``runtest.py`` has several verbose levels which can be used +for this purpose: + + python runtest.py --verbose=2 test/foo.py + +You can also use the internal ``SCons.Debug.Trace()`` function, which prints output to ``/dev/tty`` on Linux/UNIX systems and ``con`` on Windows systems, so you can see what's going on. -- cgit v0.12 From ec9f68cb44bfe788c509d1de52c3f674a0fe4655 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Thu, 27 Feb 2020 07:08:32 -0700 Subject: [PR #3571] fix error and improve docs sider spotted a cut-n-paste error introduced in the PR (srcdir set instead of srcfile) framework doc now uses directory consistently (over folder, which is a desktop concept rather than a filesystem concept) tweaked wording a bit more Signed-off-by: Mats Wichmann --- testing/framework/TestCmd.py | 2 +- testing/framework/test-framework.rst | 101 ++++++++++++++++++----------------- 2 files changed, 53 insertions(+), 50 deletions(-) diff --git a/testing/framework/TestCmd.py b/testing/framework/TestCmd.py index 9b5df8e..01d12cb 100644 --- a/testing/framework/TestCmd.py +++ b/testing/framework/TestCmd.py @@ -1409,7 +1409,7 @@ class TestCmd(object): of dstfile are created automatically if needed. """ if is_List(srcfile): - srcdir = os.path.join(*srcfile) + srcfile = os.path.join(*srcfile) srcpath, srctail = os.path.split(srcfile) spath = srcfile diff --git a/testing/framework/test-framework.rst b/testing/framework/test-framework.rst index 965efd4..ce2e3c9 100644 --- a/testing/framework/test-framework.rst +++ b/testing/framework/test-framework.rst @@ -34,10 +34,10 @@ There are three types of SCons tests: *External Tests* For the support of external Tools (in the form of packages, preferably), the testing framework is extended so it can run in standalone mode. - You can start it from the top-level folder of your Tool's source tree, + You can start it from the top-level directory of your Tool's source tree, where it then finds all Python scripts (``*.py``) underneath the local ``test/`` directory. This implies that Tool tests have to be kept in - a folder named ``test``, like for the SCons core. + a directory named ``test``, like for the SCons core. Contrasting End-to-End and Unit Tests @@ -138,8 +138,8 @@ unsuccessful tests. The above invocations all test against the scons files underneath the ``src/`` subdirectory, and do not require that a packaging build of SCons be performed -first. This is the most common mode: make some changes, and test in -place the effects. +first. This is the most common mode: make some changes, and test the +effects in place. The ``runtest.py`` script supports additional options to run tests against unpacked packages in the ``build/test-*/`` subdirectories. @@ -156,12 +156,12 @@ created just for that test, which is by default removed when the test is complete. This ensures that your source directories don't get clobbered with temporary files and changes from the test runs. If the test itself needs to know the directory, it can be obtained -as ``test.workdir``, or more commonly by calling ``test.workpath``, +as ``test.workdir``, or more commonly by calling ``test.workpath()``, a function which takes a path-component argument and returns the path to that path-component in the testing directory. The use of an ephemeral test directory means that you can't simply change -into a folder to "debug things" after a test has gone wrong. +into a directory to "debug things" after a test has gone wrong. For a way around this, check out the ``PRESERVE`` environment variable. It can be seen in action in `How to Convert Old Tests to Use Fixures`_ below. @@ -174,8 +174,8 @@ test finding options (see below) you intend to use. Example: $ python runtest.py -l test/scons-time -``runtest.py`` also has ``-n`` option, which prints the command line for -each test which would have been run, but doesn't actually execute them:: +``runtest.py`` also has a ``-n`` option, which prints the command line for +each test which would have been run, but doesn't actually run them:: $ python runtest.py -n -a @@ -187,25 +187,25 @@ When started in *standard* mode:: $ python runtest.py -a ``runtest.py`` assumes that it is run from the SCons top-level source -directory. It then dives into the ``src`` and ``test`` folders, where -it tries to find filenames +directory. It then dives into the ``src`` and ``test`` directories, +where it tries to find filenames ``*Test.py`` - for the ``src`` folder + for the ``src`` directory (unit tests) ``*.py`` - for the ``test`` folder + for the ``test`` directory (end-to-end tests) When using fixtures, you may quickly end up in a position where you have -supporting Python script files in a subfolder, but they shouldn't get +supporting Python script files in a subdirectory which shouldn't be picked up as test scripts. In this case you have two options: -#. Add a file with the name ``sconstest.skip`` to your subfolder. This - lets ``runtest.py`` skip the contents of the directory completely. -#. Create a file ``.exclude_tests`` in each folder in question, and in - it list line-by-line the files to get excluded from testing. +#. Add a file with the name ``sconstest.skip`` to your subdirectory. This + tells ``runtest.py`` to skip the contents of the directory completely. +#. Create a file ``.exclude_tests`` in each directory in question, and in + it list line-by-line the files to exclude from testing. -The same rules apply when testing external Tools by using the ``-e`` +The same rules apply when testing external Tools when using the ``-e`` option. @@ -263,13 +263,12 @@ a simple "Hello, world!" example:: ``test.write('SConstruct', ...)`` This line creates an ``SConstruct`` file in the temporary directory, to be used as input to the ``scons`` run(s) that we're testing. - Note the use of the Python triple-quote syntax for the contents - of the ``SConstruct`` file. Because input files for tests are all - created from in-line data like this, the tests can sometimes get - a little confusing to read, because some of the Python code is found + Note the use of the Python triple-quoted string for the contents + of the ``SConstruct`` file (and see the next section for an + alternative approach). ``test.write('hello.c', ...)`` - This lines creates an ``hello.c`` file in the temporary directory. + This line creates an ``hello.c`` file in the temporary directory. Note that we have to escape the newline in the ``"Hello, world!\\n"`` string so that it ends up as a single backslash in the ``hello.c`` file on disk. @@ -286,7 +285,7 @@ a simple "Hello, world!" example:: ``test.run(program='./hello', stdout="Hello, world!\n")`` This shows use of the ``TestSCons.run()`` method to execute a program other than ``scons``, in this case the ``hello`` program we just - presumably built. The ``stdout=`` keyword argument also tells the + built. The ``stdout=`` keyword argument also tells the ``TestSCons.run()`` method to fail if the program output does not match the expected string ``"Hello, world!\n"``. Like the previous ``test.run()`` line, it will also fail the test if the exit status is @@ -306,21 +305,21 @@ Working with Fixtures In the simple example above, the files to set up the test are created on the fly by the test program. We give a filename to the ``TestSCons.write()`` method, and a string holding its contents, and it gets written to the test -folder right before starting.. +directory right before starting.. This simple technique can be seen throughout most of the end-to-end tests as it was the original technique provided to test developers, -but it is definitely not the preferred way to write a new test. +but it is no longer the preferred way to write a new test. To develop this way, you first need to create the necessary files and get them to work, then convert them to an embedded string form, which may involve lots of extra escaping. These embedded files are then tricky to maintain. As a test grows multiple steps, it becomes less easy to -read, since the embedded strings aren't quite the final files, and -the volume of test code obscures the flow of the testing steps. -Additionally, as SCons moves more to the use of code checkers and -formatters to detect problems and keep a standard coding style for -better readability, note that these techniques don't look inside -strings, so they're either left out or lots of manual work has to be done. +read, since many if the embedded strings aren't quite the final files, +and the volume of test code obscures the flow of the testing steps. +Additionally, as SCons moves more to the use of automated code checkers +and formatters to detect problems and keep a standard coding style for +better readability, note that such tools don't look inside strings +for code, so the effect is lost on them. In testing parlance, a fixture is a repeatable test setup. The SCons test harness allows the use of saved files or directories to be used @@ -335,16 +334,17 @@ Directory Fixtures ################## The test harness method ``dir_fixture(srcdir, [dstdir])`` -copies the contents of the specified folder ``srcdir`` from +copies the contents of the specified directory ``srcdir`` from the directory of the called test script to the current temporary test directory. The ``srcdir`` name may be a list, in which case the elements -are concatenated with the ``os.path.join()`` method. The ``dstdir`` +are concatenated into a path first. The ``dstdir`` is assumed to be under the temporary working directory, it gets created automatically, if it does not already exist. -If ``srcdir`` represents an absolute path, it is used as-is. Otherwise, -if the harness was invoked with the environment variable ``FIXTURE_DIRS`` -set, the test instance will present that list of directories to search +If ``srcdir`` represents an absolute path, it is used as-is. +Otherwise, if the harness was invoked with the environment variable +``FIXTURE_DIRS`` set (which ``runtest.py`` does by default), +the test instance will present that list of directories to search as ``self.fixture_dirs``, each of these are additionally searched for a directory with the name of ``srcdir``. @@ -354,7 +354,7 @@ A short syntax example:: test.dir_fixture('image') test.run() -would copy all files and subfolders from the local ``image`` folder +would copy all files and subdirectories from the local ``image`` directory to the temporary directory for the current test, then run it. To see a real example for this in action, refer to the test named @@ -365,14 +365,16 @@ File Fixtures Similarly, the method ``file_fixture(srcfile, [dstfile])`` copies the file ``srcfile`` from the directory of the called script, -to the temporary test directory. The ``dstfile`` is assumed to be -under the temporary working directory, unless it is an absolute path -name. If ``dstfile`` is specified, its target directory gets created +to the temporary test directory. The ``srcfile`` name may be a list, +in which case the elements are concatenated into a path first. +The ``dstfile`` is assumed to be under the temporary working directory, +unless it is an absolute path name. +If ``dstfile`` is specified, its target directory gets created automatically if it doesn't already exist. If ``srcfile`` represents an absolute path, it is used as-is. Otherwise, any passed in fixture directories are used as additional places to -search, as for the ``dir_fixture`` case. +search for the fixture file, as for the ``dir_fixture`` case. With the following code:: @@ -384,7 +386,7 @@ With the following code:: The files ``SConstruct`` and ``src/main.cpp`` are copied to the temporary test directory. Notice the second ``file_fixture`` line preserves the path of the original, otherwise ``main.cpp`` -would have landed in the top level of the test directory. +would have been placed in the top level of the test directory. Again, a reference example can be found in the current revision of SCons, it is ``test/packaging/sandbox-test/sandbox-test.py``. @@ -400,11 +402,12 @@ How to Convert Old Tests to Use Fixures Tests using the inline ``TestSCons.write()`` method can fairly easily be converted to the fixture based approach. For this, we need to get at the -files as they are written to each temporary test folder. +files as they are written to each temporary test directory, +which we can do by taking advantage of a debugging aid: ``runtest.py`` checks for the existence of an environment variable named ``PRESERVE``. If it is set to a non-zero value, the testing -framework preserves the test folder instead of deleting it, and prints +framework preserves the test directory instead of deleting it, and prints its name to the screen. So, you should be able to give the commands:: @@ -421,8 +424,8 @@ The output will then look something like this:: PASSED Preserved directory /tmp/testcmd.4060.twlYNI -You can now copy the files from that folder to your new -*fixture* folder. Then, in the test script you simply remove all the +You can now copy the files from that directory to your new +*fixture* directory. Then, in the test script you simply remove all the tedious ``TestSCons.write()`` statements and replace them by a single ``TestSCons.dir_fixture()``. @@ -493,7 +496,7 @@ Still, there are some techniques to help debugging. The first step should be to run the tests so the harness emits more information, without forcing more information into -the test stdout/stderr which will confuse result evaulation. +the test stdout/stderr which will confuse result evaluation. ``runtest.py`` has several verbose levels which can be used for this purpose: @@ -532,7 +535,7 @@ in ``testing/framework``. Start in to create files (``test.write()``) and run commands (``test.run()``). Use ``TestSCons`` for the end-to-end tests in ``test``, but use -``TestCmd`` for the unit tests in the ``src`` folder. +``TestCmd`` for the unit tests in the ``src`` directory. The match functions work like this: -- cgit v0.12 From b742241e46d3894749e14607b5435f125db77431 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Thu, 27 Feb 2020 09:19:06 -0700 Subject: Add comments on skipping tests to framework doc [ci skip] Build up the skipping tests section by adding a bit of discussion on why you'd want to skip, and on not skipping too much by mocking parts of tests and organizing test code. Signed-off-by: Mats Wichmann --- testing/framework/test-framework.rst | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/testing/framework/test-framework.rst b/testing/framework/test-framework.rst index ce2e3c9..dad09d3 100644 --- a/testing/framework/test-framework.rst +++ b/testing/framework/test-framework.rst @@ -9,7 +9,7 @@ any surprise changes in behavior. In general, no change goes into SCons unless it has one or more new or modified tests that demonstrably exercise the bug being fixed or the feature being added. There are exceptions to this guideline, but -they should be just that, ''exceptions''. When in doubt, make sure +they should be just that, *exceptions*. When in doubt, make sure it's tested. Test Organization @@ -500,7 +500,7 @@ the test stdout/stderr which will confuse result evaluation. ``runtest.py`` has several verbose levels which can be used for this purpose: - python runtest.py --verbose=2 test/foo.py + $ python runtest.py --verbose=2 test/foo.py You can also use the internal ``SCons.Debug.Trace()`` function, which prints output to @@ -529,7 +529,7 @@ Test Infrastructure The main test API in the ``TestSCons.py`` class. ``TestSCons`` is a subclass of ``TestCommon``, which is a subclass of ``TestCmd``. -All those classes are defined in python files of the same name +All those classes are defined in Python files of the same name in ``testing/framework``. Start in ``testing/framework/TestCmd.py`` for the base API definitions, like how to create files (``test.write()``) and run commands (``test.run()``). @@ -553,7 +553,7 @@ The match functions work like this: * Joins the lines with newline (unless already a string) * joins the REs with newline (unless it's a string) and puts ``^..$`` around the whole thing - * then whole thing must match with python re.DOTALL. + * then whole thing must match with Python re.DOTALL. Use them in a test like this:: @@ -566,6 +566,12 @@ or:: Avoiding Tests Based on Tool Existence ====================================== +For many tests, if the tool being tested is backed by an external program +which is not installed on the machine under test, it may not be worth +proceeding with the test. For example, it's hard to test complilng code with +a C compiler if no C compiler exists. In this case, the test should be +skipped. + Here's a simple example:: #!python @@ -581,3 +587,20 @@ The ``where_is`` method can be used to look for programs that are do not have tool specifications. The existing test code will have many samples of using either or both of these to detect if it is worth even proceeding with a test. + +Note that it is usually possible to test at least part of the operation of +a tool without the underlying program. Tools are responsible for setting up +construction variables and having the right builders, scanners and emitters +plumbed into the environment. These things can be tested by mocking the +behavior of the executable. Many examples of this can be found in the +``test`` directory. *TODO: point to one example*. + +This leads to a suggestion for test organization: keep tool tests which +don't need the underlying program in separate files from ones which do - +it is clearer what is going on if we can see in the test results that the +plumbing tests worked but the ones using the underlying program were skipped +rather than seeing all the tests for a tool passing or being skipped. +The framework doesn't have a way to indicate a partial skip - if you executed +200 lines of test, then found a condition which caused you to skip the +last 20 lines, the whole test is marked as a skip; +it also doesn't have a way to indicate a partial pass. -- cgit v0.12 From 1a890d631d128867affc73bcf608d376c8b9c6f6 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sat, 29 Feb 2020 08:20:51 -0700 Subject: [PR #3571] more work on testing document [ci skip] Apply some of the ideas of the Python documentation style guide - headings, indents, etc. Fixed some lingering format problems. Add a table of contents (this will work on the wiki as long as we save the copy there in rest format instead of markdown - that is currently the case). Signed-off-by: Mats Wichmann --- testing/framework/test-framework.rst | 349 +++++++++++++++++------------------ 1 file changed, 174 insertions(+), 175 deletions(-) diff --git a/testing/framework/test-framework.rst b/testing/framework/test-framework.rst index dad09d3..16d3734 100644 --- a/testing/framework/test-framework.rst +++ b/testing/framework/test-framework.rst @@ -1,6 +1,11 @@ -======================= +*********************** SCons Testing Framework -======================= +*********************** +.. contents:: + :local: + +Introduction +============ SCons uses extensive automated tests to ensure quality. The primary goal is that users be able to upgrade from version to version without @@ -12,36 +17,36 @@ the feature being added. There are exceptions to this guideline, but they should be just that, *exceptions*. When in doubt, make sure it's tested. -Test Organization +Test organization ================= There are three types of SCons tests: *End-to-End Tests* - End-to-end tests of SCons are Python scripts (``*.py``) underneath the - ``test/`` subdirectory. They use the test infrastructure modules in - the ``testing/framework`` subdirectory. They build set up complete - projects and call scons to execute them, checking that the behavior is - as expected. + End-to-end tests of SCons are Python scripts (``*.py``) underneath the + ``test/`` subdirectory. They use the test infrastructure modules in + the ``testing/framework`` subdirectory. They build set up complete + projects and call scons to execute them, checking that the behavior is + as expected. *Unit Tests* - Unit tests for individual SCons modules live underneath the - ``src/engine/`` subdirectory and are the same base name as the module - to be tests, with ``Tests`` appended before the ``.py``. For example, - the unit tests for the ``Builder.py`` module are in the - ``BuilderTests.py`` script. Unit tests tend to be based on assertions. + Unit tests for individual SCons modules live underneath the + ``src/engine/`` subdirectory and are the same base name as the module + to be tests, with ``Tests`` appended before the ``.py``. For example, + the unit tests for the ``Builder.py`` module are in the + ``BuilderTests.py`` script. Unit tests tend to be based on assertions. *External Tests* - For the support of external Tools (in the form of packages, preferably), - the testing framework is extended so it can run in standalone mode. - You can start it from the top-level directory of your Tool's source tree, - where it then finds all Python scripts (``*.py``) underneath the local - ``test/`` directory. This implies that Tool tests have to be kept in - a directory named ``test``, like for the SCons core. + For the support of external Tools (in the form of packages, preferably), + the testing framework is extended so it can run in standalone mode. + You can start it from the top-level directory of your Tool's source tree, + where it then finds all Python scripts (``*.py``) underneath the local + ``test/`` directory. This implies that Tool tests have to be kept in + a directory named ``test``, like for the SCons core. -Contrasting End-to-End and Unit Tests -##################################### +Contrasting end-to-end and unit tests +------------------------------------- In general, functionality with end-to-end tests should be considered a hardened part of the public interface (that is, @@ -59,38 +64,33 @@ scripts by using the ``runtest.py --pdb`` option, but the end-to-end tests treat an SCons invocation as a "black box" and just look for external effects; simple methods like inserting ``print`` statements in the SCons code itself can disrupt those external effects. -See `Debugging End-to-End Tests`_ for some more thoughts. +See `Debugging end-to-end tests`_ for some more thoughts. -Naming Conventions -################## +Naming conventions +------------------ The end-to-end tests, more or less, stick to the following naming conventions: #. All tests end with a .py suffix. - #. In the *General* form we use ``Feature.py`` - for the test of a specified feature; try to keep this description - reasonably short - + for the test of a specified feature; try to keep this description + reasonably short ``Feature-x.py`` - for the test of a specified feature using option ``x`` + for the test of a specified feature using option ``x`` #. The *command line option* tests take the form ``option-x.py`` - for a lower-case single-letter option - + for a lower-case single-letter option ``option--X.py`` - upper-case single-letter option (with an extra hyphen, so the - file names will be unique on case-insensitive systems) - + upper-case single-letter option (with an extra hyphen, so the + file names will be unique on case-insensitive systems) ``option--lo.py`` - long option; abbreviate the long option name to a few characters + long option; abbreviate the long option name to a few characters - -Running Tests +Running tests ============= The standard set of SCons tests are run from the top-level source @@ -98,11 +98,11 @@ directory by the ``runtest.py`` script. Help is available through the ``-h`` option:: - $ python runtest.py -h + $ python runtest.py -h To simply run all the tests, use the ``-a`` option:: - $ python runtest.py -a + $ python runtest.py -a By default, ``runtest.py`` prints a count and percentage message for each test case, along with the name of the test file. If you need the output @@ -110,22 +110,22 @@ to be more silent, have a look at the ``-q``, ``-s`` and ``-k`` options. You may specifically list one or more tests to be run:: - $ python runtest.py src/engine/SCons/BuilderTests.py - $ python runtest.py test/option-j.py test/Program.py + $ python runtest.py src/engine/SCons/BuilderTests.py + $ python runtest.py test/option-j.py test/Program.py Folder names are allowed in the test list as well, so you can do:: - $ python runtest.py test/SWIG + $ python runtest.py test/SWIG to run all SWIG tests only. You can also use the ``-f`` option to execute just the tests listed in a test list file:: - $ cat testlist.txt - test/option-j.py - test/Program.py - $ python runtest.py -f testlist.txt + $ cat testlist.txt + test/option-j.py + test/Program.py + $ python runtest.py -f testlist.txt One test must be listed per line, and any lines that begin with '#' will be ignored (the intent being to allow you, for example, to comment @@ -143,10 +143,10 @@ effects in place. The ``runtest.py`` script supports additional options to run tests against unpacked packages in the ``build/test-*/`` subdirectories. -If you are testing a separate Tool outside of the SCons source tree, you -have to call the ``runtest.py`` script in *external* (stand-alone) mode:: +If you are testing a separate Tool outside of the SCons source tree, +call the ``runtest.py`` script in *external* (stand-alone) mode:: - $ python ~/scons/runtest.py -e -a + $ python ~/scons/runtest.py -e -a This ensures that the testing framework doesn't try to access SCons classes needed for some of the *internal* test cases. @@ -163,42 +163,42 @@ that path-component in the testing directory. The use of an ephemeral test directory means that you can't simply change into a directory to "debug things" after a test has gone wrong. For a way around this, check out the ``PRESERVE`` environment variable. -It can be seen in action in `How to Convert Old Tests to Use Fixures`_ below. +It can be seen in action in `How to convert old tests to use fixures`_ below. -Not Running Tests +Not running tests ================= If you simply want to check which tests would get executed, you can call the ``runtest.py`` script with the ``-l`` option combined with whichever -test finding options (see below) you intend to use. Example: +test finding options (see below) you intend to use. Example:: - $ python runtest.py -l test/scons-time + $ python runtest.py -l test/scons-time ``runtest.py`` also has a ``-n`` option, which prints the command line for each test which would have been run, but doesn't actually run them:: - $ python runtest.py -n -a + $ python runtest.py -n -a Finding Tests ============= When started in *standard* mode:: - $ python runtest.py -a + $ python runtest.py -a ``runtest.py`` assumes that it is run from the SCons top-level source directory. It then dives into the ``src`` and ``test`` directories, where it tries to find filenames ``*Test.py`` - for the ``src`` directory (unit tests) + for the ``src`` directory (unit tests) ``*.py`` - for the ``test`` directory (end-to-end tests) + for the ``test`` directory (end-to-end tests) -When using fixtures, you may quickly end up in a position where you have +When using fixtures, you may end up in a situation where you have supporting Python script files in a subdirectory which shouldn't be -picked up as test scripts. In this case you have two options: +picked up as test scripts. There are two options here: #. Add a file with the name ``sconstest.skip`` to your subdirectory. This tells ``runtest.py`` to skip the contents of the directory completely. @@ -215,91 +215,89 @@ Example End-to-End Test Script To illustrate how the end-to-end test scripts work, let's walk through a simple "Hello, world!" example:: - #!python - import TestSCons + #!python + import TestSCons - test = TestSCons.TestSCons() + test = TestSCons.TestSCons() - test.write('SConstruct', """\ - Program('hello.c') - """) + test.write('SConstruct', """\ + Program('hello.c') + """) - test.write('hello.c', """\ - #include + test.write('hello.c', """\ + #include - int - main(int argc, char *argv[]) - { + int + main(int argc, char *argv[]) + { printf("Hello, world!\\n"); exit (0); - } - """) + } + """) - test.run() + test.run() - test.run(program='./hello', stdout="Hello, world!\n") + test.run(program='./hello', stdout="Hello, world!\n") - test.pass_test() + test.pass_test() ``import TestSCons`` - Imports the main infrastructure for writing SCons tests. This is - normally the only part of the infrastructure that needs importing. - Sometimes other Python modules are necessary or helpful, and get - imported before this line. + Imports the main infrastructure for writing SCons tests. This is + normally the only part of the infrastructure that needs importing. + Sometimes other Python modules are necessary or helpful, and get + imported before this line. ``test = TestSCons.TestSCons()`` - This initializes an object for testing. A fair amount happens under - the covers when the object is created, including: - - * A temporary directory is created for all the in-line files that will - get created. + This initializes an object for testing. A fair amount happens under + the covers when the object is created, including: - * The temporary directory's removal is arranged for when - the test is finished. - - * The test does ``os.chdir()`` to the temporary directory. + * A temporary directory is created for all the in-line files that will + get created. + * The temporary directory's removal is arranged for when + the test is finished. + * The test does ``os.chdir()`` to the temporary directory. ``test.write('SConstruct', ...)`` - This line creates an ``SConstruct`` file in the temporary directory, - to be used as input to the ``scons`` run(s) that we're testing. - Note the use of the Python triple-quoted string for the contents - of the ``SConstruct`` file (and see the next section for an - alternative approach). + This line creates an ``SConstruct`` file in the temporary directory, + to be used as input to the ``scons`` run(s) that we're testing. + Note the use of the Python triple-quoted string for the contents + of the ``SConstruct`` file (and see the next section for an + alternative approach). ``test.write('hello.c', ...)`` - This line creates an ``hello.c`` file in the temporary directory. - Note that we have to escape the newline in the - ``"Hello, world!\\n"`` string so that it ends up as a single - backslash in the ``hello.c`` file on disk. + This line creates an ``hello.c`` file in the temporary directory. + Note that we have to escape the newline in the + ``"Hello, world!\\n"`` string so that it ends up as a single + backslash in the ``hello.c`` file on disk. ``test.run()`` - This actually runs SCons. Like the object initialization, things - happen under the covers: + This actually runs SCons. Like the object initialization, things + happen under the covers: - * The exit status is verified; the test exits with a failure if - the exit status is not zero. - * The error output is examined, and the test exits with a failure - if there is any. + * The exit status is verified; the test exits with a failure if + the exit status is not zero. + * The error output is examined, and the test exits with a failure + if there is any. ``test.run(program='./hello', stdout="Hello, world!\n")`` - This shows use of the ``TestSCons.run()`` method to execute a program - other than ``scons``, in this case the ``hello`` program we just - built. The ``stdout=`` keyword argument also tells the - ``TestSCons.run()`` method to fail if the program output does not - match the expected string ``"Hello, world!\n"``. Like the previous - ``test.run()`` line, it will also fail the test if the exit status is - non-zero, or there is any error output. + This shows use of the ``TestSCons.run()`` method to execute a program + other than ``scons``, in this case the ``hello`` program we just + built. The ``stdout=`` keyword argument also tells the + ``TestSCons.run()`` method to fail if the program output does not + match the expected string ``"Hello, world!\n"``. Like the previous + ``test.run()`` line, it will also fail the test if the exit status is + non-zero, or there is any error output. ``test.pass_test()`` - This is always the last line in a test script. If we get to - this line, it means we haven't bailed out on a failure or skip, - so the result was good. It prints ``PASSED`` - on the screen and makes sure we exit with a ``0`` status to indicate - the test passed. As a side effect of destroying the ``test`` object, - the created temporary directory will be removed. - -Working with Fixtures + This is always the last line in a test script. If we get to + this line, it means we haven't bailed out on a failure or skip, + so the result was good. It prints ``PASSED`` + on the screen and makes sure we exit with a ``0`` status to indicate + the test passed. As a side effect of destroying the ``test`` object, + the created temporary directory will be removed. + +Working with fixtures ===================== In the simple example above, the files to set up the test are created @@ -330,8 +328,8 @@ 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 -################## +Directory fixtures +------------------ The test harness method ``dir_fixture(srcdir, [dstdir])`` copies the contents of the specified directory ``srcdir`` from @@ -350,9 +348,9 @@ a directory with the name of ``srcdir``. A short syntax example:: - test = TestSCons.TestSCons() - test.dir_fixture('image') - test.run() + test = TestSCons.TestSCons() + test.dir_fixture('image') + test.run() would copy all files and subdirectories from the local ``image`` directory to the temporary directory for the current test, then run it. @@ -360,8 +358,8 @@ to the temporary directory for the current test, then run it. To see a real example for this in action, refer to the test named ``test/packaging/convenience-functions/convenience-functions.py``. -File Fixtures -############# +File fixtures +------------- Similarly, the method ``file_fixture(srcfile, [dstfile])`` copies the file ``srcfile`` from the directory of the called script, @@ -378,10 +376,10 @@ search for the fixture file, as for the ``dir_fixture`` case. With the following code:: - test = TestSCons.TestSCons() - test.file_fixture('SConstruct') - test.file_fixture(['src','main.cpp'],['src','main.cpp']) - test.run() + test = TestSCons.TestSCons() + test.file_fixture('SConstruct') + test.file_fixture(['src','main.cpp'],['src','main.cpp']) + test.run() The files ``SConstruct`` and ``src/main.cpp`` are copied to the temporary test directory. Notice the second ``file_fixture`` line @@ -397,8 +395,8 @@ https://bitbucket.org/dirkbaechle/scons_qt4. Also visit the SCons Tools Index at https://github.com/SCons/scons/wiki/ToolsIndex for a complete list of available Tools, though not all may have tests yet. -How to Convert Old Tests to Use Fixures -####################################### +How to convert old tests to use fixures +--------------------------------------- Tests using the inline ``TestSCons.write()`` method can fairly easily be converted to the fixture based approach. For this, we need to get at the @@ -412,7 +410,7 @@ its name to the screen. So, you should be able to give the commands:: - $ PRESERVE=1 python runtest.py test/packaging/sandbox-test.py + $ PRESERVE=1 python runtest.py test/packaging/sandbox-test.py assuming Linux and a bash-like shell. For a Windows ``cmd`` shell, use ``set PRESERVE=1`` (that will leave it set for the duration of the @@ -420,9 +418,9 @@ assuming Linux and a bash-like shell. For a Windows ``cmd`` shell, use The output will then look something like this:: - 1/1 (100.00%) /usr/bin/python -tt test/packaging/sandbox-test.py - PASSED - Preserved directory /tmp/testcmd.4060.twlYNI + 1/1 (100.00%) /usr/bin/python -tt test/packaging/sandbox-test.py + pASSED + preserved directory /tmp/testcmd.4060.twlYNI You can now copy the files from that directory to your new *fixture* directory. Then, in the test script you simply remove all the @@ -439,14 +437,14 @@ files write multiple ``SConstruct`` files across the full run. These files can be given different names - perhaps using a sufffix - and then sucessively copied to the final name as needed:: - test.file_fixture('fixture/SConstruct.part1', 'SConstruct') - # more setup, then run test - test.file_fixture('fixture/SConstruct.part2', 'SConstruct') - # etc. + test.file_fixture('fixture/SConstruct.part1', 'SConstruct') + # more setup, then run test + test.file_fixture('fixture/SConstruct.part2', 'SConstruct') + # etc. -When Not to Use a Fixture -######################### +When not to use a fixture +------------------------- Note that some files are not appropriate for use in a fixture as-is: fixture files should be static. If the creation of the file involves @@ -454,18 +452,18 @@ interpolating data discovered during the run of the test script, that process should stay in the script. Here is an example of this kind of usage that does not lend itself to a fixture:: - import TestSCons - _python_ = TestSCons._python_ + import TestSCons + _python_ = TestSCons._python_ - test.write('SConstruct', """ - cc = Environment().Dictionary('CC') - env = Environment(LINK=r'%(_python_)s mylink.py', - LINKFLAGS=[], - CC=r'%(_python_)s mycc.py', - CXX=cc, - CXXFLAGS=[]) - env.Program(target='test1', source='test1.c') - """ % locals()) + test.write('SConstruct', """ + cc = Environment().Dictionary('CC') + env = Environment(LINK=r'%(_python_)s mylink.py', + LINKFLAGS=[], + CC=r'%(_python_)s mycc.py', + CXX=cc, + CXXFLAGS=[]) + env.Program(target='test1', source='test1.c') + """ % locals()) Here the value of ``_python_`` is picked out of the script's ``locals`` dictionary - which works because we've set it above - @@ -476,7 +474,7 @@ here because we don't know the value of `_python_` until runtime. The other files created in this test may still be candidates for use as fixture files, however. -Debugging End-to-End Tests +Debugging end-to-end tests ========================== Most of the end to end tests have expectations for standard output @@ -498,9 +496,9 @@ The first step should be to run the tests so the harness emits more information, without forcing more information into the test stdout/stderr which will confuse result evaluation. ``runtest.py`` has several verbose levels which can be used -for this purpose: +for this purpose:: - $ python runtest.py --verbose=2 test/foo.py + $ python runtest.py --verbose=2 test/foo.py You can also use the internal ``SCons.Debug.Trace()`` function, which prints output to @@ -515,7 +513,7 @@ Part of the technique discussed in the section `How to Convert Old Tests to Use Fixures`_ can also be helpful for debugging purposes. If you have a failing test, try:: - $ PRESERVE=1 python runtest.py test/failing-test.py + $ PRESERVE=1 python runtest.py test/failing-test.py You can now go to the save directory reported from this run and invoke the test manually to see what it is doing, without @@ -524,7 +522,7 @@ the presence of the test infrastructure which would otherwise adding debug prints may be more useful. -Test Infrastructure +Test infrastructure =================== The main test API in the ``TestSCons.py`` class. ``TestSCons`` @@ -540,30 +538,31 @@ Use ``TestSCons`` for the end-to-end tests in ``test``, but use The match functions work like this: ``TestSCons.match_re`` - match each line with a RE + match each line with a RE - * Splits the lines into a list (unless they already are) - * splits the REs at newlines (unless already a list) and puts ^..$ around each - * then each RE must match each line. This means there must be as many - REs as lines. + * Splits the lines into a list (unless they already are) + * splits the REs at newlines (unless already a list) + and puts ``^..$`` around each + * then each RE must match each line. This means there must be as many + REs as lines. ``TestSCons.match_re_dotall`` - match all the lines against a single RE - - * Joins the lines with newline (unless already a string) - * joins the REs with newline (unless it's a string) and puts ``^..$`` - around the whole thing - * then whole thing must match with Python re.DOTALL. + match all the lines against a single RE + + * Joins the lines with newline (unless already a string) + * joins the REs with newline (unless it's a string) and puts ``^..$`` + around the whole thing + * then whole thing must match with Python re.DOTALL. Use them in a test like this:: - test.run(..., match=TestSCons.match_re, ...) + test.run(..., match=TestSCons.match_re, ...) or:: - test.must_match(..., match=TestSCons.match_re, ...) + test.must_match(..., match=TestSCons.match_re, ...) -Avoiding Tests Based on Tool Existence +Avoiding tests based on tool existence ====================================== For many tests, if the tool being tested is backed by an external program @@ -574,10 +573,10 @@ skipped. Here's a simple example:: - #!python - intelc = test.detect_tool('intelc', prog='icpc') - if not intelc: - test.skip_test("Could not load 'intelc' Tool; skipping test(s).\n") + #!python + intelc = test.detect_tool('intelc', prog='icpc') + if not intelc: + test.skip_test("Could not load 'intelc' Tool; skipping test(s).\n") See ``testing/framework/TestSCons.py`` for the ``detect_tool`` method. It calls the tool's ``generate()`` method, and then looks for the given -- cgit v0.12 From 22ef9a471baafd9d464adf2016aefc0c4d41662c Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Tue, 3 Mar 2020 07:32:23 -0700 Subject: Clean up some more Python 2 code * _subproc is a little simpler as subprocess.DEVNULL is sure to br defined. Adjusted the docstring to better show the purpose. * CacheDir didn't need the Py2 branch of getting the config. * MSCommon can use a more specific exception. * packaging can now unconditionally use inspect.getfullargspec. Signed-off-by: Mats Wichmann --- src/CHANGES.txt | 3 +- src/engine/SCons/Action.py | 29 +++++-------- src/engine/SCons/CacheDir.py | 67 ++--------------------------- src/engine/SCons/CacheDirTests.py | 2 +- src/engine/SCons/Tool/MSCommon/common.py | 3 +- src/engine/SCons/Tool/packaging/__init__.py | 14 +++--- 6 files changed, 22 insertions(+), 96 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 7c5c9c2..d661015 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -76,11 +76,12 @@ From Rob Boehne - 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 an alternate warning message cl.exe is not found and msvc config + - Add an alternate warning message if 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. - Fixed bug where changing TEXTFILESUFFIX would cause Substfile() to rebuild. (Github Issue #3540) - Script/Main.py now uses importlib instead of imp module. + - Drop some Python 2-isms. RELEASE 3.1.2 - Mon, 17 Dec 2019 02:06:27 +0000 diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index 8a8cf27..ab901f6 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -105,6 +105,7 @@ import pickle import re import sys import subprocess +from subprocess import DEVNULL import itertools import inspect from collections import OrderedDict @@ -751,30 +752,20 @@ def get_default_ENV(env): return default_ENV -def _subproc(scons_env, cmd, error = 'ignore', **kw): - """Do common setup for a subprocess.Popen() call +def _subproc(scons_env, cmd, error='ignore', **kw): + """Wrapper for subprocess which pulls from construction env. - This function is still in draft mode. We're going to need something like - it in the long run as more and more places use subprocess, but I'm sure - it'll have to be tweaked to get the full desired functionality. - one special arg (so far?), 'error', to tell what to do with exceptions. + Use for calls to subprocess which need to interpolate values from + an SCons construction enviroment into the environment passed to + subprocess. Adds an an error-handling argument. Adds ability + to specify std{in,out,err} with "'devnull'" tag. """ - # allow std{in,out,err} to be "'devnull'". This is like - # subprocess.DEVNULL, which does not exist for Py2. Use the - # subprocess one if possible. - # Clean this up when Py2 support is dropped - try: - from subprocess import DEVNULL - except ImportError: - DEVNULL = None - + # TODO: just uses subprocess.DEVNULL now, we can drop the "devnull" + # string now - it is a holdover from Py2, which didn't have DEVNULL. for stream in 'stdin', 'stdout', 'stderr': io = kw.get(stream) if is_String(io) and io == 'devnull': - if DEVNULL: - kw[stream] = DEVNULL - else: - kw[stream] = open(os.devnull, "r+") + kw[stream] = DEVNULL # Figure out what shell environment to use ENV = kw.get('env', None) diff --git a/src/engine/SCons/CacheDir.py b/src/engine/SCons/CacheDir.py index 9bb7ef3..117f6b0 100644 --- a/src/engine/SCons/CacheDir.py +++ b/src/engine/SCons/CacheDir.py @@ -135,9 +135,6 @@ def CachePushFunc(target, source, env): CachePush = SCons.Action.Action(CachePushFunc, None) -# Nasty hack to cut down to one warning for each cachedir path that needs -# upgrading. -warned = dict() class CacheDir(object): @@ -159,12 +156,12 @@ class CacheDir(object): if path is None: return - self._readconfig3(path) + self._readconfig(path) - def _readconfig3(self, path): + def _readconfig(self, path): """ - Python3 version of reading the cache config. + Read the cache config. If directory or config file do not exist, create. Take advantage of Py3 capability in os.makedirs() and in file open(): just try @@ -201,64 +198,6 @@ class CacheDir(object): raise SCons.Errors.SConsEnvironmentError(msg) - def _readconfig2(self, path): - """ - Python2 version of reading cache config. - - See if there is a config file in the cache directory. If there is, - use it. If there isn't, and the directory exists and isn't empty, - produce a warning. If the directory does not exist or is empty, - write a config file. - - :param path: path to the cache directory - """ - config_file = os.path.join(path, 'config') - if not os.path.exists(config_file): - # A note: There is a race hazard here if two processes start and - # attempt to create the cache directory at the same time. However, - # Python 2.x does not give you the option to do exclusive file - # creation (not even the option to error on opening an existing - # file for writing...). The ordering of events here is an attempt - # to alleviate this, on the basis that it's a pretty unlikely - # occurrence (would require two builds with a brand new cache - # directory) - if os.path.isdir(path) and any(f != "config" for f in os.listdir(path)): - self.config['prefix_len'] = 1 - # When building the project I was testing this on, the warning - # was output over 20 times. That seems excessive - global warned - if self.path not in warned: - msg = "Please upgrade your cache by running " +\ - "scons-configure-cache.py " + self.path - SCons.Warnings.warn(SCons.Warnings.CacheVersionWarning, msg) - warned[self.path] = True - else: - if not os.path.isdir(path): - try: - os.makedirs(path) - except OSError: - # If someone else is trying to create the directory at - # the same time as me, bad things will happen - msg = "Failed to create cache directory " + path - raise SCons.Errors.SConsEnvironmentError(msg) - - self.config['prefix_len'] = 2 - if not os.path.exists(config_file): - try: - with open(config_file, 'w') as config: - json.dump(self.config, config) - except Exception: - msg = "Failed to write cache configuration for " + path - raise SCons.Errors.SConsEnvironmentError(msg) - else: - try: - with open(config_file) as config: - self.config = json.load(config) - except ValueError: - msg = "Failed to read cache configuration for " + path - raise SCons.Errors.SConsEnvironmentError(msg) - - def CacheDebug(self, fmt, target, cachefile): if cache_debug != self.current_cache_debug: if cache_debug == '-': diff --git a/src/engine/SCons/CacheDirTests.py b/src/engine/SCons/CacheDirTests.py index ff22d01..a3114c1 100644 --- a/src/engine/SCons/CacheDirTests.py +++ b/src/engine/SCons/CacheDirTests.py @@ -168,7 +168,7 @@ class ExceptionTestCase(unittest.TestCase): os.remove(old_config) try: - self._CacheDir._readconfig3(self._CacheDir.path) + self._CacheDir._readconfig(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/MSCommon/common.py b/src/engine/SCons/Tool/MSCommon/common.py index 505136e..7f832c6 100644 --- a/src/engine/SCons/Tool/MSCommon/common.py +++ b/src/engine/SCons/Tool/MSCommon/common.py @@ -64,8 +64,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 - except IOError: + except FileNotFoundError: # don't fail if no cache file, just proceed without it pass return envcache diff --git a/src/engine/SCons/Tool/packaging/__init__.py b/src/engine/SCons/Tool/packaging/__init__.py index 5795396..f06027d 100644 --- a/src/engine/SCons/Tool/packaging/__init__.py +++ b/src/engine/SCons/Tool/packaging/__init__.py @@ -27,6 +27,10 @@ SCons Packaging Tool. __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" +import os +import importlib +from inspect import getfullargspec + import SCons.Defaults import SCons.Environment from SCons.Variables import * @@ -34,8 +38,6 @@ from SCons.Errors import * from SCons.Util import is_List, make_path_relative from SCons.Warnings import warn, Warning -import os -import importlib __all__ = [ 'src_targz', 'src_tarbz2', 'src_tarxz', 'src_zip', @@ -168,13 +170,7 @@ def Package(env, target=None, source=None, **kw): # this exception means that a needed argument for the packager is # missing. As our packagers get their "tags" as named function # arguments we need to find out which one is missing. - #TODO: getargspec deprecated in Py3. cleanup when Py2.7 dropped. - try: - from inspect import getfullargspec - argspec = getfullargspec(packager.package) - except ImportError: - from inspect import getargspec - argspec = getargspec(packager.package) + argspec = getfullargspec(packager.package) args = argspec.args if argspec.defaults: # throw away arguments with default values -- cgit v0.12 From c77d6da51612a4becc3caa77571d7f54394ca1e8 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Tue, 3 Mar 2020 08:25:01 -0700 Subject: [PR #3574] fix sider complaints Signed-off-by: Mats Wichmann --- src/engine/SCons/Action.py | 2 +- src/engine/SCons/Tool/packaging/__init__.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index ab901f6..c02dd33 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -756,7 +756,7 @@ def _subproc(scons_env, cmd, error='ignore', **kw): """Wrapper for subprocess which pulls from construction env. Use for calls to subprocess which need to interpolate values from - an SCons construction enviroment into the environment passed to + an SCons construction environment into the environment passed to subprocess. Adds an an error-handling argument. Adds ability to specify std{in,out,err} with "'devnull'" tag. """ diff --git a/src/engine/SCons/Tool/packaging/__init__.py b/src/engine/SCons/Tool/packaging/__init__.py index f06027d..b6dd42e 100644 --- a/src/engine/SCons/Tool/packaging/__init__.py +++ b/src/engine/SCons/Tool/packaging/__init__.py @@ -27,7 +27,6 @@ SCons Packaging Tool. __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" -import os import importlib from inspect import getfullargspec -- cgit v0.12 From ca71152213e6ebb10a49ce18714dfd871869ac5a Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 8 Mar 2020 19:51:50 -0700 Subject: Add msys2 installed mingw64 to PATH for mingw tool --- src/CHANGES.txt | 1 + src/engine/SCons/Tool/mingw.py | 1 + 2 files changed, 2 insertions(+) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 7c5c9c2..760a096 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -27,6 +27,7 @@ From Rob Boehne characters where it should have been simply replacing existing text. Switched to use string.replace(). - Fix Github Issue #2904 - Provide useful error message when more than one Configure Contexts are opened. Only one open is allowed. You must call conf.Finish() to complete the currently open one before creating another + - Add msys2 installed mingw to PATH for mingw tool. From Jeremy Elson: - Updated design doc to use the correct syntax for Depends() diff --git a/src/engine/SCons/Tool/mingw.py b/src/engine/SCons/Tool/mingw.py index e5f472a..d6a27ae 100644 --- a/src/engine/SCons/Tool/mingw.py +++ b/src/engine/SCons/Tool/mingw.py @@ -47,6 +47,7 @@ mingw_paths = [ r'c:\MinGW\bin', r'C:\cygwin64\bin', r'C:\msys64', + r'C:\msys64\mingw64\bin', r'C:\cygwin\bin', r'C:\msys', ] -- cgit v0.12 From 4ac5b50ac1aa748b67a2e96240f5308de4d68cee Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Mon, 9 Mar 2020 13:35:24 -0600 Subject: Fix syntax problem in Action doc [ci skip] Recent change introduced an xml problem which prevents the docs from validating or building - transforming so it builds now. Signed-off-by: Mats Wichmann --- src/engine/SCons/Action.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/engine/SCons/Action.xml b/src/engine/SCons/Action.xml index d85af3b..350082d 100644 --- a/src/engine/SCons/Action.xml +++ b/src/engine/SCons/Action.xml @@ -65,9 +65,9 @@ is set to 2 or higher, then that number of entries in the command string will be scanned for relative or absolute paths. The count will reset after any -&& entries are found. +&& entries are found. The first command in the action string and -the first after any && +the first after any && entries will be found by searching the PATH variable in the ENV environment used to @@ -88,7 +88,7 @@ with that construction environment. not be added to the targets built with that construction environment. The first command in the action string and the first after any -&& entries will be found +&& entries will be found by searching the PATH variable in the ENV environment used to execute the command. -- cgit v0.12 From 1a80c9ab6c7cf3860dc6fd71d7f30b1909bf5279 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Mon, 9 Mar 2020 11:58:18 -0600 Subject: Some user guide tweaks [ci skip] troubleshooting and caching sections got some improvements to the xml entities used, mainly for options. A few wording tweaks as well. added a blurb to troublseshooting to urge looking for simpler answers. scons.mod - options section changes to use "> +--debug=duplicate"> +--debug=explain"> +--debug=findlibs"> +--debug=includes"> +--debug=prepare"> +--debug=presub"> +--debug=stacktrace"> +--implicit-cache"> +--implicit-deps-changed"> +--implicit-deps-unchanged"> +--profile"> +--taskmastertrace"> +--tree"> +-Q"> By default, -scons +&scons; searches for known programming tools on various systems and initializes itself based on what is found. On Windows systems which identify as win32, -scons +&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), +(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 +&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 Oracle Solaris systems, -scons +&scons; searches for the native compiler tools (MIPSpro, Visual Age, aCC, and Forte tools respectively) and the GCC tool chain. On all other platforms, including POSIX (Linux and UNIX) platforms, -scons +&scons; searches in order for the GCC tool chain, and the Intel compiler tools. -You may, of course, override these default values -by appropriate configuration of -Environment construction variables. +These default values may be overridden +by appropriate setting of &consvars;. OPTIONS In general, -scons -supports the same command-line options as GNU -make, -and many of those supported by -cons. +&scons; +supports the same command-line options as GNU &Make; +and many of those supported by cons. + @@ -511,13 +510,13 @@ Will not remove any targets specified by the &NoClean; function. - --cache-debug=file + --cache-debug=file Print debug information about the &CacheDir; derived-file caching to the specified -file. +file. If -file +file is - (a hyphen), @@ -533,7 +532,7 @@ are being looked for in, retrieved from, or written to the Disable the derived-file caching specified by &CacheDir;. -scons +&scons; will neither retrieve files from the cache nor copy files to the cache. @@ -580,7 +579,7 @@ file was rebuilt or retrieved from the cache. - --config=mode + --config=mode This specifies how the &Configure; call should use or generate the @@ -624,10 +623,10 @@ in a system header file or compiler. If this option is specified, no configuration tests will be rerun and all results will be taken from cache. -Note that scons will still consider it an error -if --config=cache is specified +&scons; will report an error +if is specified and a necessary test does not -yet have any results in the cache. +have any results in the cache. @@ -688,7 +687,7 @@ directory. --debug=type[,type...] Debug the build process. -type +type specifies the kind of debugging info to emit. Multiple types may be specified, separated by commas. The following entries show the recognized types: @@ -737,13 +736,10 @@ files, as well as unlinking old targets before building them. --debug=explain -Print an explanation of precisely why -scons -is deciding to (re-)build any targets. -(Note: this does not print anything -for targets that are -not -rebuilt.) +Print an explanation of why &scons; +is deciding to (re-)build the targets +it selects for building. + @@ -764,9 +760,9 @@ and about the actual libraries it finds. This is generally used to find out what files are included by the sources of a given derived file: - -$ scons --debug=includes foo.o - + +$ scons --debug=includes foo.o + @@ -801,7 +797,7 @@ of the various classes used internally by SCons. --debug=pdb -Re-run SCons under the control of the +Re-run &scons; under the control of the pdb Python debugger. @@ -812,12 +808,12 @@ Python debugger. Print a line each time any target (internal or external) is prepared for building. -scons +&scons; prints this for each target it considers, even if that target is up to date (see also --debug=explain). This can help debug problems with targets that aren't being built; it shows whether -scons +&scons; is at least considering them or not. @@ -826,16 +822,16 @@ is at least considering them or not. --debug=presub Print the raw command line used to build each target -before the construction environment variables are substituted. +before the &consenv; variables are substituted. Also shows which targets are being built by this command. Output looks something like this: - -$ scons --debug=presub + +$ scons --debug=presub Building myprog.o with action(s): $SHCC $SHCFLAGS $SHCCFLAGS $CPPFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES ... - + @@ -871,12 +867,12 @@ when encountering an otherwise unexplained error. The elapsed wall-clock time spent executing those build commands -The time spent processing each file passed to the SConscript() function +The time spent processing each file passed to the &SConscriptFunc; function (When -scons +&scons; is executed without the option, @@ -886,7 +882,7 @@ executing all the build commands, due to the SCons processing that takes place in between executing each command. When -scons +&scons; is executed with the @@ -904,7 +900,7 @@ should take place in parallel.) - --diskcheck=types + --diskcheck=types Enable specific checks for whether or not there is a file on disk @@ -913,7 +909,7 @@ where the SCons configuration expects a directory and whether or not RCS or SCCS sources exist when searching for source and include files. The -types +types argument can be set to: all, to enable all checks explicitly @@ -948,13 +944,13 @@ where the SCons configuration expects a directory). - --duplicate=ORDER + --duplicate=ORDER There are three ways to duplicate files in a build tree: hard links, soft (symbolic) links and copies. The default behaviour of SCons is to prefer hard links to soft links to copies. You can specify different behaviours with this option. -ORDER +ORDER must be one of hard-soft-copy (the default), @@ -981,16 +977,16 @@ the mechanisms in the specified order. - -f file, --file=file, --makefile=file, --sconstruct=file + -f file, --file=file, --makefile=file, --sconstruct=file Use -file +file as the initial SConscript file. Multiple options may be specified, in which case -scons +&scons; will read all of the specified files. @@ -1024,10 +1020,10 @@ exit. - -I directory, --include-dir=directory + -I directory, --include-dir=directory Specifies a -directory +directory to search for imported Python modules. If several @@ -1048,26 +1044,26 @@ are used, the directories are searched in the order specified. Cache implicit dependencies. This causes -scons +&scons; to use the implicit (scanned) dependencies 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 +&scons; will not detect changes to implicit dependency search paths (e.g. -CPPPATH, LIBPATH) +CPPPATH, LIBPATH) that would ordinarily cause different versions of same-named files to be used. -scons +&scons; will miss changes in the implicit dependencies in cases where a new implicit dependency is added earlier in the implicit dependency search path (e.g. -CPPPATH, LIBPATH) +CPPPATH, LIBPATH) than a current implicit dependency with the same name. @@ -1128,8 +1124,10 @@ SCons command-line OPTIONS. b and -scons -are synonyms. +scons +are synonyms for +build. + The following SCons command-line options affect the build @@ -1235,30 +1233,28 @@ are synonyms. - + - - - An empty line repeats the last typed command. Command-line editing can be used if the readline module is available. - -$ scons --interactive + +$ scons --interactive scons: Reading SConscript files ... scons: done reading SConscript files. scons>>> build -n prog scons>>> exit - + + + - -j N, --jobs=N -Specifies the number of jobs (commands) to run simultaneously. +Specifies the maximum number of comcurrent jobs (commands) to run. If there is more than one option, the last one is effective. @@ -1318,10 +1314,10 @@ targets specified on the command line will still be processed. - --max-drift=SECONDS + --max-drift=SECONDS Set the maximum expected drift in the modification time of files to -SECONDS. +SECONDS. This value determines how long a file must be unmodified before its cached content signature will be used instead of @@ -1338,10 +1334,10 @@ no matter how old the file is. - --md5-chunksize=KILOBYTES + --md5-chunksize=KILOBYTES Set the block size used to compute MD5 signatures to -KILOBYTES. +KILOBYTES. This value determines the size of the chunks which are read in at once when computing MD5 signatures. Files below that size are fully stored in memory before performing the signature computation while bigger files are read in @@ -1408,11 +1404,11 @@ dirs to the toolpath. - --profile=file + --profile=file Run SCons under the Python profiler and save the results in the specified -file. +file. The results may be analyzed using the Python pstats module. @@ -1466,34 +1462,34 @@ Also suppresses SCons status messages. -S, --no-keep-going, --stop -Ignored for compatibility with GNU -make. +Ignored for compatibility with GNU &Make; --site-dir=dir -Uses the named dir as the site dir rather than the default +Uses the named dir as the site directory +rather than the default site_scons -dirs. This dir will get prepended to +directories. This directory will be prepended to sys.path, the module dir/site_init.py -will get loaded if it exists, and +will be loaded if it exists, and dir/site_tools -will get added to the default toolpath. +will be added to the default toolpath. The default set of site_scons -dirs used when +directories used when -is not specified depends on the system platform, as follows. Note -that the directories are examined in the order given, from most +is not specified depends on the system platform, as follows. +Directories are examined in the order given, from most 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. +everything else), and the directories are prepended to the paths, again so +the last directory examined comes first in the resulting path. @@ -1551,23 +1547,24 @@ $HOME/.scons/site_scons - --stack-size=KILOBYTES + --stack-size=KILOBYTES Set the size stack used to run threads to -KILOBYTES. +KILOBYTES. This value determines the stack size of the threads used to run jobs. -These are the threads that execute the actions of the builders for the +These threads execute the actions of the builders for the nodes that are out-of-date. -Note that this option has no effect unless the -num_jobs -option, which corresponds to -j and --jobs, is larger than one. Using -a stack size that is too small may cause stack overflow errors. This -usually shows up as segmentation faults that cause scons to abort +This option has no effect unless the number of concurrent +build jobs is larger than one (as set by or + on the command line or &SetOption; in a script). + + +Using a stack size that is too small may cause stack overflow errors. +This usually shows up as segmentation faults that cause scons to abort before building anything. Using a stack size that is too large will cause scons to use more memory than required and may slow down the entire -build process. - -The default value is to use a stack size of 256 kilobytes, which should +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. @@ -1576,19 +1573,17 @@ unless you encounter stack overflow errors. -t, --touch -Ignored for compatibility with GNU -make. +Ignored for compatibility with GNU &Make;. (Touching a file to make it -appear up-to-date is unnecessary when using -scons.) +appear up-to-date is unnecessary when using &scons;.) - --taskmastertrace=file + --taskmastertrace=file Prints trace information to the specified -file +file about how the internal Taskmaster object evaluates and controls the order in which Nodes are built. A file name of @@ -1598,18 +1593,18 @@ may be used to specify the standard output. - -tree=options + --tree=options Prints a tree of the dependencies after each top-level target is built. This prints out some or all of the tree, in various formats, depending on the -options +options specified: - - + + --tree=all @@ -1648,21 +1643,22 @@ for that node can be found by searching for the relevant output higher up in the tree. - + -Multiple options may be specified, +Multiple options may be specified, separated by commas: - + # Prints only derived files, with status information: -scons --tree=derived,status +scons --tree=derived,status # Prints all dependencies of target, with status information # and pruning dependencies of already-visited Nodes: -scons --tree=all,prune,status target - +scons --tree=all,prune,status target + + + - -u, --up, --search-up @@ -1694,7 +1690,7 @@ up in. -v, --version Print the -scons +&scons; version, copyright information, list of authors, and any other relevant information. Then exit. @@ -1717,10 +1713,10 @@ after other processing. - --warn=type, --warn=no-type + --warn=type, --warn=no-type Enable or disable warnings. -type +type specifies the type of warnings to be enabled or disabled: @@ -1773,18 +1769,16 @@ These warnings are disabled by default. --warn=deprecated, --warn=no-deprecated -Enables or disables all warnings about use of +Enables or disables warnings about use of currently deprecated features. These warnings are enabled by default. -Note that the - -option does not disable warnings about absolutely all deprecated features. -Warnings for some deprecated features that have already been through -several releases with deprecation warnings -may be mandatory for a release or two -before they are officially no longer supported by SCons. -Warnings for some specific deprecated features -may be enabled or disabled individually; +Not all deprecation warnings can be disabled with the + option as some +deprecated features which are late in the deprecation +cycle may have been designated as mandatory warnings, +and these will still display. +Warnings for certain deprecated features +may also be enabled or disabled individually; see below. @@ -1793,7 +1787,7 @@ see below. --warn=duplicate-environment, --warn=no-duplicate-environment Enables or disables warnings about attempts to specify a build -of a target with two different construction environments +of a target with two different &consenvs; that use the same action. These warnings are enabled by default. @@ -1813,8 +1807,8 @@ which can yield unpredictable behavior with some compilers. Enables or disables warnings about features that will be deprecated in the future. -These warnings are disabled by default. -Enabling this warning is especially +Such warnings are disabled by default. +Enabling future deprecation warnings is recommended for projects that redistribute SCons configurations for other users to build, so that the project can be warned as soon as possible @@ -1833,18 +1827,17 @@ that may require changes to the configuration. --warn=misleading-keywords, --warn=no-misleading-keywords -Enables or disables warnings about use of the misspelled keywords +Enables or disables warnings about the use of two commonly +misspelled keywords targets and sources -when calling Builders. -(Note the last -s -characters, the correct spellings are +to &Builder; calls. The correct spelling is the +singular form, even though target and -source.) -These warnings are enabled by default. +source +can themselves refer to lists of names or nodes. @@ -1862,7 +1855,7 @@ These warnings are enabled by default. Enables or disables warnings about the feature not working when -scons +&scons; is run with the Python option or from optimized Python (.pyo) modules. @@ -1893,16 +1886,16 @@ These warnings are enabled by default. --warn=reserved-variable, --warn=no-reserved-variable Enables or disables warnings about attempts to set the -reserved construction variable names -CHANGED_SOURCES, -CHANGED_TARGETS, -TARGET, -TARGETS, -SOURCE, -SOURCES, -UNCHANGED_SOURCES +reserved &consvar; names +CHANGED_SOURCES, +CHANGED_TARGETS, +TARGET, +TARGETS, +SOURCE, +SOURCES, +UNCHANGED_SOURCES or -UNCHANGED_TARGETS. +UNCHANGED_TARGETS. These warnings are disabled by default. @@ -1920,7 +1913,7 @@ 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. + expected targets. These warnings are disabled by default. @@ -1947,9 +1940,10 @@ These warnings are enabled by default. - -Y repository, --repository=repository, --srcdir=repository + -Y repository, --repository=repository, --srcdir=repository -Search the specified repository for any input and target +Search the specified repository +for any input and target files not found in the local directory hierarchy. Multiple options may be specified, in which case the @@ -1967,14 +1961,14 @@ repositories are searched in the order specified. Construction Environments A &ConsEnv; is the basic means by which the SConscript files communicate build information to -scons. +&scons;. A new &consenv; is created using the -Environment +&Environment; function: - + env = Environment() - + Variables, called &ConsVars; @@ -1982,10 +1976,10 @@ 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['BAR'] = 'bar' - + As a convenience, &consvars; may also be set or modified by the @@ -1998,16 +1992,16 @@ 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 &consvars;. - + env = Environment(parse_flags='-Iinclude -DEBUG -lm') - + This example adds 'include' to -CPPPATH, +CPPPATH, 'EBUG' to -CPPDEFINES, +CPPDEFINES, and 'm' to -LIBS. +LIBS. By default, a new &consenv; is initialized with a set of builder methods @@ -2017,17 +2011,17 @@ An optional platform keyword argument may be used to specify that an environment should be initialized for a different platform: - + env = Environment(platform = 'cygwin') env = Environment(platform = 'os2') env = Environment(platform = 'posix') env = Environment(platform = 'win32') - + Specifying a platform initializes the appropriate &consvars; in the environment to use and generate file names with prefixes -and suffixes appropriate for the platform. +and suffixes appropriate for that platform. Note that the win32 @@ -2036,7 +2030,7 @@ platform adds the and SystemRoot variables from the user's external environment -to the construction environment's +to the &consenv;'s ENV dictionary. This is so that any executed commands @@ -2046,16 +2040,16 @@ external CVS repository specifications like :pserver:anonymous@cvs.sourceforge.net:/cvsroot/scons) will work on Windows systems. -The platform argument may be function or callable object, -in which case the Environment() method -will call the specified argument to update -the new construction environment: +The platform argument may be a function or callable object. +in which case the &Environment; method +will call it to update +the new &consenv;: - + def my_platform(env): env['VAR'] = 'xyzzy' -env = Environment(platform = my_platform) +env = Environment(platform=my_platform) Additionally, a specific set of tools @@ -2063,9 +2057,9 @@ with which to initialize the environment may be specified using the optional keyword argument tools: - + env = Environment(tools=['msvc', 'lex']) - + The tools argument overrides @@ -2081,9 +2075,9 @@ be used to retain the default list. Non-built-in tools may be specified using the optional toolpath keyword argument: - + env = Environment(tools=['default', 'foo'], toolpath=['tools']) - + This looks for a tool specification in tools/foo.py @@ -2114,32 +2108,29 @@ Tools in the toolpath are used before any of the built-in ones. For example, adding gcc.py to the toolpath would override the built-in gcc tool. -Also note that the toolpath is -stored in the environment for use -by later calls to -Clone() -and -Tool() -methods: +The toolpath is +stored in the environment and will be +picked up by subsequent calls to the +&Clone; and &Tool; methods: - + base = Environment(toolpath=['custom_path']) derived = base.Clone(tools=['custom_tool']) derived.CustomBuilder() - + The elements of the tools list may also be functions or callable objects, in which case the Environment() method will call the specified elements -to update the new construction environment: +to update the new &consenv;: - + def my_tool(env): env['XYZZY'] = 'xyzzy' -env = Environment(tools = [my_tool]) +env = Environment(tools=[my_tool]) The individual elements of the tools list @@ -2159,7 +2150,7 @@ function can use the arguments to modify the tool's behavior by setting up the environment in different ways or otherwise changing its initialization. - + # in tools/my_tool.py: def generate(env, **kw): # Sets MY_TOOL to the value of keyword argument 'arg1' or 1. @@ -2177,7 +2168,7 @@ env = Environment(tools=['default', ('my_tool', {'arg1': 'abc'})], the environment it receives to customize the tool for different platforms. If no tool list is specified, then SCons will auto-detect the installed -tools using the PATH variable in the ENV construction variable and the +tools using the PATH variable in the ENV &consvar; and the platform name when the Environment is constructed. Changing the PATH variable after the Environment is constructed will not cause the tools to be redetected. @@ -2186,7 +2177,7 @@ be redetected. Tools which can be located within a subdirectory in the toolpath. With a nested tool name the dot represents a directory seperator - + # namespaced builder env = Environment(ENV=os.environ, tools=['SubDir1.SubDir2.SomeTool']) env.SomeTool(targets, sources) @@ -2204,13 +2195,8 @@ env.SomeTool(targets, sources) - - - - - - - + + @@ -2219,13 +2205,8 @@ env.SomeTool(targets, sources) - - - - - - - + + @@ -2234,10 +2215,10 @@ env.SomeTool(targets, sources) Builder Methods -You tell scons what to build +You tell &scons; what to build by calling Builders, functions which know to take a particular action when given files of a particular type -to produce a particular result type. scons +to produce a particular result type. &scons; defines a number of builders, and you can also write your own. Builders are attached to a &consenv; as methods, and the available builder methods are listed as @@ -2247,9 +2228,9 @@ The available builders can be displayed like this for debugging purposes: - + print("Builders:", list(env['BUILDERS'])) - + Builder methods always take two arguments: @@ -2267,7 +2248,7 @@ keyword arguments, described below. Because long lists of file names can lead to a lot of quoting, -scons +&scons; supplies a &Split; global function and a same-named environment method @@ -2287,7 +2268,7 @@ The following are equivalent examples of calling the &Program; builder method: - + env.Program('bar', ['bar.c', 'foo.c']) env.Program('bar', Split('bar.c foo.c')) env.Program('bar', env.Split('bar.c foo.c')) @@ -2295,7 +2276,7 @@ env.Program(source=['bar.c', 'foo.c'], target='bar') env.Program(target='bar', source=Split('bar.c foo.c')) env.Program(target='bar', source=env.Split('bar.c foo.c')) env.Program('bar', source='bar.c foo.c'.split()) - + Python follows the POSIX pathname convention for path @@ -2311,15 +2292,15 @@ from the starting point, which is the top of the directory tree for an absolute path and the current directory for a relative path. -scons recognizes a third way to specify +&scons; recognizes a third way to specify path strings: if the string begins with the # character it is -top-relative - it works like a relative path but the +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 +from the current directory. The # is allowed to be followed by a pathname separator, which is ignored if -found in that position). +found in that position. Top-relative paths only work in places where &scons; will interpret the path (see some examples below). To be used in other contexts the string will need to be converted @@ -2335,7 +2316,7 @@ file currently being processed as the "current directory". Examples: - + # The comments describing the targets that will be built # assume these calls are in a SConscript file in the # a subdirectory named "subdir". @@ -2356,6 +2337,11 @@ env.Program('#/bar', 'bar.c') # Builds the program "other/foo" (relative to the top-level # SConstruct directory) from "subdir/foo.c": env.Program('#other/foo', 'foo.c') + +# This will not work, only SCons interfaces understand '#', +# os.path.exists is pure Python: +if os.path.exists('#inc/foo.h'): + env.Append(CPPPATH='#inc') When the target shares the same base name @@ -2363,7 +2349,7 @@ as the source and only the suffix varies, and if the builder method has a suffix defined for the target file type, then the target argument may be omitted completely, and -scons +&scons; will deduce the target file name from the source file name. The following examples all build the @@ -2375,12 +2361,12 @@ or (on Windows systems) from the bar.c source file: - + env.Program(target='bar', source='bar.c') env.Program('bar', source='bar.c') env.Program(source='bar.c') env.Program('bar.c') - + As a convenience, a srcdir @@ -2402,46 +2388,46 @@ and src/f2.c: - + env.Program('build/prog', ['f1.c', 'f2.c'], srcdir='src') - + It is possible to override (replace or add) -construction variables when calling a +&consvars; when calling a builder method by passing them as keyword arguments. These overrides will only be in effect when building that target, and will not affect other parts of the build. For example, if you want to specify some libraries needed by just one program: - + env.Program('hello', 'hello.c', LIBS=['gl', 'glut']) - + or generate a shared library with a non-standard suffix: - + env.SharedLibrary('word', 'word.cpp', SHLIBSUFFIX='.ocx', LIBSUFFIXES=['.ocx']) - + -(Note that both the $SHLIBSUFFIX and $LIBSUFFIXES variables must be set -if you want SCons to search automatically +Note that both the $SHLIBSUFFIX and $LIBSUFFIXES +variables must be set if you want SCons to search automatically for dependencies on the non-standard library names; -see the descriptions of these variables, below, for more information.) +see the descriptions of these variables, below, for more information. It is also possible to use the parse_flags keyword argument in an override, to merge command-line style arguments -into the appropriate construction variables +into the appropriate &consvars; (see &f-link-env-MergeFlags;). - + env = Program('hello', 'hello.c', parse_flags='-Iinclude -DEBUG -lm') - + This example adds 'include' to CPPPATH, @@ -2451,20 +2437,20 @@ and 'm' to LIBS. Although the builder methods defined by -scons +&scons; are, in fact, -methods of a construction environment object, +methods of a &consenv; object, they may also be called without an explicit environment: - + Program('hello', 'hello.c') SharedLibrary('word', 'word.cpp') - + In this case, the methods are called internally using a default construction environment that consists of the tools and values that -scons +&scons; has determined are appropriate for the local system. Builder methods that can be called without an explicit @@ -2472,9 +2458,9 @@ environment 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 * - + All builder methods return a list-like object containing Nodes that will be built. @@ -2492,10 +2478,10 @@ For example, if it were necessary to add a specific preprocessor define when compiling one specific object file: - + bar_obj_list = env.StaticObject('bar.c', CPPDEFINES='-DBAR') -env.Program(source = ['foo.c', bar_obj_list, 'main.c']) - +env.Program(source=['foo.c', bar_obj_list, 'main.c']) + Using a Node in this way makes for a more portable build @@ -2503,41 +2489,39 @@ by avoiding having to specify a platform-specific object suffix when calling the &Program; builder method. -Note that builder calls will automatically "flatten" -the source and target file lists, -so it's all right to have the bar_obj_list -returned by the &StaticObject; call -in the middle of the source file list. +Builder calls will automatically "flatten" +lists passed as source and target, so they are free to +contain elements which are themselves lists, such as +bar_obj_list +returned by the &StaticObject; call above. If you need to manipulate a list of lists returned by builders -directly using Python, -you can either build the list by hand: +directly in Python code, +you can either build a new list by hand: - + foo = Object('foo.c') bar = Object('bar.c') objects = ['begin.o'] + foo + ['middle.o'] + bar + ['end.o'] for object in objects: print(str(object)) - + Or you can use the &Flatten; -function supplied by scons +function supplied by &scons; to create a list containing just the Nodes, which may be more convenient: - + foo = Object('foo.c') bar = Object('bar.c') objects = Flatten(['begin.o', foo, 'middle.o', bar, 'end.o']) for object in objects: print(str(object)) - + -Note also that because builder calls return +SCons builder calls return a list-like object, not an actual Python list, -you should -not -use the Python add +so it is not appropriate to use the Python add operator (+ or +=) to append builder results to a Python list. Because the list and the object are different types, @@ -2553,29 +2537,27 @@ Instead, use the Python list method to make sure the list is updated in-place. Example: - + object_files = [] -# Do NOT use += as follows: -# +# Do NOT use += here: # object_files += Object('bar.c') # # It will not update the object_files list in place. # # Instead, use the list extend method: object_files.extend(Object('bar.c')) - - + The path name for a Node's file may be used by passing the Node to Python's builtin str function: - + bar_obj_list = env.StaticObject('bar.c', CPPDEFINES='-DBAR') print("The path to bar_obj is:", str(bar_obj_list[0])) - + Note again that because the Builder call returns a list, we have to access the first element in the list @@ -2601,7 +2583,7 @@ and is non-zero, then scons will change to the target file's directory. - + # scons will change to the "sub" subdirectory # before executing the "cp" command. env.Command('sub/dir/foo.out', 'sub/dir/foo.in', @@ -2614,13 +2596,13 @@ env.Command('sub/dir/foo.out', 'sub/dir/foo.in', env.Command('sub/dir/foo.out', 'sub/dir/foo.in', "cp foo.in foo.out", chdir=1) - + Note that scons will not automatically modify its expansion of -construction variables like +&consvars; like $TARGET and $SOURCE @@ -2641,7 +2623,7 @@ and to use just the filename portion of the targets and source. -scons +&scons; predefines the following builder methods. Depending on the setup of a particular &consenv; and on the type and software @@ -2653,13 +2635,8 @@ not all builders may be available to that - - - - - - - + + @@ -2667,14 +2644,9 @@ not all builders may be available to that - - - - - - - - + + + @@ -2685,10 +2657,10 @@ targets of builder methods automatically depend on their sources. An explicit dependency can be specified using the Depends -method of a construction environment (see below). +method of a &consenv; (see below). In addition, -scons +&scons; automatically scans source files for various programming languages, so the dependencies do not need to be specified explicitly. @@ -2736,44 +2708,48 @@ object. Methods and Functions To Do Things In addition to Builder methods, -scons -provides a number of other construction environment methods +&scons; +provides a number of other &consenv; methods and global functions to manipulate the build configuration. -Usually, a construction environment method +Usually, a &consenv; method and global function with the same name both exist for convenience. In the following list, the global function is documented like: - + + Function(arguments) - -and the construction environment method looks like: - + + +and the &consenv; method looks like: + + env.Function(arguments) - + + If you can call the function in both ways, then both forms are listed. The global function and same-named -construction environment method +&consenv; method 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 +First, many of the &consenv; methods affect only that +&consenv;, while the global function has a global effect. Second, where appropriate, -calling the functionality through a construction environment will -substitute construction variables into +calling the functionality through a &consenv; will +substitute &consvars; into any supplied strings, while the global function doesn't have the -context of a construction environment to pick variables from, +context of a &consenv; to pick variables from, so it cannot perform the substitution. For example: - + env = Environment(FOO = 'foo') Default('$FOO') env.Default('$FOO') - + In the above example, the first call to the global @@ -2783,39 +2759,34 @@ function will actually add a target named to the list of default targets, while the second call to the env.Default() -construction environment method +&consenv; method will expand the value and add a target named foo to the list of default targets. -For more on construction variable expansion, +For more on &consvar; expansion, see the next section on -construction variables. +&consvars;. 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 +&Consenv; methods and global functions supported by -scons +&scons; include: - - - - - - - - + + + @@ -2823,14 +2794,9 @@ include: - - - - - - - - + + + @@ -2839,7 +2805,7 @@ include: SConscript Variables In addition to the global functions and methods, -scons +&scons; supports a number of Python variables that can be used in SConscript files to affect how you want the build to be performed. @@ -2847,11 +2813,10 @@ These variables may be accessed from custom Python modules that you import into an SConscript file by adding the following to the Python module: - + from SCons.Script import * - + - ARGLIST @@ -2877,18 +2842,17 @@ of the tuple, respectively. Example: - + print("first keyword, value =", ARGLIST[0][0], ARGLIST[0][1]) print("second keyword, value =", ARGLIST[1][0], ARGLIST[1][1]) third_tuple = ARGLIST[2] print("third keyword, value =", third_tuple[0], third_tuple[1]) for key, value in ARGLIST: # process key and value - - - + + ARGUMENTS @@ -2906,27 +2870,33 @@ dictionary. Example: - + if ARGUMENTS.get('debug', 0): env = Environment(CCFLAGS = '-g') else: env = Environment() - - - + + BUILD_TARGETS A list of the targets which -scons -will actually try to build, -regardless of whether they were specified on -the command line or via the &Default; -function or method -(but empty if neither -command line targets or &Default; calls are present). +&scons; +has been asked to build. +The contents will be either those targets listed +on the command line, or, if none, those targets set +via calls to the &Default; function or method. +It does +not +contain any not-specified dependent targets that &scons; +selects for building as a result of making the sure the +specified targets are up to date. +The list is 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 @@ -2941,60 +2911,45 @@ the contents of the list may change on each successive call to Default(). See the -DEFAULT_TARGETS -list, below, +&DEFAULT_TARGETS; list, below, for additional information. Example: - + if 'foo' in BUILD_TARGETS: print("Don't forget to test the `foo' program!") if 'special/program' in BUILD_TARGETS: SConscript('special') - + -Note that the -BUILD_TARGETS -list only contains targets listed -on the command line or via calls to the -Default() -function or method. -It does -not -contain all dependent targets that will be built as -a result of making the sure the explicitly-specified -targets are up to date. - - COMMAND_LINE_TARGETS A list of the targets explicitly specified on -the command line. +the command line. If there are command line targets, +this list will have the same contents as &BUILD_TARGETS;. If there are no targets specified on the command line, -the list is empty. +the list is empty. The elemnts of this list are strings. This can be used, for example, to take specific actions only -when a certain target or targets -is explicitly being built. +when certain targets is explicitly being built. Example: - + if 'foo' in COMMAND_LINE_TARGETS: print("Don't forget to test the `foo' program!") if 'special/program' in COMMAND_LINE_TARGETS: SConscript('special') - - - + + DEFAULT_TARGETS @@ -3002,7 +2957,9 @@ if 'special/program' in COMMAND_LINE_TARGETS: nodes that have been specified using the Default() -function or method. +function or method. If there are no command line +targets, this list will have the same contents as +&BUILD_TARGETS;. The elements of the list are nodes, so you need to run them through the Python str @@ -3010,14 +2967,11 @@ function to get at the path name for each Node. Example: - + print(str(DEFAULT_TARGETS[0])) if 'foo' in [str(t) for t in DEFAULT_TARGETS]: print("Don't forget to test the `foo' program!") - - - - + The contents of the DEFAULT_TARGETS @@ -3025,7 +2979,7 @@ list change on on each successive call to the Default() function: - + print([str(t) for t in DEFAULT_TARGETS]) # originally [] Default('foo') print([str(t) for t in DEFAULT_TARGETS]) # now a node ['foo'] @@ -3033,7 +2987,7 @@ Default('bar') print([str(t) for t in DEFAULT_TARGETS]) # now a node ['foo', 'bar'] Default(None) print([str(t) for t in DEFAULT_TARGETS]) # back to [] - + Consequently, be sure to use DEFAULT_TARGETS @@ -3044,6 +2998,9 @@ or else simply be careful of the order of these statements in your SConscript files so that you don't look for a specific default target before it's actually been added to the list. + + + @@ -3064,30 +3021,25 @@ default target before it's actually been added to the list. -A construction environment has an associated dictionary of -construction variables +A &consenv; has an associated dictionary of +&consvars; that are used by built-in or user-supplied build rules. -Construction variables must follow the same rules for +&Consvars; must follow the same rules for Python identifiers: the initial character must be an underscore or letter, followed by any number of underscores, letters, or digits. -A number of useful construction variables are automatically defined by -scons for each supported platform, and additional construction variables +A number of useful &consvars; are automatically defined by +scons for each supported platform, and additional &consvars; can be defined by the user. The following is a list of the automatically -defined construction variables: +defined &consvars;: - - - - - - - + + @@ -3096,54 +3048,49 @@ defined construction variables: - - - - - - - + + -Construction variables can be retrieved and set using the +&Consvars; can be retrieved and set using the Dictionary -method of the construction environment: +method of the &consenv;: - + cvars = env.Dictionary() cvars["CC"] = "cc" - + or using the key lookup operator [] -directly on the construction environment: +directly on the &consenv;: - + env["CC"] = "cc" - + -Construction variables can also be passed to the construction environment +&Consvars; can also be passed to the &consenv; constructor: - + env = Environment(CC="cc") - + -or when copying a construction environment using the +or when copying a &consenv; using the Clone method: - + env2 = env.Clone(CC="cl.exe") - + Configure Contexts -scons +&scons; supports configure contexts, an integrated mechanism similar to the @@ -3151,7 +3098,7 @@ various AC_CHECK macros in GNU autoconf for testing for the existence of C header files, libraries, etc. In contrast to autoconf, -scons +&scons; does not maintain an explicit cache of the tested values, but uses its normal dependency tracking to keep the checked values up to date. However, users may override this behaviour with the @@ -3196,10 +3143,9 @@ file. You can specify the same config.h file in multiple calls to Configure, -in which case -scons +in which case &SCons; will concatenate all results in the specified file. -Note that SCons +Note that &SCons; uses its normal dependency checking to decide if it's necessary to rebuild the specified @@ -3235,10 +3181,10 @@ or arguments (or both) to avoid unnecessary test execution. - + A created Configure instance has the following associated methods: @@ -3261,9 +3207,9 @@ Only one context should be active at a time. The following Checks are predefined. (This list will likely grow larger as time goes by and developers contribute new useful tests.) - + SConf.CheckHeader(context, header, [include_quotes, language]) sconf.CheckHeader(header, [include_quotes, language]) @@ -3294,9 +3240,9 @@ or C++ and selects the compiler to be used for the check. Returns 1 on success and 0 on failure. - + SConf.CheckCHeader(context, header, [include_quotes]) sconf.CheckCHeader(header, [include_quotes]) @@ -3322,9 +3268,9 @@ a two character string, where the first character denotes the opening quote and the second character denotes the closing quote (both default to \N'34'). Returns 1 on success and 0 on failure. - + SConf.CheckCXXHeader(context, header, [include_quotes]) sconf.CheckCXXHeader(header, [include_quotes]) @@ -3350,9 +3296,9 @@ a two character string, where the first character denotes the opening quote and the second character denotes the closing quote (both default to \N'34'). Returns 1 on success and 0 on failure. - + SConf.CheckFunc(context,, function_name, [header, language]) sconf.CheckFunc(function_name, [header, language]) @@ -3370,12 +3316,14 @@ of the test file that will be compiled to check if the function exists; the default is: - + + #ifdef __cplusplus extern "C" #endif char function_name(); - + + The optional language argument should be @@ -3384,9 +3332,9 @@ or C++ and selects the compiler to be used for the check; the default is "C". - + SConf.CheckLib(context, [library, symbol, header, language, autoadd=1]) sconf.CheckLib([library, symbol, header, language, autoadd=1]) @@ -3399,7 +3347,7 @@ If the value of autoadd is 1 and the library provides the specified symbol, -appends the library to the LIBS construction environment variable. +appends the library to the LIBS &consvar; library may also be None (the default), in which case @@ -3430,9 +3378,9 @@ The default value for autoadd is 1. This method returns 1 on success and 0 on error. - + SConf.CheckLibWithHeader(context, library, header, language, [call, autoadd]) sconf.CheckLibWithHeader(library, header, language, [call, autoadd]) @@ -3468,9 +3416,9 @@ can link against the specified autoadd specifies whether to add the library to the environment (only if the check succeeds). This method returns 1 on success and 0 on error. - + SConf.CheckType(context, type_name, [includes, language]) sconf.CheckType(type_name, [includes, language]) @@ -3493,16 +3441,18 @@ or and selects the compiler to be used for the check; the default is "C". Example: - + + sconf.CheckType('foo_type', '#include "my_types.h"', 'C++') - + + Configure.CheckCC(self) -Checks whether the C compiler (as defined by the CC construction variable) works +Checks whether the C compiler (as defined by the CC &consvar;) works by trying to compile a small source file. By default, SCons only detects if there is a program with the correct name, not @@ -3511,26 +3461,26 @@ if it is a functioning compiler. This uses the exact same command than the one used by the object builder for C source file, so it can be used to detect if a particular compiler flag works or not. - + Configure.CheckCXX(self) -Checks whether the C++ compiler (as defined by the CXX construction variable) +Checks whether the C++ compiler (as defined by the CXX &consvar;) works by trying to compile a small source file. By default, SCons only detects if there is a program with the correct name, not if it is a functioning compiler. This uses the exact same command than the one used by the object builder for CXX source files, so it can be used to detect if a particular compiler flag works or not. - + Configure.CheckSHCC(self) -Checks whether the C compiler (as defined by the SHCC construction variable) works +Checks whether the C compiler (as defined by the SHCC &consvar;) works by trying to compile a small source file. By default, SCons only detects if there is a program with the correct name, not if it is a functioning compiler. @@ -3538,13 +3488,13 @@ there is a program with the correct name, not if it is a functioning compiler. - + Configure.CheckSHCXX(self) -Checks whether the C++ compiler (as defined by the SHCXX construction variable) +Checks whether the C++ compiler (as defined by the SHCXX &consvar;) works by trying to compile a small source file. By default, SCons only detects if there is a program with the correct name, not if it is a functioning compiler. @@ -3552,13 +3502,12 @@ if there is a program with the correct name, not if it is a functioning compiler CXX source files, so it can be used to detect if a particular compiler flag works or not. This does not check whether the object code can be used to build a shared library, only that the compilation (not link) succeeds. - Example of a typical Configure usage: - + env = Environment() conf = Configure( env ) if not conf.CheckCHeader( 'math.h' ): @@ -3569,7 +3518,7 @@ if conf.CheckLibWithHeader( 'qt', 'qapp.h', 'c++', # do stuff for qt - usage, e.g. conf.env.Append( CPPFLAGS = '-DWITH_QT' ) env = conf.Finish() - + @@ -3603,15 +3552,16 @@ argument should be an integer. If this argument is used, the function will only check whether the type given in type_name has the expected size (in bytes). -For example, -CheckTypeSize('short', expect = 2) -will return success only if short is two bytes. +For example, - - + +CheckTypeSize('short', expect = 2) + +will return success only if short is two bytes. + SConf.CheckDeclaration(context, symbol, [includes, language]) sconf.CheckDeclaration(symbol, [includes, language]) @@ -3632,9 +3582,9 @@ or C++ and selects the compiler to be used for the check; the default is "C". - + SConf.Define(context, symbol, [value, comment]) sconf.Define(symbol, [value, comment]) @@ -3648,14 +3598,13 @@ with the optional value and the optional comment comment. - Examples: - + env = Environment() conf = Configure( env ) @@ -3671,7 +3620,7 @@ conf.Define('A_SYMBOL', 1) Be careful about quoting string values, though: - + env = Environment() conf = Configure( env ) @@ -3687,7 +3636,7 @@ conf.Define('A_SYMBOL', '"YA"') For comment: - + env = Environment() conf = Configure( env ) @@ -3719,9 +3668,9 @@ These CheckContext instances define the following methods: Usually called before the check is started. text will be displayed to the user, e.g. 'Checking for library X...' - + CheckContext.Result(self,, res) @@ -3731,9 +3680,9 @@ will be displayed to the user, e.g. 'Checking for library X...' can be either an integer or a string. In the former case, 'yes' (res != 0) or 'no' (res == 0) is displayed to the user, in the latter case the given string is displayed. - + CheckContext.TryCompile(self, text, extension) @@ -3744,9 +3693,9 @@ given string is displayed. can be compiled using the environment's Object builder. Returns 1 on success and 0 on failure. - + CheckContext.TryLink(self, text, extension) @@ -3757,9 +3706,9 @@ builder. Returns 1 on success and 0 on failure. can be compiled using the environment's Program builder. Returns 1 on success and 0 on failure. - + CheckContext.TryRun(self, text, extension) @@ -3781,9 +3730,9 @@ program. If the program fails execution (its return status is non-zero), then (0, '') is returned. - + CheckContext.TryAction(self, action, [text, extension]) @@ -3797,7 +3746,7 @@ with an optional source file (contents ) can be executed. action may be anything which can be converted to a -scons +&scons; Action. On success, (1, outputStr) @@ -3807,9 +3756,9 @@ is the content of the target file. On failure (0, '') is returned. - + CheckContext.TryBuild(self, builder, [text, extension]) @@ -3824,13 +3773,12 @@ of a source file with optional this method returns 1 on success and 0 on failure. In addition, self.lastTarget is set to the build target node, if the build was successful. - Example for implementing and using custom tests: - + def CheckQt(context, qtdir): context.Message( 'Checking for qt ...' ) lastLIBS = context.env['LIBS'] @@ -3866,14 +3814,16 @@ some variables must be specified at build time. For example, libraries needed for the build may be in non-standard locations, or site-specific compiler options may need to be passed to the compiler. -scons +&scons; provides a Variables -object to support overriding construction variables +object to support overriding &consvars; on the command line: - -$ scons VARIABLE=foo - + + +scons VARIABLE=foo + + The variable values can also be specified in a text-based SConscript file. To create a Variables object, call the Variables() function: @@ -3881,7 +3831,7 @@ To create a Variables object, call the Variables() function: Variables([files], [args]) -This creates a Variables object that will read construction variables from +This creates a Variables object that will read &consvars; from the file or list of filenames specified in files. If no files are specified, @@ -3900,11 +3850,11 @@ dictionary that holds variables specified on the command line. Example: - + vars = Variables('custom.py') vars = Variables('overrides.py', ARGUMENTS) vars = Variables(None, {FOO:'expansion', BAR:7}) - + Variables objects have the following methods: @@ -3913,7 +3863,7 @@ vars = Variables(None, {FOO:'expansion', BAR:7}) Add(key, [help, default, validator, converter]) -This adds a customizable construction variable to the Variables object. +This adds a customizable &consvar; to the Variables object. key is the name of the variable. help @@ -3923,9 +3873,9 @@ is the default value of the variable; if the default value is None and there is no explicit value specified, -the construction variable will +the &consvar; will not -be added to the construction environment. +be added to the &consenv;. validator is called to validate the value of the variable, and should take three arguments: key, value, and environment. @@ -3945,7 +3895,7 @@ and then added to the environment. Examples: - + vars.Add('CC', 'The C compiler') def validate_color(key, val, env): @@ -3953,14 +3903,14 @@ def validate_color(key, val, env): raise Exception("Invalid color value '%s'" % val) vars.Add('COLOR', validator=valid_color) - + AddVariables(list) A wrapper script that adds -multiple customizable construction variables +multiple customizable &consvars; to a Variables object. list is a list of tuple or list objects @@ -3969,23 +3919,24 @@ for an individual call to the Add method. - + opt.AddVariables( ('debug', '', 0), ('CC', 'The C compiler'), ('VALIDATE', 'An option for testing validation', 'notset', validator, None), ) - + + Update(env, [args]) -This updates a construction environment +This updates a &consenv; env -with the customized construction variables. +with the customized &consvars;. Any specified variables that are not configured for the Variables object @@ -3998,9 +3949,10 @@ method, below. but is called indirectly by passing the Variables object to the Environment() function: - + env = Environment(variables=vars) - + + @@ -4009,13 +3961,13 @@ env = Environment(variables=vars) 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. +are added to the &consenv;. Example: - + CC = 'my_cc' - + @@ -4028,14 +3980,15 @@ with which the Variables object was initialized, but for which the Variables object was not configured. - + env = Environment(variables=vars) for key, value in vars.UnknownVariables(): print("unknown variable: %s=%s" % (key, value)) - + + Save(filename, env) @@ -4045,23 +3998,24 @@ that can be used on the next invocation to automatically load the current settings. This method combined with the Variables method can be used to support caching of variables between runs. - + env = Environment() vars = Variables(['variables.cache', 'custom.py']) vars.Add(...) vars.Update(env) vars.Save('variables.cache', env) - + + GenerateHelpText(env, [sort]) This generates help text documenting the customizable construction variables suitable to passing in to the Help() function. env -is the construction environment that will be used to get the actual values +is the &consenv; that will be used to get the actual values of customizable variables. Calling with an optional sort @@ -4080,13 +4034,14 @@ function). Optionally a Boolean value of True for sort will cause a standard alphabetical sort to be performed - + Help(vars.GenerateHelpText(env)) Help(vars.GenerateHelpText(env, sort=cmp)) - + + FormatVariableHelpText(env, opt, help, default, actual) @@ -4100,14 +4055,14 @@ method to create the returned help text. It may be overridden with your own function that takes the arguments specified above and returns a string of help text formatted to your liking. -Note that the +Note that GenerateHelpText() will not put any blank lines or extra characters in between the entries, so you must add those characters to the returned string if you want the entries separated. - + def my_format(env, opt, help, default, actual): fmt = "\n%s: default=%s actual=%s (%s)\n" return fmt % (opt, default. actual, help) @@ -4115,13 +4070,13 @@ vars.FormatVariableHelpText = my_format To make it more convenient to work with customizable Variables, -scons +&scons; provides a number of functions that make it easy to set up various types of Variables: - + BoolVariable(key, help, default) @@ -4155,9 +4110,9 @@ and the values and none as false. - + EnumVariable(key, help, default, allowed_values, [map, ignorecase]) @@ -4205,9 +4160,9 @@ then values will be matched case-insensitive, and all input values will be converted to lower case. - + ListVariable(key, help, default, names, [,map]) @@ -4242,9 +4197,9 @@ input values into specific legal values in the names list. - + PackageVariable(key, help, default) @@ -4283,9 +4238,9 @@ The option will also support the values or disable to disable use of the specified option. - + PathVariable(key, help, default, [validator]) @@ -4334,10 +4289,9 @@ the name of the variable to be set; the specified value being checked; and env, -the construction environment) +the &consenv;) and should raise an exception if the specified value is not acceptable. - @@ -4348,25 +4302,27 @@ in a single call to the AddVariables method: - + vars.AddVariables( - BoolVariable('warnings', 'compilation with -Wall and similiar', 1), - EnumVariable('debug', 'debug output and symbols', 'no' - allowed_values=('yes', 'no', 'full'), - map={}, ignorecase=0), # case sensitive - ListVariable('shared', - 'libraries to build as shared libraries', - 'all', - names = list_of_libs), - PackageVariable('x11', - 'use X11 installed here (yes = search some places)', - 'yes'), - PathVariable('qtdir', 'where the root of Qt is installed', qtdir), - PathVariable('foopath', 'where the foo library is installed', foopath, - PathVariable.PathIsDir), - + BoolVariable("warnings", "compilation with -Wall and similiar", 1), + EnumVariable( + "debug", + "debug output and symbols", + "no", + allowed_values=("yes", "no", "full"), + map={}, + ignorecase=0, # case sensitive + ), + ListVariable( + "shared", "libraries to build as shared libraries", "all", names=list_of_libs + ), + PackageVariable("x11", "use X11 installed here (yes = search some places)", "yes"), + PathVariable("qtdir", "where the root of Qt is installed", qtdir), + PathVariable( + "foopath", "where the foo library is installed", foopath, PathVariable.PathIsDir + ), ) - + @@ -4420,7 +4376,7 @@ File or Directory Node. For example: - + # Get the current build dir's path, relative to top. Dir('.').path # Current dir's absolute path @@ -4432,7 +4388,7 @@ 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", foo.path) - + File and Directory Node objects have methods to create @@ -4517,7 +4473,7 @@ within the parent directory of For example: - + # Get a Node for a file within a directory incl = Dir('include') f = incl.File('header.h') @@ -4535,7 +4491,7 @@ docs = Dir('docs') html = docs.Dir('html') index = html.File('index.html') css = index.File('app.css') - + @@ -4543,22 +4499,22 @@ css = index.File('app.css') EXTENDING SCONS Builder Objects -scons +&scons; can be extended to build different types of targets by adding new Builder objects -to a construction environment. +to a &consenv;. In general, you should only need to add a new Builder object when you want to build a new type of file or other external target. If you just want to invoke a different compiler or other tool to build a Program, Object, Library, or any other type of output file for which -scons +&scons; already has an existing Builder, it is generally much easier to use those existing Builders -in a construction environment -that sets the appropriate construction variables +in a &consenv; +that sets the appropriate &consvars; (CC, LINK, etc.). Builder objects are created @@ -4567,7 +4523,7 @@ using the function. The Builder -function accepts the following arguments: +function accepts the following keyword arguments: @@ -4595,44 +4551,39 @@ takes three arguments: target - a list of target nodes, env -- the construction environment. +- the &consenv;. +The +action +and +generator +arguments must not both be used for the same Builder. + prefix The prefix that will be prepended to the target file name. -This may be specified as a: - -
- -* -string, - - -* -callable object -- a function or other callable that takes -two arguments (a construction environment and a list of sources) -and returns a prefix, - - -* -dictionary -- specifies a mapping from a specific source suffix (of the first +This may be specified as: + + + a string + a callable object - +a function or other callable that takes +two arguments (a &consenv; and a list of sources) +and returns a prefix + a dictionary - +specifies a mapping from a specific source suffix (of the first source specified) to a corresponding target prefix. Both the source suffix and target prefix specifications may use environment variable substitution, and the target prefix (the 'value' entries in the dictionary) may also be a callable object. The default target prefix -may be indicated by a dictionary entry with a key value of None. -
+may be indicated by a dictionary entry with a key value of None.
-
-
+ - - + b = Builder("build_it < $SOURCE > $TARGET", prefix = "file-") @@ -4645,21 +4596,22 @@ b = Builder("build_it < $SOURCE > $TARGET", suffix = { None: "file-", "$SRC_SFX_A": gen_prefix }) + + - suffix The suffix that will be appended to the target file name. This may be specified in the same manner as the prefix above. If the suffix is a string, then -scons +&scons; will append a '.' to the beginning of the suffix if it's not already there. The string returned by callable object (or obtained from the dictionary) is untouched and must append its own '.' to the beginning if one is desired. - + b = Builder("build_it < $SOURCE > $TARGET" suffix = "-file") @@ -4672,14 +4624,14 @@ b = Builder("build_it < $SOURCE > $TARGET", suffix = { None: ".sfx1", "$SRC_SFX_A": gen_suffix }) - + ensure_suffix When set to any true value, causes -scons +&scons; to add the target suffix specified by the suffix keyword to any target strings @@ -4687,7 +4639,7 @@ that have a different suffix. (The default behavior is to leave untouched any target file name that looks like it already has any suffix.) - + b1 = Builder("build_it < $SOURCE > $TARGET" suffix = ".out") b2 = Builder("build_it < $SOURCE > $TARGET" @@ -4702,18 +4654,19 @@ env.B1('foo.txt', 'foo.in') # Builds "bar.txt.out" because ensure_suffix is set. env.B2('bar.txt', 'bar.in') - + + src_suffix The expected source file name suffix. This may be a string or a list of strings. - + target_scanner @@ -4724,14 +4677,14 @@ This keyword argument should be used for Scanner objects that find implicit dependencies based only on the target file -and the construction environment, +and the &consenv;, not for implicit dependencies based on source files. (See the section "Scanner Objects" below, for information about creating Scanner objects.) - + source_scanner @@ -4752,13 +4705,13 @@ indicate that this Builder should scan directory trees for on-disk changes to files that -scons +&scons; does not know about from other Builder or function calls. (See the section "Scanner Objects" below, for information about creating your own Scanner objects.) - + target_factory @@ -4777,13 +4730,12 @@ or directory target. Example: - + MakeDirectoryBuilder = Builder(action=my_mkdir, target_factory=Dir) env = Environment() env.Append(BUILDERS = {'MakeDirectory':MakeDirectoryBuilder}) env.MakeDirectory('new_directory', []) - - + Note that the call to the MakeDirectory Builder needs to specify an empty source list @@ -4793,9 +4745,9 @@ and would try to deduce the target name from it, which in the absence of an automatically-added prefix or suffix would lead to a matching target and source name and a circular dependency. - + source_factory @@ -4814,15 +4766,15 @@ or directories (or both) as sources. Example: - + CollectBuilder = Builder(action=my_mkdir, source_factory=Entry) env = Environment() env.Append(BUILDERS = {'Collect':CollectBuilder}) env.Collect('archive', ['directory_name', 'file_name']) - + emitter @@ -4830,7 +4782,7 @@ env.Collect('archive', ['directory_name', 'file_name']) lists before dependencies are established and the target(s) are actually built. emitter -can also be a string containing a construction variable to expand +can also be a string containing a &consvar; to expand to an emitter function or list of functions, or a dictionary mapping source file suffixes to emitter functions. @@ -4845,14 +4797,14 @@ takes three arguments: target - a list of target nodes, env -- the construction environment. +- the &consenv;. An emitter must return a tuple containing two lists, the list of targets to be built by this builder, and the list of sources for this builder. Example: - + def e(target, source, env): return (target + ['foo.foo'], source + ['foo.src']) @@ -4867,12 +4819,12 @@ def e2(target, source, env): b = Builder("my_build < $TARGET > $SOURCE", emitter = [e, e2]) -# Calling an emitter function through a construction variable. +# Calling an emitter function through a &consvar;. env = Environment(MY_EMITTER = e) b = Builder("my_build < $TARGET > $SOURCE", emitter = '$MY_EMITTER') -# Calling a list of emitter functions through a construction variable. +# Calling a list of emitter functions through a &consvar;. env = Environment(EMITTER_LIST = [e, e2]) b = Builder("my_build < $TARGET > $SOURCE", emitter = '$EMITTER_LIST') @@ -4887,9 +4839,9 @@ b = Builder("my_build < $TARGET > $SOURCE", emitter = {'.suf1' : e_suf1, '.suf2' : e_suf2}) - + multi @@ -4901,22 +4853,22 @@ files to the target; it is not allowed to change the environment associated with the target, specify additional environment overrides, or associate a different builder with the target. - + env -A construction environment that can be used +A &consenv; that can be used to fetch source code using this Builder. (Note that this environment is not used for normal builds of normal target files, which use the environment that was used to call the Builder for the target file.) - + generator @@ -4934,7 +4886,7 @@ takes four arguments: target - a list of target nodes, env -- the construction environment, +- the &consenv;, for_signature - a Boolean value that specifies whether the generator is being called @@ -4942,7 +4894,7 @@ for generating a build signature (as opposed to actually executing the command). Example: - + def g(source, target, env, for_signature): return [["gcc", "-c", "-o"] + target + source] @@ -4955,18 +4907,18 @@ b = Builder(generator=g) and action arguments must not both be used for the same Builder. - + src_builder Specifies a builder to use when a source file name suffix does not match any of the suffixes of the builder. Using this argument produces a multi-stage builder. - + single_source @@ -4974,18 +4926,9 @@ multi-stage builder. more than one source file without target files results in implicitly calling the builder multiple times (once for each source given). Giving multiple source files together with target files results in a UserError exception. - - -The -generator -and -action -arguments must not both be used for the same Builder. - - source_ext_match @@ -5005,7 +4948,7 @@ or some other non-true value. When source_ext_match is disable, -scons +&scons; will use the suffix of the first specified source file to select the appropriate action from the action @@ -5015,27 +4958,28 @@ dictionary. the setting of source_ext_match prevents -scons +&scons; from exiting with an error due to the mismatched suffixes of foo.in and foo.extra. - + b = Builder(action={'.in' : 'build $SOURCES > $TARGET'}, source_ext_match = None) env = Environment(BUILDERS = {'MyBuild':b}) env.MyBuild('foo.out', ['foo.in', 'foo.extra']) - + + env -A construction environment that can be used +A &consenv; that can be used to fetch source code using this Builder. (Note that this environment is not @@ -5043,14 +4987,15 @@ used for normal builds of normal target files, which use the environment that was used to call the Builder for the target file.) - + b = Builder(action="build < $SOURCE > $TARGET") env = Environment(BUILDERS = {'MyBuild' : b}) env.MyBuild('foo.out', 'foo.in', my_arg = 'xyzzy') - + + chdir @@ -5074,7 +5019,7 @@ target file's directory. not automatically modify its expansion of -construction variables like +&consvars; like $TARGET and $SOURCE @@ -5086,7 +5031,7 @@ the top-level directory containing the &SConstruct; file, and consequently incorrect relative to the chdir directory. Builders created using chdir keyword argument, -will need to use construction variable +will need to use &consvar; expansions like ${TARGET.file} and @@ -5094,12 +5039,12 @@ and to use just the filename portion of the targets and source. - + b = Builder(action="build < ${SOURCE.file} > ${TARGET.file}", chdir=1) env = Environment(BUILDERS = {'MyBuild' : b}) env.MyBuild('sub/dir/foo.out', 'sub/dir/foo.in') - + WARNING: Python only keeps one current directory @@ -5115,17 +5060,17 @@ option, because individual worker threads spawned by SCons interfere with each other when they start changing directory. - + Any additional keyword arguments supplied when a Builder object is created (that is, when the Builder() function is called) will be set in the executing construction environment when the Builder object is called. The canonical example here would be -to set a construction variable to +to set a &consvar; to the repository of a source code system. Any additional keyword arguments supplied @@ -5180,25 +5125,24 @@ represented by the type of the first argument: If the first argument is already an Action object, the object is simply returned. - + String If the first argument is a string, a command-line Action is returned. -Note that the command-line string -may be preceded by an -@ -(at-sign) -to suppress printing of the specified command line, -or by a -- -(hyphen) -to ignore the exit status from the specified command: - - +If such a string begins with +@, +it indicates printing of the command line is to be suppressed. +If the string begins with +- (hyphen), +it indicated the exit status from the specified command +is to be ignored, allowing execution to continue +even if the command reports failure: + + Action('$CC -c -o $TARGET $SOURCES') # Doesn't print the line being executed. @@ -5206,7 +5150,8 @@ Action('@build $TARGET $SOURCES') # Ignores return value Action('-build $TARGET $SOURCES') - + + @@ -5215,9 +5160,9 @@ Action('-build $TARGET $SOURCES') - + List @@ -5235,12 +5180,13 @@ This allows white space to be enclosed in an argument by defining a command in a list within a list: - + Action([['cc', '-c', '-DWHITE SPACE', '-o', '$TARGET', '$SOURCES']]) - + + Function @@ -5253,7 +5199,7 @@ The Python function must take three keyword arguments, (a Node object representing the source file) and env -(the construction environment +(the &consenv; used for building the target file). The target @@ -5265,10 +5211,10 @@ The actual target and source file name(s) may be retrieved from their Node objects via the built-in Python str function: - + target_file_name = str(target) source_file_names = [str(x) for x in source] - + The function should return 0 @@ -5279,7 +5225,7 @@ The function may raise an exception or return a non-zero exit status to indicate an unsuccessful build. - + def build_it(target = None, source = None, env = None): # build the target from the source return 0 @@ -5316,7 +5262,7 @@ this function must take three keyword arguments: (a Node object representing the source file) and env -(a construction environment). +(a &consenv;). The target and @@ -5335,7 +5281,7 @@ SCons itself heavily uses the latter variant. Examples: - + def build_it(target, source, env): # build the target from the source return 0 @@ -5356,7 +5302,7 @@ l = Action(build_it, '$STRINGIT') The third and succeeding arguments, if present, -may either be a construction variable or a list of construction variables +may either be a &consvar; or a list of &consvars; whose values will be included in the signature of the Action when deciding whether a target should be rebuilt because the action changed. The variables may also be specified by a @@ -5364,13 +5310,13 @@ The variables may also be specified by a keyword parameter; if both are present, they are combined. This is necessary whenever you want a target to be rebuilt -when a specific construction variable changes. +when a specific &consvar; changes. This is not often needed for a string action, as the expanded variables will normally be part of the command line, but may be needed if a Python function action uses -the value of a construction variable when generating the command line. +the value of a &consvar; when generating the command line. - + def build_it(target, source, env): # build the target from the 'XXX' construction variable open(target[0], 'w').write(env['XXX']) @@ -5412,7 +5358,7 @@ target file's directory. not automatically modify its expansion of -construction variables like +&consvars; like $TARGET and $SOURCE @@ -5424,7 +5370,7 @@ the top-level directory containing the &SConstruct; file, and consequently incorrect relative to the chdir directory. Builders created using chdir keyword argument, -will need to use construction variable +will need to use &consvar; expansions like ${TARGET.file} and @@ -5432,10 +5378,10 @@ and to use just the filename portion of the targets and source. - + a = Action("build < ${SOURCE.file} > ${TARGET.file}", chdir=1) - + exitstatfunc @@ -5452,7 +5398,7 @@ under special conditions and SCons should, therefore, consider that the action always suceeds: - + def always_succeed(s): # Always return 0, which indicates success. return 0 @@ -5474,14 +5420,14 @@ If the batch_key argument evaluates True and is not a callable object, the configured Action object will cause -scons +&scons; to collect all targets built with the Action object -and configured with the same construction environment +and configured with the same &consenv; into single invocations of the Action object's command line or function. Command lines will typically want to use the CHANGED_SOURCES -construction variable +&consvar; (and possibly CHANGED_TARGETS as well) @@ -5490,9 +5436,9 @@ have actually changed since their targets were built. Example: - + a = Action('build $CHANGED_SOURCES', batch_key=True) - + The batch_key @@ -5511,24 +5457,24 @@ function must accept the following arguments: action The action object. - + env -The construction environment +The &consenv; configured for the target. - + target The list of targets for a particular configured action. - + source @@ -5546,16 +5492,16 @@ variable from the env argument which will cause -scons +&scons; to batch-build targets with matching values of that variable, or perhaps return the id() -of the entire construction environment, +of the entire &consenv;, in which case -scons +&scons; will batch-build -all targets configured with the same construction environment. +all targets configured with the same &consenv;. Returning None indicates that @@ -5567,7 +5513,7 @@ by a separate invocation of action's command or function. Example: - + def batch_key(action, env, target, source): tdir = target[0].dir if tdir.name == 'special': @@ -5577,7 +5523,6 @@ def batch_key(action, env, target, source): return (id(action), id(env), tdir) a = Action('build $CHANGED_SOURCES', batch_key=batch_key) - @@ -5585,13 +5530,13 @@ a = Action('build $CHANGED_SOURCES', batch_key=batch_key) Miscellaneous Action Functions -scons +&scons; supplies a number of functions that arrange for various common file and directory manipulations to be performed. These are similar in concept to "tasks" in the -Ant build tool, +&Ant; build tool, although the implementation is slightly different. These functions do not actually perform the specified action @@ -5620,9 +5565,10 @@ file is being read, you can use the Execute global function to do so: - + + Execute(Touch('file')) - + Second, you can use these functions @@ -5637,14 +5583,15 @@ without relying on platform-specific external commands: - + + env = Environment(TMPBUILD = '/tmp/builddir') env.Command('foo.out', 'foo.in', [Mkdir('$TMPBUILD'), Copy('$TMPBUILD', '${SOURCE.dir}'), "cd $TMPBUILD && make", Delete('$TMPBUILD')]) - + @@ -5658,7 +5605,7 @@ file or directory to the specified which can be octal or string, similar to the bash command. Examples: - + Execute(Chmod('file', 0o755)) env.Command('foo.out', 'foo.in', @@ -5670,10 +5617,11 @@ Execute(Chmod('file', "ugo+w")) env.Command('foo.out', 'foo.in', [Copy('$TARGET', '$SOURCE'), Chmod('$TARGET', "ugo+w")]) - + + Copy(dest, src) @@ -5685,15 +5633,16 @@ source file or directory to the destination file or directory. Examples: - + Execute(Copy('foo.output', 'foo.input')) env.Command('bar.out', 'bar.in', Copy('$TARGET', '$SOURCE')) - + + Delete(entry, [must_exist]) @@ -5715,7 +5664,7 @@ that is, the Action will silently do nothing if the entry does not exist. Examples: - + Execute(Delete('/tmp/buildroot')) env.Command('foo.out', 'foo.in', @@ -5723,10 +5672,11 @@ env.Command('foo.out', 'foo.in', MyBuildAction]) Execute(Delete('file_that_must_exist', must_exist=1)) - + + Mkdir(dir) @@ -5736,7 +5686,7 @@ directory dir . Examples: - + Execute(Mkdir('/tmp/outputdir')) env.Command('foo.out', 'foo.in', @@ -5744,10 +5694,11 @@ env.Command('foo.out', 'foo.in', Copy('/tmp/builddir/foo.in', '$SOURCE'), "cd /tmp/builddir && make", Copy('$TARGET', '/tmp/builddir/foo.out')]) - + + Move(dest, src) @@ -5760,16 +5711,17 @@ the specified file or directory. Examples: - + Execute(Move('file.destination', 'file.source')) env.Command('output_file', 'input_file', [MyBuildAction, Move('$TARGET', 'file_created_by_MyBuildAction')]) - + + Touch(file) @@ -5779,13 +5731,13 @@ on the specified file. Examples: - + Execute(Touch('file_to_be_touched')) env.Command('marker', 'input_file', [MyBuildAction, Touch('$TARGET')]) - + @@ -5795,13 +5747,13 @@ env.Command('marker', 'input_file', Variable Substitution Before executing a command, -scons -performs construction variable interpolation on the string that makes up +&scons; +performs &consvar; interpolation on the string that makes up the command line of the builder. Variables are introduced in such strings by a $ prefix. -Besides regular construction variables, scons provides the following +Besides regular &consvars;, scons provides the following special variables for each command execution: @@ -5810,49 +5762,49 @@ special variables for each command execution: The file names of all sources of the build command that have changed since the target was last built. - + CHANGED_TARGETS The file names of all targets that would be built from sources that have changed since the target was last built. - + SOURCE The file name of the source of the build command, or the file name of the first source if multiple sources are being built. - + SOURCES The file names of the sources of the build command. - + TARGET The file name of the target being built, or the file name of the first target if multiple targets are being built. - + TARGETS The file names of all targets being built. - + UNCHANGED_SOURCES @@ -5860,9 +5812,9 @@ if multiple targets are being built. that have not changed since the target was last built. - + UNCHANGED_TARGETS @@ -5870,30 +5822,29 @@ changed since the target was last built. from sources that have not changed since the target was last built. - -Note that the above variables are reserved -and may not be set in a construction environment. +The above variables are reserved +and may not be set in a &consenv;. -For example, given the construction variables +For example, given the &consvars; CC='cc', targets=['foo'] and sources=['foo.c', 'bar.c']: - + action='$CC -c -o $TARGET $SOURCES' - + would produce the command line: - + cc -c -o foo foo.c bar.c - + Variable names may be surrounded by curly braces { } @@ -5902,17 +5853,13 @@ are not part of the name. Within the curly braces, a variable name may have a Python slice subscript appended to select one or more items from a list. -In the previous example, the string: - - -${SOURCES[1]} - - -would produce: +In the previous example, the string: +${SOURCES[1]} +would produce: - + bar.c - + Additionally, a variable name may have the following special @@ -5926,47 +5873,47 @@ to modify the interpolated string: The base path of the file name, including the directory path but excluding any suffix. - + dir The name of the directory in which the file exists. - + file The file name, minus any directory portion. - + filebase Just the basename of the file, minus any suffix and minus the directory. - + suffix Just the file suffix. - + abspath The absolute path name of the file. - + posix @@ -5977,9 +5924,9 @@ with directories separated by not backslashes. This is sometimes necessary on Windows systems when a path references a file on other (POSIX) systems. - + srcpath @@ -5987,9 +5934,9 @@ when a path references a file on other (POSIX) systems. VariantDir(). If this file isn't linked, it just returns the directory and filename unchanged. - + srcdir @@ -5997,9 +5944,9 @@ it just returns the directory and filename unchanged. VariantDir(). If this file isn't linked, it just returns the directory part of the filename. - + rsrcpath @@ -6009,9 +5956,9 @@ If the file does not exist locally but exists in a Repository, the path in the Repository is returned. If this file isn't linked, it just returns the directory and filename unchanged. - + rsrcdir @@ -6019,7 +5966,6 @@ directory and filename unchanged. VariantDir(). If this file isn't linked, it just returns the directory part of the filename. - @@ -6059,7 +6005,7 @@ how this can be used. Lastly, a variable name may be a callable Python function associated with a -construction variable in the environment. +&consvar; in the environment. The function should accept four arguments: @@ -6070,18 +6016,21 @@ accept four arguments: a list of target nodes + source a list of source nodes + env -the construction environment +the &consenv; + for_signature @@ -6098,7 +6047,7 @@ the called function returns into the expanded string: - + def foo(target, source, env, for_signature): return "bar" @@ -6119,7 +6068,7 @@ so that the arguments will be associated with the instantiation of the class: - + class foo(object): def __init__(self, arg): self.arg = arg @@ -6129,7 +6078,7 @@ class foo(object): # Will expand $BAR to "my argument bar baz" env=Environment(FOO=foo, BAR="${FOO('my argument')} baz") - + The special pseudo-variables @@ -6155,23 +6104,21 @@ and will be removed before the command is executed. For example, the command line: - + echo Last build occurred $( $TODAY $). > $TARGET - - + would execute the command: - + echo Last build occurred $TODAY. > $TARGET - - + but the command signature added to any target files would be: - + echo Last build occurred . > $TARGET - + @@ -6179,25 +6126,32 @@ echo Last build occurred . > $TARGET Any Python code within curly braces -{ } -and introduced by the variable prefix $ -gets evaluated by the Python eval statement, +{} +and introduced by the variable prefix $ +will be evaluated using the Python eval statement, with the Python globals set to -the current environment's set of construction variables. +the current environment's set of &consvars;, and the result +substituted in. So in the following case: - + + env['COND'] = 0 env.Command('foo.out', 'foo.in', '''echo ${COND==1 and 'FOO' or 'BAR'} > $TARGET''') - + + the command executed will be either - + + echo FOO > foo.out - + + or - + + echo BAR > foo.out - + + according to the current value of env['COND'] when the command is executed. The evaluation takes place when the target is being @@ -6209,12 +6163,12 @@ later in the SConscript, the final value will be used. COND, FOO, and -BAR are construction variables, +BAR are &consvars;, and their values are substituted into the final command. FOO is a list, so its elements are interpolated separated by spaces. - + env=Environment() env['COND'] = 0 env['FOO'] = ['foo1', 'foo2'] @@ -6224,9 +6178,9 @@ env.Command('foo.out', 'foo.in', # Will execute this: # echo foo1 foo2 > foo.out - + -SCons uses the following rules when converting construction variables into +SCons uses the following rules when converting &consvars; into command lines: @@ -6235,25 +6189,25 @@ command lines: When the value is a string it is interpreted as a space delimited list of command line arguments. - + List When the value is a list it is interpreted as a list of command line arguments. Each element of the list is converted to a string. - + Other Anything that is not a list or string is converted to a string and interpreted as a single command line argument. - + Newline @@ -6261,7 +6215,6 @@ interpreted as a single command line argument. all other parsing, so it is not possible for arguments (e.g. file names) to contain embedded newline characters. This limitation will likely go away in a future version of SCons. - @@ -6282,16 +6235,22 @@ function accepts the following arguments: function -This can be either: -1) a Python function that will process +This can be either: + + +a Python function that will process the Node (file) and return a list of File Nodes representing the implicit dependencies (file names) found in the contents; or: -2) a dictionary that maps keys + + +a dictionary that maps keys (typically the file suffix, but see below for more discussion) -to other Scanners that should be called. +to other Scanners that should be called. + + If the argument is actually a Python function, the function must take three or four arguments: @@ -6303,7 +6262,7 @@ the function must take three or four arguments: The node argument is the internal -SCons node representing the file. +&SCons; node representing the file. Use str(node) to fetch the name of the file, and @@ -6319,11 +6278,11 @@ might not exist The env -argument is the construction environment for the scan. +argument is the &consenv; for the scan. Fetch values from it using the env.Dictionary() method or using the key lookup operator -directly on the construction environment. +directly on the &consenv;. The path @@ -6338,18 +6297,18 @@ argument (see below). arg argument is the argument supplied when the scanner was created, if any. - + name The name of the Scanner. This is mainly used to identify the Scanner internally. - + argument @@ -6358,9 +6317,9 @@ will be passed to the scanner function (described above) and the path function (specified below). - + skeys @@ -6374,14 +6333,14 @@ Scanner knows how to scan. If the argument is a string, then it will be expanded into a list by the current environment. - + path_function A Python function that takes four or five arguments: -a construction environment, +a &consenv;, a Node for the directory containing the SConscript file in which the first target was defined, @@ -6398,11 +6357,11 @@ by this Scanner object. FindPathDirs() function can be used to return a ready-made path_function -for a given construction variable name, +for a given &consvar; name, instead of having to write your own function from scratch.) - + node_class @@ -6414,9 +6373,9 @@ that are not of this class will be run through the node_factory function. - + node_factory @@ -6424,14 +6383,14 @@ function. or other object and turn it into the appropriate class of Node to be returned by this Scanner object. - + scan_check An optional Python function that takes two arguments, -a Node (file) and a construction environment, +a Node (file) and a &consenv;, and returns whether the Node should, in fact, be scanned for dependencies. @@ -6439,9 +6398,9 @@ This check can be used to eliminate unnecessary calls to the scanner function when, for example, the underlying file represented by a Node does not yet exist. - + recursive @@ -6462,34 +6421,29 @@ should return a list of Nodes that should be scanned recursively; this can be used to select a specific subset of Nodes for additional scanning. - Note that -scons +&scons; has a global SourceFileScanner object that is used by -the -Object(), -SharedObject(), -and -StaticObject() +the &Object;, &SharedObject; and &StaticObject; builders to decide which scanner should be used for different file extensions. -You can using the +You can use the SourceFileScanner.add_scanner() method to add your own Scanner object to the -scons +&SCons; infrastructure that builds target programs or libraries from a list of source files of different types: - + def xyz_scan(node, env, path): contents = node.get_text_contents() # Scan the contents and return the included files. @@ -6505,45 +6459,45 @@ env.Program('my_prog', ['file1.c', 'file2.f', 'file3.xyz'])
SYSTEM-SPECIFIC BEHAVIOR -SCons and its configuration files are very portable, +&scons; and its configuration files are very portable, due largely to its implementation in Python. There are, however, a few portability issues waiting to trap the unwary. .C file suffix -SCons handles the upper-case +&scons; handles the upper-case .C file suffix differently, depending on the capabilities of the underlying system. On a case-sensitive system such as Linux or UNIX, -SCons treats a file with a +&scons; treats a file with a .C suffix as a C++ source file. On a case-insensitive system such as Windows, -SCons treats a file with a +&scons; treats a file with a .C suffix as a C source file. .F file suffix -SCons handles the upper-case +&scons; handles the upper-case .F file suffix differently, depending on the capabilities of the underlying system. On a case-sensitive system such as Linux or UNIX, -SCons treats a file with a +&scons; treats a file with a .F suffix as a Fortran source file that is to be first run through the standard C preprocessor. On a case-insensitive system such as Windows, -SCons treats a file with a +&scons; treats a file with a .F suffix as a Fortran source file that should not @@ -6570,8 +6524,7 @@ such as the python.org and ActiveState versions, do not have the Cygwin path name semantics. This means that using a native Windows version of Python to build compiled programs using Cygwin tools -(such as gcc, bison, -and flex) +(such as &gcc;, &bison; and flex) may yield unpredictable results. "Mixing and matching" in this way can be made to work, @@ -6580,18 +6533,18 @@ in your SConscript files. In practice, users can sidestep the issue by adopting the following rules: -When using gcc, +When using &gcc;, use the Cygwin-supplied Python interpreter -to run SCons; +to run &scons;; when using Microsoft Visual C/C++ (or some other Windows compiler) -use the python.org or ActiveState version of Python -to run SCons. +use the python.org or Microsoft Store or ActiveState version of Python +to run &scons;. Windows: scons.bat file On Windows systems, -SCons is executed via a wrapper +&scons; is executed via a wrapper scons.bat file. This has (at least) two ramifications: @@ -6602,14 +6555,13 @@ on the command line may have to put double quotes around the assignments: - -scons "FOO=BAR" "BAZ=BLEH" - + +scons "FOO=BAR" "BAZ=BLEH" + Second, the Cygwin shell does not recognize this file as being the same -as an -scons +as an &scons; command issued at the command-line prompt. You can work around this either by executing @@ -6617,42 +6569,38 @@ executing from the Cygwin command line, or by creating a wrapper shell script named -scons . +scons. MinGW The MinGW bin directory must be in your PATH environment variable or the -PATH variable under the ENV construction variable for SCons +PATH variable under the ENV &consvar; for &scons; to detect and use the MinGW tools. When running under the native Windows -Python interpreter, SCons will prefer the MinGW tools over the Cygwin +Python interpreter, &scons; will prefer the MinGW tools over the Cygwin tools, if they are both installed, regardless of the order of the bin directories in the PATH variable. If you have both MSVC and MinGW installed and you want to use MinGW instead of MSVC, -then you must explicitly tell SCons to use MinGW by passing - - -tools=['mingw'] - - -to the Environment() function, because SCons will prefer the MSVC tools +then you must explicitly tell &scons; to use MinGW by passing +tools=['mingw'] +to the &Environment; function, because &scons; will prefer the MSVC tools over the MinGW tools. EXAMPLES -To help you get started using SCons, +To help you get started using &scons;, this section contains a brief overview of some common tasks. Basic Compilation From a Single Source File - + env = Environment() env.Program(target = 'foo', source = 'foo.c') - + Note: Build the file by specifying the target as an argument @@ -6663,19 +6611,19 @@ or by specifying a dot ("scons ."). Basic Compilation From Multiple Source Files - + env = Environment() env.Program(target = 'foo', source = Split('f1.c f2.c f3.c')) - + Setting a Compilation Flag - + env = Environment(CCFLAGS = '-g') env.Program(target = 'foo', source = 'foo.c') - + @@ -6684,51 +6632,51 @@ env.Program(target = 'foo', source = 'foo.c') Note: You do not need to set CCFLAGS to specify -I options by hand. -SCons will construct the right -I options from CPPPATH. +&scons; will construct the right options from CPPPATH. - + env = Environment(CPPPATH = ['.']) env.Program(target = 'foo', source = 'foo.c') - + Search Multiple Directories For .h Files - + env = Environment(CPPPATH = ['include1', 'include2']) env.Program(target = 'foo', source = 'foo.c') - + Building a Static Library - + env = Environment() env.StaticLibrary(target = 'foo', source = Split('l1.c l2.c')) env.StaticLibrary(target = 'bar', source = ['l3.c', 'l4.c']) - + Building a Shared Library - + env = Environment() env.SharedLibrary(target = 'foo', source = ['l5.c', 'l6.c']) env.SharedLibrary(target = 'bar', source = Split('l7.c l8.c')) - + Linking a Local Library Into a Program - + env = Environment(LIBS = 'mylib', LIBPATH = ['.']) env.Library(target = 'mylib', source = Split('l1.c l2.c')) env.Program(target = 'prog', source = ['p1.c', 'p2.c']) - + @@ -6736,9 +6684,9 @@ env.Program(target = 'prog', source = ['p1.c', 'p2.c']) Notice that when you invoke the Builder, you can leave off the target file suffix, -and SCons will add it automatically. +and &scons; will add it automatically. - + bld = Builder(action = 'pdftex < $SOURCES > $TARGET' suffix = '.pdf', src_suffix = '.tex') @@ -6747,19 +6695,21 @@ env.PDFBuilder(target = 'foo.pdf', source = 'foo.tex') # The following creates "bar.pdf" from "bar.tex" env.PDFBuilder(target = 'bar', source = 'bar') - + Note also that the above initialization overwrites the default Builder objects, so the Environment created above -can not be used call Builders like env.Program(), -env.Object(), env.StaticLibrary(), etc. +can not be used call Builders like +env.Program, +env.Object, +env.StaticLibrary etc. Adding Your Own Builder Object to an Environment - + bld = Builder(action = 'pdftex < $SOURCES > $TARGET' suffix = '.pdf', src_suffix = '.tex') @@ -6767,15 +6717,15 @@ env = Environment() env.Append(BUILDERS = {'PDFBuilder' : bld}) env.PDFBuilder(target = 'foo.pdf', source = 'foo.tex') env.Program(target = 'bar', source = 'bar.c') - + You also can use other Pythonic techniques to add -to the BUILDERS construction variable, such as: +to the BUILDERS &consvar;, such as: - + env = Environment() env['BUILDERS]['PDFBuilder'] = bld - + @@ -6792,7 +6742,7 @@ lines in the scanned file. This would implicitly assume that all included files live in the top-level directory: - + import re include_re = re.compile(r'^include\s+(\S+)$', re.M) @@ -6816,7 +6766,7 @@ env.Command('foo', 'foo.k', 'kprocess < $SOURCES > $TARGET') bar_in = File('bar.in') env.Command('bar', bar_in, 'kprocess $SOURCES > $TARGET') bar_in.target_scanner = kscan - + It is important to note that you have to return a list of File nodes from the scan function, simple @@ -6831,10 +6781,10 @@ a scanner which searches a path of directories (specified as the MYPATH -construction variable) +&consvar;) for files that actually exist: - + import re import os include_re = re.compile(r'^include\s+(\S+)$', re.M) @@ -6874,12 +6824,12 @@ function used in the previous example returns a function that will return a list of directories specified in the $MYPATH -construction variable. It lets SCons detect the file -incs/foo.inc, +&consvar;. It lets &scons; detect the file +incs/foo.inc, even if -foo.x +foo.x contains the line -include foo.inc +include foo.inc only. If you need to customize how the search path is derived, you would provide your own @@ -6887,7 +6837,7 @@ you would provide your own argument when creating the Scanner object, as follows: - + # MYPATH is a list of directories to search for files in def pf(env, dir, target, source, arg): top_dir = Dir('#').abspath @@ -6914,49 +6864,55 @@ scanner = Scanner(name='myscanner', SConscript file are relative to that subdirectory. - -SConstruct: +SConstruct: - env = Environment() - env.Program(target = 'foo', source = 'foo.c') + +env = Environment() +env.Program(target = 'foo', source = 'foo.c') - SConscript('sub/SConscript') +SConscript('sub/SConscript') + -sub/SConscript: +sub/SConscript: - env = Environment() - # Builds sub/foo from sub/foo.c - env.Program(target = 'foo', source = 'foo.c') + +env = Environment() +# Builds sub/foo from sub/foo.c +env.Program(target = 'foo', source = 'foo.c') - SConscript('dir/SConscript') +SConscript('dir/SConscript') + -sub/dir/SConscript: +sub/dir/SConscript: - env = Environment() - # Builds sub/dir/foo from sub/dir/foo.c - env.Program(target = 'foo', source = 'foo.c') + +env = Environment() +# Builds sub/dir/foo from sub/dir/foo.c +env.Program(target = 'foo', source = 'foo.c') Sharing Variables Between SConscript Files -You must explicitly Export() and Import() variables that +You must explicitly call &Export; and &Import; for variables that you want to share between SConscript files. - -SConstruct: +SConstruct: - env = Environment() - env.Program(target = 'foo', source = 'foo.c') + +env = Environment() +env.Program(target = 'foo', source = 'foo.c') - Export("env") - SConscript('subdirectory/SConscript') +Export("env") +SConscript('subdirectory/SConscript') + -subdirectory/SConscript: +subdirectory/SConscript: - Import("env") - env.Program(target = 'foo', source = 'foo.c') + +Import("env") +env.Program(target = 'foo', source = 'foo.c') @@ -6964,108 +6920,117 @@ subdirectory/SConscript: Building Multiple Variants From the Same Source Use the variant_dir keyword argument to -the SConscript function to establish +the &SConscriptFunc; function to establish one or more separate variant build directory trees for a given source directory: - -SConstruct: +SConstruct: - cppdefines = ['FOO'] - Export("cppdefines") - SConscript('src/SConscript', variant_dir='foo') + +cppdefines = ['FOO'] +Export("cppdefines") +SConscript('src/SConscript', variant_dir='foo') - cppdefines = ['BAR'] - Export("cppdefines") - SConscript('src/SConscript', variant_dir='bar') +cppdefines = ['BAR'] +Export("cppdefines") +SConscript('src/SConscript', variant_dir='bar') + -src/SConscript: +src/SConscript: - Import("cppdefines") - env = Environment(CPPDEFINES = cppdefines) - env.Program(target = 'src', source = 'src.c') + +Import("cppdefines") +env = Environment(CPPDEFINES = cppdefines) +env.Program(target = 'src', source = 'src.c') -Note the use of the Export() method +Note the use of the &Export; method to set the "cppdefines" variable to a different -value each time we call the SConscript function. +value each time we call the &SConscriptFunc; function. Hierarchical Build of Two Libraries Linked With a Program - -SConstruct: +SConstruct: - env = Environment(LIBPATH=['#libA', '#libB']) - Export('env') - SConscript('libA/SConscript') - SConscript('libB/SConscript') - SConscript('Main/SConscript') + +env = Environment(LIBPATH=['#libA', '#libB']) +Export('env') +SConscript('libA/SConscript') +SConscript('libB/SConscript') +SConscript('Main/SConscript') + -libA/SConscript: +libA/SConscript: - Import('env') - env.Library('a', Split('a1.c a2.c a3.c')) + +Import('env') +env.Library('a', Split('a1.c a2.c a3.c')) + -libB/SConscript: +libB/SConscript: - Import('env') - env.Library('b', Split('b1.c b2.c b3.c')) + +Import('env') +env.Library('b', Split('b1.c b2.c b3.c')) + -Main/SConscript: +Main/SConscript: - Import('env') - e = env.Clone(LIBS=['a', 'b']) - e.Program('foo', Split('m1.c m2.c m3.c')) + +Import('env') +e = env.Clone(LIBS=['a', 'b']) +e.Program('foo', Split('m1.c m2.c m3.c')) -The '#' in the LIBPATH directories specify that they're relative to the -top-level directory, so they don't turn into "Main/libA" when they're -used in Main/SConscript. +The # in the LIBPATH +directories specify that they're relative to the +top-level directory, so they don't turn into +Main/libA when they're +used in Main/SConscript Specifying only 'a' and 'b' for the library names -allows SCons to append the appropriate library +allows &scons; to append the appropriate library prefix and suffix for the current platform -(for example, 'liba.a' on POSIX systems, -'a.lib' on Windows). +(for example, liba.a on POSIX systems, +a.lib on Windows). -Customizing construction variables from the command line. +Customizing &consvars; from the command line. The following would allow the C compiler to be specified on the command line or in the file custom.py. - + vars = Variables('custom.py') vars.Add('CC', 'The C compiler.') env = Environment(variables=vars) Help(vars.GenerateHelpText(env)) - + The user could specify the C compiler on the command line: - -scons "CC=my_cc" - + +scons "CC=my_cc" + or in the custom.py file: - + CC = 'my_cc' - + or get documentation on the options: - -$ scons -h + +$ scons -h CC: The C compiler. default: None actual: cc - - + @@ -7081,41 +7046,46 @@ then include every header you want to precompile in "StdAfx.h", and finally include "StdAfx.h" as the first header in all the source files you are compiling to object files. For example: -StdAfx.h: - +StdAfx.h: + + #include <windows.h> #include <my_big_header.h> - + -StdAfx.cpp: - +StdAfx.cpp: + + #include <StdAfx.h> - + -Foo.cpp: - +Foo.cpp: + + #include <StdAfx.h> /* do some stuff */ - + -Bar.cpp: - +Bar.cpp: + + #include <StdAfx.h> /* do some other stuff */ - + -SConstruct: - +SConstruct: + + env=Environment() env['PCHSTOP'] = 'StdAfx.h' env['PCH'] = env.PCH('StdAfx.cpp')[0] env.Program('MyApp', ['Foo.cpp', 'Bar.cpp']) - + For more information see the document for the PCH builder, and the PCH and -PCHSTOP construction variables. To learn about the details of precompiled +PCHSTOP &consvars;. To learn about the details of precompiled headers consult the MSDN documentation for /Yc, /Yu, and /Yp. @@ -7125,17 +7095,18 @@ headers consult the MSDN documentation for /Yc, /Yu, and /Yp. Since including debugging information in programs and shared libraries can cause their size to increase significantly, Microsoft provides a mechanism for including the debugging information in an external file called a PDB -file. SCons supports PDB files through the PDB construction +file. &scons; supports PDB files through the PDB construction variable. -SConstruct: - +SConstruct: + + env=Environment() env['PDB'] = 'MyApp.pdb' env.Program('MyApp', ['Foo.cpp', 'Bar.cpp']) - + -For more information see the document for the PDB construction variable. +For more information see the document for the PDB &consvar;. @@ -7151,7 +7122,7 @@ However the following variables are imported by - SCONS_LIB_DIR + SCONS_LIB_DIR Specifies the directory that contains the &scons; Python module directory. Normally &scons; can deduce this, @@ -7163,7 +7134,7 @@ release, it may be necessary to specify - SCONSFLAGS + SCONSFLAGS A string of options that will be used by &scons; in addition to those passed on the command line. @@ -7171,7 +7142,7 @@ in addition to those passed on the command line. - SCONS_CACHE_MSVC_CONFIG + SCONS_CACHE_MSVC_CONFIG (Windows only). If set, save the shell environment variables generated when setting up the Microsoft Visual C++ compiler @@ -7198,19 +7169,15 @@ Remove the cache file in case of problems with this. and will silently revert to non-cached behavior in such cases. Since &scons; 3.1 (experimental). - SEE ALSO -scons -User Manual, -scons -Design Document, -scons -source code. +&SCons; User Manual, +&SCons; Design Document, +&SCons; source code. diff --git a/doc/python10/design.xml b/doc/python10/design.xml index bd571ba..bbbe887 100644 --- a/doc/python10/design.xml +++ b/doc/python10/design.xml @@ -320,7 +320,7 @@ (or other object). The signature of a derived file consists of the aggregate of the signatures of all the source files plus the command-line string used to - build the file. These signatures are stored in a &sconsign; file + build the file. These signatures are stored in a &sconsigndb; file in each directory. diff --git a/doc/scons.mod b/doc/scons.mod index 024afab..f279f47 100644 --- a/doc/scons.mod +++ b/doc/scons.mod @@ -8,6 +8,20 @@ --> + + +SCons"> +scons"> +scons-file"> +sconsign"> + top" -# Select the ID and votes columns and pick "align-->right" -# Select the priority column and pick "align-->center" -# Select the first row and click on the "bold" button -# Grab the lines between the column headers to adjust the column widths -# Grab the sort bar on the far left (just above the "1" for row one) -# and move it down one row. (Row one becomes a floating header) -# Voila! -from __future__ import print_function - -# The team members -# FIXME: These names really should be external to this script -team = sorted('Steven Gary Greg Ken Jim Bill Jason Dirk Anatoly'.split()) - -# The elements to be picked out of the issue -PickList = [ - # sort key -- these are used to sort the entry - 'target_milestone', 'priority', 'votes_desc', 'creation_ts', - # payload -- these are displayed - 'issue_id', 'votes', 'issue_type', 'target_milestone', - 'priority', 'assigned_to', 'short_desc', - ] - -# Conbert a leaf element into its value as a text string -# We assume it's "short enough" that there's only one substring -def Value(element): - v = element.firstChild - if v is None: return '' - return v.nodeValue - -# Parse the XML issues file and produce a DOM for it -import sys -if len(sys.argv) > 1: xml = sys.argv[1] -else: xml = 'issues.xml' -from xml.dom.minidom import parse -xml = parse(xml) - -# Go through the issues in the DOM, pick out the elements we want, -# and put them in our list of issues. -issues = [] -for issuezilla in xml.childNodes: - # The Issuezilla element contains the issues - if issuezilla.nodeType != issuezilla.ELEMENT_NODE: continue - for issue in issuezilla.childNodes: - # The issue elements contain the info for an issue - if issue.nodeType != issue.ELEMENT_NODE: continue - # Accumulate the pieces we want to include - d = {} - for element in issue.childNodes: - if element.nodeName in PickList: - d[element.nodeName] = Value(element) - # convert 'votes' to numeric, ascending and descending - try: - v = int('0' + d['votes']) - except KeyError: - pass - else: - d['votes_desc'] = -v - d['votes'] = v - # Marshal the elements and add them to the list - issues.append([ d[ix] for ix in PickList ]) -issues.sort() - -# Transcribe the issues into comma-separated values. -# FIXME: parameterize the output file name -import csv -writer = csv.writer(open('editlist.csv', 'w')) -# header -writer.writerow(['ID', 'Votes', 'Type/Member', 'Milestone', - 'Pri', 'Owner', 'Summary/Comments']) -for issue in issues: - row = issue[4:] # strip off sort key - #row[0] = """=hyperlink("http://scons.tigris.org/issues/show_bug.cgi?id=%s","%s")""" % (row[0],row[0]) - if row[3] == '-unspecified-': row[3] = 'triage' - writer.writerow(['','','','','','','']) - writer.writerow(row) - writer.writerow(['','','consensus','','','','']) - writer.writerow(['','','','','','','']) - for member in team: writer.writerow(['','',member,'','','','']) - -print("Exported %d issues to editlist.csv. Ready to upload to Google."%len(issues)) - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 514ecf7..e7ec71b 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -10,7 +10,7 @@ NOTE: Please include a reference to any Issues resolved by your changes in the b RELEASE VERSION/DATE TO BE FILLED IN LATER -From Rob Boehne + From Rob Boehne - Specify UTF-8 encoding when opening Java source file as text. By default, encoding is the output of locale.getpreferredencoding(False), and varies by platform. @@ -29,6 +29,7 @@ From Rob Boehne Only one open is allowed. You must call conf.Finish() to complete the currently open one before creating another - Add msys2 installed mingw default path to PATH for mingw tool. - C:\msys64\mingw64\bin + - Purge obsolete internal build and tooling scripts From Jeremy Elson: - Updated design doc to use the correct syntax for Depends() -- cgit v0.12 From 4f113a450dd5d9e83ee561ea047c8fe5461b84be Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 21 Mar 2020 16:25:35 -0700 Subject: Fix github PR templated.. --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 9e8b7a2..3b062d1 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -7,5 +7,5 @@ https://scons.org/guidelines.html ## Contributor Checklist: * [ ] I have created a new test or updated the unit tests to cover the new/changed functionality. -* [ ] I have updated `master/src/CHANGES.txt` directory (and read the `README.txt` in that directory) +* [ ] I have updated `src/CHANGES.txt` (and read the `README.txt` in that directory) * [ ] I have updated the appropriate documentation -- cgit v0.12 From 7d04c0684b7d260567e5d85ebe32ca27e3f8a786 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sun, 22 Mar 2020 09:32:05 -0600 Subject: Improve manpage markup on options [ci skip] The definition of options is now marked up with Docbook option tags. Signed-off-by: Mats Wichmann --- doc/man/scons.xml | 449 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 315 insertions(+), 134 deletions(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index 4ab58f7..a69c980 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -54,8 +54,9 @@ Steven Knight and the SCons Development Team + 2004 - 2020 - 2004 - 2020 The SCons Foundation @@ -87,7 +88,7 @@ scons options - name=val + name=val targets @@ -480,7 +481,9 @@ by appropriate setting of &consvars;. -OPTIONS + +OPTIONS + In general, &scons; supports the same command-line options as GNU &Make; @@ -492,14 +495,18 @@ and many of those supported by cons. - -b + 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. @@ -510,7 +517,7 @@ 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 @@ -528,7 +535,10 @@ are being looked for in, retrieved from, or written to the - --cache-disable, --no-cache + + , + + Disable the derived-file caching specified by &CacheDir;. @@ -539,7 +549,10 @@ nor copy files to the cache. - --cache-force, --cache-populate + + , + + When using &CacheDir;, populate a cache by copying any already-existing, up-to-date @@ -555,7 +568,7 @@ option. - --cache-readonly + Use the cache (if enabled) for reading, but do not not update the cache with changed files. @@ -564,7 +577,7 @@ cache with changed files. - --cache-show + When using &CacheDir; and retrieving a derived file from the cache, @@ -579,7 +592,7 @@ file was rebuilt or retrieved from the cache. - --config=mode + This specifies how the &Configure; call should use or generate the @@ -590,7 +603,7 @@ among the following choices. - --config=auto + scons will use its normal dependency mechanisms to decide if a test must be rebuilt or not. @@ -604,7 +617,7 @@ This is the default behavior. - --config=force + If this option is specified, all configuration tests will be re-run @@ -618,7 +631,7 @@ in a system header file or compiler. - --config=cache + If this option is specified, no configuration tests will be rerun @@ -631,7 +644,10 @@ have any results in the cache. - -C directory, --directory=directory + + , + + Run as if &scons; was started in directory @@ -672,7 +688,7 @@ to change the &SConstruct; search behavior when this option is used. - -D + Works exactly the same way as the @@ -684,7 +700,7 @@ directory. - --debug=type[,type...] + Debug the build process. type @@ -695,7 +711,7 @@ The following entries show the recognized types: - --debug=action-timestamps + Prints additional time profiling information. For each command, shows the absolute start and end times. @@ -707,7 +723,7 @@ Implies the option. - --debug=count + Print how many objects are created of the various classes used internally by SCons @@ -725,7 +741,7 @@ 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 @@ -734,7 +750,7 @@ files, as well as unlinking old targets before building them. - --debug=explain + Print an explanation of why &scons; is deciding to (re-)build the targets @@ -744,7 +760,7 @@ it selects for building. - --debug=findlibs + Instruct the scanner that searches for libraries to print a message about each potential library @@ -754,7 +770,7 @@ and about the actual libraries it finds. - --debug=includes + Print the include tree after each top-level target is built. This is generally used to find out what files are included by the sources @@ -768,7 +784,7 @@ $ scons --debug=includes foo.o - --debug=memoizer + Prints a summary of hits and misses using the Memoizer, an internal subsystem that counts @@ -778,7 +794,7 @@ instead of recomputing them each time they're needed. - --debug=memory + Prints how much memory SCons uses before and after reading the SConscript files @@ -787,7 +803,7 @@ and before and after building targets. - --debug=objects + Prints a list of the various objects of the various classes used internally by SCons. @@ -795,7 +811,7 @@ of the various classes used internally by SCons. - --debug=pdb + Re-run &scons; under the control of the pdb @@ -804,7 +820,7 @@ Python debugger. - --debug=prepare + Print a line each time any target (internal or external) is prepared for building. @@ -819,7 +835,7 @@ is at least considering them or not. - --debug=presub + Print the raw command line used to build each target before the &consenv; variables are substituted. @@ -836,7 +852,7 @@ Building myprog.o with action(s): - --debug=stacktrace + Prints an internal Python stack trace when encountering an otherwise unexplained error. @@ -844,7 +860,7 @@ when encountering an otherwise unexplained error. - --debug=time + Prints various time profiling information: @@ -900,7 +916,7 @@ should take place in parallel.) - --diskcheck=types + Enable specific checks for whether or not there is a file on disk @@ -909,7 +925,7 @@ where the SCons configuration expects a directory and whether or not RCS or SCCS sources exist when searching for source and include files. The -types +type argument can be set to: all, to enable all checks explicitly @@ -944,7 +960,7 @@ where the SCons configuration expects a directory). - --duplicate=ORDER + There are three ways to duplicate files in a build tree: hard links, soft (symbolic) links and copies. The default behaviour of SCons is to @@ -970,14 +986,19 @@ the mechanisms in the specified order. - --enable-virtualenv + Import virtualenv-related variables to SCons. - -f file, --file=file, --makefile=file, --sconstruct=file + + , + , + , + + Use file @@ -992,7 +1013,10 @@ will read all of the specified files. - -h, --help + + , + + Print a local help message for this build, if one is defined in the SConscript files, plus a line that describes the @@ -1004,7 +1028,10 @@ options. Exits after displaying the appropriate message. - -H, --help-options + + , + + Print the standard help message about command-line options and exit. @@ -1012,7 +1039,10 @@ exit. - -i, --ignore-errors + + , + + Ignore all errors from commands executed to rebuild files. @@ -1020,7 +1050,10 @@ exit. - -I directory, --include-dir=directory + + , + + Specifies a directory @@ -1033,14 +1066,14 @@ are used, the directories are searched in the order specified. - --ignore-virtualenv + Suppress importing virtualenv-related variables to SCons. - --implicit-cache + Cache implicit dependencies. This causes @@ -1069,7 +1102,7 @@ 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 @@ -1078,7 +1111,7 @@ implicit dependencies to be rescanned and recached. This implies - --implicit-deps-unchanged + Force SCons to ignore changes in the implicit dependencies. This causes cached implicit dependencies to always be used. @@ -1088,7 +1121,7 @@ This implies - --install-sandbox=path + When using the &Install; functions, prepend path @@ -1099,7 +1132,7 @@ underneath path. - --interactive + Starts SCons in interactive mode. The SConscript files are read once and a @@ -1252,7 +1285,10 @@ scons>>> exit - -j N, --jobs=N + + , + + Specifies the maximum number of comcurrent jobs (commands) to run. If there is more than one @@ -1269,7 +1305,10 @@ 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 @@ -1307,14 +1346,14 @@ targets specified on the command line will still be processed. - -m + Ignored for compatibility with non-GNU versions of &Make;. - --max-drift=SECONDS + Set the maximum expected drift in the modification time of files to SECONDS. @@ -1334,7 +1373,7 @@ no matter how old the file is. - --md5-chunksize=KILOBYTES + Set the block size used to compute MD5 signatures to KILOBYTES. @@ -1350,7 +1389,12 @@ 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. @@ -1358,7 +1402,7 @@ any out-of-date target files, but do not execute the commands. - --no-site-dir + Prevents the automatic addition of the standard site_scons @@ -1404,7 +1448,7 @@ dirs to the toolpath. - --profile=file + Run SCons under the Python profiler and save the results in the specified @@ -1415,7 +1459,9 @@ pstats module. - -q, --question + + , + Do not run any commands, or print anything. Just return an exit status that is zero if the specified targets are already up to @@ -1424,7 +1470,7 @@ date, non-zero otherwise. - -Q + Quiets SCons status messages about reading SConscript files, @@ -1441,7 +1487,7 @@ to rebuild target files are still printed. - --random + Build dependencies in a random order. This is useful when building multiple trees simultaneously with caching enabled, @@ -1451,7 +1497,11 @@ or retrieve the same target files. - -s, --silent, --quiet + + , + , + + Silent. Do not print commands that are executed to rebuild target files. @@ -1460,14 +1510,18 @@ Also suppresses SCons status messages. - -S, --no-keep-going, --stop + + , + , + + Ignored for compatibility with GNU &Make; - --site-dir=dir + Uses the named dir as the site directory rather than the default @@ -1547,7 +1601,7 @@ $HOME/.scons/site_scons - --stack-size=KILOBYTES + Set the size stack used to run threads to KILOBYTES. @@ -1571,7 +1625,10 @@ unless you encounter stack overflow errors. - -t, --touch + + , + + Ignored for compatibility with GNU &Make;. (Touching a file to make it @@ -1580,7 +1637,7 @@ appear up-to-date is unnecessary when using &scons;.) - --taskmastertrace=file + Prints trace information to the specified file @@ -1593,14 +1650,14 @@ may be used to specify the standard output. - --tree=options + Prints a tree of the dependencies after each top-level target is built. This prints out some or all of the tree, in various formats, depending on the -options +type specified: @@ -1645,8 +1702,8 @@ for the relevant output higher up in the tree. -Multiple options may be specified, -separated by commas: +Multiple type +choices may be specified, separated by commas: # Prints only derived files, with status information: @@ -1660,7 +1717,11 @@ separated by commas: - -u, --up, --search-up + + , + , + + Walks up the directory structure until an &SConstruct;, &Sconstruct;, &sconstruct;, &SConstruct.py;, @@ -1674,7 +1735,7 @@ current directory will be built. - -U + Works exactly the same way as the @@ -1687,7 +1748,10 @@ up in. - -v, --version + + , + + Print the &scons; @@ -1698,7 +1762,10 @@ Then exit. - -w, --print-directory + + , + + Print a message containing the working directory before and after other processing. @@ -1706,14 +1773,17 @@ 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 @@ -1722,14 +1792,20 @@ 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 + + , + + Enables or disables warnings about the cache directory not using the latest configuration information @@ -1739,7 +1815,10 @@ These warnings are enabled by default. - --warn=cache-write-error, --warn=no-cache-write-error + + , + + Enables or disables warnings about errors trying to write a copy of a built file to a specified @@ -1749,7 +1828,10 @@ These warnings are disabled by default. - --warn=corrupt-sconsign, --warn=no-corrupt-sconsign + + , + + Enables or disables warnings about unfamiliar signature data in .sconsign @@ -1759,7 +1841,10 @@ These warnings are enabled by default. - --warn=dependency, --warn=no-dependency + + , + + Enables or disables warnings about dependencies. These warnings are disabled by default. @@ -1767,7 +1852,10 @@ These warnings are disabled by default. - --warn=deprecated, --warn=no-deprecated + + , + + Enables or disables warnings about use of currently deprecated features. @@ -1784,7 +1872,10 @@ see below. - --warn=duplicate-environment, --warn=no-duplicate-environment + + , + + Enables or disables warnings about attempts to specify a build of a target with two different &consenvs; @@ -1794,7 +1885,10 @@ 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, @@ -1803,7 +1897,10 @@ which can yield unpredictable behavior with some compilers. - --warn=future-deprecated, --warn=no-future-deprecated + + , + + Enables or disables warnings about features that will be deprecated in the future. @@ -1818,14 +1915,20 @@ 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 + + , + + Enables or disables warnings about the use of two commonly misspelled keywords @@ -1842,7 +1945,10 @@ can themselves refer to lists of names or nodes. - --warn=missing-sconscript, --warn=no-missing-sconscript + + , + + Enables or disables warnings about missing SConscript files. These warnings are enabled by default. @@ -1850,7 +1956,10 @@ These warnings are enabled by default. - --warn=no-object-count, --warn=no-no-object-count + + , + + Enables or disables warnings about the @@ -1863,7 +1972,10 @@ option or from optimized Python (.pyo) modules. - --warn=no-parallel-support, --warn=no-no-parallel-support + + , + + Enables or disables warnings about the version of Python not being able to support parallel builds when the @@ -1874,7 +1986,10 @@ 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. @@ -1883,7 +1998,10 @@ These warnings are enabled by default. - --warn=reserved-variable, --warn=no-reserved-variable + + , + + Enables or disables warnings about attempts to set the reserved &consvar; names @@ -1901,7 +2019,10 @@ 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. @@ -1910,7 +2031,10 @@ 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 disabled by default. @@ -1940,7 +2064,11 @@ These warnings are enabled by default. - -Y repository, --repository=repository, --srcdir=repository + + , + , + + Search the specified repository for any input and target @@ -1950,15 +2078,17 @@ options may be specified, in which case the repositories are searched in the order specified. - -CONFIGURATION FILE REFERENCE + +CONFIGURATION FILE REFERENCE -Construction Environments + +Construction Environments + A &ConsEnv; is the basic means by which the SConscript files communicate build information to &scons;. @@ -2213,7 +2343,8 @@ env.SomeTool(targets, sources) -Builder Methods + +Builder Methods You tell &scons; what to build by calling Builders, functions which know to take a @@ -2707,6 +2838,7 @@ object. Methods and Functions To Do Things + In addition to Builder methods, &scons; provides a number of other &consenv; methods @@ -2803,7 +2935,9 @@ include: -SConscript Variables + +SConscript Variables + In addition to the global functions and methods, &scons; supports a number of Python variables @@ -3004,7 +3138,8 @@ default target before it's actually been added to the list. -Construction Variables + +Construction Variables @@ -3021,6 +3156,7 @@ default target before it's actually been added to the list. + A &consenv; has an associated dictionary of &consvars; that are used by built-in or user-supplied build rules. @@ -3088,7 +3224,8 @@ env2 = env.Clone(CC="cl.exe") -Configure Contexts + +Configure Contexts &scons; supports @@ -3807,7 +3944,8 @@ env = conf.Finish() -Command-Line Construction Variables + +Command-Line Construction Variables Often when building software, some variables must be specified at build time. @@ -4496,9 +4634,12 @@ css = index.File('app.css') -EXTENDING SCONS + +EXTENDING SCONS + + +Builder Objects -Builder Objects &scons; can be extended to build different types of targets by adding new Builder objects @@ -5090,7 +5231,8 @@ and emitter functions. -Action Objects + +Action Objects The Builder() @@ -5528,7 +5670,8 @@ a = Action('build $CHANGED_SOURCES', batch_key=batch_key) -Miscellaneous Action Functions + +Miscellaneous Action Functions &scons; supplies a number of functions @@ -5744,7 +5887,8 @@ env.Command('marker', 'input_file', -Variable Substitution + +Variable Substitution Before executing a command, &scons; @@ -6122,7 +6266,8 @@ echo Last build occurred . > $TARGET -Python Code Substitution + +Python Code Substitution Any Python code within curly braces @@ -6220,7 +6365,8 @@ a future version of SCons. -Scanner Objects + +Scanner Objects You can use the Scanner @@ -6458,13 +6604,17 @@ env.Program('my_prog', ['file1.c', 'file2.f', 'file3.xyz']) -SYSTEM-SPECIFIC BEHAVIOR + +SYSTEM-SPECIFIC BEHAVIOR + &scons; and its configuration files are very portable, due largely to its implementation in Python. There are, however, a few portability issues waiting to trap the unwary. -.C file suffix + +.C file suffix + &scons; handles the upper-case .C file suffix differently, @@ -6482,7 +6632,9 @@ such as Windows, suffix as a C source file. -.F file suffix + +.F file suffix + &scons; handles the upper-case .F file suffix differently, @@ -6504,7 +6656,9 @@ suffix as a Fortran source file that should be run through the C preprocessor. -Windows: Cygwin Tools and Cygwin Python vs. Windows Pythons + +Windows: Cygwin Tools and Cygwin Python vs. Windows Pythons + Cygwin supplies a set of tools and utilities that let users work on a Windows system using a more POSIX-like environment. @@ -6542,7 +6696,9 @@ use the python.org or Microsoft Store or ActiveState version of Python to run &scons;. -Windows: scons.bat file + +Windows: scons.bat file + On Windows systems, &scons; is executed via a wrapper scons.bat @@ -6573,7 +6729,8 @@ script named -MinGW + +MinGW The MinGW bin directory must be in your PATH environment variable or the PATH variable under the ENV &consvar; for &scons; @@ -6590,12 +6747,15 @@ over the MinGW tools. -EXAMPLES + +EXAMPLES + To help you get started using &scons;, this section contains a brief overview of some common tasks. -Basic Compilation From a Single Source File + +Basic Compilation From a Single Source File env = Environment() @@ -6609,7 +6769,8 @@ or by specifying a dot ("scons ."). -Basic Compilation From Multiple Source Files + +Basic Compilation From Multiple Source Files env = Environment() @@ -6618,7 +6779,8 @@ env.Program(target = 'foo', source = Split('f1.c f2.c f3.c')) -Setting a Compilation Flag + +Setting a Compilation Flag env = Environment(CCFLAGS = '-g') @@ -6627,7 +6789,8 @@ env.Program(target = 'foo', source = 'foo.c') -Search The Local Directory For .h Files + +Search The Local Directory For .h Files Note: You do not @@ -6641,7 +6804,8 @@ env.Program(target = 'foo', source = 'foo.c') -Search Multiple Directories For .h Files + +Search Multiple Directories For .h Files env = Environment(CPPPATH = ['include1', 'include2']) @@ -6650,7 +6814,8 @@ env.Program(target = 'foo', source = 'foo.c') -Building a Static Library + +Building a Static Library env = Environment() @@ -6660,7 +6825,8 @@ env.StaticLibrary(target = 'bar', source = ['l3.c', 'l4.c']) -Building a Shared Library + +Building a Shared Library env = Environment() @@ -6670,7 +6836,8 @@ env.SharedLibrary(target = 'bar', source = Split('l7.c l8.c')) -Linking a Local Library Into a Program + +Linking a Local Library Into a Program env = Environment(LIBS = 'mylib', LIBPATH = ['.']) @@ -6680,7 +6847,8 @@ env.Program(target = 'prog', source = ['p1.c', 'p2.c']) -Defining Your Own Builder Object + +Defining Your Own Builder Object Notice that when you invoke the Builder, you can leave off the target file suffix, @@ -6707,7 +6875,8 @@ can not be used call Builders like -Adding Your Own Builder Object to an Environment + +Adding Your Own Builder Object to an Environment bld = Builder(action = 'pdftex < $SOURCES > $TARGET' @@ -6729,7 +6898,8 @@ env['BUILDERS]['PDFBuilder'] = bld -Defining Your Own Scanner Object + +Defining Your Own Scanner Object The following example shows adding an extremely simple scanner (the kfile_scan() @@ -6893,7 +7063,8 @@ env.Program(target = 'foo', source = 'foo.c') -Sharing Variables Between SConscript Files + +Sharing Variables Between SConscript Files You must explicitly call &Export; and &Import; for variables that you want to share between SConscript files. @@ -6917,7 +7088,8 @@ env.Program(target = 'foo', source = 'foo.c') -Building Multiple Variants From the Same Source + +Building Multiple Variants From the Same Source Use the variant_dir keyword argument to the &SConscriptFunc; function to establish @@ -6950,7 +7122,8 @@ value each time we call the &SConscriptFunc; function. -Hierarchical Build of Two Libraries Linked With a Program + +Hierarchical Build of Two Libraries Linked With a Program SConstruct: @@ -6998,7 +7171,8 @@ prefix and suffix for the current platform -Customizing &consvars; from the command line. + +Customizing &consvars; from the command line. The following would allow the C compiler to be specified on the command line or in the file custom.py. @@ -7034,7 +7208,8 @@ CC: The C compiler. -Using Microsoft Visual C++ precompiled headers + +Using Microsoft Visual C++ precompiled headers Since windows.h includes everything and the kitchen sink, it can take quite some time to compile it over and over again for a bunch of object files, so @@ -7090,7 +7265,8 @@ headers consult the MSDN documentation for /Yc, /Yu, and /Yp. -Using Microsoft Visual C++ external debugging information + +Using Microsoft Visual C++ external debugging information Since including debugging information in programs and shared libraries can cause their size to increase significantly, Microsoft provides a mechanism @@ -7111,7 +7287,8 @@ env.Program('MyApp', ['Foo.cpp', 'Bar.cpp']) -ENVIRONMENT + +ENVIRONMENT In general, &scons; is not controlled by environment variables set in the shell used to invoke it, leaving it @@ -7174,14 +7351,18 @@ and will silently revert to non-cached behavior in such cases. -SEE ALSO + +SEE ALSO + &SCons; User Manual, &SCons; Design Document, &SCons; source code. -AUTHORS + +AUTHORS + Originally: Steven Knight knight@baldmt.com and Anthony Roach aroach@electriceyeball.com. Since 2010: The SCons Development Team scons-dev@scons.org. -- cgit v0.12 From 54f341043301ad279aab05c0c22f02abcecb21b4 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Mon, 23 Mar 2020 12:28:51 -0600 Subject: Make the manpage option-choice treatement consistent [ci skip] All the options where the option-argument is a choice between several (and possibly a choice of several, comma-separated) now are rendered in the same way. Signed-off-by: Mats Wichmann --- doc/man/scons.xml | 272 +++++++++++++++++++++++++----------------------------- 1 file changed, 124 insertions(+), 148 deletions(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index a69c980..bfc4fd7 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -277,7 +277,7 @@ When &scons; is invoked, the command line (including the contents of the &SCONSFLAGS; environment variable, if set) is processed. -Command-line options (see ;) are consumed. +Command-line options (see ) are consumed. Any variable argument assignments are collected, and remaining arguments are taken as the targets to build. @@ -594,16 +594,15 @@ file was rebuilt or retrieved from the cache. -This specifies how the &Configure; +Control how the &Configure; call should use or generate the results of configuration tests. -The option should be specified from -among the following choices. - - +modeshould be specified from +among the following choices: + - + auto scons will use its normal dependency mechanisms to decide if a test must be rebuilt or not. @@ -617,7 +616,7 @@ This is the default behavior. - + force If this option is specified, all configuration tests will be re-run @@ -631,7 +630,7 @@ in a system header file or compiler. - + cache If this option is specified, no configuration tests will be rerun @@ -642,6 +641,10 @@ and a necessary test does not have any results in the cache. + + + + @@ -707,11 +710,10 @@ directory. specifies the kind of debugging info to emit. Multiple types may be specified, separated by commas. The following entries show the recognized types: - - + - + action-timestamps Prints additional time profiling information. For each command, shows the absolute start and end times. @@ -723,7 +725,7 @@ Implies the option. - + count Print how many objects are created of the various classes used internally by SCons @@ -741,7 +743,7 @@ files). - + 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 @@ -750,7 +752,7 @@ files, as well as unlinking old targets before building them. - + explain Print an explanation of why &scons; is deciding to (re-)build the targets @@ -760,7 +762,7 @@ it selects for building. - + findlibs Instruct the scanner that searches for libraries to print a message about each potential library @@ -770,7 +772,7 @@ and about the actual libraries it finds. - + includes Print the include tree after each top-level target is built. This is generally used to find out what files are included by the sources @@ -784,7 +786,7 @@ $ scons --debug=includes foo.o - + memoizer Prints a summary of hits and misses using the Memoizer, an internal subsystem that counts @@ -794,7 +796,7 @@ instead of recomputing them each time they're needed. - + memory Prints how much memory SCons uses before and after reading the SConscript files @@ -803,7 +805,7 @@ and before and after building targets. - + objects Prints a list of the various objects of the various classes used internally by SCons. @@ -811,7 +813,7 @@ of the various classes used internally by SCons. - + pdb Re-run &scons; under the control of the pdb @@ -820,13 +822,13 @@ Python debugger. - + prepare Print a line each time any target (internal or external) is prepared for building. &scons; prints this for each target it considers, even if that -target is up to date (see also --debug=explain). +target is up to date (see also ). This can help debug problems with targets that aren't being built; it shows whether &scons; @@ -835,7 +837,7 @@ is at least considering them or not. - + presub Print the raw command line used to build each target before the &consenv; variables are substituted. @@ -852,7 +854,7 @@ Building myprog.o with action(s): - + stacktrace Prints an internal Python stack trace when encountering an otherwise unexplained error. @@ -860,7 +862,7 @@ when encountering an otherwise unexplained error. - + time Prints various time profiling information: @@ -914,6 +916,9 @@ should take place in parallel.) + + + @@ -927,21 +932,50 @@ when searching for source and include files. The type argument can be set to: -all, -to enable all checks explicitly -(the default behavior); -none, -to disable all such checks; -match, -to check that files and directories on disk -match SCons' expected configuration; -rcs, -to check for the existence of an RCS source -for any missing source or include files; -sccs, -to check for the existence of an SCCS source -for any missing source or include files. -Multiple checks can be specified separated by commas; + + + + + all + +Enable all checks explicitly (the default behavior). + + + + + none + +Disable all such checks. + + + + + match + +to check that files and directories on disk +match SCons' expected configuration. + + + + + rcs + +Check for the existence of an RCS source +for any missing source or include files. + + + + + sccs + +Check for the existence of an SCCS source +for any missing source or include files. + + + + + +Multiple checks can be specified separated by commas. for example, would still check for SCCS and RCS sources, @@ -1144,7 +1178,6 @@ and re-initialize the dependency graph from scratch. SCons interactive mode supports the following commands: -
build[OPTIONS] [TARGETS] ... @@ -1182,9 +1215,6 @@ command: --taskmastertrace=FILE --tree=OPTIONS - - - Any other SCons command-line options that are specified do not cause errors @@ -1193,8 +1223,9 @@ but have no effect on the command (mainly because they affect how the SConscript files are read, which only happens once at the beginning of interactive mode). + + - clean[OPTIONS] [TARGETS] ... @@ -1266,8 +1297,6 @@ are synonyms. -
- An empty line repeats the last typed command. Command-line editing can be used if the @@ -1660,10 +1689,9 @@ depending on the type specified: - - + - --tree=all + all Print the entire dependency tree after each top-level target is built. @@ -1673,7 +1701,7 @@ including implicit dependencies and ignored dependencies. - --tree=derived + derived Restricts the tree output to only derived (target) files, not source files. @@ -1681,14 +1709,14 @@ not source files. - --tree=status + status Prints status information for each displayed node. - --tree=prune + prune Prunes the tree to avoid repeating dependency information for nodes that have already been displayed. @@ -1700,7 +1728,7 @@ for that node can be found by searching for the relevant output higher up in the tree. - + Multiple type choices may be specified, separated by commas: @@ -1785,29 +1813,22 @@ after other processing. -Enable or disable warnings. +Enable or disable (with the no- prefix) warnings. type specifies the type of warnings to be enabled or disabled: - -
+ - - , - - + all -Enables or disables all warnings. +All warnings. - - , - - + cache-version -Enables or disables warnings about the cache directory not using +Warnings about the cache directory not using the latest configuration information CacheDir(). These warnings are enabled by default. @@ -1815,12 +1836,9 @@ These warnings are enabled by default. - - , - - + cache-write-error -Enables or disables warnings about errors trying to +Warnings about errors trying to write a copy of a built file to a specified CacheDir(). These warnings are disabled by default. @@ -1828,12 +1846,9 @@ These warnings are disabled by default. - - , - - + corrupt-sconsign -Enables or disables warnings about unfamiliar signature data in +Warnings about unfamiliar signature data in .sconsign files. These warnings are enabled by default. @@ -1841,23 +1856,17 @@ These warnings are enabled by default. - - , - - + dependency -Enables or disables warnings about dependencies. +Warnings about dependencies. These warnings are disabled by default. - - , - - + deprecated -Enables or disables warnings about use of +Warnings about use of currently deprecated features. These warnings are enabled by default. Not all deprecation warnings can be disabled with the @@ -1872,12 +1881,9 @@ see below. - - , - - + duplicate-environment -Enables or disables warnings about attempts to specify a build +Warnings about attempts to specify a build of a target with two different &consenvs; that use the same action. These warnings are enabled by default. @@ -1885,24 +1891,18 @@ These warnings are enabled by default. - - , - - + fortran-cxx-mix -Enables or disables the specific warning about linking +Warnings about linking Fortran and C++ object files in a single executable, which can yield unpredictable behavior with some compilers. - - , - - + future-deprecated -Enables or disables warnings about features +Warnings about features that will be deprecated in the future. Such warnings are disabled by default. Enabling future deprecation warnings is @@ -1915,22 +1915,16 @@ that may require changes to the configuration. - - , - - + link -Enables or disables warnings about link steps. +Warnings about link steps. - - , - - + misleading-keywords -Enables or disables warnings about the use of two commonly +Warnings about the use of two commonly misspelled keywords targets and @@ -1945,23 +1939,17 @@ can themselves refer to lists of names or nodes. - - , - - + missing-sconscript -Enables or disables warnings about missing SConscript files. +Warnings about missing SConscript files. These warnings are enabled by default. - - , - - + no-object-count -Enables or disables warnings about the +Warnings about the feature not working when &scons; @@ -1972,12 +1960,9 @@ option or from optimized Python (.pyo) modules. - - , - - + no-parallel-support -Enables or disables warnings about the version of Python +Warnings about the version of Python not being able to support parallel builds when the option is used. @@ -1986,24 +1971,18 @@ These warnings are enabled by default. - - , - - + python-version -Enables or disables the warning about running +Warnings about running SCons with a deprecated version of Python. These warnings are enabled by default. - - , - - + reserved-variable -Enables or disables warnings about attempts to set the +Warnings about attempts to set the reserved &consvar; names CHANGED_SOURCES, CHANGED_TARGETS, @@ -2019,27 +1998,24 @@ These warnings are disabled by default. - - , - - + stack-size -Enables or disables warnings about requests to set the stack size +Warnings about requests to set the stack size that could not be honored. These warnings are enabled by default. - - , - - + target_not_build -Enables or disables warnings about a build rule not building the +Warnings about a build rule not building the expected targets. These warnings are disabled by default. + + + -- cgit v0.12 From 86b44676da95a1291cfb16144378ec59687c55e5 Mon Sep 17 00:00:00 2001 From: Iosif Daniel Kurazs Date: Tue, 18 Feb 2020 15:17:33 +0200 Subject: Adding posibility to use single line drawing when displaying the dependency tree --- src/engine/SCons/Script/Main.py | 5 ++-- src/engine/SCons/Script/SConsOptions.py | 4 ++- src/engine/SCons/Util.py | 44 +++++++++++++++++++++++++-------- 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py index ce948a0..62cd908 100644 --- a/src/engine/SCons/Script/Main.py +++ b/src/engine/SCons/Script/Main.py @@ -430,10 +430,11 @@ class QuestionTask(SCons.Taskmaster.AlwaysTask): class TreePrinter(object): - def __init__(self, derived=False, prune=False, status=False): + def __init__(self, derived=False, prune=False, status=False, sLineDraw=False): self.derived = derived self.prune = prune self.status = status + self.sLineDraw = sLineDraw def get_all_children(self, node): return node.all_children() def get_derived_children(self, node): @@ -445,7 +446,7 @@ class TreePrinter(object): else: func = self.get_all_children s = self.status and 2 or 0 - SCons.Util.print_tree(t, func, prune=self.prune, showtags=s) + SCons.Util.print_tree(t, func, prune=self.prune, showtags=s, lastChild=True, singleLineDraw=self.sLineDraw) def python_version_string(): diff --git a/src/engine/SCons/Script/SConsOptions.py b/src/engine/SCons/Script/SConsOptions.py index 8ec8ccf..0c82faf 100644 --- a/src/engine/SCons/Script/SConsOptions.py +++ b/src/engine/SCons/Script/SConsOptions.py @@ -834,7 +834,7 @@ def Parser(version): help="Trace Node evaluation to FILE.", metavar="FILE") - tree_options = ["all", "derived", "prune", "status"] + tree_options = ["all", "derived", "prune", "status", "linedraw"] def opt_tree(option, opt, value, parser, tree_options=tree_options): from . import Main @@ -848,6 +848,8 @@ def Parser(version): tp.prune = True elif o == 'status': tp.status = True + elif o == 'linedraw': + tp.sLineDraw = True else: raise OptionValueError(opt_invalid('--tree', o, tree_options)) parser.values.tree_printers.append(tp) diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index 22df6fa..e55ccb4 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -254,7 +254,7 @@ def render_tree(root, child_func, prune=0, margin=[0], visited=None): IDX = lambda N: N and 1 or 0 -def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited=None): +def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited=None, lastChild=False, singleLineDraw=False): """ Print a tree of nodes. This is like render_tree, except it prints lines directly instead of creating a string representation in memory, @@ -300,7 +300,8 @@ def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited=None): [0, 1][IDX(root.has_explicit_builder())] + [0, 2][IDX(root.has_builder())] ], - ' S'[IDX(root.side_effect)], ' P'[IDX(root.precious)], + ' 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)], @@ -312,27 +313,50 @@ def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited=None): tags = [] def MMM(m): - return [" ","| "][m] + if singleLineDraw: + return [" ","│ "][m] + else: + return [" ","| "][m] + margins = list(map(MMM, margin[:-1])) children = child_func(root) + cross = "+-" + if singleLineDraw: + cross = "├─" # sign used to point to the leaf. + # check if this is the last leaf of the branch + if lastChild: + #if this if the last leaf, then terminate: + cross = "└─" # sign for the last leaf + + # if this branch has children then split it + if len(children)>0: + # if it's a leaf: + if prune and rname in visited and children: + cross += "─" + else: + cross += "┬" + if prune and rname in visited and children: - sys.stdout.write(''.join(tags + margins + ['+-[', rname, ']']) + '\n') + sys.stdout.write(''.join(tags + margins + [cross,'[', rname, ']']) + '\n') return - sys.stdout.write(''.join(tags + margins + ['+-', rname]) + '\n') + sys.stdout.write(''.join(tags + margins + [cross, rname]) + '\n') visited[rname] = 1 + # if this item has children: if children: - margin.append(1) + margin.append(1) # Initialize margin with 1 for vertical bar. idx = IDX(showtags) + _child = 0 # Initialize this for the first child. for C in children[:-1]: - print_tree(C, child_func, prune, idx, margin, visited) - margin[-1] = 0 - print_tree(children[-1], child_func, prune, idx, margin, visited) - margin.pop() + _child = _child + 1 # number the children + print_tree(C, child_func, prune, idx, margin, visited, (len(children) - _child) <= 0 ,singleLineDraw) + margin[-1] = 0 # margins are with space (index 0) because we arrived to the last child. + print_tree(children[-1], child_func, prune, idx, margin, visited, True ,singleLineDraw) # for this call child and nr of children needs to be set 0, to signal the second phase. + margin.pop() # destroy the last margin added # Functions for deciding if things are like various types, mainly to -- cgit v0.12 From 267b767057b960002091a3b1ed2f99655eaf4f35 Mon Sep 17 00:00:00 2001 From: Paul Tipei Date: Tue, 18 Feb 2020 18:32:44 +0200 Subject: updated the src/CHANGES.txt --- src/CHANGES.txt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index e7ec71b..0fd55ba 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -14,11 +14,15 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Specify UTF-8 encoding when opening Java source file as text. By default, encoding is the output of locale.getpreferredencoding(False), and varies by platform. + From Iosif Kurazs: + - Added a new flag called "linedraw" for the command line argument "--tree" + that instructs scons to use single line drawing characters to draw the dependency tree. + From William Deegan: - - Fix broken clang + MSVC 2019 combination by using MSVC configuration logic to + - 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 + - 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 @@ -119,7 +123,7 @@ RELEASE 3.1.2 - Mon, 17 Dec 2019 02:06:27 +0000 (e.g. memmove) were incorrectly recognized as not available. From Jakub Kulik - - Fix stacktrace when using SCons with Python 3.5+ and SunOS/Solaris related tools. + - Fix stacktrace when using SCons with Python 3.5+ and SunOS/Solaris related tools. From Philipp Maierhöfer: - Avoid crash with UnicodeDecodeError on Python 3 when a Latex log file in -- cgit v0.12 From 8b3a91a8ad809ac6ea24d6834f4499b0cd1175d8 Mon Sep 17 00:00:00 2001 From: Paul Tipei Date: Wed, 19 Feb 2020 10:53:46 +0200 Subject: updated the CHANGES.txt --- src/CHANGES.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 0fd55ba..d4c0b09 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -50,6 +50,10 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - 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 Iosif Kurazs: + - Added a new flag called "linedraw" for the command line argument "--tree" + that instructs scons to use single line drawing characters to draw the dependency tree. + 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 -- cgit v0.12 From 35de9e8ffb17706816d3f9bb9751297f4beb87e1 Mon Sep 17 00:00:00 2001 From: Paul Tipei Date: Wed, 19 Feb 2020 15:56:32 +0200 Subject: added the test for the new implemented feature --- test/option--tree.py | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/test/option--tree.py b/test/option--tree.py index 1b34176..d44b602 100644 --- a/test/option--tree.py +++ b/test/option--tree.py @@ -41,7 +41,7 @@ test.run(arguments='-Q --tree=foofoo', stderr="""usage: scons [OPTION] [TARGET] ... SCons Error: `foofoo' is not a valid --tree option type, try: - all, derived, prune, status + all, derived, prune, status, linedraw """, status=2) @@ -76,6 +76,39 @@ expected = """Creating 'Foo.txt' test.run(arguments='-Q --tree=all', stdout=expected, status=0) + +#Tests the new command line option "linedraw" +test.write('SConstruct', + """ +env = Environment() +env.Tool("textfile") +try: + # Python 2 + write = unichr(0xe7).encode('utf-8') +except NameError: + # Python 3 + # str is utf-8 by default + write = chr(0xe7) +env.Textfile("LineDraw", write) +""") + +if sys.version_info.major < 3: + py23_char = unichr(0xe7).encode('utf-8') +else: + py23_char = chr(0xe7) + +expected = """Creating 'LineDraw.txt' +└─┬. + ├─┬LineDraw.txt + │ └─""" + py23_char + """ + └─SConstruct +""" + + +test.run(arguments='-Q --tree=linedraw', + stdout=expected, + status=0) + test.pass_test() # Local Variables: -- cgit v0.12 From 2003f3b5c098b27a70952bfc1847f4140cb2afec Mon Sep 17 00:00:00 2001 From: Paul Tipei Date: Wed, 19 Feb 2020 17:07:16 +0200 Subject: updated the option-tree.py file --- test/option--tree.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/test/option--tree.py b/test/option--tree.py index d44b602..fb255dc 100644 --- a/test/option--tree.py +++ b/test/option--tree.py @@ -61,10 +61,7 @@ except NameError: env.Textfile("Foo", write) """) -if sys.version_info.major < 3: - py23_char = unichr(0xe7).encode('utf-8') -else: - py23_char = chr(0xe7) +py23_char = chr(0xe7) expected = """Creating 'Foo.txt' +-. -- cgit v0.12 From 58b335b85db270c7bb80858aa01abf4b03d8bd3d Mon Sep 17 00:00:00 2001 From: Paul Tipei Date: Wed, 19 Feb 2020 17:11:21 +0200 Subject: Revert "updated the option-tree.py file" This reverts commit a864ad4607bf25d7ea46e6662d2d42d9fd7c40cd. --- test/option--tree.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/option--tree.py b/test/option--tree.py index fb255dc..d44b602 100644 --- a/test/option--tree.py +++ b/test/option--tree.py @@ -61,7 +61,10 @@ except NameError: env.Textfile("Foo", write) """) -py23_char = chr(0xe7) +if sys.version_info.major < 3: + py23_char = unichr(0xe7).encode('utf-8') +else: + py23_char = chr(0xe7) expected = """Creating 'Foo.txt' +-. -- cgit v0.12 From 89d03e37128aa839ed72ec72739b2ed431b7f4da Mon Sep 17 00:00:00 2001 From: Paul Tipei Date: Wed, 19 Feb 2020 17:14:54 +0200 Subject: more cleanup --- test/option--tree.py | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/test/option--tree.py b/test/option--tree.py index d44b602..0beec7f 100644 --- a/test/option--tree.py +++ b/test/option--tree.py @@ -82,20 +82,13 @@ test.write('SConstruct', """ env = Environment() env.Tool("textfile") -try: - # Python 2 - write = unichr(0xe7).encode('utf-8') -except NameError: - # Python 3 - # str is utf-8 by default - write = chr(0xe7) +# Python 3 +# str is utf-8 by default +write = chr(0xe7) env.Textfile("LineDraw", write) """) -if sys.version_info.major < 3: - py23_char = unichr(0xe7).encode('utf-8') -else: - py23_char = chr(0xe7) +py23_char = chr(0xe7) expected = """Creating 'LineDraw.txt' └─┬. -- cgit v0.12 From 7143fba43006c5dbccb4d1d9f43aa8fa0c05c271 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Tue, 24 Mar 2020 13:07:46 -0600 Subject: Add option to use box-draw chars with --tree This picks up and hopefully completes PR #3560. Add documentation for new --tree "linedraw" option. There is a new example output in userguide, which renumbers several of the existing troubleshoot_tree example outputs. Test is cleaned up a bit (not just the added part). The actual function in Util is made a little more genral - it uses unicode chr() values instead of literally pasting in the line drawing characters. Signed-off-by: Mats Wichmann --- doc/generated/examples/troubleshoot_tree1_2.xml | 34 +++++++++++++++--- doc/generated/examples/troubleshoot_tree1_3.xml | 13 +++---- doc/generated/examples/troubleshoot_tree1_4.xml | 47 ++++-------------------- doc/generated/examples/troubleshoot_tree1_5.xml | 47 ++++++++++++++++++------ doc/generated/examples/troubleshoot_tree1_6.xml | 30 +++++----------- doc/man/scons.xml | 15 +++++++- doc/user/troubleshoot.xml | 23 +++++++++--- src/engine/SCons/Util.py | 24 +++++++++---- test/option--tree.py | 48 ++++++++----------------- 9 files changed, 151 insertions(+), 130 deletions(-) diff --git a/doc/generated/examples/troubleshoot_tree1_2.xml b/doc/generated/examples/troubleshoot_tree1_2.xml index 0bd4874..d99435d 100644 --- a/doc/generated/examples/troubleshoot_tree1_2.xml +++ b/doc/generated/examples/troubleshoot_tree1_2.xml @@ -1,7 +1,31 @@ - -% scons -Q --tree=all f2.o +% scons -Q --tree=all,linedraw +cc -o f1.o -c -I. f1.c cc -o f2.o -c -I. f2.c -+-f2.o - +-f2.c - +-inc.h +cc -o f3.o -c -I. f3.c +cc -o prog f1.o f2.o f3.o +└─┬. + ├─SConstruct + ├─f1.c + ├─┬f1.o + │ ├─f1.c + │ └─inc.h + ├─f2.c + ├─┬f2.o + │ ├─f2.c + │ └─inc.h + ├─f3.c + ├─┬f3.o + │ ├─f3.c + │ └─inc.h + ├─inc.h + └─┬prog + ├─┬f1.o + │ ├─f1.c + │ └─inc.h + ├─┬f2.o + │ ├─f2.c + │ └─inc.h + └─┬f3.o + ├─f3.c + └─inc.h diff --git a/doc/generated/examples/troubleshoot_tree1_3.xml b/doc/generated/examples/troubleshoot_tree1_3.xml index 75fa841..7f3789f 100644 --- a/doc/generated/examples/troubleshoot_tree1_3.xml +++ b/doc/generated/examples/troubleshoot_tree1_3.xml @@ -1,11 +1,6 @@ - -% scons -Q --tree=all f1.o f3.o -cc -o f1.o -c -I. f1.c -+-f1.o - +-f1.c - +-inc.h -cc -o f3.o -c -I. f3.c -+-f3.o - +-f3.c +% scons -Q --tree=all f2.o +cc -o f2.o -c -I. f2.c ++-f2.o + +-f2.c +-inc.h diff --git a/doc/generated/examples/troubleshoot_tree1_4.xml b/doc/generated/examples/troubleshoot_tree1_4.xml index 409bce9..bc0dbac 100644 --- a/doc/generated/examples/troubleshoot_tree1_4.xml +++ b/doc/generated/examples/troubleshoot_tree1_4.xml @@ -1,43 +1,10 @@ - -% scons -Q --tree=status +% scons -Q --tree=all f1.o f3.o cc -o f1.o -c -I. f1.c -cc -o f2.o -c -I. f2.c ++-f1.o + +-f1.c + +-inc.h cc -o f3.o -c -I. f3.c -cc -o prog f1.o f2.o f3.o - E = exists - R = exists in repository only - b = implicit builder - B = explicit builder - S = side effect - P = precious - A = always build - C = current - N = no clean - H = no cache - -[E b ]+-. -[E C ] +-SConstruct -[E C ] +-f1.c -[E B C ] +-f1.o -[E C ] | +-f1.c -[E C ] | +-inc.h -[E C ] +-f2.c -[E B C ] +-f2.o -[E C ] | +-f2.c -[E C ] | +-inc.h -[E C ] +-f3.c -[E B C ] +-f3.o -[E C ] | +-f3.c -[E C ] | +-inc.h -[E C ] +-inc.h -[E B C ] +-prog -[E B C ] +-f1.o -[E C ] | +-f1.c -[E C ] | +-inc.h -[E B C ] +-f2.o -[E C ] | +-f2.c -[E C ] | +-inc.h -[E B C ] +-f3.o -[E C ] +-f3.c -[E C ] +-inc.h ++-f3.o + +-f3.c + +-inc.h diff --git a/doc/generated/examples/troubleshoot_tree1_5.xml b/doc/generated/examples/troubleshoot_tree1_5.xml index b852ab0..687b1ba 100644 --- a/doc/generated/examples/troubleshoot_tree1_5.xml +++ b/doc/generated/examples/troubleshoot_tree1_5.xml @@ -1,15 +1,42 @@ - -% scons -Q --tree=derived +% scons -Q --tree=status cc -o f1.o -c -I. f1.c cc -o f2.o -c -I. f2.c cc -o f3.o -c -I. f3.c cc -o prog f1.o f2.o f3.o -+-. - +-f1.o - +-f2.o - +-f3.o - +-prog - +-f1.o - +-f2.o - +-f3.o + E = exists + R = exists in repository only + b = implicit builder + B = explicit builder + S = side effect + P = precious + A = always build + C = current + N = no clean + H = no cache + +[E b ]+-. +[E C ] +-SConstruct +[E C ] +-f1.c +[E B C ] +-f1.o +[E C ] | +-f1.c +[E C ] | +-inc.h +[E C ] +-f2.c +[E B C ] +-f2.o +[E C ] | +-f2.c +[E C ] | +-inc.h +[E C ] +-f3.c +[E B C ] +-f3.o +[E C ] | +-f3.c +[E C ] | +-inc.h +[E C ] +-inc.h +[E B C ] +-prog +[E B C ] +-f1.o +[E C ] | +-f1.c +[E C ] | +-inc.h +[E B C ] +-f2.o +[E C ] | +-f2.c +[E C ] | +-inc.h +[E B C ] +-f3.o +[E C ] +-f3.c +[E C ] +-inc.h diff --git a/doc/generated/examples/troubleshoot_tree1_6.xml b/doc/generated/examples/troubleshoot_tree1_6.xml index a0d42d7..00b05ac 100644 --- a/doc/generated/examples/troubleshoot_tree1_6.xml +++ b/doc/generated/examples/troubleshoot_tree1_6.xml @@ -1,26 +1,14 @@ - -% scons -Q --tree=derived,status +% scons -Q --tree=derived cc -o f1.o -c -I. f1.c cc -o f2.o -c -I. f2.c cc -o f3.o -c -I. f3.c cc -o prog f1.o f2.o f3.o - E = exists - R = exists in repository only - b = implicit builder - B = explicit builder - S = side effect - P = precious - A = always build - C = current - N = no clean - H = no cache - -[E b ]+-. -[E B C ] +-f1.o -[E B C ] +-f2.o -[E B C ] +-f3.o -[E B C ] +-prog -[E B C ] +-f1.o -[E B C ] +-f2.o -[E B C ] +-f3.o ++-. + +-f1.o + +-f2.o + +-f3.o + +-prog + +-f1.o + +-f2.o + +-f3.o diff --git a/doc/man/scons.xml b/doc/man/scons.xml index bfc4fd7..3d2abdf 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -1709,6 +1709,19 @@ not source files. + linedraw + +Draw the tree output using Unicode line-drawing characters +instead of plain ASCII text. This option acts as a modifier +to the selected type(s). If +specified alone, without any type, +it behaves as if all +had been specified. + + + + + status Prints status information for each displayed node. @@ -6844,7 +6857,7 @@ env.PDFBuilder(target = 'bar', source = 'bar') Note also that the above initialization overwrites the default Builder objects, so the Environment created above -can not be used call Builders like +can not be used call Builders like env.Program, env.Object, env.StaticLibrary etc. diff --git a/doc/user/troubleshoot.xml b/doc/user/troubleshoot.xml index beea8c9..7049deb 100644 --- a/doc/user/troubleshoot.xml +++ b/doc/user/troubleshoot.xml @@ -442,6 +442,19 @@ inc.h + By default &SCons; uses "ASCII art" to draw the tree. It is + possible to use line-drawing characters (Unicode calls these + Box Drawing) to make a nicer display. To do this, add the + qualifier: + + + + + scons -Q --tree=all,linedraw + + + + The option only prints the dependency graph for the specified targets (or the default target(s) if none are specified on the command line). @@ -452,7 +465,7 @@ inc.h - + scons -Q --tree=all f2.o @@ -468,7 +481,7 @@ inc.h - + scons -Q --tree=all f1.o f3.o @@ -480,7 +493,7 @@ inc.h - + scons -Q --tree=status @@ -498,7 +511,7 @@ inc.h - + scons -Q --tree=derived @@ -509,7 +522,7 @@ inc.h - + scons -Q --tree=derived,status diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index e55ccb4..767b3f9 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -267,6 +267,7 @@ def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited=None, - `showtags` - print status information to the left of each node line - `margin` - the format of the left margin to use for children of root. 1 results in a pipe, and 0 results in no pipe. - `visited` - a dictionary of visited nodes in the current branch if not prune, or in the whole tree if prune. + - `singleLineDraw` - use line-drawing characters rather than ASCII. """ rname = str(root) @@ -301,7 +302,7 @@ def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited=None, [0, 2][IDX(root.has_builder())] ], ' S'[IDX(root.side_effect)], - ' P'[IDX(root.precious)], + ' P'[IDX(root.precious)], ' A'[IDX(root.always_build)], ' C'[IDX(root.is_up_to_date())], ' N'[IDX(root.noclean)], @@ -322,21 +323,32 @@ def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited=None, children = child_func(root) + cross = "+-" if singleLineDraw: - cross = "├─" # sign used to point to the leaf. + # unicode line drawing chars: + box_horiz = chr(0x2500) # '─' + box_vert = chr(0x2510) # '│' + box_up_right = chr(0x2514) # '└' + box_down_right = chr(0x250c) # '┌' + box_down_left = chr(0x2510) # '┐' + box_up_left = chr(0x2518) # '┘' + box_vert_right = chr(0x251c) # '├' + box_horiz_down = chr(0x252c) # '┬' + + cross = box_vert_right + box_horiz # sign used to point to the leaf. # check if this is the last leaf of the branch if lastChild: #if this if the last leaf, then terminate: - cross = "└─" # sign for the last leaf + cross = box_up_right + box_horiz # sign for the last leaf # if this branch has children then split it - if len(children)>0: + if children: # if it's a leaf: if prune and rname in visited and children: - cross += "─" + cross += box_horiz else: - cross += "┬" + cross += box_horiz_down if prune and rname in visited and children: sys.stdout.write(''.join(tags + margins + [cross,'[', rname, ']']) + '\n') diff --git a/test/option--tree.py b/test/option--tree.py index 0beec7f..290f1d4 100644 --- a/test/option--tree.py +++ b/test/option--tree.py @@ -47,60 +47,42 @@ SCons Error: `foofoo' is not a valid --tree option type, try: # Test that unicode characters can be printed (escaped) with the --tree option -test.write('SConstruct', - """ +test.write('SConstruct', """\ env = Environment() env.Tool("textfile") -try: - # Python 2 - write = unichr(0xe7).encode('utf-8') -except NameError: - # Python 3 - # str is utf-8 by default - write = chr(0xe7) -env.Textfile("Foo", write) +name = "français" +env.Textfile("Foo", name) """) -if sys.version_info.major < 3: - py23_char = unichr(0xe7).encode('utf-8') -else: - py23_char = chr(0xe7) +uchar = chr(0xe7) expected = """Creating 'Foo.txt' +-. +-Foo.txt - | +-""" + py23_char + """ + | +-fran%sais +-SConstruct -""" +""" % uchar -test.run(arguments='-Q --tree=all', - stdout=expected, - status=0) +test.run(arguments='-Q --tree=all', stdout=expected, status=0) -#Tests the new command line option "linedraw" -test.write('SConstruct', - """ +# Test the "linedraw" option: same basic test as previous. +# With "--tree=linedraw" must default to "all", and use line-drawing chars. +test.write('SConstruct', """\ env = Environment() env.Tool("textfile") -# Python 3 -# str is utf-8 by default -write = chr(0xe7) -env.Textfile("LineDraw", write) +name = "français" +env.Textfile("LineDraw", name) """) -py23_char = chr(0xe7) - expected = """Creating 'LineDraw.txt' └─┬. ├─┬LineDraw.txt - │ └─""" + py23_char + """ + │ └─fran%sais └─SConstruct -""" +""" % uchar -test.run(arguments='-Q --tree=linedraw', - stdout=expected, - status=0) +test.run(arguments='-Q --tree=linedraw', stdout=expected, status=0) test.pass_test() -- cgit v0.12 From 1d6761d2c25ba0471b7d9141c9495de2e6ba31c1 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Tue, 24 Mar 2020 13:26:50 -0600 Subject: Remove duplicate entry in src/CHANGES.txt Signed-off-by: Mats Wichmann --- src/CHANGES.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index d4c0b09..f4416b2 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -14,10 +14,6 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Specify UTF-8 encoding when opening Java source file as text. By default, encoding is the output of locale.getpreferredencoding(False), and varies by platform. - From Iosif Kurazs: - - Added a new flag called "linedraw" for the command line argument "--tree" - that instructs scons to use single line drawing characters to draw the dependency tree. - 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 -- cgit v0.12 From 52e08116a2a391deb706ca6eb9b47302e93f852b Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Tue, 24 Mar 2020 14:14:00 -0600 Subject: [PR #3591] tweak --tree=linedraw Add version note to manpage Turn linedraw chars into module-level constants, and use in the other place it was hardcoded. Signed-off-by: Mats Wichmann --- doc/man/scons.xml | 1 + src/engine/SCons/Util.py | 32 ++++++++++++++++---------------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index 3d2abdf..5d71bfd 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -1718,6 +1718,7 @@ specified alone, without any type, it behaves as if all had been specified. +Since &scons; 4.0. diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index 767b3f9..588d02f 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -253,6 +253,16 @@ def render_tree(root, child_func, prune=0, margin=[0], visited=None): IDX = lambda N: N and 1 or 0 +# unicode line drawing chars: +BOX_HORIZ = chr(0x2500) # '─' +BOX_VERT = chr(0x2502) # '│' +BOX_UP_RIGHT = chr(0x2514) # '└' +BOX_DOWN_RIGHT = chr(0x250c) # '┌' +BOX_DOWN_LEFT = chr(0x2510) # '┐' +BOX_UP_LEFT = chr(0x2518) # '┘' +BOX_VERT_RIGHT = chr(0x251c) # '├' +BOX_HORIZ_DOWN = chr(0x252c) # '┬' + def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited=None, lastChild=False, singleLineDraw=False): """ @@ -315,9 +325,9 @@ def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited=None, def MMM(m): if singleLineDraw: - return [" ","│ "][m] + return [" ", BOX_VERT + " "][m] else: - return [" ","| "][m] + return [" ", "| "][m] margins = list(map(MMM, margin[:-1])) @@ -326,29 +336,19 @@ def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited=None, cross = "+-" if singleLineDraw: - # unicode line drawing chars: - box_horiz = chr(0x2500) # '─' - box_vert = chr(0x2510) # '│' - box_up_right = chr(0x2514) # '└' - box_down_right = chr(0x250c) # '┌' - box_down_left = chr(0x2510) # '┐' - box_up_left = chr(0x2518) # '┘' - box_vert_right = chr(0x251c) # '├' - box_horiz_down = chr(0x252c) # '┬' - - cross = box_vert_right + box_horiz # sign used to point to the leaf. + cross = BOX_VERT_RIGHT + BOX_HORIZ # sign used to point to the leaf. # check if this is the last leaf of the branch if lastChild: #if this if the last leaf, then terminate: - cross = box_up_right + box_horiz # sign for the last leaf + cross = BOX_UP_RIGHT + BOX_HORIZ # sign for the last leaf # if this branch has children then split it if children: # if it's a leaf: if prune and rname in visited and children: - cross += box_horiz + cross += BOX_HORIZ else: - cross += box_horiz_down + cross += BOX_HORIZ_DOWN if prune and rname in visited and children: sys.stdout.write(''.join(tags + margins + [cross,'[', rname, ']']) + '\n') -- cgit v0.12 From ad2380bcac6d2d63052147b423544bdcf5fddbd3 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Thu, 26 Mar 2020 12:45:41 -0600 Subject: Improve manpage treatment of Variables and Configure Various cleansup to sections Configure Contexts, Command-Line Construction Variables and SConscript Variables. Stylesheet-level changes place multiple function signature entries each on their own line (affects primarily Configure Contexts). A couple of stylesheet files were checked in in DOS format, changed them to the same as the rest of the codebase (this shows lots of spurious diff). Discovered a few minor tweaks to make to code implementing the above, so this is not completely doc-only. Signed-off-by: Mats Wichmann --- doc/man/epub.xsl | 70 ++++----- doc/man/html.xsl | 122 ++++++++------- doc/man/pdf.xsl | 151 +++++++++--------- doc/man/scons.xml | 241 +++++++++++++++++------------ doc/user/chtml.xsl | 122 +++++++-------- doc/user/epub.xsl | 72 ++++----- doc/user/html.xsl | 122 ++++++++------- doc/user/pdf.xsl | 153 +++++++++--------- src/engine/SCons/Script/__init__.py | 4 +- src/engine/SCons/Variables/PathVariable.py | 15 +- src/engine/SCons/Variables/__init__.py | 13 +- 11 files changed, 568 insertions(+), 517 deletions(-) diff --git a/doc/man/epub.xsl b/doc/man/epub.xsl index bc1d4b3..a9851a0 100644 --- a/doc/man/epub.xsl +++ b/doc/man/epub.xsl @@ -1,35 +1,35 @@ - - - - - - - - - + + + + + + + + + diff --git a/doc/man/html.xsl b/doc/man/html.xsl index 714412a..00cc782 100644 --- a/doc/man/html.xsl +++ b/doc/man/html.xsl @@ -1,60 +1,62 @@ - - - - - - - - - - - -/appendix toc,title -article/appendix nop -/article toc,title -book toc,title,figure,table,example,equation -/chapter toc,title -part toc,title -/preface toc,title -reference title -/sect1 toc -/sect2 toc -/sect3 toc -/sect4 toc -/sect5 toc -/section toc -set toc,title - - - - - - - - + + + + + + + + + + + + + +/appendix toc,title +article/appendix nop +/article toc,title +book toc,title,figure,table,example,equation +/chapter toc,title +part toc,title +/preface toc,title +reference title +/sect1 toc +/sect2 toc +/sect3 toc +/sect4 toc +/sect5 toc +/section toc +set toc,title + + + + + + + + diff --git a/doc/man/pdf.xsl b/doc/man/pdf.xsl index c821dde..5804774 100644 --- a/doc/man/pdf.xsl +++ b/doc/man/pdf.xsl @@ -1,75 +1,76 @@ - - - - - - - - - - - -0pt - - - - -/appendix toc,title -article/appendix nop -/article toc,title -book toc,title,figure,table,example,equation -/chapter toc,title -part toc,title -/preface toc,title -reference toc,title -/sect1 toc -/sect2 toc -/sect3 toc -/sect4 toc -/sect5 toc -/section toc -set toc,title - - - - bold - - - - - - - - - - - - - - + + + + + + + + + + + +0pt + + + + + +/appendix toc,title +article/appendix nop +/article toc,title +book toc,title,figure,table,example,equation +/chapter toc,title +part toc,title +/preface toc,title +reference toc,title +/sect1 toc +/sect2 toc +/sect3 toc +/sect4 toc +/sect5 toc +/section toc +set toc,title + + + + bold + + + + + + + + + + + + + + diff --git a/doc/man/scons.xml b/doc/man/scons.xml index 5d71bfd..b9c3161 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -2930,28 +2930,19 @@ include: In addition to the global functions and methods, &scons; -supports a number of Python variables +supports a number of variables that can be used in SConscript files -to affect how you want the build to be performed. -These variables may be accessed from custom Python modules that you -import into an SConscript file by adding the following -to the Python module: - - -from SCons.Script import * - +to affect how you want the build to be performed. ARGLIST -A list +A list of the keyword=value arguments specified on the command line. Each element in the list is a tuple -containing the -(keyword,value) -of the argument. +containing the argument. The separate keyword and @@ -3048,9 +3039,7 @@ if 'special/program' in BUILD_TARGETS: - - COMMAND_LINE_TARGETS @@ -3058,10 +3047,10 @@ if 'special/program' in BUILD_TARGETS: the command line. If there are command line targets, this list will have the same contents as &BUILD_TARGETS;. If there are no targets specified on the command line, -the list is empty. The elemnts of this list are strings. +the list is empty. The elements of this list are strings. This can be used, for example, to take specific actions only -when certain targets is explicitly being built. +when certain targets are explicitly being built. Example: @@ -3084,10 +3073,10 @@ that have been specified using the function or method. If there are no command line targets, this list will have the same contents as &BUILD_TARGETS;. -The elements of the list are nodes, -so you need to run them through the Python +Since the elements of the list are nodes, +you need to call the Python str -function to get at the path name for each Node. +function on them to get the path name for each Node. Example: @@ -3126,6 +3115,15 @@ default target before it's actually been added to the list. + +These variables may be accessed from custom Python modules that you +import into an SConscript file by adding the following +to the Python module: + + +from SCons.Script import * + + @@ -3221,10 +3219,10 @@ env2 = env.Clone(CC="cl.exe") supports configure contexts, an integrated mechanism similar to the -various AC_CHECK macros in GNU autoconf +various AC_CHECK macros in GNU &Autoconf; for testing for the existence of C header files, libraries, etc. -In contrast to autoconf, +In contrast to &Autoconf;, &scons; does not maintain an explicit cache of the tested values, but uses its normal dependency tracking to keep the checked values @@ -3252,37 +3250,38 @@ specifies a directory where the test cases are built. Note that this directory is not used for building normal targets. The default value is the directory -#/.sconf_temp. +#/.sconf_temp. log_file specifies a file which collects the output from commands that are executed to check for the existence of header files, libraries, etc. -The default is the file #/config.log. +The default is the file #/config.log. If you are using the -VariantDir() -method, +&VariantDir; function, you may want to specify a subdirectory under your variant directory. config_h specifies a C header file where the results of tests -will be written, e.g. #define HAVE_STDIO_H, #define HAVE_LIBM, etc. +will be written, e.g. +#define HAVE_STDIO_H, +#define HAVE_LIBM, etc. The default is to not write a -config.h +config.h file. You can specify the same -config.h -file in multiple calls to Configure, +config.h +file in multiple calls to &Configure;, in which case &SCons; will concatenate all results in the specified file. Note that &SCons; uses its normal dependency checking to decide if it's necessary to rebuild the specified -config_h +config_h file. This means that the file is not necessarily re-built each time scons is run, but is only rebuilt if its contents will have changed and some target that depends on the -config_h +config_h file is being built. The optional @@ -3291,9 +3290,9 @@ and help arguments can be used to suppress execution of the configuration tests when the - +/ or - +// options are used, respectively. The default behavior is always to execute configure context tests, @@ -3329,7 +3328,7 @@ with this configuration context. However, you can create a new Configure context to perform additional checks. -Only one context should be active at a time. +Only one context may be active at a time. The following Checks are predefined. (This list will likely grow larger as time @@ -3943,8 +3942,7 @@ For example, libraries needed for the build may be in non-standard locations, or site-specific compiler options may need to be passed to the compiler. &scons; -provides a -Variables +provides a &Variables; object to support overriding &consvars; on the command line: @@ -3952,23 +3950,31 @@ on the command line: scons VARIABLE=foo -The variable values can also be specified in a text-based SConscript file. -To create a Variables object, call the Variables() function: +The variable values can also be specified in an SConscript file. +To obtain the object for manipulating values, +call the &Variables; function: - Variables([files], [args]) + Variables([files[, args]]) -This creates a Variables object that will read &consvars; from -the file or list of filenames specified in -files. +If files is a file or +list of files, those are executed as Python scripts, +and the values of (global) Python variables set in +those files are added as &consvars; in the +default &consenv;. If no files are specified, or the files argument is None, -then no files will be read. -The optional argument +then no files will be read. Example file content: + + +CC = 'my_cc' + + +The optional argument args is a dictionary of values that will override anything read from the specified files; @@ -3984,10 +3990,13 @@ vars = Variables('overrides.py', ARGUMENTS) vars = Variables(None, {FOO:'expansion', BAR:7}) -Variables objects have the following methods: - + + +Variables objects have the following methods: + + Add(key, [help, default, validator, converter]) @@ -4024,7 +4033,7 @@ and then added to the environment. Examples: -vars.Add('CC', 'The C compiler') +vars.Add('CC', help='The C compiler') def validate_color(key, val, env): if not val in ['red', 'blue', 'yellow']: @@ -4035,7 +4044,7 @@ vars.Add('COLOR', validator=valid_color) - AddVariables(list) + vars.AddVariables(list) A wrapper script that adds multiple customizable &consvars; @@ -4060,7 +4069,7 @@ opt.AddVariables( - Update(env, [args]) + vars.Update(env, [args]) This updates a &consenv; env @@ -4083,23 +4092,9 @@ env = Environment(variables=vars) - - -The text file(s) that were specified -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 &consenv;. - -Example: - -CC = 'my_cc' - - - - UnknownVariables() + vars.UnknownVariables() Returns a dictionary containing any variables that were specified @@ -4118,7 +4113,7 @@ for key, value in vars.UnknownVariables(): - Save(filename, env) + vars.Save(filename, env) This saves the currently set variables into a script file named filename @@ -4138,7 +4133,7 @@ vars.Save('variables.cache', env) - GenerateHelpText(env, [sort]) + vars.GenerateHelpText(env, [sort]) This generates help text documenting the customizable construction variables suitable to passing in to the Help() function. @@ -4196,15 +4191,18 @@ def my_format(env, opt, help, default, actual): return fmt % (opt, default. actual, help) vars.FormatVariableHelpText = my_format + + + + To make it more convenient to work with customizable Variables, &scons; provides a number of functions that make it easy to set up various types of Variables: - - + BoolVariable(key, help, default) @@ -4390,27 +4388,54 @@ that will be called to verify that the specified path is acceptable. SCons supplies the -following ready-made validators: -PathVariable.PathExists -(the default), -which verifies that the specified path exists; -PathVariable.PathIsFile, -which verifies that the specified path is an existing file; -PathVariable.PathIsDir, -which verifies that the specified path is an existing directory; -PathVariable.PathIsDirCreate, -which verifies that the specified path is a directory -and will create the specified directory if the path does not exist; -and -PathVariable.PathAccept, -which simply accepts the specific path name argument without validation, -and which is suitable if you want your users +following ready-made validators: + + + + PathVariable.PathExists + +Verify that the specified path exists (the default). + + + + + PathVariable.PathIsFile + +Verify that the specified path is an existing file. + + + + + PathVariable.PathIsDir + +Verify that the specified path is an existing directory. + + + + + PathVariable.PathIsDirCreate + +Verify that the specified path is a directory +and will create the specified directory if the path does not exist. + + + + + PathVariable.PathAccept + +Simply accept the specific path name argument without validation, +suitable for when you want your users to be able to specify a directory path that will be -created as part of the build process, for example. +created as part of the build process, for example. + + + + + You may supply your own validator function, -which must take three arguments +which must accept three arguments (key, the name of the variable to be set; val, @@ -4426,28 +4451,44 @@ if the specified value is not acceptable. These functions make it convenient to create a number of variables with consistent behavior -in a single call to the -AddVariables +in a single call to the &AddVariables; method: vars.AddVariables( - BoolVariable("warnings", "compilation with -Wall and similar", 1), + BoolVariable( + "warnings", + help="compilation with -Wall and similar", + default=1, + ), EnumVariable( "debug", - "debug output and symbols", - "no", + help="debug output and symbols", + default="no", allowed_values=("yes", "no", "full"), map={}, ignorecase=0, # case sensitive ), ListVariable( - "shared", "libraries to build as shared libraries", "all", names=list_of_libs + "shared", + help="libraries to build as shared libraries", + default="all", + names=list_of_libs, ), - PackageVariable("x11", "use X11 installed here (yes = search some places)", "yes"), - PathVariable("qtdir", "where the root of Qt is installed", qtdir), + PackageVariable( + "x11", + help="use X11 installed here (yes = search some places)", + default="yes", + ), + PathVariable( + "qtdir", + help="where the root of Qt is installed", + default=qtdir), PathVariable( - "foopath", "where the foo library is installed", foopath, PathVariable.PathIsDir + "foopath", + help="where the foo library is installed", + default=foopath, + validator=PathVariable.PathIsDir, ), ) @@ -4569,7 +4610,7 @@ directory as the one the Node represents: - d.Dir(name) + f.Dir(name) Returns a directory named name @@ -4579,7 +4620,7 @@ within the parent directory of - d.File(name) + f.File(name) Returns a file named name @@ -4589,7 +4630,7 @@ within the parent directory of - d.Entry(name) + f.Entry(name) Returns an unresolved Node named name @@ -5324,7 +5365,7 @@ Action([['cc', '-c', '-DWHITE SPACE', '-o', '$TARGET', '$SOURCES']]) If the first argument is a Python function, a function Action is returned. -The Python function must take three keyword arguments, +The Python function must accept three keyword arguments, target (a Node object representing the target file), source @@ -5387,7 +5428,7 @@ The function may also be specified by the strfunction= keyword argument. Like a function to build a file, -this function must take three keyword arguments: +this function must accept three keyword arguments: target (a Node object representing the target file), source diff --git a/doc/user/chtml.xsl b/doc/user/chtml.xsl index e855c31..06b3285 100644 --- a/doc/user/chtml.xsl +++ b/doc/user/chtml.xsl @@ -1,61 +1,61 @@ - - - - - - - - - - - - -/appendix toc,title -article/appendix nop -/article toc,title -book toc,title,figure,table,example,equation -/chapter toc,title -part toc,title -/preface toc,title -reference toc,title -/sect1 toc -/sect2 toc -/sect3 toc -/sect4 toc -/sect5 toc -/section toc -set toc,title - - - - - - - - + + + + + + + + + + + + +/appendix toc,title +article/appendix nop +/article toc,title +book toc,title,figure,table,example,equation +/chapter toc,title +part toc,title +/preface toc,title +reference toc,title +/sect1 toc +/sect2 toc +/sect3 toc +/sect4 toc +/sect5 toc +/section toc +set toc,title + + + + + + + + diff --git a/doc/user/epub.xsl b/doc/user/epub.xsl index 6ff435c..6a33a63 100644 --- a/doc/user/epub.xsl +++ b/doc/user/epub.xsl @@ -1,36 +1,36 @@ - - - - - - - - - - + + + + + + + + + + diff --git a/doc/user/html.xsl b/doc/user/html.xsl index 17dc189..0c215cf 100644 --- a/doc/user/html.xsl +++ b/doc/user/html.xsl @@ -1,60 +1,62 @@ - - - - - - - - - - - -/appendix toc,title -article/appendix nop -/article toc,title -book toc,title,figure,table,example,equation -/chapter toc,title -part toc,title -/preface toc,title -reference toc,title -/sect1 toc -/sect2 toc -/sect3 toc -/sect4 toc -/sect5 toc -/section toc -set toc,title - - - - - - - - + + + + + + + + + + + + + +/appendix toc,title +article/appendix nop +/article toc,title +book toc,title,figure,table,example,equation +/chapter toc,title +part toc,title +/preface toc,title +reference toc,title +/sect1 toc +/sect2 toc +/sect3 toc +/sect4 toc +/sect5 toc +/section toc +set toc,title + + + + + + + + diff --git a/doc/user/pdf.xsl b/doc/user/pdf.xsl index 2c0d086..c869664 100644 --- a/doc/user/pdf.xsl +++ b/doc/user/pdf.xsl @@ -1,76 +1,77 @@ - - - - - - - - - - - -0pt - - - - -/appendix toc,title -article/appendix nop -/article toc,title -book toc,title,figure,table,example,equation -/chapter toc,title -part toc,title -/preface toc,title -reference toc,title -/sect1 toc -/sect2 toc -/sect3 toc -/sect4 toc -/sect5 toc -/section toc -set toc,title - - - - bold - - - - - - - - - - - - - - - + + + + + + + + + + + +0pt + + + + + +/appendix toc,title +article/appendix nop +/article toc,title +book toc,title,figure,table,example,equation +/chapter toc,title +part toc,title +/preface toc,title +reference toc,title +/sect1 toc +/sect2 toc +/sect3 toc +/sect4 toc +/sect5 toc +/section toc +set toc,title + + + + bold + + + + + + + + + + + + + + + diff --git a/src/engine/SCons/Script/__init__.py b/src/engine/SCons/Script/__init__.py index 8f526be..0a672fc 100644 --- a/src/engine/SCons/Script/__init__.py +++ b/src/engine/SCons/Script/__init__.py @@ -288,8 +288,8 @@ def set_missing_sconscript_error(flag=1): _no_missing_sconscript = flag return old -# -def Variables(files=[], args=ARGUMENTS): + +def Variables(files=None, args=ARGUMENTS): return SCons.Variables.Variables(files, args) diff --git a/src/engine/SCons/Variables/PathVariable.py b/src/engine/SCons/Variables/PathVariable.py index 0ffcbc5..eb9b299 100644 --- a/src/engine/SCons/Variables/PathVariable.py +++ b/src/engine/SCons/Variables/PathVariable.py @@ -78,11 +78,13 @@ import SCons.Errors class _PathVariableClass(object): - def PathAccept(self, key, val, env): + @staticmethod + def PathAccept(key, val, env): """Accepts any path, no checking done.""" pass - def PathIsDir(self, key, val, env): + @staticmethod + def PathIsDir(key, val, env): """Validator to check if Path is a directory.""" if not os.path.isdir(val): if os.path.isfile(val): @@ -91,7 +93,8 @@ class _PathVariableClass(object): m = 'Directory path for option %s does not exist: %s' raise SCons.Errors.UserError(m % (key, val)) - def PathIsDirCreate(self, key, val, env): + @staticmethod + def PathIsDirCreate(key, val, env): """Validator to check if Path is a directory, creating it if it does not exist.""" if os.path.isfile(val): @@ -100,7 +103,8 @@ class _PathVariableClass(object): if not os.path.isdir(val): os.makedirs(val) - def PathIsFile(self, key, val, env): + @staticmethod + def PathIsFile(key, val, env): """Validator to check if Path is a file""" if not os.path.isfile(val): if os.path.isdir(val): @@ -109,7 +113,8 @@ class _PathVariableClass(object): m = 'File path for option %s does not exist: %s' raise SCons.Errors.UserError(m % (key, val)) - def PathExists(self, key, val, env): + @staticmethod + def PathExists(key, val, env): """Validator to check if Path exists""" if not os.path.exists(val): m = 'Path for option %s does not exist: %s' diff --git a/src/engine/SCons/Variables/__init__.py b/src/engine/SCons/Variables/__init__.py index 4ff11d0..7bd4cd9 100644 --- a/src/engine/SCons/Variables/__init__.py +++ b/src/engine/SCons/Variables/__init__.py @@ -45,21 +45,20 @@ from .PathVariable import PathVariable # okay class Variables(object): - instance=None - """ Holds all the options, updates the environment with the variables, and renders the help text. """ + instance=None + def __init__(self, files=None, args=None, is_global=1): """ files - [optional] List of option configuration files to load (backward compatibility) If a single string is passed it is - automatically placed in a file list + automatically placed in a file list + args - dictionary to override values set from files. """ - # initialize arguments - if files is None: - files = [] + if args is None: args = {} self.options = [] @@ -74,7 +73,7 @@ class Variables(object): # create the singleton instance if is_global: - self=Variables.instance + self = Variables.instance if not Variables.instance: Variables.instance=self -- cgit v0.12 From 70995a263bcb9c6eace841814ca6d8306db73b65 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 27 Mar 2020 12:49:23 -0600 Subject: Further wordsmithing on configure contexts [ci skip] Address review comment (PR #3593) and clean up some markup issues and ordering. Signed-off-by: Mats Wichmann --- doc/man/scons.xml | 173 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 91 insertions(+), 82 deletions(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index b9c3161..c85ddff 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -3216,8 +3216,8 @@ env2 = env.Clone(CC="cl.exe") Configure Contexts &scons; -supports -configure contexts, +supports a +configure context, an integrated mechanism similar to the various AC_CHECK macros in GNU &Autoconf; for testing for the existence of C header @@ -3230,27 +3230,35 @@ up to date. However, users may override this behaviour with the command line option. -The following methods can be used to perform checks: +To create a configure context: Configure(env, [custom_tests, conf_dir, log_file, config_h, clean, help]) - env.Configure([custom_tests, conf_dir, log_file, config_h, clean, help]) - -This creates a configure context, which can be used to perform checks. -env + env.Configure([custom_tests, conf_dir, log_file, config_h, clean, help]) + +Create a configure context, which tracks information +discovered while running tests. The context includes a +&consenv;, which is used when running the tests and +which is updated with the check results. +When the context is complete, the (possibly modified) +environment is returned). Only one context may be active +at a time (since 4.0, &scons; will raise an exception +if this rule is not followed), but a new context can be created +after the active one is completed. + +The required env argument specifies the environment for building the tests. -This environment may be modified when performing checks. custom_tests -is a dictionary containing custom tests. -See also the section about custom tests below. +is a dictionary containing custom tests +(see the section on custom tests below). By default, no custom tests are added to the configure context. conf_dir specifies a directory where the test cases are built. Note that this directory is not used for building normal targets. The default value is the directory -#/.sconf_temp. +#/.sconf_temp. log_file specifies a file which collects the output from commands that are executed to check for the existence of header files, libraries, etc. @@ -3309,36 +3317,48 @@ arguments to avoid unnecessary test execution. - - -A created -Configure -instance has the following associated methods: - SConf.Finish(context) - sconf.Finish() - -This method should be called after configuration is done. -It returns the environment as modified -by the configuration checks performed. + context.Finish() + +This method must be called after configuration is done. +Though required, this is not enforced except +if &Configure; is called when there still an active context, +in which case an exception is raised. +&Finish; returns the environment as modified +during the course of running the configuration checks. After this method is called, no further checks can be performed with this configuration context. However, you can create a new -Configure -context to perform additional checks. -Only one context may be active at a time. - -The following Checks are predefined. -(This list will likely grow larger as time -goes by and developers contribute new useful tests.) +configure context to perform additional checks. + + + +Example of a typical Configure usage: + +env = Environment() +conf = Configure(env) +if not conf.CheckCHeader("math.h"): + print("We really need math.h!") + Exit(1) +if conf.CheckLibWithHeader("qt", "qapp.h", "c++", "QApplication qapp(0,0);"): + # do stuff for qt - usage, e.g. + conf.env.Append(CPPFLAGS="-DWITH_QT") +env = conf.Finish() + + +A configure context +has the following predefined methods which +can be used to perform checks: + + SConf.CheckHeader(context, header, [include_quotes, language]) - sconf.CheckHeader(header, [include_quotes, language]) + context.CheckHeader(header, [include_quotes, language]) Checks if header @@ -3349,7 +3369,7 @@ in which case the last item in the list is the header file to be checked, and the previous list items are header files whose -#include +#include lines should precede the header line being checked for. The optional argument @@ -3371,10 +3391,10 @@ Returns 1 on success and 0 on failure. SConf.CheckCHeader(context, header, [include_quotes]) - sconf.CheckCHeader(header, [include_quotes]) + context.CheckCHeader(header, [include_quotes]) This is a wrapper around -SConf.CheckHeader +SConf.CheckHeader which checks if header is usable in the C language. @@ -3384,7 +3404,7 @@ in which case the last item in the list is the header file to be checked, and the previous list items are header files whose -#include +#include lines should precede the header line being checked for. The optional argument @@ -3399,10 +3419,10 @@ Returns 1 on success and 0 on failure. SConf.CheckCXXHeader(context, header, [include_quotes]) - sconf.CheckCXXHeader(header, [include_quotes]) + context.CheckCXXHeader(header, [include_quotes]) This is a wrapper around -SConf.CheckHeader +SConf.CheckHeader which checks if header is usable in the C++ language. @@ -3412,7 +3432,7 @@ in which case the last item in the list is the header file to be checked, and the previous list items are header files whose -#include +#include lines should precede the header line being checked for. The optional argument @@ -3427,7 +3447,7 @@ Returns 1 on success and 0 on failure. SConf.CheckFunc(context,, function_name, [header, language]) - sconf.CheckFunc(function_name, [header, language]) + context.CheckFunc(function_name, [header, language]) Checks if the specified C or C++ function is available. @@ -3463,7 +3483,7 @@ the default is "C". SConf.CheckLib(context, [library, symbol, header, language, autoadd=1]) - sconf.CheckLib([library, symbol, header, language, autoadd=1]) + context.CheckLib([library, symbol, header, language, autoadd=1]) Checks if library @@ -3488,7 +3508,7 @@ If is not set or is None, then -SConf.CheckLib() +SConf.CheckLib() just checks if you can link against the specified library. @@ -3509,11 +3529,11 @@ This method returns 1 on success and 0 on error. SConf.CheckLibWithHeader(context, library, header, language, [call, autoadd]) - sconf.CheckLibWithHeader(library, header, language, [call, autoadd]) + context.CheckLibWithHeader(library, header, language, [call, autoadd]) In contrast to the -SConf.CheckLib +SConf.CheckLib call, this call provides a more sophisticated way to check against libraries. Again, library @@ -3526,7 +3546,7 @@ in which case the last item in the list is the header file to be checked, and the previous list items are header files whose -#include +#include lines should precede the header line being checked for. language @@ -3547,7 +3567,7 @@ succeeds). This method returns 1 on success and 0 on error. SConf.CheckType(context, type_name, [includes, language]) - sconf.CheckType(type_name, [includes, language]) + context.CheckType(type_name, [includes, language]) Checks for the existence of a type defined by typedef. @@ -3555,7 +3575,7 @@ succeeds). This method returns 1 on success and 0 on error. specifies the typedef name to check for. includes is a string containing one or more -#include +#include lines that will be inserted into the program that will be run to test for the existence of the type. The optional @@ -3576,7 +3596,8 @@ sconf.CheckType('foo_type', '#include "my_types.h"', 'C++') - Configure.CheckCC(self) + SConf.CheckCC(self) + context.CheckCC(self) Checks whether the C compiler (as defined by the CC &consvar;) works by trying to compile a small source file. @@ -3591,7 +3612,8 @@ not. - Configure.CheckCXX(self) + SConf.CheckCXX(self) + context.CheckCXX(self) Checks whether the C++ compiler (as defined by the CXX &consvar;) works by trying to compile a small source file. By default, SCons only detects @@ -3604,7 +3626,8 @@ works or not. - Configure.CheckSHCC(self) + SConf.CheckSHCC(self) + context.CheckSHCC(self) Checks whether the C compiler (as defined by the SHCC &consvar;) works by trying to compile a small source file. By default, SCons only detects if @@ -3618,7 +3641,8 @@ library, only that the compilation (not link) succeeds. - Configure.CheckSHCXX(self) + SConf.CheckSHCXX(self) + context.CheckSHCXX(self) Checks whether the C++ compiler (as defined by the SHCXX &consvar;) works by trying to compile a small source file. By default, SCons only detects @@ -3630,26 +3654,10 @@ works or not. This does not check whether the object code can be used to build a shared library, only that the compilation (not link) succeeds. - -Example of a typical Configure usage: - - -env = Environment() -conf = Configure( env ) -if not conf.CheckCHeader( 'math.h' ): - print('We really need math.h!') - Exit(1) -if conf.CheckLibWithHeader( 'qt', 'qapp.h', 'c++', - 'QApplication qapp(0,0);' ): - # do stuff for qt - usage, e.g. - conf.env.Append( CPPFLAGS = '-DWITH_QT' ) -env = conf.Finish() - - SConf.CheckTypeSize(context, type_name, [header, language, expect]) - sconf.CheckTypeSize(type_name, [header, language, expect]) + context.CheckTypeSize(type_name, [header, language, expect]) Checks for the size of a type defined by typedef. @@ -3681,7 +3689,7 @@ given in type_name has the expected size (in bytes). For example, -CheckTypeSize('short', expect = 2) +CheckTypeSize('short', expect=2) will return success only if short is two bytes. @@ -3690,7 +3698,7 @@ CheckTypeSize('short', expect = 2) SConf.CheckDeclaration(context, symbol, [includes, language]) - sconf.CheckDeclaration(symbol, [includes, language]) + context.CheckDeclaration(symbol, [includes, language]) Checks if the specified symbol @@ -3713,7 +3721,7 @@ the default is "C". SConf.Define(context, symbol, [value, comment]) - sconf.Define(symbol, [value, comment]) + context.Define(symbol, [value, comment]) This function does not check for anything, but defines a preprocessor symbol that will be added to the configuration header file. @@ -3724,23 +3732,20 @@ with the optional value and the optional comment comment. - - - -Examples: +Define Examples: env = Environment() -conf = Configure( env ) +conf = Configure(env) # Puts the following line in the config header file: # #define A_SYMBOL -conf.Define('A_SYMBOL') +conf.Define("A_SYMBOL") # Puts the following line in the config header file: # #define A_SYMBOL 1 -conf.Define('A_SYMBOL', 1) +conf.Define("A_SYMBOL", 1) @@ -3748,15 +3753,15 @@ conf.Define('A_SYMBOL', 1) env = Environment() -conf = Configure( env ) +conf = Configure(env) # Puts the following line in the config header file: # #define A_SYMBOL YA -conf.Define('A_SYMBOL', "YA") +conf.Define("A_SYMBOL", "YA") # Puts the following line in the config header file: # #define A_SYMBOL "YA" -conf.Define('A_SYMBOL', '"YA"') +conf.Define("A_SYMBOL", '"YA"') @@ -3764,14 +3769,18 @@ conf.Define('A_SYMBOL', '"YA"') env = Environment() -conf = Configure( env ) +conf = Configure(env) # Puts the following lines in the config header file: # /* Set to 1 if you have a symbol */ # #define A_SYMBOL 1 -conf.Define('A_SYMBOL', 1, 'Set to 1 if you have a symbol') +conf.Define("A_SYMBOL", 1, "Set to 1 if you have a symbol") + + + + You can define your own custom checks. in addition to the predefined checks. These are passed in a dictionary to the Configure function. @@ -3798,7 +3807,7 @@ will be displayed to the user, e.g. 'Checking for library X...' - CheckContext.Result(self,, res) + CheckContext.Result(self, res) Usually called after the check is done. -- cgit v0.12 From d0441780eeb32171e60eb50cb9ce452a82b4e067 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sun, 29 Mar 2020 13:04:22 -0600 Subject: Generate groff-style manpages with Py3 [ci skip] groff-style (aka scons.1) manpages generated empty when using lxml for generation - that is, under Python 3. Fixes #3584 Signed-off-by: Mats Wichmann --- src/CHANGES.txt | 2 ++ src/engine/SCons/Tool/docbook/__init__.py | 9 +++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index f4416b2..de5c9d4 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -89,6 +89,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Fixed bug where changing TEXTFILESUFFIX would cause Substfile() to rebuild. (Github Issue #3540) - Script/Main.py now uses importlib instead of imp module. - Drop some Python 2-isms. + - Docbook builder provides a fallback if lxml fails to generate + a document with tostring(). RELEASE 3.1.2 - Mon, 17 Dec 2019 02:06:27 +0000 diff --git a/src/engine/SCons/Tool/docbook/__init__.py b/src/engine/SCons/Tool/docbook/__init__.py index c4fdfba..7f47e9d 100644 --- a/src/engine/SCons/Tool/docbook/__init__.py +++ b/src/engine/SCons/Tool/docbook/__init__.py @@ -351,11 +351,16 @@ def __build_lxml(target, source, env): else: result = transform(doc) + # we'd like the resulting output to be readably formatted, + # so try pretty-print. Sometimes (esp. if the output is + # not an xml file) we end up with a None type somewhere in + # the transformed tree and tostring throws TypeError, + # so provide a fallback. try: with open(str(target[0]), "wb") as of: of.write(etree.tostring(result, pretty_print=True)) - except: - pass + except TypeError: + result.write_output(str(target[0])) return None -- cgit v0.12 From b6f857da62204fac68519a8f06f3d7adaf0d7847 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sun, 29 Mar 2020 13:12:14 -0600 Subject: Update doc intro section; mention pywin32 [ci skip] Slight wording change to program locations. Move requirements paragraph to last in section, and mention pywin32 is recommended on Windows. Signed-off-by: Mats Wichmann --- doc/man/scons.xml | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index c85ddff..3ebba80 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -214,9 +214,9 @@ 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 &scons; -PATH in the internal environment -to include those locations. +you explicitly include the locations into the value of +PATH in the ENV +variable in the internal &consenv;. Whenever you create a &consenv;, you can propagate the value of PATH from your external environment as follows: @@ -436,11 +436,6 @@ command-line options. The option is useful to prevent multiple builds from trying to update the cache simultaneously. -&scons; -requires Python 3.5 or higher. -There should be no other dependencies or requirements to run &scons;. - - @@ -479,6 +474,13 @@ and the Intel compiler tools. These default values may be overridden by appropriate setting of &consvars;. +&scons; +requires Python 3.5 or higher. +There should be no other dependencies or requirements to run &scons;, +although the pywin32 Python package is +strongly recommended if running on Windows systems. + +
-- cgit v0.12 From 8b1b31d6f1121cee65ba59868eec0fdd38ea7381 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sun, 29 Mar 2020 13:52:15 -0600 Subject: manpage: new markup on Scanner Objects [ci skip] Apply improved markup and add some links for Scanner Objects Signed-off-by: Mats Wichmann --- doc/man/scons.xml | 86 +++++++++++++++++++++++++++---------------------------- 1 file changed, 42 insertions(+), 44 deletions(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index c85ddff..08c6fc7 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -277,7 +277,7 @@ When &scons; is invoked, the command line (including the contents of the &SCONSFLAGS; environment variable, if set) is processed. -Command-line options (see ) are consumed. +Command-line options (see ) are consumed. Any variable argument assignments are collected, and remaining arguments are taken as the targets to build. @@ -2817,8 +2817,8 @@ Builders by adding them to the SourceFileScanner object. -See the section "Scanner Objects" -below, for more information about +See +for more information about defining your own Scanner objects and using the SourceFileScanner @@ -4861,8 +4861,8 @@ based only on the target file and the &consenv;, not for implicit dependencies based on source files. -(See the section "Scanner Objects" below, -for information about creating Scanner objects.) +See +for information about creating Scanner objects. @@ -4888,8 +4888,8 @@ for on-disk changes to files that &scons; does not know about from other Builder or function calls. -(See the section "Scanner Objects" below, -for information about creating your own Scanner objects.) +See +for information about creating your own Scanner objects. @@ -6409,17 +6409,16 @@ a future version of SCons. Scanner Objects You can use the -Scanner +&f-link-Scanner; function to define objects to scan new file types for implicit dependencies. -The -Scanner +The &f-Scanner; function accepts the following arguments: - function + function This can be either: @@ -6438,21 +6437,20 @@ to other Scanners that should be called. -If the argument is actually a Python function, -the function must take three or four arguments: - - def scanner_function(node, env, path): - - def scanner_function(node, env, path, arg=None): +If the argument is a Python function, +the function must accept three required arguments +and an optional fourth: +def scanner_function(node, env, path, arg=None): + The -node +node argument is the internal &SCons; node representing the file. Use -str(node) +str(node) to fetch the name of the file, and -node.get_contents() +node.get_contents() to fetch contents of the file. Note that the file is not @@ -6463,31 +6461,31 @@ might not exist (for example, if it's built from other files). The -env +env argument is the &consenv; for the scan. Fetch values from it using the -env.Dictionary() -method or using the key lookup operator +&f-env-Dictionary; +method or using dictionary key lookup directly on the &consenv;. The -path +path argument is a tuple (or list) of directories that can be searched for files. This will usually be the tuple returned by the -path_function +path_function argument (see below). The -arg +arg argument is the argument supplied when the scanner was created, if any. - name + name The name of the Scanner. This is mainly used @@ -6496,7 +6494,7 @@ to identify the Scanner internally. - argument + argument An optional argument that, if specified, will be passed to the scanner function @@ -6507,7 +6505,7 @@ and the path function - skeys + skeys An optional list that can be used to determine which scanner should be used for @@ -6523,7 +6521,7 @@ into a list by the current environment. - path_function + path_function A Python function that takes four or five arguments: a &consenv;, @@ -6535,35 +6533,35 @@ a list of source nodes, and an optional argument supplied when the scanner was created. The -path_function +path_function returns a tuple of directories that can be searched for files to be returned by this Scanner object. (Note that the -FindPathDirs() +&f-link-FindPathDirs; function can be used to return a ready-made -path_function +path_function for a given &consvar; name, instead of having to write your own function from scratch.) - node_class + node_class The class of Node that should be returned by this Scanner object. Any strings or other objects returned by the scanner function that are not of this class -will be run through the -node_factory -function. +will be run through the function +supplied by the +node_factory argument. - node_factory + node_factory A Python function that will take a string or other object @@ -6573,7 +6571,7 @@ to be returned by this Scanner object. - scan_check + scan_check An optional Python function that takes two arguments, a Node (file) and a &consenv;, @@ -6588,7 +6586,7 @@ represented by a Node does not yet exist. - recursive + recursive An optional flag that specifies whether this scanner should be re-invoked @@ -6597,7 +6595,7 @@ When this flag is not set, the Node subsystem will only invoke the scanner on the file being scanned, and not (for example) also on the files -specified by the #include lines +specified by the #include lines in the file being scanned. recursive may be a callable function, @@ -6613,14 +6611,14 @@ Nodes for additional scanning. Note that &scons; has a global -SourceFileScanner +SourceFileScanner object that is used by -the &Object;, &SharedObject; and &StaticObject; +the &b-link-Object;, &b-link-SharedObject; and &b-link-StaticObject; builders to decide which scanner should be used for different file extensions. You can use the -SourceFileScanner.add_scanner() +SourceFileScanner.add_scanner() method to add your own Scanner object to the &SCons; -- cgit v0.12 From 8053e4f154a8bbe1df85a431251a0636a45a4f5d Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Tue, 31 Mar 2020 09:10:54 -0600 Subject: Fix generated tools doc intermediate file. [ci skip] The process to generate tools.gen writes entities for links to construction variables used/set by each tool. When this data is written out using lxml's tostring() method, this is encoded, causing &foo; to become &foo; which then doesn't work in later processing as these files are included, as they're no longer valid entity references for substitution. This seems really hard to fix directly, because tostring() is working as documented by doing this, so for now - maybe forever in light of thoughts of converting docs to a different format - just postprocess the file to undo the damage. A hack, but fixes #3580 Signed-off-by: Mats Wichmann --- bin/docs-update-generated.py | 22 +++++++++++++++------- bin/scons-proc.py | 6 ++++++ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/bin/docs-update-generated.py b/bin/docs-update-generated.py index 52ebb0a..98c923d 100644 --- a/bin/docs-update-generated.py +++ b/bin/docs-update-generated.py @@ -43,13 +43,21 @@ def generate_all(): print("Couldn't create destination folder %s! Exiting..." % gen_folder) return # Call scons-proc.py - _ = subprocess.call([sys.executable, - os.path.join('bin','scons-proc.py'), - '-b', argpair('builders'), - '-f', argpair('functions'), - '-t', argpair('tools'), - '-v', argpair('variables')] + flist, - shell=False) + cp = subprocess.run([sys.executable, + os.path.join('bin','scons-proc.py'), + '-b', argpair('builders'), + '-f', argpair('functions'), + '-t', argpair('tools'), + '-v', argpair('variables')] + flist, + shell=False) + + cp.check_returncode() # bail if it failed + # lxml: fixup possibly broken tools.gen: + with open(os.path.join(gen_folder, 'tools.gen'), 'r') as f : + filedata = f.read() + filedata = filedata.replace(r'&cv-link', r'&cv-link') + with open(os.path.join(gen_folder, 'tools.gen'), 'w') as f : + f.write(filedata) if __name__ == "__main__": diff --git a/bin/scons-proc.py b/bin/scons-proc.py index fb05d32..cab4387 100644 --- a/bin/scons-proc.py +++ b/bin/scons-proc.py @@ -144,12 +144,18 @@ class SCons_XML(object): if v.sets: added = True vp = stf.newNode("para") + # if using lxml, the &entity; entries will be encoded, + # effectively breaking them. should fix, + # for now handled post-process in calling script. s = ['&cv-link-%s;' % x for x in v.sets] stf.setText(vp, 'Sets: ' + ', '.join(s) + '.') stf.appendNode(vl, vp) if v.uses: added = True vp = stf.newNode("para") + # if using lxml, the &entity; entries will be encoded, + # effectively breaking them. should fix, + # for now handled post-process in calling script. u = ['&cv-link-%s;' % x for x in v.uses] stf.setText(vp, 'Uses: ' + ', '.join(u) + '.') stf.appendNode(vl, vp) -- cgit v0.12 From 7a06a452f268c81fd3f509ad46025214ad586d29 Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Thu, 2 Apr 2020 09:58:16 -0400 Subject: Fix inconsistencies between RootDir attributes The RootDir class was returning different values for path and _path as well as different values for abspath and _abspath. This is because the underscored versions were being set in the RootDir constructor, while the non-underscored versions were going through the EntryProxy wrapper, which is only coded to do a simple append of paths. I considered trying to fix EntryProxy to detect this case but instead went with a simpler approach where RootDir overrides the attributes that it wants to avoid EntryProxy calls. Right now I have this as path and abspath. --- src/engine/SCons/Node/FS.py | 8 ++++++- test/Dir/DriveAbsPath.py | 49 ++++++++++++++++++++++++++++++++++++++++ test/Dir/DriveAbsPath/SConstruct | 32 ++++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 test/Dir/DriveAbsPath.py create mode 100644 test/Dir/DriveAbsPath/SConstruct diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index bb965db..b7f6abe 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -2246,7 +2246,7 @@ class RootDir(Dir): this directory. """ - __slots__ = ('_lookupDict', ) + __slots__ = ('_lookupDict', 'abspath', 'path') def __init__(self, drive, fs): if SCons.Debug.track_instances: logInstanceCreation(self, 'Node.FS.RootDir') @@ -2288,6 +2288,12 @@ class RootDir(Dir): self._tpath = dirname self.dirname = dirname + # EntryProxy interferes with this class and turns drive paths on + # Windows such as "C:" into "C:\C:". Avoid this problem by setting + # commonly-accessed attributes directly. + self.abspath = self._abspath + self.path = self._path + self._morph() self.duplicate = 0 diff --git a/test/Dir/DriveAbsPath.py b/test/Dir/DriveAbsPath.py new file mode 100644 index 0000000..90cef2a --- /dev/null +++ b/test/Dir/DriveAbsPath.py @@ -0,0 +1,49 @@ +#!/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__" + +""" +Test to confirm that Dir(drive_path).abspath works on Windows. +""" + +import os +import stat + +import TestSCons +from TestCmd import IS_WINDOWS + + +if IS_WINDOWS: + test = TestSCons.TestSCons() + test.dir_fixture('DriveAbsPath') + test.run() + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Dir/DriveAbsPath/SConstruct b/test/Dir/DriveAbsPath/SConstruct new file mode 100644 index 0000000..af19277 --- /dev/null +++ b/test/Dir/DriveAbsPath/SConstruct @@ -0,0 +1,32 @@ +import os +import SCons + +env = Environment() +drive = os.path.splitdrive(os.getcwd())[0] +drive_dir = env.fs.Dir(drive) + +if not isinstance(drive_dir, SCons.Node.FS.RootDir): + raise Exception('env.fs.Dir("%s") returned a %s instance of a RootDir' % + (drive, type(drive_dir))) + +drive_abspath1 = drive_dir._abspath +drive_abspath2 = drive_dir.abspath +if drive_abspath1 != drive_abspath2: + raise Exception('Calculated _abspath %s is not the same as abspath %s' % + (drive_abspath1, drive_abspath2)) +elif not os.path.exists(drive_abspath1): + raise Exception('Calculated abspath %s does not exist' % drive_abspath1) +elif drive.rstrip(os.path.sep) != drive_abspath1.rstrip(os.path.sep): + raise Exception('Real drive %s and calculated abspath %s are not the ' + 'same' % (drive, drive_abspath1)) + +drive_path1 = drive_dir._path +drive_path2 = drive_dir.path +if drive_path1 != drive_path2: + raise Exception('Calculated _path %s is not the same as path %s' % + (drive_path1, drive_path2)) +elif not os.path.exists(drive_path1): + raise Exception('Calculated path %s does not exist' % drive_path1) +elif drive.rstrip(os.path.sep) != drive_path1.rstrip(os.path.sep): + raise Exception('Real drive %s and calculated abspath %s are not the ' + 'same' % (drive, drive_abs)) -- cgit v0.12 From 80bb32333dfd058da51f24af6267d1f3d1ec110b Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Thu, 2 Apr 2020 10:26:20 -0400 Subject: Update CHANGES.txt --- src/CHANGES.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index de5c9d4..6ec16f3 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -45,6 +45,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - 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. + - Fixed usage of abspath and path for RootDir objects on Windows. Previously + env.fs.Dir("T:").abspath would return "T:\T:" and now it correctly returns "T:". From Iosif Kurazs: - Added a new flag called "linedraw" for the command line argument "--tree" -- cgit v0.12 From f575eba8904b850c211ceaa9538048e454751375 Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Thu, 2 Apr 2020 12:06:40 -0400 Subject: Fix test on non-Windows, fix sider errors --- test/Dir/DriveAbsPath.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/test/Dir/DriveAbsPath.py b/test/Dir/DriveAbsPath.py index 90cef2a..033ac73 100644 --- a/test/Dir/DriveAbsPath.py +++ b/test/Dir/DriveAbsPath.py @@ -28,15 +28,12 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" Test to confirm that Dir(drive_path).abspath works on Windows. """ -import os -import stat - import TestSCons from TestCmd import IS_WINDOWS +test = TestSCons.TestSCons() if IS_WINDOWS: - test = TestSCons.TestSCons() test.dir_fixture('DriveAbsPath') test.run() -- cgit v0.12 From 348f30c118b38a5c5684caeae16bfb3ff4c61cb1 Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Tue, 7 Apr 2020 10:05:47 -0400 Subject: Address review feedback --- test/Dir/DriveAbsPath.py | 11 ++++++++--- test/Dir/DriveAbsPath/SConstruct | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/test/Dir/DriveAbsPath.py b/test/Dir/DriveAbsPath.py index 033ac73..829cef2 100644 --- a/test/Dir/DriveAbsPath.py +++ b/test/Dir/DriveAbsPath.py @@ -25,7 +25,11 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" """ -Test to confirm that Dir(drive_path).abspath works on Windows. +Test to confirm that Dir(drive_path).abspath works on Windows. This verifies +that SCons no longer has an issue with Dir('T:').abspath returning 'T:\T:'. +Instead, it verifies that Dir('T:') correctly returns an instance of the +RootDir class and that class has abspath and path accessors that work +correctly. """ import TestSCons @@ -36,8 +40,9 @@ test = TestSCons.TestSCons() if IS_WINDOWS: test.dir_fixture('DriveAbsPath') test.run() - -test.pass_test() + test.pass_test() +else: + test.skip_test('Skipping Windows-only test.') # Local Variables: # tab-width:4 diff --git a/test/Dir/DriveAbsPath/SConstruct b/test/Dir/DriveAbsPath/SConstruct index af19277..5b63193 100644 --- a/test/Dir/DriveAbsPath/SConstruct +++ b/test/Dir/DriveAbsPath/SConstruct @@ -6,7 +6,7 @@ drive = os.path.splitdrive(os.getcwd())[0] drive_dir = env.fs.Dir(drive) if not isinstance(drive_dir, SCons.Node.FS.RootDir): - raise Exception('env.fs.Dir("%s") returned a %s instance of a RootDir' % + raise Exception('env.fs.Dir("%s") returned a %s instead of a RootDir' % (drive, type(drive_dir))) drive_abspath1 = drive_dir._abspath -- cgit v0.12 From bb46401bfa7fbecdbc7faac11fce10fab985d9fd Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Tue, 7 Apr 2020 09:00:40 -0600 Subject: Manpage example tweaks [ci skip] A set of minor changes to various extra files (i.e. not scons.xml itself). Mainly this reformats some example code when it looked bad in a fixed-width version (pdf or Linux-style manpage). Also: additional wording on default environment (included here because file was being modified anyway), and define an entity for default env. in doc/scons.mod. Commits changes to two generated .mod files to make sure entities list is correct even if even if a full regen of these files (bin/docs-update-generated) is not done. Signed-off-by: Mats Wichmann --- doc/generated/functions.mod | 4 --- doc/generated/tools.mod | 6 +++-- doc/scons.mod | 2 ++ src/engine/SCons/Defaults.xml | 11 ++++---- src/engine/SCons/Environment.xml | 7 ++--- src/engine/SCons/Tool/applelink.xml | 6 ++--- src/engine/SCons/Tool/jar.xml | 2 +- src/engine/SCons/Tool/javac.xml | 2 +- src/engine/SCons/Tool/javah.xml | 17 +++++++------ src/engine/SCons/Tool/msvs.xml | 6 ++++- src/engine/SCons/Tool/packaging/__init__.xml | 38 +++++++++++++++------------- 11 files changed, 54 insertions(+), 47 deletions(-) diff --git a/doc/generated/functions.mod b/doc/generated/functions.mod index 3d49229..47d2be4 100644 --- a/doc/generated/functions.mod +++ b/doc/generated/functions.mod @@ -80,7 +80,6 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. SetDefault"> SetOption"> SideEffect"> -SourceCode"> Split"> subst"> Tag"> @@ -161,7 +160,6 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. env.SetDefault"> env.SetOption"> env.SideEffect"> -env.SourceCode"> env.Split"> env.subst"> env.Tag"> @@ -252,7 +250,6 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. SetDefault"> SetOption"> SideEffect"> -SourceCode"> Split"> subst"> Tag"> @@ -333,7 +330,6 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. env.SetDefault"> env.SetOption"> env.SideEffect"> -env.SourceCode"> env.Split"> env.subst"> env.Tag"> diff --git a/doc/generated/tools.mod b/doc/generated/tools.mod index 1209d74..3f8e22a 100644 --- a/doc/generated/tools.mod +++ b/doc/generated/tools.mod @@ -78,11 +78,12 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. mwcc"> mwld"> nasm"> -Packaging"> packaging"> +Packaging"> pdf"> pdflatex"> pdftex"> +python"> qt"> rmic"> rpcgen"> @@ -186,11 +187,12 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. mwcc"> mwld"> nasm"> -Packaging"> packaging"> +Packaging"> pdf"> pdflatex"> pdftex"> +python"> qt"> rmic"> rpcgen"> diff --git a/doc/scons.mod b/doc/scons.mod index bc63a42..006107e 100644 --- a/doc/scons.mod +++ b/doc/scons.mod @@ -447,6 +447,8 @@ Construction environments"> construction environment"> construction environments"> +Default Environment"> +default environment"> Construction Variable"> Construction Variables"> diff --git a/src/engine/SCons/Defaults.xml b/src/engine/SCons/Defaults.xml index 22f46fe..06fad1c 100644 --- a/src/engine/SCons/Defaults.xml +++ b/src/engine/SCons/Defaults.xml @@ -268,12 +268,8 @@ into a list of Dir instances relative to the target being built. The list of suffixes of files that will be scanned for imported D package files. -The default list is: +The default list is ['.d']. - - -['.d'] -
@@ -584,9 +580,12 @@ in order to execute many of the global functions in this list from source code management systems. The default environment is a singleton, so the keyword arguments affect it only on the first call, on subsequent -calls the already-constructed object is returned. +calls the already-constructed object is returned and +any arguments are ignored. The default environment can be modified in the same way as any &consenv;. +Modifying the &defenv; has no effect on the environment +constructed by a subsequent &f-Environment; call.
diff --git a/src/engine/SCons/Environment.xml b/src/engine/SCons/Environment.xml index a171f38..48980e2 100644 --- a/src/engine/SCons/Environment.xml +++ b/src/engine/SCons/Environment.xml @@ -1836,9 +1836,10 @@ Examples: -Program('foo', Glob('*.c')) -Zip('/tmp/everything', Glob('.??*') + Glob('*')) -sources = Glob('*.cpp', exclude=['os_*_specific_*.cpp']) + Glob('os_%s_specific_*.cpp'%currentOS) +Program("foo", Glob("*.c")) +Zip("/tmp/everything", Glob(".??*") + Glob("*")) +sources = Glob("*.cpp", exclude=["os_*_specific_*.cpp"]) + \ + Glob( "os_%s_specific_*.cpp" % currentOS) diff --git a/src/engine/SCons/Tool/applelink.xml b/src/engine/SCons/Tool/applelink.xml index fc0cf63..977f2ce 100644 --- a/src/engine/SCons/Tool/applelink.xml +++ b/src/engine/SCons/Tool/applelink.xml @@ -171,7 +171,7 @@ See its __doc__ string for a discussion of the format. - env.AppendUnique(FRAMEWORKS=Split('System Cocoa SystemConfiguration')) +env.AppendUnique(FRAMEWORKS=Split('System Cocoa SystemConfiguration')) @@ -213,7 +213,7 @@ See its __doc__ string for a discussion of the format. - env.AppendUnique(FRAMEWORKPATH='#myframeworkdir') +env.AppendUnique(FRAMEWORKPATH='#myframeworkdir') @@ -221,7 +221,7 @@ See its __doc__ string for a discussion of the format. - ... -Fmyframeworkdir +... -Fmyframeworkdir diff --git a/src/engine/SCons/Tool/jar.xml b/src/engine/SCons/Tool/jar.xml index 30c51f8..151dda1 100644 --- a/src/engine/SCons/Tool/jar.xml +++ b/src/engine/SCons/Tool/jar.xml @@ -120,7 +120,7 @@ If this is not set, then &cv-link-JARCOM; (the command line) is displayed. -env = Environment(JARCOMSTR = "JARchiving $SOURCES into $TARGET") +env = Environment(JARCOMSTR="JARchiving $SOURCES into $TARGET") diff --git a/src/engine/SCons/Tool/javac.xml b/src/engine/SCons/Tool/javac.xml index 893130b..b1548c7 100644 --- a/src/engine/SCons/Tool/javac.xml +++ b/src/engine/SCons/Tool/javac.xml @@ -174,7 +174,7 @@ env['ENV']['LANG'] = 'en_GB.UTF-8' -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/javah.xml b/src/engine/SCons/Tool/javah.xml index 4d436b1..5a2840f 100644 --- a/src/engine/SCons/Tool/javah.xml +++ b/src/engine/SCons/Tool/javah.xml @@ -77,17 +77,18 @@ Examples: # builds java_native.h -classes = env.Java(target = 'classdir', source = 'src') -env.JavaH(target = 'java_native.h', source = classes) +classes = env.Java(target="classdir", source="src") +env.JavaH(target="java_native.h", source=classes) # builds include/package_foo.h and include/package_bar.h -env.JavaH(target = 'include', - source = ['package/foo.class', 'package/bar.class']) +env.JavaH(target="include", source=["package/foo.class", "package/bar.class"]) # builds export/foo.h and export/bar.h -env.JavaH(target = 'export', - source = ['classes/foo.class', 'classes/bar.class'], - JAVACLASSDIR = 'classes') +env.JavaH( + target="export", + source=["classes/foo.class", "classes/bar.class"], + JAVACLASSDIR="classes", +) @@ -120,7 +121,7 @@ If this is not set, then &cv-link-JAVAHCOM; (the command line) is displayed. -env = Environment(JAVAHCOMSTR = "Generating header/stub file(s) $TARGETS from $SOURCES") +env = Environment(JAVAHCOMSTR="Generating header/stub file(s) $TARGETS from $SOURCES") diff --git a/src/engine/SCons/Tool/msvs.xml b/src/engine/SCons/Tool/msvs.xml index b1f79b2..f6c9a39 100644 --- a/src/engine/SCons/Tool/msvs.xml +++ b/src/engine/SCons/Tool/msvs.xml @@ -422,7 +422,11 @@ env.MSVSProject(target='Bar' + env['MSVSPROJECTSUFFIX'], Example Usage: -env.MSVSSolution(target='Bar' + env['MSVSSOLUTIONSUFFIX'], projects=['bar' + env['MSVSPROJECTSUFFIX']], variant='Release') +env.MSVSSolution( + target="Bar" + env["MSVSSOLUTIONSUFFIX"], + projects=["bar" + env["MSVSPROJECTSUFFIX"]], + variant="Release", +) diff --git a/src/engine/SCons/Tool/packaging/__init__.xml b/src/engine/SCons/Tool/packaging/__init__.xml index 2b3c4fd..37e97ff 100644 --- a/src/engine/SCons/Tool/packaging/__init__.xml +++ b/src/engine/SCons/Tool/packaging/__init__.xml @@ -86,18 +86,19 @@ on a project that has packaging activated. -env = Environment(tools=['default', 'packaging']) -env.Install('/bin/', 'my_program') -env.Package( NAME = 'foo', - VERSION = '1.2.3', - PACKAGEVERSION = 0, - PACKAGETYPE = 'rpm', - LICENSE = 'gpl', - SUMMARY = 'balalalalal', - DESCRIPTION = 'this should be really really long', - X_RPM_GROUP = 'Application/fu', - SOURCE_URL = 'http://foo.org/foo-1.2.3.tar.gz' - ) +env = Environment(tools=["default", "packaging"]) +env.Install("/bin/", "my_program") +env.Package( + NAME="foo", + VERSION="1.2.3", + PACKAGEVERSION=0, + PACKAGETYPE="rpm", + LICENSE="gpl", + SUMMARY="balalalalal", + DESCRIPTION="this should be really really long", + X_RPM_GROUP="Application/fu", + SOURCE_URL="http://foo.org/foo-1.2.3.tar.gz", +) @@ -503,13 +504,14 @@ Added in version 3.1. env.Package( - NAME = 'foo', -... - X_RPM_EXTRADEFS = [ - '%define _unpackaged_files_terminate_build 0' - '%define _missing_doc_files_terminate_build 0' + NAME="foo", + ... + X_RPM_EXTRADEFS=[ + "%define _unpackaged_files_terminate_build 0" + "%define _missing_doc_files_terminate_build 0" ], -... ) + ... +) -- cgit v0.12 From 433c62479cc022ae7b07cf46a8c772cedae2842f Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Tue, 7 Apr 2020 10:04:24 -0600 Subject: [PR #3576] workaroud "oem" coding not on Py3.5 Use a Windows API to fetch the console output code page if Python < 3.6, where the encoding name "oem" is not yet defined (this was the original proposal in issue #3572) Signed-off-by: Mats Wichmann --- src/engine/SCons/Tool/MSCommon/common.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/engine/SCons/Tool/MSCommon/common.py b/src/engine/SCons/Tool/MSCommon/common.py index b90c25a..b2b5de9 100644 --- a/src/engine/SCons/Tool/MSCommon/common.py +++ b/src/engine/SCons/Tool/MSCommon/common.py @@ -249,14 +249,21 @@ def get_output(vcbat, args=None, env=None): # Ongoing problems getting non-corrupted text led to this # changing to "oem" from "mbcs" - the scripts run presumably # attached to a console, so some particular rules apply. + # Unfortunately, "oem" not defined in Python 3.5, so get another way + if sys.version_info.major == 3 and sys.version_info.minor < 6: + from ctypes import windll + + OEM = "cp{}".format(windll.kernel32.GetConsoleOutputCP()) + else: + OEM = "oem" if stderr: # TODO: find something better to do with stderr; # this at least prevents errors from getting swallowed. - sys.stderr.write(stderr.decode("oem")) + sys.stderr.write(stderr.decode(OEM)) if popen.wait() != 0: - raise IOError(stderr.decode("oem")) + raise IOError(stderr.decode(OEM)) - return stdout.decode("oem") + return stdout.decode(OEM) KEEPLIST = ( -- cgit v0.12 From 12d874591e3879f2cdc26be7cfe8848e9af0d331 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Wed, 8 Apr 2020 13:21:39 -0600 Subject: Add highlighting to funcs/builders [ci skip] When generating documentation from SConsXML markup, add some markup to match the Python doc style better. In pseudo-markup, we will now get: foo(args) env.foo(args) That is, the function name is highlighted, and for the environment method, env looks like a variable (which it is), rather than the literal name env. The methods to create an element now take keyword args, so they can pass them on to the etree.Element method, which understands an attribute keyword we need for one of these changes. Added a method to create a SubElement, which makes usage clearer. To complement the *Text methods, *Tail methods were added to set/get the .tail attribute of a node. This change is to the tools only, and affects the result of doing "python bin/docs-update-generated.py". Signed-off-by: Mats Wichmann --- bin/SConsDoc.py | 42 +++++++++++++++++++++++++-------- bin/scons-proc.py | 69 ++++++++++++++++++++++++++++++++++++------------------- 2 files changed, 78 insertions(+), 33 deletions(-) diff --git a/bin/SConsDoc.py b/bin/SConsDoc.py index eff8ba8..e560a44 100644 --- a/bin/SConsDoc.py +++ b/bin/SConsDoc.py @@ -257,17 +257,21 @@ if not has_libxml2: pass @staticmethod - def newNode(tag): - return etree.Element(tag) + def newNode(tag, **kwargs): + return etree.Element(tag, **kwargs) @staticmethod - def newEtreeNode(tag, init_ns=False): + def newSubNode(parent, tag, **kwargs): + return etree.SubElement(parent, tag, **kwargs) + + @staticmethod + def newEtreeNode(tag, init_ns=False, **kwargs): if init_ns: NSMAP = {None: dbxsd, 'xsi' : xsi} - return etree.Element(tag, nsmap=NSMAP) + return etree.Element(tag, nsmap=NSMAP, **kwargs) - return etree.Element(tag) + return etree.Element(tag, **kwargs) @staticmethod def copyNode(node): @@ -298,6 +302,14 @@ if not has_libxml2: root.text = txt @staticmethod + def getTail(root): + return root.tail + + @staticmethod + def setTail(root, txt): + root.tail = txt + + @staticmethod def writeGenTree(root, fp): dt = DoctypeDeclaration() try: @@ -387,12 +399,16 @@ else: pass @staticmethod - def newNode(tag): - return libxml2.newNode(tag) + def newNode(tag, **kwargs): + return etree.Element(tag, **kwargs) @staticmethod - def newEtreeNode(tag, init_ns=False): - return etree.Element(tag) + def newSubNode(parent, tag, **kwargs): + return etree.SubElement(parent, tag, **kwargs) + + @staticmethod + def newEtreeNode(tag, init_ns=False, **kwargs): + return etree.Element(tag, **kwargs) @staticmethod def copyNode(node): @@ -438,6 +454,14 @@ else: root.text = txt @staticmethod + def getTail(root): + return root.tail + + @staticmethod + def setTail(root, txt): + root.tail = txt + + @staticmethod def writeGenTree(root, fp): doc = libxml2.newDoc('1.0') dtd = doc.newDtd("sconsdoc", None, None) diff --git a/bin/scons-proc.py b/bin/scons-proc.py index cab4387..24248ae 100644 --- a/bin/scons-proc.py +++ b/bin/scons-proc.py @@ -260,15 +260,26 @@ class Builder(SConsThing): tag = 'function' def xml_terms(self): - ta = stf.newNode("term") - b = stf.newNode(self.tag) - stf.setText(b, self.name+'()') - stf.appendNode(ta, b) - tb = stf.newNode("term") - b = stf.newNode(self.tag) - stf.setText(b, 'env.'+self.name+'()') - stf.appendNode(tb, b) - return [ta, tb] + """emit xml for an scons builder + + builders don't show a full signature, just func() + """ + gterm = stf.newNode("term") + sig = stf.newSubNode(gterm, "literal") + func = stf.newSubNode(sig, "emphasis", role="bold") + stf.setText(func, self.name) + stf.setTail(func, '()') + + mterm = stf.newNode("term") + sig = stf.newSubNode(mterm, "literal") + inst = stf.newSubNode(sig, "replaceable") + stf.setText(inst, "env") + stf.setTail(inst, ".") + func = stf.newSubNode(sig, "emphasis", role="bold") + stf.setText(func, self.name) + stf.setTail(func, '()') + + return [gterm, mterm] def entityfunc(self): return self.name @@ -279,6 +290,11 @@ class Function(SConsThing): tag = 'function' def xml_terms(self): + """emit xml for an scons function + + The signature attribute controls whether to emit the + global function, the enviroment method, or both. + """ if self.arguments is None: a = stf.newNode("arguments") stf.setText(a, '()') @@ -292,17 +308,22 @@ class Function(SConsThing): signature = stf.getAttribute(arg, 'signature') s = stf.getText(arg).strip() if signature in ('both', 'global'): - t = stf.newNode("term") - syn = stf.newNode("literal") - stf.setText(syn, '%s%s' % (self.name, s)) - stf.appendNode(t, syn) - tlist.append(t) + gterm = stf.newNode("term") + sig = stf.newSubNode(gterm, "literal") + func = stf.newSubNode(sig, "emphasis", role="bold") + stf.setText(func, self.name) + stf.setTail(func, s) + tlist.append(gterm) if signature in ('both', 'env'): - t = stf.newNode("term") - syn = stf.newNode("literal") - stf.setText(syn, 'env.%s%s' % (self.name, s)) - stf.appendNode(t, syn) - tlist.append(t) + mterm = stf.newNode("term") + sig = stf.newSubNode(mterm, "literal") + inst = stf.newSubNode(sig, "replaceable") + stf.setText(inst, "env") + stf.setTail(inst, ".") + func = stf.newSubNode(sig, "emphasis", role="bold") + stf.setText(func, self.name) + stf.setTail(func, s) + tlist.append(mterm) if not tlist: tlist.append(stf.newNode("term")) @@ -331,24 +352,24 @@ class Variable(SConsThing): return '$' + self.name def write_output_files(h, buildersfiles, functionsfiles, - toolsfiles, variablesfiles, write_func): + toolsfiles, variablesfiles, write_func): if buildersfiles: - g = processor_class([ Builder(b) for b in sorted(h.builders.values()) ], + g = processor_class([Builder(b) for b in sorted(h.builders.values())], env_signatures=True) write_func(g, buildersfiles) if functionsfiles: - g = processor_class([ Function(b) for b in sorted(h.functions.values()) ], + g = processor_class([Function(b) for b in sorted(h.functions.values())], env_signatures=True) write_func(g, functionsfiles) if toolsfiles: - g = processor_class([ Tool(t) for t in sorted(h.tools.values()) ], + g = processor_class([Tool(t) for t in sorted(h.tools.values())], env_signatures=False) write_func(g, toolsfiles) if variablesfiles: - g = processor_class([ Variable(v) for v in sorted(h.cvars.values()) ], + g = processor_class([Variable(v) for v in sorted(h.cvars.values())], env_signatures=False) write_func(g, variablesfiles) -- cgit v0.12 From 268db381120e63c6790255c808aa53d8c01308ce Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Thu, 9 Apr 2020 10:24:02 -0600 Subject: [PR #3602] fix typo complained about by Sider [ci skip] enviroment -> environment (inside a docstring) Signed-off-by: Mats Wichmann --- bin/scons-proc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/scons-proc.py b/bin/scons-proc.py index 24248ae..6c1f66a 100644 --- a/bin/scons-proc.py +++ b/bin/scons-proc.py @@ -293,7 +293,7 @@ class Function(SConsThing): """emit xml for an scons function The signature attribute controls whether to emit the - global function, the enviroment method, or both. + global function, the environment method, or both. """ if self.arguments is None: a = stf.newNode("arguments") -- cgit v0.12 From f293a449ea7f9d036a85e4d880a2ba7da4751c6a Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 9 Mar 2020 11:49:40 -0700 Subject: Remove python27 code --- bin/SConsDoc.py | 68 ++++++++++++++++----------------------------------------- 1 file changed, 19 insertions(+), 49 deletions(-) diff --git a/bin/SConsDoc.py b/bin/SConsDoc.py index e560a44..1e88c5b 100644 --- a/bin/SConsDoc.py +++ b/bin/SConsDoc.py @@ -115,8 +115,6 @@ import re import sys import copy -PY2 = sys.version_info[0] == 2 - # Do we have libxml2/libxslt/lxml? has_libxml2 = True try: @@ -312,20 +310,14 @@ if not has_libxml2: @staticmethod def writeGenTree(root, fp): dt = DoctypeDeclaration() - try: - encfun = unicode # PY2 - except NameError: - encfun = str + encfun = str fp.write(etree.tostring(root, encoding=encfun, pretty_print=True, doctype=dt.createDoctype())) @staticmethod def writeTree(root, fpath): - try: - encfun = unicode # PY2 - except NameError: - encfun = "utf-8" + encfun = "utf-8" with open(fpath, 'wb') as fp: fp.write(etree.tostring(root, encoding=encfun, pretty_print=True)) @@ -859,45 +851,23 @@ class SConsDocHandler(object): # Parse it self.parseDomtree(t.root, t.xpath_context, t.nsmap) -# lifted from Ka-Ping Yee's way cool pydoc module. -if PY2: - def importfile(path): - """Import a Python source file or compiled file given its path.""" - import imp - magic = imp.get_magic() - with open(path, 'r') as ifp: - if ifp.read(len(magic)) == magic: - kind = imp.PY_COMPILED - else: - kind = imp.PY_SOURCE - filename = os.path.basename(path) - name, ext = os.path.splitext(filename) - with open(path, 'r') as ifp: - try: - module = imp.load_module(name, ifp, path, (ext, 'r', kind)) - except ImportError as e: - sys.stderr.write("Could not import %s: %s\n" % (path, e)) - return None - return module - -else: # PY3 version, from newer pydoc - def importfile(path): - """Import a Python source file or compiled file given its path.""" - from importlib.util import MAGIC_NUMBER - with open(path, 'rb') as ifp: - is_bytecode = MAGIC_NUMBER == ifp.read(len(MAGIC_NUMBER)) - filename = os.path.basename(path) - name, ext = os.path.splitext(filename) - if is_bytecode: - loader = importlib._bootstrap_external.SourcelessFileLoader(name, path) - else: - loader = importlib._bootstrap_external.SourceFileLoader(name, path) - # XXX We probably don't need to pass in the loader here. - spec = importlib.util.spec_from_file_location(name, path, loader=loader) - try: - return importlib._bootstrap._load(spec) - except ImportError: - raise ErrorDuringImport(path, sys.exc_info()) +def importfile(path): + """Import a Python source file or compiled file given its path.""" + from importlib.util import MAGIC_NUMBER + with open(path, 'rb') as ifp: + is_bytecode = MAGIC_NUMBER == ifp.read(len(MAGIC_NUMBER)) + filename = os.path.basename(path) + name, ext = os.path.splitext(filename) + if is_bytecode: + loader = importlib._bootstrap_external.SourcelessFileLoader(name, path) + else: + loader = importlib._bootstrap_external.SourceFileLoader(name, path) + # XXX We probably don't need to pass in the loader here. + spec = importlib.util.spec_from_file_location(name, path, loader=loader) + try: + return importlib._bootstrap._load(spec) + except ImportError: + raise ErrorDuringImport(path, sys.exc_info()) # Local Variables: # tab-width:4 -- cgit v0.12 From f1538fb9000a343d87676ce110076b7cc197cb0e Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 9 Mar 2020 22:29:14 -0400 Subject: add SKIP_DOC= variable to enable disabling buildign documents. Moved epydoc setup into site_scons/epydoc.py --- SConstruct | 550 ++++++++++++++++++++++-------------------------- doc/SConscript | 174 +++++---------- site_scons/epydoc.py | 100 +++++++++ site_scons/site_init.py | 3 +- 4 files changed, 408 insertions(+), 419 deletions(-) create mode 100644 site_scons/epydoc.py diff --git a/SConstruct b/SConstruct index 23797da..db71e0f 100644 --- a/SConstruct +++ b/SConstruct @@ -31,15 +31,10 @@ month_year = 'December 2019' # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -import distutils.util -import distutils.command import fnmatch import os import os.path -import re -import stat import sys -import tempfile import time import socket import textwrap @@ -98,17 +93,24 @@ if git: git_status_lines = p.readlines() revision = ARGUMENTS.get('REVISION', '') + + def generate_build_id(revision): return revision + if not revision and git: with os.popen("%s rev-parse HEAD 2> /dev/null" % git, "r") as p: git_hash = p.read().strip() + + def generate_build_id(revision): result = git_hash if [l for l in git_status_lines if 'modified' in l]: result = result + '[MODIFIED]' return result + + revision = git_hash checkpoint = ARGUMENTS.get('CHECKPOINT', '') @@ -136,11 +138,10 @@ for a in addpaths: if a not in sys.path: sys.path.append(a) - # Re-exporting LD_LIBRARY_PATH is necessary if the Python version was # built with the --enable-shared option. -ENV = { 'PATH' : os.environ['PATH'] } +ENV = {'PATH': os.environ['PATH']} for key in ['LOGNAME', 'PYTHONPATH', 'LD_LIBRARY_PATH']: if key in os.environ: ENV[key] = os.environ[key] @@ -150,73 +151,74 @@ if not os.path.isabs(build_dir): build_dir = os.path.normpath(os.path.join(os.getcwd(), build_dir)) command_line_variables = [ - ("BUILDDIR=", "The directory in which to build the packages. " + - "The default is the './build' subdirectory."), - - ("BUILD_ID=", "An identifier for the specific build." + - "The default is the Subversion revision number."), - - ("BUILD_SYSTEM=", "The system on which the packages were built. " + - "The default is whatever hostname is returned " + - "by socket.gethostname(). If SOURCE_DATE_EPOCH " + - "env var is set, '_reproducible' is the default."), - - ("CHECKPOINT=", "The specific checkpoint release being packaged, " + - "which will be appended to the VERSION string. " + - "A value of CHECKPOINT=d will generate a string " + - "of 'd' plus today's date in the format YYYMMDD. " + - "A value of CHECKPOINT=r will generate a " + - "string of 'r' plus the Subversion revision " + - "number. Any other CHECKPOINT= string will be " + - "used as is. There is no default value."), - - ("DATE=", "The date string representing when the packaging " + - "build occurred. The default is the day and time " + - "the SConstruct file was invoked, in the format " + - "YYYY/MM/DD HH:MM:SS."), - - ("DEVELOPER=", "The developer who created the packages. " + - "The default is the first set environment " + - "variable from the list $USERNAME, $LOGNAME, $USER." + - "If the SOURCE_DATE_EPOCH env var is set, " + - "'_reproducible' is the default."), - - ("REVISION=", "The revision number of the source being built. " + - "The default is the git hash returned " + - "'git rev-parse HEAD', with an appended string of " + - "'[MODIFIED]' if there are any changes in the " + - "working copy."), - - ("VERSION=", "The SCons version being packaged. The default " + - "is the hard-coded value '%s' " % default_version + - "from this SConstruct file."), - + ("BUILDDIR=", "The directory in which to build the packages. " + + "The default is the './build' subdirectory."), + + ("BUILD_ID=", "An identifier for the specific build." + + "The default is the Subversion revision number."), + + ("BUILD_SYSTEM=", "The system on which the packages were built. " + + "The default is whatever hostname is returned " + + "by socket.gethostname(). If SOURCE_DATE_EPOCH " + + "env var is set, '_reproducible' is the default."), + + ("CHECKPOINT=", "The specific checkpoint release being packaged, " + + "which will be appended to the VERSION string. " + + "A value of CHECKPOINT=d will generate a string " + + "of 'd' plus today's date in the format YYYMMDD. " + + "A value of CHECKPOINT=r will generate a " + + "string of 'r' plus the Subversion revision " + + "number. Any other CHECKPOINT= string will be " + + "used as is. There is no default value."), + + ("DATE=", "The date string representing when the packaging " + + "build occurred. The default is the day and time " + + "the SConstruct file was invoked, in the format " + + "YYYY/MM/DD HH:MM:SS."), + + ("DEVELOPER=", "The developer who created the packages. " + + "The default is the first set environment " + + "variable from the list $USERNAME, $LOGNAME, $USER." + + "If the SOURCE_DATE_EPOCH env var is set, " + + "'_reproducible' is the default."), + + ("REVISION=", "The revision number of the source being built. " + + "The default is the git hash returned " + + "'git rev-parse HEAD', with an appended string of " + + "'[MODIFIED]' if there are any changes in the " + + "working copy."), + + ("VERSION=", "The SCons version being packaged. The default " + + "is the hard-coded value '%s' " % default_version + + "from this SConstruct file."), + + ("SKIP_DOC=","Skip building all documents. The default is False (build docs)"), ] Default('.', build_dir) packaging_flavors = [ - ('tar-gz', "The normal .tar.gz file for end-user installation."), - ('local-tar-gz', "A .tar.gz file for dropping into other software " + - "for local use."), - ('zip', "The normal .zip file for end-user installation."), - ('local-zip', "A .zip file for dropping into other software " + - "for local use."), - ('src-tar-gz', "A .tar.gz file containing all the source " + - "(including tests and documentation)."), - ('src-zip', "A .zip file containing all the source " + - "(including tests and documentation)."), + ('tar-gz', "The normal .tar.gz file for end-user installation."), + ('local-tar-gz', "A .tar.gz file for dropping into other software " + + "for local use."), + ('zip', "The normal .zip file for end-user installation."), + ('local-zip', "A .zip file for dropping into other software " + + "for local use."), + ('src-tar-gz', "A .tar.gz file containing all the source " + + "(including tests and documentation)."), + ('src-zip', "A .zip file containing all the source " + + "(including tests and documentation)."), ] -test_tar_gz_dir = os.path.join(build_dir, "test-tar-gz") -test_src_tar_gz_dir = os.path.join(build_dir, "test-src-tar-gz") +test_tar_gz_dir = os.path.join(build_dir, "test-tar-gz") +test_src_tar_gz_dir = os.path.join(build_dir, "test-src-tar-gz") test_local_tar_gz_dir = os.path.join(build_dir, "test-local-tar-gz") -test_zip_dir = os.path.join(build_dir, "test-zip") -test_src_zip_dir = os.path.join(build_dir, "test-src-zip") -test_local_zip_dir = os.path.join(build_dir, "test-local-zip") +test_zip_dir = os.path.join(build_dir, "test-zip") +test_src_zip_dir = os.path.join(build_dir, "test-src-zip") +test_local_zip_dir = os.path.join(build_dir, "test-local-zip") -unpack_tar_gz_dir = os.path.join(build_dir, "unpack-tar-gz") -unpack_zip_dir = os.path.join(build_dir, "unpack-zip") +unpack_tar_gz_dir = os.path.join(build_dir, "unpack-tar-gz") +unpack_zip_dir = os.path.join(build_dir, "unpack-zip") if is_windows(): tar_hflag = '' @@ -227,9 +229,6 @@ else: python_project_subinst_dir = os.path.join("lib", project) project_script_subinst_dir = 'bin' - - - indent_fmt = ' %-26s ' Help("""\ @@ -243,9 +242,9 @@ aliases = sorted(packaging_flavors + [('doc', 'The SCons documentation.')]) for alias, help_text in aliases: tw = textwrap.TextWrapper( - width = 78, - initial_indent = indent_fmt % alias, - subsequent_indent = indent_fmt % '' + ' ', + width=78, + initial_indent=indent_fmt % alias, + subsequent_indent=indent_fmt % '' + ' ', ) Help(tw.fill(help_text) + '\n') @@ -256,61 +255,57 @@ The following command-line variables can be set: for variable, help_text in command_line_variables: tw = textwrap.TextWrapper( - width = 78, - initial_indent = indent_fmt % variable, - subsequent_indent = indent_fmt % '' + ' ', + width=78, + initial_indent=indent_fmt % variable, + subsequent_indent=indent_fmt % '' + ' ', ) Help(tw.fill(help_text) + '\n') - - - revaction = SCons_revision -revbuilder = Builder(action = Action(SCons_revision, - varlist=['COPYRIGHT', 'VERSION'])) - +revbuilder = Builder(action=Action(SCons_revision, + varlist=['COPYRIGHT', 'VERSION'])) # Just make copies, don't symlink them. SetOption('duplicate', 'copy') env = Environment( - ENV = ENV, + ENV=ENV, - BUILD = build_id, - BUILDDIR = build_dir, - BUILDSYS = build_system, - COPYRIGHT = copyright, - DATE = date, - DEB_DATE = deb_date, - DEVELOPER = developer, - DISTDIR = os.path.join(build_dir, 'dist'), - MONTH_YEAR = month_year, - REVISION = revision, - VERSION = version, + BUILD=build_id, + BUILDDIR=build_dir, + BUILDSYS=build_system, + COPYRIGHT=copyright, + DATE=date, + DEB_DATE=deb_date, + DEVELOPER=developer, + DISTDIR=os.path.join(build_dir, 'dist'), + MONTH_YEAR=month_year, + REVISION=revision, + VERSION=version, - TAR_HFLAG = tar_hflag, + TAR_HFLAG=tar_hflag, - ZIP = zip, - ZIPFLAGS = '-r', - UNZIP = unzip, - UNZIPFLAGS = '-o -d $UNPACK_ZIP_DIR', + ZIP=zip, + ZIPFLAGS='-r', + UNZIP=unzip, + UNZIPFLAGS='-o -d $UNPACK_ZIP_DIR', - ZCAT = zcat, + ZCAT=zcat, - TEST_SRC_TAR_GZ_DIR = test_src_tar_gz_dir, - TEST_SRC_ZIP_DIR = test_src_zip_dir, - TEST_TAR_GZ_DIR = test_tar_gz_dir, - TEST_ZIP_DIR = test_zip_dir, + TEST_SRC_TAR_GZ_DIR=test_src_tar_gz_dir, + TEST_SRC_ZIP_DIR=test_src_zip_dir, + TEST_TAR_GZ_DIR=test_tar_gz_dir, + TEST_ZIP_DIR=test_zip_dir, - UNPACK_TAR_GZ_DIR = unpack_tar_gz_dir, - UNPACK_ZIP_DIR = unpack_zip_dir, + UNPACK_TAR_GZ_DIR=unpack_tar_gz_dir, + UNPACK_ZIP_DIR=unpack_zip_dir, - BUILDERS = { 'SCons_revision' : revbuilder, - 'SOElim' : soelimbuilder }, + BUILDERS={'SCons_revision': revbuilder, + 'SOElim': soelimbuilder}, - PYTHON = '"%s"' % sys.executable, - PYTHONFLAGS = '-tt', - ) + PYTHON='"%s"' % sys.executable, + PYTHONFLAGS='-tt', +) Version_values = [Value(version), Value(build_id)] @@ -332,128 +327,90 @@ Version_values = [Value(version), Value(build_id)] from distutils.sysconfig import get_python_lib - python_scons = { - 'pkg' : 'python-' + project, - 'src_subdir' : 'engine', - 'inst_subdir' : get_python_lib(), - - 'debian_deps' : [ - 'debian/changelog', - 'debian/compat', - 'debian/control', - 'debian/copyright', - 'debian/dirs', - 'debian/docs', - 'debian/postinst', - 'debian/prerm', - 'debian/rules', - ], - - 'files' : [ 'LICENSE.txt', - 'README.txt', - 'setup.cfg', - 'setup.py', - ], - - 'filemap' : { - 'LICENSE.txt' : '../LICENSE.txt' - }, - - 'buildermap' : {}, - - 'explicit_deps' : { - 'SCons/__init__.py' : Version_values, - }, -} + 'pkg': 'python-' + project, + 'src_subdir': 'engine', + 'inst_subdir': get_python_lib(), + + 'files': ['LICENSE.txt', + 'README.txt', + 'setup.cfg', + 'setup.py', + ], + 'filemap': { + 'LICENSE.txt': '../LICENSE.txt' + }, + + 'buildermap': {}, + + 'explicit_deps': { + 'SCons/__init__.py': Version_values, + }, +} scons_script = { - 'pkg' : project + '-script', - 'src_subdir' : 'script', - 'inst_subdir' : 'bin', - - 'debian_deps' : [ - 'debian/changelog', - 'debian/compat', - 'debian/control', - 'debian/copyright', - 'debian/dirs', - 'debian/docs', - 'debian/postinst', - 'debian/prerm', - 'debian/rules', - ], - - 'files' : [ - 'LICENSE.txt', - 'README.txt', - 'setup.cfg', - 'setup.py', - ], - - 'filemap' : { - 'LICENSE.txt' : '../LICENSE.txt', - 'scons' : 'scons.py', - 'sconsign' : 'sconsign.py', - 'scons-time' : 'scons-time.py', - 'scons-configure-cache' : 'scons-configure-cache.py', - }, - - 'buildermap' : {}, - - 'explicit_deps' : { - 'scons' : Version_values, - 'sconsign' : Version_values, - }, + 'pkg': project + '-script', + 'src_subdir': 'script', + 'inst_subdir': 'bin', + + 'files': [ + 'LICENSE.txt', + 'README.txt', + 'setup.cfg', + 'setup.py', + ], + + 'filemap': { + 'LICENSE.txt': '../LICENSE.txt', + 'scons': 'scons.py', + 'sconsign': 'sconsign.py', + 'scons-time': 'scons-time.py', + 'scons-configure-cache': 'scons-configure-cache.py', + }, + + 'buildermap': {}, + + 'explicit_deps': { + 'scons': Version_values, + 'sconsign': Version_values, + }, } scons = { - 'pkg' : project, - - 'debian_deps' : [ - 'debian/changelog', - 'debian/compat', - 'debian/control', - 'debian/copyright', - 'debian/dirs', - 'debian/docs', - 'debian/postinst', - 'debian/prerm', - 'debian/rules', - ], - - 'files' : [ - 'CHANGES.txt', - 'LICENSE.txt', - 'README.txt', - 'RELEASE.txt', - 'scons.1', - 'sconsign.1', - 'scons-time.1', - 'script/scons.bat', - 'setup.cfg', - 'setup.py', - ], - - 'filemap' : { - 'scons.1' : '$BUILDDIR/doc/man/scons.1', - 'sconsign.1' : '$BUILDDIR/doc/man/sconsign.1', - 'scons-time.1' : '$BUILDDIR/doc/man/scons-time.1', - }, - - 'buildermap' : { - 'scons.1' : env.SOElim, - 'sconsign.1' : env.SOElim, - 'scons-time.1' : env.SOElim, - }, - - 'subpkgs' : [ python_scons, scons_script ], - - 'subinst_dirs' : { - 'python-' + project : python_project_subinst_dir, - project + '-script' : project_script_subinst_dir, - }, + 'pkg': project, + + 'files': [ + 'CHANGES.txt', + 'LICENSE.txt', + 'README.txt', + 'RELEASE.txt', + 'scons.1', + 'sconsign.1', + 'scons-time.1', + 'script/scons.bat', + 'setup.cfg', + 'setup.py', + ], + + 'filemap': { + 'scons.1': '$BUILDDIR/doc/man/scons.1', + 'sconsign.1': '$BUILDDIR/doc/man/sconsign.1', + 'scons-time.1': '$BUILDDIR/doc/man/scons-time.1', + }, + + 'buildermap': { + 'scons.1': env.SOElim, + 'sconsign.1': env.SOElim, + 'scons-time.1': env.SOElim, + }, + + 'subpkgs': [python_scons, scons_script], + + 'subinst_dirs': { + 'python-' + project: python_project_subinst_dir, + project + '-script': project_script_subinst_dir, + }, } scripts = ['scons', 'sconsign', 'scons-time', 'scons-configure-cache'] @@ -461,7 +418,7 @@ scripts = ['scons', 'sconsign', 'scons-time', 'scons-configure-cache'] src_deps = [] src_files = [] -for p in [ scons ]: +for p in [scons]: # # Initialize variables with the right directories for this package. # @@ -483,7 +440,6 @@ for p in [ scons ]: 'dist', "%s.%s.zip" % (pkg_version, platform)) - # # Update the environment with the relevant information # for this package. @@ -493,9 +449,9 @@ for p in [ scons ]: # to the directory in which setup.py exists. # setup_py = os.path.join(build, 'setup.py') - env.Replace(PKG = pkg, - PKG_VERSION = pkg_version, - SETUP_PY = '"%s"' % setup_py) + env.Replace(PKG=pkg, + PKG_VERSION=pkg_version, + SETUP_PY='"%s"' % setup_py) Local(setup_py) # @@ -511,7 +467,6 @@ for p in [ scons ]: MANIFEST_in_list = [] - if 'subpkgs' in p: # # This package includes some sub-packages. Read up their @@ -571,6 +526,7 @@ for p in [ scons ]: src_files.append("MANIFEST") MANIFEST_in_list.append(os.path.join(src, 'MANIFEST.in')) + def write_src_files(target, source, **kw): global src_files src_files.sort() @@ -578,6 +534,8 @@ for p in [ scons ]: for file in src_files: f.write(file + "\n") return 0 + + env.Command(os.path.join(build, 'MANIFEST'), MANIFEST_in_list, write_src_files) @@ -605,10 +563,10 @@ for p in [ scons ]: src_deps.append(tar_gz) - distutils_targets.extend([ tar_gz, platform_tar_gz ]) + distutils_targets.extend([tar_gz, platform_tar_gz]) - dist_tar_gz = env.Install('$DISTDIR', tar_gz) - dist_platform_tar_gz = env.Install('$DISTDIR', platform_tar_gz) + dist_tar_gz = env.Install('$DISTDIR', tar_gz) + dist_platform_tar_gz = env.Install('$DISTDIR', platform_tar_gz) Local(dist_tar_gz, dist_platform_tar_gz) AddPostAction(dist_tar_gz, Chmod(dist_tar_gz, 0o644)) AddPostAction(dist_platform_tar_gz, Chmod(dist_platform_tar_gz, 0o644)) @@ -627,10 +585,10 @@ for p in [ scons ]: unpack_tar_gz_files = [os.path.join(unpack_tar_gz_dir, pkg_version, x) for x in src_files] env.Command(unpack_tar_gz_files, dist_tar_gz, [ - Delete(os.path.join(unpack_tar_gz_dir, pkg_version)), - "$ZCAT $SOURCES > .temp", - "tar xf .temp -C $UNPACK_TAR_GZ_DIR", - Delete(".temp"), + Delete(os.path.join(unpack_tar_gz_dir, pkg_version)), + "$ZCAT $SOURCES > .temp", + "tar xf .temp -C $UNPACK_TAR_GZ_DIR", + Delete(".temp"), ]) # @@ -651,7 +609,7 @@ for p in [ scons ]: Delete(os.path.join(unpack_tar_gz_dir, pkg_version, 'build')), Delete("$TEST_TAR_GZ_DIR"), '$PYTHON $PYTHONFLAGS "%s" install "--prefix=$TEST_TAR_GZ_DIR" --standalone-lib' % \ - os.path.join(unpack_tar_gz_dir, pkg_version, 'setup.py'), + os.path.join(unpack_tar_gz_dir, pkg_version, 'setup.py'), ]) # @@ -662,10 +620,11 @@ for p in [ scons ]: digest = os.path.join(gentoo, 'files', 'digest-scons-%s' % version) env.Command(ebuild, os.path.join('gentoo', 'scons.ebuild.in'), SCons_revision) + def Digestify(target, source, env): import hashlib src = source[0].rfile() - with open(str(src),'rb') as f: + with open(str(src), 'rb') as f: contents = f.read() m = hashlib.md5() m.update(contents) @@ -673,6 +632,8 @@ for p in [ scons ]: bytes = os.stat(str(src))[6] with open(str(target[0]), 'w') as f: f.write("MD5 %s %s %d\n" % (sig, src.name, bytes)) + + env.Command(digest, tar_gz, Digestify) if not zipit: @@ -683,10 +644,10 @@ for p in [ scons ]: src_deps.append(zip) - distutils_targets.extend([ zip, platform_zip ]) + distutils_targets.extend([zip, platform_zip]) - dist_zip = env.Install('$DISTDIR', zip) - dist_platform_zip = env.Install('$DISTDIR', platform_zip) + dist_zip = env.Install('$DISTDIR', zip) + dist_platform_zip = env.Install('$DISTDIR', platform_zip) Local(dist_zip, dist_platform_zip) AddPostAction(dist_zip, Chmod(dist_zip, 0o644)) AddPostAction(dist_platform_zip, Chmod(dist_platform_zip, 0o644)) @@ -696,7 +657,7 @@ for p in [ scons ]: # build/unpack-zip/scons-{version}. # unpack_zip_files = [os.path.join(unpack_zip_dir, pkg_version, x) - for x in src_files] + for x in src_files] env.Command(unpack_zip_files, dist_zip, [ Delete(os.path.join(unpack_zip_dir, pkg_version)), @@ -721,11 +682,9 @@ for p in [ scons ]: Delete(os.path.join(unpack_zip_dir, pkg_version, 'build')), Delete("$TEST_ZIP_DIR"), '$PYTHON $PYTHONFLAGS "%s" install "--prefix=$TEST_ZIP_DIR" --standalone-lib' % \ - os.path.join(unpack_zip_dir, pkg_version, 'setup.py'), + os.path.join(unpack_zip_dir, pkg_version, 'setup.py'), ]) - - # # Use the Python distutils to generate the appropriate packages. # @@ -742,8 +701,8 @@ for p in [ scons ]: for format in distutils_formats: commands.append("$PYTHON $PYTHONFLAGS $SETUP_PY bdist_dumb -f %s" % format) - commands.append("$PYTHON $PYTHONFLAGS $SETUP_PY sdist --formats=%s" % \ - ','.join(distutils_formats)) + commands.append("$PYTHON $PYTHONFLAGS $SETUP_PY sdist --formats=%s" % \ + ','.join(distutils_formats)) env.Command(distutils_targets, build_src_files, commands) @@ -766,7 +725,7 @@ for p in [ scons ]: commands = [ Delete(build_dir_local), '$PYTHON $PYTHONFLAGS $SETUP_PY install "--install-script=%s" "--install-lib=%s" --no-install-man --no-compile --standalone-lib --no-version-script' % \ - (build_dir_local, build_dir_local_slv), + (build_dir_local, build_dir_local_slv), ] for script in scripts: @@ -813,7 +772,7 @@ for p in [ scons ]: if zipit: env.Command(dist_local_zip, local_targets, zipit, - CD = build_dir_local, PSV = '.') + CD=build_dir_local, PSV='.') unpack_targets = [os.path.join(test_local_zip_dir, x) for x in rf] commands = [Delete(test_local_zip_dir), @@ -821,7 +780,7 @@ for p in [ scons ]: unzipit] env.Command(unpack_targets, dist_local_zip, unzipit, - UNPACK_ZIP_DIR = test_local_zip_dir) + UNPACK_ZIP_DIR=test_local_zip_dir) # # @@ -839,7 +798,6 @@ files = [ 'runtest.py', ] - # # Documentation. # @@ -859,7 +817,7 @@ if git_status_lines: # sfiles = [l.split()[-1] for l in slines] pass else: - print("Not building in a Git tree; skipping building src package.") + print("Not building in a Git tree; skipping building src package.") if sfiles: remove_patterns = [ @@ -886,7 +844,7 @@ if sfiles: for file in sfiles: if file.endswith('jpg') or file.endswith('png'): # don't revision binary files. - env.Install(os.path.dirname(os.path.join(b_ps,file)), file) + env.Install(os.path.dirname(os.path.join(b_ps, file)), file) else: env.SCons_revision(os.path.join(b_ps, file), file) @@ -902,7 +860,6 @@ if sfiles: Local(*b_ps_files) if gzip: - env.Command(src_tar_gz, b_psv_stamp, "tar cz${TAR_HFLAG} -f $TARGET -C build %s" % psv) @@ -945,29 +902,28 @@ if sfiles: ENV['SCONS_LIB_DIR'] = scons_lib_dir ENV['USERNAME'] = developer env.Command(dfiles, unpack_tar_gz_files, - [ - Delete(os.path.join(unpack_tar_gz_dir, - psv, - 'build', - 'scons', - 'build')), - Delete("$TEST_SRC_TAR_GZ_DIR"), - 'cd "%s" && $PYTHON $PYTHONFLAGS "%s" "%s" VERSION="$VERSION"' % \ - (os.path.join(unpack_tar_gz_dir, psv), - os.path.join('src', 'script', 'scons.py'), - os.path.join('build', 'scons')), - '$PYTHON $PYTHONFLAGS "%s" install "--prefix=$TEST_SRC_TAR_GZ_DIR" --standalone-lib' % \ - os.path.join(unpack_tar_gz_dir, - psv, - 'build', - 'scons', - 'setup.py'), - ], - ENV = ENV) + [ + Delete(os.path.join(unpack_tar_gz_dir, + psv, + 'build', + 'scons', + 'build')), + Delete("$TEST_SRC_TAR_GZ_DIR"), + 'cd "%s" && $PYTHON $PYTHONFLAGS "%s" "%s" VERSION="$VERSION"' % \ + (os.path.join(unpack_tar_gz_dir, psv), + os.path.join('src', 'script', 'scons.py'), + os.path.join('build', 'scons')), + '$PYTHON $PYTHONFLAGS "%s" install "--prefix=$TEST_SRC_TAR_GZ_DIR" --standalone-lib' % \ + os.path.join(unpack_tar_gz_dir, + psv, + 'build', + 'scons', + 'setup.py'), + ], + ENV=ENV) if zipit: - - env.Command(src_zip, b_psv_stamp, zipit, CD = 'build', PSV = psv) + env.Command(src_zip, b_psv_stamp, zipit, CD='build', PSV=psv) # # Unpack the archive into build/unpack/scons-{version}. @@ -999,31 +955,29 @@ if sfiles: ENV['SCONS_LIB_DIR'] = scons_lib_dir ENV['USERNAME'] = developer env.Command(dfiles, unpack_zip_files, - [ - Delete(os.path.join(unpack_zip_dir, - psv, - 'build', - 'scons', - 'build')), - Delete("$TEST_SRC_ZIP_DIR"), - 'cd "%s" && $PYTHON $PYTHONFLAGS "%s" "%s" VERSION="$VERSION"' % \ - (os.path.join(unpack_zip_dir, psv), - os.path.join('src', 'script', 'scons.py'), - os.path.join('build', 'scons')), - '$PYTHON $PYTHONFLAGS "%s" install "--prefix=$TEST_SRC_ZIP_DIR" --standalone-lib' % \ - os.path.join(unpack_zip_dir, - psv, - 'build', - 'scons', - 'setup.py'), - ], - ENV = ENV) + [ + Delete(os.path.join(unpack_zip_dir, + psv, + 'build', + 'scons', + 'build')), + Delete("$TEST_SRC_ZIP_DIR"), + 'cd "%s" && $PYTHON $PYTHONFLAGS "%s" "%s" VERSION="$VERSION"' % \ + (os.path.join(unpack_zip_dir, psv), + os.path.join('src', 'script', 'scons.py'), + os.path.join('build', 'scons')), + '$PYTHON $PYTHONFLAGS "%s" install "--prefix=$TEST_SRC_ZIP_DIR" --standalone-lib' % \ + os.path.join(unpack_zip_dir, + psv, + 'build', + 'scons', + 'setup.py'), + ], + ENV=ENV) for pf, help_text in packaging_flavors: Alias(pf, [ - os.path.join(build_dir, 'test-'+pf), + os.path.join(build_dir, 'test-' + pf), os.path.join(build_dir, 'testing/framework'), os.path.join(build_dir, 'runtest.py'), ]) - - diff --git a/doc/SConscript b/doc/SConscript index 8f6d1cd..580f4ca 100644 --- a/doc/SConscript +++ b/doc/SConscript @@ -54,6 +54,11 @@ if not fop and not xep: print("doc: No PDF renderer found (fop|xep)!") skip_doc = True + +skip_doc_arg = ARGUMENTS.get('SKIP_DOC') +if skip_doc_arg is not None: + skip_doc = skip_doc_arg in ['True', '1', 'true'] + # # --- Configure build # @@ -62,7 +67,6 @@ env = env.Clone() build = os.path.join(build_dir, 'doc') -epydoc_cli = whereis('epydoc') gs = whereis('gs') lynx = whereis('lynx') @@ -494,127 +498,57 @@ else: tar_list.extend([css_file]) Local(css_file) -if not epydoc_cli: - try: - import epydoc - except ImportError: - epydoc = None +if not skip_doc: + if not epydoc_cli and not epydoc: + print("doc: epydoc not found, skipping building API documentation.") else: - # adding Epydoc builder using imported module - def epydoc_builder_action(target, source, env): - """ - Take a list of `source` files and build docs for them in - `target` dir. - - `target` and `source` are lists. - - Uses OUTDIR and EPYDOCFLAGS environment variables. - - http://www.scons.org/doc/2.0.1/HTML/scons-user/x3594.html - """ - - # the epydoc build process is the following: - # 1. build documentation index - # 2. feed doc index to writer for docs - - from epydoc.docbuilder import build_doc_index - from epydoc.docwriter.html import HTMLWriter - from epydoc.docwriter.latex import LatexWriter - - # 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 is None: - return -1 - - if env['EPYDOCFLAGS'] == '--html': - html_writer = HTMLWriter(docindex, - docformat='restructuredText', - prj_name='SCons', - prj_url='http://www.scons.org/') - try: - html_writer.write(env['OUTDIR']) - except OSError: # If directory cannot be created or any file cannot - # be created or written to. - return -2 - - """ - # PDF support requires external Linux utilites, so it's not crossplatform. - # Leaving for now. - # http://epydoc.svn.sourceforge.net/viewvc/epydoc/trunk/epydoc/src/epydoc/cli.py - - elif env['EPYDOCFLAGS'] == '--pdf': - pdf_writer = LatexWriter(docindex, - docformat='restructuredText', - prj_name='SCons', - prj_url='http://www.scons.org/') - """ - return 0 - - epydoc_commands = [ - Delete('$OUTDIR'), - epydoc_builder_action, - Touch('$TARGET'), - ] - -else: # epydoc_cli is found - epydoc_commands = [ - Delete('$OUTDIR'), - '$EPYDOC $EPYDOCFLAGS --debug --output $OUTDIR --docformat=restructuredText --name SCons --url http://www.scons.org/ $SOURCES', - Touch('$TARGET'), - ] - - -if not epydoc_cli and not epydoc: - print("doc: epydoc not found, skipping building API documentation.") -else: - # XXX Should be in common with reading the same thing in - # the SConstruct file. - # bootstrap.py runs outside of SCons, so need to process the path - e = Dir(os.path.join('#src', 'engine')).rstr() - sources = bootstrap.parseManifestLines(e, os.path.join(e, 'MANIFEST.in')) + # XXX Should be in common with reading the same thing in + # the SConstruct file. + # bootstrap.py runs outside of SCons, so need to process the path + e = Dir(os.path.join('#src', 'engine')).rstr() + sources = bootstrap.parseManifestLines(e, os.path.join(e, 'MANIFEST.in')) - # Omit some files: - # - # Don't omit Platform as we need Platform.virtualenv for the examples to be run - # sources = [x for x in sources if x.find('Platform') == -1] - sources = [x for x in sources if x.find('Tool') == -1] - sources = [x for x in sources if x.find('Options') == -1] - - e = os.path.join(build, '..', 'scons', 'engine') - sources = [os.path.join(e, x) for x in sources] - - htmldir = os.path.join(build, 'HTML', 'scons-api') - env.Command('${OUTDIR}/index.html', sources, epydoc_commands, - EPYDOC=epydoc_cli, EPYDOCFLAGS='--html', OUTDIR=htmldir) - tar_deps.append(htmldir) - tar_list.append(htmldir) - - if sys.platform == 'darwin' or not epydoc_cli: - print("doc: command line epydoc is not found, skipping PDF/PS/Tex output") - else: - # PDF and PostScript and TeX are built from the - # same invocation. - api_dir = os.path.join(build, 'scons-api') - api_pdf = os.path.join(api_dir, 'api.pdf') - api_ps = os.path.join(api_dir, 'api.ps') - api_tex = os.path.join(api_dir, 'api.tex') - api_targets = [api_pdf, api_ps, api_tex] - env.Command(api_targets, sources, epydoc_commands, - EPYDOC=epydoc_cli, EPYDOCFLAGS='--pdf', OUTDIR=api_dir) - Local(api_targets) - - pdf_install = os.path.join(build, 'PDF', 'scons-api.pdf') - env.InstallAs(pdf_install, api_pdf) - tar_deps.append(pdf_install) - tar_list.append(pdf_install) - Local(pdf_install) - - ps_install = os.path.join(build, 'PS', 'scons-api.ps') - env.InstallAs(ps_install, api_ps) - tar_deps.append(ps_install) - tar_list.append(ps_install) - Local(ps_install) + # Omit some files: + # + # Don't omit Platform as we need Platform.virtualenv for the examples to be run + # sources = [x for x in sources if x.find('Platform') == -1] + sources = [x for x in sources if x.find('Tool') == -1] + sources = [x for x in sources if x.find('Options') == -1] + + e = os.path.join(build, '..', 'scons', 'engine') + sources = [os.path.join(e, x) for x in sources] + + htmldir = os.path.join(build, 'HTML', 'scons-api') + env.Command('${OUTDIR}/index.html', sources, epydoc_commands, + EPYDOC=epydoc_cli, EPYDOCFLAGS='--html', OUTDIR=htmldir) + tar_deps.append(htmldir) + tar_list.append(htmldir) + + if sys.platform == 'darwin' or not epydoc_cli: + print("doc: command line epydoc is not found, skipping PDF/PS/Tex output") + else: + # PDF and PostScript and TeX are built from the + # same invocation. + api_dir = os.path.join(build, 'scons-api') + api_pdf = os.path.join(api_dir, 'api.pdf') + api_ps = os.path.join(api_dir, 'api.ps') + api_tex = os.path.join(api_dir, 'api.tex') + api_targets = [api_pdf, api_ps, api_tex] + env.Command(api_targets, sources, epydoc_commands, + EPYDOC=epydoc_cli, EPYDOCFLAGS='--pdf', OUTDIR=api_dir) + Local(api_targets) + + pdf_install = os.path.join(build, 'PDF', 'scons-api.pdf') + env.InstallAs(pdf_install, api_pdf) + tar_deps.append(pdf_install) + tar_list.append(pdf_install) + Local(pdf_install) + + ps_install = os.path.join(build, 'PS', 'scons-api.ps') + env.InstallAs(ps_install, api_ps) + tar_deps.append(ps_install) + tar_list.append(ps_install) + Local(ps_install) # # Now actually create the tar file of the documentation, diff --git a/site_scons/epydoc.py b/site_scons/epydoc.py new file mode 100644 index 0000000..149e9dc --- /dev/null +++ b/site_scons/epydoc.py @@ -0,0 +1,100 @@ +# +# Setup epydoc builder +# + +# +# __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. +# from Utilities import whereis +from SCons.Script import Delete, Touch, WhereIs + +epydoc_cli = WhereIs('epydoc') + + +if not epydoc_cli: + try: + import epydoc + except ImportError: + epydoc = None + else: + # adding Epydoc builder using imported module + def epydoc_builder_action(target, source, env): + """ + Take a list of `source` files and build docs for them in + `target` dir. + + `target` and `source` are lists. + + Uses OUTDIR and EPYDOCFLAGS environment variables. + + http://www.scons.org/doc/2.0.1/HTML/scons-user/x3594.html + """ + + # the epydoc build process is the following: + # 1. build documentation index + # 2. feed doc index to writer for docs + + from epydoc.docbuilder import build_doc_index + from epydoc.docwriter.html import HTMLWriter + from epydoc.docwriter.latex import LatexWriter + + # 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 is None: + return -1 + + if env['EPYDOCFLAGS'] == '--html': + html_writer = HTMLWriter(docindex, + docformat='restructuredText', + prj_name='SCons', + prj_url='http://www.scons.org/') + try: + html_writer.write(env['OUTDIR']) + except OSError: # If directory cannot be created or any file cannot + # be created or written to. + return -2 + + """ + # PDF support requires external Linux utilites, so it's not crossplatform. + # Leaving for now. + # http://epydoc.svn.sourceforge.net/viewvc/epydoc/trunk/epydoc/src/epydoc/cli.py + + elif env['EPYDOCFLAGS'] == '--pdf': + pdf_writer = LatexWriter(docindex, + docformat='restructuredText', + prj_name='SCons', + prj_url='http://www.scons.org/') + """ + return 0 + + epydoc_commands = [ + Delete('$OUTDIR'), + epydoc_builder_action, + Touch('$TARGET'), + ] + +else: # epydoc_cli is found + epydoc_commands = [ + Delete('$OUTDIR'), + '$EPYDOC $EPYDOCFLAGS --debug --output $OUTDIR --docformat=restructuredText --name SCons --url http://www.scons.org/ $SOURCES', + Touch('$TARGET'), + ] diff --git a/site_scons/site_init.py b/site_scons/site_init.py index b62eb37..d4df473 100644 --- a/site_scons/site_init.py +++ b/site_scons/site_init.py @@ -1,4 +1,5 @@ from SConsRevision import SCons_revision from Utilities import is_windows, whereis, platform, deb_date from zip_utils import unzipit, zipit, zcat -from soe_utils import soelim, soscan, soelimbuilder \ No newline at end of file +from soe_utils import soelim, soscan, soelimbuilder +from epydoc import epydoc_cli, epydoc_commands \ No newline at end of file -- cgit v0.12 From 7c466f714b9892d953ff2b91c7b0214180417000 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 15 Mar 2020 21:20:38 -0700 Subject: Initial checking of modernized setup.py. TODO: entry_points for every other script (scons.py is done) --- MANIFEST.in | 3 +++ setup.cfg | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ setup.py | 6 ++++++ 3 files changed, 73 insertions(+) create mode 100644 MANIFEST.in create mode 100644 setup.cfg create mode 100644 setup.py diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..4e4ae5a --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,3 @@ +recursive-exclude src/engine *Tests.py +global-exclude *Tests.py +recursive-include src/engine/SCons/Tool/docbook * diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..d44c1f5 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,64 @@ +[metadata] +name = SCons +version=3.9.9a99 +license = MIT +author = William Deegan +author_email =bill@baddogconsulting.com +long_description = file: README.rst +description = Open Source next-generation build tool. +group = Development/Tools +license_file = src/LICENSE.txt + + +url = http://www.scons.org/ +project-urls = + Documentation = https://scons.org/documentation.html + Twitter = https://twitter.com/SConsProject + GitHub = https://github.com/SCons/scons + Bug-Tracker = https://github.com/SCons/scons/issues + + +classifiers = + Development Status :: 5 - Production/Stable + Topic :: Utilities + Programming Language :: Python + Programming Language :: Python :: 3 + Programming Language :: Python :: 3 :: Only + Programming Language :: Python :: 3.5 + Programming Language :: Python :: 3.6 + Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 + Environment :: Console + Intended Audience :: Developers + License :: OSI Approved :: MIT License + Operating System :: POSIX :: Linux + Operating System :: Unix + Operating System :: MacOS + Operating System :: Microsoft :: Windows + + +[options] +zip_safe = False +python_requires = >=3.5 +install_requires = setuptools +setup_requires = setuptools +include_package_data = True +package_dir= + =src/engine +packages = find: + +[options.packages.find] + where=src/engine + +[options.entry_points] +console_scripts = + scons = SCons.Script.Main:main + + +[options.package_data] +* = *.txt, *.rst +SCons.Tool.docbook = *.* + + +[bdist_wheel] +universal=0 diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..ff975d4 --- /dev/null +++ b/setup.py @@ -0,0 +1,6 @@ +from setuptools import setup,find_packages + +setup( + # packages = find_packages("src/engine"), + # package_dir={"":"src/engine"}, +) \ No newline at end of file -- cgit v0.12 From 23197f27e50f9f66d9f7263fbac5c38855731922 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 21 Mar 2020 13:43:26 -0700 Subject: First pass of refactor. Moved command line argument processing into site_scons/BuildCommandLine.py. Sorted out all changes caused by that. --- SConstruct | 242 +++++++++-------------------------------- doc/SConscript | 6 +- site_scons/BuildCommandLine.py | 144 ++++++++++++++++++++++++ site_scons/epydoc.py | 4 +- site_scons/site_init.py | 10 +- src/setup.py | 6 +- 6 files changed, 214 insertions(+), 198 deletions(-) create mode 100644 site_scons/BuildCommandLine.py diff --git a/SConstruct b/SConstruct index db71e0f..6a11bca 100644 --- a/SConstruct +++ b/SConstruct @@ -35,8 +35,6 @@ import fnmatch import os import os.path import sys -import time -import socket import textwrap import bootstrap @@ -45,88 +43,16 @@ project = 'scons' default_version = '3.1.2' copyright = "Copyright (c) %s The SCons Foundation" % copyright_years -SConsignFile() - # # We let the presence or absence of various utilities determine whether # or not we bother to build certain pieces of things. This should allow # people to still do SCons packaging work even if they don't have all # of the utilities installed # -gzip = whereis('gzip') -git = os.path.exists('.git') and whereis('git') -unzip = whereis('unzip') -zip = whereis('zip') - -# -# Now grab the information that we "build" into the files. -# -date = ARGUMENTS.get('DATE') -if not date: - date = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(int(os.environ.get('SOURCE_DATE_EPOCH', time.time())))) - -developer = ARGUMENTS.get('DEVELOPER') -if not developer: - for variable in ['USERNAME', 'LOGNAME', 'USER']: - developer = os.environ.get(variable) - if developer: - break - if os.environ.get('SOURCE_DATE_EPOCH'): - developer = '_reproducible' - -build_system = ARGUMENTS.get('BUILD_SYSTEM') -if not build_system: - if os.environ.get('SOURCE_DATE_EPOCH'): - build_system = '_reproducible' - else: - build_system = socket.gethostname().split('.')[0] - -version = ARGUMENTS.get('VERSION', '') -if not version: - version = default_version - -git_status_lines = [] - -if git: - cmd = "%s ls-files 2> /dev/null" % git - with os.popen(cmd, "r") as p: - git_status_lines = p.readlines() - -revision = ARGUMENTS.get('REVISION', '') - - -def generate_build_id(revision): - return revision - - -if not revision and git: - with os.popen("%s rev-parse HEAD 2> /dev/null" % git, "r") as p: - git_hash = p.read().strip() - - - def generate_build_id(revision): - result = git_hash - if [l for l in git_status_lines if 'modified' in l]: - result = result + '[MODIFIED]' - return result - - - revision = git_hash - -checkpoint = ARGUMENTS.get('CHECKPOINT', '') -if checkpoint: - if checkpoint == 'd': - checkpoint = time.strftime('%Y%m%d', time.localtime(time.time())) - elif checkpoint == 'r': - checkpoint = 'r' + revision - version = version + '.beta.' + checkpoint - -build_id = ARGUMENTS.get('BUILD_ID') -if build_id is None: - if revision: - build_id = generate_build_id(revision) - else: - build_id = '' +print("git :%s"%git) +print("gzip :%s"%gzip) +print("unzip :%s"%unzip) +print("zip :%s"%zip_path) # # Adding some paths to sys.path, this is mainly needed @@ -138,64 +64,14 @@ for a in addpaths: if a not in sys.path: sys.path.append(a) -# Re-exporting LD_LIBRARY_PATH is necessary if the Python version was -# built with the --enable-shared option. - -ENV = {'PATH': os.environ['PATH']} -for key in ['LOGNAME', 'PYTHONPATH', 'LD_LIBRARY_PATH']: - if key in os.environ: - ENV[key] = os.environ[key] - -build_dir = ARGUMENTS.get('BUILDDIR', 'build') -if not os.path.isabs(build_dir): - build_dir = os.path.normpath(os.path.join(os.getcwd(), build_dir)) - -command_line_variables = [ - ("BUILDDIR=", "The directory in which to build the packages. " + - "The default is the './build' subdirectory."), - - ("BUILD_ID=", "An identifier for the specific build." + - "The default is the Subversion revision number."), - - ("BUILD_SYSTEM=", "The system on which the packages were built. " + - "The default is whatever hostname is returned " + - "by socket.gethostname(). If SOURCE_DATE_EPOCH " + - "env var is set, '_reproducible' is the default."), - - ("CHECKPOINT=", "The specific checkpoint release being packaged, " + - "which will be appended to the VERSION string. " + - "A value of CHECKPOINT=d will generate a string " + - "of 'd' plus today's date in the format YYYMMDD. " + - "A value of CHECKPOINT=r will generate a " + - "string of 'r' plus the Subversion revision " + - "number. Any other CHECKPOINT= string will be " + - "used as is. There is no default value."), - - ("DATE=", "The date string representing when the packaging " + - "build occurred. The default is the day and time " + - "the SConstruct file was invoked, in the format " + - "YYYY/MM/DD HH:MM:SS."), - - ("DEVELOPER=", "The developer who created the packages. " + - "The default is the first set environment " + - "variable from the list $USERNAME, $LOGNAME, $USER." + - "If the SOURCE_DATE_EPOCH env var is set, " + - "'_reproducible' is the default."), - - ("REVISION=", "The revision number of the source being built. " + - "The default is the git hash returned " + - "'git rev-parse HEAD', with an appended string of " + - "'[MODIFIED]' if there are any changes in the " + - "working copy."), - - ("VERSION=", "The SCons version being packaged. The default " + - "is the hard-coded value '%s' " % default_version + - "from this SConstruct file."), - - ("SKIP_DOC=","Skip building all documents. The default is False (build docs)"), -] +command_line = BuildCommandLine(default_version) +command_line.process_command_line_vars() + + +Default('.', command_line.build_dir) +# Just make copies, don't symlink them. +SetOption('duplicate', 'copy') -Default('.', build_dir) packaging_flavors = [ ('tar-gz', "The normal .tar.gz file for end-user installation."), @@ -210,15 +86,15 @@ packaging_flavors = [ "(including tests and documentation)."), ] -test_tar_gz_dir = os.path.join(build_dir, "test-tar-gz") -test_src_tar_gz_dir = os.path.join(build_dir, "test-src-tar-gz") -test_local_tar_gz_dir = os.path.join(build_dir, "test-local-tar-gz") -test_zip_dir = os.path.join(build_dir, "test-zip") -test_src_zip_dir = os.path.join(build_dir, "test-src-zip") -test_local_zip_dir = os.path.join(build_dir, "test-local-zip") +test_tar_gz_dir = os.path.join(command_line.build_dir, "test-tar-gz") +test_src_tar_gz_dir = os.path.join(command_line.build_dir, "test-src-tar-gz") +test_local_tar_gz_dir = os.path.join(command_line.build_dir, "test-local-tar-gz") +test_zip_dir = os.path.join(command_line.build_dir, "test-zip") +test_src_zip_dir = os.path.join(command_line.build_dir, "test-src-zip") +test_local_zip_dir = os.path.join(command_line.build_dir, "test-local-zip") -unpack_tar_gz_dir = os.path.join(build_dir, "unpack-tar-gz") -unpack_zip_dir = os.path.join(build_dir, "unpack-zip") +unpack_tar_gz_dir = os.path.join(command_line.build_dir, "unpack-tar-gz") +unpack_zip_dir = os.path.join(command_line.build_dir, "unpack-zip") if is_windows(): tar_hflag = '' @@ -253,7 +129,7 @@ The following command-line variables can be set: """) -for variable, help_text in command_line_variables: +for variable, help_text in command_line.command_line_variables: tw = textwrap.TextWrapper( width=78, initial_indent=indent_fmt % variable, @@ -265,27 +141,26 @@ revaction = SCons_revision revbuilder = Builder(action=Action(SCons_revision, varlist=['COPYRIGHT', 'VERSION'])) -# Just make copies, don't symlink them. -SetOption('duplicate', 'copy') env = Environment( - ENV=ENV, + ENV=command_line.ENV, - BUILD=build_id, - BUILDDIR=build_dir, - BUILDSYS=build_system, + BUILD=command_line.build_id, + BUILDDIR=command_line.build_dir, + BUILDSYS=command_line.build_system, COPYRIGHT=copyright, - DATE=date, + DATE=command_line.date, DEB_DATE=deb_date, - DEVELOPER=developer, - DISTDIR=os.path.join(build_dir, 'dist'), + + DEVELOPER=command_line.developer, + DISTDIR=os.path.join(command_line.build_dir, 'dist'), MONTH_YEAR=month_year, - REVISION=revision, - VERSION=version, + REVISION=command_line.revision, + VERSION=command_line.version, TAR_HFLAG=tar_hflag, - ZIP=zip, + ZIP=zip_path, ZIPFLAGS='-r', UNZIP=unzip, UNZIPFLAGS='-o -d $UNPACK_ZIP_DIR', @@ -307,7 +182,7 @@ env = Environment( PYTHONFLAGS='-tt', ) -Version_values = [Value(version), Value(build_id)] +Version_values = [Value(command_line.version), Value(command_line.build_id)] # # Define SCons packages. @@ -423,13 +298,13 @@ for p in [scons]: # Initialize variables with the right directories for this package. # pkg = p['pkg'] - pkg_version = "%s-%s" % (pkg, version) + pkg_version = "%s-%s" % (pkg, command_line.version) src = 'src' if 'src_subdir' in p: src = os.path.join(src, p['src_subdir']) - build = os.path.join(build_dir, pkg) + build = os.path.join(command_line.build_dir, pkg) tar_gz = os.path.join(build, 'dist', "%s.tar.gz" % pkg_version) platform_tar_gz = os.path.join(build, @@ -616,8 +491,8 @@ for p in [scons]: # Generate portage files for submission to Gentoo Linux. # gentoo = os.path.join(build, 'gentoo') - ebuild = os.path.join(gentoo, 'scons-%s.ebuild' % version) - digest = os.path.join(gentoo, 'files', 'digest-scons-%s' % version) + ebuild = os.path.join(gentoo, 'scons-%s.ebuild' % command_line.version) + digest = os.path.join(gentoo, 'files', 'digest-scons-%s' % command_line.version) env.Command(ebuild, os.path.join('gentoo', 'scons.ebuild.in'), SCons_revision) @@ -711,11 +586,11 @@ for p in [scons]: # build their SCons-buildable packages without having to # install SCons. # - s_l_v = '%s-local-%s' % (pkg, version) + s_l_v = '%s-local-%s' % (pkg, command_line.version) local = pkg + '-local' - build_dir_local = os.path.join(build_dir, local) - build_dir_local_slv = os.path.join(build_dir, local, s_l_v) + build_dir_local = os.path.join(command_line.build_dir, local) + build_dir_local_slv = os.path.join(command_line.build_dir, local, s_l_v) dist_local_tar_gz = os.path.join("$DISTDIR/%s.tar.gz" % s_l_v) dist_local_zip = os.path.join("$DISTDIR/%s.zip" % s_l_v) @@ -785,23 +660,10 @@ for p in [scons]: # # # -Export('build_dir', 'env') - -SConscript('testing/framework/SConscript') - -# -# -# -sp = env.Install(build_dir, 'runtest.py') -Local(sp) -files = [ - 'runtest.py', -] - # # Documentation. # -Export('build_dir', 'env', 'whereis', 'revaction') +Export('command_line', 'env', 'whereis', 'revaction') SConscript('doc/SConscript') @@ -811,8 +673,8 @@ SConscript('doc/SConscript') # -sfiles = [l.split()[-1] for l in git_status_lines] -if git_status_lines: +sfiles = [l.split()[-1] for l in command_line.git_status_lines] +if command_line.git_status_lines: # slines = [l for l in git_status_lines if 'modified:' in l] # sfiles = [l.split()[-1] for l in slines] pass @@ -831,13 +693,13 @@ if sfiles: if sfiles: ps = "%s-src" % project - psv = "%s-%s" % (ps, version) - b_ps = os.path.join(build_dir, ps) - b_psv = os.path.join(build_dir, psv) + psv = "%s-%s" % (ps, command_line.version) + b_ps = os.path.join(command_line.build_dir, ps) + b_psv = os.path.join(command_line.build_dir, psv) b_psv_stamp = b_psv + '-stamp' - src_tar_gz = os.path.join(build_dir, 'dist', '%s.tar.gz' % psv) - src_zip = os.path.join(build_dir, 'dist', '%s.zip' % psv) + src_tar_gz = os.path.join(command_line.build_dir, 'dist', '%s.tar.gz' % psv) + src_zip = os.path.join(command_line.build_dir, 'dist', '%s.zip' % psv) Local(src_tar_gz, src_zip) @@ -900,7 +762,7 @@ if sfiles: scons_lib_dir = os.path.join(unpack_tar_gz_dir, psv, 'src', 'engine') ENV = env.Dictionary('ENV').copy() ENV['SCONS_LIB_DIR'] = scons_lib_dir - ENV['USERNAME'] = developer + ENV['USERNAME'] = command_line.developer env.Command(dfiles, unpack_tar_gz_files, [ Delete(os.path.join(unpack_tar_gz_dir, @@ -953,7 +815,7 @@ if sfiles: scons_lib_dir = os.path.join(unpack_zip_dir, psv, 'src', 'engine') ENV = env.Dictionary('ENV').copy() ENV['SCONS_LIB_DIR'] = scons_lib_dir - ENV['USERNAME'] = developer + ENV['USERNAME'] = command_line.developer env.Command(dfiles, unpack_zip_files, [ Delete(os.path.join(unpack_zip_dir, @@ -977,7 +839,7 @@ if sfiles: for pf, help_text in packaging_flavors: Alias(pf, [ - os.path.join(build_dir, 'test-' + pf), - os.path.join(build_dir, 'testing/framework'), - os.path.join(build_dir, 'runtest.py'), + os.path.join(command_line.build_dir, 'test-' + pf), + os.path.join(command_line.build_dir, 'testing/framework'), + os.path.join(command_line.build_dir, 'runtest.py'), ]) diff --git a/doc/SConscript b/doc/SConscript index 580f4ca..4e9fb74 100644 --- a/doc/SConscript +++ b/doc/SConscript @@ -31,7 +31,7 @@ import glob import bootstrap -Import('build_dir', 'env', 'whereis', 'revaction') +Import('command_line', 'env', 'whereis', 'revaction') # # -- Check prerequisites for building the documentation --- @@ -64,7 +64,7 @@ if skip_doc_arg is not None: # env = env.Clone() -build = os.path.join(build_dir, 'doc') +build = os.path.join(command_line.build_dir, 'doc') gs = whereis('gs') @@ -252,7 +252,7 @@ else: fpattern = [fpattern] if use_builddir: - target_dir = env.Dir(os.path.join(build_dir, *(toolpath+paths))) + target_dir = env.Dir(os.path.join(command_line.build_dir, *(toolpath+paths))) buildsuite.extend(env.GlobInstall(target_dir, os.path.join('..', *(toolpath+paths+fpattern)))) else: diff --git a/site_scons/BuildCommandLine.py b/site_scons/BuildCommandLine.py new file mode 100644 index 0000000..4694472 --- /dev/null +++ b/site_scons/BuildCommandLine.py @@ -0,0 +1,144 @@ +import time +import os +import socket + +from SCons.Script import ARGUMENTS + +class BuildCommandLine(object): + + git = None + + def init_command_line_variables(self): + self.command_line_variables = [ + ("BUILDDIR=", "The directory in which to build the packages. " + + "The default is the './build' subdirectory."), + + ("BUILD_ID=", "An identifier for the specific build." + + "The default is the Subversion revision number."), + + ("BUILD_SYSTEM=", "The system on which the packages were built. " + + "The default is whatever hostname is returned " + + "by socket.gethostname(). If SOURCE_DATE_EPOCH " + + "env var is set, '_reproducible' is the default."), + + ("CHECKPOINT=", "The specific checkpoint release being packaged, " + + "which will be appended to the VERSION string. " + + "A value of CHECKPOINT=d will generate a string " + + "of 'd' plus today's date in the format YYYMMDD. " + + "A value of CHECKPOINT=r will generate a " + + "string of 'r' plus the Subversion revision " + + "number. Any other CHECKPOINT= string will be " + + "used as is. There is no default value."), + + ("DATE=", "The date string representing when the packaging " + + "build occurred. The default is the day and time " + + "the SConstruct file was invoked, in the format " + + "YYYY/MM/DD HH:MM:SS."), + + ("DEVELOPER=", "The developer who created the packages. " + + "The default is the first set environment " + + "variable from the list $USERNAME, $LOGNAME, $USER." + + "If the SOURCE_DATE_EPOCH env var is set, " + + "'_reproducible' is the default."), + + ("REVISION=", "The revision number of the source being built. " + + "The default is the git hash returned " + + "'git rev-parse HEAD', with an appended string of " + + "'[MODIFIED]' if there are any changes in the " + + "working copy."), + + ("VERSION=", "The SCons version being packaged. The default " + + "is the hard-coded value '%s' " % self.default_version + + "from this SConstruct file."), + + ("SKIP_DOC=", "Skip building all documents. The default is False (build docs)"), + ] + + def __init__(self, default_version="99.99.99"): + self.date = None + self.default_version = default_version + self.developer = None + self.build_dir = None + self.build_system = None + self.version = None + self.revision = None + self.git_status_lines = [] + self.git_hash = None + + self.init_command_line_variables() + + def process_command_line_vars(self): + # + # Now grab the information that we "build" into the files. + # + self.date = ARGUMENTS.get('DATE') + if not self.date: + self.date = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(int(os.environ.get('SOURCE_DATE_EPOCH', time.time())))) + + self.developer = ARGUMENTS.get('DEVELOPER') + if not self.developer: + for variable in ['USERNAME', 'LOGNAME', 'USER']: + self.developer = os.environ.get(variable) + if self.developer: + break + if os.environ.get('SOURCE_DATE_EPOCH'): + self.developer = '_reproducible' + + self.build_system = ARGUMENTS.get('BUILD_SYSTEM') + if not self.build_system: + if os.environ.get('SOURCE_DATE_EPOCH'): + self.build_system = '_reproducible' + else: + self.build_system = socket.gethostname().split('.')[0] + + self.version = ARGUMENTS.get('VERSION', '') + if not self.version: + self.version = self.default_version + + if BuildCommandLine.git: + cmd = "%s ls-files 2> /dev/null" % BuildCommandLine.git + with os.popen(cmd, "r") as p: + self.git_status_lines = p.readlines() + + self.revision = ARGUMENTS.get('REVISION', '') + + def generate_build_id(revision): + return revision + + if not self.revision and BuildCommandLine.git: + with os.popen("%s rev-parse HEAD 2> /dev/null" % BuildCommandLine.git, "r") as p: + self.git_hash = p.read().strip() + + def generate_build_id(revision): + result = self.git_hash + if [l for l in self.git_status_lines if 'modified' in l]: + result = result + '[MODIFIED]' + return result + + self.revision = self.git_hash + + self.checkpoint = ARGUMENTS.get('CHECKPOINT', '') + if self.checkpoint: + if self.checkpoint == 'd': + cself.heckpoint = time.strftime('%Y%m%d', time.localtime(time.time())) + elif self.checkpoint == 'r': + self.checkpoint = 'r' + self.revision + self.version = self.version + '.beta.' + self.checkpoint + + self.build_id = ARGUMENTS.get('BUILD_ID') + if self.build_id is None: + if self.revision: + self.build_id = generate_build_id(self.revision) + else: + self.build_id = '' + + # Re-exporting LD_LIBRARY_PATH is necessary if the Python version was + # built with the --enable-shared option. + self.ENV = {'PATH': os.environ['PATH']} + for key in ['LOGNAME', 'PYTHONPATH', 'LD_LIBRARY_PATH']: + if key in os.environ: + self.ENV[key] = os.environ[key] + + self.build_dir = ARGUMENTS.get('BUILDDIR', 'build') + if not os.path.isabs(self.build_dir): + self.build_dir = os.path.normpath(os.path.join(os.getcwd(), self.build_dir)) diff --git a/site_scons/epydoc.py b/site_scons/epydoc.py index 149e9dc..da74d9c 100644 --- a/site_scons/epydoc.py +++ b/site_scons/epydoc.py @@ -28,7 +28,6 @@ from SCons.Script import Delete, Touch, WhereIs epydoc_cli = WhereIs('epydoc') - if not epydoc_cli: try: import epydoc @@ -92,7 +91,8 @@ if not epydoc_cli: Touch('$TARGET'), ] -else: # epydoc_cli is found +else: + # epydoc_cli is found epydoc_commands = [ Delete('$OUTDIR'), '$EPYDOC $EPYDOCFLAGS --debug --output $OUTDIR --docformat=restructuredText --name SCons --url http://www.scons.org/ $SOURCES', diff --git a/site_scons/site_init.py b/site_scons/site_init.py index d4df473..7e7c569 100644 --- a/site_scons/site_init.py +++ b/site_scons/site_init.py @@ -2,4 +2,12 @@ from SConsRevision import SCons_revision from Utilities import is_windows, whereis, platform, deb_date from zip_utils import unzipit, zipit, zcat from soe_utils import soelim, soscan, soelimbuilder -from epydoc import epydoc_cli, epydoc_commands \ No newline at end of file +from epydoc import epydoc_cli, epydoc_commands +from BuildCommandLine import BuildCommandLine + +gzip = whereis('gzip') +git = os.path.exists('.git') and whereis('git') +unzip = whereis('unzip') +zip_path = whereis('zip') + +BuildCommandLine.git = git \ No newline at end of file diff --git a/src/setup.py b/src/setup.py index 261e2a4..bea888b 100755 --- a/src/setup.py +++ b/src/setup.py @@ -27,7 +27,7 @@ import distutils.command.install_data import distutils.command.install import distutils.core import distutils -# import setuptools +import setuptools """ NOTE: Installed SCons is not importable like usual Python packages. It is executed explicitly with command line scripts. This allows multiple @@ -165,7 +165,6 @@ class install(_install): self.install_bat = 0 self.no_install_bat = False # not is_win32 self.install_man = 0 - self.no_install_man = is_win32 self.standard_lib = 0 self.standalone_lib = 0 self.version_lib = 0 @@ -505,6 +504,9 @@ arguments = { 'install_data': install_data, 'install_scripts': install_scripts, 'build_scripts': build_scripts}, + 'install_requires' : { + "pywin32;platform_system=='Windows'" + } } distutils.core.setup(**arguments) -- cgit v0.12 From 072ebad9f866bdb4b79f5309071c0a92df1e21be Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 21 Mar 2020 16:35:56 -0700 Subject: Move scripts from src/scripts to scripts. Simplify scons.py to only be used for running from this source tree and for scons-local packaging --- scripts/MANIFEST.in | 4 + scripts/scons-configure-cache.py | 177 +++++ scripts/scons-time.py | 1480 +++++++++++++++++++++++++++++++++++ scripts/scons.bat | 38 + scripts/scons.py | 102 +++ scripts/sconsign.py | 652 +++++++++++++++ src/script/MANIFEST.in | 4 - src/script/scons-configure-cache.py | 177 ----- src/script/scons-time.py | 1480 ----------------------------------- src/script/scons.bat | 38 - src/script/scons.py | 208 ----- src/script/sconsign.py | 652 --------------- 12 files changed, 2453 insertions(+), 2559 deletions(-) create mode 100644 scripts/MANIFEST.in create mode 100644 scripts/scons-configure-cache.py create mode 100644 scripts/scons-time.py create mode 100644 scripts/scons.bat create mode 100755 scripts/scons.py create mode 100644 scripts/sconsign.py delete mode 100644 src/script/MANIFEST.in delete mode 100644 src/script/scons-configure-cache.py delete mode 100644 src/script/scons-time.py delete mode 100644 src/script/scons.bat delete mode 100755 src/script/scons.py delete mode 100644 src/script/sconsign.py diff --git a/scripts/MANIFEST.in b/scripts/MANIFEST.in new file mode 100644 index 0000000..d10cc82 --- /dev/null +++ b/scripts/MANIFEST.in @@ -0,0 +1,4 @@ +scons +sconsign +scons-time +scons-configure-cache diff --git a/scripts/scons-configure-cache.py b/scripts/scons-configure-cache.py new file mode 100644 index 0000000..716315c --- /dev/null +++ b/scripts/scons-configure-cache.py @@ -0,0 +1,177 @@ +#! /usr/bin/env python +# +# SCons - a Software Constructor +# +# __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. + +"""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. +""" + +import argparse +import glob +import json +import os + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +__version__ = "__VERSION__" + +__build__ = "__BUILD__" + +__buildsys__ = "__BUILDSYS__" + +__date__ = "__DATE__" + +__developer__ = "__DEVELOPER__" + + +def rearrange_cache_entries(current_prefix_len, new_prefix_len): + """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() + old_dirs = set() + for file in glob.iglob(os.path.join('*', '*')): + name = os.path.basename(file) + dname = name[:current_prefix_len].upper() + if dname not in old_dirs: + print('Migrating', dname) + old_dirs.add(dname) + dname = name[:new_prefix_len].upper() + if dname not in dirs: + os.mkdir(dname) + dirs.add(dname) + os.rename(file, os.path.join(dname, name)) + + # Now delete the original directories + for dname in old_dirs: + os.rmdir(dname) + + +# The configuration dictionary should have one entry per entry in the +# cache config. The value of each entry should include the following: +# implicit - (optional) This is to allow adding a new config entry and also +# changing the behaviour of the system at the same time. This +# indicates the value the config entry would have had if it had +# been specified. +# default - The value the config entry should have if it wasn't previously +# specified +# command-line - parameters to pass to ArgumentParser.add_argument +# converter - (optional) Function to call if conversion is required +# if this configuration entry changes +config_entries = { + 'prefix_len': { + 'implicit': 1, + 'default': 2, + 'command-line': { + 'help': 'Length of cache file name used as subdirectory prefix', + 'metavar': '', + 'type': int + }, + 'converter': rearrange_cache_entries + } +} + +parser = argparse.ArgumentParser( + description='Modify the configuration of an scons cache directory', + epilog=''' + Unspecified options will not be changed unless they are not + set at all, in which case they are set to an appropriate default. + ''') + +parser.add_argument('cache-dir', help='Path to scons cache directory') +for param in config_entries: + parser.add_argument('--' + param.replace('_', '-'), + **config_entries[param]['command-line']) +parser.add_argument('--version', + action='version', + version='%(prog)s 1.0') +parser.add_argument('--show', + action="store_true", + help="show current configuration") + +# Get the command line as a dict without any of the unspecified entries. +args = dict([x for x in vars(parser.parse_args()).items() if x[1]]) + +# It seems somewhat strange to me, but positional arguments don't get the - +# in the name changed to _, whereas optional arguments do... +cache = args['cache-dir'] +if not os.path.isdir(cache): + raise RuntimeError("There is no cache directory named %s" % cache) +os.chdir(cache) +del args['cache-dir'] + +if not os.path.exists('config'): + # old config dirs did not have a 'config' file. Try to update. + # Validate the only files in the directory are directories 0-9, a-f + expected = ['{:X}'.format(x) for x in range(0, 16)] + if not set(os.listdir('.')).issubset(expected): + raise RuntimeError( + "%s does not look like a valid version 1 cache directory" % cache) + config = dict() +else: + with open('config') as conf: + config = json.load(conf) + +if args.get('show', None): + print("Current configuration in '%s':" % cache) + print(json.dumps(config, sort_keys=True, + indent=4, separators=(',', ': '))) + # in case of the show argument, emit some stats as well + file_count = 0 + for _, _, files in os.walk('.'): + file_count += len(files) + if file_count: # skip config file if it exists + file_count -= 1 + print("Cache contains %s files" % file_count) + del args['show'] + +# Find any keys that are not currently set but should be +for key in config_entries: + if key not in config: + if 'implicit' in config_entries[key]: + config[key] = config_entries[key]['implicit'] + else: + config[key] = config_entries[key]['default'] + if key not in args: + args[key] = config_entries[key]['default'] + +# Now go through each entry in args to see if it changes an existing config +# setting. +for key in args: + if args[key] != config[key]: + if 'converter' in config_entries[key]: + config_entries[key]['converter'](config[key], args[key]) + config[key] = args[key] + +# and write the updated config file +with open('config', 'w') as conf: + json.dump(config, conf) diff --git a/scripts/scons-time.py b/scripts/scons-time.py new file mode 100644 index 0000000..e4dd863 --- /dev/null +++ b/scripts/scons-time.py @@ -0,0 +1,1480 @@ +#!/usr/bin/env python +# +# scons-time - run SCons timings and collect statistics +# +# A script for running a configuration through SCons with a standard +# set of invocations to collect timing and memory statistics and to +# capture the results in a consistent set of output files for display +# and analysis. +# + +# +# __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 getopt +import glob +import os +import re +import shutil +import sys +import tempfile +import time +import subprocess + +def HACK_for_exec(cmd, *args): + """ + For some reason, Python won't allow an exec() within a function + that also declares an internal function (including lambda functions). + This function is a hack that calls exec() in a function with no + internal functions. + """ + if not args: exec(cmd) + elif len(args) == 1: exec(cmd, args[0]) + else: exec(cmd, args[0], args[1]) + +class Plotter(object): + def increment_size(self, largest): + """ + Return the size of each horizontal increment line for a specified + maximum value. This returns a value that will provide somewhere + between 5 and 9 horizontal lines on the graph, on some set of + boundaries that are multiples of 10/100/1000/etc. + """ + i = largest // 5 + if not i: + return largest + multiplier = 1 + while i >= 10: + i = i // 10 + multiplier = multiplier * 10 + return i * multiplier + + def max_graph_value(self, largest): + # Round up to next integer. + largest = int(largest) + 1 + increment = self.increment_size(largest) + return ((largest + increment - 1) // increment) * increment + +class Line(object): + def __init__(self, points, type, title, label, comment, fmt="%s %s"): + self.points = points + self.type = type + self.title = title + self.label = label + self.comment = comment + self.fmt = fmt + + def print_label(self, inx, x, y): + if self.label: + print('set label %s "%s" at %0.1f,%0.1f right' % (inx, self.label, x, y)) + + def plot_string(self): + if self.title: + title_string = 'title "%s"' % self.title + else: + title_string = 'notitle' + return "'-' %s with lines lt %s" % (title_string, self.type) + + def print_points(self, fmt=None): + if fmt is None: + fmt = self.fmt + if self.comment: + print('# %s' % self.comment) + for x, y in self.points: + # If y is None, it usually represents some kind of break + # in the line's index number. We might want to represent + # this some way rather than just drawing the line straight + # between the two points on either side. + if y is not None: + print(fmt % (x, y)) + print('e') + + def get_x_values(self): + return [ p[0] for p in self.points ] + + def get_y_values(self): + return [ p[1] for p in self.points ] + +class Gnuplotter(Plotter): + + def __init__(self, title, key_location): + self.lines = [] + self.title = title + self.key_location = key_location + + def line(self, points, type, title=None, label=None, comment=None, fmt='%s %s'): + if points: + line = Line(points, type, title, label, comment, fmt) + self.lines.append(line) + + def plot_string(self, line): + return line.plot_string() + + def vertical_bar(self, x, type, label, comment): + if self.get_min_x() <= x <= self.get_max_x(): + points = [(x, 0), (x, self.max_graph_value(self.get_max_y()))] + self.line(points, type, label, comment) + + def get_all_x_values(self): + result = [] + for line in self.lines: + result.extend(line.get_x_values()) + return [r for r in result if r is not None] + + def get_all_y_values(self): + result = [] + for line in self.lines: + result.extend(line.get_y_values()) + return [r for r in result if r is not None] + + def get_min_x(self): + try: + return self.min_x + except AttributeError: + try: + self.min_x = min(self.get_all_x_values()) + except ValueError: + self.min_x = 0 + return self.min_x + + def get_max_x(self): + try: + return self.max_x + except AttributeError: + try: + self.max_x = max(self.get_all_x_values()) + except ValueError: + self.max_x = 0 + return self.max_x + + def get_min_y(self): + try: + return self.min_y + except AttributeError: + try: + self.min_y = min(self.get_all_y_values()) + except ValueError: + self.min_y = 0 + return self.min_y + + def get_max_y(self): + try: + return self.max_y + except AttributeError: + try: + self.max_y = max(self.get_all_y_values()) + except ValueError: + self.max_y = 0 + return self.max_y + + def draw(self): + + if not self.lines: + return + + if self.title: + print('set title "%s"' % self.title) + print('set key %s' % self.key_location) + + min_y = self.get_min_y() + max_y = self.max_graph_value(self.get_max_y()) + incr = (max_y - min_y) / 10.0 + start = min_y + (max_y / 2.0) + (2.0 * incr) + position = [ start - (i * incr) for i in range(5) ] + + inx = 1 + for line in self.lines: + line.print_label(inx, line.points[0][0]-1, + position[(inx-1) % len(position)]) + inx += 1 + + plot_strings = [ self.plot_string(l) for l in self.lines ] + print('plot ' + ', \\\n '.join(plot_strings)) + + for line in self.lines: + line.print_points() + + + +def untar(fname): + import tarfile + tar = tarfile.open(name=fname, mode='r') + for tarinfo in tar: + tar.extract(tarinfo) + tar.close() + +def unzip(fname): + import zipfile + zf = zipfile.ZipFile(fname, 'r') + for name in zf.namelist(): + dir = os.path.dirname(name) + try: + os.makedirs(dir) + except: + pass + with open(name, 'wb') as f: + f.write(zf.read(name)) + +def read_tree(dir): + for dirpath, dirnames, filenames in os.walk(dir): + for fn in filenames: + fn = os.path.join(dirpath, fn) + if os.path.isfile(fn): + with open(fn, 'rb') as f: + f.read() + +def redirect_to_file(command, log): + return '%s > %s 2>&1' % (command, log) + +def tee_to_file(command, log): + return '%s 2>&1 | tee %s' % (command, log) + + + +class SConsTimer(object): + """ + Usage: scons-time SUBCOMMAND [ARGUMENTS] + Type "scons-time help SUBCOMMAND" for help on a specific subcommand. + + Available subcommands: + func Extract test-run data for a function + help Provides help + mem Extract --debug=memory data from test runs + obj Extract --debug=count data from test runs + time Extract --debug=time data from test runs + run Runs a test configuration + """ + + name = 'scons-time' + name_spaces = ' '*len(name) + + def makedict(**kw): + return kw + + default_settings = makedict( + chdir = None, + config_file = None, + initial_commands = [], + key_location = 'bottom left', + orig_cwd = os.getcwd(), + outdir = None, + prefix = '', + python = '"%s"' % sys.executable, + redirect = redirect_to_file, + scons = None, + scons_flags = '--debug=count --debug=memory --debug=time --debug=memoizer', + scons_lib_dir = None, + scons_wrapper = None, + startup_targets = '--help', + subdir = None, + subversion_url = None, + svn = 'svn', + svn_co_flag = '-q', + tar = 'tar', + targets = '', + targets0 = None, + targets1 = None, + targets2 = None, + title = None, + unzip = 'unzip', + verbose = False, + vertical_bars = [], + + unpack_map = { + '.tar.gz' : (untar, '%(tar)s xzf %%s'), + '.tgz' : (untar, '%(tar)s xzf %%s'), + '.tar' : (untar, '%(tar)s xf %%s'), + '.zip' : (unzip, '%(unzip)s %%s'), + }, + ) + + run_titles = [ + 'Startup', + 'Full build', + 'Up-to-date build', + ] + + run_commands = [ + '%(python)s %(scons_wrapper)s %(scons_flags)s --profile=%(prof0)s %(targets0)s', + '%(python)s %(scons_wrapper)s %(scons_flags)s --profile=%(prof1)s %(targets1)s', + '%(python)s %(scons_wrapper)s %(scons_flags)s --profile=%(prof2)s %(targets2)s', + ] + + stages = [ + 'pre-read', + 'post-read', + 'pre-build', + 'post-build', + ] + + stage_strings = { + 'pre-read' : 'Memory before reading SConscript files:', + 'post-read' : 'Memory after reading SConscript files:', + 'pre-build' : 'Memory before building targets:', + 'post-build' : 'Memory after building targets:', + } + + memory_string_all = 'Memory ' + + default_stage = stages[-1] + + time_strings = { + 'total' : 'Total build time', + 'SConscripts' : 'Total SConscript file execution time', + 'SCons' : 'Total SCons execution time', + 'commands' : 'Total command execution time', + } + + time_string_all = 'Total .* time' + + # + + def __init__(self): + self.__dict__.update(self.default_settings) + + # Functions for displaying and executing commands. + + def subst(self, x, dictionary): + try: + return x % dictionary + except TypeError: + # x isn't a string (it's probably a Python function), + # so just return it. + return x + + def subst_variables(self, command, dictionary): + """ + Substitutes (via the format operator) the values in the specified + dictionary into the specified command. + + The command can be an (action, string) tuple. In all cases, we + perform substitution on strings and don't worry if something isn't + a string. (It's probably a Python function to be executed.) + """ + try: + command + '' + except TypeError: + action = command[0] + string = command[1] + args = command[2:] + else: + action = command + string = action + args = (()) + action = self.subst(action, dictionary) + string = self.subst(string, dictionary) + return (action, string, args) + + def _do_not_display(self, msg, *args): + pass + + def display(self, msg, *args): + """ + Displays the specified message. + + Each message is prepended with a standard prefix of our name + plus the time. + """ + if callable(msg): + msg = msg(*args) + else: + msg = msg % args + if msg is None: + return + fmt = '%s[%s]: %s\n' + sys.stdout.write(fmt % (self.name, time.strftime('%H:%M:%S'), msg)) + + def _do_not_execute(self, action, *args): + pass + + def execute(self, action, *args): + """ + Executes the specified action. + + The action is called if it's a callable Python function, and + otherwise passed to os.system(). + """ + if callable(action): + action(*args) + else: + os.system(action % args) + + def run_command_list(self, commands, dict): + """ + Executes a list of commands, substituting values from the + specified dictionary. + """ + commands = [ self.subst_variables(c, dict) for c in commands ] + for action, string, args in commands: + self.display(string, *args) + sys.stdout.flush() + status = self.execute(action, *args) + if status: + sys.exit(status) + + def log_display(self, command, log): + command = self.subst(command, self.__dict__) + if log: + command = self.redirect(command, log) + return command + + def log_execute(self, command, log): + command = self.subst(command, self.__dict__) + p = os.popen(command) + output = p.read() + p.close() + #TODO: convert to subrocess, os.popen is obsolete. This didn't work: + #process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True) + #output = process.stdout.read() + #process.stdout.close() + #process.wait() + if self.verbose: + sys.stdout.write(output) + # TODO: Figure out + # Not sure we need to write binary here + with open(log, 'w') as f: + f.write(str(output)) + + def archive_splitext(self, path): + """ + Splits an archive name into a filename base and extension. + + This is like os.path.splitext() (which it calls) except that it + also looks for '.tar.gz' and treats it as an atomic extensions. + """ + if path.endswith('.tar.gz'): + return path[:-7], path[-7:] + else: + return os.path.splitext(path) + + def args_to_files(self, args, tail=None): + """ + Takes a list of arguments, expands any glob patterns, and + returns the last "tail" files from the list. + """ + files = [] + for a in args: + files.extend(sorted(glob.glob(a))) + + if tail: + files = files[-tail:] + + return files + + def ascii_table(self, files, columns, + line_function, file_function=lambda x: x, + *args, **kw): + + header_fmt = ' '.join(['%12s'] * len(columns)) + line_fmt = header_fmt + ' %s' + + print(header_fmt % columns) + + for file in files: + t = line_function(file, *args, **kw) + if t is None: + t = [] + diff = len(columns) - len(t) + if diff > 0: + t += [''] * diff + t.append(file_function(file)) + print(line_fmt % tuple(t)) + + def collect_results(self, files, function, *args, **kw): + results = {} + + for file in files: + base = os.path.splitext(file)[0] + run, index = base.split('-')[-2:] + + run = int(run) + index = int(index) + + value = function(file, *args, **kw) + + try: + r = results[index] + except KeyError: + r = [] + results[index] = r + r.append((run, value)) + + return results + + def doc_to_help(self, obj): + """ + Translates an object's __doc__ string into help text. + + This strips a consistent number of spaces from each line in the + help text, essentially "outdenting" the text to the left-most + column. + """ + doc = obj.__doc__ + if doc is None: + return '' + return self.outdent(doc) + + def find_next_run_number(self, dir, prefix): + """ + Returns the next run number in a directory for the specified prefix. + + Examines the contents the specified directory for files with the + specified prefix, extracts the run numbers from each file name, + and returns the next run number after the largest it finds. + """ + x = re.compile(re.escape(prefix) + '-([0-9]+).*') + matches = [x.match(e) for e in os.listdir(dir)] + matches = [_f for _f in matches if _f] + if not matches: + return 0 + run_numbers = [int(m.group(1)) for m in matches] + return int(max(run_numbers)) + 1 + + def gnuplot_results(self, results, fmt='%s %.3f'): + """ + Prints out a set of results in Gnuplot format. + """ + gp = Gnuplotter(self.title, self.key_location) + + for i in sorted(results.keys()): + try: + t = self.run_titles[i] + except IndexError: + t = '??? %s ???' % i + results[i].sort() + gp.line(results[i], i+1, t, None, t, fmt=fmt) + + for bar_tuple in self.vertical_bars: + try: + x, type, label, comment = bar_tuple + except ValueError: + x, type, label = bar_tuple + comment = label + gp.vertical_bar(x, type, label, comment) + + gp.draw() + + def logfile_name(self, invocation): + """ + Returns the absolute path of a log file for the specificed + invocation number. + """ + name = self.prefix_run + '-%d.log' % invocation + return os.path.join(self.outdir, name) + + def outdent(self, s): + """ + Strip as many spaces from each line as are found at the beginning + of the first line in the list. + """ + lines = s.split('\n') + if lines[0] == '': + lines = lines[1:] + spaces = re.match(' *', lines[0]).group(0) + def strip_initial_spaces(l, s=spaces): + if l.startswith(spaces): + l = l[len(spaces):] + return l + return '\n'.join([ strip_initial_spaces(l) for l in lines ]) + '\n' + + def profile_name(self, invocation): + """ + Returns the absolute path of a profile file for the specified + invocation number. + """ + name = self.prefix_run + '-%d.prof' % invocation + return os.path.join(self.outdir, name) + + def set_env(self, key, value): + os.environ[key] = value + + # + + def get_debug_times(self, file, time_string=None): + """ + Fetch times from the --debug=time strings in the specified file. + """ + if time_string is None: + search_string = self.time_string_all + else: + search_string = time_string + with open(file) as f: + contents = f.read() + 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 = [ float(r) for r in result ] + if time_string is not None: + try: + result = result[0] + except IndexError: + sys.stderr.write('file %s has no results!\n' % repr(file)) + return None + return result + + def get_function_profile(self, file, function): + """ + Returns the file, line number, function name, and cumulative time. + """ + try: + import pstats + except ImportError as e: + sys.stderr.write('%s: func: %s\n' % (self.name, e)) + sys.stderr.write('%s This version of Python is missing the profiler.\n' % self.name_spaces) + sys.stderr.write('%s Cannot use the "func" subcommand.\n' % self.name_spaces) + sys.exit(1) + statistics = pstats.Stats(file).stats + matches = [ e for e in statistics.items() if e[0][2] == function ] + r = matches[0] + return r[0][0], r[0][1], r[0][2], r[1][3] + + def get_function_time(self, file, function): + """ + Returns just the cumulative time for the specified function. + """ + return self.get_function_profile(file, function)[3] + + def get_memory(self, file, memory_string=None): + """ + Returns a list of integers of the amount of memory used. The + default behavior is to return all the stages. + """ + if memory_string is None: + search_string = self.memory_string_all + else: + search_string = memory_string + with open(file) as f: + lines = f.readlines() + lines = [ l for l in lines if l.startswith(search_string) ][-4:] + result = [ int(l.split()[-1]) for l in lines[-4:] ] + if len(result) == 1: + result = result[0] + return result + + def get_object_counts(self, file, object_name, index=None): + """ + Returns the counts of the specified object_name. + """ + object_string = ' ' + object_name + '\n' + with open(file) as f: + lines = f.readlines() + line = [ l for l in lines if l.endswith(object_string) ][0] + result = [ int(field) for field in line.split()[:4] ] + if index is not None: + result = result[index] + return result + + + command_alias = {} + + def execute_subcommand(self, argv): + """ + Executes the do_*() function for the specified subcommand (argv[0]). + """ + if not argv: + return + cmdName = self.command_alias.get(argv[0], argv[0]) + try: + func = getattr(self, 'do_' + cmdName) + except AttributeError: + return self.default(argv) + try: + return func(argv) + except TypeError as e: + sys.stderr.write("%s %s: %s\n" % (self.name, cmdName, e)) + import traceback + traceback.print_exc(file=sys.stderr) + sys.stderr.write("Try '%s help %s'\n" % (self.name, cmdName)) + + def default(self, argv): + """ + The default behavior for an unknown subcommand. Prints an + error message and exits. + """ + sys.stderr.write('%s: Unknown subcommand "%s".\n' % (self.name, argv[0])) + sys.stderr.write('Type "%s help" for usage.\n' % self.name) + sys.exit(1) + + # + + def do_help(self, argv): + """ + """ + if argv[1:]: + for arg in argv[1:]: + try: + func = getattr(self, 'do_' + arg) + except AttributeError: + sys.stderr.write('%s: No help for "%s"\n' % (self.name, arg)) + else: + try: + help = getattr(self, 'help_' + arg) + except AttributeError: + sys.stdout.write(self.doc_to_help(func)) + sys.stdout.flush() + else: + help() + else: + doc = self.doc_to_help(self.__class__) + if doc: + sys.stdout.write(doc) + sys.stdout.flush() + return None + + # + + def help_func(self): + help = """\ + Usage: scons-time func [OPTIONS] FILE [...] + + -C DIR, --chdir=DIR Change to DIR before looking for files + -f FILE, --file=FILE Read configuration from specified FILE + --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT + --func=NAME, --function=NAME Report time for function NAME + -h, --help Print this help and exit + -p STRING, --prefix=STRING Use STRING as log file/profile prefix + -t NUMBER, --tail=NUMBER Only report the last NUMBER files + --title=TITLE Specify the output plot TITLE + """ + sys.stdout.write(self.outdent(help)) + sys.stdout.flush() + + def do_func(self, argv): + """ + """ + format = 'ascii' + function_name = '_main' + tail = None + + short_opts = '?C:f:hp:t:' + + long_opts = [ + 'chdir=', + 'file=', + 'fmt=', + 'format=', + 'func=', + 'function=', + 'help', + 'prefix=', + 'tail=', + 'title=', + ] + + opts, args = getopt.getopt(argv[1:], short_opts, long_opts) + + for o, a in opts: + if o in ('-C', '--chdir'): + self.chdir = a + elif o in ('-f', '--file'): + self.config_file = a + elif o in ('--fmt', '--format'): + format = a + elif o in ('--func', '--function'): + function_name = a + elif o in ('-?', '-h', '--help'): + self.do_help(['help', 'func']) + sys.exit(0) + elif o in ('--max',): + max_time = int(a) + elif o in ('-p', '--prefix'): + self.prefix = a + elif o in ('-t', '--tail'): + tail = int(a) + elif o in ('--title',): + self.title = a + + if self.config_file: + with open(self.config_file, 'r') as f: + config = f.read() + exec(config, self.__dict__) + + if self.chdir: + os.chdir(self.chdir) + + if not args: + + pattern = '%s*.prof' % self.prefix + args = self.args_to_files([pattern], tail) + + if not args: + if self.chdir: + directory = self.chdir + else: + directory = os.getcwd() + + sys.stderr.write('%s: func: No arguments specified.\n' % self.name) + sys.stderr.write('%s No %s*.prof files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) + sys.stderr.write('%s Type "%s help func" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + + else: + + args = self.args_to_files(args, tail) + + cwd_ = os.getcwd() + os.sep + + if format == 'ascii': + + for file in args: + try: + f, line, func, time = \ + self.get_function_profile(file, function_name) + except ValueError as e: + sys.stderr.write("%s: func: %s: %s\n" % + (self.name, file, e)) + else: + if f.startswith(cwd_): + f = f[len(cwd_):] + print("%.3f %s:%d(%s)" % (time, f, line, func)) + + elif format == 'gnuplot': + + results = self.collect_results(args, self.get_function_time, + function_name) + + self.gnuplot_results(results) + + else: + + sys.stderr.write('%s: func: Unknown format "%s".\n' % (self.name, format)) + sys.exit(1) + + # + + def help_mem(self): + help = """\ + Usage: scons-time mem [OPTIONS] FILE [...] + + -C DIR, --chdir=DIR Change to DIR before looking for files + -f FILE, --file=FILE Read configuration from specified FILE + --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT + -h, --help Print this help and exit + -p STRING, --prefix=STRING Use STRING as log file/profile prefix + --stage=STAGE Plot memory at the specified stage: + pre-read, post-read, pre-build, + post-build (default: post-build) + -t NUMBER, --tail=NUMBER Only report the last NUMBER files + --title=TITLE Specify the output plot TITLE + """ + sys.stdout.write(self.outdent(help)) + sys.stdout.flush() + + def do_mem(self, argv): + + format = 'ascii' + logfile_path = lambda x: x + stage = self.default_stage + tail = None + + short_opts = '?C:f:hp:t:' + + long_opts = [ + 'chdir=', + 'file=', + 'fmt=', + 'format=', + 'help', + 'prefix=', + 'stage=', + 'tail=', + 'title=', + ] + + opts, args = getopt.getopt(argv[1:], short_opts, long_opts) + + for o, a in opts: + if o in ('-C', '--chdir'): + self.chdir = a + elif o in ('-f', '--file'): + self.config_file = a + elif o in ('--fmt', '--format'): + format = a + elif o in ('-?', '-h', '--help'): + self.do_help(['help', 'mem']) + sys.exit(0) + elif o in ('-p', '--prefix'): + self.prefix = a + elif o in ('--stage',): + if a not in self.stages: + sys.stderr.write('%s: mem: Unrecognized stage "%s".\n' % (self.name, a)) + sys.exit(1) + stage = a + elif o in ('-t', '--tail'): + tail = int(a) + elif o in ('--title',): + self.title = a + + if self.config_file: + with open(self.config_file, 'r') as f: + config = f.read() + HACK_for_exec(config, self.__dict__) + + if self.chdir: + os.chdir(self.chdir) + logfile_path = lambda x: os.path.join(self.chdir, x) + + if not args: + + pattern = '%s*.log' % self.prefix + args = self.args_to_files([pattern], tail) + + if not args: + if self.chdir: + directory = self.chdir + else: + directory = os.getcwd() + + sys.stderr.write('%s: mem: No arguments specified.\n' % self.name) + sys.stderr.write('%s No %s*.log files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) + sys.stderr.write('%s Type "%s help mem" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + + else: + + args = self.args_to_files(args, tail) + + cwd_ = os.getcwd() + os.sep + + if format == 'ascii': + + self.ascii_table(args, tuple(self.stages), self.get_memory, logfile_path) + + elif format == 'gnuplot': + + results = self.collect_results(args, self.get_memory, + self.stage_strings[stage]) + + self.gnuplot_results(results) + + else: + + sys.stderr.write('%s: mem: Unknown format "%s".\n' % (self.name, format)) + sys.exit(1) + + return 0 + + # + + def help_obj(self): + help = """\ + Usage: scons-time obj [OPTIONS] OBJECT FILE [...] + + -C DIR, --chdir=DIR Change to DIR before looking for files + -f FILE, --file=FILE Read configuration from specified FILE + --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT + -h, --help Print this help and exit + -p STRING, --prefix=STRING Use STRING as log file/profile prefix + --stage=STAGE Plot memory at the specified stage: + pre-read, post-read, pre-build, + post-build (default: post-build) + -t NUMBER, --tail=NUMBER Only report the last NUMBER files + --title=TITLE Specify the output plot TITLE + """ + sys.stdout.write(self.outdent(help)) + sys.stdout.flush() + + def do_obj(self, argv): + + format = 'ascii' + logfile_path = lambda x: x + stage = self.default_stage + tail = None + + short_opts = '?C:f:hp:t:' + + long_opts = [ + 'chdir=', + 'file=', + 'fmt=', + 'format=', + 'help', + 'prefix=', + 'stage=', + 'tail=', + 'title=', + ] + + opts, args = getopt.getopt(argv[1:], short_opts, long_opts) + + for o, a in opts: + if o in ('-C', '--chdir'): + self.chdir = a + elif o in ('-f', '--file'): + self.config_file = a + elif o in ('--fmt', '--format'): + format = a + elif o in ('-?', '-h', '--help'): + self.do_help(['help', 'obj']) + sys.exit(0) + elif o in ('-p', '--prefix'): + self.prefix = a + elif o in ('--stage',): + if a not in self.stages: + sys.stderr.write('%s: obj: Unrecognized stage "%s".\n' % (self.name, a)) + sys.stderr.write('%s Type "%s help obj" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + stage = a + elif o in ('-t', '--tail'): + tail = int(a) + elif o in ('--title',): + self.title = a + + if not args: + sys.stderr.write('%s: obj: Must specify an object name.\n' % self.name) + sys.stderr.write('%s Type "%s help obj" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + + object_name = args.pop(0) + + if self.config_file: + with open(self.config_file, 'r') as f: + config = f.read() + HACK_for_exec(config, self.__dict__) + + if self.chdir: + os.chdir(self.chdir) + logfile_path = lambda x: os.path.join(self.chdir, x) + + if not args: + + pattern = '%s*.log' % self.prefix + args = self.args_to_files([pattern], tail) + + if not args: + if self.chdir: + directory = self.chdir + else: + directory = os.getcwd() + + sys.stderr.write('%s: obj: No arguments specified.\n' % self.name) + sys.stderr.write('%s No %s*.log files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) + sys.stderr.write('%s Type "%s help obj" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + + else: + + args = self.args_to_files(args, tail) + + cwd_ = os.getcwd() + os.sep + + if format == 'ascii': + + self.ascii_table(args, tuple(self.stages), self.get_object_counts, logfile_path, object_name) + + elif format == 'gnuplot': + + stage_index = 0 + for s in self.stages: + if stage == s: + break + stage_index = stage_index + 1 + + results = self.collect_results(args, self.get_object_counts, + object_name, stage_index) + + self.gnuplot_results(results) + + else: + + sys.stderr.write('%s: obj: Unknown format "%s".\n' % (self.name, format)) + sys.exit(1) + + return 0 + + # + + def help_run(self): + help = """\ + Usage: scons-time run [OPTIONS] [FILE ...] + + --chdir=DIR Name of unpacked directory for chdir + -f FILE, --file=FILE Read configuration from specified FILE + -h, --help Print this help and exit + -n, --no-exec No execute, just print command lines + --number=NUMBER Put output in files for run NUMBER + --outdir=OUTDIR Put output files in OUTDIR + -p STRING, --prefix=STRING Use STRING as log file/profile prefix + --python=PYTHON Time using the specified PYTHON + -q, --quiet Don't print command lines + --scons=SCONS Time using the specified SCONS + --svn=URL, --subversion=URL Use SCons from Subversion URL + -v, --verbose Display output of commands + """ + sys.stdout.write(self.outdent(help)) + sys.stdout.flush() + + def do_run(self, argv): + """ + """ + run_number_list = [None] + + short_opts = '?f:hnp:qs:v' + + long_opts = [ + 'file=', + 'help', + 'no-exec', + 'number=', + 'outdir=', + 'prefix=', + 'python=', + 'quiet', + 'scons=', + 'svn=', + 'subdir=', + 'subversion=', + 'verbose', + ] + + opts, args = getopt.getopt(argv[1:], short_opts, long_opts) + + for o, a in opts: + if o in ('-f', '--file'): + self.config_file = a + elif o in ('-?', '-h', '--help'): + self.do_help(['help', 'run']) + sys.exit(0) + elif o in ('-n', '--no-exec'): + self.execute = self._do_not_execute + elif o in ('--number',): + run_number_list = self.split_run_numbers(a) + elif o in ('--outdir',): + self.outdir = a + elif o in ('-p', '--prefix'): + self.prefix = a + elif o in ('--python',): + self.python = a + elif o in ('-q', '--quiet'): + self.display = self._do_not_display + elif o in ('-s', '--subdir'): + self.subdir = a + elif o in ('--scons',): + self.scons = a + elif o in ('--svn', '--subversion'): + self.subversion_url = a + elif o in ('-v', '--verbose'): + self.redirect = tee_to_file + self.verbose = True + self.svn_co_flag = '' + + if not args and not self.config_file: + sys.stderr.write('%s: run: No arguments or -f config file specified.\n' % self.name) + sys.stderr.write('%s Type "%s help run" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + + if self.config_file: + with open(self.config_file, 'r') as f: + config = f.read() + exec(config, self.__dict__) + + if args: + self.archive_list = args + + archive_file_name = os.path.split(self.archive_list[0])[1] + + if not self.subdir: + self.subdir = self.archive_splitext(archive_file_name)[0] + + if not self.prefix: + self.prefix = self.archive_splitext(archive_file_name)[0] + + prepare = None + if self.subversion_url: + prepare = self.prep_subversion_run + + for run_number in run_number_list: + self.individual_run(run_number, self.archive_list, prepare) + + def split_run_numbers(self, s): + result = [] + for n in s.split(','): + try: + x, y = n.split('-') + except ValueError: + result.append(int(n)) + else: + result.extend(list(range(int(x), int(y)+1))) + return result + + def scons_path(self, dir): + return os.path.join(dir, 'src', 'script', 'scons.py') + + def scons_lib_dir_path(self, dir): + return os.path.join(dir, 'src', 'engine') + + def prep_subversion_run(self, commands, removals): + self.svn_tmpdir = tempfile.mkdtemp(prefix=self.name + '-svn-') + removals.append((shutil.rmtree, 'rm -rf %%s', self.svn_tmpdir)) + + self.scons = self.scons_path(self.svn_tmpdir) + self.scons_lib_dir = self.scons_lib_dir_path(self.svn_tmpdir) + + commands.extend([ + '%(svn)s co %(svn_co_flag)s -r %(run_number)s %(subversion_url)s %(svn_tmpdir)s', + ]) + + def individual_run(self, run_number, archive_list, prepare=None): + """ + Performs an individual run of the default SCons invocations. + """ + + commands = [] + removals = [] + + if prepare: + prepare(commands, removals) + + save_scons = self.scons + save_scons_wrapper = self.scons_wrapper + save_scons_lib_dir = self.scons_lib_dir + + if self.outdir is None: + self.outdir = self.orig_cwd + elif not os.path.isabs(self.outdir): + self.outdir = os.path.join(self.orig_cwd, self.outdir) + + if self.scons is None: + self.scons = self.scons_path(self.orig_cwd) + + if self.scons_lib_dir is None: + self.scons_lib_dir = self.scons_lib_dir_path(self.orig_cwd) + + if self.scons_wrapper is None: + self.scons_wrapper = self.scons + + if not run_number: + run_number = self.find_next_run_number(self.outdir, self.prefix) + + self.run_number = str(run_number) + + self.prefix_run = self.prefix + '-%03d' % run_number + + if self.targets0 is None: + self.targets0 = self.startup_targets + if self.targets1 is None: + self.targets1 = self.targets + if self.targets2 is None: + self.targets2 = self.targets + + self.tmpdir = tempfile.mkdtemp(prefix=self.name + '-') + + commands.extend([ + (os.chdir, 'cd %%s', self.tmpdir), + ]) + + for archive in archive_list: + if not os.path.isabs(archive): + archive = os.path.join(self.orig_cwd, archive) + if os.path.isdir(archive): + dest = os.path.split(archive)[1] + commands.append((shutil.copytree, 'cp -r %%s %%s', archive, dest)) + else: + suffix = self.archive_splitext(archive)[1] + unpack_command = self.unpack_map.get(suffix) + if not unpack_command: + dest = os.path.split(archive)[1] + commands.append((shutil.copyfile, 'cp %%s %%s', archive, dest)) + else: + commands.append(unpack_command + (archive,)) + + commands.extend([ + (os.chdir, 'cd %%s', self.subdir), + ]) + + commands.extend(self.initial_commands) + + commands.extend([ + (lambda: read_tree('.'), + 'find * -type f | xargs cat > /dev/null'), + + (self.set_env, 'export %%s=%%s', + 'SCONS_LIB_DIR', self.scons_lib_dir), + + '%(python)s %(scons_wrapper)s --version', + ]) + + index = 0 + for run_command in self.run_commands: + setattr(self, 'prof%d' % index, self.profile_name(index)) + c = ( + self.log_execute, + self.log_display, + run_command, + self.logfile_name(index), + ) + commands.append(c) + index = index + 1 + + commands.extend([ + (os.chdir, 'cd %%s', self.orig_cwd), + ]) + + if not os.environ.get('PRESERVE'): + commands.extend(removals) + commands.append((shutil.rmtree, 'rm -rf %%s', self.tmpdir)) + + self.run_command_list(commands, self.__dict__) + + self.scons = save_scons + self.scons_lib_dir = save_scons_lib_dir + self.scons_wrapper = save_scons_wrapper + + # + + def help_time(self): + help = """\ + Usage: scons-time time [OPTIONS] FILE [...] + + -C DIR, --chdir=DIR Change to DIR before looking for files + -f FILE, --file=FILE Read configuration from specified FILE + --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT + -h, --help Print this help and exit + -p STRING, --prefix=STRING Use STRING as log file/profile prefix + -t NUMBER, --tail=NUMBER Only report the last NUMBER files + --which=TIMER Plot timings for TIMER: total, + SConscripts, SCons, commands. + """ + sys.stdout.write(self.outdent(help)) + sys.stdout.flush() + + def do_time(self, argv): + + format = 'ascii' + logfile_path = lambda x: x + tail = None + which = 'total' + + short_opts = '?C:f:hp:t:' + + long_opts = [ + 'chdir=', + 'file=', + 'fmt=', + 'format=', + 'help', + 'prefix=', + 'tail=', + 'title=', + 'which=', + ] + + opts, args = getopt.getopt(argv[1:], short_opts, long_opts) + + for o, a in opts: + if o in ('-C', '--chdir'): + self.chdir = a + elif o in ('-f', '--file'): + self.config_file = a + elif o in ('--fmt', '--format'): + format = a + elif o in ('-?', '-h', '--help'): + self.do_help(['help', 'time']) + sys.exit(0) + elif o in ('-p', '--prefix'): + self.prefix = a + elif o in ('-t', '--tail'): + tail = int(a) + elif o in ('--title',): + self.title = a + elif o in ('--which',): + if a not in list(self.time_strings.keys()): + sys.stderr.write('%s: time: Unrecognized timer "%s".\n' % (self.name, a)) + sys.stderr.write('%s Type "%s help time" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + which = a + + if self.config_file: + with open(self.config_file, 'r') as f: + config = f.read() + HACK_for_exec(config, self.__dict__) + + if self.chdir: + os.chdir(self.chdir) + logfile_path = lambda x: os.path.join(self.chdir, x) + + if not args: + + pattern = '%s*.log' % self.prefix + args = self.args_to_files([pattern], tail) + + if not args: + if self.chdir: + directory = self.chdir + else: + directory = os.getcwd() + + sys.stderr.write('%s: time: No arguments specified.\n' % self.name) + sys.stderr.write('%s No %s*.log files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) + sys.stderr.write('%s Type "%s help time" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + + else: + + args = self.args_to_files(args, tail) + + cwd_ = os.getcwd() + os.sep + + if format == 'ascii': + + columns = ("Total", "SConscripts", "SCons", "commands") + self.ascii_table(args, columns, self.get_debug_times, logfile_path) + + elif format == 'gnuplot': + + results = self.collect_results(args, self.get_debug_times, + self.time_strings[which]) + + self.gnuplot_results(results, fmt='%s %.6f') + + else: + + sys.stderr.write('%s: time: Unknown format "%s".\n' % (self.name, format)) + sys.exit(1) + +if __name__ == '__main__': + opts, args = getopt.getopt(sys.argv[1:], 'h?V', ['help', 'version']) + + ST = SConsTimer() + + for o, a in opts: + if o in ('-?', '-h', '--help'): + ST.do_help(['help']) + sys.exit(0) + elif o in ('-V', '--version'): + sys.stdout.write('scons-time version\n') + sys.exit(0) + + if not args: + sys.stderr.write('Type "%s help" for usage.\n' % ST.name) + sys.exit(1) + + ST.execute_subcommand(args) + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/scripts/scons.bat b/scripts/scons.bat new file mode 100644 index 0000000..10b8637 --- /dev/null +++ b/scripts/scons.bat @@ -0,0 +1,38 @@ +@REM __COPYRIGHT__ +@REM __FILE__ __REVISION__ __DATE__ __DEVELOPER__ +@echo off +set SCONS_ERRORLEVEL= +if "%OS%" == "Windows_NT" goto WinNT + +@REM for 9x/Me you better not have more than 9 args +python -c "from os.path import join; import sys; sys.path = [ join(sys.prefix, 'Lib', 'site-packages', 'scons-__VERSION__'), join(sys.prefix, 'Lib', 'site-packages', 'scons'), join(sys.prefix, 'scons-__VERSION__'), join(sys.prefix, 'scons')] + sys.path; import SCons.Script; SCons.Script.main()" %1 %2 %3 %4 %5 %6 %7 %8 %9 +@REM no way to set exit status of this script for 9x/Me +goto endscons + +@REM Credit where credit is due: we return the exit code despite our +@REM use of setlocal+endlocal using a technique from Bear's Journal: +@REM http://code-bear.com/bearlog/2007/06/01/getting-the-exit-code-from-a-batch-file-that-is-run-from-a-python-program/ + +:WinNT +setlocal +@REM ensure the script will be executed with the Python it was installed for +pushd %~dp0.. +set path=%~dp0;%CD%;%path% +popd +@REM try the script named as the .bat file in current dir, then in Scripts subdir +set scriptname=%~dp0%~n0.py +if not exist "%scriptname%" set scriptname=%~dp0Scripts\%~n0.py +@REM Handle when running from wheel where the script has no .py extension +if not exist "%scriptname%" set scriptname=%~dp0%~n0 +python "%scriptname%" %* +endlocal & set SCONS_ERRORLEVEL=%ERRORLEVEL% + +if NOT "%COMSPEC%" == "%SystemRoot%\system32\cmd.exe" goto returncode +if errorlevel 9009 echo you do not have python in your PATH +goto endscons + +:returncode +exit /B %SCONS_ERRORLEVEL% + +:endscons +call :returncode %SCONS_ERRORLEVEL% diff --git a/scripts/scons.py b/scripts/scons.py new file mode 100755 index 0000000..1dc6c78 --- /dev/null +++ b/scripts/scons.py @@ -0,0 +1,102 @@ +#! /usr/bin/env python +# +# SCons - a Software Constructor +# +# __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__" + +__version__ = "__VERSION__" + +__build__ = "__BUILD__" + +__buildsys__ = "__BUILDSYS__" + +__date__ = "__DATE__" + +__developer__ = "__DEVELOPER__" + + +import os +import sys + + +# Python compatibility check +if sys.version_info < (3, 5, 0): + msg = "scons: *** SCons version %s does not run under Python version %s.\n\ +Python >= 3.5 is required.\n" + sys.stderr.write(msg % (__version__, sys.version.split()[0])) + sys.exit(1) + +# Strip the script directory from sys.path so on case-insensitive +# (WIN32) systems Python doesn't think that the "scons" script is the +# "SCons" package. +script_dir = os.path.dirname(os.path.realpath(__file__)) +script_path = os.path.realpath(os.path.dirname(__file__)) +if script_path in sys.path: + sys.path.remove(script_path) + +libs = [] + +if "SCONS_LIB_DIR" in os.environ: + libs.append(os.environ["SCONS_LIB_DIR"]) + +# running from source takes 2nd priority (since 2.3.2), following SCONS_LIB_DIR +source_path = os.path.join(script_path, os.pardir, 'src', 'engine') +if os.path.isdir(source_path): + libs.append(source_path) + +# add local-install locations +local_version = 'scons-local-' + __version__ +local = 'scons-local' +if script_dir: + local_version = os.path.join(script_dir, local_version) + local = os.path.join(script_dir, local) +if os.path.isdir(local_version): + libs.append(os.path.abspath(local_version)) +if os.path.isdir(local): + libs.append(os.path.abspath(local)) + +sys.path = libs + sys.path + +############################################################################## +# END STANDARD SCons SCRIPT HEADER +############################################################################## + +if __name__ == "__main__": + try: + import SCons.Script + except ImportError: + sys.stderr.write("SCons import failed. Unable to find engine files in:\n") + for path in libs: + sys.stderr.write(" {}\n".format(path)) + raise + + # this does all the work, and calls sys.exit + # with the proper exit status when done. + SCons.Script.main() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/scripts/sconsign.py b/scripts/sconsign.py new file mode 100644 index 0000000..726838c --- /dev/null +++ b/scripts/sconsign.py @@ -0,0 +1,652 @@ +#! /usr/bin/env python +# +# SCons - a Software Constructor +# +# __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__" + +__version__ = "__VERSION__" + +__build__ = "__BUILD__" + +__buildsys__ = "__BUILDSYS__" + +__date__ = "__DATE__" + +__developer__ = "__DEVELOPER__" + +import os +import sys + +############################################################################## +# BEGIN STANDARD SCons SCRIPT HEADER +# +# This is the cut-and-paste logic so that a self-contained script can +# interoperate correctly with different SCons versions and installation +# locations for the engine. If you modify anything in this section, you +# should also change other scripts that use this same header. +############################################################################## + +# compatibility check +if sys.version_info < (3,5,0): + msg = "scons: *** SCons version %s does not run under Python version %s.\n\ +Python >= 3.5 is required.\n" + sys.stderr.write(msg % (__version__, sys.version.split()[0])) + sys.exit(1) + +# Strip the script directory from sys.path so on case-insensitive +# (WIN32) systems Python doesn't think that the "scons" script is the +# "SCons" package. +script_dir = os.path.dirname(os.path.realpath(__file__)) +script_path = os.path.realpath(os.path.dirname(__file__)) +if script_path in sys.path: + sys.path.remove(script_path) + +libs = [] + +if "SCONS_LIB_DIR" in os.environ: + libs.append(os.environ["SCONS_LIB_DIR"]) + +# running from source takes 2nd priority (since 2.3.2), following SCONS_LIB_DIR +source_path = os.path.join(script_path, os.pardir, 'engine') +if os.path.isdir(source_path): + libs.append(source_path) + +# add local-install locations +local_version = 'scons-local-' + __version__ +local = 'scons-local' +if script_dir: + local_version = os.path.join(script_dir, local_version) + local = os.path.join(script_dir, local) +if os.path.isdir(local_version): + libs.append(os.path.abspath(local_version)) +if os.path.isdir(local): + libs.append(os.path.abspath(local)) + +scons_version = 'scons-%s' % __version__ + +# preferred order of scons lookup paths +prefs = [] + +# if we can find package information, use it +try: + import pkg_resources +except ImportError: + pass +else: + try: + d = pkg_resources.get_distribution('scons') + except pkg_resources.DistributionNotFound: + pass + else: + prefs.append(d.location) + +if sys.platform == 'win32': + # Use only sys.prefix on Windows + prefs.append(sys.prefix) + prefs.append(os.path.join(sys.prefix, 'Lib', 'site-packages')) +else: + # On other (POSIX) platforms, things are more complicated due to + # the variety of path names and library locations. + # Build up some possibilities, then transform them into candidates + temp = [] + if script_dir == 'bin': + # script_dir is `pwd`/bin; + # check `pwd`/lib/scons*. + temp.append(os.getcwd()) + else: + if script_dir in ('.', ''): + script_dir = os.getcwd() + head, tail = os.path.split(script_dir) + if tail == "bin": + # script_dir is /foo/bin; + # check /foo/lib/scons*. + temp.append(head) + + head, tail = os.path.split(sys.prefix) + if tail == "usr": + # sys.prefix is /foo/usr; + # check /foo/usr/lib/scons* first, + # then /foo/usr/local/lib/scons*. + temp.append(sys.prefix) + temp.append(os.path.join(sys.prefix, "local")) + elif tail == "local": + h, t = os.path.split(head) + if t == "usr": + # sys.prefix is /foo/usr/local; + # check /foo/usr/local/lib/scons* first, + # then /foo/usr/lib/scons*. + temp.append(sys.prefix) + temp.append(head) + else: + # sys.prefix is /foo/local; + # check only /foo/local/lib/scons*. + temp.append(sys.prefix) + else: + # sys.prefix is /foo (ends in neither /usr or /local); + # check only /foo/lib/scons*. + temp.append(sys.prefix) + + # suffix these to add to our original prefs: + prefs.extend([os.path.join(x, 'lib') for x in temp]) + prefs.extend([os.path.join(x, 'lib', 'python' + sys.version[:3], + 'site-packages') for x in temp]) + + + # Add the parent directory of the current python's library to the + # preferences. This picks up differences between, e.g., lib and lib64, + # and finds the base location in case of a non-copying virtualenv. + try: + libpath = os.__file__ + except AttributeError: + pass + else: + # Split /usr/libfoo/python*/os.py to /usr/libfoo/python*. + libpath, _ = os.path.split(libpath) + # Split /usr/libfoo/python* to /usr/libfoo + libpath, tail = os.path.split(libpath) + # Check /usr/libfoo/scons*. + prefs.append(libpath) + +# Look first for 'scons-__version__' in all of our preference libs, +# then for 'scons'. Skip paths that do not exist. +libs.extend([os.path.join(x, scons_version) for x in prefs if os.path.isdir(x)]) +libs.extend([os.path.join(x, 'scons') for x in prefs if os.path.isdir(x)]) + +sys.path = libs + sys.path + +############################################################################## +# END STANDARD SCons SCRIPT HEADER +############################################################################## + +import SCons.compat + +try: + import whichdb + + whichdb = whichdb.whichdb +except ImportError as e: + from dbm import whichdb + +import time +import pickle + +import SCons.SConsign + + +def my_whichdb(filename): + if filename[-7:] == ".dblite": + return "SCons.dblite" + try: + with open(filename + ".dblite", "rb"): + return "SCons.dblite" + except IOError: + pass + return _orig_whichdb(filename) + + +# Should work on python2 +_orig_whichdb = whichdb +whichdb = my_whichdb + +# was changed for python3 +#_orig_whichdb = whichdb.whichdb +#dbm.whichdb = my_whichdb + +def my_import(mname): + import imp + + if '.' in mname: + i = mname.rfind('.') + parent = my_import(mname[:i]) + fp, pathname, description = imp.find_module(mname[i+1:], + parent.__path__) + else: + fp, pathname, description = imp.find_module(mname) + return imp.load_module(mname, fp, pathname, description) + + +class Flagger(object): + default_value = 1 + + def __setitem__(self, item, value): + self.__dict__[item] = value + self.default_value = 0 + + def __getitem__(self, item): + return self.__dict__.get(item, self.default_value) + + +Do_Call = None +Print_Directories = [] +Print_Entries = [] +Print_Flags = Flagger() +Verbose = 0 +Readable = 0 +Warns = 0 + + +def default_mapper(entry, name): + """ + Stringify an entry that doesn't have an explicit mapping. + + Args: + entry: entry + name: field name + + Returns: str + + """ + try: + val = eval("entry." + name) + except AttributeError: + val = None + if sys.version_info.major >= 3 and isinstance(val, bytes): + # This is a dirty hack for py 2/3 compatibility. csig is a bytes object + # in Python3 while Python2 bytes are str. Hence, we decode the csig to a + # Python3 string + val = val.decode() + return str(val) + + +def map_action(entry, _): + """ + Stringify an action entry and signature. + + Args: + entry: action entry + second argument is not used + + Returns: str + + """ + try: + bact = entry.bact + bactsig = entry.bactsig + except AttributeError: + return None + return '%s [%s]' % (bactsig, bact) + + +def map_timestamp(entry, _): + """ + Stringify a timestamp entry. + + Args: + entry: timestamp entry + second argument is not used + + Returns: str + + """ + try: + timestamp = entry.timestamp + except AttributeError: + timestamp = None + if Readable and timestamp: + return "'" + time.ctime(timestamp) + "'" + else: + return str(timestamp) + + +def map_bkids(entry, _): + """ + Stringify an implicit entry. + + Args: + entry: + second argument is not used + + Returns: str + + """ + try: + bkids = entry.bsources + entry.bdepends + entry.bimplicit + bkidsigs = entry.bsourcesigs + entry.bdependsigs + entry.bimplicitsigs + except AttributeError: + return None + + if len(bkids) != len(bkidsigs): + global Warns + Warns += 1 + # add warning to result rather than direct print so it will line up + msg = "Warning: missing information, {} ids but {} sigs" + result = [msg.format(len(bkids), len(bkidsigs))] + else: + result = [] + result += [nodeinfo_string(bkid, bkidsig, " ") + for bkid, bkidsig in zip(bkids, bkidsigs)] + if not result: + return None + return "\n ".join(result) + + +map_field = { + 'action' : map_action, + 'timestamp' : map_timestamp, + 'bkids' : map_bkids, +} + +map_name = { + 'implicit' : 'bkids', +} + + +def field(name, entry, verbose=Verbose): + if not Print_Flags[name]: + return None + fieldname = map_name.get(name, name) + mapper = map_field.get(fieldname, default_mapper) + val = mapper(entry, name) + if verbose: + val = name + ": " + val + return val + + +def nodeinfo_raw(name, ninfo, prefix=""): + # This just formats the dictionary, which we would normally use str() + # to do, except that we want the keys sorted for deterministic output. + d = ninfo.__getstate__() + try: + keys = ninfo.field_list + ['_version_id'] + except AttributeError: + keys = sorted(d.keys()) + l = [] + for k in keys: + l.append('%s: %s' % (repr(k), repr(d.get(k)))) + if '\n' in name: + name = repr(name) + return name + ': {' + ', '.join(l) + '}' + + +def nodeinfo_cooked(name, ninfo, prefix=""): + try: + field_list = ninfo.field_list + except AttributeError: + field_list = [] + if '\n' in name: + name = repr(name) + outlist = [name + ':'] + [ + f for f in [field(x, ninfo, Verbose) for x in field_list] if f + ] + if Verbose: + sep = '\n ' + prefix + else: + sep = ' ' + return sep.join(outlist) + + +nodeinfo_string = nodeinfo_cooked + + +def printfield(name, entry, prefix=""): + outlist = field("implicit", entry, 0) + if outlist: + if Verbose: + print(" implicit:") + print(" " + outlist) + outact = field("action", entry, 0) + if outact: + if Verbose: + print(" action: " + outact) + else: + print(" " + outact) + + +def printentries(entries, location): + if Print_Entries: + for name in Print_Entries: + try: + entry = entries[name] + except KeyError: + err = "sconsign: no entry `%s' in `%s'\n" % (name, location) + sys.stderr.write(err) + else: + try: + ninfo = entry.ninfo + except AttributeError: + print(name + ":") + else: + print(nodeinfo_string(name, entry.ninfo)) + printfield(name, entry.binfo) + else: + for name in sorted(entries.keys()): + entry = entries[name] + try: + ninfo = entry.ninfo + except AttributeError: + print(name + ":") + else: + print(nodeinfo_string(name, entry.ninfo)) + printfield(name, entry.binfo) + + +class Do_SConsignDB(object): + def __init__(self, dbm_name, dbm): + self.dbm_name = dbm_name + self.dbm = dbm + + def __call__(self, fname): + # The *dbm modules stick their own file suffixes on the names + # that are passed in. This causes us to jump through some + # hoops here. + try: + # Try opening the specified file name. Example: + # SPECIFIED OPENED BY self.dbm.open() + # --------- ------------------------- + # .sconsign => .sconsign.dblite + # .sconsign.dblite => .sconsign.dblite.dblite + db = self.dbm.open(fname, "r") + except (IOError, OSError) as e: + print_e = e + try: + # That didn't work, so try opening the base name, + # so that if they actually passed in 'sconsign.dblite' + # (for example), the dbm module will put the suffix back + # on for us and open it anyway. + db = self.dbm.open(os.path.splitext(fname)[0], "r") + except (IOError, OSError): + # That didn't work either. See if the file name + # they specified even exists (independent of the dbm + # suffix-mangling). + try: + with open(fname, "rb"): + pass # this is a touch only, we don't use it here. + except (IOError, OSError) as e: + # Nope, that file doesn't even exist, so report that + # fact back. + print_e = e + sys.stderr.write("sconsign: %s\n" % print_e) + return + except KeyboardInterrupt: + raise + except pickle.UnpicklingError: + sys.stderr.write("sconsign: ignoring invalid `%s' file `%s'\n" + % (self.dbm_name, fname)) + return + except Exception as e: + sys.stderr.write("sconsign: ignoring invalid `%s' file `%s': %s\n" + % (self.dbm_name, fname, e)) + exc_type, _, _ = sys.exc_info() + if exc_type.__name__ == "ValueError" and sys.version_info < (3,0,0): + sys.stderr.write("Python 2 only supports pickle protocols 0-2.\n") + return + + if Print_Directories: + for dir in Print_Directories: + try: + val = db[dir] + except KeyError: + err = "sconsign: no dir `%s' in `%s'\n" % (dir, args[0]) + sys.stderr.write(err) + else: + self.printentries(dir, val) + else: + for dir in sorted(db.keys()): + self.printentries(dir, db[dir]) + + @staticmethod + def printentries(dir, val): + try: + print('=== ' + dir + ':') + except TypeError: + print('=== ' + dir.decode() + ':') + printentries(pickle.loads(val), dir) + + +def Do_SConsignDir(name): + try: + with open(name, 'rb') as fp: + try: + sconsign = SCons.SConsign.Dir(fp) + except KeyboardInterrupt: + raise + except pickle.UnpicklingError: + err = "sconsign: ignoring invalid .sconsign file `%s'\n" % name + sys.stderr.write(err) + return + except Exception as e: + err = "sconsign: ignoring invalid .sconsign file `%s': %s\n" % (name, e) + sys.stderr.write(err) + return + printentries(sconsign.entries, args[0]) + except (IOError, OSError) as e: + sys.stderr.write("sconsign: %s\n" % e) + return + + +############################################################################## + +import getopt + +helpstr = """\ +Usage: sconsign [OPTIONS] [FILE ...] +Options: + -a, --act, --action Print build action information. + -c, --csig Print content signature information. + -d DIR, --dir=DIR Print only info about DIR. + -e ENTRY, --entry=ENTRY Print only info about ENTRY. + -f FORMAT, --format=FORMAT FILE is in the specified FORMAT. + -h, --help Print this message and exit. + -i, --implicit Print implicit dependency information. + -r, --readable Print timestamps in human-readable form. + --raw Print raw Python object representations. + -s, --size Print file sizes. + -t, --timestamp Print timestamp information. + -v, --verbose Verbose, describe each field. +""" + +try: + opts, args = getopt.getopt(sys.argv[1:], "acd:e:f:hirstv", + ['act', 'action', + 'csig', 'dir=', 'entry=', + 'format=', 'help', 'implicit', + 'raw', 'readable', + 'size', 'timestamp', 'verbose']) +except getopt.GetoptError as err: + sys.stderr.write(str(err) + '\n') + print(helpstr) + sys.exit(2) + +for o, a in opts: + if o in ('-a', '--act', '--action'): + Print_Flags['action'] = 1 + elif o in ('-c', '--csig'): + Print_Flags['csig'] = 1 + elif o in ('-d', '--dir'): + Print_Directories.append(a) + elif o in ('-e', '--entry'): + Print_Entries.append(a) + elif o in ('-f', '--format'): + # Try to map the given DB format to a known module + # name, that we can then try to import... + Module_Map = {'dblite': 'SCons.dblite', 'sconsign': None} + dbm_name = Module_Map.get(a, a) + if dbm_name: + try: + if dbm_name != "SCons.dblite": + dbm = my_import(dbm_name) + else: + import SCons.dblite + + dbm = SCons.dblite + # Ensure that we don't ignore corrupt DB files, + # this was handled by calling my_import('SCons.dblite') + # again in earlier versions... + SCons.dblite.ignore_corrupt_dbfiles = 0 + except ImportError: + sys.stderr.write("sconsign: illegal file format `%s'\n" % a) + print(helpstr) + sys.exit(2) + Do_Call = Do_SConsignDB(a, dbm) + else: + Do_Call = Do_SConsignDir + elif o in ('-h', '--help'): + print(helpstr) + sys.exit(0) + elif o in ('-i', '--implicit'): + Print_Flags['implicit'] = 1 + elif o in ('--raw',): + nodeinfo_string = nodeinfo_raw + elif o in ('-r', '--readable'): + Readable = 1 + elif o in ('-s', '--size'): + Print_Flags['size'] = 1 + elif o in ('-t', '--timestamp'): + Print_Flags['timestamp'] = 1 + elif o in ('-v', '--verbose'): + Verbose = 1 + +if Do_Call: + for a in args: + Do_Call(a) +else: + if not args: + args = [".sconsign.dblite"] + for a in args: + dbm_name = whichdb(a) + if dbm_name: + Map_Module = {'SCons.dblite': 'dblite'} + if dbm_name != "SCons.dblite": + dbm = my_import(dbm_name) + else: + import SCons.dblite + + dbm = SCons.dblite + # Ensure that we don't ignore corrupt DB files, + # this was handled by calling my_import('SCons.dblite') + # again in earlier versions... + SCons.dblite.ignore_corrupt_dbfiles = 0 + Do_SConsignDB(Map_Module.get(dbm_name, dbm_name), dbm)(a) + else: + Do_SConsignDir(a) + + if Warns: + print("NOTE: there were %d warnings, please check output" % Warns) +sys.exit(0) + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/script/MANIFEST.in b/src/script/MANIFEST.in deleted file mode 100644 index d10cc82..0000000 --- a/src/script/MANIFEST.in +++ /dev/null @@ -1,4 +0,0 @@ -scons -sconsign -scons-time -scons-configure-cache diff --git a/src/script/scons-configure-cache.py b/src/script/scons-configure-cache.py deleted file mode 100644 index 716315c..0000000 --- a/src/script/scons-configure-cache.py +++ /dev/null @@ -1,177 +0,0 @@ -#! /usr/bin/env python -# -# SCons - a Software Constructor -# -# __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. - -"""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. -""" - -import argparse -import glob -import json -import os - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - -__version__ = "__VERSION__" - -__build__ = "__BUILD__" - -__buildsys__ = "__BUILDSYS__" - -__date__ = "__DATE__" - -__developer__ = "__DEVELOPER__" - - -def rearrange_cache_entries(current_prefix_len, new_prefix_len): - """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() - old_dirs = set() - for file in glob.iglob(os.path.join('*', '*')): - name = os.path.basename(file) - dname = name[:current_prefix_len].upper() - if dname not in old_dirs: - print('Migrating', dname) - old_dirs.add(dname) - dname = name[:new_prefix_len].upper() - if dname not in dirs: - os.mkdir(dname) - dirs.add(dname) - os.rename(file, os.path.join(dname, name)) - - # Now delete the original directories - for dname in old_dirs: - os.rmdir(dname) - - -# The configuration dictionary should have one entry per entry in the -# cache config. The value of each entry should include the following: -# implicit - (optional) This is to allow adding a new config entry and also -# changing the behaviour of the system at the same time. This -# indicates the value the config entry would have had if it had -# been specified. -# default - The value the config entry should have if it wasn't previously -# specified -# command-line - parameters to pass to ArgumentParser.add_argument -# converter - (optional) Function to call if conversion is required -# if this configuration entry changes -config_entries = { - 'prefix_len': { - 'implicit': 1, - 'default': 2, - 'command-line': { - 'help': 'Length of cache file name used as subdirectory prefix', - 'metavar': '', - 'type': int - }, - 'converter': rearrange_cache_entries - } -} - -parser = argparse.ArgumentParser( - description='Modify the configuration of an scons cache directory', - epilog=''' - Unspecified options will not be changed unless they are not - set at all, in which case they are set to an appropriate default. - ''') - -parser.add_argument('cache-dir', help='Path to scons cache directory') -for param in config_entries: - parser.add_argument('--' + param.replace('_', '-'), - **config_entries[param]['command-line']) -parser.add_argument('--version', - action='version', - version='%(prog)s 1.0') -parser.add_argument('--show', - action="store_true", - help="show current configuration") - -# Get the command line as a dict without any of the unspecified entries. -args = dict([x for x in vars(parser.parse_args()).items() if x[1]]) - -# It seems somewhat strange to me, but positional arguments don't get the - -# in the name changed to _, whereas optional arguments do... -cache = args['cache-dir'] -if not os.path.isdir(cache): - raise RuntimeError("There is no cache directory named %s" % cache) -os.chdir(cache) -del args['cache-dir'] - -if not os.path.exists('config'): - # old config dirs did not have a 'config' file. Try to update. - # Validate the only files in the directory are directories 0-9, a-f - expected = ['{:X}'.format(x) for x in range(0, 16)] - if not set(os.listdir('.')).issubset(expected): - raise RuntimeError( - "%s does not look like a valid version 1 cache directory" % cache) - config = dict() -else: - with open('config') as conf: - config = json.load(conf) - -if args.get('show', None): - print("Current configuration in '%s':" % cache) - print(json.dumps(config, sort_keys=True, - indent=4, separators=(',', ': '))) - # in case of the show argument, emit some stats as well - file_count = 0 - for _, _, files in os.walk('.'): - file_count += len(files) - if file_count: # skip config file if it exists - file_count -= 1 - print("Cache contains %s files" % file_count) - del args['show'] - -# Find any keys that are not currently set but should be -for key in config_entries: - if key not in config: - if 'implicit' in config_entries[key]: - config[key] = config_entries[key]['implicit'] - else: - config[key] = config_entries[key]['default'] - if key not in args: - args[key] = config_entries[key]['default'] - -# Now go through each entry in args to see if it changes an existing config -# setting. -for key in args: - if args[key] != config[key]: - if 'converter' in config_entries[key]: - config_entries[key]['converter'](config[key], args[key]) - config[key] = args[key] - -# and write the updated config file -with open('config', 'w') as conf: - json.dump(config, conf) diff --git a/src/script/scons-time.py b/src/script/scons-time.py deleted file mode 100644 index e4dd863..0000000 --- a/src/script/scons-time.py +++ /dev/null @@ -1,1480 +0,0 @@ -#!/usr/bin/env python -# -# scons-time - run SCons timings and collect statistics -# -# A script for running a configuration through SCons with a standard -# set of invocations to collect timing and memory statistics and to -# capture the results in a consistent set of output files for display -# and analysis. -# - -# -# __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 getopt -import glob -import os -import re -import shutil -import sys -import tempfile -import time -import subprocess - -def HACK_for_exec(cmd, *args): - """ - For some reason, Python won't allow an exec() within a function - that also declares an internal function (including lambda functions). - This function is a hack that calls exec() in a function with no - internal functions. - """ - if not args: exec(cmd) - elif len(args) == 1: exec(cmd, args[0]) - else: exec(cmd, args[0], args[1]) - -class Plotter(object): - def increment_size(self, largest): - """ - Return the size of each horizontal increment line for a specified - maximum value. This returns a value that will provide somewhere - between 5 and 9 horizontal lines on the graph, on some set of - boundaries that are multiples of 10/100/1000/etc. - """ - i = largest // 5 - if not i: - return largest - multiplier = 1 - while i >= 10: - i = i // 10 - multiplier = multiplier * 10 - return i * multiplier - - def max_graph_value(self, largest): - # Round up to next integer. - largest = int(largest) + 1 - increment = self.increment_size(largest) - return ((largest + increment - 1) // increment) * increment - -class Line(object): - def __init__(self, points, type, title, label, comment, fmt="%s %s"): - self.points = points - self.type = type - self.title = title - self.label = label - self.comment = comment - self.fmt = fmt - - def print_label(self, inx, x, y): - if self.label: - print('set label %s "%s" at %0.1f,%0.1f right' % (inx, self.label, x, y)) - - def plot_string(self): - if self.title: - title_string = 'title "%s"' % self.title - else: - title_string = 'notitle' - return "'-' %s with lines lt %s" % (title_string, self.type) - - def print_points(self, fmt=None): - if fmt is None: - fmt = self.fmt - if self.comment: - print('# %s' % self.comment) - for x, y in self.points: - # If y is None, it usually represents some kind of break - # in the line's index number. We might want to represent - # this some way rather than just drawing the line straight - # between the two points on either side. - if y is not None: - print(fmt % (x, y)) - print('e') - - def get_x_values(self): - return [ p[0] for p in self.points ] - - def get_y_values(self): - return [ p[1] for p in self.points ] - -class Gnuplotter(Plotter): - - def __init__(self, title, key_location): - self.lines = [] - self.title = title - self.key_location = key_location - - def line(self, points, type, title=None, label=None, comment=None, fmt='%s %s'): - if points: - line = Line(points, type, title, label, comment, fmt) - self.lines.append(line) - - def plot_string(self, line): - return line.plot_string() - - def vertical_bar(self, x, type, label, comment): - if self.get_min_x() <= x <= self.get_max_x(): - points = [(x, 0), (x, self.max_graph_value(self.get_max_y()))] - self.line(points, type, label, comment) - - def get_all_x_values(self): - result = [] - for line in self.lines: - result.extend(line.get_x_values()) - return [r for r in result if r is not None] - - def get_all_y_values(self): - result = [] - for line in self.lines: - result.extend(line.get_y_values()) - return [r for r in result if r is not None] - - def get_min_x(self): - try: - return self.min_x - except AttributeError: - try: - self.min_x = min(self.get_all_x_values()) - except ValueError: - self.min_x = 0 - return self.min_x - - def get_max_x(self): - try: - return self.max_x - except AttributeError: - try: - self.max_x = max(self.get_all_x_values()) - except ValueError: - self.max_x = 0 - return self.max_x - - def get_min_y(self): - try: - return self.min_y - except AttributeError: - try: - self.min_y = min(self.get_all_y_values()) - except ValueError: - self.min_y = 0 - return self.min_y - - def get_max_y(self): - try: - return self.max_y - except AttributeError: - try: - self.max_y = max(self.get_all_y_values()) - except ValueError: - self.max_y = 0 - return self.max_y - - def draw(self): - - if not self.lines: - return - - if self.title: - print('set title "%s"' % self.title) - print('set key %s' % self.key_location) - - min_y = self.get_min_y() - max_y = self.max_graph_value(self.get_max_y()) - incr = (max_y - min_y) / 10.0 - start = min_y + (max_y / 2.0) + (2.0 * incr) - position = [ start - (i * incr) for i in range(5) ] - - inx = 1 - for line in self.lines: - line.print_label(inx, line.points[0][0]-1, - position[(inx-1) % len(position)]) - inx += 1 - - plot_strings = [ self.plot_string(l) for l in self.lines ] - print('plot ' + ', \\\n '.join(plot_strings)) - - for line in self.lines: - line.print_points() - - - -def untar(fname): - import tarfile - tar = tarfile.open(name=fname, mode='r') - for tarinfo in tar: - tar.extract(tarinfo) - tar.close() - -def unzip(fname): - import zipfile - zf = zipfile.ZipFile(fname, 'r') - for name in zf.namelist(): - dir = os.path.dirname(name) - try: - os.makedirs(dir) - except: - pass - with open(name, 'wb') as f: - f.write(zf.read(name)) - -def read_tree(dir): - for dirpath, dirnames, filenames in os.walk(dir): - for fn in filenames: - fn = os.path.join(dirpath, fn) - if os.path.isfile(fn): - with open(fn, 'rb') as f: - f.read() - -def redirect_to_file(command, log): - return '%s > %s 2>&1' % (command, log) - -def tee_to_file(command, log): - return '%s 2>&1 | tee %s' % (command, log) - - - -class SConsTimer(object): - """ - Usage: scons-time SUBCOMMAND [ARGUMENTS] - Type "scons-time help SUBCOMMAND" for help on a specific subcommand. - - Available subcommands: - func Extract test-run data for a function - help Provides help - mem Extract --debug=memory data from test runs - obj Extract --debug=count data from test runs - time Extract --debug=time data from test runs - run Runs a test configuration - """ - - name = 'scons-time' - name_spaces = ' '*len(name) - - def makedict(**kw): - return kw - - default_settings = makedict( - chdir = None, - config_file = None, - initial_commands = [], - key_location = 'bottom left', - orig_cwd = os.getcwd(), - outdir = None, - prefix = '', - python = '"%s"' % sys.executable, - redirect = redirect_to_file, - scons = None, - scons_flags = '--debug=count --debug=memory --debug=time --debug=memoizer', - scons_lib_dir = None, - scons_wrapper = None, - startup_targets = '--help', - subdir = None, - subversion_url = None, - svn = 'svn', - svn_co_flag = '-q', - tar = 'tar', - targets = '', - targets0 = None, - targets1 = None, - targets2 = None, - title = None, - unzip = 'unzip', - verbose = False, - vertical_bars = [], - - unpack_map = { - '.tar.gz' : (untar, '%(tar)s xzf %%s'), - '.tgz' : (untar, '%(tar)s xzf %%s'), - '.tar' : (untar, '%(tar)s xf %%s'), - '.zip' : (unzip, '%(unzip)s %%s'), - }, - ) - - run_titles = [ - 'Startup', - 'Full build', - 'Up-to-date build', - ] - - run_commands = [ - '%(python)s %(scons_wrapper)s %(scons_flags)s --profile=%(prof0)s %(targets0)s', - '%(python)s %(scons_wrapper)s %(scons_flags)s --profile=%(prof1)s %(targets1)s', - '%(python)s %(scons_wrapper)s %(scons_flags)s --profile=%(prof2)s %(targets2)s', - ] - - stages = [ - 'pre-read', - 'post-read', - 'pre-build', - 'post-build', - ] - - stage_strings = { - 'pre-read' : 'Memory before reading SConscript files:', - 'post-read' : 'Memory after reading SConscript files:', - 'pre-build' : 'Memory before building targets:', - 'post-build' : 'Memory after building targets:', - } - - memory_string_all = 'Memory ' - - default_stage = stages[-1] - - time_strings = { - 'total' : 'Total build time', - 'SConscripts' : 'Total SConscript file execution time', - 'SCons' : 'Total SCons execution time', - 'commands' : 'Total command execution time', - } - - time_string_all = 'Total .* time' - - # - - def __init__(self): - self.__dict__.update(self.default_settings) - - # Functions for displaying and executing commands. - - def subst(self, x, dictionary): - try: - return x % dictionary - except TypeError: - # x isn't a string (it's probably a Python function), - # so just return it. - return x - - def subst_variables(self, command, dictionary): - """ - Substitutes (via the format operator) the values in the specified - dictionary into the specified command. - - The command can be an (action, string) tuple. In all cases, we - perform substitution on strings and don't worry if something isn't - a string. (It's probably a Python function to be executed.) - """ - try: - command + '' - except TypeError: - action = command[0] - string = command[1] - args = command[2:] - else: - action = command - string = action - args = (()) - action = self.subst(action, dictionary) - string = self.subst(string, dictionary) - return (action, string, args) - - def _do_not_display(self, msg, *args): - pass - - def display(self, msg, *args): - """ - Displays the specified message. - - Each message is prepended with a standard prefix of our name - plus the time. - """ - if callable(msg): - msg = msg(*args) - else: - msg = msg % args - if msg is None: - return - fmt = '%s[%s]: %s\n' - sys.stdout.write(fmt % (self.name, time.strftime('%H:%M:%S'), msg)) - - def _do_not_execute(self, action, *args): - pass - - def execute(self, action, *args): - """ - Executes the specified action. - - The action is called if it's a callable Python function, and - otherwise passed to os.system(). - """ - if callable(action): - action(*args) - else: - os.system(action % args) - - def run_command_list(self, commands, dict): - """ - Executes a list of commands, substituting values from the - specified dictionary. - """ - commands = [ self.subst_variables(c, dict) for c in commands ] - for action, string, args in commands: - self.display(string, *args) - sys.stdout.flush() - status = self.execute(action, *args) - if status: - sys.exit(status) - - def log_display(self, command, log): - command = self.subst(command, self.__dict__) - if log: - command = self.redirect(command, log) - return command - - def log_execute(self, command, log): - command = self.subst(command, self.__dict__) - p = os.popen(command) - output = p.read() - p.close() - #TODO: convert to subrocess, os.popen is obsolete. This didn't work: - #process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True) - #output = process.stdout.read() - #process.stdout.close() - #process.wait() - if self.verbose: - sys.stdout.write(output) - # TODO: Figure out - # Not sure we need to write binary here - with open(log, 'w') as f: - f.write(str(output)) - - def archive_splitext(self, path): - """ - Splits an archive name into a filename base and extension. - - This is like os.path.splitext() (which it calls) except that it - also looks for '.tar.gz' and treats it as an atomic extensions. - """ - if path.endswith('.tar.gz'): - return path[:-7], path[-7:] - else: - return os.path.splitext(path) - - def args_to_files(self, args, tail=None): - """ - Takes a list of arguments, expands any glob patterns, and - returns the last "tail" files from the list. - """ - files = [] - for a in args: - files.extend(sorted(glob.glob(a))) - - if tail: - files = files[-tail:] - - return files - - def ascii_table(self, files, columns, - line_function, file_function=lambda x: x, - *args, **kw): - - header_fmt = ' '.join(['%12s'] * len(columns)) - line_fmt = header_fmt + ' %s' - - print(header_fmt % columns) - - for file in files: - t = line_function(file, *args, **kw) - if t is None: - t = [] - diff = len(columns) - len(t) - if diff > 0: - t += [''] * diff - t.append(file_function(file)) - print(line_fmt % tuple(t)) - - def collect_results(self, files, function, *args, **kw): - results = {} - - for file in files: - base = os.path.splitext(file)[0] - run, index = base.split('-')[-2:] - - run = int(run) - index = int(index) - - value = function(file, *args, **kw) - - try: - r = results[index] - except KeyError: - r = [] - results[index] = r - r.append((run, value)) - - return results - - def doc_to_help(self, obj): - """ - Translates an object's __doc__ string into help text. - - This strips a consistent number of spaces from each line in the - help text, essentially "outdenting" the text to the left-most - column. - """ - doc = obj.__doc__ - if doc is None: - return '' - return self.outdent(doc) - - def find_next_run_number(self, dir, prefix): - """ - Returns the next run number in a directory for the specified prefix. - - Examines the contents the specified directory for files with the - specified prefix, extracts the run numbers from each file name, - and returns the next run number after the largest it finds. - """ - x = re.compile(re.escape(prefix) + '-([0-9]+).*') - matches = [x.match(e) for e in os.listdir(dir)] - matches = [_f for _f in matches if _f] - if not matches: - return 0 - run_numbers = [int(m.group(1)) for m in matches] - return int(max(run_numbers)) + 1 - - def gnuplot_results(self, results, fmt='%s %.3f'): - """ - Prints out a set of results in Gnuplot format. - """ - gp = Gnuplotter(self.title, self.key_location) - - for i in sorted(results.keys()): - try: - t = self.run_titles[i] - except IndexError: - t = '??? %s ???' % i - results[i].sort() - gp.line(results[i], i+1, t, None, t, fmt=fmt) - - for bar_tuple in self.vertical_bars: - try: - x, type, label, comment = bar_tuple - except ValueError: - x, type, label = bar_tuple - comment = label - gp.vertical_bar(x, type, label, comment) - - gp.draw() - - def logfile_name(self, invocation): - """ - Returns the absolute path of a log file for the specificed - invocation number. - """ - name = self.prefix_run + '-%d.log' % invocation - return os.path.join(self.outdir, name) - - def outdent(self, s): - """ - Strip as many spaces from each line as are found at the beginning - of the first line in the list. - """ - lines = s.split('\n') - if lines[0] == '': - lines = lines[1:] - spaces = re.match(' *', lines[0]).group(0) - def strip_initial_spaces(l, s=spaces): - if l.startswith(spaces): - l = l[len(spaces):] - return l - return '\n'.join([ strip_initial_spaces(l) for l in lines ]) + '\n' - - def profile_name(self, invocation): - """ - Returns the absolute path of a profile file for the specified - invocation number. - """ - name = self.prefix_run + '-%d.prof' % invocation - return os.path.join(self.outdir, name) - - def set_env(self, key, value): - os.environ[key] = value - - # - - def get_debug_times(self, file, time_string=None): - """ - Fetch times from the --debug=time strings in the specified file. - """ - if time_string is None: - search_string = self.time_string_all - else: - search_string = time_string - with open(file) as f: - contents = f.read() - 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 = [ float(r) for r in result ] - if time_string is not None: - try: - result = result[0] - except IndexError: - sys.stderr.write('file %s has no results!\n' % repr(file)) - return None - return result - - def get_function_profile(self, file, function): - """ - Returns the file, line number, function name, and cumulative time. - """ - try: - import pstats - except ImportError as e: - sys.stderr.write('%s: func: %s\n' % (self.name, e)) - sys.stderr.write('%s This version of Python is missing the profiler.\n' % self.name_spaces) - sys.stderr.write('%s Cannot use the "func" subcommand.\n' % self.name_spaces) - sys.exit(1) - statistics = pstats.Stats(file).stats - matches = [ e for e in statistics.items() if e[0][2] == function ] - r = matches[0] - return r[0][0], r[0][1], r[0][2], r[1][3] - - def get_function_time(self, file, function): - """ - Returns just the cumulative time for the specified function. - """ - return self.get_function_profile(file, function)[3] - - def get_memory(self, file, memory_string=None): - """ - Returns a list of integers of the amount of memory used. The - default behavior is to return all the stages. - """ - if memory_string is None: - search_string = self.memory_string_all - else: - search_string = memory_string - with open(file) as f: - lines = f.readlines() - lines = [ l for l in lines if l.startswith(search_string) ][-4:] - result = [ int(l.split()[-1]) for l in lines[-4:] ] - if len(result) == 1: - result = result[0] - return result - - def get_object_counts(self, file, object_name, index=None): - """ - Returns the counts of the specified object_name. - """ - object_string = ' ' + object_name + '\n' - with open(file) as f: - lines = f.readlines() - line = [ l for l in lines if l.endswith(object_string) ][0] - result = [ int(field) for field in line.split()[:4] ] - if index is not None: - result = result[index] - return result - - - command_alias = {} - - def execute_subcommand(self, argv): - """ - Executes the do_*() function for the specified subcommand (argv[0]). - """ - if not argv: - return - cmdName = self.command_alias.get(argv[0], argv[0]) - try: - func = getattr(self, 'do_' + cmdName) - except AttributeError: - return self.default(argv) - try: - return func(argv) - except TypeError as e: - sys.stderr.write("%s %s: %s\n" % (self.name, cmdName, e)) - import traceback - traceback.print_exc(file=sys.stderr) - sys.stderr.write("Try '%s help %s'\n" % (self.name, cmdName)) - - def default(self, argv): - """ - The default behavior for an unknown subcommand. Prints an - error message and exits. - """ - sys.stderr.write('%s: Unknown subcommand "%s".\n' % (self.name, argv[0])) - sys.stderr.write('Type "%s help" for usage.\n' % self.name) - sys.exit(1) - - # - - def do_help(self, argv): - """ - """ - if argv[1:]: - for arg in argv[1:]: - try: - func = getattr(self, 'do_' + arg) - except AttributeError: - sys.stderr.write('%s: No help for "%s"\n' % (self.name, arg)) - else: - try: - help = getattr(self, 'help_' + arg) - except AttributeError: - sys.stdout.write(self.doc_to_help(func)) - sys.stdout.flush() - else: - help() - else: - doc = self.doc_to_help(self.__class__) - if doc: - sys.stdout.write(doc) - sys.stdout.flush() - return None - - # - - def help_func(self): - help = """\ - Usage: scons-time func [OPTIONS] FILE [...] - - -C DIR, --chdir=DIR Change to DIR before looking for files - -f FILE, --file=FILE Read configuration from specified FILE - --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT - --func=NAME, --function=NAME Report time for function NAME - -h, --help Print this help and exit - -p STRING, --prefix=STRING Use STRING as log file/profile prefix - -t NUMBER, --tail=NUMBER Only report the last NUMBER files - --title=TITLE Specify the output plot TITLE - """ - sys.stdout.write(self.outdent(help)) - sys.stdout.flush() - - def do_func(self, argv): - """ - """ - format = 'ascii' - function_name = '_main' - tail = None - - short_opts = '?C:f:hp:t:' - - long_opts = [ - 'chdir=', - 'file=', - 'fmt=', - 'format=', - 'func=', - 'function=', - 'help', - 'prefix=', - 'tail=', - 'title=', - ] - - opts, args = getopt.getopt(argv[1:], short_opts, long_opts) - - for o, a in opts: - if o in ('-C', '--chdir'): - self.chdir = a - elif o in ('-f', '--file'): - self.config_file = a - elif o in ('--fmt', '--format'): - format = a - elif o in ('--func', '--function'): - function_name = a - elif o in ('-?', '-h', '--help'): - self.do_help(['help', 'func']) - sys.exit(0) - elif o in ('--max',): - max_time = int(a) - elif o in ('-p', '--prefix'): - self.prefix = a - elif o in ('-t', '--tail'): - tail = int(a) - elif o in ('--title',): - self.title = a - - if self.config_file: - with open(self.config_file, 'r') as f: - config = f.read() - exec(config, self.__dict__) - - if self.chdir: - os.chdir(self.chdir) - - if not args: - - pattern = '%s*.prof' % self.prefix - args = self.args_to_files([pattern], tail) - - if not args: - if self.chdir: - directory = self.chdir - else: - directory = os.getcwd() - - sys.stderr.write('%s: func: No arguments specified.\n' % self.name) - sys.stderr.write('%s No %s*.prof files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) - sys.stderr.write('%s Type "%s help func" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - - else: - - args = self.args_to_files(args, tail) - - cwd_ = os.getcwd() + os.sep - - if format == 'ascii': - - for file in args: - try: - f, line, func, time = \ - self.get_function_profile(file, function_name) - except ValueError as e: - sys.stderr.write("%s: func: %s: %s\n" % - (self.name, file, e)) - else: - if f.startswith(cwd_): - f = f[len(cwd_):] - print("%.3f %s:%d(%s)" % (time, f, line, func)) - - elif format == 'gnuplot': - - results = self.collect_results(args, self.get_function_time, - function_name) - - self.gnuplot_results(results) - - else: - - sys.stderr.write('%s: func: Unknown format "%s".\n' % (self.name, format)) - sys.exit(1) - - # - - def help_mem(self): - help = """\ - Usage: scons-time mem [OPTIONS] FILE [...] - - -C DIR, --chdir=DIR Change to DIR before looking for files - -f FILE, --file=FILE Read configuration from specified FILE - --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT - -h, --help Print this help and exit - -p STRING, --prefix=STRING Use STRING as log file/profile prefix - --stage=STAGE Plot memory at the specified stage: - pre-read, post-read, pre-build, - post-build (default: post-build) - -t NUMBER, --tail=NUMBER Only report the last NUMBER files - --title=TITLE Specify the output plot TITLE - """ - sys.stdout.write(self.outdent(help)) - sys.stdout.flush() - - def do_mem(self, argv): - - format = 'ascii' - logfile_path = lambda x: x - stage = self.default_stage - tail = None - - short_opts = '?C:f:hp:t:' - - long_opts = [ - 'chdir=', - 'file=', - 'fmt=', - 'format=', - 'help', - 'prefix=', - 'stage=', - 'tail=', - 'title=', - ] - - opts, args = getopt.getopt(argv[1:], short_opts, long_opts) - - for o, a in opts: - if o in ('-C', '--chdir'): - self.chdir = a - elif o in ('-f', '--file'): - self.config_file = a - elif o in ('--fmt', '--format'): - format = a - elif o in ('-?', '-h', '--help'): - self.do_help(['help', 'mem']) - sys.exit(0) - elif o in ('-p', '--prefix'): - self.prefix = a - elif o in ('--stage',): - if a not in self.stages: - sys.stderr.write('%s: mem: Unrecognized stage "%s".\n' % (self.name, a)) - sys.exit(1) - stage = a - elif o in ('-t', '--tail'): - tail = int(a) - elif o in ('--title',): - self.title = a - - if self.config_file: - with open(self.config_file, 'r') as f: - config = f.read() - HACK_for_exec(config, self.__dict__) - - if self.chdir: - os.chdir(self.chdir) - logfile_path = lambda x: os.path.join(self.chdir, x) - - if not args: - - pattern = '%s*.log' % self.prefix - args = self.args_to_files([pattern], tail) - - if not args: - if self.chdir: - directory = self.chdir - else: - directory = os.getcwd() - - sys.stderr.write('%s: mem: No arguments specified.\n' % self.name) - sys.stderr.write('%s No %s*.log files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) - sys.stderr.write('%s Type "%s help mem" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - - else: - - args = self.args_to_files(args, tail) - - cwd_ = os.getcwd() + os.sep - - if format == 'ascii': - - self.ascii_table(args, tuple(self.stages), self.get_memory, logfile_path) - - elif format == 'gnuplot': - - results = self.collect_results(args, self.get_memory, - self.stage_strings[stage]) - - self.gnuplot_results(results) - - else: - - sys.stderr.write('%s: mem: Unknown format "%s".\n' % (self.name, format)) - sys.exit(1) - - return 0 - - # - - def help_obj(self): - help = """\ - Usage: scons-time obj [OPTIONS] OBJECT FILE [...] - - -C DIR, --chdir=DIR Change to DIR before looking for files - -f FILE, --file=FILE Read configuration from specified FILE - --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT - -h, --help Print this help and exit - -p STRING, --prefix=STRING Use STRING as log file/profile prefix - --stage=STAGE Plot memory at the specified stage: - pre-read, post-read, pre-build, - post-build (default: post-build) - -t NUMBER, --tail=NUMBER Only report the last NUMBER files - --title=TITLE Specify the output plot TITLE - """ - sys.stdout.write(self.outdent(help)) - sys.stdout.flush() - - def do_obj(self, argv): - - format = 'ascii' - logfile_path = lambda x: x - stage = self.default_stage - tail = None - - short_opts = '?C:f:hp:t:' - - long_opts = [ - 'chdir=', - 'file=', - 'fmt=', - 'format=', - 'help', - 'prefix=', - 'stage=', - 'tail=', - 'title=', - ] - - opts, args = getopt.getopt(argv[1:], short_opts, long_opts) - - for o, a in opts: - if o in ('-C', '--chdir'): - self.chdir = a - elif o in ('-f', '--file'): - self.config_file = a - elif o in ('--fmt', '--format'): - format = a - elif o in ('-?', '-h', '--help'): - self.do_help(['help', 'obj']) - sys.exit(0) - elif o in ('-p', '--prefix'): - self.prefix = a - elif o in ('--stage',): - if a not in self.stages: - sys.stderr.write('%s: obj: Unrecognized stage "%s".\n' % (self.name, a)) - sys.stderr.write('%s Type "%s help obj" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - stage = a - elif o in ('-t', '--tail'): - tail = int(a) - elif o in ('--title',): - self.title = a - - if not args: - sys.stderr.write('%s: obj: Must specify an object name.\n' % self.name) - sys.stderr.write('%s Type "%s help obj" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - - object_name = args.pop(0) - - if self.config_file: - with open(self.config_file, 'r') as f: - config = f.read() - HACK_for_exec(config, self.__dict__) - - if self.chdir: - os.chdir(self.chdir) - logfile_path = lambda x: os.path.join(self.chdir, x) - - if not args: - - pattern = '%s*.log' % self.prefix - args = self.args_to_files([pattern], tail) - - if not args: - if self.chdir: - directory = self.chdir - else: - directory = os.getcwd() - - sys.stderr.write('%s: obj: No arguments specified.\n' % self.name) - sys.stderr.write('%s No %s*.log files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) - sys.stderr.write('%s Type "%s help obj" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - - else: - - args = self.args_to_files(args, tail) - - cwd_ = os.getcwd() + os.sep - - if format == 'ascii': - - self.ascii_table(args, tuple(self.stages), self.get_object_counts, logfile_path, object_name) - - elif format == 'gnuplot': - - stage_index = 0 - for s in self.stages: - if stage == s: - break - stage_index = stage_index + 1 - - results = self.collect_results(args, self.get_object_counts, - object_name, stage_index) - - self.gnuplot_results(results) - - else: - - sys.stderr.write('%s: obj: Unknown format "%s".\n' % (self.name, format)) - sys.exit(1) - - return 0 - - # - - def help_run(self): - help = """\ - Usage: scons-time run [OPTIONS] [FILE ...] - - --chdir=DIR Name of unpacked directory for chdir - -f FILE, --file=FILE Read configuration from specified FILE - -h, --help Print this help and exit - -n, --no-exec No execute, just print command lines - --number=NUMBER Put output in files for run NUMBER - --outdir=OUTDIR Put output files in OUTDIR - -p STRING, --prefix=STRING Use STRING as log file/profile prefix - --python=PYTHON Time using the specified PYTHON - -q, --quiet Don't print command lines - --scons=SCONS Time using the specified SCONS - --svn=URL, --subversion=URL Use SCons from Subversion URL - -v, --verbose Display output of commands - """ - sys.stdout.write(self.outdent(help)) - sys.stdout.flush() - - def do_run(self, argv): - """ - """ - run_number_list = [None] - - short_opts = '?f:hnp:qs:v' - - long_opts = [ - 'file=', - 'help', - 'no-exec', - 'number=', - 'outdir=', - 'prefix=', - 'python=', - 'quiet', - 'scons=', - 'svn=', - 'subdir=', - 'subversion=', - 'verbose', - ] - - opts, args = getopt.getopt(argv[1:], short_opts, long_opts) - - for o, a in opts: - if o in ('-f', '--file'): - self.config_file = a - elif o in ('-?', '-h', '--help'): - self.do_help(['help', 'run']) - sys.exit(0) - elif o in ('-n', '--no-exec'): - self.execute = self._do_not_execute - elif o in ('--number',): - run_number_list = self.split_run_numbers(a) - elif o in ('--outdir',): - self.outdir = a - elif o in ('-p', '--prefix'): - self.prefix = a - elif o in ('--python',): - self.python = a - elif o in ('-q', '--quiet'): - self.display = self._do_not_display - elif o in ('-s', '--subdir'): - self.subdir = a - elif o in ('--scons',): - self.scons = a - elif o in ('--svn', '--subversion'): - self.subversion_url = a - elif o in ('-v', '--verbose'): - self.redirect = tee_to_file - self.verbose = True - self.svn_co_flag = '' - - if not args and not self.config_file: - sys.stderr.write('%s: run: No arguments or -f config file specified.\n' % self.name) - sys.stderr.write('%s Type "%s help run" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - - if self.config_file: - with open(self.config_file, 'r') as f: - config = f.read() - exec(config, self.__dict__) - - if args: - self.archive_list = args - - archive_file_name = os.path.split(self.archive_list[0])[1] - - if not self.subdir: - self.subdir = self.archive_splitext(archive_file_name)[0] - - if not self.prefix: - self.prefix = self.archive_splitext(archive_file_name)[0] - - prepare = None - if self.subversion_url: - prepare = self.prep_subversion_run - - for run_number in run_number_list: - self.individual_run(run_number, self.archive_list, prepare) - - def split_run_numbers(self, s): - result = [] - for n in s.split(','): - try: - x, y = n.split('-') - except ValueError: - result.append(int(n)) - else: - result.extend(list(range(int(x), int(y)+1))) - return result - - def scons_path(self, dir): - return os.path.join(dir, 'src', 'script', 'scons.py') - - def scons_lib_dir_path(self, dir): - return os.path.join(dir, 'src', 'engine') - - def prep_subversion_run(self, commands, removals): - self.svn_tmpdir = tempfile.mkdtemp(prefix=self.name + '-svn-') - removals.append((shutil.rmtree, 'rm -rf %%s', self.svn_tmpdir)) - - self.scons = self.scons_path(self.svn_tmpdir) - self.scons_lib_dir = self.scons_lib_dir_path(self.svn_tmpdir) - - commands.extend([ - '%(svn)s co %(svn_co_flag)s -r %(run_number)s %(subversion_url)s %(svn_tmpdir)s', - ]) - - def individual_run(self, run_number, archive_list, prepare=None): - """ - Performs an individual run of the default SCons invocations. - """ - - commands = [] - removals = [] - - if prepare: - prepare(commands, removals) - - save_scons = self.scons - save_scons_wrapper = self.scons_wrapper - save_scons_lib_dir = self.scons_lib_dir - - if self.outdir is None: - self.outdir = self.orig_cwd - elif not os.path.isabs(self.outdir): - self.outdir = os.path.join(self.orig_cwd, self.outdir) - - if self.scons is None: - self.scons = self.scons_path(self.orig_cwd) - - if self.scons_lib_dir is None: - self.scons_lib_dir = self.scons_lib_dir_path(self.orig_cwd) - - if self.scons_wrapper is None: - self.scons_wrapper = self.scons - - if not run_number: - run_number = self.find_next_run_number(self.outdir, self.prefix) - - self.run_number = str(run_number) - - self.prefix_run = self.prefix + '-%03d' % run_number - - if self.targets0 is None: - self.targets0 = self.startup_targets - if self.targets1 is None: - self.targets1 = self.targets - if self.targets2 is None: - self.targets2 = self.targets - - self.tmpdir = tempfile.mkdtemp(prefix=self.name + '-') - - commands.extend([ - (os.chdir, 'cd %%s', self.tmpdir), - ]) - - for archive in archive_list: - if not os.path.isabs(archive): - archive = os.path.join(self.orig_cwd, archive) - if os.path.isdir(archive): - dest = os.path.split(archive)[1] - commands.append((shutil.copytree, 'cp -r %%s %%s', archive, dest)) - else: - suffix = self.archive_splitext(archive)[1] - unpack_command = self.unpack_map.get(suffix) - if not unpack_command: - dest = os.path.split(archive)[1] - commands.append((shutil.copyfile, 'cp %%s %%s', archive, dest)) - else: - commands.append(unpack_command + (archive,)) - - commands.extend([ - (os.chdir, 'cd %%s', self.subdir), - ]) - - commands.extend(self.initial_commands) - - commands.extend([ - (lambda: read_tree('.'), - 'find * -type f | xargs cat > /dev/null'), - - (self.set_env, 'export %%s=%%s', - 'SCONS_LIB_DIR', self.scons_lib_dir), - - '%(python)s %(scons_wrapper)s --version', - ]) - - index = 0 - for run_command in self.run_commands: - setattr(self, 'prof%d' % index, self.profile_name(index)) - c = ( - self.log_execute, - self.log_display, - run_command, - self.logfile_name(index), - ) - commands.append(c) - index = index + 1 - - commands.extend([ - (os.chdir, 'cd %%s', self.orig_cwd), - ]) - - if not os.environ.get('PRESERVE'): - commands.extend(removals) - commands.append((shutil.rmtree, 'rm -rf %%s', self.tmpdir)) - - self.run_command_list(commands, self.__dict__) - - self.scons = save_scons - self.scons_lib_dir = save_scons_lib_dir - self.scons_wrapper = save_scons_wrapper - - # - - def help_time(self): - help = """\ - Usage: scons-time time [OPTIONS] FILE [...] - - -C DIR, --chdir=DIR Change to DIR before looking for files - -f FILE, --file=FILE Read configuration from specified FILE - --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT - -h, --help Print this help and exit - -p STRING, --prefix=STRING Use STRING as log file/profile prefix - -t NUMBER, --tail=NUMBER Only report the last NUMBER files - --which=TIMER Plot timings for TIMER: total, - SConscripts, SCons, commands. - """ - sys.stdout.write(self.outdent(help)) - sys.stdout.flush() - - def do_time(self, argv): - - format = 'ascii' - logfile_path = lambda x: x - tail = None - which = 'total' - - short_opts = '?C:f:hp:t:' - - long_opts = [ - 'chdir=', - 'file=', - 'fmt=', - 'format=', - 'help', - 'prefix=', - 'tail=', - 'title=', - 'which=', - ] - - opts, args = getopt.getopt(argv[1:], short_opts, long_opts) - - for o, a in opts: - if o in ('-C', '--chdir'): - self.chdir = a - elif o in ('-f', '--file'): - self.config_file = a - elif o in ('--fmt', '--format'): - format = a - elif o in ('-?', '-h', '--help'): - self.do_help(['help', 'time']) - sys.exit(0) - elif o in ('-p', '--prefix'): - self.prefix = a - elif o in ('-t', '--tail'): - tail = int(a) - elif o in ('--title',): - self.title = a - elif o in ('--which',): - if a not in list(self.time_strings.keys()): - sys.stderr.write('%s: time: Unrecognized timer "%s".\n' % (self.name, a)) - sys.stderr.write('%s Type "%s help time" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - which = a - - if self.config_file: - with open(self.config_file, 'r') as f: - config = f.read() - HACK_for_exec(config, self.__dict__) - - if self.chdir: - os.chdir(self.chdir) - logfile_path = lambda x: os.path.join(self.chdir, x) - - if not args: - - pattern = '%s*.log' % self.prefix - args = self.args_to_files([pattern], tail) - - if not args: - if self.chdir: - directory = self.chdir - else: - directory = os.getcwd() - - sys.stderr.write('%s: time: No arguments specified.\n' % self.name) - sys.stderr.write('%s No %s*.log files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) - sys.stderr.write('%s Type "%s help time" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - - else: - - args = self.args_to_files(args, tail) - - cwd_ = os.getcwd() + os.sep - - if format == 'ascii': - - columns = ("Total", "SConscripts", "SCons", "commands") - self.ascii_table(args, columns, self.get_debug_times, logfile_path) - - elif format == 'gnuplot': - - results = self.collect_results(args, self.get_debug_times, - self.time_strings[which]) - - self.gnuplot_results(results, fmt='%s %.6f') - - else: - - sys.stderr.write('%s: time: Unknown format "%s".\n' % (self.name, format)) - sys.exit(1) - -if __name__ == '__main__': - opts, args = getopt.getopt(sys.argv[1:], 'h?V', ['help', 'version']) - - ST = SConsTimer() - - for o, a in opts: - if o in ('-?', '-h', '--help'): - ST.do_help(['help']) - sys.exit(0) - elif o in ('-V', '--version'): - sys.stdout.write('scons-time version\n') - sys.exit(0) - - if not args: - sys.stderr.write('Type "%s help" for usage.\n' % ST.name) - sys.exit(1) - - ST.execute_subcommand(args) - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/script/scons.bat b/src/script/scons.bat deleted file mode 100644 index 10b8637..0000000 --- a/src/script/scons.bat +++ /dev/null @@ -1,38 +0,0 @@ -@REM __COPYRIGHT__ -@REM __FILE__ __REVISION__ __DATE__ __DEVELOPER__ -@echo off -set SCONS_ERRORLEVEL= -if "%OS%" == "Windows_NT" goto WinNT - -@REM for 9x/Me you better not have more than 9 args -python -c "from os.path import join; import sys; sys.path = [ join(sys.prefix, 'Lib', 'site-packages', 'scons-__VERSION__'), join(sys.prefix, 'Lib', 'site-packages', 'scons'), join(sys.prefix, 'scons-__VERSION__'), join(sys.prefix, 'scons')] + sys.path; import SCons.Script; SCons.Script.main()" %1 %2 %3 %4 %5 %6 %7 %8 %9 -@REM no way to set exit status of this script for 9x/Me -goto endscons - -@REM Credit where credit is due: we return the exit code despite our -@REM use of setlocal+endlocal using a technique from Bear's Journal: -@REM http://code-bear.com/bearlog/2007/06/01/getting-the-exit-code-from-a-batch-file-that-is-run-from-a-python-program/ - -:WinNT -setlocal -@REM ensure the script will be executed with the Python it was installed for -pushd %~dp0.. -set path=%~dp0;%CD%;%path% -popd -@REM try the script named as the .bat file in current dir, then in Scripts subdir -set scriptname=%~dp0%~n0.py -if not exist "%scriptname%" set scriptname=%~dp0Scripts\%~n0.py -@REM Handle when running from wheel where the script has no .py extension -if not exist "%scriptname%" set scriptname=%~dp0%~n0 -python "%scriptname%" %* -endlocal & set SCONS_ERRORLEVEL=%ERRORLEVEL% - -if NOT "%COMSPEC%" == "%SystemRoot%\system32\cmd.exe" goto returncode -if errorlevel 9009 echo you do not have python in your PATH -goto endscons - -:returncode -exit /B %SCONS_ERRORLEVEL% - -:endscons -call :returncode %SCONS_ERRORLEVEL% diff --git a/src/script/scons.py b/src/script/scons.py deleted file mode 100755 index 1e12898..0000000 --- a/src/script/scons.py +++ /dev/null @@ -1,208 +0,0 @@ -#! /usr/bin/env python -# -# SCons - a Software Constructor -# -# __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__" - -__version__ = "__VERSION__" - -__build__ = "__BUILD__" - -__buildsys__ = "__BUILDSYS__" - -__date__ = "__DATE__" - -__developer__ = "__DEVELOPER__" - -# This is the entry point to the SCons program. -# The only job of this script is to work out where the guts of the program -# could be and import them, where the real work begins. -# SCons can be invoked several different ways -# - from an installed location -# - from a "local install" copy -# - from a source tree, which has a different dir struture than the other two -# Try to account for all those possibilities. - -import os -import sys - -############################################################################## -# BEGIN STANDARD SCons SCRIPT HEADER -# -# This is the cut-and-paste logic so that a self-contained script can -# interoperate correctly with different SCons versions and installation -# locations for the engine. If you modify anything in this section, you -# should also change other scripts that use this same header. -############################################################################## - -# compatibility check -if sys.version_info < (3,5,0): - msg = "scons: *** SCons version %s does not run under Python version %s.\n\ -Python >= 3.5 is required.\n" - sys.stderr.write(msg % (__version__, sys.version.split()[0])) - sys.exit(1) - -# Strip the script directory from sys.path so on case-insensitive -# (WIN32) systems Python doesn't think that the "scons" script is the -# "SCons" package. -script_dir = os.path.dirname(os.path.realpath(__file__)) -script_path = os.path.realpath(os.path.dirname(__file__)) -if script_path in sys.path: - sys.path.remove(script_path) - -libs = [] - -if "SCONS_LIB_DIR" in os.environ: - libs.append(os.environ["SCONS_LIB_DIR"]) - -# running from source takes 2nd priority (since 2.3.2), following SCONS_LIB_DIR -source_path = os.path.join(script_path, os.pardir, 'engine') -if os.path.isdir(source_path): - libs.append(source_path) - -# add local-install locations -local_version = 'scons-local-' + __version__ -local = 'scons-local' -if script_dir: - local_version = os.path.join(script_dir, local_version) - local = os.path.join(script_dir, local) -if os.path.isdir(local_version): - libs.append(os.path.abspath(local_version)) -if os.path.isdir(local): - libs.append(os.path.abspath(local)) - -scons_version = 'scons-%s' % __version__ - -# preferred order of scons lookup paths -prefs = [] - -# if we can find package information, use it -try: - import pkg_resources -except ImportError: - pass -else: - try: - d = pkg_resources.get_distribution('scons') - except pkg_resources.DistributionNotFound: - pass - else: - prefs.append(d.location) - -if sys.platform == 'win32': - # Use only sys.prefix on Windows - prefs.append(sys.prefix) - prefs.append(os.path.join(sys.prefix, 'Lib', 'site-packages')) -else: - # On other (POSIX) platforms, things are more complicated due to - # the variety of path names and library locations. - # Build up some possibilities, then transform them into candidates - temp = [] - if script_dir == 'bin': - # script_dir is `pwd`/bin; - # check `pwd`/lib/scons*. - temp.append(os.getcwd()) - else: - if script_dir == '.' or script_dir == '': - script_dir = os.getcwd() - head, tail = os.path.split(script_dir) - if tail == "bin": - # script_dir is /foo/bin; - # check /foo/lib/scons*. - temp.append(head) - - head, tail = os.path.split(sys.prefix) - if tail == "usr": - # sys.prefix is /foo/usr; - # check /foo/usr/lib/scons* first, - # then /foo/usr/local/lib/scons*. - temp.append(sys.prefix) - temp.append(os.path.join(sys.prefix, "local")) - elif tail == "local": - h, t = os.path.split(head) - if t == "usr": - # sys.prefix is /foo/usr/local; - # check /foo/usr/local/lib/scons* first, - # then /foo/usr/lib/scons*. - temp.append(sys.prefix) - temp.append(head) - else: - # sys.prefix is /foo/local; - # check only /foo/local/lib/scons*. - temp.append(sys.prefix) - else: - # sys.prefix is /foo (ends in neither /usr or /local); - # check only /foo/lib/scons*. - temp.append(sys.prefix) - - # suffix these to add to our original prefs: - prefs.extend([os.path.join(x, 'lib') for x in temp]) - prefs.extend([os.path.join(x, 'lib', 'python' + sys.version[:3], - 'site-packages') for x in temp]) - - - # Add the parent directory of the current python's library to the - # preferences. This picks up differences between, e.g., lib and lib64, - # and finds the base location in case of a non-copying virtualenv. - try: - libpath = os.__file__ - except AttributeError: - pass - else: - # Split /usr/libfoo/python*/os.py to /usr/libfoo/python*. - libpath, tail = os.path.split(libpath) - # Split /usr/libfoo/python* to /usr/libfoo - libpath, tail = os.path.split(libpath) - # Check /usr/libfoo/scons*. - prefs.append(libpath) - -# Look first for 'scons-__version__' in all of our preference libs, -# then for 'scons'. Skip paths that do not exist. -libs.extend([os.path.join(x, scons_version) for x in prefs if os.path.isdir(x)]) -libs.extend([os.path.join(x, 'scons') for x in prefs if os.path.isdir(x)]) - -sys.path = libs + sys.path - -############################################################################## -# END STANDARD SCons SCRIPT HEADER -############################################################################## - -if __name__ == "__main__": - try: - import SCons.Script - except ImportError: - sys.stderr.write("SCons import failed. Unable to find engine files in:\n") - for path in libs: - sys.stderr.write(" {}\n".format(path)) - raise - - # this does all the work, and calls sys.exit - # with the proper exit status when done. - SCons.Script.main() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/script/sconsign.py b/src/script/sconsign.py deleted file mode 100644 index 726838c..0000000 --- a/src/script/sconsign.py +++ /dev/null @@ -1,652 +0,0 @@ -#! /usr/bin/env python -# -# SCons - a Software Constructor -# -# __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__" - -__version__ = "__VERSION__" - -__build__ = "__BUILD__" - -__buildsys__ = "__BUILDSYS__" - -__date__ = "__DATE__" - -__developer__ = "__DEVELOPER__" - -import os -import sys - -############################################################################## -# BEGIN STANDARD SCons SCRIPT HEADER -# -# This is the cut-and-paste logic so that a self-contained script can -# interoperate correctly with different SCons versions and installation -# locations for the engine. If you modify anything in this section, you -# should also change other scripts that use this same header. -############################################################################## - -# compatibility check -if sys.version_info < (3,5,0): - msg = "scons: *** SCons version %s does not run under Python version %s.\n\ -Python >= 3.5 is required.\n" - sys.stderr.write(msg % (__version__, sys.version.split()[0])) - sys.exit(1) - -# Strip the script directory from sys.path so on case-insensitive -# (WIN32) systems Python doesn't think that the "scons" script is the -# "SCons" package. -script_dir = os.path.dirname(os.path.realpath(__file__)) -script_path = os.path.realpath(os.path.dirname(__file__)) -if script_path in sys.path: - sys.path.remove(script_path) - -libs = [] - -if "SCONS_LIB_DIR" in os.environ: - libs.append(os.environ["SCONS_LIB_DIR"]) - -# running from source takes 2nd priority (since 2.3.2), following SCONS_LIB_DIR -source_path = os.path.join(script_path, os.pardir, 'engine') -if os.path.isdir(source_path): - libs.append(source_path) - -# add local-install locations -local_version = 'scons-local-' + __version__ -local = 'scons-local' -if script_dir: - local_version = os.path.join(script_dir, local_version) - local = os.path.join(script_dir, local) -if os.path.isdir(local_version): - libs.append(os.path.abspath(local_version)) -if os.path.isdir(local): - libs.append(os.path.abspath(local)) - -scons_version = 'scons-%s' % __version__ - -# preferred order of scons lookup paths -prefs = [] - -# if we can find package information, use it -try: - import pkg_resources -except ImportError: - pass -else: - try: - d = pkg_resources.get_distribution('scons') - except pkg_resources.DistributionNotFound: - pass - else: - prefs.append(d.location) - -if sys.platform == 'win32': - # Use only sys.prefix on Windows - prefs.append(sys.prefix) - prefs.append(os.path.join(sys.prefix, 'Lib', 'site-packages')) -else: - # On other (POSIX) platforms, things are more complicated due to - # the variety of path names and library locations. - # Build up some possibilities, then transform them into candidates - temp = [] - if script_dir == 'bin': - # script_dir is `pwd`/bin; - # check `pwd`/lib/scons*. - temp.append(os.getcwd()) - else: - if script_dir in ('.', ''): - script_dir = os.getcwd() - head, tail = os.path.split(script_dir) - if tail == "bin": - # script_dir is /foo/bin; - # check /foo/lib/scons*. - temp.append(head) - - head, tail = os.path.split(sys.prefix) - if tail == "usr": - # sys.prefix is /foo/usr; - # check /foo/usr/lib/scons* first, - # then /foo/usr/local/lib/scons*. - temp.append(sys.prefix) - temp.append(os.path.join(sys.prefix, "local")) - elif tail == "local": - h, t = os.path.split(head) - if t == "usr": - # sys.prefix is /foo/usr/local; - # check /foo/usr/local/lib/scons* first, - # then /foo/usr/lib/scons*. - temp.append(sys.prefix) - temp.append(head) - else: - # sys.prefix is /foo/local; - # check only /foo/local/lib/scons*. - temp.append(sys.prefix) - else: - # sys.prefix is /foo (ends in neither /usr or /local); - # check only /foo/lib/scons*. - temp.append(sys.prefix) - - # suffix these to add to our original prefs: - prefs.extend([os.path.join(x, 'lib') for x in temp]) - prefs.extend([os.path.join(x, 'lib', 'python' + sys.version[:3], - 'site-packages') for x in temp]) - - - # Add the parent directory of the current python's library to the - # preferences. This picks up differences between, e.g., lib and lib64, - # and finds the base location in case of a non-copying virtualenv. - try: - libpath = os.__file__ - except AttributeError: - pass - else: - # Split /usr/libfoo/python*/os.py to /usr/libfoo/python*. - libpath, _ = os.path.split(libpath) - # Split /usr/libfoo/python* to /usr/libfoo - libpath, tail = os.path.split(libpath) - # Check /usr/libfoo/scons*. - prefs.append(libpath) - -# Look first for 'scons-__version__' in all of our preference libs, -# then for 'scons'. Skip paths that do not exist. -libs.extend([os.path.join(x, scons_version) for x in prefs if os.path.isdir(x)]) -libs.extend([os.path.join(x, 'scons') for x in prefs if os.path.isdir(x)]) - -sys.path = libs + sys.path - -############################################################################## -# END STANDARD SCons SCRIPT HEADER -############################################################################## - -import SCons.compat - -try: - import whichdb - - whichdb = whichdb.whichdb -except ImportError as e: - from dbm import whichdb - -import time -import pickle - -import SCons.SConsign - - -def my_whichdb(filename): - if filename[-7:] == ".dblite": - return "SCons.dblite" - try: - with open(filename + ".dblite", "rb"): - return "SCons.dblite" - except IOError: - pass - return _orig_whichdb(filename) - - -# Should work on python2 -_orig_whichdb = whichdb -whichdb = my_whichdb - -# was changed for python3 -#_orig_whichdb = whichdb.whichdb -#dbm.whichdb = my_whichdb - -def my_import(mname): - import imp - - if '.' in mname: - i = mname.rfind('.') - parent = my_import(mname[:i]) - fp, pathname, description = imp.find_module(mname[i+1:], - parent.__path__) - else: - fp, pathname, description = imp.find_module(mname) - return imp.load_module(mname, fp, pathname, description) - - -class Flagger(object): - default_value = 1 - - def __setitem__(self, item, value): - self.__dict__[item] = value - self.default_value = 0 - - def __getitem__(self, item): - return self.__dict__.get(item, self.default_value) - - -Do_Call = None -Print_Directories = [] -Print_Entries = [] -Print_Flags = Flagger() -Verbose = 0 -Readable = 0 -Warns = 0 - - -def default_mapper(entry, name): - """ - Stringify an entry that doesn't have an explicit mapping. - - Args: - entry: entry - name: field name - - Returns: str - - """ - try: - val = eval("entry." + name) - except AttributeError: - val = None - if sys.version_info.major >= 3 and isinstance(val, bytes): - # This is a dirty hack for py 2/3 compatibility. csig is a bytes object - # in Python3 while Python2 bytes are str. Hence, we decode the csig to a - # Python3 string - val = val.decode() - return str(val) - - -def map_action(entry, _): - """ - Stringify an action entry and signature. - - Args: - entry: action entry - second argument is not used - - Returns: str - - """ - try: - bact = entry.bact - bactsig = entry.bactsig - except AttributeError: - return None - return '%s [%s]' % (bactsig, bact) - - -def map_timestamp(entry, _): - """ - Stringify a timestamp entry. - - Args: - entry: timestamp entry - second argument is not used - - Returns: str - - """ - try: - timestamp = entry.timestamp - except AttributeError: - timestamp = None - if Readable and timestamp: - return "'" + time.ctime(timestamp) + "'" - else: - return str(timestamp) - - -def map_bkids(entry, _): - """ - Stringify an implicit entry. - - Args: - entry: - second argument is not used - - Returns: str - - """ - try: - bkids = entry.bsources + entry.bdepends + entry.bimplicit - bkidsigs = entry.bsourcesigs + entry.bdependsigs + entry.bimplicitsigs - except AttributeError: - return None - - if len(bkids) != len(bkidsigs): - global Warns - Warns += 1 - # add warning to result rather than direct print so it will line up - msg = "Warning: missing information, {} ids but {} sigs" - result = [msg.format(len(bkids), len(bkidsigs))] - else: - result = [] - result += [nodeinfo_string(bkid, bkidsig, " ") - for bkid, bkidsig in zip(bkids, bkidsigs)] - if not result: - return None - return "\n ".join(result) - - -map_field = { - 'action' : map_action, - 'timestamp' : map_timestamp, - 'bkids' : map_bkids, -} - -map_name = { - 'implicit' : 'bkids', -} - - -def field(name, entry, verbose=Verbose): - if not Print_Flags[name]: - return None - fieldname = map_name.get(name, name) - mapper = map_field.get(fieldname, default_mapper) - val = mapper(entry, name) - if verbose: - val = name + ": " + val - return val - - -def nodeinfo_raw(name, ninfo, prefix=""): - # This just formats the dictionary, which we would normally use str() - # to do, except that we want the keys sorted for deterministic output. - d = ninfo.__getstate__() - try: - keys = ninfo.field_list + ['_version_id'] - except AttributeError: - keys = sorted(d.keys()) - l = [] - for k in keys: - l.append('%s: %s' % (repr(k), repr(d.get(k)))) - if '\n' in name: - name = repr(name) - return name + ': {' + ', '.join(l) + '}' - - -def nodeinfo_cooked(name, ninfo, prefix=""): - try: - field_list = ninfo.field_list - except AttributeError: - field_list = [] - if '\n' in name: - name = repr(name) - outlist = [name + ':'] + [ - f for f in [field(x, ninfo, Verbose) for x in field_list] if f - ] - if Verbose: - sep = '\n ' + prefix - else: - sep = ' ' - return sep.join(outlist) - - -nodeinfo_string = nodeinfo_cooked - - -def printfield(name, entry, prefix=""): - outlist = field("implicit", entry, 0) - if outlist: - if Verbose: - print(" implicit:") - print(" " + outlist) - outact = field("action", entry, 0) - if outact: - if Verbose: - print(" action: " + outact) - else: - print(" " + outact) - - -def printentries(entries, location): - if Print_Entries: - for name in Print_Entries: - try: - entry = entries[name] - except KeyError: - err = "sconsign: no entry `%s' in `%s'\n" % (name, location) - sys.stderr.write(err) - else: - try: - ninfo = entry.ninfo - except AttributeError: - print(name + ":") - else: - print(nodeinfo_string(name, entry.ninfo)) - printfield(name, entry.binfo) - else: - for name in sorted(entries.keys()): - entry = entries[name] - try: - ninfo = entry.ninfo - except AttributeError: - print(name + ":") - else: - print(nodeinfo_string(name, entry.ninfo)) - printfield(name, entry.binfo) - - -class Do_SConsignDB(object): - def __init__(self, dbm_name, dbm): - self.dbm_name = dbm_name - self.dbm = dbm - - def __call__(self, fname): - # The *dbm modules stick their own file suffixes on the names - # that are passed in. This causes us to jump through some - # hoops here. - try: - # Try opening the specified file name. Example: - # SPECIFIED OPENED BY self.dbm.open() - # --------- ------------------------- - # .sconsign => .sconsign.dblite - # .sconsign.dblite => .sconsign.dblite.dblite - db = self.dbm.open(fname, "r") - except (IOError, OSError) as e: - print_e = e - try: - # That didn't work, so try opening the base name, - # so that if they actually passed in 'sconsign.dblite' - # (for example), the dbm module will put the suffix back - # on for us and open it anyway. - db = self.dbm.open(os.path.splitext(fname)[0], "r") - except (IOError, OSError): - # That didn't work either. See if the file name - # they specified even exists (independent of the dbm - # suffix-mangling). - try: - with open(fname, "rb"): - pass # this is a touch only, we don't use it here. - except (IOError, OSError) as e: - # Nope, that file doesn't even exist, so report that - # fact back. - print_e = e - sys.stderr.write("sconsign: %s\n" % print_e) - return - except KeyboardInterrupt: - raise - except pickle.UnpicklingError: - sys.stderr.write("sconsign: ignoring invalid `%s' file `%s'\n" - % (self.dbm_name, fname)) - return - except Exception as e: - sys.stderr.write("sconsign: ignoring invalid `%s' file `%s': %s\n" - % (self.dbm_name, fname, e)) - exc_type, _, _ = sys.exc_info() - if exc_type.__name__ == "ValueError" and sys.version_info < (3,0,0): - sys.stderr.write("Python 2 only supports pickle protocols 0-2.\n") - return - - if Print_Directories: - for dir in Print_Directories: - try: - val = db[dir] - except KeyError: - err = "sconsign: no dir `%s' in `%s'\n" % (dir, args[0]) - sys.stderr.write(err) - else: - self.printentries(dir, val) - else: - for dir in sorted(db.keys()): - self.printentries(dir, db[dir]) - - @staticmethod - def printentries(dir, val): - try: - print('=== ' + dir + ':') - except TypeError: - print('=== ' + dir.decode() + ':') - printentries(pickle.loads(val), dir) - - -def Do_SConsignDir(name): - try: - with open(name, 'rb') as fp: - try: - sconsign = SCons.SConsign.Dir(fp) - except KeyboardInterrupt: - raise - except pickle.UnpicklingError: - err = "sconsign: ignoring invalid .sconsign file `%s'\n" % name - sys.stderr.write(err) - return - except Exception as e: - err = "sconsign: ignoring invalid .sconsign file `%s': %s\n" % (name, e) - sys.stderr.write(err) - return - printentries(sconsign.entries, args[0]) - except (IOError, OSError) as e: - sys.stderr.write("sconsign: %s\n" % e) - return - - -############################################################################## - -import getopt - -helpstr = """\ -Usage: sconsign [OPTIONS] [FILE ...] -Options: - -a, --act, --action Print build action information. - -c, --csig Print content signature information. - -d DIR, --dir=DIR Print only info about DIR. - -e ENTRY, --entry=ENTRY Print only info about ENTRY. - -f FORMAT, --format=FORMAT FILE is in the specified FORMAT. - -h, --help Print this message and exit. - -i, --implicit Print implicit dependency information. - -r, --readable Print timestamps in human-readable form. - --raw Print raw Python object representations. - -s, --size Print file sizes. - -t, --timestamp Print timestamp information. - -v, --verbose Verbose, describe each field. -""" - -try: - opts, args = getopt.getopt(sys.argv[1:], "acd:e:f:hirstv", - ['act', 'action', - 'csig', 'dir=', 'entry=', - 'format=', 'help', 'implicit', - 'raw', 'readable', - 'size', 'timestamp', 'verbose']) -except getopt.GetoptError as err: - sys.stderr.write(str(err) + '\n') - print(helpstr) - sys.exit(2) - -for o, a in opts: - if o in ('-a', '--act', '--action'): - Print_Flags['action'] = 1 - elif o in ('-c', '--csig'): - Print_Flags['csig'] = 1 - elif o in ('-d', '--dir'): - Print_Directories.append(a) - elif o in ('-e', '--entry'): - Print_Entries.append(a) - elif o in ('-f', '--format'): - # Try to map the given DB format to a known module - # name, that we can then try to import... - Module_Map = {'dblite': 'SCons.dblite', 'sconsign': None} - dbm_name = Module_Map.get(a, a) - if dbm_name: - try: - if dbm_name != "SCons.dblite": - dbm = my_import(dbm_name) - else: - import SCons.dblite - - dbm = SCons.dblite - # Ensure that we don't ignore corrupt DB files, - # this was handled by calling my_import('SCons.dblite') - # again in earlier versions... - SCons.dblite.ignore_corrupt_dbfiles = 0 - except ImportError: - sys.stderr.write("sconsign: illegal file format `%s'\n" % a) - print(helpstr) - sys.exit(2) - Do_Call = Do_SConsignDB(a, dbm) - else: - Do_Call = Do_SConsignDir - elif o in ('-h', '--help'): - print(helpstr) - sys.exit(0) - elif o in ('-i', '--implicit'): - Print_Flags['implicit'] = 1 - elif o in ('--raw',): - nodeinfo_string = nodeinfo_raw - elif o in ('-r', '--readable'): - Readable = 1 - elif o in ('-s', '--size'): - Print_Flags['size'] = 1 - elif o in ('-t', '--timestamp'): - Print_Flags['timestamp'] = 1 - elif o in ('-v', '--verbose'): - Verbose = 1 - -if Do_Call: - for a in args: - Do_Call(a) -else: - if not args: - args = [".sconsign.dblite"] - for a in args: - dbm_name = whichdb(a) - if dbm_name: - Map_Module = {'SCons.dblite': 'dblite'} - if dbm_name != "SCons.dblite": - dbm = my_import(dbm_name) - else: - import SCons.dblite - - dbm = SCons.dblite - # Ensure that we don't ignore corrupt DB files, - # this was handled by calling my_import('SCons.dblite') - # again in earlier versions... - SCons.dblite.ignore_corrupt_dbfiles = 0 - Do_SConsignDB(Map_Module.get(dbm_name, dbm_name), dbm)(a) - else: - Do_SConsignDir(a) - - if Warns: - print("NOTE: there were %d warnings, please check output" % Warns) -sys.exit(0) - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: -- cgit v0.12 From bdc3e10c5963399badd2833a2ae74a1f87e70b36 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 21 Mar 2020 16:36:52 -0700 Subject: update runtest.py to find scons in scripts --- runtest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtest.py b/runtest.py index 3edf36c..2ee4476 100755 --- a/runtest.py +++ b/runtest.py @@ -555,7 +555,7 @@ else: scons_runtest_dir = base if not external: - scons_script_dir = sd or os.path.join(base, 'src', 'script') + scons_script_dir = sd or os.path.join(base, 'script') scons_lib_dir = ld or os.path.join(base, 'src', 'engine') else: scons_script_dir = sd or '' -- cgit v0.12 From 2888b4f2e8ce13dab28277552ec9fe4ea222cc61 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 21 Mar 2020 17:03:08 -0700 Subject: update scripts to work from /scripts --- scripts/scons-configure-cache.py | 155 +++++++++--------- scripts/sconsign.py | 328 +++++++++++++-------------------------- 2 files changed, 192 insertions(+), 291 deletions(-) diff --git a/scripts/scons-configure-cache.py b/scripts/scons-configure-cache.py index 716315c..80783a9 100644 --- a/scripts/scons-configure-cache.py +++ b/scripts/scons-configure-cache.py @@ -100,78 +100,83 @@ config_entries = { } } -parser = argparse.ArgumentParser( - description='Modify the configuration of an scons cache directory', - epilog=''' - Unspecified options will not be changed unless they are not - set at all, in which case they are set to an appropriate default. - ''') - -parser.add_argument('cache-dir', help='Path to scons cache directory') -for param in config_entries: - parser.add_argument('--' + param.replace('_', '-'), - **config_entries[param]['command-line']) -parser.add_argument('--version', - action='version', - version='%(prog)s 1.0') -parser.add_argument('--show', - action="store_true", - help="show current configuration") - -# Get the command line as a dict without any of the unspecified entries. -args = dict([x for x in vars(parser.parse_args()).items() if x[1]]) - -# It seems somewhat strange to me, but positional arguments don't get the - -# in the name changed to _, whereas optional arguments do... -cache = args['cache-dir'] -if not os.path.isdir(cache): - raise RuntimeError("There is no cache directory named %s" % cache) -os.chdir(cache) -del args['cache-dir'] - -if not os.path.exists('config'): - # old config dirs did not have a 'config' file. Try to update. - # Validate the only files in the directory are directories 0-9, a-f - expected = ['{:X}'.format(x) for x in range(0, 16)] - if not set(os.listdir('.')).issubset(expected): - raise RuntimeError( - "%s does not look like a valid version 1 cache directory" % cache) - config = dict() -else: - with open('config') as conf: - config = json.load(conf) - -if args.get('show', None): - print("Current configuration in '%s':" % cache) - print(json.dumps(config, sort_keys=True, - indent=4, separators=(',', ': '))) - # in case of the show argument, emit some stats as well - file_count = 0 - for _, _, files in os.walk('.'): - file_count += len(files) - if file_count: # skip config file if it exists - file_count -= 1 - print("Cache contains %s files" % file_count) - del args['show'] - -# Find any keys that are not currently set but should be -for key in config_entries: - if key not in config: - if 'implicit' in config_entries[key]: - config[key] = config_entries[key]['implicit'] - else: - config[key] = config_entries[key]['default'] - if key not in args: - args[key] = config_entries[key]['default'] - -# Now go through each entry in args to see if it changes an existing config -# setting. -for key in args: - if args[key] != config[key]: - if 'converter' in config_entries[key]: - config_entries[key]['converter'](config[key], args[key]) - config[key] = args[key] - -# and write the updated config file -with open('config', 'w') as conf: - json.dump(config, conf) + +def main(): + parser = argparse.ArgumentParser( + description='Modify the configuration of an scons cache directory', + epilog=''' + Unspecified options will not be changed unless they are not + set at all, in which case they are set to an appropriate default. + ''') + + parser.add_argument('cache-dir', help='Path to scons cache directory') + for param in config_entries: + parser.add_argument('--' + param.replace('_', '-'), + **config_entries[param]['command-line']) + parser.add_argument('--version', + action='version', + version='%(prog)s 1.0') + parser.add_argument('--show', + action="store_true", + help="show current configuration") + + # Get the command line as a dict without any of the unspecified entries. + args = dict([x for x in vars(parser.parse_args()).items() if x[1]]) + + # It seems somewhat strange to me, but positional arguments don't get the - + # in the name changed to _, whereas optional arguments do... + cache = args['cache-dir'] + if not os.path.isdir(cache): + raise RuntimeError("There is no cache directory named %s" % cache) + os.chdir(cache) + del args['cache-dir'] + + if not os.path.exists('config'): + # old config dirs did not have a 'config' file. Try to update. + # Validate the only files in the directory are directories 0-9, a-f + expected = ['{:X}'.format(x) for x in range(0, 16)] + if not set(os.listdir('.')).issubset(expected): + raise RuntimeError( + "%s does not look like a valid version 1 cache directory" % cache) + config = dict() + else: + with open('config') as conf: + config = json.load(conf) + + if args.get('show', None): + print("Current configuration in '%s':" % cache) + print(json.dumps(config, sort_keys=True, + indent=4, separators=(',', ': '))) + # in case of the show argument, emit some stats as well + file_count = 0 + for _, _, files in os.walk('.'): + file_count += len(files) + if file_count: # skip config file if it exists + file_count -= 1 + print("Cache contains %s files" % file_count) + del args['show'] + + # Find any keys that are not currently set but should be + for key in config_entries: + if key not in config: + if 'implicit' in config_entries[key]: + config[key] = config_entries[key]['implicit'] + else: + config[key] = config_entries[key]['default'] + if key not in args: + args[key] = config_entries[key]['default'] + + # Now go through each entry in args to see if it changes an existing config + # setting. + for key in args: + if args[key] != config[key]: + if 'converter' in config_entries[key]: + config_entries[key]['converter'](config[key], args[key]) + config[key] = args[key] + + # and write the updated config file + with open('config', 'w') as conf: + json.dump(config, conf) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/scripts/sconsign.py b/scripts/sconsign.py index 726838c..819b9f7 100644 --- a/scripts/sconsign.py +++ b/scripts/sconsign.py @@ -35,20 +35,16 @@ __date__ = "__DATE__" __developer__ = "__DEVELOPER__" +import getopt import os import sys +from dbm import whichdb -############################################################################## -# BEGIN STANDARD SCons SCRIPT HEADER -# -# This is the cut-and-paste logic so that a self-contained script can -# interoperate correctly with different SCons versions and installation -# locations for the engine. If you modify anything in this section, you -# should also change other scripts that use this same header. -############################################################################## +import time +import pickle -# compatibility check -if sys.version_info < (3,5,0): +# python compatibility check +if sys.version_info < (3, 5, 0): msg = "scons: *** SCons version %s does not run under Python version %s.\n\ Python >= 3.5 is required.\n" sys.stderr.write(msg % (__version__, sys.version.split()[0])) @@ -68,7 +64,7 @@ if "SCONS_LIB_DIR" in os.environ: libs.append(os.environ["SCONS_LIB_DIR"]) # running from source takes 2nd priority (since 2.3.2), following SCONS_LIB_DIR -source_path = os.path.join(script_path, os.pardir, 'engine') +source_path = os.path.join(script_path, os.pardir, 'src', 'engine') if os.path.isdir(source_path): libs.append(source_path) @@ -85,94 +81,6 @@ if os.path.isdir(local): scons_version = 'scons-%s' % __version__ -# preferred order of scons lookup paths -prefs = [] - -# if we can find package information, use it -try: - import pkg_resources -except ImportError: - pass -else: - try: - d = pkg_resources.get_distribution('scons') - except pkg_resources.DistributionNotFound: - pass - else: - prefs.append(d.location) - -if sys.platform == 'win32': - # Use only sys.prefix on Windows - prefs.append(sys.prefix) - prefs.append(os.path.join(sys.prefix, 'Lib', 'site-packages')) -else: - # On other (POSIX) platforms, things are more complicated due to - # the variety of path names and library locations. - # Build up some possibilities, then transform them into candidates - temp = [] - if script_dir == 'bin': - # script_dir is `pwd`/bin; - # check `pwd`/lib/scons*. - temp.append(os.getcwd()) - else: - if script_dir in ('.', ''): - script_dir = os.getcwd() - head, tail = os.path.split(script_dir) - if tail == "bin": - # script_dir is /foo/bin; - # check /foo/lib/scons*. - temp.append(head) - - head, tail = os.path.split(sys.prefix) - if tail == "usr": - # sys.prefix is /foo/usr; - # check /foo/usr/lib/scons* first, - # then /foo/usr/local/lib/scons*. - temp.append(sys.prefix) - temp.append(os.path.join(sys.prefix, "local")) - elif tail == "local": - h, t = os.path.split(head) - if t == "usr": - # sys.prefix is /foo/usr/local; - # check /foo/usr/local/lib/scons* first, - # then /foo/usr/lib/scons*. - temp.append(sys.prefix) - temp.append(head) - else: - # sys.prefix is /foo/local; - # check only /foo/local/lib/scons*. - temp.append(sys.prefix) - else: - # sys.prefix is /foo (ends in neither /usr or /local); - # check only /foo/lib/scons*. - temp.append(sys.prefix) - - # suffix these to add to our original prefs: - prefs.extend([os.path.join(x, 'lib') for x in temp]) - prefs.extend([os.path.join(x, 'lib', 'python' + sys.version[:3], - 'site-packages') for x in temp]) - - - # Add the parent directory of the current python's library to the - # preferences. This picks up differences between, e.g., lib and lib64, - # and finds the base location in case of a non-copying virtualenv. - try: - libpath = os.__file__ - except AttributeError: - pass - else: - # Split /usr/libfoo/python*/os.py to /usr/libfoo/python*. - libpath, _ = os.path.split(libpath) - # Split /usr/libfoo/python* to /usr/libfoo - libpath, tail = os.path.split(libpath) - # Check /usr/libfoo/scons*. - prefs.append(libpath) - -# Look first for 'scons-__version__' in all of our preference libs, -# then for 'scons'. Skip paths that do not exist. -libs.extend([os.path.join(x, scons_version) for x in prefs if os.path.isdir(x)]) -libs.extend([os.path.join(x, 'scons') for x in prefs if os.path.isdir(x)]) - sys.path = libs + sys.path ############################################################################## @@ -180,17 +88,6 @@ sys.path = libs + sys.path ############################################################################## import SCons.compat - -try: - import whichdb - - whichdb = whichdb.whichdb -except ImportError as e: - from dbm import whichdb - -import time -import pickle - import SCons.SConsign @@ -202,16 +99,8 @@ def my_whichdb(filename): return "SCons.dblite" except IOError: pass - return _orig_whichdb(filename) - - -# Should work on python2 -_orig_whichdb = whichdb -whichdb = my_whichdb + return whichdb(filename) -# was changed for python3 -#_orig_whichdb = whichdb.whichdb -#dbm.whichdb = my_whichdb def my_import(mname): import imp @@ -364,8 +253,10 @@ def field(name, entry, verbose=Verbose): def nodeinfo_raw(name, ninfo, prefix=""): - # This just formats the dictionary, which we would normally use str() - # to do, except that we want the keys sorted for deterministic output. + """ + This just formats the dictionary, which we would normally use str() + to do, except that we want the keys sorted for deterministic output. + """ d = ninfo.__getstate__() try: keys = ninfo.field_list + ['_version_id'] @@ -536,54 +427,97 @@ def Do_SConsignDir(name): ############################################################################## +def main(): + global Do_Call + + helpstr = """\ + Usage: sconsign [OPTIONS] [FILE ...] + Options: + -a, --act, --action Print build action information. + -c, --csig Print content signature information. + -d DIR, --dir=DIR Print only info about DIR. + -e ENTRY, --entry=ENTRY Print only info about ENTRY. + -f FORMAT, --format=FORMAT FILE is in the specified FORMAT. + -h, --help Print this message and exit. + -i, --implicit Print implicit dependency information. + -r, --readable Print timestamps in human-readable form. + --raw Print raw Python object representations. + -s, --size Print file sizes. + -t, --timestamp Print timestamp information. + -v, --verbose Verbose, describe each field. + """ -import getopt - -helpstr = """\ -Usage: sconsign [OPTIONS] [FILE ...] -Options: - -a, --act, --action Print build action information. - -c, --csig Print content signature information. - -d DIR, --dir=DIR Print only info about DIR. - -e ENTRY, --entry=ENTRY Print only info about ENTRY. - -f FORMAT, --format=FORMAT FILE is in the specified FORMAT. - -h, --help Print this message and exit. - -i, --implicit Print implicit dependency information. - -r, --readable Print timestamps in human-readable form. - --raw Print raw Python object representations. - -s, --size Print file sizes. - -t, --timestamp Print timestamp information. - -v, --verbose Verbose, describe each field. -""" - -try: - opts, args = getopt.getopt(sys.argv[1:], "acd:e:f:hirstv", - ['act', 'action', - 'csig', 'dir=', 'entry=', - 'format=', 'help', 'implicit', - 'raw', 'readable', - 'size', 'timestamp', 'verbose']) -except getopt.GetoptError as err: - sys.stderr.write(str(err) + '\n') - print(helpstr) - sys.exit(2) - -for o, a in opts: - if o in ('-a', '--act', '--action'): - Print_Flags['action'] = 1 - elif o in ('-c', '--csig'): - Print_Flags['csig'] = 1 - elif o in ('-d', '--dir'): - Print_Directories.append(a) - elif o in ('-e', '--entry'): - Print_Entries.append(a) - elif o in ('-f', '--format'): - # Try to map the given DB format to a known module - # name, that we can then try to import... - Module_Map = {'dblite': 'SCons.dblite', 'sconsign': None} - dbm_name = Module_Map.get(a, a) - if dbm_name: - try: + try: + opts, args = getopt.getopt(sys.argv[1:], "acd:e:f:hirstv", + ['act', 'action', + 'csig', 'dir=', 'entry=', + 'format=', 'help', 'implicit', + 'raw', 'readable', + 'size', 'timestamp', 'verbose']) + except getopt.GetoptError as err: + sys.stderr.write(str(err) + '\n') + print(helpstr) + sys.exit(2) + + for o, a in opts: + if o in ('-a', '--act', '--action'): + Print_Flags['action'] = 1 + elif o in ('-c', '--csig'): + Print_Flags['csig'] = 1 + elif o in ('-d', '--dir'): + Print_Directories.append(a) + elif o in ('-e', '--entry'): + Print_Entries.append(a) + elif o in ('-f', '--format'): + # Try to map the given DB format to a known module + # name, that we can then try to import... + Module_Map = {'dblite': 'SCons.dblite', 'sconsign': None} + dbm_name = Module_Map.get(a, a) + if dbm_name: + try: + if dbm_name != "SCons.dblite": + dbm = my_import(dbm_name) + else: + import SCons.dblite + + dbm = SCons.dblite + # Ensure that we don't ignore corrupt DB files, + # this was handled by calling my_import('SCons.dblite') + # again in earlier versions... + SCons.dblite.ignore_corrupt_dbfiles = 0 + except ImportError: + sys.stderr.write("sconsign: illegal file format `%s'\n" % a) + print(helpstr) + sys.exit(2) + Do_Call = Do_SConsignDB(a, dbm) + else: + Do_Call = Do_SConsignDir + elif o in ('-h', '--help'): + print(helpstr) + sys.exit(0) + elif o in ('-i', '--implicit'): + Print_Flags['implicit'] = 1 + elif o in ('--raw',): + nodeinfo_string = nodeinfo_raw + elif o in ('-r', '--readable'): + Readable = 1 + elif o in ('-s', '--size'): + Print_Flags['size'] = 1 + elif o in ('-t', '--timestamp'): + Print_Flags['timestamp'] = 1 + elif o in ('-v', '--verbose'): + Verbose = 1 + + if Do_Call: + for a in args: + Do_Call(a) + else: + if not args: + args = [".sconsign.dblite"] + for a in args: + dbm_name = my_whichdb(a) + if dbm_name: + Map_Module = {'SCons.dblite': 'dblite'} if dbm_name != "SCons.dblite": dbm = my_import(dbm_name) else: @@ -594,56 +528,18 @@ for o, a in opts: # this was handled by calling my_import('SCons.dblite') # again in earlier versions... SCons.dblite.ignore_corrupt_dbfiles = 0 - except ImportError: - sys.stderr.write("sconsign: illegal file format `%s'\n" % a) - print(helpstr) - sys.exit(2) - Do_Call = Do_SConsignDB(a, dbm) - else: - Do_Call = Do_SConsignDir - elif o in ('-h', '--help'): - print(helpstr) - sys.exit(0) - elif o in ('-i', '--implicit'): - Print_Flags['implicit'] = 1 - elif o in ('--raw',): - nodeinfo_string = nodeinfo_raw - elif o in ('-r', '--readable'): - Readable = 1 - elif o in ('-s', '--size'): - Print_Flags['size'] = 1 - elif o in ('-t', '--timestamp'): - Print_Flags['timestamp'] = 1 - elif o in ('-v', '--verbose'): - Verbose = 1 - -if Do_Call: - for a in args: - Do_Call(a) -else: - if not args: - args = [".sconsign.dblite"] - for a in args: - dbm_name = whichdb(a) - if dbm_name: - Map_Module = {'SCons.dblite': 'dblite'} - if dbm_name != "SCons.dblite": - dbm = my_import(dbm_name) + Do_SConsignDB(Map_Module.get(dbm_name, dbm_name), dbm)(a) else: - import SCons.dblite - - dbm = SCons.dblite - # Ensure that we don't ignore corrupt DB files, - # this was handled by calling my_import('SCons.dblite') - # again in earlier versions... - SCons.dblite.ignore_corrupt_dbfiles = 0 - Do_SConsignDB(Map_Module.get(dbm_name, dbm_name), dbm)(a) - else: - Do_SConsignDir(a) + Do_SConsignDir(a) + + if Warns: + print("NOTE: there were %d warnings, please check output" % Warns) + + - if Warns: - print("NOTE: there were %d warnings, please check output" % Warns) -sys.exit(0) +if __name__ == "__main__": + main() + sys.exit(0) # Local Variables: # tab-width:4 -- cgit v0.12 From cd30b7ee366aa0a45b00b27dff287143dbfe0265 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 21 Mar 2020 17:08:33 -0700 Subject: move sconsign logic into src/engine/SCons/Utilties, update entry_points to generate sconsign script --- setup.cfg | 1 + src/engine/SCons/Utilities/__init__.py | 0 src/engine/SCons/Utilities/sconsign.py | 548 +++++++++++++++++++++++++++++++++ 3 files changed, 549 insertions(+) create mode 100644 src/engine/SCons/Utilities/__init__.py create mode 100644 src/engine/SCons/Utilities/sconsign.py diff --git a/setup.cfg b/setup.cfg index d44c1f5..8e55f10 100644 --- a/setup.cfg +++ b/setup.cfg @@ -53,6 +53,7 @@ packages = find: [options.entry_points] console_scripts = scons = SCons.Script.Main:main + sconsign = SCons.Utilities.sconsign:main [options.package_data] diff --git a/src/engine/SCons/Utilities/__init__.py b/src/engine/SCons/Utilities/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/engine/SCons/Utilities/sconsign.py b/src/engine/SCons/Utilities/sconsign.py new file mode 100644 index 0000000..819b9f7 --- /dev/null +++ b/src/engine/SCons/Utilities/sconsign.py @@ -0,0 +1,548 @@ +#! /usr/bin/env python +# +# SCons - a Software Constructor +# +# __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__" + +__version__ = "__VERSION__" + +__build__ = "__BUILD__" + +__buildsys__ = "__BUILDSYS__" + +__date__ = "__DATE__" + +__developer__ = "__DEVELOPER__" + +import getopt +import os +import sys +from dbm import whichdb + +import time +import pickle + +# python compatibility check +if sys.version_info < (3, 5, 0): + msg = "scons: *** SCons version %s does not run under Python version %s.\n\ +Python >= 3.5 is required.\n" + sys.stderr.write(msg % (__version__, sys.version.split()[0])) + sys.exit(1) + +# Strip the script directory from sys.path so on case-insensitive +# (WIN32) systems Python doesn't think that the "scons" script is the +# "SCons" package. +script_dir = os.path.dirname(os.path.realpath(__file__)) +script_path = os.path.realpath(os.path.dirname(__file__)) +if script_path in sys.path: + sys.path.remove(script_path) + +libs = [] + +if "SCONS_LIB_DIR" in os.environ: + libs.append(os.environ["SCONS_LIB_DIR"]) + +# running from source takes 2nd priority (since 2.3.2), following SCONS_LIB_DIR +source_path = os.path.join(script_path, os.pardir, 'src', 'engine') +if os.path.isdir(source_path): + libs.append(source_path) + +# add local-install locations +local_version = 'scons-local-' + __version__ +local = 'scons-local' +if script_dir: + local_version = os.path.join(script_dir, local_version) + local = os.path.join(script_dir, local) +if os.path.isdir(local_version): + libs.append(os.path.abspath(local_version)) +if os.path.isdir(local): + libs.append(os.path.abspath(local)) + +scons_version = 'scons-%s' % __version__ + +sys.path = libs + sys.path + +############################################################################## +# END STANDARD SCons SCRIPT HEADER +############################################################################## + +import SCons.compat +import SCons.SConsign + + +def my_whichdb(filename): + if filename[-7:] == ".dblite": + return "SCons.dblite" + try: + with open(filename + ".dblite", "rb"): + return "SCons.dblite" + except IOError: + pass + return whichdb(filename) + + +def my_import(mname): + import imp + + if '.' in mname: + i = mname.rfind('.') + parent = my_import(mname[:i]) + fp, pathname, description = imp.find_module(mname[i+1:], + parent.__path__) + else: + fp, pathname, description = imp.find_module(mname) + return imp.load_module(mname, fp, pathname, description) + + +class Flagger(object): + default_value = 1 + + def __setitem__(self, item, value): + self.__dict__[item] = value + self.default_value = 0 + + def __getitem__(self, item): + return self.__dict__.get(item, self.default_value) + + +Do_Call = None +Print_Directories = [] +Print_Entries = [] +Print_Flags = Flagger() +Verbose = 0 +Readable = 0 +Warns = 0 + + +def default_mapper(entry, name): + """ + Stringify an entry that doesn't have an explicit mapping. + + Args: + entry: entry + name: field name + + Returns: str + + """ + try: + val = eval("entry." + name) + except AttributeError: + val = None + if sys.version_info.major >= 3 and isinstance(val, bytes): + # This is a dirty hack for py 2/3 compatibility. csig is a bytes object + # in Python3 while Python2 bytes are str. Hence, we decode the csig to a + # Python3 string + val = val.decode() + return str(val) + + +def map_action(entry, _): + """ + Stringify an action entry and signature. + + Args: + entry: action entry + second argument is not used + + Returns: str + + """ + try: + bact = entry.bact + bactsig = entry.bactsig + except AttributeError: + return None + return '%s [%s]' % (bactsig, bact) + + +def map_timestamp(entry, _): + """ + Stringify a timestamp entry. + + Args: + entry: timestamp entry + second argument is not used + + Returns: str + + """ + try: + timestamp = entry.timestamp + except AttributeError: + timestamp = None + if Readable and timestamp: + return "'" + time.ctime(timestamp) + "'" + else: + return str(timestamp) + + +def map_bkids(entry, _): + """ + Stringify an implicit entry. + + Args: + entry: + second argument is not used + + Returns: str + + """ + try: + bkids = entry.bsources + entry.bdepends + entry.bimplicit + bkidsigs = entry.bsourcesigs + entry.bdependsigs + entry.bimplicitsigs + except AttributeError: + return None + + if len(bkids) != len(bkidsigs): + global Warns + Warns += 1 + # add warning to result rather than direct print so it will line up + msg = "Warning: missing information, {} ids but {} sigs" + result = [msg.format(len(bkids), len(bkidsigs))] + else: + result = [] + result += [nodeinfo_string(bkid, bkidsig, " ") + for bkid, bkidsig in zip(bkids, bkidsigs)] + if not result: + return None + return "\n ".join(result) + + +map_field = { + 'action' : map_action, + 'timestamp' : map_timestamp, + 'bkids' : map_bkids, +} + +map_name = { + 'implicit' : 'bkids', +} + + +def field(name, entry, verbose=Verbose): + if not Print_Flags[name]: + return None + fieldname = map_name.get(name, name) + mapper = map_field.get(fieldname, default_mapper) + val = mapper(entry, name) + if verbose: + val = name + ": " + val + return val + + +def nodeinfo_raw(name, ninfo, prefix=""): + """ + This just formats the dictionary, which we would normally use str() + to do, except that we want the keys sorted for deterministic output. + """ + d = ninfo.__getstate__() + try: + keys = ninfo.field_list + ['_version_id'] + except AttributeError: + keys = sorted(d.keys()) + l = [] + for k in keys: + l.append('%s: %s' % (repr(k), repr(d.get(k)))) + if '\n' in name: + name = repr(name) + return name + ': {' + ', '.join(l) + '}' + + +def nodeinfo_cooked(name, ninfo, prefix=""): + try: + field_list = ninfo.field_list + except AttributeError: + field_list = [] + if '\n' in name: + name = repr(name) + outlist = [name + ':'] + [ + f for f in [field(x, ninfo, Verbose) for x in field_list] if f + ] + if Verbose: + sep = '\n ' + prefix + else: + sep = ' ' + return sep.join(outlist) + + +nodeinfo_string = nodeinfo_cooked + + +def printfield(name, entry, prefix=""): + outlist = field("implicit", entry, 0) + if outlist: + if Verbose: + print(" implicit:") + print(" " + outlist) + outact = field("action", entry, 0) + if outact: + if Verbose: + print(" action: " + outact) + else: + print(" " + outact) + + +def printentries(entries, location): + if Print_Entries: + for name in Print_Entries: + try: + entry = entries[name] + except KeyError: + err = "sconsign: no entry `%s' in `%s'\n" % (name, location) + sys.stderr.write(err) + else: + try: + ninfo = entry.ninfo + except AttributeError: + print(name + ":") + else: + print(nodeinfo_string(name, entry.ninfo)) + printfield(name, entry.binfo) + else: + for name in sorted(entries.keys()): + entry = entries[name] + try: + ninfo = entry.ninfo + except AttributeError: + print(name + ":") + else: + print(nodeinfo_string(name, entry.ninfo)) + printfield(name, entry.binfo) + + +class Do_SConsignDB(object): + def __init__(self, dbm_name, dbm): + self.dbm_name = dbm_name + self.dbm = dbm + + def __call__(self, fname): + # The *dbm modules stick their own file suffixes on the names + # that are passed in. This causes us to jump through some + # hoops here. + try: + # Try opening the specified file name. Example: + # SPECIFIED OPENED BY self.dbm.open() + # --------- ------------------------- + # .sconsign => .sconsign.dblite + # .sconsign.dblite => .sconsign.dblite.dblite + db = self.dbm.open(fname, "r") + except (IOError, OSError) as e: + print_e = e + try: + # That didn't work, so try opening the base name, + # so that if they actually passed in 'sconsign.dblite' + # (for example), the dbm module will put the suffix back + # on for us and open it anyway. + db = self.dbm.open(os.path.splitext(fname)[0], "r") + except (IOError, OSError): + # That didn't work either. See if the file name + # they specified even exists (independent of the dbm + # suffix-mangling). + try: + with open(fname, "rb"): + pass # this is a touch only, we don't use it here. + except (IOError, OSError) as e: + # Nope, that file doesn't even exist, so report that + # fact back. + print_e = e + sys.stderr.write("sconsign: %s\n" % print_e) + return + except KeyboardInterrupt: + raise + except pickle.UnpicklingError: + sys.stderr.write("sconsign: ignoring invalid `%s' file `%s'\n" + % (self.dbm_name, fname)) + return + except Exception as e: + sys.stderr.write("sconsign: ignoring invalid `%s' file `%s': %s\n" + % (self.dbm_name, fname, e)) + exc_type, _, _ = sys.exc_info() + if exc_type.__name__ == "ValueError" and sys.version_info < (3,0,0): + sys.stderr.write("Python 2 only supports pickle protocols 0-2.\n") + return + + if Print_Directories: + for dir in Print_Directories: + try: + val = db[dir] + except KeyError: + err = "sconsign: no dir `%s' in `%s'\n" % (dir, args[0]) + sys.stderr.write(err) + else: + self.printentries(dir, val) + else: + for dir in sorted(db.keys()): + self.printentries(dir, db[dir]) + + @staticmethod + def printentries(dir, val): + try: + print('=== ' + dir + ':') + except TypeError: + print('=== ' + dir.decode() + ':') + printentries(pickle.loads(val), dir) + + +def Do_SConsignDir(name): + try: + with open(name, 'rb') as fp: + try: + sconsign = SCons.SConsign.Dir(fp) + except KeyboardInterrupt: + raise + except pickle.UnpicklingError: + err = "sconsign: ignoring invalid .sconsign file `%s'\n" % name + sys.stderr.write(err) + return + except Exception as e: + err = "sconsign: ignoring invalid .sconsign file `%s': %s\n" % (name, e) + sys.stderr.write(err) + return + printentries(sconsign.entries, args[0]) + except (IOError, OSError) as e: + sys.stderr.write("sconsign: %s\n" % e) + return + + +############################################################################## +def main(): + global Do_Call + + helpstr = """\ + Usage: sconsign [OPTIONS] [FILE ...] + Options: + -a, --act, --action Print build action information. + -c, --csig Print content signature information. + -d DIR, --dir=DIR Print only info about DIR. + -e ENTRY, --entry=ENTRY Print only info about ENTRY. + -f FORMAT, --format=FORMAT FILE is in the specified FORMAT. + -h, --help Print this message and exit. + -i, --implicit Print implicit dependency information. + -r, --readable Print timestamps in human-readable form. + --raw Print raw Python object representations. + -s, --size Print file sizes. + -t, --timestamp Print timestamp information. + -v, --verbose Verbose, describe each field. + """ + + try: + opts, args = getopt.getopt(sys.argv[1:], "acd:e:f:hirstv", + ['act', 'action', + 'csig', 'dir=', 'entry=', + 'format=', 'help', 'implicit', + 'raw', 'readable', + 'size', 'timestamp', 'verbose']) + except getopt.GetoptError as err: + sys.stderr.write(str(err) + '\n') + print(helpstr) + sys.exit(2) + + for o, a in opts: + if o in ('-a', '--act', '--action'): + Print_Flags['action'] = 1 + elif o in ('-c', '--csig'): + Print_Flags['csig'] = 1 + elif o in ('-d', '--dir'): + Print_Directories.append(a) + elif o in ('-e', '--entry'): + Print_Entries.append(a) + elif o in ('-f', '--format'): + # Try to map the given DB format to a known module + # name, that we can then try to import... + Module_Map = {'dblite': 'SCons.dblite', 'sconsign': None} + dbm_name = Module_Map.get(a, a) + if dbm_name: + try: + if dbm_name != "SCons.dblite": + dbm = my_import(dbm_name) + else: + import SCons.dblite + + dbm = SCons.dblite + # Ensure that we don't ignore corrupt DB files, + # this was handled by calling my_import('SCons.dblite') + # again in earlier versions... + SCons.dblite.ignore_corrupt_dbfiles = 0 + except ImportError: + sys.stderr.write("sconsign: illegal file format `%s'\n" % a) + print(helpstr) + sys.exit(2) + Do_Call = Do_SConsignDB(a, dbm) + else: + Do_Call = Do_SConsignDir + elif o in ('-h', '--help'): + print(helpstr) + sys.exit(0) + elif o in ('-i', '--implicit'): + Print_Flags['implicit'] = 1 + elif o in ('--raw',): + nodeinfo_string = nodeinfo_raw + elif o in ('-r', '--readable'): + Readable = 1 + elif o in ('-s', '--size'): + Print_Flags['size'] = 1 + elif o in ('-t', '--timestamp'): + Print_Flags['timestamp'] = 1 + elif o in ('-v', '--verbose'): + Verbose = 1 + + if Do_Call: + for a in args: + Do_Call(a) + else: + if not args: + args = [".sconsign.dblite"] + for a in args: + dbm_name = my_whichdb(a) + if dbm_name: + Map_Module = {'SCons.dblite': 'dblite'} + if dbm_name != "SCons.dblite": + dbm = my_import(dbm_name) + else: + import SCons.dblite + + dbm = SCons.dblite + # Ensure that we don't ignore corrupt DB files, + # this was handled by calling my_import('SCons.dblite') + # again in earlier versions... + SCons.dblite.ignore_corrupt_dbfiles = 0 + Do_SConsignDB(Map_Module.get(dbm_name, dbm_name), dbm)(a) + else: + Do_SConsignDir(a) + + if Warns: + print("NOTE: there were %d warnings, please check output" % Warns) + + + +if __name__ == "__main__": + main() + sys.exit(0) + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: -- cgit v0.12 From c5a750381cfb99c69e0d20228b666bfb1b0e0a41 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 21 Mar 2020 17:10:04 -0700 Subject: change scripts/sconsign.py to be shell which uses logic in SCons.Utilities.sconsign's main --- scripts/sconsign.py | 457 +--------------------------------------------------- 1 file changed, 1 insertion(+), 456 deletions(-) diff --git a/scripts/sconsign.py b/scripts/sconsign.py index 819b9f7..493bd40 100644 --- a/scripts/sconsign.py +++ b/scripts/sconsign.py @@ -35,13 +35,8 @@ __date__ = "__DATE__" __developer__ = "__DEVELOPER__" -import getopt import os import sys -from dbm import whichdb - -import time -import pickle # python compatibility check if sys.version_info < (3, 5, 0): @@ -86,457 +81,7 @@ sys.path = libs + sys.path ############################################################################## # END STANDARD SCons SCRIPT HEADER ############################################################################## - -import SCons.compat -import SCons.SConsign - - -def my_whichdb(filename): - if filename[-7:] == ".dblite": - return "SCons.dblite" - try: - with open(filename + ".dblite", "rb"): - return "SCons.dblite" - except IOError: - pass - return whichdb(filename) - - -def my_import(mname): - import imp - - if '.' in mname: - i = mname.rfind('.') - parent = my_import(mname[:i]) - fp, pathname, description = imp.find_module(mname[i+1:], - parent.__path__) - else: - fp, pathname, description = imp.find_module(mname) - return imp.load_module(mname, fp, pathname, description) - - -class Flagger(object): - default_value = 1 - - def __setitem__(self, item, value): - self.__dict__[item] = value - self.default_value = 0 - - def __getitem__(self, item): - return self.__dict__.get(item, self.default_value) - - -Do_Call = None -Print_Directories = [] -Print_Entries = [] -Print_Flags = Flagger() -Verbose = 0 -Readable = 0 -Warns = 0 - - -def default_mapper(entry, name): - """ - Stringify an entry that doesn't have an explicit mapping. - - Args: - entry: entry - name: field name - - Returns: str - - """ - try: - val = eval("entry." + name) - except AttributeError: - val = None - if sys.version_info.major >= 3 and isinstance(val, bytes): - # This is a dirty hack for py 2/3 compatibility. csig is a bytes object - # in Python3 while Python2 bytes are str. Hence, we decode the csig to a - # Python3 string - val = val.decode() - return str(val) - - -def map_action(entry, _): - """ - Stringify an action entry and signature. - - Args: - entry: action entry - second argument is not used - - Returns: str - - """ - try: - bact = entry.bact - bactsig = entry.bactsig - except AttributeError: - return None - return '%s [%s]' % (bactsig, bact) - - -def map_timestamp(entry, _): - """ - Stringify a timestamp entry. - - Args: - entry: timestamp entry - second argument is not used - - Returns: str - - """ - try: - timestamp = entry.timestamp - except AttributeError: - timestamp = None - if Readable and timestamp: - return "'" + time.ctime(timestamp) + "'" - else: - return str(timestamp) - - -def map_bkids(entry, _): - """ - Stringify an implicit entry. - - Args: - entry: - second argument is not used - - Returns: str - - """ - try: - bkids = entry.bsources + entry.bdepends + entry.bimplicit - bkidsigs = entry.bsourcesigs + entry.bdependsigs + entry.bimplicitsigs - except AttributeError: - return None - - if len(bkids) != len(bkidsigs): - global Warns - Warns += 1 - # add warning to result rather than direct print so it will line up - msg = "Warning: missing information, {} ids but {} sigs" - result = [msg.format(len(bkids), len(bkidsigs))] - else: - result = [] - result += [nodeinfo_string(bkid, bkidsig, " ") - for bkid, bkidsig in zip(bkids, bkidsigs)] - if not result: - return None - return "\n ".join(result) - - -map_field = { - 'action' : map_action, - 'timestamp' : map_timestamp, - 'bkids' : map_bkids, -} - -map_name = { - 'implicit' : 'bkids', -} - - -def field(name, entry, verbose=Verbose): - if not Print_Flags[name]: - return None - fieldname = map_name.get(name, name) - mapper = map_field.get(fieldname, default_mapper) - val = mapper(entry, name) - if verbose: - val = name + ": " + val - return val - - -def nodeinfo_raw(name, ninfo, prefix=""): - """ - This just formats the dictionary, which we would normally use str() - to do, except that we want the keys sorted for deterministic output. - """ - d = ninfo.__getstate__() - try: - keys = ninfo.field_list + ['_version_id'] - except AttributeError: - keys = sorted(d.keys()) - l = [] - for k in keys: - l.append('%s: %s' % (repr(k), repr(d.get(k)))) - if '\n' in name: - name = repr(name) - return name + ': {' + ', '.join(l) + '}' - - -def nodeinfo_cooked(name, ninfo, prefix=""): - try: - field_list = ninfo.field_list - except AttributeError: - field_list = [] - if '\n' in name: - name = repr(name) - outlist = [name + ':'] + [ - f for f in [field(x, ninfo, Verbose) for x in field_list] if f - ] - if Verbose: - sep = '\n ' + prefix - else: - sep = ' ' - return sep.join(outlist) - - -nodeinfo_string = nodeinfo_cooked - - -def printfield(name, entry, prefix=""): - outlist = field("implicit", entry, 0) - if outlist: - if Verbose: - print(" implicit:") - print(" " + outlist) - outact = field("action", entry, 0) - if outact: - if Verbose: - print(" action: " + outact) - else: - print(" " + outact) - - -def printentries(entries, location): - if Print_Entries: - for name in Print_Entries: - try: - entry = entries[name] - except KeyError: - err = "sconsign: no entry `%s' in `%s'\n" % (name, location) - sys.stderr.write(err) - else: - try: - ninfo = entry.ninfo - except AttributeError: - print(name + ":") - else: - print(nodeinfo_string(name, entry.ninfo)) - printfield(name, entry.binfo) - else: - for name in sorted(entries.keys()): - entry = entries[name] - try: - ninfo = entry.ninfo - except AttributeError: - print(name + ":") - else: - print(nodeinfo_string(name, entry.ninfo)) - printfield(name, entry.binfo) - - -class Do_SConsignDB(object): - def __init__(self, dbm_name, dbm): - self.dbm_name = dbm_name - self.dbm = dbm - - def __call__(self, fname): - # The *dbm modules stick their own file suffixes on the names - # that are passed in. This causes us to jump through some - # hoops here. - try: - # Try opening the specified file name. Example: - # SPECIFIED OPENED BY self.dbm.open() - # --------- ------------------------- - # .sconsign => .sconsign.dblite - # .sconsign.dblite => .sconsign.dblite.dblite - db = self.dbm.open(fname, "r") - except (IOError, OSError) as e: - print_e = e - try: - # That didn't work, so try opening the base name, - # so that if they actually passed in 'sconsign.dblite' - # (for example), the dbm module will put the suffix back - # on for us and open it anyway. - db = self.dbm.open(os.path.splitext(fname)[0], "r") - except (IOError, OSError): - # That didn't work either. See if the file name - # they specified even exists (independent of the dbm - # suffix-mangling). - try: - with open(fname, "rb"): - pass # this is a touch only, we don't use it here. - except (IOError, OSError) as e: - # Nope, that file doesn't even exist, so report that - # fact back. - print_e = e - sys.stderr.write("sconsign: %s\n" % print_e) - return - except KeyboardInterrupt: - raise - except pickle.UnpicklingError: - sys.stderr.write("sconsign: ignoring invalid `%s' file `%s'\n" - % (self.dbm_name, fname)) - return - except Exception as e: - sys.stderr.write("sconsign: ignoring invalid `%s' file `%s': %s\n" - % (self.dbm_name, fname, e)) - exc_type, _, _ = sys.exc_info() - if exc_type.__name__ == "ValueError" and sys.version_info < (3,0,0): - sys.stderr.write("Python 2 only supports pickle protocols 0-2.\n") - return - - if Print_Directories: - for dir in Print_Directories: - try: - val = db[dir] - except KeyError: - err = "sconsign: no dir `%s' in `%s'\n" % (dir, args[0]) - sys.stderr.write(err) - else: - self.printentries(dir, val) - else: - for dir in sorted(db.keys()): - self.printentries(dir, db[dir]) - - @staticmethod - def printentries(dir, val): - try: - print('=== ' + dir + ':') - except TypeError: - print('=== ' + dir.decode() + ':') - printentries(pickle.loads(val), dir) - - -def Do_SConsignDir(name): - try: - with open(name, 'rb') as fp: - try: - sconsign = SCons.SConsign.Dir(fp) - except KeyboardInterrupt: - raise - except pickle.UnpicklingError: - err = "sconsign: ignoring invalid .sconsign file `%s'\n" % name - sys.stderr.write(err) - return - except Exception as e: - err = "sconsign: ignoring invalid .sconsign file `%s': %s\n" % (name, e) - sys.stderr.write(err) - return - printentries(sconsign.entries, args[0]) - except (IOError, OSError) as e: - sys.stderr.write("sconsign: %s\n" % e) - return - - -############################################################################## -def main(): - global Do_Call - - helpstr = """\ - Usage: sconsign [OPTIONS] [FILE ...] - Options: - -a, --act, --action Print build action information. - -c, --csig Print content signature information. - -d DIR, --dir=DIR Print only info about DIR. - -e ENTRY, --entry=ENTRY Print only info about ENTRY. - -f FORMAT, --format=FORMAT FILE is in the specified FORMAT. - -h, --help Print this message and exit. - -i, --implicit Print implicit dependency information. - -r, --readable Print timestamps in human-readable form. - --raw Print raw Python object representations. - -s, --size Print file sizes. - -t, --timestamp Print timestamp information. - -v, --verbose Verbose, describe each field. - """ - - try: - opts, args = getopt.getopt(sys.argv[1:], "acd:e:f:hirstv", - ['act', 'action', - 'csig', 'dir=', 'entry=', - 'format=', 'help', 'implicit', - 'raw', 'readable', - 'size', 'timestamp', 'verbose']) - except getopt.GetoptError as err: - sys.stderr.write(str(err) + '\n') - print(helpstr) - sys.exit(2) - - for o, a in opts: - if o in ('-a', '--act', '--action'): - Print_Flags['action'] = 1 - elif o in ('-c', '--csig'): - Print_Flags['csig'] = 1 - elif o in ('-d', '--dir'): - Print_Directories.append(a) - elif o in ('-e', '--entry'): - Print_Entries.append(a) - elif o in ('-f', '--format'): - # Try to map the given DB format to a known module - # name, that we can then try to import... - Module_Map = {'dblite': 'SCons.dblite', 'sconsign': None} - dbm_name = Module_Map.get(a, a) - if dbm_name: - try: - if dbm_name != "SCons.dblite": - dbm = my_import(dbm_name) - else: - import SCons.dblite - - dbm = SCons.dblite - # Ensure that we don't ignore corrupt DB files, - # this was handled by calling my_import('SCons.dblite') - # again in earlier versions... - SCons.dblite.ignore_corrupt_dbfiles = 0 - except ImportError: - sys.stderr.write("sconsign: illegal file format `%s'\n" % a) - print(helpstr) - sys.exit(2) - Do_Call = Do_SConsignDB(a, dbm) - else: - Do_Call = Do_SConsignDir - elif o in ('-h', '--help'): - print(helpstr) - sys.exit(0) - elif o in ('-i', '--implicit'): - Print_Flags['implicit'] = 1 - elif o in ('--raw',): - nodeinfo_string = nodeinfo_raw - elif o in ('-r', '--readable'): - Readable = 1 - elif o in ('-s', '--size'): - Print_Flags['size'] = 1 - elif o in ('-t', '--timestamp'): - Print_Flags['timestamp'] = 1 - elif o in ('-v', '--verbose'): - Verbose = 1 - - if Do_Call: - for a in args: - Do_Call(a) - else: - if not args: - args = [".sconsign.dblite"] - for a in args: - dbm_name = my_whichdb(a) - if dbm_name: - Map_Module = {'SCons.dblite': 'dblite'} - if dbm_name != "SCons.dblite": - dbm = my_import(dbm_name) - else: - import SCons.dblite - - dbm = SCons.dblite - # Ensure that we don't ignore corrupt DB files, - # this was handled by calling my_import('SCons.dblite') - # again in earlier versions... - SCons.dblite.ignore_corrupt_dbfiles = 0 - Do_SConsignDB(Map_Module.get(dbm_name, dbm_name), dbm)(a) - else: - Do_SConsignDir(a) - - if Warns: - print("NOTE: there were %d warnings, please check output" % Warns) - - - +from SCons.Utilities.sconsign import main if __name__ == "__main__": main() sys.exit(0) -- cgit v0.12 From 309b955883e72bebca17ce54c4a58e442107c90c Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 21 Mar 2020 17:16:24 -0700 Subject: move scons-time.py from scripts to bin. As far as I can tell this is really for internal use only --- bin/scons-time.py | 1480 +++++++++++++++++++++++++++++++++++++++++++++++++ scripts/scons-time.py | 1480 ------------------------------------------------- 2 files changed, 1480 insertions(+), 1480 deletions(-) create mode 100644 bin/scons-time.py delete mode 100644 scripts/scons-time.py diff --git a/bin/scons-time.py b/bin/scons-time.py new file mode 100644 index 0000000..e4dd863 --- /dev/null +++ b/bin/scons-time.py @@ -0,0 +1,1480 @@ +#!/usr/bin/env python +# +# scons-time - run SCons timings and collect statistics +# +# A script for running a configuration through SCons with a standard +# set of invocations to collect timing and memory statistics and to +# capture the results in a consistent set of output files for display +# and analysis. +# + +# +# __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 getopt +import glob +import os +import re +import shutil +import sys +import tempfile +import time +import subprocess + +def HACK_for_exec(cmd, *args): + """ + For some reason, Python won't allow an exec() within a function + that also declares an internal function (including lambda functions). + This function is a hack that calls exec() in a function with no + internal functions. + """ + if not args: exec(cmd) + elif len(args) == 1: exec(cmd, args[0]) + else: exec(cmd, args[0], args[1]) + +class Plotter(object): + def increment_size(self, largest): + """ + Return the size of each horizontal increment line for a specified + maximum value. This returns a value that will provide somewhere + between 5 and 9 horizontal lines on the graph, on some set of + boundaries that are multiples of 10/100/1000/etc. + """ + i = largest // 5 + if not i: + return largest + multiplier = 1 + while i >= 10: + i = i // 10 + multiplier = multiplier * 10 + return i * multiplier + + def max_graph_value(self, largest): + # Round up to next integer. + largest = int(largest) + 1 + increment = self.increment_size(largest) + return ((largest + increment - 1) // increment) * increment + +class Line(object): + def __init__(self, points, type, title, label, comment, fmt="%s %s"): + self.points = points + self.type = type + self.title = title + self.label = label + self.comment = comment + self.fmt = fmt + + def print_label(self, inx, x, y): + if self.label: + print('set label %s "%s" at %0.1f,%0.1f right' % (inx, self.label, x, y)) + + def plot_string(self): + if self.title: + title_string = 'title "%s"' % self.title + else: + title_string = 'notitle' + return "'-' %s with lines lt %s" % (title_string, self.type) + + def print_points(self, fmt=None): + if fmt is None: + fmt = self.fmt + if self.comment: + print('# %s' % self.comment) + for x, y in self.points: + # If y is None, it usually represents some kind of break + # in the line's index number. We might want to represent + # this some way rather than just drawing the line straight + # between the two points on either side. + if y is not None: + print(fmt % (x, y)) + print('e') + + def get_x_values(self): + return [ p[0] for p in self.points ] + + def get_y_values(self): + return [ p[1] for p in self.points ] + +class Gnuplotter(Plotter): + + def __init__(self, title, key_location): + self.lines = [] + self.title = title + self.key_location = key_location + + def line(self, points, type, title=None, label=None, comment=None, fmt='%s %s'): + if points: + line = Line(points, type, title, label, comment, fmt) + self.lines.append(line) + + def plot_string(self, line): + return line.plot_string() + + def vertical_bar(self, x, type, label, comment): + if self.get_min_x() <= x <= self.get_max_x(): + points = [(x, 0), (x, self.max_graph_value(self.get_max_y()))] + self.line(points, type, label, comment) + + def get_all_x_values(self): + result = [] + for line in self.lines: + result.extend(line.get_x_values()) + return [r for r in result if r is not None] + + def get_all_y_values(self): + result = [] + for line in self.lines: + result.extend(line.get_y_values()) + return [r for r in result if r is not None] + + def get_min_x(self): + try: + return self.min_x + except AttributeError: + try: + self.min_x = min(self.get_all_x_values()) + except ValueError: + self.min_x = 0 + return self.min_x + + def get_max_x(self): + try: + return self.max_x + except AttributeError: + try: + self.max_x = max(self.get_all_x_values()) + except ValueError: + self.max_x = 0 + return self.max_x + + def get_min_y(self): + try: + return self.min_y + except AttributeError: + try: + self.min_y = min(self.get_all_y_values()) + except ValueError: + self.min_y = 0 + return self.min_y + + def get_max_y(self): + try: + return self.max_y + except AttributeError: + try: + self.max_y = max(self.get_all_y_values()) + except ValueError: + self.max_y = 0 + return self.max_y + + def draw(self): + + if not self.lines: + return + + if self.title: + print('set title "%s"' % self.title) + print('set key %s' % self.key_location) + + min_y = self.get_min_y() + max_y = self.max_graph_value(self.get_max_y()) + incr = (max_y - min_y) / 10.0 + start = min_y + (max_y / 2.0) + (2.0 * incr) + position = [ start - (i * incr) for i in range(5) ] + + inx = 1 + for line in self.lines: + line.print_label(inx, line.points[0][0]-1, + position[(inx-1) % len(position)]) + inx += 1 + + plot_strings = [ self.plot_string(l) for l in self.lines ] + print('plot ' + ', \\\n '.join(plot_strings)) + + for line in self.lines: + line.print_points() + + + +def untar(fname): + import tarfile + tar = tarfile.open(name=fname, mode='r') + for tarinfo in tar: + tar.extract(tarinfo) + tar.close() + +def unzip(fname): + import zipfile + zf = zipfile.ZipFile(fname, 'r') + for name in zf.namelist(): + dir = os.path.dirname(name) + try: + os.makedirs(dir) + except: + pass + with open(name, 'wb') as f: + f.write(zf.read(name)) + +def read_tree(dir): + for dirpath, dirnames, filenames in os.walk(dir): + for fn in filenames: + fn = os.path.join(dirpath, fn) + if os.path.isfile(fn): + with open(fn, 'rb') as f: + f.read() + +def redirect_to_file(command, log): + return '%s > %s 2>&1' % (command, log) + +def tee_to_file(command, log): + return '%s 2>&1 | tee %s' % (command, log) + + + +class SConsTimer(object): + """ + Usage: scons-time SUBCOMMAND [ARGUMENTS] + Type "scons-time help SUBCOMMAND" for help on a specific subcommand. + + Available subcommands: + func Extract test-run data for a function + help Provides help + mem Extract --debug=memory data from test runs + obj Extract --debug=count data from test runs + time Extract --debug=time data from test runs + run Runs a test configuration + """ + + name = 'scons-time' + name_spaces = ' '*len(name) + + def makedict(**kw): + return kw + + default_settings = makedict( + chdir = None, + config_file = None, + initial_commands = [], + key_location = 'bottom left', + orig_cwd = os.getcwd(), + outdir = None, + prefix = '', + python = '"%s"' % sys.executable, + redirect = redirect_to_file, + scons = None, + scons_flags = '--debug=count --debug=memory --debug=time --debug=memoizer', + scons_lib_dir = None, + scons_wrapper = None, + startup_targets = '--help', + subdir = None, + subversion_url = None, + svn = 'svn', + svn_co_flag = '-q', + tar = 'tar', + targets = '', + targets0 = None, + targets1 = None, + targets2 = None, + title = None, + unzip = 'unzip', + verbose = False, + vertical_bars = [], + + unpack_map = { + '.tar.gz' : (untar, '%(tar)s xzf %%s'), + '.tgz' : (untar, '%(tar)s xzf %%s'), + '.tar' : (untar, '%(tar)s xf %%s'), + '.zip' : (unzip, '%(unzip)s %%s'), + }, + ) + + run_titles = [ + 'Startup', + 'Full build', + 'Up-to-date build', + ] + + run_commands = [ + '%(python)s %(scons_wrapper)s %(scons_flags)s --profile=%(prof0)s %(targets0)s', + '%(python)s %(scons_wrapper)s %(scons_flags)s --profile=%(prof1)s %(targets1)s', + '%(python)s %(scons_wrapper)s %(scons_flags)s --profile=%(prof2)s %(targets2)s', + ] + + stages = [ + 'pre-read', + 'post-read', + 'pre-build', + 'post-build', + ] + + stage_strings = { + 'pre-read' : 'Memory before reading SConscript files:', + 'post-read' : 'Memory after reading SConscript files:', + 'pre-build' : 'Memory before building targets:', + 'post-build' : 'Memory after building targets:', + } + + memory_string_all = 'Memory ' + + default_stage = stages[-1] + + time_strings = { + 'total' : 'Total build time', + 'SConscripts' : 'Total SConscript file execution time', + 'SCons' : 'Total SCons execution time', + 'commands' : 'Total command execution time', + } + + time_string_all = 'Total .* time' + + # + + def __init__(self): + self.__dict__.update(self.default_settings) + + # Functions for displaying and executing commands. + + def subst(self, x, dictionary): + try: + return x % dictionary + except TypeError: + # x isn't a string (it's probably a Python function), + # so just return it. + return x + + def subst_variables(self, command, dictionary): + """ + Substitutes (via the format operator) the values in the specified + dictionary into the specified command. + + The command can be an (action, string) tuple. In all cases, we + perform substitution on strings and don't worry if something isn't + a string. (It's probably a Python function to be executed.) + """ + try: + command + '' + except TypeError: + action = command[0] + string = command[1] + args = command[2:] + else: + action = command + string = action + args = (()) + action = self.subst(action, dictionary) + string = self.subst(string, dictionary) + return (action, string, args) + + def _do_not_display(self, msg, *args): + pass + + def display(self, msg, *args): + """ + Displays the specified message. + + Each message is prepended with a standard prefix of our name + plus the time. + """ + if callable(msg): + msg = msg(*args) + else: + msg = msg % args + if msg is None: + return + fmt = '%s[%s]: %s\n' + sys.stdout.write(fmt % (self.name, time.strftime('%H:%M:%S'), msg)) + + def _do_not_execute(self, action, *args): + pass + + def execute(self, action, *args): + """ + Executes the specified action. + + The action is called if it's a callable Python function, and + otherwise passed to os.system(). + """ + if callable(action): + action(*args) + else: + os.system(action % args) + + def run_command_list(self, commands, dict): + """ + Executes a list of commands, substituting values from the + specified dictionary. + """ + commands = [ self.subst_variables(c, dict) for c in commands ] + for action, string, args in commands: + self.display(string, *args) + sys.stdout.flush() + status = self.execute(action, *args) + if status: + sys.exit(status) + + def log_display(self, command, log): + command = self.subst(command, self.__dict__) + if log: + command = self.redirect(command, log) + return command + + def log_execute(self, command, log): + command = self.subst(command, self.__dict__) + p = os.popen(command) + output = p.read() + p.close() + #TODO: convert to subrocess, os.popen is obsolete. This didn't work: + #process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True) + #output = process.stdout.read() + #process.stdout.close() + #process.wait() + if self.verbose: + sys.stdout.write(output) + # TODO: Figure out + # Not sure we need to write binary here + with open(log, 'w') as f: + f.write(str(output)) + + def archive_splitext(self, path): + """ + Splits an archive name into a filename base and extension. + + This is like os.path.splitext() (which it calls) except that it + also looks for '.tar.gz' and treats it as an atomic extensions. + """ + if path.endswith('.tar.gz'): + return path[:-7], path[-7:] + else: + return os.path.splitext(path) + + def args_to_files(self, args, tail=None): + """ + Takes a list of arguments, expands any glob patterns, and + returns the last "tail" files from the list. + """ + files = [] + for a in args: + files.extend(sorted(glob.glob(a))) + + if tail: + files = files[-tail:] + + return files + + def ascii_table(self, files, columns, + line_function, file_function=lambda x: x, + *args, **kw): + + header_fmt = ' '.join(['%12s'] * len(columns)) + line_fmt = header_fmt + ' %s' + + print(header_fmt % columns) + + for file in files: + t = line_function(file, *args, **kw) + if t is None: + t = [] + diff = len(columns) - len(t) + if diff > 0: + t += [''] * diff + t.append(file_function(file)) + print(line_fmt % tuple(t)) + + def collect_results(self, files, function, *args, **kw): + results = {} + + for file in files: + base = os.path.splitext(file)[0] + run, index = base.split('-')[-2:] + + run = int(run) + index = int(index) + + value = function(file, *args, **kw) + + try: + r = results[index] + except KeyError: + r = [] + results[index] = r + r.append((run, value)) + + return results + + def doc_to_help(self, obj): + """ + Translates an object's __doc__ string into help text. + + This strips a consistent number of spaces from each line in the + help text, essentially "outdenting" the text to the left-most + column. + """ + doc = obj.__doc__ + if doc is None: + return '' + return self.outdent(doc) + + def find_next_run_number(self, dir, prefix): + """ + Returns the next run number in a directory for the specified prefix. + + Examines the contents the specified directory for files with the + specified prefix, extracts the run numbers from each file name, + and returns the next run number after the largest it finds. + """ + x = re.compile(re.escape(prefix) + '-([0-9]+).*') + matches = [x.match(e) for e in os.listdir(dir)] + matches = [_f for _f in matches if _f] + if not matches: + return 0 + run_numbers = [int(m.group(1)) for m in matches] + return int(max(run_numbers)) + 1 + + def gnuplot_results(self, results, fmt='%s %.3f'): + """ + Prints out a set of results in Gnuplot format. + """ + gp = Gnuplotter(self.title, self.key_location) + + for i in sorted(results.keys()): + try: + t = self.run_titles[i] + except IndexError: + t = '??? %s ???' % i + results[i].sort() + gp.line(results[i], i+1, t, None, t, fmt=fmt) + + for bar_tuple in self.vertical_bars: + try: + x, type, label, comment = bar_tuple + except ValueError: + x, type, label = bar_tuple + comment = label + gp.vertical_bar(x, type, label, comment) + + gp.draw() + + def logfile_name(self, invocation): + """ + Returns the absolute path of a log file for the specificed + invocation number. + """ + name = self.prefix_run + '-%d.log' % invocation + return os.path.join(self.outdir, name) + + def outdent(self, s): + """ + Strip as many spaces from each line as are found at the beginning + of the first line in the list. + """ + lines = s.split('\n') + if lines[0] == '': + lines = lines[1:] + spaces = re.match(' *', lines[0]).group(0) + def strip_initial_spaces(l, s=spaces): + if l.startswith(spaces): + l = l[len(spaces):] + return l + return '\n'.join([ strip_initial_spaces(l) for l in lines ]) + '\n' + + def profile_name(self, invocation): + """ + Returns the absolute path of a profile file for the specified + invocation number. + """ + name = self.prefix_run + '-%d.prof' % invocation + return os.path.join(self.outdir, name) + + def set_env(self, key, value): + os.environ[key] = value + + # + + def get_debug_times(self, file, time_string=None): + """ + Fetch times from the --debug=time strings in the specified file. + """ + if time_string is None: + search_string = self.time_string_all + else: + search_string = time_string + with open(file) as f: + contents = f.read() + 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 = [ float(r) for r in result ] + if time_string is not None: + try: + result = result[0] + except IndexError: + sys.stderr.write('file %s has no results!\n' % repr(file)) + return None + return result + + def get_function_profile(self, file, function): + """ + Returns the file, line number, function name, and cumulative time. + """ + try: + import pstats + except ImportError as e: + sys.stderr.write('%s: func: %s\n' % (self.name, e)) + sys.stderr.write('%s This version of Python is missing the profiler.\n' % self.name_spaces) + sys.stderr.write('%s Cannot use the "func" subcommand.\n' % self.name_spaces) + sys.exit(1) + statistics = pstats.Stats(file).stats + matches = [ e for e in statistics.items() if e[0][2] == function ] + r = matches[0] + return r[0][0], r[0][1], r[0][2], r[1][3] + + def get_function_time(self, file, function): + """ + Returns just the cumulative time for the specified function. + """ + return self.get_function_profile(file, function)[3] + + def get_memory(self, file, memory_string=None): + """ + Returns a list of integers of the amount of memory used. The + default behavior is to return all the stages. + """ + if memory_string is None: + search_string = self.memory_string_all + else: + search_string = memory_string + with open(file) as f: + lines = f.readlines() + lines = [ l for l in lines if l.startswith(search_string) ][-4:] + result = [ int(l.split()[-1]) for l in lines[-4:] ] + if len(result) == 1: + result = result[0] + return result + + def get_object_counts(self, file, object_name, index=None): + """ + Returns the counts of the specified object_name. + """ + object_string = ' ' + object_name + '\n' + with open(file) as f: + lines = f.readlines() + line = [ l for l in lines if l.endswith(object_string) ][0] + result = [ int(field) for field in line.split()[:4] ] + if index is not None: + result = result[index] + return result + + + command_alias = {} + + def execute_subcommand(self, argv): + """ + Executes the do_*() function for the specified subcommand (argv[0]). + """ + if not argv: + return + cmdName = self.command_alias.get(argv[0], argv[0]) + try: + func = getattr(self, 'do_' + cmdName) + except AttributeError: + return self.default(argv) + try: + return func(argv) + except TypeError as e: + sys.stderr.write("%s %s: %s\n" % (self.name, cmdName, e)) + import traceback + traceback.print_exc(file=sys.stderr) + sys.stderr.write("Try '%s help %s'\n" % (self.name, cmdName)) + + def default(self, argv): + """ + The default behavior for an unknown subcommand. Prints an + error message and exits. + """ + sys.stderr.write('%s: Unknown subcommand "%s".\n' % (self.name, argv[0])) + sys.stderr.write('Type "%s help" for usage.\n' % self.name) + sys.exit(1) + + # + + def do_help(self, argv): + """ + """ + if argv[1:]: + for arg in argv[1:]: + try: + func = getattr(self, 'do_' + arg) + except AttributeError: + sys.stderr.write('%s: No help for "%s"\n' % (self.name, arg)) + else: + try: + help = getattr(self, 'help_' + arg) + except AttributeError: + sys.stdout.write(self.doc_to_help(func)) + sys.stdout.flush() + else: + help() + else: + doc = self.doc_to_help(self.__class__) + if doc: + sys.stdout.write(doc) + sys.stdout.flush() + return None + + # + + def help_func(self): + help = """\ + Usage: scons-time func [OPTIONS] FILE [...] + + -C DIR, --chdir=DIR Change to DIR before looking for files + -f FILE, --file=FILE Read configuration from specified FILE + --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT + --func=NAME, --function=NAME Report time for function NAME + -h, --help Print this help and exit + -p STRING, --prefix=STRING Use STRING as log file/profile prefix + -t NUMBER, --tail=NUMBER Only report the last NUMBER files + --title=TITLE Specify the output plot TITLE + """ + sys.stdout.write(self.outdent(help)) + sys.stdout.flush() + + def do_func(self, argv): + """ + """ + format = 'ascii' + function_name = '_main' + tail = None + + short_opts = '?C:f:hp:t:' + + long_opts = [ + 'chdir=', + 'file=', + 'fmt=', + 'format=', + 'func=', + 'function=', + 'help', + 'prefix=', + 'tail=', + 'title=', + ] + + opts, args = getopt.getopt(argv[1:], short_opts, long_opts) + + for o, a in opts: + if o in ('-C', '--chdir'): + self.chdir = a + elif o in ('-f', '--file'): + self.config_file = a + elif o in ('--fmt', '--format'): + format = a + elif o in ('--func', '--function'): + function_name = a + elif o in ('-?', '-h', '--help'): + self.do_help(['help', 'func']) + sys.exit(0) + elif o in ('--max',): + max_time = int(a) + elif o in ('-p', '--prefix'): + self.prefix = a + elif o in ('-t', '--tail'): + tail = int(a) + elif o in ('--title',): + self.title = a + + if self.config_file: + with open(self.config_file, 'r') as f: + config = f.read() + exec(config, self.__dict__) + + if self.chdir: + os.chdir(self.chdir) + + if not args: + + pattern = '%s*.prof' % self.prefix + args = self.args_to_files([pattern], tail) + + if not args: + if self.chdir: + directory = self.chdir + else: + directory = os.getcwd() + + sys.stderr.write('%s: func: No arguments specified.\n' % self.name) + sys.stderr.write('%s No %s*.prof files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) + sys.stderr.write('%s Type "%s help func" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + + else: + + args = self.args_to_files(args, tail) + + cwd_ = os.getcwd() + os.sep + + if format == 'ascii': + + for file in args: + try: + f, line, func, time = \ + self.get_function_profile(file, function_name) + except ValueError as e: + sys.stderr.write("%s: func: %s: %s\n" % + (self.name, file, e)) + else: + if f.startswith(cwd_): + f = f[len(cwd_):] + print("%.3f %s:%d(%s)" % (time, f, line, func)) + + elif format == 'gnuplot': + + results = self.collect_results(args, self.get_function_time, + function_name) + + self.gnuplot_results(results) + + else: + + sys.stderr.write('%s: func: Unknown format "%s".\n' % (self.name, format)) + sys.exit(1) + + # + + def help_mem(self): + help = """\ + Usage: scons-time mem [OPTIONS] FILE [...] + + -C DIR, --chdir=DIR Change to DIR before looking for files + -f FILE, --file=FILE Read configuration from specified FILE + --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT + -h, --help Print this help and exit + -p STRING, --prefix=STRING Use STRING as log file/profile prefix + --stage=STAGE Plot memory at the specified stage: + pre-read, post-read, pre-build, + post-build (default: post-build) + -t NUMBER, --tail=NUMBER Only report the last NUMBER files + --title=TITLE Specify the output plot TITLE + """ + sys.stdout.write(self.outdent(help)) + sys.stdout.flush() + + def do_mem(self, argv): + + format = 'ascii' + logfile_path = lambda x: x + stage = self.default_stage + tail = None + + short_opts = '?C:f:hp:t:' + + long_opts = [ + 'chdir=', + 'file=', + 'fmt=', + 'format=', + 'help', + 'prefix=', + 'stage=', + 'tail=', + 'title=', + ] + + opts, args = getopt.getopt(argv[1:], short_opts, long_opts) + + for o, a in opts: + if o in ('-C', '--chdir'): + self.chdir = a + elif o in ('-f', '--file'): + self.config_file = a + elif o in ('--fmt', '--format'): + format = a + elif o in ('-?', '-h', '--help'): + self.do_help(['help', 'mem']) + sys.exit(0) + elif o in ('-p', '--prefix'): + self.prefix = a + elif o in ('--stage',): + if a not in self.stages: + sys.stderr.write('%s: mem: Unrecognized stage "%s".\n' % (self.name, a)) + sys.exit(1) + stage = a + elif o in ('-t', '--tail'): + tail = int(a) + elif o in ('--title',): + self.title = a + + if self.config_file: + with open(self.config_file, 'r') as f: + config = f.read() + HACK_for_exec(config, self.__dict__) + + if self.chdir: + os.chdir(self.chdir) + logfile_path = lambda x: os.path.join(self.chdir, x) + + if not args: + + pattern = '%s*.log' % self.prefix + args = self.args_to_files([pattern], tail) + + if not args: + if self.chdir: + directory = self.chdir + else: + directory = os.getcwd() + + sys.stderr.write('%s: mem: No arguments specified.\n' % self.name) + sys.stderr.write('%s No %s*.log files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) + sys.stderr.write('%s Type "%s help mem" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + + else: + + args = self.args_to_files(args, tail) + + cwd_ = os.getcwd() + os.sep + + if format == 'ascii': + + self.ascii_table(args, tuple(self.stages), self.get_memory, logfile_path) + + elif format == 'gnuplot': + + results = self.collect_results(args, self.get_memory, + self.stage_strings[stage]) + + self.gnuplot_results(results) + + else: + + sys.stderr.write('%s: mem: Unknown format "%s".\n' % (self.name, format)) + sys.exit(1) + + return 0 + + # + + def help_obj(self): + help = """\ + Usage: scons-time obj [OPTIONS] OBJECT FILE [...] + + -C DIR, --chdir=DIR Change to DIR before looking for files + -f FILE, --file=FILE Read configuration from specified FILE + --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT + -h, --help Print this help and exit + -p STRING, --prefix=STRING Use STRING as log file/profile prefix + --stage=STAGE Plot memory at the specified stage: + pre-read, post-read, pre-build, + post-build (default: post-build) + -t NUMBER, --tail=NUMBER Only report the last NUMBER files + --title=TITLE Specify the output plot TITLE + """ + sys.stdout.write(self.outdent(help)) + sys.stdout.flush() + + def do_obj(self, argv): + + format = 'ascii' + logfile_path = lambda x: x + stage = self.default_stage + tail = None + + short_opts = '?C:f:hp:t:' + + long_opts = [ + 'chdir=', + 'file=', + 'fmt=', + 'format=', + 'help', + 'prefix=', + 'stage=', + 'tail=', + 'title=', + ] + + opts, args = getopt.getopt(argv[1:], short_opts, long_opts) + + for o, a in opts: + if o in ('-C', '--chdir'): + self.chdir = a + elif o in ('-f', '--file'): + self.config_file = a + elif o in ('--fmt', '--format'): + format = a + elif o in ('-?', '-h', '--help'): + self.do_help(['help', 'obj']) + sys.exit(0) + elif o in ('-p', '--prefix'): + self.prefix = a + elif o in ('--stage',): + if a not in self.stages: + sys.stderr.write('%s: obj: Unrecognized stage "%s".\n' % (self.name, a)) + sys.stderr.write('%s Type "%s help obj" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + stage = a + elif o in ('-t', '--tail'): + tail = int(a) + elif o in ('--title',): + self.title = a + + if not args: + sys.stderr.write('%s: obj: Must specify an object name.\n' % self.name) + sys.stderr.write('%s Type "%s help obj" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + + object_name = args.pop(0) + + if self.config_file: + with open(self.config_file, 'r') as f: + config = f.read() + HACK_for_exec(config, self.__dict__) + + if self.chdir: + os.chdir(self.chdir) + logfile_path = lambda x: os.path.join(self.chdir, x) + + if not args: + + pattern = '%s*.log' % self.prefix + args = self.args_to_files([pattern], tail) + + if not args: + if self.chdir: + directory = self.chdir + else: + directory = os.getcwd() + + sys.stderr.write('%s: obj: No arguments specified.\n' % self.name) + sys.stderr.write('%s No %s*.log files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) + sys.stderr.write('%s Type "%s help obj" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + + else: + + args = self.args_to_files(args, tail) + + cwd_ = os.getcwd() + os.sep + + if format == 'ascii': + + self.ascii_table(args, tuple(self.stages), self.get_object_counts, logfile_path, object_name) + + elif format == 'gnuplot': + + stage_index = 0 + for s in self.stages: + if stage == s: + break + stage_index = stage_index + 1 + + results = self.collect_results(args, self.get_object_counts, + object_name, stage_index) + + self.gnuplot_results(results) + + else: + + sys.stderr.write('%s: obj: Unknown format "%s".\n' % (self.name, format)) + sys.exit(1) + + return 0 + + # + + def help_run(self): + help = """\ + Usage: scons-time run [OPTIONS] [FILE ...] + + --chdir=DIR Name of unpacked directory for chdir + -f FILE, --file=FILE Read configuration from specified FILE + -h, --help Print this help and exit + -n, --no-exec No execute, just print command lines + --number=NUMBER Put output in files for run NUMBER + --outdir=OUTDIR Put output files in OUTDIR + -p STRING, --prefix=STRING Use STRING as log file/profile prefix + --python=PYTHON Time using the specified PYTHON + -q, --quiet Don't print command lines + --scons=SCONS Time using the specified SCONS + --svn=URL, --subversion=URL Use SCons from Subversion URL + -v, --verbose Display output of commands + """ + sys.stdout.write(self.outdent(help)) + sys.stdout.flush() + + def do_run(self, argv): + """ + """ + run_number_list = [None] + + short_opts = '?f:hnp:qs:v' + + long_opts = [ + 'file=', + 'help', + 'no-exec', + 'number=', + 'outdir=', + 'prefix=', + 'python=', + 'quiet', + 'scons=', + 'svn=', + 'subdir=', + 'subversion=', + 'verbose', + ] + + opts, args = getopt.getopt(argv[1:], short_opts, long_opts) + + for o, a in opts: + if o in ('-f', '--file'): + self.config_file = a + elif o in ('-?', '-h', '--help'): + self.do_help(['help', 'run']) + sys.exit(0) + elif o in ('-n', '--no-exec'): + self.execute = self._do_not_execute + elif o in ('--number',): + run_number_list = self.split_run_numbers(a) + elif o in ('--outdir',): + self.outdir = a + elif o in ('-p', '--prefix'): + self.prefix = a + elif o in ('--python',): + self.python = a + elif o in ('-q', '--quiet'): + self.display = self._do_not_display + elif o in ('-s', '--subdir'): + self.subdir = a + elif o in ('--scons',): + self.scons = a + elif o in ('--svn', '--subversion'): + self.subversion_url = a + elif o in ('-v', '--verbose'): + self.redirect = tee_to_file + self.verbose = True + self.svn_co_flag = '' + + if not args and not self.config_file: + sys.stderr.write('%s: run: No arguments or -f config file specified.\n' % self.name) + sys.stderr.write('%s Type "%s help run" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + + if self.config_file: + with open(self.config_file, 'r') as f: + config = f.read() + exec(config, self.__dict__) + + if args: + self.archive_list = args + + archive_file_name = os.path.split(self.archive_list[0])[1] + + if not self.subdir: + self.subdir = self.archive_splitext(archive_file_name)[0] + + if not self.prefix: + self.prefix = self.archive_splitext(archive_file_name)[0] + + prepare = None + if self.subversion_url: + prepare = self.prep_subversion_run + + for run_number in run_number_list: + self.individual_run(run_number, self.archive_list, prepare) + + def split_run_numbers(self, s): + result = [] + for n in s.split(','): + try: + x, y = n.split('-') + except ValueError: + result.append(int(n)) + else: + result.extend(list(range(int(x), int(y)+1))) + return result + + def scons_path(self, dir): + return os.path.join(dir, 'src', 'script', 'scons.py') + + def scons_lib_dir_path(self, dir): + return os.path.join(dir, 'src', 'engine') + + def prep_subversion_run(self, commands, removals): + self.svn_tmpdir = tempfile.mkdtemp(prefix=self.name + '-svn-') + removals.append((shutil.rmtree, 'rm -rf %%s', self.svn_tmpdir)) + + self.scons = self.scons_path(self.svn_tmpdir) + self.scons_lib_dir = self.scons_lib_dir_path(self.svn_tmpdir) + + commands.extend([ + '%(svn)s co %(svn_co_flag)s -r %(run_number)s %(subversion_url)s %(svn_tmpdir)s', + ]) + + def individual_run(self, run_number, archive_list, prepare=None): + """ + Performs an individual run of the default SCons invocations. + """ + + commands = [] + removals = [] + + if prepare: + prepare(commands, removals) + + save_scons = self.scons + save_scons_wrapper = self.scons_wrapper + save_scons_lib_dir = self.scons_lib_dir + + if self.outdir is None: + self.outdir = self.orig_cwd + elif not os.path.isabs(self.outdir): + self.outdir = os.path.join(self.orig_cwd, self.outdir) + + if self.scons is None: + self.scons = self.scons_path(self.orig_cwd) + + if self.scons_lib_dir is None: + self.scons_lib_dir = self.scons_lib_dir_path(self.orig_cwd) + + if self.scons_wrapper is None: + self.scons_wrapper = self.scons + + if not run_number: + run_number = self.find_next_run_number(self.outdir, self.prefix) + + self.run_number = str(run_number) + + self.prefix_run = self.prefix + '-%03d' % run_number + + if self.targets0 is None: + self.targets0 = self.startup_targets + if self.targets1 is None: + self.targets1 = self.targets + if self.targets2 is None: + self.targets2 = self.targets + + self.tmpdir = tempfile.mkdtemp(prefix=self.name + '-') + + commands.extend([ + (os.chdir, 'cd %%s', self.tmpdir), + ]) + + for archive in archive_list: + if not os.path.isabs(archive): + archive = os.path.join(self.orig_cwd, archive) + if os.path.isdir(archive): + dest = os.path.split(archive)[1] + commands.append((shutil.copytree, 'cp -r %%s %%s', archive, dest)) + else: + suffix = self.archive_splitext(archive)[1] + unpack_command = self.unpack_map.get(suffix) + if not unpack_command: + dest = os.path.split(archive)[1] + commands.append((shutil.copyfile, 'cp %%s %%s', archive, dest)) + else: + commands.append(unpack_command + (archive,)) + + commands.extend([ + (os.chdir, 'cd %%s', self.subdir), + ]) + + commands.extend(self.initial_commands) + + commands.extend([ + (lambda: read_tree('.'), + 'find * -type f | xargs cat > /dev/null'), + + (self.set_env, 'export %%s=%%s', + 'SCONS_LIB_DIR', self.scons_lib_dir), + + '%(python)s %(scons_wrapper)s --version', + ]) + + index = 0 + for run_command in self.run_commands: + setattr(self, 'prof%d' % index, self.profile_name(index)) + c = ( + self.log_execute, + self.log_display, + run_command, + self.logfile_name(index), + ) + commands.append(c) + index = index + 1 + + commands.extend([ + (os.chdir, 'cd %%s', self.orig_cwd), + ]) + + if not os.environ.get('PRESERVE'): + commands.extend(removals) + commands.append((shutil.rmtree, 'rm -rf %%s', self.tmpdir)) + + self.run_command_list(commands, self.__dict__) + + self.scons = save_scons + self.scons_lib_dir = save_scons_lib_dir + self.scons_wrapper = save_scons_wrapper + + # + + def help_time(self): + help = """\ + Usage: scons-time time [OPTIONS] FILE [...] + + -C DIR, --chdir=DIR Change to DIR before looking for files + -f FILE, --file=FILE Read configuration from specified FILE + --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT + -h, --help Print this help and exit + -p STRING, --prefix=STRING Use STRING as log file/profile prefix + -t NUMBER, --tail=NUMBER Only report the last NUMBER files + --which=TIMER Plot timings for TIMER: total, + SConscripts, SCons, commands. + """ + sys.stdout.write(self.outdent(help)) + sys.stdout.flush() + + def do_time(self, argv): + + format = 'ascii' + logfile_path = lambda x: x + tail = None + which = 'total' + + short_opts = '?C:f:hp:t:' + + long_opts = [ + 'chdir=', + 'file=', + 'fmt=', + 'format=', + 'help', + 'prefix=', + 'tail=', + 'title=', + 'which=', + ] + + opts, args = getopt.getopt(argv[1:], short_opts, long_opts) + + for o, a in opts: + if o in ('-C', '--chdir'): + self.chdir = a + elif o in ('-f', '--file'): + self.config_file = a + elif o in ('--fmt', '--format'): + format = a + elif o in ('-?', '-h', '--help'): + self.do_help(['help', 'time']) + sys.exit(0) + elif o in ('-p', '--prefix'): + self.prefix = a + elif o in ('-t', '--tail'): + tail = int(a) + elif o in ('--title',): + self.title = a + elif o in ('--which',): + if a not in list(self.time_strings.keys()): + sys.stderr.write('%s: time: Unrecognized timer "%s".\n' % (self.name, a)) + sys.stderr.write('%s Type "%s help time" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + which = a + + if self.config_file: + with open(self.config_file, 'r') as f: + config = f.read() + HACK_for_exec(config, self.__dict__) + + if self.chdir: + os.chdir(self.chdir) + logfile_path = lambda x: os.path.join(self.chdir, x) + + if not args: + + pattern = '%s*.log' % self.prefix + args = self.args_to_files([pattern], tail) + + if not args: + if self.chdir: + directory = self.chdir + else: + directory = os.getcwd() + + sys.stderr.write('%s: time: No arguments specified.\n' % self.name) + sys.stderr.write('%s No %s*.log files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) + sys.stderr.write('%s Type "%s help time" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + + else: + + args = self.args_to_files(args, tail) + + cwd_ = os.getcwd() + os.sep + + if format == 'ascii': + + columns = ("Total", "SConscripts", "SCons", "commands") + self.ascii_table(args, columns, self.get_debug_times, logfile_path) + + elif format == 'gnuplot': + + results = self.collect_results(args, self.get_debug_times, + self.time_strings[which]) + + self.gnuplot_results(results, fmt='%s %.6f') + + else: + + sys.stderr.write('%s: time: Unknown format "%s".\n' % (self.name, format)) + sys.exit(1) + +if __name__ == '__main__': + opts, args = getopt.getopt(sys.argv[1:], 'h?V', ['help', 'version']) + + ST = SConsTimer() + + for o, a in opts: + if o in ('-?', '-h', '--help'): + ST.do_help(['help']) + sys.exit(0) + elif o in ('-V', '--version'): + sys.stdout.write('scons-time version\n') + sys.exit(0) + + if not args: + sys.stderr.write('Type "%s help" for usage.\n' % ST.name) + sys.exit(1) + + ST.execute_subcommand(args) + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/scripts/scons-time.py b/scripts/scons-time.py deleted file mode 100644 index e4dd863..0000000 --- a/scripts/scons-time.py +++ /dev/null @@ -1,1480 +0,0 @@ -#!/usr/bin/env python -# -# scons-time - run SCons timings and collect statistics -# -# A script for running a configuration through SCons with a standard -# set of invocations to collect timing and memory statistics and to -# capture the results in a consistent set of output files for display -# and analysis. -# - -# -# __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 getopt -import glob -import os -import re -import shutil -import sys -import tempfile -import time -import subprocess - -def HACK_for_exec(cmd, *args): - """ - For some reason, Python won't allow an exec() within a function - that also declares an internal function (including lambda functions). - This function is a hack that calls exec() in a function with no - internal functions. - """ - if not args: exec(cmd) - elif len(args) == 1: exec(cmd, args[0]) - else: exec(cmd, args[0], args[1]) - -class Plotter(object): - def increment_size(self, largest): - """ - Return the size of each horizontal increment line for a specified - maximum value. This returns a value that will provide somewhere - between 5 and 9 horizontal lines on the graph, on some set of - boundaries that are multiples of 10/100/1000/etc. - """ - i = largest // 5 - if not i: - return largest - multiplier = 1 - while i >= 10: - i = i // 10 - multiplier = multiplier * 10 - return i * multiplier - - def max_graph_value(self, largest): - # Round up to next integer. - largest = int(largest) + 1 - increment = self.increment_size(largest) - return ((largest + increment - 1) // increment) * increment - -class Line(object): - def __init__(self, points, type, title, label, comment, fmt="%s %s"): - self.points = points - self.type = type - self.title = title - self.label = label - self.comment = comment - self.fmt = fmt - - def print_label(self, inx, x, y): - if self.label: - print('set label %s "%s" at %0.1f,%0.1f right' % (inx, self.label, x, y)) - - def plot_string(self): - if self.title: - title_string = 'title "%s"' % self.title - else: - title_string = 'notitle' - return "'-' %s with lines lt %s" % (title_string, self.type) - - def print_points(self, fmt=None): - if fmt is None: - fmt = self.fmt - if self.comment: - print('# %s' % self.comment) - for x, y in self.points: - # If y is None, it usually represents some kind of break - # in the line's index number. We might want to represent - # this some way rather than just drawing the line straight - # between the two points on either side. - if y is not None: - print(fmt % (x, y)) - print('e') - - def get_x_values(self): - return [ p[0] for p in self.points ] - - def get_y_values(self): - return [ p[1] for p in self.points ] - -class Gnuplotter(Plotter): - - def __init__(self, title, key_location): - self.lines = [] - self.title = title - self.key_location = key_location - - def line(self, points, type, title=None, label=None, comment=None, fmt='%s %s'): - if points: - line = Line(points, type, title, label, comment, fmt) - self.lines.append(line) - - def plot_string(self, line): - return line.plot_string() - - def vertical_bar(self, x, type, label, comment): - if self.get_min_x() <= x <= self.get_max_x(): - points = [(x, 0), (x, self.max_graph_value(self.get_max_y()))] - self.line(points, type, label, comment) - - def get_all_x_values(self): - result = [] - for line in self.lines: - result.extend(line.get_x_values()) - return [r for r in result if r is not None] - - def get_all_y_values(self): - result = [] - for line in self.lines: - result.extend(line.get_y_values()) - return [r for r in result if r is not None] - - def get_min_x(self): - try: - return self.min_x - except AttributeError: - try: - self.min_x = min(self.get_all_x_values()) - except ValueError: - self.min_x = 0 - return self.min_x - - def get_max_x(self): - try: - return self.max_x - except AttributeError: - try: - self.max_x = max(self.get_all_x_values()) - except ValueError: - self.max_x = 0 - return self.max_x - - def get_min_y(self): - try: - return self.min_y - except AttributeError: - try: - self.min_y = min(self.get_all_y_values()) - except ValueError: - self.min_y = 0 - return self.min_y - - def get_max_y(self): - try: - return self.max_y - except AttributeError: - try: - self.max_y = max(self.get_all_y_values()) - except ValueError: - self.max_y = 0 - return self.max_y - - def draw(self): - - if not self.lines: - return - - if self.title: - print('set title "%s"' % self.title) - print('set key %s' % self.key_location) - - min_y = self.get_min_y() - max_y = self.max_graph_value(self.get_max_y()) - incr = (max_y - min_y) / 10.0 - start = min_y + (max_y / 2.0) + (2.0 * incr) - position = [ start - (i * incr) for i in range(5) ] - - inx = 1 - for line in self.lines: - line.print_label(inx, line.points[0][0]-1, - position[(inx-1) % len(position)]) - inx += 1 - - plot_strings = [ self.plot_string(l) for l in self.lines ] - print('plot ' + ', \\\n '.join(plot_strings)) - - for line in self.lines: - line.print_points() - - - -def untar(fname): - import tarfile - tar = tarfile.open(name=fname, mode='r') - for tarinfo in tar: - tar.extract(tarinfo) - tar.close() - -def unzip(fname): - import zipfile - zf = zipfile.ZipFile(fname, 'r') - for name in zf.namelist(): - dir = os.path.dirname(name) - try: - os.makedirs(dir) - except: - pass - with open(name, 'wb') as f: - f.write(zf.read(name)) - -def read_tree(dir): - for dirpath, dirnames, filenames in os.walk(dir): - for fn in filenames: - fn = os.path.join(dirpath, fn) - if os.path.isfile(fn): - with open(fn, 'rb') as f: - f.read() - -def redirect_to_file(command, log): - return '%s > %s 2>&1' % (command, log) - -def tee_to_file(command, log): - return '%s 2>&1 | tee %s' % (command, log) - - - -class SConsTimer(object): - """ - Usage: scons-time SUBCOMMAND [ARGUMENTS] - Type "scons-time help SUBCOMMAND" for help on a specific subcommand. - - Available subcommands: - func Extract test-run data for a function - help Provides help - mem Extract --debug=memory data from test runs - obj Extract --debug=count data from test runs - time Extract --debug=time data from test runs - run Runs a test configuration - """ - - name = 'scons-time' - name_spaces = ' '*len(name) - - def makedict(**kw): - return kw - - default_settings = makedict( - chdir = None, - config_file = None, - initial_commands = [], - key_location = 'bottom left', - orig_cwd = os.getcwd(), - outdir = None, - prefix = '', - python = '"%s"' % sys.executable, - redirect = redirect_to_file, - scons = None, - scons_flags = '--debug=count --debug=memory --debug=time --debug=memoizer', - scons_lib_dir = None, - scons_wrapper = None, - startup_targets = '--help', - subdir = None, - subversion_url = None, - svn = 'svn', - svn_co_flag = '-q', - tar = 'tar', - targets = '', - targets0 = None, - targets1 = None, - targets2 = None, - title = None, - unzip = 'unzip', - verbose = False, - vertical_bars = [], - - unpack_map = { - '.tar.gz' : (untar, '%(tar)s xzf %%s'), - '.tgz' : (untar, '%(tar)s xzf %%s'), - '.tar' : (untar, '%(tar)s xf %%s'), - '.zip' : (unzip, '%(unzip)s %%s'), - }, - ) - - run_titles = [ - 'Startup', - 'Full build', - 'Up-to-date build', - ] - - run_commands = [ - '%(python)s %(scons_wrapper)s %(scons_flags)s --profile=%(prof0)s %(targets0)s', - '%(python)s %(scons_wrapper)s %(scons_flags)s --profile=%(prof1)s %(targets1)s', - '%(python)s %(scons_wrapper)s %(scons_flags)s --profile=%(prof2)s %(targets2)s', - ] - - stages = [ - 'pre-read', - 'post-read', - 'pre-build', - 'post-build', - ] - - stage_strings = { - 'pre-read' : 'Memory before reading SConscript files:', - 'post-read' : 'Memory after reading SConscript files:', - 'pre-build' : 'Memory before building targets:', - 'post-build' : 'Memory after building targets:', - } - - memory_string_all = 'Memory ' - - default_stage = stages[-1] - - time_strings = { - 'total' : 'Total build time', - 'SConscripts' : 'Total SConscript file execution time', - 'SCons' : 'Total SCons execution time', - 'commands' : 'Total command execution time', - } - - time_string_all = 'Total .* time' - - # - - def __init__(self): - self.__dict__.update(self.default_settings) - - # Functions for displaying and executing commands. - - def subst(self, x, dictionary): - try: - return x % dictionary - except TypeError: - # x isn't a string (it's probably a Python function), - # so just return it. - return x - - def subst_variables(self, command, dictionary): - """ - Substitutes (via the format operator) the values in the specified - dictionary into the specified command. - - The command can be an (action, string) tuple. In all cases, we - perform substitution on strings and don't worry if something isn't - a string. (It's probably a Python function to be executed.) - """ - try: - command + '' - except TypeError: - action = command[0] - string = command[1] - args = command[2:] - else: - action = command - string = action - args = (()) - action = self.subst(action, dictionary) - string = self.subst(string, dictionary) - return (action, string, args) - - def _do_not_display(self, msg, *args): - pass - - def display(self, msg, *args): - """ - Displays the specified message. - - Each message is prepended with a standard prefix of our name - plus the time. - """ - if callable(msg): - msg = msg(*args) - else: - msg = msg % args - if msg is None: - return - fmt = '%s[%s]: %s\n' - sys.stdout.write(fmt % (self.name, time.strftime('%H:%M:%S'), msg)) - - def _do_not_execute(self, action, *args): - pass - - def execute(self, action, *args): - """ - Executes the specified action. - - The action is called if it's a callable Python function, and - otherwise passed to os.system(). - """ - if callable(action): - action(*args) - else: - os.system(action % args) - - def run_command_list(self, commands, dict): - """ - Executes a list of commands, substituting values from the - specified dictionary. - """ - commands = [ self.subst_variables(c, dict) for c in commands ] - for action, string, args in commands: - self.display(string, *args) - sys.stdout.flush() - status = self.execute(action, *args) - if status: - sys.exit(status) - - def log_display(self, command, log): - command = self.subst(command, self.__dict__) - if log: - command = self.redirect(command, log) - return command - - def log_execute(self, command, log): - command = self.subst(command, self.__dict__) - p = os.popen(command) - output = p.read() - p.close() - #TODO: convert to subrocess, os.popen is obsolete. This didn't work: - #process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True) - #output = process.stdout.read() - #process.stdout.close() - #process.wait() - if self.verbose: - sys.stdout.write(output) - # TODO: Figure out - # Not sure we need to write binary here - with open(log, 'w') as f: - f.write(str(output)) - - def archive_splitext(self, path): - """ - Splits an archive name into a filename base and extension. - - This is like os.path.splitext() (which it calls) except that it - also looks for '.tar.gz' and treats it as an atomic extensions. - """ - if path.endswith('.tar.gz'): - return path[:-7], path[-7:] - else: - return os.path.splitext(path) - - def args_to_files(self, args, tail=None): - """ - Takes a list of arguments, expands any glob patterns, and - returns the last "tail" files from the list. - """ - files = [] - for a in args: - files.extend(sorted(glob.glob(a))) - - if tail: - files = files[-tail:] - - return files - - def ascii_table(self, files, columns, - line_function, file_function=lambda x: x, - *args, **kw): - - header_fmt = ' '.join(['%12s'] * len(columns)) - line_fmt = header_fmt + ' %s' - - print(header_fmt % columns) - - for file in files: - t = line_function(file, *args, **kw) - if t is None: - t = [] - diff = len(columns) - len(t) - if diff > 0: - t += [''] * diff - t.append(file_function(file)) - print(line_fmt % tuple(t)) - - def collect_results(self, files, function, *args, **kw): - results = {} - - for file in files: - base = os.path.splitext(file)[0] - run, index = base.split('-')[-2:] - - run = int(run) - index = int(index) - - value = function(file, *args, **kw) - - try: - r = results[index] - except KeyError: - r = [] - results[index] = r - r.append((run, value)) - - return results - - def doc_to_help(self, obj): - """ - Translates an object's __doc__ string into help text. - - This strips a consistent number of spaces from each line in the - help text, essentially "outdenting" the text to the left-most - column. - """ - doc = obj.__doc__ - if doc is None: - return '' - return self.outdent(doc) - - def find_next_run_number(self, dir, prefix): - """ - Returns the next run number in a directory for the specified prefix. - - Examines the contents the specified directory for files with the - specified prefix, extracts the run numbers from each file name, - and returns the next run number after the largest it finds. - """ - x = re.compile(re.escape(prefix) + '-([0-9]+).*') - matches = [x.match(e) for e in os.listdir(dir)] - matches = [_f for _f in matches if _f] - if not matches: - return 0 - run_numbers = [int(m.group(1)) for m in matches] - return int(max(run_numbers)) + 1 - - def gnuplot_results(self, results, fmt='%s %.3f'): - """ - Prints out a set of results in Gnuplot format. - """ - gp = Gnuplotter(self.title, self.key_location) - - for i in sorted(results.keys()): - try: - t = self.run_titles[i] - except IndexError: - t = '??? %s ???' % i - results[i].sort() - gp.line(results[i], i+1, t, None, t, fmt=fmt) - - for bar_tuple in self.vertical_bars: - try: - x, type, label, comment = bar_tuple - except ValueError: - x, type, label = bar_tuple - comment = label - gp.vertical_bar(x, type, label, comment) - - gp.draw() - - def logfile_name(self, invocation): - """ - Returns the absolute path of a log file for the specificed - invocation number. - """ - name = self.prefix_run + '-%d.log' % invocation - return os.path.join(self.outdir, name) - - def outdent(self, s): - """ - Strip as many spaces from each line as are found at the beginning - of the first line in the list. - """ - lines = s.split('\n') - if lines[0] == '': - lines = lines[1:] - spaces = re.match(' *', lines[0]).group(0) - def strip_initial_spaces(l, s=spaces): - if l.startswith(spaces): - l = l[len(spaces):] - return l - return '\n'.join([ strip_initial_spaces(l) for l in lines ]) + '\n' - - def profile_name(self, invocation): - """ - Returns the absolute path of a profile file for the specified - invocation number. - """ - name = self.prefix_run + '-%d.prof' % invocation - return os.path.join(self.outdir, name) - - def set_env(self, key, value): - os.environ[key] = value - - # - - def get_debug_times(self, file, time_string=None): - """ - Fetch times from the --debug=time strings in the specified file. - """ - if time_string is None: - search_string = self.time_string_all - else: - search_string = time_string - with open(file) as f: - contents = f.read() - 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 = [ float(r) for r in result ] - if time_string is not None: - try: - result = result[0] - except IndexError: - sys.stderr.write('file %s has no results!\n' % repr(file)) - return None - return result - - def get_function_profile(self, file, function): - """ - Returns the file, line number, function name, and cumulative time. - """ - try: - import pstats - except ImportError as e: - sys.stderr.write('%s: func: %s\n' % (self.name, e)) - sys.stderr.write('%s This version of Python is missing the profiler.\n' % self.name_spaces) - sys.stderr.write('%s Cannot use the "func" subcommand.\n' % self.name_spaces) - sys.exit(1) - statistics = pstats.Stats(file).stats - matches = [ e for e in statistics.items() if e[0][2] == function ] - r = matches[0] - return r[0][0], r[0][1], r[0][2], r[1][3] - - def get_function_time(self, file, function): - """ - Returns just the cumulative time for the specified function. - """ - return self.get_function_profile(file, function)[3] - - def get_memory(self, file, memory_string=None): - """ - Returns a list of integers of the amount of memory used. The - default behavior is to return all the stages. - """ - if memory_string is None: - search_string = self.memory_string_all - else: - search_string = memory_string - with open(file) as f: - lines = f.readlines() - lines = [ l for l in lines if l.startswith(search_string) ][-4:] - result = [ int(l.split()[-1]) for l in lines[-4:] ] - if len(result) == 1: - result = result[0] - return result - - def get_object_counts(self, file, object_name, index=None): - """ - Returns the counts of the specified object_name. - """ - object_string = ' ' + object_name + '\n' - with open(file) as f: - lines = f.readlines() - line = [ l for l in lines if l.endswith(object_string) ][0] - result = [ int(field) for field in line.split()[:4] ] - if index is not None: - result = result[index] - return result - - - command_alias = {} - - def execute_subcommand(self, argv): - """ - Executes the do_*() function for the specified subcommand (argv[0]). - """ - if not argv: - return - cmdName = self.command_alias.get(argv[0], argv[0]) - try: - func = getattr(self, 'do_' + cmdName) - except AttributeError: - return self.default(argv) - try: - return func(argv) - except TypeError as e: - sys.stderr.write("%s %s: %s\n" % (self.name, cmdName, e)) - import traceback - traceback.print_exc(file=sys.stderr) - sys.stderr.write("Try '%s help %s'\n" % (self.name, cmdName)) - - def default(self, argv): - """ - The default behavior for an unknown subcommand. Prints an - error message and exits. - """ - sys.stderr.write('%s: Unknown subcommand "%s".\n' % (self.name, argv[0])) - sys.stderr.write('Type "%s help" for usage.\n' % self.name) - sys.exit(1) - - # - - def do_help(self, argv): - """ - """ - if argv[1:]: - for arg in argv[1:]: - try: - func = getattr(self, 'do_' + arg) - except AttributeError: - sys.stderr.write('%s: No help for "%s"\n' % (self.name, arg)) - else: - try: - help = getattr(self, 'help_' + arg) - except AttributeError: - sys.stdout.write(self.doc_to_help(func)) - sys.stdout.flush() - else: - help() - else: - doc = self.doc_to_help(self.__class__) - if doc: - sys.stdout.write(doc) - sys.stdout.flush() - return None - - # - - def help_func(self): - help = """\ - Usage: scons-time func [OPTIONS] FILE [...] - - -C DIR, --chdir=DIR Change to DIR before looking for files - -f FILE, --file=FILE Read configuration from specified FILE - --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT - --func=NAME, --function=NAME Report time for function NAME - -h, --help Print this help and exit - -p STRING, --prefix=STRING Use STRING as log file/profile prefix - -t NUMBER, --tail=NUMBER Only report the last NUMBER files - --title=TITLE Specify the output plot TITLE - """ - sys.stdout.write(self.outdent(help)) - sys.stdout.flush() - - def do_func(self, argv): - """ - """ - format = 'ascii' - function_name = '_main' - tail = None - - short_opts = '?C:f:hp:t:' - - long_opts = [ - 'chdir=', - 'file=', - 'fmt=', - 'format=', - 'func=', - 'function=', - 'help', - 'prefix=', - 'tail=', - 'title=', - ] - - opts, args = getopt.getopt(argv[1:], short_opts, long_opts) - - for o, a in opts: - if o in ('-C', '--chdir'): - self.chdir = a - elif o in ('-f', '--file'): - self.config_file = a - elif o in ('--fmt', '--format'): - format = a - elif o in ('--func', '--function'): - function_name = a - elif o in ('-?', '-h', '--help'): - self.do_help(['help', 'func']) - sys.exit(0) - elif o in ('--max',): - max_time = int(a) - elif o in ('-p', '--prefix'): - self.prefix = a - elif o in ('-t', '--tail'): - tail = int(a) - elif o in ('--title',): - self.title = a - - if self.config_file: - with open(self.config_file, 'r') as f: - config = f.read() - exec(config, self.__dict__) - - if self.chdir: - os.chdir(self.chdir) - - if not args: - - pattern = '%s*.prof' % self.prefix - args = self.args_to_files([pattern], tail) - - if not args: - if self.chdir: - directory = self.chdir - else: - directory = os.getcwd() - - sys.stderr.write('%s: func: No arguments specified.\n' % self.name) - sys.stderr.write('%s No %s*.prof files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) - sys.stderr.write('%s Type "%s help func" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - - else: - - args = self.args_to_files(args, tail) - - cwd_ = os.getcwd() + os.sep - - if format == 'ascii': - - for file in args: - try: - f, line, func, time = \ - self.get_function_profile(file, function_name) - except ValueError as e: - sys.stderr.write("%s: func: %s: %s\n" % - (self.name, file, e)) - else: - if f.startswith(cwd_): - f = f[len(cwd_):] - print("%.3f %s:%d(%s)" % (time, f, line, func)) - - elif format == 'gnuplot': - - results = self.collect_results(args, self.get_function_time, - function_name) - - self.gnuplot_results(results) - - else: - - sys.stderr.write('%s: func: Unknown format "%s".\n' % (self.name, format)) - sys.exit(1) - - # - - def help_mem(self): - help = """\ - Usage: scons-time mem [OPTIONS] FILE [...] - - -C DIR, --chdir=DIR Change to DIR before looking for files - -f FILE, --file=FILE Read configuration from specified FILE - --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT - -h, --help Print this help and exit - -p STRING, --prefix=STRING Use STRING as log file/profile prefix - --stage=STAGE Plot memory at the specified stage: - pre-read, post-read, pre-build, - post-build (default: post-build) - -t NUMBER, --tail=NUMBER Only report the last NUMBER files - --title=TITLE Specify the output plot TITLE - """ - sys.stdout.write(self.outdent(help)) - sys.stdout.flush() - - def do_mem(self, argv): - - format = 'ascii' - logfile_path = lambda x: x - stage = self.default_stage - tail = None - - short_opts = '?C:f:hp:t:' - - long_opts = [ - 'chdir=', - 'file=', - 'fmt=', - 'format=', - 'help', - 'prefix=', - 'stage=', - 'tail=', - 'title=', - ] - - opts, args = getopt.getopt(argv[1:], short_opts, long_opts) - - for o, a in opts: - if o in ('-C', '--chdir'): - self.chdir = a - elif o in ('-f', '--file'): - self.config_file = a - elif o in ('--fmt', '--format'): - format = a - elif o in ('-?', '-h', '--help'): - self.do_help(['help', 'mem']) - sys.exit(0) - elif o in ('-p', '--prefix'): - self.prefix = a - elif o in ('--stage',): - if a not in self.stages: - sys.stderr.write('%s: mem: Unrecognized stage "%s".\n' % (self.name, a)) - sys.exit(1) - stage = a - elif o in ('-t', '--tail'): - tail = int(a) - elif o in ('--title',): - self.title = a - - if self.config_file: - with open(self.config_file, 'r') as f: - config = f.read() - HACK_for_exec(config, self.__dict__) - - if self.chdir: - os.chdir(self.chdir) - logfile_path = lambda x: os.path.join(self.chdir, x) - - if not args: - - pattern = '%s*.log' % self.prefix - args = self.args_to_files([pattern], tail) - - if not args: - if self.chdir: - directory = self.chdir - else: - directory = os.getcwd() - - sys.stderr.write('%s: mem: No arguments specified.\n' % self.name) - sys.stderr.write('%s No %s*.log files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) - sys.stderr.write('%s Type "%s help mem" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - - else: - - args = self.args_to_files(args, tail) - - cwd_ = os.getcwd() + os.sep - - if format == 'ascii': - - self.ascii_table(args, tuple(self.stages), self.get_memory, logfile_path) - - elif format == 'gnuplot': - - results = self.collect_results(args, self.get_memory, - self.stage_strings[stage]) - - self.gnuplot_results(results) - - else: - - sys.stderr.write('%s: mem: Unknown format "%s".\n' % (self.name, format)) - sys.exit(1) - - return 0 - - # - - def help_obj(self): - help = """\ - Usage: scons-time obj [OPTIONS] OBJECT FILE [...] - - -C DIR, --chdir=DIR Change to DIR before looking for files - -f FILE, --file=FILE Read configuration from specified FILE - --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT - -h, --help Print this help and exit - -p STRING, --prefix=STRING Use STRING as log file/profile prefix - --stage=STAGE Plot memory at the specified stage: - pre-read, post-read, pre-build, - post-build (default: post-build) - -t NUMBER, --tail=NUMBER Only report the last NUMBER files - --title=TITLE Specify the output plot TITLE - """ - sys.stdout.write(self.outdent(help)) - sys.stdout.flush() - - def do_obj(self, argv): - - format = 'ascii' - logfile_path = lambda x: x - stage = self.default_stage - tail = None - - short_opts = '?C:f:hp:t:' - - long_opts = [ - 'chdir=', - 'file=', - 'fmt=', - 'format=', - 'help', - 'prefix=', - 'stage=', - 'tail=', - 'title=', - ] - - opts, args = getopt.getopt(argv[1:], short_opts, long_opts) - - for o, a in opts: - if o in ('-C', '--chdir'): - self.chdir = a - elif o in ('-f', '--file'): - self.config_file = a - elif o in ('--fmt', '--format'): - format = a - elif o in ('-?', '-h', '--help'): - self.do_help(['help', 'obj']) - sys.exit(0) - elif o in ('-p', '--prefix'): - self.prefix = a - elif o in ('--stage',): - if a not in self.stages: - sys.stderr.write('%s: obj: Unrecognized stage "%s".\n' % (self.name, a)) - sys.stderr.write('%s Type "%s help obj" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - stage = a - elif o in ('-t', '--tail'): - tail = int(a) - elif o in ('--title',): - self.title = a - - if not args: - sys.stderr.write('%s: obj: Must specify an object name.\n' % self.name) - sys.stderr.write('%s Type "%s help obj" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - - object_name = args.pop(0) - - if self.config_file: - with open(self.config_file, 'r') as f: - config = f.read() - HACK_for_exec(config, self.__dict__) - - if self.chdir: - os.chdir(self.chdir) - logfile_path = lambda x: os.path.join(self.chdir, x) - - if not args: - - pattern = '%s*.log' % self.prefix - args = self.args_to_files([pattern], tail) - - if not args: - if self.chdir: - directory = self.chdir - else: - directory = os.getcwd() - - sys.stderr.write('%s: obj: No arguments specified.\n' % self.name) - sys.stderr.write('%s No %s*.log files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) - sys.stderr.write('%s Type "%s help obj" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - - else: - - args = self.args_to_files(args, tail) - - cwd_ = os.getcwd() + os.sep - - if format == 'ascii': - - self.ascii_table(args, tuple(self.stages), self.get_object_counts, logfile_path, object_name) - - elif format == 'gnuplot': - - stage_index = 0 - for s in self.stages: - if stage == s: - break - stage_index = stage_index + 1 - - results = self.collect_results(args, self.get_object_counts, - object_name, stage_index) - - self.gnuplot_results(results) - - else: - - sys.stderr.write('%s: obj: Unknown format "%s".\n' % (self.name, format)) - sys.exit(1) - - return 0 - - # - - def help_run(self): - help = """\ - Usage: scons-time run [OPTIONS] [FILE ...] - - --chdir=DIR Name of unpacked directory for chdir - -f FILE, --file=FILE Read configuration from specified FILE - -h, --help Print this help and exit - -n, --no-exec No execute, just print command lines - --number=NUMBER Put output in files for run NUMBER - --outdir=OUTDIR Put output files in OUTDIR - -p STRING, --prefix=STRING Use STRING as log file/profile prefix - --python=PYTHON Time using the specified PYTHON - -q, --quiet Don't print command lines - --scons=SCONS Time using the specified SCONS - --svn=URL, --subversion=URL Use SCons from Subversion URL - -v, --verbose Display output of commands - """ - sys.stdout.write(self.outdent(help)) - sys.stdout.flush() - - def do_run(self, argv): - """ - """ - run_number_list = [None] - - short_opts = '?f:hnp:qs:v' - - long_opts = [ - 'file=', - 'help', - 'no-exec', - 'number=', - 'outdir=', - 'prefix=', - 'python=', - 'quiet', - 'scons=', - 'svn=', - 'subdir=', - 'subversion=', - 'verbose', - ] - - opts, args = getopt.getopt(argv[1:], short_opts, long_opts) - - for o, a in opts: - if o in ('-f', '--file'): - self.config_file = a - elif o in ('-?', '-h', '--help'): - self.do_help(['help', 'run']) - sys.exit(0) - elif o in ('-n', '--no-exec'): - self.execute = self._do_not_execute - elif o in ('--number',): - run_number_list = self.split_run_numbers(a) - elif o in ('--outdir',): - self.outdir = a - elif o in ('-p', '--prefix'): - self.prefix = a - elif o in ('--python',): - self.python = a - elif o in ('-q', '--quiet'): - self.display = self._do_not_display - elif o in ('-s', '--subdir'): - self.subdir = a - elif o in ('--scons',): - self.scons = a - elif o in ('--svn', '--subversion'): - self.subversion_url = a - elif o in ('-v', '--verbose'): - self.redirect = tee_to_file - self.verbose = True - self.svn_co_flag = '' - - if not args and not self.config_file: - sys.stderr.write('%s: run: No arguments or -f config file specified.\n' % self.name) - sys.stderr.write('%s Type "%s help run" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - - if self.config_file: - with open(self.config_file, 'r') as f: - config = f.read() - exec(config, self.__dict__) - - if args: - self.archive_list = args - - archive_file_name = os.path.split(self.archive_list[0])[1] - - if not self.subdir: - self.subdir = self.archive_splitext(archive_file_name)[0] - - if not self.prefix: - self.prefix = self.archive_splitext(archive_file_name)[0] - - prepare = None - if self.subversion_url: - prepare = self.prep_subversion_run - - for run_number in run_number_list: - self.individual_run(run_number, self.archive_list, prepare) - - def split_run_numbers(self, s): - result = [] - for n in s.split(','): - try: - x, y = n.split('-') - except ValueError: - result.append(int(n)) - else: - result.extend(list(range(int(x), int(y)+1))) - return result - - def scons_path(self, dir): - return os.path.join(dir, 'src', 'script', 'scons.py') - - def scons_lib_dir_path(self, dir): - return os.path.join(dir, 'src', 'engine') - - def prep_subversion_run(self, commands, removals): - self.svn_tmpdir = tempfile.mkdtemp(prefix=self.name + '-svn-') - removals.append((shutil.rmtree, 'rm -rf %%s', self.svn_tmpdir)) - - self.scons = self.scons_path(self.svn_tmpdir) - self.scons_lib_dir = self.scons_lib_dir_path(self.svn_tmpdir) - - commands.extend([ - '%(svn)s co %(svn_co_flag)s -r %(run_number)s %(subversion_url)s %(svn_tmpdir)s', - ]) - - def individual_run(self, run_number, archive_list, prepare=None): - """ - Performs an individual run of the default SCons invocations. - """ - - commands = [] - removals = [] - - if prepare: - prepare(commands, removals) - - save_scons = self.scons - save_scons_wrapper = self.scons_wrapper - save_scons_lib_dir = self.scons_lib_dir - - if self.outdir is None: - self.outdir = self.orig_cwd - elif not os.path.isabs(self.outdir): - self.outdir = os.path.join(self.orig_cwd, self.outdir) - - if self.scons is None: - self.scons = self.scons_path(self.orig_cwd) - - if self.scons_lib_dir is None: - self.scons_lib_dir = self.scons_lib_dir_path(self.orig_cwd) - - if self.scons_wrapper is None: - self.scons_wrapper = self.scons - - if not run_number: - run_number = self.find_next_run_number(self.outdir, self.prefix) - - self.run_number = str(run_number) - - self.prefix_run = self.prefix + '-%03d' % run_number - - if self.targets0 is None: - self.targets0 = self.startup_targets - if self.targets1 is None: - self.targets1 = self.targets - if self.targets2 is None: - self.targets2 = self.targets - - self.tmpdir = tempfile.mkdtemp(prefix=self.name + '-') - - commands.extend([ - (os.chdir, 'cd %%s', self.tmpdir), - ]) - - for archive in archive_list: - if not os.path.isabs(archive): - archive = os.path.join(self.orig_cwd, archive) - if os.path.isdir(archive): - dest = os.path.split(archive)[1] - commands.append((shutil.copytree, 'cp -r %%s %%s', archive, dest)) - else: - suffix = self.archive_splitext(archive)[1] - unpack_command = self.unpack_map.get(suffix) - if not unpack_command: - dest = os.path.split(archive)[1] - commands.append((shutil.copyfile, 'cp %%s %%s', archive, dest)) - else: - commands.append(unpack_command + (archive,)) - - commands.extend([ - (os.chdir, 'cd %%s', self.subdir), - ]) - - commands.extend(self.initial_commands) - - commands.extend([ - (lambda: read_tree('.'), - 'find * -type f | xargs cat > /dev/null'), - - (self.set_env, 'export %%s=%%s', - 'SCONS_LIB_DIR', self.scons_lib_dir), - - '%(python)s %(scons_wrapper)s --version', - ]) - - index = 0 - for run_command in self.run_commands: - setattr(self, 'prof%d' % index, self.profile_name(index)) - c = ( - self.log_execute, - self.log_display, - run_command, - self.logfile_name(index), - ) - commands.append(c) - index = index + 1 - - commands.extend([ - (os.chdir, 'cd %%s', self.orig_cwd), - ]) - - if not os.environ.get('PRESERVE'): - commands.extend(removals) - commands.append((shutil.rmtree, 'rm -rf %%s', self.tmpdir)) - - self.run_command_list(commands, self.__dict__) - - self.scons = save_scons - self.scons_lib_dir = save_scons_lib_dir - self.scons_wrapper = save_scons_wrapper - - # - - def help_time(self): - help = """\ - Usage: scons-time time [OPTIONS] FILE [...] - - -C DIR, --chdir=DIR Change to DIR before looking for files - -f FILE, --file=FILE Read configuration from specified FILE - --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT - -h, --help Print this help and exit - -p STRING, --prefix=STRING Use STRING as log file/profile prefix - -t NUMBER, --tail=NUMBER Only report the last NUMBER files - --which=TIMER Plot timings for TIMER: total, - SConscripts, SCons, commands. - """ - sys.stdout.write(self.outdent(help)) - sys.stdout.flush() - - def do_time(self, argv): - - format = 'ascii' - logfile_path = lambda x: x - tail = None - which = 'total' - - short_opts = '?C:f:hp:t:' - - long_opts = [ - 'chdir=', - 'file=', - 'fmt=', - 'format=', - 'help', - 'prefix=', - 'tail=', - 'title=', - 'which=', - ] - - opts, args = getopt.getopt(argv[1:], short_opts, long_opts) - - for o, a in opts: - if o in ('-C', '--chdir'): - self.chdir = a - elif o in ('-f', '--file'): - self.config_file = a - elif o in ('--fmt', '--format'): - format = a - elif o in ('-?', '-h', '--help'): - self.do_help(['help', 'time']) - sys.exit(0) - elif o in ('-p', '--prefix'): - self.prefix = a - elif o in ('-t', '--tail'): - tail = int(a) - elif o in ('--title',): - self.title = a - elif o in ('--which',): - if a not in list(self.time_strings.keys()): - sys.stderr.write('%s: time: Unrecognized timer "%s".\n' % (self.name, a)) - sys.stderr.write('%s Type "%s help time" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - which = a - - if self.config_file: - with open(self.config_file, 'r') as f: - config = f.read() - HACK_for_exec(config, self.__dict__) - - if self.chdir: - os.chdir(self.chdir) - logfile_path = lambda x: os.path.join(self.chdir, x) - - if not args: - - pattern = '%s*.log' % self.prefix - args = self.args_to_files([pattern], tail) - - if not args: - if self.chdir: - directory = self.chdir - else: - directory = os.getcwd() - - sys.stderr.write('%s: time: No arguments specified.\n' % self.name) - sys.stderr.write('%s No %s*.log files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) - sys.stderr.write('%s Type "%s help time" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - - else: - - args = self.args_to_files(args, tail) - - cwd_ = os.getcwd() + os.sep - - if format == 'ascii': - - columns = ("Total", "SConscripts", "SCons", "commands") - self.ascii_table(args, columns, self.get_debug_times, logfile_path) - - elif format == 'gnuplot': - - results = self.collect_results(args, self.get_debug_times, - self.time_strings[which]) - - self.gnuplot_results(results, fmt='%s %.6f') - - else: - - sys.stderr.write('%s: time: Unknown format "%s".\n' % (self.name, format)) - sys.exit(1) - -if __name__ == '__main__': - opts, args = getopt.getopt(sys.argv[1:], 'h?V', ['help', 'version']) - - ST = SConsTimer() - - for o, a in opts: - if o in ('-?', '-h', '--help'): - ST.do_help(['help']) - sys.exit(0) - elif o in ('-V', '--version'): - sys.stdout.write('scons-time version\n') - sys.exit(0) - - if not args: - sys.stderr.write('Type "%s help" for usage.\n' % ST.name) - sys.exit(1) - - ST.execute_subcommand(args) - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: -- cgit v0.12 From 3c542bcc3f67fe1daaa7a822f856afe7086dc974 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 21 Mar 2020 17:36:23 -0700 Subject: move scons-configure-cache logic into SCons.Utilities.ConfigureCache:main and update references and add entry_point in setup.cfg --- scripts/scons-configure-cache.py | 181 +++++++------------------- setup.cfg | 1 + src/engine/SCons/Utilities/ConfigureCache.py | 182 +++++++++++++++++++++++++++ 3 files changed, 230 insertions(+), 134 deletions(-) create mode 100644 src/engine/SCons/Utilities/ConfigureCache.py diff --git a/scripts/scons-configure-cache.py b/scripts/scons-configure-cache.py index 80783a9..62cab56 100644 --- a/scripts/scons-configure-cache.py +++ b/scripts/scons-configure-cache.py @@ -30,12 +30,6 @@ 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. """ - -import argparse -import glob -import json -import os - __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" __version__ = "__VERSION__" @@ -49,134 +43,53 @@ __date__ = "__DATE__" __developer__ = "__DEVELOPER__" -def rearrange_cache_entries(current_prefix_len, new_prefix_len): - """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() - old_dirs = set() - for file in glob.iglob(os.path.join('*', '*')): - name = os.path.basename(file) - dname = name[:current_prefix_len].upper() - if dname not in old_dirs: - print('Migrating', dname) - old_dirs.add(dname) - dname = name[:new_prefix_len].upper() - if dname not in dirs: - os.mkdir(dname) - dirs.add(dname) - os.rename(file, os.path.join(dname, name)) - - # Now delete the original directories - for dname in old_dirs: - os.rmdir(dname) - - -# The configuration dictionary should have one entry per entry in the -# cache config. The value of each entry should include the following: -# implicit - (optional) This is to allow adding a new config entry and also -# changing the behaviour of the system at the same time. This -# indicates the value the config entry would have had if it had -# been specified. -# default - The value the config entry should have if it wasn't previously -# specified -# command-line - parameters to pass to ArgumentParser.add_argument -# converter - (optional) Function to call if conversion is required -# if this configuration entry changes -config_entries = { - 'prefix_len': { - 'implicit': 1, - 'default': 2, - 'command-line': { - 'help': 'Length of cache file name used as subdirectory prefix', - 'metavar': '', - 'type': int - }, - 'converter': rearrange_cache_entries - } -} - - -def main(): - parser = argparse.ArgumentParser( - description='Modify the configuration of an scons cache directory', - epilog=''' - Unspecified options will not be changed unless they are not - set at all, in which case they are set to an appropriate default. - ''') - - parser.add_argument('cache-dir', help='Path to scons cache directory') - for param in config_entries: - parser.add_argument('--' + param.replace('_', '-'), - **config_entries[param]['command-line']) - parser.add_argument('--version', - action='version', - version='%(prog)s 1.0') - parser.add_argument('--show', - action="store_true", - help="show current configuration") - - # Get the command line as a dict without any of the unspecified entries. - args = dict([x for x in vars(parser.parse_args()).items() if x[1]]) - - # It seems somewhat strange to me, but positional arguments don't get the - - # in the name changed to _, whereas optional arguments do... - cache = args['cache-dir'] - if not os.path.isdir(cache): - raise RuntimeError("There is no cache directory named %s" % cache) - os.chdir(cache) - del args['cache-dir'] - - if not os.path.exists('config'): - # old config dirs did not have a 'config' file. Try to update. - # Validate the only files in the directory are directories 0-9, a-f - expected = ['{:X}'.format(x) for x in range(0, 16)] - if not set(os.listdir('.')).issubset(expected): - raise RuntimeError( - "%s does not look like a valid version 1 cache directory" % cache) - config = dict() - else: - with open('config') as conf: - config = json.load(conf) - - if args.get('show', None): - print("Current configuration in '%s':" % cache) - print(json.dumps(config, sort_keys=True, - indent=4, separators=(',', ': '))) - # in case of the show argument, emit some stats as well - file_count = 0 - for _, _, files in os.walk('.'): - file_count += len(files) - if file_count: # skip config file if it exists - file_count -= 1 - print("Cache contains %s files" % file_count) - del args['show'] - - # Find any keys that are not currently set but should be - for key in config_entries: - if key not in config: - if 'implicit' in config_entries[key]: - config[key] = config_entries[key]['implicit'] - else: - config[key] = config_entries[key]['default'] - if key not in args: - args[key] = config_entries[key]['default'] - - # Now go through each entry in args to see if it changes an existing config - # setting. - for key in args: - if args[key] != config[key]: - if 'converter' in config_entries[key]: - config_entries[key]['converter'](config[key], args[key]) - config[key] = args[key] - - # and write the updated config file - with open('config', 'w') as conf: - json.dump(config, conf) +import os +import sys + +# python compatibility check +if sys.version_info < (3, 5, 0): + msg = "scons: *** SCons version %s does not run under Python version %s.\n\ +Python >= 3.5 is required.\n" + sys.stderr.write(msg % (__version__, sys.version.split()[0])) + sys.exit(1) + +# Strip the script directory from sys.path so on case-insensitive +# (WIN32) systems Python doesn't think that the "scons" script is the +# "SCons" package. +script_dir = os.path.dirname(os.path.realpath(__file__)) +script_path = os.path.realpath(os.path.dirname(__file__)) +if script_path in sys.path: + sys.path.remove(script_path) + +libs = [] + +if "SCONS_LIB_DIR" in os.environ: + libs.append(os.environ["SCONS_LIB_DIR"]) + +# running from source takes 2nd priority (since 2.3.2), following SCONS_LIB_DIR +source_path = os.path.join(script_path, os.pardir, 'src', 'engine') +if os.path.isdir(source_path): + libs.append(source_path) + +# add local-install locations +local_version = 'scons-local-' + __version__ +local = 'scons-local' +if script_dir: + local_version = os.path.join(script_dir, local_version) + local = os.path.join(script_dir, local) +if os.path.isdir(local_version): + libs.append(os.path.abspath(local_version)) +if os.path.isdir(local): + libs.append(os.path.abspath(local)) + +scons_version = 'scons-%s' % __version__ + +sys.path = libs + sys.path + +############################################################################## +# END STANDARD SCons SCRIPT HEADER +############################################################################## +from SCons.Utilities.ConfigureCache import main if __name__ == "__main__": main() \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index 8e55f10..2eb7728 100644 --- a/setup.cfg +++ b/setup.cfg @@ -54,6 +54,7 @@ packages = find: console_scripts = scons = SCons.Script.Main:main sconsign = SCons.Utilities.sconsign:main + scons-configure-cache = SCons.Utilities.ConfigureCache:main [options.package_data] diff --git a/src/engine/SCons/Utilities/ConfigureCache.py b/src/engine/SCons/Utilities/ConfigureCache.py new file mode 100644 index 0000000..80783a9 --- /dev/null +++ b/src/engine/SCons/Utilities/ConfigureCache.py @@ -0,0 +1,182 @@ +#! /usr/bin/env python +# +# SCons - a Software Constructor +# +# __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. + +"""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. +""" + +import argparse +import glob +import json +import os + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +__version__ = "__VERSION__" + +__build__ = "__BUILD__" + +__buildsys__ = "__BUILDSYS__" + +__date__ = "__DATE__" + +__developer__ = "__DEVELOPER__" + + +def rearrange_cache_entries(current_prefix_len, new_prefix_len): + """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() + old_dirs = set() + for file in glob.iglob(os.path.join('*', '*')): + name = os.path.basename(file) + dname = name[:current_prefix_len].upper() + if dname not in old_dirs: + print('Migrating', dname) + old_dirs.add(dname) + dname = name[:new_prefix_len].upper() + if dname not in dirs: + os.mkdir(dname) + dirs.add(dname) + os.rename(file, os.path.join(dname, name)) + + # Now delete the original directories + for dname in old_dirs: + os.rmdir(dname) + + +# The configuration dictionary should have one entry per entry in the +# cache config. The value of each entry should include the following: +# implicit - (optional) This is to allow adding a new config entry and also +# changing the behaviour of the system at the same time. This +# indicates the value the config entry would have had if it had +# been specified. +# default - The value the config entry should have if it wasn't previously +# specified +# command-line - parameters to pass to ArgumentParser.add_argument +# converter - (optional) Function to call if conversion is required +# if this configuration entry changes +config_entries = { + 'prefix_len': { + 'implicit': 1, + 'default': 2, + 'command-line': { + 'help': 'Length of cache file name used as subdirectory prefix', + 'metavar': '', + 'type': int + }, + 'converter': rearrange_cache_entries + } +} + + +def main(): + parser = argparse.ArgumentParser( + description='Modify the configuration of an scons cache directory', + epilog=''' + Unspecified options will not be changed unless they are not + set at all, in which case they are set to an appropriate default. + ''') + + parser.add_argument('cache-dir', help='Path to scons cache directory') + for param in config_entries: + parser.add_argument('--' + param.replace('_', '-'), + **config_entries[param]['command-line']) + parser.add_argument('--version', + action='version', + version='%(prog)s 1.0') + parser.add_argument('--show', + action="store_true", + help="show current configuration") + + # Get the command line as a dict without any of the unspecified entries. + args = dict([x for x in vars(parser.parse_args()).items() if x[1]]) + + # It seems somewhat strange to me, but positional arguments don't get the - + # in the name changed to _, whereas optional arguments do... + cache = args['cache-dir'] + if not os.path.isdir(cache): + raise RuntimeError("There is no cache directory named %s" % cache) + os.chdir(cache) + del args['cache-dir'] + + if not os.path.exists('config'): + # old config dirs did not have a 'config' file. Try to update. + # Validate the only files in the directory are directories 0-9, a-f + expected = ['{:X}'.format(x) for x in range(0, 16)] + if not set(os.listdir('.')).issubset(expected): + raise RuntimeError( + "%s does not look like a valid version 1 cache directory" % cache) + config = dict() + else: + with open('config') as conf: + config = json.load(conf) + + if args.get('show', None): + print("Current configuration in '%s':" % cache) + print(json.dumps(config, sort_keys=True, + indent=4, separators=(',', ': '))) + # in case of the show argument, emit some stats as well + file_count = 0 + for _, _, files in os.walk('.'): + file_count += len(files) + if file_count: # skip config file if it exists + file_count -= 1 + print("Cache contains %s files" % file_count) + del args['show'] + + # Find any keys that are not currently set but should be + for key in config_entries: + if key not in config: + if 'implicit' in config_entries[key]: + config[key] = config_entries[key]['implicit'] + else: + config[key] = config_entries[key]['default'] + if key not in args: + args[key] = config_entries[key]['default'] + + # Now go through each entry in args to see if it changes an existing config + # setting. + for key in args: + if args[key] != config[key]: + if 'converter' in config_entries[key]: + config_entries[key]['converter'](config[key], args[key]) + config[key] = args[key] + + # and write the updated config file + with open('config', 'w') as conf: + json.dump(config, conf) + +if __name__ == "__main__": + main() \ No newline at end of file -- cgit v0.12 From a51455a5b9d359f7ea5bc578d776f1aedb952d77 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 21 Mar 2020 17:36:38 -0700 Subject: comment out packaging part of build --- SConstruct | 1260 ++++++++++++++++++++++++++++---------------------------- doc/SConscript | 2 +- 2 files changed, 631 insertions(+), 631 deletions(-) diff --git a/SConstruct b/SConstruct index 6a11bca..f696499 100644 --- a/SConstruct +++ b/SConstruct @@ -200,462 +200,462 @@ Version_values = [Value(command_line.version), Value(command_line.build_id)] # separate packages. # -from distutils.sysconfig import get_python_lib - -python_scons = { - 'pkg': 'python-' + project, - 'src_subdir': 'engine', - 'inst_subdir': get_python_lib(), - - 'files': ['LICENSE.txt', - 'README.txt', - 'setup.cfg', - 'setup.py', - ], - - 'filemap': { - 'LICENSE.txt': '../LICENSE.txt' - }, - - 'buildermap': {}, - - 'explicit_deps': { - 'SCons/__init__.py': Version_values, - }, -} - -scons_script = { - 'pkg': project + '-script', - 'src_subdir': 'script', - 'inst_subdir': 'bin', - - 'files': [ - 'LICENSE.txt', - 'README.txt', - 'setup.cfg', - 'setup.py', - ], - - 'filemap': { - 'LICENSE.txt': '../LICENSE.txt', - 'scons': 'scons.py', - 'sconsign': 'sconsign.py', - 'scons-time': 'scons-time.py', - 'scons-configure-cache': 'scons-configure-cache.py', - }, - - 'buildermap': {}, - - 'explicit_deps': { - 'scons': Version_values, - 'sconsign': Version_values, - }, -} - -scons = { - 'pkg': project, - - 'files': [ - 'CHANGES.txt', - 'LICENSE.txt', - 'README.txt', - 'RELEASE.txt', - 'scons.1', - 'sconsign.1', - 'scons-time.1', - 'script/scons.bat', - 'setup.cfg', - 'setup.py', - ], - - 'filemap': { - 'scons.1': '$BUILDDIR/doc/man/scons.1', - 'sconsign.1': '$BUILDDIR/doc/man/sconsign.1', - 'scons-time.1': '$BUILDDIR/doc/man/scons-time.1', - }, - - 'buildermap': { - 'scons.1': env.SOElim, - 'sconsign.1': env.SOElim, - 'scons-time.1': env.SOElim, - }, - - 'subpkgs': [python_scons, scons_script], - - 'subinst_dirs': { - 'python-' + project: python_project_subinst_dir, - project + '-script': project_script_subinst_dir, - }, -} - -scripts = ['scons', 'sconsign', 'scons-time', 'scons-configure-cache'] - -src_deps = [] -src_files = [] - -for p in [scons]: - # - # Initialize variables with the right directories for this package. - # - pkg = p['pkg'] - pkg_version = "%s-%s" % (pkg, command_line.version) - - src = 'src' - if 'src_subdir' in p: - src = os.path.join(src, p['src_subdir']) - - build = os.path.join(command_line.build_dir, pkg) - - tar_gz = os.path.join(build, 'dist', "%s.tar.gz" % pkg_version) - platform_tar_gz = os.path.join(build, - 'dist', - "%s.%s.tar.gz" % (pkg_version, platform)) - zip = os.path.join(build, 'dist', "%s.zip" % pkg_version) - platform_zip = os.path.join(build, - 'dist', - "%s.%s.zip" % (pkg_version, platform)) - - # - # Update the environment with the relevant information - # for this package. - # - # We can get away with calling setup.py using a directory path - # like this because we put a preamble in it that will chdir() - # to the directory in which setup.py exists. - # - setup_py = os.path.join(build, 'setup.py') - env.Replace(PKG=pkg, - PKG_VERSION=pkg_version, - SETUP_PY='"%s"' % setup_py) - Local(setup_py) - - # - # Read up the list of source files from our MANIFEST.in. - # This list should *not* include LICENSE.txt, MANIFEST, - # README.txt, or setup.py. Make a copy of the list for the - # destination files. - # - manifest_in = File(os.path.join(src, 'MANIFEST.in')).rstr() - src_files = bootstrap.parseManifestLines(src, manifest_in) - raw_files = src_files[:] - dst_files = src_files[:] - - MANIFEST_in_list = [] - - if 'subpkgs' in p: - # - # This package includes some sub-packages. Read up their - # MANIFEST.in files, and add them to our source and destination - # file lists, modifying them as appropriate to add the - # specified subdirs. - # - for sp in p['subpkgs']: - ssubdir = sp['src_subdir'] - isubdir = p['subinst_dirs'][sp['pkg']] - - MANIFEST_in = File(os.path.join(src, ssubdir, 'MANIFEST.in')).rstr() - MANIFEST_in_list.append(MANIFEST_in) - files = bootstrap.parseManifestLines(os.path.join(src, ssubdir), MANIFEST_in) - - raw_files.extend(files) - src_files.extend([os.path.join(ssubdir, x) for x in files]) - - files = [os.path.join(isubdir, x) for x in files] - dst_files.extend(files) - for k, f in sp['filemap'].items(): - if f: - k = os.path.join(ssubdir, k) - p['filemap'][k] = os.path.join(ssubdir, f) - for f, deps in sp['explicit_deps'].items(): - f = os.path.join(build, ssubdir, f) - env.Depends(f, deps) - - # - # Now that we have the "normal" source files, add those files - # that are standard for each distribution. Note that we don't - # add these to dst_files, because they don't get installed. - # And we still have the MANIFEST to add. - # - src_files.extend(p['files']) - - # - # Now run everything in src_file through the sed command we - # concocted to expand __FILE__, __VERSION__, etc. - # - for b in src_files: - s = p['filemap'].get(b, b) - if not s[0] == '$' and not os.path.isabs(s): - s = os.path.join(src, s) - - builder = p['buildermap'].get(b, env.SCons_revision) - x = builder(os.path.join(build, b), s) - - Local(x) - - # - # NOW, finally, we can create the MANIFEST, which we do - # by having Python spit out the contents of the src_files - # array we've carefully created. After we've added - # MANIFEST itself to the array, of course. - # - src_files.append("MANIFEST") - MANIFEST_in_list.append(os.path.join(src, 'MANIFEST.in')) - - - def write_src_files(target, source, **kw): - global src_files - src_files.sort() - with open(str(target[0]), 'w') as f: - for file in src_files: - f.write(file + "\n") - return 0 - - - env.Command(os.path.join(build, 'MANIFEST'), - MANIFEST_in_list, - write_src_files) - - # - # Now go through and arrange to create whatever packages we can. - # - build_src_files = [os.path.join(build, x) for x in src_files] - Local(*build_src_files) - - distutils_formats = [] - distutils_targets = [] - dist_distutils_targets = [] - - for target in distutils_targets: - dist_target = env.Install('$DISTDIR', target) - AddPostAction(dist_target, Chmod(dist_target, 0o644)) - dist_distutils_targets += dist_target - - if not gzip: - print("gzip not found in %s; skipping .tar.gz package for %s." % (os.environ['PATH'], pkg)) - else: - - distutils_formats.append('gztar') - - src_deps.append(tar_gz) - - distutils_targets.extend([tar_gz, platform_tar_gz]) - - dist_tar_gz = env.Install('$DISTDIR', tar_gz) - dist_platform_tar_gz = env.Install('$DISTDIR', platform_tar_gz) - Local(dist_tar_gz, dist_platform_tar_gz) - AddPostAction(dist_tar_gz, Chmod(dist_tar_gz, 0o644)) - AddPostAction(dist_platform_tar_gz, Chmod(dist_platform_tar_gz, 0o644)) - - # - # Unpack the tar.gz archive created by the distutils into - # build/unpack-tar-gz/scons-{version}. - # - # We'd like to replace the last three lines with the following: - # - # tar zxf $SOURCES -C $UNPACK_TAR_GZ_DIR - # - # but that gives heartburn to Cygwin's tar, so work around it - # with separate zcat-tar-rm commands. - # - unpack_tar_gz_files = [os.path.join(unpack_tar_gz_dir, pkg_version, x) - for x in src_files] - env.Command(unpack_tar_gz_files, dist_tar_gz, [ - Delete(os.path.join(unpack_tar_gz_dir, pkg_version)), - "$ZCAT $SOURCES > .temp", - "tar xf .temp -C $UNPACK_TAR_GZ_DIR", - Delete(".temp"), - ]) - - # - # Run setup.py in the unpacked subdirectory to "install" everything - # into our build/test subdirectory. The runtest.py script will set - # PYTHONPATH so that the tests only look under build/test-{package}, - # and under testing/framework (for the testing modules TestCmd.py, TestSCons.py, - # etc.). This makes sure that our tests pass with what - # we really packaged, not because of something hanging around in - # the development directory. - # - # We can get away with calling setup.py using a directory path - # like this because we put a preamble in it that will chdir() - # to the directory in which setup.py exists. - # - dfiles = [os.path.join(test_tar_gz_dir, x) for x in dst_files] - env.Command(dfiles, unpack_tar_gz_files, [ - Delete(os.path.join(unpack_tar_gz_dir, pkg_version, 'build')), - Delete("$TEST_TAR_GZ_DIR"), - '$PYTHON $PYTHONFLAGS "%s" install "--prefix=$TEST_TAR_GZ_DIR" --standalone-lib' % \ - os.path.join(unpack_tar_gz_dir, pkg_version, 'setup.py'), - ]) - - # - # Generate portage files for submission to Gentoo Linux. - # - gentoo = os.path.join(build, 'gentoo') - ebuild = os.path.join(gentoo, 'scons-%s.ebuild' % command_line.version) - digest = os.path.join(gentoo, 'files', 'digest-scons-%s' % command_line.version) - env.Command(ebuild, os.path.join('gentoo', 'scons.ebuild.in'), SCons_revision) - - - def Digestify(target, source, env): - import hashlib - src = source[0].rfile() - with open(str(src), 'rb') as f: - contents = f.read() - m = hashlib.md5() - m.update(contents) - sig = m.hexdigest() - bytes = os.stat(str(src))[6] - with open(str(target[0]), 'w') as f: - f.write("MD5 %s %s %d\n" % (sig, src.name, bytes)) - - - env.Command(digest, tar_gz, Digestify) - - if not zipit: - print("zip not found; skipping .zip package for %s." % pkg) - else: - - distutils_formats.append('zip') - - src_deps.append(zip) - - distutils_targets.extend([zip, platform_zip]) - - dist_zip = env.Install('$DISTDIR', zip) - dist_platform_zip = env.Install('$DISTDIR', platform_zip) - Local(dist_zip, dist_platform_zip) - AddPostAction(dist_zip, Chmod(dist_zip, 0o644)) - AddPostAction(dist_platform_zip, Chmod(dist_platform_zip, 0o644)) - - # - # Unpack the zip archive created by the distutils into - # build/unpack-zip/scons-{version}. - # - unpack_zip_files = [os.path.join(unpack_zip_dir, pkg_version, x) - for x in src_files] - - env.Command(unpack_zip_files, dist_zip, [ - Delete(os.path.join(unpack_zip_dir, pkg_version)), - unzipit, - ]) - - # - # Run setup.py in the unpacked subdirectory to "install" everything - # into our build/test subdirectory. The runtest.py script will set - # PYTHONPATH so that the tests only look under build/test-{package}, - # and under testing/framework (for the testing modules TestCmd.py, TestSCons.py, - # etc.). This makes sure that our tests pass with what - # we really packaged, not because of something hanging around in - # the development directory. - # - # We can get away with calling setup.py using a directory path - # like this because we put a preamble in it that will chdir() - # to the directory in which setup.py exists. - # - dfiles = [os.path.join(test_zip_dir, x) for x in dst_files] - env.Command(dfiles, unpack_zip_files, [ - Delete(os.path.join(unpack_zip_dir, pkg_version, 'build')), - Delete("$TEST_ZIP_DIR"), - '$PYTHON $PYTHONFLAGS "%s" install "--prefix=$TEST_ZIP_DIR" --standalone-lib' % \ - os.path.join(unpack_zip_dir, pkg_version, 'setup.py'), - ]) - - # - # Use the Python distutils to generate the appropriate packages. - # - commands = [ - Delete(os.path.join(build, 'build', 'lib')), - Delete(os.path.join(build, 'build', 'scripts')), - ] - - if distutils_formats: - commands.append(Delete(os.path.join(build, - 'build', - 'bdist.' + platform, - 'dumb'))) - for format in distutils_formats: - commands.append("$PYTHON $PYTHONFLAGS $SETUP_PY bdist_dumb -f %s" % format) - - commands.append("$PYTHON $PYTHONFLAGS $SETUP_PY sdist --formats=%s" % \ - ','.join(distutils_formats)) - - env.Command(distutils_targets, build_src_files, commands) - - # - # Now create local packages for people who want to let people - # build their SCons-buildable packages without having to - # install SCons. - # - s_l_v = '%s-local-%s' % (pkg, command_line.version) - - local = pkg + '-local' - build_dir_local = os.path.join(command_line.build_dir, local) - build_dir_local_slv = os.path.join(command_line.build_dir, local, s_l_v) - - dist_local_tar_gz = os.path.join("$DISTDIR/%s.tar.gz" % s_l_v) - dist_local_zip = os.path.join("$DISTDIR/%s.zip" % s_l_v) - AddPostAction(dist_local_tar_gz, Chmod(dist_local_tar_gz, 0o644)) - AddPostAction(dist_local_zip, Chmod(dist_local_zip, 0o644)) - - commands = [ - Delete(build_dir_local), - '$PYTHON $PYTHONFLAGS $SETUP_PY install "--install-script=%s" "--install-lib=%s" --no-install-man --no-compile --standalone-lib --no-version-script' % \ - (build_dir_local, build_dir_local_slv), - ] - - for script in scripts: - # add .py extension for scons-local scripts on non-windows platforms - if is_windows(): - break - local_script = os.path.join(build_dir_local, script) - commands.append(Move(local_script + '.py', local_script)) - - rf = [x for x in raw_files if not x in scripts] - rf = [os.path.join(s_l_v, x) for x in rf] - for script in scripts: - rf.append("%s.py" % script) - local_targets = [os.path.join(build_dir_local, x) for x in rf] - - env.Command(local_targets, build_src_files, commands) - - scons_LICENSE = os.path.join(build_dir_local, 'scons-LICENSE') - l = env.SCons_revision(scons_LICENSE, 'LICENSE-local') - local_targets.append(l) - Local(l) - - scons_README = os.path.join(build_dir_local, 'scons-README') - l = env.SCons_revision(scons_README, 'README-local') - local_targets.append(l) - Local(l) - - if gzip: - if is_windows(): - # avoid problem with tar interpreting c:/ as a remote machine - tar_cargs = '-cz --force-local -f' - else: - tar_cargs = '-czf' - env.Command(dist_local_tar_gz, - local_targets, - "cd %s && tar %s $( ${TARGET.abspath} $) *" % (build_dir_local, tar_cargs)) - - unpack_targets = [os.path.join(test_local_tar_gz_dir, x) for x in rf] - commands = [Delete(test_local_tar_gz_dir), - Mkdir(test_local_tar_gz_dir), - "cd %s && tar xzf $( ${SOURCE.abspath} $)" % test_local_tar_gz_dir] - - env.Command(unpack_targets, dist_local_tar_gz, commands) - - if zipit: - env.Command(dist_local_zip, local_targets, zipit, - CD=build_dir_local, PSV='.') - - unpack_targets = [os.path.join(test_local_zip_dir, x) for x in rf] - commands = [Delete(test_local_zip_dir), - Mkdir(test_local_zip_dir), - unzipit] - - env.Command(unpack_targets, dist_local_zip, unzipit, - UNPACK_ZIP_DIR=test_local_zip_dir) +# from distutils.sysconfig import get_python_lib +# +# python_scons = { +# 'pkg': 'python-' + project, +# 'src_subdir': 'engine', +# 'inst_subdir': get_python_lib(), +# +# 'files': ['LICENSE.txt', +# 'README.txt', +# 'setup.cfg', +# 'setup.py', +# ], +# +# 'filemap': { +# 'LICENSE.txt': '../LICENSE.txt' +# }, +# +# 'buildermap': {}, +# +# 'explicit_deps': { +# 'SCons/__init__.py': Version_values, +# }, +# } + +# scons_script = { +# 'pkg': project + '-script', +# 'src_subdir': 'script', +# 'inst_subdir': 'bin', +# +# 'files': [ +# 'LICENSE.txt', +# 'README.txt', +# 'setup.cfg', +# 'setup.py', +# ], +# +# 'filemap': { +# 'LICENSE.txt': '../LICENSE.txt', +# 'scons': 'scons.py', +# 'sconsign': 'sconsign.py', +# 'scons-time': 'scons-time.py', +# 'scons-configure-cache': 'scons-configure-cache.py', +# }, +# +# 'buildermap': {}, +# +# 'explicit_deps': { +# 'scons': Version_values, +# 'sconsign': Version_values, +# }, +# } + +# scons = { +# 'pkg': project, +# +# 'files': [ +# 'CHANGES.txt', +# 'LICENSE.txt', +# 'README.txt', +# 'RELEASE.txt', +# 'scons.1', +# 'sconsign.1', +# 'scons-time.1', +# # 'script/scons.bat', +# 'setup.cfg', +# 'setup.py', +# ], +# +# 'filemap': { +# 'scons.1': '$BUILDDIR/doc/man/scons.1', +# 'sconsign.1': '$BUILDDIR/doc/man/sconsign.1', +# 'scons-time.1': '$BUILDDIR/doc/man/scons-time.1', +# }, +# +# 'buildermap': { +# 'scons.1': env.SOElim, +# 'sconsign.1': env.SOElim, +# 'scons-time.1': env.SOElim, +# }, +# +# 'subpkgs': [python_scons], +# +# 'subinst_dirs': { +# 'python-' + project: python_project_subinst_dir, +# project + '-script': project_script_subinst_dir, +# }, +# } +# +# scripts = ['scons', 'sconsign', 'scons-time', 'scons-configure-cache'] +# +# src_deps = [] +# src_files = [] +# +# for p in [scons]: +# # +# # Initialize variables with the right directories for this package. +# # +# pkg = p['pkg'] +# pkg_version = "%s-%s" % (pkg, command_line.version) +# +# src = 'src' +# if 'src_subdir' in p: +# src = os.path.join(src, p['src_subdir']) +# +# build = os.path.join(command_line.build_dir, pkg) +# +# tar_gz = os.path.join(build, 'dist', "%s.tar.gz" % pkg_version) +# platform_tar_gz = os.path.join(build, +# 'dist', +# "%s.%s.tar.gz" % (pkg_version, platform)) +# zip = os.path.join(build, 'dist', "%s.zip" % pkg_version) +# platform_zip = os.path.join(build, +# 'dist', +# "%s.%s.zip" % (pkg_version, platform)) +# +# # +# # Update the environment with the relevant information +# # for this package. +# # +# # We can get away with calling setup.py using a directory path +# # like this because we put a preamble in it that will chdir() +# # to the directory in which setup.py exists. +# # +# setup_py = os.path.join(build, 'setup.py') +# env.Replace(PKG=pkg, +# PKG_VERSION=pkg_version, +# SETUP_PY='"%s"' % setup_py) +# Local(setup_py) +# +# # +# # Read up the list of source files from our MANIFEST.in. +# # This list should *not* include LICENSE.txt, MANIFEST, +# # README.txt, or setup.py. Make a copy of the list for the +# # destination files. +# # +# manifest_in = File(os.path.join(src, 'MANIFEST.in')).rstr() +# src_files = bootstrap.parseManifestLines(src, manifest_in) +# raw_files = src_files[:] +# dst_files = src_files[:] +# +# MANIFEST_in_list = [] +# +# if 'subpkgs' in p: +# # +# # This package includes some sub-packages. Read up their +# # MANIFEST.in files, and add them to our source and destination +# # file lists, modifying them as appropriate to add the +# # specified subdirs. +# # +# for sp in p['subpkgs']: +# ssubdir = sp['src_subdir'] +# isubdir = p['subinst_dirs'][sp['pkg']] +# +# MANIFEST_in = File(os.path.join(src, ssubdir, 'MANIFEST.in')).rstr() +# MANIFEST_in_list.append(MANIFEST_in) +# files = bootstrap.parseManifestLines(os.path.join(src, ssubdir), MANIFEST_in) +# +# raw_files.extend(files) +# src_files.extend([os.path.join(ssubdir, x) for x in files]) +# +# files = [os.path.join(isubdir, x) for x in files] +# dst_files.extend(files) +# for k, f in sp['filemap'].items(): +# if f: +# k = os.path.join(ssubdir, k) +# p['filemap'][k] = os.path.join(ssubdir, f) +# for f, deps in sp['explicit_deps'].items(): +# f = os.path.join(build, ssubdir, f) +# env.Depends(f, deps) +# +# # +# # Now that we have the "normal" source files, add those files +# # that are standard for each distribution. Note that we don't +# # add these to dst_files, because they don't get installed. +# # And we still have the MANIFEST to add. +# # +# src_files.extend(p['files']) +# +# # +# # Now run everything in src_file through the sed command we +# # concocted to expand __FILE__, __VERSION__, etc. +# # +# for b in src_files: +# s = p['filemap'].get(b, b) +# if not s[0] == '$' and not os.path.isabs(s): +# s = os.path.join(src, s) +# +# builder = p['buildermap'].get(b, env.SCons_revision) +# x = builder(os.path.join(build, b), s) +# +# Local(x) +# +# # +# # NOW, finally, we can create the MANIFEST, which we do +# # by having Python spit out the contents of the src_files +# # array we've carefully created. After we've added +# # MANIFEST itself to the array, of course. +# # +# src_files.append("MANIFEST") +# MANIFEST_in_list.append(os.path.join(src, 'MANIFEST.in')) +# +# +# def write_src_files(target, source, **kw): +# global src_files +# src_files.sort() +# with open(str(target[0]), 'w') as f: +# for file in src_files: +# f.write(file + "\n") +# return 0 +# +# +# env.Command(os.path.join(build, 'MANIFEST'), +# MANIFEST_in_list, +# write_src_files) +# +# # +# # Now go through and arrange to create whatever packages we can. +# # +# build_src_files = [os.path.join(build, x) for x in src_files] +# Local(*build_src_files) +# +# distutils_formats = [] +# distutils_targets = [] +# dist_distutils_targets = [] +# +# for target in distutils_targets: +# dist_target = env.Install('$DISTDIR', target) +# AddPostAction(dist_target, Chmod(dist_target, 0o644)) +# dist_distutils_targets += dist_target +# +# if not gzip: +# print("gzip not found in %s; skipping .tar.gz package for %s." % (os.environ['PATH'], pkg)) +# else: +# +# distutils_formats.append('gztar') +# +# src_deps.append(tar_gz) +# +# distutils_targets.extend([tar_gz, platform_tar_gz]) +# +# dist_tar_gz = env.Install('$DISTDIR', tar_gz) +# dist_platform_tar_gz = env.Install('$DISTDIR', platform_tar_gz) +# Local(dist_tar_gz, dist_platform_tar_gz) +# AddPostAction(dist_tar_gz, Chmod(dist_tar_gz, 0o644)) +# AddPostAction(dist_platform_tar_gz, Chmod(dist_platform_tar_gz, 0o644)) +# +# # +# # Unpack the tar.gz archive created by the distutils into +# # build/unpack-tar-gz/scons-{version}. +# # +# # We'd like to replace the last three lines with the following: +# # +# # tar zxf $SOURCES -C $UNPACK_TAR_GZ_DIR +# # +# # but that gives heartburn to Cygwin's tar, so work around it +# # with separate zcat-tar-rm commands. +# # +# unpack_tar_gz_files = [os.path.join(unpack_tar_gz_dir, pkg_version, x) +# for x in src_files] +# env.Command(unpack_tar_gz_files, dist_tar_gz, [ +# Delete(os.path.join(unpack_tar_gz_dir, pkg_version)), +# "$ZCAT $SOURCES > .temp", +# "tar xf .temp -C $UNPACK_TAR_GZ_DIR", +# Delete(".temp"), +# ]) +# +# # +# # Run setup.py in the unpacked subdirectory to "install" everything +# # into our build/test subdirectory. The runtest.py script will set +# # PYTHONPATH so that the tests only look under build/test-{package}, +# # and under testing/framework (for the testing modules TestCmd.py, TestSCons.py, +# # etc.). This makes sure that our tests pass with what +# # we really packaged, not because of something hanging around in +# # the development directory. +# # +# # We can get away with calling setup.py using a directory path +# # like this because we put a preamble in it that will chdir() +# # to the directory in which setup.py exists. +# # +# dfiles = [os.path.join(test_tar_gz_dir, x) for x in dst_files] +# env.Command(dfiles, unpack_tar_gz_files, [ +# Delete(os.path.join(unpack_tar_gz_dir, pkg_version, 'build')), +# Delete("$TEST_TAR_GZ_DIR"), +# '$PYTHON $PYTHONFLAGS "%s" install "--prefix=$TEST_TAR_GZ_DIR" --standalone-lib' % \ +# os.path.join(unpack_tar_gz_dir, pkg_version, 'setup.py'), +# ]) +# +# # +# # Generate portage files for submission to Gentoo Linux. +# # +# gentoo = os.path.join(build, 'gentoo') +# ebuild = os.path.join(gentoo, 'scons-%s.ebuild' % command_line.version) +# digest = os.path.join(gentoo, 'files', 'digest-scons-%s' % command_line.version) +# env.Command(ebuild, os.path.join('gentoo', 'scons.ebuild.in'), SCons_revision) +# +# +# def Digestify(target, source, env): +# import hashlib +# src = source[0].rfile() +# with open(str(src), 'rb') as f: +# contents = f.read() +# m = hashlib.md5() +# m.update(contents) +# sig = m.hexdigest() +# bytes = os.stat(str(src))[6] +# with open(str(target[0]), 'w') as f: +# f.write("MD5 %s %s %d\n" % (sig, src.name, bytes)) +# +# +# env.Command(digest, tar_gz, Digestify) +# +# if not zipit: +# print("zip not found; skipping .zip package for %s." % pkg) +# else: +# +# distutils_formats.append('zip') +# +# src_deps.append(zip) +# +# distutils_targets.extend([zip, platform_zip]) +# +# dist_zip = env.Install('$DISTDIR', zip) +# dist_platform_zip = env.Install('$DISTDIR', platform_zip) +# Local(dist_zip, dist_platform_zip) +# AddPostAction(dist_zip, Chmod(dist_zip, 0o644)) +# AddPostAction(dist_platform_zip, Chmod(dist_platform_zip, 0o644)) +# +# # +# # Unpack the zip archive created by the distutils into +# # build/unpack-zip/scons-{version}. +# # +# unpack_zip_files = [os.path.join(unpack_zip_dir, pkg_version, x) +# for x in src_files] +# +# env.Command(unpack_zip_files, dist_zip, [ +# Delete(os.path.join(unpack_zip_dir, pkg_version)), +# unzipit, +# ]) +# +# # +# # Run setup.py in the unpacked subdirectory to "install" everything +# # into our build/test subdirectory. The runtest.py script will set +# # PYTHONPATH so that the tests only look under build/test-{package}, +# # and under testing/framework (for the testing modules TestCmd.py, TestSCons.py, +# # etc.). This makes sure that our tests pass with what +# # we really packaged, not because of something hanging around in +# # the development directory. +# # +# # We can get away with calling setup.py using a directory path +# # like this because we put a preamble in it that will chdir() +# # to the directory in which setup.py exists. +# # +# dfiles = [os.path.join(test_zip_dir, x) for x in dst_files] +# env.Command(dfiles, unpack_zip_files, [ +# Delete(os.path.join(unpack_zip_dir, pkg_version, 'build')), +# Delete("$TEST_ZIP_DIR"), +# '$PYTHON $PYTHONFLAGS "%s" install "--prefix=$TEST_ZIP_DIR" --standalone-lib' % \ +# os.path.join(unpack_zip_dir, pkg_version, 'setup.py'), +# ]) +# +# # +# # Use the Python distutils to generate the appropriate packages. +# # +# commands = [ +# Delete(os.path.join(build, 'build', 'lib')), +# Delete(os.path.join(build, 'build', 'scripts')), +# ] +# +# if distutils_formats: +# commands.append(Delete(os.path.join(build, +# 'build', +# 'bdist.' + platform, +# 'dumb'))) +# for format in distutils_formats: +# commands.append("$PYTHON $PYTHONFLAGS $SETUP_PY bdist_dumb -f %s" % format) +# +# commands.append("$PYTHON $PYTHONFLAGS $SETUP_PY sdist --formats=%s" % \ +# ','.join(distutils_formats)) +# +# env.Command(distutils_targets, build_src_files, commands) +# +# # +# # Now create local packages for people who want to let people +# # build their SCons-buildable packages without having to +# # install SCons. +# # +# s_l_v = '%s-local-%s' % (pkg, command_line.version) +# +# local = pkg + '-local' +# build_dir_local = os.path.join(command_line.build_dir, local) +# build_dir_local_slv = os.path.join(command_line.build_dir, local, s_l_v) +# +# dist_local_tar_gz = os.path.join("$DISTDIR/%s.tar.gz" % s_l_v) +# dist_local_zip = os.path.join("$DISTDIR/%s.zip" % s_l_v) +# AddPostAction(dist_local_tar_gz, Chmod(dist_local_tar_gz, 0o644)) +# AddPostAction(dist_local_zip, Chmod(dist_local_zip, 0o644)) +# +# commands = [ +# Delete(build_dir_local), +# '$PYTHON $PYTHONFLAGS $SETUP_PY install "--install-script=%s" "--install-lib=%s" --no-install-man --no-compile --standalone-lib --no-version-script' % \ +# (build_dir_local, build_dir_local_slv), +# ] +# +# for script in scripts: +# # add .py extension for scons-local scripts on non-windows platforms +# if is_windows(): +# break +# local_script = os.path.join(build_dir_local, script) +# commands.append(Move(local_script + '.py', local_script)) +# +# rf = [x for x in raw_files if not x in scripts] +# rf = [os.path.join(s_l_v, x) for x in rf] +# for script in scripts: +# rf.append("%s.py" % script) +# local_targets = [os.path.join(build_dir_local, x) for x in rf] +# +# env.Command(local_targets, build_src_files, commands) +# +# scons_LICENSE = os.path.join(build_dir_local, 'scons-LICENSE') +# l = env.SCons_revision(scons_LICENSE, 'LICENSE-local') +# local_targets.append(l) +# Local(l) +# +# scons_README = os.path.join(build_dir_local, 'scons-README') +# l = env.SCons_revision(scons_README, 'README-local') +# local_targets.append(l) +# Local(l) +# +# if gzip: +# if is_windows(): +# # avoid problem with tar interpreting c:/ as a remote machine +# tar_cargs = '-cz --force-local -f' +# else: +# tar_cargs = '-czf' +# env.Command(dist_local_tar_gz, +# local_targets, +# "cd %s && tar %s $( ${TARGET.abspath} $) *" % (build_dir_local, tar_cargs)) +# +# unpack_targets = [os.path.join(test_local_tar_gz_dir, x) for x in rf] +# commands = [Delete(test_local_tar_gz_dir), +# Mkdir(test_local_tar_gz_dir), +# "cd %s && tar xzf $( ${SOURCE.abspath} $)" % test_local_tar_gz_dir] +# +# env.Command(unpack_targets, dist_local_tar_gz, commands) +# +# if zipit: +# env.Command(dist_local_zip, local_targets, zipit, +# CD=build_dir_local, PSV='.') +# +# unpack_targets = [os.path.join(test_local_zip_dir, x) for x in rf] +# commands = [Delete(test_local_zip_dir), +# Mkdir(test_local_zip_dir), +# unzipit] +# +# env.Command(unpack_targets, dist_local_zip, unzipit, +# UNPACK_ZIP_DIR=test_local_zip_dir) # # @@ -667,179 +667,179 @@ Export('command_line', 'env', 'whereis', 'revaction') SConscript('doc/SConscript') +# # +# # If we're running in a Git working directory, pack up a complete +# # source archive from the project files and files in the change. +# # # -# If we're running in a Git working directory, pack up a complete -# source archive from the project files and files in the change. # - - -sfiles = [l.split()[-1] for l in command_line.git_status_lines] -if command_line.git_status_lines: - # slines = [l for l in git_status_lines if 'modified:' in l] - # sfiles = [l.split()[-1] for l in slines] - pass -else: - print("Not building in a Git tree; skipping building src package.") - -if sfiles: - remove_patterns = [ - '*.gitignore', - '*.hgignore', - 'www/*', - ] - - for p in remove_patterns: - sfiles = [s for s in sfiles if not fnmatch.fnmatch(s, p)] - - if sfiles: - ps = "%s-src" % project - psv = "%s-%s" % (ps, command_line.version) - b_ps = os.path.join(command_line.build_dir, ps) - b_psv = os.path.join(command_line.build_dir, psv) - b_psv_stamp = b_psv + '-stamp' - - src_tar_gz = os.path.join(command_line.build_dir, 'dist', '%s.tar.gz' % psv) - src_zip = os.path.join(command_line.build_dir, 'dist', '%s.zip' % psv) - - Local(src_tar_gz, src_zip) - - for file in sfiles: - if file.endswith('jpg') or file.endswith('png'): - # don't revision binary files. - env.Install(os.path.dirname(os.path.join(b_ps, file)), file) - else: - env.SCons_revision(os.path.join(b_ps, file), file) - - b_ps_files = [os.path.join(b_ps, x) for x in sfiles] - cmds = [ - Delete(b_psv), - Copy(b_psv, b_ps), - Touch("$TARGET"), - ] - - env.Command(b_psv_stamp, src_deps + b_ps_files, cmds) - - Local(*b_ps_files) - - if gzip: - env.Command(src_tar_gz, b_psv_stamp, - "tar cz${TAR_HFLAG} -f $TARGET -C build %s" % psv) - - # - # Unpack the archive into build/unpack/scons-{version}. - # - unpack_tar_gz_files = [os.path.join(unpack_tar_gz_dir, psv, x) - for x in sfiles] - - # - # We'd like to replace the last three lines with the following: - # - # tar zxf $SOURCES -C $UNPACK_TAR_GZ_DIR - # - # but that gives heartburn to Cygwin's tar, so work around it - # with separate zcat-tar-rm commands. - env.Command(unpack_tar_gz_files, src_tar_gz, [ - Delete(os.path.join(unpack_tar_gz_dir, psv)), - "$ZCAT $SOURCES > .temp", - "tar xf .temp -C $UNPACK_TAR_GZ_DIR", - Delete(".temp"), - ]) - - # - # Run setup.py in the unpacked subdirectory to "install" everything - # into our build/test subdirectory. The runtest.py script will set - # PYTHONPATH so that the tests only look under build/test-{package}, - # and under testing/framework (for the testing modules TestCmd.py, - # TestSCons.py, etc.). This makes sure that our tests pass with - # what we really packaged, not because of something hanging around - # in the development directory. - # - # We can get away with calling setup.py using a directory path - # like this because we put a preamble in it that will chdir() - # to the directory in which setup.py exists. - # - dfiles = [os.path.join(test_src_tar_gz_dir, x) for x in dst_files] - scons_lib_dir = os.path.join(unpack_tar_gz_dir, psv, 'src', 'engine') - ENV = env.Dictionary('ENV').copy() - ENV['SCONS_LIB_DIR'] = scons_lib_dir - ENV['USERNAME'] = command_line.developer - env.Command(dfiles, unpack_tar_gz_files, - [ - Delete(os.path.join(unpack_tar_gz_dir, - psv, - 'build', - 'scons', - 'build')), - Delete("$TEST_SRC_TAR_GZ_DIR"), - 'cd "%s" && $PYTHON $PYTHONFLAGS "%s" "%s" VERSION="$VERSION"' % \ - (os.path.join(unpack_tar_gz_dir, psv), - os.path.join('src', 'script', 'scons.py'), - os.path.join('build', 'scons')), - '$PYTHON $PYTHONFLAGS "%s" install "--prefix=$TEST_SRC_TAR_GZ_DIR" --standalone-lib' % \ - os.path.join(unpack_tar_gz_dir, - psv, - 'build', - 'scons', - 'setup.py'), - ], - ENV=ENV) - - if zipit: - env.Command(src_zip, b_psv_stamp, zipit, CD='build', PSV=psv) - - # - # Unpack the archive into build/unpack/scons-{version}. - # - unpack_zip_files = [os.path.join(unpack_zip_dir, psv, x) - for x in sfiles] - - env.Command(unpack_zip_files, src_zip, [ - Delete(os.path.join(unpack_zip_dir, psv)), - unzipit - ]) - - # - # Run setup.py in the unpacked subdirectory to "install" everything - # into our build/test subdirectory. The runtest.py script will set - # PYTHONPATH so that the tests only look under build/test-{package}, - # and under testing/framework (for the testing modules TestCmd.py, - # TestSCons.py, etc.). This makes sure that our tests pass with - # what we really packaged, not because of something hanging - # around in the development directory. - # - # We can get away with calling setup.py using a directory path - # like this because we put a preamble in it that will chdir() - # to the directory in which setup.py exists. - # - dfiles = [os.path.join(test_src_zip_dir, x) for x in dst_files] - scons_lib_dir = os.path.join(unpack_zip_dir, psv, 'src', 'engine') - ENV = env.Dictionary('ENV').copy() - ENV['SCONS_LIB_DIR'] = scons_lib_dir - ENV['USERNAME'] = command_line.developer - env.Command(dfiles, unpack_zip_files, - [ - Delete(os.path.join(unpack_zip_dir, - psv, - 'build', - 'scons', - 'build')), - Delete("$TEST_SRC_ZIP_DIR"), - 'cd "%s" && $PYTHON $PYTHONFLAGS "%s" "%s" VERSION="$VERSION"' % \ - (os.path.join(unpack_zip_dir, psv), - os.path.join('src', 'script', 'scons.py'), - os.path.join('build', 'scons')), - '$PYTHON $PYTHONFLAGS "%s" install "--prefix=$TEST_SRC_ZIP_DIR" --standalone-lib' % \ - os.path.join(unpack_zip_dir, - psv, - 'build', - 'scons', - 'setup.py'), - ], - ENV=ENV) - -for pf, help_text in packaging_flavors: - Alias(pf, [ - os.path.join(command_line.build_dir, 'test-' + pf), - os.path.join(command_line.build_dir, 'testing/framework'), - os.path.join(command_line.build_dir, 'runtest.py'), - ]) +# sfiles = [l.split()[-1] for l in command_line.git_status_lines] +# if command_line.git_status_lines: +# # slines = [l for l in git_status_lines if 'modified:' in l] +# # sfiles = [l.split()[-1] for l in slines] +# pass +# else: +# print("Not building in a Git tree; skipping building src package.") +# +# if sfiles: +# remove_patterns = [ +# '*.gitignore', +# '*.hgignore', +# 'www/*', +# ] +# +# for p in remove_patterns: +# sfiles = [s for s in sfiles if not fnmatch.fnmatch(s, p)] +# +# if sfiles: +# ps = "%s-src" % project +# psv = "%s-%s" % (ps, command_line.version) +# b_ps = os.path.join(command_line.build_dir, ps) +# b_psv = os.path.join(command_line.build_dir, psv) +# b_psv_stamp = b_psv + '-stamp' +# +# src_tar_gz = os.path.join(command_line.build_dir, 'dist', '%s.tar.gz' % psv) +# src_zip = os.path.join(command_line.build_dir, 'dist', '%s.zip' % psv) +# +# Local(src_tar_gz, src_zip) +# +# for file in sfiles: +# if file.endswith('jpg') or file.endswith('png'): +# # don't revision binary files. +# env.Install(os.path.dirname(os.path.join(b_ps, file)), file) +# else: +# env.SCons_revision(os.path.join(b_ps, file), file) +# +# b_ps_files = [os.path.join(b_ps, x) for x in sfiles] +# cmds = [ +# Delete(b_psv), +# Copy(b_psv, b_ps), +# Touch("$TARGET"), +# ] +# +# env.Command(b_psv_stamp, src_deps + b_ps_files, cmds) +# +# Local(*b_ps_files) +# +# if gzip: +# env.Command(src_tar_gz, b_psv_stamp, +# "tar cz${TAR_HFLAG} -f $TARGET -C build %s" % psv) +# +# # +# # Unpack the archive into build/unpack/scons-{version}. +# # +# unpack_tar_gz_files = [os.path.join(unpack_tar_gz_dir, psv, x) +# for x in sfiles] +# +# # +# # We'd like to replace the last three lines with the following: +# # +# # tar zxf $SOURCES -C $UNPACK_TAR_GZ_DIR +# # +# # but that gives heartburn to Cygwin's tar, so work around it +# # with separate zcat-tar-rm commands. +# env.Command(unpack_tar_gz_files, src_tar_gz, [ +# Delete(os.path.join(unpack_tar_gz_dir, psv)), +# "$ZCAT $SOURCES > .temp", +# "tar xf .temp -C $UNPACK_TAR_GZ_DIR", +# Delete(".temp"), +# ]) +# +# # +# # Run setup.py in the unpacked subdirectory to "install" everything +# # into our build/test subdirectory. The runtest.py script will set +# # PYTHONPATH so that the tests only look under build/test-{package}, +# # and under testing/framework (for the testing modules TestCmd.py, +# # TestSCons.py, etc.). This makes sure that our tests pass with +# # what we really packaged, not because of something hanging around +# # in the development directory. +# # +# # We can get away with calling setup.py using a directory path +# # like this because we put a preamble in it that will chdir() +# # to the directory in which setup.py exists. +# # +# dfiles = [os.path.join(test_src_tar_gz_dir, x) for x in dst_files] +# scons_lib_dir = os.path.join(unpack_tar_gz_dir, psv, 'src', 'engine') +# ENV = env.Dictionary('ENV').copy() +# ENV['SCONS_LIB_DIR'] = scons_lib_dir +# ENV['USERNAME'] = command_line.developer +# env.Command(dfiles, unpack_tar_gz_files, +# [ +# Delete(os.path.join(unpack_tar_gz_dir, +# psv, +# 'build', +# 'scons', +# 'build')), +# Delete("$TEST_SRC_TAR_GZ_DIR"), +# 'cd "%s" && $PYTHON $PYTHONFLAGS "%s" "%s" VERSION="$VERSION"' % \ +# (os.path.join(unpack_tar_gz_dir, psv), +# os.path.join('src', 'script', 'scons.py'), +# os.path.join('build', 'scons')), +# '$PYTHON $PYTHONFLAGS "%s" install "--prefix=$TEST_SRC_TAR_GZ_DIR" --standalone-lib' % \ +# os.path.join(unpack_tar_gz_dir, +# psv, +# 'build', +# 'scons', +# 'setup.py'), +# ], +# ENV=ENV) +# +# if zipit: +# env.Command(src_zip, b_psv_stamp, zipit, CD='build', PSV=psv) +# +# # +# # Unpack the archive into build/unpack/scons-{version}. +# # +# unpack_zip_files = [os.path.join(unpack_zip_dir, psv, x) +# for x in sfiles] +# +# env.Command(unpack_zip_files, src_zip, [ +# Delete(os.path.join(unpack_zip_dir, psv)), +# unzipit +# ]) +# +# # +# # Run setup.py in the unpacked subdirectory to "install" everything +# # into our build/test subdirectory. The runtest.py script will set +# # PYTHONPATH so that the tests only look under build/test-{package}, +# # and under testing/framework (for the testing modules TestCmd.py, +# # TestSCons.py, etc.). This makes sure that our tests pass with +# # what we really packaged, not because of something hanging +# # around in the development directory. +# # +# # We can get away with calling setup.py using a directory path +# # like this because we put a preamble in it that will chdir() +# # to the directory in which setup.py exists. +# # +# dfiles = [os.path.join(test_src_zip_dir, x) for x in dst_files] +# scons_lib_dir = os.path.join(unpack_zip_dir, psv, 'src', 'engine') +# ENV = env.Dictionary('ENV').copy() +# ENV['SCONS_LIB_DIR'] = scons_lib_dir +# ENV['USERNAME'] = command_line.developer +# env.Command(dfiles, unpack_zip_files, +# [ +# Delete(os.path.join(unpack_zip_dir, +# psv, +# 'build', +# 'scons', +# 'build')), +# Delete("$TEST_SRC_ZIP_DIR"), +# 'cd "%s" && $PYTHON $PYTHONFLAGS "%s" "%s" VERSION="$VERSION"' % \ +# (os.path.join(unpack_zip_dir, psv), +# os.path.join('src', 'script', 'scons.py'), +# os.path.join('build', 'scons')), +# '$PYTHON $PYTHONFLAGS "%s" install "--prefix=$TEST_SRC_ZIP_DIR" --standalone-lib' % \ +# os.path.join(unpack_zip_dir, +# psv, +# 'build', +# 'scons', +# 'setup.py'), +# ], +# ENV=ENV) +# +# for pf, help_text in packaging_flavors: +# Alias(pf, [ +# os.path.join(command_line.build_dir, 'test-' + pf), +# os.path.join(command_line.build_dir, 'testing/framework'), +# os.path.join(command_line.build_dir, 'runtest.py'), +# ]) diff --git a/doc/SConscript b/doc/SConscript index 4e9fb74..df68ecc 100644 --- a/doc/SConscript +++ b/doc/SConscript @@ -76,7 +76,7 @@ tar_deps = [] tar_list = [] orig_env = env -env = orig_env.Clone(SCONS_PY = File('#src/script/scons.py').rfile()) +env = orig_env.Clone(SCONS_PY = File('#/scripts/scons.py').rfile()) # # --- Helpers --- -- cgit v0.12 From 111837ba11bdf49703e9d6bdc5e79f0231a88095 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 21 Mar 2020 17:43:51 -0700 Subject: Fix doc sconscript --- doc/SConscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/SConscript b/doc/SConscript index df68ecc..8b22b3b 100644 --- a/doc/SConscript +++ b/doc/SConscript @@ -562,4 +562,4 @@ if tar_deps: Local(t) Alias('doc', t) else: - Alias('doc', os.path.join(build_dir, 'doc')) + Alias('doc', os.path.join(command_line.build_dir, 'doc')) -- cgit v0.12 From 349d79172a60b2840a17c03456be93560ec974e0 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 21 Mar 2020 18:11:03 -0700 Subject: Fix scripts dirname typo --- runtest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtest.py b/runtest.py index 2ee4476..65b2179 100755 --- a/runtest.py +++ b/runtest.py @@ -555,7 +555,7 @@ else: scons_runtest_dir = base if not external: - scons_script_dir = sd or os.path.join(base, 'script') + scons_script_dir = sd or os.path.join(base, 'scripts') scons_lib_dir = ld or os.path.join(base, 'src', 'engine') else: scons_script_dir = sd or '' -- cgit v0.12 From 4ace04ea384de1e76126c4a6dfae8c8fbe2b3db8 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 21 Mar 2020 19:22:33 -0700 Subject: Fix scons-time tests. Remove subversion test --- bin/scons-time.py | 1480 --------------------------------- scripts/scons-time.py | 1480 +++++++++++++++++++++++++++++++++ test/scons-time/run/archive/dir.py | 1 + test/scons-time/run/config/targets.py | 2 +- test/scons-time/run/option/quiet.py | 2 +- test/scons-time/run/option/verbose.py | 2 +- test/scons-time/run/subversion.py | 81 -- testing/framework/TestSCons_time.py | 8 +- 8 files changed, 1488 insertions(+), 1568 deletions(-) delete mode 100644 bin/scons-time.py create mode 100644 scripts/scons-time.py delete mode 100644 test/scons-time/run/subversion.py diff --git a/bin/scons-time.py b/bin/scons-time.py deleted file mode 100644 index e4dd863..0000000 --- a/bin/scons-time.py +++ /dev/null @@ -1,1480 +0,0 @@ -#!/usr/bin/env python -# -# scons-time - run SCons timings and collect statistics -# -# A script for running a configuration through SCons with a standard -# set of invocations to collect timing and memory statistics and to -# capture the results in a consistent set of output files for display -# and analysis. -# - -# -# __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 getopt -import glob -import os -import re -import shutil -import sys -import tempfile -import time -import subprocess - -def HACK_for_exec(cmd, *args): - """ - For some reason, Python won't allow an exec() within a function - that also declares an internal function (including lambda functions). - This function is a hack that calls exec() in a function with no - internal functions. - """ - if not args: exec(cmd) - elif len(args) == 1: exec(cmd, args[0]) - else: exec(cmd, args[0], args[1]) - -class Plotter(object): - def increment_size(self, largest): - """ - Return the size of each horizontal increment line for a specified - maximum value. This returns a value that will provide somewhere - between 5 and 9 horizontal lines on the graph, on some set of - boundaries that are multiples of 10/100/1000/etc. - """ - i = largest // 5 - if not i: - return largest - multiplier = 1 - while i >= 10: - i = i // 10 - multiplier = multiplier * 10 - return i * multiplier - - def max_graph_value(self, largest): - # Round up to next integer. - largest = int(largest) + 1 - increment = self.increment_size(largest) - return ((largest + increment - 1) // increment) * increment - -class Line(object): - def __init__(self, points, type, title, label, comment, fmt="%s %s"): - self.points = points - self.type = type - self.title = title - self.label = label - self.comment = comment - self.fmt = fmt - - def print_label(self, inx, x, y): - if self.label: - print('set label %s "%s" at %0.1f,%0.1f right' % (inx, self.label, x, y)) - - def plot_string(self): - if self.title: - title_string = 'title "%s"' % self.title - else: - title_string = 'notitle' - return "'-' %s with lines lt %s" % (title_string, self.type) - - def print_points(self, fmt=None): - if fmt is None: - fmt = self.fmt - if self.comment: - print('# %s' % self.comment) - for x, y in self.points: - # If y is None, it usually represents some kind of break - # in the line's index number. We might want to represent - # this some way rather than just drawing the line straight - # between the two points on either side. - if y is not None: - print(fmt % (x, y)) - print('e') - - def get_x_values(self): - return [ p[0] for p in self.points ] - - def get_y_values(self): - return [ p[1] for p in self.points ] - -class Gnuplotter(Plotter): - - def __init__(self, title, key_location): - self.lines = [] - self.title = title - self.key_location = key_location - - def line(self, points, type, title=None, label=None, comment=None, fmt='%s %s'): - if points: - line = Line(points, type, title, label, comment, fmt) - self.lines.append(line) - - def plot_string(self, line): - return line.plot_string() - - def vertical_bar(self, x, type, label, comment): - if self.get_min_x() <= x <= self.get_max_x(): - points = [(x, 0), (x, self.max_graph_value(self.get_max_y()))] - self.line(points, type, label, comment) - - def get_all_x_values(self): - result = [] - for line in self.lines: - result.extend(line.get_x_values()) - return [r for r in result if r is not None] - - def get_all_y_values(self): - result = [] - for line in self.lines: - result.extend(line.get_y_values()) - return [r for r in result if r is not None] - - def get_min_x(self): - try: - return self.min_x - except AttributeError: - try: - self.min_x = min(self.get_all_x_values()) - except ValueError: - self.min_x = 0 - return self.min_x - - def get_max_x(self): - try: - return self.max_x - except AttributeError: - try: - self.max_x = max(self.get_all_x_values()) - except ValueError: - self.max_x = 0 - return self.max_x - - def get_min_y(self): - try: - return self.min_y - except AttributeError: - try: - self.min_y = min(self.get_all_y_values()) - except ValueError: - self.min_y = 0 - return self.min_y - - def get_max_y(self): - try: - return self.max_y - except AttributeError: - try: - self.max_y = max(self.get_all_y_values()) - except ValueError: - self.max_y = 0 - return self.max_y - - def draw(self): - - if not self.lines: - return - - if self.title: - print('set title "%s"' % self.title) - print('set key %s' % self.key_location) - - min_y = self.get_min_y() - max_y = self.max_graph_value(self.get_max_y()) - incr = (max_y - min_y) / 10.0 - start = min_y + (max_y / 2.0) + (2.0 * incr) - position = [ start - (i * incr) for i in range(5) ] - - inx = 1 - for line in self.lines: - line.print_label(inx, line.points[0][0]-1, - position[(inx-1) % len(position)]) - inx += 1 - - plot_strings = [ self.plot_string(l) for l in self.lines ] - print('plot ' + ', \\\n '.join(plot_strings)) - - for line in self.lines: - line.print_points() - - - -def untar(fname): - import tarfile - tar = tarfile.open(name=fname, mode='r') - for tarinfo in tar: - tar.extract(tarinfo) - tar.close() - -def unzip(fname): - import zipfile - zf = zipfile.ZipFile(fname, 'r') - for name in zf.namelist(): - dir = os.path.dirname(name) - try: - os.makedirs(dir) - except: - pass - with open(name, 'wb') as f: - f.write(zf.read(name)) - -def read_tree(dir): - for dirpath, dirnames, filenames in os.walk(dir): - for fn in filenames: - fn = os.path.join(dirpath, fn) - if os.path.isfile(fn): - with open(fn, 'rb') as f: - f.read() - -def redirect_to_file(command, log): - return '%s > %s 2>&1' % (command, log) - -def tee_to_file(command, log): - return '%s 2>&1 | tee %s' % (command, log) - - - -class SConsTimer(object): - """ - Usage: scons-time SUBCOMMAND [ARGUMENTS] - Type "scons-time help SUBCOMMAND" for help on a specific subcommand. - - Available subcommands: - func Extract test-run data for a function - help Provides help - mem Extract --debug=memory data from test runs - obj Extract --debug=count data from test runs - time Extract --debug=time data from test runs - run Runs a test configuration - """ - - name = 'scons-time' - name_spaces = ' '*len(name) - - def makedict(**kw): - return kw - - default_settings = makedict( - chdir = None, - config_file = None, - initial_commands = [], - key_location = 'bottom left', - orig_cwd = os.getcwd(), - outdir = None, - prefix = '', - python = '"%s"' % sys.executable, - redirect = redirect_to_file, - scons = None, - scons_flags = '--debug=count --debug=memory --debug=time --debug=memoizer', - scons_lib_dir = None, - scons_wrapper = None, - startup_targets = '--help', - subdir = None, - subversion_url = None, - svn = 'svn', - svn_co_flag = '-q', - tar = 'tar', - targets = '', - targets0 = None, - targets1 = None, - targets2 = None, - title = None, - unzip = 'unzip', - verbose = False, - vertical_bars = [], - - unpack_map = { - '.tar.gz' : (untar, '%(tar)s xzf %%s'), - '.tgz' : (untar, '%(tar)s xzf %%s'), - '.tar' : (untar, '%(tar)s xf %%s'), - '.zip' : (unzip, '%(unzip)s %%s'), - }, - ) - - run_titles = [ - 'Startup', - 'Full build', - 'Up-to-date build', - ] - - run_commands = [ - '%(python)s %(scons_wrapper)s %(scons_flags)s --profile=%(prof0)s %(targets0)s', - '%(python)s %(scons_wrapper)s %(scons_flags)s --profile=%(prof1)s %(targets1)s', - '%(python)s %(scons_wrapper)s %(scons_flags)s --profile=%(prof2)s %(targets2)s', - ] - - stages = [ - 'pre-read', - 'post-read', - 'pre-build', - 'post-build', - ] - - stage_strings = { - 'pre-read' : 'Memory before reading SConscript files:', - 'post-read' : 'Memory after reading SConscript files:', - 'pre-build' : 'Memory before building targets:', - 'post-build' : 'Memory after building targets:', - } - - memory_string_all = 'Memory ' - - default_stage = stages[-1] - - time_strings = { - 'total' : 'Total build time', - 'SConscripts' : 'Total SConscript file execution time', - 'SCons' : 'Total SCons execution time', - 'commands' : 'Total command execution time', - } - - time_string_all = 'Total .* time' - - # - - def __init__(self): - self.__dict__.update(self.default_settings) - - # Functions for displaying and executing commands. - - def subst(self, x, dictionary): - try: - return x % dictionary - except TypeError: - # x isn't a string (it's probably a Python function), - # so just return it. - return x - - def subst_variables(self, command, dictionary): - """ - Substitutes (via the format operator) the values in the specified - dictionary into the specified command. - - The command can be an (action, string) tuple. In all cases, we - perform substitution on strings and don't worry if something isn't - a string. (It's probably a Python function to be executed.) - """ - try: - command + '' - except TypeError: - action = command[0] - string = command[1] - args = command[2:] - else: - action = command - string = action - args = (()) - action = self.subst(action, dictionary) - string = self.subst(string, dictionary) - return (action, string, args) - - def _do_not_display(self, msg, *args): - pass - - def display(self, msg, *args): - """ - Displays the specified message. - - Each message is prepended with a standard prefix of our name - plus the time. - """ - if callable(msg): - msg = msg(*args) - else: - msg = msg % args - if msg is None: - return - fmt = '%s[%s]: %s\n' - sys.stdout.write(fmt % (self.name, time.strftime('%H:%M:%S'), msg)) - - def _do_not_execute(self, action, *args): - pass - - def execute(self, action, *args): - """ - Executes the specified action. - - The action is called if it's a callable Python function, and - otherwise passed to os.system(). - """ - if callable(action): - action(*args) - else: - os.system(action % args) - - def run_command_list(self, commands, dict): - """ - Executes a list of commands, substituting values from the - specified dictionary. - """ - commands = [ self.subst_variables(c, dict) for c in commands ] - for action, string, args in commands: - self.display(string, *args) - sys.stdout.flush() - status = self.execute(action, *args) - if status: - sys.exit(status) - - def log_display(self, command, log): - command = self.subst(command, self.__dict__) - if log: - command = self.redirect(command, log) - return command - - def log_execute(self, command, log): - command = self.subst(command, self.__dict__) - p = os.popen(command) - output = p.read() - p.close() - #TODO: convert to subrocess, os.popen is obsolete. This didn't work: - #process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True) - #output = process.stdout.read() - #process.stdout.close() - #process.wait() - if self.verbose: - sys.stdout.write(output) - # TODO: Figure out - # Not sure we need to write binary here - with open(log, 'w') as f: - f.write(str(output)) - - def archive_splitext(self, path): - """ - Splits an archive name into a filename base and extension. - - This is like os.path.splitext() (which it calls) except that it - also looks for '.tar.gz' and treats it as an atomic extensions. - """ - if path.endswith('.tar.gz'): - return path[:-7], path[-7:] - else: - return os.path.splitext(path) - - def args_to_files(self, args, tail=None): - """ - Takes a list of arguments, expands any glob patterns, and - returns the last "tail" files from the list. - """ - files = [] - for a in args: - files.extend(sorted(glob.glob(a))) - - if tail: - files = files[-tail:] - - return files - - def ascii_table(self, files, columns, - line_function, file_function=lambda x: x, - *args, **kw): - - header_fmt = ' '.join(['%12s'] * len(columns)) - line_fmt = header_fmt + ' %s' - - print(header_fmt % columns) - - for file in files: - t = line_function(file, *args, **kw) - if t is None: - t = [] - diff = len(columns) - len(t) - if diff > 0: - t += [''] * diff - t.append(file_function(file)) - print(line_fmt % tuple(t)) - - def collect_results(self, files, function, *args, **kw): - results = {} - - for file in files: - base = os.path.splitext(file)[0] - run, index = base.split('-')[-2:] - - run = int(run) - index = int(index) - - value = function(file, *args, **kw) - - try: - r = results[index] - except KeyError: - r = [] - results[index] = r - r.append((run, value)) - - return results - - def doc_to_help(self, obj): - """ - Translates an object's __doc__ string into help text. - - This strips a consistent number of spaces from each line in the - help text, essentially "outdenting" the text to the left-most - column. - """ - doc = obj.__doc__ - if doc is None: - return '' - return self.outdent(doc) - - def find_next_run_number(self, dir, prefix): - """ - Returns the next run number in a directory for the specified prefix. - - Examines the contents the specified directory for files with the - specified prefix, extracts the run numbers from each file name, - and returns the next run number after the largest it finds. - """ - x = re.compile(re.escape(prefix) + '-([0-9]+).*') - matches = [x.match(e) for e in os.listdir(dir)] - matches = [_f for _f in matches if _f] - if not matches: - return 0 - run_numbers = [int(m.group(1)) for m in matches] - return int(max(run_numbers)) + 1 - - def gnuplot_results(self, results, fmt='%s %.3f'): - """ - Prints out a set of results in Gnuplot format. - """ - gp = Gnuplotter(self.title, self.key_location) - - for i in sorted(results.keys()): - try: - t = self.run_titles[i] - except IndexError: - t = '??? %s ???' % i - results[i].sort() - gp.line(results[i], i+1, t, None, t, fmt=fmt) - - for bar_tuple in self.vertical_bars: - try: - x, type, label, comment = bar_tuple - except ValueError: - x, type, label = bar_tuple - comment = label - gp.vertical_bar(x, type, label, comment) - - gp.draw() - - def logfile_name(self, invocation): - """ - Returns the absolute path of a log file for the specificed - invocation number. - """ - name = self.prefix_run + '-%d.log' % invocation - return os.path.join(self.outdir, name) - - def outdent(self, s): - """ - Strip as many spaces from each line as are found at the beginning - of the first line in the list. - """ - lines = s.split('\n') - if lines[0] == '': - lines = lines[1:] - spaces = re.match(' *', lines[0]).group(0) - def strip_initial_spaces(l, s=spaces): - if l.startswith(spaces): - l = l[len(spaces):] - return l - return '\n'.join([ strip_initial_spaces(l) for l in lines ]) + '\n' - - def profile_name(self, invocation): - """ - Returns the absolute path of a profile file for the specified - invocation number. - """ - name = self.prefix_run + '-%d.prof' % invocation - return os.path.join(self.outdir, name) - - def set_env(self, key, value): - os.environ[key] = value - - # - - def get_debug_times(self, file, time_string=None): - """ - Fetch times from the --debug=time strings in the specified file. - """ - if time_string is None: - search_string = self.time_string_all - else: - search_string = time_string - with open(file) as f: - contents = f.read() - 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 = [ float(r) for r in result ] - if time_string is not None: - try: - result = result[0] - except IndexError: - sys.stderr.write('file %s has no results!\n' % repr(file)) - return None - return result - - def get_function_profile(self, file, function): - """ - Returns the file, line number, function name, and cumulative time. - """ - try: - import pstats - except ImportError as e: - sys.stderr.write('%s: func: %s\n' % (self.name, e)) - sys.stderr.write('%s This version of Python is missing the profiler.\n' % self.name_spaces) - sys.stderr.write('%s Cannot use the "func" subcommand.\n' % self.name_spaces) - sys.exit(1) - statistics = pstats.Stats(file).stats - matches = [ e for e in statistics.items() if e[0][2] == function ] - r = matches[0] - return r[0][0], r[0][1], r[0][2], r[1][3] - - def get_function_time(self, file, function): - """ - Returns just the cumulative time for the specified function. - """ - return self.get_function_profile(file, function)[3] - - def get_memory(self, file, memory_string=None): - """ - Returns a list of integers of the amount of memory used. The - default behavior is to return all the stages. - """ - if memory_string is None: - search_string = self.memory_string_all - else: - search_string = memory_string - with open(file) as f: - lines = f.readlines() - lines = [ l for l in lines if l.startswith(search_string) ][-4:] - result = [ int(l.split()[-1]) for l in lines[-4:] ] - if len(result) == 1: - result = result[0] - return result - - def get_object_counts(self, file, object_name, index=None): - """ - Returns the counts of the specified object_name. - """ - object_string = ' ' + object_name + '\n' - with open(file) as f: - lines = f.readlines() - line = [ l for l in lines if l.endswith(object_string) ][0] - result = [ int(field) for field in line.split()[:4] ] - if index is not None: - result = result[index] - return result - - - command_alias = {} - - def execute_subcommand(self, argv): - """ - Executes the do_*() function for the specified subcommand (argv[0]). - """ - if not argv: - return - cmdName = self.command_alias.get(argv[0], argv[0]) - try: - func = getattr(self, 'do_' + cmdName) - except AttributeError: - return self.default(argv) - try: - return func(argv) - except TypeError as e: - sys.stderr.write("%s %s: %s\n" % (self.name, cmdName, e)) - import traceback - traceback.print_exc(file=sys.stderr) - sys.stderr.write("Try '%s help %s'\n" % (self.name, cmdName)) - - def default(self, argv): - """ - The default behavior for an unknown subcommand. Prints an - error message and exits. - """ - sys.stderr.write('%s: Unknown subcommand "%s".\n' % (self.name, argv[0])) - sys.stderr.write('Type "%s help" for usage.\n' % self.name) - sys.exit(1) - - # - - def do_help(self, argv): - """ - """ - if argv[1:]: - for arg in argv[1:]: - try: - func = getattr(self, 'do_' + arg) - except AttributeError: - sys.stderr.write('%s: No help for "%s"\n' % (self.name, arg)) - else: - try: - help = getattr(self, 'help_' + arg) - except AttributeError: - sys.stdout.write(self.doc_to_help(func)) - sys.stdout.flush() - else: - help() - else: - doc = self.doc_to_help(self.__class__) - if doc: - sys.stdout.write(doc) - sys.stdout.flush() - return None - - # - - def help_func(self): - help = """\ - Usage: scons-time func [OPTIONS] FILE [...] - - -C DIR, --chdir=DIR Change to DIR before looking for files - -f FILE, --file=FILE Read configuration from specified FILE - --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT - --func=NAME, --function=NAME Report time for function NAME - -h, --help Print this help and exit - -p STRING, --prefix=STRING Use STRING as log file/profile prefix - -t NUMBER, --tail=NUMBER Only report the last NUMBER files - --title=TITLE Specify the output plot TITLE - """ - sys.stdout.write(self.outdent(help)) - sys.stdout.flush() - - def do_func(self, argv): - """ - """ - format = 'ascii' - function_name = '_main' - tail = None - - short_opts = '?C:f:hp:t:' - - long_opts = [ - 'chdir=', - 'file=', - 'fmt=', - 'format=', - 'func=', - 'function=', - 'help', - 'prefix=', - 'tail=', - 'title=', - ] - - opts, args = getopt.getopt(argv[1:], short_opts, long_opts) - - for o, a in opts: - if o in ('-C', '--chdir'): - self.chdir = a - elif o in ('-f', '--file'): - self.config_file = a - elif o in ('--fmt', '--format'): - format = a - elif o in ('--func', '--function'): - function_name = a - elif o in ('-?', '-h', '--help'): - self.do_help(['help', 'func']) - sys.exit(0) - elif o in ('--max',): - max_time = int(a) - elif o in ('-p', '--prefix'): - self.prefix = a - elif o in ('-t', '--tail'): - tail = int(a) - elif o in ('--title',): - self.title = a - - if self.config_file: - with open(self.config_file, 'r') as f: - config = f.read() - exec(config, self.__dict__) - - if self.chdir: - os.chdir(self.chdir) - - if not args: - - pattern = '%s*.prof' % self.prefix - args = self.args_to_files([pattern], tail) - - if not args: - if self.chdir: - directory = self.chdir - else: - directory = os.getcwd() - - sys.stderr.write('%s: func: No arguments specified.\n' % self.name) - sys.stderr.write('%s No %s*.prof files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) - sys.stderr.write('%s Type "%s help func" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - - else: - - args = self.args_to_files(args, tail) - - cwd_ = os.getcwd() + os.sep - - if format == 'ascii': - - for file in args: - try: - f, line, func, time = \ - self.get_function_profile(file, function_name) - except ValueError as e: - sys.stderr.write("%s: func: %s: %s\n" % - (self.name, file, e)) - else: - if f.startswith(cwd_): - f = f[len(cwd_):] - print("%.3f %s:%d(%s)" % (time, f, line, func)) - - elif format == 'gnuplot': - - results = self.collect_results(args, self.get_function_time, - function_name) - - self.gnuplot_results(results) - - else: - - sys.stderr.write('%s: func: Unknown format "%s".\n' % (self.name, format)) - sys.exit(1) - - # - - def help_mem(self): - help = """\ - Usage: scons-time mem [OPTIONS] FILE [...] - - -C DIR, --chdir=DIR Change to DIR before looking for files - -f FILE, --file=FILE Read configuration from specified FILE - --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT - -h, --help Print this help and exit - -p STRING, --prefix=STRING Use STRING as log file/profile prefix - --stage=STAGE Plot memory at the specified stage: - pre-read, post-read, pre-build, - post-build (default: post-build) - -t NUMBER, --tail=NUMBER Only report the last NUMBER files - --title=TITLE Specify the output plot TITLE - """ - sys.stdout.write(self.outdent(help)) - sys.stdout.flush() - - def do_mem(self, argv): - - format = 'ascii' - logfile_path = lambda x: x - stage = self.default_stage - tail = None - - short_opts = '?C:f:hp:t:' - - long_opts = [ - 'chdir=', - 'file=', - 'fmt=', - 'format=', - 'help', - 'prefix=', - 'stage=', - 'tail=', - 'title=', - ] - - opts, args = getopt.getopt(argv[1:], short_opts, long_opts) - - for o, a in opts: - if o in ('-C', '--chdir'): - self.chdir = a - elif o in ('-f', '--file'): - self.config_file = a - elif o in ('--fmt', '--format'): - format = a - elif o in ('-?', '-h', '--help'): - self.do_help(['help', 'mem']) - sys.exit(0) - elif o in ('-p', '--prefix'): - self.prefix = a - elif o in ('--stage',): - if a not in self.stages: - sys.stderr.write('%s: mem: Unrecognized stage "%s".\n' % (self.name, a)) - sys.exit(1) - stage = a - elif o in ('-t', '--tail'): - tail = int(a) - elif o in ('--title',): - self.title = a - - if self.config_file: - with open(self.config_file, 'r') as f: - config = f.read() - HACK_for_exec(config, self.__dict__) - - if self.chdir: - os.chdir(self.chdir) - logfile_path = lambda x: os.path.join(self.chdir, x) - - if not args: - - pattern = '%s*.log' % self.prefix - args = self.args_to_files([pattern], tail) - - if not args: - if self.chdir: - directory = self.chdir - else: - directory = os.getcwd() - - sys.stderr.write('%s: mem: No arguments specified.\n' % self.name) - sys.stderr.write('%s No %s*.log files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) - sys.stderr.write('%s Type "%s help mem" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - - else: - - args = self.args_to_files(args, tail) - - cwd_ = os.getcwd() + os.sep - - if format == 'ascii': - - self.ascii_table(args, tuple(self.stages), self.get_memory, logfile_path) - - elif format == 'gnuplot': - - results = self.collect_results(args, self.get_memory, - self.stage_strings[stage]) - - self.gnuplot_results(results) - - else: - - sys.stderr.write('%s: mem: Unknown format "%s".\n' % (self.name, format)) - sys.exit(1) - - return 0 - - # - - def help_obj(self): - help = """\ - Usage: scons-time obj [OPTIONS] OBJECT FILE [...] - - -C DIR, --chdir=DIR Change to DIR before looking for files - -f FILE, --file=FILE Read configuration from specified FILE - --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT - -h, --help Print this help and exit - -p STRING, --prefix=STRING Use STRING as log file/profile prefix - --stage=STAGE Plot memory at the specified stage: - pre-read, post-read, pre-build, - post-build (default: post-build) - -t NUMBER, --tail=NUMBER Only report the last NUMBER files - --title=TITLE Specify the output plot TITLE - """ - sys.stdout.write(self.outdent(help)) - sys.stdout.flush() - - def do_obj(self, argv): - - format = 'ascii' - logfile_path = lambda x: x - stage = self.default_stage - tail = None - - short_opts = '?C:f:hp:t:' - - long_opts = [ - 'chdir=', - 'file=', - 'fmt=', - 'format=', - 'help', - 'prefix=', - 'stage=', - 'tail=', - 'title=', - ] - - opts, args = getopt.getopt(argv[1:], short_opts, long_opts) - - for o, a in opts: - if o in ('-C', '--chdir'): - self.chdir = a - elif o in ('-f', '--file'): - self.config_file = a - elif o in ('--fmt', '--format'): - format = a - elif o in ('-?', '-h', '--help'): - self.do_help(['help', 'obj']) - sys.exit(0) - elif o in ('-p', '--prefix'): - self.prefix = a - elif o in ('--stage',): - if a not in self.stages: - sys.stderr.write('%s: obj: Unrecognized stage "%s".\n' % (self.name, a)) - sys.stderr.write('%s Type "%s help obj" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - stage = a - elif o in ('-t', '--tail'): - tail = int(a) - elif o in ('--title',): - self.title = a - - if not args: - sys.stderr.write('%s: obj: Must specify an object name.\n' % self.name) - sys.stderr.write('%s Type "%s help obj" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - - object_name = args.pop(0) - - if self.config_file: - with open(self.config_file, 'r') as f: - config = f.read() - HACK_for_exec(config, self.__dict__) - - if self.chdir: - os.chdir(self.chdir) - logfile_path = lambda x: os.path.join(self.chdir, x) - - if not args: - - pattern = '%s*.log' % self.prefix - args = self.args_to_files([pattern], tail) - - if not args: - if self.chdir: - directory = self.chdir - else: - directory = os.getcwd() - - sys.stderr.write('%s: obj: No arguments specified.\n' % self.name) - sys.stderr.write('%s No %s*.log files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) - sys.stderr.write('%s Type "%s help obj" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - - else: - - args = self.args_to_files(args, tail) - - cwd_ = os.getcwd() + os.sep - - if format == 'ascii': - - self.ascii_table(args, tuple(self.stages), self.get_object_counts, logfile_path, object_name) - - elif format == 'gnuplot': - - stage_index = 0 - for s in self.stages: - if stage == s: - break - stage_index = stage_index + 1 - - results = self.collect_results(args, self.get_object_counts, - object_name, stage_index) - - self.gnuplot_results(results) - - else: - - sys.stderr.write('%s: obj: Unknown format "%s".\n' % (self.name, format)) - sys.exit(1) - - return 0 - - # - - def help_run(self): - help = """\ - Usage: scons-time run [OPTIONS] [FILE ...] - - --chdir=DIR Name of unpacked directory for chdir - -f FILE, --file=FILE Read configuration from specified FILE - -h, --help Print this help and exit - -n, --no-exec No execute, just print command lines - --number=NUMBER Put output in files for run NUMBER - --outdir=OUTDIR Put output files in OUTDIR - -p STRING, --prefix=STRING Use STRING as log file/profile prefix - --python=PYTHON Time using the specified PYTHON - -q, --quiet Don't print command lines - --scons=SCONS Time using the specified SCONS - --svn=URL, --subversion=URL Use SCons from Subversion URL - -v, --verbose Display output of commands - """ - sys.stdout.write(self.outdent(help)) - sys.stdout.flush() - - def do_run(self, argv): - """ - """ - run_number_list = [None] - - short_opts = '?f:hnp:qs:v' - - long_opts = [ - 'file=', - 'help', - 'no-exec', - 'number=', - 'outdir=', - 'prefix=', - 'python=', - 'quiet', - 'scons=', - 'svn=', - 'subdir=', - 'subversion=', - 'verbose', - ] - - opts, args = getopt.getopt(argv[1:], short_opts, long_opts) - - for o, a in opts: - if o in ('-f', '--file'): - self.config_file = a - elif o in ('-?', '-h', '--help'): - self.do_help(['help', 'run']) - sys.exit(0) - elif o in ('-n', '--no-exec'): - self.execute = self._do_not_execute - elif o in ('--number',): - run_number_list = self.split_run_numbers(a) - elif o in ('--outdir',): - self.outdir = a - elif o in ('-p', '--prefix'): - self.prefix = a - elif o in ('--python',): - self.python = a - elif o in ('-q', '--quiet'): - self.display = self._do_not_display - elif o in ('-s', '--subdir'): - self.subdir = a - elif o in ('--scons',): - self.scons = a - elif o in ('--svn', '--subversion'): - self.subversion_url = a - elif o in ('-v', '--verbose'): - self.redirect = tee_to_file - self.verbose = True - self.svn_co_flag = '' - - if not args and not self.config_file: - sys.stderr.write('%s: run: No arguments or -f config file specified.\n' % self.name) - sys.stderr.write('%s Type "%s help run" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - - if self.config_file: - with open(self.config_file, 'r') as f: - config = f.read() - exec(config, self.__dict__) - - if args: - self.archive_list = args - - archive_file_name = os.path.split(self.archive_list[0])[1] - - if not self.subdir: - self.subdir = self.archive_splitext(archive_file_name)[0] - - if not self.prefix: - self.prefix = self.archive_splitext(archive_file_name)[0] - - prepare = None - if self.subversion_url: - prepare = self.prep_subversion_run - - for run_number in run_number_list: - self.individual_run(run_number, self.archive_list, prepare) - - def split_run_numbers(self, s): - result = [] - for n in s.split(','): - try: - x, y = n.split('-') - except ValueError: - result.append(int(n)) - else: - result.extend(list(range(int(x), int(y)+1))) - return result - - def scons_path(self, dir): - return os.path.join(dir, 'src', 'script', 'scons.py') - - def scons_lib_dir_path(self, dir): - return os.path.join(dir, 'src', 'engine') - - def prep_subversion_run(self, commands, removals): - self.svn_tmpdir = tempfile.mkdtemp(prefix=self.name + '-svn-') - removals.append((shutil.rmtree, 'rm -rf %%s', self.svn_tmpdir)) - - self.scons = self.scons_path(self.svn_tmpdir) - self.scons_lib_dir = self.scons_lib_dir_path(self.svn_tmpdir) - - commands.extend([ - '%(svn)s co %(svn_co_flag)s -r %(run_number)s %(subversion_url)s %(svn_tmpdir)s', - ]) - - def individual_run(self, run_number, archive_list, prepare=None): - """ - Performs an individual run of the default SCons invocations. - """ - - commands = [] - removals = [] - - if prepare: - prepare(commands, removals) - - save_scons = self.scons - save_scons_wrapper = self.scons_wrapper - save_scons_lib_dir = self.scons_lib_dir - - if self.outdir is None: - self.outdir = self.orig_cwd - elif not os.path.isabs(self.outdir): - self.outdir = os.path.join(self.orig_cwd, self.outdir) - - if self.scons is None: - self.scons = self.scons_path(self.orig_cwd) - - if self.scons_lib_dir is None: - self.scons_lib_dir = self.scons_lib_dir_path(self.orig_cwd) - - if self.scons_wrapper is None: - self.scons_wrapper = self.scons - - if not run_number: - run_number = self.find_next_run_number(self.outdir, self.prefix) - - self.run_number = str(run_number) - - self.prefix_run = self.prefix + '-%03d' % run_number - - if self.targets0 is None: - self.targets0 = self.startup_targets - if self.targets1 is None: - self.targets1 = self.targets - if self.targets2 is None: - self.targets2 = self.targets - - self.tmpdir = tempfile.mkdtemp(prefix=self.name + '-') - - commands.extend([ - (os.chdir, 'cd %%s', self.tmpdir), - ]) - - for archive in archive_list: - if not os.path.isabs(archive): - archive = os.path.join(self.orig_cwd, archive) - if os.path.isdir(archive): - dest = os.path.split(archive)[1] - commands.append((shutil.copytree, 'cp -r %%s %%s', archive, dest)) - else: - suffix = self.archive_splitext(archive)[1] - unpack_command = self.unpack_map.get(suffix) - if not unpack_command: - dest = os.path.split(archive)[1] - commands.append((shutil.copyfile, 'cp %%s %%s', archive, dest)) - else: - commands.append(unpack_command + (archive,)) - - commands.extend([ - (os.chdir, 'cd %%s', self.subdir), - ]) - - commands.extend(self.initial_commands) - - commands.extend([ - (lambda: read_tree('.'), - 'find * -type f | xargs cat > /dev/null'), - - (self.set_env, 'export %%s=%%s', - 'SCONS_LIB_DIR', self.scons_lib_dir), - - '%(python)s %(scons_wrapper)s --version', - ]) - - index = 0 - for run_command in self.run_commands: - setattr(self, 'prof%d' % index, self.profile_name(index)) - c = ( - self.log_execute, - self.log_display, - run_command, - self.logfile_name(index), - ) - commands.append(c) - index = index + 1 - - commands.extend([ - (os.chdir, 'cd %%s', self.orig_cwd), - ]) - - if not os.environ.get('PRESERVE'): - commands.extend(removals) - commands.append((shutil.rmtree, 'rm -rf %%s', self.tmpdir)) - - self.run_command_list(commands, self.__dict__) - - self.scons = save_scons - self.scons_lib_dir = save_scons_lib_dir - self.scons_wrapper = save_scons_wrapper - - # - - def help_time(self): - help = """\ - Usage: scons-time time [OPTIONS] FILE [...] - - -C DIR, --chdir=DIR Change to DIR before looking for files - -f FILE, --file=FILE Read configuration from specified FILE - --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT - -h, --help Print this help and exit - -p STRING, --prefix=STRING Use STRING as log file/profile prefix - -t NUMBER, --tail=NUMBER Only report the last NUMBER files - --which=TIMER Plot timings for TIMER: total, - SConscripts, SCons, commands. - """ - sys.stdout.write(self.outdent(help)) - sys.stdout.flush() - - def do_time(self, argv): - - format = 'ascii' - logfile_path = lambda x: x - tail = None - which = 'total' - - short_opts = '?C:f:hp:t:' - - long_opts = [ - 'chdir=', - 'file=', - 'fmt=', - 'format=', - 'help', - 'prefix=', - 'tail=', - 'title=', - 'which=', - ] - - opts, args = getopt.getopt(argv[1:], short_opts, long_opts) - - for o, a in opts: - if o in ('-C', '--chdir'): - self.chdir = a - elif o in ('-f', '--file'): - self.config_file = a - elif o in ('--fmt', '--format'): - format = a - elif o in ('-?', '-h', '--help'): - self.do_help(['help', 'time']) - sys.exit(0) - elif o in ('-p', '--prefix'): - self.prefix = a - elif o in ('-t', '--tail'): - tail = int(a) - elif o in ('--title',): - self.title = a - elif o in ('--which',): - if a not in list(self.time_strings.keys()): - sys.stderr.write('%s: time: Unrecognized timer "%s".\n' % (self.name, a)) - sys.stderr.write('%s Type "%s help time" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - which = a - - if self.config_file: - with open(self.config_file, 'r') as f: - config = f.read() - HACK_for_exec(config, self.__dict__) - - if self.chdir: - os.chdir(self.chdir) - logfile_path = lambda x: os.path.join(self.chdir, x) - - if not args: - - pattern = '%s*.log' % self.prefix - args = self.args_to_files([pattern], tail) - - if not args: - if self.chdir: - directory = self.chdir - else: - directory = os.getcwd() - - sys.stderr.write('%s: time: No arguments specified.\n' % self.name) - sys.stderr.write('%s No %s*.log files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) - sys.stderr.write('%s Type "%s help time" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - - else: - - args = self.args_to_files(args, tail) - - cwd_ = os.getcwd() + os.sep - - if format == 'ascii': - - columns = ("Total", "SConscripts", "SCons", "commands") - self.ascii_table(args, columns, self.get_debug_times, logfile_path) - - elif format == 'gnuplot': - - results = self.collect_results(args, self.get_debug_times, - self.time_strings[which]) - - self.gnuplot_results(results, fmt='%s %.6f') - - else: - - sys.stderr.write('%s: time: Unknown format "%s".\n' % (self.name, format)) - sys.exit(1) - -if __name__ == '__main__': - opts, args = getopt.getopt(sys.argv[1:], 'h?V', ['help', 'version']) - - ST = SConsTimer() - - for o, a in opts: - if o in ('-?', '-h', '--help'): - ST.do_help(['help']) - sys.exit(0) - elif o in ('-V', '--version'): - sys.stdout.write('scons-time version\n') - sys.exit(0) - - if not args: - sys.stderr.write('Type "%s help" for usage.\n' % ST.name) - sys.exit(1) - - ST.execute_subcommand(args) - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/scripts/scons-time.py b/scripts/scons-time.py new file mode 100644 index 0000000..6494349 --- /dev/null +++ b/scripts/scons-time.py @@ -0,0 +1,1480 @@ +#!/usr/bin/env python +# +# scons-time - run SCons timings and collect statistics +# +# A script for running a configuration through SCons with a standard +# set of invocations to collect timing and memory statistics and to +# capture the results in a consistent set of output files for display +# and analysis. +# + +# +# __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 getopt +import glob +import os +import re +import shutil +import sys +import tempfile +import time +import subprocess + +def HACK_for_exec(cmd, *args): + """ + For some reason, Python won't allow an exec() within a function + that also declares an internal function (including lambda functions). + This function is a hack that calls exec() in a function with no + internal functions. + """ + if not args: exec(cmd) + elif len(args) == 1: exec(cmd, args[0]) + else: exec(cmd, args[0], args[1]) + +class Plotter(object): + def increment_size(self, largest): + """ + Return the size of each horizontal increment line for a specified + maximum value. This returns a value that will provide somewhere + between 5 and 9 horizontal lines on the graph, on some set of + boundaries that are multiples of 10/100/1000/etc. + """ + i = largest // 5 + if not i: + return largest + multiplier = 1 + while i >= 10: + i = i // 10 + multiplier = multiplier * 10 + return i * multiplier + + def max_graph_value(self, largest): + # Round up to next integer. + largest = int(largest) + 1 + increment = self.increment_size(largest) + return ((largest + increment - 1) // increment) * increment + +class Line(object): + def __init__(self, points, type, title, label, comment, fmt="%s %s"): + self.points = points + self.type = type + self.title = title + self.label = label + self.comment = comment + self.fmt = fmt + + def print_label(self, inx, x, y): + if self.label: + print('set label %s "%s" at %0.1f,%0.1f right' % (inx, self.label, x, y)) + + def plot_string(self): + if self.title: + title_string = 'title "%s"' % self.title + else: + title_string = 'notitle' + return "'-' %s with lines lt %s" % (title_string, self.type) + + def print_points(self, fmt=None): + if fmt is None: + fmt = self.fmt + if self.comment: + print('# %s' % self.comment) + for x, y in self.points: + # If y is None, it usually represents some kind of break + # in the line's index number. We might want to represent + # this some way rather than just drawing the line straight + # between the two points on either side. + if y is not None: + print(fmt % (x, y)) + print('e') + + def get_x_values(self): + return [ p[0] for p in self.points ] + + def get_y_values(self): + return [ p[1] for p in self.points ] + +class Gnuplotter(Plotter): + + def __init__(self, title, key_location): + self.lines = [] + self.title = title + self.key_location = key_location + + def line(self, points, type, title=None, label=None, comment=None, fmt='%s %s'): + if points: + line = Line(points, type, title, label, comment, fmt) + self.lines.append(line) + + def plot_string(self, line): + return line.plot_string() + + def vertical_bar(self, x, type, label, comment): + if self.get_min_x() <= x <= self.get_max_x(): + points = [(x, 0), (x, self.max_graph_value(self.get_max_y()))] + self.line(points, type, label, comment) + + def get_all_x_values(self): + result = [] + for line in self.lines: + result.extend(line.get_x_values()) + return [r for r in result if r is not None] + + def get_all_y_values(self): + result = [] + for line in self.lines: + result.extend(line.get_y_values()) + return [r for r in result if r is not None] + + def get_min_x(self): + try: + return self.min_x + except AttributeError: + try: + self.min_x = min(self.get_all_x_values()) + except ValueError: + self.min_x = 0 + return self.min_x + + def get_max_x(self): + try: + return self.max_x + except AttributeError: + try: + self.max_x = max(self.get_all_x_values()) + except ValueError: + self.max_x = 0 + return self.max_x + + def get_min_y(self): + try: + return self.min_y + except AttributeError: + try: + self.min_y = min(self.get_all_y_values()) + except ValueError: + self.min_y = 0 + return self.min_y + + def get_max_y(self): + try: + return self.max_y + except AttributeError: + try: + self.max_y = max(self.get_all_y_values()) + except ValueError: + self.max_y = 0 + return self.max_y + + def draw(self): + + if not self.lines: + return + + if self.title: + print('set title "%s"' % self.title) + print('set key %s' % self.key_location) + + min_y = self.get_min_y() + max_y = self.max_graph_value(self.get_max_y()) + incr = (max_y - min_y) / 10.0 + start = min_y + (max_y / 2.0) + (2.0 * incr) + position = [ start - (i * incr) for i in range(5) ] + + inx = 1 + for line in self.lines: + line.print_label(inx, line.points[0][0]-1, + position[(inx-1) % len(position)]) + inx += 1 + + plot_strings = [ self.plot_string(l) for l in self.lines ] + print('plot ' + ', \\\n '.join(plot_strings)) + + for line in self.lines: + line.print_points() + + + +def untar(fname): + import tarfile + tar = tarfile.open(name=fname, mode='r') + for tarinfo in tar: + tar.extract(tarinfo) + tar.close() + +def unzip(fname): + import zipfile + zf = zipfile.ZipFile(fname, 'r') + for name in zf.namelist(): + dir = os.path.dirname(name) + try: + os.makedirs(dir) + except: + pass + with open(name, 'wb') as f: + f.write(zf.read(name)) + +def read_tree(dir): + for dirpath, dirnames, filenames in os.walk(dir): + for fn in filenames: + fn = os.path.join(dirpath, fn) + if os.path.isfile(fn): + with open(fn, 'rb') as f: + f.read() + +def redirect_to_file(command, log): + return '%s > %s 2>&1' % (command, log) + +def tee_to_file(command, log): + return '%s 2>&1 | tee %s' % (command, log) + + + +class SConsTimer(object): + """ + Usage: scons-time SUBCOMMAND [ARGUMENTS] + Type "scons-time help SUBCOMMAND" for help on a specific subcommand. + + Available subcommands: + func Extract test-run data for a function + help Provides help + mem Extract --debug=memory data from test runs + obj Extract --debug=count data from test runs + time Extract --debug=time data from test runs + run Runs a test configuration + """ + + name = 'scons-time' + name_spaces = ' '*len(name) + + def makedict(**kw): + return kw + + default_settings = makedict( + chdir = None, + config_file = None, + initial_commands = [], + key_location = 'bottom left', + orig_cwd = os.getcwd(), + outdir = None, + prefix = '', + python = '"%s"' % sys.executable, + redirect = redirect_to_file, + scons = None, + scons_flags = '--debug=count --debug=memory --debug=time --debug=memoizer', + scons_lib_dir = None, + scons_wrapper = None, + startup_targets = '--help', + subdir = None, + subversion_url = None, + svn = 'svn', + svn_co_flag = '-q', + tar = 'tar', + targets = '', + targets0 = None, + targets1 = None, + targets2 = None, + title = None, + unzip = 'unzip', + verbose = False, + vertical_bars = [], + + unpack_map = { + '.tar.gz' : (untar, '%(tar)s xzf %%s'), + '.tgz' : (untar, '%(tar)s xzf %%s'), + '.tar' : (untar, '%(tar)s xf %%s'), + '.zip' : (unzip, '%(unzip)s %%s'), + }, + ) + + run_titles = [ + 'Startup', + 'Full build', + 'Up-to-date build', + ] + + run_commands = [ + '%(python)s %(scons_wrapper)s %(scons_flags)s --profile=%(prof0)s %(targets0)s', + '%(python)s %(scons_wrapper)s %(scons_flags)s --profile=%(prof1)s %(targets1)s', + '%(python)s %(scons_wrapper)s %(scons_flags)s --profile=%(prof2)s %(targets2)s', + ] + + stages = [ + 'pre-read', + 'post-read', + 'pre-build', + 'post-build', + ] + + stage_strings = { + 'pre-read' : 'Memory before reading SConscript files:', + 'post-read' : 'Memory after reading SConscript files:', + 'pre-build' : 'Memory before building targets:', + 'post-build' : 'Memory after building targets:', + } + + memory_string_all = 'Memory ' + + default_stage = stages[-1] + + time_strings = { + 'total' : 'Total build time', + 'SConscripts' : 'Total SConscript file execution time', + 'SCons' : 'Total SCons execution time', + 'commands' : 'Total command execution time', + } + + time_string_all = 'Total .* time' + + # + + def __init__(self): + self.__dict__.update(self.default_settings) + + # Functions for displaying and executing commands. + + def subst(self, x, dictionary): + try: + return x % dictionary + except TypeError: + # x isn't a string (it's probably a Python function), + # so just return it. + return x + + def subst_variables(self, command, dictionary): + """ + Substitutes (via the format operator) the values in the specified + dictionary into the specified command. + + The command can be an (action, string) tuple. In all cases, we + perform substitution on strings and don't worry if something isn't + a string. (It's probably a Python function to be executed.) + """ + try: + command + '' + except TypeError: + action = command[0] + string = command[1] + args = command[2:] + else: + action = command + string = action + args = (()) + action = self.subst(action, dictionary) + string = self.subst(string, dictionary) + return (action, string, args) + + def _do_not_display(self, msg, *args): + pass + + def display(self, msg, *args): + """ + Displays the specified message. + + Each message is prepended with a standard prefix of our name + plus the time. + """ + if callable(msg): + msg = msg(*args) + else: + msg = msg % args + if msg is None: + return + fmt = '%s[%s]: %s\n' + sys.stdout.write(fmt % (self.name, time.strftime('%H:%M:%S'), msg)) + + def _do_not_execute(self, action, *args): + pass + + def execute(self, action, *args): + """ + Executes the specified action. + + The action is called if it's a callable Python function, and + otherwise passed to os.system(). + """ + if callable(action): + action(*args) + else: + os.system(action % args) + + def run_command_list(self, commands, dict): + """ + Executes a list of commands, substituting values from the + specified dictionary. + """ + commands = [ self.subst_variables(c, dict) for c in commands ] + for action, string, args in commands: + self.display(string, *args) + sys.stdout.flush() + status = self.execute(action, *args) + if status: + sys.exit(status) + + def log_display(self, command, log): + command = self.subst(command, self.__dict__) + if log: + command = self.redirect(command, log) + return command + + def log_execute(self, command, log): + command = self.subst(command, self.__dict__) + p = os.popen(command) + output = p.read() + p.close() + #TODO: convert to subrocess, os.popen is obsolete. This didn't work: + #process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True) + #output = process.stdout.read() + #process.stdout.close() + #process.wait() + if self.verbose: + sys.stdout.write(output) + # TODO: Figure out + # Not sure we need to write binary here + with open(log, 'w') as f: + f.write(str(output)) + + def archive_splitext(self, path): + """ + Splits an archive name into a filename base and extension. + + This is like os.path.splitext() (which it calls) except that it + also looks for '.tar.gz' and treats it as an atomic extensions. + """ + if path.endswith('.tar.gz'): + return path[:-7], path[-7:] + else: + return os.path.splitext(path) + + def args_to_files(self, args, tail=None): + """ + Takes a list of arguments, expands any glob patterns, and + returns the last "tail" files from the list. + """ + files = [] + for a in args: + files.extend(sorted(glob.glob(a))) + + if tail: + files = files[-tail:] + + return files + + def ascii_table(self, files, columns, + line_function, file_function=lambda x: x, + *args, **kw): + + header_fmt = ' '.join(['%12s'] * len(columns)) + line_fmt = header_fmt + ' %s' + + print(header_fmt % columns) + + for file in files: + t = line_function(file, *args, **kw) + if t is None: + t = [] + diff = len(columns) - len(t) + if diff > 0: + t += [''] * diff + t.append(file_function(file)) + print(line_fmt % tuple(t)) + + def collect_results(self, files, function, *args, **kw): + results = {} + + for file in files: + base = os.path.splitext(file)[0] + run, index = base.split('-')[-2:] + + run = int(run) + index = int(index) + + value = function(file, *args, **kw) + + try: + r = results[index] + except KeyError: + r = [] + results[index] = r + r.append((run, value)) + + return results + + def doc_to_help(self, obj): + """ + Translates an object's __doc__ string into help text. + + This strips a consistent number of spaces from each line in the + help text, essentially "outdenting" the text to the left-most + column. + """ + doc = obj.__doc__ + if doc is None: + return '' + return self.outdent(doc) + + def find_next_run_number(self, dir, prefix): + """ + Returns the next run number in a directory for the specified prefix. + + Examines the contents the specified directory for files with the + specified prefix, extracts the run numbers from each file name, + and returns the next run number after the largest it finds. + """ + x = re.compile(re.escape(prefix) + '-([0-9]+).*') + matches = [x.match(e) for e in os.listdir(dir)] + matches = [_f for _f in matches if _f] + if not matches: + return 0 + run_numbers = [int(m.group(1)) for m in matches] + return int(max(run_numbers)) + 1 + + def gnuplot_results(self, results, fmt='%s %.3f'): + """ + Prints out a set of results in Gnuplot format. + """ + gp = Gnuplotter(self.title, self.key_location) + + for i in sorted(results.keys()): + try: + t = self.run_titles[i] + except IndexError: + t = '??? %s ???' % i + results[i].sort() + gp.line(results[i], i+1, t, None, t, fmt=fmt) + + for bar_tuple in self.vertical_bars: + try: + x, type, label, comment = bar_tuple + except ValueError: + x, type, label = bar_tuple + comment = label + gp.vertical_bar(x, type, label, comment) + + gp.draw() + + def logfile_name(self, invocation): + """ + Returns the absolute path of a log file for the specificed + invocation number. + """ + name = self.prefix_run + '-%d.log' % invocation + return os.path.join(self.outdir, name) + + def outdent(self, s): + """ + Strip as many spaces from each line as are found at the beginning + of the first line in the list. + """ + lines = s.split('\n') + if lines[0] == '': + lines = lines[1:] + spaces = re.match(' *', lines[0]).group(0) + def strip_initial_spaces(l, s=spaces): + if l.startswith(spaces): + l = l[len(spaces):] + return l + return '\n'.join([ strip_initial_spaces(l) for l in lines ]) + '\n' + + def profile_name(self, invocation): + """ + Returns the absolute path of a profile file for the specified + invocation number. + """ + name = self.prefix_run + '-%d.prof' % invocation + return os.path.join(self.outdir, name) + + def set_env(self, key, value): + os.environ[key] = value + + # + + def get_debug_times(self, file, time_string=None): + """ + Fetch times from the --debug=time strings in the specified file. + """ + if time_string is None: + search_string = self.time_string_all + else: + search_string = time_string + with open(file) as f: + contents = f.read() + 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 = [ float(r) for r in result ] + if time_string is not None: + try: + result = result[0] + except IndexError: + sys.stderr.write('file %s has no results!\n' % repr(file)) + return None + return result + + def get_function_profile(self, file, function): + """ + Returns the file, line number, function name, and cumulative time. + """ + try: + import pstats + except ImportError as e: + sys.stderr.write('%s: func: %s\n' % (self.name, e)) + sys.stderr.write('%s This version of Python is missing the profiler.\n' % self.name_spaces) + sys.stderr.write('%s Cannot use the "func" subcommand.\n' % self.name_spaces) + sys.exit(1) + statistics = pstats.Stats(file).stats + matches = [ e for e in statistics.items() if e[0][2] == function ] + r = matches[0] + return r[0][0], r[0][1], r[0][2], r[1][3] + + def get_function_time(self, file, function): + """ + Returns just the cumulative time for the specified function. + """ + return self.get_function_profile(file, function)[3] + + def get_memory(self, file, memory_string=None): + """ + Returns a list of integers of the amount of memory used. The + default behavior is to return all the stages. + """ + if memory_string is None: + search_string = self.memory_string_all + else: + search_string = memory_string + with open(file) as f: + lines = f.readlines() + lines = [ l for l in lines if l.startswith(search_string) ][-4:] + result = [ int(l.split()[-1]) for l in lines[-4:] ] + if len(result) == 1: + result = result[0] + return result + + def get_object_counts(self, file, object_name, index=None): + """ + Returns the counts of the specified object_name. + """ + object_string = ' ' + object_name + '\n' + with open(file) as f: + lines = f.readlines() + line = [ l for l in lines if l.endswith(object_string) ][0] + result = [ int(field) for field in line.split()[:4] ] + if index is not None: + result = result[index] + return result + + + command_alias = {} + + def execute_subcommand(self, argv): + """ + Executes the do_*() function for the specified subcommand (argv[0]). + """ + if not argv: + return + cmdName = self.command_alias.get(argv[0], argv[0]) + try: + func = getattr(self, 'do_' + cmdName) + except AttributeError: + return self.default(argv) + try: + return func(argv) + except TypeError as e: + sys.stderr.write("%s %s: %s\n" % (self.name, cmdName, e)) + import traceback + traceback.print_exc(file=sys.stderr) + sys.stderr.write("Try '%s help %s'\n" % (self.name, cmdName)) + + def default(self, argv): + """ + The default behavior for an unknown subcommand. Prints an + error message and exits. + """ + sys.stderr.write('%s: Unknown subcommand "%s".\n' % (self.name, argv[0])) + sys.stderr.write('Type "%s help" for usage.\n' % self.name) + sys.exit(1) + + # + + def do_help(self, argv): + """ + """ + if argv[1:]: + for arg in argv[1:]: + try: + func = getattr(self, 'do_' + arg) + except AttributeError: + sys.stderr.write('%s: No help for "%s"\n' % (self.name, arg)) + else: + try: + help = getattr(self, 'help_' + arg) + except AttributeError: + sys.stdout.write(self.doc_to_help(func)) + sys.stdout.flush() + else: + help() + else: + doc = self.doc_to_help(self.__class__) + if doc: + sys.stdout.write(doc) + sys.stdout.flush() + return None + + # + + def help_func(self): + help = """\ + Usage: scons-time func [OPTIONS] FILE [...] + + -C DIR, --chdir=DIR Change to DIR before looking for files + -f FILE, --file=FILE Read configuration from specified FILE + --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT + --func=NAME, --function=NAME Report time for function NAME + -h, --help Print this help and exit + -p STRING, --prefix=STRING Use STRING as log file/profile prefix + -t NUMBER, --tail=NUMBER Only report the last NUMBER files + --title=TITLE Specify the output plot TITLE + """ + sys.stdout.write(self.outdent(help)) + sys.stdout.flush() + + def do_func(self, argv): + """ + """ + format = 'ascii' + function_name = '_main' + tail = None + + short_opts = '?C:f:hp:t:' + + long_opts = [ + 'chdir=', + 'file=', + 'fmt=', + 'format=', + 'func=', + 'function=', + 'help', + 'prefix=', + 'tail=', + 'title=', + ] + + opts, args = getopt.getopt(argv[1:], short_opts, long_opts) + + for o, a in opts: + if o in ('-C', '--chdir'): + self.chdir = a + elif o in ('-f', '--file'): + self.config_file = a + elif o in ('--fmt', '--format'): + format = a + elif o in ('--func', '--function'): + function_name = a + elif o in ('-?', '-h', '--help'): + self.do_help(['help', 'func']) + sys.exit(0) + elif o in ('--max',): + max_time = int(a) + elif o in ('-p', '--prefix'): + self.prefix = a + elif o in ('-t', '--tail'): + tail = int(a) + elif o in ('--title',): + self.title = a + + if self.config_file: + with open(self.config_file, 'r') as f: + config = f.read() + exec(config, self.__dict__) + + if self.chdir: + os.chdir(self.chdir) + + if not args: + + pattern = '%s*.prof' % self.prefix + args = self.args_to_files([pattern], tail) + + if not args: + if self.chdir: + directory = self.chdir + else: + directory = os.getcwd() + + sys.stderr.write('%s: func: No arguments specified.\n' % self.name) + sys.stderr.write('%s No %s*.prof files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) + sys.stderr.write('%s Type "%s help func" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + + else: + + args = self.args_to_files(args, tail) + + cwd_ = os.getcwd() + os.sep + + if format == 'ascii': + + for file in args: + try: + f, line, func, time = \ + self.get_function_profile(file, function_name) + except ValueError as e: + sys.stderr.write("%s: func: %s: %s\n" % + (self.name, file, e)) + else: + if f.startswith(cwd_): + f = f[len(cwd_):] + print("%.3f %s:%d(%s)" % (time, f, line, func)) + + elif format == 'gnuplot': + + results = self.collect_results(args, self.get_function_time, + function_name) + + self.gnuplot_results(results) + + else: + + sys.stderr.write('%s: func: Unknown format "%s".\n' % (self.name, format)) + sys.exit(1) + + # + + def help_mem(self): + help = """\ + Usage: scons-time mem [OPTIONS] FILE [...] + + -C DIR, --chdir=DIR Change to DIR before looking for files + -f FILE, --file=FILE Read configuration from specified FILE + --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT + -h, --help Print this help and exit + -p STRING, --prefix=STRING Use STRING as log file/profile prefix + --stage=STAGE Plot memory at the specified stage: + pre-read, post-read, pre-build, + post-build (default: post-build) + -t NUMBER, --tail=NUMBER Only report the last NUMBER files + --title=TITLE Specify the output plot TITLE + """ + sys.stdout.write(self.outdent(help)) + sys.stdout.flush() + + def do_mem(self, argv): + + format = 'ascii' + logfile_path = lambda x: x + stage = self.default_stage + tail = None + + short_opts = '?C:f:hp:t:' + + long_opts = [ + 'chdir=', + 'file=', + 'fmt=', + 'format=', + 'help', + 'prefix=', + 'stage=', + 'tail=', + 'title=', + ] + + opts, args = getopt.getopt(argv[1:], short_opts, long_opts) + + for o, a in opts: + if o in ('-C', '--chdir'): + self.chdir = a + elif o in ('-f', '--file'): + self.config_file = a + elif o in ('--fmt', '--format'): + format = a + elif o in ('-?', '-h', '--help'): + self.do_help(['help', 'mem']) + sys.exit(0) + elif o in ('-p', '--prefix'): + self.prefix = a + elif o in ('--stage',): + if a not in self.stages: + sys.stderr.write('%s: mem: Unrecognized stage "%s".\n' % (self.name, a)) + sys.exit(1) + stage = a + elif o in ('-t', '--tail'): + tail = int(a) + elif o in ('--title',): + self.title = a + + if self.config_file: + with open(self.config_file, 'r') as f: + config = f.read() + HACK_for_exec(config, self.__dict__) + + if self.chdir: + os.chdir(self.chdir) + logfile_path = lambda x: os.path.join(self.chdir, x) + + if not args: + + pattern = '%s*.log' % self.prefix + args = self.args_to_files([pattern], tail) + + if not args: + if self.chdir: + directory = self.chdir + else: + directory = os.getcwd() + + sys.stderr.write('%s: mem: No arguments specified.\n' % self.name) + sys.stderr.write('%s No %s*.log files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) + sys.stderr.write('%s Type "%s help mem" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + + else: + + args = self.args_to_files(args, tail) + + cwd_ = os.getcwd() + os.sep + + if format == 'ascii': + + self.ascii_table(args, tuple(self.stages), self.get_memory, logfile_path) + + elif format == 'gnuplot': + + results = self.collect_results(args, self.get_memory, + self.stage_strings[stage]) + + self.gnuplot_results(results) + + else: + + sys.stderr.write('%s: mem: Unknown format "%s".\n' % (self.name, format)) + sys.exit(1) + + return 0 + + # + + def help_obj(self): + help = """\ + Usage: scons-time obj [OPTIONS] OBJECT FILE [...] + + -C DIR, --chdir=DIR Change to DIR before looking for files + -f FILE, --file=FILE Read configuration from specified FILE + --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT + -h, --help Print this help and exit + -p STRING, --prefix=STRING Use STRING as log file/profile prefix + --stage=STAGE Plot memory at the specified stage: + pre-read, post-read, pre-build, + post-build (default: post-build) + -t NUMBER, --tail=NUMBER Only report the last NUMBER files + --title=TITLE Specify the output plot TITLE + """ + sys.stdout.write(self.outdent(help)) + sys.stdout.flush() + + def do_obj(self, argv): + + format = 'ascii' + logfile_path = lambda x: x + stage = self.default_stage + tail = None + + short_opts = '?C:f:hp:t:' + + long_opts = [ + 'chdir=', + 'file=', + 'fmt=', + 'format=', + 'help', + 'prefix=', + 'stage=', + 'tail=', + 'title=', + ] + + opts, args = getopt.getopt(argv[1:], short_opts, long_opts) + + for o, a in opts: + if o in ('-C', '--chdir'): + self.chdir = a + elif o in ('-f', '--file'): + self.config_file = a + elif o in ('--fmt', '--format'): + format = a + elif o in ('-?', '-h', '--help'): + self.do_help(['help', 'obj']) + sys.exit(0) + elif o in ('-p', '--prefix'): + self.prefix = a + elif o in ('--stage',): + if a not in self.stages: + sys.stderr.write('%s: obj: Unrecognized stage "%s".\n' % (self.name, a)) + sys.stderr.write('%s Type "%s help obj" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + stage = a + elif o in ('-t', '--tail'): + tail = int(a) + elif o in ('--title',): + self.title = a + + if not args: + sys.stderr.write('%s: obj: Must specify an object name.\n' % self.name) + sys.stderr.write('%s Type "%s help obj" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + + object_name = args.pop(0) + + if self.config_file: + with open(self.config_file, 'r') as f: + config = f.read() + HACK_for_exec(config, self.__dict__) + + if self.chdir: + os.chdir(self.chdir) + logfile_path = lambda x: os.path.join(self.chdir, x) + + if not args: + + pattern = '%s*.log' % self.prefix + args = self.args_to_files([pattern], tail) + + if not args: + if self.chdir: + directory = self.chdir + else: + directory = os.getcwd() + + sys.stderr.write('%s: obj: No arguments specified.\n' % self.name) + sys.stderr.write('%s No %s*.log files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) + sys.stderr.write('%s Type "%s help obj" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + + else: + + args = self.args_to_files(args, tail) + + cwd_ = os.getcwd() + os.sep + + if format == 'ascii': + + self.ascii_table(args, tuple(self.stages), self.get_object_counts, logfile_path, object_name) + + elif format == 'gnuplot': + + stage_index = 0 + for s in self.stages: + if stage == s: + break + stage_index = stage_index + 1 + + results = self.collect_results(args, self.get_object_counts, + object_name, stage_index) + + self.gnuplot_results(results) + + else: + + sys.stderr.write('%s: obj: Unknown format "%s".\n' % (self.name, format)) + sys.exit(1) + + return 0 + + # + + def help_run(self): + help = """\ + Usage: scons-time run [OPTIONS] [FILE ...] + + --chdir=DIR Name of unpacked directory for chdir + -f FILE, --file=FILE Read configuration from specified FILE + -h, --help Print this help and exit + -n, --no-exec No execute, just print command lines + --number=NUMBER Put output in files for run NUMBER + --outdir=OUTDIR Put output files in OUTDIR + -p STRING, --prefix=STRING Use STRING as log file/profile prefix + --python=PYTHON Time using the specified PYTHON + -q, --quiet Don't print command lines + --scons=SCONS Time using the specified SCONS + --svn=URL, --subversion=URL Use SCons from Subversion URL + -v, --verbose Display output of commands + """ + sys.stdout.write(self.outdent(help)) + sys.stdout.flush() + + def do_run(self, argv): + """ + """ + run_number_list = [None] + + short_opts = '?f:hnp:qs:v' + + long_opts = [ + 'file=', + 'help', + 'no-exec', + 'number=', + 'outdir=', + 'prefix=', + 'python=', + 'quiet', + 'scons=', + 'svn=', + 'subdir=', + 'subversion=', + 'verbose', + ] + + opts, args = getopt.getopt(argv[1:], short_opts, long_opts) + + for o, a in opts: + if o in ('-f', '--file'): + self.config_file = a + elif o in ('-?', '-h', '--help'): + self.do_help(['help', 'run']) + sys.exit(0) + elif o in ('-n', '--no-exec'): + self.execute = self._do_not_execute + elif o in ('--number',): + run_number_list = self.split_run_numbers(a) + elif o in ('--outdir',): + self.outdir = a + elif o in ('-p', '--prefix'): + self.prefix = a + elif o in ('--python',): + self.python = a + elif o in ('-q', '--quiet'): + self.display = self._do_not_display + elif o in ('-s', '--subdir'): + self.subdir = a + elif o in ('--scons',): + self.scons = a + elif o in ('--svn', '--subversion'): + self.subversion_url = a + elif o in ('-v', '--verbose'): + self.redirect = tee_to_file + self.verbose = True + self.svn_co_flag = '' + + if not args and not self.config_file: + sys.stderr.write('%s: run: No arguments or -f config file specified.\n' % self.name) + sys.stderr.write('%s Type "%s help run" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + + if self.config_file: + with open(self.config_file, 'r') as f: + config = f.read() + exec(config, self.__dict__) + + if args: + self.archive_list = args + + archive_file_name = os.path.split(self.archive_list[0])[1] + + if not self.subdir: + self.subdir = self.archive_splitext(archive_file_name)[0] + + if not self.prefix: + self.prefix = self.archive_splitext(archive_file_name)[0] + + prepare = None + if self.subversion_url: + prepare = self.prep_subversion_run + + for run_number in run_number_list: + self.individual_run(run_number, self.archive_list, prepare) + + def split_run_numbers(self, s): + result = [] + for n in s.split(','): + try: + x, y = n.split('-') + except ValueError: + result.append(int(n)) + else: + result.extend(list(range(int(x), int(y)+1))) + return result + + def scons_path(self, dir): + return os.path.join(dir,'scripts', 'scons.py') + + def scons_lib_dir_path(self, dir): + return os.path.join(dir, 'src', 'engine') + + def prep_subversion_run(self, commands, removals): + self.svn_tmpdir = tempfile.mkdtemp(prefix=self.name + '-svn-') + removals.append((shutil.rmtree, 'rm -rf %%s', self.svn_tmpdir)) + + self.scons = self.scons_path(self.svn_tmpdir) + self.scons_lib_dir = self.scons_lib_dir_path(self.svn_tmpdir) + + commands.extend([ + '%(svn)s co %(svn_co_flag)s -r %(run_number)s %(subversion_url)s %(svn_tmpdir)s', + ]) + + def individual_run(self, run_number, archive_list, prepare=None): + """ + Performs an individual run of the default SCons invocations. + """ + + commands = [] + removals = [] + + if prepare: + prepare(commands, removals) + + save_scons = self.scons + save_scons_wrapper = self.scons_wrapper + save_scons_lib_dir = self.scons_lib_dir + + if self.outdir is None: + self.outdir = self.orig_cwd + elif not os.path.isabs(self.outdir): + self.outdir = os.path.join(self.orig_cwd, self.outdir) + + if self.scons is None: + self.scons = self.scons_path(self.orig_cwd) + + if self.scons_lib_dir is None: + self.scons_lib_dir = self.scons_lib_dir_path(self.orig_cwd) + + if self.scons_wrapper is None: + self.scons_wrapper = self.scons + + if not run_number: + run_number = self.find_next_run_number(self.outdir, self.prefix) + + self.run_number = str(run_number) + + self.prefix_run = self.prefix + '-%03d' % run_number + + if self.targets0 is None: + self.targets0 = self.startup_targets + if self.targets1 is None: + self.targets1 = self.targets + if self.targets2 is None: + self.targets2 = self.targets + + self.tmpdir = tempfile.mkdtemp(prefix=self.name + '-') + + commands.extend([ + (os.chdir, 'cd %%s', self.tmpdir), + ]) + + for archive in archive_list: + if not os.path.isabs(archive): + archive = os.path.join(self.orig_cwd, archive) + if os.path.isdir(archive): + dest = os.path.split(archive)[1] + commands.append((shutil.copytree, 'cp -r %%s %%s', archive, dest)) + else: + suffix = self.archive_splitext(archive)[1] + unpack_command = self.unpack_map.get(suffix) + if not unpack_command: + dest = os.path.split(archive)[1] + commands.append((shutil.copyfile, 'cp %%s %%s', archive, dest)) + else: + commands.append(unpack_command + (archive,)) + + commands.extend([ + (os.chdir, 'cd %%s', self.subdir), + ]) + + commands.extend(self.initial_commands) + + commands.extend([ + (lambda: read_tree('.'), + 'find * -type f | xargs cat > /dev/null'), + + (self.set_env, 'export %%s=%%s', + 'SCONS_LIB_DIR', self.scons_lib_dir), + + '%(python)s %(scons_wrapper)s --version', + ]) + + index = 0 + for run_command in self.run_commands: + setattr(self, 'prof%d' % index, self.profile_name(index)) + c = ( + self.log_execute, + self.log_display, + run_command, + self.logfile_name(index), + ) + commands.append(c) + index = index + 1 + + commands.extend([ + (os.chdir, 'cd %%s', self.orig_cwd), + ]) + + if not os.environ.get('PRESERVE'): + commands.extend(removals) + commands.append((shutil.rmtree, 'rm -rf %%s', self.tmpdir)) + + self.run_command_list(commands, self.__dict__) + + self.scons = save_scons + self.scons_lib_dir = save_scons_lib_dir + self.scons_wrapper = save_scons_wrapper + + # + + def help_time(self): + help = """\ + Usage: scons-time time [OPTIONS] FILE [...] + + -C DIR, --chdir=DIR Change to DIR before looking for files + -f FILE, --file=FILE Read configuration from specified FILE + --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT + -h, --help Print this help and exit + -p STRING, --prefix=STRING Use STRING as log file/profile prefix + -t NUMBER, --tail=NUMBER Only report the last NUMBER files + --which=TIMER Plot timings for TIMER: total, + SConscripts, SCons, commands. + """ + sys.stdout.write(self.outdent(help)) + sys.stdout.flush() + + def do_time(self, argv): + + format = 'ascii' + logfile_path = lambda x: x + tail = None + which = 'total' + + short_opts = '?C:f:hp:t:' + + long_opts = [ + 'chdir=', + 'file=', + 'fmt=', + 'format=', + 'help', + 'prefix=', + 'tail=', + 'title=', + 'which=', + ] + + opts, args = getopt.getopt(argv[1:], short_opts, long_opts) + + for o, a in opts: + if o in ('-C', '--chdir'): + self.chdir = a + elif o in ('-f', '--file'): + self.config_file = a + elif o in ('--fmt', '--format'): + format = a + elif o in ('-?', '-h', '--help'): + self.do_help(['help', 'time']) + sys.exit(0) + elif o in ('-p', '--prefix'): + self.prefix = a + elif o in ('-t', '--tail'): + tail = int(a) + elif o in ('--title',): + self.title = a + elif o in ('--which',): + if a not in list(self.time_strings.keys()): + sys.stderr.write('%s: time: Unrecognized timer "%s".\n' % (self.name, a)) + sys.stderr.write('%s Type "%s help time" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + which = a + + if self.config_file: + with open(self.config_file, 'r') as f: + config = f.read() + HACK_for_exec(config, self.__dict__) + + if self.chdir: + os.chdir(self.chdir) + logfile_path = lambda x: os.path.join(self.chdir, x) + + if not args: + + pattern = '%s*.log' % self.prefix + args = self.args_to_files([pattern], tail) + + if not args: + if self.chdir: + directory = self.chdir + else: + directory = os.getcwd() + + sys.stderr.write('%s: time: No arguments specified.\n' % self.name) + sys.stderr.write('%s No %s*.log files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) + sys.stderr.write('%s Type "%s help time" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + + else: + + args = self.args_to_files(args, tail) + + cwd_ = os.getcwd() + os.sep + + if format == 'ascii': + + columns = ("Total", "SConscripts", "SCons", "commands") + self.ascii_table(args, columns, self.get_debug_times, logfile_path) + + elif format == 'gnuplot': + + results = self.collect_results(args, self.get_debug_times, + self.time_strings[which]) + + self.gnuplot_results(results, fmt='%s %.6f') + + else: + + sys.stderr.write('%s: time: Unknown format "%s".\n' % (self.name, format)) + sys.exit(1) + +if __name__ == '__main__': + opts, args = getopt.getopt(sys.argv[1:], 'h?V', ['help', 'version']) + + ST = SConsTimer() + + for o, a in opts: + if o in ('-?', '-h', '--help'): + ST.do_help(['help']) + sys.exit(0) + elif o in ('-V', '--version'): + sys.stdout.write('scons-time version\n') + sys.exit(0) + + if not args: + sys.stderr.write('Type "%s help" for usage.\n' % ST.name) + sys.exit(1) + + ST.execute_subcommand(args) + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/scons-time/run/archive/dir.py b/test/scons-time/run/archive/dir.py index 590d568..6b6d992 100644 --- a/test/scons-time/run/archive/dir.py +++ b/test/scons-time/run/archive/dir.py @@ -32,6 +32,7 @@ directory tree. import TestSCons_time test = TestSCons_time.TestSCons_time() +test.verbose_set(1) test.write_fake_scons_py() diff --git a/test/scons-time/run/config/targets.py b/test/scons-time/run/config/targets.py index 482a44d..1712b32 100644 --- a/test/scons-time/run/config/targets.py +++ b/test/scons-time/run/config/targets.py @@ -45,7 +45,7 @@ targets = 'target1 target2' test.run(arguments = 'run -f config foo.tar.gz') -scons_py = re.escape(test.workpath('src', 'script', 'scons.py')) +scons_py = re.escape(test.workpath('scripts', 'scons.py')) src_engine = re.escape(test.workpath('src', 'engine')) prof1 = re.escape(test.workpath('foo-000-1.prof')) diff --git a/test/scons-time/run/option/quiet.py b/test/scons-time/run/option/quiet.py index 2910e8e..0f6c22b 100644 --- a/test/scons-time/run/option/quiet.py +++ b/test/scons-time/run/option/quiet.py @@ -37,7 +37,7 @@ python = TestSCons_time.python test = TestSCons_time.TestSCons_time(match = TestSCons_time.match_re, diff = TestSCons_time.diff_re) -scons_py = re.escape(test.workpath('src', 'script', 'scons.py')) +scons_py = re.escape(test.workpath('scripts', 'scons.py')) src_engine = re.escape(test.workpath('src', 'engine')) tmp_scons_time = test.tempdir_re() diff --git a/test/scons-time/run/option/verbose.py b/test/scons-time/run/option/verbose.py index 6f8f72f..9c4e7e8 100644 --- a/test/scons-time/run/option/verbose.py +++ b/test/scons-time/run/option/verbose.py @@ -39,7 +39,7 @@ _python_ = re.escape('"' + sys.executable + '"') test = TestSCons_time.TestSCons_time(match = TestSCons_time.match_re, diff = TestSCons_time.diff_re) -scons_py = re.escape(test.workpath('src', 'script', 'scons.py')) +scons_py = re.escape(test.workpath('scripts', 'scons.py')) src_engine = re.escape(test.workpath('src', 'engine')) tmp_scons_time = test.tempdir_re() diff --git a/test/scons-time/run/subversion.py b/test/scons-time/run/subversion.py deleted file mode 100644 index f895760..0000000 --- a/test/scons-time/run/subversion.py +++ /dev/null @@ -1,81 +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 ability to "check out" an SCons revision from a fake -Subversion utility. -""" - -import re -import tempfile - -import TestSCons_time - -test = TestSCons_time.TestSCons_time() - -test.write_sample_project('foo.tar') - -_python_ = TestSCons_time._python_ -my_svn_py = test.write_fake_svn_py('my_svn.py') - -test.write('config', """\ -svn = r'%(_python_)s %(my_svn_py)s' -""" % locals()) - -test.run(arguments = 'run -f config --svn http://xyzzy --number 617,716 foo.tar') - -test.must_exist('foo-617-0.log', - 'foo-617-0.prof', - 'foo-617-1.log', - 'foo-617-1.prof', - 'foo-617-2.log', - 'foo-617-2.prof') - -test.must_exist('foo-716-0.log', - 'foo-716-0.prof', - 'foo-716-1.log', - 'foo-716-1.prof', - 'foo-716-2.log', - 'foo-716-2.prof') - -expect = [ - test.tempdir_re('src', 'script', 'scons.py'), - 'SCONS_LIB_DIR = %s' % test.tempdir_re('src', 'engine'), -] - -content = test.read(test.workpath('foo-617-2.log'), mode='r') - -def re_find(content, line): - return re.search(line, content) -test.must_contain_all_lines(content, expect, 'foo-617-2.log', re_find) - -test.pass_test() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/testing/framework/TestSCons_time.py b/testing/framework/TestSCons_time.py index 6f46e26..c6373eb 100644 --- a/testing/framework/TestSCons_time.py +++ b/testing/framework/TestSCons_time.py @@ -60,7 +60,7 @@ import os import sys dir = sys.argv[-1] -script_dir = dir + '/src/script' +script_dir = dir + '/scripts' os.makedirs(script_dir) with open(script_dir + '/scons.py', 'w') as f: f.write(r'''%s''') @@ -73,7 +73,7 @@ import os import sys dir = sys.argv[-1] -script_dir = dir + '/src/script' +script_dir = dir + '/scripts' os.makedirs(script_dir) with open(script_dir + '/scons.py', 'w') as f: f.write(r'''%s''') @@ -230,8 +230,8 @@ class TestSCons_time(TestCommon): return x def write_fake_scons_py(self): - self.subdir('src', ['src', 'script']) - self.write('src/script/scons.py', scons_py) + self.subdir('scripts') + self.write('scripts/scons.py', scons_py) def write_fake_svn_py(self, name): name = self.workpath(name) -- cgit v0.12 From 5e8c9536ec9f76901fcc02cc716fd9ccf2d9aaa5 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 21 Mar 2020 19:50:04 -0700 Subject: Fix sconsign tests and script --- src/engine/SCons/Utilities/sconsign.py | 49 +++------------------------------- test/sconsign/script/SConsignFile.py | 1 - 2 files changed, 4 insertions(+), 46 deletions(-) diff --git a/src/engine/SCons/Utilities/sconsign.py b/src/engine/SCons/Utilities/sconsign.py index 819b9f7..8b16b18 100644 --- a/src/engine/SCons/Utilities/sconsign.py +++ b/src/engine/SCons/Utilities/sconsign.py @@ -43,50 +43,6 @@ from dbm import whichdb import time import pickle -# python compatibility check -if sys.version_info < (3, 5, 0): - msg = "scons: *** SCons version %s does not run under Python version %s.\n\ -Python >= 3.5 is required.\n" - sys.stderr.write(msg % (__version__, sys.version.split()[0])) - sys.exit(1) - -# Strip the script directory from sys.path so on case-insensitive -# (WIN32) systems Python doesn't think that the "scons" script is the -# "SCons" package. -script_dir = os.path.dirname(os.path.realpath(__file__)) -script_path = os.path.realpath(os.path.dirname(__file__)) -if script_path in sys.path: - sys.path.remove(script_path) - -libs = [] - -if "SCONS_LIB_DIR" in os.environ: - libs.append(os.environ["SCONS_LIB_DIR"]) - -# running from source takes 2nd priority (since 2.3.2), following SCONS_LIB_DIR -source_path = os.path.join(script_path, os.pardir, 'src', 'engine') -if os.path.isdir(source_path): - libs.append(source_path) - -# add local-install locations -local_version = 'scons-local-' + __version__ -local = 'scons-local' -if script_dir: - local_version = os.path.join(script_dir, local_version) - local = os.path.join(script_dir, local) -if os.path.isdir(local_version): - libs.append(os.path.abspath(local_version)) -if os.path.isdir(local): - libs.append(os.path.abspath(local)) - -scons_version = 'scons-%s' % __version__ - -sys.path = libs + sys.path - -############################################################################## -# END STANDARD SCons SCRIPT HEADER -############################################################################## - import SCons.compat import SCons.SConsign @@ -429,6 +385,10 @@ def Do_SConsignDir(name): ############################################################################## def main(): global Do_Call + global nodeinfo_string + global args + global Verbose + global Readable helpstr = """\ Usage: sconsign [OPTIONS] [FILE ...] @@ -536,7 +496,6 @@ def main(): print("NOTE: there were %d warnings, please check output" % Warns) - if __name__ == "__main__": main() sys.exit(0) diff --git a/test/sconsign/script/SConsignFile.py b/test/sconsign/script/SConsignFile.py index 8055b68..cd82fac 100644 --- a/test/sconsign/script/SConsignFile.py +++ b/test/sconsign/script/SConsignFile.py @@ -36,7 +36,6 @@ import TestSConsign _python_ = TestSCons._python_ test = TestSConsign.TestSConsign(match = TestSConsign.match_re) - test.subdir('sub1', 'sub2') fake_cc_py = test.workpath('fake_cc.py') -- cgit v0.12 From d3acf86b170be29de6b0328b063f5451e1f7e917 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 21 Mar 2020 20:05:46 -0700 Subject: Fix tests. IMPLICIT_COMMAND_DEPENDENCIES=all needs to be quoted --- test/Repository/Program.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Repository/Program.py b/test/Repository/Program.py index 1af3578..3946d95 100644 --- a/test/Repository/Program.py +++ b/test/Repository/Program.py @@ -32,7 +32,7 @@ if sys.platform == 'win32': else: _exe = '' -for implicit_deps in ['0', '1', '"all"']: +for implicit_deps in ['0', '1', '2', '\"all\"']: # First, test a single repository. test = TestSCons.TestSCons() test.subdir('repository', 'work1') -- cgit v0.12 From e9fa3ea7c3e57feded1d200b88650629cccae885 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 21 Mar 2020 20:02:33 -0700 Subject: Fix test --- test/packaging/rpm/explicit-target.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/packaging/rpm/explicit-target.py b/test/packaging/rpm/explicit-target.py index fba0237..0cf486e 100644 --- a/test/packaging/rpm/explicit-target.py +++ b/test/packaging/rpm/explicit-target.py @@ -77,7 +77,7 @@ env.Package( NAME = 'foo', expect = """ scons: *** Setting target is not supported for rpm. -""" + test.python_file_line(test.workpath('SConstruct'), 23) +""" + test.python_file_line(test.workpath('SConstruct'), 12) test.run(arguments='', status=2, stderr=expect) -- cgit v0.12 From 269341a2cc10c1a789d21232ce94ad2b1fceab25 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 22 Mar 2020 12:44:08 -0700 Subject: drop runntest.py's run from packages. define SCONS_TOOLS_DIR and use that for scons-time tests --- bin/scons-time.py | 1480 +++++++++++++++++++++++++++++++++++ runtest.py | 116 +-- scripts/scons-time.py | 1480 ----------------------------------- testing/framework/TestSCons_time.py | 4 +- 4 files changed, 1519 insertions(+), 1561 deletions(-) create mode 100644 bin/scons-time.py delete mode 100644 scripts/scons-time.py diff --git a/bin/scons-time.py b/bin/scons-time.py new file mode 100644 index 0000000..6494349 --- /dev/null +++ b/bin/scons-time.py @@ -0,0 +1,1480 @@ +#!/usr/bin/env python +# +# scons-time - run SCons timings and collect statistics +# +# A script for running a configuration through SCons with a standard +# set of invocations to collect timing and memory statistics and to +# capture the results in a consistent set of output files for display +# and analysis. +# + +# +# __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 getopt +import glob +import os +import re +import shutil +import sys +import tempfile +import time +import subprocess + +def HACK_for_exec(cmd, *args): + """ + For some reason, Python won't allow an exec() within a function + that also declares an internal function (including lambda functions). + This function is a hack that calls exec() in a function with no + internal functions. + """ + if not args: exec(cmd) + elif len(args) == 1: exec(cmd, args[0]) + else: exec(cmd, args[0], args[1]) + +class Plotter(object): + def increment_size(self, largest): + """ + Return the size of each horizontal increment line for a specified + maximum value. This returns a value that will provide somewhere + between 5 and 9 horizontal lines on the graph, on some set of + boundaries that are multiples of 10/100/1000/etc. + """ + i = largest // 5 + if not i: + return largest + multiplier = 1 + while i >= 10: + i = i // 10 + multiplier = multiplier * 10 + return i * multiplier + + def max_graph_value(self, largest): + # Round up to next integer. + largest = int(largest) + 1 + increment = self.increment_size(largest) + return ((largest + increment - 1) // increment) * increment + +class Line(object): + def __init__(self, points, type, title, label, comment, fmt="%s %s"): + self.points = points + self.type = type + self.title = title + self.label = label + self.comment = comment + self.fmt = fmt + + def print_label(self, inx, x, y): + if self.label: + print('set label %s "%s" at %0.1f,%0.1f right' % (inx, self.label, x, y)) + + def plot_string(self): + if self.title: + title_string = 'title "%s"' % self.title + else: + title_string = 'notitle' + return "'-' %s with lines lt %s" % (title_string, self.type) + + def print_points(self, fmt=None): + if fmt is None: + fmt = self.fmt + if self.comment: + print('# %s' % self.comment) + for x, y in self.points: + # If y is None, it usually represents some kind of break + # in the line's index number. We might want to represent + # this some way rather than just drawing the line straight + # between the two points on either side. + if y is not None: + print(fmt % (x, y)) + print('e') + + def get_x_values(self): + return [ p[0] for p in self.points ] + + def get_y_values(self): + return [ p[1] for p in self.points ] + +class Gnuplotter(Plotter): + + def __init__(self, title, key_location): + self.lines = [] + self.title = title + self.key_location = key_location + + def line(self, points, type, title=None, label=None, comment=None, fmt='%s %s'): + if points: + line = Line(points, type, title, label, comment, fmt) + self.lines.append(line) + + def plot_string(self, line): + return line.plot_string() + + def vertical_bar(self, x, type, label, comment): + if self.get_min_x() <= x <= self.get_max_x(): + points = [(x, 0), (x, self.max_graph_value(self.get_max_y()))] + self.line(points, type, label, comment) + + def get_all_x_values(self): + result = [] + for line in self.lines: + result.extend(line.get_x_values()) + return [r for r in result if r is not None] + + def get_all_y_values(self): + result = [] + for line in self.lines: + result.extend(line.get_y_values()) + return [r for r in result if r is not None] + + def get_min_x(self): + try: + return self.min_x + except AttributeError: + try: + self.min_x = min(self.get_all_x_values()) + except ValueError: + self.min_x = 0 + return self.min_x + + def get_max_x(self): + try: + return self.max_x + except AttributeError: + try: + self.max_x = max(self.get_all_x_values()) + except ValueError: + self.max_x = 0 + return self.max_x + + def get_min_y(self): + try: + return self.min_y + except AttributeError: + try: + self.min_y = min(self.get_all_y_values()) + except ValueError: + self.min_y = 0 + return self.min_y + + def get_max_y(self): + try: + return self.max_y + except AttributeError: + try: + self.max_y = max(self.get_all_y_values()) + except ValueError: + self.max_y = 0 + return self.max_y + + def draw(self): + + if not self.lines: + return + + if self.title: + print('set title "%s"' % self.title) + print('set key %s' % self.key_location) + + min_y = self.get_min_y() + max_y = self.max_graph_value(self.get_max_y()) + incr = (max_y - min_y) / 10.0 + start = min_y + (max_y / 2.0) + (2.0 * incr) + position = [ start - (i * incr) for i in range(5) ] + + inx = 1 + for line in self.lines: + line.print_label(inx, line.points[0][0]-1, + position[(inx-1) % len(position)]) + inx += 1 + + plot_strings = [ self.plot_string(l) for l in self.lines ] + print('plot ' + ', \\\n '.join(plot_strings)) + + for line in self.lines: + line.print_points() + + + +def untar(fname): + import tarfile + tar = tarfile.open(name=fname, mode='r') + for tarinfo in tar: + tar.extract(tarinfo) + tar.close() + +def unzip(fname): + import zipfile + zf = zipfile.ZipFile(fname, 'r') + for name in zf.namelist(): + dir = os.path.dirname(name) + try: + os.makedirs(dir) + except: + pass + with open(name, 'wb') as f: + f.write(zf.read(name)) + +def read_tree(dir): + for dirpath, dirnames, filenames in os.walk(dir): + for fn in filenames: + fn = os.path.join(dirpath, fn) + if os.path.isfile(fn): + with open(fn, 'rb') as f: + f.read() + +def redirect_to_file(command, log): + return '%s > %s 2>&1' % (command, log) + +def tee_to_file(command, log): + return '%s 2>&1 | tee %s' % (command, log) + + + +class SConsTimer(object): + """ + Usage: scons-time SUBCOMMAND [ARGUMENTS] + Type "scons-time help SUBCOMMAND" for help on a specific subcommand. + + Available subcommands: + func Extract test-run data for a function + help Provides help + mem Extract --debug=memory data from test runs + obj Extract --debug=count data from test runs + time Extract --debug=time data from test runs + run Runs a test configuration + """ + + name = 'scons-time' + name_spaces = ' '*len(name) + + def makedict(**kw): + return kw + + default_settings = makedict( + chdir = None, + config_file = None, + initial_commands = [], + key_location = 'bottom left', + orig_cwd = os.getcwd(), + outdir = None, + prefix = '', + python = '"%s"' % sys.executable, + redirect = redirect_to_file, + scons = None, + scons_flags = '--debug=count --debug=memory --debug=time --debug=memoizer', + scons_lib_dir = None, + scons_wrapper = None, + startup_targets = '--help', + subdir = None, + subversion_url = None, + svn = 'svn', + svn_co_flag = '-q', + tar = 'tar', + targets = '', + targets0 = None, + targets1 = None, + targets2 = None, + title = None, + unzip = 'unzip', + verbose = False, + vertical_bars = [], + + unpack_map = { + '.tar.gz' : (untar, '%(tar)s xzf %%s'), + '.tgz' : (untar, '%(tar)s xzf %%s'), + '.tar' : (untar, '%(tar)s xf %%s'), + '.zip' : (unzip, '%(unzip)s %%s'), + }, + ) + + run_titles = [ + 'Startup', + 'Full build', + 'Up-to-date build', + ] + + run_commands = [ + '%(python)s %(scons_wrapper)s %(scons_flags)s --profile=%(prof0)s %(targets0)s', + '%(python)s %(scons_wrapper)s %(scons_flags)s --profile=%(prof1)s %(targets1)s', + '%(python)s %(scons_wrapper)s %(scons_flags)s --profile=%(prof2)s %(targets2)s', + ] + + stages = [ + 'pre-read', + 'post-read', + 'pre-build', + 'post-build', + ] + + stage_strings = { + 'pre-read' : 'Memory before reading SConscript files:', + 'post-read' : 'Memory after reading SConscript files:', + 'pre-build' : 'Memory before building targets:', + 'post-build' : 'Memory after building targets:', + } + + memory_string_all = 'Memory ' + + default_stage = stages[-1] + + time_strings = { + 'total' : 'Total build time', + 'SConscripts' : 'Total SConscript file execution time', + 'SCons' : 'Total SCons execution time', + 'commands' : 'Total command execution time', + } + + time_string_all = 'Total .* time' + + # + + def __init__(self): + self.__dict__.update(self.default_settings) + + # Functions for displaying and executing commands. + + def subst(self, x, dictionary): + try: + return x % dictionary + except TypeError: + # x isn't a string (it's probably a Python function), + # so just return it. + return x + + def subst_variables(self, command, dictionary): + """ + Substitutes (via the format operator) the values in the specified + dictionary into the specified command. + + The command can be an (action, string) tuple. In all cases, we + perform substitution on strings and don't worry if something isn't + a string. (It's probably a Python function to be executed.) + """ + try: + command + '' + except TypeError: + action = command[0] + string = command[1] + args = command[2:] + else: + action = command + string = action + args = (()) + action = self.subst(action, dictionary) + string = self.subst(string, dictionary) + return (action, string, args) + + def _do_not_display(self, msg, *args): + pass + + def display(self, msg, *args): + """ + Displays the specified message. + + Each message is prepended with a standard prefix of our name + plus the time. + """ + if callable(msg): + msg = msg(*args) + else: + msg = msg % args + if msg is None: + return + fmt = '%s[%s]: %s\n' + sys.stdout.write(fmt % (self.name, time.strftime('%H:%M:%S'), msg)) + + def _do_not_execute(self, action, *args): + pass + + def execute(self, action, *args): + """ + Executes the specified action. + + The action is called if it's a callable Python function, and + otherwise passed to os.system(). + """ + if callable(action): + action(*args) + else: + os.system(action % args) + + def run_command_list(self, commands, dict): + """ + Executes a list of commands, substituting values from the + specified dictionary. + """ + commands = [ self.subst_variables(c, dict) for c in commands ] + for action, string, args in commands: + self.display(string, *args) + sys.stdout.flush() + status = self.execute(action, *args) + if status: + sys.exit(status) + + def log_display(self, command, log): + command = self.subst(command, self.__dict__) + if log: + command = self.redirect(command, log) + return command + + def log_execute(self, command, log): + command = self.subst(command, self.__dict__) + p = os.popen(command) + output = p.read() + p.close() + #TODO: convert to subrocess, os.popen is obsolete. This didn't work: + #process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True) + #output = process.stdout.read() + #process.stdout.close() + #process.wait() + if self.verbose: + sys.stdout.write(output) + # TODO: Figure out + # Not sure we need to write binary here + with open(log, 'w') as f: + f.write(str(output)) + + def archive_splitext(self, path): + """ + Splits an archive name into a filename base and extension. + + This is like os.path.splitext() (which it calls) except that it + also looks for '.tar.gz' and treats it as an atomic extensions. + """ + if path.endswith('.tar.gz'): + return path[:-7], path[-7:] + else: + return os.path.splitext(path) + + def args_to_files(self, args, tail=None): + """ + Takes a list of arguments, expands any glob patterns, and + returns the last "tail" files from the list. + """ + files = [] + for a in args: + files.extend(sorted(glob.glob(a))) + + if tail: + files = files[-tail:] + + return files + + def ascii_table(self, files, columns, + line_function, file_function=lambda x: x, + *args, **kw): + + header_fmt = ' '.join(['%12s'] * len(columns)) + line_fmt = header_fmt + ' %s' + + print(header_fmt % columns) + + for file in files: + t = line_function(file, *args, **kw) + if t is None: + t = [] + diff = len(columns) - len(t) + if diff > 0: + t += [''] * diff + t.append(file_function(file)) + print(line_fmt % tuple(t)) + + def collect_results(self, files, function, *args, **kw): + results = {} + + for file in files: + base = os.path.splitext(file)[0] + run, index = base.split('-')[-2:] + + run = int(run) + index = int(index) + + value = function(file, *args, **kw) + + try: + r = results[index] + except KeyError: + r = [] + results[index] = r + r.append((run, value)) + + return results + + def doc_to_help(self, obj): + """ + Translates an object's __doc__ string into help text. + + This strips a consistent number of spaces from each line in the + help text, essentially "outdenting" the text to the left-most + column. + """ + doc = obj.__doc__ + if doc is None: + return '' + return self.outdent(doc) + + def find_next_run_number(self, dir, prefix): + """ + Returns the next run number in a directory for the specified prefix. + + Examines the contents the specified directory for files with the + specified prefix, extracts the run numbers from each file name, + and returns the next run number after the largest it finds. + """ + x = re.compile(re.escape(prefix) + '-([0-9]+).*') + matches = [x.match(e) for e in os.listdir(dir)] + matches = [_f for _f in matches if _f] + if not matches: + return 0 + run_numbers = [int(m.group(1)) for m in matches] + return int(max(run_numbers)) + 1 + + def gnuplot_results(self, results, fmt='%s %.3f'): + """ + Prints out a set of results in Gnuplot format. + """ + gp = Gnuplotter(self.title, self.key_location) + + for i in sorted(results.keys()): + try: + t = self.run_titles[i] + except IndexError: + t = '??? %s ???' % i + results[i].sort() + gp.line(results[i], i+1, t, None, t, fmt=fmt) + + for bar_tuple in self.vertical_bars: + try: + x, type, label, comment = bar_tuple + except ValueError: + x, type, label = bar_tuple + comment = label + gp.vertical_bar(x, type, label, comment) + + gp.draw() + + def logfile_name(self, invocation): + """ + Returns the absolute path of a log file for the specificed + invocation number. + """ + name = self.prefix_run + '-%d.log' % invocation + return os.path.join(self.outdir, name) + + def outdent(self, s): + """ + Strip as many spaces from each line as are found at the beginning + of the first line in the list. + """ + lines = s.split('\n') + if lines[0] == '': + lines = lines[1:] + spaces = re.match(' *', lines[0]).group(0) + def strip_initial_spaces(l, s=spaces): + if l.startswith(spaces): + l = l[len(spaces):] + return l + return '\n'.join([ strip_initial_spaces(l) for l in lines ]) + '\n' + + def profile_name(self, invocation): + """ + Returns the absolute path of a profile file for the specified + invocation number. + """ + name = self.prefix_run + '-%d.prof' % invocation + return os.path.join(self.outdir, name) + + def set_env(self, key, value): + os.environ[key] = value + + # + + def get_debug_times(self, file, time_string=None): + """ + Fetch times from the --debug=time strings in the specified file. + """ + if time_string is None: + search_string = self.time_string_all + else: + search_string = time_string + with open(file) as f: + contents = f.read() + 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 = [ float(r) for r in result ] + if time_string is not None: + try: + result = result[0] + except IndexError: + sys.stderr.write('file %s has no results!\n' % repr(file)) + return None + return result + + def get_function_profile(self, file, function): + """ + Returns the file, line number, function name, and cumulative time. + """ + try: + import pstats + except ImportError as e: + sys.stderr.write('%s: func: %s\n' % (self.name, e)) + sys.stderr.write('%s This version of Python is missing the profiler.\n' % self.name_spaces) + sys.stderr.write('%s Cannot use the "func" subcommand.\n' % self.name_spaces) + sys.exit(1) + statistics = pstats.Stats(file).stats + matches = [ e for e in statistics.items() if e[0][2] == function ] + r = matches[0] + return r[0][0], r[0][1], r[0][2], r[1][3] + + def get_function_time(self, file, function): + """ + Returns just the cumulative time for the specified function. + """ + return self.get_function_profile(file, function)[3] + + def get_memory(self, file, memory_string=None): + """ + Returns a list of integers of the amount of memory used. The + default behavior is to return all the stages. + """ + if memory_string is None: + search_string = self.memory_string_all + else: + search_string = memory_string + with open(file) as f: + lines = f.readlines() + lines = [ l for l in lines if l.startswith(search_string) ][-4:] + result = [ int(l.split()[-1]) for l in lines[-4:] ] + if len(result) == 1: + result = result[0] + return result + + def get_object_counts(self, file, object_name, index=None): + """ + Returns the counts of the specified object_name. + """ + object_string = ' ' + object_name + '\n' + with open(file) as f: + lines = f.readlines() + line = [ l for l in lines if l.endswith(object_string) ][0] + result = [ int(field) for field in line.split()[:4] ] + if index is not None: + result = result[index] + return result + + + command_alias = {} + + def execute_subcommand(self, argv): + """ + Executes the do_*() function for the specified subcommand (argv[0]). + """ + if not argv: + return + cmdName = self.command_alias.get(argv[0], argv[0]) + try: + func = getattr(self, 'do_' + cmdName) + except AttributeError: + return self.default(argv) + try: + return func(argv) + except TypeError as e: + sys.stderr.write("%s %s: %s\n" % (self.name, cmdName, e)) + import traceback + traceback.print_exc(file=sys.stderr) + sys.stderr.write("Try '%s help %s'\n" % (self.name, cmdName)) + + def default(self, argv): + """ + The default behavior for an unknown subcommand. Prints an + error message and exits. + """ + sys.stderr.write('%s: Unknown subcommand "%s".\n' % (self.name, argv[0])) + sys.stderr.write('Type "%s help" for usage.\n' % self.name) + sys.exit(1) + + # + + def do_help(self, argv): + """ + """ + if argv[1:]: + for arg in argv[1:]: + try: + func = getattr(self, 'do_' + arg) + except AttributeError: + sys.stderr.write('%s: No help for "%s"\n' % (self.name, arg)) + else: + try: + help = getattr(self, 'help_' + arg) + except AttributeError: + sys.stdout.write(self.doc_to_help(func)) + sys.stdout.flush() + else: + help() + else: + doc = self.doc_to_help(self.__class__) + if doc: + sys.stdout.write(doc) + sys.stdout.flush() + return None + + # + + def help_func(self): + help = """\ + Usage: scons-time func [OPTIONS] FILE [...] + + -C DIR, --chdir=DIR Change to DIR before looking for files + -f FILE, --file=FILE Read configuration from specified FILE + --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT + --func=NAME, --function=NAME Report time for function NAME + -h, --help Print this help and exit + -p STRING, --prefix=STRING Use STRING as log file/profile prefix + -t NUMBER, --tail=NUMBER Only report the last NUMBER files + --title=TITLE Specify the output plot TITLE + """ + sys.stdout.write(self.outdent(help)) + sys.stdout.flush() + + def do_func(self, argv): + """ + """ + format = 'ascii' + function_name = '_main' + tail = None + + short_opts = '?C:f:hp:t:' + + long_opts = [ + 'chdir=', + 'file=', + 'fmt=', + 'format=', + 'func=', + 'function=', + 'help', + 'prefix=', + 'tail=', + 'title=', + ] + + opts, args = getopt.getopt(argv[1:], short_opts, long_opts) + + for o, a in opts: + if o in ('-C', '--chdir'): + self.chdir = a + elif o in ('-f', '--file'): + self.config_file = a + elif o in ('--fmt', '--format'): + format = a + elif o in ('--func', '--function'): + function_name = a + elif o in ('-?', '-h', '--help'): + self.do_help(['help', 'func']) + sys.exit(0) + elif o in ('--max',): + max_time = int(a) + elif o in ('-p', '--prefix'): + self.prefix = a + elif o in ('-t', '--tail'): + tail = int(a) + elif o in ('--title',): + self.title = a + + if self.config_file: + with open(self.config_file, 'r') as f: + config = f.read() + exec(config, self.__dict__) + + if self.chdir: + os.chdir(self.chdir) + + if not args: + + pattern = '%s*.prof' % self.prefix + args = self.args_to_files([pattern], tail) + + if not args: + if self.chdir: + directory = self.chdir + else: + directory = os.getcwd() + + sys.stderr.write('%s: func: No arguments specified.\n' % self.name) + sys.stderr.write('%s No %s*.prof files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) + sys.stderr.write('%s Type "%s help func" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + + else: + + args = self.args_to_files(args, tail) + + cwd_ = os.getcwd() + os.sep + + if format == 'ascii': + + for file in args: + try: + f, line, func, time = \ + self.get_function_profile(file, function_name) + except ValueError as e: + sys.stderr.write("%s: func: %s: %s\n" % + (self.name, file, e)) + else: + if f.startswith(cwd_): + f = f[len(cwd_):] + print("%.3f %s:%d(%s)" % (time, f, line, func)) + + elif format == 'gnuplot': + + results = self.collect_results(args, self.get_function_time, + function_name) + + self.gnuplot_results(results) + + else: + + sys.stderr.write('%s: func: Unknown format "%s".\n' % (self.name, format)) + sys.exit(1) + + # + + def help_mem(self): + help = """\ + Usage: scons-time mem [OPTIONS] FILE [...] + + -C DIR, --chdir=DIR Change to DIR before looking for files + -f FILE, --file=FILE Read configuration from specified FILE + --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT + -h, --help Print this help and exit + -p STRING, --prefix=STRING Use STRING as log file/profile prefix + --stage=STAGE Plot memory at the specified stage: + pre-read, post-read, pre-build, + post-build (default: post-build) + -t NUMBER, --tail=NUMBER Only report the last NUMBER files + --title=TITLE Specify the output plot TITLE + """ + sys.stdout.write(self.outdent(help)) + sys.stdout.flush() + + def do_mem(self, argv): + + format = 'ascii' + logfile_path = lambda x: x + stage = self.default_stage + tail = None + + short_opts = '?C:f:hp:t:' + + long_opts = [ + 'chdir=', + 'file=', + 'fmt=', + 'format=', + 'help', + 'prefix=', + 'stage=', + 'tail=', + 'title=', + ] + + opts, args = getopt.getopt(argv[1:], short_opts, long_opts) + + for o, a in opts: + if o in ('-C', '--chdir'): + self.chdir = a + elif o in ('-f', '--file'): + self.config_file = a + elif o in ('--fmt', '--format'): + format = a + elif o in ('-?', '-h', '--help'): + self.do_help(['help', 'mem']) + sys.exit(0) + elif o in ('-p', '--prefix'): + self.prefix = a + elif o in ('--stage',): + if a not in self.stages: + sys.stderr.write('%s: mem: Unrecognized stage "%s".\n' % (self.name, a)) + sys.exit(1) + stage = a + elif o in ('-t', '--tail'): + tail = int(a) + elif o in ('--title',): + self.title = a + + if self.config_file: + with open(self.config_file, 'r') as f: + config = f.read() + HACK_for_exec(config, self.__dict__) + + if self.chdir: + os.chdir(self.chdir) + logfile_path = lambda x: os.path.join(self.chdir, x) + + if not args: + + pattern = '%s*.log' % self.prefix + args = self.args_to_files([pattern], tail) + + if not args: + if self.chdir: + directory = self.chdir + else: + directory = os.getcwd() + + sys.stderr.write('%s: mem: No arguments specified.\n' % self.name) + sys.stderr.write('%s No %s*.log files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) + sys.stderr.write('%s Type "%s help mem" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + + else: + + args = self.args_to_files(args, tail) + + cwd_ = os.getcwd() + os.sep + + if format == 'ascii': + + self.ascii_table(args, tuple(self.stages), self.get_memory, logfile_path) + + elif format == 'gnuplot': + + results = self.collect_results(args, self.get_memory, + self.stage_strings[stage]) + + self.gnuplot_results(results) + + else: + + sys.stderr.write('%s: mem: Unknown format "%s".\n' % (self.name, format)) + sys.exit(1) + + return 0 + + # + + def help_obj(self): + help = """\ + Usage: scons-time obj [OPTIONS] OBJECT FILE [...] + + -C DIR, --chdir=DIR Change to DIR before looking for files + -f FILE, --file=FILE Read configuration from specified FILE + --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT + -h, --help Print this help and exit + -p STRING, --prefix=STRING Use STRING as log file/profile prefix + --stage=STAGE Plot memory at the specified stage: + pre-read, post-read, pre-build, + post-build (default: post-build) + -t NUMBER, --tail=NUMBER Only report the last NUMBER files + --title=TITLE Specify the output plot TITLE + """ + sys.stdout.write(self.outdent(help)) + sys.stdout.flush() + + def do_obj(self, argv): + + format = 'ascii' + logfile_path = lambda x: x + stage = self.default_stage + tail = None + + short_opts = '?C:f:hp:t:' + + long_opts = [ + 'chdir=', + 'file=', + 'fmt=', + 'format=', + 'help', + 'prefix=', + 'stage=', + 'tail=', + 'title=', + ] + + opts, args = getopt.getopt(argv[1:], short_opts, long_opts) + + for o, a in opts: + if o in ('-C', '--chdir'): + self.chdir = a + elif o in ('-f', '--file'): + self.config_file = a + elif o in ('--fmt', '--format'): + format = a + elif o in ('-?', '-h', '--help'): + self.do_help(['help', 'obj']) + sys.exit(0) + elif o in ('-p', '--prefix'): + self.prefix = a + elif o in ('--stage',): + if a not in self.stages: + sys.stderr.write('%s: obj: Unrecognized stage "%s".\n' % (self.name, a)) + sys.stderr.write('%s Type "%s help obj" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + stage = a + elif o in ('-t', '--tail'): + tail = int(a) + elif o in ('--title',): + self.title = a + + if not args: + sys.stderr.write('%s: obj: Must specify an object name.\n' % self.name) + sys.stderr.write('%s Type "%s help obj" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + + object_name = args.pop(0) + + if self.config_file: + with open(self.config_file, 'r') as f: + config = f.read() + HACK_for_exec(config, self.__dict__) + + if self.chdir: + os.chdir(self.chdir) + logfile_path = lambda x: os.path.join(self.chdir, x) + + if not args: + + pattern = '%s*.log' % self.prefix + args = self.args_to_files([pattern], tail) + + if not args: + if self.chdir: + directory = self.chdir + else: + directory = os.getcwd() + + sys.stderr.write('%s: obj: No arguments specified.\n' % self.name) + sys.stderr.write('%s No %s*.log files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) + sys.stderr.write('%s Type "%s help obj" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + + else: + + args = self.args_to_files(args, tail) + + cwd_ = os.getcwd() + os.sep + + if format == 'ascii': + + self.ascii_table(args, tuple(self.stages), self.get_object_counts, logfile_path, object_name) + + elif format == 'gnuplot': + + stage_index = 0 + for s in self.stages: + if stage == s: + break + stage_index = stage_index + 1 + + results = self.collect_results(args, self.get_object_counts, + object_name, stage_index) + + self.gnuplot_results(results) + + else: + + sys.stderr.write('%s: obj: Unknown format "%s".\n' % (self.name, format)) + sys.exit(1) + + return 0 + + # + + def help_run(self): + help = """\ + Usage: scons-time run [OPTIONS] [FILE ...] + + --chdir=DIR Name of unpacked directory for chdir + -f FILE, --file=FILE Read configuration from specified FILE + -h, --help Print this help and exit + -n, --no-exec No execute, just print command lines + --number=NUMBER Put output in files for run NUMBER + --outdir=OUTDIR Put output files in OUTDIR + -p STRING, --prefix=STRING Use STRING as log file/profile prefix + --python=PYTHON Time using the specified PYTHON + -q, --quiet Don't print command lines + --scons=SCONS Time using the specified SCONS + --svn=URL, --subversion=URL Use SCons from Subversion URL + -v, --verbose Display output of commands + """ + sys.stdout.write(self.outdent(help)) + sys.stdout.flush() + + def do_run(self, argv): + """ + """ + run_number_list = [None] + + short_opts = '?f:hnp:qs:v' + + long_opts = [ + 'file=', + 'help', + 'no-exec', + 'number=', + 'outdir=', + 'prefix=', + 'python=', + 'quiet', + 'scons=', + 'svn=', + 'subdir=', + 'subversion=', + 'verbose', + ] + + opts, args = getopt.getopt(argv[1:], short_opts, long_opts) + + for o, a in opts: + if o in ('-f', '--file'): + self.config_file = a + elif o in ('-?', '-h', '--help'): + self.do_help(['help', 'run']) + sys.exit(0) + elif o in ('-n', '--no-exec'): + self.execute = self._do_not_execute + elif o in ('--number',): + run_number_list = self.split_run_numbers(a) + elif o in ('--outdir',): + self.outdir = a + elif o in ('-p', '--prefix'): + self.prefix = a + elif o in ('--python',): + self.python = a + elif o in ('-q', '--quiet'): + self.display = self._do_not_display + elif o in ('-s', '--subdir'): + self.subdir = a + elif o in ('--scons',): + self.scons = a + elif o in ('--svn', '--subversion'): + self.subversion_url = a + elif o in ('-v', '--verbose'): + self.redirect = tee_to_file + self.verbose = True + self.svn_co_flag = '' + + if not args and not self.config_file: + sys.stderr.write('%s: run: No arguments or -f config file specified.\n' % self.name) + sys.stderr.write('%s Type "%s help run" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + + if self.config_file: + with open(self.config_file, 'r') as f: + config = f.read() + exec(config, self.__dict__) + + if args: + self.archive_list = args + + archive_file_name = os.path.split(self.archive_list[0])[1] + + if not self.subdir: + self.subdir = self.archive_splitext(archive_file_name)[0] + + if not self.prefix: + self.prefix = self.archive_splitext(archive_file_name)[0] + + prepare = None + if self.subversion_url: + prepare = self.prep_subversion_run + + for run_number in run_number_list: + self.individual_run(run_number, self.archive_list, prepare) + + def split_run_numbers(self, s): + result = [] + for n in s.split(','): + try: + x, y = n.split('-') + except ValueError: + result.append(int(n)) + else: + result.extend(list(range(int(x), int(y)+1))) + return result + + def scons_path(self, dir): + return os.path.join(dir,'scripts', 'scons.py') + + def scons_lib_dir_path(self, dir): + return os.path.join(dir, 'src', 'engine') + + def prep_subversion_run(self, commands, removals): + self.svn_tmpdir = tempfile.mkdtemp(prefix=self.name + '-svn-') + removals.append((shutil.rmtree, 'rm -rf %%s', self.svn_tmpdir)) + + self.scons = self.scons_path(self.svn_tmpdir) + self.scons_lib_dir = self.scons_lib_dir_path(self.svn_tmpdir) + + commands.extend([ + '%(svn)s co %(svn_co_flag)s -r %(run_number)s %(subversion_url)s %(svn_tmpdir)s', + ]) + + def individual_run(self, run_number, archive_list, prepare=None): + """ + Performs an individual run of the default SCons invocations. + """ + + commands = [] + removals = [] + + if prepare: + prepare(commands, removals) + + save_scons = self.scons + save_scons_wrapper = self.scons_wrapper + save_scons_lib_dir = self.scons_lib_dir + + if self.outdir is None: + self.outdir = self.orig_cwd + elif not os.path.isabs(self.outdir): + self.outdir = os.path.join(self.orig_cwd, self.outdir) + + if self.scons is None: + self.scons = self.scons_path(self.orig_cwd) + + if self.scons_lib_dir is None: + self.scons_lib_dir = self.scons_lib_dir_path(self.orig_cwd) + + if self.scons_wrapper is None: + self.scons_wrapper = self.scons + + if not run_number: + run_number = self.find_next_run_number(self.outdir, self.prefix) + + self.run_number = str(run_number) + + self.prefix_run = self.prefix + '-%03d' % run_number + + if self.targets0 is None: + self.targets0 = self.startup_targets + if self.targets1 is None: + self.targets1 = self.targets + if self.targets2 is None: + self.targets2 = self.targets + + self.tmpdir = tempfile.mkdtemp(prefix=self.name + '-') + + commands.extend([ + (os.chdir, 'cd %%s', self.tmpdir), + ]) + + for archive in archive_list: + if not os.path.isabs(archive): + archive = os.path.join(self.orig_cwd, archive) + if os.path.isdir(archive): + dest = os.path.split(archive)[1] + commands.append((shutil.copytree, 'cp -r %%s %%s', archive, dest)) + else: + suffix = self.archive_splitext(archive)[1] + unpack_command = self.unpack_map.get(suffix) + if not unpack_command: + dest = os.path.split(archive)[1] + commands.append((shutil.copyfile, 'cp %%s %%s', archive, dest)) + else: + commands.append(unpack_command + (archive,)) + + commands.extend([ + (os.chdir, 'cd %%s', self.subdir), + ]) + + commands.extend(self.initial_commands) + + commands.extend([ + (lambda: read_tree('.'), + 'find * -type f | xargs cat > /dev/null'), + + (self.set_env, 'export %%s=%%s', + 'SCONS_LIB_DIR', self.scons_lib_dir), + + '%(python)s %(scons_wrapper)s --version', + ]) + + index = 0 + for run_command in self.run_commands: + setattr(self, 'prof%d' % index, self.profile_name(index)) + c = ( + self.log_execute, + self.log_display, + run_command, + self.logfile_name(index), + ) + commands.append(c) + index = index + 1 + + commands.extend([ + (os.chdir, 'cd %%s', self.orig_cwd), + ]) + + if not os.environ.get('PRESERVE'): + commands.extend(removals) + commands.append((shutil.rmtree, 'rm -rf %%s', self.tmpdir)) + + self.run_command_list(commands, self.__dict__) + + self.scons = save_scons + self.scons_lib_dir = save_scons_lib_dir + self.scons_wrapper = save_scons_wrapper + + # + + def help_time(self): + help = """\ + Usage: scons-time time [OPTIONS] FILE [...] + + -C DIR, --chdir=DIR Change to DIR before looking for files + -f FILE, --file=FILE Read configuration from specified FILE + --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT + -h, --help Print this help and exit + -p STRING, --prefix=STRING Use STRING as log file/profile prefix + -t NUMBER, --tail=NUMBER Only report the last NUMBER files + --which=TIMER Plot timings for TIMER: total, + SConscripts, SCons, commands. + """ + sys.stdout.write(self.outdent(help)) + sys.stdout.flush() + + def do_time(self, argv): + + format = 'ascii' + logfile_path = lambda x: x + tail = None + which = 'total' + + short_opts = '?C:f:hp:t:' + + long_opts = [ + 'chdir=', + 'file=', + 'fmt=', + 'format=', + 'help', + 'prefix=', + 'tail=', + 'title=', + 'which=', + ] + + opts, args = getopt.getopt(argv[1:], short_opts, long_opts) + + for o, a in opts: + if o in ('-C', '--chdir'): + self.chdir = a + elif o in ('-f', '--file'): + self.config_file = a + elif o in ('--fmt', '--format'): + format = a + elif o in ('-?', '-h', '--help'): + self.do_help(['help', 'time']) + sys.exit(0) + elif o in ('-p', '--prefix'): + self.prefix = a + elif o in ('-t', '--tail'): + tail = int(a) + elif o in ('--title',): + self.title = a + elif o in ('--which',): + if a not in list(self.time_strings.keys()): + sys.stderr.write('%s: time: Unrecognized timer "%s".\n' % (self.name, a)) + sys.stderr.write('%s Type "%s help time" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + which = a + + if self.config_file: + with open(self.config_file, 'r') as f: + config = f.read() + HACK_for_exec(config, self.__dict__) + + if self.chdir: + os.chdir(self.chdir) + logfile_path = lambda x: os.path.join(self.chdir, x) + + if not args: + + pattern = '%s*.log' % self.prefix + args = self.args_to_files([pattern], tail) + + if not args: + if self.chdir: + directory = self.chdir + else: + directory = os.getcwd() + + sys.stderr.write('%s: time: No arguments specified.\n' % self.name) + sys.stderr.write('%s No %s*.log files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) + sys.stderr.write('%s Type "%s help time" for help.\n' % (self.name_spaces, self.name)) + sys.exit(1) + + else: + + args = self.args_to_files(args, tail) + + cwd_ = os.getcwd() + os.sep + + if format == 'ascii': + + columns = ("Total", "SConscripts", "SCons", "commands") + self.ascii_table(args, columns, self.get_debug_times, logfile_path) + + elif format == 'gnuplot': + + results = self.collect_results(args, self.get_debug_times, + self.time_strings[which]) + + self.gnuplot_results(results, fmt='%s %.6f') + + else: + + sys.stderr.write('%s: time: Unknown format "%s".\n' % (self.name, format)) + sys.exit(1) + +if __name__ == '__main__': + opts, args = getopt.getopt(sys.argv[1:], 'h?V', ['help', 'version']) + + ST = SConsTimer() + + for o, a in opts: + if o in ('-?', '-h', '--help'): + ST.do_help(['help']) + sys.exit(0) + elif o in ('-V', '--version'): + sys.stdout.write('scons-time version\n') + sys.exit(0) + + if not args: + sys.stderr.write('Type "%s help" for usage.\n' % ST.name) + sys.exit(1) + + ST.execute_subcommand(args) + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/runtest.py b/runtest.py index 65b2179..10d16ba 100755 --- a/runtest.py +++ b/runtest.py @@ -478,90 +478,49 @@ else: Test = SystemExecutor # --- start processing --- -if package: - - dirs = { - 'deb' : 'usr', - 'local-tar-gz' : None, - 'local-zip' : None, - 'rpm' : 'usr', - 'src-tar-gz' : '', - 'src-zip' : '', - 'tar-gz' : '', - 'zip' : '', - } - - # The hard-coded "python2.1" here is the library directory - # name on Debian systems, not an executable, so it's all right. - lib = { - 'deb' : os.path.join('python2.1', 'site-packages') - } - - if package not in dirs: - sys.stderr.write("Unknown package '%s'\n" % package) - sys.exit(2) - - test_dir = os.path.join(builddir, 'test-%s' % package) - - if dirs[package] is None: - scons_script_dir = test_dir - globs = glob.glob(os.path.join(test_dir, 'scons-local-*')) - if not globs: - sys.stderr.write("No `scons-local-*' dir in `%s'\n" % test_dir) - sys.exit(2) - scons_lib_dir = None - pythonpath_dir = globs[len(globs)-1] - elif sys.platform == 'win32': - scons_script_dir = os.path.join(test_dir, dirs[package], 'Scripts') - scons_lib_dir = os.path.join(test_dir, dirs[package]) - pythonpath_dir = scons_lib_dir - else: - scons_script_dir = os.path.join(test_dir, dirs[package], 'bin') - sconslib = lib.get(package, 'scons') - scons_lib_dir = os.path.join(test_dir, dirs[package], 'lib', sconslib) - pythonpath_dir = scons_lib_dir - scons_runtest_dir = builddir +sd = None +tools_dir = None +ld = None + +if not baseline or baseline == '.': + base = cwd +elif baseline == '-': + url = None + with os.popen("svn info 2>&1", "r") as p: + svn_info = p.read() + match = re.search(r'URL: (.*)', svn_info) + if match: + url = match.group(1) + if not url: + sys.stderr.write('runtest.py: could not find a URL:\n') + sys.stderr.write(svn_info) + sys.exit(1) + import tempfile + base = tempfile.mkdtemp(prefix='runtest-tmp-') + + command = 'cd %s && svn co -q %s' % (base, url) + base = os.path.join(base, os.path.split(url)[1]) + if printcommand: + print(command) + if execute_tests: + os.system(command) else: - sd = None - ld = None - - if not baseline or baseline == '.': - base = cwd - elif baseline == '-': - url = None - with os.popen("svn info 2>&1", "r") as p: - svn_info = p.read() - match = re.search(r'URL: (.*)', svn_info) - if match: - url = match.group(1) - if not url: - sys.stderr.write('runtest.py: could not find a URL:\n') - sys.stderr.write(svn_info) - sys.exit(1) - base = tempfile.mkdtemp(prefix='runtest-tmp-') - - command = 'cd %s && svn co -q %s' % (base, url) - - base = os.path.join(base, os.path.split(url)[1]) - if printcommand: - print(command) - if execute_tests: - os.system(command) - else: - base = baseline + base = baseline - scons_runtest_dir = base +scons_runtest_dir = base - if not external: - scons_script_dir = sd or os.path.join(base, 'scripts') - scons_lib_dir = ld or os.path.join(base, 'src', 'engine') - else: - scons_script_dir = sd or '' - scons_lib_dir = ld or '' +if not external: + scons_script_dir = sd or os.path.join(base, 'scripts') + scons_tools_dir = tools_dir or os.path.join(base, 'bin') + scons_lib_dir = ld or os.path.join(base, 'src', 'engine') +else: + scons_script_dir = sd or '' + scons_tools_dir = tools_dir or '' + scons_lib_dir = ld or '' - pythonpath_dir = scons_lib_dir +pythonpath_dir = scons_lib_dir if scons: # Let the version of SCons that the -x option pointed to find @@ -581,6 +540,7 @@ if external: os.environ['SCONS_RUNTEST_DIR'] = scons_runtest_dir os.environ['SCONS_SCRIPT_DIR'] = scons_script_dir +os.environ['SCONS_TOOLS_DIR'] = scons_tools_dir os.environ['SCONS_CWD'] = cwd os.environ['SCONS_VERSION'] = version diff --git a/scripts/scons-time.py b/scripts/scons-time.py deleted file mode 100644 index 6494349..0000000 --- a/scripts/scons-time.py +++ /dev/null @@ -1,1480 +0,0 @@ -#!/usr/bin/env python -# -# scons-time - run SCons timings and collect statistics -# -# A script for running a configuration through SCons with a standard -# set of invocations to collect timing and memory statistics and to -# capture the results in a consistent set of output files for display -# and analysis. -# - -# -# __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 getopt -import glob -import os -import re -import shutil -import sys -import tempfile -import time -import subprocess - -def HACK_for_exec(cmd, *args): - """ - For some reason, Python won't allow an exec() within a function - that also declares an internal function (including lambda functions). - This function is a hack that calls exec() in a function with no - internal functions. - """ - if not args: exec(cmd) - elif len(args) == 1: exec(cmd, args[0]) - else: exec(cmd, args[0], args[1]) - -class Plotter(object): - def increment_size(self, largest): - """ - Return the size of each horizontal increment line for a specified - maximum value. This returns a value that will provide somewhere - between 5 and 9 horizontal lines on the graph, on some set of - boundaries that are multiples of 10/100/1000/etc. - """ - i = largest // 5 - if not i: - return largest - multiplier = 1 - while i >= 10: - i = i // 10 - multiplier = multiplier * 10 - return i * multiplier - - def max_graph_value(self, largest): - # Round up to next integer. - largest = int(largest) + 1 - increment = self.increment_size(largest) - return ((largest + increment - 1) // increment) * increment - -class Line(object): - def __init__(self, points, type, title, label, comment, fmt="%s %s"): - self.points = points - self.type = type - self.title = title - self.label = label - self.comment = comment - self.fmt = fmt - - def print_label(self, inx, x, y): - if self.label: - print('set label %s "%s" at %0.1f,%0.1f right' % (inx, self.label, x, y)) - - def plot_string(self): - if self.title: - title_string = 'title "%s"' % self.title - else: - title_string = 'notitle' - return "'-' %s with lines lt %s" % (title_string, self.type) - - def print_points(self, fmt=None): - if fmt is None: - fmt = self.fmt - if self.comment: - print('# %s' % self.comment) - for x, y in self.points: - # If y is None, it usually represents some kind of break - # in the line's index number. We might want to represent - # this some way rather than just drawing the line straight - # between the two points on either side. - if y is not None: - print(fmt % (x, y)) - print('e') - - def get_x_values(self): - return [ p[0] for p in self.points ] - - def get_y_values(self): - return [ p[1] for p in self.points ] - -class Gnuplotter(Plotter): - - def __init__(self, title, key_location): - self.lines = [] - self.title = title - self.key_location = key_location - - def line(self, points, type, title=None, label=None, comment=None, fmt='%s %s'): - if points: - line = Line(points, type, title, label, comment, fmt) - self.lines.append(line) - - def plot_string(self, line): - return line.plot_string() - - def vertical_bar(self, x, type, label, comment): - if self.get_min_x() <= x <= self.get_max_x(): - points = [(x, 0), (x, self.max_graph_value(self.get_max_y()))] - self.line(points, type, label, comment) - - def get_all_x_values(self): - result = [] - for line in self.lines: - result.extend(line.get_x_values()) - return [r for r in result if r is not None] - - def get_all_y_values(self): - result = [] - for line in self.lines: - result.extend(line.get_y_values()) - return [r for r in result if r is not None] - - def get_min_x(self): - try: - return self.min_x - except AttributeError: - try: - self.min_x = min(self.get_all_x_values()) - except ValueError: - self.min_x = 0 - return self.min_x - - def get_max_x(self): - try: - return self.max_x - except AttributeError: - try: - self.max_x = max(self.get_all_x_values()) - except ValueError: - self.max_x = 0 - return self.max_x - - def get_min_y(self): - try: - return self.min_y - except AttributeError: - try: - self.min_y = min(self.get_all_y_values()) - except ValueError: - self.min_y = 0 - return self.min_y - - def get_max_y(self): - try: - return self.max_y - except AttributeError: - try: - self.max_y = max(self.get_all_y_values()) - except ValueError: - self.max_y = 0 - return self.max_y - - def draw(self): - - if not self.lines: - return - - if self.title: - print('set title "%s"' % self.title) - print('set key %s' % self.key_location) - - min_y = self.get_min_y() - max_y = self.max_graph_value(self.get_max_y()) - incr = (max_y - min_y) / 10.0 - start = min_y + (max_y / 2.0) + (2.0 * incr) - position = [ start - (i * incr) for i in range(5) ] - - inx = 1 - for line in self.lines: - line.print_label(inx, line.points[0][0]-1, - position[(inx-1) % len(position)]) - inx += 1 - - plot_strings = [ self.plot_string(l) for l in self.lines ] - print('plot ' + ', \\\n '.join(plot_strings)) - - for line in self.lines: - line.print_points() - - - -def untar(fname): - import tarfile - tar = tarfile.open(name=fname, mode='r') - for tarinfo in tar: - tar.extract(tarinfo) - tar.close() - -def unzip(fname): - import zipfile - zf = zipfile.ZipFile(fname, 'r') - for name in zf.namelist(): - dir = os.path.dirname(name) - try: - os.makedirs(dir) - except: - pass - with open(name, 'wb') as f: - f.write(zf.read(name)) - -def read_tree(dir): - for dirpath, dirnames, filenames in os.walk(dir): - for fn in filenames: - fn = os.path.join(dirpath, fn) - if os.path.isfile(fn): - with open(fn, 'rb') as f: - f.read() - -def redirect_to_file(command, log): - return '%s > %s 2>&1' % (command, log) - -def tee_to_file(command, log): - return '%s 2>&1 | tee %s' % (command, log) - - - -class SConsTimer(object): - """ - Usage: scons-time SUBCOMMAND [ARGUMENTS] - Type "scons-time help SUBCOMMAND" for help on a specific subcommand. - - Available subcommands: - func Extract test-run data for a function - help Provides help - mem Extract --debug=memory data from test runs - obj Extract --debug=count data from test runs - time Extract --debug=time data from test runs - run Runs a test configuration - """ - - name = 'scons-time' - name_spaces = ' '*len(name) - - def makedict(**kw): - return kw - - default_settings = makedict( - chdir = None, - config_file = None, - initial_commands = [], - key_location = 'bottom left', - orig_cwd = os.getcwd(), - outdir = None, - prefix = '', - python = '"%s"' % sys.executable, - redirect = redirect_to_file, - scons = None, - scons_flags = '--debug=count --debug=memory --debug=time --debug=memoizer', - scons_lib_dir = None, - scons_wrapper = None, - startup_targets = '--help', - subdir = None, - subversion_url = None, - svn = 'svn', - svn_co_flag = '-q', - tar = 'tar', - targets = '', - targets0 = None, - targets1 = None, - targets2 = None, - title = None, - unzip = 'unzip', - verbose = False, - vertical_bars = [], - - unpack_map = { - '.tar.gz' : (untar, '%(tar)s xzf %%s'), - '.tgz' : (untar, '%(tar)s xzf %%s'), - '.tar' : (untar, '%(tar)s xf %%s'), - '.zip' : (unzip, '%(unzip)s %%s'), - }, - ) - - run_titles = [ - 'Startup', - 'Full build', - 'Up-to-date build', - ] - - run_commands = [ - '%(python)s %(scons_wrapper)s %(scons_flags)s --profile=%(prof0)s %(targets0)s', - '%(python)s %(scons_wrapper)s %(scons_flags)s --profile=%(prof1)s %(targets1)s', - '%(python)s %(scons_wrapper)s %(scons_flags)s --profile=%(prof2)s %(targets2)s', - ] - - stages = [ - 'pre-read', - 'post-read', - 'pre-build', - 'post-build', - ] - - stage_strings = { - 'pre-read' : 'Memory before reading SConscript files:', - 'post-read' : 'Memory after reading SConscript files:', - 'pre-build' : 'Memory before building targets:', - 'post-build' : 'Memory after building targets:', - } - - memory_string_all = 'Memory ' - - default_stage = stages[-1] - - time_strings = { - 'total' : 'Total build time', - 'SConscripts' : 'Total SConscript file execution time', - 'SCons' : 'Total SCons execution time', - 'commands' : 'Total command execution time', - } - - time_string_all = 'Total .* time' - - # - - def __init__(self): - self.__dict__.update(self.default_settings) - - # Functions for displaying and executing commands. - - def subst(self, x, dictionary): - try: - return x % dictionary - except TypeError: - # x isn't a string (it's probably a Python function), - # so just return it. - return x - - def subst_variables(self, command, dictionary): - """ - Substitutes (via the format operator) the values in the specified - dictionary into the specified command. - - The command can be an (action, string) tuple. In all cases, we - perform substitution on strings and don't worry if something isn't - a string. (It's probably a Python function to be executed.) - """ - try: - command + '' - except TypeError: - action = command[0] - string = command[1] - args = command[2:] - else: - action = command - string = action - args = (()) - action = self.subst(action, dictionary) - string = self.subst(string, dictionary) - return (action, string, args) - - def _do_not_display(self, msg, *args): - pass - - def display(self, msg, *args): - """ - Displays the specified message. - - Each message is prepended with a standard prefix of our name - plus the time. - """ - if callable(msg): - msg = msg(*args) - else: - msg = msg % args - if msg is None: - return - fmt = '%s[%s]: %s\n' - sys.stdout.write(fmt % (self.name, time.strftime('%H:%M:%S'), msg)) - - def _do_not_execute(self, action, *args): - pass - - def execute(self, action, *args): - """ - Executes the specified action. - - The action is called if it's a callable Python function, and - otherwise passed to os.system(). - """ - if callable(action): - action(*args) - else: - os.system(action % args) - - def run_command_list(self, commands, dict): - """ - Executes a list of commands, substituting values from the - specified dictionary. - """ - commands = [ self.subst_variables(c, dict) for c in commands ] - for action, string, args in commands: - self.display(string, *args) - sys.stdout.flush() - status = self.execute(action, *args) - if status: - sys.exit(status) - - def log_display(self, command, log): - command = self.subst(command, self.__dict__) - if log: - command = self.redirect(command, log) - return command - - def log_execute(self, command, log): - command = self.subst(command, self.__dict__) - p = os.popen(command) - output = p.read() - p.close() - #TODO: convert to subrocess, os.popen is obsolete. This didn't work: - #process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True) - #output = process.stdout.read() - #process.stdout.close() - #process.wait() - if self.verbose: - sys.stdout.write(output) - # TODO: Figure out - # Not sure we need to write binary here - with open(log, 'w') as f: - f.write(str(output)) - - def archive_splitext(self, path): - """ - Splits an archive name into a filename base and extension. - - This is like os.path.splitext() (which it calls) except that it - also looks for '.tar.gz' and treats it as an atomic extensions. - """ - if path.endswith('.tar.gz'): - return path[:-7], path[-7:] - else: - return os.path.splitext(path) - - def args_to_files(self, args, tail=None): - """ - Takes a list of arguments, expands any glob patterns, and - returns the last "tail" files from the list. - """ - files = [] - for a in args: - files.extend(sorted(glob.glob(a))) - - if tail: - files = files[-tail:] - - return files - - def ascii_table(self, files, columns, - line_function, file_function=lambda x: x, - *args, **kw): - - header_fmt = ' '.join(['%12s'] * len(columns)) - line_fmt = header_fmt + ' %s' - - print(header_fmt % columns) - - for file in files: - t = line_function(file, *args, **kw) - if t is None: - t = [] - diff = len(columns) - len(t) - if diff > 0: - t += [''] * diff - t.append(file_function(file)) - print(line_fmt % tuple(t)) - - def collect_results(self, files, function, *args, **kw): - results = {} - - for file in files: - base = os.path.splitext(file)[0] - run, index = base.split('-')[-2:] - - run = int(run) - index = int(index) - - value = function(file, *args, **kw) - - try: - r = results[index] - except KeyError: - r = [] - results[index] = r - r.append((run, value)) - - return results - - def doc_to_help(self, obj): - """ - Translates an object's __doc__ string into help text. - - This strips a consistent number of spaces from each line in the - help text, essentially "outdenting" the text to the left-most - column. - """ - doc = obj.__doc__ - if doc is None: - return '' - return self.outdent(doc) - - def find_next_run_number(self, dir, prefix): - """ - Returns the next run number in a directory for the specified prefix. - - Examines the contents the specified directory for files with the - specified prefix, extracts the run numbers from each file name, - and returns the next run number after the largest it finds. - """ - x = re.compile(re.escape(prefix) + '-([0-9]+).*') - matches = [x.match(e) for e in os.listdir(dir)] - matches = [_f for _f in matches if _f] - if not matches: - return 0 - run_numbers = [int(m.group(1)) for m in matches] - return int(max(run_numbers)) + 1 - - def gnuplot_results(self, results, fmt='%s %.3f'): - """ - Prints out a set of results in Gnuplot format. - """ - gp = Gnuplotter(self.title, self.key_location) - - for i in sorted(results.keys()): - try: - t = self.run_titles[i] - except IndexError: - t = '??? %s ???' % i - results[i].sort() - gp.line(results[i], i+1, t, None, t, fmt=fmt) - - for bar_tuple in self.vertical_bars: - try: - x, type, label, comment = bar_tuple - except ValueError: - x, type, label = bar_tuple - comment = label - gp.vertical_bar(x, type, label, comment) - - gp.draw() - - def logfile_name(self, invocation): - """ - Returns the absolute path of a log file for the specificed - invocation number. - """ - name = self.prefix_run + '-%d.log' % invocation - return os.path.join(self.outdir, name) - - def outdent(self, s): - """ - Strip as many spaces from each line as are found at the beginning - of the first line in the list. - """ - lines = s.split('\n') - if lines[0] == '': - lines = lines[1:] - spaces = re.match(' *', lines[0]).group(0) - def strip_initial_spaces(l, s=spaces): - if l.startswith(spaces): - l = l[len(spaces):] - return l - return '\n'.join([ strip_initial_spaces(l) for l in lines ]) + '\n' - - def profile_name(self, invocation): - """ - Returns the absolute path of a profile file for the specified - invocation number. - """ - name = self.prefix_run + '-%d.prof' % invocation - return os.path.join(self.outdir, name) - - def set_env(self, key, value): - os.environ[key] = value - - # - - def get_debug_times(self, file, time_string=None): - """ - Fetch times from the --debug=time strings in the specified file. - """ - if time_string is None: - search_string = self.time_string_all - else: - search_string = time_string - with open(file) as f: - contents = f.read() - 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 = [ float(r) for r in result ] - if time_string is not None: - try: - result = result[0] - except IndexError: - sys.stderr.write('file %s has no results!\n' % repr(file)) - return None - return result - - def get_function_profile(self, file, function): - """ - Returns the file, line number, function name, and cumulative time. - """ - try: - import pstats - except ImportError as e: - sys.stderr.write('%s: func: %s\n' % (self.name, e)) - sys.stderr.write('%s This version of Python is missing the profiler.\n' % self.name_spaces) - sys.stderr.write('%s Cannot use the "func" subcommand.\n' % self.name_spaces) - sys.exit(1) - statistics = pstats.Stats(file).stats - matches = [ e for e in statistics.items() if e[0][2] == function ] - r = matches[0] - return r[0][0], r[0][1], r[0][2], r[1][3] - - def get_function_time(self, file, function): - """ - Returns just the cumulative time for the specified function. - """ - return self.get_function_profile(file, function)[3] - - def get_memory(self, file, memory_string=None): - """ - Returns a list of integers of the amount of memory used. The - default behavior is to return all the stages. - """ - if memory_string is None: - search_string = self.memory_string_all - else: - search_string = memory_string - with open(file) as f: - lines = f.readlines() - lines = [ l for l in lines if l.startswith(search_string) ][-4:] - result = [ int(l.split()[-1]) for l in lines[-4:] ] - if len(result) == 1: - result = result[0] - return result - - def get_object_counts(self, file, object_name, index=None): - """ - Returns the counts of the specified object_name. - """ - object_string = ' ' + object_name + '\n' - with open(file) as f: - lines = f.readlines() - line = [ l for l in lines if l.endswith(object_string) ][0] - result = [ int(field) for field in line.split()[:4] ] - if index is not None: - result = result[index] - return result - - - command_alias = {} - - def execute_subcommand(self, argv): - """ - Executes the do_*() function for the specified subcommand (argv[0]). - """ - if not argv: - return - cmdName = self.command_alias.get(argv[0], argv[0]) - try: - func = getattr(self, 'do_' + cmdName) - except AttributeError: - return self.default(argv) - try: - return func(argv) - except TypeError as e: - sys.stderr.write("%s %s: %s\n" % (self.name, cmdName, e)) - import traceback - traceback.print_exc(file=sys.stderr) - sys.stderr.write("Try '%s help %s'\n" % (self.name, cmdName)) - - def default(self, argv): - """ - The default behavior for an unknown subcommand. Prints an - error message and exits. - """ - sys.stderr.write('%s: Unknown subcommand "%s".\n' % (self.name, argv[0])) - sys.stderr.write('Type "%s help" for usage.\n' % self.name) - sys.exit(1) - - # - - def do_help(self, argv): - """ - """ - if argv[1:]: - for arg in argv[1:]: - try: - func = getattr(self, 'do_' + arg) - except AttributeError: - sys.stderr.write('%s: No help for "%s"\n' % (self.name, arg)) - else: - try: - help = getattr(self, 'help_' + arg) - except AttributeError: - sys.stdout.write(self.doc_to_help(func)) - sys.stdout.flush() - else: - help() - else: - doc = self.doc_to_help(self.__class__) - if doc: - sys.stdout.write(doc) - sys.stdout.flush() - return None - - # - - def help_func(self): - help = """\ - Usage: scons-time func [OPTIONS] FILE [...] - - -C DIR, --chdir=DIR Change to DIR before looking for files - -f FILE, --file=FILE Read configuration from specified FILE - --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT - --func=NAME, --function=NAME Report time for function NAME - -h, --help Print this help and exit - -p STRING, --prefix=STRING Use STRING as log file/profile prefix - -t NUMBER, --tail=NUMBER Only report the last NUMBER files - --title=TITLE Specify the output plot TITLE - """ - sys.stdout.write(self.outdent(help)) - sys.stdout.flush() - - def do_func(self, argv): - """ - """ - format = 'ascii' - function_name = '_main' - tail = None - - short_opts = '?C:f:hp:t:' - - long_opts = [ - 'chdir=', - 'file=', - 'fmt=', - 'format=', - 'func=', - 'function=', - 'help', - 'prefix=', - 'tail=', - 'title=', - ] - - opts, args = getopt.getopt(argv[1:], short_opts, long_opts) - - for o, a in opts: - if o in ('-C', '--chdir'): - self.chdir = a - elif o in ('-f', '--file'): - self.config_file = a - elif o in ('--fmt', '--format'): - format = a - elif o in ('--func', '--function'): - function_name = a - elif o in ('-?', '-h', '--help'): - self.do_help(['help', 'func']) - sys.exit(0) - elif o in ('--max',): - max_time = int(a) - elif o in ('-p', '--prefix'): - self.prefix = a - elif o in ('-t', '--tail'): - tail = int(a) - elif o in ('--title',): - self.title = a - - if self.config_file: - with open(self.config_file, 'r') as f: - config = f.read() - exec(config, self.__dict__) - - if self.chdir: - os.chdir(self.chdir) - - if not args: - - pattern = '%s*.prof' % self.prefix - args = self.args_to_files([pattern], tail) - - if not args: - if self.chdir: - directory = self.chdir - else: - directory = os.getcwd() - - sys.stderr.write('%s: func: No arguments specified.\n' % self.name) - sys.stderr.write('%s No %s*.prof files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) - sys.stderr.write('%s Type "%s help func" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - - else: - - args = self.args_to_files(args, tail) - - cwd_ = os.getcwd() + os.sep - - if format == 'ascii': - - for file in args: - try: - f, line, func, time = \ - self.get_function_profile(file, function_name) - except ValueError as e: - sys.stderr.write("%s: func: %s: %s\n" % - (self.name, file, e)) - else: - if f.startswith(cwd_): - f = f[len(cwd_):] - print("%.3f %s:%d(%s)" % (time, f, line, func)) - - elif format == 'gnuplot': - - results = self.collect_results(args, self.get_function_time, - function_name) - - self.gnuplot_results(results) - - else: - - sys.stderr.write('%s: func: Unknown format "%s".\n' % (self.name, format)) - sys.exit(1) - - # - - def help_mem(self): - help = """\ - Usage: scons-time mem [OPTIONS] FILE [...] - - -C DIR, --chdir=DIR Change to DIR before looking for files - -f FILE, --file=FILE Read configuration from specified FILE - --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT - -h, --help Print this help and exit - -p STRING, --prefix=STRING Use STRING as log file/profile prefix - --stage=STAGE Plot memory at the specified stage: - pre-read, post-read, pre-build, - post-build (default: post-build) - -t NUMBER, --tail=NUMBER Only report the last NUMBER files - --title=TITLE Specify the output plot TITLE - """ - sys.stdout.write(self.outdent(help)) - sys.stdout.flush() - - def do_mem(self, argv): - - format = 'ascii' - logfile_path = lambda x: x - stage = self.default_stage - tail = None - - short_opts = '?C:f:hp:t:' - - long_opts = [ - 'chdir=', - 'file=', - 'fmt=', - 'format=', - 'help', - 'prefix=', - 'stage=', - 'tail=', - 'title=', - ] - - opts, args = getopt.getopt(argv[1:], short_opts, long_opts) - - for o, a in opts: - if o in ('-C', '--chdir'): - self.chdir = a - elif o in ('-f', '--file'): - self.config_file = a - elif o in ('--fmt', '--format'): - format = a - elif o in ('-?', '-h', '--help'): - self.do_help(['help', 'mem']) - sys.exit(0) - elif o in ('-p', '--prefix'): - self.prefix = a - elif o in ('--stage',): - if a not in self.stages: - sys.stderr.write('%s: mem: Unrecognized stage "%s".\n' % (self.name, a)) - sys.exit(1) - stage = a - elif o in ('-t', '--tail'): - tail = int(a) - elif o in ('--title',): - self.title = a - - if self.config_file: - with open(self.config_file, 'r') as f: - config = f.read() - HACK_for_exec(config, self.__dict__) - - if self.chdir: - os.chdir(self.chdir) - logfile_path = lambda x: os.path.join(self.chdir, x) - - if not args: - - pattern = '%s*.log' % self.prefix - args = self.args_to_files([pattern], tail) - - if not args: - if self.chdir: - directory = self.chdir - else: - directory = os.getcwd() - - sys.stderr.write('%s: mem: No arguments specified.\n' % self.name) - sys.stderr.write('%s No %s*.log files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) - sys.stderr.write('%s Type "%s help mem" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - - else: - - args = self.args_to_files(args, tail) - - cwd_ = os.getcwd() + os.sep - - if format == 'ascii': - - self.ascii_table(args, tuple(self.stages), self.get_memory, logfile_path) - - elif format == 'gnuplot': - - results = self.collect_results(args, self.get_memory, - self.stage_strings[stage]) - - self.gnuplot_results(results) - - else: - - sys.stderr.write('%s: mem: Unknown format "%s".\n' % (self.name, format)) - sys.exit(1) - - return 0 - - # - - def help_obj(self): - help = """\ - Usage: scons-time obj [OPTIONS] OBJECT FILE [...] - - -C DIR, --chdir=DIR Change to DIR before looking for files - -f FILE, --file=FILE Read configuration from specified FILE - --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT - -h, --help Print this help and exit - -p STRING, --prefix=STRING Use STRING as log file/profile prefix - --stage=STAGE Plot memory at the specified stage: - pre-read, post-read, pre-build, - post-build (default: post-build) - -t NUMBER, --tail=NUMBER Only report the last NUMBER files - --title=TITLE Specify the output plot TITLE - """ - sys.stdout.write(self.outdent(help)) - sys.stdout.flush() - - def do_obj(self, argv): - - format = 'ascii' - logfile_path = lambda x: x - stage = self.default_stage - tail = None - - short_opts = '?C:f:hp:t:' - - long_opts = [ - 'chdir=', - 'file=', - 'fmt=', - 'format=', - 'help', - 'prefix=', - 'stage=', - 'tail=', - 'title=', - ] - - opts, args = getopt.getopt(argv[1:], short_opts, long_opts) - - for o, a in opts: - if o in ('-C', '--chdir'): - self.chdir = a - elif o in ('-f', '--file'): - self.config_file = a - elif o in ('--fmt', '--format'): - format = a - elif o in ('-?', '-h', '--help'): - self.do_help(['help', 'obj']) - sys.exit(0) - elif o in ('-p', '--prefix'): - self.prefix = a - elif o in ('--stage',): - if a not in self.stages: - sys.stderr.write('%s: obj: Unrecognized stage "%s".\n' % (self.name, a)) - sys.stderr.write('%s Type "%s help obj" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - stage = a - elif o in ('-t', '--tail'): - tail = int(a) - elif o in ('--title',): - self.title = a - - if not args: - sys.stderr.write('%s: obj: Must specify an object name.\n' % self.name) - sys.stderr.write('%s Type "%s help obj" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - - object_name = args.pop(0) - - if self.config_file: - with open(self.config_file, 'r') as f: - config = f.read() - HACK_for_exec(config, self.__dict__) - - if self.chdir: - os.chdir(self.chdir) - logfile_path = lambda x: os.path.join(self.chdir, x) - - if not args: - - pattern = '%s*.log' % self.prefix - args = self.args_to_files([pattern], tail) - - if not args: - if self.chdir: - directory = self.chdir - else: - directory = os.getcwd() - - sys.stderr.write('%s: obj: No arguments specified.\n' % self.name) - sys.stderr.write('%s No %s*.log files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) - sys.stderr.write('%s Type "%s help obj" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - - else: - - args = self.args_to_files(args, tail) - - cwd_ = os.getcwd() + os.sep - - if format == 'ascii': - - self.ascii_table(args, tuple(self.stages), self.get_object_counts, logfile_path, object_name) - - elif format == 'gnuplot': - - stage_index = 0 - for s in self.stages: - if stage == s: - break - stage_index = stage_index + 1 - - results = self.collect_results(args, self.get_object_counts, - object_name, stage_index) - - self.gnuplot_results(results) - - else: - - sys.stderr.write('%s: obj: Unknown format "%s".\n' % (self.name, format)) - sys.exit(1) - - return 0 - - # - - def help_run(self): - help = """\ - Usage: scons-time run [OPTIONS] [FILE ...] - - --chdir=DIR Name of unpacked directory for chdir - -f FILE, --file=FILE Read configuration from specified FILE - -h, --help Print this help and exit - -n, --no-exec No execute, just print command lines - --number=NUMBER Put output in files for run NUMBER - --outdir=OUTDIR Put output files in OUTDIR - -p STRING, --prefix=STRING Use STRING as log file/profile prefix - --python=PYTHON Time using the specified PYTHON - -q, --quiet Don't print command lines - --scons=SCONS Time using the specified SCONS - --svn=URL, --subversion=URL Use SCons from Subversion URL - -v, --verbose Display output of commands - """ - sys.stdout.write(self.outdent(help)) - sys.stdout.flush() - - def do_run(self, argv): - """ - """ - run_number_list = [None] - - short_opts = '?f:hnp:qs:v' - - long_opts = [ - 'file=', - 'help', - 'no-exec', - 'number=', - 'outdir=', - 'prefix=', - 'python=', - 'quiet', - 'scons=', - 'svn=', - 'subdir=', - 'subversion=', - 'verbose', - ] - - opts, args = getopt.getopt(argv[1:], short_opts, long_opts) - - for o, a in opts: - if o in ('-f', '--file'): - self.config_file = a - elif o in ('-?', '-h', '--help'): - self.do_help(['help', 'run']) - sys.exit(0) - elif o in ('-n', '--no-exec'): - self.execute = self._do_not_execute - elif o in ('--number',): - run_number_list = self.split_run_numbers(a) - elif o in ('--outdir',): - self.outdir = a - elif o in ('-p', '--prefix'): - self.prefix = a - elif o in ('--python',): - self.python = a - elif o in ('-q', '--quiet'): - self.display = self._do_not_display - elif o in ('-s', '--subdir'): - self.subdir = a - elif o in ('--scons',): - self.scons = a - elif o in ('--svn', '--subversion'): - self.subversion_url = a - elif o in ('-v', '--verbose'): - self.redirect = tee_to_file - self.verbose = True - self.svn_co_flag = '' - - if not args and not self.config_file: - sys.stderr.write('%s: run: No arguments or -f config file specified.\n' % self.name) - sys.stderr.write('%s Type "%s help run" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - - if self.config_file: - with open(self.config_file, 'r') as f: - config = f.read() - exec(config, self.__dict__) - - if args: - self.archive_list = args - - archive_file_name = os.path.split(self.archive_list[0])[1] - - if not self.subdir: - self.subdir = self.archive_splitext(archive_file_name)[0] - - if not self.prefix: - self.prefix = self.archive_splitext(archive_file_name)[0] - - prepare = None - if self.subversion_url: - prepare = self.prep_subversion_run - - for run_number in run_number_list: - self.individual_run(run_number, self.archive_list, prepare) - - def split_run_numbers(self, s): - result = [] - for n in s.split(','): - try: - x, y = n.split('-') - except ValueError: - result.append(int(n)) - else: - result.extend(list(range(int(x), int(y)+1))) - return result - - def scons_path(self, dir): - return os.path.join(dir,'scripts', 'scons.py') - - def scons_lib_dir_path(self, dir): - return os.path.join(dir, 'src', 'engine') - - def prep_subversion_run(self, commands, removals): - self.svn_tmpdir = tempfile.mkdtemp(prefix=self.name + '-svn-') - removals.append((shutil.rmtree, 'rm -rf %%s', self.svn_tmpdir)) - - self.scons = self.scons_path(self.svn_tmpdir) - self.scons_lib_dir = self.scons_lib_dir_path(self.svn_tmpdir) - - commands.extend([ - '%(svn)s co %(svn_co_flag)s -r %(run_number)s %(subversion_url)s %(svn_tmpdir)s', - ]) - - def individual_run(self, run_number, archive_list, prepare=None): - """ - Performs an individual run of the default SCons invocations. - """ - - commands = [] - removals = [] - - if prepare: - prepare(commands, removals) - - save_scons = self.scons - save_scons_wrapper = self.scons_wrapper - save_scons_lib_dir = self.scons_lib_dir - - if self.outdir is None: - self.outdir = self.orig_cwd - elif not os.path.isabs(self.outdir): - self.outdir = os.path.join(self.orig_cwd, self.outdir) - - if self.scons is None: - self.scons = self.scons_path(self.orig_cwd) - - if self.scons_lib_dir is None: - self.scons_lib_dir = self.scons_lib_dir_path(self.orig_cwd) - - if self.scons_wrapper is None: - self.scons_wrapper = self.scons - - if not run_number: - run_number = self.find_next_run_number(self.outdir, self.prefix) - - self.run_number = str(run_number) - - self.prefix_run = self.prefix + '-%03d' % run_number - - if self.targets0 is None: - self.targets0 = self.startup_targets - if self.targets1 is None: - self.targets1 = self.targets - if self.targets2 is None: - self.targets2 = self.targets - - self.tmpdir = tempfile.mkdtemp(prefix=self.name + '-') - - commands.extend([ - (os.chdir, 'cd %%s', self.tmpdir), - ]) - - for archive in archive_list: - if not os.path.isabs(archive): - archive = os.path.join(self.orig_cwd, archive) - if os.path.isdir(archive): - dest = os.path.split(archive)[1] - commands.append((shutil.copytree, 'cp -r %%s %%s', archive, dest)) - else: - suffix = self.archive_splitext(archive)[1] - unpack_command = self.unpack_map.get(suffix) - if not unpack_command: - dest = os.path.split(archive)[1] - commands.append((shutil.copyfile, 'cp %%s %%s', archive, dest)) - else: - commands.append(unpack_command + (archive,)) - - commands.extend([ - (os.chdir, 'cd %%s', self.subdir), - ]) - - commands.extend(self.initial_commands) - - commands.extend([ - (lambda: read_tree('.'), - 'find * -type f | xargs cat > /dev/null'), - - (self.set_env, 'export %%s=%%s', - 'SCONS_LIB_DIR', self.scons_lib_dir), - - '%(python)s %(scons_wrapper)s --version', - ]) - - index = 0 - for run_command in self.run_commands: - setattr(self, 'prof%d' % index, self.profile_name(index)) - c = ( - self.log_execute, - self.log_display, - run_command, - self.logfile_name(index), - ) - commands.append(c) - index = index + 1 - - commands.extend([ - (os.chdir, 'cd %%s', self.orig_cwd), - ]) - - if not os.environ.get('PRESERVE'): - commands.extend(removals) - commands.append((shutil.rmtree, 'rm -rf %%s', self.tmpdir)) - - self.run_command_list(commands, self.__dict__) - - self.scons = save_scons - self.scons_lib_dir = save_scons_lib_dir - self.scons_wrapper = save_scons_wrapper - - # - - def help_time(self): - help = """\ - Usage: scons-time time [OPTIONS] FILE [...] - - -C DIR, --chdir=DIR Change to DIR before looking for files - -f FILE, --file=FILE Read configuration from specified FILE - --fmt=FORMAT, --format=FORMAT Print data in specified FORMAT - -h, --help Print this help and exit - -p STRING, --prefix=STRING Use STRING as log file/profile prefix - -t NUMBER, --tail=NUMBER Only report the last NUMBER files - --which=TIMER Plot timings for TIMER: total, - SConscripts, SCons, commands. - """ - sys.stdout.write(self.outdent(help)) - sys.stdout.flush() - - def do_time(self, argv): - - format = 'ascii' - logfile_path = lambda x: x - tail = None - which = 'total' - - short_opts = '?C:f:hp:t:' - - long_opts = [ - 'chdir=', - 'file=', - 'fmt=', - 'format=', - 'help', - 'prefix=', - 'tail=', - 'title=', - 'which=', - ] - - opts, args = getopt.getopt(argv[1:], short_opts, long_opts) - - for o, a in opts: - if o in ('-C', '--chdir'): - self.chdir = a - elif o in ('-f', '--file'): - self.config_file = a - elif o in ('--fmt', '--format'): - format = a - elif o in ('-?', '-h', '--help'): - self.do_help(['help', 'time']) - sys.exit(0) - elif o in ('-p', '--prefix'): - self.prefix = a - elif o in ('-t', '--tail'): - tail = int(a) - elif o in ('--title',): - self.title = a - elif o in ('--which',): - if a not in list(self.time_strings.keys()): - sys.stderr.write('%s: time: Unrecognized timer "%s".\n' % (self.name, a)) - sys.stderr.write('%s Type "%s help time" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - which = a - - if self.config_file: - with open(self.config_file, 'r') as f: - config = f.read() - HACK_for_exec(config, self.__dict__) - - if self.chdir: - os.chdir(self.chdir) - logfile_path = lambda x: os.path.join(self.chdir, x) - - if not args: - - pattern = '%s*.log' % self.prefix - args = self.args_to_files([pattern], tail) - - if not args: - if self.chdir: - directory = self.chdir - else: - directory = os.getcwd() - - sys.stderr.write('%s: time: No arguments specified.\n' % self.name) - sys.stderr.write('%s No %s*.log files found in "%s".\n' % (self.name_spaces, self.prefix, directory)) - sys.stderr.write('%s Type "%s help time" for help.\n' % (self.name_spaces, self.name)) - sys.exit(1) - - else: - - args = self.args_to_files(args, tail) - - cwd_ = os.getcwd() + os.sep - - if format == 'ascii': - - columns = ("Total", "SConscripts", "SCons", "commands") - self.ascii_table(args, columns, self.get_debug_times, logfile_path) - - elif format == 'gnuplot': - - results = self.collect_results(args, self.get_debug_times, - self.time_strings[which]) - - self.gnuplot_results(results, fmt='%s %.6f') - - else: - - sys.stderr.write('%s: time: Unknown format "%s".\n' % (self.name, format)) - sys.exit(1) - -if __name__ == '__main__': - opts, args = getopt.getopt(sys.argv[1:], 'h?V', ['help', 'version']) - - ST = SConsTimer() - - for o, a in opts: - if o in ('-?', '-h', '--help'): - ST.do_help(['help']) - sys.exit(0) - elif o in ('-V', '--version'): - sys.stdout.write('scons-time version\n') - sys.exit(0) - - if not args: - sys.stderr.write('Type "%s help" for usage.\n' % ST.name) - sys.exit(1) - - ST.execute_subcommand(args) - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/testing/framework/TestSCons_time.py b/testing/framework/TestSCons_time.py index c6373eb..0573404 100644 --- a/testing/framework/TestSCons_time.py +++ b/testing/framework/TestSCons_time.py @@ -158,7 +158,7 @@ class TestSCons_time(TestCommon): self.orig_cwd = os.getcwd() try: - script_dir = os.environ['SCONS_SCRIPT_DIR'] + script_dir = os.environ['SCONS_TOOLS_DIR'] except KeyError: pass else: @@ -173,8 +173,6 @@ class TestSCons_time(TestCommon): if 'interpreter' not in kw: kw['interpreter'] = [python,] - if sys.version_info[0] < 3: - kw['interpreter'].append('-tt') if 'match' not in kw: kw['match'] = match_exact -- cgit v0.12 From 7b5438367cd25d1cb093a323d4b9c997cd26fd79 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 21 Mar 2020 21:41:14 -0700 Subject: Fix quoting on IMPLICIT_COMMAND_DEPENDENCIES=all --- test/Repository/StaticLibrary.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Repository/StaticLibrary.py b/test/Repository/StaticLibrary.py index 29cb841..c4a901b 100644 --- a/test/Repository/StaticLibrary.py +++ b/test/Repository/StaticLibrary.py @@ -30,7 +30,7 @@ import TestSCons _obj = TestSCons._obj _exe = TestSCons._exe -for implicit_deps in ['1', '2']: +for implicit_deps in ['0', '1', '2', '\"all\"']: test = TestSCons.TestSCons() # -- cgit v0.12 From 8a4074083f20090e9092f67b888275d4c83763a2 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 22 Mar 2020 13:15:09 -0700 Subject: Change location of scons.py to scripts --- bootstrap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap.py b/bootstrap.py index d47c966..7d8528a 100755 --- a/bootstrap.py +++ b/bootstrap.py @@ -183,7 +183,7 @@ def main(): else: pass_through_args.append(arg) - scons_py = os.path.join('src', 'script', 'scons.py') + scons_py = os.path.join('scripts', 'scons.py') src_engine = os.path.join('src', 'engine') MANIFEST_in = find(os.path.join(src_engine, 'MANIFEST.in')) manifest_files = [os.path.join(src_engine, x) -- cgit v0.12 From 26b4d168832b27d89962c5faf9a2ed75b174abc8 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 22 Mar 2020 13:15:39 -0700 Subject: Disable generating API docs for now epydoc is unmaintained and (?) not working with py3. Need to switch to sphinx(?) --- doc/SConscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/SConscript b/doc/SConscript index 8b22b3b..6a522d0 100644 --- a/doc/SConscript +++ b/doc/SConscript @@ -499,7 +499,7 @@ else: Local(css_file) if not skip_doc: - if not epydoc_cli and not epydoc: + if True: #not epydoc_cli and not epydoc: print("doc: epydoc not found, skipping building API documentation.") else: # XXX Should be in common with reading the same thing in -- cgit v0.12 From e836436961ed13cf430452bfe81016aea243dbe3 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 22 Mar 2020 13:23:06 -0700 Subject: remove gentoo ebuild logic. distro packager has their own --- SConstruct | 10 +--------- gentoo/scons.ebuild.in | 26 -------------------------- 2 files changed, 1 insertion(+), 35 deletions(-) delete mode 100644 gentoo/scons.ebuild.in diff --git a/SConstruct b/SConstruct index f696499..97fda1d 100644 --- a/SConstruct +++ b/SConstruct @@ -486,15 +486,7 @@ Version_values = [Value(command_line.version), Value(command_line.build_id)] # '$PYTHON $PYTHONFLAGS "%s" install "--prefix=$TEST_TAR_GZ_DIR" --standalone-lib' % \ # os.path.join(unpack_tar_gz_dir, pkg_version, 'setup.py'), # ]) -# -# # -# # Generate portage files for submission to Gentoo Linux. -# # -# gentoo = os.path.join(build, 'gentoo') -# ebuild = os.path.join(gentoo, 'scons-%s.ebuild' % command_line.version) -# digest = os.path.join(gentoo, 'files', 'digest-scons-%s' % command_line.version) -# env.Command(ebuild, os.path.join('gentoo', 'scons.ebuild.in'), SCons_revision) -# +## # # def Digestify(target, source, env): # import hashlib diff --git a/gentoo/scons.ebuild.in b/gentoo/scons.ebuild.in deleted file mode 100644 index 50c9ad9..0000000 --- a/gentoo/scons.ebuild.in +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright 1999-2003 Gentoo Technologies, Inc. -# Distributed under the terms of the GNU General Public License v2 -# $__NULL__Header: /home/cvsroot/gentoo-x86/dev-util/scons/scons-__VERSION__.ebuild,v 1.2 2003/02/13 12:00:11 vapier Exp __NULL__$ - -MY_P=${PN}-__VERSION__ -S=${WORKDIR}/${MY_P} -DESCRIPTION="Extensible python-based build utility" -SRC_URI="mirror://sourceforge/${PN}/${MY_P}.tar.gz" -HOMEPAGE="http://www.scons.org" - -SLOT="0" -LICENSE="as-is" -KEYWORDS="~x86 ~sparc" - -DEPEND=">=dev-lang/python-2.4" - -src_compile() { - python setup.py build -} - -src_install () { - python setup.py install --root=${D} - dodoc *.txt PKG-INFO MANIFEST - doman scons.1 - doman sconsign.1 -} -- cgit v0.12 From 559a661338b1c6988107de4a3caf8c49d2ee708d Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 22 Mar 2020 21:01:46 -0700 Subject: add logic to not include *Tests.py in wheel --- MANIFEST.in | 6 +- SConstruct | 640 ------------------------------------------------- setup.py | 25 +- src/MANIFEST.in | 0 src/engine/MANIFEST.in | 186 -------------- src/setup.cfg | 8 - src/setup.py | 522 ---------------------------------------- 7 files changed, 26 insertions(+), 1361 deletions(-) delete mode 100644 src/MANIFEST.in delete mode 100644 src/engine/MANIFEST.in delete mode 100644 src/setup.cfg delete mode 100755 src/setup.py diff --git a/MANIFEST.in b/MANIFEST.in index 4e4ae5a..04aee14 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,3 +1,5 @@ -recursive-exclude src/engine *Tests.py -global-exclude *Tests.py +global-exclude **Tests.py + recursive-include src/engine/SCons/Tool/docbook * + + diff --git a/SConstruct b/SConstruct index 97fda1d..a76471f 100644 --- a/SConstruct +++ b/SConstruct @@ -184,470 +184,6 @@ env = Environment( Version_values = [Value(command_line.version), Value(command_line.build_id)] -# -# Define SCons packages. -# -# In the original, more complicated packaging scheme, we were going -# to have separate packages for: -# -# python-scons only the build engine -# scons-script only the script -# scons the script plus the build engine -# -# We're now only delivering a single "scons" package, but this is still -# "built" as two sub-packages (the build engine and the script), so -# the definitions remain here, even though we're not using them for -# separate packages. -# - -# from distutils.sysconfig import get_python_lib -# -# python_scons = { -# 'pkg': 'python-' + project, -# 'src_subdir': 'engine', -# 'inst_subdir': get_python_lib(), -# -# 'files': ['LICENSE.txt', -# 'README.txt', -# 'setup.cfg', -# 'setup.py', -# ], -# -# 'filemap': { -# 'LICENSE.txt': '../LICENSE.txt' -# }, -# -# 'buildermap': {}, -# -# 'explicit_deps': { -# 'SCons/__init__.py': Version_values, -# }, -# } - -# scons_script = { -# 'pkg': project + '-script', -# 'src_subdir': 'script', -# 'inst_subdir': 'bin', -# -# 'files': [ -# 'LICENSE.txt', -# 'README.txt', -# 'setup.cfg', -# 'setup.py', -# ], -# -# 'filemap': { -# 'LICENSE.txt': '../LICENSE.txt', -# 'scons': 'scons.py', -# 'sconsign': 'sconsign.py', -# 'scons-time': 'scons-time.py', -# 'scons-configure-cache': 'scons-configure-cache.py', -# }, -# -# 'buildermap': {}, -# -# 'explicit_deps': { -# 'scons': Version_values, -# 'sconsign': Version_values, -# }, -# } - -# scons = { -# 'pkg': project, -# -# 'files': [ -# 'CHANGES.txt', -# 'LICENSE.txt', -# 'README.txt', -# 'RELEASE.txt', -# 'scons.1', -# 'sconsign.1', -# 'scons-time.1', -# # 'script/scons.bat', -# 'setup.cfg', -# 'setup.py', -# ], -# -# 'filemap': { -# 'scons.1': '$BUILDDIR/doc/man/scons.1', -# 'sconsign.1': '$BUILDDIR/doc/man/sconsign.1', -# 'scons-time.1': '$BUILDDIR/doc/man/scons-time.1', -# }, -# -# 'buildermap': { -# 'scons.1': env.SOElim, -# 'sconsign.1': env.SOElim, -# 'scons-time.1': env.SOElim, -# }, -# -# 'subpkgs': [python_scons], -# -# 'subinst_dirs': { -# 'python-' + project: python_project_subinst_dir, -# project + '-script': project_script_subinst_dir, -# }, -# } -# -# scripts = ['scons', 'sconsign', 'scons-time', 'scons-configure-cache'] -# -# src_deps = [] -# src_files = [] -# -# for p in [scons]: -# # -# # Initialize variables with the right directories for this package. -# # -# pkg = p['pkg'] -# pkg_version = "%s-%s" % (pkg, command_line.version) -# -# src = 'src' -# if 'src_subdir' in p: -# src = os.path.join(src, p['src_subdir']) -# -# build = os.path.join(command_line.build_dir, pkg) -# -# tar_gz = os.path.join(build, 'dist', "%s.tar.gz" % pkg_version) -# platform_tar_gz = os.path.join(build, -# 'dist', -# "%s.%s.tar.gz" % (pkg_version, platform)) -# zip = os.path.join(build, 'dist', "%s.zip" % pkg_version) -# platform_zip = os.path.join(build, -# 'dist', -# "%s.%s.zip" % (pkg_version, platform)) -# -# # -# # Update the environment with the relevant information -# # for this package. -# # -# # We can get away with calling setup.py using a directory path -# # like this because we put a preamble in it that will chdir() -# # to the directory in which setup.py exists. -# # -# setup_py = os.path.join(build, 'setup.py') -# env.Replace(PKG=pkg, -# PKG_VERSION=pkg_version, -# SETUP_PY='"%s"' % setup_py) -# Local(setup_py) -# -# # -# # Read up the list of source files from our MANIFEST.in. -# # This list should *not* include LICENSE.txt, MANIFEST, -# # README.txt, or setup.py. Make a copy of the list for the -# # destination files. -# # -# manifest_in = File(os.path.join(src, 'MANIFEST.in')).rstr() -# src_files = bootstrap.parseManifestLines(src, manifest_in) -# raw_files = src_files[:] -# dst_files = src_files[:] -# -# MANIFEST_in_list = [] -# -# if 'subpkgs' in p: -# # -# # This package includes some sub-packages. Read up their -# # MANIFEST.in files, and add them to our source and destination -# # file lists, modifying them as appropriate to add the -# # specified subdirs. -# # -# for sp in p['subpkgs']: -# ssubdir = sp['src_subdir'] -# isubdir = p['subinst_dirs'][sp['pkg']] -# -# MANIFEST_in = File(os.path.join(src, ssubdir, 'MANIFEST.in')).rstr() -# MANIFEST_in_list.append(MANIFEST_in) -# files = bootstrap.parseManifestLines(os.path.join(src, ssubdir), MANIFEST_in) -# -# raw_files.extend(files) -# src_files.extend([os.path.join(ssubdir, x) for x in files]) -# -# files = [os.path.join(isubdir, x) for x in files] -# dst_files.extend(files) -# for k, f in sp['filemap'].items(): -# if f: -# k = os.path.join(ssubdir, k) -# p['filemap'][k] = os.path.join(ssubdir, f) -# for f, deps in sp['explicit_deps'].items(): -# f = os.path.join(build, ssubdir, f) -# env.Depends(f, deps) -# -# # -# # Now that we have the "normal" source files, add those files -# # that are standard for each distribution. Note that we don't -# # add these to dst_files, because they don't get installed. -# # And we still have the MANIFEST to add. -# # -# src_files.extend(p['files']) -# -# # -# # Now run everything in src_file through the sed command we -# # concocted to expand __FILE__, __VERSION__, etc. -# # -# for b in src_files: -# s = p['filemap'].get(b, b) -# if not s[0] == '$' and not os.path.isabs(s): -# s = os.path.join(src, s) -# -# builder = p['buildermap'].get(b, env.SCons_revision) -# x = builder(os.path.join(build, b), s) -# -# Local(x) -# -# # -# # NOW, finally, we can create the MANIFEST, which we do -# # by having Python spit out the contents of the src_files -# # array we've carefully created. After we've added -# # MANIFEST itself to the array, of course. -# # -# src_files.append("MANIFEST") -# MANIFEST_in_list.append(os.path.join(src, 'MANIFEST.in')) -# -# -# def write_src_files(target, source, **kw): -# global src_files -# src_files.sort() -# with open(str(target[0]), 'w') as f: -# for file in src_files: -# f.write(file + "\n") -# return 0 -# -# -# env.Command(os.path.join(build, 'MANIFEST'), -# MANIFEST_in_list, -# write_src_files) -# -# # -# # Now go through and arrange to create whatever packages we can. -# # -# build_src_files = [os.path.join(build, x) for x in src_files] -# Local(*build_src_files) -# -# distutils_formats = [] -# distutils_targets = [] -# dist_distutils_targets = [] -# -# for target in distutils_targets: -# dist_target = env.Install('$DISTDIR', target) -# AddPostAction(dist_target, Chmod(dist_target, 0o644)) -# dist_distutils_targets += dist_target -# -# if not gzip: -# print("gzip not found in %s; skipping .tar.gz package for %s." % (os.environ['PATH'], pkg)) -# else: -# -# distutils_formats.append('gztar') -# -# src_deps.append(tar_gz) -# -# distutils_targets.extend([tar_gz, platform_tar_gz]) -# -# dist_tar_gz = env.Install('$DISTDIR', tar_gz) -# dist_platform_tar_gz = env.Install('$DISTDIR', platform_tar_gz) -# Local(dist_tar_gz, dist_platform_tar_gz) -# AddPostAction(dist_tar_gz, Chmod(dist_tar_gz, 0o644)) -# AddPostAction(dist_platform_tar_gz, Chmod(dist_platform_tar_gz, 0o644)) -# -# # -# # Unpack the tar.gz archive created by the distutils into -# # build/unpack-tar-gz/scons-{version}. -# # -# # We'd like to replace the last three lines with the following: -# # -# # tar zxf $SOURCES -C $UNPACK_TAR_GZ_DIR -# # -# # but that gives heartburn to Cygwin's tar, so work around it -# # with separate zcat-tar-rm commands. -# # -# unpack_tar_gz_files = [os.path.join(unpack_tar_gz_dir, pkg_version, x) -# for x in src_files] -# env.Command(unpack_tar_gz_files, dist_tar_gz, [ -# Delete(os.path.join(unpack_tar_gz_dir, pkg_version)), -# "$ZCAT $SOURCES > .temp", -# "tar xf .temp -C $UNPACK_TAR_GZ_DIR", -# Delete(".temp"), -# ]) -# -# # -# # Run setup.py in the unpacked subdirectory to "install" everything -# # into our build/test subdirectory. The runtest.py script will set -# # PYTHONPATH so that the tests only look under build/test-{package}, -# # and under testing/framework (for the testing modules TestCmd.py, TestSCons.py, -# # etc.). This makes sure that our tests pass with what -# # we really packaged, not because of something hanging around in -# # the development directory. -# # -# # We can get away with calling setup.py using a directory path -# # like this because we put a preamble in it that will chdir() -# # to the directory in which setup.py exists. -# # -# dfiles = [os.path.join(test_tar_gz_dir, x) for x in dst_files] -# env.Command(dfiles, unpack_tar_gz_files, [ -# Delete(os.path.join(unpack_tar_gz_dir, pkg_version, 'build')), -# Delete("$TEST_TAR_GZ_DIR"), -# '$PYTHON $PYTHONFLAGS "%s" install "--prefix=$TEST_TAR_GZ_DIR" --standalone-lib' % \ -# os.path.join(unpack_tar_gz_dir, pkg_version, 'setup.py'), -# ]) -## -# -# def Digestify(target, source, env): -# import hashlib -# src = source[0].rfile() -# with open(str(src), 'rb') as f: -# contents = f.read() -# m = hashlib.md5() -# m.update(contents) -# sig = m.hexdigest() -# bytes = os.stat(str(src))[6] -# with open(str(target[0]), 'w') as f: -# f.write("MD5 %s %s %d\n" % (sig, src.name, bytes)) -# -# -# env.Command(digest, tar_gz, Digestify) -# -# if not zipit: -# print("zip not found; skipping .zip package for %s." % pkg) -# else: -# -# distutils_formats.append('zip') -# -# src_deps.append(zip) -# -# distutils_targets.extend([zip, platform_zip]) -# -# dist_zip = env.Install('$DISTDIR', zip) -# dist_platform_zip = env.Install('$DISTDIR', platform_zip) -# Local(dist_zip, dist_platform_zip) -# AddPostAction(dist_zip, Chmod(dist_zip, 0o644)) -# AddPostAction(dist_platform_zip, Chmod(dist_platform_zip, 0o644)) -# -# # -# # Unpack the zip archive created by the distutils into -# # build/unpack-zip/scons-{version}. -# # -# unpack_zip_files = [os.path.join(unpack_zip_dir, pkg_version, x) -# for x in src_files] -# -# env.Command(unpack_zip_files, dist_zip, [ -# Delete(os.path.join(unpack_zip_dir, pkg_version)), -# unzipit, -# ]) -# -# # -# # Run setup.py in the unpacked subdirectory to "install" everything -# # into our build/test subdirectory. The runtest.py script will set -# # PYTHONPATH so that the tests only look under build/test-{package}, -# # and under testing/framework (for the testing modules TestCmd.py, TestSCons.py, -# # etc.). This makes sure that our tests pass with what -# # we really packaged, not because of something hanging around in -# # the development directory. -# # -# # We can get away with calling setup.py using a directory path -# # like this because we put a preamble in it that will chdir() -# # to the directory in which setup.py exists. -# # -# dfiles = [os.path.join(test_zip_dir, x) for x in dst_files] -# env.Command(dfiles, unpack_zip_files, [ -# Delete(os.path.join(unpack_zip_dir, pkg_version, 'build')), -# Delete("$TEST_ZIP_DIR"), -# '$PYTHON $PYTHONFLAGS "%s" install "--prefix=$TEST_ZIP_DIR" --standalone-lib' % \ -# os.path.join(unpack_zip_dir, pkg_version, 'setup.py'), -# ]) -# -# # -# # Use the Python distutils to generate the appropriate packages. -# # -# commands = [ -# Delete(os.path.join(build, 'build', 'lib')), -# Delete(os.path.join(build, 'build', 'scripts')), -# ] -# -# if distutils_formats: -# commands.append(Delete(os.path.join(build, -# 'build', -# 'bdist.' + platform, -# 'dumb'))) -# for format in distutils_formats: -# commands.append("$PYTHON $PYTHONFLAGS $SETUP_PY bdist_dumb -f %s" % format) -# -# commands.append("$PYTHON $PYTHONFLAGS $SETUP_PY sdist --formats=%s" % \ -# ','.join(distutils_formats)) -# -# env.Command(distutils_targets, build_src_files, commands) -# -# # -# # Now create local packages for people who want to let people -# # build their SCons-buildable packages without having to -# # install SCons. -# # -# s_l_v = '%s-local-%s' % (pkg, command_line.version) -# -# local = pkg + '-local' -# build_dir_local = os.path.join(command_line.build_dir, local) -# build_dir_local_slv = os.path.join(command_line.build_dir, local, s_l_v) -# -# dist_local_tar_gz = os.path.join("$DISTDIR/%s.tar.gz" % s_l_v) -# dist_local_zip = os.path.join("$DISTDIR/%s.zip" % s_l_v) -# AddPostAction(dist_local_tar_gz, Chmod(dist_local_tar_gz, 0o644)) -# AddPostAction(dist_local_zip, Chmod(dist_local_zip, 0o644)) -# -# commands = [ -# Delete(build_dir_local), -# '$PYTHON $PYTHONFLAGS $SETUP_PY install "--install-script=%s" "--install-lib=%s" --no-install-man --no-compile --standalone-lib --no-version-script' % \ -# (build_dir_local, build_dir_local_slv), -# ] -# -# for script in scripts: -# # add .py extension for scons-local scripts on non-windows platforms -# if is_windows(): -# break -# local_script = os.path.join(build_dir_local, script) -# commands.append(Move(local_script + '.py', local_script)) -# -# rf = [x for x in raw_files if not x in scripts] -# rf = [os.path.join(s_l_v, x) for x in rf] -# for script in scripts: -# rf.append("%s.py" % script) -# local_targets = [os.path.join(build_dir_local, x) for x in rf] -# -# env.Command(local_targets, build_src_files, commands) -# -# scons_LICENSE = os.path.join(build_dir_local, 'scons-LICENSE') -# l = env.SCons_revision(scons_LICENSE, 'LICENSE-local') -# local_targets.append(l) -# Local(l) -# -# scons_README = os.path.join(build_dir_local, 'scons-README') -# l = env.SCons_revision(scons_README, 'README-local') -# local_targets.append(l) -# Local(l) -# -# if gzip: -# if is_windows(): -# # avoid problem with tar interpreting c:/ as a remote machine -# tar_cargs = '-cz --force-local -f' -# else: -# tar_cargs = '-czf' -# env.Command(dist_local_tar_gz, -# local_targets, -# "cd %s && tar %s $( ${TARGET.abspath} $) *" % (build_dir_local, tar_cargs)) -# -# unpack_targets = [os.path.join(test_local_tar_gz_dir, x) for x in rf] -# commands = [Delete(test_local_tar_gz_dir), -# Mkdir(test_local_tar_gz_dir), -# "cd %s && tar xzf $( ${SOURCE.abspath} $)" % test_local_tar_gz_dir] -# -# env.Command(unpack_targets, dist_local_tar_gz, commands) -# -# if zipit: -# env.Command(dist_local_zip, local_targets, zipit, -# CD=build_dir_local, PSV='.') -# -# unpack_targets = [os.path.join(test_local_zip_dir, x) for x in rf] -# commands = [Delete(test_local_zip_dir), -# Mkdir(test_local_zip_dir), -# unzipit] -# -# env.Command(unpack_targets, dist_local_zip, unzipit, -# UNPACK_ZIP_DIR=test_local_zip_dir) # # @@ -659,179 +195,3 @@ Export('command_line', 'env', 'whereis', 'revaction') SConscript('doc/SConscript') -# # -# # If we're running in a Git working directory, pack up a complete -# # source archive from the project files and files in the change. -# # -# -# -# sfiles = [l.split()[-1] for l in command_line.git_status_lines] -# if command_line.git_status_lines: -# # slines = [l for l in git_status_lines if 'modified:' in l] -# # sfiles = [l.split()[-1] for l in slines] -# pass -# else: -# print("Not building in a Git tree; skipping building src package.") -# -# if sfiles: -# remove_patterns = [ -# '*.gitignore', -# '*.hgignore', -# 'www/*', -# ] -# -# for p in remove_patterns: -# sfiles = [s for s in sfiles if not fnmatch.fnmatch(s, p)] -# -# if sfiles: -# ps = "%s-src" % project -# psv = "%s-%s" % (ps, command_line.version) -# b_ps = os.path.join(command_line.build_dir, ps) -# b_psv = os.path.join(command_line.build_dir, psv) -# b_psv_stamp = b_psv + '-stamp' -# -# src_tar_gz = os.path.join(command_line.build_dir, 'dist', '%s.tar.gz' % psv) -# src_zip = os.path.join(command_line.build_dir, 'dist', '%s.zip' % psv) -# -# Local(src_tar_gz, src_zip) -# -# for file in sfiles: -# if file.endswith('jpg') or file.endswith('png'): -# # don't revision binary files. -# env.Install(os.path.dirname(os.path.join(b_ps, file)), file) -# else: -# env.SCons_revision(os.path.join(b_ps, file), file) -# -# b_ps_files = [os.path.join(b_ps, x) for x in sfiles] -# cmds = [ -# Delete(b_psv), -# Copy(b_psv, b_ps), -# Touch("$TARGET"), -# ] -# -# env.Command(b_psv_stamp, src_deps + b_ps_files, cmds) -# -# Local(*b_ps_files) -# -# if gzip: -# env.Command(src_tar_gz, b_psv_stamp, -# "tar cz${TAR_HFLAG} -f $TARGET -C build %s" % psv) -# -# # -# # Unpack the archive into build/unpack/scons-{version}. -# # -# unpack_tar_gz_files = [os.path.join(unpack_tar_gz_dir, psv, x) -# for x in sfiles] -# -# # -# # We'd like to replace the last three lines with the following: -# # -# # tar zxf $SOURCES -C $UNPACK_TAR_GZ_DIR -# # -# # but that gives heartburn to Cygwin's tar, so work around it -# # with separate zcat-tar-rm commands. -# env.Command(unpack_tar_gz_files, src_tar_gz, [ -# Delete(os.path.join(unpack_tar_gz_dir, psv)), -# "$ZCAT $SOURCES > .temp", -# "tar xf .temp -C $UNPACK_TAR_GZ_DIR", -# Delete(".temp"), -# ]) -# -# # -# # Run setup.py in the unpacked subdirectory to "install" everything -# # into our build/test subdirectory. The runtest.py script will set -# # PYTHONPATH so that the tests only look under build/test-{package}, -# # and under testing/framework (for the testing modules TestCmd.py, -# # TestSCons.py, etc.). This makes sure that our tests pass with -# # what we really packaged, not because of something hanging around -# # in the development directory. -# # -# # We can get away with calling setup.py using a directory path -# # like this because we put a preamble in it that will chdir() -# # to the directory in which setup.py exists. -# # -# dfiles = [os.path.join(test_src_tar_gz_dir, x) for x in dst_files] -# scons_lib_dir = os.path.join(unpack_tar_gz_dir, psv, 'src', 'engine') -# ENV = env.Dictionary('ENV').copy() -# ENV['SCONS_LIB_DIR'] = scons_lib_dir -# ENV['USERNAME'] = command_line.developer -# env.Command(dfiles, unpack_tar_gz_files, -# [ -# Delete(os.path.join(unpack_tar_gz_dir, -# psv, -# 'build', -# 'scons', -# 'build')), -# Delete("$TEST_SRC_TAR_GZ_DIR"), -# 'cd "%s" && $PYTHON $PYTHONFLAGS "%s" "%s" VERSION="$VERSION"' % \ -# (os.path.join(unpack_tar_gz_dir, psv), -# os.path.join('src', 'script', 'scons.py'), -# os.path.join('build', 'scons')), -# '$PYTHON $PYTHONFLAGS "%s" install "--prefix=$TEST_SRC_TAR_GZ_DIR" --standalone-lib' % \ -# os.path.join(unpack_tar_gz_dir, -# psv, -# 'build', -# 'scons', -# 'setup.py'), -# ], -# ENV=ENV) -# -# if zipit: -# env.Command(src_zip, b_psv_stamp, zipit, CD='build', PSV=psv) -# -# # -# # Unpack the archive into build/unpack/scons-{version}. -# # -# unpack_zip_files = [os.path.join(unpack_zip_dir, psv, x) -# for x in sfiles] -# -# env.Command(unpack_zip_files, src_zip, [ -# Delete(os.path.join(unpack_zip_dir, psv)), -# unzipit -# ]) -# -# # -# # Run setup.py in the unpacked subdirectory to "install" everything -# # into our build/test subdirectory. The runtest.py script will set -# # PYTHONPATH so that the tests only look under build/test-{package}, -# # and under testing/framework (for the testing modules TestCmd.py, -# # TestSCons.py, etc.). This makes sure that our tests pass with -# # what we really packaged, not because of something hanging -# # around in the development directory. -# # -# # We can get away with calling setup.py using a directory path -# # like this because we put a preamble in it that will chdir() -# # to the directory in which setup.py exists. -# # -# dfiles = [os.path.join(test_src_zip_dir, x) for x in dst_files] -# scons_lib_dir = os.path.join(unpack_zip_dir, psv, 'src', 'engine') -# ENV = env.Dictionary('ENV').copy() -# ENV['SCONS_LIB_DIR'] = scons_lib_dir -# ENV['USERNAME'] = command_line.developer -# env.Command(dfiles, unpack_zip_files, -# [ -# Delete(os.path.join(unpack_zip_dir, -# psv, -# 'build', -# 'scons', -# 'build')), -# Delete("$TEST_SRC_ZIP_DIR"), -# 'cd "%s" && $PYTHON $PYTHONFLAGS "%s" "%s" VERSION="$VERSION"' % \ -# (os.path.join(unpack_zip_dir, psv), -# os.path.join('src', 'script', 'scons.py'), -# os.path.join('build', 'scons')), -# '$PYTHON $PYTHONFLAGS "%s" install "--prefix=$TEST_SRC_ZIP_DIR" --standalone-lib' % \ -# os.path.join(unpack_zip_dir, -# psv, -# 'build', -# 'scons', -# 'setup.py'), -# ], -# ENV=ENV) -# -# for pf, help_text in packaging_flavors: -# Alias(pf, [ -# os.path.join(command_line.build_dir, 'test-' + pf), -# os.path.join(command_line.build_dir, 'testing/framework'), -# os.path.join(command_line.build_dir, 'runtest.py'), -# ]) diff --git a/setup.py b/setup.py index ff975d4..349a24e 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,25 @@ -from setuptools import setup,find_packages +import fnmatch +from setuptools import find_packages, setup +from setuptools.command.build_py import build_py as build_py_orig + + +exclude = ['*Tests'] + + +class build_py(build_py_orig): + + def find_package_modules(self, package, package_dir): + """ + Custom module to find package modules. + It will strip out any modules which match the glob patters in exclude above + """ + modules = super().find_package_modules(package, package_dir) + return [(pkg, mod, file, ) for (pkg, mod, file, ) in modules + if not any(fnmatch.fnmatchcase(mod, pat=pattern) + for pattern in exclude)] setup( - # packages = find_packages("src/engine"), - # package_dir={"":"src/engine"}, + cmdclass={ + 'build_py': build_py, + } ) \ No newline at end of file diff --git a/src/MANIFEST.in b/src/MANIFEST.in deleted file mode 100644 index e69de29..0000000 diff --git a/src/engine/MANIFEST.in b/src/engine/MANIFEST.in deleted file mode 100644 index 3c2c0c2..0000000 --- a/src/engine/MANIFEST.in +++ /dev/null @@ -1,186 +0,0 @@ -SCons/__init__.py -SCons/__main__.py -SCons/Action.py -SCons/Builder.py -SCons/compat/*.py -SCons/CacheDir.py -SCons/Conftest.py -SCons/cpp.py -SCons/dblite.py -SCons/Debug.py -SCons/Defaults.py -SCons/Environment.py -SCons/Errors.py -SCons/Executor.py -SCons/Job.py -SCons/exitfuncs.py -SCons/Memoize.py -SCons/Node/__init__.py -SCons/Node/Alias.py -SCons/Node/FS.py -SCons/Node/Python.py -SCons/PathList.py -SCons/Platform/__init__.py -SCons/Platform/aix.py -SCons/Platform/cygwin.py -SCons/Platform/darwin.py -SCons/Platform/hpux.py -SCons/Platform/irix.py -SCons/Platform/os2.py -SCons/Platform/mingw.py -SCons/Platform/posix.py -SCons/Platform/sunos.py -SCons/Platform/win32.py -SCons/Platform/virtualenv.py -SCons/Scanner/__init__.py -SCons/Scanner/C.py -SCons/Scanner/D.py -SCons/Scanner/Dir.py -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 -SCons/SConsign.py -SCons/Script/__init__.py -SCons/Script/Interactive.py -SCons/Script/Main.py -SCons/Script/SConscript.py -SCons/Script/SConsOptions.py -SCons/Subst.py -SCons/Taskmaster.py -SCons/Tool/__init__.py -SCons/Tool/386asm.py -SCons/Tool/aixc++.py -SCons/Tool/aixcxx.py -SCons/Tool/aixcc.py -SCons/Tool/aixf77.py -SCons/Tool/aixlink.py -SCons/Tool/applelink.py -SCons/Tool/ar.py -SCons/Tool/as.py -SCons/Tool/bcc32.py -SCons/Tool/c++.py -SCons/Tool/cxx.py -SCons/Tool/cc.py -SCons/Tool/cyglink.py -SCons/Tool/clangCommon/__init__.py -SCons/Tool/clang.py -SCons/Tool/clangxx.py -SCons/Tool/cvf.py -SCons/Tool/DCommon.py -SCons/Tool/default.py -SCons/Tool/dmd.py -SCons/Tool/docbook/__init__.py -SCons/Tool/dvi.py -SCons/Tool/dvipdf.py -SCons/Tool/dvips.py -SCons/Tool/f03.py -SCons/Tool/f08.py -SCons/Tool/f77.py -SCons/Tool/f90.py -SCons/Tool/f95.py -SCons/Tool/filesystem.py -SCons/Tool/fortran.py -SCons/Tool/FortranCommon.py -SCons/Tool/g++.py -SCons/Tool/gxx.py -SCons/Tool/g77.py -SCons/Tool/gas.py -SCons/Tool/gcc.py -SCons/Tool/gdc.py -SCons/Tool/gfortran.py -SCons/Tool/gnulink.py -SCons/Tool/gs.py -SCons/Tool/hpc++.py -SCons/Tool/hpcxx.py -SCons/Tool/hpcc.py -SCons/Tool/hplink.py -SCons/Tool/icc.py -SCons/Tool/icl.py -SCons/Tool/ifl.py -SCons/Tool/ifort.py -SCons/Tool/ilink.py -SCons/Tool/ilink32.py -SCons/Tool/install.py -SCons/Tool/intelc.py -SCons/Tool/ipkg.py -SCons/Tool/jar.py -SCons/Tool/JavaCommon.py -SCons/Tool/javac.py -SCons/Tool/javah.py -SCons/Tool/latex.py -SCons/Tool/ldc.py -SCons/Tool/lex.py -SCons/Tool/link.py -SCons/Tool/linkloc.py -SCons/Tool/MSCommon/__init__.py -SCons/Tool/MSCommon/arch.py -SCons/Tool/MSCommon/common.py -SCons/Tool/MSCommon/netframework.py -SCons/Tool/MSCommon/sdk.py -SCons/Tool/MSCommon/vs.py -SCons/Tool/MSCommon/vc.py -SCons/Tool/m4.py -SCons/Tool/masm.py -SCons/Tool/midl.py -SCons/Tool/mingw.py -SCons/Tool/mslib.py -SCons/Tool/mslink.py -SCons/Tool/mssdk.py -SCons/Tool/msvc.py -SCons/Tool/msvs.py -SCons/Tool/mwcc.py -SCons/Tool/mwld.py -SCons/Tool/nasm.py -SCons/Tool/packaging/*.py -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 -SCons/Tool/rpm.py -SCons/Tool/rpmutils.py -SCons/Tool/sgiar.py -SCons/Tool/sgic++.py -SCons/Tool/sgicxx.py -SCons/Tool/sgicc.py -SCons/Tool/sgilink.py -SCons/Tool/sunar.py -SCons/Tool/sunc++.py -SCons/Tool/suncxx.py -SCons/Tool/suncc.py -SCons/Tool/sunf77.py -SCons/Tool/sunf90.py -SCons/Tool/sunf95.py -SCons/Tool/sunlink.py -SCons/Tool/swig.py -SCons/Tool/tar.py -SCons/Tool/tex.py -SCons/Tool/textfile.py -SCons/Tool/tlib.py -SCons/Tool/wix.py -SCons/Tool/yacc.py -SCons/Tool/zip.py -SCons/Util.py -SCons/Variables/__init__.py -SCons/Variables/BoolVariable.py -SCons/Variables/EnumVariable.py -SCons/Variables/ListVariable.py -SCons/Variables/PackageVariable.py -SCons/Variables/PathVariable.py -SCons/Warnings.py -SCons/Tool/GettextCommon.py -SCons/Tool/gettext_tool.py -SCons/Tool/msgfmt.py -SCons/Tool/msginit.py -SCons/Tool/msgmerge.py -SCons/Tool/xgettext.py -#SCons/Tool/docbook/docbook-xsl-1.76.1/** -#SCons/Tool/docbook/utils/** diff --git a/src/setup.cfg b/src/setup.cfg deleted file mode 100644 index bda7571..0000000 --- a/src/setup.cfg +++ /dev/null @@ -1,8 +0,0 @@ -[bdist_rpm] -group = Development/Tools - -[bdist_wininst] -title = SCons - a software construction tool - -[bdist_wheel] -universal=1 diff --git a/src/setup.py b/src/setup.py deleted file mode 100755 index bea888b..0000000 --- a/src/setup.py +++ /dev/null @@ -1,522 +0,0 @@ -# -# __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. - -import distutils.command.build_scripts -import distutils.command.install_scripts -import distutils.command.install_lib -import distutils.command.install_data -import distutils.command.install -import distutils.core -import distutils -import setuptools -""" -NOTE: Installed SCons is not importable like usual Python packages. It is - executed explicitly with command line scripts. This allows multiple - SCons versions to coexist within single Python installation, which - is critical for enterprise build cases. Explicit invokation is - necessary to avoid confusion over which version of SCons is active. - - By default SCons is installed into versioned directory, e.g. - site-packages/scons-2.1.0.alpha.20101125 and much of the stuff - below is dedicated to make it happen on various platforms. -""" - - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - -import os -import stat -import sys - -Version = "__VERSION__" - -man_pages = [ - 'scons.1', - 'sconsign.1', - 'scons-time.1', -] - -# change to setup.py directory if it was executed from other dir -(head, tail) = os.path.split(sys.argv[0]) -if head: - os.chdir(head) - sys.argv[0] = tail - -# flag if setup.py is run on win32 or _for_ win32 platform, -# (when building windows installer on linux, for example) -is_win32 = 0 -if not sys.platform == 'win32': - try: - if sys.argv[1] == 'bdist_wininst': - is_win32 = 1 - except IndexError: - pass -else: - is_win32 = 1 - - -_install = distutils.command.install.install -_install_data = distutils.command.install_data.install_data -_install_lib = distutils.command.install_lib.install_lib -_install_scripts = distutils.command.install_scripts.install_scripts -_build_scripts = distutils.command.build_scripts.build_scripts - - -class _options(object): - pass - - -Options = _options() - -Installed = [] - - -def set_explicitly(name, args): - """ - Return if the installation directory was set explicitly by the - user on the command line. This is complicated by the fact that - "install --install-lib=/foo" gets turned into "install_lib - --install-dir=/foo" internally. - """ - if args[0] == "install_" + name: - s = "--install-dir=" - else: - # The command is something else (usually "install") - s = "--install-%s=" % name - set = 0 - length = len(s) - for a in args[1:]: - if a[:length] == s: - set = 1 - break - return set - - -class install(_install): - user_options = _install.user_options + [ - ('no-scons-script', None, - "don't install 'scons', only install 'scons-%s'" % Version), - ('no-version-script', None, - "don't install 'scons-%s', only install 'scons'" % Version), - ('install-bat', None, - "install 'scons.bat' script"), - ('no-install-bat', None, - "do not install 'scons.bat' script"), - ('install-man', None, - "install SCons man pages"), - ('no-install-man', None, - "do not install SCons man pages"), - ('standard-lib', None, - "install SCons library in standard Python location"), - ('standalone-lib', None, - "install SCons library in separate standalone directory"), - ('version-lib', None, - "install SCons library in version-numbered directory"), - ] - boolean_options = _install.boolean_options + [ - 'no-scons-script', - 'no-version-script', - 'install-bat', - 'no-install-bat', - 'install-man', - 'no-install-man', - 'standard-lib', - 'standalone-lib', - 'version-lib' - ] - - if hasattr(os, 'link'): - user_options.append( - ('hardlink-scons', None, - "hard link 'scons' to the version-numbered script, don't make a separate 'scons' copy"), - ) - boolean_options.append('hardlink-script') - - if hasattr(os, 'symlink'): - user_options.append( - ('symlink-scons', None, - "make 'scons' a symbolic link to the version-numbered script, don't make a separate 'scons' copy"), - ) - boolean_options.append('symlink-script') - - def initialize_options(self): - _install.initialize_options(self) - self.no_scons_script = 0 - self.no_version_script = 0 - self.install_bat = 0 - self.no_install_bat = False # not is_win32 - self.install_man = 0 - self.standard_lib = 0 - self.standalone_lib = 0 - self.version_lib = 0 - self.hardlink_scons = 0 - self.symlink_scons = 0 - # Don't warn about having to put the library directory in the - # search path. - self.warn_dir = 0 - - def finalize_options(self): - _install.finalize_options(self) - if self.install_bat: - Options.install_bat = 1 - else: - Options.install_bat = not self.no_install_bat - if self.install_man: - Options.install_man = 1 - else: - Options.install_man = not self.no_install_man - Options.standard_lib = self.standard_lib - Options.standalone_lib = self.standalone_lib - Options.version_lib = self.version_lib - Options.install_scons_script = not self.no_scons_script - Options.install_version_script = not self.no_version_script - Options.hardlink_scons = self.hardlink_scons - Options.symlink_scons = self.symlink_scons - - -def get_scons_prefix(libdir, is_win32): - """ - Return the right prefix for SCons library installation. Find - this by starting with the library installation directory - (.../site-packages, most likely) and crawling back up until we reach - a directory name beginning with "python" (or "Python"). - """ - drive, head = os.path.splitdrive(libdir) - while head: - if head == os.sep: - break - head, tail = os.path.split(head) - if tail.lower()[:6] == "python": - # Found the Python library directory... - if is_win32: - # ...on Win32 systems, "scons" goes in the directory: - # C:\PythonXX => C:\PythonXX\scons - return os.path.join(drive + head, tail) - else: - # ...on other systems, "scons" goes above the directory: - # /usr/lib/pythonX.X => /usr/lib/scons - return os.path.join(drive + head) - return libdir - - -def force_to_usr_local(self): - """ - A hack to decide if we need to "force" the installation directories - to be under /usr/local. This is because Mac Os X Tiger and - Leopard, by default, put the libraries and scripts in their own - directories under /Library or /System/Library. - """ - return (sys.platform[:6] == 'darwin' and - (self.install_dir[:9] == '/Library/' or - self.install_dir[:16] == '/System/Library/')) - - -class install_lib(_install_lib): - def finalize_options(self): - _install_lib.finalize_options(self) - if force_to_usr_local(self): - self.install_dir = '/usr/local/lib' - args = self.distribution.script_args - if not set_explicitly("lib", args): - # They didn't explicitly specify the installation - # directory for libraries... - is_win32 = sys.platform == "win32" or args[0] == 'bdist_wininst' - prefix = get_scons_prefix(self.install_dir, is_win32) - if Options.standalone_lib: - # ...but they asked for a standalone directory. - self.install_dir = os.path.join(prefix, "scons") - elif Options.version_lib: - # ...they asked for a version-specific directory, - self.install_dir = os.path.join(prefix, "scons-%s" % Version) - elif not Options.standard_lib: - # default. - self.install_dir = os.path.join(prefix, "scons") - - msg = "Installed SCons library modules into %s" % self.install_dir - Installed.append(msg) - - -class install_scripts(_install_scripts): - def finalize_options(self): - _install_scripts.finalize_options(self) - if force_to_usr_local(self): - self.install_dir = '/usr/local/bin' - self.build_dir = os.path.join('build', 'scripts') - msg = "Installed SCons scripts into %s" % self.install_dir - Installed.append(msg) - - def do_nothing(self, *args, **kw): - pass - - def hardlink_scons(self, src, dst, ver): - try: - os.unlink(dst) - except OSError: - pass - os.link(ver, dst) - - def symlink_scons(self, src, dst, ver): - try: - os.unlink(dst) - except OSError: - pass - os.symlink(os.path.split(ver)[1], dst) - - def copy_scons(self, src, dst, *args): - try: - os.unlink(dst) - except OSError: - pass - self.copy_file(src, dst) - self.outfiles.append(dst) - - def run(self): - # --- distutils copy/paste --- - if not self.skip_build: - self.run_command('build_scripts') - # --- /distutils copy/paste --- - - # Custom SCons installation stuff. - if Options.hardlink_scons: - create_basename_script = self.hardlink_scons - elif Options.symlink_scons: - create_basename_script = self.symlink_scons - elif Options.install_scons_script: - create_basename_script = self.copy_scons - else: - create_basename_script = self.do_nothing - - if Options.install_version_script: - create_version_script = self.copy_scons - else: - create_version_script = self.do_nothing - - inputs = self.get_inputs() - bat_scripts = [x for x in inputs if x[-4:] == '.bat'] - non_bat_scripts = [x for x in inputs if x[-4:] != '.bat'] - - self.outfiles = [] - self.mkpath(self.install_dir) - - for src in non_bat_scripts: - base = os.path.basename(src) - scons = os.path.join(self.install_dir, base) - scons_ver = scons + '-' + Version - if is_win32: - scons = scons + '.py' - scons_ver = scons_ver + '.py' - create_version_script(src, scons_ver) - create_basename_script(src, scons, scons_ver) - - if Options.install_bat: - if is_win32: - bat_install_dir = get_scons_prefix(self.install_dir, is_win32) - else: - bat_install_dir = self.install_dir - for src in bat_scripts: - scons_bat = os.path.join(bat_install_dir, 'scons.bat') - scons_version_bat = os.path.join(bat_install_dir, - 'scons-' + Version + '.bat') - self.copy_scons(src, scons_bat) - self.copy_scons(src, scons_version_bat) - - # --- distutils copy/paste --- - if hasattr(os, 'chmod') and hasattr(os, 'stat'): - # Set the executable bits (owner, group, and world) on - # all the scripts we just installed. - for file in self.get_outputs(): - if self.dry_run: - # log.info("changing mode of %s", file) - pass - else: - # Use symbolic versions of permissions so this script doesn't fail to parse under python3.x - exec_and_read_permission = stat.S_IXOTH | stat.S_IXUSR | stat.S_IXGRP | stat.S_IROTH | stat.S_IRUSR | stat.S_IRGRP - mode_mask = 4095 # Octal 07777 used because python3 has different octal syntax than python 2 - mode = ((os.stat(file)[stat.ST_MODE]) | - exec_and_read_permission) & mode_mask - # log.info("changing mode of %s to %o", file, mode) - os.chmod(file, mode) - # --- /distutils copy/paste --- - - -class build_scripts(_build_scripts): - def finalize_options(self): - _build_scripts.finalize_options(self) - self.build_dir = os.path.join('build', 'scripts') - - -class install_data(_install_data): - def initialize_options(self): - _install_data.initialize_options(self) - - def finalize_options(self): - _install_data.finalize_options(self) - if force_to_usr_local(self): - self.install_dir = '/usr/local' - if Options.install_man: - if is_win32: - dir = 'Doc' - else: - dir = os.path.join('man', 'man1') - self.data_files = [(dir, man_pages)] - man_dir = os.path.join(self.install_dir, dir) - msg = "Installed SCons man pages into %s" % man_dir - Installed.append(msg) - else: - self.data_files = [] - - -description = "Open Source next-generation build tool." - -long_description = """Open Source next-generation build tool. -Improved, cross-platform substitute for the classic Make -utility. In short, SCons is an easier, more reliable -and faster way to build software.""" - -scripts = [ - 'script/scons', - 'script/sconsign', - 'script/scons-time', - 'script/scons-configure-cache', - - # We include scons.bat in the list of scripts, even on UNIX systems, - # because we provide an option to allow it be installed explicitly, - # for example if you're installing from UNIX on a share that's - # accessible to Windows and you want the scons.bat. - 'script/scons.bat', -] - -arguments = { - 'name': "scons", - 'version': Version, - 'description': description, - 'long_description': long_description, - 'author': 'William Deegan', - 'author_email': 'bill@baddogconsulting.com', - 'url': "http://www.scons.org/", - 'packages': ["SCons", - "SCons.compat", - "SCons.Node", - "SCons.Platform", - "SCons.Scanner", - "SCons.Script", - "SCons.Tool", - "SCons.Tool.clangCommon", - "SCons.Tool.docbook", - 'SCons.Tool.clangCommon', - "SCons.Tool.MSCommon", - "SCons.Tool.packaging", - "SCons.Variables", - ], - 'package_dir': {'': 'engine', - 'SCons.Tool.docbook': 'engine/SCons/Tool/docbook'}, - 'package_data': {'SCons.Tool.docbook': ['docbook-xsl-1.76.1/*', - 'docbook-xsl-1.76.1/common/*', - 'docbook-xsl-1.76.1/docsrc/*', - 'docbook-xsl-1.76.1/eclipse/*', - 'docbook-xsl-1.76.1/epub/*', - 'docbook-xsl-1.76.1/epub/bin/*', - 'docbook-xsl-1.76.1/epub/bin/lib/*', - 'docbook-xsl-1.76.1/epub/bin/xslt/*', - 'docbook-xsl-1.76.1/extensions/*', - 'docbook-xsl-1.76.1/fo/*', - 'docbook-xsl-1.76.1/highlighting/*', - 'docbook-xsl-1.76.1/html/*', - 'docbook-xsl-1.76.1/htmlhelp/*', - 'docbook-xsl-1.76.1/images/*', - 'docbook-xsl-1.76.1/images/callouts/*', - 'docbook-xsl-1.76.1/images/colorsvg/*', - 'docbook-xsl-1.76.1/javahelp/*', - 'docbook-xsl-1.76.1/lib/*', - 'docbook-xsl-1.76.1/manpages/*', - 'docbook-xsl-1.76.1/params/*', - 'docbook-xsl-1.76.1/profiling/*', - 'docbook-xsl-1.76.1/roundtrip/*', - 'docbook-xsl-1.76.1/slides/browser/*', - 'docbook-xsl-1.76.1/slides/fo/*', - 'docbook-xsl-1.76.1/slides/graphics/*', - 'docbook-xsl-1.76.1/slides/graphics/active/*', - 'docbook-xsl-1.76.1/slides/graphics/inactive/*', - 'docbook-xsl-1.76.1/slides/graphics/toc/*', - 'docbook-xsl-1.76.1/slides/html/*', - 'docbook-xsl-1.76.1/slides/htmlhelp/*', - 'docbook-xsl-1.76.1/slides/keynote/*', - 'docbook-xsl-1.76.1/slides/keynote/xsltsl/*', - 'docbook-xsl-1.76.1/slides/svg/*', - 'docbook-xsl-1.76.1/slides/xhtml/*', - 'docbook-xsl-1.76.1/template/*', - 'docbook-xsl-1.76.1/tests/*', - 'docbook-xsl-1.76.1/tools/bin/*', - 'docbook-xsl-1.76.1/tools/make/*', - 'docbook-xsl-1.76.1/webhelp/*', - 'docbook-xsl-1.76.1/webhelp/docs/*', - 'docbook-xsl-1.76.1/webhelp/docs/common/*', - 'docbook-xsl-1.76.1/webhelp/docs/common/css/*', - 'docbook-xsl-1.76.1/webhelp/docs/common/images/*', - 'docbook-xsl-1.76.1/webhelp/docs/common/jquery/*', - 'docbook-xsl-1.76.1/webhelp/docs/common/jquery/theme-redmond/*', - 'docbook-xsl-1.76.1/webhelp/docs/common/jquery/theme-redmond/images/*', - 'docbook-xsl-1.76.1/webhelp/docs/common/jquery/treeview/*', - 'docbook-xsl-1.76.1/webhelp/docs/common/jquery/treeview/images/*', - 'docbook-xsl-1.76.1/webhelp/docs/content/*', - 'docbook-xsl-1.76.1/webhelp/docs/content/search/*', - 'docbook-xsl-1.76.1/webhelp/docs/content/search/stemmers/*', - 'docbook-xsl-1.76.1/webhelp/docsrc/*', - 'docbook-xsl-1.76.1/webhelp/template/*', - 'docbook-xsl-1.76.1/webhelp/template/common/*', - 'docbook-xsl-1.76.1/webhelp/template/common/css/*', - 'docbook-xsl-1.76.1/webhelp/template/common/images/*', - 'docbook-xsl-1.76.1/webhelp/template/common/jquery/*', - 'docbook-xsl-1.76.1/webhelp/template/common/jquery/theme-redmond/*', - 'docbook-xsl-1.76.1/webhelp/template/common/jquery/theme-redmond/images/*', - 'docbook-xsl-1.76.1/webhelp/template/common/jquery/treeview/*', - 'docbook-xsl-1.76.1/webhelp/template/common/jquery/treeview/images/*', - 'docbook-xsl-1.76.1/webhelp/template/content/search/*', - 'docbook-xsl-1.76.1/webhelp/template/content/search/stemmers/*', - 'docbook-xsl-1.76.1/webhelp/xsl/*', - 'docbook-xsl-1.76.1/website/*', - 'docbook-xsl-1.76.1/xhtml/*', - 'docbook-xsl-1.76.1/xhtml-1_1/*', - 'utils/*']}, - 'data_files': [('man/man1', man_pages)], - 'scripts': scripts, - 'cmdclass': {'install': install, - 'install_lib': install_lib, - 'install_data': install_data, - 'install_scripts': install_scripts, - 'build_scripts': build_scripts}, - 'install_requires' : { - "pywin32;platform_system=='Windows'" - } -} - -distutils.core.setup(**arguments) - -if Installed: - for i in Installed: - print(i) - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: -- cgit v0.12 From e3908345f0c0aef30cc332995384a1fa310ba46c Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 30 Mar 2020 16:24:30 -0700 Subject: Update location of LICENSE and use same version in sdist and wheel --- MANIFEST.in | 5 +++++ setup.cfg | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/MANIFEST.in b/MANIFEST.in index 04aee14..c283957 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -2,4 +2,9 @@ global-exclude **Tests.py recursive-include src/engine/SCons/Tool/docbook * +# For license file +include LICENSE + + + diff --git a/setup.cfg b/setup.cfg index 2eb7728..614303c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,13 +1,13 @@ [metadata] name = SCons -version=3.9.9a99 +version=3.9.9a991 license = MIT author = William Deegan author_email =bill@baddogconsulting.com long_description = file: README.rst description = Open Source next-generation build tool. group = Development/Tools -license_file = src/LICENSE.txt +license_file = LICENSE url = http://www.scons.org/ -- cgit v0.12 From 8bdb821413e97e614311999006409f6702f91610 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 30 Mar 2020 16:25:05 -0700 Subject: Remove src/LICENSE.txt. Just use the version in the basedir --- src/LICENSE.txt | 22 ---------------------- 1 file changed, 22 deletions(-) delete mode 100644 src/LICENSE.txt diff --git a/src/LICENSE.txt b/src/LICENSE.txt deleted file mode 100644 index 1641aba..0000000 --- a/src/LICENSE.txt +++ /dev/null @@ -1,22 +0,0 @@ -MIT License - -__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. -- cgit v0.12 From a369a98389636358108827a3de04fa17970bf6bb Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 30 Mar 2020 16:54:32 -0700 Subject: Clean up unused imports --- SConstruct | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/SConstruct b/SConstruct index a76471f..5be7d22 100644 --- a/SConstruct +++ b/SConstruct @@ -31,13 +31,10 @@ month_year = 'December 2019' # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -import fnmatch -import os import os.path import sys import textwrap -import bootstrap project = 'scons' default_version = '3.1.2' @@ -64,6 +61,7 @@ for a in addpaths: if a not in sys.path: sys.path.append(a) +# Use site_scons logic to process command line arguments command_line = BuildCommandLine(default_version) command_line.process_command_line_vars() -- cgit v0.12 From 90657e02371290930ddcedcedbc9494d888ea670 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 30 Mar 2020 16:56:13 -0700 Subject: remove unused imports. --- bin/scons-proc.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/bin/scons-proc.py b/bin/scons-proc.py index 6c1f66a..e039cd0 100644 --- a/bin/scons-proc.py +++ b/bin/scons-proc.py @@ -11,10 +11,7 @@ # import getopt import os -import re -import string import sys -from io import StringIO # usable as of 2.6; takes unicode only import SConsDoc from SConsDoc import tf as stf @@ -107,10 +104,10 @@ class SCons_XML(object): for k, v in kw.items(): setattr(self, k, v) - def fopen(self, name): + def fopen(self, name, mode='w'): if name == '-': return sys.stdout - return open(name, 'w') + return open(name, mode) def write(self, files): gen, mod = files.split(',') -- cgit v0.12 From a9ab8cae92f95e7410cb534020ff03e15c753f9e Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 9 Apr 2020 14:01:07 -0700 Subject: Update CHANGES.txt --- src/CHANGES.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 6ec16f3..ac8a3ac 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -30,6 +30,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Add msys2 installed mingw default path to PATH for mingw tool. - C:\msys64\mingw64\bin - Purge obsolete internal build and tooling scripts + - Resolve Issue #3451 and Issue #3450 - Rewrite SCons setup.py and packaging. Move script logic to entry points so + package can create scripts which use the correct version of Python. From Jeremy Elson: - Updated design doc to use the correct syntax for Depends() -- cgit v0.12 From 23fd1a45db2d57767dcbb50c151295dc93975181 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 9 Apr 2020 15:11:52 -0700 Subject: pep8 --- src/engine/SCons/Tool/MSCommon/vc.py | 12 +++++++----- src/engine/SCons/Tool/msvc.py | 1 + 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py index 82fb6b9..f5a410f 100644 --- a/src/engine/SCons/Tool/MSCommon/vc.py +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -233,16 +233,16 @@ _VCVER = ["14.2", "14.1", "14.1Exp", "14.0", "14.0Exp", "12.0", "12.0Exp", "11.0 # if using vswhere, a further mapping is needed _VCVER_TO_VSWHERE_VER = { - '14.2' : '[16.0, 17.0)', - '14.1' : '[15.0, 16.0)', + '14.2': '[16.0, 17.0)', + '14.1': '[15.0, 16.0)', } _VCVER_TO_PRODUCT_DIR = { - '14.2' : [ + '14.2': [ (SCons.Util.HKEY_LOCAL_MACHINE, r'')], # not set by this version - '14.1' : [ + '14.1': [ (SCons.Util.HKEY_LOCAL_MACHINE, r'')], # not set by this version - '14.1Exp' : [ + '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')], @@ -290,6 +290,7 @@ _VCVER_TO_PRODUCT_DIR = { ] } + def msvc_version_to_maj_min(msvc_version): msvc_version_numeric = get_msvc_version_numeric(msvc_version) @@ -303,6 +304,7 @@ def msvc_version_to_maj_min(msvc_version): except ValueError as e: raise ValueError("Unrecognized version %s (%s)" % (msvc_version,msvc_version_numeric)) + def is_host_target_supported(host_target, msvc_version): """Check if (host, target) pair is supported for a VC version. diff --git a/src/engine/SCons/Tool/msvc.py b/src/engine/SCons/Tool/msvc.py index 65c0e91..05a20e0 100644 --- a/src/engine/SCons/Tool/msvc.py +++ b/src/engine/SCons/Tool/msvc.py @@ -214,6 +214,7 @@ ShCXXAction = SCons.Action.Action("$SHCXXCOM", "$SHCXXCOMSTR", batch_key=msvc_batch_key, targets='$CHANGED_TARGETS') + def generate(env): """Add Builders and construction variables for MSVC++ to an Environment.""" static_obj, shared_obj = SCons.Tool.createObjBuilders(env) -- cgit v0.12 From a4c2ee46188f8b43a451af01eda8b3cfefb1b663 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 10 Apr 2020 12:24:03 -0600 Subject: Second try at fixing sets/uses Tool doc generation. [ci skip] Fixes #3580 a different way: generate the link itself into the tools.gen file, instead of post-processing the broken entity reference back into a usable form. Signed-off-by: Mats Wichmann --- bin/docs-update-generated.py | 10 +++------- bin/scons-proc.py | 28 ++++++++++++++++++---------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/bin/docs-update-generated.py b/bin/docs-update-generated.py index 98c923d..0a373aa 100644 --- a/bin/docs-update-generated.py +++ b/bin/docs-update-generated.py @@ -51,13 +51,9 @@ def generate_all(): '-v', argpair('variables')] + flist, shell=False) - cp.check_returncode() # bail if it failed - # lxml: fixup possibly broken tools.gen: - with open(os.path.join(gen_folder, 'tools.gen'), 'r') as f : - filedata = f.read() - filedata = filedata.replace(r'&cv-link', r'&cv-link') - with open(os.path.join(gen_folder, 'tools.gen'), 'w') as f : - f.write(filedata) + # No-op: scons-proc doesn't actually set an exit code at the moment. + if cp.returncode: + print("Generation failed", file=sys.stderr) if __name__ == "__main__": diff --git a/bin/scons-proc.py b/bin/scons-proc.py index 6c1f66a..ac52894 100644 --- a/bin/scons-proc.py +++ b/bin/scons-proc.py @@ -141,23 +141,31 @@ class SCons_XML(object): added = True stf.appendNode(vl, stf.copyNode(s)) + # Generate the text for sets/uses lists of construction vars. + # This used to include an entity reference which would be replaced + # by the link to the cvar, but with lxml, dumping out the tree + # with tostring() will encode the & introducing the entity, + # breaking it. Instead generate the actual link. (issue #3580) if v.sets: added = True vp = stf.newNode("para") - # if using lxml, the &entity; entries will be encoded, - # effectively breaking them. should fix, - # for now handled post-process in calling script. - s = ['&cv-link-%s;' % x for x in v.sets] - stf.setText(vp, 'Sets: ' + ', '.join(s) + '.') + stf.setText(vp, "Sets: ") + for setv in v.sets: + link = stf.newSubNode(vp, "link", linkend="cv-%s" % setv) + linktgt = stf.newSubNode(link, "varname") + stf.setText(linktgt, "$" + setv) + stf.setTail(link, " ") stf.appendNode(vl, vp) + if v.uses: added = True vp = stf.newNode("para") - # if using lxml, the &entity; entries will be encoded, - # effectively breaking them. should fix, - # for now handled post-process in calling script. - u = ['&cv-link-%s;' % x for x in v.uses] - stf.setText(vp, 'Uses: ' + ', '.join(u) + '.') + stf.setText(vp, "Uses: ") + for use in v.uses: + link = stf.newSubNode(vp, "link", linkend="cv-%s" % use) + linktgt = stf.newSubNode(link, "varname") + stf.setText(linktgt, "$" + use) + stf.setTail(link, " ") stf.appendNode(vl, vp) # Still nothing added to this list item? -- cgit v0.12 From 91b699c9e13a94d37bd6467930874672eff4c5b1 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 10 Apr 2020 15:21:04 -0700 Subject: Resolve issue #3605. Allow specifying VSWHERE to environment --- src/CHANGES.txt | 2 + src/engine/SCons/Tool/MSCommon/__init__.py | 3 +- src/engine/SCons/Tool/MSCommon/vc.py | 57 +++++++++++++++++------------ src/engine/SCons/Tool/MSCommon/vcTests.py | 35 ++++++++++++++++-- src/engine/SCons/Tool/MSCommon/vs.py | 36 +++++++++--------- src/engine/SCons/Tool/linkloc.py | 2 +- src/engine/SCons/Tool/msvc.py | 5 ++- src/engine/SCons/Tool/msvc.xml | 34 +++++++++++++++++ src/engine/SCons/Tool/msvsTests.py | 2 +- src/script/scons.bat | 6 +-- test/Win32/scons-bat-error.py | 2 +- test/fixture/no_msvc/no_msvcs_sconstruct.py | 2 +- 12 files changed, 133 insertions(+), 53 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 6ec16f3..862380b 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -30,6 +30,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Add msys2 installed mingw default path to PATH for mingw tool. - C:\msys64\mingw64\bin - Purge obsolete internal build and tooling scripts + - Allow user specified location for vswhere.exe specified by VSWHERE. + NOTE: This must be set at the time the 'msvc' tool is initialized to have any effect. From Jeremy Elson: - Updated design doc to use the correct syntax for Depends() diff --git a/src/engine/SCons/Tool/MSCommon/__init__.py b/src/engine/SCons/Tool/MSCommon/__init__.py index c87bf71..be7720a 100644 --- a/src/engine/SCons/Tool/MSCommon/__init__.py +++ b/src/engine/SCons/Tool/MSCommon/__init__.py @@ -42,7 +42,8 @@ from SCons.Tool.MSCommon.sdk import mssdk_exists, \ from SCons.Tool.MSCommon.vc import msvc_exists, \ msvc_setup_env, \ msvc_setup_env_once, \ - msvc_version_to_maj_min + msvc_version_to_maj_min, \ + msvc_find_vswhere from SCons.Tool.MSCommon.vs import get_default_version, \ get_vs_by_version, \ diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py index f5a410f..ce1341d 100644 --- a/src/engine/SCons/Tool/MSCommon/vc.py +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -323,7 +323,32 @@ def is_host_target_supported(host_target, msvc_version): return True -def find_vc_pdir_vswhere(msvc_version): +VSWHERE_PATHS = [os.path.join(p,'vswhere.exe') for p in [ + 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"), +]] + +def msvc_find_vswhere(): + """ + Find the location of vswhere + """ + # 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. + # NB: this gets called from testsuite on non-Windows platforms. + # Whether that makes sense or not, don't break it for those. + # TODO: requested to add a user-specified path to vswhere + # and have this routine set the same var if it finds it. + vswhere_path = None + for pf in VSWHERE_PATHS: + if os.path.exists(pf): + vswhere_path = pf + break + + return vswhere_path + +def find_vc_pdir_vswhere(msvc_version, env=None): """ Find the MSVC product directory using the vswhere program. @@ -338,26 +363,12 @@ 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 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. - # 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, "vswhere.exe") - if os.path.exists(vswhere_path): - break + if env is None or not env.get('VSWHERE'): + vswhere_path = msvc_find_vswhere() else: - # No vswhere on system, no install info available this way - return None + vswhere_path = env.subst('$VSWHERE') + debug('find_vc_pdir_vswhere(): VSWHERE = %s'%vswhere_path) vswhere_cmd = [ vswhere_path, "-products", "*", @@ -381,7 +392,7 @@ def find_vc_pdir_vswhere(msvc_version): return None -def find_vc_pdir(msvc_version): +def find_vc_pdir(env, msvc_version): """Find the MSVC product directory for the given version. Tries to look up the path using a registry key from the table @@ -412,7 +423,7 @@ def find_vc_pdir(msvc_version): try: comps = None if not key: - comps = find_vc_pdir_vswhere(msvc_version) + comps = find_vc_pdir_vswhere(msvc_version, env) if not comps: debug('find_vc_pdir_vswhere(): no VC found for version {}'.format(repr(msvc_version))) raise SCons.Util.WinError @@ -450,7 +461,7 @@ def find_batch_file(env,msvc_version,host_arch,target_arch): so use that and return an indication we don't need the argument we would have computed to run vcvarsall.bat. """ - pdir = find_vc_pdir(msvc_version) + pdir = find_vc_pdir(env, msvc_version) if pdir is None: raise NoVersionFound("No version of Visual Studio found") debug('find_batch_file() in {}'.format(pdir)) @@ -635,7 +646,7 @@ def get_installed_vcs(env=None): for ver in _VCVER: debug('trying to find VC %s' % ver) try: - VC_DIR = find_vc_pdir(ver) + VC_DIR = find_vc_pdir(env, ver) if VC_DIR: debug('found VC %s' % ver) if _check_cl_exists_in_vc_dir(env, VC_DIR, ver): diff --git a/src/engine/SCons/Tool/MSCommon/vcTests.py b/src/engine/SCons/Tool/MSCommon/vcTests.py index 09991f5..f5f7a44 100644 --- a/src/engine/SCons/Tool/MSCommon/vcTests.py +++ b/src/engine/SCons/Tool/MSCommon/vcTests.py @@ -24,6 +24,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" +import sys import os import os.path import unittest @@ -45,12 +46,42 @@ MSVCUnsupportedTargetArch = SCons.Tool.MSCommon.vc.MSVCUnsupportedTargetArch MS_TOOLS_VERSION='1.1.1' +class VswhereTestCase(unittest.TestCase): + @staticmethod + def _createVSWhere(path): + os.makedirs(os.path.dirname(path)) + with open(path, 'w') as f: + f.write("Created:%s"%f) + + def testDefaults(self): + """ + Verify that msvc_find_vswhere() find's files in the specified paths + """ + # import pdb; pdb.set_trace() + vswhere_dirs = [os.path.splitdrive(p)[1] for p in SCons.Tool.MSCommon.vc.VSWHERE_PATHS] + base_dir = test.workpath('fake_vswhere') + test_vswhere_dirs = [os.path.join(base_dir,d[1:]) for d in vswhere_dirs] + + SCons.Tool.MSCommon.vc.VSWHERE_PATHS = test_vswhere_dirs + for vsw in test_vswhere_dirs: + VswhereTestCase._createVSWhere(vsw) + find_path = SCons.Tool.MSCommon.vc.msvc_find_vswhere() + self.assertTrue(vsw == find_path, "Didn't find vswhere in %s found in %s"%(vsw, find_path)) + os.remove(vsw) + + # def specifiedVswherePathTest(self): + # "Verify that msvc.generate() respects VSWHERE Specified" + + + + + class MSVcTestCase(unittest.TestCase): @staticmethod def _createDummyCl(path, add_bin=True): """ - Creates a dummy cl.ex in the correct directory. + Creates a dummy cl.exe in the correct directory. It will create all missing parent directories as well Args: @@ -74,8 +105,6 @@ class MSVcTestCase(unittest.TestCase): ct.write('created') - - def runTest(self): """ Check that all proper HOST_PLATFORM and TARGET_PLATFORM are handled. diff --git a/src/engine/SCons/Tool/MSCommon/vs.py b/src/engine/SCons/Tool/MSCommon/vs.py index e13f52f..e71eb27 100644 --- a/src/engine/SCons/Tool/MSCommon/vs.py +++ b/src/engine/SCons/Tool/MSCommon/vs.py @@ -64,22 +64,22 @@ class VisualStudio(object): return None return batch_file - def find_vs_dir_by_vc(self): - SCons.Tool.MSCommon.vc.get_installed_vcs() - dir = SCons.Tool.MSCommon.vc.find_vc_pdir(self.vc_version) + def find_vs_dir_by_vc(self, env): + SCons.Tool.MSCommon.vc.get_installed_vcs(env) + dir = SCons.Tool.MSCommon.vc.find_vc_pdir(env, self.vc_version) if not dir: debug('find_vs_dir_by_vc(): no installed VC %s' % self.vc_version) return None return os.path.abspath(os.path.join(dir, os.pardir)) - def find_vs_dir_by_reg(self): + def find_vs_dir_by_reg(self, env): root = 'Software\\' if is_win64(): root = root + 'Wow6432Node\\' for key in self.hkeys: if key=='use_dir': - return self.find_vs_dir_by_vc() + return self.find_vs_dir_by_vc(env) key = root + key try: comps = read_reg(key) @@ -90,19 +90,19 @@ class VisualStudio(object): return comps return None - def find_vs_dir(self): + def find_vs_dir(self, env): """ Can use registry or location of VC to find vs dir First try to find by registry, and if that fails find via VC dir """ - vs_dir=self.find_vs_dir_by_reg() + vs_dir=self.find_vs_dir_by_reg(env) if not vs_dir: - vs_dir = self.find_vs_dir_by_vc() + vs_dir = self.find_vs_dir_by_vc(env) debug('find_vs_dir(): found VS in ' + str(vs_dir )) return vs_dir - def find_executable(self): - vs_dir = self.get_vs_dir() + def find_executable(self, env): + vs_dir = self.get_vs_dir(env) if not vs_dir: debug('find_executable(): no vs_dir ({})'.format(vs_dir)) return None @@ -121,21 +121,21 @@ class VisualStudio(object): self._cache['batch_file'] = batch_file return batch_file - def get_executable(self): + def get_executable(self, env=None): try: debug('get_executable using cache:%s'%self._cache['executable']) return self._cache['executable'] except KeyError: - executable = self.find_executable() + executable = self.find_executable(env) self._cache['executable'] = executable debug('get_executable not in cache:%s'%executable) return executable - def get_vs_dir(self): + def get_vs_dir(self, env): try: return self._cache['vs_dir'] except KeyError: - vs_dir = self.find_vs_dir() + vs_dir = self.find_vs_dir(env) self._cache['vs_dir'] = vs_dir return vs_dir @@ -413,7 +413,7 @@ for vs in SupportedVSList: InstalledVSList = None InstalledVSMap = None -def get_installed_visual_studios(): +def get_installed_visual_studios(env=None): global InstalledVSList global InstalledVSMap if InstalledVSList is None: @@ -421,7 +421,7 @@ def get_installed_visual_studios(): InstalledVSMap = {} for vs in SupportedVSList: debug('trying to find VS %s' % vs.version) - if vs.get_executable(): + if vs.get_executable(env): debug('found VS %s' % vs.version) InstalledVSList.append(vs) InstalledVSMap[vs.version] = vs @@ -472,8 +472,8 @@ def reset_installed_visual_studios(): # for variable, directory in env_tuple_list: # env.PrependENVPath(variable, directory) -def msvs_exists(): - return (len(get_installed_visual_studios()) > 0) +def msvs_exists(env=None): + return (len(get_installed_visual_studios(env)) > 0) def get_vs_by_version(msvs): global InstalledVSMap diff --git a/src/engine/SCons/Tool/linkloc.py b/src/engine/SCons/Tool/linkloc.py index c73852b..ad189b2 100644 --- a/src/engine/SCons/Tool/linkloc.py +++ b/src/engine/SCons/Tool/linkloc.py @@ -101,7 +101,7 @@ def generate(env): addPharLapPaths(env) def exists(env): - if msvs_exists(): + if msvs_exists(env): return env.Detect('linkloc') else: return 0 diff --git a/src/engine/SCons/Tool/msvc.py b/src/engine/SCons/Tool/msvc.py index 05a20e0..463e372 100644 --- a/src/engine/SCons/Tool/msvc.py +++ b/src/engine/SCons/Tool/msvc.py @@ -48,7 +48,7 @@ import SCons.Util import SCons.Warnings import SCons.Scanner.RC -from .MSCommon import msvc_exists, msvc_setup_env_once, msvc_version_to_maj_min +from .MSCommon import msvc_exists, msvc_setup_env_once, msvc_version_to_maj_min, msvc_find_vswhere CSuffixes = ['.c', '.C'] CXXSuffixes = ['.cc', '.cpp', '.cxx', '.c++', '.C++'] @@ -277,6 +277,9 @@ def generate(env): # without it for lex generation env["LEXUNISTD"] = SCons.Util.CLVar("--nounistd") + # Get user specified vswhere location or locate. + env['VSWHERE'] = env.get('VSWHERE', msvc_find_vswhere()) + # Set-up ms tools paths msvc_setup_env_once(env) diff --git a/src/engine/SCons/Tool/msvc.xml b/src/engine/SCons/Tool/msvc.xml index 100c84c..bdbf253 100644 --- a/src/engine/SCons/Tool/msvc.xml +++ b/src/engine/SCons/Tool/msvc.xml @@ -475,4 +475,38 @@ Valid values are '1' or '0' + + + +Specify the location of vswhere.exe. + + + +vswhere.exe is used to locate MSVC/MSVS installations. +It was initially distributed with MSVS 2017. But can detect MSVC 2010 and newer with -legacy argument. +If &cv-VSWHERE; is set, SCons will use that location. + + +Otherwise SCons will look in the following locations and set VSWHERE to the PATH vswhere.exe +is located. + + +Note that &cv-VSWHERE; must be set in when tool msvc is initialized. This is either in the call to +Environment(VSWHERE='c:/my/path/to/vswhere') or +if Environment created specifying not to automatically initialize any tools or tools which doesn't include msvc or MSVS +such as Environment(Tools=[]) + + + + + +%ProgramFiles(x86)%\Microsoft Visual Studio\Installer +"%ProgramFiles%\Microsoft Visual Studio\Installer +%ChocolateyInstall%\bin + + + + + + diff --git a/src/engine/SCons/Tool/msvsTests.py b/src/engine/SCons/Tool/msvsTests.py index b3373ea..1bacc2c 100644 --- a/src/engine/SCons/Tool/msvsTests.py +++ b/src/engine/SCons/Tool/msvsTests.py @@ -580,7 +580,7 @@ def DummyQueryValue(key, value): def DummyExists(path): return 1 -def DummyVsWhere(msvc_version): +def DummyVsWhere(msvc_version, env): # not testing versions with vswhere, so return none return None diff --git a/src/script/scons.bat b/src/script/scons.bat index 10b8637..1031929 100644 --- a/src/script/scons.bat +++ b/src/script/scons.bat @@ -1,11 +1,11 @@ @REM __COPYRIGHT__ @REM __FILE__ __REVISION__ __DATE__ __DEVELOPER__ -@echo off +@REM echo off set SCONS_ERRORLEVEL= if "%OS%" == "Windows_NT" goto WinNT @REM for 9x/Me you better not have more than 9 args -python -c "from os.path import join; import sys; sys.path = [ join(sys.prefix, 'Lib', 'site-packages', 'scons-__VERSION__'), join(sys.prefix, 'Lib', 'site-packages', 'scons'), join(sys.prefix, 'scons-__VERSION__'), join(sys.prefix, 'scons')] + sys.path; import SCons.Script; SCons.Script.main()" %1 %2 %3 %4 %5 %6 %7 %8 %9 +py -c "from os.path import join; import sys; sys.path = [ join(sys.prefix, 'Lib', 'site-packages', 'scons-__VERSION__'), join(sys.prefix, 'Lib', 'site-packages', 'scons'), join(sys.prefix, 'scons-__VERSION__'), join(sys.prefix, 'scons')] + sys.path; import SCons.Script; SCons.Script.main()" %1 %2 %3 %4 %5 %6 %7 %8 %9 @REM no way to set exit status of this script for 9x/Me goto endscons @@ -24,7 +24,7 @@ set scriptname=%~dp0%~n0.py if not exist "%scriptname%" set scriptname=%~dp0Scripts\%~n0.py @REM Handle when running from wheel where the script has no .py extension if not exist "%scriptname%" set scriptname=%~dp0%~n0 -python "%scriptname%" %* +py "%scriptname%" %* endlocal & set SCONS_ERRORLEVEL=%ERRORLEVEL% if NOT "%COMSPEC%" == "%SystemRoot%\system32\cmd.exe" goto returncode diff --git a/test/Win32/scons-bat-error.py b/test/Win32/scons-bat-error.py index d772132..4d5d00c 100644 --- a/test/Win32/scons-bat-error.py +++ b/test/Win32/scons-bat-error.py @@ -39,7 +39,7 @@ if sys.platform != 'win32': msg = "Skipping scons.bat test on non-Windows platform '%s'\n" % sys.platform test.skip_test(msg) -python = test.where_is('python') +python = sys.executable #test.where_is('python') if not python: msg = "Skipping scons.bat test; python is not on %PATH%.\n" diff --git a/test/fixture/no_msvc/no_msvcs_sconstruct.py b/test/fixture/no_msvc/no_msvcs_sconstruct.py index e0b59e6..11a06ac 100644 --- a/test/fixture/no_msvc/no_msvcs_sconstruct.py +++ b/test/fixture/no_msvc/no_msvcs_sconstruct.py @@ -1,7 +1,7 @@ import SCons import SCons.Tool.MSCommon -def DummyVsWhere(msvc_version): +def DummyVsWhere(env, msvc_version): # not testing versions with vswhere, so return none return None -- cgit v0.12 From 4d582eed59c08a9cb42dbcebf4bb89261cc01b48 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 10 Apr 2020 15:23:33 -0700 Subject: restore scons.bat to original --- src/script/scons.bat | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/script/scons.bat b/src/script/scons.bat index 1031929..10b8637 100644 --- a/src/script/scons.bat +++ b/src/script/scons.bat @@ -1,11 +1,11 @@ @REM __COPYRIGHT__ @REM __FILE__ __REVISION__ __DATE__ __DEVELOPER__ -@REM echo off +@echo off set SCONS_ERRORLEVEL= if "%OS%" == "Windows_NT" goto WinNT @REM for 9x/Me you better not have more than 9 args -py -c "from os.path import join; import sys; sys.path = [ join(sys.prefix, 'Lib', 'site-packages', 'scons-__VERSION__'), join(sys.prefix, 'Lib', 'site-packages', 'scons'), join(sys.prefix, 'scons-__VERSION__'), join(sys.prefix, 'scons')] + sys.path; import SCons.Script; SCons.Script.main()" %1 %2 %3 %4 %5 %6 %7 %8 %9 +python -c "from os.path import join; import sys; sys.path = [ join(sys.prefix, 'Lib', 'site-packages', 'scons-__VERSION__'), join(sys.prefix, 'Lib', 'site-packages', 'scons'), join(sys.prefix, 'scons-__VERSION__'), join(sys.prefix, 'scons')] + sys.path; import SCons.Script; SCons.Script.main()" %1 %2 %3 %4 %5 %6 %7 %8 %9 @REM no way to set exit status of this script for 9x/Me goto endscons @@ -24,7 +24,7 @@ set scriptname=%~dp0%~n0.py if not exist "%scriptname%" set scriptname=%~dp0Scripts\%~n0.py @REM Handle when running from wheel where the script has no .py extension if not exist "%scriptname%" set scriptname=%~dp0%~n0 -py "%scriptname%" %* +python "%scriptname%" %* endlocal & set SCONS_ERRORLEVEL=%ERRORLEVEL% if NOT "%COMSPEC%" == "%SystemRoot%\system32\cmd.exe" goto returncode -- cgit v0.12 From 067ac2b4b793bd45cb3595ef311553ede59aa236 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 10 Apr 2020 20:36:24 -0700 Subject: Fix tar bz2 test so it won't crash when no bzip2 is present --- test/packaging/tar/bz2_packaging.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/packaging/tar/bz2_packaging.py b/test/packaging/tar/bz2_packaging.py index 3c1afe3..0c8dcea 100644 --- a/test/packaging/tar/bz2_packaging.py +++ b/test/packaging/tar/bz2_packaging.py @@ -44,7 +44,6 @@ 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 @@ -56,6 +55,9 @@ if sys.platform == 'win32': if tar[:8] != bz2[:8]: # catch one in \WINDOWS, one not test.skip_test('tar found, but usable bzip2 not, skipping test\n') +bz2_path = os.path.dirname(bz2) + + test.subdir('src') test.write([ 'src', 'main.c'], r""" -- cgit v0.12 From b2596f777bbcc6cea3d792dd4cbfa580981cb93b Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 10 Apr 2020 20:58:04 -0700 Subject: don't change eol on .in files --- .gitattributes | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitattributes b/.gitattributes index 089d31b..54fb67f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4,3 +4,4 @@ src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1 linguist-vendored *.xsl linguist-documentation *.gen linguist-documentation +*.in eol=lf -- cgit v0.12 From 331107e44adf317090693650afd534c11d325a4a Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sat, 11 Apr 2020 12:52:43 -0600 Subject: Update doc wording for IMPLICIT_COMMAND_DEPEDENCIES [ci skip] Reword, remove a bit of redundancy by describing actions containing && in one place instead of repeatedly. Actually mention the case of setting the cvar to True. Doc-only change. Signed-off-by: Mats Wichmann --- src/engine/SCons/Action.xml | 91 ++++++++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 38 deletions(-) diff --git a/src/engine/SCons/Action.xml b/src/engine/SCons/Action.xml index 350082d..107e389 100644 --- a/src/engine/SCons/Action.xml +++ b/src/engine/SCons/Action.xml @@ -35,19 +35,39 @@ executed to build targets. By default, SCons will add to each target an implicit dependency on the command -represented by the first argument on any -command line it executes. +represented by the first argument of any +command line it executes (which is typically +the command itself). By setting such +a dependency, &SCons; can determine that +a target should be rebuilt if the command changes, +such as when a compiler is upgraded to a new version. The specific file for the dependency is found by searching the PATH variable in the -ENV -environment used to execute the command. +ENV dictionary +in the &consenv; used to execute the command. +The default is the same as +setting the &consvar; +&cv-IMPLICIT_COMMAND_DEPENDENCIES; +to a true value (True, +any non-zero number, etc.). -If the construction variable -&cv-IMPLICIT_COMMAND_DEPENDENCIES; +Action strings can be segmented by the +use of an AND operator, &&. +In a segemented string, each segment is a separate +command line, these are run +sequentially until one fails or the entire +sequence has been executed. If an +action string is segmented, then the selected +behavior of &cv-IMPLICIT_COMMAND_DEPENDENCIES; +is applied to each segment. + + + +If &cv-IMPLICIT_COMMAND_DEPENDENCIES; is set to a false value (None, False, @@ -55,50 +75,45 @@ is set to a false value etc.), then the implicit dependency will not be added to the targets -built with that construction environment. +built with that &consenv;. -If the construction variable -&cv-IMPLICIT_COMMAND_DEPENDENCIES; -is set to 2 or higher, -then that number of entries in the command -string will be scanned for relative or absolute -paths. The count will reset after any -&& entries are found. -The first command in the action string and -the first after any && -entries will be found by searching the -PATH variable in the -ENV environment used to -execute the command. All other commands will -only be found if they are absolute paths or -valid paths relative to the working directory. +If &cv-IMPLICIT_COMMAND_DEPENDENCIES; +is set to integer 2 or higher, +then that number of arguments in the command line +will be scanned for relative or absolute paths. +If any are present, they will be added as +implicit dependencies to the targets built +with that &consenv;. +The first argument in the command line will be +searched for using the PATH +variable in the ENV dictionary +in the &consenv; used to execute the command. +The other arguments will only be found if they +are absolute paths or valid paths relative +to the working directory. -If the construction variable -&cv-IMPLICIT_COMMAND_DEPENDENCIES; -is set to all, then -all entries in all command strings will be -scanned for relative or absolute paths. If -any are present, they will be added as +If &cv-IMPLICIT_COMMAND_DEPENDENCIES; +is set to all, +then all arguments in the command line will be +scanned for relative or absolute paths. +If any are present, they will be added as implicit dependencies to the targets built -with that construction environment. -not be added to the targets built with that -construction environment. The first command -in the action string and the first after any -&& entries will be found -by searching the PATH -variable in the ENV -environment used to execute the command. -All other commands will only be found if they +with that &consenv;. +The first argument in the command line will be +searched for using the PATH +variable in the ENV dictionary +in the &consenv; used to execute the command. +The other arguments will only be found if they are absolute paths or valid paths relative to the working directory. -env = Environment(IMPLICIT_COMMAND_DEPENDENCIES = 0) +env = Environment(IMPLICIT_COMMAND_DEPENDENCIES=False) -- cgit v0.12 From 7819d4c757bba420ec4b96251c188f7665a49369 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 11 Apr 2020 16:59:42 -0700 Subject: Address github review notes and sider issues --- SConstruct | 2 +- bin/SConsDoc.py | 3 +- bin/scons-time.py | 180 +++++++++++++++++---------------- runtest.py | 22 +--- setup.py | 2 +- site_scons/BuildCommandLine.py | 9 +- site_scons/epydoc.py | 2 +- site_scons/site_init.py | 4 +- src/engine/SCons/Utilities/sconsign.py | 10 +- test/scons-time/run/archive/dir.py | 1 - 10 files changed, 116 insertions(+), 119 deletions(-) diff --git a/SConstruct b/SConstruct index 5be7d22..4fdb401 100644 --- a/SConstruct +++ b/SConstruct @@ -37,7 +37,7 @@ import textwrap project = 'scons' -default_version = '3.1.2' +default_version = '3.9.9' copyright = "Copyright (c) %s The SCons Foundation" % copyright_years # diff --git a/bin/SConsDoc.py b/bin/SConsDoc.py index 1e88c5b..e211b3c 100644 --- a/bin/SConsDoc.py +++ b/bin/SConsDoc.py @@ -114,6 +114,7 @@ import os.path import re import sys import copy +import importlib # Do we have libxml2/libxslt/lxml? has_libxml2 = True @@ -867,7 +868,7 @@ def importfile(path): try: return importlib._bootstrap._load(spec) except ImportError: - raise ErrorDuringImport(path, sys.exc_info()) + raise Exception(path, sys.exc_info()) # Local Variables: # tab-width:4 diff --git a/bin/scons-time.py b/bin/scons-time.py index 6494349..37de2f0 100644 --- a/bin/scons-time.py +++ b/bin/scons-time.py @@ -40,7 +40,7 @@ import shutil import sys import tempfile import time -import subprocess + def HACK_for_exec(cmd, *args): """ @@ -49,9 +49,13 @@ def HACK_for_exec(cmd, *args): This function is a hack that calls exec() in a function with no internal functions. """ - if not args: exec(cmd) - elif len(args) == 1: exec(cmd, args[0]) - else: exec(cmd, args[0], args[1]) + if not args: + exec(cmd) + elif len(args) == 1: + exec(cmd, args[0]) + else: + exec(cmd, args[0], args[1]) + class Plotter(object): def increment_size(self, largest): @@ -76,6 +80,7 @@ class Plotter(object): increment = self.increment_size(largest) return ((largest + increment - 1) // increment) * increment + class Line(object): def __init__(self, points, type, title, label, comment, fmt="%s %s"): self.points = points @@ -111,10 +116,11 @@ class Line(object): print('e') def get_x_values(self): - return [ p[0] for p in self.points ] + return [p[0] for p in self.points] def get_y_values(self): - return [ p[1] for p in self.points ] + return [p[1] for p in self.points] + class Gnuplotter(Plotter): @@ -201,22 +207,21 @@ class Gnuplotter(Plotter): max_y = self.max_graph_value(self.get_max_y()) incr = (max_y - min_y) / 10.0 start = min_y + (max_y / 2.0) + (2.0 * incr) - position = [ start - (i * incr) for i in range(5) ] + position = [start - (i * incr) for i in range(5)] inx = 1 for line in self.lines: - line.print_label(inx, line.points[0][0]-1, - position[(inx-1) % len(position)]) + line.print_label(inx, line.points[0][0] - 1, + position[(inx - 1) % len(position)]) inx += 1 - plot_strings = [ self.plot_string(l) for l in self.lines ] + plot_strings = [self.plot_string(l) for l in self.lines] print('plot ' + ', \\\n '.join(plot_strings)) for line in self.lines: line.print_points() - def untar(fname): import tarfile tar = tarfile.open(name=fname, mode='r') @@ -224,6 +229,7 @@ def untar(fname): tar.extract(tarinfo) tar.close() + def unzip(fname): import zipfile zf = zipfile.ZipFile(fname, 'r') @@ -231,11 +237,12 @@ def unzip(fname): dir = os.path.dirname(name) try: os.makedirs(dir) - except: + except OSError: pass with open(name, 'wb') as f: f.write(zf.read(name)) + def read_tree(dir): for dirpath, dirnames, filenames in os.walk(dir): for fn in filenames: @@ -244,14 +251,15 @@ def read_tree(dir): with open(fn, 'rb') as f: f.read() + def redirect_to_file(command, log): return '%s > %s 2>&1' % (command, log) + def tee_to_file(command, log): return '%s 2>&1 | tee %s' % (command, log) - class SConsTimer(object): """ Usage: scons-time SUBCOMMAND [ARGUMENTS] @@ -267,45 +275,45 @@ class SConsTimer(object): """ name = 'scons-time' - name_spaces = ' '*len(name) + name_spaces = ' ' * len(name) def makedict(**kw): return kw default_settings = makedict( - chdir = None, - config_file = None, - initial_commands = [], - key_location = 'bottom left', - orig_cwd = os.getcwd(), - outdir = None, - prefix = '', - python = '"%s"' % sys.executable, - redirect = redirect_to_file, - scons = None, - scons_flags = '--debug=count --debug=memory --debug=time --debug=memoizer', - scons_lib_dir = None, - scons_wrapper = None, - startup_targets = '--help', - subdir = None, - subversion_url = None, - svn = 'svn', - svn_co_flag = '-q', - tar = 'tar', - targets = '', - targets0 = None, - targets1 = None, - targets2 = None, - title = None, - unzip = 'unzip', - verbose = False, - vertical_bars = [], - - unpack_map = { - '.tar.gz' : (untar, '%(tar)s xzf %%s'), - '.tgz' : (untar, '%(tar)s xzf %%s'), - '.tar' : (untar, '%(tar)s xf %%s'), - '.zip' : (unzip, '%(unzip)s %%s'), + chdir=None, + config_file=None, + initial_commands=[], + key_location='bottom left', + orig_cwd=os.getcwd(), + outdir=None, + prefix='', + python='"%s"' % sys.executable, + redirect=redirect_to_file, + scons=None, + scons_flags='--debug=count --debug=memory --debug=time --debug=memoizer', + scons_lib_dir=None, + scons_wrapper=None, + startup_targets='--help', + subdir=None, + subversion_url=None, + svn='svn', + svn_co_flag='-q', + tar='tar', + targets='', + targets0=None, + targets1=None, + targets2=None, + title=None, + unzip='unzip', + verbose=False, + vertical_bars=[], + + unpack_map={ + '.tar.gz': (untar, '%(tar)s xzf %%s'), + '.tgz': (untar, '%(tar)s xzf %%s'), + '.tar': (untar, '%(tar)s xf %%s'), + '.zip': (unzip, '%(unzip)s %%s'), }, ) @@ -329,10 +337,10 @@ class SConsTimer(object): ] stage_strings = { - 'pre-read' : 'Memory before reading SConscript files:', - 'post-read' : 'Memory after reading SConscript files:', - 'pre-build' : 'Memory before building targets:', - 'post-build' : 'Memory after building targets:', + 'pre-read': 'Memory before reading SConscript files:', + 'post-read': 'Memory after reading SConscript files:', + 'pre-build': 'Memory before building targets:', + 'post-build': 'Memory after building targets:', } memory_string_all = 'Memory ' @@ -340,10 +348,10 @@ class SConsTimer(object): default_stage = stages[-1] time_strings = { - 'total' : 'Total build time', - 'SConscripts' : 'Total SConscript file execution time', - 'SCons' : 'Total SCons execution time', - 'commands' : 'Total command execution time', + 'total': 'Total build time', + 'SConscripts': 'Total SConscript file execution time', + 'SCons': 'Total SCons execution time', + 'commands': 'Total command execution time', } time_string_all = 'Total .* time' @@ -425,7 +433,7 @@ class SConsTimer(object): Executes a list of commands, substituting values from the specified dictionary. """ - commands = [ self.subst_variables(c, dict) for c in commands ] + commands = [self.subst_variables(c, dict) for c in commands] for action, string, args in commands: self.display(string, *args) sys.stdout.flush() @@ -444,11 +452,11 @@ class SConsTimer(object): p = os.popen(command) output = p.read() p.close() - #TODO: convert to subrocess, os.popen is obsolete. This didn't work: - #process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True) - #output = process.stdout.read() - #process.stdout.close() - #process.wait() + # TODO: convert to subrocess, os.popen is obsolete. This didn't work: + # process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True) + # output = process.stdout.read() + # process.stdout.close() + # process.wait() if self.verbose: sys.stdout.write(output) # TODO: Figure out @@ -563,7 +571,7 @@ class SConsTimer(object): except IndexError: t = '??? %s ???' % i results[i].sort() - gp.line(results[i], i+1, t, None, t, fmt=fmt) + gp.line(results[i], i + 1, t, None, t, fmt=fmt) for bar_tuple in self.vertical_bars: try: @@ -592,11 +600,13 @@ class SConsTimer(object): if lines[0] == '': lines = lines[1:] spaces = re.match(' *', lines[0]).group(0) - def strip_initial_spaces(l, s=spaces): - if l.startswith(spaces): - l = l[len(spaces):] - return l - return '\n'.join([ strip_initial_spaces(l) for l in lines ]) + '\n' + + def strip_initial_spaces(line, s=spaces): + if line.startswith(spaces): + line = line[len(spaces):] + return line + + return '\n'.join([strip_initial_spaces(l) for l in lines]) + '\n' def profile_name(self, invocation): """ @@ -625,7 +635,7 @@ class SConsTimer(object): sys.stderr.write('file %s has no contents!\n' % repr(file)) return None result = re.findall(r'%s: ([\d.]*)' % search_string, contents)[-4:] - result = [ float(r) for r in result ] + result = [float(r) for r in result] if time_string is not None: try: result = result[0] @@ -646,7 +656,7 @@ class SConsTimer(object): sys.stderr.write('%s Cannot use the "func" subcommand.\n' % self.name_spaces) sys.exit(1) statistics = pstats.Stats(file).stats - matches = [ e for e in statistics.items() if e[0][2] == function ] + matches = [e for e in statistics.items() if e[0][2] == function] r = matches[0] return r[0][0], r[0][1], r[0][2], r[1][3] @@ -667,8 +677,8 @@ class SConsTimer(object): search_string = memory_string with open(file) as f: lines = f.readlines() - lines = [ l for l in lines if l.startswith(search_string) ][-4:] - result = [ int(l.split()[-1]) for l in lines[-4:] ] + lines = [l for l in lines if l.startswith(search_string)][-4:] + result = [int(l.split()[-1]) for l in lines[-4:]] if len(result) == 1: result = result[0] return result @@ -680,13 +690,12 @@ class SConsTimer(object): object_string = ' ' + object_name + '\n' with open(file) as f: lines = f.readlines() - line = [ l for l in lines if l.endswith(object_string) ][0] - result = [ int(field) for field in line.split()[:4] ] + line = [l for l in lines if l.endswith(object_string)][0] + result = [int(field) for field in line.split()[:4]] if index is not None: result = result[index] return result - command_alias = {} def execute_subcommand(self, argv): @@ -841,7 +850,7 @@ class SConsTimer(object): for file in args: try: f, line, func, time = \ - self.get_function_profile(file, function_name) + self.get_function_profile(file, function_name) except ValueError as e: sys.stderr.write("%s: func: %s: %s\n" % (self.name, file, e)) @@ -956,7 +965,7 @@ class SConsTimer(object): args = self.args_to_files(args, tail) - cwd_ = os.getcwd() + os.sep + # cwd_ = os.getcwd() + os.sep if format == 'ascii': @@ -1216,11 +1225,11 @@ class SConsTimer(object): except ValueError: result.append(int(n)) else: - result.extend(list(range(int(x), int(y)+1))) + result.extend(list(range(int(x), int(y) + 1))) return result def scons_path(self, dir): - return os.path.join(dir,'scripts', 'scons.py') + return os.path.join(dir, 'scripts', 'scons.py') def scons_lib_dir_path(self, dir): return os.path.join(dir, 'src', 'engine') @@ -1247,9 +1256,9 @@ class SConsTimer(object): if prepare: prepare(commands, removals) - save_scons = self.scons - save_scons_wrapper = self.scons_wrapper - save_scons_lib_dir = self.scons_lib_dir + save_scons = self.scons + save_scons_wrapper = self.scons_wrapper + save_scons_lib_dir = self.scons_lib_dir if self.outdir is None: self.outdir = self.orig_cwd @@ -1308,7 +1317,7 @@ class SConsTimer(object): commands.extend([ (lambda: read_tree('.'), - 'find * -type f | xargs cat > /dev/null'), + 'find * -type f | xargs cat > /dev/null'), (self.set_env, 'export %%s=%%s', 'SCONS_LIB_DIR', self.scons_lib_dir), @@ -1338,9 +1347,9 @@ class SConsTimer(object): self.run_command_list(commands, self.__dict__) - self.scons = save_scons - self.scons_lib_dir = save_scons_lib_dir - self.scons_wrapper = save_scons_wrapper + self.scons = save_scons + self.scons_lib_dir = save_scons_lib_dir + self.scons_wrapper = save_scons_wrapper # @@ -1454,6 +1463,7 @@ class SConsTimer(object): sys.stderr.write('%s: time: Unknown format "%s".\n' % (self.name, format)) sys.exit(1) + if __name__ == '__main__': opts, args = getopt.getopt(sys.argv[1:], 'h?V', ['help', 'version']) diff --git a/runtest.py b/runtest.py index 10d16ba..519cc74 100755 --- a/runtest.py +++ b/runtest.py @@ -486,26 +486,8 @@ ld = None if not baseline or baseline == '.': base = cwd elif baseline == '-': - url = None - with os.popen("svn info 2>&1", "r") as p: - svn_info = p.read() - match = re.search(r'URL: (.*)', svn_info) - if match: - url = match.group(1) - if not url: - sys.stderr.write('runtest.py: could not find a URL:\n') - sys.stderr.write(svn_info) - sys.exit(1) - import tempfile - base = tempfile.mkdtemp(prefix='runtest-tmp-') - - command = 'cd %s && svn co -q %s' % (base, url) - - base = os.path.join(base, os.path.split(url)[1]) - if printcommand: - print(command) - if execute_tests: - os.system(command) + print("This logic used to checkout from svn. It's been removed. If you used this, please let us know on devel mailing list, IRC, or discord server") + sys.exit(-1) else: base = baseline diff --git a/setup.py b/setup.py index 349a24e..d6b7783 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,5 @@ import fnmatch -from setuptools import find_packages, setup +from setuptools import setup from setuptools.command.build_py import build_py as build_py_orig diff --git a/site_scons/BuildCommandLine.py b/site_scons/BuildCommandLine.py index 4694472..b8c7d63 100644 --- a/site_scons/BuildCommandLine.py +++ b/site_scons/BuildCommandLine.py @@ -102,25 +102,28 @@ class BuildCommandLine(object): self.revision = ARGUMENTS.get('REVISION', '') - def generate_build_id(revision): + def _generate_build_id(revision): return revision + generate_build_id=_generate_build_id + if not self.revision and BuildCommandLine.git: with os.popen("%s rev-parse HEAD 2> /dev/null" % BuildCommandLine.git, "r") as p: self.git_hash = p.read().strip() - def generate_build_id(revision): + def _generate_build_id_git(revision): result = self.git_hash if [l for l in self.git_status_lines if 'modified' in l]: result = result + '[MODIFIED]' return result + generate_build_id = _generate_build_id_git self.revision = self.git_hash self.checkpoint = ARGUMENTS.get('CHECKPOINT', '') if self.checkpoint: if self.checkpoint == 'd': - cself.heckpoint = time.strftime('%Y%m%d', time.localtime(time.time())) + self.checkpoint = time.strftime('%Y%m%d', time.localtime(time.time())) elif self.checkpoint == 'r': self.checkpoint = 'r' + self.revision self.version = self.version + '.beta.' + self.checkpoint diff --git a/site_scons/epydoc.py b/site_scons/epydoc.py index da74d9c..3d6e5de 100644 --- a/site_scons/epydoc.py +++ b/site_scons/epydoc.py @@ -53,7 +53,7 @@ if not epydoc_cli: from epydoc.docbuilder import build_doc_index from epydoc.docwriter.html import HTMLWriter - from epydoc.docwriter.latex import LatexWriter + # from epydoc.docwriter.latex import LatexWriter # first arg is a list where can be names of python package dirs, # python files, object names or objects itself diff --git a/site_scons/site_init.py b/site_scons/site_init.py index 7e7c569..81c4753 100644 --- a/site_scons/site_init.py +++ b/site_scons/site_init.py @@ -1,8 +1,10 @@ +import os.path + from SConsRevision import SCons_revision from Utilities import is_windows, whereis, platform, deb_date from zip_utils import unzipit, zipit, zcat from soe_utils import soelim, soscan, soelimbuilder -from epydoc import epydoc_cli, epydoc_commands +# from epydoc import epydoc_cli, epydoc_commands from BuildCommandLine import BuildCommandLine gzip = whereis('gzip') diff --git a/src/engine/SCons/Utilities/sconsign.py b/src/engine/SCons/Utilities/sconsign.py index 8b16b18..89084ba 100644 --- a/src/engine/SCons/Utilities/sconsign.py +++ b/src/engine/SCons/Utilities/sconsign.py @@ -218,12 +218,12 @@ def nodeinfo_raw(name, ninfo, prefix=""): keys = ninfo.field_list + ['_version_id'] except AttributeError: keys = sorted(d.keys()) - l = [] - for k in keys: - l.append('%s: %s' % (repr(k), repr(d.get(k)))) + values = [] + for key in keys: + values.append('%s: %s' % (repr(key), repr(d.get(key)))) if '\n' in name: name = repr(name) - return name + ': {' + ', '.join(l) + '}' + return name + ': {' + ', '.join(values) + '}' def nodeinfo_cooked(name, ninfo, prefix=""): @@ -280,7 +280,7 @@ def printentries(entries, location): for name in sorted(entries.keys()): entry = entries[name] try: - ninfo = entry.ninfo + entry.ninfo except AttributeError: print(name + ":") else: diff --git a/test/scons-time/run/archive/dir.py b/test/scons-time/run/archive/dir.py index 6b6d992..590d568 100644 --- a/test/scons-time/run/archive/dir.py +++ b/test/scons-time/run/archive/dir.py @@ -32,7 +32,6 @@ directory tree. import TestSCons_time test = TestSCons_time.TestSCons_time() -test.verbose_set(1) test.write_fake_scons_py() -- cgit v0.12 From b94470116ca5cb31cb9f9737adf24ea9b69b0f55 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 11 Apr 2020 17:08:05 -0700 Subject: Address PR comments --- src/engine/SCons/Tool/MSCommon/vc.py | 2 -- src/engine/SCons/Tool/msvc.xml | 10 +++++----- test/Win32/scons-bat-error.py | 2 +- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py index ce1341d..456ccae 100644 --- a/src/engine/SCons/Tool/MSCommon/vc.py +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -338,8 +338,6 @@ def msvc_find_vswhere(): # 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. - # TODO: requested to add a user-specified path to vswhere - # and have this routine set the same var if it finds it. vswhere_path = None for pf in VSWHERE_PATHS: if os.path.exists(pf): diff --git a/src/engine/SCons/Tool/msvc.xml b/src/engine/SCons/Tool/msvc.xml index bdbf253..3e8ec95 100644 --- a/src/engine/SCons/Tool/msvc.xml +++ b/src/engine/SCons/Tool/msvc.xml @@ -487,14 +487,14 @@ It was initially distributed with MSVS 2017. But can detect MSVC 2010 and newer If &cv-VSWHERE; is set, SCons will use that location. -Otherwise SCons will look in the following locations and set VSWHERE to the PATH vswhere.exe -is located. +Otherwise SCons will look in the following locations and set VSWHERE to the first directory vswhere.exe +is found. -Note that &cv-VSWHERE; must be set in when tool msvc is initialized. This is either in the call to +Note that &cv-VSWHERE; must be set at the same time or prior to the msvc tool being initialized. So either set it as follows Environment(VSWHERE='c:/my/path/to/vswhere') or -if Environment created specifying not to automatically initialize any tools or tools which doesn't include msvc or MSVS -such as Environment(Tools=[]) +if your Environment() is created specifying no tools tools=[] or with a list of tools not including msvs or msvc or mslink + such as Environment(Tools=[]) diff --git a/test/Win32/scons-bat-error.py b/test/Win32/scons-bat-error.py index 4d5d00c..d772132 100644 --- a/test/Win32/scons-bat-error.py +++ b/test/Win32/scons-bat-error.py @@ -39,7 +39,7 @@ if sys.platform != 'win32': msg = "Skipping scons.bat test on non-Windows platform '%s'\n" % sys.platform test.skip_test(msg) -python = sys.executable #test.where_is('python') +python = test.where_is('python') if not python: msg = "Skipping scons.bat test; python is not on %PATH%.\n" -- cgit v0.12 From e0ad3d9278e9344c26557265f9970ded675bb92d Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 11 Apr 2020 21:24:47 -0700 Subject: resolve some sider issues --- bin/scons-time.py | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/bin/scons-time.py b/bin/scons-time.py index 37de2f0..693b254 100644 --- a/bin/scons-time.py +++ b/bin/scons-time.py @@ -894,7 +894,11 @@ class SConsTimer(object): def do_mem(self, argv): format = 'ascii' - logfile_path = lambda x: x + def _logfile_path(x): + return x + + logfile_path = _logfile_path + stage = self.default_stage tail = None @@ -943,10 +947,12 @@ class SConsTimer(object): if self.chdir: os.chdir(self.chdir) - logfile_path = lambda x: os.path.join(self.chdir, x) + def _logfile_path_join(x): + return os.path.join(self.chdir, x) - if not args: + logfile_path = _logfile_path_join + if not args: pattern = '%s*.log' % self.prefix args = self.args_to_files([pattern], tail) @@ -1008,7 +1014,12 @@ class SConsTimer(object): def do_obj(self, argv): format = 'ascii' - logfile_path = lambda x: x + + def _logfile_path(x): + return x + + logfile_path = _logfile_path + stage = self.default_stage tail = None @@ -1065,10 +1076,13 @@ class SConsTimer(object): if self.chdir: os.chdir(self.chdir) - logfile_path = lambda x: os.path.join(self.chdir, x) - if not args: + def _logfile_path_join(x): + return os.path.join(self.chdir, x) + logfile_path = _logfile_path_join + + if not args: pattern = '%s*.log' % self.prefix args = self.args_to_files([pattern], tail) @@ -1372,7 +1386,12 @@ class SConsTimer(object): def do_time(self, argv): format = 'ascii' - logfile_path = lambda x: x + + def _logfile_path(x): + return x + + logfile_path = _logfile_path + tail = None which = 'total' @@ -1422,10 +1441,13 @@ class SConsTimer(object): if self.chdir: os.chdir(self.chdir) - logfile_path = lambda x: os.path.join(self.chdir, x) - if not args: + def _logfile_path_join(x): + return os.path.join(self.chdir, x) + logfile_path = _logfile_path_join + + if not args: pattern = '%s*.log' % self.prefix args = self.args_to_files([pattern], tail) -- cgit v0.12 From ac04f36c2aae0408a5f024dfbdc56a9751e8c144 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sun, 12 Apr 2020 09:49:33 -0600 Subject: [PR #3611] implicit deps fix review comment [ci skip] The updated wording suggested any non-zero value for IMPLICIT_COMMAND_DEPENDENCIES was the same as the default, but in fact values >1 have a different meaning. In updating the wording, nocited that Action.py didn't recognize False-like values the same way as they were listed, or like other parts of scons, where there are multiple false-like values - updated. Signed-off-by: Mats Wichmann --- src/engine/SCons/Action.py | 2 +- src/engine/SCons/Action.xml | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index c02dd33..5bc85d5 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -964,7 +964,7 @@ class CommandAction(_ActionAction): if is_String(icd) and icd[:1] == '$': icd = env.subst(icd) - if not icd or icd in ('0', 'None'): + if not icd or str(icd).lower in ('0', 'none', 'false', 'no', 'off'): return [] try: diff --git a/src/engine/SCons/Action.xml b/src/engine/SCons/Action.xml index 107e389..b519cdc 100644 --- a/src/engine/SCons/Action.xml +++ b/src/engine/SCons/Action.xml @@ -50,8 +50,10 @@ in the &consenv; used to execute the command. The default is the same as setting the &consvar; &cv-IMPLICIT_COMMAND_DEPENDENCIES; -to a true value (True, -any non-zero number, etc.). +to a True-like value (true, +yes, +or 1 - but not a number +greater than one, as that has a different meaning). @@ -68,10 +70,11 @@ is applied to each segment. If &cv-IMPLICIT_COMMAND_DEPENDENCIES; -is set to a false value -(None, -False, -0, +is set to a False-like value +(none, +false, +no, +0, etc.), then the implicit dependency will not be added to the targets @@ -80,7 +83,7 @@ built with that &consenv;. If &cv-IMPLICIT_COMMAND_DEPENDENCIES; -is set to integer 2 or higher, +is set to 2 or higher, then that number of arguments in the command line will be scanned for relative or absolute paths. If any are present, they will be added as @@ -97,7 +100,7 @@ to the working directory. If &cv-IMPLICIT_COMMAND_DEPENDENCIES; -is set to all, +is set to all, then all arguments in the command line will be scanned for relative or absolute paths. If any are present, they will be added as -- cgit v0.12 From afc8807fcc940e9b31043b1cdca68fd29c23719c Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 12 Apr 2020 15:53:59 -0700 Subject: Address comments on PR for docs --- src/engine/SCons/Tool/msvc.xml | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/engine/SCons/Tool/msvc.xml b/src/engine/SCons/Tool/msvc.xml index 3e8ec95..48ce13f 100644 --- a/src/engine/SCons/Tool/msvc.xml +++ b/src/engine/SCons/Tool/msvc.xml @@ -482,14 +482,23 @@ Specify the location of vswhere.exe. -vswhere.exe is used to locate MSVC/MSVS installations. -It was initially distributed with MSVS 2017. But can detect MSVC 2010 and newer with -legacy argument. +Propose: The vswhere command is distributed with Microsoft Visual Studio and Build + Tools since the 2017 edition, but is also available standalone. It fully detects 2017 and later editions, + but with the argument, can detect installations of the 2010 through 2015 + editions with limited data returned. If &cv-VSWHERE; is set, SCons will use that location. -Otherwise SCons will look in the following locations and set VSWHERE to the first directory vswhere.exe -is found. + Otherwise SCons will look in the following locations and set &cv-VSWHERE; to the path of the first vswhere.exe +located. + + +%ProgramFiles(x86)%\Microsoft Visual Studio\Installer +"%ProgramFiles%\Microsoft Visual Studio\Installer +%ChocolateyInstall%\bin + + Note that &cv-VSWHERE; must be set at the same time or prior to the msvc tool being initialized. So either set it as follows Environment(VSWHERE='c:/my/path/to/vswhere') or @@ -499,11 +508,7 @@ if your Environment() is created specifying no tools tools=[] - -%ProgramFiles(x86)%\Microsoft Visual Studio\Installer -"%ProgramFiles%\Microsoft Visual Studio\Installer -%ChocolateyInstall%\bin - + -- cgit v0.12 From 5c8ff63775a475510dc9fd555b99bdf0bf319d79 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 12 Apr 2020 15:54:28 -0700 Subject: If no vswhere.exe is found, do not try to run it. Was breaking tests on non-win32 --- src/engine/SCons/Tool/MSCommon/vc.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py index 456ccae..58be07c 100644 --- a/src/engine/SCons/Tool/MSCommon/vc.py +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -366,6 +366,9 @@ def find_vc_pdir_vswhere(msvc_version, env=None): else: vswhere_path = env.subst('$VSWHERE') + if vswhere_path is None: + return None + debug('find_vc_pdir_vswhere(): VSWHERE = %s'%vswhere_path) vswhere_cmd = [ vswhere_path, @@ -374,6 +377,8 @@ def find_vc_pdir_vswhere(msvc_version, env=None): "-property", "installationPath", ] + debug("find_vc_pdir_vswhere(): running: %s" % vswhere_cmd) + #cp = subprocess.run(vswhere_cmd, capture_output=True) # 3.7+ only cp = subprocess.run(vswhere_cmd, stdout=PIPE, stderr=PIPE) -- cgit v0.12 From c82e9618c97b084f8c385ae55637d3ac6cf2ed2a Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 12 Apr 2020 15:57:56 -0700 Subject: resolve sider issue. import sys not needed --- src/engine/SCons/Tool/MSCommon/vcTests.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/engine/SCons/Tool/MSCommon/vcTests.py b/src/engine/SCons/Tool/MSCommon/vcTests.py index f5f7a44..3474887 100644 --- a/src/engine/SCons/Tool/MSCommon/vcTests.py +++ b/src/engine/SCons/Tool/MSCommon/vcTests.py @@ -24,7 +24,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" -import sys import os import os.path import unittest -- cgit v0.12 From 9c295184d3efbaff6d24d656f503f3ee1fb380b8 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 12 Apr 2020 17:57:00 -0700 Subject: fix vcTests.py creating already existing dir on win32 --- src/engine/SCons/Tool/MSCommon/vcTests.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/engine/SCons/Tool/MSCommon/vcTests.py b/src/engine/SCons/Tool/MSCommon/vcTests.py index 3474887..884e90e 100644 --- a/src/engine/SCons/Tool/MSCommon/vcTests.py +++ b/src/engine/SCons/Tool/MSCommon/vcTests.py @@ -48,7 +48,8 @@ MS_TOOLS_VERSION='1.1.1' class VswhereTestCase(unittest.TestCase): @staticmethod def _createVSWhere(path): - os.makedirs(os.path.dirname(path)) + if not os.path.isdir(os.path.dirname(path)): + os.makedirs(os.path.dirname(path)) with open(path, 'w') as f: f.write("Created:%s"%f) -- cgit v0.12 From c69043c502044994840e246d8c4926a15b7d2bdb Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 12 Apr 2020 19:37:01 -0700 Subject: We're all py3 now can use exist_ok=True on os.mkdirs(). Thanks mwichmann --- src/engine/SCons/Tool/MSCommon/vcTests.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/engine/SCons/Tool/MSCommon/vcTests.py b/src/engine/SCons/Tool/MSCommon/vcTests.py index 884e90e..eb09def 100644 --- a/src/engine/SCons/Tool/MSCommon/vcTests.py +++ b/src/engine/SCons/Tool/MSCommon/vcTests.py @@ -48,8 +48,7 @@ MS_TOOLS_VERSION='1.1.1' class VswhereTestCase(unittest.TestCase): @staticmethod def _createVSWhere(path): - if not os.path.isdir(os.path.dirname(path)): - os.makedirs(os.path.dirname(path)) + os.makedirs(os.path.dirname(path), exist_ok=True) with open(path, 'w') as f: f.write("Created:%s"%f) -- cgit v0.12 From d3f1aa7d7225bff44a18b7ccaad52af071494dab Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 14 Apr 2020 10:39:53 -0700 Subject: [ci skip] adding notice that python bootstrap.py is now obsolete --- bootstrap.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bootstrap.py b/bootstrap.py index 7d8528a..3bf53ea 100755 --- a/bootstrap.py +++ b/bootstrap.py @@ -220,6 +220,10 @@ def main(): if __name__ == "__main__": + print("Please use") + print("python scripts/scons.py") + print("Instead of python bootstrap.py. Bootstrap.py is obsolete") + sys.exit(-1) main() # Local Variables: -- cgit v0.12 From 9ec99deef3afe9d6230b29cc87cfc5ecc9916186 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Thu, 16 Apr 2020 11:16:37 -0600 Subject: Update generation of scons-xml entities [ci skip] PR #3602 introduced a new problem - the documents that include the generated functions and builders files now don't validate. The global function/environment method name was bolded by using , but Docbook doesn't allow that inside a element (it actually works fine with the processing tools we use, but does fail validation). Rework the idea: use and for the markup, and change the way those are rendered in html (man/html.xsl and user/html.xsl) - the PDF already rendered these in bold so no change needed there. Also don't wrap the whole contents of the element in , which would have left the argument list in regular font which the function name and instance name in monospace - an odd look. So the argument list was wrapped in , since that's what they are. Don't bother to try to parse it down into individual args, just do the whole chunk, less the parentheses. Signed-off-by: Mats Wichmann --- bin/scons-proc.py | 51 +++++++++++++++++++++++++++++++++++---------------- doc/man/html.xsl | 8 +++++++- doc/user/html.xsl | 9 +++++++-- 3 files changed, 49 insertions(+), 19 deletions(-) diff --git a/bin/scons-proc.py b/bin/scons-proc.py index ac52894..d6e5030 100644 --- a/bin/scons-proc.py +++ b/bin/scons-proc.py @@ -254,6 +254,7 @@ class Proxy(object): ## return self.__dict__ < other.__dict__ class SConsThing(Proxy): + """Base class for the SConsDoc special elements""" def idfunc(self): return self.name @@ -263,6 +264,7 @@ class SConsThing(Proxy): return [e] class Builder(SConsThing): + """Generate the descriptions and entities for elements""" description = 'builder' prefix = 'b-' tag = 'function' @@ -272,20 +274,20 @@ class Builder(SConsThing): builders don't show a full signature, just func() """ + # build term for global function gterm = stf.newNode("term") - sig = stf.newSubNode(gterm, "literal") - func = stf.newSubNode(sig, "emphasis", role="bold") + func = stf.newSubNode(gterm, "function") stf.setText(func, self.name) stf.setTail(func, '()') + # build term for env. method mterm = stf.newNode("term") - sig = stf.newSubNode(mterm, "literal") - inst = stf.newSubNode(sig, "replaceable") + inst = stf.newSubNode(mterm, "parameter") stf.setText(inst, "env") stf.setTail(inst, ".") - func = stf.newSubNode(sig, "emphasis", role="bold") - stf.setText(func, self.name) - stf.setTail(func, '()') + meth = stf.newSubNode(mterm, "methodname") + stf.setText(meth, self.name) + stf.setTail(meth, '()') return [gterm, mterm] @@ -293,6 +295,7 @@ class Builder(SConsThing): return self.name class Function(SConsThing): + """Generate the descriptions and entities for elements""" description = 'function' prefix = 'f-' tag = 'function' @@ -314,23 +317,37 @@ class Function(SConsThing): signature = 'both' if stf.hasAttribute(arg, 'signature'): signature = stf.getAttribute(arg, 'signature') - s = stf.getText(arg).strip() + sig = stf.getText(arg).strip()[1:-1] # strip (), temporarily if signature in ('both', 'global'): + # build term for global function gterm = stf.newNode("term") - sig = stf.newSubNode(gterm, "literal") - func = stf.newSubNode(sig, "emphasis", role="bold") + func = stf.newSubNode(gterm, "function") stf.setText(func, self.name) - stf.setTail(func, s) + if sig: + # if there are parameters, use that entity + stf.setTail(func, "(") + s = stf.newSubNode(gterm, "parameter") + stf.setText(s, sig) + stf.setTail(s, ")") + else: + stf.setTail(func, "()") tlist.append(gterm) if signature in ('both', 'env'): + # build term for env. method mterm = stf.newNode("term") - sig = stf.newSubNode(mterm, "literal") - inst = stf.newSubNode(sig, "replaceable") + inst = stf.newSubNode(mterm, "replaceable") stf.setText(inst, "env") stf.setTail(inst, ".") - func = stf.newSubNode(sig, "emphasis", role="bold") - stf.setText(func, self.name) - stf.setTail(func, s) + meth = stf.newSubNode(mterm, "methodname") + stf.setText(meth, self.name) + if sig: + # if there are parameters, use that entity + stf.setTail(meth, "(") + s = stf.newSubNode(mterm, "parameter") + stf.setText(s, sig) + stf.setTail(s, ")") + else: + stf.setTail(meth, "()") tlist.append(mterm) if not tlist: @@ -341,6 +358,7 @@ class Function(SConsThing): return self.name class Tool(SConsThing): + """Generate the descriptions and entities for elements""" description = 'tool' prefix = 't-' tag = 'literal' @@ -352,6 +370,7 @@ class Tool(SConsThing): return self.name class Variable(SConsThing): + """Generate the descriptions and entities for elements""" description = 'construction variable' prefix = 'cv-' tag = 'envar' diff --git a/doc/man/html.xsl b/doc/man/html.xsl index 00cc782..d4f33da 100644 --- a/doc/man/html.xsl +++ b/doc/man/html.xsl @@ -28,7 +28,7 @@ xmlns:fo="http://www.w3.org/1999/XSL/Format" version="1.0"> - + @@ -54,6 +54,12 @@ reference title set toc,title + + + + + + diff --git a/doc/user/html.xsl b/doc/user/html.xsl index 0c215cf..2cef43d 100644 --- a/doc/user/html.xsl +++ b/doc/user/html.xsl @@ -28,7 +28,7 @@ xmlns:fo="http://www.w3.org/1999/XSL/Format" version="1.0"> - + @@ -54,9 +54,14 @@ reference toc,title set toc,title + + + + + + - -- cgit v0.12 From 88449724330bb0864b74d6ff1b30b26eb03eff4b Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Thu, 9 Apr 2020 09:45:13 -0600 Subject: Update markup on TARGETS, SOURCES, ARGUMENTS [ci skip] Use to mark up variables in these three areas, also a few other variables that were marked up differently. Sometimes that markup comes in the form of using an existing entity (&BUILD_TARGETS; for example), which is already suitably marked up in the entity definition. Use to mark up when they're in the context of function params. The parse_flags kwarg now includes a link to the env.ParseFlags method, since the latter describes how the args are distributed. Signed-off-by: Mats Wichmann --- doc/man/scons.xml | 106 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 55 insertions(+), 51 deletions(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index 5630e93..6c46462 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -1185,11 +1185,11 @@ and re-initialize the dependency graph from scratch. build[OPTIONS] [TARGETS] ... Builds the specified -TARGETS +TARGETS (and their dependencies) with the specified SCons command-line -OPTIONS. +OPTIONS. b and scons @@ -1232,9 +1232,10 @@ which only happens once at the beginning of interactive mode). clean[OPTIONS] [TARGETS] ... Cleans the specified -TARGETS +TARGETS (and their dependencies) -with the specified options. +with the specified +OPTIONS. c is a synonym. This command is itself a synonym for @@ -2000,15 +2001,15 @@ These warnings are enabled by default. Warnings about attempts to set the reserved &consvar; names -CHANGED_SOURCES, -CHANGED_TARGETS, -TARGET, -TARGETS, -SOURCE, -SOURCES, -UNCHANGED_SOURCES +CHANGED_SOURCES, +CHANGED_TARGETS, +TARGET, +TARGETS, +SOURCE, +SOURCES, +UNCHANGED_SOURCES or -UNCHANGED_TARGETS. +UNCHANGED_TARGETS. These warnings are disabled by default. @@ -2105,7 +2106,7 @@ env['BAR'] = 'bar' As a convenience, &consvars; may also be set or modified by the -parse_flags +parse_flags keyword argument, which applies the &f-link-env-MergeFlags; method (described below) to the argument value @@ -2119,11 +2120,15 @@ env = Environment(parse_flags='-Iinclude -DEBUG -lm') This example adds 'include' to -CPPPATH, +the CPPPATH &consvar; 'EBUG' to -CPPDEFINES, +CPPDEFINES, and 'm' to -LIBS. +LIBS. +&f-link-env-ParseFlags; describes how these arguments +are distributed to &consvars;. + + By default, a new &consenv; is initialized with a set of builder methods @@ -2148,21 +2153,21 @@ and suffixes appropriate for that platform. Note that the win32 platform adds the -SystemDrive +SystemDrive and -SystemRoot +SystemRoot variables from the user's external environment to the &consenv;'s -ENV +ENV dictionary. This is so that any executed commands that use sockets to connect with other systems (such as fetching source files from external CVS repository specifications like -:pserver:anonymous@cvs.sourceforge.net:/cvsroot/scons) +:pserver:anonymous@cvs.sourceforge.net:/cvsroot/scons) will work on Windows systems. -The platform argument may be a function or callable object. +The platform argument may be a function or callable object, in which case the &Environment; method will call it to update the new &consenv;: @@ -2259,15 +2264,15 @@ env = Environment(tools=[my_tool]) may also themselves be two-element lists of the form (toolname, kw_dict). SCons searches for the -toolname +toolname specification file as described above, and passes -kw_dict, +kw_dict, which must be a dictionary, as keyword arguments to the tool's -generate +generate function. The -generate +generate function can use the arguments to modify the tool's behavior by setting up the environment in different ways or otherwise changing its initialization. @@ -2535,7 +2540,7 @@ env.SharedLibrary('word', 'word.cpp', LIBSUFFIXES=['.ocx']) -Note that both the $SHLIBSUFFIX and $LIBSUFFIXES +Note that both the $SHLIBSUFFIX and $LIBSUFFIXES variables must be set if you want SCons to search automatically for dependencies on the non-standard library names; see the descriptions of these variables, below, for more information. @@ -2553,11 +2558,11 @@ env = Program('hello', 'hello.c', parse_flags='-Iinclude -DEBUG -lm') This example adds 'include' to -CPPPATH, +CPPPATH, 'EBUG' to -CPPDEFINES, +CPPDEFINES, and 'm' to -LIBS. +LIBS. Although the builder methods defined by &scons; @@ -2938,7 +2943,7 @@ to affect how you want the build to be performed. - ARGLIST + &ARGLIST; A list of the keyword=value @@ -2971,7 +2976,7 @@ for key, value in ARGLIST: - ARGUMENTS + &ARGUMENTS; A dictionary of all the keyword=value @@ -2981,8 +2986,7 @@ and if a given keyword has more than one value assigned to it on the command line, the last (right-most) value is -the one in the -ARGUMENTS +the one in the &ARGUMENTS; dictionary. Example: @@ -2997,7 +3001,7 @@ else: - BUILD_TARGETS + &BUILD_TARGETS; A list of the targets which &scons; @@ -3043,7 +3047,7 @@ if 'special/program' in BUILD_TARGETS: - COMMAND_LINE_TARGETS + &COMMAND_LINE_TARGETS; A list of the targets explicitly specified on the command line. If there are command line targets, @@ -3066,7 +3070,7 @@ if 'special/program' in COMMAND_LINE_TARGETS: - DEFAULT_TARGETS + &DEFAULT_TARGETS; A list of the target nodes @@ -5610,10 +5614,10 @@ and configured with the same &consenv; into single invocations of the Action object's command line or function. Command lines will typically want to use the -CHANGED_SOURCES +cHANGED_SOURCES &consvar; (and possibly -CHANGED_TARGETS +CHANGED_TARGETS as well) to only pass to the command line those sources that have actually changed since their targets were built. @@ -5944,7 +5948,7 @@ special variables for each command execution: - CHANGED_SOURCES + CHANGED_SOURCES The file names of all sources of the build command that have changed since the target was last built. @@ -5952,7 +5956,7 @@ that have changed since the target was last built. - CHANGED_TARGETS + CHANGED_TARGETS The file names of all targets that would be built from sources that have changed since the target was last built. @@ -5960,7 +5964,7 @@ from sources that have changed since the target was last built. - SOURCE + SOURCE The file name of the source of the build command, or the file name of the first source @@ -5969,14 +5973,14 @@ if multiple sources are being built. - SOURCES + SOURCES The file names of the sources of the build command. - TARGET + TARGET The file name of the target being built, or the file name of the first target @@ -5985,14 +5989,14 @@ if multiple targets are being built. - TARGETS + TARGETS The file names of all targets being built. - UNCHANGED_SOURCES + UNCHANGED_SOURCES The file names of all sources of the build command that have @@ -6245,7 +6249,7 @@ env=Environment(FOO=foo, BAR="$FOO baz") Python function by creating a callable class that stores one or more arguments in an object, and then uses them when the -__call__() +__call__() method is called. Note that in this case, the entire variable expansion must @@ -6347,12 +6351,12 @@ built, not when the SConscript is being read. So if later in the SConscript, the final value will be used. Here's a more interesting example. Note that all of -COND, -FOO, +COND, +FOO, and -BAR are &consvars;, +BAR are &consvars;, and their values are substituted into the final command. -FOO is a list, so its elements are interpolated +FOO is a list, so its elements are interpolated separated by spaces. @@ -6929,7 +6933,7 @@ env.Program(target = 'bar', source = 'bar.c') You also can use other Pythonic techniques to add -to the BUILDERS &consvar;, such as: +to the BUILDERS &consvar;, such as: env = Environment() -- cgit v0.12 From 944270dc1fd82c6fbb43f414f0ae87b2d3fe3976 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Thu, 16 Apr 2020 14:17:45 -0600 Subject: [PR #3612] doc update: cvars are [ci skip] Consider construction variable as environment variables, using that markup in scons.xml and generating it into the variables.gen file (which is included in man and userguide). If possible, use the entity from variables.mod, which already has the envar markup generated. Signed-off-by: Mats Wichmann --- bin/scons-proc.py | 12 ++++++++-- doc/man/scons.xml | 71 ++++++++++++++++++++++++++----------------------------- 2 files changed, 44 insertions(+), 39 deletions(-) diff --git a/bin/scons-proc.py b/bin/scons-proc.py index 4370004..30832a0 100644 --- a/bin/scons-proc.py +++ b/bin/scons-proc.py @@ -273,7 +273,7 @@ class Builder(SConsThing): """ # build term for global function gterm = stf.newNode("term") - func = stf.newSubNode(gterm, "function") + func = stf.newSubNode(gterm, Builder.tag) stf.setText(func, self.name) stf.setTail(func, '()') @@ -282,6 +282,7 @@ class Builder(SConsThing): inst = stf.newSubNode(mterm, "parameter") stf.setText(inst, "env") stf.setTail(inst, ".") + # we could use here, but it's a "method" meth = stf.newSubNode(mterm, "methodname") stf.setText(meth, self.name) stf.setTail(meth, '()') @@ -318,7 +319,7 @@ class Function(SConsThing): if signature in ('both', 'global'): # build term for global function gterm = stf.newNode("term") - func = stf.newSubNode(gterm, "function") + func = stf.newSubNode(gterm, Function.tag) stf.setText(func, self.name) if sig: # if there are parameters, use that entity @@ -335,6 +336,7 @@ class Function(SConsThing): inst = stf.newSubNode(mterm, "replaceable") stf.setText(inst, "env") stf.setTail(inst, ".") + # we could use here, but it's a "method" meth = stf.newSubNode(mterm, "methodname") stf.setText(meth, self.name) if sig: @@ -371,6 +373,12 @@ class Variable(SConsThing): description = 'construction variable' prefix = 'cv-' tag = 'envar' + + def xml_terms(self): + term = stf.newNode("term") + var = stf.newSubNode(term, Variable.tag) + stf.setText(var, self.name) + return [term] def entityfunc(self): return '$' + self.name diff --git a/doc/man/scons.xml b/doc/man/scons.xml index 6c46462..c52a4b8 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -2001,15 +2001,15 @@ These warnings are enabled by default. Warnings about attempts to set the reserved &consvar; names -CHANGED_SOURCES, -CHANGED_TARGETS, -TARGET, -TARGETS, -SOURCE, -SOURCES, -UNCHANGED_SOURCES +&cv-CHANGED_SOURCES;, +&cv-CHANGED_TARGETS;, +&cv-TARGET;, +&cv-TARGETS;, +&cv-SOURCE;, +&cv-SOURCES;, +&cv-UNCHANGED_SOURCES; or -UNCHANGED_TARGETS. +&cv-UNCHANGED_TARGETS;. These warnings are disabled by default. @@ -2120,11 +2120,11 @@ env = Environment(parse_flags='-Iinclude -DEBUG -lm') This example adds 'include' to -the CPPPATH &consvar; +the CPPPATH &consvar; 'EBUG' to -CPPDEFINES, +CPPDEFINES, and 'm' to -LIBS. +LIBS. &f-link-env-ParseFlags; describes how these arguments are distributed to &consvars;. @@ -2153,12 +2153,12 @@ and suffixes appropriate for that platform. Note that the win32 platform adds the -SystemDrive +SystemDrive and -SystemRoot +SystemRoot variables from the user's external environment to the &consenv;'s -ENV +ENV dictionary. This is so that any executed commands that use sockets to connect with other systems @@ -2540,7 +2540,7 @@ env.SharedLibrary('word', 'word.cpp', LIBSUFFIXES=['.ocx']) -Note that both the $SHLIBSUFFIX and $LIBSUFFIXES +Note that both the $SHLIBSUFFIX and $LIBSUFFIXES variables must be set if you want SCons to search automatically for dependencies on the non-standard library names; see the descriptions of these variables, below, for more information. @@ -2558,11 +2558,11 @@ env = Program('hello', 'hello.c', parse_flags='-Iinclude -DEBUG -lm') This example adds 'include' to -CPPPATH, +CPPPATH, 'EBUG' to -CPPDEFINES, +CPPDEFINES, and 'm' to -LIBS. +LIBS. Although the builder methods defined by &scons; @@ -5614,11 +5614,8 @@ and configured with the same &consenv; into single invocations of the Action object's command line or function. Command lines will typically want to use the -cHANGED_SOURCES -&consvar; -(and possibly -CHANGED_TARGETS -as well) +&cv-CHANGED_SOURCES; &consvar; +(and possibly &cv-CHANGED_TARGETS; as well) to only pass to the command line those sources that have actually changed since their targets were built. @@ -5948,7 +5945,7 @@ special variables for each command execution: - CHANGED_SOURCES + &cv-CHANGED_SOURCES; The file names of all sources of the build command that have changed since the target was last built. @@ -5956,7 +5953,7 @@ that have changed since the target was last built. - CHANGED_TARGETS + &cv-CHANGED_TARGETS; The file names of all targets that would be built from sources that have changed since the target was last built. @@ -5964,7 +5961,7 @@ from sources that have changed since the target was last built. - SOURCE + &cv-SOURCE; The file name of the source of the build command, or the file name of the first source @@ -5973,14 +5970,14 @@ if multiple sources are being built. - SOURCES + &cv-SOURCES; The file names of the sources of the build command. - TARGET + &cv-TARGET; The file name of the target being built, or the file name of the first target @@ -5989,14 +5986,14 @@ if multiple targets are being built. - TARGETS + &cv-TARGETS; The file names of all targets being built. - UNCHANGED_SOURCES + &cv-UNCHANGED_SOURCES; The file names of all sources of the build command that have @@ -6006,7 +6003,7 @@ changed since the target was last built. - UNCHANGED_TARGETS + &cv-UNCHANGED_TARGETS; The file names of all targets that would be built from sources that have @@ -6187,7 +6184,7 @@ ${SOURCE.rsrcdir} => /usr/repository/src to enclose arbitrary Python code to be evaluated. (In fact, this is how the above modifiers are substituted, they are simply attributes of the Python objects -that represent TARGET, SOURCES, etc.) +that represent &cv-TARGET;, &cv-SOURCES;, etc.) See the section "Python Code Substitution" below, for more thorough examples of how this can be used. @@ -6351,12 +6348,12 @@ built, not when the SConscript is being read. So if later in the SConscript, the final value will be used. Here's a more interesting example. Note that all of -COND, -FOO, +COND, +FOO, and -BAR are &consvars;, +BAR are &consvars;, and their values are substituted into the final command. -FOO is a list, so its elements are interpolated +FOO is a list, so its elements are interpolated separated by spaces. @@ -6933,7 +6930,7 @@ env.Program(target = 'bar', source = 'bar.c') You also can use other Pythonic techniques to add -to the BUILDERS &consvar;, such as: +to the BUILDERS &consvar;, such as: env = Environment() -- cgit v0.12 From 9b809a71fe4babb7766d31e1c19ef0a9545ef2b5 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Mon, 13 Apr 2020 12:16:52 -0600 Subject: docs: update Variables content [ci skip] * Apply current formatting styles for funcs/methods (that is, func/method name is marked up, instance name is marked up, params are marked up, each with the appropriate docbook tag. * Word around the obsolete reference to built-in cmp function, which no longer exists in Python 3. We should probably transtion the API towards taking a key function instead, since that conversion is already done internally. * Clarify the way AddVariables is described - it takes a list of tuples, but that "list" isn't a Python list object, but rather one or more tuples, varargs-style. Also describe the content of the tuples. * Tweak some other wordings on variable helpers and validators. * Rework userguide chapter examples to use keyword arguments for calls to Add and for the *Variable functions. * Add a User Guide example of a help message that is more than a simple one (reuses an EnumVariable example) to illustrate that the generated help text is more than the help=helpstring. * Word differently the back-reference to Options in the User Guide. Signed-off-by: Mats Wichmann --- .../examples/commandline_EnumVariable_3.xml | 16 +- .../examples/commandline_EnumVariable_4.xml | 13 + doc/man/scons.xml | 360 +++++++++++---------- doc/user/command-line.xml | 263 ++++++++------- 4 files changed, 343 insertions(+), 309 deletions(-) create mode 100644 doc/generated/examples/commandline_EnumVariable_4.xml diff --git a/doc/generated/examples/commandline_EnumVariable_3.xml b/doc/generated/examples/commandline_EnumVariable_3.xml index bb9a6d5..eb5d3c1 100644 --- a/doc/generated/examples/commandline_EnumVariable_3.xml +++ b/doc/generated/examples/commandline_EnumVariable_3.xml @@ -1,14 +1,8 @@ - -% scons -Q COLOR=Red foo.o +% scons -Q -h -scons: *** Invalid value for option COLOR: Red. Valid values are: ('red', 'green', 'blue') -File "/home/my/project/SConstruct", line 5, in <module> -% scons -Q COLOR=BLUE foo.o +COLOR: Set background color (red|green|blue) + default: red + actual: red -scons: *** Invalid value for option COLOR: BLUE. Valid values are: ('red', 'green', 'blue') -File "/home/my/project/SConstruct", line 5, in <module> -% scons -Q COLOR=nAvY foo.o - -scons: *** Invalid value for option COLOR: nAvY. Valid values are: ('red', 'green', 'blue') -File "/home/my/project/SConstruct", line 5, in <module> +Use scons -H for help about command-line options. diff --git a/doc/generated/examples/commandline_EnumVariable_4.xml b/doc/generated/examples/commandline_EnumVariable_4.xml new file mode 100644 index 0000000..7c37f72 --- /dev/null +++ b/doc/generated/examples/commandline_EnumVariable_4.xml @@ -0,0 +1,13 @@ +% scons -Q COLOR=Red foo.o + +scons: *** Invalid value for option COLOR: Red. Valid values are: ('red', 'green', 'blue') +File "/home/my/project/SConstruct", line 6, in <module> +% scons -Q COLOR=BLUE foo.o + +scons: *** Invalid value for option COLOR: BLUE. Valid values are: ('red', 'green', 'blue') +File "/home/my/project/SConstruct", line 6, in <module> +% scons -Q COLOR=nAvY foo.o + +scons: *** Invalid value for option COLOR: nAvY. Valid values are: ('red', 'green', 'blue') +File "/home/my/project/SConstruct", line 6, in <module> + diff --git a/doc/man/scons.xml b/doc/man/scons.xml index c52a4b8..b1eea06 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -3952,12 +3952,12 @@ env = conf.Finish() Command-Line Construction Variables Often when building software, -some variables must be specified at build time. +some variables need to be specified at build time. For example, libraries needed for the build may be in non-standard locations, or site-specific compiler options may need to be passed to the compiler. -&scons; -provides a &Variables; +&SCons; +provides a Variables object to support overriding &consvars; on the command line: @@ -3965,37 +3965,38 @@ on the command line: scons VARIABLE=foo -The variable values can also be specified in an SConscript file. -To obtain the object for manipulating values, +The variable values can also be specified in an SConscript file. + +To obtain the object for manipulating values, call the &Variables; function: - Variables([files[, args]]) + Variables([files, [args]]) -If files is a file or +If files is a file or list of files, those are executed as Python scripts, and the values of (global) Python variables set in -those files are added as &consvars; in the -default &consenv;. +those files are added as &consvars; in the &DefEnv;. If no files are specified, or the -files +files argument is -None, -then no files will be read. Example file content: +None, +then no files will be read. The following example file +contents could be used to set an alternative C compiler: CC = 'my_cc' -The optional argument -args -is a dictionary of -values that will override anything read from the specified files; +If +args +is specified, it is a dictionary of +values that will override anything read from +files. it is primarily intended to be passed the -ARGUMENTS -dictionary that holds variables +&ARGUMENTS; dictionary that holds variables specified on the command line. Example: @@ -4013,93 +4014,97 @@ vars = Variables(None, {FOO:'expansion', BAR:7}) - Add(key, [help, default, validator, converter]) + vars.Add(key, [help, default, validator, converter]) -This adds a customizable &consvar; to the Variables object. -key +Add a customizable &consvar; to the Variables object. +key is the name of the variable. -help +help is the help text for the variable. -default +default is the default value of the variable; if the default value is -None +None and there is no explicit value specified, -the &consvar; will -not +the &consvar; will not be added to the &consenv;. -validator -is called to validate the value of the variable, and should take three -arguments: key, value, and environment. +If set, validator +is called to validate the value of the variable. +A function supplied as a validator shall accept +arguments: key, +value, and env. The recommended way to handle an invalid value is to raise an exception (see example below). -converter +If set, converter is called to convert the value before putting it in the environment, and should take either a value, or the value and environment, as parameters. -The -converter -must return a value, +The converter function must return a value, which will be converted into a string before being validated by the -validator +validator (if any) -and then added to the environment. +and then added to the &consenv;. Examples: vars.Add('CC', help='The C compiler') -def validate_color(key, val, env): +def valid_color(key, val, env): if not val in ['red', 'blue', 'yellow']: raise Exception("Invalid color value '%s'" % val) + vars.Add('COLOR', validator=valid_color) - vars.AddVariables(list) + vars.AddVariables(args) -A wrapper script that adds +A convenience method that adds multiple customizable &consvars; -to a Variables object. -list -is a list of tuple or list objects +to a Variables object in one call; +equivalent to calling &Add; multiple times. +The args +are tuples (or lists) that contain the arguments -for an individual call to the -Add -method. +for an individual call to the &Add; method. +Since tuples are not Python mappings, +the arguments cannot use the keyword form, +but rather are positional arguments as documented +for &Add;: a required name, the rest optional +but must be in the specified in order if used. + + opt.AddVariables( - ('debug', '', 0), - ('CC', 'The C compiler'), - ('VALIDATE', 'An option for testing validation', - 'notset', validator, None), - ) + ("debug", "", 0), + ("CC", "The C compiler"), + ("VALIDATE", "An option for testing validation", "notset", validator, None), +) - vars.Update(env, [args]) + vars.Update(env, [args]) -This updates a &consenv; -env -with the customized &consvars;. -Any specified variables that are -not +Update a &consenv; +env +with the customized &consvars; . +Any specified variables that are not configured for the Variables object will be saved and may be -retrieved with the -UnknownVariables() +retrieved using the +&UnknownVariables; method, below. Normally this method is not called directly, -but is called indirectly by passing the Variables object to -the Environment() function: +but rather invoked indirectly by passing the Variables object to +the &f-link-Environment; function: env = Environment(variables=vars) @@ -4109,9 +4114,9 @@ env = Environment(variables=vars) - vars.UnknownVariables() + vars.UnknownVariables() -Returns a dictionary containing any +Return a dictionary containing any variables that were specified either in the files or the dictionary with which the Variables object was initialized, @@ -4128,10 +4133,10 @@ for key, value in vars.UnknownVariables(): - vars.Save(filename, env) + vars.Save(filename, env) -This saves the currently set variables into a script file named -filename +Save the currently set variables into a script file named +by filename that can be used on the next invocation to automatically load the current settings. This method combined with the Variables method can be used to support caching of variables between runs. @@ -4148,32 +4153,31 @@ vars.Save('variables.cache', env) - vars.GenerateHelpText(env, [sort]) + vars.GenerateHelpText(env, [sort]) -This generates help text documenting the customizable construction -variables suitable to passing in to the Help() function. -env +Generate help text documenting the customizable construction +variables, suitable for passing in to the &f-link-Help; function. +env is the &consenv; that will be used to get the actual values -of customizable variables. Calling with -an optional -sort -function -will cause the output to be sorted -by the specified argument. -The specific -sort -function -should take two arguments -and return --1, 0 or 1 -(like the standard Python -cmp -function). +of the customizable variables. If the (optional) +value of sort +is callable, it is used as a comparison function to +determine how to sort the added variables. +This function must accept two arguments, compare them, +and return a negative integer if the first is +less-than the second, zero for equality, or a positive integer +for greater-than. -Optionally a Boolean value of True for sort will cause a standard alphabetical sort to be performed +Optionally a Boolean value of True +for sort will cause a standard +alphabetical sort to be performed. Help(vars.GenerateHelpText(env)) + +def cmp(a, b): + return (a > b) - (a < b) + Help(vars.GenerateHelpText(env, sort=cmp)) @@ -4181,20 +4185,18 @@ Help(vars.GenerateHelpText(env, sort=cmp)) - FormatVariableHelpText(env, opt, help, default, actual) + vars.FormatVariableHelpText(env, opt, help, default, actual) -This method returns a formatted string +Return a formatted string containing the printable help text for one option. It is normally not called directly, -but is called by the -GenerateHelpText() +but is called by the &GenerateHelpText; method to create the returned help text. It may be overridden with your own function that takes the arguments specified above and returns a string of help text formatted to your liking. -Note that -GenerateHelpText() +Note that &GenerateHelpText; will not put any blank lines or extra characters in between the entries, so you must add those characters to the returned @@ -4203,7 +4205,7 @@ string if you want the entries separated. def my_format(env, opt, help, default, actual): fmt = "\n%s: default=%s actual=%s (%s)\n" - return fmt % (opt, default. actual, help) + return fmt % (opt, default, actual, help) vars.FormatVariableHelpText = my_format @@ -4215,47 +4217,48 @@ vars.FormatVariableHelpText = my_format &scons; provides a number of functions that make it easy to set up -various types of Variables: +various types of Variables. +Each of these return a tuple ready to be passed to +the &Add; or &AddVariables; method: - BoolVariable(key, help, default) + BoolVariable(key, help, default) Return a tuple of arguments to set up a Boolean option. The option will use the specified name -key, +key, have a default value of -default, -and display the specified -help -text. +default, +and help +will form the descriptive part of the help text. The option will interpret the values -y, -yes, -t, -true, -1, -on +y, +yes, +t, +true, +1, +on and -all +all as true, and the values -n, -no, -f, -false, -0, -off +n, +no, +f, +false, +0, +off and -none +none as false. - EnumVariable(key, help, default, allowed_values, [map, ignorecase]) + EnumVariable(key, help, default, allowed_values, [map, ignorecase]) Return a tuple of arguments to set up an option @@ -4263,49 +4266,48 @@ whose value may be one of a specified list of legal enumerated values. The option will use the specified name -key, +key, have a default value of -default, -and display the specified -help -text. +default, +and help +will form the descriptive part of the help text. The option will only support those values in the -allowed_values +allowed_values list. The optional -map +map argument is a dictionary that can be used to convert input values into specific legal values in the -allowed_values +allowed_values list. If the value of -ignore_case +ignore_case is 0 (the default), then the values are case-sensitive. If the value of -ignore_case +ignore_case is 1, then values will be matched -case-insensitive. +case-insensitively. If the value of -ignore_case +ignore_case is 2, then values will be matched -case-insensitive, +case-insensitively, and all input values will be converted to lower case. - ListVariable(key, help, default, names, [,map]) + ListVariable(key, help, default, names, [map]) Return a tuple of arguments to set up an option @@ -4313,36 +4315,38 @@ whose value may be one or more of a specified list of legal enumerated values. The option will use the specified name -key, +key, have a default value of -default, -and display the specified -help -text. -The option will only support the values -all, -none, +default, +and help +will form the descriptive part of the help text. +The option will only accept the values +all, +none, or the values in the -names +names list. More than one value may be specified, -with all values separated by commas. +separated by commas. The default may be a string of comma-separated default values, or a list of the default values. The optional -map +map argument is a dictionary that can be used to convert input values into specific legal values in the -names -list. +names +list. +(Note that the additional values accepted through +the use of a map are not +reflected in the generated help message). - PackageVariable(key, help, default) + PackageVariable(key, help, default) Return a tuple of arguments to set up an option @@ -4352,52 +4356,50 @@ enabled, disabled or given an explicit path name. The option will use the specified name -key, +key, have a default value of -default, -and display the specified -help -text. +default, +and help +will form the descriptive part of the help text. The option will support the values -yes, -true, -on, -enable +yes, +true, +on, +enable or -search, +search, in which case the specified -default +default will be used, or the option may be set to an arbitrary string (typically the path name to a package that is being enabled). The option will also support the values -no, -false, -off +no, +false, +off or -disable +disable to disable use of the specified option. - PathVariable(key, help, default, [validator]) + PathVariable(key, help, default, [validator]) Return a tuple of arguments to set up an option whose value is expected to be a path name. The option will use the specified name -key, +key, have a default value of -default, -and display the specified -help -text. +default, +and help +will form the descriptive part of the help text. An additional -validator +validator may be specified that will be called to verify that the specified path @@ -4407,38 +4409,40 @@ following ready-made validators: - PathVariable.PathExists + PathVariable.PathExists -Verify that the specified path exists (the default). +Verify that the specified path exists +(this the default behavior if no +validator is supplied). - PathVariable.PathIsFile + PathVariable.PathIsFile -Verify that the specified path is an existing file. +Verify that the specified path exists and is a regular file. - PathVariable.PathIsDir + PathVariable.PathIsDir -Verify that the specified path is an existing directory. +Verify that the specified path exists and is a directory. - PathVariable.PathIsDirCreate + PathVariable.PathIsDirCreate -Verify that the specified path is a directory -and will create the specified directory if the path does not exist. +Verify that the specified path exists and is a directory; +if it does not exist, create the directory. - PathVariable.PathAccept + PathVariable.PathAccept -Simply accept the specific path name argument without validation, +Accept the specific path name argument without validation, suitable for when you want your users to be able to specify a directory path that will be created as part of the build process, for example. @@ -4451,12 +4455,12 @@ You may supply your own validator function, which must accept three arguments -(key, +(key, the name of the variable to be set; -val, +val, the specified value being checked; and -env, +env, the &consenv;) and should raise an exception if the specified value is not acceptable. @@ -7220,7 +7224,7 @@ line or in the file custom.py. vars = Variables('custom.py') -vars.Add('CC', 'The C compiler.') +vars.Add('CC', help='The C compiler.') env = Environment(variables=vars) Help(vars.GenerateHelpText(env)) diff --git a/doc/user/command-line.xml b/doc/user/command-line.xml index d8f9fff..4033372 100644 --- a/doc/user/command-line.xml +++ b/doc/user/command-line.xml @@ -873,7 +873,7 @@ cppdefines = [] for key, value in ARGLIST: if key == 'define': cppdefines.append(value) -env = Environment(CPPDEFINES = cppdefines) +env = Environment(CPPDEFINES=cppdefines) env.Object('prog.c') @@ -943,8 +943,7 @@ prog.c a program for release, and that the value of this variable should be added to the command line - with the appropriate -D option - (or other command line option) + with the appropriate define to pass the value to the C compiler. Here's how you might do that by setting the appropriate value in a dictionary for the @@ -955,9 +954,8 @@ prog.c vars = Variables(None, ARGUMENTS) -vars.Add('RELEASE', 'Set to 1 to build for release', 0) -env = Environment(variables = vars, - CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) +vars.Add('RELEASE', default=0) +env = Environment(variables=vars, CPPDEFINES={'RELEASE_BUILD': '${RELEASE}'}) env.Program(['foo.c', 'bar.c']) @@ -975,11 +973,8 @@ bar.c (the vars = Variables(None, ARGUMENTS) call). It then uses the object's &Add; method to indicate that the &RELEASE; - variable can be set on the command line, - and that its default value will be 0 - (the third argument to the &Add; method). - The second argument is a line of help text; - we'll learn how to use it in the next section. + variable can be set on the command line, and that + if not set the default value will be 0. @@ -1003,18 +998,19 @@ bar.c - NOTE: Before &SCons; release 0.98.1, these build variables - were known as "command-line build options." - The class was actually named the &Options; class, - and in the sections below, - the various functions were named + Historical note: In old &SCons; (prior to 1.0), + these build variables were known as "command-line build options." + The class was named the &Options; class, + and the predefined functions to construct options were named &BoolOption;, &EnumOption;, &ListOption;, - &PathOption;, &PackageOption; and &AddOptions;. - These older names still work, - and you may encounter them in older - &SConscript; files, - but they have been officially deprecated - as of &SCons; version 2.0. + &PathOption;, &PackageOption; and &AddOptions; (contrast + with the current names in "Pre-Defined Build Variable Functions" + below. You may encounter these names in older + &SConscript; files, wiki pages, blog entries, StackExchange + articles, etc. + These old names no longer work, but a mental substitution + of Variable" for Option + will let the concepts transfer to current usage models. @@ -1032,12 +1028,17 @@ bar.c when the user runs scons -h. You could write this text by hand, but &SCons; provides an easier way. - &Variables; objects support a + Variables objects support a &GenerateHelpText; method that will, as its name suggests, generate text that describes the various variables that - have been added to it. + have been added to it. The default text includes + the help string itself plus other information + such as allowed values. + (The generated text can also be customized by + replacing the FormatVariableHelpText + method). You then pass the output from this method to the &Help; function: @@ -1046,8 +1047,8 @@ bar.c vars = Variables(None, ARGUMENTS) -vars.Add('RELEASE', 'Set to 1 to build for release', 0) -env = Environment(variables = vars) +vars.Add('RELEASE', help='Set to 1 to build for release', default=0) +env = Environment(variables=vars) Help(vars.GenerateHelpText(env)) @@ -1093,9 +1094,8 @@ Help(vars.GenerateHelpText(env)) vars = Variables('custom.py') -vars.Add('RELEASE', 'Set to 1 to build for release', 0) -env = Environment(variables = vars, - CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) +vars.Add('RELEASE', help='Set to 1 to build for release', default=0) +env = Environment(variables=vars, CPPDEFINES={'RELEASE_BUILD': '${RELEASE}'}) env.Program(['foo.c', 'bar.c']) Help(vars.GenerateHelpText(env)) @@ -1139,12 +1139,11 @@ RELEASE = 1 - vars = Variables('custom.py') - vars.Add('RELEASE', 'Set to 1 to build for release', 0) - env = Environment(variables = vars, - CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) - env.Program(['foo.c', 'bar.c']) - Help(vars.GenerateHelpText(env)) +vars = Variables('custom.py') +vars.Add('RELEASE', help='Set to 1 to build for release', default=0) +env = Environment(variables=vars, CPPDEFINES={'RELEASE_BUILD': '${RELEASE}'}) +env.Program(['foo.c', 'bar.c']) +Help(vars.GenerateHelpText(env)) foo.c @@ -1195,6 +1194,8 @@ vars = Variables('custom.py', ARGUMENTS) &SCons; provides a number of functions that provide ready-made behaviors for various types of command-line build variables. + These functions all return a tuple which is ready + to be passed to an &Add; call. @@ -1230,9 +1231,10 @@ vars = Variables('custom.py', ARGUMENTS) vars = Variables('custom.py') -vars.Add(BoolVariable('RELEASE', 'Set to build for release', 0)) -env = Environment(variables = vars, - CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) +vars.Add(BoolVariable('RELEASE', + help='Set to build for release', + default=0)) +env = Environment(variables=vars, CPPDEFINES={'RELEASE_BUILD': '${RELEASE}'}) env.Program('foo.c') @@ -1334,11 +1336,13 @@ foo.c vars = Variables('custom.py') -vars.Add(EnumVariable('COLOR', 'Set background color', 'red', - allowed_values=('red', 'green', 'blue'))) -env = Environment(variables = vars, - CPPDEFINES={'COLOR' : '"${COLOR}"'}) +vars.Add(EnumVariable('COLOR', + help='Set background color', + default='red', + allowed_values=('red', 'green', 'blue'))) +env = Environment(variables=vars, CPPDEFINES={'COLOR': '"${COLOR}"'}) env.Program('foo.c') +Help(vars.GenerateHelpText(env)) foo.c @@ -1373,6 +1377,20 @@ foo.c + This example can also serve to further illustrate help + generation: the help message here picks up not only the + help text, but augments it with + information gathered from allowed_values + and default: + + + + + scons -Q -h + + + + The &EnumVariable; function also supports a way to map alternate names to allowed values. Suppose, for example, @@ -1388,11 +1406,12 @@ foo.c vars = Variables('custom.py') -vars.Add(EnumVariable('COLOR', 'Set background color', 'red', - allowed_values=('red', 'green', 'blue'), - map={'navy':'blue'})) -env = Environment(variables = vars, - CPPDEFINES={'COLOR' : '"${COLOR}"'}) +vars.Add(EnumVariable('COLOR', + help='Set background color', + default='red', + allowed_values=('red', 'green', 'blue'), + map={'navy':'blue'})) +env = Environment(variables=vars, CPPDEFINES={'COLOR': '"${COLOR}"'}) env.Program('foo.c') @@ -1424,7 +1443,7 @@ foo.c - + scons -Q COLOR=Red foo.o scons -Q COLOR=BLUE foo.o scons -Q COLOR=nAvY foo.o @@ -1443,12 +1462,13 @@ foo.c vars = Variables('custom.py') -vars.Add(EnumVariable('COLOR', 'Set background color', 'red', - allowed_values=('red', 'green', 'blue'), - map={'navy':'blue'}, - ignorecase=1)) -env = Environment(variables = vars, - CPPDEFINES={'COLOR' : '"${COLOR}"'}) +vars.Add(EnumVariable('COLOR', + help='Set background color', + default='red', + allowed_values=('red', 'green', 'blue'), + map={'navy':'blue'}, + ignorecase=1)) +env = Environment(variables=vars, CPPDEFINES={'COLOR':'"${COLOR}"'}) env.Program('foo.c') @@ -1483,12 +1503,13 @@ foo.c vars = Variables('custom.py') -vars.Add(EnumVariable('COLOR', 'Set background color', 'red', - allowed_values=('red', 'green', 'blue'), - map={'navy':'blue'}, - ignorecase=2)) -env = Environment(variables = vars, - CPPDEFINES={'COLOR' : '"${COLOR}"'}) +vars.Add(EnumVariable('COLOR', + help='Set background color', + default='red', + allowed_values=('red', 'green', 'blue'), + map={'navy':'blue'}, + ignorecase=2)) +env = Environment(variables=vars, CPPDEFINES={'COLOR': '"${COLOR}"'}) env.Program('foo.c') @@ -1532,10 +1553,11 @@ foo.c vars = Variables('custom.py') -vars.Add(ListVariable('COLORS', 'List of colors', 0, - ['red', 'green', 'blue'])) -env = Environment(variables = vars, - CPPDEFINES={'COLORS' : '"${COLORS}"'}) +vars.Add(ListVariable('COLORS', + help='List of colors', + default=0, + names=['red', 'green', 'blue'])) +env = Environment(variables=vars, CPPDEFINES={'COLORS': '"${COLORS}"'}) env.Program('foo.c') @@ -1604,10 +1626,9 @@ foo.c vars = Variables('custom.py') vars.Add(PathVariable('CONFIG', - 'Path to configuration file', - '__ROOT__/etc/my_config')) -env = Environment(variables = vars, - CPPDEFINES={'CONFIG_FILE' : '"$CONFIG"'}) + help='Path to configuration file', + default='__ROOT__/etc/my_config')) +env = Environment(variables=vars, CPPDEFINES={'CONFIG_FILE': '"$CONFIG"'}) env.Program('foo.c') @@ -1652,7 +1673,7 @@ foo.c that you can use to change this behavior. If you want to ensure that any specified paths are, in fact, files and not directories, - use the &PathVariable_PathIsFile; method: + use the &PathVariable_PathIsFile; method as the validation function: @@ -1660,11 +1681,10 @@ foo.c vars = Variables('custom.py') vars.Add(PathVariable('CONFIG', - 'Path to configuration file', - '__ROOT__/etc/my_config', - PathVariable.PathIsFile)) -env = Environment(variables = vars, - CPPDEFINES={'CONFIG_FILE' : '"$CONFIG"'}) + help='Path to configuration file', + default='__ROOT__/etc/my_config', + validator=PathVariable.PathIsFile)) +env = Environment(variables=vars, CPPDEFINES={'CONFIG_FILE': '"$CONFIG"'}) env.Program('foo.c') @@ -1679,7 +1699,7 @@ foo.c Conversely, to ensure that any specified paths are directories and not files, - use the &PathVariable_PathIsDir; method: + use the &PathVariable_PathIsDir; method as the validation function: @@ -1687,11 +1707,10 @@ foo.c vars = Variables('custom.py') vars.Add(PathVariable('DBDIR', - 'Path to database directory', - '__ROOT__/var/my_dbdir', - PathVariable.PathIsDir)) -env = Environment(variables = vars, - CPPDEFINES={'DBDIR' : '"$DBDIR"'}) + help='Path to database directory', + default='__ROOT__/var/my_dbdir', + validator=PathVariable.PathIsDir)) +env = Environment(variables=vars, CPPDEFINES={'DBDIR': '"$DBDIR"'}) env.Program('foo.c') @@ -1708,7 +1727,7 @@ foo.c are directories, and you would like the directory created if it doesn't already exist, - use the &PathVariable_PathIsDirCreate; method: + use the &PathVariable_PathIsDirCreate; method as the validation function: @@ -1716,11 +1735,10 @@ foo.c vars = Variables('custom.py') vars.Add(PathVariable('DBDIR', - 'Path to database directory', - '__ROOT__/var/my_dbdir', - PathVariable.PathIsDirCreate)) -env = Environment(variables = vars, - CPPDEFINES={'DBDIR' : '"$DBDIR"'}) + help='Path to database directory', + default='__ROOT__/var/my_dbdir', + validator=PathVariable.PathIsDirCreate)) +env = Environment(variables=vars, CPPDEFINES={'DBDIR': '"$DBDIR"'}) env.Program('foo.c') @@ -1744,11 +1762,10 @@ foo.c vars = Variables('custom.py') vars.Add(PathVariable('OUTPUT', - 'Path to output file or directory', - None, - PathVariable.PathAccept)) -env = Environment(variables = vars, - CPPDEFINES={'OUTPUT' : '"$OUTPUT"'}) + help='Path to output file or directory', + default=None, + validator=PathVariable.PathAccept)) +env = Environment(variables=vars, CPPDEFINES={'OUTPUT': '"$OUTPUT"'}) env.Program('foo.c') @@ -1777,13 +1794,12 @@ foo.c -vars = Variables('custom.py') -vars.Add(PackageVariable('PACKAGE', - 'Location package', - '__ROOT__/opt/location')) -env = Environment(variables = vars, - CPPDEFINES={'PACKAGE' : '"$PACKAGE"'}) -env.Program('foo.c') +vars = Variables("custom.py") +vars.Add(PackageVariable("PACKAGE", + help="Location package", + default="__ROOT__/opt/location")) +env = Environment(variables=vars, CPPDEFINES={"PACKAGE": '"$PACKAGE"'}) +env.Program("foo.c") foo.c @@ -1798,8 +1814,8 @@ foo.c - When the &SConscript; file uses the &PackageVariable; funciton, - user can now still use the default + When the &SConscript; file uses the &PackageVariable; function, + the user can still use the default or supply an overriding path name, but can now explicitly set the specified variable to a value @@ -1828,16 +1844,17 @@ foo.c Lastly, &SCons; provides a way to add multiple build variables to a &Variables; object at once. Instead of having to call the &Add; method - multiple times, - you can call the &AddVariables; - method with a list of build variables - to be added to the object. + multiple times, you can call the &AddVariables; + method with the build variables to be added to the object. Each build variable is specified as either a tuple of arguments, - just like you'd pass to the &Add; method itself, or as a call to one of the pre-defined - functions for pre-packaged command-line build variables. - in any order: + functions for pre-packaged command-line build variables, + which returns such a tuple. Note that an individual tuple + cannot take keyword arguments in the way that a call to + &Add; or one of the build variable functions can. + The order of variables given to &AddVariables; does not + matter. @@ -1847,18 +1864,25 @@ vars = Variables() vars.AddVariables( ('RELEASE', 'Set to 1 to build for release', 0), ('CONFIG', 'Configuration file', '/etc/my_config'), - BoolVariable('warnings', 'compilation with -Wall and similiar', 1), - EnumVariable('debug', 'debug output and symbols', 'no', - allowed_values=('yes', 'no', 'full'), - map={}, ignorecase=0), # case sensitive + BoolVariable('warnings', + help='compilation with -Wall and similiar', + default=1), + EnumVariable('debug', + help='debug output and symbols', + default='no', + allowed_values=('yes', 'no', 'full'), + map={}, + ignorecase=0), ListVariable('shared', - 'libraries to build as shared libraries', - 'all', - names = list_of_libs), + help='libraries to build as shared libraries', + default='all', + names = list_of_libs), PackageVariable('x11', - 'use X11 installed here (yes = search some places)', - 'yes'), - PathVariable('qtdir', 'where the root of Qt is installed', qtdir), + help='use X11 installed here (yes = search some places)', + default='yes'), + PathVariable('qtdir', + help='where the root of Qt is installed', + default=qtdir), ) @@ -1905,9 +1929,8 @@ vars.AddVariables( vars = Variables(None) -vars.Add('RELEASE', 'Set to 1 to build for release', 0) -env = Environment(variables = vars, - CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) +vars.Add('RELEASE', help='Set to 1 to build for release', default=0) +env = Environment(variables=vars, CPPDEFINES={'RELEASE_BUILD': '${RELEASE}'}) unknown = vars.UnknownVariables() if unknown: print("Unknown variables: %s"%unknown.keys()) -- cgit v0.12 From dd0eb0294ac23ca70ab7b083ff25762ce4ee6ab3 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Tue, 14 Apr 2020 13:43:24 -0600 Subject: Docs: update the Configure Context sections [ci skip] Apply new formatting styles. Tweak a lot of wordings. Make sure manpage consistently describes return types. Signed-off-by: Mats Wichmann --- doc/man/scons.xml | 565 +++++++++++++++++++++++++++-------------------------- doc/user/sconf.xml | 95 +++++---- 2 files changed, 343 insertions(+), 317 deletions(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index c52a4b8..f7eed2d 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -3209,8 +3209,7 @@ env = Environment(CC="cc") or when copying a &consenv; using the -Clone -method: +&f-link-Clone; method: env2 = env.Clone(CC="cl.exe") @@ -3221,67 +3220,75 @@ env2 = env.Clone(CC="cl.exe") Configure Contexts -&scons; +&SCons; supports a -configure context, +&configure_context;, an integrated mechanism similar to the various AC_CHECK macros in GNU &Autoconf; -for testing for the existence of C header -files, libraries, etc. -In contrast to &Autoconf;, +for testing the existence of external items needed +for the build, such as C header files, libraries, etc. +The mechanism is portable across platforms. + + + &scons; -does not maintain an explicit cache of the tested values, +does not maintain an explicit cache of the tested values +(this is different than &Autoconf;), but uses its normal dependency tracking to keep the checked values up to date. However, users may override this behaviour with the command line option. -To create a configure context: - - Configure(env, [custom_tests, conf_dir, log_file, config_h, clean, help]) - env.Configure([custom_tests, conf_dir, log_file, config_h, clean, help]) + Configure(env, [custom_tests, conf_dir, log_file, config_h, clean, help]) + env.Configure([custom_tests, conf_dir, log_file, config_h, clean, help]) -Create a configure context, which tracks information -discovered while running tests. The context includes a -&consenv;, which is used when running the tests and -which is updated with the check results. -When the context is complete, the (possibly modified) -environment is returned). Only one context may be active +Create a &configure_context;, which tracks information +discovered while running tests. The context includes a local &consenv; +(available as context.env) +which is used when running the tests and +which can be updated with the check results. +Only one context may be active at a time (since 4.0, &scons; will raise an exception -if this rule is not followed), but a new context can be created -after the active one is completed. - -The required env argument -specifies the environment for building the tests. -custom_tests -is a dictionary containing custom tests +on an attempt to create a new context when there is +an active context), but a new context can be created +after the active one is completed. +For the global function form, the required env +describes the initial values for the context's local &consenv;; +for the &consenv; method form the instance provides the values. + +custom_tests +specifies a dictionary containing custom tests (see the section on custom tests below). -By default, no custom tests are added to the configure context. -conf_dir +The default value is None, +meaning no custom tests are added to the &configure_context;. + +conf_dir specifies a directory where the test cases are built. -Note that this directory is not used for building -normal targets. -The default value is the directory -#/.sconf_temp. -log_file +This directory is not used for building normal targets. +The default value is +#/.sconf_temp. + +log_file specifies a file which collects the output from commands that are executed to check for the existence of header files, libraries, etc. -The default is the file #/config.log. +The default is #/config.log. If you are using the &VariantDir; function, -you may want to specify a subdirectory under your variant directory. -config_h +you may want to specify a subdirectory under your variant directory. + +config_h specifies a C header file where the results of tests -will be written, e.g. +will be written. The results will consist of lines like #define HAVE_STDIO_H, #define HAVE_LIBM, etc. +Customarily, the name chosen is config.h. The default is to not write a -config.h +config_h file. You can specify the same -config.h +config_h file in multiple calls to &Configure;, in which case &SCons; will concatenate all results in the specified file. @@ -3289,19 +3296,17 @@ Note that &SCons; uses its normal dependency checking to decide if it's necessary to rebuild the specified -config_h +config_h file. This means that the file is not necessarily re-built each time scons is run, but is only rebuilt if its contents will have changed and some target that depends on the -config_h +config_h file is being built. - -The optional -clean +The clean and -help +help arguments can be used to suppress execution of the configuration tests when the / @@ -3309,15 +3314,15 @@ or // options are used, respectively. The default behavior is always to execute -configure context tests, +&configure_context; tests, since the results of the tests may affect the list of targets to be cleaned or the help text. If the configure tests do not affect these, then you may add the -clean=False + or -help=False + arguments (or both) to avoid unnecessary test execution. @@ -3325,19 +3330,19 @@ to avoid unnecessary test execution. - SConf.Finish(context) - context.Finish() + SConf.Finish(context) + context.Finish() This method must be called after configuration is done. Though required, this is not enforced except -if &Configure; is called when there still an active context, +if &Configure; is called again while there is still an active context, in which case an exception is raised. &Finish; returns the environment as modified during the course of running the configuration checks. After this method is called, no further checks can be performed with this configuration context. However, you can create a new -configure context to perform additional checks. +&configure_context; to perform additional checks. @@ -3357,19 +3362,27 @@ if conf.CheckLibWithHeader("qt", "qapp.h", "c++", "QApplication qapp(0,0);"): env = conf.Finish() -A configure context +A &configure_context; has the following predefined methods which -can be used to perform checks: +can be used to perform checks. Where +language is a required or +optional parameter, the choice can currently +be C or C++. The spellings accepted for +C are C or c; +for C++ the value can be +CXX, cxx, C++ +or c++. + - SConf.CheckHeader(context, header, [include_quotes, language]) - context.CheckHeader(header, [include_quotes, language]) + SConf.CheckHeader(context, header, [include_quotes, language]) + context.CheckHeader(header, [include_quotes, language]) Checks if -header +header is usable in the specified language. -header +header may be a list, in which case the last item in the list is the header file to be checked, @@ -3379,32 +3392,32 @@ header files whose lines should precede the header line being checked for. The optional argument -include_quotes +include_quotes must be a two character string, where the first character denotes the opening quote and the second character denotes the closing quote. -By default, both characters are " (double quote). +By default, both characters are " (double quote). The optional argument -language +language should be either C or C++ and selects the compiler to be used for the check. -Returns 1 on success and 0 on failure. +Returns a boolean indicating success or failure. - SConf.CheckCHeader(context, header, [include_quotes]) - context.CheckCHeader(header, [include_quotes]) + SConf.CheckCHeader(context, header, [include_quotes]) + context.CheckCHeader(header, [include_quotes]) This is a wrapper around -SConf.CheckHeader +SConf.CheckHeader which checks if -header +header is usable in the C language. -header +header may be a list, in which case the last item in the list is the header file to be checked, @@ -3414,25 +3427,25 @@ header files whose lines should precede the header line being checked for. The optional argument -include_quotes +include_quotes must be a two character string, where the first character denotes the opening -quote and the second character denotes the closing quote (both default -to \N'34'). -Returns 1 on success and 0 on failure. +quote and the second character denotes the closing quote. +By default, both characters are " (double quote). +Returns a boolean indicating success or failure. - SConf.CheckCXXHeader(context, header, [include_quotes]) - context.CheckCXXHeader(header, [include_quotes]) + SConf.CheckCXXHeader(context, header, [include_quotes]) + context.CheckCXXHeader(header, [include_quotes]) This is a wrapper around -SConf.CheckHeader +SConf.CheckHeader which checks if -header +header is usable in the C++ language. -header +header may be a list, in which case the last item in the list is the header file to be checked, @@ -3442,25 +3455,32 @@ header files whose lines should precede the header line being checked for. The optional argument -include_quotes +include_quotes must be a two character string, where the first character denotes the opening -quote and the second character denotes the closing quote (both default -to \N'34'). -Returns 1 on success and 0 on failure. +quote and the second character denotes the closing quote. +By default, both characters are " (double quote). +Returns a boolean indicating success or failure. - SConf.CheckFunc(context,, function_name, [header, language]) - context.CheckFunc(function_name, [header, language]) + SConf.CheckFunc(context, function_name, [header, language]) + context.CheckFunc(function_name, [header, language]) Checks if the specified -C or C++ function is available. -function_name +C or C++ library function is available based on the +context's local environment settings (that is, using +the values of CFLAGS, +CPPFLAGS, LIBS +or other relevant &consvars;). + + + +function_name is the name of the function to check for. The optional -header +header argument is a string that will be placed at the top @@ -3476,77 +3496,65 @@ extern "C" char function_name(); -The optional -language -argument should be -C -or -C++ -and selects the compiler to be used for the check; -the default is "C". + +Returns an empty string on success, a string containing +an error message on failure. + - SConf.CheckLib(context, [library, symbol, header, language, autoadd=1]) - context.CheckLib([library, symbol, header, language, autoadd=1]) + SConf.CheckLib(context, [library, symbol, header, language, autoadd=True]) + context.CheckLib([library, symbol, header, language, autoadd=True]) Checks if -library +library provides -symbol. -If the value of -autoadd -is 1 and the library provides the specified -symbol, -appends the library to the LIBS &consvar; -library -may also be None (the default), +symbol. +If +autoadd +is true (the default) and the library provides the specified +symbol, +appends the library to the LIBS &consvar; +library +may also be None (the default), in which case -symbol -is checked with the current LIBS variable, +symbol +is checked with the current LIBS variable, or a list of library names, in which case each library in the list will be checked for -symbol. +symbol. If -symbol +symbol is not set or is -None, +None, then -SConf.CheckLib() +SConf.CheckLib just checks if you can link against the specified -library. -The optional -language -argument should be -C -or -C++ -and selects the compiler to be used for the check; -the default is "C". -The default value for -autoadd -is 1. -This method returns 1 on success and 0 on error. +library. +Note though it is legal syntax, it would +not be very useful to call this method +with library +and symbol both +omitted or None. +Returns a boolean indicating success or failure. - SConf.CheckLibWithHeader(context, library, header, language, [call, autoadd]) - context.CheckLibWithHeader(library, header, language, [call, autoadd]) + SConf.CheckLibWithHeader(context, library, header, language, [call, autoadd=True]) + context.CheckLibWithHeader(library, header, language, [call, autoadd=True]) -In contrast to the -SConf.CheckLib -call, this call provides a more sophisticated way to check against libraries. -Again, -library +Provides a more sophisticated way to check against libraries then the +SConf.CheckLib call. +library specifies the library or a list of libraries to check. -header +header specifies a header to check for. -header +header may be a list, in which case the last item in the list is the header file to be checked, @@ -3555,91 +3563,95 @@ header files whose #include lines should precede the header line being checked for. -language -may be one of 'C','c','CXX','cxx','C++' and 'c++'. -call +call can be any valid expression (with a trailing ';'). If -call +call is not set, the default simply checks that you can link against the specified -library. -autoadd -specifies whether to add the library to the environment (only if the check -succeeds). This method returns 1 on success and 0 on error. +library. +autoadd (default true) +specifies whether to add the library to the environment if the check +succeeds. +Returns a boolean indicating success or failure. - SConf.CheckType(context, type_name, [includes, language]) - context.CheckType(type_name, [includes, language]) + SConf.CheckType(context, type_name, [includes, language]) + context.CheckType(type_name, [includes, language]) Checks for the existence of a type defined by -typedef. -type_name +typedef. +type_name specifies the typedef name to check for. -includes +includes is a string containing one or more #include lines that will be inserted into the program that will be run to test for the existence of the type. -The optional -language -argument should be -C -or -C++ -and selects the compiler to be used for the check; -the default is "C". Example: sconf.CheckType('foo_type', '#include "my_types.h"', 'C++') + +Returns an empty string on success, a string containing +an error message on failure. + + - SConf.CheckCC(self) - context.CheckCC(self) + SConf.CheckCC(context) + context.CheckCC() -Checks whether the C compiler (as defined by the CC &consvar;) works -by trying to compile a small source file. +Checks whether the C compiler (as defined by the +CC &consvar;) works +by trying to compile a small source file. +Returns a boolean indicating success or failure. By default, SCons only detects if there is a program with the correct name, not if it is a functioning compiler. -This uses the exact same command than the one used by the object builder for C -source file, so it can be used to detect if a particular compiler flag works or +This uses the exact same command as the one used by the object builder for C +source files, so it can be used to detect if a particular compiler flag works or not. - SConf.CheckCXX(self) - context.CheckCXX(self) + SConf.CheckCXX(context) + context.CheckCXX() -Checks whether the C++ compiler (as defined by the CXX &consvar;) -works by trying to compile a small source file. By default, SCons only detects -if there is a program with the correct name, not if it is a functioning compiler. +Checks whether the C++ compiler (as defined by the +CXX &consvar;) +works by trying to compile a small source file. By default, +SCons only detects if there is a program with the correct name, +not if it is a functioning compiler. +Returns a boolean indicating success or failure. -This uses the exact same command than the one used by the object builder for -CXX source files, so it can be used to detect if a particular compiler flag +This uses the exact same command as the one used by the object builder for +C++ source files, so it can be used to detect if a particular compiler flag works or not. - SConf.CheckSHCC(self) - context.CheckSHCC(self) + SConf.CheckSHCC(context) + context.CheckSHCC() -Checks whether the C compiler (as defined by the SHCC &consvar;) works -by trying to compile a small source file. By default, SCons only detects if -there is a program with the correct name, not if it is a functioning compiler. +Checks whether the shared-object C compiler (as defined by the +SHCC &consvar;) works +by trying to compile a small source file. By default, +SCons only detects if there is a program with the correct name, +not if it is a functioning compiler. +Returns a boolean indicating success or failure. -This uses the exact same command than the one used by the object builder for C +This uses the exact same command as the one used by the object builder for C source file, so it can be used to detect if a particular compiler flag works or not. This does not check whether the object code can be used to build a shared library, only that the compilation (not link) succeeds. @@ -3647,97 +3659,90 @@ library, only that the compilation (not link) succeeds. - SConf.CheckSHCXX(self) - context.CheckSHCXX(self) + SConf.CheckSHCXX(context) + context.CheckSHCXX() -Checks whether the C++ compiler (as defined by the SHCXX &consvar;) -works by trying to compile a small source file. By default, SCons only detects -if there is a program with the correct name, not if it is a functioning compiler. +Checks whether the shared-object C++ compiler (as defined by the +SHCXX &consvar;) +works by trying to compile a small source file. By default, +SCons only detects if there is a program with the correct name, +not if it is a functioning compiler. +Returns a boolean indicating success or failure. -This uses the exact same command than the one used by the object builder for -CXX source files, so it can be used to detect if a particular compiler flag +This uses the exact same command as the one used by the object builder for +C++ source files, so it can be used to detect if a particular compiler flag works or not. This does not check whether the object code can be used to build a shared library, only that the compilation (not link) succeeds. - SConf.CheckTypeSize(context, type_name, [header, language, expect]) - context.CheckTypeSize(type_name, [header, language, expect]) + SConf.CheckTypeSize(context, type_name, [header, language, expect]) + context.CheckTypeSize(type_name, [header, language, expect]) Checks for the size of a type defined by -typedef. -type_name +typedef. +type_name specifies the typedef name to check for. The optional -header +header argument is a string that will be placed at the top of the test file that will be compiled -to check if the function exists; +to check if the type exists; the default is empty. -The optional -language -argument should be -C -or -C++ -and selects the compiler to be used for the check; -the default is "C". -The optional -expect -argument should be an integer. -If this argument is used, -the function will only check whether the type -given in type_name has the expected size (in bytes). +If the optional +expect, +is supplied, it should be an integer size; +&CheckTypeSize; will fail unless +type_name is actually +that size. +Returns the size in bytes, or zero if the type was not found +(or if the size did not match expect). + + For example, CheckTypeSize('short', expect=2) -will return success only if short is two bytes. +will return the size 2 only if short is +actually two bytes. - SConf.CheckDeclaration(context, symbol, [includes, language]) - context.CheckDeclaration(symbol, [includes, language]) + SConf.CheckDeclaration(context, symbol, [includes, language]) + context.CheckDeclaration(symbol, [includes, language]) Checks if the specified -symbol +symbol is declared. -includes +includes is a string containing one or more -#include +#include lines that will be inserted into the program -that will be run to test for the existence of the type. -The optional -language -argument should be -C -or -C++ -and selects the compiler to be used for the check; -the default is "C". +that will be run to test for the existence of the symbol. +Returns a boolean indicating success or failure. - SConf.Define(context, symbol, [value, comment]) - context.Define(symbol, [value, comment]) + SConf.Define(context, symbol, [value, comment]) + context.Define(symbol, [value, comment]) This function does not check for anything, but defines a preprocessor symbol that will be added to the configuration header file. -It is the equivalent of AC_DEFINE, +It is the equivalent of AC_DEFINE, and defines the symbol -name +name with the optional -value +value and the optional comment -comment. +comment. Define Examples: @@ -3787,112 +3792,119 @@ conf.Define("A_SYMBOL", 1, "Set to 1 if you have a symbol") -You can define your own custom checks. +You can define your own custom checks in addition to the predefined checks. -These are passed in a dictionary to the Configure function. +You pass a dictionary of these +to the &Configure; function +as the custom_tests argument. This dictionary maps the names of the checks -to user defined Python callables -(either Python functions or class instances implementing the -__call__ +to the user defined Python callables +(either Python functions or class instances implementing a +__call__ method). -The first argument of the call is always a -CheckContext +Each custom check will be called with a first +argument of a CheckContext, instance followed by the arguments, which must be supplied by the user of the check. -These CheckContext instances define the following methods: +A CheckContext instance defines the following methods: - CheckContext.Message(self, text) + context.Message(text) -Usually called before the check is started. -text -will be displayed to the user, e.g. 'Checking for library X...' +Displays a message, as an indicator of progess. +text +will be displayed, e.g. +Checking for library X.... +Usually called before the check is started. + - CheckContext.Result(self, res) + context.Result(res) -Usually called after the check is done. -res -can be either an integer or a string. In the former case, 'yes' (res != 0) -or 'no' (res == 0) is displayed to the user, in the latter case the -given string is displayed. +Displays a result message, as an indicator of progress. + +res +can be either an integer or a string. If an integer, displays +yes +(if res evaluates True) +or no +(if res evaluates False). +If a string, it is displayed as-is. +Usually called after the check has completed. - CheckContext.TryCompile(self, text, extension) + context.TryCompile(text, extension='') Checks if a file with the specified -extension +extension (e.g. '.c') containing -text +text can be compiled using the environment's -Object -builder. Returns 1 on success and 0 on failure. +&Object; builder. +Returns a boolean indicating success or failure. - CheckContext.TryLink(self, text, extension) + context.TryLink(text, extension='') Checks, if a file with the specified -extension +extension (e.g. '.c') containing -text -can be compiled using the environment's -Program -builder. Returns 1 on success and 0 on failure. +text +can be compiled using the environment's &Program; builder. +Returns a boolean indicating success or failure. - CheckContext.TryRun(self, text, extension) + context.TryRun(text, extension='') -Checks, if a file with the specified -extension +Checks if a file with the specified +extension (e.g. '.c') containing -text +text can be compiled using the environment's -Program -builder. On success, the program is run. If the program +&Program; builder. On success, the program is run. If the program executes successfully (that is, its return status is 0), a tuple (1, outputStr) is returned, where -outputStr +outputStr is the standard output of the program. If the program fails execution (its return status is non-zero), -then (0, '') is returned. +then (0, '') is returned. - CheckContext.TryAction(self, action, [text, extension]) + context.TryAction(action, [text, extension='']) Checks if the specified -action +action with an optional source file (contents -text -, extension -extension -= '' -) can be executed. -action +text, +extension +extension) +can be executed. +action may be anything which can be converted to a &scons; Action. On success, (1, outputStr) is returned, where -outputStr +outputStr is the content of the target file. On failure (0, '') @@ -3901,23 +3913,24 @@ is returned. - CheckContext.TryBuild(self, builder, [text, extension]) + context.TryBuild(builder[, text, extension='']) Low level implementation for testing specific builds; the methods above are based on this method. Given the Builder instance -builder +builder and the optional -text +text of a source file with optional -extension, -this method returns 1 on success and 0 on failure. In addition, -self.lastTarget -is set to the build target node, if the build was successful. +extension, +returns a boolean indicating success or failure. +In addition, +context.lastTarget +is set to the build target node if the build was successful. -Example for implementing and using custom tests: +Example of implementing and using custom tests: def CheckQt(context, qtdir): @@ -3925,7 +3938,7 @@ def CheckQt(context, qtdir): lastLIBS = context.env['LIBS'] lastLIBPATH = context.env['LIBPATH'] lastCPPPATH= context.env['CPPPATH'] - context.env.Append(LIBS = 'qt', LIBPATH = qtdir + '/lib', CPPPATH = qtdir + '/include' ) + context.env.Append(LIBS='qt', LIBPATH=qtdir + '/lib', CPPPATH=qtdir + '/include') ret = context.TryLink(""" #include <qapp.h> int main(int argc, char **argv) { @@ -3934,12 +3947,12 @@ int main(int argc, char **argv) { } """) if not ret: - context.env.Replace(LIBS = lastLIBS, LIBPATH=lastLIBPATH, CPPPATH=lastCPPPATH) + context.env.Replace(LIBS=lastLIBS, LIBPATH=lastLIBPATH, CPPPATH=lastCPPPATH) context.Result( ret ) return ret env = Environment() -conf = Configure( env, custom_tests = { 'CheckQt' : CheckQt } ) +conf = Configure(env, custom_tests = {'CheckQt': CheckQt}) if not conf.CheckQt('/usr/lib/qt'): print('We really need qt!') Exit(1) diff --git a/doc/user/sconf.xml b/doc/user/sconf.xml index 109e468..8961606 100644 --- a/doc/user/sconf.xml +++ b/doc/user/sconf.xml @@ -46,35 +46,29 @@ - &SCons; has integrated support for multi-platform build configuration - similar to that offered by GNU &Autoconf;, - such as - figuring out what libraries or header files - are available on the local system. + &SCons; has integrated support for build configuration + similar in style to GNU &Autoconf;, but designed to be + transparently multi-platform. The configuration system + can help figure out if external build requirements such + as system libraries or header files + are available on the build system. This section describes how to use this &SCons; feature. + (See also the &SCons; man page for additional information). - - - This chapter is still under development, - so not everything is explained as well as it should be. - See the &SCons; man page for additional information. - - -
&Configure_Contexts; The basic framework for multi-platform build configuration - in &SCons; is to attach a &configure_context; to a - construction environment by calling the &Configure; function, - perform a number of checks for + in &SCons; is to create a &configure_context; inside a + &consenv; by calling the &Configure; function, + perform the desired checks for libraries, functions, header files, etc., - and to then call the configure context's &Finish; method + and then call the configure context's &Finish; method to finish off the configuration: @@ -88,7 +82,15 @@ env = conf.Finish() - &SCons; provides a number of basic checks, + The &Finish; call is required; if a new context is + created while a context is active, even in a different + &consenv;, &scons; will complain and exit. + + + + + + &SCons; provides a number of pre-defined basic checks, as well as a mechanism for adding your own custom checks. @@ -125,8 +127,11 @@ env = conf.Finish() Testing the existence of a header file requires knowing what language the header file is. - A configure context has a &CheckCHeader; method - that checks for the existence of a C header file: + This information is supplied in the language + keyword parameter to the &CheckHeader; method. + Since &scons; grew up in a world of C/C++ code, + a &configure_context; also has a &CheckCHeader; method + that specifically checks for the existence of a C header file: @@ -134,7 +139,7 @@ env = conf.Finish() env = Environment() conf = Configure(env) if not conf.CheckCHeader('math.h'): - print 'Math.h must be installed!' + print('Math.h must be installed!') Exit(1) if conf.CheckCHeader('foo.h'): conf.env.Append('-DHAS_FOO_H') @@ -143,10 +148,18 @@ env = conf.Finish() - Note that you can choose to terminate + As shown in the example, depending on the circumstances + you can choose to terminate the build if a given header file doesn't exist, or you can modify the construction environment - based on the existence of a header file. + based on the presence or absence of a header file + (the same applies to any other check). If there are a + many elements to check for, it may be friendlier for + the user if you do not terminate on the first failure, + but track the problems found until the end and report on + all of them, that way the user does not have to iterate + multiple times, each time finding one new dependency that + needs to be installed. @@ -162,7 +175,7 @@ env = conf.Finish() env = Environment() conf = Configure(env) if not conf.CheckCXXHeader('vector.h'): - print 'vector.h must be installed!' + print('vector.h must be installed!') Exit(1) env = conf.Finish() @@ -183,8 +196,8 @@ env = conf.Finish() env = Environment() conf = Configure(env) if not conf.CheckFunc('strcpy'): - print 'Did not find strcpy(), using local version' - conf.env.Append(CPPDEFINES = '-Dstrcpy=my_local_strcpy') + print('Did not find strcpy(), using local version') + conf.env.Append(CPPDEFINES='-Dstrcpy=my_local_strcpy') env = conf.Finish() @@ -197,7 +210,7 @@ env = conf.Finish() Check for the availability of a library using the &CheckLib; method. - You only specify the basename of the library, + You only specify the base part of the library name, you don't need to add a lib prefix or a .a or .lib suffix: @@ -207,7 +220,7 @@ env = conf.Finish() env = Environment() conf = Configure(env) if not conf.CheckLib('m'): - print 'Did not find libm.a or m.lib, exiting!' + print('Did not find libm.a or m.lib, exiting!') Exit(1) env = conf.Finish() @@ -227,8 +240,8 @@ env = conf.Finish() env = Environment() conf = Configure(env) -if not conf.CheckLibWithHeader('m', 'math.h', 'c'): - print 'Did not find libm.a or m.lib, exiting!' +if not conf.CheckLibWithHeader('m', 'math.h', language='c'): + print('Did not find libm.a or m.lib, exiting!') Exit(1) env = conf.Finish() @@ -257,8 +270,8 @@ env = conf.Finish() env = Environment() conf = Configure(env) if not conf.CheckType('off_t'): - print 'Did not find off_t typedef, assuming int' - conf.env.Append(CCFLAGS = '-Doff_t=int') + print('Did not find off_t typedef, assuming int') + conf.env.Append(CCFLAGS='-Doff_t=int') env = conf.Finish() @@ -276,8 +289,8 @@ env = conf.Finish() env = Environment() conf = Configure(env) if not conf.CheckType('off_t', '#include <sys/types.h>\n'): - print 'Did not find off_t typedef, assuming int' - conf.env.Append(CCFLAGS = '-Doff_t=int') + print('Did not find off_t typedef, assuming int') + conf.env.Append(CCFLAGS='-Doff_t=int') env = conf.Finish() @@ -292,7 +305,7 @@ env = conf.Finish() env = Environment() conf = Configure(env) int_size = conf.CheckTypeSize('unsigned int') -print 'sizeof unsigned int is', int_size +print('sizeof unsigned int is', int_size) env = conf.Finish() @@ -317,7 +330,7 @@ scons: `.' is up to date. env = Environment() conf = Configure(env) if not conf.CheckProg('foobar'): - print 'Unable to find the program foobar on the system' + print('Unable to find the program foobar on the system') Exit(1) env = conf.Finish() @@ -399,7 +412,7 @@ def CheckMyLibrary(context): env = Environment() -conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary}) +conf = Configure(env, custom_tests={'CheckMyLibrary': CheckMyLibrary}) @@ -436,9 +449,9 @@ def CheckMyLibrary(context): return result env = Environment() -conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary}) +conf = Configure(env, custom_tests={'CheckMyLibrary': CheckMyLibrary}) if not conf.CheckMyLibrary(): - print 'MyLibrary is not installed!' + print('MyLibrary is not installed!') Exit(1) env = conf.Finish() @@ -516,9 +529,9 @@ Removed foo env = Environment() if not env.GetOption('clean'): - conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary}) + conf = Configure(env, custom_tests={'CheckMyLibrary': CheckMyLibrary}) if not conf.CheckMyLibrary(): - print 'MyLibrary is not installed!' + print('MyLibrary is not installed!') Exit(1) env = conf.Finish() -- cgit v0.12 From 1f3946d6ff394cd1f68828de83ab1638c81574ca Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sat, 18 Apr 2020 16:22:44 -0600 Subject: Fix one more instance of moved scons.py [ci skip] SConsExamples still using src/script Signed-off-by: Mats Wichmann --- bin/SConsExamples.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/bin/SConsExamples.py b/bin/SConsExamples.py index ff72a27..05bd02e 100644 --- a/bin/SConsExamples.py +++ b/bin/SConsExamples.py @@ -415,9 +415,9 @@ def exampleNamesAreUnique(dpath): sys.path.append(os.path.join(os.getcwd(), 'testing/framework')) sys.path.append(os.path.join(os.getcwd(), 'build', 'testing/framework')) -scons_py = os.path.join('bootstrap', 'src', 'script', 'scons.py') +scons_py = os.path.join('bootstrap', 'scripts', 'scons.py') if not os.path.exists(scons_py): - scons_py = os.path.join('src', 'script', 'scons.py') + scons_py = os.path.join('scripts', 'scons.py') scons_py = os.path.join(os.getcwd(), scons_py) @@ -748,8 +748,7 @@ def command_ls(args, c, test, values): for a in args: l.extend(ls(test.workpath('WORK', a))) return l - else: - return ls(test.workpath('WORK')) + return ls(test.workpath('WORK')) def command_sleep(args, c, test, values): time.sleep(int(args[0])) -- cgit v0.12 From e50e04cc7323da19bdfe099d7dda86dcde085919 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sun, 19 Apr 2020 06:01:22 -0600 Subject: SConsExamples: drop bootstrap reference [ci skip] bootstrap directory not used any longer, dropped. One generated example (troubleshoot_stacktrace) was directly affected. A different generated troubleshooting example was instroduced by an earlier change but never committed, including here for completeness. Signed-off-by: Mats Wichmann --- bin/SConsExamples.py | 12 +++-------- .../examples/troubleshoot_stacktrace_2.xml | 11 +++++----- doc/generated/examples/troubleshoot_tree1_7.xml | 25 ++++++++++++++++++++++ 3 files changed, 33 insertions(+), 15 deletions(-) create mode 100644 doc/generated/examples/troubleshoot_tree1_7.xml diff --git a/bin/SConsExamples.py b/bin/SConsExamples.py index 05bd02e..063fba1 100644 --- a/bin/SConsExamples.py +++ b/bin/SConsExamples.py @@ -415,15 +415,9 @@ def exampleNamesAreUnique(dpath): sys.path.append(os.path.join(os.getcwd(), 'testing/framework')) sys.path.append(os.path.join(os.getcwd(), 'build', 'testing/framework')) -scons_py = os.path.join('bootstrap', 'scripts', 'scons.py') -if not os.path.exists(scons_py): - scons_py = os.path.join('scripts', 'scons.py') - +scons_py = os.path.join('scripts', 'scons.py') scons_py = os.path.join(os.getcwd(), scons_py) - -scons_lib_dir = os.path.join(os.getcwd(), 'bootstrap', 'src', 'engine') -if not os.path.exists(scons_lib_dir): - scons_lib_dir = os.path.join(os.getcwd(), 'src', 'engine') +scons_lib_dir = os.path.join(os.getcwd(), 'src', 'engine') os.environ['SCONS_LIB_DIR'] = scons_lib_dir @@ -879,7 +873,7 @@ def create_scons_output(e): if not command.output and lines: ncontent = '\n'.join(lines) ncontent = address_re.sub(r' at 0x700000>', ncontent) - ncontent = engine_re.sub(r' File "bootstrap/src/engine/SCons/', ncontent) + ncontent = engine_re.sub(r' File "src/engine/SCons/', ncontent) ncontent = file_re.sub(r'\1 ', ncontent) ncontent = nodelist_re.sub(r"\1 'NodeList' object \2", ncontent) ncontent = ncontent.replace('__ROOT__', '') diff --git a/doc/generated/examples/troubleshoot_stacktrace_2.xml b/doc/generated/examples/troubleshoot_stacktrace_2.xml index 70a429d..7ace0ec 100644 --- a/doc/generated/examples/troubleshoot_stacktrace_2.xml +++ b/doc/generated/examples/troubleshoot_stacktrace_2.xml @@ -1,13 +1,12 @@ - -% scons -Q --debug=stacktrace +% scons -Q --debug=stacktrace scons: *** [prog.o] Source `prog.c' not found, needed by target `prog.o'. scons: internal stack trace: - File "bootstrap/src/engine/SCons/Job.py", line 199, in start + File "src/engine/SCons/Job.py", line 199, in start task.prepare() - File "bootstrap/src/engine/SCons/Script/Main.py", line 191, in prepare + File "src/engine/SCons/Script/Main.py", line 189, in prepare return SCons.Taskmaster.OutOfDateTask.prepare(self) - File "bootstrap/src/engine/SCons/Taskmaster.py", line 198, in prepare + File "src/engine/SCons/Taskmaster.py", line 196, in prepare executor.prepare() - File "bootstrap/src/engine/SCons/Executor.py", line 431, in prepare + File "src/engine/SCons/Executor.py", line 429, in prepare raise SCons.Errors.StopError(msg % (s, self.batches[0].targets[0])) diff --git a/doc/generated/examples/troubleshoot_tree1_7.xml b/doc/generated/examples/troubleshoot_tree1_7.xml new file mode 100644 index 0000000..2b16556 --- /dev/null +++ b/doc/generated/examples/troubleshoot_tree1_7.xml @@ -0,0 +1,25 @@ +% scons -Q --tree=derived,status +cc -o f1.o -c -I. f1.c +cc -o f2.o -c -I. f2.c +cc -o f3.o -c -I. f3.c +cc -o prog f1.o f2.o f3.o + E = exists + R = exists in repository only + b = implicit builder + B = explicit builder + S = side effect + P = precious + A = always build + C = current + N = no clean + H = no cache + +[E b ]+-. +[E B C ] +-f1.o +[E B C ] +-f2.o +[E B C ] +-f3.o +[E B C ] +-prog +[E B C ] +-f1.o +[E B C ] +-f2.o +[E B C ] +-f3.o + -- cgit v0.12 From d270eb25f5cca3224c89498c79b8a39f9a69241a Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Mon, 20 Apr 2020 09:02:59 -0600 Subject: [PR #3615] address some review comments on Variables [ci skip] Signed-off-by: Mats Wichmann --- doc/man/scons.xml | 16 ++++++++-------- doc/user/command-line.xml | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index b1eea06..54065dc 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -3957,7 +3957,7 @@ For example, libraries needed for the build may be in non-standard locations, or site-specific compiler options may need to be passed to the compiler. &SCons; -provides a Variables +provides a &Variables; object to support overriding &consvars; on the command line: @@ -4116,7 +4116,7 @@ env = Environment(variables=vars) vars.UnknownVariables() -Return a dictionary containing any +Returns a dictionary containing any variables that were specified either in the files or the dictionary with which the Variables object was initialized, @@ -4187,7 +4187,7 @@ Help(vars.GenerateHelpText(env, sort=cmp)) vars.FormatVariableHelpText(env, opt, help, default, actual) -Return a formatted string +Returns a formatted string containing the printable help text for one option. It is normally not called directly, @@ -4225,7 +4225,7 @@ the &Add; or &AddVariables; method: BoolVariable(key, help, default) -Return a tuple of arguments +Returns a tuple of arguments to set up a Boolean option. The option will use the specified name @@ -4260,7 +4260,7 @@ as false. EnumVariable(key, help, default, allowed_values, [map, ignorecase]) -Return a tuple of arguments +Returns a tuple of arguments to set up an option whose value may be one of a specified list of legal enumerated values. @@ -4309,7 +4309,7 @@ converted to lower case. ListVariable(key, help, default, names, [map]) -Return a tuple of arguments +Returns a tuple of arguments to set up an option whose value may be one or more of a specified list of legal enumerated values. @@ -4348,7 +4348,7 @@ reflected in the generated help message). PackageVariable(key, help, default) -Return a tuple of arguments +Returns a tuple of arguments to set up an option whose value is a path name of a package that may be @@ -4388,7 +4388,7 @@ to disable use of the specified option. PathVariable(key, help, default, [validator]) -Return a tuple of arguments +Returns a tuple of arguments to set up an option whose value is expected to be a path name. The option will use diff --git a/doc/user/command-line.xml b/doc/user/command-line.xml index 4033372..903fe56 100644 --- a/doc/user/command-line.xml +++ b/doc/user/command-line.xml @@ -998,7 +998,7 @@ bar.c - Historical note: In old &SCons; (prior to 1.0), + Historical note: In old &SCons; (prior to 0.98.1), these build variables were known as "command-line build options." The class was named the &Options; class, and the predefined functions to construct options were named -- cgit v0.12 From 124b7db49590ba05c3d2f6f0e0d1ae719a16cc11 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 21 Apr 2020 09:37:19 -0700 Subject: PEP8 + removed '-Wl,-Bsymbolic' from SHLIBVERSIONFLAGS fixes issue #3247 --- src/engine/SCons/Tool/gnulink.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/engine/SCons/Tool/gnulink.py b/src/engine/SCons/Tool/gnulink.py index b1d5088..5372322 100644 --- a/src/engine/SCons/Tool/gnulink.py +++ b/src/engine/SCons/Tool/gnulink.py @@ -35,9 +35,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import SCons.Util import SCons.Tool -import os import sys -import re from . import link @@ -57,21 +55,22 @@ def generate(env): # OpenBSD doesn't usually use SONAME for libraries use_soname = not sys.platform.startswith('openbsd') - link._setup_versioned_lib_variables(env, tool = 'gnulink', use_soname = use_soname) + link._setup_versioned_lib_variables(env, tool='gnulink', use_soname=use_soname) env['LINKCALLBACKS'] = link._versioned_lib_callbacks() - # For backward-compatibility with older SCons versions - env['SHLIBVERSIONFLAGS'] = SCons.Util.CLVar('-Wl,-Bsymbolic') - + # # For backward-compatibility with older SCons versions + # env['SHLIBVERSIONFLAGS'] = SCons.Util.CLVar('') + + def exists(env): # TODO: sync with link.smart_link() to choose a linker - linkers = { 'CXX': ['g++'], 'CC': ['gcc'] } + linkers = {'CXX': ['g++'], 'CC': ['gcc']} alltools = [] for langvar, linktools in linkers.items(): - if langvar in env: # use CC over CXX when user specified CC but not CXX + if langvar in env: # use CC over CXX when user specified CC but not CXX return SCons.Tool.FindTool(linktools, env) alltools.extend(linktools) - return SCons.Tool.FindTool(alltools, env) # find CXX or CC + return SCons.Tool.FindTool(alltools, env) # find CXX or CC # Local Variables: # tab-width:4 -- cgit v0.12 From dba5fb0b1f651b8d4d4b61d7be15a5bee3ca8052 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 21 Apr 2020 09:37:19 -0700 Subject: PEP8 + removed '-Wl,-Bsymbolic' from SHLIBVERSIONFLAGS fixes issue #3248 --- src/engine/SCons/Tool/gnulink.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/engine/SCons/Tool/gnulink.py b/src/engine/SCons/Tool/gnulink.py index b1d5088..5372322 100644 --- a/src/engine/SCons/Tool/gnulink.py +++ b/src/engine/SCons/Tool/gnulink.py @@ -35,9 +35,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import SCons.Util import SCons.Tool -import os import sys -import re from . import link @@ -57,21 +55,22 @@ def generate(env): # OpenBSD doesn't usually use SONAME for libraries use_soname = not sys.platform.startswith('openbsd') - link._setup_versioned_lib_variables(env, tool = 'gnulink', use_soname = use_soname) + link._setup_versioned_lib_variables(env, tool='gnulink', use_soname=use_soname) env['LINKCALLBACKS'] = link._versioned_lib_callbacks() - # For backward-compatibility with older SCons versions - env['SHLIBVERSIONFLAGS'] = SCons.Util.CLVar('-Wl,-Bsymbolic') - + # # For backward-compatibility with older SCons versions + # env['SHLIBVERSIONFLAGS'] = SCons.Util.CLVar('') + + def exists(env): # TODO: sync with link.smart_link() to choose a linker - linkers = { 'CXX': ['g++'], 'CC': ['gcc'] } + linkers = {'CXX': ['g++'], 'CC': ['gcc']} alltools = [] for langvar, linktools in linkers.items(): - if langvar in env: # use CC over CXX when user specified CC but not CXX + if langvar in env: # use CC over CXX when user specified CC but not CXX return SCons.Tool.FindTool(linktools, env) alltools.extend(linktools) - return SCons.Tool.FindTool(alltools, env) # find CXX or CC + return SCons.Tool.FindTool(alltools, env) # find CXX or CC # Local Variables: # tab-width:4 -- cgit v0.12 From 78e41a171a19f460c064970b7234ccd0df4253e2 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 21 Apr 2020 09:42:05 -0700 Subject: Added notes to RELEASE.txt and CHANGES.txt for Issue #3248 --- src/CHANGES.txt | 3 +++ src/RELEASE.txt | 33 +++++---------------------------- 2 files changed, 8 insertions(+), 28 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index efe5464..6b7c014 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -32,6 +32,9 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Purge obsolete internal build and tooling scripts - Resolve Issue #3451 and Issue #3450 - Rewrite SCons setup.py and packaging. Move script logic to entry points so package can create scripts which use the correct version of Python. + - Resolve Issue #3248 - Removing '-Wl,-Bsymbolic' from SHLIBVERSIONFLAGS + NOTE: If your build depends on the above you must now add to your SHLIBVERSIONFLAGS + From Jeremy Elson: - Updated design doc to use the correct syntax for Depends() diff --git a/src/RELEASE.txt b/src/RELEASE.txt index 825122e..1b21a3b 100755 --- a/src/RELEASE.txt +++ b/src/RELEASE.txt @@ -1,33 +1,9 @@ - A new SCons checkpoint release, 3.1.3.alpha.yyyymmdd, is now available + A new SCons release, 4.0.0, is now available on the SCons download page: https://scons.org/pages/download.html - XXX The primary purpose of this release ... XXX - - A SCons "checkpoint release" is intended to provide early access to - new features so they can be tested in the field before being released - for adoption by other software distributions. - - Note that a checkpoint release is developed using the same test-driven - development methodology as all SCons releases. Existing SCons - functionality should all work as it does in previous releases (except - for any changes identified in the release notes) and early adopters - should be able to use a checkpoint release safely for production work - with existing SConscript files. If not, it represents not only a bug - in SCons but also a hole in the regression test suite, and we want to - hear about it. - - New features may be more lightly tested than in past releases, - especially as concerns their interaction with all of the other - functionality in SCons. We are especially interested in hearing bug - reports about new functionality. - - We do not recommend that downstream distributions (Debian, Fedora, - etc.) package a checkpoint release, mainly to avoid confusing the - "public" release numbering with the long checkpoint release names. - - Here is a summary of the changes since 1.3.0: + Here is a summary of the changes since 3.1.2: NEW FUNCTIONALITY @@ -39,8 +15,9 @@ CHANGED/ENHANCED EXISTING FUNCTIONALITY - - List modifications to existing features, where the previous behavior - wouldn't actually be considered a bug + - Resolve Issue #3248 - Removing '-Wl,-Bsymbolic' from SHLIBVERSIONFLAGS + NOTE: If your build depends on the above you must now add to your SHLIBVERSIONFLAGS + FIXES -- cgit v0.12 From 984a0f0a14ff97852b3f0062c9046e13be9c968d Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 21 Apr 2020 09:46:45 -0700 Subject: Fix tests expecting -Bsymbolic --- test/LINK/LDMODULEVERSIONFLAGS.py | 2 +- test/LINK/SHLIBVERSIONFLAGS.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/LINK/LDMODULEVERSIONFLAGS.py b/test/LINK/LDMODULEVERSIONFLAGS.py index 0683b72..d8f280a 100644 --- a/test/LINK/LDMODULEVERSIONFLAGS.py +++ b/test/LINK/LDMODULEVERSIONFLAGS.py @@ -40,7 +40,7 @@ tool_list = SCons.Platform.DefaultToolList(platform, env) test = TestSCons.TestSCons() if 'gnulink' in tool_list: - versionflags = r".+ -Wl,-Bsymbolic -Wl,-soname=libfoo.so.1( .+)+" + versionflags = r".+ -Wl,-soname=libfoo.so.1( .+)+" elif 'sunlink' in tool_list: versionflags = r".+ -h libfoo.so.1( .+)+" else: diff --git a/test/LINK/SHLIBVERSIONFLAGS.py b/test/LINK/SHLIBVERSIONFLAGS.py index 9d91868..bec9a82 100644 --- a/test/LINK/SHLIBVERSIONFLAGS.py +++ b/test/LINK/SHLIBVERSIONFLAGS.py @@ -39,7 +39,7 @@ tool_list = SCons.Platform.DefaultToolList(platform, env) test = TestSCons.TestSCons() if 'gnulink' in tool_list: - versionflags = r".+ -Wl,-Bsymbolic -Wl,-soname=libfoo.so.1( .+)+" + versionflags = r".+ -Wl,-soname=libfoo.so.1( .+)+" elif 'sunlink' in tool_list: versionflags = r".+ -h libfoo.so.1( .+)+" elif 'applelink' in tool_list: -- cgit v0.12 From c0e9c494d9dd441627047d462a2c22e8c2beeb9f Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 21 Apr 2020 11:17:06 -0700 Subject: [ci skip] Update docs --- src/engine/SCons/Tool/msvc.xml | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/engine/SCons/Tool/msvc.xml b/src/engine/SCons/Tool/msvc.xml index 48ce13f..bdde91b 100644 --- a/src/engine/SCons/Tool/msvc.xml +++ b/src/engine/SCons/Tool/msvc.xml @@ -482,7 +482,7 @@ Specify the location of vswhere.exe. -Propose: The vswhere command is distributed with Microsoft Visual Studio and Build + The vswhere command is distributed with Microsoft Visual Studio and Build Tools since the 2017 edition, but is also available standalone. It fully detects 2017 and later editions, but with the argument, can detect installations of the 2010 through 2015 editions with limited data returned. @@ -501,9 +501,19 @@ located. Note that &cv-VSWHERE; must be set at the same time or prior to the msvc tool being initialized. So either set it as follows -Environment(VSWHERE='c:/my/path/to/vswhere') or -if your Environment() is created specifying no tools tools=[] or with a list of tools not including msvs or msvc or mslink - such as Environment(Tools=[]) + + +env = Environment(VSWHERE='c:/my/path/to/vswhere') + + +or if your Environment() is created specifying no tools +tools=[] +or with a list of tools not including msvs or msvc or mslink such as + + env = Environment(Tools=[]) + env['VSWHERE'] = r'c:/my/vswhere/install/location/vswhere.exe' + env.Tool() + -- cgit v0.12 From 735bd26ddff03d49544287b16996d8cd456c072f Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 21 Apr 2020 14:07:39 -0700 Subject: [ci skip] Doc updates --- src/engine/SCons/Tool/msvc.xml | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/engine/SCons/Tool/msvc.xml b/src/engine/SCons/Tool/msvc.xml index bdde91b..97de279 100644 --- a/src/engine/SCons/Tool/msvc.xml +++ b/src/engine/SCons/Tool/msvc.xml @@ -478,48 +478,48 @@ Valid values are '1' or '0' -Specify the location of vswhere.exe. +Specify the location of vswhere.exe. - The vswhere command is distributed with Microsoft Visual Studio and Build - Tools since the 2017 edition, but is also available standalone. It fully detects 2017 and later editions, - but with the argument, can detect installations of the 2010 through 2015 + The vswhere.exe executable is distributed with Microsoft Visual Studio and Build + Tools since the 2017 edition, but is also available standalone. + It provides full information about installations of 2017 and later editions. + With the argument, vswhere.exe can detect installations of the 2010 through 2015 editions with limited data returned. -If &cv-VSWHERE; is set, SCons will use that location. +If VSWHERE is set, SCons will use that location. - Otherwise SCons will look in the following locations and set &cv-VSWHERE; to the path of the first vswhere.exe + Otherwise SCons will look in the following locations and set VSWHERE to the path of the first vswhere.exe located. -%ProgramFiles(x86)%\Microsoft Visual Studio\Installer -"%ProgramFiles%\Microsoft Visual Studio\Installer -%ChocolateyInstall%\bin +%ProgramFiles(x86)%\Microsoft Visual Studio\Installer +%ProgramFiles%\Microsoft Visual Studio\Installer +%ChocolateyInstall%\bin -Note that &cv-VSWHERE; must be set at the same time or prior to the msvc tool being initialized. So either set it as follows + Note that VSWHERE must be set at the same time or prior to any of &t-link-msvc;, &t-link-msvs; , and/or &t-link-mslink; &f-link-Tool; being initialized. + Either set it as follows env = Environment(VSWHERE='c:/my/path/to/vswhere') -or if your Environment() is created specifying no tools +or if your &f-link-Environment; is created specifying no tools tools=[] -or with a list of tools not including msvs or msvc or mslink such as +or with an empty list of tools or with a list of tools which doesn't include &t-link-default;, &t-link-msvs;, &t-link-msvc; or &t-link-mslink;. - env = Environment(Tools=[]) + env = Environment(tools=[]) env['VSWHERE'] = r'c:/my/vswhere/install/location/vswhere.exe' - env.Tool() + env.Tool('msvc') + env.Tool('mslink') + env.Tool('msvs') - - - - -- cgit v0.12 From 3fed7a63425265d3151f52515fdbd4f62867e57d Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 21 Apr 2020 17:23:58 -0700 Subject: [ci skip] updated wording for VSWHERE --- src/engine/SCons/Tool/msvc.xml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/engine/SCons/Tool/msvc.xml b/src/engine/SCons/Tool/msvc.xml index 97de279..e92fa9b 100644 --- a/src/engine/SCons/Tool/msvc.xml +++ b/src/engine/SCons/Tool/msvc.xml @@ -508,10 +508,11 @@ located. env = Environment(VSWHERE='c:/my/path/to/vswhere') -or if your &f-link-Environment; is created specifying no tools -tools=[] -or with an empty list of tools or with a list of tools which doesn't include &t-link-default;, &t-link-msvs;, &t-link-msvc; or &t-link-mslink;. - +or if your &consenv; is created specifying an empty tools list +(or a list of tools which omits all of default, msvs, msvc, and mslink), +and also before &f-link-env-Tool; is called to ininitialize any of those tools: + + env = Environment(tools=[]) env['VSWHERE'] = r'c:/my/vswhere/install/location/vswhere.exe' env.Tool('msvc') -- cgit v0.12 From 74505ffdada84b796fb5f6adc42878f330fc9460 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 22 Apr 2020 12:07:07 -0700 Subject: [ci skip] Speedup xml validation called by bin/docs-update-generated.py by caching parsed docbook schema. Yields approx 60x speedup --- bin/SConsDoc.py | 10 +++++++--- src/CHANGES.txt | 1 + 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/bin/SConsDoc.py b/bin/SConsDoc.py index e211b3c..960a0c9 100644 --- a/bin/SConsDoc.py +++ b/bin/SConsDoc.py @@ -345,10 +345,14 @@ if not has_libxml2: t = etree.Element(root, nsmap=NSMAP) return self.decorateWithHeader(t) + # singleton to cache parsed xmlschema.. + xmlschema = None + @staticmethod def validateXml(fpath, xmlschema_context): - # Use lxml - xmlschema = etree.XMLSchema(xmlschema_context) + + if TreeFactory.xmlschema is None: + TreeFactory.xmlschema = etree.XMLSchema(xmlschema_context) try: doc = etree.parse(fpath) except Exception as e: @@ -357,7 +361,7 @@ if not has_libxml2: return False doc.xinclude() try: - xmlschema.assertValid(doc) + TreeFactory.xmlschema.assertValid(doc) except Exception as e: print("ERROR: %s fails to validate:" % fpath) print(e) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 6b7c014..c1bf24c 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -34,6 +34,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER package can create scripts which use the correct version of Python. - Resolve Issue #3248 - Removing '-Wl,-Bsymbolic' from SHLIBVERSIONFLAGS NOTE: If your build depends on the above you must now add to your SHLIBVERSIONFLAGS + - Speedup bin/docs-update-generated by caching parsed docbook schema. (60x speedup) From Jeremy Elson: -- cgit v0.12 From ac5f38d85dba2eb4f4c9569d4c2dc718a98d3888 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Wed, 22 Apr 2020 18:04:30 -0600 Subject: docs: update Tool description [ci skip] Tools is now is own subsection of Construction Environments, with an expanded description, also slightly reorganizing existing content. The description of the Tool function/method was also reworded to be more descriptive and less repetitive. Signed-off-by: Mats Wichmann --- doc/man/scons.xml | 155 ++++++++++++++++++++++++++------------- src/engine/SCons/Environment.xml | 75 +++++++++---------- 2 files changed, 142 insertions(+), 88 deletions(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index db173c5..49e09ce 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -2179,28 +2179,75 @@ def my_platform(env): env = Environment(platform=my_platform) -Additionally, a specific set of tools -with which to initialize the environment + + + +Tools + + +&SCons; has a large number of predefined tools which +are used to help initialize the &consenv;, +and additional tools can be added. +An &scons; tool specification +is only responsible for setup. +For example, if the SConscript file declares +the need to construct an object file from +a C-language source file by calling the +&b-link-Object; builder, then a tool representing +an available C compiler needs to have run first, +to set up the builder and all the &consvars; +it needs, in that &consenv;. Normally this +happens invisibly: &scons; has per-platform +lists of default tools, and it runs through those tools, +calling the ones which are actually applicable +(skipping those where necessary programs are not +installed on the build system, etc.). + + + +A specific set of tools +with which to initialize the environment when +creating it may be specified using the optional keyword argument -tools: +tools. +This is useful to override the defaults, +to specify non-default built-in tools, and +to supply added tools: env = Environment(tools=['msvc', 'lex']) +Tools can also be called by using the &f-link-Tool; +method (see below). + + + The tools argument overrides -the tool list, it does not add to it, so be +the default tool list, it does not add to it, so be sure to include all the tools you need. For example if you are building a c/c++ program -you must add a tool for both compiler and linker, +you must specify a tool for at least a compiler and a linker, as in tools=['clang', 'link']. The tool name 'default' can be used to retain the default list. -Non-built-in tools may be specified using the -optional toolpath keyword argument: +If no tools list is specified, +or the list includes 'default', +then &scons; will detect usable tools, +using the value of PATH +in the ENV &consvar; (not +the external PATH from os.environ) +for looking up any backing programs, and the platform name in effect +to determine the default tools for that platform. +Changing the PATH +variable after the &consenv; is constructed will not cause the tools to +be redetected. + +To help locate added tools, specify the +toolpath keyword argument: env = Environment(tools=['default', 'foo'], toolpath=['tools']) @@ -2212,33 +2259,14 @@ as well as using the ordinary default tools for the platform. -A tool specification must include two functions: -generate(env, **kw) -and exists(env). -The -generate -function -modifies the environment referenced by env -to set up variables so that the tool -can be executed; -it may use any keyword arguments -that the user supplies in kw (see below) -to vary its initialization. -The -exists -function should return a true -value if the tool is available. - - - -Tools in the toolpath are used before +Tools in the toolpath are used in preference to any of the built-in ones. For example, adding -gcc.py to the toolpath -would override the built-in gcc tool. +a tool gcc.py to the toolpath +directory would override the built-in gcc tool. The toolpath is stored in the environment and will be picked up by subsequent calls to the -&Clone; and &Tool; methods: +&f-Clone; and &f-Tool; methods: @@ -2247,11 +2275,40 @@ derived = base.Clone(tools=['custom_tool']) derived.CustomBuilder() -The elements of the tools list may also + +A tool specification must include two functions: + + + + + generate(env, **kwargs) + +Modifies the environment referenced by env +to set up variables so that the facilities represented by +the tool can be executed. +It may use any keyword arguments +that the user supplies in kwargs +to vary its initialization. + + + + exists(env) + +Return True if the tool can +be called. Usually this means looking up one or more +known programs using the PATH from the +supplied env, but the tool can +make the "exists" decision in any way it chooses. + + + + + +The elements of the tools list may also be functions or callable objects, -in which case the Environment() method -will call the specified elements -to update the new &consenv;: +in which case the &Environment; method +will call those objects +to update the new &consenv; (see &f-link-Tool; for more details): def my_tool(env): @@ -2260,9 +2317,9 @@ def my_tool(env): env = Environment(tools=[my_tool]) -The individual elements of the tools list -may also themselves be two-element lists of the form -(toolname, kw_dict). +The individual elements of the tools list +may also themselves be lists or tuples of the form +(toolname, kw_dict). SCons searches for the toolname specification file as described above, and @@ -2279,9 +2336,9 @@ or otherwise changing its initialization. # in tools/my_tool.py: -def generate(env, **kw): - # Sets MY_TOOL to the value of keyword argument 'arg1' or 1. - env['MY_TOOL'] = kw.get('arg1', '1') +def generate(env, **kwargs): + # Sets MY_TOOL to the value of keyword 'arg1' '1' if not supplied + env['MY_TOOL'] = kwargs.get('arg1', '1') def exists(env): return True @@ -2291,18 +2348,14 @@ env = Environment(tools=['default', ('my_tool', {'arg1': 'abc'})], toolpath=['tools']) -The tool definition (i.e. my_tool()) can use the PLATFORM variable from -the environment it receives to customize the tool for different platforms. - -If no tool list is specified, then SCons will auto-detect the installed -tools using the PATH variable in the ENV &consvar; and the -platform name when the Environment is constructed. Changing the PATH -variable after the Environment is constructed will not cause the tools to -be redetected. +The tool definition (my_tool in the example) +can use the +PLATFORM variable from +the &consenv; it is passed to customize the tool for different platforms. - One feature now present within Scons is the ability to have nested tools. -Tools which can be located within a subdirectory in the toolpath. -With a nested tool name the dot represents a directory seperator +Tools can be "nested" - that is, they +can be located within a subdirectory in the toolpath. +A nested tool name uses a dot to represent a directory seperator # namespaced builder diff --git a/src/engine/SCons/Environment.xml b/src/engine/SCons/Environment.xml index 48980e2..5dea66e 100644 --- a/src/engine/SCons/Environment.xml +++ b/src/engine/SCons/Environment.xml @@ -3017,31 +3017,29 @@ source_nodes = env.subst('$EXPAND_TO_NODELIST', -(string, [toolpath, **kw]) +(name, [toolpath, **kwargs]) + -The -&f-Tool; -form of the function -returns a callable object -that can be used to initialize -a construction environment using the -tools keyword of the Environment() method. -The object may be called with a construction -environment as an argument, -in which case the object will -add the necessary variables -to the construction environment -and the name of the tool will be added to the -&cv-link-TOOLS; -construction variable. +Runs the tool identified by +name, which is +searched for in standard locations and any +paths specified by the optional +toolpath, +to update a &consenv; with &consvars; +needed to use the mechanisms that tool describes. +Any additional keyword arguments +kwargs are passed +on to the tool module's generate function. -Additional keyword arguments are passed to the tool's -generate() -method. +When called as a &consenv; method, +the tool module is called to update the +&consenv; and the name of the tool is +appended to the &cv-link-TOOLS; +&consvar; in that environment. @@ -3049,33 +3047,36 @@ Examples: -env = Environment(tools = [ Tool('msvc') ]) - -env = Environment() -t = Tool('msvc') -t(env) # adds 'msvc' to the TOOLS variable -u = Tool('opengl', toolpath = ['tools']) -u(env) # adds 'opengl' to the TOOLS variable +env.Tool('gcc') +env.Tool('opengl', toolpath=['build/tools']) -The -&f-env-Tool; -form of the function -applies the callable object for the specified tool -string -to the environment through which the method was called. +When called as a global function, +returns a callable tool object; +the tool is not called at this time, +as it lacks the context of an environment to update. +This tool object can be passed to an +&f-link-Environment; or &f-link-Clone; call +as part of the tools keyword argument, +or it can be called directly, +passing a &consenv; to update as the argument. +Either approach will also update the +TOOLS &consvar;. -Additional keyword arguments are passed to the tool's -generate() -method. +Examples: -env.Tool('gcc') -env.Tool('opengl', toolpath = ['build/tools']) +env = Environment(tools=[Tool('msvc')]) + +env = Environment() +t = Tool('msvc') +t(env) # adds 'msvc' to the TOOLS variable +u = Tool('opengl', toolpath = ['tools']) +u(env) # adds 'opengl' to the TOOLS variable -- cgit v0.12 From 7ec2c76c12d1254c2c31a20d15ae5c39540adb3e Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 22 Apr 2020 17:17:24 -0700 Subject: Add system test for setting and retrieving VSWHERE --- test/MSVC/VSWHERE-fixture/SConstruct | 22 ++++++++ test/MSVC/VSWHERE.py | 101 +++++++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 test/MSVC/VSWHERE-fixture/SConstruct create mode 100644 test/MSVC/VSWHERE.py diff --git a/test/MSVC/VSWHERE-fixture/SConstruct b/test/MSVC/VSWHERE-fixture/SConstruct new file mode 100644 index 0000000..38dfb0b --- /dev/null +++ b/test/MSVC/VSWHERE-fixture/SConstruct @@ -0,0 +1,22 @@ +import os +import os.path + +from SCons.Tool.MSCommon.vc import VSWHERE_PATHS + +# Dump out expected paths +for vw_path in VSWHERE_PATHS: + print("VSWHERE_PATH=%s"%vw_path) + + +# Allow normal detection logic to find vswhere.exe +env1=Environment() +print("VSWHERE-detect=%s" % env1['VSWHERE']) + +# Copy found vswhere.exe to current dir +v_local = os.path.join(os.getcwd(), 'vswhere.exe') +Execute(Copy(os.path.join(os.getcwd(), 'vswhere.exe'), env1['VSWHERE'])) + +# With VSWHERE set to copied vswhere.exe (see above), find vswhere.exe +env=Environment(VSWHERE=v_local) +print("VSWHERE-env=%s" % env['VSWHERE']) + diff --git a/test/MSVC/VSWHERE.py b/test/MSVC/VSWHERE.py new file mode 100644 index 0000000..0d6b991 --- /dev/null +++ b/test/MSVC/VSWHERE.py @@ -0,0 +1,101 @@ +#!/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__" + +""" +Test the ability to configure the $VSWHERE construction variable. +Also test that vswhere.exe is found and sets VSWHERE to the correct values +""" +import os.path +import TestSCons + +_python_ = TestSCons._python_ + +test = TestSCons.TestSCons() +test.verbose_set(1) + +test.skip_if_not_msvc() +test.dir_fixture('VSWHERE-fixture') + +test.run(arguments=".") + +# Now grab info out of stdout +lines = test.stdout().splitlines() + +# Debug code +# print("LINES:\n%s" % lines) + +default_locations = [] +detected_path = None +env_path = None +for l in lines: + if 'VSWHERE_PATH' in l: + path = l.strip().split('=')[-1] + default_locations.append(path) + elif 'VSWHERE-detect' in l: + detected_path = l.strip().split('=')[-1] + elif 'VSWHERE-env' in l: + env_path = l.strip().split('=')[-1] + +# Debug code +# print("VPP:%s" % default_locations) +# print("V-D:%s" % detected_path) +# print("V-E:%s" % env_path) + + +test.fail_test(len(default_locations) == 0, + message='No default vswhere.exe locations found') +test.fail_test( + detected_path is None, message='No vswhere.exe detected in default paths :%s' % default_locations) +test.fail_test(detected_path not in default_locations, + message='detected path [%s] not in default locations[%s]' % (detected_path, default_locations)) + +expected_env_path = os.path.join(test.workdir, 'vswhere.exe') +test.fail_test(env_path != expected_env_path, + message='VSWHERE not\n\t%s\n\t but\n\t%s' % (expected_env_path, env_path)) + + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: + +expected = r""" +PS C:\Users\Bill\AppData\Local\Temp\testcmd.11256.1ae1_as5> py -3.8 C:\Users\Bill\devel\scons\git\scons-2\scripts\scons.py +scons: Reading SConscript files ... +VSWHERE_PATH=C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe +VSWHERE_PATH=C:\Program Files\Microsoft Visual Studio\Installer\vswhere.exe +VSWHERE_PATH=C:\ProgramData\chocolatey\bin\vswhere.exe +VSWHERE-detect=C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe +Copy("C:\Users\Bill\AppData\Local\Temp\testcmd.11256.1ae1_as5\vswhere.exe", "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe") +VSWHERE-env=C:\Users\Bill\AppData\Local\Temp\testcmd.11256.1ae1_as5\vswhere.exe +scons: done reading SConscript files. +scons: Building targets ... +scons: `.' is up to date. +scons: done building targets. +""" -- cgit v0.12 From eb33c9cb44f91356a40b108606ee2a03ec93cadc Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Wed, 22 Apr 2020 19:00:54 -0600 Subject: Fix typo "seperator" caught by sider [ci skip] Signed-off-by: Mats Wichmann --- doc/man/scons.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index 49e09ce..c201f05 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -2355,7 +2355,7 @@ the &consenv; it is passed to customize the tool for different platforms. Tools can be "nested" - that is, they can be located within a subdirectory in the toolpath. -A nested tool name uses a dot to represent a directory seperator +A nested tool name uses a dot to represent a directory separator # namespaced builder -- cgit v0.12 From e65ced18e9bc02fdb3c4e3166821f96cf5cf9ff9 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sat, 25 Apr 2020 13:33:22 -0600 Subject: docs: build up description of export/import/return [ci skip] User Guide wording missed some details - one of which is mentioned in an issue. Fixes #798. Signed-off-by: Mats Wichmann --- doc/user/hierarchy.xml | 141 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 97 insertions(+), 44 deletions(-) diff --git a/doc/user/hierarchy.xml b/doc/user/hierarchy.xml index e5a8470..b54e2a5 100644 --- a/doc/user/hierarchy.xml +++ b/doc/user/hierarchy.xml @@ -508,7 +508,7 @@ x In the previous example, each of the subsidiary &SConscript; files created its own construction environment - by calling &Environment; separately. + by calling &f-link-Environment; separately. This obviously works fine, but if each program must be built with the same construction variables, @@ -521,10 +521,10 @@ x - &SCons; supports the ability to export variables - from a parent &SConscript; file - to its subsidiary &SConscript; files, - which allows you to share common initialized + &SCons; supports the ability to export variables + from an &SConscript; file + so they can be imported by other + &SConscript; files, thus allowing you to share common initialized values throughout your build hierarchy. @@ -534,17 +534,13 @@ x - There are two ways to export a variable, - such as a construction environment, - from an &SConscript; file, - so that it may be used by other &SConscript; files. - First, you can call the &Export; - function with a list of variables, - or a string of white-space separated variable names. - Each call to &Export; adds one - or more variables to a global list - of variables that are available for import - by other &SConscript; files. + There are two ways to export a variable + from an &SConscript; file. + The first way is to call the &f-link-Export; function. + &Export; takes one or more arguments that are + string representations of the variable names - that is, + to export the variable env, + you supply the string env to &Export;: @@ -567,9 +563,9 @@ Export('env', 'debug') - Because white space is not legal in Python variable names, - the &Export; function will even automatically split - a string into separate names for you: + Beacuse a Python identifier cannot contain spaces, + &Export; assumes a string containing spaces is multiple + variable names to export and splits it for you: @@ -579,9 +575,42 @@ Export('env debug') - Second, you can specify a list of - variables to export as a second argument - to the &SConscript; function call: + &Export; will also accept arguments in keyword style. + This style can be used, for example, to set variables + that have not been set by name in the SConscript file, + and thus the keys are the intended variable names, + not a string representation: + + + + +Export(MODE="DEBUG", TARGET="arm") + + + + + The styles can be mixed, however note that Python function calling + syntax requires all non-keyword arguments to precede any + keyword arguments in the call. + + + + + + The &Export; function adds the variables to a global + location from which other &SConscript; files can import. + Exporting conceptually works the same as Python assignment + statements - if you assign a name to something, then later assign + the same name to something else, the reference to the original + is lost. + + + + + + The other way to export is you can specify a list of + variables as a second argument + to the &f-link-SConscript; function call: @@ -591,7 +620,7 @@ SConscript('src/SConscript', 'env') - Or as the &exports; keyword argument: + Or (preferably, for readability) as the &exports; keyword argument: @@ -602,7 +631,7 @@ SConscript('src/SConscript', exports='env') These calls export the specified variables - to only the listed &SConscript; files. + to only the listed &SConscript; file. You may, however, specify more than one &SConscript; file in a list: @@ -632,7 +661,7 @@ SConscript(['src1/SConscript', Once a variable has been exported from a calling &SConscript; file, it may be used in other &SConscript; files - by calling the &Import; function: + by calling the &f-link-Import; function: @@ -643,43 +672,66 @@ env.Program('prog', ['prog.c']) - The &Import; call makes the env construction - environment available to the &SConscript; file, - after which the variable can be used to build - programs, libraries, etc. + The &Import; call makes the previously defined env + variable available to the &SConscript; file. + Assuming env is a &consenv;, + after import it can be used to build programs, libraries, etc. + The use case of passing around a &consenv; is extremely common + in larger &scons; builds. Like the &Export; function, - the &Import; function can be used + the &Import; function can be called with multiple variable names: Import('env', 'debug') -env = env.Clone(DEBUG = debug) +env = env.Clone(DEBUG=debug) env.Program('prog', ['prog.c']) + + + + In this example, we pull in the common &consenv; + env, and + use the value of the debug + variable to make a modified copy by passing + that to a &f-link-Clone; call. + + - And the &Import; function will similarly - split a string along white-space + The &Import; function will (like &Export;) + split a string containing white-space into separate variable names: Import('env debug') -env = env.Clone(DEBUG = debug) +env = env.Clone(DEBUG=debug) env.Program('prog', ['prog.c']) + &Import; prefers a local defintion to a global one, + so that if there is a global export of foo, + and the calling SConscript has + exported foo to this SConscript, + the import will find the foo + exported to this SConscript. + + + + + Lastly, as a special case, you may import all of the variables that have been exported by supplying an asterisk @@ -689,7 +741,7 @@ env.Program('prog', ['prog.c']) Import('*') -env = env.Clone(DEBUG = debug) +env = env.Clone(DEBUG=debug) env.Program('prog', ['prog.c']) @@ -713,13 +765,14 @@ env.Program('prog', ['prog.c']) &SConscript; file in some way. For example, suppose that you want to create one - library from source files - scattered throughout a number - of subsidiary &SConscript; files. - You can do this by using the &Return; + library from object files built by + several subsidiary &SConscript; files. + You can do this by using the &f-link-Return; function to return values from the subsidiary &SConscript; files - to the calling file. + to the calling file. Like &Import; and &Export;, + &Return; takes a string representation of the variable + name, not the variable name itself. @@ -727,8 +780,8 @@ env.Program('prog', ['prog.c']) If, for example, we have two subdirectories &foo; and &bar; - that should each contribute a source - file to a Library, + that should each contribute an object + file to a library, what we'd like to be able to do is collect the object files from the subsidiary &SConscript; calls @@ -770,7 +823,7 @@ void bar(void) { printf("bar/bar.c\n"); } We can do this by using the &Return; function in the - foo/SConscript file like this: + foo/SConscript file like this: @@ -780,7 +833,7 @@ void bar(void) { printf("bar/bar.c\n"); } (The corresponding - bar/SConscript + bar/SConscript file should be pretty obvious.) Then when we run &SCons;, the object files from the subsidiary subdirectories -- cgit v0.12 From b3f2e6671a3cfa34b9e73f2ca20eac1ef9d409a0 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sun, 26 Apr 2020 10:37:09 -0600 Subject: Exports doc fixes [ci skip] Fix a couple of typos discoverted by sider. Update doc entries in the (shared) function descriptions of Export, Import and Return (Environment.xml) Signed-off-by: Mats Wichmann --- doc/user/hierarchy.xml | 4 +- src/engine/SCons/Script/SConscript.xml | 82 +++++++++++++++++----------------- 2 files changed, 44 insertions(+), 42 deletions(-) diff --git a/doc/user/hierarchy.xml b/doc/user/hierarchy.xml index b54e2a5..11a68f9 100644 --- a/doc/user/hierarchy.xml +++ b/doc/user/hierarchy.xml @@ -563,7 +563,7 @@ Export('env', 'debug') - Beacuse a Python identifier cannot contain spaces, + Because a Python identifier cannot contain spaces, &Export; assumes a string containing spaces is multiple variable names to export and splits it for you: @@ -721,7 +721,7 @@ env.Program('prog', ['prog.c']) - &Import; prefers a local defintion to a global one, + &Import; prefers a local definition to a global one, so that if there is a global export of foo, and the calling SConscript has exported foo to this SConscript, diff --git a/src/engine/SCons/Script/SConscript.xml b/src/engine/SCons/Script/SConscript.xml index a1e0129..d42fdac 100644 --- a/src/engine/SCons/Script/SConscript.xml +++ b/src/engine/SCons/Script/SConscript.xml @@ -26,7 +26,7 @@ See its __doc__ string for a discussion of the format. -(targets) +(targets...) @@ -163,21 +163,23 @@ is used if no value is specified. -(vars) +([vars...], [key=value...]) -This tells -&scons; -to export a list of variables from the current -SConscript file to all other SConscript files. -The exported variables are kept in a global collection, -so subsequent calls to +Exports a list of variables from the current +SConscript file to a global collection where they can be +imported by any other SConscript file. +vars are keys used to +look up the value, so they must be +string represenations of the names of the variables +to be exported. +Subsequent calls to &f-Export; -will over-write previous exports that have the same name. +will over-write any previous exports that have the same name. Multiple variable names can be passed to &f-Export; -as separate arguments or as a list. +as separate arguments or as words in a space-separated string. Keyword arguments can be used to provide names and their values. A dictionary can be used to map variables to a different name when exported. Both local variables and global variables can be exported. @@ -214,7 +216,7 @@ function supports an argument that makes it easier to to export a variable or set of variables to a single SConscript file. See the description of the -&f-SConscript; +&f-link-SConscript; function, below. @@ -270,26 +272,25 @@ message. -(vars) +(vars...) -This tells -&scons; -to import a list of variables into the current SConscript file. This -will import variables that were exported with -&f-Export; -or in the +Imports a list of variables into the current SConscript file. +The variables must be string representations of variable +names which have been previously exported either by the +&f-link-Export; function or by the exports argument to &f-link-SConscript;. Variables exported by &f-SConscript; -have precedence. +take precedence. Multiple variable names can be passed to &f-Import; -as separate arguments or as a list. The variable "*" can be used -to import all variables. +as separate arguments or as words in a space-separated string. +The wildcard "*" can be used to import all +available variables. @@ -311,32 +312,35 @@ Import("*") -By default, -this stops processing the current SConscript -file and returns to the calling SConscript file -the values of the variables named in the +Return to the calling SConscript, optionally +returning the values of variables named in the vars string arguments. Multiple strings contaning variable names may be passed to -&f-Return;. -Any strings that contain white space +&f-Return;. A string containing white space +is split into words, which are considered individual +variable names. +Returns a tuple of values, or value that evaluates +False +if no vars were specified. +By default &Return; stops processing the current SConscript +and returns immediately. The optional stop= keyword argument may be set to a false value to continue processing the rest of the SConscript file after the &f-Return; -call. -This was the default behavior prior to SCons 0.98. +call (this was the default behavior prior to SCons 0.98.) However, the values returned are still the values of the variables in the named vars at the point &f-Return; -is called. +was called. @@ -434,17 +438,15 @@ SConscript(dirs=['sub1', 'sub2'], name='MySConscript') The optional exports -argument provides a list of variable names or a dictionary of -named values to export to the -script(s). -These variables are locally exported only to the specified -script(s), -and do not affect the global pool of variables used by the -&f-Export; +argument provides a list of string representations of +variable names or a dictionary of named values to export. +These variables are locally exported only to the called +SConscript files +and do not affect the global pool of variables managed by the +&f-link-Export; function. -The subsidiary -script(s) +The subsidiary SConscript files must use the &f-link-Import; function to import the variables. @@ -482,7 +484,7 @@ argument is interpreted relative to the directory of the calling file. See the description of the &f-VariantDir; -function below for additional details and restrictions. +function for additional details and restrictions. -- cgit v0.12 From d56a0181a1f095fcb01dd4d8039c6bb2d14d92cb Mon Sep 17 00:00:00 2001 From: James Benton Date: Mon, 6 Apr 2020 14:28:58 +0100 Subject: Add support for passing cppflags through to Visual Studio project generation. These flags can affect intellisense, for example if you are using C++17 you will have intellisense errors unless you set the appropriate CFLAGS to inform inform intellisense of the C++ version you are using. Additionally /Zc:__cplusplus is required for intellisense to recognise a provided /std:c++ switch, as it is not a usual build flag we must append it to the flags when we see /std:c++. For more information see the page on /Zc:__cplusplus: https://docs.microsoft.com/en-us/cpp/build/reference/zc-cplusplus --- src/CHANGES.txt | 8 ++++++ src/engine/SCons/Tool/msvs.py | 19 +++++++++++-- src/engine/SCons/Tool/msvs.xml | 19 +++++++++++++ src/engine/SCons/Tool/msvsTests.py | 57 +++++++++++++++++++++----------------- 4 files changed, 76 insertions(+), 27 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 643de92..6500a0f 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -115,6 +115,14 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Docbook builder provides a fallback if lxml fails to generate a document with tostring(). + From James Benton: + - Improve Visual Studio solution/project generation code to add support + for a per-variant cppflags. Intellisense can be affected by cppflags, + this is especially important when it comes to /std:c++* which specifies + what C++ standard version to target. SCons will append /Zc:__cplusplus + to the project's cppflags when a /std:c++* flag is found as this is + required for intellisense to use the C++ standard version from cppflags. + RELEASE 3.1.2 - Mon, 17 Dec 2019 02:06:27 +0000 diff --git a/src/engine/SCons/Tool/msvs.py b/src/engine/SCons/Tool/msvs.py index 7332b49..376d814 100644 --- a/src/engine/SCons/Tool/msvs.py +++ b/src/engine/SCons/Tool/msvs.py @@ -76,6 +76,13 @@ def processIncludes(includes, env, target, source): return [env.Dir(i).abspath for i in SCons.PathList.PathList(includes).subst_path(env, target, source)] +def processFlags(flags, env): + # If /std:c++XX is in flags then we need to ensure /Zc:__cplusplus is in + # flags to tell intellisense to respect our specified standard + if any(f.startswith('/std:c++') for f in flags) and \ + not any(f == '/Zc:__cplusplus' for f in flags): + flags.append('/Zc:__cplusplus') + return [env.subst(f) for f in flags] external_makefile_guid = '{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}' @@ -508,6 +515,10 @@ class _DSPGenerator(object): cpppaths = GetKeyFromEnv(env, 'cpppaths', variants) else: cpppaths = [env.get('CPPPATH', [])] * len(variants) + if 'cppflags' in env: + cppflags = GetKeyFromEnv(env, 'cppflags', variants) + else: + cppflags = [env.get('CCFLAGS', []) + env.get('CXXFLAGS', []) + env.get('CPPFLAGS', [])] * len(variants) self.env = env @@ -550,12 +561,13 @@ class _DSPGenerator(object): for n in sourcenames: self.sources[n].sort(key=lambda a: a.lower()) - def AddConfig(self, variant, buildtarget, outdir, runfile, cmdargs, cppdefines, cpppaths, dspfile=dspfile, env=env): + def AddConfig(self, variant, buildtarget, outdir, runfile, cmdargs, cppdefines, cpppaths, cppflags, dspfile=dspfile, env=env): config = Config() config.buildtarget = buildtarget config.outdir = outdir config.cmdargs = cmdargs config.cppdefines = cppdefines + config.cppflags = cppflags config.runfile = runfile # Dir objects can't be pickled, so we need an absolute path here. @@ -573,7 +585,7 @@ class _DSPGenerator(object): print("Adding '" + self.name + ' - ' + config.variant + '|' + config.platform + "' to '" + str(dspfile) + "'") for i in range(len(variants)): - AddConfig(self, variants[i], buildtarget[i], outdir[i], runfile[i], cmdargs[i], cppdefines[i], cpppaths[i]) + AddConfig(self, variants[i], buildtarget[i], outdir[i], runfile[i], cmdargs[i], cppdefines[i], cpppaths[i], cppflags[i]) seen = set() self.platforms = [p.platform for p in self.configs.values() @@ -1144,6 +1156,7 @@ V10DSPCommandLine = """\ \t\t$(NMakeForcedIncludes) \t\t$(NMakeAssemblySearchPath) \t\t$(NMakeForcedUsingAssemblies) +\t\t%(additionaloptions)s """ V15DSPHeader = """\ @@ -1243,6 +1256,7 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): cmdargs = self.configs[kind].cmdargs cpppaths = self.configs[kind].cpppaths cppdefines = self.configs[kind].cppdefines + cppflags = self.configs[kind].cppflags env_has_buildtarget = 'MSVSBUILDTARGET' in self.env if not env_has_buildtarget: @@ -1262,6 +1276,7 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): # assumes they don't. preprocdefs = xmlify(';'.join(processDefines(cppdefines))) includepath = xmlify(';'.join(processIncludes(cpppaths, self.env, None, None))) + additionaloptions = xmlify(' '.join(processFlags(cppflags, self.env))) if not env_has_buildtarget: del self.env['MSVSBUILDTARGET'] diff --git a/src/engine/SCons/Tool/msvs.xml b/src/engine/SCons/Tool/msvs.xml index f6c9a39..e6aa511 100644 --- a/src/engine/SCons/Tool/msvs.xml +++ b/src/engine/SCons/Tool/msvs.xml @@ -145,6 +145,25 @@ See its __doc__ string for a discussion of the format. + cppflags + + + Compiler flags for the different variants. + If a /std:c++ flag is found then /Zc:__cplusplus is + appended to the flags if not already found, this + ensures that intellisense uses the /std:c++ switch. + The number of cppflags entries + must match the number of variant + entries, or be empty (not specified). If you give + only one, it will automatically be propagated to all + variants. If you don't give this parameter, SCons + will combine the invoking environment's + CCFLAGS, CXXFLAGS, + CPPFLAGS entries for all variants. + + + + cpppaths diff --git a/src/engine/SCons/Tool/msvsTests.py b/src/engine/SCons/Tool/msvsTests.py index 1bacc2c..e1f098f 100644 --- a/src/engine/SCons/Tool/msvsTests.py +++ b/src/engine/SCons/Tool/msvsTests.py @@ -677,6 +677,9 @@ class msvsTestCase(unittest.TestCase): list_cppdefines = [['_A', '_B', 'C'], ['_B', '_C_'], ['D'], []] list_cpppaths = [[r'C:\test1'], [r'C:\test1;C:\test2'], [self.fs.Dir('subdir')], []] + list_cppflags = [['/std:c++17', '/Zc:__cplusplus'], + ['/std:c++14', '/Zc:__cplusplus'], + ['/std:c++11', '/Zc:__cplusplus'], []] def TestParamsFromList(test_variant, test_list): """ @@ -716,36 +719,39 @@ class msvsTestCase(unittest.TestCase): tests_cmdargs = TestParamsFromList(list_variant, list_cmdargs) tests_cppdefines = TestParamsFromList(list_variant, list_cppdefines) tests_cpppaths = TestParamsFromList(list_variant, list_cpppaths) + tests_cppflags = TestParamsFromList(list_variant, list_cppflags) # Run the test for each test case for param_cmdargs, expected_cmdargs in tests_cmdargs: for param_cppdefines, expected_cppdefines in tests_cppdefines: for param_cpppaths, expected_cpppaths in tests_cpppaths: - debug('Testing %s. with :\n variant = %s \n cmdargs = "%s" \n cppdefines = "%s" \n cpppaths = "%s"' % \ - (str_function_test, list_variant, param_cmdargs, param_cppdefines, param_cpppaths)) - param_configs = [] - expected_configs = {} - for platform in ['Win32', 'x64']: - for variant in ['Debug', 'Release']: - variant_platform = '%s|%s' % (variant, platform) - runfile = '%s\\%s\\test.exe' % (platform, variant) - buildtarget = '%s\\%s\\test.exe' % (platform, variant) - outdir = '%s\\%s' % (platform, variant) - - # Create parameter list for this variant_platform - param_configs.append([variant_platform, runfile, buildtarget, outdir]) - - # Create expected dictionary result for this variant_platform - expected_configs[variant_platform] = { - 'variant': variant, - 'platform': platform, - 'runfile': runfile, - 'buildtarget': buildtarget, - 'outdir': outdir, - 'cmdargs': expected_cmdargs[variant_platform], - 'cppdefines': expected_cppdefines[variant_platform], - 'cpppaths': expected_cpppaths[variant_platform], - } + for param_cppflags, expected_cppflags in tests_cppflags: + print('Testing %s. with :\n variant = %s \n cmdargs = "%s" \n cppdefines = "%s" \n cpppaths = "%s" \n cppflags = "%s"' % \ + (str_function_test, list_variant, param_cmdargs, param_cppdefines, param_cpppaths, param_cppflags)) + param_configs = [] + expected_configs = {} + for platform in ['Win32', 'x64']: + for variant in ['Debug', 'Release']: + variant_platform = '%s|%s' % (variant, platform) + runfile = '%s\\%s\\test.exe' % (platform, variant) + buildtarget = '%s\\%s\\test.exe' % (platform, variant) + outdir = '%s\\%s' % (platform, variant) + + # Create parameter list for this variant_platform + param_configs.append([variant_platform, runfile, buildtarget, outdir]) + + # Create expected dictionary result for this variant_platform + expected_configs[variant_platform] = { + 'variant': variant, + 'platform': platform, + 'runfile': runfile, + 'buildtarget': buildtarget, + 'outdir': outdir, + 'cmdargs': expected_cmdargs[variant_platform], + 'cppdefines': expected_cppdefines[variant_platform], + 'cpppaths': expected_cpppaths[variant_platform], + 'cppflags': expected_cppflags[variant_platform], + } # Create parameter environment with final parameter dictionary param_dict = dict(list(zip(('variant', 'runfile', 'buildtarget', 'outdir'), @@ -753,6 +759,7 @@ class msvsTestCase(unittest.TestCase): param_dict['cmdargs'] = param_cmdargs param_dict['cppdefines'] = param_cppdefines param_dict['cpppaths'] = param_cpppaths + param_dict['cppflags'] = param_cppflags # Hack to be able to run the test with a 'DummyEnv' class _DummyEnv(DummyEnv): -- cgit v0.12 From 163e83e856edb4eb420fe103f1337b52fff05ae8 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Tue, 28 Apr 2020 08:15:27 -0600 Subject: docs: tweak Export wording a bit more [ci skip] Be more clear in response to a review comment. Signed-off-by: Mats Wichmann --- doc/user/hierarchy.xml | 69 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 25 deletions(-) diff --git a/doc/user/hierarchy.xml b/doc/user/hierarchy.xml index 11a68f9..92639cf 100644 --- a/doc/user/hierarchy.xml +++ b/doc/user/hierarchy.xml @@ -2,7 +2,7 @@ %scons; - + %builders-mod; @@ -11,7 +11,7 @@ %tools-mod; %variables-mod; - + ]> export variables from an &SConscript; file - so they can be imported by other + so they can be imported by other &SConscript; files, thus allowing you to share common initialized values throughout your build hierarchy. @@ -537,10 +537,9 @@ x There are two ways to export a variable from an &SConscript; file. The first way is to call the &f-link-Export; function. - &Export; takes one or more arguments that are - string representations of the variable names - that is, - to export the variable env, - you supply the string env to &Export;: + &Export; is pretty flexible - in the simplest form, + you pass it a string that represents the name of + the variable, and &Export; stores that with its value: @@ -564,22 +563,42 @@ Export('env', 'debug') Because a Python identifier cannot contain spaces, - &Export; assumes a string containing spaces is multiple - variable names to export and splits it for you: + &Export; assumes a string containing spaces is is a + shortcut for multiple variable names to export and + splits it up for you: +env = Environment() +debug = ARGUMENTS['debug'] Export('env debug') + You can also pass &Export; a dictionary of values. + This form allows the opportunity to export a variable + from the current scope under a different name - + in this example, the value of foo + is exported under the name "bar": + + +env = Environment() +foo = "FOO" +args = {"env": env, "bar": foo} +Export(args) + + + + + + &Export; will also accept arguments in keyword style. - This style can be used, for example, to set variables - that have not been set by name in the SConscript file, - and thus the keys are the intended variable names, - not a string representation: + This form adds the ability to create exported variables + that have not actually been set locally in the SConscript file. + When used this way, the key is the intended variable name, + not a string representation as with the other forms: @@ -589,7 +608,7 @@ Export(MODE="DEBUG", TARGET="arm") - The styles can be mixed, however note that Python function calling + The styles can be mixed, though Python function calling syntax requires all non-keyword arguments to precede any keyword arguments in the call. @@ -599,10 +618,10 @@ Export(MODE="DEBUG", TARGET="arm") The &Export; function adds the variables to a global location from which other &SConscript; files can import. - Exporting conceptually works the same as Python assignment - statements - if you assign a name to something, then later assign - the same name to something else, the reference to the original - is lost. + Calls to &Export; are cumulative. When you call &Export; + you are actually updating a Python dictionary, so it + is fine to export a variable you have already exported, + but when doing so, the previoue value is lost. @@ -620,7 +639,7 @@ SConscript('src/SConscript', 'env') - Or (preferably, for readability) as the &exports; keyword argument: + Or (preferably, for readability) using the &exports; keyword argument: @@ -631,8 +650,8 @@ SConscript('src/SConscript', exports='env') These calls export the specified variables - to only the listed &SConscript; file. - You may, however, specify more than one + to only the listed &SConscript; file(s). + You may specify more than one &SConscript; file in a list: @@ -672,7 +691,7 @@ env.Program('prog', ['prog.c']) - The &Import; call makes the previously defined env + The &Import; call makes the previously defined env variable available to the &SConscript; file. Assuming env is a &consenv;, after import it can be used to build programs, libraries, etc. @@ -694,7 +713,7 @@ Import('env', 'debug') env = env.Clone(DEBUG=debug) env.Program('prog', ['prog.c']) - + In this example, we pull in the common &consenv; @@ -725,7 +744,7 @@ env.Program('prog', ['prog.c']) so that if there is a global export of foo, and the calling SConscript has exported foo to this SConscript, - the import will find the foo + the import will find the foo exported to this SConscript. @@ -749,7 +768,7 @@ env.Program('prog', ['prog.c']) If you're dealing with a lot of &SConscript; files, this can be a lot simpler than keeping - arbitrary lists of imported variables in each file. + arbitrary lists of imported variables up to date in each file. -- cgit v0.12 From aaf6595eba0f393fe474b42fda7360b734ae590e Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Tue, 28 Apr 2020 10:27:20 -0600 Subject: docs: tweak "manpage" (shared) Return, SConscript [ci skip] After previous updates, the manpage part (also shared to the userguide) was a little less precise than it could be. SConscript definition now describes the return value more accurately (e.g. add what happens if multiple scripts called) and moved to its own paragraph (at end) rather than inline. Signed-off-by: Mats Wichmann --- src/engine/SCons/Script/SConscript.xml | 177 ++++++++++++++++----------------- 1 file changed, 83 insertions(+), 94 deletions(-) diff --git a/src/engine/SCons/Script/SConscript.xml b/src/engine/SCons/Script/SConscript.xml index d42fdac..8a6a928 100644 --- a/src/engine/SCons/Script/SConscript.xml +++ b/src/engine/SCons/Script/SConscript.xml @@ -167,21 +167,22 @@ is used if no value is specified. -Exports a list of variables from the current +Exports variables from the current SConscript file to a global collection where they can be -imported by any other SConscript file. -vars are keys used to -look up the value, so they must be -string represenations of the names of the variables -to be exported. -Subsequent calls to -&f-Export; -will over-write any previous exports that have the same name. -Multiple variable names can be passed to -&f-Export; -as separate arguments or as words in a space-separated string. +imported by other SConscript files. +vars may be one or more +strings representing variable names to be exported. +If a string contains whitespace, it is split into +separate strings, as if multiple string arguments +had been given. A vars argument +may also be a dictionary, which can be used to map variables +to different names when exported. Keyword arguments can be used to provide names and their values. -A dictionary can be used to map variables to a different name when exported. + + + +&f-Export; calls are cumulative. Specifying a previously +exported variable will overwirte the earlier value. Both local variables and global variables can be exported. @@ -202,22 +203,19 @@ Export("env", "package") Export(["env", "package"]) # Make env available using the name debug: -Export(debug = env) +Export(debug=env) # Make env available using the name debug: -Export({"debug":env}) +Export({"debug": env}) Note that the -&f-SConscript; -function supports an -exports -argument that makes it easier to to export a variable or -set of variables to a single SConscript file. -See the description of the &f-link-SConscript; -function, below. +function supports an &exports; +argument that allows exporting a variable or +set of variables to a specific SConscript file or files. +See the description below. @@ -276,12 +274,12 @@ message. -Imports a list of variables into the current SConscript file. -The variables must be string representations of variable -names which have been previously exported either by the +Imports variables into the current SConscript file. +vars +must be strings representating names of variables +which have been previously exported either by the &f-link-Export; function or by the -exports -argument to +&exports; argument to &f-link-SConscript;. Variables exported by &f-SConscript; @@ -308,29 +306,29 @@ Import("*") -([vars..., stop=]) +([vars..., stop=True]) Return to the calling SConscript, optionally -returning the values of variables named in the -vars -string arguments. +returning the values of variables named in +vars. Multiple strings contaning variable names may be passed to &f-Return;. A string containing white space -is split into words, which are considered individual -variable names. -Returns a tuple of values, or value that evaluates -False -if no vars were specified. +is split into individual variable names. +Returns the value if one variable is specified, +else returns a tuple of values. +Returns an empty tuple if vars +is omitted. By default &Return; stops processing the current SConscript and returns immediately. The optional -stop= -keyword argument may be set to a false value +stop +keyword argument +may be set to a false value to continue processing the rest of the SConscript file after the &f-Return; @@ -348,7 +346,7 @@ Examples: -# Returns without returning a value. +# Returns no values (evaluates False) Return() # Returns the value of the 'foo' Python variable. @@ -374,22 +372,13 @@ Return('val1 val2') -This tells -&scons; -to execute -one or more subsidiary SConscript (configuration) files. -Any variables returned by a called script using -&f-link-Return; -will be returned by the call to -&f-SConscript;. +Execute one or more subsidiary SConscript (configuration) files. There are two ways to call the -&f-SConscript; -function. +&f-SConscript; function. -The first way you can call -&f-SConscript; +The first calling style is to explicitly specify one or more scripts as the first argument. @@ -408,22 +397,22 @@ config = SConscript('MyConfig.py') -The second way you can call +The second way to call &f-SConscript; is to specify a list of (sub)directory names as a -dirs=subdirs +dirs=subdirs keyword argument. In this case, &scons; -will, by default, +will execute a subsidiary configuration file named &SConscript; in each of the specified directories. You may specify a name other than &SConscript; by supplying an optional -name=script +name=script keyword argument. The first three examples below have the same effect as the first three examples above: @@ -438,10 +427,10 @@ SConscript(dirs=['sub1', 'sub2'], name='MySConscript') The optional exports -argument provides a list of string representations of -variable names or a dictionary of named values to export. +argument provides a string or list of strings representing +variable names, or a dictionary of named values, to export. These variables are locally exported only to the called -SConscript files +SConscript file(s) and do not affect the global pool of variables managed by the &f-link-Export; function. @@ -463,49 +452,34 @@ SConscript(dirs=['one', 'two', 'three'], exports='shared_info') If the optional variant_dir argument is present, it causes an effect equivalent to the -&f-link-VariantDir; -method described below. -(If -variant_dir -is not present, the - -duplicate - -argument is ignored.) -The -variant_dir - +&f-link-VariantDir; function. +The variant_dir argument is interpreted relative to the directory of the calling -&SConscript; -file. -See the description of the -&f-VariantDir; -function for additional details and restrictions. +SConscript file. +The optional +duplicate argument is +interpreted as for &f-link-VariantDir;. +If variant_dir +is omitted, the duplicate argument is ignored. +See the description of +&f-link-VariantDir; +below for additional details and restrictions. If variant_dir is present, - the source directory is the directory in which the -&SConscript; +SConscript file resides and the -&SConscript; +SConscript file is evaluated as if it were in the variant_dir directory: -SConscript('src/SConscript', variant_dir = 'build') +SConscript('src/SConscript', variant_dir='build') @@ -524,7 +498,7 @@ in the same directory as the -SConscript('SConscript', variant_dir = 'build') +SConscript('SConscript', variant_dir='build') @@ -570,14 +544,17 @@ TODO??? SConscript('build/SConscript', src_dir='src') -The optional +If the optional must_exist -argument, if true, causes an exception to be raised if a requested -&SConscript; file is not found. The current default is false, -causing only a warning to be omitted, but this behavior is deprecated. +is True, +causes an exception to be raised if a requested +SConscript file is not found. The current default is +False, +causing only a warning to be emitted, but this default is deprecated +(since 3.1). For scripts which truly intend to be optional, transition to -explicty supplying -must_exist=False to the call. +explicitly supplying +must_exist=False to the &f-SConscript; call. @@ -613,6 +590,18 @@ SConscript('doc/SConscript', variant_dir='build/doc', duplicate=0) SConscript('src/SConscript', variant_dir='build/x86', duplicate=0) SConscript('src/SConscript', variant_dir='build/ppc', duplicate=0) + + +&f-SConscript; returns the values of any variables +named by the executed SConscript(s) in arguments +to the &f-link-Return; function (see above for details). +If a single &f-SConscript; call causes multiple scripts to +be executed, the return value is a tuple containing +the returns of all of the scripts. If an executed +script does not explicitly call &Return;, it returns +None. + + -- cgit v0.12 From 7114b9c214e14ea40c12c47f0799e92feaa9d817 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Tue, 28 Apr 2020 10:37:52 -0600 Subject: docs: fix typos from sider Signed-off-by: Mats Wichmann --- doc/user/hierarchy.xml | 2 +- src/engine/SCons/Script/SConscript.xml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/user/hierarchy.xml b/doc/user/hierarchy.xml index 92639cf..ec1864c 100644 --- a/doc/user/hierarchy.xml +++ b/doc/user/hierarchy.xml @@ -621,7 +621,7 @@ Export(MODE="DEBUG", TARGET="arm") Calls to &Export; are cumulative. When you call &Export; you are actually updating a Python dictionary, so it is fine to export a variable you have already exported, - but when doing so, the previoue value is lost. + but when doing so, the previous value is lost. diff --git a/src/engine/SCons/Script/SConscript.xml b/src/engine/SCons/Script/SConscript.xml index 8a6a928..8b88dca 100644 --- a/src/engine/SCons/Script/SConscript.xml +++ b/src/engine/SCons/Script/SConscript.xml @@ -182,7 +182,7 @@ Keyword arguments can be used to provide names and their values. &f-Export; calls are cumulative. Specifying a previously -exported variable will overwirte the earlier value. +exported variable will overwrite the earlier value. Both local variables and global variables can be exported. @@ -276,7 +276,7 @@ message. Imports variables into the current SConscript file. vars -must be strings representating names of variables +must be strings representing names of variables which have been previously exported either by the &f-link-Export; function or by the &exports; argument to -- cgit v0.12 From 40b4f08cf3c61870761f015fb2db8e3606d0b656 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 28 Apr 2020 20:03:49 -0700 Subject: [ci skip] Bump version --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 614303c..e4cee9d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = SCons -version=3.9.9a991 +version=3.9.9a992 license = MIT author = William Deegan author_email =bill@baddogconsulting.com -- cgit v0.12 From fa5d94516ebe9e0f73049ed07db3d729f70e3d63 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 28 Apr 2020 20:06:04 -0700 Subject: [ci skip] Reorder contributors in CHANGES.txt to be alpha by last name --- src/CHANGES.txt | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 6500a0f..7712902 100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -10,6 +10,14 @@ NOTE: Please include a reference to any Issues resolved by your changes in the b RELEASE VERSION/DATE TO BE FILLED IN LATER + From James Benton: + - Improve Visual Studio solution/project generation code to add support + for a per-variant cppflags. Intellisense can be affected by cppflags, + this is especially important when it comes to /std:c++* which specifies + what C++ standard version to target. SCons will append /Zc:__cplusplus + to the project's cppflags when a /std:c++* flag is found as this is + required for intellisense to use the C++ standard version from cppflags. + From Rob Boehne - Specify UTF-8 encoding when opening Java source file as text. By default, encoding is the output of locale.getpreferredencoding(False), and varies by platform. @@ -115,13 +123,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Docbook builder provides a fallback if lxml fails to generate a document with tostring(). - From James Benton: - - Improve Visual Studio solution/project generation code to add support - for a per-variant cppflags. Intellisense can be affected by cppflags, - this is especially important when it comes to /std:c++* which specifies - what C++ standard version to target. SCons will append /Zc:__cplusplus - to the project's cppflags when a /std:c++* flag is found as this is - required for intellisense to use the C++ standard version from cppflags. + RELEASE 3.1.2 - Mon, 17 Dec 2019 02:06:27 +0000 -- cgit v0.12 From 54352952b9cd900091d3bcc50a82028a36f184f1 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 28 Apr 2020 20:06:34 -0700 Subject: [ci skip] minor reformatting --- src/engine/SCons/Tool/msvs.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/engine/SCons/Tool/msvs.py b/src/engine/SCons/Tool/msvs.py index 376d814..e5c9bd0 100644 --- a/src/engine/SCons/Tool/msvs.py +++ b/src/engine/SCons/Tool/msvs.py @@ -67,6 +67,7 @@ def xmlify(s): s = s.replace('\n', ' ') return s + def processIncludes(includes, env, target, source): """ Process a CPPPATH list in includes, given the env, target and source. @@ -76,16 +77,21 @@ def processIncludes(includes, env, target, source): return [env.Dir(i).abspath for i in SCons.PathList.PathList(includes).subst_path(env, target, source)] + def processFlags(flags, env): - # If /std:c++XX is in flags then we need to ensure /Zc:__cplusplus is in - # flags to tell intellisense to respect our specified standard + """ + If /std:c++XX is in flags then we need to ensure /Zc:__cplusplus is in + flags to tell intellisense to respect our specified standard + """ if any(f.startswith('/std:c++') for f in flags) and \ not any(f == '/Zc:__cplusplus' for f in flags): flags.append('/Zc:__cplusplus') return [env.subst(f) for f in flags] + external_makefile_guid = '{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}' + def _generateGUID(slnfile, name): """This generates a dummy GUID for the sln file to use. It is based on the MD5 signatures of the sln filename plus the name of @@ -101,8 +107,10 @@ def _generateGUID(slnfile, name): solution = "{" + solution[:8] + "-" + solution[8:12] + "-" + solution[12:16] + "-" + solution[16:20] + "-" + solution[20:32] + "}" return solution + version_re = re.compile(r'(\d+\.\d+)(.*)') + def msvs_parse_version(s): """ Split a Visual Studio version, which may in fact be something like -- cgit v0.12 From d51ce52175bbce59b87eae7a09489f3433262f55 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Wed, 29 Apr 2020 07:23:02 -0600 Subject: tests: use unittest decorator for skipping FSTests updated to use the suggested way of skipping tests - a decorator which does the check up front, rather than a manual check inside the function. Effect: test run will show 's' rather than '-' on skipped tests. Signed-off-by: Mats Wichmann --- src/engine/SCons/Node/FSTests.py | 48 ++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index 3f2cb0e..b2014cb 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -707,26 +707,27 @@ class BaseTestCase(_tempdirTestCase): nonexistent = fs.Entry('nonexistent') assert not nonexistent.isfile() - if sys.platform != 'win32' and hasattr(os, 'symlink'): - def test_islink(self): - """Test the Base.islink() method""" - test = self.test - test.subdir('dir') - test.write("file", "file\n") - test.symlink("symlink", "symlink") - fs = SCons.Node.FS.FS() + @unittest.skipUnless(sys.platform != 'win32' and hasattr(os, 'symlink'), + "symlink is not used on Windows") + def test_islink(self): + """Test the Base.islink() method""" + test = self.test + test.subdir('dir') + test.write("file", "file\n") + test.symlink("symlink", "symlink") + fs = SCons.Node.FS.FS() - dir = fs.Entry('dir') - assert not dir.islink() + dir = fs.Entry('dir') + assert not dir.islink() - file = fs.Entry('file') - assert not file.islink() + file = fs.Entry('file') + assert not file.islink() - symlink = fs.Entry('symlink') - assert symlink.islink() + symlink = fs.Entry('symlink') + assert symlink.islink() - nonexistent = fs.Entry('nonexistent') - assert not nonexistent.islink() + nonexistent = fs.Entry('nonexistent') + assert not nonexistent.islink() class DirNodeInfoTestCase(_tempdirTestCase): @@ -1339,13 +1340,15 @@ class FSTestCase(_tempdirTestCase): # get_contents() returns the binary contents. test.write("binary_file", "Foo\x1aBar") f1 = fs.File(test.workpath("binary_file")) - assert f1.get_contents() == bytearray("Foo\x1aBar", 'utf-8'), f1.get_contents() + assert f1.get_contents() == bytearray("Foo\x1aBar", 'utf-8'), \ + f1.get_contents() # This tests to make sure we can decode UTF-8 text files. test_string = "Foo\x1aBar" test.write("utf8_file", test_string.encode('utf-8')) f1 = fs.File(test.workpath("utf8_file")) - f1.get_text_contents() == "Foo\x1aBar", f1.get_text_contents() + assert f1.get_text_contents() == "Foo\x1aBar", \ + f1.get_text_contents() # Check for string which doesn't have BOM and isn't valid # ASCII @@ -1846,10 +1849,9 @@ class FSTestCase(_tempdirTestCase): d = root._lookup_abs('/tmp/foo-nonexistent/nonexistent-dir', SCons.Node.FS.Dir) assert d.__class__ == SCons.Node.FS.Dir, str(d.__class__) + @unittest.skipUnless(sys.platform == "win32", "requires Windows") def test_lookup_uncpath(self): """Testing looking up a UNC path on Windows""" - if sys.platform not in ('win32',): - return test = self.test fs = self.fs path = '//servername/C$/foo' @@ -1859,19 +1861,17 @@ class FSTestCase(_tempdirTestCase): assert str(f) == r'\\servername\C$\foo', \ 'UNC path %s got looked up as %s' % (path, f) + @unittest.skipUnless(sys.platform.startswith == "win32", "requires Windows") def test_unc_drive_letter(self): """Test drive-letter lookup for windows UNC-style directories""" - if sys.platform not in ('win32',): - return share = self.fs.Dir(r'\\SERVER\SHARE\Directory') assert str(share) == r'\\SERVER\SHARE\Directory', str(share) + @unittest.skipUnless(sys.platform == "win32", "requires Windows") def test_UNC_dirs_2689(self): """Test some UNC dirs that printed incorrectly and/or caused infinite recursion errors prior to r5180 (SCons 2.1).""" fs = self.fs - if sys.platform not in ('win32',): - return p = fs.Dir(r"\\computername\sharename").get_abspath() assert p == r"\\computername\sharename", p p = fs.Dir(r"\\\computername\sharename").get_abspath() -- cgit v0.12