diff options
37 files changed, 791 insertions, 693 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index 08fdd34..03692d6 100755 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -107,11 +107,14 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Small refactor of scons daemons using a shared StateInfo class for communication between the scons interactive thread and the http server thread. Added error handling for scons interactive failing to startup. - - Added SHELL_ENV_GENERATOR construction variables. This variable allows the user to Define - a function which will be called to generate or alter the execution environment which will - be used in the shell command of some Action. - Ninja: Updated ninja scons daemon scripts to output errors to stderr as well as the daemon log. - Ninja: Fix typo in ninja scons daemon startup which causes ConnectionRefusedError to not retry + - Added SHELL_ENV_GENERATORS construction variable. This variable should be set to a list + (or an iterable) which contains functions to be called in order + when constructing the execution environment (Generally this is the shell environment + variables). This allows the user to customize how (for example) PATH is constructed. + Note that these are called for every build command run by SCons. It could have considerable + performance impact if not used carefully. to connect to the server during start up. From Mats Wichmann: @@ -157,6 +160,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Restore the ability of the content-timestamp decider to see that a a source which is a symlink has changed if the file-system target of that link has been modified (issue #3880) + - Modernize a few tests that use now-deprecated unittest.getTestCaseNames + and unittest.makeSuite - Python itself suggests the replacements. From Zhichang Yu: - Added MSVC_USE_SCRIPT_ARGS variable to pass arguments to MSVC_USE_SCRIPT. diff --git a/RELEASE.txt b/RELEASE.txt index 832698d..cfa8afc 100755 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -16,9 +16,12 @@ NEW FUNCTIONALITY - Added MSVC_USE_SCRIPT_ARGS variable to pass arguments to MSVC_USE_SCRIPT. - Added Configure.CheckMember() checker to check if struct/class has the specified member. -- Added SHELL_ENV_GENERATOR construction variables. This variable allows the user to Define - a function which will be called to generate or alter the execution environment which will - be used in the shell command of some Action. +- Added SHELL_ENV_GENERATORS construction variable. This variable should be set to a list + (or an iterable) which contains functions to be called in order + when constructing the execution environment (Generally this is the shell environment + variables). This allows the user to customize how (for example) PATH is constructed. + Note that these are called for every build command run by SCons. It could have considerable + performance impact if not used carefully. - Added MSVC_USE_SETTINGS variable to pass a dictionary to configure the msvc compiler system environment as an alternative to bypassing Visual Studio autodetection entirely. diff --git a/SCons/Action.py b/SCons/Action.py index 0849178..6e67c7f 100644 --- a/SCons/Action.py +++ b/SCons/Action.py @@ -732,7 +732,7 @@ def _string_from_cmd_list(cmd_list): default_ENV = None -def get_default_ENV(env, target=None, source=None): +def get_default_ENV(env): """ A fiddlin' little function that has an 'import SCons.Environment' which can't be moved to the top level without creating an import loop. Since @@ -755,6 +755,29 @@ def get_default_ENV(env, target=None, source=None): return default_ENV +def _resolve_shell_env(env, target, source): + """ + First get default environment. + Then if SHELL_ENV_GENERATORS is set and is iterable, + call each callable in that list to allow it to alter + the created execution environment. + """ + ENV = get_default_ENV(env) + shell_gen = env.get('SHELL_ENV_GENERATORS') + if shell_gen: + try: + shell_gens = iter(shell_gen) + except TypeError: + raise SCons.Errors.UserError("SHELL_ENV_GENERATORS must be iteratable.") + else: + ENV = ENV.copy() + for generator in shell_gens: + ENV = generator(env, target, source, ENV) + if not isinstance(ENV, dict): + raise SCons.Errors.UserError(f"SHELL_ENV_GENERATORS function: {generator} must return a dict.") + return ENV + + def _subproc(scons_env, cmd, error='ignore', **kw): """Wrapper for subprocess which pulls from construction env. @@ -924,10 +947,9 @@ class CommandAction(_ActionAction): escape = env.get('ESCAPE', lambda x: x) - ENV = env.get('SHELL_ENV_GENERATOR', get_default_ENV)(env, target, source) + ENV = _resolve_shell_env(env, target, source) # Ensure that the ENV values are all strings: - for key, value in ENV.items(): if not is_String(value): if is_List(value): diff --git a/SCons/Action.xml b/SCons/Action.xml index 2c18d55..1346db2 100644 --- a/SCons/Action.xml +++ b/SCons/Action.xml @@ -200,18 +200,32 @@ in which the command should be executed. </summary> </cvar> -<cvar name="SHELL_ENV_GENERATOR"> +<cvar name="SHELL_ENV_GENERATORS"> <summary> <para> -A function to generate or alter the environment dictionary which will be used -when executing the &cv-link-SPAWN; function. This primarily give the -user a chance to customize the execution environment for particular Actions. -It must return a dictionary containing the environment variables as -keys and the values as values. +Must be a list (or an iterable) containing functions where each function generates or +alters the environment dictionary which will be used +when executing the &cv-link-SPAWN; function. The functions will initially +be passed a reference of the current execution environment (e.g. env['ENV']), +and each called while iterating the list. Each function must return a dictionary +which will then be passed to the next function iterated. The return dictionary +should contain keys which represent the environment variables and their respective +values. + +This primary purpose of this construction variable is to give the user the ability +to substitute execution environment variables based on env, targets, and sources. +If desired, the user can completely customize the execution environment for particular +targets. </para> <example_commands> -def custom_shell_env(env, target, source): +def custom_shell_env(env, target, source, shell_env): + """customize shell_env if desired""" + if str(target[0]) == 'special_target': + shell_env['SPECIAL_VAR'] = env.subst('SOME_VAR', target=target, source=source) + return shell_env + +env["SHELL_ENV_GENERATORS"] = [custom_shell_env] </example_commands> <para> @@ -223,10 +237,15 @@ execution environment can be derived from. <varname>target</varname> The list of targets associated with this action. </para> - <para> + <para> <varname>source</varname> The list of sources associated with this action. </para> + <para> + <varname>shell_env</varname> +The current shell_env after iterating other SHELL_ENV_GENERATORS functions. This can be compared +to the passed env['ENV'] to detect any changes. + </para> </summary> </cvar> diff --git a/SCons/Environment.xml b/SCons/Environment.xml index 3a6df97..5c4326c 100644 --- a/SCons/Environment.xml +++ b/SCons/Environment.xml @@ -318,7 +318,7 @@ Added methods propagate through &f-env-Clone; calls. </para> <para> -Examples: +More examples: </para> <example_commands> @@ -3416,42 +3416,41 @@ env.UpdateValue(target = Value(output), source = Value(input)) </arguments> <summary> <para> -Sets up an alternate build location. -When building in the <parameter>variant_dir</parameter>, -&SCons; backfills as needed with files from <parameter>src_dir</parameter> -to create a complete build directory. +Sets up a mapping to define a variant build directory in +<parameter>variant_dir</parameter>. +<parameter>src_dir</parameter> may not be underneath +<parameter>variant_dir</parameter>. +A &f-VariantDir; mapping is global, even if called using the +&f-env-VariantDir; form. &f-VariantDir; can be called multiple times with the same <parameter>src_dir</parameter> -to set up multiple builds with different options -(<emphasis>variants</emphasis>). +to set up multiple variant builds with different options. </para> <para> -The -<parameter>variant</parameter> -location must be in or underneath the project top directory, -and <parameter>src_dir</parameter> -may not be underneath -<parameter>variant_dir</parameter>. +Note if <parameter>variant_dir</parameter> +is not under the project top directory, +target selection rules will not pick targets in the +variant directory unless they are explicitly specified. </para> <para> +When files in <parameter>variant_dir</parameter> are referenced, +&SCons; backfills as needed with files from <parameter>src_dir</parameter> +to create a complete build directory. By default, &SCons; -physically duplicates the source files and SConscript files -as needed into 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 +physically duplicates the source files, SConscript files, +and directory structure as needed into the variant directory. +Thus, a build performed in the variant directory is guaranteed to be identical +to a build performed in the source directory even if intermediate source files are generated during the build, or if preprocessors or other scanners search for included files -relative to the source file, +using paths relative to the source file, or if individual compilers or other invoked tools are hard-coded to put derived files in the same directory as source files. Only the files &SCons; calculates are needed for the build are duplicated into <parameter>variant_dir</parameter>. -</para> - -<para> If possible on the platform, the duplication is performed by linking rather than copying. This behavior is affected by the @@ -3470,44 +3469,46 @@ to invoke Builders using the path names of source files in <parameter>src_dir</parameter> and the path names of derived files within <parameter>variant_dir</parameter>. -This is more efficient than -<literal>duplicate=True</literal>, +This is more efficient than duplicating, and is safe for most builds; -revert to <constant>True</constant> +revert to <literal>duplicate=True</literal> if it causes problems. </para> <para> &f-VariantDir; -works most naturally with used with a subsidiary SConscript file. -The subsidiary SConscript file is called as if it -were in +works most naturally when used with a subsidiary SConscript file. +The subsidiary SConscript file must be called as if it were in <parameter>variant_dir</parameter>, regardless of the value of <parameter>duplicate</parameter>. -This is how you tell -&scons; -which variant of a source tree to build: +When calling an SConscript file, you can use the +<parameter>exports</parameter> keyword argument +to pass parameters (individually or as an appropriately set up environment) +so the SConscript can pick up the right settings for that variant build. +The SConscript must &f-link-Import; these to use them. Example: </para> <example_commands> +env1 = Environment(...settings for variant1...) +env2 = Environment(...settings for variant2...) + # run src/SConscript in two variant directories VariantDir('build/variant1', 'src') -SConscript('build/variant1/SConscript') +SConscript('build/variant1/SConscript', exports={"env": env1}) VariantDir('build/variant2', 'src') -SConscript('build/variant2/SConscript') +SConscript('build/variant2/SConscript', exports={"env": env2}) </example_commands> <para> See also the -&f-link-SConscript; -function, described above, +&f-link-SConscript; function for another way to specify a variant directory in conjunction with calling a subsidiary SConscript file. </para> <para> -Examples: +More examples: </para> <example_commands> diff --git a/SCons/Scanner/ScannerTests.py b/SCons/Scanner/ScannerTests.py index 68332a0..b9cb209 100644 --- a/SCons/Scanner/ScannerTests.py +++ b/SCons/Scanner/ScannerTests.py @@ -621,7 +621,9 @@ def suite(): ClassicCPPTestCase, ] for tclass in tclasses: - names = unittest.getTestCaseNames(tclass, 'test_') + loader = unittest.TestLoader() + loader.testMethodPrefix = 'test_' + names = loader.getTestCaseNames(tclass) suite.addTests(list(map(tclass, names))) return suite diff --git a/SCons/Script/SConscript.xml b/SCons/Script/SConscript.xml index 3c5b907..eb52acc 100644 --- a/SCons/Script/SConscript.xml +++ b/SCons/Script/SConscript.xml @@ -363,42 +363,38 @@ Return('val1 val2') <!-- (scripts, [exports, variant_dir, src_dir, duplicate, must_exist]) --> </arguments> <arguments> -(dirs=subdirs, [name=script, exports, variant_dir, duplicate, must_exist]) -<!-- (dirs=subdirs, [name=script, exports, variant_dir, src_dir, duplicate, must_exist]) --> +(dirs=subdirs, [name=scriptname, exports, variant_dir, duplicate, must_exist]) +<!-- (dirs=subdirs, [name=scriptname, exports, variant_dir, src_dir, duplicate, must_exist]) --> </arguments> <summary> <para> -Execute one or more subsidiary SConscript (configuration) files. +Executes one or more subsidiary SConscript (configuration) files. There are two ways to call the &f-SConscript; function. </para> <para> -The first calling style -is to explicitly specify one or more -<varname>scripts</varname> -as the first argument. +The first calling style is to supply +one or more SConscript file names +as the first (positional) argument. A single script may be specified as a string; -multiple scripts must be specified as a list +multiple scripts must be specified as a list of strings (either explicitly or as created by a function like &f-link-Split;). Examples: </para> <example_commands> -SConscript('SConscript') # run SConscript in the current directory +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') </example_commands> <para> -The second way to call -&f-SConscript; -is to specify a list of (sub)directory names -as a -<varname>dirs</varname>=<replaceable>subdirs</replaceable> -keyword argument. +The other calling style is to omit the positional argument naming +scripts and instead specify a list of directory names using the +<varname>dirs</varname> keyword argument. In this case, &scons; will @@ -408,14 +404,14 @@ in each of the specified directories. You may specify a name other than &SConscript; by supplying an optional -<varname>name</varname>=<replaceable>script</replaceable> +<varname>name</varname>=<replaceable>scriptname</replaceable> keyword argument. The first three examples below have the same effect as the first three examples above: </para> <example_commands> -SConscript(dirs='.') # run SConscript in the current directory -SConscript(dirs='src') # run SConscript in the src directory +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') </example_commands> @@ -423,8 +419,12 @@ SConscript(dirs=['sub1', 'sub2'], name='MySConscript') <para> The optional <varname>exports</varname> -argument provides a string or list of strings representing +keyword argument provides a string or list of strings representing variable names, or a dictionary of named values, to export. +For the first calling style only, a second positional argument +will be interpreted as <varname>exports</varname>; the +second calling style must use the keyword argument form +for <varname>exports</varname>. These variables are locally exported only to the called SConscript file(s) and do not affect the global pool of variables managed by the @@ -448,38 +448,24 @@ SConscript(dirs=['one', 'two', 'three'], exports='shared_info') If the optional <varname>variant_dir</varname> argument is present, it causes an effect equivalent to the -&f-link-VariantDir; function. +&f-link-VariantDir; function, +but in effect only within the scope of the &f-SConscript; call. The <varname>variant_dir</varname> -argument is interpreted relative to the directory of the calling -SConscript file. -The optional -<varname>duplicate</varname> argument is -interpreted as for &f-link-VariantDir;. -If <varname>variant_dir</varname> -is omitted, the <varname>duplicate</varname> argument is ignored. -See the description of -&f-link-VariantDir; -below for additional details and restrictions. -</para> - -<para> -If -<varname>variant_dir</varname> -is present, -the source directory is the directory in which the -SConscript -file resides and the -SConscript +argument is interpreted relative to the directory of the +<emphasis>calling</emphasis> SConscript file. +The source directory is the directory in which the +<emphasis>called</emphasis> SConscript +file resides and the SConscript file is evaluated as if it were in the <varname>variant_dir</varname> -directory: +directory. Thus: </para> <example_commands> SConscript('src/SConscript', variant_dir='build') </example_commands> <para> -is equivalent to +is equivalent to: </para> <example_commands> @@ -488,9 +474,8 @@ SConscript('build/SConscript') </example_commands> <para> -This later paradigm is often used when the sources are -in the same directory as the -&SConstruct;: +If the sources are in the same directory as the +&SConstruct;, </para> <example_commands> @@ -498,7 +483,7 @@ SConscript('SConscript', variant_dir='build') </example_commands> <para> -is equivalent to +is equivalent to: </para> <example_commands> @@ -507,6 +492,17 @@ SConscript('build/SConscript') </example_commands> <para> +The optional +<varname>duplicate</varname> argument is +interpreted as for &f-link-VariantDir;. +If the <varname>variant_dir</varname> argument +is omitted, the <varname>duplicate</varname> argument is ignored. +See the description of +&f-link-VariantDir; +for additional details and restrictions. +</para> + +<para> <!-- If <varname>variant_dir</varname> @@ -589,11 +585,11 @@ SConscript('src/SConscript', variant_dir='build/ppc', duplicate=0) <para> &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). +named by the executed SConscript file(s) in arguments +to the &f-link-Return; function. 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 +the returns of each of the scripts. If an executed script does not explicitly call &Return;, it returns <constant>None</constant>. </para> diff --git a/SCons/Tool/MSCommon/common.py b/SCons/Tool/MSCommon/common.py index f542e02..c9f07f5 100644 --- a/SCons/Tool/MSCommon/common.py +++ b/SCons/Tool/MSCommon/common.py @@ -35,6 +35,10 @@ from contextlib import suppress from pathlib import Path import SCons.Util +import SCons.Warnings + +class MSVCCacheInvalidWarning(SCons.Warnings.WarningOnByDefault): + pass # SCONS_MSCOMMON_DEBUG is internal-use so undocumented: # set to '-' to print to console, else set to filename to log to @@ -110,7 +114,15 @@ def read_script_env_cache(): # json to the cache dictionary. Reconstruct the cache key # tuple from the key list written to json. envcache_list = json.load(f) - envcache = {tuple(d['key']): d['data'] for d in envcache_list} + if isinstance(envcache_list, list): + envcache = {tuple(d['key']): d['data'] for d in envcache_list} + else: + # don't fail if incompatible format, just proceed without it + warn_msg = "Incompatible format for msvc cache file {}: file may be overwritten.".format( + repr(CONFIG_CACHE) + ) + SCons.Warnings.warn(MSVCCacheInvalidWarning, warn_msg) + debug(warn_msg) except FileNotFoundError: # don't fail if no cache file, just proceed without it pass diff --git a/SCons/Tool/ToolTests.py b/SCons/Tool/ToolTests.py index 7cff7c8..9338c2d 100644 --- a/SCons/Tool/ToolTests.py +++ b/SCons/Tool/ToolTests.py @@ -116,7 +116,9 @@ class ToolTestCase(unittest.TestCase): if __name__ == "__main__": - suite = unittest.makeSuite(ToolTestCase, 'test_') + loader = unittest.TestLoader() + loader.testMethodPrefix = 'test_' + suite = loader.loadTestsFromTestCase(ToolTestCase) TestUnit.run(suite) # Local Variables: diff --git a/SCons/Tool/msvsTests.py b/SCons/Tool/msvsTests.py index 4cbaf0e..c4d2e98 100644 --- a/SCons/Tool/msvsTests.py +++ b/SCons/Tool/msvsTests.py @@ -982,7 +982,9 @@ if __name__ == "__main__": if k in os.environ: del os.environ[k] - suite = unittest.makeSuite(test_class, 'test_') + loader = unittest.TestLoader() + loader.testMethodPrefix = 'test_' + suite = loader.loadTestsFromTestCase(test_class) if not TestUnit.cli.get_runner()().run(suite).wasSuccessful(): exit_val = 1 finally: diff --git a/SCons/Tool/ninja/Methods.py b/SCons/Tool/ninja/Methods.py index 2be576f..c0afab8 100644 --- a/SCons/Tool/ninja/Methods.py +++ b/SCons/Tool/ninja/Methods.py @@ -81,7 +81,7 @@ def get_generic_shell_command(env, node, action, targets, sources, executor=None "GENERATED_CMD", { "cmd": generate_command(env, node, action, targets, sources, executor=executor), - "env": get_command_env(env), + "env": get_command_env(env, targets, sources), }, # Since this function is a rule mapping provider, it must return a list of dependencies, # and usually this would be the path to a tool, such as a compiler, used for this rule. @@ -266,7 +266,7 @@ def gen_get_response_file_command(env, rule, tool, tool_is_dynamic=False, custom variables = {"rspc": rsp_content, rule: cmd} if use_command_env: - variables["env"] = get_command_env(env) + variables["env"] = get_command_env(env, targets, sources) for key, value in custom_env.items(): variables["env"] += env.subst( diff --git a/SCons/Tool/ninja/NinjaState.py b/SCons/Tool/ninja/NinjaState.py index 770da07..70be248 100644 --- a/SCons/Tool/ninja/NinjaState.py +++ b/SCons/Tool/ninja/NinjaState.py @@ -821,6 +821,15 @@ class SConsToNinjaTranslator: # Remove all preceding and proceeding whitespace cmdline = cmdline.strip() + env = node.env if node.env else self.env + executor = node.get_executor() + if executor is not None: + targets = executor.get_all_targets() + else: + if hasattr(node, "target_peers"): + targets = node.target_peers + else: + targets = [node] # Make sure we didn't generate an empty cmdline if cmdline: @@ -829,7 +838,7 @@ class SConsToNinjaTranslator: "rule": get_rule(node, "GENERATED_CMD"), "variables": { "cmd": cmdline, - "env": get_command_env(node.env if node.env else self.env), + "env": get_command_env(env, targets, node.sources), }, "implicit": dependencies, } diff --git a/SCons/Tool/ninja/Utils.py b/SCons/Tool/ninja/Utils.py index c5f7ee4..b2c3cd3 100644 --- a/SCons/Tool/ninja/Utils.py +++ b/SCons/Tool/ninja/Utils.py @@ -262,7 +262,7 @@ def ninja_noop(*_args, **_kwargs): return None -def get_command_env(env): +def get_command_env(env, target, source): """ Return a string that sets the environment for any environment variables that differ between the OS environment and the SCons command ENV. @@ -278,7 +278,7 @@ def get_command_env(env): # os.environ or differ from it. We assume if it's a new or # differing key from the process environment then it's # important to pass down to commands in the Ninja file. - ENV = get_default_ENV(env) + ENV = SCons.Action._resolve_shell_env(env, target, source) scons_specified_env = { key: value for key, value in ENV.items() diff --git a/SCons/Tool/swig.xml b/SCons/Tool/swig.xml index 19ec21f..a6d85ce 100644 --- a/SCons/Tool/swig.xml +++ b/SCons/Tool/swig.xml @@ -26,7 +26,7 @@ See its __doc__ string for a discussion of the format. <tool name="swig"> <summary> <para> -Sets construction variables for the SWIG interface generator. +Sets construction variables for the &swig; interface compiler. </para> </summary> <sets> @@ -50,7 +50,7 @@ Sets construction variables for the SWIG interface generator. <cvar name="SWIG"> <summary> <para> -The scripting language wrapper and interface generator. +The name of the &swig; compiler to use. </para> </summary> </cvar> @@ -59,10 +59,11 @@ The scripting language wrapper and interface generator. <summary> <para> The suffix that will be used for intermediate C -source files generated by -the scripting language wrapper and interface generator. -The default value is -<filename>_wrap</filename>&cv-link-CFILESUFFIX;. +source files generated by &swig;. +The default value is <literal>'_wrap$CFILESUFFIX'</literal> - +that is, the concatenation of the string +<literal>_wrap</literal> +and the current C suffix &cv-link-CFILESUFFIX;. By default, this value is used whenever the <option>-c++</option> option is @@ -78,8 +79,8 @@ construction variable. <summary> <para> 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 +files generated by &swig;. +These are only generated for C++ code when the &swig; 'directors' feature is turned on. The default value is <filename>_wrap.h</filename>. @@ -90,8 +91,7 @@ The default value is <cvar name="SWIGCOM"> <summary> <para> -The command line used to call -the scripting language wrapper and interface generator. +The command line used to call &swig;. </para> </summary> </cvar> @@ -99,8 +99,7 @@ the scripting language wrapper and interface generator. <cvar name="SWIGCOMSTR"> <summary> <para> -The string displayed when calling -the scripting language wrapper and interface generator. +The string displayed when calling &swig;. If this is not set, then &cv-link-SWIGCOM; (the command line) is displayed. </para> </summary> @@ -110,12 +109,13 @@ If this is not set, then &cv-link-SWIGCOM; (the command line) is displayed. <summary> <para> The suffix that will be used for intermediate C++ -source files generated by -the scripting language wrapper and interface generator. -The default value is -<filename>_wrap</filename>&cv-link-CFILESUFFIX;. +source files generated by &swig;. +The default value is <literal>'_wrap$CXXFILESUFFIX'</literal> - +that is, the concatenation of the string +<literal>_wrap</literal> +and the current C++ suffix &cv-link-CXXFILESUFFIX;. By default, this value is used whenever the -<filename>-c++</filename> +<option>-c++</option> option is specified as part of the &cv-link-SWIGFLAGS; construction variable. @@ -126,22 +126,14 @@ construction variable. <cvar name="SWIGFLAGS"> <summary> <para> -General options passed to -the scripting language wrapper and interface generator. -This is where you should set -<option>-python</option>, +General options passed to &swig;. +This is where you should set the target language +(<option>-python</option>, <option>-perl5</option>, -<option>-tcl</option>, -or whatever other options you want to specify to SWIG. -If you set the -<option>-c++</option> -option in this variable, -&scons; -will, by default, -generate a C++ intermediate source file -with the extension that is specified as the -&cv-link-CXXFILESUFFIX; -variable. +<option>-tcl</option>, etc.) +and whatever other options you want to specify to &swig;, +such as the <option>-c++</option> to generate C++ code +instead of C Code. </para> </summary> </cvar> @@ -150,7 +142,7 @@ variable. <summary> <para> An automatically-generated construction variable -containing the SWIG command-line options +containing the &swig; command-line options for specifying directories to be searched for included files. The value of &cv-_SWIGINCFLAGS; is created by respectively prepending and appending @@ -164,7 +156,7 @@ of each directory in &cv-SWIGPATH;. <cvar name="SWIGINCPREFIX"> <summary> <para> -The prefix used to specify an include directory on the SWIG command line. +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 &cv-SWIGPATH; construction variable when the &cv-_SWIGINCFLAGS; variable is automatically generated. @@ -175,7 +167,7 @@ when the &cv-_SWIGINCFLAGS; variable is automatically generated. <cvar name="SWIGINCSUFFIX"> <summary> <para> -The suffix used to specify an include directory on the SWIG command line. +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 &cv-SWIGPATH; construction variable when the &cv-_SWIGINCFLAGS; variable is automatically generated. @@ -186,8 +178,7 @@ when the &cv-_SWIGINCFLAGS; variable is automatically generated. <cvar name="SWIGOUTDIR"> <summary> <para> -Specifies the output directory in which -the scripting language wrapper and interface generator +Specifies the output directory in which &swig; should place generated language-specific files. This will be used by SCons to identify the files that will be generated by the &swig; call, @@ -200,22 +191,24 @@ and translated into the <cvar name="SWIGPATH"> <summary> <para> -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 +The list of directories that &swig; +will search for included files. +&SCons;' SWIG implicit dependency scanner will search these directories for include files. The default value is an empty list. </para> <para> Don't explicitly put include directory -arguments in SWIGFLAGS; +arguments in &cv-link-SWIGFLAGS; the result will be non-portable and the directories will not be searched by the dependency scanner. -Note: directory names in SWIGPATH will be looked-up relative to the SConscript +Note: directory names in &cv-link-SWIGPATH; +will be looked-up relative to the SConscript directory when they are used in a command. To force &scons; -to look-up a directory relative to the root of the source tree use #: +to look-up a directory relative to the root of the source tree use +a top-relative path (<literal>#</literal>): </para> <example_commands> @@ -258,7 +251,7 @@ env = Environment(SWIGCOM="my_swig -o $TARGET $_SWIGINCFLAGS $SOURCES") <cvar name="SWIGVERSION"> <summary> <para> -The version number of the SWIG tool. +The detected version string of the &swig; tool. </para> </summary> </cvar> diff --git a/SCons/cppTests.py b/SCons/cppTests.py index a9aef9d..f20c302 100644 --- a/SCons/cppTests.py +++ b/SCons/cppTests.py @@ -876,7 +876,9 @@ if __name__ == '__main__': fileTestCase, ] for tclass in tclasses: - names = unittest.getTestCaseNames(tclass, 'test_') + loader = unittest.TestLoader() + loader.testMethodPrefix = 'test_' + names = loader.getTestCaseNames(tclass) try: names = sorted(set(names)) except NameError: diff --git a/doc/man/scons.xml b/doc/man/scons.xml index a5eff28..a98f4e8 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -12,10 +12,10 @@ 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 @@ -145,16 +145,16 @@ to support additional input file types. <para>Information about files involved in the build, including a cryptographic hash of the contents, -is cached for later reuse, -By default content hashes are used to determine if a file -has changed since the last build, +is cached for later reuse. +By default this hash (the <firstterm>&contentsig;</firstterm>) +is used to determine if a file has changed since the last build, but this can be controlled by selecting an appropriate <firstterm>&f-link-Decider;</firstterm> function. Implicit dependency files are also part of out-of-date computation. The scanned implicit dependency information can optionally be cached and used to speed up future builds. -A hash of each executed build action is cached, -so that changes to build instructions (changing flags, etc.) +A hash of each executed build action (the <firstterm>&buildsig;</firstterm> +is cached, so that changes to build instructions (changing flags, etc.) or to the build tools themselves (new version) can also trigger a rebuild. </para> @@ -4968,20 +4968,51 @@ vars.AddVariables( </refsect2> <refsect2 id='node_objects'> -<title>File and Directory Nodes</title> +<title>Node Objects</title> + +<para> +&SCons; represents objects that are the sources or targets of +build operations as <firstterm>Nodes</firstterm>, +which are internal data structures. +There are a number of user-visible types of nodes: +File Nodes, Directory Nodes, Value Nodes and Alias Nodes. +Some of the node types have public attributes and methods, +described below. Each of the node types has a global function +and a matching environment method to create instances: +&f-link-File;, &f-link-Dir;, &f-link-Value; and &f-link-Alias;. +</para> + +<refsect3 id='file_and_directory_nodes'> +<title>Filesystem Nodes</title> <para> 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:</para> +File and Directory Nodes +(collectively, Filesystem Nodes) +represent build components that correspond to an entry +in the computer's filesystem, +whether or not such an entry exists at the time the Node is created. +You do not usually need to explicitly create filesystem Nodes, +since when you supply a string as a target or source of a Builder, +&SCons; will create the Nodes as needed to populate the +dependency graph. +Builders return the target Node(s) in the form of a list, +which you can then make use of. +However, since filesystem Nodes have some useful +public attributes and methods +that you can use in SConscript files, +it is sometimes appropriate to create them manually, +outside the regular context of a Builder call. +</para> +<para> +The following attributes provide information about a Node: +</para> <variablelist> <varlistentry> - <term><replaceable>n</replaceable>.<varname>path</varname></term> + <term><replaceable>node</replaceable>.<varname>path</varname></term> <listitem> <para>The build path of the given @@ -4995,21 +5026,21 @@ is not being used.</para> </varlistentry> <varlistentry> - <term><replaceable>n</replaceable>.<varname>abspath</varname></term> + <term><replaceable>node</replaceable>.<varname>abspath</varname></term> <listitem> <para>The absolute build path of the given file or directory.</para> </listitem> </varlistentry> <varlistentry> - <term><replaceable>n</replaceable>.<varname>relpath</varname></term> + <term><replaceable>node</replaceable>.<varname>relpath</varname></term> <listitem> <para>The build path of the given file or directory relative to the root SConstruct file's directory.</para> </listitem> </varlistentry> <varlistentry> - <term><replaceable>n</replaceable>.<function>srcnode</function>()</term> + <term><replaceable>node</replaceable>.<function>srcnode</function>()</term> <listitem> <para>The <function>srcnode</function> @@ -5022,101 +5053,116 @@ File or Directory Node. </varlistentry> </variablelist> -<para>For example:</para> +<para>Examples:</para> <programlisting language="python"> # Get the current build dir's path, relative to top. Dir('.').path + # Current dir's absolute path Dir('.').abspath + # Current dir's path relative to the root SConstruct file's directory Dir('.').relpath + # Next line is always '.', because it is the top dir's path relative to itself. Dir('#.').path -File('foo.c').srcnode().path # source path of the given source file. -# Builders also return File objects: +# Source path of the given source file. +File('foo.c').srcnode().path + +# Builders return lists of File objects: foo = env.Program('foo.c') -print("foo will be built in", foo.path) +print("foo will be built in", foo[0].path) </programlisting> <para> -File and Directory Node objects have methods to create +Filesystem Node objects have methods to create new File and Directory Nodes relative to the original Node. +There are also times when you may need to refer to an entry +in a filesystem without knowing in advance whether it's a +file or a directory. +For those situations, +there is an <function>Entry</function> method of filesystem node objects, +which returns a Node that can represent either a file or a directory. </para> <para> -If the object is a Directory Node, -these methods will place the the new Node within the directory -the Node represents: +If the original Node is a Directory Node, +these methods will place the new Node within the directory +the original Node represents: </para> <variablelist> <varlistentry> - <term><replaceable>d</replaceable>.<function>Dir</function>(<parameter>name</parameter>)</term> + <term><replaceable>node</replaceable>.<function>Dir</function>(<parameter>name</parameter>)</term> <listitem> -<para>Returns a directory Node for a subdirectory of -<replaceable>d</replaceable> -named -<parameter>name</parameter>.</para> +<para>Returns a directory Node +<parameter>name</parameter> +which is a subdirectory of +the directory represented by +<replaceable>node</replaceable>.</para> </listitem> </varlistentry> <varlistentry> - <term><replaceable>d</replaceable>.<function>File</function>(<parameter>name</parameter>)</term> + <term><replaceable>node</replaceable>.<function>File</function>(<parameter>name</parameter>)</term> <listitem> -<para>Returns a file Node for a file within -<replaceable>d</replaceable> -named -<parameter>name</parameter>.</para> +<para>Returns a file Node +<parameter>name</parameter> +in the directory represented by +<replaceable>node</replaceable>.</para> </listitem> </varlistentry> <varlistentry> - <term><replaceable>d</replaceable>.<function>Entry</function>(<parameter>name</parameter>)</term> + <term><replaceable>node</replaceable>.<function>Entry</function>(<parameter>name</parameter>)</term> <listitem> -<para>Returns an unresolved Node within -<replaceable>d</replaceable> -named -<parameter>name</parameter>.</para> +<para>Returns an unresolved Node +<parameter>name</parameter> +in the directory represented by +<replaceable>node</replaceable>.</para> </listitem> </varlistentry> </variablelist> <para> -If the object is a File Node, +If the original Node is a File Node, these methods will place the the new Node in the same -directory as the one the Node represents: +directory as the one the original Node represents: </para> <variablelist> <varlistentry> - <term><replaceable>f</replaceable>.<function>Dir</function>(<parameter>name</parameter>)</term> + <term><replaceable>node</replaceable>.<function>Dir</function>(<parameter>name</parameter>)</term> <listitem> -<para>Returns a directory named +<para>Returns a Node <parameter>name</parameter> -within the parent directory of -<replaceable>f</replaceable>.</para> +for a directory in the parent directory of +the file represented by +<replaceable>node</replaceable>.</para> </listitem> </varlistentry> <varlistentry> - <term><replaceable>f</replaceable>.<function>File</function>(<parameter>name</parameter>)</term> + <term><replaceable>node</replaceable>.<function>File</function>(<parameter>name</parameter>)</term> <listitem> -<para>Returns a file named +<para>Returns a Node <parameter>name</parameter> -within the parent directory of -<replaceable>f</replaceable>.</para> +for a file in the parent directory of +the file represented by +<replaceable>node</replaceable>.</para> </listitem> </varlistentry> <varlistentry> - <term><replaceable>f</replaceable>.<function>Entry</function>(<parameter>name</parameter>)</term> + <term><replaceable>node</replaceable>.<function>Entry</function>(<parameter>name</parameter>)</term> <listitem> -<para>Returns an unresolved Node named +<para>Returns an unresolved Node <parameter>name</parameter> -within the parent directory of -<replaceable>f</replaceable>.</para> +in the parent directory of +the file represented by +<replaceable>node</replaceable>.</para> </listitem> </varlistentry> </variablelist> @@ -5142,6 +5188,56 @@ html = docs.Dir('html') index = html.File('index.html') css = index.File('app.css') </programlisting> +</refsect3> + +<refsect3 id='value_and_alias_nodes'> +<title>Value and Alias Nodes</title> + +<para> +&SCons; provides two other Node types to represent +object that will not have an equivalent filesystem entry. +Such Nodes always need to be created explicitly. +</para> + +<para> +The &f-link-Alias; method returns an Alias Node. +Aliases are virtual objects - they will not themselves result +in physical objects being constructed, but are entered into +the dependency graph related to their sources. +An alias is checked for up to date by checking if +its sources are up to date. +An alias is built by making sure its sources have been built, +and if any building took place, +applying any Actions that are defined as part of the alias. +</para> + +<para> +An &f-link-Alias; call creates an entry in the alias namespace, +which is used for disambiguation. +If an alias source has a string valued name, +it will be resolved to a filesystem entry Node, +unless it is found in the alias namespace, +in which case it it resolved to the matching alias Node. +As a result, the order of &f-Alias; calls is significant. +An alias can refer to another alias, but only if the +other alias has previously been created. +</para> + +<para> +The &f-link-Value; method returns a Value Node. +Value nodes are often used for generated data that +will not have any corresponding filesystem entry, +but will be used to determine whether a build target is out of date, +or to include as part of a build Action. +Common examples are timestamp strings, +revision control version strings +and other run-time generated strings. +</para> + +<para> +A Value Node can also be the target of a builder. +</para> +</refsect3> </refsect2> </refsect1> @@ -5156,13 +5252,14 @@ to customize its behavior. A number of the main operations use callable objects which can be supplemented by writing your own. Builders, Scanners and Tools each use a kind of plugin system, -allowing you to seamlessly drop in new ones. +allowing you to easily drop in new ones. Information about creating <link linkend='builder_objects'>Builder Objects</link> and <link linkend='scanner_objects'>Scanner Objects</link> appear in the following sections. -The instructions &SCons; actually uses to make things are called -Actions, and it is easy to create Action Objects and hand them +The instructions &SCons; actually uses to +construct things are called Actions, +and it is easy to create Action Objects and hand them to the objects that need to know about those actions (besides Builders, see &f-link-AddPostAction;, &f-link-AddPreAction; and &f-link-Alias; for some examples @@ -5762,14 +5859,13 @@ The canonical example here would be to set a &consvar; to the repository of a source code system.</para> -<para>Any additional keyword arguments supplied +<para>Any such keyword arguments supplied when a Builder object is called will only be associated with the target created by that particular &f-Builder; call (and any other files built as a -result of the call).</para> - -<para>These extra keyword arguments are passed to the +result of the call). +These extra keyword arguments are passed to the following functions: <link linkend='generator_function'>command generator functions</link>, <link linkend='miscellaneous_action_functions'>function Actions</link>, @@ -7249,7 +7345,7 @@ A tool specification module must include two functions: <listitem> <para>Modify the &consenv; <parameter>env</parameter> to set up necessary &consvars;, Builders, Emitters, etc., -so the facilities represented by the tool can be executed. +so the facilities represented by the tool can be executed. Care should be taken not to overwrite &consvars; intended to be settable by the user. For example: </para> @@ -7506,8 +7602,8 @@ arguments to itself, not to &scons;:</para> </screen> <para>Second, the Cygwin shell does not -reognize typing <userinput>scons</userinput> -at the command line prompt as referring to this weapper. +recognize typing <userinput>scons</userinput> +at the command line prompt as referring to this wrapper. You can work around this either by executing <userinput>scons.bat</userinput> (including the extension) diff --git a/doc/scons.mod b/doc/scons.mod index 8a6df17..77a7d24 100644 --- a/doc/scons.mod +++ b/doc/scons.mod @@ -63,6 +63,7 @@ <!ENTITY f77 "<application xmlns='http://www.scons.org/dbxsd/v1.0'>f77</application>"> <!ENTITY f90 "<application xmlns='http://www.scons.org/dbxsd/v1.0'>f90</application>"> <!ENTITY f95 "<application xmlns='http://www.scons.org/dbxsd/v1.0'>f95</application>"> +<!ENTITY flex "<application xmlns='http://www.scons.org/dbxsd/v1.0'>flex</application>"> <!ENTITY gas "<application xmlns='http://www.scons.org/dbxsd/v1.0'>gas</application>"> <!ENTITY gcc "<application xmlns='http://www.scons.org/dbxsd/v1.0'>gcc</application>"> <!ENTITY g77 "<application xmlns='http://www.scons.org/dbxsd/v1.0'>g77</application>"> @@ -84,7 +85,7 @@ <!ENTITY rmic "<application xmlns='http://www.scons.org/dbxsd/v1.0'>rmic</application>"> <!ENTITY ScCons "<application xmlns='http://www.scons.org/dbxsd/v1.0'>ScCons</application>"> <!ENTITY sleep "<application xmlns='http://www.scons.org/dbxsd/v1.0'>sleep</application>"> -<!ENTITY swig "<application xmlns='http://www.scons.org/dbxsd/v1.0'>swig</application>"> +<!ENTITY swig "<application xmlns='http://www.scons.org/dbxsd/v1.0'>SWIG</application>"> <!ENTITY tar "<application xmlns='http://www.scons.org/dbxsd/v1.0'>tar</application>"> <!ENTITY tex "<application xmlns='http://www.scons.org/dbxsd/v1.0'>tex</application>"> <!ENTITY touch "<application xmlns='http://www.scons.org/dbxsd/v1.0'>touch</application>"> diff --git a/test/Actions/subst_shell_env-fixture/SConstruct b/test/Actions/subst_shell_env-fixture/SConstruct index 6e48add..5ba822e 100644 --- a/test/Actions/subst_shell_env-fixture/SConstruct +++ b/test/Actions/subst_shell_env-fixture/SConstruct @@ -1,24 +1,36 @@ import sys -def custom_environment_expansion(env, target, source): - ENV = env['ENV'].copy() - ENV['EXPANDED_SHELL_VAR'] = env.subst(env['ENV']['EXPANDED_SHELL_VAR'], target=target, source=source) +def custom_environment_expansion1(env, target, source, shell_env): + ENV = shell_env.copy() + ENV['EXPANDED_SHELL_VAR1'] = env.subst(env['ENV']['EXPANDED_SHELL_VAR1'], target=target, source=source) + return ENV + +def custom_environment_expansion2(env, target, source, shell_env): + ENV = shell_env.copy() + ENV['EXPANDED_SHELL_VAR2'] = env.subst(env['ENV']['EXPANDED_SHELL_VAR2'], target=target, source=source) return ENV def expand_this_generator(env, target, source, for_signature): return "I_got_expanded_to_" + str(target[0]) +def expand_that_generator(env, target, source, for_signature): + return str(target[0]) + "_is_from_expansion" + env = Environment(tools=['textfile']) -env['SHELL_ENV_GENERATOR'] = custom_environment_expansion +env['SHELL_ENV_GENERATORS'] = [custom_environment_expansion1, custom_environment_expansion2] env['EXPAND_THIS'] = expand_this_generator -env['ENV']['EXPANDED_SHELL_VAR'] = "$EXPAND_THIS" +env['EXPAND_THAT'] = expand_that_generator + +env['ENV']['EXPANDED_SHELL_VAR1'] = "$EXPAND_THIS" +env['ENV']['EXPANDED_SHELL_VAR2'] = "$EXPAND_THAT" env['ENV']['NON_EXPANDED_SHELL_VAR'] = "$EXPAND_THIS" env.Textfile('expand_script.py', [ 'import os', - 'print(os.environ["EXPANDED_SHELL_VAR"])', + 'print(os.environ["EXPANDED_SHELL_VAR1"])', + 'print(os.environ["EXPANDED_SHELL_VAR2"])', 'print(os.environ["NON_EXPANDED_SHELL_VAR"])', ]) env.Command('out.txt', 'expand_script.py', fr'{sys.executable} $SOURCE > $TARGET') diff --git a/test/Actions/subst_shell_env.py b/test/Actions/subst_shell_env.py index 9f5c5db..02ba640 100644 --- a/test/Actions/subst_shell_env.py +++ b/test/Actions/subst_shell_env.py @@ -25,7 +25,7 @@ """ Verify that shell environment variables can be expanded per target/source -when exectuting actions on the command line. +when executing actions on the command line. """ import os @@ -36,8 +36,8 @@ test = TestSCons.TestSCons() test.dir_fixture('subst_shell_env-fixture') test.run(arguments = ['-Q']) -test.must_match('out.txt', f"I_got_expanded_to_out.txt{os.linesep}$EXPAND_THIS{os.linesep}") -test.must_match('out2.txt', f"I_got_expanded_to_out2.txt{os.linesep}$EXPAND_THIS{os.linesep}") +test.must_match('out.txt', f"I_got_expanded_to_out.txt{os.linesep}out.txt_is_from_expansion{os.linesep}$EXPAND_THIS{os.linesep}") +test.must_match('out2.txt', f"I_got_expanded_to_out2.txt{os.linesep}out2.txt_is_from_expansion{os.linesep}$EXPAND_THIS{os.linesep}") test.pass_test() diff --git a/test/CacheDir/timestamp-match.py b/test/CacheDir/timestamp-match.py index 4b64137..fd9c659 100644 --- a/test/CacheDir/timestamp-match.py +++ b/test/CacheDir/timestamp-match.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,9 +22,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 CAcheDir() works when using 'timestamp-match' decisions. @@ -41,21 +40,15 @@ Command('file.out', 'file.in', Copy('$TARGET', '$SOURCE')) test.write('file.in', "file.in\n") -test.run(arguments = '--cache-show --debug=explain .') - +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.up_to_date(options = '--cache-show --debug=explain', arguments = '.') - -test.sleep() - +test.sleep() # delay for timestamps 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.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() diff --git a/test/CacheDir/timestamp-newer.py b/test/CacheDir/timestamp-newer.py index 618f467..567078e 100644 --- a/test/CacheDir/timestamp-newer.py +++ b/test/CacheDir/timestamp-newer.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,9 +22,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 CAcheDir() works when using 'timestamp-newer' decisions. @@ -41,21 +40,16 @@ Command('file.out', 'file.in', Copy('$TARGET', '$SOURCE')) test.write('file.in', "file.in\n") -test.run(arguments = '--cache-show --debug=explain .') - +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.up_to_date(options = '--cache-show --debug=explain', arguments = '.') - -test.sleep() - +test.sleep() # delay for timestamps 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.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() diff --git a/test/Copy-Action.py b/test/Copy-Action.py index 4bfa0da..e135a9f 100644 --- a/test/Copy-Action.py +++ b/test/Copy-Action.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,9 +22,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 the Copy() Action works, and preserves file modification @@ -37,29 +36,32 @@ import TestSCons test = TestSCons.TestSCons() -test.write('SConstruct', """ +test.write('SConstruct', """\ Execute(Copy('f1.out', 'f1.in')) Execute(Copy(File('d2.out'), 'd2.in')) Execute(Copy('d3.out', File('f3.in'))) + def cat(env, source, target): target = str(target[0]) with open(target, "w") as f: for src in source: with open(str(src), "r") as ifp: f.write(ifp.read()) + Cat = Action(cat) env = Environment() -env.Command('bar.out', 'bar.in', [Cat, - Copy("f4.out", "f4.in"), - Copy("d5.out", "d5.in"), - Copy("d6.out", "f6.in")]) -env = Environment(OUTPUT = 'f7.out', INPUT = 'f7.in') +env.Command( + 'bar.out', + 'bar.in', + [Cat, Copy("f4.out", "f4.in"), Copy("d5.out", "d5.in"), Copy("d6.out", "f6.in")], +) +env = Environment(OUTPUT='f7.out', INPUT='f7.in') env.Command('f8.out', 'f8.in', [Copy('$OUTPUT', '$INPUT'), Cat]) env.Command('f9.out', 'f9.in', [Cat, Copy('${TARGET}-Copy', '$SOURCE')]) -env.CopyTo( 'd4', 'f10.in' ) -env.CopyAs( 'd4/f11.out', 'f11.in') -env.CopyAs( 'd4/f12.out', 'd5/f12.in') +env.CopyTo('d4', 'f10.in') +env.CopyAs('d4/f11.out', 'f11.in') +env.CopyAs('d4/f12.out', 'd5/f12.in') env.Command('f 13.out', 'f 13.in', Copy('$TARGET', '$SOURCE')) """) @@ -87,19 +89,20 @@ test.write('f 13.in', "f 13.in\n") os.chmod('f1.in', 0o646) os.chmod('f4.in', 0o644) -test.sleep() +test.sleep() # delay for timestamps d4_f10_in = os.path.join('d4', 'f10.in') d4_f11_out = os.path.join('d4', 'f11.out') d4_f12_out = os.path.join('d4', 'f12.out') d5_f12_in = os.path.join('d5', 'f12.in') -expect = test.wrap_stdout(read_str = """\ +expect = test.wrap_stdout( + read_str="""\ Copy("f1.out", "f1.in") Copy("d2.out", "d2.in") Copy("d3.out", "f3.in") """, - build_str = """\ + build_str="""\ cat(["bar.out"], ["bar.in"]) Copy("f4.out", "f4.in") Copy("d5.out", "d5.in") @@ -112,9 +115,10 @@ Copy("f7.out", "f7.in") cat(["f8.out"], ["f8.in"]) cat(["f9.out"], ["f9.in"]) Copy("f9.out-Copy", "f9.in") -""" % locals()) +""" % locals(), +) -test.run(options = '-n', arguments = '.', stdout = expect) +test.run(options='-n', arguments='.', stdout=expect) test.must_not_exist('f1.out') test.must_not_exist('d2.out') @@ -162,23 +166,21 @@ def must_be_same(f1, f2): for value in ['ST_MODE', 'ST_MTIME']: v = getattr(stat, value) if s1[v] != s2[v]: - msg = '%s[%s] %s != %s[%s] %s\n' % \ - (repr(f1), value, s1[v], - repr(f2), value, s2[v],) + msg = f"{f1!r}[{value}] {s1[v]} != {f2!r}[{value}] {s2[v]}\n" sys.stderr.write(msg) - errors = errors + 1 - -must_be_same('f1.out', 'f1.in') -must_be_same(['d2.out', 'file'], ['d2.in', 'file']) -must_be_same(['d3.out', 'f3.in'], 'f3.in') -must_be_same('f4.out', 'f4.in') -must_be_same(['d5.out', 'file'], ['d5.in', 'file']) -must_be_same(['d6.out', 'f6.in'], 'f6.in') -must_be_same('f7.out', 'f7.in') -must_be_same(['d4', 'f10.in'], 'f10.in') -must_be_same(['d4', 'f11.out'], 'f11.in') -must_be_same(['d4', 'f12.out'], ['d5', 'f12.in']) -must_be_same('f 13.out', 'f 13.in') + errors += 1 + +must_be_same('f1.out', 'f1.in') +must_be_same(['d2.out', 'file'], ['d2.in', 'file']) +must_be_same(['d3.out', 'f3.in'], 'f3.in') +must_be_same('f4.out', 'f4.in') +must_be_same(['d5.out', 'file'], ['d5.in', 'file']) +must_be_same(['d6.out', 'f6.in'], 'f6.in') +must_be_same('f7.out', 'f7.in') +must_be_same(['d4', 'f10.in'], 'f10.in') +must_be_same(['d4', 'f11.out'], 'f11.in') +must_be_same(['d4', 'f12.out'], ['d5', 'f12.in']) +must_be_same('f 13.out', 'f 13.in') if errors: test.fail_test() diff --git a/test/Decider/MD5-timestamp-Repository.py b/test/Decider/MD5-timestamp-Repository.py index 1826f68..201bdfe 100644 --- a/test/Decider/MD5-timestamp-Repository.py +++ b/test/Decider/MD5-timestamp-Repository.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,9 +22,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 behavior of the MD5-timestamp Decider() setting when combined with Repository() usage @@ -38,13 +37,11 @@ test = TestSCons.TestSCons() test.subdir('Repository', 'work') repository = test.workpath('Repository') - test.write(['Repository','content1.in'], "content1.in 1\n") test.write(['Repository','content2.in'], "content2.in 1\n") test.write(['Repository','content3.in'], "content3.in 1\n") # test.writable('Repository', 0) - test.write(['work','SConstruct'], """\ Repository(r'%s') DefaultEnvironment(tools=[]) @@ -53,18 +50,14 @@ m.Decider('MD5-timestamp') m.Command('content1.out', 'content1.in', Copy('$TARGET', '$SOURCE')) m.Command('content2.out', 'content2.in', Copy('$TARGET', '$SOURCE')) m.Command('content3.out', 'content3.in', Copy('$TARGET', '$SOURCE')) -"""%repository) +""" % repository) test.run(chdir='work',arguments='.') - test.up_to_date(chdir='work',arguments='.') -test.sleep() - +test.sleep() # delay for timestamps test.write(['Repository','content1.in'], "content1.in 2\n") - test.touch(['Repository','content2.in']) - time_content = os.stat(os.path.join(repository,'content3.in'))[stat.ST_MTIME] test.write(['Repository','content3.in'], "content3.in 2\n") test.touch(['Repository','content3.in'], time_content) @@ -76,10 +69,9 @@ test.touch(['Repository','content3.in'], time_content) expect = test.wrap_stdout("""\ Copy("content1.out", "%s") -"""%os.path.join(repository,'content1.in')) +""" % os.path.join(repository, 'content1.in')) test.run(chdir='work', arguments='.', stdout=expect) - test.up_to_date(chdir='work', arguments='.') test.pass_test() diff --git a/test/Decider/MD5-timestamp.py b/test/Decider/MD5-timestamp.py index 6fcdb42..3815639 100644 --- a/test/Decider/MD5-timestamp.py +++ b/test/Decider/MD5-timestamp.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,9 +22,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 behavior of the MD5-timestamp Decider() setting. @@ -49,15 +48,10 @@ test.write('content2.in', "content2.in 1\n") test.write('content3.in', "content3.in 1\n") test.run(arguments = '.') - test.up_to_date(arguments = '.') - - -test.sleep() - +test.sleep() # delay for timestamps test.write('content1.in', "content1.in 2\n") - test.touch('content2.in') time_content = os.stat('content3.in')[stat.ST_MTIME] @@ -73,11 +67,8 @@ expect = test.wrap_stdout("""\ Copy("content1.out", "content1.in") """) -test.run(arguments = '.', stdout=expect) - -test.up_to_date(arguments = '.') - - +test.run(arguments='.', stdout=expect) +test.up_to_date(arguments='.') test.pass_test() diff --git a/test/Decider/timestamp.py b/test/Decider/timestamp.py index e528d77..d713a62 100644 --- a/test/Decider/timestamp.py +++ b/test/Decider/timestamp.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,9 +22,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 various interactions of the timestamp-match and timestamp-newer @@ -54,27 +53,21 @@ test.write('newer1.in', "newer1.in\n") test.write('newer2.in', "newer2.in\n") test.run(arguments = '.') - test.up_to_date(arguments = '.') time_match = os.stat('match2.out')[stat.ST_MTIME] time_newer = os.stat('newer2.out')[stat.ST_MTIME] - - # Now make all the source files newer than (different timestamps from) # the last time the targets were built, and touch the target files # of match1.out and newer1.out to see the different effects. - -test.sleep() - +test.sleep() # delay for timestamps test.touch('match1.in') test.touch('newer1.in') test.touch('match2.in') test.touch('newer2.in') -test.sleep() - +test.sleep() # delay for timestamps test.touch('match1.out') test.touch('newer1.out') @@ -90,7 +83,7 @@ Copy("match2.out", "match2.in") Copy("newer2.out", "newer2.in") """) -test.run(arguments = '.', stdout=expect) +test.run(arguments='.', stdout=expect) # Now, for the somewhat pathological case, reset the match2.out and # newer2.out timestamps to the older timestamp when the targets were @@ -107,9 +100,7 @@ expect = test.wrap_stdout("""\ Copy("newer2.out", "newer2.in") """) -test.run(arguments = '.', stdout=expect) - - +test.run(arguments='.', stdout=expect) test.pass_test() diff --git a/test/Dir/source.py b/test/Dir/source.py index c35d169..a0ba987 100644 --- a/test/Dir/source.py +++ b/test/Dir/source.py @@ -42,15 +42,16 @@ test.subdir('tstamp', [ 'tstamp', 'subdir' ], test.write('SConstruct', """\ DefaultEnvironment(tools=[]) + def writeTarget(target, source, env): - f=open(str(target[0]), 'w') + f = open(str(target[0]), 'w') f.write("stuff\\n") f.close() return 0 -test_bld_dir = Builder(action=writeTarget, - source_factory=Dir, - source_scanner=DirScanner) +test_bld_dir = Builder( + action=writeTarget, source_factory=Dir, source_scanner=DirScanner +) test_bld_file = Builder(action=writeTarget) env = Environment(tools=[]) env['BUILDERS']['TestDir'] = test_bld_dir @@ -61,34 +62,36 @@ env_tstamp.Decider('timestamp-newer') env_tstamp.TestFile(source='junk.txt', target='tstamp/junk.out') env_tstamp.TestDir(source='tstamp', target='tstamp.out') env_tstamp.Command('cmd-tstamp-noscan.out', 'cmd-tstamp', writeTarget) -env_tstamp.Command('cmd-tstamp.out', 'cmd-tstamp', writeTarget, - source_scanner=DirScanner) +env_tstamp.Command( + 'cmd-tstamp.out', 'cmd-tstamp', writeTarget, source_scanner=DirScanner +) env_content = env.Clone() env_content.Decider('content') env_content.TestFile(source='junk.txt', target='content/junk.out') env_content.TestDir(source='content', target='content.out') env_content.Command('cmd-content-noscan.out', 'cmd-content', writeTarget) -env_content.Command('cmd-content.out', 'cmd-content', writeTarget, - source_scanner=DirScanner) +env_content.Command( + 'cmd-content.out', 'cmd-content', writeTarget, source_scanner=DirScanner +) """) -test.write([ 'tstamp', 'foo.txt' ], 'foo.txt 1\n') -test.write([ 'tstamp', '#hash.txt' ], 'hash.txt 1\n') -test.write([ 'tstamp', 'subdir', 'bar.txt'], 'bar.txt 1\n') -test.write([ 'tstamp', 'subdir', '#hash.txt'], 'hash.txt 1\n') -test.write([ 'content', 'foo.txt' ], 'foo.txt 1\n') -test.write([ 'content', '#hash.txt' ], 'hash.txt 1\n') -test.write([ 'content', 'subdir', 'bar.txt' ], 'bar.txt 1\n') -test.write([ 'content', 'subdir', '#hash.txt' ], 'hash.txt 1\n') -test.write([ 'cmd-tstamp', 'foo.txt' ], 'foo.txt 1\n') -test.write([ 'cmd-tstamp', '#hash.txt' ], 'hash.txt 1\n') -test.write([ 'cmd-tstamp', 'subdir', 'bar.txt' ], 'bar.txt 1\n') -test.write([ 'cmd-tstamp', 'subdir', '#hash.txt' ], 'hash.txt 1\n') -test.write([ 'cmd-content', 'foo.txt' ], 'foo.txt 1\n') -test.write([ 'cmd-content', '#hash.txt' ], '#hash.txt 1\n') -test.write([ 'cmd-content', 'subdir', 'bar.txt' ], 'bar.txt 1\n') -test.write([ 'cmd-content', 'subdir', '#hash.txt' ], 'hash.txt 1\n') +test.write(['tstamp', 'foo.txt'], 'foo.txt 1\n') +test.write(['tstamp', '#hash.txt'], 'hash.txt 1\n') +test.write(['tstamp', 'subdir', 'bar.txt'], 'bar.txt 1\n') +test.write(['tstamp', 'subdir', '#hash.txt'], 'hash.txt 1\n') +test.write(['content', 'foo.txt'], 'foo.txt 1\n') +test.write(['content', '#hash.txt'], 'hash.txt 1\n') +test.write(['content', 'subdir', 'bar.txt'], 'bar.txt 1\n') +test.write(['content', 'subdir', '#hash.txt'], 'hash.txt 1\n') +test.write(['cmd-tstamp', 'foo.txt'], 'foo.txt 1\n') +test.write(['cmd-tstamp', '#hash.txt'], 'hash.txt 1\n') +test.write(['cmd-tstamp', 'subdir', 'bar.txt'], 'bar.txt 1\n') +test.write(['cmd-tstamp', 'subdir', '#hash.txt'], 'hash.txt 1\n') +test.write(['cmd-content', 'foo.txt'], 'foo.txt 1\n') +test.write(['cmd-content', '#hash.txt'], '#hash.txt 1\n') +test.write(['cmd-content', 'subdir', 'bar.txt'], 'bar.txt 1\n') +test.write(['cmd-content', 'subdir', '#hash.txt'], 'hash.txt 1\n') test.write('junk.txt', 'junk.txt\n') test.run(arguments=".", stderr=None) @@ -106,61 +109,61 @@ test.up_to_date(arguments='cmd-content.out') test.up_to_date(arguments='cmd-tstamp-noscan.out') test.up_to_date(arguments='cmd-content-noscan.out') -test.sleep() +test.sleep() # delay for timestamps -test.write([ 'tstamp', 'foo.txt' ], 'foo.txt 2\n') +test.write(['tstamp', 'foo.txt'], 'foo.txt 2\n') test.not_up_to_date(arguments='tstamp.out') -test.write([ 'tstamp', 'new.txt' ], 'new.txt\n') +test.write(['tstamp', 'new.txt'], 'new.txt\n') test.not_up_to_date(arguments='tstamp.out') -test.write([ 'content', 'foo.txt' ], 'foo.txt 2\n') +test.write(['content', 'foo.txt'], 'foo.txt 2\n') test.not_up_to_date(arguments='content.out') -test.write([ 'content', 'new.txt' ], 'new.txt\n') +test.write(['content', 'new.txt'], 'new.txt\n') test.not_up_to_date(arguments='content.out') -test.write([ 'cmd-tstamp', 'foo.txt' ], 'foo.txt 2\n') +test.write(['cmd-tstamp', 'foo.txt'], 'foo.txt 2\n') test.not_up_to_date(arguments='cmd-tstamp.out') test.up_to_date(arguments='cmd-tstamp-noscan.out') -test.write([ 'cmd-tstamp', 'new.txt' ], 'new.txt\n') +test.write(['cmd-tstamp', 'new.txt'], 'new.txt\n') test.not_up_to_date(arguments='cmd-tstamp.out') test.up_to_date(arguments='cmd-tstamp-noscan.out') -test.write([ 'cmd-content', 'foo.txt' ], 'foo.txt 2\n') +test.write(['cmd-content', 'foo.txt'], 'foo.txt 2\n') test.not_up_to_date(arguments='cmd-content.out') test.up_to_date(arguments='cmd-content-noscan.out') -test.write([ 'cmd-content', 'new.txt' ], 'new.txt\n') +test.write(['cmd-content', 'new.txt'], 'new.txt\n') test.not_up_to_date(arguments='cmd-content.out') test.up_to_date(arguments='cmd-content-noscan.out') -test.write([ 'tstamp', 'subdir', 'bar.txt' ], 'bar.txt 2\n') +test.write(['tstamp', 'subdir', 'bar.txt'], 'bar.txt 2\n') test.not_up_to_date(arguments='tstamp.out') -test.write([ 'tstamp', 'subdir', 'new.txt' ], 'new.txt\n') +test.write(['tstamp', 'subdir', 'new.txt'], 'new.txt\n') test.not_up_to_date(arguments='tstamp.out') -test.write([ 'content', 'subdir', 'bar.txt' ], 'bar.txt 2\n') +test.write(['content', 'subdir', 'bar.txt'], 'bar.txt 2\n') test.not_up_to_date(arguments='content.out') -test.write([ 'content', 'subdir', 'new.txt' ], 'new.txt\n') +test.write(['content', 'subdir', 'new.txt'], 'new.txt\n') test.not_up_to_date(arguments='content.out') -test.write([ 'cmd-tstamp', 'subdir', 'bar.txt' ], 'bar.txt 2\n') +test.write(['cmd-tstamp', 'subdir', 'bar.txt'], 'bar.txt 2\n') test.not_up_to_date(arguments='cmd-tstamp.out') test.up_to_date(arguments='cmd-tstamp-noscan.out') -test.write([ 'cmd-tstamp', 'subdir', 'new.txt' ], 'new.txt\n') +test.write(['cmd-tstamp', 'subdir', 'new.txt'], 'new.txt\n') test.not_up_to_date(arguments='cmd-tstamp.out') test.up_to_date(arguments='cmd-tstamp-noscan.out') -test.write([ 'cmd-content', 'subdir', 'bar.txt' ], 'bar.txt 2\n') +test.write(['cmd-content', 'subdir', 'bar.txt'], 'bar.txt 2\n') test.not_up_to_date(arguments='cmd-content.out') test.up_to_date(arguments='cmd-content-noscan.out') -test.write([ 'cmd-content', 'subdir', 'new.txt' ], 'new.txt\n') +test.write(['cmd-content', 'subdir', 'new.txt'], 'new.txt\n') test.not_up_to_date(arguments='cmd-content.out') test.up_to_date(arguments='cmd-content-noscan.out') diff --git a/test/Libs/LIBPATH.py b/test/Libs/LIBPATH.py index b5a1b54..d663e56 100644 --- a/test/Libs/LIBPATH.py +++ b/test/Libs/LIBPATH.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,9 +22,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 os.path import time @@ -40,20 +40,17 @@ test.subdir('lib1', 'lib2') prog1 = test.workpath('prog') + _exe prog2 = test.workpath(dll_ + 'shlib') + _dll -test.write('SConstruct', """ -env1 = Environment(LIBS = [ 'foo1' ], - LIBPATH = [ '$FOO' ], - FOO='./lib1') +test.write('SConstruct', """\ +env1 = Environment(LIBS=['foo1'], LIBPATH=['$FOO'], FOO='./lib1') f1 = env1.SharedObject('f1', 'f1.c') -env1.Program(target = 'prog', source = 'prog.c') -env1.Library(target = './lib1/foo1', source = f1) +env1.Program(target='prog', source='prog.c') +env1.Library(target='./lib1/foo1', source=f1) -env2 = Environment(LIBS = 'foo2', - LIBPATH = '.') -env2.SharedLibrary(target = 'shlib', source = 'shlib.c', no_import_lib = 1) -env2.Library(target = 'foo2', source = f1) +env2 = Environment(LIBS='foo2', LIBPATH='.') +env2.SharedLibrary(target='shlib', source='shlib.c', no_import_lib=1) +env2.Library(target='foo2', source=f1) """) test.write('f1.c', r""" @@ -99,8 +96,8 @@ test.run(program = prog1, oldtime1 = os.path.getmtime(prog1) oldtime2 = os.path.getmtime(prog2) -time.sleep(2) -test.run(arguments = '.') +test.sleep() # delay for timestamps +test.run(arguments='.') test.fail_test(oldtime1 != os.path.getmtime(prog1)) test.fail_test(oldtime2 != os.path.getmtime(prog2)) @@ -115,30 +112,25 @@ f1(void) } """) -test.run(arguments = '.', - stderr=TestSCons.noisy_ar, - match=TestSCons.match_re_dotall) -test.run(program = prog1, - stdout = "f1.c 1\nprog.c\n") +test.run(arguments='.', stderr=TestSCons.noisy_ar, match=TestSCons.match_re_dotall) +test.run(program=prog1, stdout="f1.c 1\nprog.c\n") test.fail_test(oldtime2 == os.path.getmtime(prog2)) #test.up_to_date(arguments = '.') # Change LIBPATH and make sure we don't rebuild because of it. -test.write('SConstruct', """ -env1 = Environment(LIBS = [ 'foo1' ], - LIBPATH = [ './lib1', './lib2' ]) +test.write('SConstruct', """\ +env1 = Environment(LIBS=['foo1'], LIBPATH=['./lib1', './lib2']) f1 = env1.SharedObject('f1', 'f1.c') -env1.Program(target = 'prog', source = 'prog.c') -env1.Library(target = './lib1/foo1', source = f1) +env1.Program(target='prog', source='prog.c') +env1.Library(target='./lib1/foo1', source=f1) -env2 = Environment(LIBS = 'foo2', - LIBPATH = Split('. ./lib2')) -env2.SharedLibrary(target = 'shlib', source = 'shlib.c', no_import_lib = 1) -env2.Library(target = 'foo2', source = f1) +env2 = Environment(LIBS='foo2', LIBPATH=Split('. ./lib2')) +env2.SharedLibrary(target='shlib', source='shlib.c', no_import_lib=1) +env2.Library(target='foo2', source=f1) """) -test.up_to_date(arguments = '.', stderr=None) +test.up_to_date(arguments='.', stderr=None) test.write('f1.c', r""" #include <stdio.h> @@ -150,27 +142,22 @@ f1(void) } """) -test.run(arguments = '.', - stderr=TestSCons.noisy_ar, - match=TestSCons.match_re_dotall) -test.run(program = prog1, - stdout = "f1.c 2\nprog.c\n") +test.run(arguments='.', stderr=TestSCons.noisy_ar, match=TestSCons.match_re_dotall) +test.run(program=prog1, stdout="f1.c 2\nprog.c\n") -test.up_to_date(arguments = '.') +test.up_to_date(arguments='.') # We need at least one file for some implementations of the Library # builder, notably the SGI one. test.write('empty.c', 'int a=0;\n') # Check that a null-string LIBPATH doesn't blow up. -test.write('SConstruct', """ -env = Environment(LIBPATH = '') -env.Library('foo', source = 'empty.c') +test.write('SConstruct', """\ +env = Environment(LIBPATH='') +env.Library('foo', source='empty.c') """) -test.run(arguments = '.', - stderr=TestSCons.noisy_ar, - match=TestSCons.match_re_dotall) +test.run(arguments='.', stderr=TestSCons.noisy_ar, match=TestSCons.match_re_dotall) test.pass_test() diff --git a/test/PharLap.py b/test/PharLap.py index 8e56f21..0a54151 100644 --- a/test/PharLap.py +++ b/test/PharLap.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,9 +22,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__" import os import sys @@ -284,10 +283,10 @@ test.write([ "baz", "bar.lnk"],""" @asm.emb """) -test.write("SConstruct", """ -env=Environment(tools = [ 'linkloc', '386asm' ], - ASFLAGS='-twocase -cvsym', - LINKFLAGS='@foo.lnk') +test.write("SConstruct", """\ +env = Environment( + tools=['linkloc', '386asm'], ASFLAGS='-twocase -cvsym', LINKFLAGS='@foo.lnk' +) env.Program(target='minasm', source='minasm.asm') """) @@ -304,8 +303,8 @@ test.write([ "baz", "bar.lnk"],""" """) oldtime = os.path.getmtime(test.workpath('minasm.exe')) -time.sleep(2) # Give the time stamp time to change -test.run(arguments = '.') +test.sleep() # delay for timestamps +test.run(arguments='.') test.fail_test(oldtime == os.path.getmtime(test.workpath('minasm.exe'))) test.pass_test() diff --git a/test/Program.py b/test/Program.py index 15fd0c3..640787f 100644 --- a/test/Program.py +++ b/test/Program.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,9 +22,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__" import os.path import time @@ -40,13 +39,13 @@ foo4 = test.workpath('foo4' + _exe) foo5 = test.workpath('foo5' + _exe) foo_args = 'foo1%s foo2%s foo3%s foo4%s foo5%s' % (_exe, _exe, _exe, _exe, _exe) -test.write('SConstruct', """ +test.write('SConstruct', """\ env = Environment() -env.Program(target = 'foo1', source = 'f1.c') -env.Program(target = 'foo2', source = Split('f2a.c f2b.c f2c.c')) +env.Program(target='foo1', source='f1.c') +env.Program(target='foo2', source=Split('f2a.c f2b.c f2c.c')) f3a = File('f3a.c') f3b = File('f3b.c') -Program(target = 'foo3', source = [f3a, [f3b, 'f3c.c']]) +Program(target='foo3', source=[f3a, [f3b, 'f3c.c']]) env.Program('foo4', 'f4.c') env.Program('foo5.c') """) @@ -156,15 +155,14 @@ main(int argc, char *argv[]) } """) -test.run(arguments = '.') +test.run(arguments='.') -test.run(program = foo1, stdout = "f1.c\n") -test.run(program = foo2, stdout = "f2a.c\nf2b.c\nf2c.c\n") -test.run(program = foo3, stdout = "f3a.c\nf3b.c\nf3c.c\n") -test.run(program = foo4, stdout = "f4.c\n") -test.run(program = foo5, stdout = "foo5.c\n") - -test.up_to_date(arguments = '.') +test.run(program=foo1, stdout="f1.c\n") +test.run(program=foo2, stdout="f2a.c\nf2b.c\nf2c.c\n") +test.run(program=foo3, stdout="f3a.c\nf3b.c\nf3c.c\n") +test.run(program=foo4, stdout="f4.c\n") +test.run(program=foo5, stdout="foo5.c\n") +test.up_to_date(arguments='.') test.write('f1.c', r""" #include <stdio.h> @@ -211,15 +209,14 @@ main(int argc, char *argv[]) } """) -test.run(arguments = '.') - -test.run(program = foo1, stdout = "f1.c X\n") -test.run(program = foo2, stdout = "f2a.c\nf2b.c\nf2c.c\n") -test.run(program = foo3, stdout = "f3a.c\nf3b.c X\nf3c.c\n") -test.run(program = foo4, stdout = "f4.c X\n") -test.run(program = foo5, stdout = "foo5.c X\n") +test.run(arguments='.') -test.up_to_date(arguments = '.') +test.run(program=foo1, stdout="f1.c X\n") +test.run(program=foo2, stdout="f2a.c\nf2b.c\nf2c.c\n") +test.run(program=foo3, stdout="f3a.c\nf3b.c X\nf3c.c\n") +test.run(program=foo4, stdout="f4.c X\n") +test.run(program=foo5, stdout="foo5.c X\n") +test.up_to_date(arguments='.') # make sure the programs didn't get rebuilt, because nothing changed: oldtime1 = os.path.getmtime(foo1) @@ -228,10 +225,8 @@ oldtime3 = os.path.getmtime(foo3) oldtime4 = os.path.getmtime(foo4) oldtime5 = os.path.getmtime(foo5) -time.sleep(2) # introduce a small delay, to make the test valid - -test.run(arguments = foo_args) - +test.sleep() # delay for timestamps +test.run(arguments=foo_args) test.fail_test(oldtime1 != os.path.getmtime(foo1)) test.fail_test(oldtime2 != os.path.getmtime(foo2)) test.fail_test(oldtime3 != os.path.getmtime(foo3)) @@ -284,15 +279,14 @@ main(int argc, char *argv[]) } """) -test.run(arguments = foo_args) - -test.run(program = foo1, stdout = "f1.c Y\n") -test.run(program = foo2, stdout = "f2a.c\nf2b.c\nf2c.c\n") -test.run(program = foo3, stdout = "f3a.c\nf3b.c Y\nf3c.c\n") -test.run(program = foo4, stdout = "f4.c Y\n") -test.run(program = foo5, stdout = "foo5.c Y\n") +test.run(arguments=foo_args) -test.up_to_date(arguments = foo_args) +test.run(program=foo1, stdout="f1.c Y\n") +test.run(program=foo2, stdout="f2a.c\nf2b.c\nf2c.c\n") +test.run(program=foo3, stdout="f3a.c\nf3b.c Y\nf3c.c\n") +test.run(program=foo4, stdout="f4.c Y\n") +test.run(program=foo5, stdout="foo5.c Y\n") +test.up_to_date(arguments=foo_args) test.write('f1.c', r""" #include <stdio.h> @@ -340,15 +334,14 @@ main(int argc, char *argv[]) } """) -test.run(arguments = foo_args) - -test.run(program = foo1, stdout = "f1.c Z\n") -test.run(program = foo2, stdout = "f2a.c\nf2b.c\nf2c.c\n") -test.run(program = foo3, stdout = "f3a.c\nf3b.c Z\nf3c.c\n") -test.run(program = foo4, stdout = "f4.c Z\n") -test.run(program = foo5, stdout = "foo5.c Z\n") +test.run(arguments=foo_args) -test.up_to_date(arguments = foo_args) +test.run(program=foo1, stdout="f1.c Z\n") +test.run(program=foo2, stdout="f2a.c\nf2b.c\nf2c.c\n") +test.run(program=foo3, stdout="f3a.c\nf3b.c Z\nf3c.c\n") +test.run(program=foo4, stdout="f4.c Z\n") +test.run(program=foo5, stdout="foo5.c Z\n") +test.up_to_date(arguments=foo_args) # make sure the programs didn't get rebuilt, because nothing changed: oldtime1 = os.path.getmtime(foo1) @@ -357,10 +350,8 @@ oldtime3 = os.path.getmtime(foo3) oldtime4 = os.path.getmtime(foo4) oldtime5 = os.path.getmtime(foo5) -time.sleep(2) # introduce a small delay, to make the test valid - -test.run(arguments = foo_args) - +test.sleep() # delay for timestamps +test.run(arguments=foo_args) test.fail_test(not (oldtime1 == os.path.getmtime(foo1))) test.fail_test(not (oldtime2 == os.path.getmtime(foo2))) test.fail_test(not (oldtime3 == os.path.getmtime(foo3))) diff --git a/test/Repository/no-SConsignFile.py b/test/Repository/no-SConsignFile.py index d7f570c..6b5b3e2 100644 --- a/test/Repository/no-SConsignFile.py +++ b/test/Repository/no-SConsignFile.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,9 +22,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 that using Repository() works even when the Repository has no @@ -63,13 +62,10 @@ test.write(['src', 'foo.h'], """\ # Make sure it's past the max_drift time, # so the source file signatures get saved. -test.sleep(2) +test.sleep() # delay for timestamps test.run(chdir='build', arguments='.') - -test.run(program=test.workpath('build', 'foo'), - stdout="src/foo.h\nsrc/foo.c\n") - +test.run(program=test.workpath('build', 'foo'), stdout="src/foo.h\nsrc/foo.c\n") test.up_to_date(chdir='build', arguments='.') test.pass_test() diff --git a/test/Repository/variants.py b/test/Repository/variants.py index c95e853..a07d7a0 100644 --- a/test/Repository/variants.py +++ b/test/Repository/variants.py @@ -31,20 +31,22 @@ from TestSCons import TestSCons, _exe, _obj test = TestSCons() -test.subdir('repository', - ['repository', 'src1'], - ['repository', 'src2'], - ['repository', 'src2', 'include'], - ['repository', 'src2', 'xxx'], - ['repository', 'build2'], - ['repository', 'build2', 'foo'], - ['repository', 'build2', 'bar'], - 'work1', - ['work1', 'src1'], - 'work2', - ['work2', 'src2'], - ['work2', 'src2', 'include'], - ['work2', 'src2', 'xxx']) +test.subdir( + 'repository', + ['repository', 'src1'], + ['repository', 'src2'], + ['repository', 'src2', 'include'], + ['repository', 'src2', 'xxx'], + ['repository', 'build2'], + ['repository', 'build2', 'foo'], + ['repository', 'build2', 'bar'], + 'work1', + ['work1', 'src1'], + 'work2', + ['work2', 'src2'], + ['work2', 'src2', 'include'], + ['work2', 'src2', 'xxx'], +) aaa_obj = 'aaa' + _obj bbb_obj = 'bbb' + _obj @@ -56,14 +58,18 @@ repository_build1_foo_xxx = test.workpath('repository', 'build1', 'foo', 'xxx') work1_build1_foo_xxx = test.workpath('work1', 'build1', 'foo', 'xxx') work1_build1_bar_xxx = test.workpath('work1', 'build1', 'bar', 'xxx') -repository_build2_foo_src2_xxx_xxx = test.workpath('repository', 'build2', - 'foo', 'src2', 'xxx', 'xxx') -repository_build2_bar_src2_xxx_xxx = test.workpath('repository', 'build2', - 'bar', 'src2', 'xxx', 'xxx') -work2_build2_foo_src2_xxx_xxx = test.workpath('work2', 'build2', - 'foo', 'src2', 'xxx', 'xxx') -work2_build2_bar_src2_xxx_xxx = test.workpath('work2', 'build2', - 'bar', 'src2', 'xxx', 'xxx') +repository_build2_foo_src2_xxx_xxx = test.workpath( + 'repository', 'build2', 'foo', 'src2', 'xxx', 'xxx' +) +repository_build2_bar_src2_xxx_xxx = test.workpath( + 'repository', 'build2', 'bar', 'src2', 'xxx', 'xxx' +) +work2_build2_foo_src2_xxx_xxx = test.workpath( + 'work2', 'build2', 'foo', 'src2', 'xxx', 'xxx' +) +work2_build2_bar_src2_xxx_xxx = test.workpath( + 'work2', 'build2', 'bar', 'src2', 'xxx', 'xxx' +) opts = "-Y " + test.workpath('repository') @@ -73,12 +79,13 @@ OS = ARGUMENTS.get('OS', '') build1_os = "#build1/" + OS default = Environment() ccflags = { - '' : '', - 'foo' : '-DFOO', - 'bar' : '-DBAR', + '': '', + 'foo': '-DFOO', + 'bar': '-DBAR', } -env1 = Environment(CCFLAGS = default.subst('$CCFLAGS %s' % ccflags[OS]), - CPPPATH = build1_os) +env1 = Environment( + CCFLAGS=default.subst('$CCFLAGS %s' % ccflags[OS]), CPPPATH=build1_os +) VariantDir(build1_os, 'src1') SConscript(build1_os + '/SConscript', "env1") @@ -95,8 +102,9 @@ test.write(['repository', 'build2', 'foo', 'SConscript'], r""" VariantDir('src2', '#src2') default = Environment() -env2 = Environment(CCFLAGS = default.subst('$CCFLAGS -DFOO'), - CPPPATH = ['#src2/xxx', '#src2/include']) +env2 = Environment( + CCFLAGS=default.subst('$CCFLAGS -DFOO'), CPPPATH=['#src2/xxx', '#src2/include'] +) SConscript('src2/xxx/SConscript', "env2") """) @@ -105,8 +113,9 @@ test.write(['repository', 'build2', 'bar', 'SConscript'], r""" VariantDir('src2', '#src2') default = Environment() -env2 = Environment(CCFLAGS = default.subst('$CCFLAGS -DBAR'), - CPPPATH = ['#src2/xxx', '#src2/include']) +env2 = Environment( + CCFLAGS=default.subst('$CCFLAGS -DBAR'), CPPPATH=['#src2/xxx', '#src2/include'] +) SConscript('src2/xxx/SConscript', "env2") """) @@ -216,12 +225,9 @@ repository/src1/bbb.c: REPOSITORY_FOO repository/src1/main.c: REPOSITORY_FOO """) -database_name=test.get_sconsignname() - -test.fail_test(os.path.exists( - test.workpath('repository', 'src1', database_name))) -test.fail_test(os.path.exists( - test.workpath('repository', 'src2', database_name))) +database_name = test.get_sconsignname() +test.fail_test(os.path.exists(test.workpath('repository', 'src1', database_name))) +test.fail_test(os.path.exists(test.workpath('repository', 'src2', database_name))) test.fail_test(os.path.exists(test.workpath('work1', 'src1', database_name))) test.fail_test(os.path.exists(test.workpath('work2', 'src2', database_name))) @@ -237,10 +243,8 @@ repository/src2/xxx/include.h: BAR repository/src2/xxx/main.c: BAR """) -test.fail_test(os.path.exists( - test.workpath('repository', 'src1', database_name))) -test.fail_test(os.path.exists( - test.workpath('repository', 'src2', database_name))) +test.fail_test(os.path.exists(test.workpath('repository', 'src1', database_name))) +test.fail_test(os.path.exists(test.workpath('repository', 'src2', database_name))) test.fail_test(os.path.exists(test.workpath('work1', 'src1', database_name))) test.fail_test(os.path.exists(test.workpath('work2', 'src2', database_name))) @@ -251,15 +255,10 @@ test.writable('repository', 0) # test.up_to_date(chdir='work1', options=opts + " OS=foo", arguments='build1') -test.fail_test(os.path.exists( - test.workpath('work1', 'build1', 'foo', aaa_obj))) -test.fail_test(os.path.exists( - test.workpath('work1', 'build1', 'foo', bbb_obj))) -test.fail_test(os.path.exists(test.workpath( - 'work1', 'build1', 'foo', main_obj))) - -test.fail_test(os.path.exists( - test.workpath('work1', 'build1', 'foo', xxx_exe))) +test.fail_test(os.path.exists(test.workpath('work1', 'build1', 'foo', aaa_obj))) +test.fail_test(os.path.exists(test.workpath('work1', 'build1', 'foo', bbb_obj))) +test.fail_test(os.path.exists(test.workpath('work1', 'build1', 'foo', main_obj))) +test.fail_test(os.path.exists(test.workpath('work1', 'build1', 'foo', xxx_exe))) # test.run(chdir='work1', options=opts, arguments='OS=bar .') @@ -271,18 +270,13 @@ repository/src1/bbb.c: REPOSITORY_BAR repository/src1/main.c: REPOSITORY_BAR """) -test.fail_test(os.path.exists( - test.workpath('repository', 'src1', database_name))) -test.fail_test(os.path.exists( - test.workpath('repository', 'src2', database_name))) +test.fail_test(os.path.exists(test.workpath('repository', 'src1', database_name))) +test.fail_test(os.path.exists(test.workpath('repository', 'src2', database_name))) test.fail_test(os.path.exists(test.workpath('work1', 'src1', database_name))) test.fail_test(os.path.exists(test.workpath('work2', 'src2', database_name))) - test.up_to_date(chdir='work1', options=opts + " OS=bar", arguments='build1') -# Ensure file time stamps will be newer. -time.sleep(2) - +test.sleep() # delay for timestamps test.write(['work1', 'src1', 'iii.h'], r""" #ifdef FOO #define STRING "WORK_FOO" @@ -302,13 +296,10 @@ repository/src1/bbb.c: WORK_BAR repository/src1/main.c: WORK_BAR """) -test.fail_test(os.path.exists( - test.workpath('repository', 'src1', database_name))) -test.fail_test(os.path.exists( - test.workpath('repository', 'src2', database_name))) +test.fail_test(os.path.exists(test.workpath('repository', 'src1', database_name))) +test.fail_test(os.path.exists(test.workpath('repository', 'src2', database_name))) test.fail_test(os.path.exists(test.workpath('work1', 'src1', database_name))) test.fail_test(os.path.exists(test.workpath('work2', 'src2', database_name))) - test.up_to_date(chdir='work1', options=opts + " OS=bar", arguments='build1') # @@ -320,38 +311,39 @@ repository/src1/bbb.c: WORK_FOO repository/src1/main.c: WORK_FOO """) -test.fail_test(os.path.exists( - test.workpath('repository', 'src1', database_name))) -test.fail_test(os.path.exists( - test.workpath('repository', 'src2', database_name))) +test.fail_test(os.path.exists(test.workpath('repository', 'src1', database_name))) +test.fail_test(os.path.exists(test.workpath('repository', 'src2', database_name))) test.fail_test(os.path.exists(test.workpath('work1', 'src1', database_name))) test.fail_test(os.path.exists(test.workpath('work2', 'src2', database_name))) - test.up_to_date(chdir='work1', options=opts + " OS=foo", arguments='build1') - -# test.up_to_date(chdir='work2', options=opts, arguments='build2') -test.fail_test(os.path.exists(test.workpath( - 'work2', 'build2', 'foo', 'src2', 'xxx', aaa_obj))) -test.fail_test(os.path.exists(test.workpath( - 'work2', 'build2', 'foo', 'src2', 'xxx', bbb_obj))) -test.fail_test(os.path.exists(test.workpath( - 'work2', 'build2', 'foo', 'src2', 'xxx', main_obj))) -test.fail_test(os.path.exists(test.workpath( - 'work2', 'build2', 'foo', 'src2', 'xxx', xxx_exe))) -test.fail_test(os.path.exists(test.workpath( - 'work2', 'build2', 'bar', 'src2', 'xxx', aaa_obj))) -test.fail_test(os.path.exists(test.workpath( - 'work2', 'build2', 'bar', 'src2', 'xxx', bbb_obj))) -test.fail_test(os.path.exists(test.workpath( - 'work2', 'build2', 'bar', 'src2', 'xxx', main_obj))) -test.fail_test(os.path.exists(test.workpath( - 'work2', 'build2', 'bar', 'src2', 'xxx', xxx_exe))) - -# Ensure file time stamps will be newer. -time.sleep(2) - +test.fail_test( + os.path.exists(test.workpath('work2', 'build2', 'foo', 'src2', 'xxx', aaa_obj)) +) +test.fail_test( + os.path.exists(test.workpath('work2', 'build2', 'foo', 'src2', 'xxx', bbb_obj)) +) +test.fail_test( + os.path.exists(test.workpath('work2', 'build2', 'foo', 'src2', 'xxx', main_obj)) +) +test.fail_test( + os.path.exists(test.workpath('work2', 'build2', 'foo', 'src2', 'xxx', xxx_exe)) +) +test.fail_test( + os.path.exists(test.workpath('work2', 'build2', 'bar', 'src2', 'xxx', aaa_obj)) +) +test.fail_test( + os.path.exists(test.workpath('work2', 'build2', 'bar', 'src2', 'xxx', bbb_obj)) +) +test.fail_test( + os.path.exists(test.workpath('work2', 'build2', 'bar', 'src2', 'xxx', main_obj)) +) +test.fail_test( + os.path.exists(test.workpath('work2', 'build2', 'bar', 'src2', 'xxx', xxx_exe)) +) + +test.sleep() # delay for timestamps test.write(['work2', 'src2', 'include', 'my_string.h'], r""" #ifdef FOO #define INCLUDE_OS "FOO" @@ -362,7 +354,6 @@ test.write(['work2', 'src2', 'include', 'my_string.h'], r""" #define INCLUDE_STRING "work2/src2/include/my_string.h: %s\n" """) -# test.run(chdir='work2', options=opts, arguments='build2') test.run(program=work2_build2_foo_src2_xxx_xxx, stdout="""\ @@ -377,16 +368,12 @@ repository/src2/xxx/include.h: BAR repository/src2/xxx/main.c: BAR """) -test.fail_test(os.path.exists( - test.workpath('repository', 'src1', database_name))) -test.fail_test(os.path.exists( - test.workpath('repository', 'src2', database_name))) +test.fail_test(os.path.exists(test.workpath('repository', 'src1', database_name))) +test.fail_test(os.path.exists(test.workpath('repository', 'src2', database_name))) test.fail_test(os.path.exists(test.workpath('work1', 'src1', database_name))) test.fail_test(os.path.exists(test.workpath('work2', 'src2', database_name))) -# Ensure file time stamps will be newer. -time.sleep(2) - +test.sleep() # delay for timestamps test.write(['work2', 'src2', 'xxx', 'include.h'], r""" #include <my_string.h> #ifdef FOO @@ -412,38 +399,37 @@ work2/src2/xxx/include.h: BAR repository/src2/xxx/main.c: BAR """) -test.fail_test(os.path.exists( - test.workpath('repository', 'src1', database_name))) -test.fail_test(os.path.exists( - test.workpath('repository', 'src2', database_name))) +test.fail_test(os.path.exists(test.workpath('repository', 'src1', database_name))) +test.fail_test(os.path.exists(test.workpath('repository', 'src2', database_name))) test.fail_test(os.path.exists(test.workpath('work1', 'src1', database_name))) test.fail_test(os.path.exists(test.workpath('work2', 'src2', database_name))) -# test.unlink(['work2', 'src2', 'include', 'my_string.h']) - test.run(chdir='work2', options=opts, arguments='build2') -test.run(program=work2_build2_foo_src2_xxx_xxx, stdout="""\ +test.run( + program=work2_build2_foo_src2_xxx_xxx, + stdout="""\ repository/src2/include/my_string.h: FOO work2/src2/xxx/include.h: FOO repository/src2/xxx/main.c: FOO -""") +""", +) -test.run(program=work2_build2_bar_src2_xxx_xxx, stdout="""\ +test.run( + program=work2_build2_bar_src2_xxx_xxx, + stdout="""\ repository/src2/include/my_string.h: BAR work2/src2/xxx/include.h: BAR repository/src2/xxx/main.c: BAR -""") +""", +) -test.fail_test(os.path.exists( - test.workpath('repository', 'src1', database_name))) -test.fail_test(os.path.exists( - test.workpath('repository', 'src2', database_name))) +test.fail_test(os.path.exists(test.workpath('repository', 'src1', database_name))) +test.fail_test(os.path.exists(test.workpath('repository', 'src2', database_name))) test.fail_test(os.path.exists(test.workpath('work1', 'src1', database_name))) test.fail_test(os.path.exists(test.workpath('work2', 'src2', database_name))) -# test.pass_test() # Local Variables: diff --git a/test/Touch.py b/test/Touch.py index 431cd6c..3538c7d 100644 --- a/test/Touch.py +++ b/test/Touch.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,9 +22,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 the Touch() Action works. @@ -34,30 +33,29 @@ import TestSCons test = TestSCons.TestSCons() -test.write('SConstruct', """ +test.write('SConstruct', """\ Execute(Touch('f1')) Execute(Touch(File('f1-File'))) + def cat(env, source, target): target = str(target[0]) with open(target, "wb") as f: for src in source: with open(str(src), "rb") as ifp: f.write(ifp.read()) + Cat = Action(cat) env = Environment() env.Command('f2.out', 'f2.in', [Cat, Touch("f3")]) env = Environment(FILE='f4') env.Command('f5.out', 'f5.in', [Touch("$FILE"), Cat]) -env.Command('f6.out', 'f6.in', [Cat, - Touch("Touch-$SOURCE"), - Touch("$TARGET-Touch")]) +env.Command('f6.out', 'f6.in', [Cat, Touch("Touch-$SOURCE"), Touch("$TARGET-Touch")]) # Make sure Touch works with a list of arguments env = Environment() -env.Command('f7.out', 'f7.in', [Cat, - Touch(["Touch-$SOURCE", - "$TARGET-Touch", - File("f8")])]) +env.Command( + 'f7.out', 'f7.in', [Cat, Touch(["Touch-$SOURCE", "$TARGET-Touch", File("f8")])] +) """) test.write('f1', "f1\n") @@ -70,11 +68,12 @@ test.write('f7.in', "f7.in\n") old_f1_time = os.path.getmtime(test.workpath('f1')) old_f1_File_time = os.path.getmtime(test.workpath('f1-File')) -expect = test.wrap_stdout(read_str = """\ +expect = test.wrap_stdout( + read_str="""\ Touch("f1") Touch("f1-File") """, - build_str = """\ + build_str="""\ cat(["f2.out"], ["f2.in"]) Touch("f3") Touch("f4") @@ -84,11 +83,11 @@ Touch("Touch-f6.in") Touch("f6.out-Touch") cat(["f7.out"], ["f7.in"]) Touch(["Touch-f7.in", "f7.out-Touch", "f8"]) -""") -test.run(options = '-n', arguments = '.', stdout = expect) - -test.sleep(2) +""", +) +test.run(options='-n', arguments='.', stdout=expect) +test.sleep() # delay for timestamps new_f1_time = os.path.getmtime(test.workpath('f1')) test.fail_test(old_f1_time != new_f1_time) new_f1_File_time = os.path.getmtime(test.workpath('f1-File')) diff --git a/test/chained-build.py b/test/chained-build.py index 871a593..10d0b46 100644 --- a/test/chained-build.py +++ b/test/chained-build.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,9 +22,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__" import TestSCons @@ -58,23 +57,20 @@ test.write(['w1', 'SConstruct1'], SConstruct1_contents) test.write(['w1', 'SConstruct2'], SConstruct2_contents) test.write(['w1', 'foo.in'], "foo.in 1") -test.run(chdir='w1', - arguments="--max-drift=0 -f SConstruct1 foo.mid", - stdout = test.wrap_stdout('build(["foo.mid"], ["foo.in"])\n')) - -test.run(chdir='w1', - arguments="--max-drift=0 -f SConstruct2 foo.out", - stdout = test.wrap_stdout('build(["foo.out"], ["foo.mid"])\n')) - -test.up_to_date(chdir='w1', - options="--max-drift=0 -f SConstruct1", - arguments="foo.mid") - -test.up_to_date(chdir='w1', - options="--max-drift=0 -f SConstruct2", - arguments="foo.out") - -test.sleep() # make sure foo.in rewrite has new mod-time +test.run( + chdir='w1', + arguments="--max-drift=0 -f SConstruct1 foo.mid", + stdout=test.wrap_stdout('build(["foo.mid"], ["foo.in"])\n'), +) +test.run( + chdir='w1', + arguments="--max-drift=0 -f SConstruct2 foo.out", + stdout=test.wrap_stdout('build(["foo.out"], ["foo.mid"])\n'), +) +test.up_to_date(chdir='w1', options="--max-drift=0 -f SConstruct1", arguments="foo.mid") +test.up_to_date(chdir='w1', options="--max-drift=0 -f SConstruct2", arguments="foo.out") + +test.sleep() # delay for timestamps test.write(['w1', 'foo.in'], "foo.in 2") # Because we're using --max-drift=0, we use the cached csig value @@ -86,17 +82,19 @@ test.up_to_date(chdir='w1', # Now try with --max-drift disabled. The build of foo.out should still # be considered up-to-date, but the build of foo.mid now detects the # change and rebuilds, too, which then causes a rebuild of foo.out. -test.up_to_date(chdir='w1', - options="--max-drift=-1 -f SConstruct2", - arguments="foo.out") - -test.run(chdir='w1', - arguments="--max-drift=-1 -f SConstruct1 foo.mid", - stdout = test.wrap_stdout('build(["foo.mid"], ["foo.in"])\n')) - -test.run(chdir='w1', - arguments="--max-drift=-1 -f SConstruct2 foo.out", - stdout = test.wrap_stdout('build(["foo.out"], ["foo.mid"])\n')) +test.up_to_date( + chdir='w1', options="--max-drift=-1 -f SConstruct2", arguments="foo.out" +) +test.run( + chdir='w1', + arguments="--max-drift=-1 -f SConstruct1 foo.mid", + stdout=test.wrap_stdout('build(["foo.mid"], ["foo.in"])\n'), +) +test.run( + chdir='w1', + arguments="--max-drift=-1 -f SConstruct2 foo.out", + stdout=test.wrap_stdout('build(["foo.out"], ["foo.mid"])\n'), +) test.pass_test() diff --git a/test/sconsign/script/Signatures.py b/test/sconsign/script/Signatures.py index ef8bac0..2225f83 100644 --- a/test/sconsign/script/Signatures.py +++ b/test/sconsign/script/Signatures.py @@ -44,8 +44,8 @@ if NEED_HELPER: # in the expected output because paths in the .sconsign files are # canonicalized to use / as the separator. -sub1_hello_c = 'sub1/hello.c' -sub1_hello_obj = 'sub1/hello.obj' +sub1_hello_c = 'sub1/hello.c' +sub1_hello_obj = 'sub1/hello.obj' test.subdir('sub1', 'sub2') @@ -135,7 +135,7 @@ env2.Program('sub2/hello.c') """, ) # TODO in the above, we would normally want to run a python program -# using "our python" like this: +# using "our Python" like this: # CCCOM=[[r'{_python_}', r'{fake_cc_py}', 'sub2', '$TARGET', '$SOURCE']], # LINKCOM=[[r'{_python_}', r'{fake_link_py}', '$TARGET', '$SOURCE']], # however we're looking at dependencies with sconsign, so that breaks things. @@ -160,17 +160,16 @@ test.write(['sub2', 'inc2.h'], r"""\ #define STRING2 "inc2.h" """) -test.sleep() - +test.sleep() # delay for timestamps test.run(arguments = '. --max-drift=1') sig_re = r'[0-9a-fA-F]{32,64}' date_re = r'\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' - database_name = test.get_sconsignname() -test.run_sconsign(arguments = f"-e hello.exe -e hello.obj sub1/{database_name}", - stdout = r"""hello.exe: %(sig_re)s \d+ \d+ +test.run_sconsign( + arguments=f"-e hello.exe -e hello.obj sub1/{database_name}", + stdout=r"""hello.exe: %(sig_re)s \d+ \d+ %(sub1_hello_obj)s: %(sig_re)s \d+ \d+ fake_link\.py: None \d+ \d+ %(sig_re)s \[.*\] @@ -178,10 +177,12 @@ hello.obj: %(sig_re)s \d+ \d+ %(sub1_hello_c)s: None \d+ \d+ fake_cc\.py: None \d+ \d+ %(sig_re)s \[.*\] -""" % locals()) +""" % locals(), +) -test.run_sconsign(arguments = f"-e hello.exe -e hello.obj -r sub1/{database_name}", - stdout = r"""hello.exe: %(sig_re)s '%(date_re)s' \d+ +test.run_sconsign( + arguments=f"-e hello.exe -e hello.obj -r sub1/{database_name}", + stdout=r"""hello.exe: %(sig_re)s '%(date_re)s' \d+ %(sub1_hello_obj)s: %(sig_re)s '%(date_re)s' \d+ fake_link\.py: None '%(date_re)s' \d+ %(sig_re)s \[.*\] @@ -189,7 +190,8 @@ hello.obj: %(sig_re)s '%(date_re)s' \d+ %(sub1_hello_c)s: None '%(date_re)s' \d+ fake_cc\.py: None '%(date_re)s' \d+ %(sig_re)s \[.*\] -""" % locals()) +""" % locals(), +) test.pass_test() diff --git a/test/sconsign/script/dblite.py b/test/sconsign/script/dblite.py index 1fcf8c0..24d8403 100644 --- a/test/sconsign/script/dblite.py +++ b/test/sconsign/script/dblite.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,9 +22,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 various ways of getting at a an sconsign file written with @@ -97,17 +96,11 @@ main(int argc, char *argv[]) } """) -test.write(['sub2', 'inc1.h'], r"""\ -#define STRING1 "inc1.h" -""") - -test.write(['sub2', 'inc2.h'], r"""\ -#define STRING2 "inc2.h" -""") - -test.sleep() +test.write(['sub2', 'inc1.h'], r'#define STRING1 "inc1.h"') +test.write(['sub2', 'inc2.h'], r'#define STRING2 "inc2.h"') -test.run(arguments = '. --max-drift=1') +test.sleep() # delay for timestamps +test.run(arguments='. --max-drift=1') sig_re = r'[0-9a-fA-F]{32,64}' date_re = r'\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d' @@ -146,23 +139,23 @@ hello%(_obj)s: %(sig_re)s '%(date_re)s' \d+ common_flags = '-e hello%(_exe)s -e hello%(_obj)s -d sub1' % locals() -test.run_sconsign(arguments = "%s my_sconsign" % common_flags, - stdout = expect) +test.run_sconsign(arguments="%s my_sconsign" % common_flags, stdout=expect) -test.run_sconsign(arguments = "%s my_sconsign.dblite" % common_flags, - stdout = expect) +test.run_sconsign(arguments="%s my_sconsign.dblite" % common_flags, stdout=expect) -test.run_sconsign(arguments = "%s -f dblite my_sconsign" % common_flags, - stdout = expect) +test.run_sconsign(arguments="%s -f dblite my_sconsign" % common_flags, stdout=expect) -test.run_sconsign(arguments = "%s -f dblite my_sconsign.dblite" % common_flags, - stdout = expect) +test.run_sconsign( + arguments="%s -f dblite my_sconsign.dblite" % common_flags, stdout=expect +) -test.run_sconsign(arguments = "%s -r -f dblite my_sconsign" % common_flags, - stdout = expect_r) +test.run_sconsign( + arguments="%s -r -f dblite my_sconsign" % common_flags, stdout=expect_r +) -test.run_sconsign(arguments = "%s -r -f dblite my_sconsign.dblite" % common_flags, - stdout = expect_r) +test.run_sconsign( + arguments="%s -r -f dblite my_sconsign.dblite" % common_flags, stdout=expect_r +) test.pass_test() diff --git a/testing/framework/TestCmdTests.py b/testing/framework/TestCmdTests.py index 212c59a..3b29091 100644 --- a/testing/framework/TestCmdTests.py +++ b/testing/framework/TestCmdTests.py @@ -3389,8 +3389,10 @@ if __name__ == "__main__": ]) suite = unittest.TestSuite() for tclass in tclasses: - names = unittest.getTestCaseNames(tclass, 'test_') - suite.addTests([ tclass(n) for n in names ]) + loader = unittest.TestLoader() + loader.testMethodPrefix = 'test_' + names = loader.getTestCaseNames(tclass) + suite.addTests([tclass(n) for n in names]) if not unittest.TextTestRunner().run(suite).wasSuccessful(): sys.exit(1) diff --git a/testing/framework/TestCommonTests.py b/testing/framework/TestCommonTests.py index 03a5508..dff7a50 100644 --- a/testing/framework/TestCommonTests.py +++ b/testing/framework/TestCommonTests.py @@ -2429,8 +2429,10 @@ if __name__ == "__main__": ] suite = unittest.TestSuite() for tclass in tclasses: - names = unittest.getTestCaseNames(tclass, 'test_') - suite.addTests([ tclass(n) for n in names ]) + loader = unittest.TestLoader() + loader.testMethodPrefix = 'test_' + names = loader.getTestCaseNames(tclass) + suite.addTests([tclass(n) for n in names]) if not unittest.TextTestRunner().run(suite).wasSuccessful(): sys.exit(1) |