Added fix for TeX includes with same name as subdirs.
[scons.git] / test / NodeOps.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 # This test is used to verify that the Buildability of a set of nodes
28 # is unaffected by various querying operations on those nodes:
29 #
30 # 1) Calling exists() on a Node (e.g. from find_file) in a VariantDir
31 #    will cause that node to be duplicated into the builddir.
32 #    However, this should *not* occur during a dryrun (-n).  When not
33 #    performed during a dryrun, this should not affect buildability.
34 # 2) Calling is_derived() should not affect buildability.
35
36 import sys
37 import TestSCons
38 import os
39
40 _exe = TestSCons._exe
41 lib_ = TestSCons.lib_
42 _lib = TestSCons._lib
43 _obj = TestSCons._obj
44 dll_ = TestSCons.dll_
45 _dll = TestSCons._dll
46     
47 if os.name == 'posix':
48     os.environ['LD_LIBRARY_PATH'] = '.'
49 if sys.platform.find('irix') > -1:
50     os.environ['LD_LIBRARYN32_PATH'] = '.'
51
52 test = TestSCons.TestSCons()
53
54 test.subdir('bld', 'src', ['src', 'subsrcdir'])
55
56 sconstruct = r"""
57 foo = Environment(SHOBJPREFIX='', WINDOWS_INSERT_DEF=1)
58 foo.Append(SHCXXFLAGS = '-DFOO')
59 bar = Environment(SHOBJPREFIX='', WINDOWS_INSERT_DEF=1)
60 bar.Append(SHCXXFLAGS = '-DBAR')
61 src = Dir('src')
62 VariantDir('bld', src, duplicate=1)
63 Nodes=[]
64 Nodes.extend(foo.SharedObject(target = 'foo%(_obj)s', source = 'prog.cpp'))
65 Nodes.extend(bar.SharedObject(target = 'bar%(_obj)s', source = 'prog.cpp'))
66 SConscript('bld/SConscript', ['Nodes'])
67 if %(_E)s:
68   import os
69   derived = [N.is_derived() for N in Nodes]
70   real1 = [os.path.exists(str(N)) for N in Nodes]
71   exists = [N.exists() for N in Nodes]
72   real2 = [os.path.exists(str(N)) for N in Nodes]
73   for N,D,R,E,F in zip(Nodes, derived, real1, exists, real2):
74     print '%%s: %%s %%s %%s %%s'%%(N,D,R,E,F)
75 foo.SharedLibrary(target = 'foo', source = 'foo%(_obj)s')
76 bar.SharedLibrary(target = 'bar', source = 'bar%(_obj)s')
77
78 fooMain = foo.Clone(LIBS='foo', LIBPATH='.')
79 foo_obj = fooMain.Object(target='foomain', source='main.c')
80 fooMain.Program(target='fooprog', source=foo_obj)
81
82 barMain = bar.Clone(LIBS='bar', LIBPATH='.')
83 bar_obj = barMain.Object(target='barmain', source='main.c')
84 barMain.Program(target='barprog', source=bar_obj)
85
86 gooMain = foo.Clone(LIBS='goo', LIBPATH='bld')
87 goo_obj = gooMain.Object(target='goomain', source='main.c')
88 gooMain.Program(target='gooprog', source=goo_obj)
89 """
90
91 test.write('foo.def', r"""
92 LIBRARY        "foo"
93
94 EXPORTS
95    doIt
96 """)
97
98 test.write('bar.def', r"""
99 LIBRARY        "bar"
100
101 EXPORTS
102    doIt
103 """)
104
105 test.write('prog.cpp', r"""
106 #include <stdio.h>
107
108 extern "C" void
109 doIt()
110 {
111 #ifdef FOO
112         printf("prog.cpp:  FOO\n");
113 #endif
114 #ifdef BAR
115         printf("prog.cpp:  BAR\n");
116 #endif
117 }
118 """)
119
120 sconscript = r"""
121 import os
122 Import('*')
123
124 import __builtin__
125 try:
126     __builtin__.True
127 except AttributeError:
128     __builtin__.True = 1
129     __builtin__.False = 0
130
131 def mycopy(env, source, target):
132     open(str(target[0]),'w').write(open(str(source[0]),'r').read())
133
134 def exists_test(node):
135     before = os.path.exists(str(node))  # doesn't exist yet in VariantDir
136     via_node = node.exists()            # side effect causes copy from src
137     after = os.path.exists(str(node))
138     node.is_derived()
139     import SCons.Script
140     if GetOption('no_exec'):
141         if (before,via_node,after) != (False,False,False):
142             import sys
143             sys.stderr.write('VariantDir exists() populated during dryrun!\n')
144             sys.exit(-2)
145     else:
146         if (before,via_node,after) != (False,True,True):
147             import sys
148             sys.stderr.write('VariantDir exists() population did not occur! (%%s:%%s,%%s,%%s)\n'%%(str(node),before,via_node,after))
149             sys.exit(-2)
150
151 goo = Environment()
152 goo.Append(CFLAGS = '-DFOO')
153 goof_in = File('goof.in')
154 if %(_E)s:
155     exists_test(goof_in)
156 Nodes.append(goof_in)
157 Nodes.extend(goo.Command(target='goof.c', source='goof.in', action=mycopy))
158 boo_src = File('subsrcdir/boo.c')
159 if %(_E)s:
160     exists_test(boo_src)
161 boo_objs = goo.Object(target='subsrcdir/boo%(_obj)s', source = boo_src)
162 Nodes.extend(boo_objs)
163 Nodes.extend(goo.Object(target='goo%(_obj)s',source='goof.c'))
164 goo.Library(target = 'goo', source = ['goo%(_obj)s'] + boo_objs)
165 """
166
167 test.write(['src', 'goof.in'], r"""
168 #include <stdio.h>
169
170 extern char *boo_sub();
171
172 void
173 doIt()
174 {
175 #ifdef FOO
176         printf("prog.cpp:  %s\n", boo_sub());
177 #endif
178 }
179 """)
180
181 test.write(['src', 'subsrcdir', 'boo.c'], r"""
182 char *
183 boo_sub()
184 {
185     return "GOO";
186 }
187 """)
188
189 test.write('main.c', r"""
190 void doIt();
191
192 int
193 main(int argc, char* argv[])
194 {
195     doIt();
196     return 0;
197 }
198 """)
199
200 builddir_srcnodes = [ os.path.join('bld', 'goof.in'),
201                       os.path.join('bld', 'subsrcdir', 'boo.c'),
202                     ]
203
204 sub_build_nodes = [ os.path.join('bld', 'subsrcdir','boo' + _obj),
205                     os.path.join('bld', 'goo' + _obj),
206                     os.path.join('bld', 'goof.c'),
207                     os.path.join('bld', lib_ + 'goo' + _lib),
208 ]
209
210 build_nodes = ['fooprog' + _exe,
211                dll_ + 'foo' + _dll,
212                'foo' + _obj,
213                'barprog' + _exe,
214                dll_ + 'bar' + _dll,
215                'bar' + _obj,
216
217                'gooprog' + _exe,
218
219                ] + builddir_srcnodes + sub_build_nodes
220
221 def cleanup_test():
222     "cleanup after running a test"
223     for F in builddir_srcnodes:
224         test.unlink(F)  # will be repopulated during clean operation
225     test.run(arguments = '-c')
226     for F in builddir_srcnodes:
227         test.unlink(F)
228     for name in build_nodes:
229         test.must_not_exist(test.workpath(name))
230
231
232 ### First pass, make sure everything goes quietly
233
234 for name in build_nodes:
235     test.must_not_exist(test.workpath(name))
236
237 _E=0
238 test.write('SConstruct', sconstruct % locals() )
239 test.write(['src', 'SConscript'], sconscript % locals() )
240
241 test.run(arguments = '.',
242          stderr=TestSCons.noisy_ar,
243          match=TestSCons.match_re_dotall)
244
245 test.run(program = test.workpath('fooprog'), stdout = "prog.cpp:  FOO\n")
246 test.run(program = test.workpath('barprog'), stdout = "prog.cpp:  BAR\n")
247 test.run(program = test.workpath('gooprog'), stdout = "prog.cpp:  GOO\n")
248
249 for name in build_nodes:
250     test.must_exist(test.workpath(name))
251
252 cleanup_test()
253
254 ### Next pass: add internal Node ops that may have side effects to
255 ### ensure that those side-effects don't interfere with building
256
257 for name in build_nodes:
258     test.must_not_exist(test.workpath(name))
259
260 _E=1
261 test.write('SConstruct', sconstruct % locals() )
262 test.write(['src', 'SConscript'], sconscript % locals() )
263
264 test.run(arguments = '.',
265          stderr=TestSCons.noisy_ar,
266          match=TestSCons.match_re_dotall)
267
268 test.run(program = test.workpath('fooprog'), stdout = "prog.cpp:  FOO\n")
269 test.run(program = test.workpath('barprog'), stdout = "prog.cpp:  BAR\n")
270 test.run(program = test.workpath('gooprog'), stdout = "prog.cpp:  GOO\n")
271
272 for name in build_nodes:
273     test.must_exist(test.workpath(name))
274
275 cleanup_test()
276
277 ### Next pass: try a dry-run first and verify that it doesn't change
278 ### the buildability.
279
280 for name in build_nodes:
281     test.must_not_exist(test.workpath(name))
282
283 _E=1
284 test.write('SConstruct', sconstruct % locals() )
285 test.write(['src', 'SConscript'], sconscript % locals() )
286
287 test.run(arguments = '-n .',
288          stderr=TestSCons.noisy_ar,
289          match=TestSCons.match_re_dotall)
290
291 for name in build_nodes:
292     test.must_not_exist(test.workpath(name))
293
294 test.run(arguments = '.',
295          stderr=TestSCons.noisy_ar,
296          match=TestSCons.match_re_dotall)
297
298 test.run(program = test.workpath('fooprog'), stdout = "prog.cpp:  FOO\n")
299 test.run(program = test.workpath('barprog'), stdout = "prog.cpp:  BAR\n")
300 test.run(program = test.workpath('gooprog'), stdout = "prog.cpp:  GOO\n")
301
302 for name in build_nodes:
303     test.must_exist(test.workpath(name))
304
305 cleanup_test()
306
307 ### Next pass: do an up-build from a VariantDir src
308
309
310 for name in build_nodes:
311     test.must_not_exist(test.workpath(name))
312
313 _E=0
314 test.write('SConstruct', sconstruct % locals() )
315 test.write(['src', 'SConscript'], sconscript % locals() )
316
317 test.run(chdir='src', arguments = '-u',
318          stderr=TestSCons.noisy_ar,
319          match=TestSCons.match_re_dotall)
320
321 for name in build_nodes:
322     if name in sub_build_nodes or name in builddir_srcnodes:
323         test.must_exist(test.workpath(name))
324     else:
325         test.must_not_exist(test.workpath(name))
326
327 cleanup_test()
328
329 ### Next pass: do an up-build from a VariantDir src with Node Ops
330 ### side-effects
331
332 for name in build_nodes:
333     test.must_not_exist(test.workpath(name))
334
335 _E=1
336 test.write('SConstruct', sconstruct % locals() )
337 test.write(['src', 'SConscript'], sconscript % locals() )
338
339 test.run(chdir='src', arguments = '-u',
340          stderr=TestSCons.noisy_ar,
341          match=TestSCons.match_re_dotall)
342
343 for name in build_nodes:
344     if name in sub_build_nodes or name in builddir_srcnodes:
345         test.must_exist(test.workpath(name))
346     else:
347         test.must_not_exist(test.workpath(name))
348
349 cleanup_test()
350
351 test.pass_test()
352
353 # Local Variables:
354 # tab-width:4
355 # indent-tabs-mode:nil
356 # End:
357 # vim: set expandtab tabstop=4 shiftwidth=4: