summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Knight <knight@baldmt.com>2003-10-21 05:17:36 (GMT)
committerSteven Knight <knight@baldmt.com>2003-10-21 05:17:36 (GMT)
commit126c5fee1b33ff06e42659a1f0874697fbd4c080 (patch)
tree16ff259ccaf68ef4255ab4b9105c43b406240072
parentd7b83ed1833bfbf8db7827526ea0967e7d341018 (diff)
downloadSCons-126c5fee1b33ff06e42659a1f0874697fbd4c080.zip
SCons-126c5fee1b33ff06e42659a1f0874697fbd4c080.tar.gz
SCons-126c5fee1b33ff06e42659a1f0874697fbd4c080.tar.bz2
Fix various SConf bugs. (Christoph Wiedemann)
-rw-r--r--src/CHANGES.txt7
-rw-r--r--src/engine/SCons/EnvironmentTests.py3
-rw-r--r--src/engine/SCons/SConf.py35
-rw-r--r--src/engine/SCons/SConfTests.py2
-rw-r--r--src/engine/SCons/Script/SConscript.py6
-rw-r--r--test/Configure.py140
-rw-r--r--test/SConscript.py10
7 files changed, 140 insertions, 63 deletions
diff --git a/src/CHANGES.txt b/src/CHANGES.txt
index 22edc26..b779323 100644
--- a/src/CHANGES.txt
+++ b/src/CHANGES.txt
@@ -168,6 +168,13 @@ RELEASE X.XX - XXX
- Fix a bug in detection of Qt installed on the local system.
+ - Support returning Python 2.3 BooleanType values from Configure checks.
+
+ - Provide an error message if someone mistakenly tries to call a
+ Configure check from within a Builder function.
+
+ - Support calling a Builder when a Configure context is still open.
+
RELEASE 0.92 - Wed, 20 Aug 2003 03:45:28 -0500
diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py
index 2ad0a32..d079feb 100644
--- a/src/engine/SCons/EnvironmentTests.py
+++ b/src/engine/SCons/EnvironmentTests.py
@@ -1443,6 +1443,9 @@ class EnvironmentTestCase(unittest.TestCase):
# Configure() will write to a local temporary file.
test = TestCmd.TestCmd(workdir = '')
save = os.getcwd()
+ # Configure() will test, if we are reading a SConscript file
+ import SCons.Script.SConscript
+ SCons.Script.SConscript.sconscript_reading = 1
try:
os.chdir(test.workpath())
diff --git a/src/engine/SCons/SConf.py b/src/engine/SCons/SConf.py
index 0fbde14..144099f 100644
--- a/src/engine/SCons/SConf.py
+++ b/src/engine/SCons/SConf.py
@@ -33,7 +33,7 @@ import os
import string
import sys
import traceback
-from types import *
+import types
import SCons.Action
import SCons.Builder
@@ -70,6 +70,8 @@ def _stringSource( target, source, env ):
return (target[0].get_path() + ' <- \n |' +
string.replace( env['SCONF_TEXT'], "\n", "\n |" ) )
+BooleanTypes = [types.IntType]
+if hasattr(types, 'BooleanType'): BooleanTypes.append(types.BooleanType)
class SConf:
"""This is simply a class to represent a configure context. After
@@ -92,6 +94,9 @@ class SConf:
Note also the conf_dir and log_file arguments (you may want to
build tests in the BuildDir, not in the SourceDir)
"""
+ import SCons.Script.SConscript
+ if not SCons.Script.SConscript.sconscript_reading:
+ raise SCons.Errors.UserError, "Calling Configure from Builders is not supported."
global SConfFS
if not SConfFS:
SConfFS = SCons.Node.FS.FS(SCons.Node.FS.default_fs.pathTop)
@@ -246,6 +251,9 @@ class SConf:
suff = self.env.subst( builder.builder.suffix )
target = self.confdir.File(pref + f + suff)
self.env['SCONF_TEXT'] = text
+ self.env['PIPE_BUILD'] = 1
+ self.env['PSTDOUT'] = self.logstream
+ self.env['PSTDERR'] = self.logstream
if text != None:
source = self.confdir.File(f + extension)
sourceNode = self.env.SConfSourceBuilder(target=source,
@@ -260,6 +268,10 @@ class SConf:
nodesToBeBuilt.extend(nodes)
ret = self.BuildNodes(nodesToBeBuilt)
+ # clean up environment
+ del self.env['PIPE_BUILD']
+ del self.env['PSTDOUT']
+ del self.env['PSTDERR']
del self.env['SCONF_TEXT']
_ac_build_counter = _ac_build_counter + 1
@@ -440,9 +452,6 @@ class SConf:
# the build system not to override it with a eventually
# existing file with the same name in the source directory
self.logfile.dir.add_ignore( [self.logfile] )
- self.env['PIPE_BUILD'] = 1
- self.env['PSTDOUT'] = self.logstream
- self.env['PSTDERR'] = self.logstream
tb = traceback.extract_stack()[-3]
@@ -471,10 +480,6 @@ class SConf:
if self.logstream != None:
self.logstream.close()
self.logstream = None
- # clean up environment
- del self.env['PIPE_BUILD']
- del self.env['PSTDOUT']
- del self.env['PSTDERR']
# remove the SConfSourceBuilder from the environment
blds = self.env['BUILDERS']
del blds['SConfSourceBuilder']
@@ -529,15 +534,15 @@ class CheckContext:
'failed'.
The result is only displayed when self.did_show_result is not set.
"""
- if type(res) == IntType:
+ if type(res) in BooleanTypes:
if res:
text = "ok"
else:
text = "failed"
- elif type(res) == StringType:
+ elif type(res) == types.StringType:
text = res
else:
- raise TypeError, "Expected string or int"
+ raise TypeError, "Expected string, int or bool, got " + str(type(res))
if self.did_show_result == 0:
if self.cached:
@@ -578,12 +583,12 @@ class CheckContext:
def BuildProg(self, text, ext):
# TODO: should use self.vardict for $CC, $CPPFLAGS, etc.
res = self.TryBuild(self.env.Program, text, ext)
- if type(res) == IntType:
+ if type(res) in BooleanTypes:
if res:
ret = ""
else:
ret = "failed to build test program"
- elif type(res) == StringType:
+ elif type(res) == types.StringType:
ret = res
else:
raise TypeError, "Expected string or int"
@@ -592,12 +597,12 @@ class CheckContext:
def CompileProg(self, text, ext):
# TODO: should use self.vardict for $CC, $CPPFLAGS, etc.
res = self.TryBuild(self.env.Object, text, ext)
- if type(res) == IntType:
+ if type(res) in BooleanTypes:
if res:
ret = ""
else:
ret = "failed to compile test program"
- elif type(res) == StringType:
+ elif type(res) == types.StringType:
ret = res
else:
raise TypeError, "Expected string or int"
diff --git a/src/engine/SCons/SConfTests.py b/src/engine/SCons/SConfTests.py
index 78b27bd..2028c3b 100644
--- a/src/engine/SCons/SConfTests.py
+++ b/src/engine/SCons/SConfTests.py
@@ -64,6 +64,8 @@ class SConfTestCase(unittest.TestCase):
# we only use SCons.Environment and SCons.SConf for these tests.
import SCons.Environment
import SCons.SConf
+ import SCons.Script.SConscript
+ SCons.Script.SConscript.sconscript_reading = 1
self.Environment = SCons.Environment
self.SConf = SCons.SConf
# and we need a new environment, cause references may point to
diff --git a/src/engine/SCons/Script/SConscript.py b/src/engine/SCons/Script/SConscript.py
index 92cd68d..8212061 100644
--- a/src/engine/SCons/Script/SConscript.py
+++ b/src/engine/SCons/Script/SConscript.py
@@ -67,6 +67,9 @@ global_exports = {}
# chdir flag
sconscript_chdir = 1
+# will be set to 1, if we are reading a SConscript
+sconscript_reading = 0
+
def _scons_add_args(alist):
global arguments
for arg in alist:
@@ -139,6 +142,8 @@ def Return(*vars):
stack[-1].retval = tuple(retval)
def _SConscript(fs, *files, **kw):
+ global sconscript_reading
+ sconscript_reading = 1
top = fs.Top
sd = fs.SConstruct_dir.rdir()
exports = kw.get('exports', [])
@@ -215,6 +220,7 @@ def _SConscript(fs, *files, **kw):
f.path)
finally:
+ sconscript_reading = 0
sys.path = old_sys_path
frame = stack.pop()
try:
diff --git a/test/Configure.py b/test/Configure.py
index 9170469..2b134dc 100644
--- a/test/Configure.py
+++ b/test/Configure.py
@@ -40,32 +40,38 @@ else:
# to use cygwin compilers on cmd.exe -> uncomment following line
#lib = 'm'
-oldPwd = os.getcwd()
+work_cnt = 0
+work_dir = None
python = TestSCons.python
-test = None
-
-def reset(dot = 1):
- global test, oldPwd
- os.chdir( oldPwd )
- TestSCons.scons = None
- test = TestSCons.TestSCons()
- if dot == 1:
+test = TestSCons.TestSCons()
+
+
+def reset(match = 1):
+ global test, work_dir, work_cnt
+ work_cnt = work_cnt + 1
+ work_dir='test%d' % work_cnt
+ test.subdir(work_dir)
+ if match == 0:
+ test.match_func = TestCmd.match_re
+ elif match == 1:
test.match_func = TestCmd.match_re_dotall
-
+ elif match == 2:
+ test.match_func = TestCmd.match_exact
def checkFiles(test, files):
+ global work_dir
for f in files:
- test.fail_test( not os.path.isfile( test.workpath(f) ) )
+ test.fail_test( not os.path.isfile( test.workpath(work_dir,f) ) )
def checkLog( test, logfile, numUpToDate, numCache ):
- test.fail_test(not os.path.exists(test.workpath(logfile)))
- log = test.read(test.workpath(logfile))
+ test.fail_test(not os.path.exists(test.workpath(work_dir, logfile)))
+ log = test.read(test.workpath(work_dir, logfile))
try:
test.fail_test( len( re.findall( "is up to date", log ) ) != numUpToDate )
test.fail_test( len( re.findall( "\(cached\): Building \S+ failed in a previous run.", log ) ) != numCache )
except:
- print "contents of log ", test.workpath(logfile), "\n", log
+ print "contents of log ", test.workpath(work_dir, logfile), "\n", log
raise
@@ -73,9 +79,9 @@ try:
# 1.1 if checks are ok, the cache mechanism should work
- reset(dot=0)
+ reset(match=2)
- test.write( 'SConstruct', """
+ test.write([work_dir, 'SConstruct'], """
env = Environment()
import os
env['ENV']['PATH'] = os.environ['PATH']
@@ -102,17 +108,17 @@ Checking for C++ header file vector... yes
""" % (lib, lib))
- test.run(stdout = required_stdout)
+ test.run(chdir=work_dir, stdout = required_stdout)
checkLog(test,'config.log', 0, 0 )
- test.run(stdout = required_stdout)
+ test.run(chdir=work_dir, stdout = required_stdout)
checkLog(test,'config.log',12, 0 )
# 1.2 if checks are not ok, the cache mechanism should work as well
# (via explicit cache)
- reset(dot = 0) # match exactly, "()" is a regexp thing
+ reset(match=2) # match exactly, "()" is a regexp thing
- test.write( 'SConstruct', """
+ test.write([work_dir, 'SConstruct'], """
env = Environment()
import os
env['ENV']['PATH'] = os.environ['PATH']
@@ -132,10 +138,10 @@ Checking for main() in C library no_c_library_SAFFDG... no
""")
- test.run(stdout = required_stdout)
+ test.run(chdir=work_dir, stdout = required_stdout)
checkLog(test, 'config.log', 0, 0 )
- test.run(stdout = required_stdout)
+ test.run(chdir=work_dir, stdout = required_stdout)
checkLog(test, 'config.log', 2, 2 )
@@ -143,7 +149,7 @@ Checking for main() in C library no_c_library_SAFFDG... no
reset()
- test.write( 'SConstruct', """
+ test.write([work_dir, 'SConstruct'], """
env = Environment()
import os
env['ENV']['PATH'] = os.environ['PATH']
@@ -154,11 +160,11 @@ env = conf.Finish()
Export( 'env' )
SConscript( 'SConscript' )
""")
- test.write( 'SConscript', """
+ test.write([work_dir, 'SConscript'], """
Import( 'env' )
env.Program( 'TestProgram', 'TestProgram.c' )
""")
- test.write( 'TestProgram.c', """
+ test.write([work_dir, 'TestProgram.c'], """
#include <stdio.h>
int main() {
@@ -170,10 +176,10 @@ int main() {
"""Checking for C header file math.h... yes
Checking for C header file no_std_c_header.h... no
""")
- test.run( stdout = required_stdout )
+ test.run(chdir=work_dir, stdout = required_stdout )
checkLog( test, 'config.log', 0, 0 )
- test.run( stdout = required_stdout )
+ test.run(chdir=work_dir, stdout = required_stdout )
checkLog( test, 'config.log', 3, 1 )
@@ -181,7 +187,7 @@ Checking for C header file no_std_c_header.h... no
reset()
- test.write( 'SConstruct', """
+ test.write([work_dir, 'SConstruct'], """
env = Environment(LOGFILE='build/config.log')
import os
env['ENV']['PATH'] = os.environ['PATH']
@@ -194,11 +200,11 @@ Export( 'env' )
# print open( 'build/config.log' ).readlines()
SConscript( 'build/SConscript' )
""")
- test.write( 'SConscript', """
+ test.write([work_dir, 'SConscript'], """
Import( 'env' )
env.Program( 'TestProgram', 'TestProgram.c' )
""")
- test.write( 'TestProgram.c', """
+ test.write([work_dir, 'TestProgram.c'], """
#include <stdio.h>
int main() {
@@ -210,18 +216,18 @@ int main() {
"""Checking for C header file math.h... yes
Checking for C header file no_std_c_header.h... no
""")
- test.run( stdout = required_stdout )
+ test.run(chdir=work_dir, stdout = required_stdout )
checkLog( test, 'build/config.log', 0, 0 )
- test.run( stdout = required_stdout )
+ test.run(chdir=work_dir, stdout = required_stdout )
checkLog( test, 'build/config.log', 3, 1 )
# 2.3 test that Configure calls in SConscript files work
# even if BuildDir is set
reset()
- test.subdir( 'sub', ['sub', 'local'] )
- test.write( 'SConstruct', """
+ test.subdir( [work_dir, 'sub'], [work_dir, 'sub', 'local'] )
+ test.write([work_dir, 'SConstruct'], """
opts = Options()
opts.Add('chdir')
env = Environment(options=opts)
@@ -232,11 +238,12 @@ else:
BuildDir( 'build', '.' )
SConscript( 'build/SConscript' )
""")
- test.write( 'sub/local/local_header.h', "/* Hello World */" )
- test.write( 'SConscript', """
+ test.write([work_dir, 'sub', 'local', 'local_header.h'],
+ "/* Hello World */" )
+ test.write([work_dir, 'SConscript'], """
SConscript( 'sub/SConscript' )
""")
- test.write( 'sub/SConscript', """
+ test.write([work_dir, 'sub', 'SConscript'], """
def CustomTest(context):
context.Message('Executing Custom Test ... ')
ret = context.TryCompile('#include "local_header.h"', '.c')
@@ -261,10 +268,10 @@ if not conf.CustomTest():
env = conf.Finish()
env.Program( 'TestProgram', 'TestProgram.c' )
""")
- test.write( 'sub/TestProgram.h', """
+ test.write([work_dir, 'sub', 'TestProgram.h'], """
/* Just a test header */
""")
- test.write( 'sub/TestProgram.c', """
+ test.write([work_dir, 'sub', 'TestProgram.c'], """
#include "TestProgram.h"
#include <stdio.h>
@@ -279,22 +286,22 @@ Checking for C header file no_std_c_header.h... no
Executing Custom Test ... ok
""")
# first with SConscriptChdir(0)
- test.run(stdout = required_stdout, arguments='chdir=no')
+ test.run(chdir=work_dir, stdout = required_stdout, arguments='chdir=no')
checkFiles( test, [".sconf_temp/.cache", "config.log"] )
checkLog( test, 'config.log', 0, 0 )
- test.run(stdout = required_stdout, arguments='chdir=no')
+ test.run(chdir=work_dir, stdout = required_stdout, arguments='chdir=no')
checkFiles( test, [".sconf_temp/.cache", "config.log"] )
checkLog( test, 'config.log', 5, 1 )
- shutil.rmtree(test.workpath(".sconf_temp"))
+ shutil.rmtree(test.workpath(work_dir, ".sconf_temp"))
# now with SConscriptChdir(1)
- test.run(stdout = required_stdout, arguments='chdir=yes')
+ test.run(chdir=work_dir, stdout = required_stdout, arguments='chdir=yes')
checkFiles( test, [".sconf_temp/.cache", "config.log"] )
checkLog( test, 'config.log', 0, 0 )
- test.run(stdout = required_stdout, arguments='chdir=yes')
+ test.run(chdir=work_dir, stdout = required_stdout, arguments='chdir=yes')
checkFiles( test, [".sconf_temp/.cache", "config.log"] )
checkLog( test, 'config.log', 5, 1 )
@@ -307,8 +314,8 @@ Executing Custom Test ... ok
linkFAIL = "void myFunc(); int main() { myFunc(); }"
runOK = compileOK
runFAIL = "int main() { return 1; }"
- test.write('pyAct.py', 'import sys\nprint sys.argv[1]\nsys.exit(int(sys.argv[1]))\n')
- test.write('SConstruct', """
+ test.write([work_dir, 'pyAct.py'], 'import sys\nprint sys.argv[1]\nsys.exit(int(sys.argv[1]))\n')
+ test.write([work_dir, 'SConstruct'], """
def CheckCustom(test):
test.Message( 'Executing MyTest ... ' )
retCompileOK = test.TryCompile( '%s', '.c' )
@@ -336,12 +343,49 @@ env = conf.Finish()
python, python ) )
required_stdout = test.wrap_stdout(build_str='.*',
read_str="Executing MyTest ... ok\n")
- test.run(stdout = required_stdout)
+ test.run(chdir=work_dir, stdout = required_stdout)
checkLog( test, 'config.log', 0, 0 )
- test.run(stdout = required_stdout)
+ test.run(chdir=work_dir, stdout = required_stdout)
checkLog( test, 'config.log', 12, 4 )
+ # 4.1 test that calling normal builders from an actual configuring
+ # environment works
+ reset()
+
+ test.write([work_dir, 'cmd.py'], r"""
+import sys
+sys.stderr.write( 'Hello World on stderr\n' )
+sys.stdout.write( 'Hello World on stdout\n' )
+open(sys.argv[1], 'w').write( 'Hello World\n' )
+""")
+
+ test.write([work_dir, 'SConstruct'], """
+env = Environment()
+def CustomTest(*args):
+ return 0
+conf = env.Configure(custom_tests = {'MyTest' : CustomTest})
+if not conf.MyTest():
+ env.Command("hello", [], "%s cmd.py $TARGET")
+env = conf.Finish()
+""" % python)
+ test.run(chdir=work_dir, stderr="Hello World on stderr\n")
+
+ # 4.2 test that calling Configure from a builder results in a
+ # readable Error
+ reset(match=2)
+
+ test.write([work_dir, 'SConstruct'], """
+def ConfigureAction(target, source, env):
+ env.Configure()
+ return 0
+env = Environment(BUILDERS = {'MyAction' :
+ Builder(action=Action(ConfigureAction))})
+env.MyAction('target', [])
+""")
+ test.run(chdir=work_dir, status=2,
+ stderr="scons: *** Calling Configure from Builders is not supported.\n")
+
test.pass_test()
finally:
diff --git a/test/SConscript.py b/test/SConscript.py
index d889c44..69b7a82 100644
--- a/test/SConscript.py
+++ b/test/SConscript.py
@@ -384,4 +384,14 @@ test.run(arguments = ".",
stdout = test.wrap_stdout(read_str = "SConstruct\nsub/SConscript\nx = xxx\n",
build_str = "scons: `.' is up to date.\n"))
+test.write("SConstruct", """\
+def builder(target, source, env):
+ import SCons.Script.SConscript
+ assert SCons.Script.SConscript.sconscript_reading == 0
+env = Environment(BUILDERS={'builder':Builder(action=builder)})
+env.builder('test',[])
+import SCons.Script.SConscript
+assert SCons.Script.SConscript.sconscript_reading == 1
+""")
+
test.pass_test()