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 rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog"
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=None, args=None, 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
60 if files is None:
61 files = []
62 if args is None:
63 args = {}
64 self.options = []
65 self.args = args
66 if not SCons.Util.is_List(files):
67 if files:
68 files = [ files ]
69 else:
70 files = []
71 self.files = files
72 self.unknown = {}
73
74
75 if is_global:
76 self=Variables.instance
77
78 if not Variables.instance:
79 Variables.instance=self
80
81 - def _do_add(self, key, help="", default=None, validator=None, converter=None):
82 class Variable(object):
83 pass
84
85 option = Variable()
86
87
88
89 if SCons.Util.is_List(key) or SCons.Util.is_Tuple(key):
90 option.key = key[0]
91 option.aliases = key[1:]
92 else:
93 option.key = key
94 option.aliases = [ key ]
95 option.help = help
96 option.default = default
97 option.validator = validator
98 option.converter = converter
99
100 self.options.append(option)
101
102
103
104 for alias in list(option.aliases) + [ option.key ]:
105 if alias in self.unknown:
106 del self.unknown[alias]
107
109 """
110 Returns the keywords for the options
111 """
112 return [o.key for o in self.options]
113
114 - def Add(self, key, help="", default=None, validator=None, converter=None, **kw):
115 """
116 Add an option.
117
118 key - the name of the variable, or a list or tuple of arguments
119 help - optional help text for the options
120 default - optional default value
121 validator - optional function that is called to validate the option's value
122 Called with (key, value, environment)
123 converter - optional function that is called to convert the option's value before
124 putting it in the environment.
125 """
126
127 if SCons.Util.is_List(key) or isinstance(key, tuple):
128 self._do_add(*key)
129 return
130
131 if not SCons.Util.is_String(key) or \
132 not SCons.Environment.is_valid_construction_var(key):
133 raise SCons.Errors.UserError("Illegal Variables.Add() key `%s'" % str(key))
134
135 self._do_add(key, help, default, validator, converter)
136
138 """
139 Add a list of options.
140
141 Each list element is a tuple/list of arguments to be passed on
142 to the underlying method for adding options.
143
144 Example:
145 opt.AddVariables(
146 ('debug', '', 0),
147 ('CC', 'The C compiler'),
148 ('VALIDATE', 'An option for testing validation', 'notset',
149 validator, None),
150 )
151 """
152 for o in optlist:
153 self._do_add(*o)
154
155
156 - def Update(self, env, args=None):
157 """
158 Update an environment with the option variables.
159
160 env - the environment to update.
161 """
162
163 values = {}
164
165
166 for option in self.options:
167 if not option.default is None:
168 values[option.key] = option.default
169
170
171 for filename in self.files:
172 if os.path.exists(filename):
173 dir = os.path.split(os.path.abspath(filename))[0]
174 if dir:
175 sys.path.insert(0, dir)
176 try:
177 values['__name__'] = filename
178 exec open(filename, 'rU').read() in {}, values
179 finally:
180 if dir:
181 del sys.path[0]
182 del values['__name__']
183
184
185 if args is None:
186 args = self.args
187
188 for arg, value in args.items():
189 added = False
190 for option in self.options:
191 if arg in list(option.aliases) + [ option.key ]:
192 values[option.key] = value
193 added = True
194 if not added:
195 self.unknown[arg] = value
196
197
198
199 for option in self.options:
200 try:
201 env[option.key] = values[option.key]
202 except KeyError:
203 pass
204
205
206 for option in self.options:
207 if option.converter and option.key in values:
208 value = env.subst('${%s}'%option.key)
209 try:
210 try:
211 env[option.key] = option.converter(value)
212 except TypeError:
213 env[option.key] = option.converter(value, env)
214 except ValueError, x:
215 raise SCons.Errors.UserError('Error converting option: %s\n%s'%(option.key, x))
216
217
218
219 for option in self.options:
220 if option.validator and option.key in values:
221 option.validator(option.key, env.subst('${%s}'%option.key), env)
222
224 """
225 Returns any options in the specified arguments lists that
226 were not known, declared options in this object.
227 """
228 return self.unknown
229
230 - def Save(self, filename, env):
231 """
232 Saves all the options in the given file. This file can
233 then be used to load the options next run. This can be used
234 to create an option cache file.
235
236 filename - Name of the file to save into
237 env - the environment get the option values from
238 """
239
240
241 try:
242 fh = open(filename, 'w')
243
244 try:
245
246
247
248 for option in self.options:
249 try:
250 value = env[option.key]
251 try:
252 prepare = value.prepare_to_store
253 except AttributeError:
254 try:
255 eval(repr(value))
256 except KeyboardInterrupt:
257 raise
258 except:
259
260
261 value = SCons.Util.to_String(value)
262 else:
263 value = prepare()
264
265 defaultVal = env.subst(SCons.Util.to_String(option.default))
266 if option.converter:
267 defaultVal = option.converter(defaultVal)
268
269 if str(env.subst('${%s}' % option.key)) != str(defaultVal):
270 fh.write('%s = %s\n' % (option.key, repr(value)))
271 except KeyError:
272 pass
273 finally:
274 fh.close()
275
276 except IOError, x:
277 raise SCons.Errors.UserError('Error writing options to file: %s\n%s' % (filename, x))
278
279 - def GenerateHelpText(self, env, sort=None):
280 """
281 Generate the help text for the options.
282
283 env - an environment that is used to get the current values
284 of the options.
285 """
286
287 if sort:
288 options = sorted(self.options, key=lambda x: x.key)
289 else:
290 options = self.options
291
292 def format(opt, self=self, env=env):
293 if opt.key in env:
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 = [_f for _f in map(format, options) if _f]
299
300 return ''.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 = [a for a in aliases if a != key]
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