RELEASE 0.15 - XXX
+ From Chad Austin:
+
+ - Fix the _concat() documentation, and add a test for it.
+
+ - Portability fixes for non-GNU versions of lex and yacc.
+
From Matt Balvin:
- Fix handling of library prefixes when the subdirectory matches
the prefix.
+ From Timothee Bessett:
+
+ - Add an M4 Builder.
+
From Charles Crain:
- Use '.lnk' as the suffix on the temporary file for linking long
command lines (necessary for the Phar Lap linkloc linker).
+ - Save non-string Options values as their actual type.
+
+ - Save Options string values that contain a single quote correctly.
+
+ - Save any Options values that are changed from the default
+ Environment values, not just ones changed on the command line or in
+ an Options file.
+
+ - Make closing the Options file descriptor exception-safe.
+
From Steven Knight:
- SCons now enforces (with an error) that construction variables
must have the same form as valid Python identifiers.
- Fix man page bugs: remove duplicate AddPostAction() description;
- document no_import_lib.
+ document no_import_lib; mention that CPPFLAGS does not contain
+ $_CPPINCFLAGS; mention that F77FLAGS does not contain $_F77INCFLAGS;
+ mention that LINKFLAGS and SHLINKFLAGS contains neither $_LIBFLAGS
+ nor $_LIBDIRFLAGS.
- Eliminate a dependency on the distutils.fancy_getopt module by
copying and pasting its wrap_text() function directly.
+ - Make the Script.Options() subclass match the underlying base class
+ implementation.
+
From Steve Leblanc:
- Don't update the .sconsign files when run with -n.
+ From Gary Oberbrunner:
+
+ - Add support for the Intel C Compiler (icl.exe).
+
+ From Anthony Roach
+
+ - Fix Import('*').
+
+ From David Snopek
+
+ - Fix use of SConf in paths with white space in them.
+
+ - Add CheckFunc and CheckType functionality to SConf.
+
+ - Fix use of SConf with Builders that return a list of nodes.
+
From David Snopek and Christoph Wiedemann
- Fix use of the SConf subsystem with SConscriptChdir().
+ From Greg Spencer
+
+ - Check for the existence of MS Visual Studio on disk before using it,
+ to avoid getting fooled by leftover junk in the registry.
+
+ - Add support for MSVC++ .NET.
+
+ - Add support for MS Visual Studio project files (DSP, DSW,
+ SLN and VCPROJ files).
+
RELEASE 0.14 - Wed, 21 May 2003 05:16:32 -0500
option.default = default
option.validater = validater
option.converter = converter
- option.should_save = 0
self.options.append(option)
if args is None:
args = self.args
values.update(args)
-
- # Update should save state.
- # This will mark options that have either been set on
- # the command line or in a loaded option file.
- # KeyError occurs when an option has default of None
- # and has not been set.
- for option in self.options:
- try:
- if values[option.key] != option.default:
- option.should_save = 1
- except KeyError:
- pass
# put the variables in the environment:
# (don't copy over variables that are not declared
# Call the convert functions:
for option in self.options:
- if option.converter:
+ if option.converter and values.has_key(option.key):
value = env.subst('${%s}'%option.key)
try:
env[option.key] = option.converter(value)
for option in self.options:
if option.validater:
option.validater(option.key, env.subst('${%s}'%option.key), env)
-
-
def Save(self, filename, env):
"""
try:
fh = open(filename, 'w')
- # Make an assignment in the file for each option within the environment
- # that was assigned a value other than the default.
- for option in self.options:
- try:
- value = env[option.key]
- if option.should_save:
- fh.write('%s = \'%s\'\n' % (option.key, value))
- except KeyError:
- pass
-
- fh.close()
+ try:
+ # Make an assignment in the file for each option within the environment
+ # that was assigned a value other than the default.
+ for option in self.options:
+ try:
+ value = env[option.key]
+ try:
+ eval(repr(value))
+ except:
+ # Convert stuff that has a repr() that
+ # cannot be evaluated into a string
+ value = SCons.Util.to_String(value)
+ if env.subst('${%s}' % option.key) != \
+ env.subst(SCons.Util.to_String(option.default)):
+ fh.write('%s = %s\n' % (option.key, repr(value)))
+ except KeyError:
+ pass
+ finally:
+ fh.close()
except IOError, x:
raise SCons.Errors.UserError, 'Error writing options to file: %s\n%s' % (filename, x)
import unittest
import TestSCons
import SCons.Options
+import SCons.Util
import sys
import string
def __init__(self):
self.dict = {}
def subst(self, x):
- return self.dict[x[2:-1]]
+ return SCons.Util.scons_subst(x, self)
def __setitem__(self, key, value):
self.dict[key] = value
def __getitem__(self, key):
return self.dict[key]
def has_key(self, key):
return self.dict.has_key(key)
+ def Dictionary(self):
+ return self.dict
def check(key, value, env):
- assert value == 6 * 9, "key %s = %s" % (key, value)
+ assert int(value) == 6 * 9, "key %s = %s" % (key, repr(value))
# Check saved option file by executing and comparing against
# the expected dictionary
gdict = {}
ldict = {}
execfile(file, gdict, ldict)
- assert expected == ldict
+ assert expected == ldict, "%s\n...not equal to...\n%s" % (expected, ldict)
class OptionsTestCase(unittest.TestCase):
def test_Add(self):
assert o.default == None
assert o.validater == None
assert o.converter == None
- assert o.should_save == 0
o = opts.options[1]
assert o.key == 'ANSWER'
opts.Update(env, {'ANSWER':'42'})
assert env['ANSWER'] == 54
+ # Test against a former bug. If we supply a converter,
+ # but no default, the value should *not* appear in the
+ # Environment if no value is specified in the options file
+ # or args.
+ test = TestSCons.TestSCons()
+ file = test.workpath('custom.py')
+ opts = SCons.Options.Options(file)
+
+ opts.Add('ANSWER',
+ help='THE answer to THE question',
+ converter=str)
+
+ env = Environment()
+ opts.Update(env, {})
+ assert not env.has_key('ANSWER')
+
def test_args(self):
"""Test updating an Environment with arguments overridden"""
21,
None,
None)
+ opts.Add('OPT_VAL_2',
+ default='foo')
+ opts.Add('OPT_VAL_3',
+ default=1)
env = Environment()
- opts.Update(env, {})
+ opts.Update(env, {'OPT_VAL_3' : 2})
assert env['OPT_VAL'] == 21
+ assert env['OPT_VAL_2'] == 'foo'
+ assert env['OPT_VAL_3'] == 2
+ env['OPT_VAL_2'] = 'bar'
opts.Save(cache_file, env)
- checkSave(cache_file, {})
+ checkSave(cache_file, { 'OPT_VAL_2' : 'bar',
+ 'OPT_VAL_3' : 2 })
+
+ # Test against some old bugs
+ class Foo:
+ def __init__(self, x):
+ self.x = x
+ def __str__(self):
+ return self.x
+
+ test = TestSCons.TestSCons()
+ cache_file = test.workpath('cached.options')
+ opts = SCons.Options.Options()
+
+ opts.Add('THIS_USED_TO_BREAK',
+ 'An option to test',
+ "Default")
+ opts.Add('THIS_ALSO_BROKE',
+ 'An option to test',
+ "Default2")
+
+ opts.Add('THIS_SHOULD_WORK',
+ 'An option to test',
+ Foo('bar'))
+
+ env = Environment()
+ opts.Update(env, { 'THIS_USED_TO_BREAK' : "Single'Quotes'In'String",
+ 'THIS_ALSO_BROKE' : "\\Escape\nSequences\t",
+ 'THIS_SHOULD_WORK' : Foo('baz') })
+ opts.Save(cache_file, env)
+ checkSave(cache_file, { 'THIS_USED_TO_BREAK' : "Single'Quotes'In'String",
+ 'THIS_ALSO_BROKE' : "\\Escape\nSequences\t",
+ 'THIS_SHOULD_WORK' : 'baz' })
def test_GenerateHelpText(self):
opts = SCons.Options.Options()
gdict = {}
ldict = {}
execfile(file, gdict, ldict)
- assert expected == ldict
+ assert expected == ldict, "%s\n...not equal to...\n%s" % (expected, ldict)
# First test with no command line options
# This should just leave the custom.py settings
test.run()
check(['1','0'])
-checkSave('options.saved', { 'RELEASE_BUILD':'1', 'DEBUG_BUILD':'0'})
+checkSave('options.saved', { 'RELEASE_BUILD':1, 'DEBUG_BUILD':0})
# Override with command line arguments
test.run(arguments='"DEBUG_BUILD=3"')
check(['1','3'])
-checkSave('options.saved', {'RELEASE_BUILD':'1', 'DEBUG_BUILD':'3'})
+checkSave('options.saved', {'RELEASE_BUILD':1, 'DEBUG_BUILD':3})
# Now make sure that saved options are overridding the custom.py
test.run()
check(['1','3'])
-checkSave('options.saved', {'DEBUG_BUILD':'3', 'RELEASE_BUILD':'1'})
+checkSave('options.saved', {'DEBUG_BUILD':3, 'RELEASE_BUILD':1})
# Load no options from file(s)
# Used to test for correct output in save option file
# Now specify same option non-default and make sure only it is written out
test.run(arguments='"DEBUG_BUILD=0"')
check(['0','0'])
-checkSave('options.saved',{'DEBUG_BUILD':'0'})
+checkSave('options.saved',{'DEBUG_BUILD':0})
test.write('SConstruct', """
opts = Options('custom.py')