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
30 __revision__ = "src/engine/SCons/Variables/__init__.py 5110 2010/07/25 16:14:38 bdeegan"
31
32 import os.path
33 import string
34 import sys
35
36 import SCons.Environment
37 import SCons.Errors
38 import SCons.Util
39 import SCons.Warnings
40
41 from BoolVariable import BoolVariable
42 from EnumVariable import EnumVariable
43 from ListVariable import ListVariable
44 from PackageVariable import PackageVariable
45 from PathVariable import PathVariable
46
47
49 instance=None
50
51 """
52 Holds all the options, updates the environment with the variables,
53 and renders the help text.
54 """
55 - def __init__(self, files=[], args={}, is_global=1):
56 """
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
60 """
61 self.options = []
62 self.args = args
63 if not SCons.Util.is_List(files):
64 if files:
65 files = [ files ]
66 else:
67 files = []
68 self.files = files
69 self.unknown = {}
70
71
72 if is_global:
73 self=Variables.instance
74
75 if not Variables.instance:
76 Variables.instance=self
77
78 - def _do_add(self, key, help="", default=None, validator=None, converter=None):
79 class Variable:
80 pass
81
82 option = Variable()
83
84
85
86 if SCons.Util.is_List(key) or SCons.Util.is_Tuple(key):
87 option.key = key[0]
88 option.aliases = key[1:]
89 else:
90 option.key = key
91 option.aliases = [ key ]
92 option.help = help
93 option.default = default
94 option.validator = validator
95 option.converter = converter
96
97 self.options.append(option)
98
99
100
101 for alias in list(option.aliases) + [ option.key ]:
102
103
104 if alias in self.unknown.keys():
105 del self.unknown[alias]
106
108 """
109 Returns the keywords for the options
110 """
111 return map(lambda o: o.key, self.options)
112
113 - def Add(self, key, help="", default=None, validator=None, converter=None, **kw):
114 """
115 Add an option.
116
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.
124 """
125
126 if SCons.Util.is_List(key) or type(key) == type(()):
127 apply(self._do_add, key)
128 return
129
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)
133
134 self._do_add(key, help, default, validator, converter)
135
137 """
138 Add a list of options.
139
140 Each list element is a tuple/list of arguments to be passed on
141 to the underlying method for adding options.
142
143 Example:
144 opt.AddVariables(
145 ('debug', '', 0),
146 ('CC', 'The C compiler'),
147 ('VALIDATE', 'An option for testing validation', 'notset',
148 validator, None),
149 )
150 """
151 for o in optlist:
152 apply(self._do_add, o)
153
154
155 - def Update(self, env, args=None):
156 """
157 Update an environment with the option variables.
158
159 env - the environment to update.
160 """
161
162 values = {}
163
164
165 for option in self.options:
166 if not option.default is None:
167 values[option.key] = option.default
168
169
170 for filename in self.files:
171 if os.path.exists(filename):
172 dir = os.path.split(os.path.abspath(filename))[0]
173 if dir:
174 sys.path.insert(0, dir)
175 try:
176 values['__name__'] = filename
177 exec open(filename, 'rU').read() in {}, values
178 finally:
179 if dir:
180 del sys.path[0]
181 del values['__name__']
182
183
184 if args is None:
185 args = self.args
186
187 for arg, value in args.items():
188 added = False
189 for option in self.options:
190 if arg in list(option.aliases) + [ option.key ]:
191 values[option.key] = value
192 added = True
193 if not added:
194 self.unknown[arg] = value
195
196
197
198 for option in self.options:
199 try:
200 env[option.key] = values[option.key]
201 except KeyError:
202 pass
203
204
205 for option in self.options:
206 if option.converter and values.has_key(option.key):
207 value = env.subst('${%s}'%option.key)
208 try:
209 try:
210 env[option.key] = option.converter(value)
211 except TypeError:
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)
215
216
217
218 for option in self.options:
219 if option.validator and values.has_key(option.key):
220 option.validator(option.key, env.subst('${%s}'%option.key), env)
221
223 """
224 Returns any options in the specified arguments lists that
225 were not known, declared options in this object.
226 """
227 return self.unknown
228
229 - def Save(self, filename, env):
230 """
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.
234
235 filename - Name of the file to save into
236 env - the environment get the option values from
237 """
238
239
240 try:
241 fh = open(filename, 'w')
242
243 try:
244
245
246
247 for option in self.options:
248 try:
249 value = env[option.key]
250 try:
251 prepare = value.prepare_to_store
252 except AttributeError:
253 try:
254 eval(repr(value))
255 except KeyboardInterrupt:
256 raise
257 except:
258
259
260 value = SCons.Util.to_String(value)
261 else:
262 value = prepare()
263
264 defaultVal = env.subst(SCons.Util.to_String(option.default))
265 if option.converter:
266 defaultVal = option.converter(defaultVal)
267
268 if str(env.subst('${%s}' % option.key)) != str(defaultVal):
269 fh.write('%s = %s\n' % (option.key, repr(value)))
270 except KeyError:
271 pass
272 finally:
273 fh.close()
274
275 except IOError, x:
276 raise SCons.Errors.UserError, 'Error writing options to file: %s\n%s' % (filename, x)
277
278 - def GenerateHelpText(self, env, sort=None):
279 """
280 Generate the help text for the options.
281
282 env - an environment that is used to get the current values
283 of the options.
284 """
285
286 if sort:
287 options = self.options[:]
288 options.sort(lambda x,y,func=sort: func(x.key,y.key))
289 else:
290 options = self.options
291
292 def format(opt, self=self, env=env):
293 if env.has_key(opt.key):
294 actual = env.subst('${%s}' % opt.key)
295 else:
296 actual = None
297 return self.FormatVariableHelpText(env, opt.key, opt.help, opt.default, actual, opt.aliases)
298 lines = filter(None, map(format, options))
299
300 return string.join(lines, '')
301
302 format = '\n%s: %s\n default: %s\n actual: %s\n'
303 format_ = '\n%s: %s\n default: %s\n actual: %s\n aliases: %s\n'
304
306
307 aliases = filter(lambda a, k=key: a != k, aliases)
308 if len(aliases)==0:
309 return self.format % (key, help, default, actual)
310 else:
311 return self.format_ % (key, help, default, actual, aliases)
312
313
314
315
316
317
318