Support construction variable expansion anywhere in a file or path name.
[scons.git] / test / Options.py
1 #!/usr/bin/env python
2 #
3 # __COPYRIGHT__
4 #
5 # Permission is hereby granted, free of charge, to any person obtaining
6 # a copy of this software and associated documentation files (the
7 # "Software"), to deal in the Software without restriction, including
8 # without limitation the rights to use, copy, modify, merge, publish,
9 # distribute, sublicense, and/or sell copies of the Software, and to
10 # permit persons to whom the Software is furnished to do so, subject to
11 # the following conditions:
12 #
13 # The above copyright notice and this permission notice shall be included
14 # in all copies or substantial portions of the Software.
15 #
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
17 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
18 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 #
24
25 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
26
27 import TestSCons
28 import string
29
30 test = TestSCons.TestSCons()
31
32 test.write('SConstruct', """
33 env = Environment()
34 print env['CC']
35 print env['CCFLAGS']
36 Default(env.Alias('dummy', None))
37 """)
38 test.run()
39 cc, ccflags = string.split(test.stdout(), '\n')[1:3]
40
41 test.write('SConstruct', """
42 # test validator.  Change a key and add a new one to the environment
43 def validator(key, value, environ):
44     environ[key] = "v"
45     environ["valid_key"] = "v"
46
47 opts = Options('custom.py')
48 opts.Add('RELEASE_BUILD',
49          'Set to 1 to build a release build',
50          0,
51          None,
52          int)
53
54 opts.Add('DEBUG_BUILD',
55          'Set to 1 to build a debug build',
56          1,
57          None,
58          int)
59
60 opts.Add('CC',
61          'The C compiler')
62
63 opts.Add('VALIDATE',
64          'An option for testing validation',
65          "notset",
66          validator,
67          None)
68
69 opts.Add('UNSPECIFIED',
70          'An option with no value')
71
72 def test_tool(env):
73     if env['RELEASE_BUILD']:
74         env['CCFLAGS'] = env['CCFLAGS'] + ' -O'
75     if env['DEBUG_BUILD']:
76         env['CCFLAGS'] = env['CCFLAGS'] + ' -g'
77
78
79 env = Environment(options=opts, tools=['default', test_tool])
80
81 Help('Variables settable in custom.py or on the command line:\\n' + opts.GenerateHelpText(env))
82
83 print env['RELEASE_BUILD']
84 print env['DEBUG_BUILD']
85 print env['CC']
86 print env['CCFLAGS']
87 print env['VALIDATE']
88 print env['valid_key']
89
90 # unspecified options should not be set:
91 assert not env.has_key('UNSPECIFIED')
92
93 # undeclared options should be ignored:
94 assert not env.has_key('UNDECLARED')
95
96 # calling Update() should not effect options that
97 # are not declared on the options object:
98 r = env['RELEASE_BUILD']
99 opts = Options()
100 opts.Update(env)
101 assert env['RELEASE_BUILD'] == r
102
103 Default(env.Alias('dummy', None))
104
105 """)
106
107 def check(expect):
108     result = string.split(test.stdout(), '\n')
109     assert result[1:len(expect)+1] == expect, (result[1:len(expect)+1], expect)
110
111 test.run()
112 check(['0', '1', cc, ccflags + ' -g', 'v', 'v'])
113
114 test.run(arguments='"RELEASE_BUILD=1"')
115 check(['1', '1', cc, ccflags + ' -O -g', 'v', 'v'])
116
117 test.run(arguments='"RELEASE_BUILD=1" "DEBUG_BUILD=0"')
118 check(['1', '0', cc, ccflags + ' -O', 'v', 'v'])
119
120 test.run(arguments='"CC=not_a_c_compiler"')
121 check(['0', '1', 'not_a_c_compiler', ccflags + ' -g', 'v', 'v'])
122
123 test.run(arguments='"UNDECLARED=foo"')
124 check(['0', '1', cc, ccflags + ' -g', 'v', 'v'])
125
126 test.run(arguments='"CCFLAGS=--taco"')
127 check(['0', '1', cc, ccflags + ' -g', 'v', 'v'])
128
129 test.write('custom.py', """
130 DEBUG_BUILD=0
131 RELEASE_BUILD=1
132 """)
133
134 test.run()
135 check(['1', '0', cc, ccflags + ' -O', 'v', 'v'])
136
137 test.run(arguments='"DEBUG_BUILD=1"')
138 check(['1', '1', cc, ccflags + ' -O -g', 'v', 'v'])
139
140 test.run(arguments='-h',
141          stdout = """scons: Reading SConscript files ...
142 scons: done reading SConscript files.
143 Variables settable in custom.py or on the command line:
144
145 RELEASE_BUILD: Set to 1 to build a release build
146     default: 0
147     actual: 1
148
149 DEBUG_BUILD: Set to 1 to build a debug build
150     default: 1
151     actual: 0
152
153 CC: The C compiler
154     default: None
155     actual: %s
156
157 VALIDATE: An option for testing validation
158     default: notset
159     actual: v
160
161 UNSPECIFIED: An option with no value
162     default: None
163     actual: None
164
165 Use scons -H for help about command-line options.
166 """%cc)
167
168 # Test saving of options and multi loading
169 #
170 test.write('SConstruct', """
171 opts = Options(['custom.py', 'options.saved'])
172 opts.Add('RELEASE_BUILD',
173          'Set to 1 to build a release build',
174          0,
175          None,
176          int)
177
178 opts.Add('DEBUG_BUILD',
179          'Set to 1 to build a debug build',
180          1,
181          None,
182          int)
183
184 opts.Add('UNSPECIFIED',
185          'An option with no value')
186
187 env = Environment(options = opts)
188
189 print env['RELEASE_BUILD']
190 print env['DEBUG_BUILD']
191
192 opts.Save('options.saved', env)
193 """)
194
195 # Check the save file by executing and comparing against
196 # the expected dictionary
197 def checkSave(file, expected):
198     gdict = {}
199     ldict = {}
200     execfile(file, gdict, ldict)
201     assert expected == ldict, "%s\n...not equal to...\n%s" % (expected, ldict)
202
203 # First test with no command line options
204 # This should just leave the custom.py settings
205 test.run()
206 check(['1','0'])
207 checkSave('options.saved', { 'RELEASE_BUILD':1, 'DEBUG_BUILD':0})
208
209 # Override with command line arguments
210 test.run(arguments='"DEBUG_BUILD=3"')
211 check(['1','3'])
212 checkSave('options.saved', {'RELEASE_BUILD':1, 'DEBUG_BUILD':3})
213
214 # Now make sure that saved options are overridding the custom.py
215 test.run()
216 check(['1','3'])
217 checkSave('options.saved', {'DEBUG_BUILD':3, 'RELEASE_BUILD':1})
218
219 # Load no options from file(s)
220 # Used to test for correct output in save option file
221 test.write('SConstruct', """
222 opts = Options()
223 opts.Add('RELEASE_BUILD',
224          'Set to 1 to build a release build',
225          '0',
226          None,
227          int)
228
229 opts.Add('DEBUG_BUILD',
230          'Set to 1 to build a debug build',
231          '1',
232          None,
233          int)
234
235 opts.Add('UNSPECIFIED',
236          'An option with no value')
237
238 env = Environment(options = opts)
239
240 print env['RELEASE_BUILD']
241 print env['DEBUG_BUILD']
242
243 opts.Save('options.saved', env)
244 """)
245
246 # First check for empty output file when nothing is passed on command line
247 test.run()
248 check(['0','1'])
249 checkSave('options.saved', {})
250
251 # Now specify one option the same as default and make sure it doesn't write out
252 test.run(arguments='"DEBUG_BUILD=1"')
253 check(['0','1'])
254 checkSave('options.saved', {})
255
256 # Now specify same option non-default and make sure only it is written out
257 test.run(arguments='"DEBUG_BUILD=0"')
258 check(['0','0'])
259 checkSave('options.saved',{'DEBUG_BUILD':0})
260
261 test.write('SConstruct', """
262 opts = Options('custom.py')
263 opts.Add('RELEASE_BUILD',
264          'Set to 1 to build a release build',
265          0,
266          None,
267          int)
268
269 opts.Add('DEBUG_BUILD',
270          'Set to 1 to build a debug build',
271          1,
272          None,
273          int)
274
275 opts.Add('CC',
276          'The C compiler')
277
278 opts.Add('UNSPECIFIED',
279          'An option with no value')
280
281 env = Environment(options=opts)
282
283 Help('Variables settable in custom.py or on the command line:\\n' + opts.GenerateHelpText(env,sort=cmp))
284
285 """)
286
287 test.run(arguments='-h',
288          stdout = """scons: Reading SConscript files ...
289 scons: done reading SConscript files.
290 Variables settable in custom.py or on the command line:
291
292 CC: The C compiler
293     default: None
294     actual: %s
295
296 DEBUG_BUILD: Set to 1 to build a debug build
297     default: 1
298     actual: 0
299
300 RELEASE_BUILD: Set to 1 to build a release build
301     default: 0
302     actual: 1
303
304 UNSPECIFIED: An option with no value
305     default: None
306     actual: None
307
308 Use scons -H for help about command-line options.
309 """%cc)
310
311 test.write('SConstruct', """
312 import SCons.Options
313 env1 = Environment(options = Options())
314 env2 = Environment(options = SCons.Options.Options())
315 """)
316
317 test.run()
318
319 test.pass_test()