diff options
author | Steven Knight <knight@baldmt.com> | 2003-06-12 15:28:38 (GMT) |
---|---|---|
committer | Steven Knight <knight@baldmt.com> | 2003-06-12 15:28:38 (GMT) |
commit | 823ab5a50f9856308ee9559f968d62409ad625da (patch) | |
tree | c24bc193f5a9acbceed0bb58b44768355f3ee945 | |
parent | 6c11c2362e17142f384a914d821d0e0cd021ecd2 (diff) | |
download | SCons-823ab5a50f9856308ee9559f968d62409ad625da.zip SCons-823ab5a50f9856308ee9559f968d62409ad625da.tar.gz SCons-823ab5a50f9856308ee9559f968d62409ad625da.tar.bz2 |
Raise an error if SConf needs to do something but -n or -q is specified. (Christoph Wiedemann)
-rw-r--r-- | src/engine/SCons/Errors.py | 6 | ||||
-rw-r--r-- | src/engine/SCons/ErrorsTests.py | 6 | ||||
-rw-r--r-- | src/engine/SCons/SConf.py | 39 | ||||
-rw-r--r-- | src/engine/SCons/Script/__init__.py | 6 | ||||
-rw-r--r-- | test/option-n.py | 76 | ||||
-rw-r--r-- | test/option-q.py | 80 |
6 files changed, 206 insertions, 7 deletions
diff --git a/src/engine/SCons/Errors.py b/src/engine/SCons/Errors.py index 9743674..cc8bb3d 100644 --- a/src/engine/SCons/Errors.py +++ b/src/engine/SCons/Errors.py @@ -55,3 +55,9 @@ class ExplicitExit(Exception): self.node = node self.status = status self.args = args + +class ConfigureDryRunError(UserError): + """Raised when a file needs to be updated during a Configure process, + but the user requested a dry-run""" + def __init__(self,file): + UserError.__init__(self,"Cannot update configure test (%s) within a dry-run." % str(file)) diff --git a/src/engine/SCons/ErrorsTests.py b/src/engine/SCons/ErrorsTests.py index b128026..810f840 100644 --- a/src/engine/SCons/ErrorsTests.py +++ b/src/engine/SCons/ErrorsTests.py @@ -58,6 +58,12 @@ class ErrorsTestCase(unittest.TestCase): except SCons.Errors.ExplicitExit, e: assert e.node == "node" + def test_ConfigureDryRunError(self): + """Test the ConfigureDryRunError.""" + try: + raise SCons.Errors.ConfigureDryRunError, "FileName" + except SCons.Errors.UserError, e: + assert e.args == "Cannot update configure test (FileName) within a dry-run." if __name__ == "__main__": diff --git a/src/engine/SCons/SConf.py b/src/engine/SCons/SConf.py index 7336cde..b62dabf 100644 --- a/src/engine/SCons/SConf.py +++ b/src/engine/SCons/SConf.py @@ -47,6 +47,9 @@ import SCons.Warnings # but it showed up that there are too many side effects in doing that. SConfFS=SCons.Node.FS.default_fs +# to be set, if we are in dry-run mode +dryrun = 0 + _ac_build_counter = 0 _ac_config_counter = 0 _activeSConfObjects = {} @@ -159,6 +162,22 @@ class SConf: def do_failed(self, status=2): pass + class SConfDryRunTask(SConfBuildTask): + """Raise ConfiugreDryRunErrors whenever a target is to + be built. Pass these Errors to the main script.""" + def execute(self): + target = self.targets[0] + if (target.get_state() != SCons.Node.up_to_date and + target.has_builder() and + not hasattr(target.builder, 'status')): + + raise SCons.Errors.ConfigureDryRunError(target) + + def failed(self): + if sys.exc_type == SCons.Errors.ConfigureDryRunError: + raise + SConfBuildTask.failed(self) + if self.logstream != None: # override stdout / stderr to write in log file oldStdout = sys.stdout @@ -176,8 +195,12 @@ class SConf: try: # ToDo: use user options for calc self.calc = SCons.Sig.Calculator(max_drift=0) + if dryrun: + buildTask = SConfDryRunTask + else: + buildTask = SConfBuildTask tm = SCons.Taskmaster.Taskmaster( nodes, - SConfBuildTask, + buildTask, self.calc ) # we don't want to build tests in parallel jobs = SCons.Job.Jobs(1, tm ) @@ -365,6 +388,8 @@ class SConf: self.cache = {} def _dumpCache(self): + if dryrun: + return # try to dump build-error cache try: cacheDesc = {'scons_version' : SCons.__version__, @@ -377,9 +402,13 @@ class SConf: def _createDir( self, node ): dirName = node.get_path() - if not os.path.isdir( dirName ): - os.makedirs( dirName ) - node._exists = 1 + if dryrun: + if not os.path.isdir( dirName ): + raise SCons.Errors.ConfigureDryRunError(dirName) + else: + if not os.path.isdir( dirName ): + os.makedirs( dirName ) + node._exists = 1 def _startup(self): """Private method. Set up logstream, and set the environment @@ -394,7 +423,7 @@ class SConf: self._createDir(self.confdir) self.confdir.up().add_ignore( [self.confdir] ) - if self.logfile != None: + if self.logfile != None and not dryrun: # truncate logfile, if SConf.Configure is called for the first time # in a build if _ac_config_counter == 0: diff --git a/src/engine/SCons/Script/__init__.py b/src/engine/SCons/Script/__init__.py index 1c773f0..139d296 100644 --- a/src/engine/SCons/Script/__init__.py +++ b/src/engine/SCons/Script/__init__.py @@ -723,8 +723,12 @@ def _main(): if options.warn: _setup_warn(options.warn) if options.noexec: + SCons.SConf.dryrun = 1 SCons.Action.execute_actions = None CleanTask.execute = CleanTask.show + if options.question: + SCons.SConf.dryrun = 1 + if options.no_progress or options.silent: display.set_mode(0) if options.silent: @@ -977,6 +981,8 @@ def main(): _scons_syntax_error(e) except SCons.Errors.UserError, e: _scons_user_error(e) + except SCons.Errors.ConfigureDryRunError, e: + _scons_configure_dryrun_error(e) except: _scons_other_errors() diff --git a/test/option-n.py b/test/option-n.py index bccb785..86f4c3a 100644 --- a/test/option-n.py +++ b/test/option-n.py @@ -32,13 +32,18 @@ This test verifies: installed when -n is used; 4) that source files don't get duplicated in a BuildDir when -n is used. + 5) that Configure calls don't build any files. If a file + needs to be build (i.e. is not up-to-date), a ConfigureError + is raised. """ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" +import os import os.path import string import sys +import TestCmd import TestSCons python = TestSCons.python @@ -155,5 +160,74 @@ test.fail_test(not os.path.exists(test.workpath('install', 'f3.in'))) test.run(arguments = '-n build') test.fail_test(os.path.exists(test.workpath('build', 'f4.in'))) -test.pass_test() +# test Configure-calls in conjunction with -n +test.subdir('configure') +test.match_func = TestCmd.match_re_dotall +test.write('configure/SConstruct', +"""def CustomTest(context): + def userAction(target,source,env): + import shutil + shutil.copyfile( str(source[0]), str(target[0])) + def strAction(target,source,env): + return "cp " + str(source[0]) + " " + str(target[0]) + context.Message("Executing Custom Test ... " ) + (ok, msg) = context.TryAction(Action(userAction,strAction), + "Hello World", ".in") + context.Result(ok) + return ok + +env = Environment() +conf = Configure( env, + custom_tests={'CustomTest':CustomTest}, + conf_dir="config.test", + log_file="config.log" ) +if not conf.CustomTest(): + Exit(1) +else: + env = conf.Finish() +""") +# test that conf_dir isn't created and an error is raised +stderr=r""" +scons: \*\*\* Cannot update configure test \(config\.test\) within a dry-run\. +File \S+, line \S+, in \S+ +""" +test.run(arguments="-n",stderr=stderr,status=2, + chdir=test.workpath("configure")) +test.fail_test(os.path.exists(test.workpath("configure", "config.test"))) +test.fail_test(os.path.exists(test.workpath("configure", "config.log"))) + +# test that targets are not built, if conf_dir exists. +# verify that .cache and config.log are not created. +# an error should be raised +stderr=r""" +scons: \*\*\* Cannot update configure test \(config\.test.conftest_0\.in\) within a dry-run\. +File \S+, line \S+, in \S+ +""" +test.subdir(['configure','config.test']) +test.run(arguments="-n",stderr=stderr,status=2, + chdir=test.workpath("configure")) +test.fail_test(os.path.exists(test.workpath("configure", "config.test", + ".cache"))) +test.fail_test(os.path.exists(test.workpath("configure", "config.test", + "conftest_0"))) +test.fail_test(os.path.exists(test.workpath("configure", "config.test", + "conftest_0.in"))) +test.fail_test(os.path.exists(test.workpath("configure", "config.log"))) + +# test that no error is raised, if all targets are up-to-date. In this +# case .cache and config.log shouldn't be created +stdout=test.wrap_stdout(build_str='scons: "." is up to date.\n', + read_str="""\ +Executing Custom Test ... ok +""") +test.run(status=0,chdir=test.workpath("configure")) +cache1_mtime = os.path.getmtime(test.workpath("configure","config.test",".cache")) +log1_mtime = os.path.getmtime(test.workpath("configure","config.log")) +test.run(stdout=stdout,arguments="-n",status=0, + chdir=test.workpath("configure")) +cache2_mtime = os.path.getmtime(test.workpath("configure","config.test",".cache")) +log2_mtime = os.path.getmtime(test.workpath("configure","config.log")) +test.fail_test( cache1_mtime != cache2_mtime ) +test.fail_test( log1_mtime != log2_mtime ) +test.pass_test() diff --git a/test/option-q.py b/test/option-q.py index e745760..449d5eb 100644 --- a/test/option-q.py +++ b/test/option-q.py @@ -28,6 +28,7 @@ import os.path import string import sys +import TestCmd import TestSCons test = TestSCons.TestSCons() @@ -72,5 +73,82 @@ test.fail_test(test.read('bbb.out') != "bbb.in\n") test.run(arguments = '--question bbb.out', status = 0) + +# test -q in conjunction with Configure Tests +# mostly copy&paste from test/option-n.py +test.subdir('configure') +test.match_func = TestCmd.match_re_dotall +test.write('configure/aaa.in', 'Hello world') +test.write('configure/SConstruct', +"""def userAction(target,source,env): + import shutil + shutil.copyfile( str(source[0]), str(target[0])) + +def strAction(target,source,env): + return "cp " + str(source[0]) + " " + str(target[0]) + +def CustomTest(context): + context.Message("Executing Custom Test ... " ) + (ok, msg) = context.TryAction(Action(userAction,strAction), + "Hello World", ".in") + context.Result(ok) + return ok + +env = Environment(BUILDERS={'B' : Builder(action=Action(userAction,strAction))}) + +conf = Configure( env, + custom_tests={'CustomTest':CustomTest}, + conf_dir="config.test", + log_file="config.log") +if not conf.CustomTest(): + Exit(1) +else: + env = conf.Finish() + +env.B(target='aaa.out', source='aaa.in') +""") +# test that conf_dir isn't created and an error is raised +stderr=r""" +scons: \*\*\* Cannot update configure test \(config\.test\) within a dry-run\. +File \S+, line \S+, in \S+ +""" +test.run(arguments="-q aaa.out",stderr=stderr,status=2, + chdir=test.workpath("configure")) +test.fail_test(os.path.exists(test.workpath("configure", "config.test"))) +test.fail_test(os.path.exists(test.workpath("configure", "config.log"))) + +# test that targets are not built, if conf_dir exists. +# verify that .cache and config.log are not created. +# an error should be raised +stderr=r""" +scons: \*\*\* Cannot update configure test \(config\.test.conftest_0\.in\) within a dry-run\. +File \S+, line \S+, in \S+ +""" +test.subdir(['configure','config.test']) +test.run(arguments="-q aaa.out",stderr=stderr,status=2, + chdir=test.workpath("configure")) +test.fail_test(os.path.exists(test.workpath("configure", "config.test", + ".cache"))) +test.fail_test(os.path.exists(test.workpath("configure", "config.test", + "conftest_0"))) +test.fail_test(os.path.exists(test.workpath("configure", "config.test", + "conftest_0.in"))) +test.fail_test(os.path.exists(test.workpath("configure", "config.log"))) + +# test that no error is raised, if all targets are up-to-date. In this +# case .cache and config.log shouldn't be created +stdout=test.wrap_stdout(build_str='cp aaa.in aaa.out\n', + read_str="""\ +Executing Custom Test ... ok +""") +test.run(stdout=stdout,arguments="aaa.out",status=0,chdir=test.workpath("configure")) +cache1_mtime = os.path.getmtime(test.workpath("configure","config.test",".cache")) +log1_mtime = os.path.getmtime(test.workpath("configure","config.log")) +test.run(arguments="-q aaa.out",status=0, + chdir=test.workpath("configure")) +cache2_mtime = os.path.getmtime(test.workpath("configure","config.test",".cache")) +log2_mtime = os.path.getmtime(test.workpath("configure","config.log")) +test.fail_test( cache1_mtime != cache2_mtime ) +test.fail_test( log1_mtime != log2_mtime ) + test.pass_test() - |