1 """engine.SCons.Variables
2
3 This file defines the Variables class that is used to add user-friendly
4 customizable variables to an SCons build.
5 """
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 __revision__ = "src/engine/SCons/Variables/__init__.py 5023 2010/06/14 22:05:46 scons"
30
31 import os.path
32 import sys
33
34 import SCons.Environment
35 import SCons.Errors
36 import SCons.Util
37 import SCons.Warnings
38
39 from BoolVariable import BoolVariable
40 from EnumVariable import EnumVariable
41 from ListVariable import ListVariable
42 from PackageVariable import PackageVariable
43 from PathVariable import PathVariable
44
45
47 instance=None
48
49 """
50 Holds all the options, updates the environment with the variables,
51 and renders the help text.
52 """
53 - def __init__(self, files=[], args={}, is_global=1):
54 """
55 files - [optional] List of option configuration files to load
56 (backward compatibility) If a single string is passed it is
57 automatically placed in a file list
58 """
59 self.options = []
60 self.args = args
61 if not SCons.Util.is_List(files):
62 if files:
63 files = [ files ]
64 else:
65 files = []
66 self.files = files
67 self.unknown = {}
68
69
70 if is_global:
71 self=Variables.instance
72
73 if not Variables.instance:
74 Variables.instance=self
75
76 - def _do_add(self, key, help="", default=None, validator=None, converter=None):
77 class Variable(object):
78 pass
79
80 option = Variable()
81
82
83
84 if SCons.Util.is_List(key) or SCons.Util.is_Tuple(key):
85 option.key = key[0]
86 option.aliases = key[1:]
87 else:
88 option.key = key
89 option.aliases = [ key ]
90 option.help = help
91 option.default = default
92 option.validator = validator
93 option.converter = converter
94
95 self.options.append(option)
96
97
98
99 for alias in list(option.aliases) + [ option.key ]:
100 if alias in self.unknown:
101 del self.unknown[alias]
102
104 """
105 Returns the keywords for the options
106 """
107 return [o.key for o in self.options]
108
109 - def Add(self, key, help="", default=None, validator=None, converter=None, **kw):
110 """
111 Add an option.
112
113 key - the name of the variable, or a list or tuple of arguments
114 help - optional help text for the options
115 default - optional default value
116 validator - optional function that is called to validate the option's value
117 Called with (key, value, environment)
118 converter - optional function that is called to convert the option's value before
119 putting it in the environment.
120 """
121
122 if SCons.Util.is_List(key) or isinstance(key, tuple):
123 self._do_add(*key)
124 return
125
126 if not SCons.Util.is_String(key) or \
127 not SCons.Environment.is_valid_construction_var(key):
128 raise SCons.Errors.UserError("Illegal Variables.Add() key `%s'" % str(key))
129
130 self._do_add(key, help, default, validator, converter)
131
133 """
134 Add a list of options.
135
136 Each list element is a tuple/list of arguments to be passed on
137 to the underlying method for adding options.
138
139 Example:
140 opt.AddVariables(
141 ('debug', '', 0),
142 ('CC', 'The C compiler'),
143 ('VALIDATE', 'An option for testing validation', 'notset',
144 validator, None),
145 )
146 """
147 for o in optlist:
148 self._do_add(*o)
149
150
151 - def Update(self, env, args=None):
152 """
153 Update an environment with the option variables.
154
155 env - the environment to update.
156 """
157
158 values = {}
159
160
161 for option in self.options:
162 if not option.default is None:
163 values[option.key] = option.default
164
165
166 for filename in self.files:
167 if os.path.exists(filename):
168 dir = os.path.split(os.path.abspath(filename))[0]
169 if dir:
170 sys.path.insert(0, dir)
171 try:
172 values['__name__'] = filename
173 exec open(filename, 'rU').read() in {}, values
174 finally:
175 if dir:
176 del sys.path[0]
177 del values['__name__']
178
179
180 if args is None:
181 args = self.args
182
183 for arg, value in args.items():
184 added = False
185 for option in self.options:
186 if arg in list(option.aliases) + [ option.key ]:
187 values[option.key] = value
188 added = True
189 if not added:
190 self.unknown[arg] = value
191
192
193
194 for option in self.options:
195 try:
196 env[option.key] = values[option.key]
197 except KeyError:
198 pass
199
200
201 for option in self.options:
202 if option.converter and option.key in values:
203 value = env.subst('${%s}'%option.key)
204 try:
205 try:
206 env[option.key] = option.converter(value)
207 except TypeError:
208 env[option.key] = option.converter(value, env)
209 except ValueError, x:
210 raise SCons.Errors.UserError('Error converting option: %s\n%s'%(option.key, x))
211
212
213
214 for option in self.options:
215 if option.validator and option.key in values:
216 option.validator(option.key, env.subst('${%s}'%option.key), env)
217
219 """
220 Returns any options in the specified arguments lists that
221 were not known, declared options in this object.
222 """
223 return self.unknown
224
225 - def Save(self, filename, env):
226 """
227 Saves all the options in the given file. This file can
228 then be used to load the options next run. This can be used
229 to create an option cache file.
230
231 filename - Name of the file to save into
232 env - the environment get the option values from
233 """
234
235
236 try:
237 fh = open(filename, 'w')
238
239 try:
240
241
242
243 for option in self.options:
244 try:
245 value = env[option.key]
246 try:
247 prepare = value.prepare_to_store
248 except AttributeError:
249 try:
250 eval(repr(value))
251 except KeyboardInterrupt:
252 raise
253 except:
254
255
256 value = SCons.Util.to_String(value)
257 else:
258 value = prepare()
259
260 defaultVal = env.subst(SCons.Util.to_String(option.default))
261 if option.converter:
262 defaultVal = option.converter(defaultVal)
263
264 if str(env.subst('${%s}' % option.key)) != str(defaultVal):
265 fh.write('%s = %s\n' % (option.key, repr(value)))
266 except KeyError:
267 pass
268 finally:
269 fh.close()
270
271 except IOError, x:
272 raise SCons.Errors.UserError('Error writing options to file: %s\n%s' % (filename, x))
273
274 - def GenerateHelpText(self, env, sort=None):
275 """
276 Generate the help text for the options.
277
278 env - an environment that is used to get the current values
279 of the options.
280 """
281
282 if sort:
283 options = sorted(self.options, key=lambda x: x.key)
284 else:
285 options = self.options
286
287 def format(opt, self=self, env=env):
288 if opt.key in env:
289 actual = env.subst('${%s}' % opt.key)
290 else:
291 actual = None
292 return self.FormatVariableHelpText(env, opt.key, opt.help, opt.default, actual, opt.aliases)
293 lines = [_f for _f in map(format, options) if _f]
294
295 return ''.join(lines)
296
297 format = '\n%s: %s\n default: %s\n actual: %s\n'
298 format_ = '\n%s: %s\n default: %s\n actual: %s\n aliases: %s\n'
299
301
302 aliases = [a for a in aliases if a != key]
303 if len(aliases)==0:
304 return self.format % (key, help, default, actual)
305 else:
306 return self.format_ % (key, help, default, actual, aliases)
307
308
309
310
311
312
313