From 8440b074e1616d81286dceb4d0a448ce671c2c66 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Tue, 9 Jan 2024 07:33:40 -0700 Subject: Maint: remove dead code from sconsign The Utilities/sconsign.py code used to do its own importing of the suitable module to read the sconsign file; for a while now it leaves that to the sconsign module, but some remnants of the old code were still present, which caused checkers and IDEs to grumble about usage of the "imp" module, which is removed from Python as of 3.12. Dropping this (uncalled) code and associated comments quiets the grumbles. Also tweaked manpage just a bit. Signed-off-by: Mats Wichmann --- CHANGES.txt | 1 + SCons/Utilities/sconsign.py | 22 ------------ doc/man/sconsign.xml | 81 ++++++++++++++++++++++----------------------- 3 files changed, 40 insertions(+), 64 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index adb955c..fbed74c 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -56,6 +56,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER From Mats Wichmann: - Add support for Python 3.13 (as of alpha 2). So far only affects expected bytecodes in ActionTests.py. + - sconsign cleanup - remove some dead code, minor manpage tweaks. RELEASE 4.6.0 - Sun, 19 Nov 2023 17:22:20 -0700 diff --git a/SCons/Utilities/sconsign.py b/SCons/Utilities/sconsign.py index a02ebb0..4cef477 100644 --- a/SCons/Utilities/sconsign.py +++ b/SCons/Utilities/sconsign.py @@ -51,24 +51,6 @@ def my_whichdb(filename): return whichdb(filename) -def my_import(mname): - """Import database module. - - This was used if the module was *not* SCons.dblite, to allow - for programmatic importing. It is no longer used, in favor of - importlib.import_module, and will be removed eventually. - """ - import imp - - if '.' in mname: - i = mname.rfind('.') - parent = my_import(mname[:i]) - fp, pathname, description = imp.find_module(mname[i+1:], parent.__path__) - else: - fp, pathname, description = imp.find_module(mname) - return imp.load_module(mname, fp, pathname, description) - - class Flagger: default_value = 1 @@ -449,8 +431,6 @@ Options: dbm = SCons.dblite # Ensure that we don't ignore corrupt DB files, - # this was handled by calling my_import('SCons.dblite') - # again in earlier versions... SCons.dblite.IGNORE_CORRUPT_DBFILES = False except ImportError: sys.stderr.write("sconsign: illegal file format `%s'\n" % a) @@ -492,8 +472,6 @@ Options: dbm = SCons.dblite # Ensure that we don't ignore corrupt DB files, - # this was handled by calling my_import('SCons.dblite') - # again in earlier versions... SCons.dblite.IGNORE_CORRUPT_DBFILES = False Do_SConsignDB(Map_Module.get(dbm_name, dbm_name), dbm)(a) else: diff --git a/doc/man/sconsign.xml b/doc/man/sconsign.xml index 726f86e..b5b01ca 100644 --- a/doc/man/sconsign.xml +++ b/doc/man/sconsign.xml @@ -1,29 +1,17 @@ - + +%version; + +%scons; +]> + -DESCRIPTION + +DESCRIPTION Displays the contents of one or more -sconsign files, -the signature database files -used by the SCons build tool. +sconsign files, +the signature/dependency database +used by the &SCons; build tool. By default, @@ -64,26 +53,34 @@ Without options, individual dependency entries are printed in the following format: -depfile: signature timestamp length - implicit_dependency_1: content_signature timestamp length - implicit_dependency_2: content_signature timestamp length +depfile: csig timestamp length + implicit_dependency_1: csig timestamp length + implicit_dependency_2: csig timestamp length ... - action_signature [action string] + bactsig [action string] -None + +csig +is the content signature, +a hash of the file's contents. +bactsig +is the build action signature, +a hash of the command line or other build action +used to build a target. +None is printed in place of any missing timestamp, - content signature -(csig) -or -build action signature +csig, +or bactsig values for any entry or any of its dependencies. If the entry has no implicit dependencies, or no build action, -those lines are omitted. +the corresponding lines are omitted. + -By default, + +By default, sconsign assumes that any file @@ -92,14 +89,13 @@ arguments that end with a suffix contains signature entries for more than one directory -(that is, -was specified by the +(that is, was specified by the SConsignFile -function). +&SCons; function). Any file argument that has no suffix -is assumed to be an old-style +is assumed to be an old-style (deprecated) sconsign file containing the signature entries for a single directory. If neither of those is true, @@ -299,7 +295,8 @@ for all entries or the specified entries. SEE ALSO -scons, +The &SCons; reference (manpage) at +, the SCons User Guide at , the SCons source code -- cgit v0.12 From 4fc13f6468e4625ae931f11127e19d7f6c3ed8b3 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Mon, 29 Jan 2024 09:25:26 -0700 Subject: Adjust sconsign manpage Following review comments, restored more descriptive names and reworded some things. Signed-off-by: Mats Wichmann --- doc/man/sconsign.xml | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/doc/man/sconsign.xml b/doc/man/sconsign.xml index b5b01ca..9ece78a 100644 --- a/doc/man/sconsign.xml +++ b/doc/man/sconsign.xml @@ -43,6 +43,9 @@ Displays the contents of one or more sconsign files, the signature/dependency database used by the &SCons; build tool. +The database contains all Nodes that are known to the build, +either by declaration in the build configuration, +produced as side effects, or detected by inspection. By default, @@ -53,33 +56,39 @@ Without options, individual dependency entries are printed in the following format: -depfile: csig timestamp length - implicit_dependency_1: csig timestamp length - implicit_dependency_2: csig timestamp length +depfile: content-signature timestamp length + implicit-dependency-1: content-signature timestamp length + implicit-dependency-2: content-signature timestamp length ... - bactsig [action string] + build-signature [action-string] -csig -is the content signature, -a hash of the file's contents. -bactsig -is the build action signature, -a hash of the command line or other build action -used to build a target. +content-signature +is the hash of the file's contents (csig) +and build-signature +is the hash of the command line or other build action +used to build a target (bactsig). +If provided, +action-string +is the unexpanded string action or the function called. None is printed in place of any missing timestamp, csig, or bactsig -values for any entry -or any of its dependencies. +values for any entry or any of its dependencies. If the entry has no implicit dependencies, or no build action, the corresponding lines are omitted. +An indicator line is printed for each directory, +as directories do not have signatures in the database +and so would not otherwise be shown. + + + By default, sconsign assumes that any -- cgit v0.12 From f27c3cacbd666751de947858dab8be600764874d Mon Sep 17 00:00:00 2001 From: Andrew Morrow Date: Thu, 25 Jan 2024 20:02:32 -0500 Subject: cache push on any thread --- SCons/Node/NodeTests.py | 2 -- SCons/Node/__init__.py | 2 -- SCons/Taskmaster/__init__.py | 7 ++----- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/SCons/Node/NodeTests.py b/SCons/Node/NodeTests.py index 42fae01..fc98104 100644 --- a/SCons/Node/NodeTests.py +++ b/SCons/Node/NodeTests.py @@ -1296,7 +1296,6 @@ class NodeTestCase(unittest.TestCase): n.includes = 'testincludes' n.Tag('found_includes', {'testkey':'testvalue'}) n.implicit = 'testimplicit' - n.cached = 1 x = MyExecutor() n.set_executor(x) @@ -1304,7 +1303,6 @@ class NodeTestCase(unittest.TestCase): n.clear() assert n.includes is None, n.includes - assert n.cached == 0, n.cached assert x.cleaned_up def test_get_subst_proxy(self) -> None: diff --git a/SCons/Node/__init__.py b/SCons/Node/__init__.py index 3da4faf..08e1254 100644 --- a/SCons/Node/__init__.py +++ b/SCons/Node/__init__.py @@ -588,7 +588,6 @@ class Node(metaclass=NoSlotsPyPy): self.pseudo = False self.noclean = 0 self.nocache = 0 - self.cached = 0 # is this node pulled from cache? self.always_build = None self.includes = None self.attributes = self.Attrs() # Generic place to stick information about the Node. @@ -864,7 +863,6 @@ class Node(metaclass=NoSlotsPyPy): delattr(self, attr) except AttributeError: pass - self.cached = 0 self.includes = None def clear_memoized_values(self) -> None: diff --git a/SCons/Taskmaster/__init__.py b/SCons/Taskmaster/__init__.py index d3002fa..33e9118 100644 --- a/SCons/Taskmaster/__init__.py +++ b/SCons/Taskmaster/__init__.py @@ -244,9 +244,8 @@ class Task(ABC): SCons.Warnings.warn(SCons.Warnings.CacheCleanupErrorWarning, "Failed copying all target files from cache, Error while attempting to remove file %s retrieved from cache: %s" % (t.get_internal_path(), e)) self.targets[0].build() - else: - for t in cached_targets: - t.cached = 1 + for t in self.targets: + t.push_to_cache() except SystemExit: exc_value = sys.exc_info()[1] raise SCons.Errors.ExplicitExit(self.targets[0], exc_value.code) @@ -299,8 +298,6 @@ class Task(ABC): for side_effect in t.side_effects: side_effect.set_state(NODE_NO_STATE) t.set_state(NODE_EXECUTED) - if not t.cached: - t.push_to_cache() t.built() t.visited() if (not print_prepare and -- cgit v0.12 From aa572ff11d79bb9e4a2b6fd9296d345d06cdd7b3 Mon Sep 17 00:00:00 2001 From: Andrew Morrow Date: Tue, 30 Jan 2024 12:55:48 -0500 Subject: Add note to CHANGES.txt --- CHANGES.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 44a458a..3409f3b 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -65,6 +65,9 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER Python to 3.6, and it was not until Python 3.7 where `threading` became default supported. In practice, we expect most real world Python 3.6 deployments will have `threading` support enabled, so this will not be an issue. + - CacheDir writes no longer happen within the taskmaster critical section, + and therefore can run in parallel with both other CacheDir writes and the + taskmaster DAG walk. From Mats Wichmann: - Add support for Python 3.13 (as of alpha 2). So far only affects -- cgit v0.12 From d5084ec4b04033670568933e99d7b6c86a072e07 Mon Sep 17 00:00:00 2001 From: Andrew Morrow Date: Tue, 30 Jan 2024 13:02:27 -0500 Subject: Add note to RELEASE.txt as well --- RELEASE.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RELEASE.txt b/RELEASE.txt index 2952d4f..37454c9 100644 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -63,6 +63,8 @@ IMPROVEMENTS the new scheduler is now used for -j1 builds as well. NOTE: This should significantly improve SCons performance for larger parallel builds (Larger -j values) +- CacheDir writes no longer happen within the taskmaster critical section, and therefore + can run in parallel with both other CacheDir writes and the taskmaster DAG walk. PACKAGING -- cgit v0.12 From e0272d22c5d34346548d40ed092ffcfc4e156542 Mon Sep 17 00:00:00 2001 From: Andrew Morrow Date: Mon, 5 Feb 2024 13:13:35 -0500 Subject: Partially revert "cache push on any thread" This partially reverts commit 8a6b5e4b12254afbba8cf4aadb78300a92a42de7 to restore `Node.cached` field. --- SCons/Node/NodeTests.py | 2 ++ SCons/Node/__init__.py | 2 ++ SCons/Taskmaster/__init__.py | 3 +++ 3 files changed, 7 insertions(+) diff --git a/SCons/Node/NodeTests.py b/SCons/Node/NodeTests.py index fc98104..42fae01 100644 --- a/SCons/Node/NodeTests.py +++ b/SCons/Node/NodeTests.py @@ -1296,6 +1296,7 @@ class NodeTestCase(unittest.TestCase): n.includes = 'testincludes' n.Tag('found_includes', {'testkey':'testvalue'}) n.implicit = 'testimplicit' + n.cached = 1 x = MyExecutor() n.set_executor(x) @@ -1303,6 +1304,7 @@ class NodeTestCase(unittest.TestCase): n.clear() assert n.includes is None, n.includes + assert n.cached == 0, n.cached assert x.cleaned_up def test_get_subst_proxy(self) -> None: diff --git a/SCons/Node/__init__.py b/SCons/Node/__init__.py index 08e1254..3da4faf 100644 --- a/SCons/Node/__init__.py +++ b/SCons/Node/__init__.py @@ -588,6 +588,7 @@ class Node(metaclass=NoSlotsPyPy): self.pseudo = False self.noclean = 0 self.nocache = 0 + self.cached = 0 # is this node pulled from cache? self.always_build = None self.includes = None self.attributes = self.Attrs() # Generic place to stick information about the Node. @@ -863,6 +864,7 @@ class Node(metaclass=NoSlotsPyPy): delattr(self, attr) except AttributeError: pass + self.cached = 0 self.includes = None def clear_memoized_values(self) -> None: diff --git a/SCons/Taskmaster/__init__.py b/SCons/Taskmaster/__init__.py index 33e9118..4d768ee 100644 --- a/SCons/Taskmaster/__init__.py +++ b/SCons/Taskmaster/__init__.py @@ -246,6 +246,9 @@ class Task(ABC): self.targets[0].build() for t in self.targets: t.push_to_cache() + else: + for t in cached_targets: + t.cached = 1 except SystemExit: exc_value = sys.exc_info()[1] raise SCons.Errors.ExplicitExit(self.targets[0], exc_value.code) -- cgit v0.12 From 4d0998763b82f69166328a8104dc0eda3a1b779f Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Wed, 7 Feb 2024 07:47:46 -0700 Subject: Add Pseudo() to global functions, had been omitted. When Pseudo was added in SCons 2.3.1, it was not added to the GlobalDefaultEnvironmentFunctions table which makes environment methods available in the default environment. Reworked the test so it does not rewrite the test SConstruct, and added steps to test the global function version as well. Fixes #4474. Signed-off-by: Mats Wichmann --- CHANGES.txt | 1 + RELEASE.txt | 2 ++ SCons/Script/__init__.py | 1 + test/Pseudo.py | 79 ++++++++++++++++++++++++++++++++---------------- 4 files changed, 57 insertions(+), 26 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 44a458a..b3a0d6e 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -74,6 +74,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER Fixes #3529. - Clarify/fix documentation of Scanners in User Guide and Manpage. Fixes #4468. + - Add Pseudo() to global functions, had been omitted. Fixes #4474. RELEASE 4.6.0 - Sun, 19 Nov 2023 17:22:20 -0700 diff --git a/RELEASE.txt b/RELEASE.txt index 2952d4f..28b6c6a 100644 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -52,6 +52,8 @@ FIXES build of the project file fails. - On Windows platform, when collecting command output (Configure checks), make sure decoding of bytes doesn't fail. +- Documentation indicated that both Pseudo() and env.Pseudo() were usable, + but Pseudo() did not work; is now enabled. IMPROVEMENTS ------------ diff --git a/SCons/Script/__init__.py b/SCons/Script/__init__.py index 0d2940c..a62650f 100644 --- a/SCons/Script/__init__.py +++ b/SCons/Script/__init__.py @@ -343,6 +343,7 @@ GlobalDefaultEnvironmentFunctions = [ 'Local', 'ParseDepends', 'Precious', + 'Pseudo', 'PyPackageDir', 'Repository', 'Requires', diff --git a/test/Pseudo.py b/test/Pseudo.py index db3c30c..ec953f7 100644 --- a/test/Pseudo.py +++ b/test/Pseudo.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,41 +22,66 @@ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" +""" +Test the Pseudo method +""" import TestSCons test = TestSCons.TestSCons() -# Firstly, build a pseudo target and make sure we get no warnings it -# doesn't exist under any circumstances -test.write('SConstruct', """ +test.write('SConstruct', """\ env = Environment() -env.Pseudo(env.Command('foo.out', [], '@echo boo')) -""") - -test.run(arguments='-Q', stdout = 'boo\n') +foo = env.Command('foo.out', [], '@echo boo') +bar = env.Command('bar.out', [], Touch('$TARGET')) +env.Pseudo(foo, bar) -test.run(arguments='-Q --warning=target-not-built', stdout = "boo\n") - -# Now do the same thing again but create the target and check we get an -# error if it exists after the build -test.write('SConstruct', """ -env = Environment() -env.Pseudo(env.Command('foo.out', [], Touch('$TARGET'))) +gfoo = Command('foo.glb', [], '@echo boo') +gbar = Command('bar.glb', [], Touch('$TARGET')) +Pseudo(gfoo, gbar) """) -test.run(arguments='-Q', stdout = 'Touch("foo.out")\n', stderr = None, - status = 2) -test.must_contain_all_lines(test.stderr(), - 'scons: *** Pseudo target foo.out must not exist') -test.run(arguments='-Q --warning=target-not-built', - stdout = 'Touch("foo.out")\n', - stderr = None, status = 2) -test.must_contain_all_lines(test.stderr(), - 'scons: *** Pseudo target foo.out must not exist') +# foo.out build does not create file, should generate no errors +test.run(arguments='-Q foo.out', stdout='boo\n') +# missing target warning triggers if requested +test.run(arguments='-Q foo.out --warning=target-not-built', stdout="boo\n") +# bar.out build creates file, error if it exists after the build +test.run(arguments='-Q bar.out', stdout='Touch("bar.out")\n', stderr=None, status=2) +test.must_contain_all_lines( + test.stderr(), + 'scons: *** Pseudo target bar.out must not exist', +) +# warning must not appear since target created +test.run( + arguments='-Q bar.out --warning=target-not-built', + stdout='Touch("bar.out")\n', + stderr=None, + status=2, +) +test.must_contain_all_lines( + test.stderr(), + 'scons: *** Pseudo target bar.out must not exist', +) + +# repeat the process for the global function form (was missing initially) +test.run(arguments='-Q foo.glb', stdout='boo\n') +test.run(arguments='-Q foo.glb --warning=target-not-built', stdout="boo\n") +test.run(arguments='-Q bar.glb', stdout='Touch("bar.glb")\n', stderr=None, status=2) +test.must_contain_all_lines( + test.stderr(), + 'scons: *** Pseudo target bar.glb must not exist', +) +test.run( + arguments='-Q bar.glb --warning=target-not-built', + stdout='Touch("bar.glb")\n', + stderr=None, + status=2, +) +test.must_contain_all_lines( + test.stderr(), + 'scons: *** Pseudo target bar.glb must not exist', +) test.pass_test() -- cgit v0.12