From 68eb8859776439714c6e38a6e2ef53031199afbc Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Tue, 4 Jun 2024 09:44:18 -0600 Subject: [PATCH] Teach Clone() to respect the variables= kwarg. Previously, "variables" would just be set as a construction var, now it has the same meaning as an Environment() call. Docs updated and test added. Fixes #3590 Signed-off-by: Mats Wichmann --- CHANGES.txt | 1 + RELEASE.txt | 1 + SCons/Environment.py | 28 +++++++++++++----- SCons/Environment.xml | 32 +++++++++++++++------ test/Clone-Variables.py | 63 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 109 insertions(+), 16 deletions(-) create mode 100644 test/Clone-Variables.py diff --git a/CHANGES.txt b/CHANGES.txt index ab13ef074b..0f827a7943 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -85,6 +85,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER Now matches the annotation and docstring (which were prematurely updated in 4.6). All SCons usage except unit test was already fully consistent with a bool. + - The Clone() method now respects the variables argument (fixes #3590) RELEASE 4.7.0 - Sun, 17 Mar 2024 17:22:20 -0700 diff --git a/RELEASE.txt b/RELEASE.txt index b9c253f4d4..c994041623 100644 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -58,6 +58,7 @@ FIXES - Improved the conversion of a "foreign" exception from an action into BuildError by making sure our defaults get applied even in corner cases. Fixes Issue #4530 +- The Clone() method now respects the variables argument (fixes #3590) IMPROVEMENTS ------------ diff --git a/SCons/Environment.py b/SCons/Environment.py index ae44414154..952ffc17c8 100644 --- a/SCons/Environment.py +++ b/SCons/Environment.py @@ -1568,16 +1568,28 @@ def AppendUnique(self, delete_existing: bool=False, **kw) -> None: self._dict[key] = dk + val self.scanner_map_delete(kw) - def Clone(self, tools=[], toolpath=None, parse_flags = None, **kw): + def Clone(self, tools=[], toolpath=None, variables=None, parse_flags=None, **kw): """Return a copy of a construction Environment. - The copy is like a Python "deep copy"--that is, independent - copies are made recursively of each objects--except that - a reference is copied when an object is not deep-copyable - (like a function). There are no references to any mutable - objects in the original Environment. - """ + The copy is like a Python "deep copy": independent copies are made + recursively of each object, except that a reference is copied when + an object is not deep-copyable (like a function). There are no + references to any mutable objects in the original environment. + + Unrecognized keyword arguments are taken as construction variable + assignments. + Arguments: + tools: list of tools to initialize. + toolpath: list of paths to search for tools. + variables: a :class:`~SCons.Variables.Variables` object to + use to populate construction variables from command-line + variables. + parse_flags: option strings to parse into construction variables. + + .. versionadded:: 4.8.0 + The optional *variables* parameter was added. + """ builders = self._dict.get('BUILDERS', {}) clone = copy.copy(self) @@ -1603,6 +1615,8 @@ def Clone(self, tools=[], toolpath=None, parse_flags = None, **kw): for key, value in kw.items(): new[key] = SCons.Subst.scons_subst_once(value, self, key) clone.Replace(**new) + if variables: + variables.Update(clone) apply_tools(clone, tools, toolpath) diff --git a/SCons/Environment.xml b/SCons/Environment.xml index 5f152f22ee..c09d3848d6 100644 --- a/SCons/Environment.xml +++ b/SCons/Environment.xml @@ -1079,11 +1079,12 @@ Clean(docdir, os.path.join(docdir, projectname)) -Returns a separate copy of a construction environment. -If there are any keyword arguments specified, -they are added to the returned copy, +Returns an independent copy of a &consenv;. +If there are any unrecognized keyword arguments specified, +they are added as &consvars; in the copy, overwriting any existing values -for the keywords. +for those keywords. +See the manpage section "Construction Environments" for more details. @@ -1096,8 +1097,9 @@ env3 = env.Clone(CCFLAGS='-g') -Additionally, a list of tools and a toolpath may be specified, as in -the &f-link-Environment; constructor: +A list of tools +and a toolpath may be specified, +as in the &f-link-Environment; constructor: @@ -1110,7 +1112,7 @@ env4 = env.Clone(tools=['msvc', MyTool]) The parse_flags -keyword argument is also recognized to allow merging command-line +keyword argument is also recognized, to allow merging command-line style arguments into the appropriate construction variables (see &f-link-env-MergeFlags;). @@ -1119,6 +1121,17 @@ variables (see &f-link-env-MergeFlags;). # create an environment for compiling programs that use wxWidgets wx_env = env.Clone(parse_flags='!wx-config --cflags --cxxflags') + + +The variables +keyword argument is also recognized, to allow (re)initializing +&consvars; from a Variables object. + + + +Changed in version 4.8.0: +the variables parameter was added. + @@ -1760,7 +1773,7 @@ will print: -Return a new construction environment +Return a new &consenv; initialized with the specified key=value pairs. @@ -1770,7 +1783,8 @@ The keyword arguments toolpath, tools and variables -are also specially recognized. +are specially recognized and do not lead to +&consvar; creation. See the manpage section "Construction Environments" for more details. diff --git a/test/Clone-Variables.py b/test/Clone-Variables.py new file mode 100644 index 0000000000..383caeafbb --- /dev/null +++ b/test/Clone-Variables.py @@ -0,0 +1,63 @@ +#!/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 that Clone() respects the variables kwarg. + +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +vars = Variables() +vars.Add(BoolVariable('MYTEST', 'help', default=False)) + +_ = DefaultEnvironment(tools=[]) +env = Environment(variables=vars, tools=[]) +print(f"MYTEST={env.Dictionary('MYTEST')}") +env.Replace(MYTEST=True) +print(f"MYTEST={env.Dictionary('MYTEST')}") +env1 = env.Clone(variables=vars) +print(f"MYTEST={env1.Dictionary('MYTEST')}") +""") + +expect = """\ +MYTEST=False +MYTEST=True +MYTEST=False +""" + +test.run(arguments = '-q -Q', stdout=expect) + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: