1 """engine.SCons.Options
3 This file defines the Options 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.
30 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
42 from BoolOption import BoolOption # okay
43 from EnumOption import EnumOption # okay
44 from ListOption import ListOption # naja
45 from PackageOption import PackageOption # naja
46 from PathOption import PathOption # okay
53 Holds all the options, updates the environment with the variables,
54 and renders the help text.
56 def __init__(self, files=[], args={}, is_global=1):
58 files - [optional] List of option configuration files to load
59 (backward compatibility) If a single string is passed it is
60 automatically placed in a file list
64 if not SCons.Util.is_List(files):
72 # create the singleton instance
76 if not Options.instance:
79 def _do_add(self, key, help="", default=None, validator=None, converter=None):
85 # if we get a list or a tuple, we take the first element as the
86 # option key and store the remaining in aliases.
87 if SCons.Util.is_List(key) or SCons.Util.is_Tuple(key):
89 option.aliases = key[1:]
92 option.aliases = [ key ]
94 option.default = default
95 option.validator = validator
96 option.converter = converter
98 self.options.append(option)
102 Returns the keywords for the options
104 return map(lambda o: o.key, self.options)
106 def Add(self, key, help="", default=None, validator=None, converter=None, **kw):
110 key - the name of the variable, or a list or tuple of arguments
111 help - optional help text for the options
112 default - optional default value
113 validator - optional function that is called to validate the option's value
114 Called with (key, value, environment)
115 converter - optional function that is called to convert the option's value before
116 putting it in the environment.
119 if SCons.Util.is_List(key) or type(key) == type(()):
120 apply(self._do_add, key)
123 if not SCons.Util.is_String(key) or \
124 not SCons.Util.is_valid_construction_var(key):
125 raise SCons.Errors.UserError, "Illegal Options.Add() key `%s'" % str(key)
127 self._do_add(key, help, default, validator, converter)
129 def AddOptions(self, *optlist):
131 Add a list of options.
133 Each list element is a tuple/list of arguments to be passed on
134 to the underlying method for adding options.
139 ('CC', 'The C compiler'),
140 ('VALIDATE', 'An option for testing validation', 'notset',
145 apply(self._do_add, o)
148 def Update(self, env, args=None):
150 Update an environment with the option variables.
152 env - the environment to update.
157 # first set the defaults:
158 for option in self.options:
159 if not option.default is None:
160 values[option.key] = option.default
162 # next set the value specified in the options file
163 for filename in self.files:
164 if os.path.exists(filename):
165 dir = os.path.split(os.path.abspath(filename))[0]
167 sys.path.insert(0, dir)
169 values['__name__'] = filename
170 execfile(filename, {}, values)
174 del values['__name__']
176 # set the values specified on the command line
180 for arg, value in args.items():
182 for option in self.options:
183 if arg in option.aliases + [ option.key ]:
184 values[option.key] = value
187 self.unknown[arg] = value
189 # put the variables in the environment:
190 # (don't copy over variables that are not declared as options)
191 for option in self.options:
193 env[option.key] = values[option.key]
197 # Call the convert functions:
198 for option in self.options:
199 if option.converter and values.has_key(option.key):
200 value = env.subst('${%s}'%option.key)
203 env[option.key] = option.converter(value)
205 env[option.key] = option.converter(value, env)
206 except ValueError, x:
207 raise SCons.Errors.UserError, 'Error converting option: %s\n%s'%(option.key, x)
210 # Finally validate the values:
211 for option in self.options:
212 if option.validator and values.has_key(option.key):
213 option.validator(option.key, env.subst('${%s}'%option.key), env)
215 def UnknownOptions(self):
217 Returns any options in the specified arguments lists that
218 were not known, declared options in this object.
222 def Save(self, filename, env):
224 Saves all the options in the given file. This file can
225 then be used to load the options next run. This can be used
226 to create an option cache file.
228 filename - Name of the file to save into
229 env - the environment get the option values from
232 # Create the file and write out the header
234 fh = open(filename, 'w')
237 # Make an assignment in the file for each option within the environment
238 # that was assigned a value other than the default.
239 for option in self.options:
241 value = env[option.key]
244 except KeyboardInterrupt:
247 # Convert stuff that has a repr() that
248 # cannot be evaluated into a string
249 value = SCons.Util.to_String(value)
251 defaultVal = env.subst(SCons.Util.to_String(option.default))
253 defaultVal = option.converter(defaultVal)
255 if str(env.subst('${%s}' % option.key)) != str(defaultVal):
256 fh.write('%s = %s\n' % (option.key, repr(value)))
263 raise SCons.Errors.UserError, 'Error writing options to file: %s\n%s' % (filename, x)
265 def GenerateHelpText(self, env, sort=None):
267 Generate the help text for the options.
269 env - an environment that is used to get the current values
274 options = self.options[:]
275 options.sort(lambda x,y,func=sort: func(x.key,y.key))
277 options = self.options
279 def format(opt, self=self, env=env):
280 if env.has_key(opt.key):
281 actual = env.subst('${%s}' % opt.key)
284 return self.FormatOptionHelpText(env, opt.key, opt.help, opt.default, actual, opt.aliases)
285 lines = filter(None, map(format, options))
287 return string.join(lines, '')
289 format = '\n%s: %s\n default: %s\n actual: %s\n'
290 format_ = '\n%s: %s\n default: %s\n actual: %s\n aliases: %s\n'
292 def FormatOptionHelpText(self, env, key, help, default, actual, aliases=[]):
293 # Don't display the key name itself as an alias.
294 aliases = filter(lambda a, k=key: a != k, aliases)
296 return self.format % (key, help, default, actual)
298 return self.format_ % (key, help, default, actual, aliases)