From b2b7a3c12b894a2561ba91fd55896d56c063d402 Mon Sep 17 00:00:00 2001 From: Daniel Moody Date: Wed, 25 May 2022 22:24:01 -0500 Subject: Fix for #2757, non conftest nodes involved in configure checks now get node info cleared after check. --- CHANGES.txt | 2 + RELEASE.txt | 2 + SCons/SConf.py | 13 +++++++ SCons/SConfTests.py | 2 + test/Configure/conftest_source_file.py | 52 ++++++++++++++++++++++++++ test/Configure/conftest_source_file/SConstruct | 6 +++ test/Configure/conftest_source_file/header1.h | 2 + test/Configure/conftest_source_file/header2.h | 2 + test/Configure/conftest_source_file/main.c | 2 + test/sconsign/script/Configure.py | 4 +- testing/framework/TestSCons.py | 4 +- 11 files changed, 87 insertions(+), 4 deletions(-) create mode 100644 test/Configure/conftest_source_file.py create mode 100644 test/Configure/conftest_source_file/SConstruct create mode 100644 test/Configure/conftest_source_file/header1.h create mode 100644 test/Configure/conftest_source_file/header2.h create mode 100644 test/Configure/conftest_source_file/main.c diff --git a/CHANGES.txt b/CHANGES.txt index 519ced9..d3879d0 100755 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -105,6 +105,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Updated ninja scons daemon scripts to output errors to stderr as well as the daemon log. - Fix typo in ninja scons daemon startup which causes ConnectionRefusedError to not retry to connect to the server during start up. + - Fix for issue #2757, 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. From Mats Wichmann: - Tweak the way default site_scons paths on Windows are expressed to diff --git a/RELEASE.txt b/RELEASE.txt index 5bfee35..3f7d198 100755 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -126,6 +126,8 @@ FIXES - The system environment variable names imported for MSVC 7.0 and 6.0 were updated to be consistent with the variables names defined by their respective installers. This fixes an error caused when bypassing MSVC detection by specifying the MSVC 7.0 batch file directly. +- Fix for issue #2757, 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. IMPROVEMENTS ------------ diff --git a/SCons/SConf.py b/SCons/SConf.py index 4e8d410..dc7ec17 100644 --- a/SCons/SConf.py +++ b/SCons/SConf.py @@ -227,6 +227,8 @@ class SConfBuildTask(SCons.Taskmaster.AlwaysTask): This is almost the same as SCons.Script.BuildTask. Handles SConfErrors correctly and knows about the current cache_mode. """ + sconf_nodes = set() + def display(self, message): if sconf_global.logstream: sconf_global.logstream.write("scons: Configure: " + message + "\n") @@ -376,6 +378,17 @@ class SConfBuildTask(SCons.Taskmaster.AlwaysTask): sconsign.set_entry(t.name, sconsign_entry) sconsign.merge() + def make_ready_current(self): + self.sconf_nodes.update(self.targets) + super().make_ready_current() + make_ready = make_ready_current + + def postprocess(self): + for node in self.sconf_nodes: + if not node.is_conftest(): + node.ninfo = node.new_ninfo() + super().postprocess() + class SConfBase: """This is simply a class to represent a configure context. After creating a SConf object, you can call any tests. After finished with your diff --git a/SCons/SConfTests.py b/SCons/SConfTests.py index a06b227..477226e 100644 --- a/SCons/SConfTests.py +++ b/SCons/SConfTests.py @@ -214,6 +214,8 @@ class SConfTestCase(unittest.TestCase): pass def get_stored_info(self): pass + def is_conftest(self): + return True def get_executor(self): class Executor: def __init__(self, targets): diff --git a/test/Configure/conftest_source_file.py b/test/Configure/conftest_source_file.py new file mode 100644 index 0000000..6f43cb5 --- /dev/null +++ b/test/Configure/conftest_source_file.py @@ -0,0 +1,52 @@ +#!/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. + +""" +Template for end-to-end test file. +Replace this with a description of the test. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.dir_fixture("conftest_source_file") + +test.run(arguments='.') + +test.write('header2.h', """ +#pragma once +int test_header = 2; +""") + +test.not_up_to_date(read_str="Checking for C header file header1.h... (cached) yes\n") + +test.pass_test() + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/test/Configure/conftest_source_file/SConstruct b/test/Configure/conftest_source_file/SConstruct new file mode 100644 index 0000000..72f0522 --- /dev/null +++ b/test/Configure/conftest_source_file/SConstruct @@ -0,0 +1,6 @@ +env = Environment() +env.Append(CPPPATH=['.']) +conf1 = Configure(env) +conf1.CheckHeader("header1.h") +conf1.Finish() +env.Program('out', 'main.c') \ No newline at end of file diff --git a/test/Configure/conftest_source_file/header1.h b/test/Configure/conftest_source_file/header1.h new file mode 100644 index 0000000..85dcd68 --- /dev/null +++ b/test/Configure/conftest_source_file/header1.h @@ -0,0 +1,2 @@ +#pragma once +#include "header2.h" \ No newline at end of file diff --git a/test/Configure/conftest_source_file/header2.h b/test/Configure/conftest_source_file/header2.h new file mode 100644 index 0000000..2cf8e90 --- /dev/null +++ b/test/Configure/conftest_source_file/header2.h @@ -0,0 +1,2 @@ +#pragma once +int test_header = 1; \ No newline at end of file diff --git a/test/Configure/conftest_source_file/main.c b/test/Configure/conftest_source_file/main.c new file mode 100644 index 0000000..a9f9570 --- /dev/null +++ b/test/Configure/conftest_source_file/main.c @@ -0,0 +1,2 @@ +#include "header1.h" +int main(){return 0;} \ No newline at end of file diff --git a/test/sconsign/script/Configure.py b/test/sconsign/script/Configure.py index 02a2c20..7597634 100644 --- a/test/sconsign/script/Configure.py +++ b/test/sconsign/script/Configure.py @@ -84,10 +84,10 @@ conftest_%(sig_re)s_0.c: %(sig_re)s \[.*\] conftest_%(sig_re)s_0_%(sig_re)s%(_obj)s: %(_sconf_temp_conftest_0_c)s: %(sig_re)s \d+ \d+ - %(CC)s: %(sig_re)s \d+ \d+ + %(CC)s: %(sig_re)s None None %(sig_re)s \[.*\] === %(CC_dir)s: -%(CC_file)s: %(sig_re)s \d+ \d+ +%(CC_file)s: None None None """ % locals() # grab .sconsign or .sconsign_ diff --git a/testing/framework/TestSCons.py b/testing/framework/TestSCons.py index ec82102..b8c729e 100644 --- a/testing/framework/TestSCons.py +++ b/testing/framework/TestSCons.py @@ -489,7 +489,7 @@ class TestSCons(TestCommon): kw['match'] = self.match_re_dotall self.run(**kw) - def not_up_to_date(self, arguments='.', **kw): + def not_up_to_date(self, arguments='.', read_str="", **kw): """Asserts that none of the targets listed in arguments is up to date, but does not make any assumptions on other targets. This function is most useful in conjunction with the -n option. @@ -499,7 +499,7 @@ class TestSCons(TestCommon): s = s + "(?!scons: `%s' is up to date.)" % re.escape(arg) s = '(' + s + '[^\n]*\n)*' kw['arguments'] = arguments - stdout = re.escape(self.wrap_stdout(build_str='ARGUMENTSGOHERE')) + stdout = re.escape(self.wrap_stdout(read_str=read_str, build_str='ARGUMENTSGOHERE')) kw['stdout'] = stdout.replace('ARGUMENTSGOHERE', s) kw['match'] = self.match_re_dotall self.run(**kw) -- cgit v0.12 From 59c4623c943b1ec083ed2f1857a1f699d3be9c6a Mon Sep 17 00:00:00 2001 From: Daniel Moody Date: Wed, 25 May 2022 22:45:28 -0500 Subject: update conftest_source_file test to make sure subsequent builds don't rebuild --- test/Configure/conftest_source_file.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/Configure/conftest_source_file.py b/test/Configure/conftest_source_file.py index 6f43cb5..451d06a 100644 --- a/test/Configure/conftest_source_file.py +++ b/test/Configure/conftest_source_file.py @@ -43,6 +43,10 @@ int test_header = 2; test.not_up_to_date(read_str="Checking for C header file header1.h... (cached) yes\n") +test.up_to_date(read_str="Checking for C header file header1.h... yes\n") + +test.up_to_date(read_str="Checking for C header file header1.h... (cached) yes\n") + test.pass_test() # Local Variables: -- cgit v0.12 From 1899835f95765dff0cbb5f3bacbae8095e8975c6 Mon Sep 17 00:00:00 2001 From: Daniel Moody Date: Thu, 26 May 2022 00:28:13 -0500 Subject: update test to test real source with no deps --- test/Configure/conftest_source_file.py | 15 ++++++++++++--- test/Configure/conftest_source_file/SConstruct | 1 + test/Configure/conftest_source_file/header3.h | 2 ++ 3 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 test/Configure/conftest_source_file/header3.h diff --git a/test/Configure/conftest_source_file.py b/test/Configure/conftest_source_file.py index 451d06a..c5c593e 100644 --- a/test/Configure/conftest_source_file.py +++ b/test/Configure/conftest_source_file.py @@ -28,6 +28,8 @@ Template for end-to-end test file. Replace this with a description of the test. """ +import textwrap + import TestSCons test = TestSCons.TestSCons() @@ -36,16 +38,23 @@ test.dir_fixture("conftest_source_file") test.run(arguments='.') +conf_text = textwrap.dedent("""\ + Checking for C header file header1.h... {cached1}yes + Checking for C header file header3.h... {cached3}yes +""") + +test.up_to_date(read_str=conf_text.format(cached1='(cached) ', cached3='(cached) ')) + test.write('header2.h', """ #pragma once int test_header = 2; """) -test.not_up_to_date(read_str="Checking for C header file header1.h... (cached) yes\n") +test.not_up_to_date(read_str=conf_text.format(cached1='(cached) ', cached3='(cached) ')) -test.up_to_date(read_str="Checking for C header file header1.h... yes\n") +test.up_to_date(read_str=conf_text.format(cached1='', cached3='(cached) ')) -test.up_to_date(read_str="Checking for C header file header1.h... (cached) yes\n") +test.up_to_date(read_str=conf_text.format(cached1='(cached) ', cached3='(cached) ')) test.pass_test() diff --git a/test/Configure/conftest_source_file/SConstruct b/test/Configure/conftest_source_file/SConstruct index 72f0522..2e0b672 100644 --- a/test/Configure/conftest_source_file/SConstruct +++ b/test/Configure/conftest_source_file/SConstruct @@ -2,5 +2,6 @@ env = Environment() env.Append(CPPPATH=['.']) conf1 = Configure(env) conf1.CheckHeader("header1.h") +conf1.CheckHeader("header3.h") conf1.Finish() env.Program('out', 'main.c') \ No newline at end of file diff --git a/test/Configure/conftest_source_file/header3.h b/test/Configure/conftest_source_file/header3.h new file mode 100644 index 0000000..dc4359e --- /dev/null +++ b/test/Configure/conftest_source_file/header3.h @@ -0,0 +1,2 @@ +#pragma once +int test_header = 3; \ No newline at end of file -- cgit v0.12 From 78e5ce0c8fa9a7fcc1376fd554565bd80f089815 Mon Sep 17 00:00:00 2001 From: Daniel Moody Date: Thu, 26 May 2022 00:46:12 -0500 Subject: small optimizations --- SCons/SConf.py | 9 ++++----- test/Configure/conftest_source_file.py | 12 ++++++------ 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/SCons/SConf.py b/SCons/SConf.py index dc7ec17..224bf5a 100644 --- a/SCons/SConf.py +++ b/SCons/SConf.py @@ -227,7 +227,7 @@ class SConfBuildTask(SCons.Taskmaster.AlwaysTask): This is almost the same as SCons.Script.BuildTask. Handles SConfErrors correctly and knows about the current cache_mode. """ - sconf_nodes = set() + non_sconf_nodes = set() def display(self, message): if sconf_global.logstream: @@ -379,14 +379,13 @@ class SConfBuildTask(SCons.Taskmaster.AlwaysTask): sconsign.merge() def make_ready_current(self): - self.sconf_nodes.update(self.targets) + self.non_sconf_nodes.update([t for t in self.targets if not t.is_conftest()]) super().make_ready_current() make_ready = make_ready_current def postprocess(self): - for node in self.sconf_nodes: - if not node.is_conftest(): - node.ninfo = node.new_ninfo() + for node in self.non_sconf_nodes: + node.ninfo = node.new_ninfo() super().postprocess() class SConfBase: diff --git a/test/Configure/conftest_source_file.py b/test/Configure/conftest_source_file.py index c5c593e..2e3598c 100644 --- a/test/Configure/conftest_source_file.py +++ b/test/Configure/conftest_source_file.py @@ -39,22 +39,22 @@ test.dir_fixture("conftest_source_file") test.run(arguments='.') conf_text = textwrap.dedent("""\ - Checking for C header file header1.h... {cached1}yes - Checking for C header file header3.h... {cached3}yes + Checking for C header file header1.h... {}yes + Checking for C header file header3.h... (cached) yes """) -test.up_to_date(read_str=conf_text.format(cached1='(cached) ', cached3='(cached) ')) +test.up_to_date(read_str=conf_text.format('(cached) ')) test.write('header2.h', """ #pragma once int test_header = 2; """) -test.not_up_to_date(read_str=conf_text.format(cached1='(cached) ', cached3='(cached) ')) +test.not_up_to_date(read_str=conf_text.format('(cached) ')) -test.up_to_date(read_str=conf_text.format(cached1='', cached3='(cached) ')) +test.up_to_date(read_str=conf_text.format('')) -test.up_to_date(read_str=conf_text.format(cached1='(cached) ', cached3='(cached) ')) +test.up_to_date(read_str=conf_text.format('(cached) ')) test.pass_test() -- cgit v0.12 From 370689946ff4e5e9656b71190f69b502e75c2d8d Mon Sep 17 00:00:00 2001 From: Daniel Moody Date: Thu, 26 May 2022 12:20:47 -0500 Subject: make sure config=force doesn't cause rebuild --- test/Configure/conftest_source_file.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/test/Configure/conftest_source_file.py b/test/Configure/conftest_source_file.py index 2e3598c..879c436 100644 --- a/test/Configure/conftest_source_file.py +++ b/test/Configure/conftest_source_file.py @@ -29,6 +29,7 @@ Replace this with a description of the test. """ import textwrap +import os import TestSCons @@ -39,22 +40,25 @@ test.dir_fixture("conftest_source_file") test.run(arguments='.') conf_text = textwrap.dedent("""\ - Checking for C header file header1.h... {}yes - Checking for C header file header3.h... (cached) yes + Checking for C header file header1.h... {arg1}yes + Checking for C header file header3.h... {arg2}yes """) -test.up_to_date(read_str=conf_text.format('(cached) ')) +test.up_to_date(read_str=conf_text.format(arg1='(cached) ', arg2='(cached) ')) test.write('header2.h', """ #pragma once int test_header = 2; """) -test.not_up_to_date(read_str=conf_text.format('(cached) ')) +test.not_up_to_date(read_str=conf_text.format(arg1='(cached) ', arg2='(cached) ')) -test.up_to_date(read_str=conf_text.format('')) +test.up_to_date(read_str=conf_text.format(arg1='', arg2='(cached) ')) +os.environ['SCONSFLAGS'] = '--config=force' +test.up_to_date(read_str=conf_text.format(arg1='', arg2='')) +os.environ['SCONSFLAGS'] = '' -test.up_to_date(read_str=conf_text.format('(cached) ')) +test.up_to_date(read_str=conf_text.format(arg1='(cached) ', arg2='(cached) ')) test.pass_test() -- cgit v0.12 From e980c5bc26892ce4db1e45516e9983bbc6a2bd33 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 28 Jan 2023 13:38:24 -0800 Subject: Add comments to code and DefaultEnvironment() with no tools loaded for test --- SCons/SConf.py | 9 +++++++++ test/Configure/conftest_source_file/SConstruct | 1 + 2 files changed, 10 insertions(+) diff --git a/SCons/SConf.py b/SCons/SConf.py index 224bf5a..0fd813b 100644 --- a/SCons/SConf.py +++ b/SCons/SConf.py @@ -379,11 +379,20 @@ class SConfBuildTask(SCons.Taskmaster.AlwaysTask): sconsign.merge() def make_ready_current(self): + # We're overriding make_ready_current() call to add to the list + # of nodes used by this task, filtering out any nodes created + # by the checker for it's own purpose. self.non_sconf_nodes.update([t for t in self.targets if not t.is_conftest()]) super().make_ready_current() make_ready = make_ready_current def postprocess(self): + # We're done executing this task, so now we'll go through all the + # nodes used by this task which aren't nodes created for + # Configure checkers, but rather are existing or built files + # and reset their node info. + # If we do not reset their node info, any changes in these + # nodes will not trigger builds in the normal build process for node in self.non_sconf_nodes: node.ninfo = node.new_ninfo() super().postprocess() diff --git a/test/Configure/conftest_source_file/SConstruct b/test/Configure/conftest_source_file/SConstruct index 2e0b672..dd8d28e 100644 --- a/test/Configure/conftest_source_file/SConstruct +++ b/test/Configure/conftest_source_file/SConstruct @@ -1,3 +1,4 @@ +DefaultEnvironment(tools=[]) env = Environment() env.Append(CPPPATH=['.']) conf1 = Configure(env) -- cgit v0.12 From 146e4a0d52d02aab0329a72b51234d85d79d17a2 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 28 Jan 2023 16:52:53 -0800 Subject: [ci skip] Remove duplicated text in CHANGES.txt --- CHANGES.txt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index ce91690..7221d20 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -54,12 +54,6 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER for a specified builder from the CacheDir, fails to do so, and then runs into an error when deleting the files which were retrieved. Previously if this happened there was no errors or warnings. - - Fix for issue #2757, 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. Fix issue where - a Configure() checker uses a source file in their processing, which then - causes SCons to ignore any changes to those source files during the regular build. This - would then prevent SCons from rebuilding any files which depend on those source files from - rebuilding. - Fix issue #2757, where Configure checks that perform a check which reads a modified source (including program, source or header file(s)) would incorrectly mark that file "up to date" so the actual build would not see the file as modified. Leading to incorrect incremental builds. -- cgit v0.12