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