From b28e86d47635d1ae4ae63eac603f166ec7c95221 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Tue, 1 Nov 2022 09:44:54 -0600 Subject: Split out CPPDEFINES handling in Append methods Rather than having lots of special-case code for CPPDEFINES in four separate routines, add a new _add_cppdefines function to handle it, paying attention to append/prepend, unique/duplicating, and keep-original/replace-original. The existing special case handing was then removed from Append and AppendUnique (it was never present in Prepend and PrependUnique anyway - see #3876, but these now get it due to a call to the new function). Tuple handling is now consistent with list handling: a single tuple is treated as macro names to add, not as a name=value pair. A tuple or list has to be a member of a containing tuple or list to get the macro=value treatment. This *may* affect some existing usage. macro=value tuples without a value can now be entered either in (macro,) form or (macro, None) form. Internally, whenever append/prepend is done, existing contents are forced to a deque, which allows efficient adding at either end without resorting to the tricks the Prepend functions currently do (they still do these tricks, but only in non-CPPDEFINES cases). As a result, values from a dict are not stored as a dict, which has some effect on ordering: values will be *consistently* ordered, but the ones from the dict are no longer necessarily sorted. In SCons/Defaults.py, processDefines no longer sorts a dict it is passed, since Python now preserves dict order. This does not affect the E2E test for CPPDEFINES - since those all call an Append routine, CPPDEFINES will always be a deque, and so processDefines never sees a dict in that case. It could well affect real-life usage - if setup of CPPDEFINES was such that it used to contain a dict with multiple entries, the order might change (sorting would have presented the keys from that dict in alphabetical order). This would lead to a one-time rebuild for actions that change (after that it will remain consistent). In the E2E test CPPDEFINES/append.py some bits were reformatted, and the handler routine now accounts for the type being a deque - since the test does a text comparison of internally produced output, it failed if the word "deque" appeared. Some new test cases were added to also exercise strings with spaces embedded in them. Changes were made to the expected output of the E2E test. These reflect changes in the way data is now stored in CPPDEFINES, and in some cases in order. Most of these do not change the meaning (i.e. "result" changes, but "final" output is the same). These are the exceptions: - "appending a dict to a list-of-2lists", AppendUnique case: order now preserved as entered (previously took the order of the appended dict) - "appending a string to a dict", Append case: not stored as a dict, so ordering is as originally entered. - "appending a dict to a dict", Append case: no longer merge into a dict, so this is now an actual append rather than a merge of dicts which caused the uniquing effect even without calling AppendUnique (arguably the old way was incorrect). A new test/CPPDEFINES/prepend.py is added to test Prepend* cases. append.py and prepend.py are structured to fetch the SConstruct from a fixture file. append.py got an added test in the main text matrix, a string of the macro=value form. The same 5x5 maxtrix is used in the new prepend.py test as well ("expected" values for these had to be added as well). Cosmetically, append and prepend now print their test summary so strings have quotation marks - the "orig" lines in the expected output was adjusted. This change looks like: - orig = FOO, append = FOO + orig = 'FOO', append = 'FOO' The other tests in test/CPPDEFINES got copyright updating and reformatting, but otherwise do not change. Documentation updated to clarify behavior. Fixes #4254 Fixes #3876 Signed-off-by: Mats Wichmann --- CHANGES.txt | 19 +- RELEASE.txt | 24 ++- SCons/Defaults.py | 95 ++++----- SCons/Defaults.xml | 95 ++++++--- SCons/Environment.py | 306 +++++++++++++++++------------ SCons/Environment.xml | 247 ++++++++++++++--------- SCons/Util/types.py | 24 +-- test/CPPDEFINES/append.py | 214 +++++++++++--------- test/CPPDEFINES/basic.py | 55 ++++-- test/CPPDEFINES/fixture/SConstruct-Append | 99 ++++++++++ test/CPPDEFINES/fixture/SConstruct-Prepend | 100 ++++++++++ test/CPPDEFINES/live.py | 33 ++-- test/CPPDEFINES/pkg-config.py | 50 +++-- test/CPPDEFINES/prepend.py | 258 ++++++++++++++++++++++++ test/CPPDEFINES/scan.py | 32 +-- test/CPPDEFINES/undefined.py | 13 +- 16 files changed, 1179 insertions(+), 485 deletions(-) create mode 100644 test/CPPDEFINES/fixture/SConstruct-Append create mode 100644 test/CPPDEFINES/fixture/SConstruct-Prepend create mode 100644 test/CPPDEFINES/prepend.py diff --git a/CHANGES.txt b/CHANGES.txt index 5a3651a..41a966b 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -133,6 +133,17 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER Also added "unique" keyword, to control whether a library is added or not if it is already in the $LIBS construction var in the configure context. (issue #2768). + - Special-case handling for CPPDEFINES in the Append/Prepend routines + split out into its own function to simplify the remaining code and + fix problems. The e2e test test/CPPDEFINES/append.py is expanded + to cover missed cases, and AppendUnique no longer mismatches with + what Append does (#3876). Inconsistent handling of tuples to specify + macro=value outputs is also cleaned up (#4254). The special handling + now also works for Prepend/PrependUnique, and a corresponding test + test/CPPDEFINES/prepend.py was added to verify the behavior. + SCons used to sort keys set or appended via a dict type, in order to + assure order of commandline flags did not change across runs. This + behavior has been dropped since Python now assures consistent dict order. RELEASE 4.4.0 - Sat, 30 Jul 2022 14:08:29 -0700 @@ -295,16 +306,16 @@ RELEASE 4.4.0 - Sat, 30 Jul 2022 14:08:29 -0700 - Ninja:Added user configurable setting of ninja depfile format via NINJA_DEPFILE_PARSE_FORMAT. Now setting NINJA_DEPFILE_PARSE_FORMAT to [msvc,gcc,clang] can force the ninja expected format. Compiler tools will also configure the variable automatically. - - Ninja: Made ninja tool force the ninja file as the only target. + - Ninja: Made ninja tool force the ninja file as the only target. - Ninja: Improved the default targets setup and made sure there is always a default target for the ninja file, which excludes targets that start and stop the daemon. - Ninja: Update ninja tool so targets passed to SCons are propagated to ninja when scons automatically executes ninja. - - Small refactor of scons daemons using a shared StateInfo class for communication + - 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. - 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 + - 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 @@ -546,7 +557,7 @@ RELEASE 4.2.0 - Sat, 31 Jul 2021 18:12:46 -0700 - Fix Issue #3906 - `IMPLICIT_COMMAND_DEPENDENCIES` was not properly disabled when set to any string value (For example ['none','false','no','off']) Also previously 'All' wouldn't have the desired affect. - + From Ivan Kravets: - Provide a custom argument escape function for `TempFileMunge` using a new `TEMPFILEARGESCFUNC` variable. Useful if you need to apply extra operations on diff --git a/RELEASE.txt b/RELEASE.txt index 6c1c5f2..1bf6bf8 100644 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -51,7 +51,12 @@ CHANGED/ENHANCED EXISTING FUNCTIONALITY which controls whether to add the library if it is already in the $LIBS list. This brings the library-adding functionality in Configure in line with the regular Append, AppendUnique, Prepend and PrependUnique methods. - +- CPPDEFINES values added via a dictionary type are longer sorted by + key. This used to be required to maintain a consistent order of + commandline arguments between SCons runs, but meant macros were not + always emitted in the order entered. Sorting is no longer required + after Python interpreter improvements. There might be a one-time + rebuild of targets that involved such sorted keys in their actions. FIXES ----- @@ -90,7 +95,17 @@ FIXES actual build would not see the file as modified. Leading to incorrect incremental builds. Now configure checks now clear node info for non conftest nodes, so they will be re-evaluated for the real taskmaster run when the build commences. - +- Inconsistent behavior of adding CPPDEFINES values via tuple arguments + has been cleaned up (problems described in issue #4254). In order to + achieve consistency, a rule for for adding macros-with-values via a + tuple (or list) is now enforced: they need to be entered as members + of a containing sequence. ["NAME", "VALUE"] and ("NAME", "VALUE") + are now treated the same (two individual macro names), rather than + the latter sometimes, but not always, being handled as a single + NAME=VALUE macro. Use a construct like [("NAME", "VALUE")] to get the + macro-with-value behavior. +- Handling of CPPDEFINES macros via Prepend and PrependUnique now works + (previously this was special-cased only for Append and AppendUnique). IMPROVEMENTS ------------ @@ -133,12 +148,17 @@ DOCUMENTATION - Updated the User Guide chapter on installation: modernized the notes on Python installs, SCons installs, and having multiple SCons versions present on a single system. +<<<<<<< HEAD - Updated the User Guide chapter on variant directories with more explanation, and the introduction of terms like "out of tree" that may help in forming a mental model. - Additional explanations for MSVSProject and MSVSSolution builders. - Updated MSVC documentation - adds "version added" annotations on recently added construction variables and provides a version-mapping table. +======= +- Added further details in the documentation of Append and related methods + on the special handling of CPPDEFINES. +>>>>>>> d9a82d681 (Split out CPPDEFINES handling in Append methods) DEVELOPMENT ----------- diff --git a/SCons/Defaults.py b/SCons/Defaults.py index 40c3e4a..da90260 100644 --- a/SCons/Defaults.py +++ b/SCons/Defaults.py @@ -36,6 +36,7 @@ import shutil import stat import sys import time +from collections import deque import SCons.Action import SCons.Builder @@ -46,7 +47,7 @@ import SCons.PathList import SCons.Scanner.Dir import SCons.Subst import SCons.Tool -import SCons.Util +from SCons.Util import is_List, is_String, is_Tuple, is_Dict, flatten # A placeholder for a default Environment (for fetching source files # from source code management systems and the like). This must be @@ -166,7 +167,7 @@ def get_paths_str(dest) -> str: def quote(arg): return f'"{arg}"' - if SCons.Util.is_List(dest): + if is_List(dest): elem_strs = [quote(d) for d in dest] return f'[{", ".join(elem_strs)}]' else: @@ -202,11 +203,11 @@ def chmod_func(dest, mode) -> None: """ from string import digits SCons.Node.FS.invalidate_node_memos(dest) - if not SCons.Util.is_List(dest): + if not is_List(dest): dest = [dest] - if SCons.Util.is_String(mode) and 0 not in [i in digits for i in mode]: + if is_String(mode) and 0 not in [i in digits for i in mode]: mode = int(mode, 8) - if not SCons.Util.is_String(mode): + if not is_String(mode): for element in dest: os.chmod(str(element), mode) else: @@ -244,7 +245,7 @@ def chmod_func(dest, mode) -> None: def chmod_strfunc(dest, mode) -> str: """strfunction for the Chmod action function.""" - if not SCons.Util.is_String(mode): + if not is_String(mode): return f'Chmod({get_paths_str(dest)}, {mode:#o})' else: return f'Chmod({get_paths_str(dest)}, "{mode}")' @@ -272,10 +273,10 @@ def copy_func(dest, src, symlinks=True) -> int: """ dest = str(dest) - src = [str(n) for n in src] if SCons.Util.is_List(src) else str(src) + src = [str(n) for n in src] if is_List(src) else str(src) SCons.Node.FS.invalidate_node_memos(dest) - if SCons.Util.is_List(src): + if is_List(src): # this fails only if dest exists and is not a dir try: os.makedirs(dest, exist_ok=True) @@ -322,7 +323,7 @@ def delete_func(dest, must_exist=False) -> None: unless *must_exist* evaluates false (the default). """ SCons.Node.FS.invalidate_node_memos(dest) - if not SCons.Util.is_List(dest): + if not is_List(dest): dest = [dest] for entry in dest: entry = str(entry) @@ -348,7 +349,7 @@ Delete = ActionFactory(delete_func, delete_strfunc) def mkdir_func(dest) -> None: """Implementation of the Mkdir action function.""" SCons.Node.FS.invalidate_node_memos(dest) - if not SCons.Util.is_List(dest): + if not is_List(dest): dest = [dest] for entry in dest: os.makedirs(str(entry), exist_ok=True) @@ -372,7 +373,7 @@ Move = ActionFactory( def touch_func(dest) -> None: """Implementation of the Touch action function.""" SCons.Node.FS.invalidate_node_memos(dest) - if not SCons.Util.is_List(dest): + if not is_List(dest): dest = [dest] for file in dest: file = str(file) @@ -433,7 +434,7 @@ def _concat_ixes(prefix, items_iter, suffix, env): prefix = str(env.subst(prefix, SCons.Subst.SUBST_RAW)) suffix = str(env.subst(suffix, SCons.Subst.SUBST_RAW)) - for x in SCons.Util.flatten(items_iter): + for x in flatten(items_iter): if isinstance(x, SCons.Node.FS.File): result.append(x) continue @@ -479,8 +480,8 @@ def _stripixes(prefix, itms, suffix, stripprefixes, stripsuffixes, env, c=None): else: c = _concat_ixes - stripprefixes = list(map(env.subst, SCons.Util.flatten(stripprefixes))) - stripsuffixes = list(map(env.subst, SCons.Util.flatten(stripsuffixes))) + stripprefixes = list(map(env.subst, flatten(stripprefixes))) + stripsuffixes = list(map(env.subst, flatten(stripsuffixes))) stripped = [] for l in SCons.PathList.PathList(itms).subst_path(env, None, None): @@ -488,7 +489,7 @@ def _stripixes(prefix, itms, suffix, stripprefixes, stripsuffixes, env, c=None): stripped.append(l) continue - if not SCons.Util.is_String(l): + if not is_String(l): l = str(l) for stripprefix in stripprefixes: @@ -511,49 +512,49 @@ def _stripixes(prefix, itms, suffix, stripprefixes, stripsuffixes, env, c=None): def processDefines(defs): - """process defines, resolving strings, lists, dictionaries, into a list of - strings + """Return list of strings for preprocessor defines from *defs*. + + Resolves all the different forms CPPDEFINES can be assembled in. + Any prefix/suffix is handled elsewhere (usually :func:`_concat_ixes`). """ - if SCons.Util.is_List(defs): - l = [] - for d in defs: - if d is None: + dlist = [] + if is_List(defs): + for define in defs: + if define is None: continue - elif SCons.Util.is_List(d) or isinstance(d, tuple): - if len(d) >= 2: - l.append(str(d[0]) + '=' + str(d[1])) + elif is_List(define) or is_Tuple(define): + if len(define) >= 2 and define[1] is not None: + # TODO: do we need to quote define[1] if it contains space? + dlist.append(str(define[0]) + '=' + str(define[1])) else: - l.append(str(d[0])) - elif SCons.Util.is_Dict(d): - for macro, value in d.items(): + dlist.append(str(define[0])) + elif is_Dict(define): + for macro, value in define.items(): if value is not None: - l.append(str(macro) + '=' + str(value)) + # TODO: do we need to quote value if it contains space? + dlist.append(str(macro) + '=' + str(value)) else: - l.append(str(macro)) - elif SCons.Util.is_String(d): - l.append(str(d)) + dlist.append(str(macro)) + elif is_String(define): + dlist.append(str(define)) else: - raise SCons.Errors.UserError("DEFINE %s is not a list, dict, string or None." % repr(d)) - elif SCons.Util.is_Dict(defs): - # The items in a dictionary are stored in random order, but - # if the order of the command-line options changes from - # invocation to invocation, then the signature of the command - # line will change and we'll get random unnecessary rebuilds. - # Consequently, we have to sort the keys to ensure a - # consistent order... - l = [] - for k, v in sorted(defs.items()): - if v is None: - l.append(str(k)) + raise SCons.Errors.UserError( + f"DEFINE {d!r} is not a list, dict, string or None." + ) + elif is_Dict(defs): + for macro, value in defs.items(): + if value is None: + dlist.append(str(macro)) else: - l.append(str(k) + '=' + str(v)) + dlist.append(str(macro) + '=' + str(value)) else: - l = [str(defs)] - return l + dlist.append(str(defs)) + + return dlist def _defines(prefix, defs, suffix, env, target=None, source=None, c=_concat_ixes): - """A wrapper around _concat_ixes that turns a list or string + """A wrapper around :func:`_concat_ixes` that turns a list or string into a list of C preprocessor command-line definitions. """ diff --git a/SCons/Defaults.xml b/SCons/Defaults.xml index 27b0882..7b37475 100644 --- a/SCons/Defaults.xml +++ b/SCons/Defaults.xml @@ -92,68 +92,111 @@ to each definition in &cv-link-CPPDEFINES;. A platform independent specification of C preprocessor macro definitions. -The definitions will be added to command lines +The definitions are added to command lines through the automatically-generated -&cv-link-_CPPDEFFLAGS; &consvar; (see above), +&cv-link-_CPPDEFFLAGS; &consvar;, which is constructed according to -the type of value of &cv-CPPDEFINES;: +the contents of &cv-CPPDEFINES;: + + If &cv-CPPDEFINES; is a string, the values of the &cv-link-CPPDEFPREFIX; and &cv-link-CPPDEFSUFFIX; &consvars; -will be respectively prepended and appended to -each definition in &cv-link-CPPDEFINES;. +are respectively prepended and appended to +each definition in &cv-CPPDEFINES;, +split on whitespace. -# Will add -Dxyz to POSIX compiler command lines, +# Adds -Dxyz to POSIX compiler command lines, # and /Dxyz to Microsoft Visual C++ command lines. env = Environment(CPPDEFINES='xyz') + + If &cv-CPPDEFINES; is a list, the values of the &cv-CPPDEFPREFIX; and &cv-CPPDEFSUFFIX; &consvars; -will be respectively prepended and appended to +are respectively prepended and appended to each element in the list. -If any element is a list or tuple, -then the first item is the name being -defined and the second item is its value: +If any element is a tuple (or list) +then the first item of the tuple is the macro name +and the second is the macro definition. +If the definition is not omitted or None, +the name and definition are combined into a single +name=definition item +before the preending/appending. -# Will add -DB=2 -DA to POSIX compiler command lines, +# Adds -DB=2 -DA to POSIX compiler command lines, # and /DB=2 /DA to Microsoft Visual C++ command lines. env = Environment(CPPDEFINES=[('B', 2), 'A']) + + If &cv-CPPDEFINES; is a dictionary, the values of the &cv-CPPDEFPREFIX; and &cv-CPPDEFSUFFIX; &consvars; -will be respectively prepended and appended to -each item from the dictionary. -The key of each dictionary item -is a name being defined -to the dictionary item's corresponding value; -if the value is -None, -then the name is defined without an explicit value. -Note that the resulting flags are sorted by keyword -to ensure that the order of the options on the -command line is consistent each time -&scons; -is run. +are respectively prepended and appended to +each key from the dictionary. +If the value for a key is not None, +then the key (macro name) and the value +(macros definition) are combined into a single +name=definition item +before the prepending/appending. -# Will add -DA -DB=2 to POSIX compiler command lines, -# and /DA /DB=2 to Microsoft Visual C++ command lines. +# Adds -DA -DB=2 to POSIX compiler command lines, +# or /DA /DB=2 to Microsoft Visual C++ command lines. env = Environment(CPPDEFINES={'B':2, 'A':None}) + + + + +Depending on how contents are added to &cv-CPPDEFINES;, +it may be transformed into a compound type, +for example a list containing strings, tuples and/or dictionaries. +&SCons; can correctly expand such a compound type. + + + +Note that &SCons; may call the compiler via a shell. +If a macro definition contains characters such as spaces that +have meaning to the shell, or is intended to be a string value, +you may need to use the shell's quoting syntax to avoid +interpretation by the shell before the preprocessor sees it. +Function-like macros are not supported via this mechanism +(and some compilers do not even implement that functionality +via the command lines). +When quoting, note that +one set of quote characters are used to define a &Python; string, +then quotes embedded inside that would be consumed by the shell +unless escaped. These examples may help illustrate: + + + +env = Environment(CPPDEFINES=['USE_ALT_HEADER=\\"foo_alt.h\\"']) +env = Environment(CPPDEFINES=[('USE_ALT_HEADER', '\\"foo_alt.h\\"')]) + + + +:Changed in version 4.5: +&SCons; no longer sorts &cv-CPPDEFINES; values entered +in dictionary form. &Python; now preserves dictionary +keys in the order they are entered, so it is no longer +necessary to sort them to ensure a stable command line. + + diff --git a/SCons/Environment.py b/SCons/Environment.py index 7212c89..bc69f05 100644 --- a/SCons/Environment.py +++ b/SCons/Environment.py @@ -35,7 +35,7 @@ import os import sys import re import shlex -from collections import UserDict +from collections import UserDict, deque import SCons.Action import SCons.Builder @@ -193,6 +193,162 @@ def _delete_duplicates(l, keep_last): return result +def _add_cppdefines( + env_dict: dict, + val, # add annotation? + prepend: bool = False, + unique: bool = False, + delete_existing: bool = False, +) -> None: + """Adds to CPPDEFINES, using the rules for C preprocessor macros. + + Split out from regular construction variable handling because these + entries can express either a macro with a replacement list or one + without. A macro with replacement list can be supplied three ways: + as a combined string ``name=value``; as a tuple contained in + a sequence type ``[("name", value)]``; or as a dictionary entry + ``{"name": value}``. Appending/prepending can be unconditional + (duplicates allowed) or uniquing (no dupes). + + Note if a replacement list is supplied, "unique" requires a full + match - both the name and the replacement must be equal. + + Args: + env_dict: the dictionary containing the ``CPPDEFINES`` to be modified. + val: the value to add, can be string, sequence or dict + prepend: whether to put *val* in front or back. + unique: whether to add *val* if it already exists. + delete_existing: if *unique* is true, add *val* after removing previous. + """ + + def _add_define(item, defines: deque, prepend: bool = False) -> None: + """Convenience function to prepend/append a single value. + + Sole purpose is to shorten code in the outer function. + """ + if prepend: + defines.appendleft(item) + else: + defines.append(item) + + + def _is_in(item, defines: deque): + """Returns match for *item* if found in *defines*. + + Accounts for type differences: ("FOO", "BAR"), ["FOO", "BAR"] + "FOO=BAR" and {"FOO": "BAR"} all iffer as far as Python equality + comparison is concerned, but are the same for purposes of creating + the preprocessor macro. Since the caller may wish to remove a + matched entry, we need to return it - cannot remove *item* + itself unless it happened to be an exact (type) match. + + Called from a place we know *defines* is always a deque, and + *item* will not be a dict, so don't need do much type checking. + If this ends up used more generally, would need to adjust that. + + Note implied assumption that members of a list-valued define + will not be dicts - we cannot actually guarantee this, since + if the initial add is a list its contents are not converted. + """ + def _macro_conv(v) -> list: + """Normalizes a macro to a list for comparisons.""" + if is_Tuple(v): + return list(v) + elif is_String(v): + return v.split("=") + return v + + if item in defines: # cheap check first + return item + + item = _macro_conv(item) + for define in defines: + if item == _macro_conv(define): + return define + + return False + + + key = 'CPPDEFINES' + try: + defines = env_dict[key] + except KeyError: + # This is a new entry, just save it as is. Defer conversion to + # deque until someone tries to amend the value, processDefines + # can handle all of these fine. + if is_String(val): + env_dict[key] = val.split() + else: + env_dict[key] = val + return + + # Convert type of existing to deque to simplify processing of addition - + # inserting at either end is cheap. + if isinstance(defines, deque): + # filter deques out to avoid catching in is_List check below + pass + elif is_String(defines): + env_dict[key] = deque(defines.split()) + elif is_Tuple(defines) or is_List(defines): + # a little extra work in case the initial container has dict + # item(s) inside it, so those can be matched by _is_in(). + result = deque() + for define in defines: + if is_Dict(define): + result.extend(define.items()) + else: + result.append(define) + env_dict[key] = result + elif is_Dict(defines): + env_dict[key] = deque(defines.items()) + else: + env_dict[key] = deque(defines) + defines = env_dict[key] # in case we reassigned it after the try block. + + if is_Dict(val): + # Unpack the dict while applying to existing + for item in val.items(): + if unique: + match = _is_in(item, defines) + if match and delete_existing: + defines.remove(match) + _add_define(item, defines, prepend) + elif not match: + _add_define(item, defines, prepend) + else: + _add_define(item, defines, prepend) + + elif is_String(val): + if unique: + match = _is_in(val, defines) + if match and delete_existing: + defines.remove(match) + _add_define(val, defines, prepend) + elif not match: + _add_define(val, defines, prepend) + else: + _add_define(val, defines, prepend) + + elif is_List(val): + tmp = [] + for item in val: + if unique: + match = _is_in(item, defines) + if match and delete_existing: + defines.remove(match) + tmp.append(item) + elif not match: + tmp.append(item) + else: + tmp.append(item) + + if prepend: + defines.extendleft(tmp) + else: + defines.extend(tmp) + + # else: # are there any other cases? processDefines doesn't think so. + # The following is partly based on code in a comment added by Peter # Shannon at the following page (there called the "transplant" class): @@ -837,8 +993,8 @@ class SubstitutionEnvironment: def MergeFlags(self, args, unique=True) -> None: """Merge flags into construction variables. - Merges the flags from ``args`` into this construction environent. - If ``args`` is not a dict, it is first converted to one with + Merges the flags from *args* into this construction environent. + If *args* is not a dict, it is first converted to one with flags distributed into appropriate construction variables. See :meth:`ParseFlags`. @@ -1215,16 +1371,15 @@ class Base(SubstitutionEnvironment): kw = copy_non_reserved_keywords(kw) for key, val in kw.items(): + if key == 'CPPDEFINES': + _add_cppdefines(self._dict, val) + continue + try: - if key == 'CPPDEFINES' and is_String(self._dict[key]): - self._dict[key] = [self._dict[key]] orig = self._dict[key] except KeyError: # No existing var in the environment, so set to the new value. - if key == 'CPPDEFINES' and is_String(val): - self._dict[key] = [val] - else: - self._dict[key] = val + self._dict[key] = val continue try: @@ -1263,19 +1418,8 @@ class Base(SubstitutionEnvironment): # things like UserList will incorrectly coerce the # original dict to a list (which we don't want). if is_List(val): - if key == 'CPPDEFINES': - tmp = [] - for (k, v) in orig.items(): - if v is not None: - tmp.append((k, v)) - else: - tmp.append((k,)) - orig = tmp - orig += val - self._dict[key] = orig - else: - for v in val: - orig[v] = None + for v in val: + orig[v] = None else: try: update_dict(val) @@ -1330,6 +1474,9 @@ class Base(SubstitutionEnvironment): """ kw = copy_non_reserved_keywords(kw) for key, val in kw.items(): + if key == 'CPPDEFINES': + _add_cppdefines(self._dict, val, unique=True, delete_existing=delete_existing) + continue if is_List(val): val = _delete_duplicates(val, delete_existing) if key not in self._dict or self._dict[key] in ('', None): @@ -1338,46 +1485,8 @@ class Base(SubstitutionEnvironment): self._dict[key].update(val) elif is_List(val): dk = self._dict[key] - if key == 'CPPDEFINES': - tmp = [] - for i in val: - if is_List(i): - if len(i) >= 2: - tmp.append((i[0], i[1])) - else: - tmp.append((i[0],)) - elif is_Tuple(i): - tmp.append(i) - else: - tmp.append((i,)) - val = tmp - # Construct a list of (key, value) tuples. - if is_Dict(dk): - tmp = [] - for (k, v) in dk.items(): - if v is not None: - tmp.append((k, v)) - else: - tmp.append((k,)) - dk = tmp - elif is_String(dk): - dk = [(dk,)] - else: - tmp = [] - for i in dk: - if is_List(i): - if len(i) >= 2: - tmp.append((i[0], i[1])) - else: - tmp.append((i[0],)) - elif is_Tuple(i): - tmp.append(i) - else: - tmp.append((i,)) - dk = tmp - else: - if not is_List(dk): - dk = [dk] + if not is_List(dk): + dk = [dk] if delete_existing: dk = [x for x in dk if x not in val] else: @@ -1386,70 +1495,15 @@ class Base(SubstitutionEnvironment): else: dk = self._dict[key] if is_List(dk): - if key == 'CPPDEFINES': - tmp = [] - for i in dk: - if is_List(i): - if len(i) >= 2: - tmp.append((i[0], i[1])) - else: - tmp.append((i[0],)) - elif is_Tuple(i): - tmp.append(i) - else: - tmp.append((i,)) - dk = tmp - # Construct a list of (key, value) tuples. - if is_Dict(val): - tmp = [] - for (k, v) in val.items(): - if v is not None: - tmp.append((k, v)) - else: - tmp.append((k,)) - val = tmp - elif is_String(val): - val = [(val,)] - if delete_existing: - dk = list(filter(lambda x, val=val: x not in val, dk)) - self._dict[key] = dk + val - else: - dk = [x for x in dk if x not in val] - self._dict[key] = dk + val + # By elimination, val is not a list. Since dk is a + # list, wrap val in a list first. + if delete_existing: + dk = list(filter(lambda x, val=val: x not in val, dk)) + self._dict[key] = dk + [val] else: - # By elimination, val is not a list. Since dk is a - # list, wrap val in a list first. - if delete_existing: - dk = list(filter(lambda x, val=val: x not in val, dk)) + if val not in dk: self._dict[key] = dk + [val] - else: - if val not in dk: - self._dict[key] = dk + [val] else: - if key == 'CPPDEFINES': - if is_String(dk): - dk = [dk] - elif is_Dict(dk): - tmp = [] - for (k, v) in dk.items(): - if v is not None: - tmp.append((k, v)) - else: - tmp.append((k,)) - dk = tmp - if is_String(val): - if val in dk: - val = [] - else: - val = [val] - elif is_Dict(val): - tmp = [] - for i,j in val.items(): - if j is not None: - tmp.append((i,j)) - else: - tmp.append(i) - val = tmp if delete_existing: dk = [x for x in dk if x not in val] self._dict[key] = dk + val @@ -1726,6 +1780,9 @@ class Base(SubstitutionEnvironment): kw = copy_non_reserved_keywords(kw) for key, val in kw.items(): + if key == 'CPPDEFINES': + _add_cppdefines(self._dict, val, prepend=True) + continue try: orig = self._dict[key] except KeyError: @@ -1815,6 +1872,9 @@ class Base(SubstitutionEnvironment): """ kw = copy_non_reserved_keywords(kw) for key, val in kw.items(): + if key == 'CPPDEFINES': + _add_cppdefines(self._dict, val, unique=True, prepend=True, delete_existing=delete_existing) + continue if is_List(val): val = _delete_duplicates(val, not delete_existing) if key not in self._dict or self._dict[key] in ('', None): diff --git a/SCons/Environment.xml b/SCons/Environment.xml index 2e06b1e..3790a22 100644 --- a/SCons/Environment.xml +++ b/SCons/Environment.xml @@ -499,126 +499,191 @@ Multiple targets can be passed in to a single call to -Intelligently append values to &consvars; in the &consenv; -named by env. +Appends value(s) intelligently to &consvars; in +env. The &consvars; and values to add to them are passed as key=val pairs (&Python; keyword arguments). &f-env-Append; is designed to allow adding values -without normally having to know the data type of an existing &consvar;. +without having to think about the data type of an existing &consvar;. Regular &Python; syntax can also be used to manipulate the &consvar;, -but for that you must know the type of the &consvar;: -for example, different &Python; syntax is needed to combine -a list of values with a single string value, or vice versa. +but for that you may need to know the types involved, +for example pure &Python; lets you directly "add" two lists of strings, +but adding a string to a list or a list to a string requires +different syntax - things &f-Append; takes care of. Some pre-defined &consvars; do have type expectations -based on how &SCons; will use them, +based on how &SCons; will use them: for example &cv-link-CPPDEFINES; is normally a string or a list of strings, -but can be a string, -a list of strings, -a list of tuples, -or a dictionary, while &cv-link-LIBEMITTER; -would expect a callable or list of callables, -and &cv-link-BUILDERS; would expect a mapping type. +but can also be a list of tuples or a dictionary; +while &cv-link-LIBEMITTER; +is expected to be a callable or list of callables, +and &cv-link-BUILDERS; is expected to be a dictionary. Consult the documentation for the various &consvars; for more details. -The following descriptions apply to both the append -and prepend functions, the only difference being -the insertion point of the added values. - - -If env. does not have a &consvar; -indicated by key, -val -is added to the environment under that key as-is. - - - -val can be almost any type, -and &SCons; will combine it with an existing value into an appropriate type, -but there are a few special cases to be aware of. -When two strings are combined, -the result is normally a new string, -with the caller responsible for supplying any needed separation. -The exception to this is the &consvar; &cv-link-CPPDEFINES;, -in which each item will be postprocessed by adding a prefix -and/or suffix, -so the contents are treated as a list of strings, that is, -adding a string will result in a separate string entry, -not a combined string. For &cv-CPPDEFINES; as well as -for &cv-link-LIBS;, and the various *PATH; -variables, &SCons; will supply the compiler-specific -syntax (e.g. adding a -D or /D -prefix for &cv-CPPDEFINES;), so this syntax should be omitted when +The following descriptions apply to both the &f-Append; +and &f-Prepend; methods, as well as their +Unique variants, +with the differences being the insertion point of the added values +and whether duplication is allowed. + + + +val can be almost any type. +If env does not have a &consvar; +named key, +then key is simply +stored with a value of val. +Otherwise, val is +combinined with the existing value, +possibly converting into an appropriate type +which can hold the expanded contents. +There are a few special cases to be aware of. +Normally, when two strings are combined, +the result is a new string containing their concatenation +(and you are responsible for supplying any needed separation); +however, the contents of &cv-link-CPPDEFINES; will +will be postprocessed by adding a prefix and/or suffix +to each entry when the command line is produced, +so &SCons; keeps them separate - +appending a string will result in a separate string entry, +not a combined string. +For &cv-CPPDEFINES;. as well as +&cv-link-LIBS;, and the various *PATH variables, +&SCons; will amend the variable by supplying the compiler-specific +syntax (e.g. prepending a -D or /D +prefix for &cv-CPPDEFINES;), so you should omit this syntax when adding values to these variables. -Example (gcc syntax shown in the expansion of &CPPDEFINES;): +Examples (gcc syntax shown in the expansion of &CPPDEFINES;): env = Environment(CXXFLAGS="-std=c11", CPPDEFINES="RELEASE") -print("CXXFLAGS={}, CPPDEFINES={}".format(env['CXXFLAGS'], env['CPPDEFINES'])) -# notice including a leading space in CXXFLAGS value +print(f"CXXFLAGS = {env['CXXFLAGS']}, CPPDEFINES = {env['CPPDEFINES']}") +# notice including a leading space in CXXFLAGS addition env.Append(CXXFLAGS=" -O", CPPDEFINES="EXTRA") -print("CXXFLAGS={}, CPPDEFINES={}".format(env['CXXFLAGS'], env['CPPDEFINES'])) -print("CPPDEFINES will expand to {}".format(env.subst("$_CPPDEFFLAGS"))) +print(f"CXXFLAGS = {env['CXXFLAGS']}, CPPDEFINES = {env['CPPDEFINES']}") +print("CPPDEFINES will expand to", env.subst('$_CPPDEFFLAGS')) $ scons -Q -CXXFLAGS=-std=c11, CPPDEFINES=RELEASE -CXXFLAGS=-std=c11 -O, CPPDEFINES=['RELEASE', 'EXTRA'] -CPPDEFINES will expand to -DRELEASE -DEXTRA +CXXFLAGS = -std=c11, CPPDEFINES = RELEASE +CXXFLAGS = -std=c11 -O, CPPDEFINES = deque(['RELEASE', 'EXTRA']) +CPPDEFINES will expand to -DRELEASE -DEXTRA scons: `.' is up to date. -Because &cv-link-CPPDEFINES; is intended to -describe C/C++ pre-processor macro definitions, +Because &cv-link-CPPDEFINES; is intended for command-line +specification of C/C++ preprocessor macros, it accepts additional syntax. -Preprocessor macros can be valued, or un-valued, as in --DBAR=1 or --DFOO. -The macro can be be supplied as a complete string including the value, -or as a tuple (or list) of macro, value, or as a dictionary. -Example (again gcc syntax in the expanded defines): +A command-line preprocessor macro can predefine a name by itself +(-DFOO), +which gives it an implicit value, +or be given with a macro definition +(-DBAR=1). +&SCons; allows you to specify a macro with a definition +using a name=value string, +or a tuple (name, value) +(which must be supplied inside a sequence type), +or a dictionary {name: value}. env = Environment(CPPDEFINES="FOO") -print("CPPDEFINES={}".format(env['CPPDEFINES'])) +print("CPPDEFINES =", env['CPPDEFINES']) env.Append(CPPDEFINES="BAR=1") -print("CPPDEFINES={}".format(env['CPPDEFINES'])) -env.Append(CPPDEFINES=("OTHER", 2)) -print("CPPDEFINES={}".format(env['CPPDEFINES'])) +print("CPPDEFINES =", env['CPPDEFINES']) +env.Append(CPPDEFINES=[("OTHER", 2)]) +print("CPPDEFINES =", env['CPPDEFINES']) env.Append(CPPDEFINES={"EXTRA": "arg"}) -print("CPPDEFINES={}".format(env['CPPDEFINES'])) -print("CPPDEFINES will expand to {}".format(env.subst("$_CPPDEFFLAGS"))) +print("CPPDEFINES =", env['CPPDEFINES']) +print("CPPDEFINES will expand to", env.subst('$_CPPDEFFLAGS')) $ scons -Q -CPPDEFINES=FOO -CPPDEFINES=['FOO', 'BAR=1'] -CPPDEFINES=['FOO', 'BAR=1', ('OTHER', 2)] -CPPDEFINES=['FOO', 'BAR=1', ('OTHER', 2), {'EXTRA': 'arg'}] +CPPDEFINES = FOO +CPPDEFINES = deque(['FOO', 'BAR=1']) +CPPDEFINES = deque(['FOO', 'BAR=1', ('OTHER', 2)]) +CPPDEFINES = deque(['FOO', 'BAR=1', ('OTHER', 2), ('EXTRA', 'arg')]) CPPDEFINES will expand to -DFOO -DBAR=1 -DOTHER=2 -DEXTRA=arg scons: `.' is up to date. -Adding a string val -to a dictonary &consvar; will enter -val as the key in the dict, +Multiple &cv-CPPDEFINES; macros can be supplied in a sequence of tuples, +or using the dictionary form. +If a given macro name should not have a definition, +omit the value from tuple or give it as +None; +if using the dictionary form, +specify the value as None. + + + +env = Environment() +env.Append(CPPDEFINES=[("ONE", 1), ("TWO", )]) +print("CPPDEFINES =", env['CPPDEFINES']) +env.Append(CPPDEFINES={"THREE": 3, "FOUR": None}) +print("CPPDEFINES =", env['CPPDEFINES']) +print("CPPDEFINES will expand to", env.subst('$_CPPDEFFLAGS')) + + + +$ scons -Q +CPPDEFINES = [('ONE', 1), ('TWO',)] +CPPDEFINES = [('ONE', 1), ('TWO',), {'THREE': 3, 'FOUR': None}] +CPPDEFINES will expand to -DONE=1 -DTWO -DTHREE=3 -DFOUR +scons: `.' is up to date. + + + +Changed in version 4.5: +clarified that to receive the special handling, +the tuple form must be supplied inside +a sequence (e.g. a list); a single tuple will be interpreted +just like a single list. +Previously this form was inconsistently interpreted by +various &SCons; methods. + + + +env = Environment() +env.Append(CPPDEFINES=("MACRO1", "MACRO2")) +print("CPPDEFINES =", env['CPPDEFINES']) +env.Append(CPPDEFINES=[("MACRO3", "MACRO4")]) +print("CPPDEFINES =", env['CPPDEFINES']) +print("CPPDEFINES will expand to", env.subst('$_CPPDEFFLAGS')) + + + +$ scons -Q +CPPDEFINES = ('MACRO1', 'MACRO2') +CPPDEFINES = deque(['MACRO1', 'MACRO2', ('MACRO3', 'MACRO4')]) +CPPDEFINES will expand to -DMACRO1 -DMACRO2 -DMACRO3=MACRO4 +scons: `.' is up to date. + + + +See &cv-link-CPPDEFINES; for more details. + + + +Appending a string val +to a dictonary-typed &consvar; enters +val as the key in the dictionary, and None as its value. -Using a tuple type to supply a key + value only works -for the special case of &cv-link-CPPDEFINES; +Using a tuple type to supply a key, value +only works for the special case of &cv-CPPDEFINES; described above. Although most combinations of types work without needing to know the details, some combinations -do not make sense and a &Python; exception will be raised. +do not make sense and &Python; raises an exception. @@ -626,7 +691,7 @@ When using &f-env-Append; to modify &consvars; which are path specifications (conventionally, the names of such end in PATH), it is recommended to add the values as a list of strings, -even if there is only a single string to add. +even if you are only adding a single string. The same goes for adding library names to &cv-LIBS;. @@ -696,20 +761,20 @@ See also &f-link-env-PrependENVPath;. -(key=val, [...], delete_existing=False) +(key=val, [...], [delete_existing=False]) Append values to &consvars; in the current &consenv;, maintaining uniqueness. -Works like &f-link-env-Append; (see for details), -except that values already present in the &consvar; -will not be added again. +Works like &f-link-env-Append;, +except that values that would become duplicates +are not added. If delete_existing -is True, -the existing matching value is first removed, -and the requested value is added, -having the effect of moving such values to the end. +is set to a true value, then for any duplicate, +the existing instance of val is first removed, +then val is appended, +having the effect of moving it to the end. @@ -2716,22 +2781,22 @@ See also &f-link-env-AppendENVPath;. -(key=val, delete_existing=False, [...]) +(key=val, [...], [delete_existing=False]) Prepend values to &consvars; in the current &consenv;, maintaining uniqueness. -Works like &f-link-env-Append; (see for details), +Works like &f-link-env-Append;, except that values are added to the front, -rather than the end, of any existing value of the &consvar;, -and values already present in the &consvar; -will not be added again. +rather than the end, of the &consvar;, +and values that would become duplicates +are not added. If delete_existing -is True, -the existing matching value is first removed, -and the requested value is inserted, -having the effect of moving such values to the front. +is set to a true value, then for any duplicate, +the existing instance of val is first removed, +then val is inserted, +having the effect of moving it to the front. diff --git a/SCons/Util/types.py b/SCons/Util/types.py index 9aef13e..1602055 100644 --- a/SCons/Util/types.py +++ b/SCons/Util/types.py @@ -12,7 +12,7 @@ import pprint import re from typing import Optional -from collections import UserDict, UserList, UserString +from collections import UserDict, UserList, UserString, deque from collections.abc import MappingView # Functions for deciding if things are like various types, mainly to @@ -23,20 +23,22 @@ from collections.abc import MappingView # exception, but handling the exception when it's not the right type is # often too slow. -# We are using the following trick to speed up these -# functions. Default arguments are used to take a snapshot of -# the global functions and constants used by these functions. This -# transforms accesses to global variable into local variables -# accesses (i.e. LOAD_FAST instead of LOAD_GLOBAL). -# Since checkers dislike this, it's now annotated for pylint to flag +# A trick is used to speed up these functions. Default arguments are +# used to take a snapshot of the global functions and constants used +# by these functions. This transforms accesses to global variables into +# local variable accesses (i.e. LOAD_FAST instead of LOAD_GLOBAL). +# Since checkers dislike this, it's now annotated for pylint, to flag # (mostly for other readers of this code) we're doing this intentionally. -# TODO: PY3 check these are still valid choices for all of these funcs. +# TODO: experts affirm this is still faster, but maybe check if worth it? DictTypes = (dict, UserDict) -ListTypes = (list, UserList) +ListTypes = (list, UserList, deque) -# Handle getting dictionary views. -SequenceTypes = (list, tuple, UserList, MappingView) +# With Python 3, there are view types that are sequences. Other interesting +# sequences are range and bytearray. What we don't want is strings: while +# they are iterable sequences, in SCons usage iterating over a string is +# almost never what we want. So basically iterable-but-not-string: +SequenceTypes = (list, tuple, deque, UserList, MappingView) # Note that profiling data shows a speed-up when comparing # explicitly with str instead of simply comparing diff --git a/test/CPPDEFINES/append.py b/test/CPPDEFINES/append.py index 874fceb..4c5e562 100644 --- a/test/CPPDEFINES/append.py +++ b/test/CPPDEFINES/append.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 appending to CPPPDEFINES with various data types. @@ -33,115 +32,122 @@ import TestSCons test = TestSCons.TestSCons() -# Note: we explicitly set CPPDEFPREFIX here to simplify testing on -# Windows. - -test.write('SConstruct', """\ -env_1738_2 = Environment(CPPDEFPREFIX='-D') -env_1738_2['CPPDEFINES'] = ['FOO'] -env_1738_2.Append(CPPDEFINES={'value' : '1'}) -print(env_1738_2.subst('$_CPPDEFFLAGS')) -#env_1738_2.Object('test_1738_2', 'main.c') - -# https://github.com/SCons/scons/issues/2300 -env_2300_1 = Environment(CPPDEFINES = 'foo', CPPDEFPREFIX='-D') -env_2300_1.Append(CPPDEFINES='bar') -print(env_2300_1.subst('$_CPPDEFFLAGS')) - -env_2300_2 = Environment(CPPDEFINES = ['foo'], CPPDEFPREFIX='-D') # note the list -env_2300_2.Append(CPPDEFINES='bar') -print(env_2300_2.subst('$_CPPDEFFLAGS')) - -# https://github.com/SCons/scons/issues/1152 -# https://github.com/SCons/scons/issues/2900 -# Python3 dicts dont preserve order. Hence we supply subclass of OrderedDict -# whose __str__ and __repr__ act like a normal dict. -from collections import OrderedDict -class OrderedPrintingDict(OrderedDict): - def __repr__(self): - return '{' + ', '.join(['%r: %r'%(k, v) for (k, v) in self.items()]) + '}' - - __str__ = __repr__ - - # Because dict-like objects (except dict and UserDict) are not deep copied - # directly when constructing Environment(CPPDEFINES = OrderedPrintingDict(...)) - def __semi_deepcopy__(self): - return self.copy() - -cases=[('string', 'FOO'), - ('list', ['NAME1', 'NAME2']), - ('list-of-2lists', [('NAME1','VAL1'), ['NAME2','VAL2']]), - ('dict', OrderedPrintingDict([('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')])) - ] - -for (t1, c1) in cases: - for (t2, c2) in cases: - print("==== Testing CPPDEFINES, appending a %s to a %s"%(t2, t1)) - print(" orig = %s, append = %s"%(c1, c2)) - env=Environment(CPPDEFINES = c1, CPPDEFPREFIX='-D') - env.Append(CPPDEFINES = c2) - final=env.subst('$_CPPDEFFLAGS',source="src", target="tgt") - print('Append:\\n\\tresult=%s\\n\\tfinal=%s'%\\ - (env['CPPDEFINES'], final)) - env=Environment(CPPDEFINES = c1, CPPDEFPREFIX='-D') - env.AppendUnique(CPPDEFINES = c2) - final=env.subst('$_CPPDEFFLAGS',source="src", target="tgt") - print('AppendUnique:\\n\\tresult=%s\\n\\tfinal=%s'%\\ - (env['CPPDEFINES'], final)) -""") +# Note: explicitly set CPPDEFPREFIX here to simplify testing on Windows. +# Link: fixture/SConstruct-Append +test.file_fixture(["fixture", "SConstruct-Append"], "SConstruct") expect_print_output="""\ -DFOO -Dvalue=1 -Dfoo -Dbar -Dfoo -Dbar +-Dfoo -Dbar -Dbaz +-Dfoo bar -Dbaz +-Dfoo -Dbar baz +-DMacro2=Value2 -DMacro3=Value3 -DMacro1=Value1 ==== Testing CPPDEFINES, appending a string to a string - orig = FOO, append = FOO + orig = 'FOO', append = 'FOO' Append: result=['FOO', 'FOO'] final=-DFOO -DFOO AppendUnique: result=['FOO'] final=-DFOO +==== Testing CPPDEFINES, appending a valuestring to a string + orig = 'FOO', append = 'NAME1=VAL1' +Append: + result=['FOO', 'NAME1=VAL1'] + final=-DFOO -DNAME1=VAL1 +AppendUnique: + result=['FOO', 'NAME1=VAL1'] + final=-DFOO -DNAME1=VAL1 ==== Testing CPPDEFINES, appending a list to a string - orig = FOO, append = ['NAME1', 'NAME2'] + orig = 'FOO', append = ['NAME1', 'NAME2'] Append: result=['FOO', 'NAME1', 'NAME2'] final=-DFOO -DNAME1 -DNAME2 AppendUnique: - result=[('FOO',), ('NAME1',), ('NAME2',)] + result=['FOO', 'NAME1', 'NAME2'] final=-DFOO -DNAME1 -DNAME2 ==== Testing CPPDEFINES, appending a list-of-2lists to a string - orig = FOO, append = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + orig = 'FOO', append = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Append: result=['FOO', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] final=-DFOO -DNAME1=VAL1 -DNAME2=VAL2 AppendUnique: - result=[('FOO',), ('NAME1', 'VAL1'), ('NAME2', 'VAL2')] + result=['FOO', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] final=-DFOO -DNAME1=VAL1 -DNAME2=VAL2 ==== Testing CPPDEFINES, appending a dict to a string - orig = FOO, append = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} + orig = 'FOO', append = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} Append: - result=['FOO', {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}] + result=['FOO', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] final=-DFOO -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 AppendUnique: - result=['FOO', ('NAME2', 'VAL2'), 'NAME3', ('NAME1', 'VAL1')] + result=['FOO', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] final=-DFOO -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 +==== Testing CPPDEFINES, appending a string to a valuestring + orig = 'NAME1=VAL1', append = 'FOO' +Append: + result=['NAME1=VAL1', 'FOO'] + final=-DNAME1=VAL1 -DFOO +AppendUnique: + result=['NAME1=VAL1', 'FOO'] + final=-DNAME1=VAL1 -DFOO +==== Testing CPPDEFINES, appending a valuestring to a valuestring + orig = 'NAME1=VAL1', append = 'NAME1=VAL1' +Append: + result=['NAME1=VAL1', 'NAME1=VAL1'] + final=-DNAME1=VAL1 -DNAME1=VAL1 +AppendUnique: + result=['NAME1=VAL1'] + final=-DNAME1=VAL1 +==== Testing CPPDEFINES, appending a list to a valuestring + orig = 'NAME1=VAL1', append = ['NAME1', 'NAME2'] +Append: + result=['NAME1=VAL1', 'NAME1', 'NAME2'] + final=-DNAME1=VAL1 -DNAME1 -DNAME2 +AppendUnique: + result=['NAME1=VAL1', 'NAME1', 'NAME2'] + final=-DNAME1=VAL1 -DNAME1 -DNAME2 +==== Testing CPPDEFINES, appending a list-of-2lists to a valuestring + orig = 'NAME1=VAL1', append = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] +Append: + result=['NAME1=VAL1', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME1=VAL1 -DNAME1=VAL1 -DNAME2=VAL2 +AppendUnique: + result=['NAME1=VAL1', ['NAME2', 'VAL2']] + final=-DNAME1=VAL1 -DNAME2=VAL2 +==== Testing CPPDEFINES, appending a dict to a valuestring + orig = 'NAME1=VAL1', append = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} +Append: + result=['NAME1=VAL1', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 +AppendUnique: + result=['NAME1=VAL1', ('NAME2', 'VAL2'), ('NAME3', None)] + final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME3 ==== Testing CPPDEFINES, appending a string to a list - orig = ['NAME1', 'NAME2'], append = FOO + orig = ['NAME1', 'NAME2'], append = 'FOO' Append: result=['NAME1', 'NAME2', 'FOO'] final=-DNAME1 -DNAME2 -DFOO AppendUnique: - result=[('NAME1',), ('NAME2',), ('FOO',)] + result=['NAME1', 'NAME2', 'FOO'] final=-DNAME1 -DNAME2 -DFOO +==== Testing CPPDEFINES, appending a valuestring to a list + orig = ['NAME1', 'NAME2'], append = 'NAME1=VAL1' +Append: + result=['NAME1', 'NAME2', 'NAME1=VAL1'] + final=-DNAME1 -DNAME2 -DNAME1=VAL1 +AppendUnique: + result=['NAME1', 'NAME2', 'NAME1=VAL1'] + final=-DNAME1 -DNAME2 -DNAME1=VAL1 ==== Testing CPPDEFINES, appending a list to a list orig = ['NAME1', 'NAME2'], append = ['NAME1', 'NAME2'] Append: result=['NAME1', 'NAME2', 'NAME1', 'NAME2'] final=-DNAME1 -DNAME2 -DNAME1 -DNAME2 AppendUnique: - result=[('NAME1',), ('NAME2',)] + result=['NAME1', 'NAME2'] final=-DNAME1 -DNAME2 ==== Testing CPPDEFINES, appending a list-of-2lists to a list orig = ['NAME1', 'NAME2'], append = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] @@ -149,31 +155,39 @@ Append: result=['NAME1', 'NAME2', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] final=-DNAME1 -DNAME2 -DNAME1=VAL1 -DNAME2=VAL2 AppendUnique: - result=[('NAME1',), ('NAME2',), ('NAME1', 'VAL1'), ('NAME2', 'VAL2')] + result=['NAME1', 'NAME2', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] final=-DNAME1 -DNAME2 -DNAME1=VAL1 -DNAME2=VAL2 ==== Testing CPPDEFINES, appending a dict to a list orig = ['NAME1', 'NAME2'], append = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} Append: - result=['NAME1', 'NAME2', {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}] + result=['NAME1', 'NAME2', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] final=-DNAME1 -DNAME2 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 AppendUnique: - result=[('NAME1',), ('NAME2',), ('NAME2', 'VAL2'), ('NAME3',), ('NAME1', 'VAL1')] + result=['NAME1', 'NAME2', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] final=-DNAME1 -DNAME2 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 ==== Testing CPPDEFINES, appending a string to a list-of-2lists - orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], append = FOO + orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], append = 'FOO' Append: result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], 'FOO'] final=-DNAME1=VAL1 -DNAME2=VAL2 -DFOO AppendUnique: - result=[('NAME1', 'VAL1'), ('NAME2', 'VAL2'), ('FOO',)] + result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], 'FOO'] final=-DNAME1=VAL1 -DNAME2=VAL2 -DFOO +==== Testing CPPDEFINES, appending a valuestring to a list-of-2lists + orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], append = 'NAME1=VAL1' +Append: + result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], 'NAME1=VAL1'] + final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME1=VAL1 +AppendUnique: + result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME1=VAL1 -DNAME2=VAL2 ==== Testing CPPDEFINES, appending a list to a list-of-2lists orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], append = ['NAME1', 'NAME2'] Append: result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], 'NAME1', 'NAME2'] final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME1 -DNAME2 AppendUnique: - result=[('NAME1', 'VAL1'), ('NAME2', 'VAL2'), ('NAME1',), ('NAME2',)] + result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], 'NAME1', 'NAME2'] final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME1 -DNAME2 ==== Testing CPPDEFINES, appending a list-of-2lists to a list-of-2lists orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], append = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] @@ -181,55 +195,61 @@ Append: result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME1=VAL1 -DNAME2=VAL2 AppendUnique: - result=[('NAME1', 'VAL1'), ('NAME2', 'VAL2')] + result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2']] final=-DNAME1=VAL1 -DNAME2=VAL2 ==== Testing CPPDEFINES, appending a dict to a list-of-2lists orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], append = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} Append: - result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}] + result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 AppendUnique: - result=[('NAME2', 'VAL2'), ('NAME3',), ('NAME1', 'VAL1')] - final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 + result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], ('NAME3', None)] + final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME3 ==== Testing CPPDEFINES, appending a string to a dict - orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, append = FOO + orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, append = 'FOO' Append: - result={'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1', 'FOO': None} - final=-DFOO -DNAME1=VAL1 -DNAME2=VAL2 -DNAME3 + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1'), 'FOO'] + final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DFOO AppendUnique: - result=[('NAME2', 'VAL2'), ('NAME3',), ('NAME1', 'VAL1'), 'FOO'] + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1'), 'FOO'] final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DFOO +==== Testing CPPDEFINES, appending a valuestring to a dict + orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, append = 'NAME1=VAL1' +Append: + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1'), 'NAME1=VAL1'] + final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DNAME1=VAL1 +AppendUnique: + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 ==== Testing CPPDEFINES, appending a list to a dict orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, append = ['NAME1', 'NAME2'] Append: - result=[('NAME2', 'VAL2'), ('NAME3',), ('NAME1', 'VAL1'), 'NAME1', 'NAME2'] + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1'), 'NAME1', 'NAME2'] final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DNAME1 -DNAME2 AppendUnique: - result=[('NAME2', 'VAL2'), ('NAME3',), ('NAME1', 'VAL1'), ('NAME1',), ('NAME2',)] + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1'), 'NAME1', 'NAME2'] final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DNAME1 -DNAME2 ==== Testing CPPDEFINES, appending a list-of-2lists to a dict orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, append = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Append: - result=[('NAME2', 'VAL2'), ('NAME3',), ('NAME1', 'VAL1'), ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1'), ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DNAME1=VAL1 -DNAME2=VAL2 AppendUnique: - result=[('NAME2', 'VAL2'), ('NAME3',), ('NAME1', 'VAL1')] + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 ==== Testing CPPDEFINES, appending a dict to a dict orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, append = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} Append: - result={'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} - final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME3 + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1'), ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 AppendUnique: - result={'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} - final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME3 + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 """ build_output="scons: `.' is up to date.\n" - -expect = test.wrap_stdout(build_str=build_output, - read_str = expect_print_output) -test.run(arguments = '.', stdout=expect) +expect = test.wrap_stdout(build_str=build_output, read_str=expect_print_output) +test.run(arguments='.', stdout=expect) test.pass_test() # Local Variables: diff --git a/test/CPPDEFINES/basic.py b/test/CPPDEFINES/basic.py index 176f543..b66ea8a 100755 --- a/test/CPPDEFINES/basic.py +++ b/test/CPPDEFINES/basic.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 basic use of CPPPDEFINES with various data types. @@ -37,7 +36,7 @@ test_list = [ 'xyz', ['x', 'y', 'z'], ['x', ['y', 123], 'z', ('int', '$INTEGER')], - { 'c' : 3, 'b': None, 'a' : 1 }, + {'c': 3, 'b': None, 'a': 1}, "${TESTDEFS}", "${GEN}", ] @@ -48,33 +47,59 @@ def generator(target, source, env, for_signature): return 'TARGET_AND_SOURCE_ARE_MISSING' for i in test_list: - env = Environment(CPPDEFPREFIX='-D', CPPDEFSUFFIX='', INTEGER=0, TESTDEFS=["FOO", "BAR=1"], GEN=generator) + env = Environment( + CPPDEFPREFIX='-D', + CPPDEFSUFFIX='', + INTEGER=0, + TESTDEFS=["FOO", "BAR=1"], + GEN=generator, + ) ttt = env.Entry('#ttt') sss = env.Entry('#sss') - print(env.Clone(CPPDEFINES=i).subst('$_CPPDEFFLAGS', target=[ttt], source=[sss])) + print( + env.Clone(CPPDEFINES=i).subst( + '$_CPPDEFFLAGS', + target=[ttt], + source=[sss], + ) + ) + for i in test_list: - env = Environment(CPPDEFPREFIX='|', CPPDEFSUFFIX='|', INTEGER=1, TESTDEFS=["FOO", "BAR=1"], GEN=generator) + env = Environment( + CPPDEFPREFIX='|', + CPPDEFSUFFIX='|', + INTEGER=1, + TESTDEFS=["FOO", "BAR=1"], + GEN=generator, + ) ttt = env.Entry('#ttt') sss = env.Entry('#sss') - print(env.Clone(CPPDEFINES=i).subst('$_CPPDEFFLAGS', target=[ttt], source=[sss])) + print( + env.Clone(CPPDEFINES=i).subst( + '$_CPPDEFFLAGS', + target=[ttt], + source=[sss], + ) + ) """) -expect = test.wrap_stdout(build_str="scons: `.' is up to date.\n", - read_str = """\ +expect = test.wrap_stdout( + build_str="scons: `.' is up to date.\n", + read_str="""\ -Dxyz -Dx -Dy -Dz -Dx -Dy=123 -Dz -Dint=0 --Da=1 -Db -Dc=3 +-Dc=3 -Db -Da=1 -DFOO -DBAR=1 -Dttt_GENERATED_sss |xyz| |x| |y| |z| |x| |y=123| |z| |int=1| -|a=1| |b| |c=3| +|c=3| |b| |a=1| |FOO| |BAR=1| |ttt_GENERATED_sss| -""") - +""", +) test.run(arguments = '.', stdout=expect) test.pass_test() diff --git a/test/CPPDEFINES/fixture/SConstruct-Append b/test/CPPDEFINES/fixture/SConstruct-Append new file mode 100644 index 0000000..a9dea8c --- /dev/null +++ b/test/CPPDEFINES/fixture/SConstruct-Append @@ -0,0 +1,99 @@ +# Special cases: +# https://github.com/SCons/scons/issues/1738 +env_1738_2 = Environment(CPPDEFPREFIX='-D') +env_1738_2['CPPDEFINES'] = ['FOO'] +env_1738_2.Append(CPPDEFINES={'value': '1'}) +print(env_1738_2.subst('$_CPPDEFFLAGS')) +# env_1738_2.Object('test_1738_2', 'main.c') + +# https://github.com/SCons/scons/issues/2300 +env_2300_1 = Environment(CPPDEFINES='foo', CPPDEFPREFIX='-D') +env_2300_1.Append(CPPDEFINES='bar') +print(env_2300_1.subst('$_CPPDEFFLAGS')) + +env_2300_2 = Environment(CPPDEFINES=['foo'], CPPDEFPREFIX='-D') # note the list +env_2300_2.Append(CPPDEFINES='bar') +print(env_2300_2.subst('$_CPPDEFFLAGS')) + +# an initial space-separated string will be split, but not a string in a list +env_multi = Environment(CPPDEFPREFIX='-D') +env_multi['CPPDEFINES'] = "foo bar" +env_multi.Append(CPPDEFINES="baz") +print(env_multi.subst('$_CPPDEFFLAGS')) +env_multi = Environment(CPPDEFPREFIX='-D') +env_multi['CPPDEFINES'] = ["foo bar"] +env_multi.Append(CPPDEFINES="baz") +print(env_multi.subst('$_CPPDEFFLAGS')) +env_multi = Environment(CPPDEFPREFIX='-D') +env_multi['CPPDEFINES'] = "foo" +env_multi.Append(CPPDEFINES=["bar baz"]) +print(env_multi.subst('$_CPPDEFFLAGS')) + +# check that AppendUnique(..., delete_existing=True) works as expected +# each addition is in different but matching form, and different order +# so we expect a reordered list, but with the same macro defines. +env_multi = Environment(CPPDEFPREFIX='-D') +env_multi.Append(CPPDEFINES=["Macro1=Value1", ("Macro2", "Value2"), {"Macro3": "Value3"}]) +env_multi.AppendUnique(CPPDEFINES="Macro2=Value2", delete_existing=True) +env_multi.AppendUnique(CPPDEFINES=[("Macro3", "Value3")], delete_existing=True) +env_multi.AppendUnique(CPPDEFINES={"Macro1": "Value1"}, delete_existing=True) +print(env_multi.subst('$_CPPDEFFLAGS')) + +# https://github.com/SCons/scons/issues/1152 +# https://github.com/SCons/scons/issues/2900 +# Python3 dicts dont preserve order. Hence we supply subclass of OrderedDict +# whose __str__ and __repr__ act like a normal dict. +from collections import OrderedDict + +class OrderedPrintingDict(OrderedDict): + def __repr__(self): + return '{' + ', '.join([f'{k!r}: {v!r}' for (k, v) in self.items()]) + '}' + + __str__ = __repr__ + + # Because dict-like objects (except dict and UserDict) are not deep copied + # directly when constructing Environment(CPPDEFINES=OrderedPrintingDict(...)) + def __semi_deepcopy__(self): + return self.copy() + + +# each of these types will be appended to each of the others +# the first item in each tuple is a label for the output +cases = [ + ('string', 'FOO'), + ('valuestring', 'NAME1=VAL1'), + ('list', ['NAME1', 'NAME2']), + ('list-of-2lists', [('NAME1', 'VAL1'), ['NAME2', 'VAL2']]), + ( + 'dict', + OrderedPrintingDict([('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')]), + ), +] + + +def dlist(coll): + # if it's a deque, turn it into a list for display purposes + from collections import deque + + if isinstance(coll, deque): + return list(coll) + return coll + + +for (t1, c1) in cases: + for (t2, c2) in cases: + print(f"==== Testing CPPDEFINES, appending a {t2} to a {t1}") + # string-like appearance if the value is a string + orig = f"'{c1}'" if isinstance(c1, str) else c1 + app = f"'{c2}'" if isinstance(c2, str) else c2 + print(f" orig = {orig}, append = {app}") + env = Environment(CPPDEFINES=c1, CPPDEFPREFIX='-D') + env.Append(CPPDEFINES=c2) + final = env.subst('$_CPPDEFFLAGS', source="src", target="tgt") + print(f"Append:\n\tresult={dlist(env['CPPDEFINES'])}\n\tfinal={final}") + env = Environment(CPPDEFINES=c1, CPPDEFPREFIX='-D') + env.AppendUnique(CPPDEFINES=c2) + final = env.subst('$_CPPDEFFLAGS', source="src", target="tgt") + print( + f"AppendUnique:\n\tresult={dlist(env['CPPDEFINES'])}\n\tfinal={final}" + ) diff --git a/test/CPPDEFINES/fixture/SConstruct-Prepend b/test/CPPDEFINES/fixture/SConstruct-Prepend new file mode 100644 index 0000000..5934530 --- /dev/null +++ b/test/CPPDEFINES/fixture/SConstruct-Prepend @@ -0,0 +1,100 @@ +# Special cases: +# https://github.com/SCons/scons/issues/1738 +env_1738_2 = Environment(CPPDEFPREFIX='-D') +env_1738_2['CPPDEFINES'] = ['FOO'] +env_1738_2.Prepend(CPPDEFINES={'value': '1'}) +print(env_1738_2.subst('$_CPPDEFFLAGS')) +# env_1738_2.Object('test_1738_2', 'main.c') + +# https://github.com/SCons/scons/issues/2300 +env_2300_1 = Environment(CPPDEFINES='foo', CPPDEFPREFIX='-D') +env_2300_1.Prepend(CPPDEFINES='bar') +print(env_2300_1.subst('$_CPPDEFFLAGS')) + +env_2300_2 = Environment(CPPDEFINES=['foo'], CPPDEFPREFIX='-D') # note the list +env_2300_2.Prepend(CPPDEFINES='bar') +print(env_2300_2.subst('$_CPPDEFFLAGS')) + +# an initial space-separated string will be split, but not a string in a list +env_multi = Environment(CPPDEFPREFIX='-D') +env_multi['CPPDEFINES'] = "foo bar" +env_multi.Prepend(CPPDEFINES="baz") +print(env_multi.subst('$_CPPDEFFLAGS')) +env_multi = Environment(CPPDEFPREFIX='-D') +env_multi['CPPDEFINES'] = ["foo bar"] +env_multi.Prepend(CPPDEFINES="baz") +print(env_multi.subst('$_CPPDEFFLAGS')) +env_multi = Environment(CPPDEFPREFIX='-D') +env_multi['CPPDEFINES'] = "foo" +env_multi.Prepend(CPPDEFINES=["bar baz"]) +print(env_multi.subst('$_CPPDEFFLAGS')) + +# check that PrependUnique(..., delete_existing=True) works as expected +# each addition is in different but matching form, and different order, +# so we expect a reordered list, but with the same macro defines. +env_multi = Environment(CPPDEFPREFIX='-D') +env_multi.Prepend(CPPDEFINES=["Macro1=Value1", ("Macro2", "Value2"), {"Macro3": "Value3"}]) +env_multi.PrependUnique(CPPDEFINES="Macro2=Value2", delete_existing=True) +env_multi.PrependUnique(CPPDEFINES=[("Macro3", "Value3")], delete_existing=True) +env_multi.PrependUnique(CPPDEFINES={"Macro1": "Value1"}, delete_existing=True) +print(env_multi.subst('$_CPPDEFFLAGS')) + +# https://github.com/SCons/scons/issues/1152 +# https://github.com/SCons/scons/issues/2900 +# Python3 dicts dont preserve order. Hence we supply subclass of OrderedDict +# whose __str__ and __repr__ act like a normal dict. +from collections import OrderedDict + + +class OrderedPrintingDict(OrderedDict): + def __repr__(self): + return '{' + ', '.join([f'{k!r}: {v!r}' for (k, v) in self.items()]) + '}' + + __str__ = __repr__ + + # Because dict-like objects (except dict and UserDict) are not deep copied + # directly when constructing Environment(CPPDEFINES=OrderedPrintingDict(...)) + def __semi_deepcopy__(self): + return self.copy() + + +# each of these types will be prepended to each of the others +# the first item in each tuple is a label for the output +cases = [ + ('string', 'FOO'), + ('valuestring', 'NAME1=VAL1'), + ('list', ['NAME1', 'NAME2']), + ('list-of-2lists', [('NAME1', 'VAL1'), ['NAME2', 'VAL2']]), + ( + 'dict', + OrderedPrintingDict([('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')]), + ), +] + + +def dlist(coll): + # if it's a deque, turn it into a list for display purposes + from collections import deque + + if isinstance(coll, deque): + return list(coll) + return coll + + +for (t1, c1) in cases: + for (t2, c2) in cases: + print(f"==== Testing CPPDEFINES, prepending a {t2} to a {t1}") + # string-like appearance if the value is a string + orig = f"'{c1}'" if isinstance(c1, str) else c1 + pre = f"'{c2}'" if isinstance(c2, str) else c2 + print(f" orig = {orig}, prepend = {pre}") + env = Environment(CPPDEFINES=c1, CPPDEFPREFIX='-D') + env.Prepend(CPPDEFINES=c2) + final = env.subst('$_CPPDEFFLAGS', source="src", target="tgt") + print(f"Prepend:\n\tresult={dlist(env['CPPDEFINES'])}\n\tfinal={final}") + env = Environment(CPPDEFINES=c1, CPPDEFPREFIX='-D') + env.PrependUnique(CPPDEFINES=c2) + final = env.subst('$_CPPDEFFLAGS', source="src", target="tgt") + print( + f"PrependUnique:\n\tresult={dlist(env['CPPDEFINES'])}\n\tfinal={final}" + ) diff --git a/test/CPPDEFINES/live.py b/test/CPPDEFINES/live.py index 0c7ad78..97e0e13 100644 --- a/test/CPPDEFINES/live.py +++ b/test/CPPDEFINES/live.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 basic use of CPPDEFINES with live compilation. @@ -33,14 +32,14 @@ import TestSCons test = TestSCons.TestSCons() test.write('SConstruct', """\ -foo = Environment(CPPDEFINES = ['FOO', ('VAL', '$VALUE')], VALUE=7) -bar = Environment(CPPDEFINES = {'BAR':None, 'VAL':8}) -baz = Environment(CPPDEFINES = ['BAZ', ('VAL', 9)]) -f = foo.Object(target = 'foo', source = 'prog.c') -b = bar.Object(target = 'bar', source = 'prog.c') -foo.Program(target = 'foo', source = f) -bar.Program(target = 'bar', source = b) -baz.Program(target = 'baz', source = 'baz.cpp') +foo = Environment(CPPDEFINES=['FOO', ('VAL', '$VALUE')], VALUE=7) +bar = Environment(CPPDEFINES={'BAR': None, 'VAL': 8}) +baz = Environment(CPPDEFINES=['BAZ', ('VAL', 9)]) +f = foo.Object(target='foo', source='prog.c') +b = bar.Object(target='bar', source='prog.c') +foo.Program(target='foo', source=f) +bar.Program(target='bar', source=b) +baz.Program(target='baz', source='baz.cpp') """) test.write('prog.c', r""" @@ -74,12 +73,10 @@ main(int argc, char *argv[]) } """) - -test.run(arguments = '.') - -test.run(program = test.workpath('foo'), stdout = "prog.c: FOO 7\n") -test.run(program = test.workpath('bar'), stdout = "prog.c: BAR 8\n") -test.run(program = test.workpath('baz'), stdout = "baz.cpp: BAZ 9\n") +test.run(arguments='.') +test.run(program=test.workpath('foo'), stdout="prog.c: FOO 7\n") +test.run(program=test.workpath('bar'), stdout="prog.c: BAR 8\n") +test.run(program=test.workpath('baz'), stdout="baz.cpp: BAZ 9\n") test.pass_test() diff --git a/test/CPPDEFINES/pkg-config.py b/test/CPPDEFINES/pkg-config.py index 65210ce..cd8c9dc 100644 --- a/test/CPPDEFINES/pkg-config.py +++ b/test/CPPDEFINES/pkg-config.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 merging with MergeFlags to CPPPDEFINES with various data types. @@ -69,12 +68,14 @@ else: test.write('SConstruct', """\ import os import sys + # Python3 dicts dont preserve order. Hence we supply subclass of OrderedDict # whose __str__ and __repr__ act like a normal dict. from collections import OrderedDict + class OrderedPrintingDict(OrderedDict): def __repr__(self): - return '{' + ', '.join(['%r: %r'%(k, v) for (k, v) in self.items()]) + '}' + return '{' + ', '.join(['%r: %r' % (k, v) for (k, v) in self.items()]) + '}' __str__ = __repr__ @@ -85,29 +86,41 @@ class OrderedPrintingDict(OrderedDict): """ + """ # https://github.com/SCons/scons/issues/2671 # Passing test cases -env_1 = Environment(CPPDEFINES=[('DEBUG','1'), 'TEST'], tools = ['%(pkg_config_tools)s']) +env_1 = Environment(CPPDEFINES=[('DEBUG', '1'), 'TEST'], tools=['%(pkg_config_tools)s']) if sys.platform == 'win32': - os.environ['PKG_CONFIG_PATH'] = env_1.Dir('.').abspath.replace("\\\\" , "/") -env_1.ParseConfig('%(pkg_config_cl_path)s "%(pkg_config_path)s" --cflags %(pkg_config_file)s') + os.environ['PKG_CONFIG_PATH'] = env_1.Dir('.').abspath.replace("\\\\", "/") +env_1.ParseConfig( + '%(pkg_config_cl_path)s "%(pkg_config_path)s" --cflags %(pkg_config_file)s' +) print(env_1.subst('$_CPPDEFFLAGS')) -env_2 = Environment(CPPDEFINES=[('DEBUG','1'), 'TEST'], tools = ['%(pkg_config_tools)s']) +env_2 = Environment(CPPDEFINES=[('DEBUG', '1'), 'TEST'], tools=['%(pkg_config_tools)s']) env_2.MergeFlags('-DSOMETHING -DVARIABLE=2') print(env_2.subst('$_CPPDEFFLAGS')) # Failing test cases -env_3 = Environment(CPPDEFINES=OrderedPrintingDict([('DEBUG', 1), ('TEST', None)]), tools = ['%(pkg_config_tools)s']) -env_3.ParseConfig('%(pkg_config_cl_path)s "%(pkg_config_path)s" --cflags %(pkg_config_file)s') +env_3 = Environment( + CPPDEFINES=OrderedPrintingDict([('DEBUG', 1), ('TEST', None)]), + tools=['%(pkg_config_tools)s'], +) +env_3.ParseConfig( + '%(pkg_config_cl_path)s "%(pkg_config_path)s" --cflags %(pkg_config_file)s' +) print(env_3.subst('$_CPPDEFFLAGS')) -env_4 = Environment(CPPDEFINES=OrderedPrintingDict([('DEBUG', 1), ('TEST', None)]), tools = ['%(pkg_config_tools)s']) +env_4 = Environment( + CPPDEFINES=OrderedPrintingDict([('DEBUG', 1), ('TEST', None)]), + tools=['%(pkg_config_tools)s'], +) env_4.MergeFlags('-DSOMETHING -DVARIABLE=2') print(env_4.subst('$_CPPDEFFLAGS')) # https://github.com/SCons/scons/issues/1738 -env_1738_1 = Environment(tools = ['%(pkg_config_tools)s']) -env_1738_1.ParseConfig('%(pkg_config_cl_path)s "%(pkg_config_path)s" --cflags --libs %(pkg_config_file)s') -env_1738_1.Append(CPPDEFINES={'value' : '1'}) +env_1738_1 = Environment(tools=['%(pkg_config_tools)s']) +env_1738_1.ParseConfig( + '%(pkg_config_cl_path)s "%(pkg_config_path)s" --cflags --libs %(pkg_config_file)s' +) +env_1738_1.Append(CPPDEFINES={'value': '1'}) print(env_1738_1.subst('$_CPPDEFFLAGS')) """%locals() ) @@ -119,11 +132,10 @@ expect_print_output="""\ -DSOMETHING -DVARIABLE=2 -Dvalue=1 """ -build_output="scons: `.' is up to date.\n" +build_output = "scons: `.' is up to date.\n" +expect = test.wrap_stdout(build_str=build_output, read_str=expect_print_output) +test.run(arguments='.', stdout=expect) -expect = test.wrap_stdout(build_str=build_output, - read_str = expect_print_output) -test.run(arguments = '.', stdout=expect) test.pass_test() # Local Variables: diff --git a/test/CPPDEFINES/prepend.py b/test/CPPDEFINES/prepend.py new file mode 100644 index 0000000..3e8d8d1 --- /dev/null +++ b/test/CPPDEFINES/prepend.py @@ -0,0 +1,258 @@ +#!/usr/bin/env python +# +# 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 +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +""" +Verify prepending to CPPPDEFINES with various data types. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +# Note: explicitly set CPPDEFPREFIX here to simplify testing on Windows. + +# Link: fixture/SConstruct-Prepend +test.file_fixture(["fixture", "SConstruct-Prepend"], "SConstruct") + +expect_print_output="""\ +-Dvalue=1 -DFOO +-Dbar -Dfoo +-Dbar -Dfoo +-Dbaz -Dfoo -Dbar +-Dbaz -Dfoo bar +-Dbar baz -Dfoo +-DMacro1=Value1 -DMacro3=Value3 -DMacro2=Value2 +==== Testing CPPDEFINES, prepending a string to a string + orig = 'FOO', prepend = 'FOO' +Prepend: + result=['FOO', 'FOO'] + final=-DFOO -DFOO +PrependUnique: + result=['FOO'] + final=-DFOO +==== Testing CPPDEFINES, prepending a valuestring to a string + orig = 'FOO', prepend = 'NAME1=VAL1' +Prepend: + result=['NAME1=VAL1', 'FOO'] + final=-DNAME1=VAL1 -DFOO +PrependUnique: + result=['NAME1=VAL1', 'FOO'] + final=-DNAME1=VAL1 -DFOO +==== Testing CPPDEFINES, prepending a list to a string + orig = 'FOO', prepend = ['NAME1', 'NAME2'] +Prepend: + result=['NAME2', 'NAME1', 'FOO'] + final=-DNAME2 -DNAME1 -DFOO +PrependUnique: + result=['NAME2', 'NAME1', 'FOO'] + final=-DNAME2 -DNAME1 -DFOO +==== Testing CPPDEFINES, prepending a list-of-2lists to a string + orig = 'FOO', prepend = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] +Prepend: + result=[['NAME2', 'VAL2'], ('NAME1', 'VAL1'), 'FOO'] + final=-DNAME2=VAL2 -DNAME1=VAL1 -DFOO +PrependUnique: + result=[['NAME2', 'VAL2'], ('NAME1', 'VAL1'), 'FOO'] + final=-DNAME2=VAL2 -DNAME1=VAL1 -DFOO +==== Testing CPPDEFINES, prepending a dict to a string + orig = 'FOO', prepend = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} +Prepend: + result=[('NAME1', 'VAL1'), ('NAME3', None), ('NAME2', 'VAL2'), 'FOO'] + final=-DNAME1=VAL1 -DNAME3 -DNAME2=VAL2 -DFOO +PrependUnique: + result=[('NAME1', 'VAL1'), ('NAME3', None), ('NAME2', 'VAL2'), 'FOO'] + final=-DNAME1=VAL1 -DNAME3 -DNAME2=VAL2 -DFOO +==== Testing CPPDEFINES, prepending a string to a valuestring + orig = 'NAME1=VAL1', prepend = 'FOO' +Prepend: + result=['FOO', 'NAME1=VAL1'] + final=-DFOO -DNAME1=VAL1 +PrependUnique: + result=['FOO', 'NAME1=VAL1'] + final=-DFOO -DNAME1=VAL1 +==== Testing CPPDEFINES, prepending a valuestring to a valuestring + orig = 'NAME1=VAL1', prepend = 'NAME1=VAL1' +Prepend: + result=['NAME1=VAL1', 'NAME1=VAL1'] + final=-DNAME1=VAL1 -DNAME1=VAL1 +PrependUnique: + result=['NAME1=VAL1'] + final=-DNAME1=VAL1 +==== Testing CPPDEFINES, prepending a list to a valuestring + orig = 'NAME1=VAL1', prepend = ['NAME1', 'NAME2'] +Prepend: + result=['NAME2', 'NAME1', 'NAME1=VAL1'] + final=-DNAME2 -DNAME1 -DNAME1=VAL1 +PrependUnique: + result=['NAME2', 'NAME1', 'NAME1=VAL1'] + final=-DNAME2 -DNAME1 -DNAME1=VAL1 +==== Testing CPPDEFINES, prepending a list-of-2lists to a valuestring + orig = 'NAME1=VAL1', prepend = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] +Prepend: + result=[['NAME2', 'VAL2'], ('NAME1', 'VAL1'), 'NAME1=VAL1'] + final=-DNAME2=VAL2 -DNAME1=VAL1 -DNAME1=VAL1 +PrependUnique: + result=[['NAME2', 'VAL2'], 'NAME1=VAL1'] + final=-DNAME2=VAL2 -DNAME1=VAL1 +==== Testing CPPDEFINES, prepending a dict to a valuestring + orig = 'NAME1=VAL1', prepend = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} +Prepend: + result=[('NAME1', 'VAL1'), ('NAME3', None), ('NAME2', 'VAL2'), 'NAME1=VAL1'] + final=-DNAME1=VAL1 -DNAME3 -DNAME2=VAL2 -DNAME1=VAL1 +PrependUnique: + result=[('NAME3', None), ('NAME2', 'VAL2'), 'NAME1=VAL1'] + final=-DNAME3 -DNAME2=VAL2 -DNAME1=VAL1 +==== Testing CPPDEFINES, prepending a string to a list + orig = ['NAME1', 'NAME2'], prepend = 'FOO' +Prepend: + result=['FOO', 'NAME1', 'NAME2'] + final=-DFOO -DNAME1 -DNAME2 +PrependUnique: + result=['FOO', 'NAME1', 'NAME2'] + final=-DFOO -DNAME1 -DNAME2 +==== Testing CPPDEFINES, prepending a valuestring to a list + orig = ['NAME1', 'NAME2'], prepend = 'NAME1=VAL1' +Prepend: + result=['NAME1=VAL1', 'NAME1', 'NAME2'] + final=-DNAME1=VAL1 -DNAME1 -DNAME2 +PrependUnique: + result=['NAME1=VAL1', 'NAME1', 'NAME2'] + final=-DNAME1=VAL1 -DNAME1 -DNAME2 +==== Testing CPPDEFINES, prepending a list to a list + orig = ['NAME1', 'NAME2'], prepend = ['NAME1', 'NAME2'] +Prepend: + result=['NAME2', 'NAME1', 'NAME1', 'NAME2'] + final=-DNAME2 -DNAME1 -DNAME1 -DNAME2 +PrependUnique: + result=['NAME1', 'NAME2'] + final=-DNAME1 -DNAME2 +==== Testing CPPDEFINES, prepending a list-of-2lists to a list + orig = ['NAME1', 'NAME2'], prepend = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] +Prepend: + result=[['NAME2', 'VAL2'], ('NAME1', 'VAL1'), 'NAME1', 'NAME2'] + final=-DNAME2=VAL2 -DNAME1=VAL1 -DNAME1 -DNAME2 +PrependUnique: + result=[['NAME2', 'VAL2'], ('NAME1', 'VAL1'), 'NAME1', 'NAME2'] + final=-DNAME2=VAL2 -DNAME1=VAL1 -DNAME1 -DNAME2 +==== Testing CPPDEFINES, prepending a dict to a list + orig = ['NAME1', 'NAME2'], prepend = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} +Prepend: + result=[('NAME1', 'VAL1'), ('NAME3', None), ('NAME2', 'VAL2'), 'NAME1', 'NAME2'] + final=-DNAME1=VAL1 -DNAME3 -DNAME2=VAL2 -DNAME1 -DNAME2 +PrependUnique: + result=[('NAME1', 'VAL1'), ('NAME3', None), ('NAME2', 'VAL2'), 'NAME1', 'NAME2'] + final=-DNAME1=VAL1 -DNAME3 -DNAME2=VAL2 -DNAME1 -DNAME2 +==== Testing CPPDEFINES, prepending a string to a list-of-2lists + orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], prepend = 'FOO' +Prepend: + result=['FOO', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DFOO -DNAME1=VAL1 -DNAME2=VAL2 +PrependUnique: + result=['FOO', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DFOO -DNAME1=VAL1 -DNAME2=VAL2 +==== Testing CPPDEFINES, prepending a valuestring to a list-of-2lists + orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], prepend = 'NAME1=VAL1' +Prepend: + result=['NAME1=VAL1', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME1=VAL1 -DNAME1=VAL1 -DNAME2=VAL2 +PrependUnique: + result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME1=VAL1 -DNAME2=VAL2 +==== Testing CPPDEFINES, prepending a list to a list-of-2lists + orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], prepend = ['NAME1', 'NAME2'] +Prepend: + result=['NAME2', 'NAME1', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME2 -DNAME1 -DNAME1=VAL1 -DNAME2=VAL2 +PrependUnique: + result=['NAME2', 'NAME1', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME2 -DNAME1 -DNAME1=VAL1 -DNAME2=VAL2 +==== Testing CPPDEFINES, prepending a list-of-2lists to a list-of-2lists + orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], prepend = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] +Prepend: + result=[['NAME2', 'VAL2'], ('NAME1', 'VAL1'), ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME2=VAL2 -DNAME1=VAL1 -DNAME1=VAL1 -DNAME2=VAL2 +PrependUnique: + result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME1=VAL1 -DNAME2=VAL2 +==== Testing CPPDEFINES, prepending a dict to a list-of-2lists + orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], prepend = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} +Prepend: + result=[('NAME1', 'VAL1'), ('NAME3', None), ('NAME2', 'VAL2'), ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME1=VAL1 -DNAME3 -DNAME2=VAL2 -DNAME1=VAL1 -DNAME2=VAL2 +PrependUnique: + result=[('NAME3', None), ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME3 -DNAME1=VAL1 -DNAME2=VAL2 +==== Testing CPPDEFINES, prepending a string to a dict + orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, prepend = 'FOO' +Prepend: + result=['FOO', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DFOO -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 +PrependUnique: + result=['FOO', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DFOO -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 +==== Testing CPPDEFINES, prepending a valuestring to a dict + orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, prepend = 'NAME1=VAL1' +Prepend: + result=['NAME1=VAL1', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 +PrependUnique: + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 +==== Testing CPPDEFINES, prepending a list to a dict + orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, prepend = ['NAME1', 'NAME2'] +Prepend: + result=['NAME2', 'NAME1', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME2 -DNAME1 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 +PrependUnique: + result=['NAME2', 'NAME1', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME2 -DNAME1 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 +==== Testing CPPDEFINES, prepending a list-of-2lists to a dict + orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, prepend = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] +Prepend: + result=[['NAME2', 'VAL2'], ('NAME1', 'VAL1'), ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME2=VAL2 -DNAME1=VAL1 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 +PrependUnique: + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 +==== Testing CPPDEFINES, prepending a dict to a dict + orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, prepend = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} +Prepend: + result=[('NAME1', 'VAL1'), ('NAME3', None), ('NAME2', 'VAL2'), ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME1=VAL1 -DNAME3 -DNAME2=VAL2 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 +PrependUnique: + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 +""" + +build_output="scons: `.' is up to date.\n" +expect = test.wrap_stdout(build_str=build_output, read_str=expect_print_output) +test.run(arguments='.', stdout=expect) +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/CPPDEFINES/scan.py b/test/CPPDEFINES/scan.py index 5318642..49cbec2 100644 --- a/test/CPPDEFINES/scan.py +++ b/test/CPPDEFINES/scan.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 use of the Scanner that evaluates CPP lines works as expected. @@ -41,12 +40,12 @@ f3_exe = 'f3' + TestSCons._exe f4_exe = 'f4' + TestSCons._exe test.write('SConstruct', """\ -env = Environment(CPPPATH = ['.']) +env = Environment(CPPPATH=['.']) -f1 = env.Object('f1', 'fff.c', CPPDEFINES = ['F1']) -f2 = env.Object('f2', 'fff.c', CPPDEFINES = [('F2', 1)]) -f3 = env.Object('f3', 'fff.c', CPPDEFINES = {'F3':None}) -f4 = env.Object('f4', 'fff.c', CPPDEFINES = {'F4':1}) +f1 = env.Object('f1', 'fff.c', CPPDEFINES=['F1']) +f2 = env.Object('f2', 'fff.c', CPPDEFINES=[('F2', 1)]) +f3 = env.Object('f3', 'fff.c', CPPDEFINES={'F3': None}) +f4 = env.Object('f4', 'fff.c', CPPDEFINES={'F4': 1}) env.Program('f1', ['prog.c', f1]) env.Program('f2', ['prog.c', f2]) @@ -110,20 +109,16 @@ main(int argc, char *argv[]) test.run(arguments = '.') - test.run(program = test.workpath('f1'), stdout = "prog.c: F1\n") test.run(program = test.workpath('f2'), stdout = "prog.c: F2\n") test.run(program = test.workpath('f3'), stdout = "prog.c: F3\n") test.run(program = test.workpath('f4'), stdout = "prog.c: F4\n") - - test.write('f1.h', """ #define STRING "F1 again" """) test.up_to_date(arguments = '%(f2_exe)s %(f3_exe)s %(f4_exe)s' % locals()) - test.not_up_to_date(arguments = '.') test.run(program = test.workpath('f1'), stdout = "prog.c: F1 again\n") @@ -131,14 +126,11 @@ test.run(program = test.workpath('f2'), stdout = "prog.c: F2\n") test.run(program = test.workpath('f3'), stdout = "prog.c: F3\n") test.run(program = test.workpath('f4'), stdout = "prog.c: F4\n") - - test.write('f2.h', """ #define STRING "F2 again" """) test.up_to_date(arguments = '%(f1_exe)s %(f3_exe)s %(f4_exe)s' % locals()) - test.not_up_to_date(arguments = '.') test.run(program = test.workpath('f1'), stdout = "prog.c: F1 again\n") @@ -146,14 +138,11 @@ test.run(program = test.workpath('f2'), stdout = "prog.c: F2 again\n") test.run(program = test.workpath('f3'), stdout = "prog.c: F3\n") test.run(program = test.workpath('f4'), stdout = "prog.c: F4\n") - - test.write('f3.h', """ #define STRING "F3 again" """) test.up_to_date(arguments = '%(f1_exe)s %(f2_exe)s %(f4_exe)s' % locals()) - test.not_up_to_date(arguments = '.') test.run(program = test.workpath('f1'), stdout = "prog.c: F1 again\n") @@ -161,14 +150,11 @@ test.run(program = test.workpath('f2'), stdout = "prog.c: F2 again\n") test.run(program = test.workpath('f3'), stdout = "prog.c: F3 again\n") test.run(program = test.workpath('f4'), stdout = "prog.c: F4\n") - - test.write('f4.h', """ #define STRING "F4 again" """) test.up_to_date(arguments = '%(f1_exe)s %(f2_exe)s %(f3_exe)s' % locals()) - test.not_up_to_date(arguments = '.') test.run(program = test.workpath('f1'), stdout = "prog.c: F1 again\n") @@ -176,8 +162,6 @@ test.run(program = test.workpath('f2'), stdout = "prog.c: F2 again\n") test.run(program = test.workpath('f3'), stdout = "prog.c: F3 again\n") test.run(program = test.workpath('f4'), stdout = "prog.c: F4 again\n") - - test.pass_test() # Local Variables: diff --git a/test/CPPDEFINES/undefined.py b/test/CPPDEFINES/undefined.py index b26b05a..31568ea 100644 --- a/test/CPPDEFINES/undefined.py +++ b/test/CPPDEFINES/undefined.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 $_CPPDEFFLAGS doesn't barf when CPPDEFINES isn't defined. @@ -37,10 +36,8 @@ env = Environment() print(env.subst('$_CPPDEFFLAGS')) """) -expect = test.wrap_stdout(build_str="scons: `.' is up to date.\n", - read_str = "\n") - -test.run(arguments = '.', stdout=expect) +expect = test.wrap_stdout(build_str="scons: `.' is up to date.\n", read_str="\n") +test.run(arguments='.', stdout=expect) test.pass_test() -- cgit v0.12 From 41402d74766c0f7c008bfb6186c7bda15f703993 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Mon, 14 Nov 2022 12:11:47 -0700 Subject: Fix some pyside complaints Signed-off-by: Mats Wichmann --- SCons/Defaults.py | 3 +-- SCons/Environment.py | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/SCons/Defaults.py b/SCons/Defaults.py index da90260..ad64041 100644 --- a/SCons/Defaults.py +++ b/SCons/Defaults.py @@ -36,7 +36,6 @@ import shutil import stat import sys import time -from collections import deque import SCons.Action import SCons.Builder @@ -539,7 +538,7 @@ def processDefines(defs): dlist.append(str(define)) else: raise SCons.Errors.UserError( - f"DEFINE {d!r} is not a list, dict, string or None." + f"DEFINE {define!r} is not a list, dict, string or None." ) elif is_Dict(defs): for macro, value in defs.items(): diff --git a/SCons/Environment.py b/SCons/Environment.py index bc69f05..4be5df0 100644 --- a/SCons/Environment.py +++ b/SCons/Environment.py @@ -263,8 +263,8 @@ def _add_cppdefines( item = _macro_conv(item) for define in defines: - if item == _macro_conv(define): - return define + if item == _macro_conv(define): + return define return False -- cgit v0.12 From b1ff3a052e8523ef360fd65a906bdaeaa6cbeb92 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 16 Dec 2022 08:44:44 -0700 Subject: test/CPPDEFINES: stop using tabs The test output for append and prepend generated tabs, and so the "expected" strings had to contain tab indents. This made Sider on the CI extremely noisy. There's no specific benefit to tabs here, so just change them to spaces. Signed-off-by: Mats Wichmann --- test/CPPDEFINES/append.py | 200 ++++++++++++++--------------- test/CPPDEFINES/fixture/SConstruct-Append | 4 +- test/CPPDEFINES/fixture/SConstruct-Prepend | 4 +- test/CPPDEFINES/prepend.py | 200 ++++++++++++++--------------- 4 files changed, 204 insertions(+), 204 deletions(-) diff --git a/test/CPPDEFINES/append.py b/test/CPPDEFINES/append.py index 4c5e562..0d074cf 100644 --- a/test/CPPDEFINES/append.py +++ b/test/CPPDEFINES/append.py @@ -48,203 +48,203 @@ expect_print_output="""\ ==== Testing CPPDEFINES, appending a string to a string orig = 'FOO', append = 'FOO' Append: - result=['FOO', 'FOO'] - final=-DFOO -DFOO + result=['FOO', 'FOO'] + final=-DFOO -DFOO AppendUnique: - result=['FOO'] - final=-DFOO + result=['FOO'] + final=-DFOO ==== Testing CPPDEFINES, appending a valuestring to a string orig = 'FOO', append = 'NAME1=VAL1' Append: - result=['FOO', 'NAME1=VAL1'] - final=-DFOO -DNAME1=VAL1 + result=['FOO', 'NAME1=VAL1'] + final=-DFOO -DNAME1=VAL1 AppendUnique: - result=['FOO', 'NAME1=VAL1'] - final=-DFOO -DNAME1=VAL1 + result=['FOO', 'NAME1=VAL1'] + final=-DFOO -DNAME1=VAL1 ==== Testing CPPDEFINES, appending a list to a string orig = 'FOO', append = ['NAME1', 'NAME2'] Append: - result=['FOO', 'NAME1', 'NAME2'] - final=-DFOO -DNAME1 -DNAME2 + result=['FOO', 'NAME1', 'NAME2'] + final=-DFOO -DNAME1 -DNAME2 AppendUnique: - result=['FOO', 'NAME1', 'NAME2'] - final=-DFOO -DNAME1 -DNAME2 + result=['FOO', 'NAME1', 'NAME2'] + final=-DFOO -DNAME1 -DNAME2 ==== Testing CPPDEFINES, appending a list-of-2lists to a string orig = 'FOO', append = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Append: - result=['FOO', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] - final=-DFOO -DNAME1=VAL1 -DNAME2=VAL2 + result=['FOO', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DFOO -DNAME1=VAL1 -DNAME2=VAL2 AppendUnique: - result=['FOO', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] - final=-DFOO -DNAME1=VAL1 -DNAME2=VAL2 + result=['FOO', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DFOO -DNAME1=VAL1 -DNAME2=VAL2 ==== Testing CPPDEFINES, appending a dict to a string orig = 'FOO', append = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} Append: - result=['FOO', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] - final=-DFOO -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 + result=['FOO', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DFOO -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 AppendUnique: - result=['FOO', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] - final=-DFOO -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 + result=['FOO', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DFOO -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 ==== Testing CPPDEFINES, appending a string to a valuestring orig = 'NAME1=VAL1', append = 'FOO' Append: - result=['NAME1=VAL1', 'FOO'] - final=-DNAME1=VAL1 -DFOO + result=['NAME1=VAL1', 'FOO'] + final=-DNAME1=VAL1 -DFOO AppendUnique: - result=['NAME1=VAL1', 'FOO'] - final=-DNAME1=VAL1 -DFOO + result=['NAME1=VAL1', 'FOO'] + final=-DNAME1=VAL1 -DFOO ==== Testing CPPDEFINES, appending a valuestring to a valuestring orig = 'NAME1=VAL1', append = 'NAME1=VAL1' Append: - result=['NAME1=VAL1', 'NAME1=VAL1'] - final=-DNAME1=VAL1 -DNAME1=VAL1 + result=['NAME1=VAL1', 'NAME1=VAL1'] + final=-DNAME1=VAL1 -DNAME1=VAL1 AppendUnique: - result=['NAME1=VAL1'] - final=-DNAME1=VAL1 + result=['NAME1=VAL1'] + final=-DNAME1=VAL1 ==== Testing CPPDEFINES, appending a list to a valuestring orig = 'NAME1=VAL1', append = ['NAME1', 'NAME2'] Append: - result=['NAME1=VAL1', 'NAME1', 'NAME2'] - final=-DNAME1=VAL1 -DNAME1 -DNAME2 + result=['NAME1=VAL1', 'NAME1', 'NAME2'] + final=-DNAME1=VAL1 -DNAME1 -DNAME2 AppendUnique: - result=['NAME1=VAL1', 'NAME1', 'NAME2'] - final=-DNAME1=VAL1 -DNAME1 -DNAME2 + result=['NAME1=VAL1', 'NAME1', 'NAME2'] + final=-DNAME1=VAL1 -DNAME1 -DNAME2 ==== Testing CPPDEFINES, appending a list-of-2lists to a valuestring orig = 'NAME1=VAL1', append = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Append: - result=['NAME1=VAL1', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] - final=-DNAME1=VAL1 -DNAME1=VAL1 -DNAME2=VAL2 + result=['NAME1=VAL1', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME1=VAL1 -DNAME1=VAL1 -DNAME2=VAL2 AppendUnique: - result=['NAME1=VAL1', ['NAME2', 'VAL2']] - final=-DNAME1=VAL1 -DNAME2=VAL2 + result=['NAME1=VAL1', ['NAME2', 'VAL2']] + final=-DNAME1=VAL1 -DNAME2=VAL2 ==== Testing CPPDEFINES, appending a dict to a valuestring orig = 'NAME1=VAL1', append = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} Append: - result=['NAME1=VAL1', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] - final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 + result=['NAME1=VAL1', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 AppendUnique: - result=['NAME1=VAL1', ('NAME2', 'VAL2'), ('NAME3', None)] - final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME3 + result=['NAME1=VAL1', ('NAME2', 'VAL2'), ('NAME3', None)] + final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME3 ==== Testing CPPDEFINES, appending a string to a list orig = ['NAME1', 'NAME2'], append = 'FOO' Append: - result=['NAME1', 'NAME2', 'FOO'] - final=-DNAME1 -DNAME2 -DFOO + result=['NAME1', 'NAME2', 'FOO'] + final=-DNAME1 -DNAME2 -DFOO AppendUnique: - result=['NAME1', 'NAME2', 'FOO'] - final=-DNAME1 -DNAME2 -DFOO + result=['NAME1', 'NAME2', 'FOO'] + final=-DNAME1 -DNAME2 -DFOO ==== Testing CPPDEFINES, appending a valuestring to a list orig = ['NAME1', 'NAME2'], append = 'NAME1=VAL1' Append: - result=['NAME1', 'NAME2', 'NAME1=VAL1'] - final=-DNAME1 -DNAME2 -DNAME1=VAL1 + result=['NAME1', 'NAME2', 'NAME1=VAL1'] + final=-DNAME1 -DNAME2 -DNAME1=VAL1 AppendUnique: - result=['NAME1', 'NAME2', 'NAME1=VAL1'] - final=-DNAME1 -DNAME2 -DNAME1=VAL1 + result=['NAME1', 'NAME2', 'NAME1=VAL1'] + final=-DNAME1 -DNAME2 -DNAME1=VAL1 ==== Testing CPPDEFINES, appending a list to a list orig = ['NAME1', 'NAME2'], append = ['NAME1', 'NAME2'] Append: - result=['NAME1', 'NAME2', 'NAME1', 'NAME2'] - final=-DNAME1 -DNAME2 -DNAME1 -DNAME2 + result=['NAME1', 'NAME2', 'NAME1', 'NAME2'] + final=-DNAME1 -DNAME2 -DNAME1 -DNAME2 AppendUnique: - result=['NAME1', 'NAME2'] - final=-DNAME1 -DNAME2 + result=['NAME1', 'NAME2'] + final=-DNAME1 -DNAME2 ==== Testing CPPDEFINES, appending a list-of-2lists to a list orig = ['NAME1', 'NAME2'], append = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Append: - result=['NAME1', 'NAME2', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] - final=-DNAME1 -DNAME2 -DNAME1=VAL1 -DNAME2=VAL2 + result=['NAME1', 'NAME2', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME1 -DNAME2 -DNAME1=VAL1 -DNAME2=VAL2 AppendUnique: - result=['NAME1', 'NAME2', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] - final=-DNAME1 -DNAME2 -DNAME1=VAL1 -DNAME2=VAL2 + result=['NAME1', 'NAME2', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME1 -DNAME2 -DNAME1=VAL1 -DNAME2=VAL2 ==== Testing CPPDEFINES, appending a dict to a list orig = ['NAME1', 'NAME2'], append = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} Append: - result=['NAME1', 'NAME2', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] - final=-DNAME1 -DNAME2 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 + result=['NAME1', 'NAME2', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME1 -DNAME2 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 AppendUnique: - result=['NAME1', 'NAME2', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] - final=-DNAME1 -DNAME2 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 + result=['NAME1', 'NAME2', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME1 -DNAME2 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 ==== Testing CPPDEFINES, appending a string to a list-of-2lists orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], append = 'FOO' Append: - result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], 'FOO'] - final=-DNAME1=VAL1 -DNAME2=VAL2 -DFOO + result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], 'FOO'] + final=-DNAME1=VAL1 -DNAME2=VAL2 -DFOO AppendUnique: - result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], 'FOO'] - final=-DNAME1=VAL1 -DNAME2=VAL2 -DFOO + result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], 'FOO'] + final=-DNAME1=VAL1 -DNAME2=VAL2 -DFOO ==== Testing CPPDEFINES, appending a valuestring to a list-of-2lists orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], append = 'NAME1=VAL1' Append: - result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], 'NAME1=VAL1'] - final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME1=VAL1 + result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], 'NAME1=VAL1'] + final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME1=VAL1 AppendUnique: - result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2']] - final=-DNAME1=VAL1 -DNAME2=VAL2 + result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME1=VAL1 -DNAME2=VAL2 ==== Testing CPPDEFINES, appending a list to a list-of-2lists orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], append = ['NAME1', 'NAME2'] Append: - result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], 'NAME1', 'NAME2'] - final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME1 -DNAME2 + result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], 'NAME1', 'NAME2'] + final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME1 -DNAME2 AppendUnique: - result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], 'NAME1', 'NAME2'] - final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME1 -DNAME2 + result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], 'NAME1', 'NAME2'] + final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME1 -DNAME2 ==== Testing CPPDEFINES, appending a list-of-2lists to a list-of-2lists orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], append = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Append: - result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] - final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME1=VAL1 -DNAME2=VAL2 + result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME1=VAL1 -DNAME2=VAL2 AppendUnique: - result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2']] - final=-DNAME1=VAL1 -DNAME2=VAL2 + result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME1=VAL1 -DNAME2=VAL2 ==== Testing CPPDEFINES, appending a dict to a list-of-2lists orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], append = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} Append: - result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] - final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 + result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 AppendUnique: - result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], ('NAME3', None)] - final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME3 + result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], ('NAME3', None)] + final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME3 ==== Testing CPPDEFINES, appending a string to a dict orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, append = 'FOO' Append: - result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1'), 'FOO'] - final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DFOO + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1'), 'FOO'] + final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DFOO AppendUnique: - result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1'), 'FOO'] - final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DFOO + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1'), 'FOO'] + final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DFOO ==== Testing CPPDEFINES, appending a valuestring to a dict orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, append = 'NAME1=VAL1' Append: - result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1'), 'NAME1=VAL1'] - final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DNAME1=VAL1 + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1'), 'NAME1=VAL1'] + final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DNAME1=VAL1 AppendUnique: - result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] - final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 ==== Testing CPPDEFINES, appending a list to a dict orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, append = ['NAME1', 'NAME2'] Append: - result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1'), 'NAME1', 'NAME2'] - final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DNAME1 -DNAME2 + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1'), 'NAME1', 'NAME2'] + final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DNAME1 -DNAME2 AppendUnique: - result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1'), 'NAME1', 'NAME2'] - final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DNAME1 -DNAME2 + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1'), 'NAME1', 'NAME2'] + final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DNAME1 -DNAME2 ==== Testing CPPDEFINES, appending a list-of-2lists to a dict orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, append = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Append: - result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1'), ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] - final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DNAME1=VAL1 -DNAME2=VAL2 + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1'), ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DNAME1=VAL1 -DNAME2=VAL2 AppendUnique: - result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] - final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 ==== Testing CPPDEFINES, appending a dict to a dict orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, append = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} Append: - result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1'), ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] - final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1'), ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 AppendUnique: - result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] - final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 """ build_output="scons: `.' is up to date.\n" diff --git a/test/CPPDEFINES/fixture/SConstruct-Append b/test/CPPDEFINES/fixture/SConstruct-Append index a9dea8c..af4db9d 100644 --- a/test/CPPDEFINES/fixture/SConstruct-Append +++ b/test/CPPDEFINES/fixture/SConstruct-Append @@ -90,10 +90,10 @@ for (t1, c1) in cases: env = Environment(CPPDEFINES=c1, CPPDEFPREFIX='-D') env.Append(CPPDEFINES=c2) final = env.subst('$_CPPDEFFLAGS', source="src", target="tgt") - print(f"Append:\n\tresult={dlist(env['CPPDEFINES'])}\n\tfinal={final}") + print(f"Append:\n result={dlist(env['CPPDEFINES'])}\n final={final}") env = Environment(CPPDEFINES=c1, CPPDEFPREFIX='-D') env.AppendUnique(CPPDEFINES=c2) final = env.subst('$_CPPDEFFLAGS', source="src", target="tgt") print( - f"AppendUnique:\n\tresult={dlist(env['CPPDEFINES'])}\n\tfinal={final}" + f"AppendUnique:\n result={dlist(env['CPPDEFINES'])}\n final={final}" ) diff --git a/test/CPPDEFINES/fixture/SConstruct-Prepend b/test/CPPDEFINES/fixture/SConstruct-Prepend index 5934530..52b66e8 100644 --- a/test/CPPDEFINES/fixture/SConstruct-Prepend +++ b/test/CPPDEFINES/fixture/SConstruct-Prepend @@ -91,10 +91,10 @@ for (t1, c1) in cases: env = Environment(CPPDEFINES=c1, CPPDEFPREFIX='-D') env.Prepend(CPPDEFINES=c2) final = env.subst('$_CPPDEFFLAGS', source="src", target="tgt") - print(f"Prepend:\n\tresult={dlist(env['CPPDEFINES'])}\n\tfinal={final}") + print(f"Prepend:\n result={dlist(env['CPPDEFINES'])}\n final={final}") env = Environment(CPPDEFINES=c1, CPPDEFPREFIX='-D') env.PrependUnique(CPPDEFINES=c2) final = env.subst('$_CPPDEFFLAGS', source="src", target="tgt") print( - f"PrependUnique:\n\tresult={dlist(env['CPPDEFINES'])}\n\tfinal={final}" + f"PrependUnique:\n result={dlist(env['CPPDEFINES'])}\n final={final}" ) diff --git a/test/CPPDEFINES/prepend.py b/test/CPPDEFINES/prepend.py index 3e8d8d1..2e63e87 100644 --- a/test/CPPDEFINES/prepend.py +++ b/test/CPPDEFINES/prepend.py @@ -47,203 +47,203 @@ expect_print_output="""\ ==== Testing CPPDEFINES, prepending a string to a string orig = 'FOO', prepend = 'FOO' Prepend: - result=['FOO', 'FOO'] - final=-DFOO -DFOO + result=['FOO', 'FOO'] + final=-DFOO -DFOO PrependUnique: - result=['FOO'] - final=-DFOO + result=['FOO'] + final=-DFOO ==== Testing CPPDEFINES, prepending a valuestring to a string orig = 'FOO', prepend = 'NAME1=VAL1' Prepend: - result=['NAME1=VAL1', 'FOO'] - final=-DNAME1=VAL1 -DFOO + result=['NAME1=VAL1', 'FOO'] + final=-DNAME1=VAL1 -DFOO PrependUnique: - result=['NAME1=VAL1', 'FOO'] - final=-DNAME1=VAL1 -DFOO + result=['NAME1=VAL1', 'FOO'] + final=-DNAME1=VAL1 -DFOO ==== Testing CPPDEFINES, prepending a list to a string orig = 'FOO', prepend = ['NAME1', 'NAME2'] Prepend: - result=['NAME2', 'NAME1', 'FOO'] - final=-DNAME2 -DNAME1 -DFOO + result=['NAME2', 'NAME1', 'FOO'] + final=-DNAME2 -DNAME1 -DFOO PrependUnique: - result=['NAME2', 'NAME1', 'FOO'] - final=-DNAME2 -DNAME1 -DFOO + result=['NAME2', 'NAME1', 'FOO'] + final=-DNAME2 -DNAME1 -DFOO ==== Testing CPPDEFINES, prepending a list-of-2lists to a string orig = 'FOO', prepend = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Prepend: - result=[['NAME2', 'VAL2'], ('NAME1', 'VAL1'), 'FOO'] - final=-DNAME2=VAL2 -DNAME1=VAL1 -DFOO + result=[['NAME2', 'VAL2'], ('NAME1', 'VAL1'), 'FOO'] + final=-DNAME2=VAL2 -DNAME1=VAL1 -DFOO PrependUnique: - result=[['NAME2', 'VAL2'], ('NAME1', 'VAL1'), 'FOO'] - final=-DNAME2=VAL2 -DNAME1=VAL1 -DFOO + result=[['NAME2', 'VAL2'], ('NAME1', 'VAL1'), 'FOO'] + final=-DNAME2=VAL2 -DNAME1=VAL1 -DFOO ==== Testing CPPDEFINES, prepending a dict to a string orig = 'FOO', prepend = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} Prepend: - result=[('NAME1', 'VAL1'), ('NAME3', None), ('NAME2', 'VAL2'), 'FOO'] - final=-DNAME1=VAL1 -DNAME3 -DNAME2=VAL2 -DFOO + result=[('NAME1', 'VAL1'), ('NAME3', None), ('NAME2', 'VAL2'), 'FOO'] + final=-DNAME1=VAL1 -DNAME3 -DNAME2=VAL2 -DFOO PrependUnique: - result=[('NAME1', 'VAL1'), ('NAME3', None), ('NAME2', 'VAL2'), 'FOO'] - final=-DNAME1=VAL1 -DNAME3 -DNAME2=VAL2 -DFOO + result=[('NAME1', 'VAL1'), ('NAME3', None), ('NAME2', 'VAL2'), 'FOO'] + final=-DNAME1=VAL1 -DNAME3 -DNAME2=VAL2 -DFOO ==== Testing CPPDEFINES, prepending a string to a valuestring orig = 'NAME1=VAL1', prepend = 'FOO' Prepend: - result=['FOO', 'NAME1=VAL1'] - final=-DFOO -DNAME1=VAL1 + result=['FOO', 'NAME1=VAL1'] + final=-DFOO -DNAME1=VAL1 PrependUnique: - result=['FOO', 'NAME1=VAL1'] - final=-DFOO -DNAME1=VAL1 + result=['FOO', 'NAME1=VAL1'] + final=-DFOO -DNAME1=VAL1 ==== Testing CPPDEFINES, prepending a valuestring to a valuestring orig = 'NAME1=VAL1', prepend = 'NAME1=VAL1' Prepend: - result=['NAME1=VAL1', 'NAME1=VAL1'] - final=-DNAME1=VAL1 -DNAME1=VAL1 + result=['NAME1=VAL1', 'NAME1=VAL1'] + final=-DNAME1=VAL1 -DNAME1=VAL1 PrependUnique: - result=['NAME1=VAL1'] - final=-DNAME1=VAL1 + result=['NAME1=VAL1'] + final=-DNAME1=VAL1 ==== Testing CPPDEFINES, prepending a list to a valuestring orig = 'NAME1=VAL1', prepend = ['NAME1', 'NAME2'] Prepend: - result=['NAME2', 'NAME1', 'NAME1=VAL1'] - final=-DNAME2 -DNAME1 -DNAME1=VAL1 + result=['NAME2', 'NAME1', 'NAME1=VAL1'] + final=-DNAME2 -DNAME1 -DNAME1=VAL1 PrependUnique: - result=['NAME2', 'NAME1', 'NAME1=VAL1'] - final=-DNAME2 -DNAME1 -DNAME1=VAL1 + result=['NAME2', 'NAME1', 'NAME1=VAL1'] + final=-DNAME2 -DNAME1 -DNAME1=VAL1 ==== Testing CPPDEFINES, prepending a list-of-2lists to a valuestring orig = 'NAME1=VAL1', prepend = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Prepend: - result=[['NAME2', 'VAL2'], ('NAME1', 'VAL1'), 'NAME1=VAL1'] - final=-DNAME2=VAL2 -DNAME1=VAL1 -DNAME1=VAL1 + result=[['NAME2', 'VAL2'], ('NAME1', 'VAL1'), 'NAME1=VAL1'] + final=-DNAME2=VAL2 -DNAME1=VAL1 -DNAME1=VAL1 PrependUnique: - result=[['NAME2', 'VAL2'], 'NAME1=VAL1'] - final=-DNAME2=VAL2 -DNAME1=VAL1 + result=[['NAME2', 'VAL2'], 'NAME1=VAL1'] + final=-DNAME2=VAL2 -DNAME1=VAL1 ==== Testing CPPDEFINES, prepending a dict to a valuestring orig = 'NAME1=VAL1', prepend = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} Prepend: - result=[('NAME1', 'VAL1'), ('NAME3', None), ('NAME2', 'VAL2'), 'NAME1=VAL1'] - final=-DNAME1=VAL1 -DNAME3 -DNAME2=VAL2 -DNAME1=VAL1 + result=[('NAME1', 'VAL1'), ('NAME3', None), ('NAME2', 'VAL2'), 'NAME1=VAL1'] + final=-DNAME1=VAL1 -DNAME3 -DNAME2=VAL2 -DNAME1=VAL1 PrependUnique: - result=[('NAME3', None), ('NAME2', 'VAL2'), 'NAME1=VAL1'] - final=-DNAME3 -DNAME2=VAL2 -DNAME1=VAL1 + result=[('NAME3', None), ('NAME2', 'VAL2'), 'NAME1=VAL1'] + final=-DNAME3 -DNAME2=VAL2 -DNAME1=VAL1 ==== Testing CPPDEFINES, prepending a string to a list orig = ['NAME1', 'NAME2'], prepend = 'FOO' Prepend: - result=['FOO', 'NAME1', 'NAME2'] - final=-DFOO -DNAME1 -DNAME2 + result=['FOO', 'NAME1', 'NAME2'] + final=-DFOO -DNAME1 -DNAME2 PrependUnique: - result=['FOO', 'NAME1', 'NAME2'] - final=-DFOO -DNAME1 -DNAME2 + result=['FOO', 'NAME1', 'NAME2'] + final=-DFOO -DNAME1 -DNAME2 ==== Testing CPPDEFINES, prepending a valuestring to a list orig = ['NAME1', 'NAME2'], prepend = 'NAME1=VAL1' Prepend: - result=['NAME1=VAL1', 'NAME1', 'NAME2'] - final=-DNAME1=VAL1 -DNAME1 -DNAME2 + result=['NAME1=VAL1', 'NAME1', 'NAME2'] + final=-DNAME1=VAL1 -DNAME1 -DNAME2 PrependUnique: - result=['NAME1=VAL1', 'NAME1', 'NAME2'] - final=-DNAME1=VAL1 -DNAME1 -DNAME2 + result=['NAME1=VAL1', 'NAME1', 'NAME2'] + final=-DNAME1=VAL1 -DNAME1 -DNAME2 ==== Testing CPPDEFINES, prepending a list to a list orig = ['NAME1', 'NAME2'], prepend = ['NAME1', 'NAME2'] Prepend: - result=['NAME2', 'NAME1', 'NAME1', 'NAME2'] - final=-DNAME2 -DNAME1 -DNAME1 -DNAME2 + result=['NAME2', 'NAME1', 'NAME1', 'NAME2'] + final=-DNAME2 -DNAME1 -DNAME1 -DNAME2 PrependUnique: - result=['NAME1', 'NAME2'] - final=-DNAME1 -DNAME2 + result=['NAME1', 'NAME2'] + final=-DNAME1 -DNAME2 ==== Testing CPPDEFINES, prepending a list-of-2lists to a list orig = ['NAME1', 'NAME2'], prepend = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Prepend: - result=[['NAME2', 'VAL2'], ('NAME1', 'VAL1'), 'NAME1', 'NAME2'] - final=-DNAME2=VAL2 -DNAME1=VAL1 -DNAME1 -DNAME2 + result=[['NAME2', 'VAL2'], ('NAME1', 'VAL1'), 'NAME1', 'NAME2'] + final=-DNAME2=VAL2 -DNAME1=VAL1 -DNAME1 -DNAME2 PrependUnique: - result=[['NAME2', 'VAL2'], ('NAME1', 'VAL1'), 'NAME1', 'NAME2'] - final=-DNAME2=VAL2 -DNAME1=VAL1 -DNAME1 -DNAME2 + result=[['NAME2', 'VAL2'], ('NAME1', 'VAL1'), 'NAME1', 'NAME2'] + final=-DNAME2=VAL2 -DNAME1=VAL1 -DNAME1 -DNAME2 ==== Testing CPPDEFINES, prepending a dict to a list orig = ['NAME1', 'NAME2'], prepend = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} Prepend: - result=[('NAME1', 'VAL1'), ('NAME3', None), ('NAME2', 'VAL2'), 'NAME1', 'NAME2'] - final=-DNAME1=VAL1 -DNAME3 -DNAME2=VAL2 -DNAME1 -DNAME2 + result=[('NAME1', 'VAL1'), ('NAME3', None), ('NAME2', 'VAL2'), 'NAME1', 'NAME2'] + final=-DNAME1=VAL1 -DNAME3 -DNAME2=VAL2 -DNAME1 -DNAME2 PrependUnique: - result=[('NAME1', 'VAL1'), ('NAME3', None), ('NAME2', 'VAL2'), 'NAME1', 'NAME2'] - final=-DNAME1=VAL1 -DNAME3 -DNAME2=VAL2 -DNAME1 -DNAME2 + result=[('NAME1', 'VAL1'), ('NAME3', None), ('NAME2', 'VAL2'), 'NAME1', 'NAME2'] + final=-DNAME1=VAL1 -DNAME3 -DNAME2=VAL2 -DNAME1 -DNAME2 ==== Testing CPPDEFINES, prepending a string to a list-of-2lists orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], prepend = 'FOO' Prepend: - result=['FOO', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] - final=-DFOO -DNAME1=VAL1 -DNAME2=VAL2 + result=['FOO', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DFOO -DNAME1=VAL1 -DNAME2=VAL2 PrependUnique: - result=['FOO', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] - final=-DFOO -DNAME1=VAL1 -DNAME2=VAL2 + result=['FOO', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DFOO -DNAME1=VAL1 -DNAME2=VAL2 ==== Testing CPPDEFINES, prepending a valuestring to a list-of-2lists orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], prepend = 'NAME1=VAL1' Prepend: - result=['NAME1=VAL1', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] - final=-DNAME1=VAL1 -DNAME1=VAL1 -DNAME2=VAL2 + result=['NAME1=VAL1', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME1=VAL1 -DNAME1=VAL1 -DNAME2=VAL2 PrependUnique: - result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2']] - final=-DNAME1=VAL1 -DNAME2=VAL2 + result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME1=VAL1 -DNAME2=VAL2 ==== Testing CPPDEFINES, prepending a list to a list-of-2lists orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], prepend = ['NAME1', 'NAME2'] Prepend: - result=['NAME2', 'NAME1', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] - final=-DNAME2 -DNAME1 -DNAME1=VAL1 -DNAME2=VAL2 + result=['NAME2', 'NAME1', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME2 -DNAME1 -DNAME1=VAL1 -DNAME2=VAL2 PrependUnique: - result=['NAME2', 'NAME1', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] - final=-DNAME2 -DNAME1 -DNAME1=VAL1 -DNAME2=VAL2 + result=['NAME2', 'NAME1', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME2 -DNAME1 -DNAME1=VAL1 -DNAME2=VAL2 ==== Testing CPPDEFINES, prepending a list-of-2lists to a list-of-2lists orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], prepend = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Prepend: - result=[['NAME2', 'VAL2'], ('NAME1', 'VAL1'), ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] - final=-DNAME2=VAL2 -DNAME1=VAL1 -DNAME1=VAL1 -DNAME2=VAL2 + result=[['NAME2', 'VAL2'], ('NAME1', 'VAL1'), ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME2=VAL2 -DNAME1=VAL1 -DNAME1=VAL1 -DNAME2=VAL2 PrependUnique: - result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2']] - final=-DNAME1=VAL1 -DNAME2=VAL2 + result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME1=VAL1 -DNAME2=VAL2 ==== Testing CPPDEFINES, prepending a dict to a list-of-2lists orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], prepend = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} Prepend: - result=[('NAME1', 'VAL1'), ('NAME3', None), ('NAME2', 'VAL2'), ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] - final=-DNAME1=VAL1 -DNAME3 -DNAME2=VAL2 -DNAME1=VAL1 -DNAME2=VAL2 + result=[('NAME1', 'VAL1'), ('NAME3', None), ('NAME2', 'VAL2'), ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME1=VAL1 -DNAME3 -DNAME2=VAL2 -DNAME1=VAL1 -DNAME2=VAL2 PrependUnique: - result=[('NAME3', None), ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] - final=-DNAME3 -DNAME1=VAL1 -DNAME2=VAL2 + result=[('NAME3', None), ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME3 -DNAME1=VAL1 -DNAME2=VAL2 ==== Testing CPPDEFINES, prepending a string to a dict orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, prepend = 'FOO' Prepend: - result=['FOO', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] - final=-DFOO -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 + result=['FOO', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DFOO -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 PrependUnique: - result=['FOO', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] - final=-DFOO -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 + result=['FOO', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DFOO -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 ==== Testing CPPDEFINES, prepending a valuestring to a dict orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, prepend = 'NAME1=VAL1' Prepend: - result=['NAME1=VAL1', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] - final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 + result=['NAME1=VAL1', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 PrependUnique: - result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] - final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 ==== Testing CPPDEFINES, prepending a list to a dict orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, prepend = ['NAME1', 'NAME2'] Prepend: - result=['NAME2', 'NAME1', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] - final=-DNAME2 -DNAME1 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 + result=['NAME2', 'NAME1', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME2 -DNAME1 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 PrependUnique: - result=['NAME2', 'NAME1', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] - final=-DNAME2 -DNAME1 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 + result=['NAME2', 'NAME1', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME2 -DNAME1 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 ==== Testing CPPDEFINES, prepending a list-of-2lists to a dict orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, prepend = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Prepend: - result=[['NAME2', 'VAL2'], ('NAME1', 'VAL1'), ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] - final=-DNAME2=VAL2 -DNAME1=VAL1 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 + result=[['NAME2', 'VAL2'], ('NAME1', 'VAL1'), ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME2=VAL2 -DNAME1=VAL1 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 PrependUnique: - result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] - final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 ==== Testing CPPDEFINES, prepending a dict to a dict orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, prepend = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} Prepend: - result=[('NAME1', 'VAL1'), ('NAME3', None), ('NAME2', 'VAL2'), ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] - final=-DNAME1=VAL1 -DNAME3 -DNAME2=VAL2 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 + result=[('NAME1', 'VAL1'), ('NAME3', None), ('NAME2', 'VAL2'), ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME1=VAL1 -DNAME3 -DNAME2=VAL2 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 PrependUnique: - result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] - final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 """ build_output="scons: `.' is up to date.\n" -- cgit v0.12 From 6ea34c031395e9488bf9a55b25d4b567d2c0627d Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sun, 29 Jan 2023 13:14:44 -0700 Subject: CPPDEFINES: reword some doc stuff Fix a typo Try to further clarify how to add valued macros. Signed-off-by: Mats Wichmann --- SCons/Environment.py | 13 +++++++------ SCons/Environment.xml | 37 +++++++++++++++++++++---------------- 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/SCons/Environment.py b/SCons/Environment.py index 4be5df0..e73da82 100644 --- a/SCons/Environment.py +++ b/SCons/Environment.py @@ -235,12 +235,13 @@ def _add_cppdefines( def _is_in(item, defines: deque): """Returns match for *item* if found in *defines*. - Accounts for type differences: ("FOO", "BAR"), ["FOO", "BAR"] - "FOO=BAR" and {"FOO": "BAR"} all iffer as far as Python equality - comparison is concerned, but are the same for purposes of creating - the preprocessor macro. Since the caller may wish to remove a - matched entry, we need to return it - cannot remove *item* - itself unless it happened to be an exact (type) match. + Accounts for type differences: tuple ("FOO", "BAR"), list + ["FOO", "BAR"], string "FOO=BAR" and dict {"FOO": "BAR"} all + differ as far as Python equality comparison is concerned, but + are the same for purposes of creating the preprocessor macro. + Since the caller may wish to remove a matched entry, we need to + return it - cannot remove *item* itself unless it happened to + be an exact (type) match. Called from a place we know *defines* is always a deque, and *item* will not be a dict, so don't need do much type checking. diff --git a/SCons/Environment.xml b/SCons/Environment.xml index 3790a22..f7e2da9 100644 --- a/SCons/Environment.xml +++ b/SCons/Environment.xml @@ -570,7 +570,7 @@ print("CPPDEFINES will expand to", env.subst('$_CPPDEFFLAGS')) $ scons -Q CXXFLAGS = -std=c11, CPPDEFINES = RELEASE CXXFLAGS = -std=c11 -O, CPPDEFINES = deque(['RELEASE', 'EXTRA']) -CPPDEFINES will expand to -DRELEASE -DEXTRA +CPPDEFINES will expand to -DRELEASE -DEXTRA scons: `.' is up to date. @@ -581,13 +581,16 @@ it accepts additional syntax. A command-line preprocessor macro can predefine a name by itself (-DFOO), which gives it an implicit value, -or be given with a macro definition +or be given with a replacement value (-DBAR=1). -&SCons; allows you to specify a macro with a definition -using a name=value string, -or a tuple (name, value) -(which must be supplied inside a sequence type), -or a dictionary {name: value}. +&SCons; allows you to specify a macro with replacement +three different ways: +using a string, like +macro=replacement; +as a (non-string) sequence inside a (non-string) sequence, +like [(macro, replacement)] +or as a key/value pair in a dictionary +{macro: replacement}. Examples: @@ -613,29 +616,31 @@ scons: `.' is up to date. -Multiple &cv-CPPDEFINES; macros can be supplied in a sequence of tuples, +Multiple &cv-CPPDEFINES; macros can be added in a single call +using a (non-string) sequence, or using the dictionary form. -If a given macro name should not have a definition, -omit the value from tuple or give it as +If a given macro name should not have a replacement value, +supply that macro as a string, +or either omit the replacement value or give it as None; if using the dictionary form, -specify the value as None. +specify the value as None. Examples: env = Environment() -env.Append(CPPDEFINES=[("ONE", 1), ("TWO", )]) +env.Append(CPPDEFINES=[("ONE", 1), "TWO", ("THREE", )]) print("CPPDEFINES =", env['CPPDEFINES']) -env.Append(CPPDEFINES={"THREE": 3, "FOUR": None}) +env.Append(CPPDEFINES={"FOUR": 4, "FIVE": None}) print("CPPDEFINES =", env['CPPDEFINES']) print("CPPDEFINES will expand to", env.subst('$_CPPDEFFLAGS')) $ scons -Q -CPPDEFINES = [('ONE', 1), ('TWO',)] -CPPDEFINES = [('ONE', 1), ('TWO',), {'THREE': 3, 'FOUR': None}] -CPPDEFINES will expand to -DONE=1 -DTWO -DTHREE=3 -DFOUR +CPPDEFINES = [('ONE', 1), 'TWO', ('THREE',)] +CPPDEFINES = deque([('ONE', 1), 'TWO', ('THREE',), ('FOUR', 4), ('FIVE', None)]) +CPPDEFINES will expand to -DONE=1 -DTWO -DTHREE -DFOUR=4 -DFIVE scons: `.' is up to date. -- cgit v0.12 From 6abf249d2e38df51dd8e647176b7ce6dacfdf9b9 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Mon, 30 Jan 2023 13:27:41 -0700 Subject: Fix some CPPDEFINES handling problems A few places were deciding what to do based on result of is_List, when the intent was really list-or-tuple-or-derivatives - changed to is_Sequence. Added some test cases, including a unit test for processDefines (which would have caught one of these cases). Signed-off-by: Mats Wichmann --- SCons/Defaults.py | 6 +- SCons/DefaultsTests.py | 56 +++++++++++++++---- SCons/Environment.py | 2 +- test/CPPDEFINES/append.py | 89 ++++++++++++++++++++++++++++++ test/CPPDEFINES/fixture/SConstruct-Append | 5 ++ test/CPPDEFINES/fixture/SConstruct-Prepend | 5 ++ test/CPPDEFINES/prepend.py | 89 ++++++++++++++++++++++++++++++ 7 files changed, 238 insertions(+), 14 deletions(-) diff --git a/SCons/Defaults.py b/SCons/Defaults.py index ad64041..250ccf6 100644 --- a/SCons/Defaults.py +++ b/SCons/Defaults.py @@ -46,7 +46,7 @@ import SCons.PathList import SCons.Scanner.Dir import SCons.Subst import SCons.Tool -from SCons.Util import is_List, is_String, is_Tuple, is_Dict, flatten +from SCons.Util import is_List, is_String, is_Sequence, is_Dict, flatten # A placeholder for a default Environment (for fetching source files # from source code management systems and the like). This must be @@ -517,11 +517,11 @@ def processDefines(defs): Any prefix/suffix is handled elsewhere (usually :func:`_concat_ixes`). """ dlist = [] - if is_List(defs): + if is_Sequence(defs): for define in defs: if define is None: continue - elif is_List(define) or is_Tuple(define): + elif is_Sequence(define): if len(define) >= 2 and define[1] is not None: # TODO: do we need to quote define[1] if it contains space? dlist.append(str(define[0]) + '=' + str(define[1])) diff --git a/SCons/DefaultsTests.py b/SCons/DefaultsTests.py index 7fd62ae..b876552 100644 --- a/SCons/DefaultsTests.py +++ b/SCons/DefaultsTests.py @@ -27,7 +27,7 @@ import collections import TestCmd -from SCons.Defaults import mkdir_func, _defines +from SCons.Defaults import mkdir_func, _defines, processDefines class DummyEnvironment(collections.UserDict): @@ -90,18 +90,54 @@ class DefaultsTestCase(unittest.TestCase): """ env = DummyEnvironment() - # Neither source or target specified - x = _defines('-D', ['A', 'B', 'C'], 'XYZ', env) - self.assertEqual(x, ['-DAXYZ', '-DBXYZ', '-DCXYZ']) + with self.subTest(): + # Neither source or target specified + x = _defines('-D', ['A', 'B', 'C'], 'XYZ', env) + self.assertEqual(x, ['-DAXYZ', '-DBXYZ', '-DCXYZ']) - # only source specified - y = _defines('-D', ['AA', 'BA', 'CA'], 'XYZA', env, 'XYZ') - self.assertEqual(y, ['-DAAXYZA', '-DBAXYZA', '-DCAXYZA']) + with self.subTest(): + # only source specified + y = _defines('-D', ['AA', 'BA', 'CA'], 'XYZA', env, 'XYZ') + self.assertEqual(y, ['-DAAXYZA', '-DBAXYZA', '-DCAXYZA']) - # source and target specified - z = _defines('-D', ['AAB', 'BAB', 'CAB'], 'XYZAB', env, 'XYZ', 'abc') - self.assertEqual(z,['-DAABXYZAB', '-DBABXYZAB', '-DCABXYZAB']) + with self.subTest(): + # source and target specified + z = _defines('-D', ['AAB', 'BAB', 'CAB'], 'XYZAB', env, 'XYZ', 'abc') + self.assertEqual(z, ['-DAABXYZAB', '-DBABXYZAB', '-DCABXYZAB']) + def test_processDefines(self): + """Verify correct handling in processDefines.""" + env = DummyEnvironment() + + with self.subTest(): + # macro name only + rv = processDefines('name') + self.assertEqual(rv, ['name']) + + with self.subTest(): + # macro with value + rv = processDefines('name=val') + self.assertEqual(rv, ['name=val']) + + with self.subTest(): + # single list + rv = processDefines(['name', 'val']) + self.assertEqual(rv, ['name', 'val']) + + with self.subTest(): + # single tuple + rv = processDefines(('name', 'val')) + self.assertEqual(rv, ['name', 'val']) + + with self.subTest(): + # single dict + rv = processDefines({'foo': None, 'name': 'val'}) + self.assertEqual(rv, ['foo', 'name=val']) + + with self.subTest(): + # compound list + rv = processDefines(['foo', ('name', 'val'), ['name2', 'val2']]) + self.assertEqual(rv, ['foo', 'name=val', 'name2=val2']) if __name__ == "__main__": diff --git a/SCons/Environment.py b/SCons/Environment.py index e73da82..e10bec1 100644 --- a/SCons/Environment.py +++ b/SCons/Environment.py @@ -330,7 +330,7 @@ def _add_cppdefines( else: _add_define(val, defines, prepend) - elif is_List(val): + elif is_Sequence(val): tmp = [] for item in val: if unique: diff --git a/test/CPPDEFINES/append.py b/test/CPPDEFINES/append.py index 0d074cf..2a31021 100644 --- a/test/CPPDEFINES/append.py +++ b/test/CPPDEFINES/append.py @@ -45,6 +45,7 @@ expect_print_output="""\ -Dfoo bar -Dbaz -Dfoo -Dbar baz -DMacro2=Value2 -DMacro3=Value3 -DMacro1=Value1 +-DMacro1 -DValue1 ==== Testing CPPDEFINES, appending a string to a string orig = 'FOO', append = 'FOO' Append: @@ -69,6 +70,14 @@ Append: AppendUnique: result=['FOO', 'NAME1', 'NAME2'] final=-DFOO -DNAME1 -DNAME2 +==== Testing CPPDEFINES, appending a tuple to a string + orig = 'FOO', append = ('NAME1', 'NAME2') +Append: + result=['FOO', 'NAME1', 'NAME2'] + final=-DFOO -DNAME1 -DNAME2 +AppendUnique: + result=['FOO', 'NAME1', 'NAME2'] + final=-DFOO -DNAME1 -DNAME2 ==== Testing CPPDEFINES, appending a list-of-2lists to a string orig = 'FOO', append = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Append: @@ -109,6 +118,14 @@ Append: AppendUnique: result=['NAME1=VAL1', 'NAME1', 'NAME2'] final=-DNAME1=VAL1 -DNAME1 -DNAME2 +==== Testing CPPDEFINES, appending a tuple to a valuestring + orig = 'NAME1=VAL1', append = ('NAME1', 'NAME2') +Append: + result=['NAME1=VAL1', 'NAME1', 'NAME2'] + final=-DNAME1=VAL1 -DNAME1 -DNAME2 +AppendUnique: + result=['NAME1=VAL1', 'NAME1', 'NAME2'] + final=-DNAME1=VAL1 -DNAME1 -DNAME2 ==== Testing CPPDEFINES, appending a list-of-2lists to a valuestring orig = 'NAME1=VAL1', append = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Append: @@ -149,6 +166,14 @@ Append: AppendUnique: result=['NAME1', 'NAME2'] final=-DNAME1 -DNAME2 +==== Testing CPPDEFINES, appending a tuple to a list + orig = ['NAME1', 'NAME2'], append = ('NAME1', 'NAME2') +Append: + result=['NAME1', 'NAME2', 'NAME1', 'NAME2'] + final=-DNAME1 -DNAME2 -DNAME1 -DNAME2 +AppendUnique: + result=['NAME1', 'NAME2'] + final=-DNAME1 -DNAME2 ==== Testing CPPDEFINES, appending a list-of-2lists to a list orig = ['NAME1', 'NAME2'], append = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Append: @@ -165,6 +190,54 @@ Append: AppendUnique: result=['NAME1', 'NAME2', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] final=-DNAME1 -DNAME2 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 +==== Testing CPPDEFINES, appending a string to a tuple + orig = ('NAME1', 'NAME2'), append = 'FOO' +Append: + result=['NAME1', 'NAME2', 'FOO'] + final=-DNAME1 -DNAME2 -DFOO +AppendUnique: + result=['NAME1', 'NAME2', 'FOO'] + final=-DNAME1 -DNAME2 -DFOO +==== Testing CPPDEFINES, appending a valuestring to a tuple + orig = ('NAME1', 'NAME2'), append = 'NAME1=VAL1' +Append: + result=['NAME1', 'NAME2', 'NAME1=VAL1'] + final=-DNAME1 -DNAME2 -DNAME1=VAL1 +AppendUnique: + result=['NAME1', 'NAME2', 'NAME1=VAL1'] + final=-DNAME1 -DNAME2 -DNAME1=VAL1 +==== Testing CPPDEFINES, appending a list to a tuple + orig = ('NAME1', 'NAME2'), append = ['NAME1', 'NAME2'] +Append: + result=['NAME1', 'NAME2', 'NAME1', 'NAME2'] + final=-DNAME1 -DNAME2 -DNAME1 -DNAME2 +AppendUnique: + result=['NAME1', 'NAME2'] + final=-DNAME1 -DNAME2 +==== Testing CPPDEFINES, appending a tuple to a tuple + orig = ('NAME1', 'NAME2'), append = ('NAME1', 'NAME2') +Append: + result=['NAME1', 'NAME2', 'NAME1', 'NAME2'] + final=-DNAME1 -DNAME2 -DNAME1 -DNAME2 +AppendUnique: + result=['NAME1', 'NAME2'] + final=-DNAME1 -DNAME2 +==== Testing CPPDEFINES, appending a list-of-2lists to a tuple + orig = ('NAME1', 'NAME2'), append = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] +Append: + result=['NAME1', 'NAME2', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME1 -DNAME2 -DNAME1=VAL1 -DNAME2=VAL2 +AppendUnique: + result=['NAME1', 'NAME2', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME1 -DNAME2 -DNAME1=VAL1 -DNAME2=VAL2 +==== Testing CPPDEFINES, appending a dict to a tuple + orig = ('NAME1', 'NAME2'), append = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} +Append: + result=['NAME1', 'NAME2', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME1 -DNAME2 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 +AppendUnique: + result=['NAME1', 'NAME2', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME1 -DNAME2 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 ==== Testing CPPDEFINES, appending a string to a list-of-2lists orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], append = 'FOO' Append: @@ -189,6 +262,14 @@ Append: AppendUnique: result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], 'NAME1', 'NAME2'] final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME1 -DNAME2 +==== Testing CPPDEFINES, appending a tuple to a list-of-2lists + orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], append = ('NAME1', 'NAME2') +Append: + result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], 'NAME1', 'NAME2'] + final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME1 -DNAME2 +AppendUnique: + result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], 'NAME1', 'NAME2'] + final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME1 -DNAME2 ==== Testing CPPDEFINES, appending a list-of-2lists to a list-of-2lists orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], append = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Append: @@ -229,6 +310,14 @@ Append: AppendUnique: result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1'), 'NAME1', 'NAME2'] final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DNAME1 -DNAME2 +==== Testing CPPDEFINES, appending a tuple to a dict + orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, append = ('NAME1', 'NAME2') +Append: + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1'), 'NAME1', 'NAME2'] + final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DNAME1 -DNAME2 +AppendUnique: + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1'), 'NAME1', 'NAME2'] + final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DNAME1 -DNAME2 ==== Testing CPPDEFINES, appending a list-of-2lists to a dict orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, append = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Append: diff --git a/test/CPPDEFINES/fixture/SConstruct-Append b/test/CPPDEFINES/fixture/SConstruct-Append index af4db9d..76b86ad 100644 --- a/test/CPPDEFINES/fixture/SConstruct-Append +++ b/test/CPPDEFINES/fixture/SConstruct-Append @@ -39,6 +39,10 @@ env_multi.AppendUnique(CPPDEFINES=[("Macro3", "Value3")], delete_existing=True) env_multi.AppendUnique(CPPDEFINES={"Macro1": "Value1"}, delete_existing=True) print(env_multi.subst('$_CPPDEFFLAGS')) +# a lone tuple +env_multi = Environment(CPPDEFPREFIX='-D', CPPDEFINES=("Macro1", "Value1")) +print(env_multi.subst('$_CPPDEFFLAGS')) + # https://github.com/SCons/scons/issues/1152 # https://github.com/SCons/scons/issues/2900 # Python3 dicts dont preserve order. Hence we supply subclass of OrderedDict @@ -63,6 +67,7 @@ cases = [ ('string', 'FOO'), ('valuestring', 'NAME1=VAL1'), ('list', ['NAME1', 'NAME2']), + ('tuple', ('NAME1', 'NAME2')), ('list-of-2lists', [('NAME1', 'VAL1'), ['NAME2', 'VAL2']]), ( 'dict', diff --git a/test/CPPDEFINES/fixture/SConstruct-Prepend b/test/CPPDEFINES/fixture/SConstruct-Prepend index 52b66e8..4628ea4 100644 --- a/test/CPPDEFINES/fixture/SConstruct-Prepend +++ b/test/CPPDEFINES/fixture/SConstruct-Prepend @@ -39,6 +39,10 @@ env_multi.PrependUnique(CPPDEFINES=[("Macro3", "Value3")], delete_existing=True) env_multi.PrependUnique(CPPDEFINES={"Macro1": "Value1"}, delete_existing=True) print(env_multi.subst('$_CPPDEFFLAGS')) +# a lone tuple +env_tuple = Environment(CPPDEFPREFIX='-D', CPPDEFINES=("Macro1", "Value1")) +print(env_tuple.subst('$_CPPDEFFLAGS')) + # https://github.com/SCons/scons/issues/1152 # https://github.com/SCons/scons/issues/2900 # Python3 dicts dont preserve order. Hence we supply subclass of OrderedDict @@ -64,6 +68,7 @@ cases = [ ('string', 'FOO'), ('valuestring', 'NAME1=VAL1'), ('list', ['NAME1', 'NAME2']), + ('tuple', ('NAME1', 'NAME2')), ('list-of-2lists', [('NAME1', 'VAL1'), ['NAME2', 'VAL2']]), ( 'dict', diff --git a/test/CPPDEFINES/prepend.py b/test/CPPDEFINES/prepend.py index 2e63e87..5ec2e46 100644 --- a/test/CPPDEFINES/prepend.py +++ b/test/CPPDEFINES/prepend.py @@ -44,6 +44,7 @@ expect_print_output="""\ -Dbaz -Dfoo bar -Dbar baz -Dfoo -DMacro1=Value1 -DMacro3=Value3 -DMacro2=Value2 +-DMacro1 -DValue1 ==== Testing CPPDEFINES, prepending a string to a string orig = 'FOO', prepend = 'FOO' Prepend: @@ -68,6 +69,14 @@ Prepend: PrependUnique: result=['NAME2', 'NAME1', 'FOO'] final=-DNAME2 -DNAME1 -DFOO +==== Testing CPPDEFINES, prepending a tuple to a string + orig = 'FOO', prepend = ('NAME1', 'NAME2') +Prepend: + result=['NAME2', 'NAME1', 'FOO'] + final=-DNAME2 -DNAME1 -DFOO +PrependUnique: + result=['NAME2', 'NAME1', 'FOO'] + final=-DNAME2 -DNAME1 -DFOO ==== Testing CPPDEFINES, prepending a list-of-2lists to a string orig = 'FOO', prepend = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Prepend: @@ -108,6 +117,14 @@ Prepend: PrependUnique: result=['NAME2', 'NAME1', 'NAME1=VAL1'] final=-DNAME2 -DNAME1 -DNAME1=VAL1 +==== Testing CPPDEFINES, prepending a tuple to a valuestring + orig = 'NAME1=VAL1', prepend = ('NAME1', 'NAME2') +Prepend: + result=['NAME2', 'NAME1', 'NAME1=VAL1'] + final=-DNAME2 -DNAME1 -DNAME1=VAL1 +PrependUnique: + result=['NAME2', 'NAME1', 'NAME1=VAL1'] + final=-DNAME2 -DNAME1 -DNAME1=VAL1 ==== Testing CPPDEFINES, prepending a list-of-2lists to a valuestring orig = 'NAME1=VAL1', prepend = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Prepend: @@ -148,6 +165,14 @@ Prepend: PrependUnique: result=['NAME1', 'NAME2'] final=-DNAME1 -DNAME2 +==== Testing CPPDEFINES, prepending a tuple to a list + orig = ['NAME1', 'NAME2'], prepend = ('NAME1', 'NAME2') +Prepend: + result=['NAME2', 'NAME1', 'NAME1', 'NAME2'] + final=-DNAME2 -DNAME1 -DNAME1 -DNAME2 +PrependUnique: + result=['NAME1', 'NAME2'] + final=-DNAME1 -DNAME2 ==== Testing CPPDEFINES, prepending a list-of-2lists to a list orig = ['NAME1', 'NAME2'], prepend = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Prepend: @@ -164,6 +189,54 @@ Prepend: PrependUnique: result=[('NAME1', 'VAL1'), ('NAME3', None), ('NAME2', 'VAL2'), 'NAME1', 'NAME2'] final=-DNAME1=VAL1 -DNAME3 -DNAME2=VAL2 -DNAME1 -DNAME2 +==== Testing CPPDEFINES, prepending a string to a tuple + orig = ('NAME1', 'NAME2'), prepend = 'FOO' +Prepend: + result=['FOO', 'NAME1', 'NAME2'] + final=-DFOO -DNAME1 -DNAME2 +PrependUnique: + result=['FOO', 'NAME1', 'NAME2'] + final=-DFOO -DNAME1 -DNAME2 +==== Testing CPPDEFINES, prepending a valuestring to a tuple + orig = ('NAME1', 'NAME2'), prepend = 'NAME1=VAL1' +Prepend: + result=['NAME1=VAL1', 'NAME1', 'NAME2'] + final=-DNAME1=VAL1 -DNAME1 -DNAME2 +PrependUnique: + result=['NAME1=VAL1', 'NAME1', 'NAME2'] + final=-DNAME1=VAL1 -DNAME1 -DNAME2 +==== Testing CPPDEFINES, prepending a list to a tuple + orig = ('NAME1', 'NAME2'), prepend = ['NAME1', 'NAME2'] +Prepend: + result=['NAME2', 'NAME1', 'NAME1', 'NAME2'] + final=-DNAME2 -DNAME1 -DNAME1 -DNAME2 +PrependUnique: + result=['NAME1', 'NAME2'] + final=-DNAME1 -DNAME2 +==== Testing CPPDEFINES, prepending a tuple to a tuple + orig = ('NAME1', 'NAME2'), prepend = ('NAME1', 'NAME2') +Prepend: + result=['NAME2', 'NAME1', 'NAME1', 'NAME2'] + final=-DNAME2 -DNAME1 -DNAME1 -DNAME2 +PrependUnique: + result=['NAME1', 'NAME2'] + final=-DNAME1 -DNAME2 +==== Testing CPPDEFINES, prepending a list-of-2lists to a tuple + orig = ('NAME1', 'NAME2'), prepend = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] +Prepend: + result=[['NAME2', 'VAL2'], ('NAME1', 'VAL1'), 'NAME1', 'NAME2'] + final=-DNAME2=VAL2 -DNAME1=VAL1 -DNAME1 -DNAME2 +PrependUnique: + result=[['NAME2', 'VAL2'], ('NAME1', 'VAL1'), 'NAME1', 'NAME2'] + final=-DNAME2=VAL2 -DNAME1=VAL1 -DNAME1 -DNAME2 +==== Testing CPPDEFINES, prepending a dict to a tuple + orig = ('NAME1', 'NAME2'), prepend = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} +Prepend: + result=[('NAME1', 'VAL1'), ('NAME3', None), ('NAME2', 'VAL2'), 'NAME1', 'NAME2'] + final=-DNAME1=VAL1 -DNAME3 -DNAME2=VAL2 -DNAME1 -DNAME2 +PrependUnique: + result=[('NAME1', 'VAL1'), ('NAME3', None), ('NAME2', 'VAL2'), 'NAME1', 'NAME2'] + final=-DNAME1=VAL1 -DNAME3 -DNAME2=VAL2 -DNAME1 -DNAME2 ==== Testing CPPDEFINES, prepending a string to a list-of-2lists orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], prepend = 'FOO' Prepend: @@ -188,6 +261,14 @@ Prepend: PrependUnique: result=['NAME2', 'NAME1', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] final=-DNAME2 -DNAME1 -DNAME1=VAL1 -DNAME2=VAL2 +==== Testing CPPDEFINES, prepending a tuple to a list-of-2lists + orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], prepend = ('NAME1', 'NAME2') +Prepend: + result=['NAME2', 'NAME1', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME2 -DNAME1 -DNAME1=VAL1 -DNAME2=VAL2 +PrependUnique: + result=['NAME2', 'NAME1', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME2 -DNAME1 -DNAME1=VAL1 -DNAME2=VAL2 ==== Testing CPPDEFINES, prepending a list-of-2lists to a list-of-2lists orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], prepend = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Prepend: @@ -228,6 +309,14 @@ Prepend: PrependUnique: result=['NAME2', 'NAME1', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] final=-DNAME2 -DNAME1 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 +==== Testing CPPDEFINES, prepending a tuple to a dict + orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, prepend = ('NAME1', 'NAME2') +Prepend: + result=['NAME2', 'NAME1', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME2 -DNAME1 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 +PrependUnique: + result=['NAME2', 'NAME1', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME2 -DNAME1 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 ==== Testing CPPDEFINES, prepending a list-of-2lists to a dict orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, prepend = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Prepend: -- cgit v0.12 From 3a3cf8f4da6416d246e41528416112198f695cab Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 2 Feb 2023 20:29:05 -0800 Subject: [ci skip] remove umerged conflict markers in RELEASE.txt --- RELEASE.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/RELEASE.txt b/RELEASE.txt index 1bf6bf8..31b56aa 100644 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -148,17 +148,14 @@ DOCUMENTATION - Updated the User Guide chapter on installation: modernized the notes on Python installs, SCons installs, and having multiple SCons versions present on a single system. -<<<<<<< HEAD - Updated the User Guide chapter on variant directories with more explanation, and the introduction of terms like "out of tree" that may help in forming a mental model. - Additional explanations for MSVSProject and MSVSSolution builders. - Updated MSVC documentation - adds "version added" annotations on recently added construction variables and provides a version-mapping table. -======= - Added further details in the documentation of Append and related methods on the special handling of CPPDEFINES. ->>>>>>> d9a82d681 (Split out CPPDEFINES handling in Append methods) DEVELOPMENT ----------- -- cgit v0.12 From db0ae34d6da183bce93c3f044abb727b0474c8c2 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 2 Feb 2023 20:43:57 -0800 Subject: Alter append logic to keep existing append of tuple value yielding -Dkey=value --- SCons/Environment.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/SCons/Environment.py b/SCons/Environment.py index e10bec1..26f7036 100644 --- a/SCons/Environment.py +++ b/SCons/Environment.py @@ -269,7 +269,6 @@ def _add_cppdefines( return False - key = 'CPPDEFINES' try: defines = env_dict[key] @@ -330,6 +329,19 @@ def _add_cppdefines( else: _add_define(val, defines, prepend) + # A tuple appended to anything should yield -Dkey=value + elif is_Tuple(val): + item = (val[0], val[1]) + if unique: + match = _is_in(item, defines) + if match and delete_existing: + defines.remove(match) + _add_define(item, defines, prepend) + elif not match: + _add_define(item, defines, prepend) + else: + _add_define(item, defines, prepend) + elif is_Sequence(val): tmp = [] for item in val: -- cgit v0.12 From 12d4966b67182a282e3911ad9b0e1dbe8f6a52d7 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 2 Feb 2023 20:46:29 -0800 Subject: Add explicit note to RELEASE.txt warning about rebuilds if you use dictionaries to specify CPPDEFINES --- RELEASE.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/RELEASE.txt b/RELEASE.txt index 31b56aa..f06945d 100644 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -17,6 +17,9 @@ NOTE: If you build with Python 3.10.0 and then rebuild with 3.10.1 (or higher), see unexpected rebuilds. This is due to Python internals changing which changed the signature of a Python Action Function. +NOTE: If you use dictionaries to specify your CPPDEFINES, most likely the order of the CPPDEFINES + on the generated command line will change causing a rebuild. + NEW FUNCTIONALITY ----------------- -- cgit v0.12 From b3e6192cfe79c3e4e162ed64a15ba200883f616f Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Thu, 9 Feb 2023 12:30:42 -0700 Subject: Adjusted CPPDEFINES behavior for list and tuple After the previous proposals, addition of a bare tuple is restored to the valued-macro behavior (this previously did not work consistently). Strings are now consistently split if they contain spaces, except if entered as a list member, in which case (as documented) they are left alone. tuples with nore than two members are now flagged as a UserError; previously the first two members were taken as name=value and any further members were silently ignored. More tests added. Signed-off-by: Mats Wichmann --- CHANGES.txt | 20 +-- RELEASE.txt | 23 ++-- SCons/Defaults.py | 47 +++++-- SCons/DefaultsTests.py | 7 +- SCons/Environment.py | 94 +++++++++----- SCons/Environment.xml | 69 +++++----- SCons/Util/types.py | 11 +- test/CPPDEFINES/append.py | 200 +++++++++++++++-------------- test/CPPDEFINES/fixture/SConstruct-Append | 23 ++-- test/CPPDEFINES/fixture/SConstruct-Prepend | 21 ++- test/CPPDEFINES/prepend.py | 200 +++++++++++++++-------------- 11 files changed, 404 insertions(+), 311 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 41a966b..e10feab 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -134,16 +134,18 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER or not if it is already in the $LIBS construction var in the configure context. (issue #2768). - Special-case handling for CPPDEFINES in the Append/Prepend routines - split out into its own function to simplify the remaining code and + is split out into its own function to simplify the remaining code and fix problems. The e2e test test/CPPDEFINES/append.py is expanded - to cover missed cases, and AppendUnique no longer mismatches with - what Append does (#3876). Inconsistent handling of tuples to specify - macro=value outputs is also cleaned up (#4254). The special handling - now also works for Prepend/PrependUnique, and a corresponding test - test/CPPDEFINES/prepend.py was added to verify the behavior. - SCons used to sort keys set or appended via a dict type, in order to - assure order of commandline flags did not change across runs. This - behavior has been dropped since Python now assures consistent dict order. + to cover missed cases, and AppendUnique no longer mismatches + with what Append does (#3876). Inconsistent handling of tuples + to specify macro=value outputs is also cleaned up (#4254). The + special handling now also works for Prepend/PrependUnique, and a + corresponding e2e test test/CPPDEFINES/prepend.py was added to verify + the behavior. A unit test for SCons.Util.processDefines, used to + convert CPPDEFINES into a list of strings, is added. SCons used + to sort keys set or appended via a dict type, in order to assure + order of commandline flags did not change across runs. This behavior + has been dropped since Python now assures consistent dict order. RELEASE 4.4.0 - Sat, 30 Jul 2022 14:08:29 -0700 diff --git a/RELEASE.txt b/RELEASE.txt index f06945d..7a431c2 100644 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -17,8 +17,10 @@ NOTE: If you build with Python 3.10.0 and then rebuild with 3.10.1 (or higher), see unexpected rebuilds. This is due to Python internals changing which changed the signature of a Python Action Function. -NOTE: If you use dictionaries to specify your CPPDEFINES, most likely the order of the CPPDEFINES - on the generated command line will change causing a rebuild. +NOTE: If you use a dictionary to specify your CPPDEFINES, the order of + dictionary keys is now preserved when generating the command line. + Previously these were sorted alphabecially: this may cause a change + which leads to a rebuild. NEW FUNCTIONALITY @@ -98,15 +100,14 @@ FIXES actual build would not see the file as modified. Leading to incorrect incremental builds. Now configure checks now clear node info for non conftest nodes, so they will be re-evaluated for the real taskmaster run when the build commences. -- Inconsistent behavior of adding CPPDEFINES values via tuple arguments - has been cleaned up (problems described in issue #4254). In order to - achieve consistency, a rule for for adding macros-with-values via a - tuple (or list) is now enforced: they need to be entered as members - of a containing sequence. ["NAME", "VALUE"] and ("NAME", "VALUE") - are now treated the same (two individual macro names), rather than - the latter sometimes, but not always, being handled as a single - NAME=VALUE macro. Use a construct like [("NAME", "VALUE")] to get the - macro-with-value behavior. +- Inconsistent behavior of adding values to the CPPDEFINES construction + variable has been cleaned up (described in issue #4254). Now a tuple, + whether provided by itself or as a member of a list, is consistently + interpreted as a macro with replacement value. When adding a list, + individual members are added in sequence without interpretation. + A string value containing spaces is split if it is the initial value or + added, but not if it is given as a member of an added list. Detection + of duplicate macros now works for both valued and unvalued forms. - Handling of CPPDEFINES macros via Prepend and PrependUnique now works (previously this was special-cased only for Append and AppendUnique). diff --git a/SCons/Defaults.py b/SCons/Defaults.py index 250ccf6..ea7e930 100644 --- a/SCons/Defaults.py +++ b/SCons/Defaults.py @@ -36,6 +36,7 @@ import shutil import stat import sys import time +from typing import List import SCons.Action import SCons.Builder @@ -46,7 +47,7 @@ import SCons.PathList import SCons.Scanner.Dir import SCons.Subst import SCons.Tool -from SCons.Util import is_List, is_String, is_Sequence, is_Dict, flatten +from SCons.Util import is_List, is_String, is_Sequence, is_Tuple, is_Dict, flatten # A placeholder for a default Environment (for fetching source files # from source code management systems and the like). This must be @@ -510,42 +511,67 @@ def _stripixes(prefix, itms, suffix, stripprefixes, stripsuffixes, env, c=None): return c(prefix, stripped, suffix, env) -def processDefines(defs): +def processDefines(defs) -> List[str]: """Return list of strings for preprocessor defines from *defs*. - Resolves all the different forms CPPDEFINES can be assembled in. + Resolves the different forms ``CPPDEFINES`` can be assembled in: + if the Append/Prepend routines are used beyond a initial setting it + will be a deque, but if written to only once (Environment initializer, + or direct write) it can be a multitude of types. + Any prefix/suffix is handled elsewhere (usually :func:`_concat_ixes`). """ dlist = [] - if is_Sequence(defs): + if is_List(defs): for define in defs: if define is None: continue elif is_Sequence(define): - if len(define) >= 2 and define[1] is not None: - # TODO: do we need to quote define[1] if it contains space? - dlist.append(str(define[0]) + '=' + str(define[1])) + if len(define) > 2: + raise SCons.Errors.UserError( + f"Invalid tuple in CPPDEFINES: {define!r}, " + "must be a two-tuple" + ) + name, *value = define + if value and value[0] is not None: + # TODO: do we need to quote value if it contains space? + dlist.append(f"{name}={value[0]}") else: dlist.append(str(define[0])) elif is_Dict(define): for macro, value in define.items(): if value is not None: # TODO: do we need to quote value if it contains space? - dlist.append(str(macro) + '=' + str(value)) + dlist.append(f"{macro}={value}") else: dlist.append(str(macro)) elif is_String(define): dlist.append(str(define)) else: raise SCons.Errors.UserError( - f"DEFINE {define!r} is not a list, dict, string or None." + f"CPPDEFINES entry {define!r} is not a tuple, list, " + "dict, string or None." ) + elif is_Tuple(defs): + if len(defs) > 2: + raise SCons.Errors.UserError( + f"Invalid tuple in CPPDEFINES: {defs!r}, " + "must be a two-tuple" + ) + name, *value = defs + if value and value[0] is not None: + # TODO: do we need to quote value if it contains space? + dlist.append(f"{name}={value[0]}") + else: + dlist.append(str(define[0])) elif is_Dict(defs): for macro, value in defs.items(): if value is None: dlist.append(str(macro)) else: - dlist.append(str(macro) + '=' + str(value)) + dlist.append(f"{macro}={value}") + elif is_String(defs): + return defs.split() else: dlist.append(str(defs)) @@ -556,7 +582,6 @@ def _defines(prefix, defs, suffix, env, target=None, source=None, c=_concat_ixes """A wrapper around :func:`_concat_ixes` that turns a list or string into a list of C preprocessor command-line definitions. """ - return c(prefix, env.subst_list(processDefines(defs), target=target, source=source), suffix, env) diff --git a/SCons/DefaultsTests.py b/SCons/DefaultsTests.py index b876552..c9a6663 100644 --- a/SCons/DefaultsTests.py +++ b/SCons/DefaultsTests.py @@ -120,6 +120,11 @@ class DefaultsTestCase(unittest.TestCase): self.assertEqual(rv, ['name=val']) with self.subTest(): + # space-separated macros + rv = processDefines('name1 name2=val2') + self.assertEqual(rv, ['name1', 'name2=val2']) + + with self.subTest(): # single list rv = processDefines(['name', 'val']) self.assertEqual(rv, ['name', 'val']) @@ -127,7 +132,7 @@ class DefaultsTestCase(unittest.TestCase): with self.subTest(): # single tuple rv = processDefines(('name', 'val')) - self.assertEqual(rv, ['name', 'val']) + self.assertEqual(rv, ['name=val']) with self.subTest(): # single dict diff --git a/SCons/Environment.py b/SCons/Environment.py index 26f7036..3bd1a62 100644 --- a/SCons/Environment.py +++ b/SCons/Environment.py @@ -65,6 +65,7 @@ from SCons.Util import ( flatten, is_Dict, is_List, + is_Scalar, is_Sequence, is_String, is_Tuple, @@ -202,16 +203,18 @@ def _add_cppdefines( ) -> None: """Adds to CPPDEFINES, using the rules for C preprocessor macros. - Split out from regular construction variable handling because these - entries can express either a macro with a replacement list or one - without. A macro with replacement list can be supplied three ways: - as a combined string ``name=value``; as a tuple contained in - a sequence type ``[("name", value)]``; or as a dictionary entry - ``{"name": value}``. Appending/prepending can be unconditional - (duplicates allowed) or uniquing (no dupes). + This is split out from regular construction variable addition because + these entries can express either a macro with a replacement value or + one without. A macro with replacement value can be supplied as *val* + in three ways: as a combined string ``"name=value"``; as a tuple + ``(name, value)``, or as an entry in a dictionary ``{"name": value}``. + A list argument with multiple macros can also be given. - Note if a replacement list is supplied, "unique" requires a full - match - both the name and the replacement must be equal. + Additions can be unconditional (duplicates allowed) or uniquing (no dupes). + + Note if a replacement value is supplied, *unique* requires a full + match to decide uniqueness - both the macro name and the replacement. + The inner :func:`_is_in` is used to figure that out. Args: env_dict: the dictionary containing the ``CPPDEFINES`` to be modified. @@ -239,12 +242,13 @@ def _add_cppdefines( ["FOO", "BAR"], string "FOO=BAR" and dict {"FOO": "BAR"} all differ as far as Python equality comparison is concerned, but are the same for purposes of creating the preprocessor macro. + Also an unvalued string should match something like ``("FOO", None)``. Since the caller may wish to remove a matched entry, we need to return it - cannot remove *item* itself unless it happened to be an exact (type) match. Called from a place we know *defines* is always a deque, and - *item* will not be a dict, so don't need do much type checking. + *item* will not be a dict, so don't need to do much type checking. If this ends up used more generally, would need to adjust that. Note implied assumption that members of a list-valued define @@ -256,7 +260,10 @@ def _add_cppdefines( if is_Tuple(v): return list(v) elif is_String(v): - return v.split("=") + rv = v.split("=") + if len(rv) == 1: + return [v, None] + return rv return v if item in defines: # cheap check first @@ -274,22 +281,32 @@ def _add_cppdefines( defines = env_dict[key] except KeyError: # This is a new entry, just save it as is. Defer conversion to - # deque until someone tries to amend the value, processDefines - # can handle all of these fine. + # preferred type until someone tries to amend the value. + # processDefines has no problem with unconverted values if it + # gets called without any later additions. if is_String(val): env_dict[key] = val.split() else: env_dict[key] = val return - # Convert type of existing to deque to simplify processing of addition - - # inserting at either end is cheap. + # Convert type of existing to deque (if necessary) to simplify processing + # of additions - inserting at either end is cheap. Deferred conversion + # is also useful in case CPPDEFINES was set initially without calling + # through here (e.g. Environment kwarg, or direct assignment). if isinstance(defines, deque): - # filter deques out to avoid catching in is_List check below + # Already a deque? do nothing. Explicit check is so we don't get + # picked up by the is_list case below. pass elif is_String(defines): env_dict[key] = deque(defines.split()) - elif is_Tuple(defines) or is_List(defines): + elif is_Tuple(defines): + if len(defines) > 2: + raise SCons.Errors.UserError( + f"Invalid tuple in CPPDEFINES: {define!r}, must be a two-tuple" + ) + env_dict[key] = deque([defines]) + elif is_List(defines): # a little extra work in case the initial container has dict # item(s) inside it, so those can be matched by _is_in(). result = deque() @@ -303,8 +320,9 @@ def _add_cppdefines( env_dict[key] = deque(defines.items()) else: env_dict[key] = deque(defines) - defines = env_dict[key] # in case we reassigned it after the try block. + defines = env_dict[key] # in case we reassigned due to conversion + # now actually do the addition. if is_Dict(val): # Unpack the dict while applying to existing for item in val.items(): @@ -319,6 +337,31 @@ def _add_cppdefines( _add_define(item, defines, prepend) elif is_String(val): + for v in val.split(): + if unique: + match = _is_in(v, defines) + if match and delete_existing: + defines.remove(match) + _add_define(v, defines, prepend) + elif not match: + _add_define(v, defines, prepend) + else: + _add_define(v, defines, prepend) + + # A tuple appended to anything should yield -Dkey=value + elif is_Tuple(val): + if len(val) > 2: + raise SCons.Errors.UserError( + f"Invalid tuple added to CPPDEFINES: {val!r}, " + "must be a two-tuple" + ) + if len(val) == 1: + val = (val[0], None) # normalize + if not is_Scalar(val[0]) or not is_Scalar(val[1]): + raise SCons.Errors.UserError( + f"Invalid tuple added to CPPDEFINES: {val!r}, " + "values must be scalar" + ) if unique: match = _is_in(val, defines) if match and delete_existing: @@ -329,20 +372,7 @@ def _add_cppdefines( else: _add_define(val, defines, prepend) - # A tuple appended to anything should yield -Dkey=value - elif is_Tuple(val): - item = (val[0], val[1]) - if unique: - match = _is_in(item, defines) - if match and delete_existing: - defines.remove(match) - _add_define(item, defines, prepend) - elif not match: - _add_define(item, defines, prepend) - else: - _add_define(item, defines, prepend) - - elif is_Sequence(val): + elif is_List(val): tmp = [] for item in val: if unique: diff --git a/SCons/Environment.xml b/SCons/Environment.xml index f7e2da9..f87e883 100644 --- a/SCons/Environment.xml +++ b/SCons/Environment.xml @@ -512,7 +512,7 @@ but adding a string to a list or a list to a string requires different syntax - things &f-Append; takes care of. Some pre-defined &consvars; do have type expectations based on how &SCons; will use them: -for example &cv-link-CPPDEFINES; is normally a string or a list of strings, +for example &cv-link-CPPDEFINES; is often a string or a list of strings, but can also be a list of tuples or a dictionary; while &cv-link-LIBEMITTER; is expected to be a callable or list of callables, @@ -577,20 +577,41 @@ scons: `.' is up to date. Because &cv-link-CPPDEFINES; is intended for command-line specification of C/C++ preprocessor macros, -it accepts additional syntax. -A command-line preprocessor macro can predefine a name by itself -(-DFOO), -which gives it an implicit value, -or be given with a replacement value -(-DBAR=1). -&SCons; allows you to specify a macro with replacement -three different ways: -using a string, like -macro=replacement; -as a (non-string) sequence inside a (non-string) sequence, -like [(macro, replacement)] -or as a key/value pair in a dictionary -{macro: replacement}. Examples: +additional syntax is accepted when adding to it. +The preprocessor accepts arguments to predefine a macro name by itself +(-DFOO for most compilers, +/DFOO for Microsoft C++), +which gives it an implicit value of 1, +or can be given with a replacement value +(-DBAR=TEXT). +&SCons; follows these rules when adding to &cv-CPPDEFINES;: + + + +A string is split on spaces, +giving an easy way to enter multiple macros in one addition. +Use an = to specify a valued macro. + + +A tuple is treated as a valued macro. +Use the value None if the macro should not have a value. +It is an error to supply more than two elements in such a tuple. + + +A list is processed in order, +adding each item without further interpretation. +In this case, space-separated strings are not split. + + +A dictionary is processed in order, +adding each key:value pair as a valued macro. +Use the value None if the macro should not have a value. + + + + + +Examples: @@ -616,15 +637,7 @@ scons: `.' is up to date. -Multiple &cv-CPPDEFINES; macros can be added in a single call -using a (non-string) sequence, -or using the dictionary form. -If a given macro name should not have a replacement value, -supply that macro as a string, -or either omit the replacement value or give it as -None; -if using the dictionary form, -specify the value as None. Examples: +Examples of adding multiple macros: @@ -646,12 +659,8 @@ scons: `.' is up to date. Changed in version 4.5: -clarified that to receive the special handling, -the tuple form must be supplied inside -a sequence (e.g. a list); a single tuple will be interpreted -just like a single list. -Previously this form was inconsistently interpreted by -various &SCons; methods. +clarifined the use of tuples vs. other types, +handling is now consistent across the four functions. diff --git a/SCons/Util/types.py b/SCons/Util/types.py index 1602055..2071217 100644 --- a/SCons/Util/types.py +++ b/SCons/Util/types.py @@ -13,7 +13,7 @@ import re from typing import Optional from collections import UserDict, UserList, UserString, deque -from collections.abc import MappingView +from collections.abc import MappingView, Iterable # Functions for deciding if things are like various types, mainly to # handle UserDict, UserList and UserString like their underlying types. @@ -86,16 +86,19 @@ def is_String( # pylint: disable=redefined-outer-name,redefined-builtin def is_Scalar( # pylint: disable=redefined-outer-name,redefined-builtin - obj, isinstance=isinstance, StringTypes=StringTypes, SequenceTypes=SequenceTypes + obj, isinstance=isinstance, StringTypes=StringTypes, Iterable=Iterable, ) -> bool: - """Check if object is a scalar.""" + """Check if object is a scalar: not a container or iterable.""" # Profiling shows that there is an impressive speed-up of 2x # when explicitly checking for strings instead of just not # sequence when the argument (i.e. obj) is already a string. # But, if obj is a not string then it is twice as fast to # check only for 'not sequence'. The following code therefore # assumes that the obj argument is a string most of the time. - return isinstance(obj, StringTypes) or not isinstance(obj, SequenceTypes) + # Update: now using collections.abc.Iterable for the 2nd check. + # Note: None is considered a "scalar" for this check, which is correct + # for the usage in SCons.Environment._add_cppdefines. + return isinstance(obj, StringTypes) or not isinstance(obj, Iterable) # From Dinu C. Gherman, diff --git a/test/CPPDEFINES/append.py b/test/CPPDEFINES/append.py index 2a31021..32917ab 100644 --- a/test/CPPDEFINES/append.py +++ b/test/CPPDEFINES/append.py @@ -44,7 +44,9 @@ expect_print_output="""\ -Dfoo -Dbar -Dbaz -Dfoo bar -Dbaz -Dfoo -Dbar baz --DMacro2=Value2 -DMacro3=Value3 -DMacro1=Value1 +-Dfoo -Dbar -Dbaz +-DMacro2=Value2 -DMacro4 -DMacro3=Value3 -DMacro1=Value1 +-DMacro1=Value1 -DMacro1 -DValue1 ==== Testing CPPDEFINES, appending a string to a string orig = 'FOO', append = 'FOO' @@ -63,21 +65,21 @@ AppendUnique: result=['FOO', 'NAME1=VAL1'] final=-DFOO -DNAME1=VAL1 ==== Testing CPPDEFINES, appending a list to a string - orig = 'FOO', append = ['NAME1', 'NAME2'] + orig = 'FOO', append = ['NAME1', 'NAME2', 'NAME3'] Append: - result=['FOO', 'NAME1', 'NAME2'] - final=-DFOO -DNAME1 -DNAME2 + result=['FOO', 'NAME1', 'NAME2', 'NAME3'] + final=-DFOO -DNAME1 -DNAME2 -DNAME3 AppendUnique: - result=['FOO', 'NAME1', 'NAME2'] - final=-DFOO -DNAME1 -DNAME2 + result=['FOO', 'NAME1', 'NAME2', 'NAME3'] + final=-DFOO -DNAME1 -DNAME2 -DNAME3 ==== Testing CPPDEFINES, appending a tuple to a string - orig = 'FOO', append = ('NAME1', 'NAME2') + orig = 'FOO', append = ('NAME1', 'VAL1') Append: - result=['FOO', 'NAME1', 'NAME2'] - final=-DFOO -DNAME1 -DNAME2 + result=['FOO', ('NAME1', 'VAL1')] + final=-DFOO -DNAME1=VAL1 AppendUnique: - result=['FOO', 'NAME1', 'NAME2'] - final=-DFOO -DNAME1 -DNAME2 + result=['FOO', ('NAME1', 'VAL1')] + final=-DFOO -DNAME1=VAL1 ==== Testing CPPDEFINES, appending a list-of-2lists to a string orig = 'FOO', append = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Append: @@ -111,21 +113,21 @@ AppendUnique: result=['NAME1=VAL1'] final=-DNAME1=VAL1 ==== Testing CPPDEFINES, appending a list to a valuestring - orig = 'NAME1=VAL1', append = ['NAME1', 'NAME2'] + orig = 'NAME1=VAL1', append = ['NAME1', 'NAME2', 'NAME3'] Append: - result=['NAME1=VAL1', 'NAME1', 'NAME2'] - final=-DNAME1=VAL1 -DNAME1 -DNAME2 + result=['NAME1=VAL1', 'NAME1', 'NAME2', 'NAME3'] + final=-DNAME1=VAL1 -DNAME1 -DNAME2 -DNAME3 AppendUnique: - result=['NAME1=VAL1', 'NAME1', 'NAME2'] - final=-DNAME1=VAL1 -DNAME1 -DNAME2 + result=['NAME1=VAL1', 'NAME1', 'NAME2', 'NAME3'] + final=-DNAME1=VAL1 -DNAME1 -DNAME2 -DNAME3 ==== Testing CPPDEFINES, appending a tuple to a valuestring - orig = 'NAME1=VAL1', append = ('NAME1', 'NAME2') + orig = 'NAME1=VAL1', append = ('NAME1', 'VAL1') Append: - result=['NAME1=VAL1', 'NAME1', 'NAME2'] - final=-DNAME1=VAL1 -DNAME1 -DNAME2 + result=['NAME1=VAL1', ('NAME1', 'VAL1')] + final=-DNAME1=VAL1 -DNAME1=VAL1 AppendUnique: - result=['NAME1=VAL1', 'NAME1', 'NAME2'] - final=-DNAME1=VAL1 -DNAME1 -DNAME2 + result=['NAME1=VAL1'] + final=-DNAME1=VAL1 ==== Testing CPPDEFINES, appending a list-of-2lists to a valuestring orig = 'NAME1=VAL1', append = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Append: @@ -143,101 +145,101 @@ AppendUnique: result=['NAME1=VAL1', ('NAME2', 'VAL2'), ('NAME3', None)] final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME3 ==== Testing CPPDEFINES, appending a string to a list - orig = ['NAME1', 'NAME2'], append = 'FOO' + orig = ['NAME1', 'NAME2', 'NAME3'], append = 'FOO' Append: - result=['NAME1', 'NAME2', 'FOO'] - final=-DNAME1 -DNAME2 -DFOO + result=['NAME1', 'NAME2', 'NAME3', 'FOO'] + final=-DNAME1 -DNAME2 -DNAME3 -DFOO AppendUnique: - result=['NAME1', 'NAME2', 'FOO'] - final=-DNAME1 -DNAME2 -DFOO + result=['NAME1', 'NAME2', 'NAME3', 'FOO'] + final=-DNAME1 -DNAME2 -DNAME3 -DFOO ==== Testing CPPDEFINES, appending a valuestring to a list - orig = ['NAME1', 'NAME2'], append = 'NAME1=VAL1' + orig = ['NAME1', 'NAME2', 'NAME3'], append = 'NAME1=VAL1' Append: - result=['NAME1', 'NAME2', 'NAME1=VAL1'] - final=-DNAME1 -DNAME2 -DNAME1=VAL1 + result=['NAME1', 'NAME2', 'NAME3', 'NAME1=VAL1'] + final=-DNAME1 -DNAME2 -DNAME3 -DNAME1=VAL1 AppendUnique: - result=['NAME1', 'NAME2', 'NAME1=VAL1'] - final=-DNAME1 -DNAME2 -DNAME1=VAL1 + result=['NAME1', 'NAME2', 'NAME3', 'NAME1=VAL1'] + final=-DNAME1 -DNAME2 -DNAME3 -DNAME1=VAL1 ==== Testing CPPDEFINES, appending a list to a list - orig = ['NAME1', 'NAME2'], append = ['NAME1', 'NAME2'] + orig = ['NAME1', 'NAME2', 'NAME3'], append = ['NAME1', 'NAME2', 'NAME3'] Append: - result=['NAME1', 'NAME2', 'NAME1', 'NAME2'] - final=-DNAME1 -DNAME2 -DNAME1 -DNAME2 + result=['NAME1', 'NAME2', 'NAME3', 'NAME1', 'NAME2', 'NAME3'] + final=-DNAME1 -DNAME2 -DNAME3 -DNAME1 -DNAME2 -DNAME3 AppendUnique: - result=['NAME1', 'NAME2'] - final=-DNAME1 -DNAME2 + result=['NAME1', 'NAME2', 'NAME3'] + final=-DNAME1 -DNAME2 -DNAME3 ==== Testing CPPDEFINES, appending a tuple to a list - orig = ['NAME1', 'NAME2'], append = ('NAME1', 'NAME2') + orig = ['NAME1', 'NAME2', 'NAME3'], append = ('NAME1', 'VAL1') Append: - result=['NAME1', 'NAME2', 'NAME1', 'NAME2'] - final=-DNAME1 -DNAME2 -DNAME1 -DNAME2 + result=['NAME1', 'NAME2', 'NAME3', ('NAME1', 'VAL1')] + final=-DNAME1 -DNAME2 -DNAME3 -DNAME1=VAL1 AppendUnique: - result=['NAME1', 'NAME2'] - final=-DNAME1 -DNAME2 + result=['NAME1', 'NAME2', 'NAME3', ('NAME1', 'VAL1')] + final=-DNAME1 -DNAME2 -DNAME3 -DNAME1=VAL1 ==== Testing CPPDEFINES, appending a list-of-2lists to a list - orig = ['NAME1', 'NAME2'], append = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + orig = ['NAME1', 'NAME2', 'NAME3'], append = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Append: - result=['NAME1', 'NAME2', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] - final=-DNAME1 -DNAME2 -DNAME1=VAL1 -DNAME2=VAL2 + result=['NAME1', 'NAME2', 'NAME3', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME1 -DNAME2 -DNAME3 -DNAME1=VAL1 -DNAME2=VAL2 AppendUnique: - result=['NAME1', 'NAME2', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] - final=-DNAME1 -DNAME2 -DNAME1=VAL1 -DNAME2=VAL2 + result=['NAME1', 'NAME2', 'NAME3', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME1 -DNAME2 -DNAME3 -DNAME1=VAL1 -DNAME2=VAL2 ==== Testing CPPDEFINES, appending a dict to a list - orig = ['NAME1', 'NAME2'], append = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} + orig = ['NAME1', 'NAME2', 'NAME3'], append = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} Append: - result=['NAME1', 'NAME2', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] - final=-DNAME1 -DNAME2 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 + result=['NAME1', 'NAME2', 'NAME3', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME1 -DNAME2 -DNAME3 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 AppendUnique: - result=['NAME1', 'NAME2', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] - final=-DNAME1 -DNAME2 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 + result=['NAME1', 'NAME2', 'NAME3', ('NAME2', 'VAL2'), ('NAME1', 'VAL1')] + final=-DNAME1 -DNAME2 -DNAME3 -DNAME2=VAL2 -DNAME1=VAL1 ==== Testing CPPDEFINES, appending a string to a tuple - orig = ('NAME1', 'NAME2'), append = 'FOO' + orig = ('NAME1', 'VAL1'), append = 'FOO' Append: - result=['NAME1', 'NAME2', 'FOO'] - final=-DNAME1 -DNAME2 -DFOO + result=[('NAME1', 'VAL1'), 'FOO'] + final=-DNAME1=VAL1 -DFOO AppendUnique: - result=['NAME1', 'NAME2', 'FOO'] - final=-DNAME1 -DNAME2 -DFOO + result=[('NAME1', 'VAL1'), 'FOO'] + final=-DNAME1=VAL1 -DFOO ==== Testing CPPDEFINES, appending a valuestring to a tuple - orig = ('NAME1', 'NAME2'), append = 'NAME1=VAL1' + orig = ('NAME1', 'VAL1'), append = 'NAME1=VAL1' Append: - result=['NAME1', 'NAME2', 'NAME1=VAL1'] - final=-DNAME1 -DNAME2 -DNAME1=VAL1 + result=[('NAME1', 'VAL1'), 'NAME1=VAL1'] + final=-DNAME1=VAL1 -DNAME1=VAL1 AppendUnique: - result=['NAME1', 'NAME2', 'NAME1=VAL1'] - final=-DNAME1 -DNAME2 -DNAME1=VAL1 + result=[('NAME1', 'VAL1')] + final=-DNAME1=VAL1 ==== Testing CPPDEFINES, appending a list to a tuple - orig = ('NAME1', 'NAME2'), append = ['NAME1', 'NAME2'] + orig = ('NAME1', 'VAL1'), append = ['NAME1', 'NAME2', 'NAME3'] Append: - result=['NAME1', 'NAME2', 'NAME1', 'NAME2'] - final=-DNAME1 -DNAME2 -DNAME1 -DNAME2 + result=[('NAME1', 'VAL1'), 'NAME1', 'NAME2', 'NAME3'] + final=-DNAME1=VAL1 -DNAME1 -DNAME2 -DNAME3 AppendUnique: - result=['NAME1', 'NAME2'] - final=-DNAME1 -DNAME2 + result=[('NAME1', 'VAL1'), 'NAME1', 'NAME2', 'NAME3'] + final=-DNAME1=VAL1 -DNAME1 -DNAME2 -DNAME3 ==== Testing CPPDEFINES, appending a tuple to a tuple - orig = ('NAME1', 'NAME2'), append = ('NAME1', 'NAME2') + orig = ('NAME1', 'VAL1'), append = ('NAME1', 'VAL1') Append: - result=['NAME1', 'NAME2', 'NAME1', 'NAME2'] - final=-DNAME1 -DNAME2 -DNAME1 -DNAME2 + result=[('NAME1', 'VAL1'), ('NAME1', 'VAL1')] + final=-DNAME1=VAL1 -DNAME1=VAL1 AppendUnique: - result=['NAME1', 'NAME2'] - final=-DNAME1 -DNAME2 + result=[('NAME1', 'VAL1')] + final=-DNAME1=VAL1 ==== Testing CPPDEFINES, appending a list-of-2lists to a tuple - orig = ('NAME1', 'NAME2'), append = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + orig = ('NAME1', 'VAL1'), append = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Append: - result=['NAME1', 'NAME2', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] - final=-DNAME1 -DNAME2 -DNAME1=VAL1 -DNAME2=VAL2 + result=[('NAME1', 'VAL1'), ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME1=VAL1 -DNAME1=VAL1 -DNAME2=VAL2 AppendUnique: - result=['NAME1', 'NAME2', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] - final=-DNAME1 -DNAME2 -DNAME1=VAL1 -DNAME2=VAL2 + result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME1=VAL1 -DNAME2=VAL2 ==== Testing CPPDEFINES, appending a dict to a tuple - orig = ('NAME1', 'NAME2'), append = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} + orig = ('NAME1', 'VAL1'), append = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} Append: - result=['NAME1', 'NAME2', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] - final=-DNAME1 -DNAME2 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 + result=[('NAME1', 'VAL1'), ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 AppendUnique: - result=['NAME1', 'NAME2', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] - final=-DNAME1 -DNAME2 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 + result=[('NAME1', 'VAL1'), ('NAME2', 'VAL2'), ('NAME3', None)] + final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME3 ==== Testing CPPDEFINES, appending a string to a list-of-2lists orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], append = 'FOO' Append: @@ -255,21 +257,21 @@ AppendUnique: result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2']] final=-DNAME1=VAL1 -DNAME2=VAL2 ==== Testing CPPDEFINES, appending a list to a list-of-2lists - orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], append = ['NAME1', 'NAME2'] + orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], append = ['NAME1', 'NAME2', 'NAME3'] Append: - result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], 'NAME1', 'NAME2'] - final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME1 -DNAME2 + result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], 'NAME1', 'NAME2', 'NAME3'] + final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME1 -DNAME2 -DNAME3 AppendUnique: - result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], 'NAME1', 'NAME2'] - final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME1 -DNAME2 + result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], 'NAME1', 'NAME2', 'NAME3'] + final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME1 -DNAME2 -DNAME3 ==== Testing CPPDEFINES, appending a tuple to a list-of-2lists - orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], append = ('NAME1', 'NAME2') + orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], append = ('NAME1', 'VAL1') Append: - result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], 'NAME1', 'NAME2'] - final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME1 -DNAME2 + result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], ('NAME1', 'VAL1')] + final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME1=VAL1 AppendUnique: - result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2'], 'NAME1', 'NAME2'] - final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME1 -DNAME2 + result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME1=VAL1 -DNAME2=VAL2 ==== Testing CPPDEFINES, appending a list-of-2lists to a list-of-2lists orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], append = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Append: @@ -303,21 +305,21 @@ AppendUnique: result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 ==== Testing CPPDEFINES, appending a list to a dict - orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, append = ['NAME1', 'NAME2'] + orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, append = ['NAME1', 'NAME2', 'NAME3'] Append: - result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1'), 'NAME1', 'NAME2'] - final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DNAME1 -DNAME2 + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1'), 'NAME1', 'NAME2', 'NAME3'] + final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DNAME1 -DNAME2 -DNAME3 AppendUnique: result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1'), 'NAME1', 'NAME2'] final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DNAME1 -DNAME2 ==== Testing CPPDEFINES, appending a tuple to a dict - orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, append = ('NAME1', 'NAME2') + orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, append = ('NAME1', 'VAL1') Append: - result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1'), 'NAME1', 'NAME2'] - final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DNAME1 -DNAME2 + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1'), ('NAME1', 'VAL1')] + final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DNAME1=VAL1 AppendUnique: - result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1'), 'NAME1', 'NAME2'] - final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 -DNAME1 -DNAME2 + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 ==== Testing CPPDEFINES, appending a list-of-2lists to a dict orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, append = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Append: diff --git a/test/CPPDEFINES/fixture/SConstruct-Append b/test/CPPDEFINES/fixture/SConstruct-Append index 76b86ad..df47f68 100644 --- a/test/CPPDEFINES/fixture/SConstruct-Append +++ b/test/CPPDEFINES/fixture/SConstruct-Append @@ -15,7 +15,7 @@ env_2300_2 = Environment(CPPDEFINES=['foo'], CPPDEFPREFIX='-D') # note the list env_2300_2.Append(CPPDEFINES='bar') print(env_2300_2.subst('$_CPPDEFFLAGS')) -# an initial space-separated string will be split, but not a string in a list +# An initial space-separated string will be split, but not a string in a list. env_multi = Environment(CPPDEFPREFIX='-D') env_multi['CPPDEFINES'] = "foo bar" env_multi.Append(CPPDEFINES="baz") @@ -28,20 +28,27 @@ env_multi = Environment(CPPDEFPREFIX='-D') env_multi['CPPDEFINES'] = "foo" env_multi.Append(CPPDEFINES=["bar baz"]) print(env_multi.subst('$_CPPDEFFLAGS')) +env_multi = Environment(CPPDEFPREFIX='-D') +env_multi['CPPDEFINES'] = "foo" +env_multi.Append(CPPDEFINES="bar baz") +print(env_multi.subst('$_CPPDEFFLAGS')) -# check that AppendUnique(..., delete_existing=True) works as expected -# each addition is in different but matching form, and different order +# Check that AppendUnique(..., delete_existing=True) works as expected. +# Each addition is in different but matching form, and different order # so we expect a reordered list, but with the same macro defines. env_multi = Environment(CPPDEFPREFIX='-D') -env_multi.Append(CPPDEFINES=["Macro1=Value1", ("Macro2", "Value2"), {"Macro3": "Value3"}]) +env_multi.Append(CPPDEFINES=["Macro1=Value1", ("Macro2", "Value2"), {"Macro3": "Value3"}, "Macro4"]) env_multi.AppendUnique(CPPDEFINES="Macro2=Value2", delete_existing=True) +env_multi.AppendUnique(CPPDEFINES=[("Macro4", None)], delete_existing=True) env_multi.AppendUnique(CPPDEFINES=[("Macro3", "Value3")], delete_existing=True) env_multi.AppendUnique(CPPDEFINES={"Macro1": "Value1"}, delete_existing=True) print(env_multi.subst('$_CPPDEFFLAGS')) -# a lone tuple +# A lone tuple handled differently than a lone list. env_multi = Environment(CPPDEFPREFIX='-D', CPPDEFINES=("Macro1", "Value1")) print(env_multi.subst('$_CPPDEFFLAGS')) +env_multi = Environment(CPPDEFPREFIX='-D', CPPDEFINES=["Macro1", "Value1"]) +print(env_multi.subst('$_CPPDEFFLAGS')) # https://github.com/SCons/scons/issues/1152 # https://github.com/SCons/scons/issues/2900 @@ -66,11 +73,11 @@ class OrderedPrintingDict(OrderedDict): cases = [ ('string', 'FOO'), ('valuestring', 'NAME1=VAL1'), - ('list', ['NAME1', 'NAME2']), - ('tuple', ('NAME1', 'NAME2')), + ('list', ['NAME1', 'NAME2', 'NAME3']), + ('tuple', ('NAME1', 'VAL1')), ('list-of-2lists', [('NAME1', 'VAL1'), ['NAME2', 'VAL2']]), ( - 'dict', + 'dict', # intentionally not sorted by key OrderedPrintingDict([('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')]), ), ] diff --git a/test/CPPDEFINES/fixture/SConstruct-Prepend b/test/CPPDEFINES/fixture/SConstruct-Prepend index 4628ea4..7fd4d84 100644 --- a/test/CPPDEFINES/fixture/SConstruct-Prepend +++ b/test/CPPDEFINES/fixture/SConstruct-Prepend @@ -15,7 +15,7 @@ env_2300_2 = Environment(CPPDEFINES=['foo'], CPPDEFPREFIX='-D') # note the list env_2300_2.Prepend(CPPDEFINES='bar') print(env_2300_2.subst('$_CPPDEFFLAGS')) -# an initial space-separated string will be split, but not a string in a list +# An initial space-separated string will be split, but not a string in a list. env_multi = Environment(CPPDEFPREFIX='-D') env_multi['CPPDEFINES'] = "foo bar" env_multi.Prepend(CPPDEFINES="baz") @@ -28,20 +28,27 @@ env_multi = Environment(CPPDEFPREFIX='-D') env_multi['CPPDEFINES'] = "foo" env_multi.Prepend(CPPDEFINES=["bar baz"]) print(env_multi.subst('$_CPPDEFFLAGS')) +env_multi = Environment(CPPDEFPREFIX='-D') +env_multi['CPPDEFINES'] = "foo" +env_multi.Prepend(CPPDEFINES="bar baz") +print(env_multi.subst('$_CPPDEFFLAGS')) -# check that PrependUnique(..., delete_existing=True) works as expected -# each addition is in different but matching form, and different order, +# Check that AppendUnique(..., delete_existing=True) works as expected. +# Each addition is in different but matching form, and different order # so we expect a reordered list, but with the same macro defines. env_multi = Environment(CPPDEFPREFIX='-D') env_multi.Prepend(CPPDEFINES=["Macro1=Value1", ("Macro2", "Value2"), {"Macro3": "Value3"}]) env_multi.PrependUnique(CPPDEFINES="Macro2=Value2", delete_existing=True) +env_multi.AppendUnique(CPPDEFINES=[("Macro4", None)], delete_existing=True) env_multi.PrependUnique(CPPDEFINES=[("Macro3", "Value3")], delete_existing=True) env_multi.PrependUnique(CPPDEFINES={"Macro1": "Value1"}, delete_existing=True) print(env_multi.subst('$_CPPDEFFLAGS')) -# a lone tuple +# A lone tuple handled differently than a lone list. env_tuple = Environment(CPPDEFPREFIX='-D', CPPDEFINES=("Macro1", "Value1")) print(env_tuple.subst('$_CPPDEFFLAGS')) +env_multi = Environment(CPPDEFPREFIX='-D', CPPDEFINES=["Macro1", "Value1"]) +print(env_multi.subst('$_CPPDEFFLAGS')) # https://github.com/SCons/scons/issues/1152 # https://github.com/SCons/scons/issues/2900 @@ -67,11 +74,11 @@ class OrderedPrintingDict(OrderedDict): cases = [ ('string', 'FOO'), ('valuestring', 'NAME1=VAL1'), - ('list', ['NAME1', 'NAME2']), - ('tuple', ('NAME1', 'NAME2')), + ('list', ['NAME1', 'NAME2', 'NAME3']), + ('tuple', ('NAME1', 'VAL1')), ('list-of-2lists', [('NAME1', 'VAL1'), ['NAME2', 'VAL2']]), ( - 'dict', + 'dict', # intentionally not sorted by key OrderedPrintingDict([('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')]), ), ] diff --git a/test/CPPDEFINES/prepend.py b/test/CPPDEFINES/prepend.py index 5ec2e46..16bedac 100644 --- a/test/CPPDEFINES/prepend.py +++ b/test/CPPDEFINES/prepend.py @@ -43,7 +43,9 @@ expect_print_output="""\ -Dbaz -Dfoo -Dbar -Dbaz -Dfoo bar -Dbar baz -Dfoo --DMacro1=Value1 -DMacro3=Value3 -DMacro2=Value2 +-Dbaz -Dbar -Dfoo +-DMacro1=Value1 -DMacro3=Value3 -DMacro2=Value2 -DMacro4 +-DMacro1=Value1 -DMacro1 -DValue1 ==== Testing CPPDEFINES, prepending a string to a string orig = 'FOO', prepend = 'FOO' @@ -62,21 +64,21 @@ PrependUnique: result=['NAME1=VAL1', 'FOO'] final=-DNAME1=VAL1 -DFOO ==== Testing CPPDEFINES, prepending a list to a string - orig = 'FOO', prepend = ['NAME1', 'NAME2'] + orig = 'FOO', prepend = ['NAME1', 'NAME2', 'NAME3'] Prepend: - result=['NAME2', 'NAME1', 'FOO'] - final=-DNAME2 -DNAME1 -DFOO + result=['NAME3', 'NAME2', 'NAME1', 'FOO'] + final=-DNAME3 -DNAME2 -DNAME1 -DFOO PrependUnique: - result=['NAME2', 'NAME1', 'FOO'] - final=-DNAME2 -DNAME1 -DFOO + result=['NAME3', 'NAME2', 'NAME1', 'FOO'] + final=-DNAME3 -DNAME2 -DNAME1 -DFOO ==== Testing CPPDEFINES, prepending a tuple to a string - orig = 'FOO', prepend = ('NAME1', 'NAME2') + orig = 'FOO', prepend = ('NAME1', 'VAL1') Prepend: - result=['NAME2', 'NAME1', 'FOO'] - final=-DNAME2 -DNAME1 -DFOO + result=[('NAME1', 'VAL1'), 'FOO'] + final=-DNAME1=VAL1 -DFOO PrependUnique: - result=['NAME2', 'NAME1', 'FOO'] - final=-DNAME2 -DNAME1 -DFOO + result=[('NAME1', 'VAL1'), 'FOO'] + final=-DNAME1=VAL1 -DFOO ==== Testing CPPDEFINES, prepending a list-of-2lists to a string orig = 'FOO', prepend = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Prepend: @@ -110,21 +112,21 @@ PrependUnique: result=['NAME1=VAL1'] final=-DNAME1=VAL1 ==== Testing CPPDEFINES, prepending a list to a valuestring - orig = 'NAME1=VAL1', prepend = ['NAME1', 'NAME2'] + orig = 'NAME1=VAL1', prepend = ['NAME1', 'NAME2', 'NAME3'] Prepend: - result=['NAME2', 'NAME1', 'NAME1=VAL1'] - final=-DNAME2 -DNAME1 -DNAME1=VAL1 + result=['NAME3', 'NAME2', 'NAME1', 'NAME1=VAL1'] + final=-DNAME3 -DNAME2 -DNAME1 -DNAME1=VAL1 PrependUnique: - result=['NAME2', 'NAME1', 'NAME1=VAL1'] - final=-DNAME2 -DNAME1 -DNAME1=VAL1 + result=['NAME3', 'NAME2', 'NAME1', 'NAME1=VAL1'] + final=-DNAME3 -DNAME2 -DNAME1 -DNAME1=VAL1 ==== Testing CPPDEFINES, prepending a tuple to a valuestring - orig = 'NAME1=VAL1', prepend = ('NAME1', 'NAME2') + orig = 'NAME1=VAL1', prepend = ('NAME1', 'VAL1') Prepend: - result=['NAME2', 'NAME1', 'NAME1=VAL1'] - final=-DNAME2 -DNAME1 -DNAME1=VAL1 + result=[('NAME1', 'VAL1'), 'NAME1=VAL1'] + final=-DNAME1=VAL1 -DNAME1=VAL1 PrependUnique: - result=['NAME2', 'NAME1', 'NAME1=VAL1'] - final=-DNAME2 -DNAME1 -DNAME1=VAL1 + result=['NAME1=VAL1'] + final=-DNAME1=VAL1 ==== Testing CPPDEFINES, prepending a list-of-2lists to a valuestring orig = 'NAME1=VAL1', prepend = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Prepend: @@ -142,101 +144,101 @@ PrependUnique: result=[('NAME3', None), ('NAME2', 'VAL2'), 'NAME1=VAL1'] final=-DNAME3 -DNAME2=VAL2 -DNAME1=VAL1 ==== Testing CPPDEFINES, prepending a string to a list - orig = ['NAME1', 'NAME2'], prepend = 'FOO' + orig = ['NAME1', 'NAME2', 'NAME3'], prepend = 'FOO' Prepend: - result=['FOO', 'NAME1', 'NAME2'] - final=-DFOO -DNAME1 -DNAME2 + result=['FOO', 'NAME1', 'NAME2', 'NAME3'] + final=-DFOO -DNAME1 -DNAME2 -DNAME3 PrependUnique: - result=['FOO', 'NAME1', 'NAME2'] - final=-DFOO -DNAME1 -DNAME2 + result=['FOO', 'NAME1', 'NAME2', 'NAME3'] + final=-DFOO -DNAME1 -DNAME2 -DNAME3 ==== Testing CPPDEFINES, prepending a valuestring to a list - orig = ['NAME1', 'NAME2'], prepend = 'NAME1=VAL1' + orig = ['NAME1', 'NAME2', 'NAME3'], prepend = 'NAME1=VAL1' Prepend: - result=['NAME1=VAL1', 'NAME1', 'NAME2'] - final=-DNAME1=VAL1 -DNAME1 -DNAME2 + result=['NAME1=VAL1', 'NAME1', 'NAME2', 'NAME3'] + final=-DNAME1=VAL1 -DNAME1 -DNAME2 -DNAME3 PrependUnique: - result=['NAME1=VAL1', 'NAME1', 'NAME2'] - final=-DNAME1=VAL1 -DNAME1 -DNAME2 + result=['NAME1=VAL1', 'NAME1', 'NAME2', 'NAME3'] + final=-DNAME1=VAL1 -DNAME1 -DNAME2 -DNAME3 ==== Testing CPPDEFINES, prepending a list to a list - orig = ['NAME1', 'NAME2'], prepend = ['NAME1', 'NAME2'] + orig = ['NAME1', 'NAME2', 'NAME3'], prepend = ['NAME1', 'NAME2', 'NAME3'] Prepend: - result=['NAME2', 'NAME1', 'NAME1', 'NAME2'] - final=-DNAME2 -DNAME1 -DNAME1 -DNAME2 + result=['NAME3', 'NAME2', 'NAME1', 'NAME1', 'NAME2', 'NAME3'] + final=-DNAME3 -DNAME2 -DNAME1 -DNAME1 -DNAME2 -DNAME3 PrependUnique: - result=['NAME1', 'NAME2'] - final=-DNAME1 -DNAME2 + result=['NAME1', 'NAME2', 'NAME3'] + final=-DNAME1 -DNAME2 -DNAME3 ==== Testing CPPDEFINES, prepending a tuple to a list - orig = ['NAME1', 'NAME2'], prepend = ('NAME1', 'NAME2') + orig = ['NAME1', 'NAME2', 'NAME3'], prepend = ('NAME1', 'VAL1') Prepend: - result=['NAME2', 'NAME1', 'NAME1', 'NAME2'] - final=-DNAME2 -DNAME1 -DNAME1 -DNAME2 + result=[('NAME1', 'VAL1'), 'NAME1', 'NAME2', 'NAME3'] + final=-DNAME1=VAL1 -DNAME1 -DNAME2 -DNAME3 PrependUnique: - result=['NAME1', 'NAME2'] - final=-DNAME1 -DNAME2 + result=[('NAME1', 'VAL1'), 'NAME1', 'NAME2', 'NAME3'] + final=-DNAME1=VAL1 -DNAME1 -DNAME2 -DNAME3 ==== Testing CPPDEFINES, prepending a list-of-2lists to a list - orig = ['NAME1', 'NAME2'], prepend = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + orig = ['NAME1', 'NAME2', 'NAME3'], prepend = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Prepend: - result=[['NAME2', 'VAL2'], ('NAME1', 'VAL1'), 'NAME1', 'NAME2'] - final=-DNAME2=VAL2 -DNAME1=VAL1 -DNAME1 -DNAME2 + result=[['NAME2', 'VAL2'], ('NAME1', 'VAL1'), 'NAME1', 'NAME2', 'NAME3'] + final=-DNAME2=VAL2 -DNAME1=VAL1 -DNAME1 -DNAME2 -DNAME3 PrependUnique: - result=[['NAME2', 'VAL2'], ('NAME1', 'VAL1'), 'NAME1', 'NAME2'] - final=-DNAME2=VAL2 -DNAME1=VAL1 -DNAME1 -DNAME2 + result=[['NAME2', 'VAL2'], ('NAME1', 'VAL1'), 'NAME1', 'NAME2', 'NAME3'] + final=-DNAME2=VAL2 -DNAME1=VAL1 -DNAME1 -DNAME2 -DNAME3 ==== Testing CPPDEFINES, prepending a dict to a list - orig = ['NAME1', 'NAME2'], prepend = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} + orig = ['NAME1', 'NAME2', 'NAME3'], prepend = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} Prepend: - result=[('NAME1', 'VAL1'), ('NAME3', None), ('NAME2', 'VAL2'), 'NAME1', 'NAME2'] - final=-DNAME1=VAL1 -DNAME3 -DNAME2=VAL2 -DNAME1 -DNAME2 + result=[('NAME1', 'VAL1'), ('NAME3', None), ('NAME2', 'VAL2'), 'NAME1', 'NAME2', 'NAME3'] + final=-DNAME1=VAL1 -DNAME3 -DNAME2=VAL2 -DNAME1 -DNAME2 -DNAME3 PrependUnique: - result=[('NAME1', 'VAL1'), ('NAME3', None), ('NAME2', 'VAL2'), 'NAME1', 'NAME2'] - final=-DNAME1=VAL1 -DNAME3 -DNAME2=VAL2 -DNAME1 -DNAME2 + result=[('NAME1', 'VAL1'), ('NAME2', 'VAL2'), 'NAME1', 'NAME2', 'NAME3'] + final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME1 -DNAME2 -DNAME3 ==== Testing CPPDEFINES, prepending a string to a tuple - orig = ('NAME1', 'NAME2'), prepend = 'FOO' + orig = ('NAME1', 'VAL1'), prepend = 'FOO' Prepend: - result=['FOO', 'NAME1', 'NAME2'] - final=-DFOO -DNAME1 -DNAME2 + result=['FOO', ('NAME1', 'VAL1')] + final=-DFOO -DNAME1=VAL1 PrependUnique: - result=['FOO', 'NAME1', 'NAME2'] - final=-DFOO -DNAME1 -DNAME2 + result=['FOO', ('NAME1', 'VAL1')] + final=-DFOO -DNAME1=VAL1 ==== Testing CPPDEFINES, prepending a valuestring to a tuple - orig = ('NAME1', 'NAME2'), prepend = 'NAME1=VAL1' + orig = ('NAME1', 'VAL1'), prepend = 'NAME1=VAL1' Prepend: - result=['NAME1=VAL1', 'NAME1', 'NAME2'] - final=-DNAME1=VAL1 -DNAME1 -DNAME2 + result=['NAME1=VAL1', ('NAME1', 'VAL1')] + final=-DNAME1=VAL1 -DNAME1=VAL1 PrependUnique: - result=['NAME1=VAL1', 'NAME1', 'NAME2'] - final=-DNAME1=VAL1 -DNAME1 -DNAME2 + result=[('NAME1', 'VAL1')] + final=-DNAME1=VAL1 ==== Testing CPPDEFINES, prepending a list to a tuple - orig = ('NAME1', 'NAME2'), prepend = ['NAME1', 'NAME2'] + orig = ('NAME1', 'VAL1'), prepend = ['NAME1', 'NAME2', 'NAME3'] Prepend: - result=['NAME2', 'NAME1', 'NAME1', 'NAME2'] - final=-DNAME2 -DNAME1 -DNAME1 -DNAME2 + result=['NAME3', 'NAME2', 'NAME1', ('NAME1', 'VAL1')] + final=-DNAME3 -DNAME2 -DNAME1 -DNAME1=VAL1 PrependUnique: - result=['NAME1', 'NAME2'] - final=-DNAME1 -DNAME2 + result=['NAME3', 'NAME2', 'NAME1', ('NAME1', 'VAL1')] + final=-DNAME3 -DNAME2 -DNAME1 -DNAME1=VAL1 ==== Testing CPPDEFINES, prepending a tuple to a tuple - orig = ('NAME1', 'NAME2'), prepend = ('NAME1', 'NAME2') + orig = ('NAME1', 'VAL1'), prepend = ('NAME1', 'VAL1') Prepend: - result=['NAME2', 'NAME1', 'NAME1', 'NAME2'] - final=-DNAME2 -DNAME1 -DNAME1 -DNAME2 + result=[('NAME1', 'VAL1'), ('NAME1', 'VAL1')] + final=-DNAME1=VAL1 -DNAME1=VAL1 PrependUnique: - result=['NAME1', 'NAME2'] - final=-DNAME1 -DNAME2 + result=[('NAME1', 'VAL1')] + final=-DNAME1=VAL1 ==== Testing CPPDEFINES, prepending a list-of-2lists to a tuple - orig = ('NAME1', 'NAME2'), prepend = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + orig = ('NAME1', 'VAL1'), prepend = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Prepend: - result=[['NAME2', 'VAL2'], ('NAME1', 'VAL1'), 'NAME1', 'NAME2'] - final=-DNAME2=VAL2 -DNAME1=VAL1 -DNAME1 -DNAME2 + result=[['NAME2', 'VAL2'], ('NAME1', 'VAL1'), ('NAME1', 'VAL1')] + final=-DNAME2=VAL2 -DNAME1=VAL1 -DNAME1=VAL1 PrependUnique: - result=[['NAME2', 'VAL2'], ('NAME1', 'VAL1'), 'NAME1', 'NAME2'] - final=-DNAME2=VAL2 -DNAME1=VAL1 -DNAME1 -DNAME2 + result=[['NAME2', 'VAL2'], ('NAME1', 'VAL1')] + final=-DNAME2=VAL2 -DNAME1=VAL1 ==== Testing CPPDEFINES, prepending a dict to a tuple - orig = ('NAME1', 'NAME2'), prepend = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} + orig = ('NAME1', 'VAL1'), prepend = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'} Prepend: - result=[('NAME1', 'VAL1'), ('NAME3', None), ('NAME2', 'VAL2'), 'NAME1', 'NAME2'] - final=-DNAME1=VAL1 -DNAME3 -DNAME2=VAL2 -DNAME1 -DNAME2 + result=[('NAME1', 'VAL1'), ('NAME3', None), ('NAME2', 'VAL2'), ('NAME1', 'VAL1')] + final=-DNAME1=VAL1 -DNAME3 -DNAME2=VAL2 -DNAME1=VAL1 PrependUnique: - result=[('NAME1', 'VAL1'), ('NAME3', None), ('NAME2', 'VAL2'), 'NAME1', 'NAME2'] - final=-DNAME1=VAL1 -DNAME3 -DNAME2=VAL2 -DNAME1 -DNAME2 + result=[('NAME3', None), ('NAME2', 'VAL2'), ('NAME1', 'VAL1')] + final=-DNAME3 -DNAME2=VAL2 -DNAME1=VAL1 ==== Testing CPPDEFINES, prepending a string to a list-of-2lists orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], prepend = 'FOO' Prepend: @@ -254,21 +256,21 @@ PrependUnique: result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2']] final=-DNAME1=VAL1 -DNAME2=VAL2 ==== Testing CPPDEFINES, prepending a list to a list-of-2lists - orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], prepend = ['NAME1', 'NAME2'] + orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], prepend = ['NAME1', 'NAME2', 'NAME3'] Prepend: - result=['NAME2', 'NAME1', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] - final=-DNAME2 -DNAME1 -DNAME1=VAL1 -DNAME2=VAL2 + result=['NAME3', 'NAME2', 'NAME1', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME3 -DNAME2 -DNAME1 -DNAME1=VAL1 -DNAME2=VAL2 PrependUnique: - result=['NAME2', 'NAME1', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] - final=-DNAME2 -DNAME1 -DNAME1=VAL1 -DNAME2=VAL2 + result=['NAME3', 'NAME2', 'NAME1', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME3 -DNAME2 -DNAME1 -DNAME1=VAL1 -DNAME2=VAL2 ==== Testing CPPDEFINES, prepending a tuple to a list-of-2lists - orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], prepend = ('NAME1', 'NAME2') + orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], prepend = ('NAME1', 'VAL1') Prepend: - result=['NAME2', 'NAME1', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] - final=-DNAME2 -DNAME1 -DNAME1=VAL1 -DNAME2=VAL2 + result=[('NAME1', 'VAL1'), ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME1=VAL1 -DNAME1=VAL1 -DNAME2=VAL2 PrependUnique: - result=['NAME2', 'NAME1', ('NAME1', 'VAL1'), ['NAME2', 'VAL2']] - final=-DNAME2 -DNAME1 -DNAME1=VAL1 -DNAME2=VAL2 + result=[('NAME1', 'VAL1'), ['NAME2', 'VAL2']] + final=-DNAME1=VAL1 -DNAME2=VAL2 ==== Testing CPPDEFINES, prepending a list-of-2lists to a list-of-2lists orig = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']], prepend = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Prepend: @@ -302,21 +304,21 @@ PrependUnique: result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 ==== Testing CPPDEFINES, prepending a list to a dict - orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, prepend = ['NAME1', 'NAME2'] + orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, prepend = ['NAME1', 'NAME2', 'NAME3'] Prepend: - result=['NAME2', 'NAME1', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] - final=-DNAME2 -DNAME1 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 + result=['NAME3', 'NAME2', 'NAME1', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME3 -DNAME2 -DNAME1 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 PrependUnique: result=['NAME2', 'NAME1', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] final=-DNAME2 -DNAME1 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 ==== Testing CPPDEFINES, prepending a tuple to a dict - orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, prepend = ('NAME1', 'NAME2') + orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, prepend = ('NAME1', 'VAL1') Prepend: - result=['NAME2', 'NAME1', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] - final=-DNAME2 -DNAME1 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 + result=[('NAME1', 'VAL1'), ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME1=VAL1 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 PrependUnique: - result=['NAME2', 'NAME1', ('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] - final=-DNAME2 -DNAME1 -DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 + result=[('NAME2', 'VAL2'), ('NAME3', None), ('NAME1', 'VAL1')] + final=-DNAME2=VAL2 -DNAME3 -DNAME1=VAL1 ==== Testing CPPDEFINES, prepending a list-of-2lists to a dict orig = {'NAME2': 'VAL2', 'NAME3': None, 'NAME1': 'VAL1'}, prepend = [('NAME1', 'VAL1'), ['NAME2', 'VAL2']] Prepend: -- cgit v0.12 From 0f7b5fbae63e3486255b2b9951373075d55a9a58 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 10 Feb 2023 12:06:40 -0700 Subject: Adjust CPPDEFINES tests to be more resilient In a hope to make the tests runnable against a checkout that does not include PR #4263, add some try blocks so the things which used to blow up can generate errors rather than aborting the test run. The prepend test still fails against master. Signed-off-by: Mats Wichmann --- test/CPPDEFINES/fixture/SConstruct-Append | 27 +++++++++++++++++---------- test/CPPDEFINES/fixture/SConstruct-Prepend | 27 +++++++++++++++++---------- 2 files changed, 34 insertions(+), 20 deletions(-) diff --git a/test/CPPDEFINES/fixture/SConstruct-Append b/test/CPPDEFINES/fixture/SConstruct-Append index df47f68..62d7352 100644 --- a/test/CPPDEFINES/fixture/SConstruct-Append +++ b/test/CPPDEFINES/fixture/SConstruct-Append @@ -96,16 +96,23 @@ for (t1, c1) in cases: for (t2, c2) in cases: print(f"==== Testing CPPDEFINES, appending a {t2} to a {t1}") # string-like appearance if the value is a string - orig = f"'{c1}'" if isinstance(c1, str) else c1 - app = f"'{c2}'" if isinstance(c2, str) else c2 + orig = f"{c1!r}" if isinstance(c1, str) else c1 + app = f"{c2!r}" if isinstance(c2, str) else c2 print(f" orig = {orig}, append = {app}") env = Environment(CPPDEFINES=c1, CPPDEFPREFIX='-D') - env.Append(CPPDEFINES=c2) - final = env.subst('$_CPPDEFFLAGS', source="src", target="tgt") - print(f"Append:\n result={dlist(env['CPPDEFINES'])}\n final={final}") + try: + env.Append(CPPDEFINES=c2) + final = env.subst('$_CPPDEFFLAGS', source="src", target="tgt") + print(f"Append:\n result={dlist(env['CPPDEFINES'])}\n final={final}") + except Exception as t: + print(f"Append:\n FAILED: {t}") + env = Environment(CPPDEFINES=c1, CPPDEFPREFIX='-D') - env.AppendUnique(CPPDEFINES=c2) - final = env.subst('$_CPPDEFFLAGS', source="src", target="tgt") - print( - f"AppendUnique:\n result={dlist(env['CPPDEFINES'])}\n final={final}" - ) + try: + env.AppendUnique(CPPDEFINES=c2) + final = env.subst('$_CPPDEFFLAGS', source="src", target="tgt") + print( + f"AppendUnique:\n result={dlist(env['CPPDEFINES'])}\n final={final}" + ) + except Exception as t: + print(f"AppendUnique:\n FAILED: {t}") diff --git a/test/CPPDEFINES/fixture/SConstruct-Prepend b/test/CPPDEFINES/fixture/SConstruct-Prepend index 7fd4d84..4234de2 100644 --- a/test/CPPDEFINES/fixture/SConstruct-Prepend +++ b/test/CPPDEFINES/fixture/SConstruct-Prepend @@ -97,16 +97,23 @@ for (t1, c1) in cases: for (t2, c2) in cases: print(f"==== Testing CPPDEFINES, prepending a {t2} to a {t1}") # string-like appearance if the value is a string - orig = f"'{c1}'" if isinstance(c1, str) else c1 - pre = f"'{c2}'" if isinstance(c2, str) else c2 + orig = f"{c1!r}" if isinstance(c1, str) else c1 + pre = f"{c2!r}" if isinstance(c2, str) else c2 print(f" orig = {orig}, prepend = {pre}") env = Environment(CPPDEFINES=c1, CPPDEFPREFIX='-D') - env.Prepend(CPPDEFINES=c2) - final = env.subst('$_CPPDEFFLAGS', source="src", target="tgt") - print(f"Prepend:\n result={dlist(env['CPPDEFINES'])}\n final={final}") + try: + env.Prepend(CPPDEFINES=c2) + final = env.subst('$_CPPDEFFLAGS', source="src", target="tgt") + print(f"Prepend:\n result={dlist(env['CPPDEFINES'])}\n final={final}") + except Exception as t: + print(f"Prepend:\n FAILED: {t}") + env = Environment(CPPDEFINES=c1, CPPDEFPREFIX='-D') - env.PrependUnique(CPPDEFINES=c2) - final = env.subst('$_CPPDEFFLAGS', source="src", target="tgt") - print( - f"PrependUnique:\n result={dlist(env['CPPDEFINES'])}\n final={final}" - ) + try: + env.PrependUnique(CPPDEFINES=c2) + final = env.subst('$_CPPDEFFLAGS', source="src", target="tgt") + print( + f"PrependUnique:\n result={dlist(env['CPPDEFINES'])}\n final={final}" + ) + except Exception as t: + print(f"PrependUnique:\n FAILED: {t}") -- cgit v0.12 From e37f8b71a89adebae1592edca7c5371d50322e42 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 10 Feb 2023 17:41:38 -0800 Subject: Added DefaultEnvironment(tools=[]) to fixtures for CPPDEFINES. Added negative test for non-two-tuple. Minor wording change --- SCons/Defaults.py | 4 ++-- SCons/DefaultsTests.py | 10 ++++++++++ test/CPPDEFINES/fixture/SConstruct-Append | 2 ++ test/CPPDEFINES/fixture/SConstruct-Prepend | 1 + 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/SCons/Defaults.py b/SCons/Defaults.py index ea7e930..72af1bd 100644 --- a/SCons/Defaults.py +++ b/SCons/Defaults.py @@ -530,7 +530,7 @@ def processDefines(defs) -> List[str]: if len(define) > 2: raise SCons.Errors.UserError( f"Invalid tuple in CPPDEFINES: {define!r}, " - "must be a two-tuple" + "must be a tuple with only two elements" ) name, *value = define if value and value[0] is not None: @@ -556,7 +556,7 @@ def processDefines(defs) -> List[str]: if len(defs) > 2: raise SCons.Errors.UserError( f"Invalid tuple in CPPDEFINES: {defs!r}, " - "must be a two-tuple" + "must be a tuple with only two elements" ) name, *value = defs if value and value[0] is not None: diff --git a/SCons/DefaultsTests.py b/SCons/DefaultsTests.py index c9a6663..66e219a 100644 --- a/SCons/DefaultsTests.py +++ b/SCons/DefaultsTests.py @@ -28,6 +28,7 @@ import collections import TestCmd from SCons.Defaults import mkdir_func, _defines, processDefines +from SCons.Errors import UserError class DummyEnvironment(collections.UserDict): @@ -144,6 +145,15 @@ class DefaultsTestCase(unittest.TestCase): rv = processDefines(['foo', ('name', 'val'), ['name2', 'val2']]) self.assertEqual(rv, ['foo', 'name=val', 'name2=val2']) + with self.subTest(): + # invalid tuple + try: + rv = processDefines([('name', 'val', 'bad')]) + except UserError as e: + pass + else: + self.fail("Invalid tuple should throw SCons.Errors.UserError") + if __name__ == "__main__": unittest.main() diff --git a/test/CPPDEFINES/fixture/SConstruct-Append b/test/CPPDEFINES/fixture/SConstruct-Append index 62d7352..1149fc3 100644 --- a/test/CPPDEFINES/fixture/SConstruct-Append +++ b/test/CPPDEFINES/fixture/SConstruct-Append @@ -1,3 +1,5 @@ +DefaultEnvironment(tools=[]) + # Special cases: # https://github.com/SCons/scons/issues/1738 env_1738_2 = Environment(CPPDEFPREFIX='-D') diff --git a/test/CPPDEFINES/fixture/SConstruct-Prepend b/test/CPPDEFINES/fixture/SConstruct-Prepend index 4234de2..67d637c 100644 --- a/test/CPPDEFINES/fixture/SConstruct-Prepend +++ b/test/CPPDEFINES/fixture/SConstruct-Prepend @@ -1,3 +1,4 @@ +DefaultEnvironment(tools=[]) # Special cases: # https://github.com/SCons/scons/issues/1738 env_1738_2 = Environment(CPPDEFPREFIX='-D') -- cgit v0.12 From c1adc3e49673431d57cbb157a1f6157070e3a1f6 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Wed, 15 Feb 2023 09:39:33 -0700 Subject: Tweak Append/Prepend e2e tests Added another try block so complete prepend e2e test can be run on a branch where PR #4263 is not applied (for comparison). Added license header. Changed invalid-tuple unittest to use assertRaises (behavior is the same) Also added a versionadded and a versionchanged to docstrings. Signed-off-by: Mats Wichmann --- SCons/Defaults.py | 5 +++++ SCons/DefaultsTests.py | 8 +++----- SCons/Environment.py | 4 +++- test/CPPDEFINES/fixture/SConstruct-Append | 23 ++++++++++++++++++----- test/CPPDEFINES/fixture/SConstruct-Prepend | 26 ++++++++++++++++++++------ 5 files changed, 49 insertions(+), 17 deletions(-) diff --git a/SCons/Defaults.py b/SCons/Defaults.py index 72af1bd..4ca7ab8 100644 --- a/SCons/Defaults.py +++ b/SCons/Defaults.py @@ -520,6 +520,11 @@ def processDefines(defs) -> List[str]: or direct write) it can be a multitude of types. Any prefix/suffix is handled elsewhere (usually :func:`_concat_ixes`). + + .. versionchanged:: 4.5 + Bare tuples are now treated the same as tuple-in-sequence, assumed + to describe a valued macro. Bare strings are now split on space. + A dictionary is no longer sorted before handling. """ dlist = [] if is_List(defs): diff --git a/SCons/DefaultsTests.py b/SCons/DefaultsTests.py index 66e219a..b23f328 100644 --- a/SCons/DefaultsTests.py +++ b/SCons/DefaultsTests.py @@ -147,12 +147,10 @@ class DefaultsTestCase(unittest.TestCase): with self.subTest(): # invalid tuple - try: + with self.assertRaises( + UserError, msg="Invalid tuple should throw SCons.Errors.UserError" + ): rv = processDefines([('name', 'val', 'bad')]) - except UserError as e: - pass - else: - self.fail("Invalid tuple should throw SCons.Errors.UserError") if __name__ == "__main__": diff --git a/SCons/Environment.py b/SCons/Environment.py index 3bd1a62..74c5641 100644 --- a/SCons/Environment.py +++ b/SCons/Environment.py @@ -201,7 +201,7 @@ def _add_cppdefines( unique: bool = False, delete_existing: bool = False, ) -> None: - """Adds to CPPDEFINES, using the rules for C preprocessor macros. + """Adds to ``CPPDEFINES``, using the rules for C preprocessor macros. This is split out from regular construction variable addition because these entries can express either a macro with a replacement value or @@ -222,6 +222,8 @@ def _add_cppdefines( prepend: whether to put *val* in front or back. unique: whether to add *val* if it already exists. delete_existing: if *unique* is true, add *val* after removing previous. + + .. versionadded:: 4.5 """ def _add_define(item, defines: deque, prepend: bool = False) -> None: diff --git a/test/CPPDEFINES/fixture/SConstruct-Append b/test/CPPDEFINES/fixture/SConstruct-Append index 1149fc3..8c26270 100644 --- a/test/CPPDEFINES/fixture/SConstruct-Append +++ b/test/CPPDEFINES/fixture/SConstruct-Append @@ -1,3 +1,9 @@ +# SPDX-License-Identifier: MIT +# +# Copyright The SCons Foundation + +"""Append/AppendUnique tests""" + DefaultEnvironment(tools=[]) # Special cases: @@ -22,14 +28,17 @@ env_multi = Environment(CPPDEFPREFIX='-D') env_multi['CPPDEFINES'] = "foo bar" env_multi.Append(CPPDEFINES="baz") print(env_multi.subst('$_CPPDEFFLAGS')) + env_multi = Environment(CPPDEFPREFIX='-D') env_multi['CPPDEFINES'] = ["foo bar"] env_multi.Append(CPPDEFINES="baz") print(env_multi.subst('$_CPPDEFFLAGS')) + env_multi = Environment(CPPDEFPREFIX='-D') env_multi['CPPDEFINES'] = "foo" env_multi.Append(CPPDEFINES=["bar baz"]) print(env_multi.subst('$_CPPDEFFLAGS')) + env_multi = Environment(CPPDEFPREFIX='-D') env_multi['CPPDEFINES'] = "foo" env_multi.Append(CPPDEFINES="bar baz") @@ -40,11 +49,15 @@ print(env_multi.subst('$_CPPDEFFLAGS')) # so we expect a reordered list, but with the same macro defines. env_multi = Environment(CPPDEFPREFIX='-D') env_multi.Append(CPPDEFINES=["Macro1=Value1", ("Macro2", "Value2"), {"Macro3": "Value3"}, "Macro4"]) -env_multi.AppendUnique(CPPDEFINES="Macro2=Value2", delete_existing=True) -env_multi.AppendUnique(CPPDEFINES=[("Macro4", None)], delete_existing=True) -env_multi.AppendUnique(CPPDEFINES=[("Macro3", "Value3")], delete_existing=True) -env_multi.AppendUnique(CPPDEFINES={"Macro1": "Value1"}, delete_existing=True) -print(env_multi.subst('$_CPPDEFFLAGS')) +try: + env_multi.AppendUnique(CPPDEFINES="Macro2=Value2", delete_existing=True) + env_multi.AppendUnique(CPPDEFINES=[("Macro4", None)], delete_existing=True) + env_multi.AppendUnique(CPPDEFINES=[("Macro3", "Value3")], delete_existing=True) + env_multi.AppendUnique(CPPDEFINES={"Macro1": "Value1"}, delete_existing=True) +except Exception as t: + print(f"Prepend FAILED: {t}") +else: + print(env_multi.subst('$_CPPDEFFLAGS')) # A lone tuple handled differently than a lone list. env_multi = Environment(CPPDEFPREFIX='-D', CPPDEFINES=("Macro1", "Value1")) diff --git a/test/CPPDEFINES/fixture/SConstruct-Prepend b/test/CPPDEFINES/fixture/SConstruct-Prepend index 67d637c..26546f1 100644 --- a/test/CPPDEFINES/fixture/SConstruct-Prepend +++ b/test/CPPDEFINES/fixture/SConstruct-Prepend @@ -1,4 +1,11 @@ +# SPDX-License-Identifier: MIT +# +# Copyright The SCons Foundation + +"""Prepend/PrependUnique tests""" + DefaultEnvironment(tools=[]) + # Special cases: # https://github.com/SCons/scons/issues/1738 env_1738_2 = Environment(CPPDEFPREFIX='-D') @@ -21,29 +28,36 @@ env_multi = Environment(CPPDEFPREFIX='-D') env_multi['CPPDEFINES'] = "foo bar" env_multi.Prepend(CPPDEFINES="baz") print(env_multi.subst('$_CPPDEFFLAGS')) + env_multi = Environment(CPPDEFPREFIX='-D') env_multi['CPPDEFINES'] = ["foo bar"] env_multi.Prepend(CPPDEFINES="baz") print(env_multi.subst('$_CPPDEFFLAGS')) + env_multi = Environment(CPPDEFPREFIX='-D') env_multi['CPPDEFINES'] = "foo" env_multi.Prepend(CPPDEFINES=["bar baz"]) print(env_multi.subst('$_CPPDEFFLAGS')) + env_multi = Environment(CPPDEFPREFIX='-D') env_multi['CPPDEFINES'] = "foo" env_multi.Prepend(CPPDEFINES="bar baz") print(env_multi.subst('$_CPPDEFFLAGS')) -# Check that AppendUnique(..., delete_existing=True) works as expected. +# Check that PrependUnique(..., delete_existing=True) works as expected. # Each addition is in different but matching form, and different order # so we expect a reordered list, but with the same macro defines. env_multi = Environment(CPPDEFPREFIX='-D') env_multi.Prepend(CPPDEFINES=["Macro1=Value1", ("Macro2", "Value2"), {"Macro3": "Value3"}]) -env_multi.PrependUnique(CPPDEFINES="Macro2=Value2", delete_existing=True) -env_multi.AppendUnique(CPPDEFINES=[("Macro4", None)], delete_existing=True) -env_multi.PrependUnique(CPPDEFINES=[("Macro3", "Value3")], delete_existing=True) -env_multi.PrependUnique(CPPDEFINES={"Macro1": "Value1"}, delete_existing=True) -print(env_multi.subst('$_CPPDEFFLAGS')) +try: + env_multi.PrependUnique(CPPDEFINES="Macro2=Value2", delete_existing=True) + env_multi.PrependUnique(CPPDEFINES=[("Macro4", None)], delete_existing=True) + env_multi.PrependUnique(CPPDEFINES=[("Macro3", "Value3")], delete_existing=True) + env_multi.PrependUnique(CPPDEFINES={"Macro1": "Value1"}, delete_existing=True) +except Exception as t: + print(f"Prepend FAILED: {t}") +else: + print(env_multi.subst('$_CPPDEFFLAGS')) # A lone tuple handled differently than a lone list. env_tuple = Environment(CPPDEFPREFIX='-D', CPPDEFINES=("Macro1", "Value1")) -- cgit v0.12 From d4c99290d1afb1a388f834ab3b66d13919259742 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Wed, 15 Feb 2023 10:30:56 -0700 Subject: CPPDEFINES prepend test fix Signed-off-by: Mats Wichmann --- test/CPPDEFINES/prepend.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/CPPDEFINES/prepend.py b/test/CPPDEFINES/prepend.py index 16bedac..fb61678 100644 --- a/test/CPPDEFINES/prepend.py +++ b/test/CPPDEFINES/prepend.py @@ -44,7 +44,7 @@ expect_print_output="""\ -Dbaz -Dfoo bar -Dbar baz -Dfoo -Dbaz -Dbar -Dfoo --DMacro1=Value1 -DMacro3=Value3 -DMacro2=Value2 -DMacro4 +-DMacro1=Value1 -DMacro3=Value3 -DMacro4 -DMacro2=Value2 -DMacro1=Value1 -DMacro1 -DValue1 ==== Testing CPPDEFINES, prepending a string to a string -- cgit v0.12 From 143882c3a228497267e0130463d31b3d93a6b852 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 15 Feb 2023 19:13:45 -0800 Subject: rewording of CHANGES.txt info. Changed versionadded to 4.5.0 --- CHANGES.txt | 21 ++++++++------------- RELEASE.txt | 8 ++++---- SCons/Defaults.py | 2 +- SCons/Environment.py | 2 +- 4 files changed, 14 insertions(+), 19 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index e10feab..4a2cb0d 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -133,19 +133,14 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER Also added "unique" keyword, to control whether a library is added or not if it is already in the $LIBS construction var in the configure context. (issue #2768). - - Special-case handling for CPPDEFINES in the Append/Prepend routines - is split out into its own function to simplify the remaining code and - fix problems. The e2e test test/CPPDEFINES/append.py is expanded - to cover missed cases, and AppendUnique no longer mismatches - with what Append does (#3876). Inconsistent handling of tuples - to specify macro=value outputs is also cleaned up (#4254). The - special handling now also works for Prepend/PrependUnique, and a - corresponding e2e test test/CPPDEFINES/prepend.py was added to verify - the behavior. A unit test for SCons.Util.processDefines, used to - convert CPPDEFINES into a list of strings, is added. SCons used - to sort keys set or appended via a dict type, in order to assure - order of commandline flags did not change across runs. This behavior - has been dropped since Python now assures consistent dict order. + - Completely refactored the CPPDEFINES logic in Append/AppendUnique/Prepend/PrependUnique + This change fixes the following GH Issues: + - GH Issue #3876 - Append() and AppendUnique() will handle CPPDEFINES the same + - GH Issue #4254 - Make handling tuples in CPPDEFINES consistent. + - We no longer sort the keys added to CPPDEFINES by their dictionary keys. + We take advantage that their order is now stable based on insertion order + in Python 3.5+ + - Added/modifed unit and system tests to verify these changes. RELEASE 4.4.0 - Sat, 30 Jul 2022 14:08:29 -0700 diff --git a/RELEASE.txt b/RELEASE.txt index 7a431c2..756d674 100644 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -17,10 +17,10 @@ NOTE: If you build with Python 3.10.0 and then rebuild with 3.10.1 (or higher), see unexpected rebuilds. This is due to Python internals changing which changed the signature of a Python Action Function. -NOTE: If you use a dictionary to specify your CPPDEFINES, the order of - dictionary keys is now preserved when generating the command line. - Previously these were sorted alphabecially: this may cause a change - which leads to a rebuild. +NOTE: If you use a dictionary to specify your CPPDEFINES, you may see unexpected build results + The insertion order of dictionary keys is now preserved when generating the command line. + Previously these were sorted alphabecially. This change to the command line, + while generating identical set of CPPDEFINES can change order and cause a rebuild. NEW FUNCTIONALITY diff --git a/SCons/Defaults.py b/SCons/Defaults.py index 4ca7ab8..b21ce4c 100644 --- a/SCons/Defaults.py +++ b/SCons/Defaults.py @@ -521,7 +521,7 @@ def processDefines(defs) -> List[str]: Any prefix/suffix is handled elsewhere (usually :func:`_concat_ixes`). - .. versionchanged:: 4.5 + .. versionchanged:: 4.5.0 Bare tuples are now treated the same as tuple-in-sequence, assumed to describe a valued macro. Bare strings are now split on space. A dictionary is no longer sorted before handling. diff --git a/SCons/Environment.py b/SCons/Environment.py index 74c5641..9140d27 100644 --- a/SCons/Environment.py +++ b/SCons/Environment.py @@ -223,7 +223,7 @@ def _add_cppdefines( unique: whether to add *val* if it already exists. delete_existing: if *unique* is true, add *val* after removing previous. - .. versionadded:: 4.5 + .. versionadded:: 4.5.0 """ def _add_define(item, defines: deque, prepend: bool = False) -> None: -- cgit v0.12 From bf391cdde553f25749ebc1256edd32c28273d85d Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 16 Feb 2023 10:43:57 -0800 Subject: clarify notice --- RELEASE.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASE.txt b/RELEASE.txt index 756d674..7a96cec 100644 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -17,7 +17,7 @@ NOTE: If you build with Python 3.10.0 and then rebuild with 3.10.1 (or higher), see unexpected rebuilds. This is due to Python internals changing which changed the signature of a Python Action Function. -NOTE: If you use a dictionary to specify your CPPDEFINES, you may see unexpected build results +NOTE: If you use a dictionary to specify your CPPDEFINES, you may see an unexpected rebuild. The insertion order of dictionary keys is now preserved when generating the command line. Previously these were sorted alphabecially. This change to the command line, while generating identical set of CPPDEFINES can change order and cause a rebuild. -- cgit v0.12