1 """engine.SCons.Variables
3 This file defines the Variables class that is used to add user-friendly
4 customizable variables to an SCons build.
8 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
10 # Permission is hereby granted, free of charge, to any person obtaining
11 # a copy of this software and associated documentation files (the
12 # "Software"), to deal in the Software without restriction, including
13 # without limitation the rights to use, copy, modify, merge, publish,
14 # distribute, sublicense, and/or sell copies of the Software, and to
15 # permit persons to whom the Software is furnished to do so, subject to
16 # the following conditions:
18 # The above copyright notice and this permission notice shall be included
19 # in all copies or substantial portions of the Software.
21 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
22 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
23 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 __revision__ = "src/engine/SCons/Variables/__init__.py 3842 2008/12/20 22:59:52 scons"
36 import SCons.Environment
41 from BoolVariable import BoolVariable # okay
42 from EnumVariable import EnumVariable # okay
43 from ListVariable import ListVariable # naja
44 from PackageVariable import PackageVariable # naja
45 from PathVariable import PathVariable # okay
52 Holds all the options, updates the environment with the variables,
53 and renders the help text.
55 def __init__(self, files=[], args={}, is_global=1):
57 files - [optional] List of option configuration files to load
58 (backward compatibility) If a single string is passed it is
59 automatically placed in a file list
63 if not SCons.Util.is_List(files):
71 # create the singleton instance
73 self=Variables.instance
75 if not Variables.instance:
76 Variables.instance=self
78 def _do_add(self, key, help="", default=None, validator=None, converter=None):
84 # if we get a list or a tuple, we take the first element as the
85 # option key and store the remaining in aliases.
86 if SCons.Util.is_List(key) or SCons.Util.is_Tuple(key):
88 option.aliases = key[1:]
91 option.aliases = [ key ]
93 option.default = default
94 option.validator = validator
95 option.converter = converter
97 self.options.append(option)
101 Returns the keywords for the options
103 return map(lambda o: o.key, self.options)
105 def Add(self, key, help="", default=None, validator=None, converter=None, **kw):
109 key - the name of the variable, or a list or tuple of arguments
110 help - optional help text for the options
111 default - optional default value
112 validator - optional function that is called to validate the option's value
113 Called with (key, value, environment)
114 converter - optional function that is called to convert the option's value before
115 putting it in the environment.
118 if SCons.Util.is_List(key) or type(key) == type(()):
119 apply(self._do_add, key)
122 if not SCons.Util.is_String(key) or \
123 not SCons.Environment.is_valid_construction_var(key):
124 raise SCons.Errors.UserError, "Illegal Variables.Add() key `%s'" % str(key)
126 self._do_add(key, help, default, validator, converter)
128 def AddVariables(self, *optlist):
130 Add a list of options.
132 Each list element is a tuple/list of arguments to be passed on
133 to the underlying method for adding options.
138 ('CC', 'The C compiler'),
139 ('VALIDATE', 'An option for testing validation', 'notset',
144 apply(self._do_add, o)
147 def Update(self, env, args=None):
149 Update an environment with the option variables.
151 env - the environment to update.
156 # first set the defaults:
157 for option in self.options:
158 if not option.default is None:
159 values[option.key] = option.default
161 # next set the value specified in the options file
162 for filename in self.files:
163 if os.path.exists(filename):
164 dir = os.path.split(os.path.abspath(filename))[0]
166 sys.path.insert(0, dir)
168 values['__name__'] = filename
169 execfile(filename, {}, values)
173 del values['__name__']
175 # set the values specified on the command line
179 for arg, value in args.items():
181 for option in self.options:
182 if arg in option.aliases + [ option.key ]:
183 values[option.key] = value
186 self.unknown[arg] = value
188 # put the variables in the environment:
189 # (don't copy over variables that are not declared as options)
190 for option in self.options:
192 env[option.key] = values[option.key]
196 # Call the convert functions:
197 for option in self.options:
198 if option.converter and values.has_key(option.key):
199 value = env.subst('${%s}'%option.key)
202 env[option.key] = option.converter(value)
204 env[option.key] = option.converter(value, env)
205 except ValueError, x:
206 raise SCons.Errors.UserError, 'Error converting option: %s\n%s'%(option.key, x)
209 # Finally validate the values:
210 for option in self.options:
211 if option.validator and values.has_key(option.key):
212 option.validator(option.key, env.subst('${%s}'%option.key), env)
214 def UnknownVariables(self):
216 Returns any options in the specified arguments lists that
217 were not known, declared options in this object.
221 def Save(self, filename, env):
223 Saves all the options in the given file. This file can
224 then be used to load the options next run. This can be used
225 to create an option cache file.
227 filename - Name of the file to save into
228 env - the environment get the option values from
231 # Create the file and write out the header
233 fh = open(filename, 'w')
236 # Make an assignment in the file for each option
237 # within the environment that was assigned a value
238 # other than the default.
239 for option in self.options:
241 value = env[option.key]
243 prepare = value.prepare_to_store
244 except AttributeError:
247 except KeyboardInterrupt:
250 # Convert stuff that has a repr() that
251 # cannot be evaluated into a string
252 value = SCons.Util.to_String(value)
256 defaultVal = env.subst(SCons.Util.to_String(option.default))
258 defaultVal = option.converter(defaultVal)
260 if str(env.subst('${%s}' % option.key)) != str(defaultVal):
261 fh.write('%s = %s\n' % (option.key, repr(value)))
268 raise SCons.Errors.UserError, 'Error writing options to file: %s\n%s' % (filename, x)
270 def GenerateHelpText(self, env, sort=None):
272 Generate the help text for the options.
274 env - an environment that is used to get the current values
279 options = self.options[:]
280 options.sort(lambda x,y,func=sort: func(x.key,y.key))
282 options = self.options
284 def format(opt, self=self, env=env):
285 if env.has_key(opt.key):
286 actual = env.subst('${%s}' % opt.key)
289 return self.FormatVariableHelpText(env, opt.key, opt.help, opt.default, actual, opt.aliases)
290 lines = filter(None, map(format, options))
292 return string.join(lines, '')
294 format = '\n%s: %s\n default: %s\n actual: %s\n'
295 format_ = '\n%s: %s\n default: %s\n actual: %s\n aliases: %s\n'
297 def FormatVariableHelpText(self, env, key, help, default, actual, aliases=[]):
298 # Don't display the key name itself as an alias.
299 aliases = filter(lambda a, k=key: a != k, aliases)
301 return self.format % (key, help, default, actual)
303 return self.format_ % (key, help, default, actual, aliases)