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.
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.
29 from __future__ import generators ### KEEP FOR COMPATIBILITY FIXERS
31 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
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)
99 # options might be added after the 'unknown' dict has been set up,
100 # so we remove the key and all its aliases from that dict
101 for alias in list(option.aliases) + [ option.key ]:
103 #if alias in self.unknown:
104 if alias in self.unknown.keys():
105 del self.unknown[alias]
109 Returns the keywords for the options
111 return [o.key for o in self.options]
113 def Add(self, key, help="", default=None, validator=None, converter=None, **kw):
117 key - the name of the variable, or a list or tuple of arguments
118 help - optional help text for the options
119 default - optional default value
120 validator - optional function that is called to validate the option's value
121 Called with (key, value, environment)
122 converter - optional function that is called to convert the option's value before
123 putting it in the environment.
126 if SCons.Util.is_List(key) or isinstance(key, tuple):
130 if not SCons.Util.is_String(key) or \
131 not SCons.Environment.is_valid_construction_var(key):
132 raise SCons.Errors.UserError("Illegal Variables.Add() key `%s'" % str(key))
134 self._do_add(key, help, default, validator, converter)
136 def AddVariables(self, *optlist):
138 Add a list of options.
140 Each list element is a tuple/list of arguments to be passed on
141 to the underlying method for adding options.
146 ('CC', 'The C compiler'),
147 ('VALIDATE', 'An option for testing validation', 'notset',
155 def Update(self, env, args=None):
157 Update an environment with the option variables.
159 env - the environment to update.
164 # first set the defaults:
165 for option in self.options:
166 if not option.default is None:
167 values[option.key] = option.default
169 # next set the value specified in the options file
170 for filename in self.files:
171 if os.path.exists(filename):
172 dir = os.path.split(os.path.abspath(filename))[0]
174 sys.path.insert(0, dir)
176 values['__name__'] = filename
177 exec open(filename, 'rU').read() in {}, values
181 del values['__name__']
183 # set the values specified on the command line
187 for arg, value in args.items():
189 for option in self.options:
190 if arg in list(option.aliases) + [ option.key ]:
191 values[option.key] = value
194 self.unknown[arg] = value
196 # put the variables in the environment:
197 # (don't copy over variables that are not declared as options)
198 for option in self.options:
200 env[option.key] = values[option.key]
204 # Call the convert functions:
205 for option in self.options:
206 if option.converter and option.key in values:
207 value = env.subst('${%s}'%option.key)
210 env[option.key] = option.converter(value)
212 env[option.key] = option.converter(value, env)
213 except ValueError, x:
214 raise SCons.Errors.UserError('Error converting option: %s\n%s'%(option.key, x))
217 # Finally validate the values:
218 for option in self.options:
219 if option.validator and option.key in values:
220 option.validator(option.key, env.subst('${%s}'%option.key), env)
222 def UnknownVariables(self):
224 Returns any options in the specified arguments lists that
225 were not known, declared options in this object.
229 def Save(self, filename, env):
231 Saves all the options in the given file. This file can
232 then be used to load the options next run. This can be used
233 to create an option cache file.
235 filename - Name of the file to save into
236 env - the environment get the option values from
239 # Create the file and write out the header
241 fh = open(filename, 'w')
244 # Make an assignment in the file for each option
245 # within the environment that was assigned a value
246 # other than the default.
247 for option in self.options:
249 value = env[option.key]
251 prepare = value.prepare_to_store
252 except AttributeError:
255 except KeyboardInterrupt:
258 # Convert stuff that has a repr() that
259 # cannot be evaluated into a string
260 value = SCons.Util.to_String(value)
264 defaultVal = env.subst(SCons.Util.to_String(option.default))
266 defaultVal = option.converter(defaultVal)
268 if str(env.subst('${%s}' % option.key)) != str(defaultVal):
269 fh.write('%s = %s\n' % (option.key, repr(value)))
276 raise SCons.Errors.UserError('Error writing options to file: %s\n%s' % (filename, x))
278 def GenerateHelpText(self, env, sort=None):
280 Generate the help text for the options.
282 env - an environment that is used to get the current values
287 options = sorted(self.options, cmp=lambda x,y: sort(x.key,y.key))
289 options = self.options
291 def format(opt, self=self, env=env):
293 actual = env.subst('${%s}' % opt.key)
296 return self.FormatVariableHelpText(env, opt.key, opt.help, opt.default, actual, opt.aliases)
297 lines = [_f for _f in map(format, options) if _f]
299 return ''.join(lines)
301 format = '\n%s: %s\n default: %s\n actual: %s\n'
302 format_ = '\n%s: %s\n default: %s\n actual: %s\n aliases: %s\n'
304 def FormatVariableHelpText(self, env, key, help, default, actual, aliases=[]):
305 # Don't display the key name itself as an alias.
306 aliases = [a for a in aliases if a != key]
308 return self.format % (key, help, default, actual)
310 return self.format_ % (key, help, default, actual, aliases)
314 # indent-tabs-mode:nil
316 # vim: set expandtab tabstop=4 shiftwidth=4: