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 3842 2008/12/20 22:59:52 scons"
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
100 """
101 Returns the keywords for the options
102 """
103 return map(lambda o: o.key, self.options)
104
105 - def Add(self, key, help="", default=None, validator=None, converter=None, **kw):
106 """
107 Add an option.
108
109 key - the name of the variable, or a list or tuple of arguments
110 help - optional help text for the options
111 default - optional default value
112 validator - optional function that is called to validate the option's value
113 Called with (key, value, environment)
114 converter - optional function that is called to convert the option's value before
115 putting it in the environment.
116 """
117
118 if SCons.Util.is_List(key) or type(key) == type(()):
119 apply(self._do_add, key)
120 return
121
122 if not SCons.Util.is_String(key) or \
123 not SCons.Environment.is_valid_construction_var(key):
124 raise SCons.Errors.UserError, "Illegal Variables.Add() key `%s'" % str(key)
125
126 self._do_add(key, help, default, validator, converter)
127
129 """
130 Add a list of options.
131
132 Each list element is a tuple/list of arguments to be passed on
133 to the underlying method for adding options.
134
135 Example:
136 opt.AddVariables(
137 ('debug', '', 0),
138 ('CC', 'The C compiler'),
139 ('VALIDATE', 'An option for testing validation', 'notset',
140 validator, None),
141 )
142 """
143 for o in optlist:
144 apply(self._do_add, o)
145
146
147 - def Update(self, env, args=None):
148 """
149 Update an environment with the option variables.
150
151 env - the environment to update.
152 """
153
154 values = {}
155
156
157 for option in self.options:
158 if not option.default is None:
159 values[option.key] = option.default
160
161
162 for filename in self.files:
163 if os.path.exists(filename):
164 dir = os.path.split(os.path.abspath(filename))[0]
165 if dir:
166 sys.path.insert(0, dir)
167 try:
168 values['__name__'] = filename
169 execfile(filename, {}, values)
170 finally:
171 if dir:
172 del sys.path[0]
173 del values['__name__']
174
175
176 if args is None:
177 args = self.args
178
179 for arg, value in args.items():
180 added = False
181 for option in self.options:
182 if arg in option.aliases + [ option.key ]:
183 values[option.key] = value
184 added = True
185 if not added:
186 self.unknown[arg] = value
187
188
189
190 for option in self.options:
191 try:
192 env[option.key] = values[option.key]
193 except KeyError:
194 pass
195
196
197 for option in self.options:
198 if option.converter and values.has_key(option.key):
199 value = env.subst('${%s}'%option.key)
200 try:
201 try:
202 env[option.key] = option.converter(value)
203 except TypeError:
204 env[option.key] = option.converter(value, env)
205 except ValueError, x:
206 raise SCons.Errors.UserError, 'Error converting option: %s\n%s'%(option.key, x)
207
208
209
210 for option in self.options:
211 if option.validator and values.has_key(option.key):
212 option.validator(option.key, env.subst('${%s}'%option.key), env)
213
215 """
216 Returns any options in the specified arguments lists that
217 were not known, declared options in this object.
218 """
219 return self.unknown
220
221 - def Save(self, filename, env):
222 """
223 Saves all the options in the given file. This file can
224 then be used to load the options next run. This can be used
225 to create an option cache file.
226
227 filename - Name of the file to save into
228 env - the environment get the option values from
229 """
230
231
232 try:
233 fh = open(filename, 'w')
234
235 try:
236
237
238
239 for option in self.options:
240 try:
241 value = env[option.key]
242 try:
243 prepare = value.prepare_to_store
244 except AttributeError:
245 try:
246 eval(repr(value))
247 except KeyboardInterrupt:
248 raise
249 except:
250
251
252 value = SCons.Util.to_String(value)
253 else:
254 value = prepare()
255
256 defaultVal = env.subst(SCons.Util.to_String(option.default))
257 if option.converter:
258 defaultVal = option.converter(defaultVal)
259
260 if str(env.subst('${%s}' % option.key)) != str(defaultVal):
261 fh.write('%s = %s\n' % (option.key, repr(value)))
262 except KeyError:
263 pass
264 finally:
265 fh.close()
266
267 except IOError, x:
268 raise SCons.Errors.UserError, 'Error writing options to file: %s\n%s' % (filename, x)
269
270 - def GenerateHelpText(self, env, sort=None):
271 """
272 Generate the help text for the options.
273
274 env - an environment that is used to get the current values
275 of the options.
276 """
277
278 if sort:
279 options = self.options[:]
280 options.sort(lambda x,y,func=sort: func(x.key,y.key))
281 else:
282 options = self.options
283
284 def format(opt, self=self, env=env):
285 if env.has_key(opt.key):
286 actual = env.subst('${%s}' % opt.key)
287 else:
288 actual = None
289 return self.FormatVariableHelpText(env, opt.key, opt.help, opt.default, actual, opt.aliases)
290 lines = filter(None, map(format, options))
291
292 return string.join(lines, '')
293
294 format = '\n%s: %s\n default: %s\n actual: %s\n'
295 format_ = '\n%s: %s\n default: %s\n actual: %s\n aliases: %s\n'
296
298
299 aliases = filter(lambda a, k=key: a != k, aliases)
300 if len(aliases)==0:
301 return self.format % (key, help, default, actual)
302 else:
303 return self.format_ % (key, help, default, actual, aliases)
304